diff --git a/DEPS b/DEPS index 47e5d56..a930b38 100644 --- a/DEPS +++ b/DEPS
@@ -308,11 +308,11 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. - 'src_internal_revision': 'd0f96e734c0973ba26686d8571a7701bb4be2a17', + 'src_internal_revision': '10067623e5b28dcbed49736689d2c9bc61aed9ac', # 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': 'a314118792512895108df4034926e89e18d957fb', + 'skia_revision': 'e19670f7040668370997825e2227ec2c054fce1e', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # 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 ANGLE # and whatever else without interference from each other. - 'angle_revision': '1196966d01b599b2fb99b4e511b65014a2f5a3a8', + 'angle_revision': '91d464283d745216a6ba807c8cfa33b7379e0fb7', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling SwiftShader # and whatever else without interference from each other. @@ -400,7 +400,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling devtools-frontend # and whatever else without interference from each other. - 'devtools_frontend_revision': '4d4076e1e451ad48e061b65e36e6a23d694352eb', + 'devtools_frontend_revision': '7f8f2c84b5c6c49132f6cb4e47be53d3d9142603', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libprotobuf-mutator # and whatever else without interference from each other. @@ -1206,7 +1206,7 @@ 'packages': [ { 'package': 'chromium/chrome/android/orderfiles/arm64', - 'version': 'AHfmVUwPElkCFn737a4YXWSHOseGHSRAlas2xuRDfJUC', + 'version': 'Q5hkbiFnOSgfMnLwtqgL9o7FZdrVQXZS640FMqAeRaAC', }, ], 'condition': 'checkout_android and non_git_source', @@ -1624,12 +1624,12 @@ 'src/clank': { 'url': Var('chrome_git') + '/clank/internal/apps.git' + '@' + - '4e03d7f1d820432e53f07bc1767ccf69e771c62d', + '11ba6df62aa898c8ee3e52e1dc7ead2903903eb4', 'condition': 'checkout_android and checkout_src_internal', }, 'src/docs/website': { - 'url': Var('chromium_git') + '/website.git' + '@' + 'd9a0c174b535ee5165fb8ef278324be9efa49352', + 'url': Var('chromium_git') + '/website.git' + '@' + '105a46915f47f94998e4a3084520835f24ea5a6c', }, 'src/ios/third_party/earl_grey2/src': { @@ -2028,7 +2028,7 @@ # Tools used when building Chrome for Chrome OS. This affects both the Simple # Chrome workflow, as well as the chromeos-chrome ebuild. 'src/third_party/chromite': { - 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '9f275ec850a249ec3e4d4221e21e729b7ca2eb0a', + 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'eec00b35328af2e160bfc59e1c7f85c75cf049dd', 'condition': 'checkout_chromeos', }, @@ -2060,7 +2060,7 @@ Var('chromium_git') + '/chromium/web-tests.git' + '@' + Var('crossbench_web_tests_revision'), 'src/third_party/depot_tools': - Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'f0d44b0b80f8d5c98e2ee72f5e35379fa249f2e5', + Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'e0a877ed8f3f1685b9ca9bcadb1430bf5640ffc7', 'src/third_party/devtools-frontend/src': Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'), @@ -2610,7 +2610,7 @@ Var('pdfium_git') + '/pdfium.git' + '@' + Var('pdfium_revision'), 'src/third_party/perfetto': - Var('chromium_git') + '/external/github.com/google/perfetto.git' + '@' + '03b636c73098d523aea8254d37e194d8957b11af', + Var('chromium_git') + '/external/github.com/google/perfetto.git' + '@' + 'bfd6932dfc3d9270ee05558daec56fbe359012e0', 'src/base/tracing/test/data': { 'bucket': 'perfetto', @@ -2936,13 +2936,13 @@ 'dep_type': 'cipd', }, - 'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@a39d345d38f7499321e634436c35f80967ae0beb', + 'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@ef433db61dc17278fb7452441edfa8c3ca0d986e', 'src/third_party/glslang/src': '{chromium_git}/external/github.com/KhronosGroup/glslang@19246e3fbc095586e0e325b378ea351aababeb7c', 'src/third_party/spirv-cross/src': '{chromium_git}/external/github.com/KhronosGroup/SPIRV-Cross@b8fcf307f1f347089e3c46eb4451d27f32ebc8d3', 'src/third_party/spirv-headers/src': '{chromium_git}/external/github.com/KhronosGroup/SPIRV-Headers@6146b3d9ad4fcc5fb512209d348e97ce03749169', - 'src/third_party/spirv-tools/src': '{chromium_git}/external/github.com/KhronosGroup/SPIRV-Tools@3e36d0af6f2ad0bc7f870fdf4234b9e4477cd1d4', + 'src/third_party/spirv-tools/src': '{chromium_git}/external/github.com/KhronosGroup/SPIRV-Tools@8c1e6ca9b896a5a82ea39973a2f677f515f1f45d', 'src/third_party/vulkan-headers/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-Headers@2fa203425eb4af9dfc6b03f97ef72b0b5bcb8350', - 'src/third_party/vulkan-loader/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-Loader@918e869d4eb54a2fbe78546f4931f1ff9e9454bf', + 'src/third_party/vulkan-loader/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-Loader@0db9a0d55e33f8b63b733f37dc59eb441d51abf0', 'src/third_party/vulkan-tools/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-Tools@48b5d246b2d0b1a41ee7ea1b69525ae7bb38a2ae', 'src/third_party/vulkan-utility-libraries/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-Utility-Libraries@c010c19e796035e92fb3b0462cb887518a41a7c1', 'src/third_party/vulkan-validation-layers/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-ValidationLayers@5e6c6bd96224c1c0bb73414a9227d93f7cc236b0', @@ -2988,7 +2988,7 @@ Var('chromium_git') + '/webpagereplay.git' + '@' + Var('webpagereplay_revision'), 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + 'f1785bbb3d0159af1fbc4d5cb4cdffc1fdd0e670', + Var('webrtc_git') + '/src.git' + '@' + 'e175a31bf923aed9877f67f8530f6e08b280d5e7', # Wuffs' canonical repository is at github.com/google/wuffs, but we use # Skia's mirror of Wuffs, the same as in upstream Skia's DEPS file. @@ -3587,7 +3587,7 @@ # grepping. 'src/chrome/installer/mac/internal': { 'url': Var('chrome_git') + '/chrome/installer/mac/internal.git' + '@' + - '27b07a5c4a105a8b4508c61bc9aa6dc52b519907', + '47bf0993574233a3bbd271c8318d0299e542d1f5', 'condition': 'checkout_src_internal', }, @@ -3759,7 +3759,7 @@ 'src/ios_internal': { 'url': Var('chrome_git') + '/chrome/ios_internal.git' + '@' + - '0e7f5890f35d56c7b441abc8bb45d50cc7d77163', + '9ff06ac623af71709d9872aeb472d71b60f3b744', 'condition': 'checkout_ios and checkout_src_internal', },
diff --git a/android_webview/java/src/org/chromium/android_webview/variations/VariationsSeedLoader.java b/android_webview/java/src/org/chromium/android_webview/variations/VariationsSeedLoader.java index 01fd792..3bdaf583 100644 --- a/android_webview/java/src/org/chromium/android_webview/variations/VariationsSeedLoader.java +++ b/android_webview/java/src/org/chromium/android_webview/variations/VariationsSeedLoader.java
@@ -327,7 +327,7 @@ private void updateSeedFileAndRequestNewFromServiceOnBackgroundThread( boolean foundNewSeed, boolean needNewSeed, long seedFileTime) { // This work is not time critical. - PostTask.postTask( + PostTask.postDelayedTask( TaskTraits.BEST_EFFORT_MAY_BLOCK, () -> { if (foundNewSeed) { @@ -346,7 +346,8 @@ } onBackgroundWorkFinished(); - }); + }, + 2500); } // Connects to VariationsSeedServer service. Sends a file descriptor for our local copy of the
diff --git a/android_webview/test/data/web_tests/virtual/stable/webexposed/global-interface-listing-expected.txt b/android_webview/test/data/web_tests/virtual/stable/webexposed/global-interface-listing-expected.txt index 320e96d2..f6d3d40 100644 --- a/android_webview/test/data/web_tests/virtual/stable/webexposed/global-interface-listing-expected.txt +++ b/android_webview/test/data/web_tests/virtual/stable/webexposed/global-interface-listing-expected.txt
@@ -5189,6 +5189,8 @@ getter element getter id getter loadTime + getter paintTime + getter presentationTime getter renderTime getter size getter url @@ -6487,6 +6489,8 @@ getter loadTime getter naturalHeight getter naturalWidth + getter paintTime + getter presentationTime getter renderTime getter url method constructor @@ -6512,6 +6516,8 @@ attribute @@toStringTag getter blockingDuration getter firstUIEventTimestamp + getter paintTime + getter presentationTime getter renderStart getter scripts getter styleAndLayoutStart @@ -6572,7 +6578,10 @@ method getEntriesByType interface PerformancePaintTiming : PerformanceEntry attribute @@toStringTag + getter paintTime + getter presentationTime method constructor + method toJSON interface PerformanceResourceTiming : PerformanceEntry attribute @@toStringTag getter connectEnd
diff --git a/ash/ash_strings.grd b/ash/ash_strings.grd index a61cf6b..eea0bedc 100644 --- a/ash/ash_strings.grd +++ b/ash/ash_strings.grd
@@ -4376,6 +4376,9 @@ <message name="IDS_ASH_ACCELERATOR_DESCRIPTION_NEW_INCOGNITO_WINDOW" translateable="false" desc="Label for accelerator action - Open new Incognito window."> Open new Incognito window </message> + <message name="IDS_ASH_ACCELERATOR_DESCRIPTION_NEW_SPLIT_VIEW" desc="Label for accelerator action - Add tab to new split view."> + Add tab to new split view + </message> <message name="IDS_ASH_ACCELERATOR_DESCRIPTION_NEW_TAB" desc="Label for accelerator action - Open new tab."> Open new tab </message>
diff --git a/ash/ash_strings_grd/IDS_ASH_ACCELERATOR_DESCRIPTION_NEW_SPLIT_VIEW.png.sha1 b/ash/ash_strings_grd/IDS_ASH_ACCELERATOR_DESCRIPTION_NEW_SPLIT_VIEW.png.sha1 new file mode 100644 index 0000000..1cbebc15 --- /dev/null +++ b/ash/ash_strings_grd/IDS_ASH_ACCELERATOR_DESCRIPTION_NEW_SPLIT_VIEW.png.sha1
@@ -0,0 +1 @@ +be7d6fece3565ffaecc077777751e717eada1c51 \ No newline at end of file
diff --git a/ash/glanceables/tasks/glanceables_task_view.cc b/ash/glanceables/tasks/glanceables_task_view.cc index 314ba8a..9b1420f 100644 --- a/ash/glanceables/tasks/glanceables_task_view.cc +++ b/ash/glanceables/tasks/glanceables_task_view.cc
@@ -327,7 +327,6 @@ SetPaintToLayer(); layer()->SetFillsBoundsOpaquely(false); - // TODO(crbug.com/40232718): See View::SetLayoutManagerUseConstrainedSpace SetLayoutManagerUseConstrainedSpace(false); check_button_ = @@ -344,7 +343,6 @@ views::FlexSpecification(views::LayoutOrientation::kHorizontal, views::MinimumFlexSizeRule::kScaleToZero, views::MaximumFlexSizeRule::kUnbounded)); - // TODO(crbug.com/40232718): See View::SetLayoutManagerUseConstrainedSpace contents_view_->SetLayoutManagerUseConstrainedSpace(false); tasks_title_view_ =
diff --git a/ash/webui/shortcut_customization_ui/backend/accelerator_layout_table.cc b/ash/webui/shortcut_customization_ui/backend/accelerator_layout_table.cc index 0e70a09..7f6f9b13 100644 --- a/ash/webui/shortcut_customization_ui/backend/accelerator_layout_table.cc +++ b/ash/webui/shortcut_customization_ui/backend/accelerator_layout_table.cc
@@ -311,6 +311,9 @@ NonConfigurableAcceleratorDetails( {ui::Accelerator(ui::VKEY_BROWSER_BACK, ui::EF_CONTROL_DOWN | ui::EF_SHIFT_DOWN)})}, + {NonConfigurableActions::kBrowserNewSplitView, + NonConfigurableAcceleratorDetails({ui::Accelerator( + ui::VKEY_N, ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN)})}, {NonConfigurableActions::kAmbientOpenRightClickMenu, NonConfigurableAcceleratorDetails( {ui::Accelerator(ui::VKEY_F10, ui::EF_SHIFT_DOWN)})}, @@ -1367,6 +1370,14 @@ mojom::AcceleratorSubcategory::kDeveloperTools, /*locked=*/true, mojom::AcceleratorLayoutStyle::kDefault, mojom::AcceleratorSource::kAmbient)}, + {NonConfigurableActions::kBrowserNewSplitView, + AcceleratorLayoutDetails(NonConfigurableActions::kBrowserNewSplitView, + IDS_ASH_ACCELERATOR_DESCRIPTION_NEW_SPLIT_VIEW, + mojom::AcceleratorCategory::kBrowser, + mojom::AcceleratorSubcategory::kTabs, + /*locked=*/true, + mojom::AcceleratorLayoutStyle::kDefault, + mojom::AcceleratorSource::kAmbient)}, // Text {NonConfigurableActions::kAmbientGoToBeginningOfDocument,
diff --git a/ash/webui/shortcut_customization_ui/backend/accelerator_layout_table.h b/ash/webui/shortcut_customization_ui/backend/accelerator_layout_table.h index 1e5ecba07b..5863448 100644 --- a/ash/webui/shortcut_customization_ui/backend/accelerator_layout_table.h +++ b/ash/webui/shortcut_customization_ui/backend/accelerator_layout_table.h
@@ -112,6 +112,7 @@ kBrowserSelectPreviousTab, kBrowserPageUp, kBrowserPageDown, + kBrowserNewSplitView, // Ambient action ids: kAmbientDragLinkInSameTab, kAmbientCycleForwardMRU, @@ -404,6 +405,7 @@ NonConfigurableActions::kAmbientOpenLinkInTab, NonConfigurableActions::kAmbientOpenLinkInTabBackground, NonConfigurableActions::kBrowserStopDragTab, + NonConfigurableActions::kBrowserNewSplitView, // Browser > Bookmarks NonConfigurableActions::kBrowserBookmarkThisTab,
diff --git a/base/i18n/streaming_utf8_validator_unittest.cc b/base/i18n/streaming_utf8_validator_unittest.cc index 49eb362d..4178991 100644 --- a/base/i18n/streaming_utf8_validator_unittest.cc +++ b/base/i18n/streaming_utf8_validator_unittest.cc
@@ -2,14 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40284755): Remove this and spanify to fix the errors. -// -// Note: U8_NEXT couldn't be rewritten using the spanification_tool, because it -// is a macro. -#pragma allow_unsafe_buffers -#endif - #include "base/i18n/streaming_utf8_validator.h" #include <stddef.h> @@ -17,14 +9,18 @@ #include <stdio.h> #include <string.h> +#include <array> +#include <ranges> #include <string> #include <string_view> +#include <vector> #include "base/containers/span.h" #include "base/functional/bind.h" #include "base/location.h" #include "base/logging.h" #include "base/memory/ref_counted.h" +#include "base/numerics/byte_conversions.h" #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversion_utils.h" @@ -56,7 +52,8 @@ size_t char_index = 0; while (char_index < src.size()) { base_icu::UChar32 code_point; - U8_NEXT(src, char_index, src.size(), code_point); + // U8_NEXT has unsafe buffer accesses in their internal implementation. + UNSAFE_TODO(U8_NEXT(src, char_index, src.size(), code_point)); if (!base::IsValidCodepoint(code_point)) { return false; } @@ -68,8 +65,7 @@ // verifies that IsStringUtf8 and StreamingUtf8Validator agree on // whether it is valid UTF-8 or not. void TestNumber(uint32_t n) const { - uint8_t test[sizeof n]; - memcpy(test, &n, sizeof n); + auto test = base::byte_span_from_ref(n); StreamingUtf8Validator validator; EXPECT_EQ(IsStringUtf8(test), validator.AddBytes(test) == VALID_ENDPOINT) << "Difference of opinion for \"" @@ -125,14 +121,12 @@ // All of the strings in |valid| must represent a single codepoint, because // partial sequences are constructed by taking non-empty prefixes of these // strings. -const char* const valid[] = { - "\r", "\n", "a", "\xc2\x81", "\xe1\x80\xbf", "\xf1\x80\xa0\xbf", +constexpr auto valid = std::to_array<std::string_view>({ + "\r", "\n", "a", "\xc2\x81", "\xe1\x80\xbf", "\xf1\x80\xa0\xbf", "\xef\xbb\xbf", // UTF-8 BOM -}; +}); -const char* const* const valid_end = std::end(valid); - -const char* const invalid[] = { +constexpr auto invalid = std::to_array<std::string_view>({ // always invalid bytes "\xc0", "\xc1", @@ -174,14 +168,17 @@ // BOMs in UTF-16(BE|LE) "\xfe\xff", "\xff\xfe", -}; - -const char* const* const invalid_end = std::end(invalid); +}); // A ForwardIterator which returns all the non-empty prefixes of the elements of // "valid". class PartialIterator { public: + using value_type = std::string_view; + using difference_type = std::ptrdiff_t; + using iterator_category = std::forward_iterator_tag; + + public: // The constructor returns the first iterator, ie. it is equivalent to // begin(). PartialIterator() : index_(0), prefix_length_(0) { Advance(); } @@ -196,8 +193,15 @@ return *this; } + // Required for std::incrementable concept. + PartialIterator operator++(int) { + PartialIterator temp = *this; + ++(*this); + return temp; + } + std::string_view operator*() const { - return std::string_view(valid[index_], prefix_length_); + return valid[index_].substr(0, prefix_length_); } friend bool operator==(const PartialIterator&, @@ -209,11 +213,11 @@ : index_(index), prefix_length_(prefix_length) {} void Advance() { - if (index_ < std::size(valid) && prefix_length_ < strlen(valid[index_])) { + if (index_ < std::size(valid) && prefix_length_ < valid[index_].size()) { ++prefix_length_; } while (index_ < std::size(valid) && - prefix_length_ == strlen(valid[index_])) { + prefix_length_ == valid[index_].size()) { ++index_; prefix_length_ = 1; } @@ -224,33 +228,32 @@ size_t prefix_length_; }; +std::ranges::subrange<PartialIterator, PartialIterator> GetPartialSequences() { + return std::ranges::subrange<PartialIterator, PartialIterator>( + PartialIterator(), PartialIterator::end()); +} // A test fixture for tests which test one UTF-8 sequence (or invalid // byte sequence) at a time. class StreamingUtf8ValidatorSingleSequenceTest : public ::testing::Test { protected: // Iterator must be convertible when de-referenced to std::string_view. - template <typename Iterator> - void CheckRange(Iterator begin, - Iterator end, - StreamingUtf8Validator::State expected) { - for (Iterator it = begin; it != end; ++it) { + template <typename Range> + void CheckRange(const Range& range, StreamingUtf8Validator::State expected) { + for (std::string_view sequence : range) { StreamingUtf8Validator validator; - std::string_view sequence = *it; EXPECT_EQ(expected, validator.AddBytes(base::as_byte_span(sequence))) << "Failed for \"" << sequence << "\""; } } // Adding input a byte at a time should make absolutely no difference. - template <typename Iterator> - void CheckRangeByteAtATime(Iterator begin, - Iterator end, + template <typename Range> + void CheckRangeByteAtATime(const Range& range, StreamingUtf8Validator::State expected) { - for (Iterator it = begin; it != end; ++it) { + for (std::string_view sequence : range) { StreamingUtf8Validator validator; - std::string_view sequence = *it; StreamingUtf8Validator::State state = VALID_ENDPOINT; - for (const auto& cit : sequence) { + for (char cit : sequence) { state = validator.AddBytes(base::byte_span_from_ref(cit)); } EXPECT_EQ(expected, state) << "Failed for \"" << sequence << "\""; @@ -264,17 +267,13 @@ // Check every possible concatenation of byte sequences from two // ranges, and verify that the combination matches the expected // state. - template <typename Iterator1, typename Iterator2> - void CheckCombinations(Iterator1 begin1, - Iterator1 end1, - Iterator2 begin2, - Iterator2 end2, + template <typename Range1, typename Range2> + void CheckCombinations(const Range1& range1, + const Range2& range2, StreamingUtf8Validator::State expected) { StreamingUtf8Validator validator; - for (Iterator1 it1 = begin1; it1 != end1; ++it1) { - std::string_view c1 = *it1; - for (Iterator2 it2 = begin2; it2 != end2; ++it2) { - std::string_view c2 = *it2; + for (std::string_view c1 : range1) { + for (std::string_view c2 : range2) { validator.AddBytes(base::as_byte_span(c1)); EXPECT_EQ(expected, validator.AddBytes(base::as_byte_span(c2))) << "Failed for \"" << c1 << c2 << "\""; @@ -315,69 +314,63 @@ } TEST_F(StreamingUtf8ValidatorSingleSequenceTest, Valid) { - CheckRange(valid, valid_end, VALID_ENDPOINT); + CheckRange(valid, VALID_ENDPOINT); } TEST_F(StreamingUtf8ValidatorSingleSequenceTest, Partial) { - CheckRange(PartialIterator(), PartialIterator::end(), VALID_MIDPOINT); + CheckRange(GetPartialSequences(), VALID_MIDPOINT); } TEST_F(StreamingUtf8ValidatorSingleSequenceTest, Invalid) { - CheckRange(invalid, invalid_end, INVALID); + CheckRange(invalid, INVALID); } TEST_F(StreamingUtf8ValidatorSingleSequenceTest, ValidByByte) { - CheckRangeByteAtATime(valid, valid_end, VALID_ENDPOINT); + CheckRangeByteAtATime(valid, VALID_ENDPOINT); } TEST_F(StreamingUtf8ValidatorSingleSequenceTest, PartialByByte) { - CheckRangeByteAtATime(PartialIterator(), PartialIterator::end(), - VALID_MIDPOINT); + CheckRangeByteAtATime(GetPartialSequences(), VALID_MIDPOINT); } TEST_F(StreamingUtf8ValidatorSingleSequenceTest, InvalidByByte) { - CheckRangeByteAtATime(invalid, invalid_end, INVALID); + CheckRangeByteAtATime(invalid, INVALID); } TEST_F(StreamingUtf8ValidatorDoubleSequenceTest, ValidPlusValidIsValid) { - CheckCombinations(valid, valid_end, valid, valid_end, VALID_ENDPOINT); + CheckCombinations(valid, valid, VALID_ENDPOINT); } TEST_F(StreamingUtf8ValidatorDoubleSequenceTest, ValidPlusPartialIsPartial) { - CheckCombinations(valid, valid_end, PartialIterator(), PartialIterator::end(), - VALID_MIDPOINT); + CheckCombinations(valid, GetPartialSequences(), VALID_MIDPOINT); } TEST_F(StreamingUtf8ValidatorDoubleSequenceTest, PartialPlusValidIsInvalid) { - CheckCombinations(PartialIterator(), PartialIterator::end(), valid, valid_end, - INVALID); + CheckCombinations(GetPartialSequences(), valid, INVALID); } TEST_F(StreamingUtf8ValidatorDoubleSequenceTest, PartialPlusPartialIsInvalid) { - CheckCombinations(PartialIterator(), PartialIterator::end(), - PartialIterator(), PartialIterator::end(), INVALID); + CheckCombinations(GetPartialSequences(), GetPartialSequences(), INVALID); } TEST_F(StreamingUtf8ValidatorDoubleSequenceTest, ValidPlusInvalidIsInvalid) { - CheckCombinations(valid, valid_end, invalid, invalid_end, INVALID); + CheckCombinations(valid, invalid, INVALID); } TEST_F(StreamingUtf8ValidatorDoubleSequenceTest, InvalidPlusValidIsInvalid) { - CheckCombinations(invalid, invalid_end, valid, valid_end, INVALID); + CheckCombinations(invalid, valid, INVALID); } TEST_F(StreamingUtf8ValidatorDoubleSequenceTest, InvalidPlusInvalidIsInvalid) { - CheckCombinations(invalid, invalid_end, invalid, invalid_end, INVALID); + CheckCombinations(invalid, invalid, INVALID); } TEST_F(StreamingUtf8ValidatorDoubleSequenceTest, InvalidPlusPartialIsInvalid) { - CheckCombinations(invalid, invalid_end, PartialIterator(), - PartialIterator::end(), INVALID); + CheckCombinations(invalid, GetPartialSequences(), INVALID); } TEST_F(StreamingUtf8ValidatorDoubleSequenceTest, PartialPlusInvalidIsInvalid) { - CheckCombinations(PartialIterator(), PartialIterator::end(), invalid, - invalid_end, INVALID); + CheckCombinations(GetPartialSequences(), invalid, INVALID); } TEST(StreamingUtf8ValidatorValidateTest, EmptyIsValid) {
diff --git a/base/memory/memory_pressure_listener.h b/base/memory/memory_pressure_listener.h index f0f05555..0e7eb66 100644 --- a/base/memory/memory_pressure_listener.h +++ b/base/memory/memory_pressure_listener.h
@@ -72,7 +72,8 @@ kUrgentPageDiscardingPolicy = 41, kTabLoader = 42, kBackgroundTabLoadingPolicy = 43, - kThumbnailCache = 44, + // Deprecated. + // kThumbnailCache = 44, kUserspaceSwapPolicy = 45, kWorkingSetTrimmerPolicyChromeOS = 46, kLruRendererCache = 47,
diff --git a/base/metrics/sample_vector_unittest.cc b/base/metrics/sample_vector_unittest.cc index ebfabbe..f4bda08 100644 --- a/base/metrics/sample_vector_unittest.cc +++ b/base/metrics/sample_vector_unittest.cc
@@ -420,8 +420,7 @@ LocalPersistentMemoryAllocator allocator(64 << 10, 0, ""); std::atomic<PersistentMemoryAllocator::Reference> samples_ref; samples_ref.store(0, std::memory_order_relaxed); - HistogramSamples::Metadata samples_meta; - UNSAFE_TODO(memset(&samples_meta, 0, sizeof(samples_meta))); + HistogramSamples::Metadata samples_meta = {}; // Custom buckets: [1, 5) [5, 10) BucketRanges ranges(3); @@ -515,8 +514,7 @@ LocalPersistentMemoryAllocator allocator(64 << 10, 0, ""); std::atomic<PersistentMemoryAllocator::Reference> samples_ref; samples_ref.store(0, std::memory_order_relaxed); - HistogramSamples::Metadata samples_meta; - UNSAFE_TODO(memset(&samples_meta, 0, sizeof(samples_meta))); + HistogramSamples::Metadata samples_meta = {}; // Custom buckets: [1, 5) [5, 10) BucketRanges ranges(3);
diff --git a/build/android/pylib/local/device/local_device_instrumentation_test_run.py b/build/android/pylib/local/device/local_device_instrumentation_test_run.py index bf0ebec1..ecc8f2a 100644 --- a/build/android/pylib/local/device/local_device_instrumentation_test_run.py +++ b/build/android/pylib/local/device/local_device_instrumentation_test_run.py
@@ -680,8 +680,8 @@ install_steps += [push_test_data, create_flag_changer] post_install_steps += [ - set_debug_app, approve_app_links, disable_system_modals, - set_vega_permissions, DismissCrashDialogs + self._SetDefaultBrowserApp, set_debug_app, approve_app_links, + disable_system_modals, set_vega_permissions, DismissCrashDialogs ] def bind_crash_handler(step, dev): @@ -758,6 +758,8 @@ if self._webview_flag_changers[str(dev)].GetCurrentFlags(): self._webview_flag_changers[str(dev)].Restore() + self._ClearDefaultBrowserApp(dev) + # Remove package-specific configuration dev.RunShellCommand(['am', 'clear-debug-app'], check_return=True) @@ -779,6 +781,61 @@ self._env.parallel_devices.pMap(individual_device_tear_down) + def _SetDefaultBrowserApp(self, dev): + # Safely granting the browser role requires the + # "set-bypassing-role-qualification" ADB command, which was introduced in + # Android 13 (API 33). + if dev.build_version_sdk < version_codes.TIRAMISU: + return + + browser_activity_names = self._test_instance.test_apk.GetActivityNamesWithCategory( + 'android.intent.category.APP_BROWSER') + if browser_activity_names: + # By default, the add-role-holder command targets the system user + # (User 0). + # + # However, some bots (such as automotive bots) run in the Headless System + # User Mode, where User 0 runs in the background, while the actual + # "driver" user is usually User 10 (or higher). + # + # Therefore, we must specify the current user ID when running the + # add-role-holder command as the test APK may not be installed for + # User 0. + # + # Additionally, we should bypass role qualification in case the test APK + # doesn't meet Android requirements for the browser role (such as + # declaring specific Intent filters in its manifest to handle web links). + user_id = dev.GetCurrentUser() + dev.RunShellCommand( + ['cmd', 'role', 'set-bypassing-role-qualification', 'true'], + check_return=True) + dev.RunShellCommand([ + 'cmd', 'role', 'add-role-holder', '--user', + str(user_id), 'android.app.role.BROWSER', + self._test_instance.test_apk.GetPackageName() + ], + check_return=True) + + def _ClearDefaultBrowserApp(self, dev): + # We only set the test APK as the default browser app for Android 13+. + # See _SetDefaultBrowserApp(). + if dev.build_version_sdk < version_codes.TIRAMISU: + return + + browser_activity_names = self._test_instance.test_apk.GetActivityNamesWithCategory( + 'android.intent.category.APP_BROWSER') + if browser_activity_names: + user_id = dev.GetCurrentUser() + dev.RunShellCommand([ + 'cmd', 'role', 'remove-role-holder', '--user', + str(user_id), 'android.app.role.BROWSER', + self._test_instance.test_apk.GetPackageName() + ], + check_return=True) + dev.RunShellCommand( + ['cmd', 'role', 'set-bypassing-role-qualification', 'false'], + check_return=True) + def _ToggleAppLinks(self, dev, state): # The set-app-links command was added in Android 12 (sdk = 31). The # restrictions that require us to set the app links were also added in
diff --git a/build/config/android/rules.gni b/build/config/android/rules.gni index 2aebf6c..a8ab90dd 100644 --- a/build/config/android/rules.gni +++ b/build/config/android/rules.gni
@@ -209,7 +209,11 @@ # } template("java_cpp_enum") { action_with_pydeps(target_name) { - forward_variables_from(invoker, TESTONLY_AND_VISIBILITY + [ "sources" ]) + forward_variables_from(invoker, + TESTONLY_AND_VISIBILITY + [ + "sources", + "deps", + ]) # The sources aren't compiled so don't check their dependencies. check_includes = false
diff --git a/build/config/sanitizers/BUILD.gn b/build/config/sanitizers/BUILD.gn index c748ab4..0b9a92f 100644 --- a/build/config/sanitizers/BUILD.gn +++ b/build/config/sanitizers/BUILD.gn
@@ -496,14 +496,6 @@ "-mllvm", "-sanitizer-coverage-prune-blocks=1", ] - - if (current_cpu == "arm") { - # http://crbug.com/517105 - cflags += [ - "-mllvm", - "-sanitizer-coverage-block-threshold=0", - ] - } } if (sanitizer_coverage_allowlist != "") { cflags += [ "-fsanitize-coverage-allowlist=" +
diff --git a/cc/paint/decoded_draw_image.cc b/cc/paint/decoded_draw_image.cc index 5ebf482a..ec26ab2 100644 --- a/cc/paint/decoded_draw_image.cc +++ b/cc/paint/decoded_draw_image.cc
@@ -18,22 +18,21 @@ bool is_budgeted) : DecodedDrawImage(std::move(image), nullptr, - std::nullopt, + gfx::HDRMetadata(), std::move(dark_mode_color_filter), src_rect_offset, scale_adjustment, filter_quality, is_budgeted) {} -DecodedDrawImage::DecodedDrawImage( - sk_sp<SkImage> image, - sk_sp<SkImage> gainmap_image, - const std::optional<gfx::HDRMetadata>& hdr_metadata, - sk_sp<ColorFilter> dark_mode_color_filter, - const SkSize& src_rect_offset, - const SkSize& scale_adjustment, - PaintFlags::FilterQuality filter_quality, - bool is_budgeted) +DecodedDrawImage::DecodedDrawImage(sk_sp<SkImage> image, + sk_sp<SkImage> gainmap_image, + const gfx::HDRMetadata& hdr_metadata, + sk_sp<ColorFilter> dark_mode_color_filter, + const SkSize& src_rect_offset, + const SkSize& scale_adjustment, + PaintFlags::FilterQuality filter_quality, + bool is_budgeted) : image_(std::move(image)), gainmap_image_(std::move(gainmap_image)), hdr_metadata_(hdr_metadata),
diff --git a/cc/paint/decoded_draw_image.h b/cc/paint/decoded_draw_image.h index c55922f..0660ea9 100644 --- a/cc/paint/decoded_draw_image.h +++ b/cc/paint/decoded_draw_image.h
@@ -36,7 +36,7 @@ bool is_budgeted); DecodedDrawImage(sk_sp<SkImage> image, sk_sp<SkImage> gainmap_image, - const std::optional<gfx::HDRMetadata>& hdr_metadata, + const gfx::HDRMetadata& hdr_metadata, sk_sp<ColorFilter> dark_mode_color_filter, const SkSize& src_rect_offset, const SkSize& scale_adjustment, @@ -61,9 +61,7 @@ const sk_sp<SkImage>& image() const { return image_; } const sk_sp<SkImage>& gainmap_image() const { return gainmap_image_; } - const std::optional<gfx::HDRMetadata>& hdr_metadata() const { - return hdr_metadata_; - } + const gfx::HDRMetadata& hdr_metadata() const { return hdr_metadata_; } const sk_sp<ColorFilter>& dark_mode_color_filter() const { return dark_mode_color_filter_; } @@ -92,7 +90,7 @@ private: sk_sp<SkImage> image_; sk_sp<SkImage> gainmap_image_; - std::optional<gfx::HDRMetadata> hdr_metadata_; + gfx::HDRMetadata hdr_metadata_; gpu::Mailbox mailbox_; std::optional<uint32_t> transfer_cache_entry_id_; sk_sp<ColorFilter> dark_mode_color_filter_;
diff --git a/cc/paint/image_transfer_cache_entry.cc b/cc/paint/image_transfer_cache_entry.cc index 8d924ed..2a9f14e 100644 --- a/cc/paint/image_transfer_cache_entry.cc +++ b/cc/paint/image_transfer_cache_entry.cc
@@ -491,7 +491,7 @@ ClientImageTransferCacheEntry::ClientImageTransferCacheEntry( const Image& image, bool needs_mips, - const std::optional<gfx::HDRMetadata>& hdr_metadata, + const gfx::HDRMetadata& hdr_metadata, sk_sp<SkColorSpace> target_color_space) : needs_mips_(needs_mips), target_color_space_(target_color_space), @@ -538,9 +538,9 @@ bool has_gainmap = gainmap_image_.has_value(); writer.Write(has_gainmap); writer.Write(needs_mips_); - writer.Write(hdr_metadata_.has_value()); - if (hdr_metadata_.has_value()) { - writer.Write(hdr_metadata_.value()); + writer.Write(!hdr_metadata_.IsEmpty()); + if (!hdr_metadata_.IsEmpty()) { + writer.Write(hdr_metadata_); } writer.Write(target_color_space_.get()); WriteImage(writer, image_); @@ -561,8 +561,8 @@ safe_size += PaintOpWriter::SerializedSize<bool>(); // has_gainmap safe_size += PaintOpWriter::SerializedSize<bool>(); // needs_mips safe_size += PaintOpWriter::SerializedSize<bool>(); // has_hdr_metadata - if (hdr_metadata_.has_value()) { - safe_size += PaintOpWriter::SerializedSize(hdr_metadata_.value()); + if (!hdr_metadata_.IsEmpty()) { + safe_size += PaintOpWriter::SerializedSize(hdr_metadata_); } safe_size += PaintOpWriter::SerializedSize(target_color_space_.get()); safe_size += SafeSizeForImage(image_);
diff --git a/cc/paint/image_transfer_cache_entry.h b/cc/paint/image_transfer_cache_entry.h index 582e860..caa3657 100644 --- a/cc/paint/image_transfer_cache_entry.h +++ b/cc/paint/image_transfer_cache_entry.h
@@ -84,7 +84,7 @@ ClientImageTransferCacheEntry( const Image& image, bool needs_mips, - const std::optional<gfx::HDRMetadata>& hdr_metadata = std::nullopt, + const gfx::HDRMetadata& hdr_metadata, sk_sp<SkColorSpace> target_color_space = nullptr); ClientImageTransferCacheEntry(const Image& image, const Image& gainmap_image, @@ -121,7 +121,7 @@ std::optional<SkGainmapInfo> gainmap_info_; // The HDR metadata for non-gainmap HDR metadata. - std::optional<gfx::HDRMetadata> hdr_metadata_; + gfx::HDRMetadata hdr_metadata_; }; class CC_PAINT_EXPORT ServiceImageTransferCacheEntry final @@ -183,9 +183,7 @@ size_t num_planes() const { return plane_images_.size(); } bool fits_on_gpu() const; - const std::optional<gfx::HDRMetadata>& hdr_metadata() const { - return hdr_metadata_; - } + const gfx::HDRMetadata& hdr_metadata() const { return hdr_metadata_; } private: raw_ptr<GrDirectContext> gr_context_ = nullptr; @@ -199,7 +197,7 @@ // HDR metadata used by global tone map application and (potentially but not // yet) gain map application. - std::optional<gfx::HDRMetadata> hdr_metadata_; + gfx::HDRMetadata hdr_metadata_; // The value of `size_` is computed during deserialization and never updated // (even if the size of the image changes due to mipmaps being requested).
diff --git a/cc/paint/image_transfer_cache_entry_unittest.cc b/cc/paint/image_transfer_cache_entry_unittest.cc index 7675678..55fed083 100644 --- a/cc/paint/image_transfer_cache_entry_unittest.cc +++ b/cc/paint/image_transfer_cache_entry_unittest.cc
@@ -249,7 +249,7 @@ auto client_entry(std::make_unique<ClientImageTransferCacheEntry>( ClientImageTransferCacheEntry::Image(yuva_pixmaps.planes(), yuva_info, nullptr /* decoded color space*/), - true /* needs_mips */, std::nullopt)); + true /* needs_mips */, gfx::HDRMetadata())); uint32_t size = client_entry->SerializedSize(); auto data = PaintOpWriter::AllocateAlignedBuffer<uint8_t>(size); ASSERT_TRUE(client_entry->Serialize( @@ -400,7 +400,7 @@ ClientImageTransferCacheEntry client_entry( ClientImageTransferCacheEntry::Image(&bitmap.pixmap()), true, - std::nullopt); + gfx::HDRMetadata()); const uint32_t storage_size = client_entry.SerializedSize(); auto storage = PaintOpWriter::AllocateAlignedBuffer<uint8_t>(storage_size); client_entry.Serialize(base::span(storage.get(), storage_size)); @@ -430,7 +430,7 @@ SkImageInfo::MakeN32Premul(gr_context->maxTextureSize() + 1, 10)); ClientImageTransferCacheEntry client_entry( ClientImageTransferCacheEntry::Image(&bitmap.pixmap()), false, - std::nullopt); + gfx::HDRMetadata()); const uint32_t storage_size = client_entry.SerializedSize(); auto storage = PaintOpWriter::AllocateAlignedBuffer<uint8_t>(storage_size); client_entry.Serialize(base::span(storage.get(), storage_size)); @@ -451,7 +451,5 @@ EXPECT_EQ(pre_mip_image, service_entry.image()); } - - } // namespace } // namespace cc
diff --git a/cc/paint/oop_pixeltest.cc b/cc/paint/oop_pixeltest.cc index adb3fb3..8c3cda2 100644 --- a/cc/paint/oop_pixeltest.cc +++ b/cc/paint/oop_pixeltest.cc
@@ -1079,13 +1079,12 @@ sk_make_sp<FakePaintImageGenerator>(image->imageInfo()); { ImageHeaderMetadata image_metadata; - image_metadata.hdr_metadata.emplace(); if (peak_luminance.has_value()) { - image_metadata.hdr_metadata->cta_861_3.emplace(peak_luminance.value(), - kContentAvgNits); + image_metadata.hdr_metadata.cta_861_3.emplace(peak_luminance.value(), + kContentAvgNits); } if (white_luminance.has_value()) { - image_metadata.hdr_metadata->ndwl.emplace(white_luminance.value()); + image_metadata.hdr_metadata.ndwl.emplace(white_luminance.value()); } image_generator->SetImageHeaderMetadata(image_metadata); EXPECT_TRUE(image->peekPixels(&image_generator->GetPixmap()));
diff --git a/cc/paint/paint_image.h b/cc/paint/paint_image.h index 1454081..4f60edcb 100644 --- a/cc/paint/paint_image.h +++ b/cc/paint/paint_image.h
@@ -94,8 +94,8 @@ // The subsampling format used for the chroma planes, e.g., YUV 4:2:0. YUVSubsampling yuv_subsampling = YUVSubsampling::kUnknown; - // The HDR metadata included with the image, if present. - std::optional<gfx::HDRMetadata> hdr_metadata; + // Any HDR metadata included with the image. + gfx::HDRMetadata hdr_metadata; // The visible size of the image (i.e., the area that contains meaningful // pixels). @@ -374,11 +374,11 @@ return gainmap_info_.value(); } - std::optional<gfx::HDRMetadata> GetHDRMetadata() const { + gfx::HDRMetadata GetHDRMetadata() const { if (const auto* image_metadata = GetImageHeaderMetadata()) { return image_metadata->hdr_metadata; } - return std::nullopt; + return gfx::HDRMetadata(); } std::string ToString() const; @@ -435,7 +435,7 @@ // HDR metadata used by global tone map application and (potentially but not // yet) gain map application. - std::optional<gfx::HDRMetadata> hdr_metadata_; + gfx::HDRMetadata hdr_metadata_; sk_sp<TextureBacking> texture_backing_;
diff --git a/cc/paint/paint_image_builder.h b/cc/paint/paint_image_builder.h index 67eb68d..c6354eed 100644 --- a/cc/paint/paint_image_builder.h +++ b/cc/paint/paint_image_builder.h
@@ -86,8 +86,7 @@ paint_image_.gainmap_info_ = gainmap_info; return std::move(*this); } - PaintImageBuilder&& set_hdr_metadata( - std::optional<gfx::HDRMetadata> hdr_metadata) { + PaintImageBuilder&& set_hdr_metadata(gfx::HDRMetadata hdr_metadata) { paint_image_.hdr_metadata_ = hdr_metadata; return std::move(*this); }
diff --git a/cc/paint/paint_op.cc b/cc/paint/paint_op.cc index 4970adfa..0d2bf56f 100644 --- a/cc/paint/paint_op.cc +++ b/cc/paint/paint_op.cc
@@ -1323,7 +1323,7 @@ // Retrieve the SkImages and sampling. sk_sp<SkImage> sk_image; sk_sp<SkImage> gainmap_sk_image; - std::optional<gfx::HDRMetadata> hdr_metadata; + gfx::HDRMetadata hdr_metadata; SkSamplingOptions sampling = op->sampling; // If the SkImages are from an ImageProvider, keep them in scope. ImageProvider::ScopedResult scoped_result; @@ -1441,7 +1441,7 @@ // Retrieve the SkImages, adjusted source rect, and sampling. sk_sp<SkImage> sk_image; sk_sp<SkImage> gainmap_sk_image; - std::optional<gfx::HDRMetadata> hdr_metadata; + gfx::HDRMetadata hdr_metadata; SkRect adjusted_src; SkSamplingOptions sampling; // If the SkImages are from an ImageProvider, keep them in scope.
diff --git a/cc/paint/paint_op_reader.cc b/cc/paint/paint_op_reader.cc index ae42bd05..40f0a505 100644 --- a/cc/paint/paint_op_reader.cc +++ b/cc/paint/paint_op_reader.cc
@@ -538,9 +538,7 @@ builder = std::move(builder).set_gainmap_texture_image( entry->gainmap_image(), entry->gainmap_info()); } - if (entry->hdr_metadata().has_value()) { - builder = std::move(builder).set_hdr_metadata(entry->hdr_metadata()); - } + builder = std::move(builder).set_hdr_metadata(entry->hdr_metadata()); *image = builder.TakePaintImage(); } }
diff --git a/cc/paint/tone_map_util.cc b/cc/paint/tone_map_util.cc index bc71c01..a7b653f 100644 --- a/cc/paint/tone_map_util.cc +++ b/cc/paint/tone_map_util.cc
@@ -243,7 +243,7 @@ void ToneMapUtil::AddGlobalToneMapFilterToPaint( SkPaint& paint, const SkImage* image, - const std::optional<gfx::HDRMetadata>& metadata, + const gfx::HDRMetadata& metadata, float target_hdr_headroom) { if (!image || !image->colorSpace()) { return; @@ -252,8 +252,8 @@ image->colorSpace()->transferFn(&trfn); gfx::HdrMetadataAgtmParsed agtm; - const bool agtm_parsed = metadata.has_value() && metadata->agtm.has_value() && - agtm.Parse(metadata->agtm.value()); + const bool agtm_parsed = + metadata.agtm.has_value() && agtm.Parse(metadata.agtm.value()); // The remainder of the function will construct `filter` to perform all // transformations (scaling, OOTF, and tone mapping). @@ -267,9 +267,8 @@ return agtm.hdr_reference_white; } // Then NDWL. - if (metadata.has_value() && metadata->ndwl.has_value() && - metadata->ndwl->nits > 0.f) { - return metadata->ndwl->nits; + if (metadata.ndwl.has_value() && metadata.ndwl->nits > 0.f) { + return metadata.ndwl->nits; } // Then defer to the source color space. if (skcms_TransferFunction_isPQ(&trfn) ||
diff --git a/cc/paint/tone_map_util.h b/cc/paint/tone_map_util.h index 23cf360..16861e1 100644 --- a/cc/paint/tone_map_util.h +++ b/cc/paint/tone_map_util.h
@@ -35,11 +35,10 @@ static bool UseGlobalToneMapFilter(const SkColorSpace* cs); // Add a color filter to `paint` that will perform tone mapping. - static void AddGlobalToneMapFilterToPaint( - SkPaint& paint, - const SkImage* image, - const std::optional<gfx::HDRMetadata>& metadata, - float target_hdr_headroom); + static void AddGlobalToneMapFilterToPaint(SkPaint& paint, + const SkImage* image, + const gfx::HDRMetadata& metadata, + float target_hdr_headroom); }; } // namespace cc
diff --git a/cc/test/test_options_provider.cc b/cc/test/test_options_provider.cc index 23f23d9..40ac64ba 100644 --- a/cc/test/test_options_provider.cc +++ b/cc/test/test_options_provider.cc
@@ -113,7 +113,7 @@ // Create a transfer cache entry for this image. ClientImageTransferCacheEntry cache_entry( ClientImageTransferCacheEntry::Image(&bitmap.pixmap()), - false /* needs_mips */, std::nullopt); + false /* needs_mips */, gfx::HDRMetadata()); const uint32_t data_size = cache_entry.SerializedSize(); auto data = PaintOpWriter::AllocateAlignedBuffer<uint8_t>(data_size); if (!cache_entry.Serialize(
diff --git a/cc/tiles/gpu_image_decode_cache.cc b/cc/tiles/gpu_image_decode_cache.cc index 1f2897bb..f377c56 100644 --- a/cc/tiles/gpu_image_decode_cache.cc +++ b/cc/tiles/gpu_image_decode_cache.cc
@@ -2212,7 +2212,7 @@ ToneMapUtil::UseGlobalToneMapFilter(decoded_color_space.get())) { target_color_space = nullptr; } - const std::optional<gfx::HDRMetadata> hdr_metadata = + const gfx::HDRMetadata& hdr_metadata = draw_image.paint_image().GetHDRMetadata(); std::array<ClientImageTransferCacheEntry::Image, kAuxImageCount> image;
diff --git a/cc/tiles/software_image_decode_cache_utils.cc b/cc/tiles/software_image_decode_cache_utils.cc index f4f6fb1..8f9d9912 100644 --- a/cc/tiles/software_image_decode_cache_utils.cc +++ b/cc/tiles/software_image_decode_cache_utils.cc
@@ -462,7 +462,7 @@ SoftwareImageDecodeCacheUtils::CacheEntry::CacheEntry( sk_sp<SkImage> image, sk_sp<SkImage> gainmap_image, - const std::optional<gfx::HDRMetadata>& hdr_metadata, + const gfx::HDRMetadata& hdr_metadata, std::unique_ptr<base::DiscardableMemory> in_memory, const SkSize& src_rect_offset) : is_locked(true),
diff --git a/cc/tiles/software_image_decode_cache_utils.h b/cc/tiles/software_image_decode_cache_utils.h index f315bfb..11c3dbf5 100644 --- a/cc/tiles/software_image_decode_cache_utils.h +++ b/cc/tiles/software_image_decode_cache_utils.h
@@ -130,7 +130,7 @@ CacheEntry(); CacheEntry(sk_sp<SkImage> image, sk_sp<SkImage> gainmap_image, - const std::optional<gfx::HDRMetadata>& hdr_metadata, + const gfx::HDRMetadata& hdr_metadata, std::unique_ptr<base::DiscardableMemory> memory, const SkSize& src_rect_offset); ~CacheEntry(); @@ -150,7 +150,7 @@ DCHECK(is_locked); return gainmap_image_; } - const std::optional<gfx::HDRMetadata>& hdr_metadata() const { + const gfx::HDRMetadata& hdr_metadata() const { DCHECK(is_locked); return hdr_metadata_; } @@ -185,7 +185,7 @@ private: sk_sp<SkImage> image_; sk_sp<SkImage> gainmap_image_; - std::optional<gfx::HDRMetadata> hdr_metadata_; + gfx::HDRMetadata hdr_metadata_; SkSize src_rect_offset_; uint64_t tracing_id_; // Indicates whether this entry was ever in the cache.
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn index 536648e..b8bd6d9 100644 --- a/chrome/android/BUILD.gn +++ b/chrome/android/BUILD.gn
@@ -1131,7 +1131,6 @@ "//chrome/browser/search_engines/android:junit", "//chrome/browser/search_resumption:junit", "//chrome/browser/serial/android:junit", - "//chrome/browser/settings:junit_tests", "//chrome/browser/signin/services/android:junit", "//chrome/browser/single_tab/android:junit", "//chrome/browser/supervised_user:junit",
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabArchiveSettingsFragment.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabArchiveSettingsFragment.java index 58199dae..747d282 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabArchiveSettingsFragment.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabArchiveSettingsFragment.java
@@ -14,7 +14,7 @@ import org.chromium.chrome.R; import org.chromium.chrome.browser.preferences.ChromeSharedPreferences; import org.chromium.chrome.browser.settings.ChromeBaseSettingsFragment; -import org.chromium.chrome.browser.settings.search.BaseSearchIndexProvider; +import org.chromium.chrome.browser.settings.search.ChromeBaseSearchIndexProvider; import org.chromium.chrome.browser.tab.TabArchiveSettings; import org.chromium.chrome.browser.tab.TabArchiveSettings.Observer; import org.chromium.components.browser_ui.settings.ChromeSwitchPreference; @@ -115,7 +115,7 @@ return AnimationType.PROPERTY; } - public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = - new BaseSearchIndexProvider( + public static final ChromeBaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = + new ChromeBaseSearchIndexProvider( TabArchiveSettingsFragment.class.getName(), R.xml.tab_archive_settings); }
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabsSettings.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabsSettings.java index 02fb7fd..c33aa2d 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabsSettings.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabsSettings.java
@@ -22,6 +22,7 @@ import org.chromium.chrome.browser.preferences.ChromeSharedPreferences; import org.chromium.chrome.browser.preferences.Pref; import org.chromium.chrome.browser.settings.ChromeBaseSettingsFragment; +import org.chromium.chrome.browser.settings.search.ChromeBaseSearchIndexProvider; import org.chromium.chrome.browser.tab.TabArchiveSettings; import org.chromium.chrome.browser.tab_group_sync.TabGroupSyncFeatures; import org.chromium.components.browser_ui.settings.ChromeSwitchPreference; @@ -167,4 +168,8 @@ public @Nullable String getMainMenuKey() { return "tabs"; } + + // TODO(crbug.com/444470792): Determine what pieces of logic are dynamic and need handling. + public static final ChromeBaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = + new ChromeBaseSearchIndexProvider(TabsSettings.class.getName(), R.xml.tabs_settings); }
diff --git a/chrome/android/java/res/xml/main_preferences.xml b/chrome/android/java/res/xml/main_preferences.xml index 7a5712a..a783fb73a 100644 --- a/chrome/android/java/res/xml/main_preferences.xml +++ b/chrome/android/java/res/xml/main_preferences.xml
@@ -8,8 +8,9 @@ <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:orderingFromXml="false"> -<!-- `order=0` is reserved and it will be added in code. --> -<!-- TODO(crbug.com/364906215): Move SettingsPromoCardPreference here once SyncPromoPreference is removed --> + <org.chromium.chrome.browser.ui.settings_promo_card.SettingsPromoCardPreference + android:key="settings_promo_card" + android:order="0" /> <PreferenceCategory android:key="account_and_google_services_section" android:order="1"
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java index a1f82e7..5e06afd 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
@@ -3218,8 +3218,8 @@ } @Override - public int getTabCountForRelaunchFromSharedPrefs() { - return MultiWindowUtils.getTabCountForRelaunchFromSharedPrefs(mWindowId); + public int getTabCountForRelaunchFromPersistentStore() { + return MultiWindowUtils.getTabCountForRelaunchFromPersistentStore(mWindowId); } }; } @@ -3322,15 +3322,15 @@ if (startIncognito) mTabModelSelector.selectModel(true); } - TabModelSelectorObserver getTabModelSelectorObserverForTesting() { + public TabModelSelectorObserver getTabModelSelectorObserverForTesting() { return mTabModelSelectorObserver; } - boolean getCreatedTabOnStartupForTesting() { + public boolean getCreatedTabOnStartupForTesting() { return mCreatedTabOnStartup; } - void setCreatedTabOnStartupForTesting(boolean createdTabOnStartup) { + public void setCreatedTabOnStartupForTesting(boolean createdTabOnStartup) { mCreatedTabOnStartup = createdTabOnStartup; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/about_settings/AboutChromeSettings.java b/chrome/android/java/src/org/chromium/chrome/browser/about_settings/AboutChromeSettings.java index b4db437..3e4f90d0 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/about_settings/AboutChromeSettings.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/about_settings/AboutChromeSettings.java
@@ -21,7 +21,7 @@ import org.chromium.build.annotations.Nullable; import org.chromium.chrome.R; import org.chromium.chrome.browser.settings.ChromeBaseSettingsFragment; -import org.chromium.chrome.browser.settings.search.BaseSearchIndexProvider; +import org.chromium.chrome.browser.settings.search.ChromeBaseSearchIndexProvider; import org.chromium.chrome.browser.tracing.settings.DeveloperSettings; import org.chromium.components.browser_ui.settings.EmbeddableSettingsPage; import org.chromium.components.browser_ui.settings.SettingsFragment; @@ -76,7 +76,9 @@ p.setSummary(AboutSettingsBridge.getOSVersion()); p = findPreference(PREF_LEGAL_INFORMATION); assumeNonNull(p); - int currentYear = CalendarFactory.get().get(Calendar.YEAR); + Calendar calendar = CalendarFactory.get(); + calendar.setTimeInMillis(System.currentTimeMillis()); + int currentYear = calendar.get(Calendar.YEAR); p.setSummary(getString(R.string.legal_information_summary, currentYear)); } @@ -158,7 +160,7 @@ return "about_chrome"; } - public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = - new BaseSearchIndexProvider( + public static final ChromeBaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = + new ChromeBaseSearchIndexProvider( AboutChromeSettings.class.getName(), R.xml.about_chrome_preferences); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/about_settings/LegalInformationSettings.java b/chrome/android/java/src/org/chromium/chrome/browser/about_settings/LegalInformationSettings.java index cceeefc..afb4b5b 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/about_settings/LegalInformationSettings.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/about_settings/LegalInformationSettings.java
@@ -12,7 +12,7 @@ import org.chromium.build.annotations.Nullable; import org.chromium.chrome.R; import org.chromium.chrome.browser.settings.ChromeBaseSettingsFragment; -import org.chromium.chrome.browser.settings.search.BaseSearchIndexProvider; +import org.chromium.chrome.browser.settings.search.ChromeBaseSearchIndexProvider; import org.chromium.components.browser_ui.settings.EmbeddableSettingsPage; import org.chromium.components.browser_ui.settings.SettingsFragment; import org.chromium.components.browser_ui.settings.SettingsUtils; @@ -39,7 +39,7 @@ return SettingsFragment.AnimationType.PROPERTY; } - public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = - new BaseSearchIndexProvider( + public static final ChromeBaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = + new ChromeBaseSearchIndexProvider( LegalInformationSettings.class.getName(), R.xml.legal_information_preferences); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/appearance/settings/AppearanceSettingsFragment.java b/chrome/android/java/src/org/chromium/chrome/browser/appearance/settings/AppearanceSettingsFragment.java index 9376066..4265f55 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/appearance/settings/AppearanceSettingsFragment.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/appearance/settings/AppearanceSettingsFragment.java
@@ -27,6 +27,7 @@ import org.chromium.chrome.browser.preferences.PrefServiceUtil; import org.chromium.chrome.browser.settings.ChromeBaseSettingsFragment; import org.chromium.chrome.browser.settings.ChromeManagedPreferenceDelegate; +import org.chromium.chrome.browser.settings.search.ChromeBaseSearchIndexProvider; import org.chromium.chrome.browser.toolbar.adaptive.AdaptiveToolbarStatePredictor; import org.chromium.components.browser_ui.settings.ChromeSwitchPreference; import org.chromium.components.browser_ui.settings.CustomDividerFragment; @@ -281,4 +282,10 @@ @Nullable PrefObserver getPrefObserverForTesting() { return mPrefObserver; } + + // TODO(crbug.com/444470792): Determine what pieces of logic are dynamic and need handling. Some + // changes here need to be reflected in MainSettings as well. + public static final ChromeBaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = + new ChromeBaseSearchIndexProvider( + AppearanceSettingsFragment.class.getName(), R.xml.appearance_preferences); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill/settings/AndroidPaymentAppsFragment.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill/settings/AndroidPaymentAppsFragment.java index 3f4adee4..0978baf 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/autofill/settings/AndroidPaymentAppsFragment.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill/settings/AndroidPaymentAppsFragment.java
@@ -23,6 +23,7 @@ import org.chromium.chrome.R; import org.chromium.chrome.browser.payments.ServiceWorkerPaymentAppBridge; import org.chromium.chrome.browser.settings.ChromeBaseSettingsFragment; +import org.chromium.chrome.browser.settings.search.ChromeBaseSearchIndexProvider; import org.chromium.components.browser_ui.settings.EmbeddableSettingsPage; import org.chromium.components.browser_ui.settings.SettingsFragment; import org.chromium.components.browser_ui.settings.TextMessagePreference; @@ -116,4 +117,10 @@ public @SettingsFragment.AnimationType int getAnimationType() { return SettingsFragment.AnimationType.PROPERTY; } + + // TODO(crbug.com/444470792): Determine what pieces of logic are dynamic and need handling. This + // also includes checking if there are any subprefs that need to be built on the fly due to no + // xml file. + public static final ChromeBaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = + new ChromeBaseSearchIndexProvider(AndroidPaymentAppsFragment.class.getName(), 0); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill/settings/AutofillBuyNowPayLaterFragment.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill/settings/AutofillBuyNowPayLaterFragment.java index 375b536..d061d58 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/autofill/settings/AutofillBuyNowPayLaterFragment.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill/settings/AutofillBuyNowPayLaterFragment.java
@@ -29,6 +29,7 @@ import org.chromium.chrome.browser.autofill.PersonalDataManager; import org.chromium.chrome.browser.autofill.PersonalDataManagerFactory; import org.chromium.chrome.browser.settings.ChromeBaseSettingsFragment; +import org.chromium.chrome.browser.settings.search.ChromeBaseSearchIndexProvider; import org.chromium.components.autofill.payments.BnplIssuerForSettings; import org.chromium.components.browser_ui.settings.ChromeBasePreference; import org.chromium.components.browser_ui.settings.ChromeSwitchPreference; @@ -198,4 +199,9 @@ public @SettingsFragment.AnimationType int getAnimationType() { return SettingsFragment.AnimationType.PROPERTY; } + + // TODO(crbug.com/444470792): Determine what pieces of logic are dynamic and need handling. Any + // entries that need to be built on the fly? + public static final ChromeBaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = + new ChromeBaseSearchIndexProvider(AutofillBuyNowPayLaterFragment.class.getName(), 0); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill/settings/AutofillCardBenefitsFragment.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill/settings/AutofillCardBenefitsFragment.java index c2747fe4..2558a82 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/autofill/settings/AutofillCardBenefitsFragment.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill/settings/AutofillCardBenefitsFragment.java
@@ -39,6 +39,7 @@ import org.chromium.chrome.browser.autofill.PersonalDataManagerFactory; import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.settings.ChromeBaseSettingsFragment; +import org.chromium.chrome.browser.settings.search.ChromeBaseSearchIndexProvider; import org.chromium.components.autofill.ImageSize; import org.chromium.components.browser_ui.settings.ChromeBasePreference; import org.chromium.components.browser_ui.settings.ChromeSwitchPreference; @@ -298,4 +299,9 @@ public @SettingsFragment.AnimationType int getAnimationType() { return SettingsFragment.AnimationType.PROPERTY; } + + // TODO(crbug.com/444470792): Determine what pieces of logic are dynamic and need handling. Any + // entries that need adding? + public static final ChromeBaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = + new ChromeBaseSearchIndexProvider(AutofillCardBenefitsFragment.class.getName(), 0); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill/settings/AutofillPaymentMethodsFragment.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill/settings/AutofillPaymentMethodsFragment.java index 73ccf6ad..8ce3b900 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/autofill/settings/AutofillPaymentMethodsFragment.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill/settings/AutofillPaymentMethodsFragment.java
@@ -53,6 +53,7 @@ import org.chromium.chrome.browser.settings.ChromeBaseSettingsFragment; import org.chromium.chrome.browser.settings.ChromeManagedPreferenceDelegate; import org.chromium.chrome.browser.settings.SettingsNavigationFactory; +import org.chromium.chrome.browser.settings.search.ChromeBaseSearchIndexProvider; import org.chromium.components.autofill.IbanRecordType; import org.chromium.components.autofill.ImageSize; import org.chromium.components.autofill.MandatoryReauthAuthenticationFlowEvent; @@ -847,4 +848,9 @@ && ChromeFeatureList.isEnabled( ChromeFeatureList.THIRD_PARTY_DISABLE_CHROME_AUTOFILL_SETTINGS_SCREEN); } + + // TODO(crbug.com/444470792): Determine what pieces of logic are dynamic and need handling. Any + // entries that need adding? + public static final ChromeBaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = + new ChromeBaseSearchIndexProvider(AutofillPaymentMethodsFragment.class.getName(), 0); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill/settings/AutofillProfilesFragment.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill/settings/AutofillProfilesFragment.java index 8a43d29..e1279875 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/autofill/settings/AutofillProfilesFragment.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill/settings/AutofillProfilesFragment.java
@@ -45,6 +45,7 @@ import org.chromium.chrome.browser.settings.ChromeBaseSettingsFragment; import org.chromium.chrome.browser.settings.ChromeManagedPreferenceDelegate; import org.chromium.chrome.browser.settings.SettingsNavigationFactory; +import org.chromium.chrome.browser.settings.search.ChromeBaseSearchIndexProvider; import org.chromium.chrome.browser.signin.services.IdentityServicesProvider; import org.chromium.chrome.browser.sync.SyncServiceFactory; import org.chromium.components.autofill.AutofillProfile; @@ -453,4 +454,9 @@ && ChromeFeatureList.isEnabled( ChromeFeatureList.THIRD_PARTY_DISABLE_CHROME_AUTOFILL_SETTINGS_SCREEN); } + + // TODO(crbug.com/444470792): Determine what pieces of logic are dynamic and need handling. Any + // entries that need adding? + public static final ChromeBaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = + new ChromeBaseSearchIndexProvider(AutofillProfilesFragment.class.getName(), 0); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill/settings/FinancialAccountsManagementFragment.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill/settings/FinancialAccountsManagementFragment.java index 37e82c2..21a7192 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/autofill/settings/FinancialAccountsManagementFragment.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill/settings/FinancialAccountsManagementFragment.java
@@ -31,6 +31,7 @@ import org.chromium.chrome.browser.customtabs.CustomTabActivity; import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.settings.ChromeBaseSettingsFragment; +import org.chromium.chrome.browser.settings.search.ChromeBaseSearchIndexProvider; import org.chromium.components.autofill.ImageSize; import org.chromium.components.autofill.payments.AccountType; import org.chromium.components.autofill.payments.BankAccount; @@ -300,4 +301,10 @@ public @SettingsFragment.AnimationType int getAnimationType() { return SettingsFragment.AnimationType.PROPERTY; } + + // TODO(crbug.com/444470792): Determine what pieces of logic are dynamic and need handling. + // Should this prefs parent pass a title in the Bundle args? Any entries that need adding? + public static final ChromeBaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = + new ChromeBaseSearchIndexProvider( + FinancialAccountsManagementFragment.class.getName(), 0); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill/settings/NonCardPaymentMethodsManagementFragment.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill/settings/NonCardPaymentMethodsManagementFragment.java index 24f865a4..2b081b0 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/autofill/settings/NonCardPaymentMethodsManagementFragment.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill/settings/NonCardPaymentMethodsManagementFragment.java
@@ -29,6 +29,7 @@ import org.chromium.chrome.browser.customtabs.CustomTabActivity; import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.settings.ChromeBaseSettingsFragment; +import org.chromium.chrome.browser.settings.search.ChromeBaseSearchIndexProvider; import org.chromium.components.autofill.ImageSize; import org.chromium.components.autofill.payments.Ewallet; import org.chromium.components.browser_ui.settings.ChromeSwitchPreference; @@ -214,4 +215,10 @@ public @SettingsFragment.AnimationType int getAnimationType() { return SettingsFragment.AnimationType.PROPERTY; } + + // TODO(crbug.com/444470792): Determine what pieces of logic are dynamic and need handling. Any + // entries that need adding? + public static final ChromeBaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = + new ChromeBaseSearchIndexProvider( + NonCardPaymentMethodsManagementFragment.class.getName(), 0); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/base/SplitCompatAppComponentFactory.java b/chrome/android/java/src/org/chromium/chrome/browser/base/SplitCompatAppComponentFactory.java index 6712d6f2..69ce7c40 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/base/SplitCompatAppComponentFactory.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/base/SplitCompatAppComponentFactory.java
@@ -25,7 +25,6 @@ import org.chromium.build.annotations.Nullable; import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.incognito_window.PreAttachIntentObserver; -import org.chromium.ui.base.DeviceFormFactor; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -80,12 +79,7 @@ getComponentClassLoader(cl, className), className, intent); if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.UPSIDE_DOWN_CAKE - && - // TODO(crbug.com/448671285): Change to call - // IncognitoUtils#shouldOpenIncognitoAsWindow() - (ChromeFeatureList.sAndroidOpenIncognitoAsWindow.isEnabled() - && DeviceFormFactor.isNonMultiDisplayContextOnTablet( - ContextUtils.getApplicationContext())) + && ChromeFeatureList.sAndroidOpenIncognitoAsWindow.isEnabled() && intent != null && activity instanceof PreAttachIntentObserver observer) { observer.onPreAttachIntentAvailable(intent);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browsing_data/ClearBrowsingDataFragment.java b/chrome/android/java/src/org/chromium/chrome/browser/browsing_data/ClearBrowsingDataFragment.java index e783980..a9ef9e9 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/browsing_data/ClearBrowsingDataFragment.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/browsing_data/ClearBrowsingDataFragment.java
@@ -53,6 +53,7 @@ import org.chromium.chrome.browser.searchwidget.SearchActivity; import org.chromium.chrome.browser.settings.ChromeBaseSettingsFragment; import org.chromium.chrome.browser.settings.SettingsNavigationFactory; +import org.chromium.chrome.browser.settings.search.ChromeBaseSearchIndexProvider; import org.chromium.chrome.browser.signin.services.IdentityServicesProvider; import org.chromium.chrome.browser.signin.services.SigninManager; import org.chromium.chrome.browser.ui.messages.snackbar.Snackbar; @@ -970,4 +971,10 @@ public @AnimationType int getAnimationType() { return AnimationType.PROPERTY; } + + // TODO(crbug.com/444470792): Determine what pieces of logic are dynamic and need handling. + public static final ChromeBaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = + new ChromeBaseSearchIndexProvider( + ClearBrowsingDataFragment.class.getName(), + R.xml.clear_browsing_data_preferences); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ChromeContextMenuPopulator.java b/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ChromeContextMenuPopulator.java index 85164e2..2fa43ec8 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ChromeContextMenuPopulator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ChromeContextMenuPopulator.java
@@ -37,6 +37,7 @@ import org.chromium.base.Callback; import org.chromium.base.ContextUtils; import org.chromium.base.Log; +import org.chromium.base.ResettersForTesting; import org.chromium.base.metrics.RecordHistogram; import org.chromium.base.metrics.RecordUserAction; import org.chromium.base.shared_preferences.SharedPreferencesManager; @@ -117,10 +118,14 @@ 1512; // Random id to avoid possible collisions. private static final int MAX_CUSTOM_MENU_ITEMS = 4; private static final String TAG = "CCMenuPopulator"; + private static final String LENS_SUPPORT_STATUS_HISTOGRAM_NAME = + "ContextMenu.LensSupportStatus"; private static final String UMA_CONTEXTUAL_CUSTOM_ACTION_TYPE_DISPLAYED = "CustomTabs.ContextMenu.DisplayedContextualCustomActionType"; private static final String UMA_CONTEXTUAL_CUSTOM_ACTION_TYPE_SELECTED = "CustomTabs.ContextMenu.SelectedContextualCustomActionType"; + private static @Nullable Boolean sIsDefaultBrowserForTesting; + private final Context mContext; private final TabContextMenuItemDelegate mItemDelegate; private final List<CustomContentAction> mCustomContentActions; @@ -128,8 +133,7 @@ private final Supplier<ShareDelegate> mShareDelegateSupplier; private final ContextMenuParams mParams; private final ContextMenuNativeDelegate mNativeDelegate; - private static final String LENS_SUPPORT_STATUS_HISTOGRAM_NAME = - "ContextMenu.LensSupportStatus"; + private final boolean mIsDownloadRestrictedByPolicy; private final SparseArray<CustomContentAction> mCustomActionMap; @@ -717,9 +721,7 @@ boolean addNewEntries = !UrlUtilities.isInternalScheme(mParams.getUrl()) && !isEmptyUrl(mParams.getUrl()); - if (ChromeSharedPreferences.getInstance() - .readBoolean(ChromePreferenceKeys.CHROME_DEFAULT_BROWSER, false) - && addNewEntries) { + if (isDefaultBrowser() && addNewEntries) { if (mItemDelegate.isIncognitoSupported()) { items.add(0, createListItem(Item.OPEN_IN_CHROME_INCOGNITO_TAB)); } @@ -1331,8 +1333,16 @@ }; } + private static boolean isDefaultBrowser() { + return sIsDefaultBrowserForTesting != null + ? sIsDefaultBrowserForTesting + : ChromeSharedPreferences.getInstance() + .readBoolean(ChromePreferenceKeys.CHROME_DEFAULT_BROWSER, false); + } + /** * Checks whether a url is empty or blank. + * * @param url The url need to be checked. * @return True if the url is empty or "about:blank". */ @@ -1609,6 +1619,11 @@ return UMA_CONTEXTUAL_CUSTOM_ACTION_TYPE_SELECTED; } + static void setIsDefaultBrowserForTesting(boolean isDefaultBrowser) { + sIsDefaultBrowserForTesting = isDefaultBrowser; + ResettersForTesting.register(() -> sIsDefaultBrowserForTesting = null); + } + public void setPendingIntentSenderForTesting(PendingIntentSender sender) { mPendingIntentSender = sender; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchSettingsFragment.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchSettingsFragment.java index 31a65648..ff0f784 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchSettingsFragment.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchSettingsFragment.java
@@ -18,7 +18,7 @@ import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.settings.ChromeBaseSettingsFragment; import org.chromium.chrome.browser.settings.ChromeManagedPreferenceDelegate; -import org.chromium.chrome.browser.settings.search.BaseSearchIndexProvider; +import org.chromium.chrome.browser.settings.search.ChromeBaseSearchIndexProvider; import org.chromium.components.browser_ui.settings.ChromeSwitchPreference; import org.chromium.components.browser_ui.settings.SettingsFragment; import org.chromium.components.browser_ui.settings.SettingsUtils; @@ -103,8 +103,8 @@ return SettingsFragment.AnimationType.PROPERTY; } - public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = - new BaseSearchIndexProvider( + public static final ChromeBaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = + new ChromeBaseSearchIndexProvider( ContextualSearchSettingsFragment.class.getName(), R.xml.contextual_search_preferences); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/homepage/settings/HomepageSettings.java b/chrome/android/java/src/org/chromium/chrome/browser/homepage/settings/HomepageSettings.java index 3c470a26..8ec80bc 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/homepage/settings/HomepageSettings.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/homepage/settings/HomepageSettings.java
@@ -21,7 +21,7 @@ import org.chromium.chrome.browser.homepage.settings.RadioButtonGroupHomepagePreference.PreferenceValues; import org.chromium.chrome.browser.settings.ChromeBaseSettingsFragment; import org.chromium.chrome.browser.settings.ChromeManagedPreferenceDelegate; -import org.chromium.chrome.browser.settings.search.BaseSearchIndexProvider; +import org.chromium.chrome.browser.settings.search.ChromeBaseSearchIndexProvider; import org.chromium.components.browser_ui.settings.ChromeSwitchPreference; import org.chromium.components.browser_ui.settings.SettingsUtils; import org.chromium.components.embedder_support.util.UrlUtilities; @@ -272,7 +272,7 @@ return "homepage"; } - public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = - new BaseSearchIndexProvider( + public static final ChromeBaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = + new ChromeBaseSearchIndexProvider( HomepageSettings.class.getName(), R.xml.homepage_preferences); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/multiwindow/MultiInstanceManagerApi31.java b/chrome/android/java/src/org/chromium/chrome/browser/multiwindow/MultiInstanceManagerApi31.java index 3cd809f6..2389ee2 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/multiwindow/MultiInstanceManagerApi31.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/multiwindow/MultiInstanceManagerApi31.java
@@ -23,6 +23,7 @@ import android.util.SparseBooleanArray; import android.util.SparseIntArray; +import androidx.annotation.StringRes; import androidx.annotation.VisibleForTesting; import org.chromium.base.ActivityState; @@ -54,8 +55,6 @@ import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.incognito.IncognitoUtils; import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher; -import org.chromium.chrome.browser.multiwindow.MultiInstanceManager.NewWindowAppSource; -import org.chromium.chrome.browser.multiwindow.MultiInstanceManager.PersistedInstanceType; import org.chromium.chrome.browser.multiwindow.MultiInstanceState.MultiInstanceStateObserver; import org.chromium.chrome.browser.multiwindow.UiUtils.NameWindowDialogSource; import org.chromium.chrome.browser.preferences.ChromePreferenceKeys; @@ -126,12 +125,18 @@ new EmptyTabObserver() { @Override public void onTitleUpdated(Tab tab) { - if (!tab.isIncognito()) writeTitle(mInstanceId, tab); + if (!tab.isIncognito()) { + MultiInstancePersistentStore.writeActiveTabTitle( + mInstanceId, tab.getTitle()); + } } @Override public void onUrlUpdated(Tab tab) { - if (!tab.isIncognito()) writeUrl(mInstanceId, tab); + if (!tab.isIncognito()) { + MultiInstancePersistentStore.writeActiveTabUrl( + mInstanceId, tab.getOriginalUrl().getSpec()); + } } }; @@ -160,9 +165,7 @@ mDesktopWindowStateManagerSupplier = desktopWindowStateManagerSupplier; mOnMultiInstanceStateChanged = this::onMultiInstanceStateChanged; mRenameCallback = - (pair) -> { - writeCustomTitle(pair.first, pair.second); - }; + (pair) -> MultiInstancePersistentStore.writeCustomTitle(pair.first, pair.second); // Check if instance limit has changed and update SharedPrefs. SharedPreferencesManager prefs = ChromeSharedPreferences.getInstance(); @@ -236,7 +239,6 @@ @Override public void moveTabsToOtherWindow(List<Tab> tabs, @NewWindowAppSource int source) { - // TODO(crbug.com/465141949): Add unit tests. // Check the number of instances that the tab/s is able to move into. int instanceCount = MultiWindowUtils.getInstanceCountWithFallback(PersistedInstanceType.ACTIVE); @@ -262,16 +264,13 @@ return; } - TargetSelectorCoordinator.showDialog( - mActivity, - mModalDialogManagerSupplier.get(), - new LargeIconBridge(getProfile()), + showTargetSelectorDialog( (instanceInfo) -> { moveTabsToWindow(instanceInfo, tabs, TabList.INVALID_TAB_INDEX, source); // Close the source instance window, if needed. closeChromeWindowIfEmpty(mInstanceId); }, - getInstanceInfo(instanceType), + instanceType, UiUtils.isInstanceSwitcherV2Enabled() ? R.string.menu_move_tab_to_other_window : R.string.menu_move_to_other_window); @@ -336,10 +335,7 @@ return; } - TargetSelectorCoordinator.showDialog( - mActivity, - mModalDialogManagerSupplier.get(), - new LargeIconBridge(getProfile()), + showTargetSelectorDialog( (instanceInfo) -> { ChromeTabbedActivity selectedActivity = (ChromeTabbedActivity) getActivityById(instanceInfo.instanceId); @@ -355,7 +351,7 @@ NewWindowAppSource.OTHER, preferNew); }, - getInstanceInfo(instanceType), + instanceType, R.string.contextmenu_open_in_other_window); } @@ -384,10 +380,7 @@ return; } - TargetSelectorCoordinator.showDialog( - mActivity, - mModalDialogManagerSupplier.get(), - new LargeIconBridge(getProfile()), + showTargetSelectorDialog( (instanceInfo) -> { moveTabGroupToWindow( instanceInfo, tabGroupMetadata, TabList.INVALID_TAB_INDEX, source); @@ -395,7 +388,7 @@ // Close the source instance window, if needed. closeChromeWindowIfEmpty(mInstanceId); }, - getInstanceInfo(instanceType), + instanceType, UiUtils.isInstanceSwitcherV2Enabled() ? R.string.menu_move_group_to_other_window : R.string.menu_move_to_other_window); @@ -555,6 +548,20 @@ }); } + @VisibleForTesting + void showTargetSelectorDialog( + Callback<InstanceInfo> moveCallback, + @PersistedInstanceType int instanceType, + @StringRes int titleId) { + TargetSelectorCoordinator.showDialog( + mActivity, + mModalDialogManagerSupplier.get(), + new LargeIconBridge(getProfile()), + moveCallback, + getInstanceInfo(instanceType), + titleId); + } + private Intent createIntentForGeneralReparenting( ChromeTabbedActivity targetActivity, int tabAtIndex) { assert targetActivity != null; @@ -681,11 +688,11 @@ i, persistedTaskId, type, - assumeNonNull(readUrl(i)), - assumeNonNull(readTitle(i)), - readCustomTitle(i), - readTabCount(i), - readIncognitoTabCount(i), + assumeNonNull(MultiInstancePersistentStore.readActiveTabUrl(i)), + assumeNonNull(MultiInstancePersistentStore.readActiveTabTitle(i)), + MultiInstancePersistentStore.readCustomTitle(i), + MultiInstancePersistentStore.readNormalTabCount(i), + MultiInstancePersistentStore.readIncognitoTabCount(i), readIncognitoSelected(i), readLastAccessedTime(i), readClosedByUser(i))); @@ -1003,11 +1010,15 @@ ? TabModelUtils.getCurrentTab(selector.getModel(false)) : mActiveTab; if (urlTab != null) { - writeUrl(mInstanceId, urlTab); - writeTitle(mInstanceId, urlTab); + MultiInstancePersistentStore.writeActiveTabUrl( + mInstanceId, urlTab.getOriginalUrl().getSpec()); + MultiInstancePersistentStore.writeActiveTabTitle( + mInstanceId, urlTab.getTitle()); } else { - writeUrl(mInstanceId, EMPTY_DATA); - writeTitle(mInstanceId, EMPTY_DATA); + MultiInstancePersistentStore.writeActiveTabUrl( + mInstanceId, EMPTY_DATA); + MultiInstancePersistentStore.writeActiveTabTitle( + mInstanceId, EMPTY_DATA); } } } @@ -1244,95 +1255,16 @@ .readBoolean(incognitoSelectedKey(index), false); } - @VisibleForTesting - static String urlKey(int index) { - return ChromePreferenceKeys.MULTI_INSTANCE_URL.createKey(String.valueOf(index)); - } - - @VisibleForTesting - static @Nullable String readUrl(int index) { - return ChromeSharedPreferences.getInstance().readString(urlKey(index), null); - } - - static void writeUrl(int index, String url) { - ChromeSharedPreferences.getInstance().writeString(urlKey(index), url); - } - - private static void writeUrl(int index, Tab tab) { - assert !tab.isIncognito(); - writeUrl(index, tab.getOriginalUrl().getSpec()); - } - - @VisibleForTesting - static String titleKey(int index) { - return ChromePreferenceKeys.MULTI_INSTANCE_TITLE.createKey(String.valueOf(index)); - } - - @VisibleForTesting - static String customTitleKey(int index) { - return ChromePreferenceKeys.MULTI_INSTANCE_CUSTOM_TITLE.createKey(String.valueOf(index)); - } - - @VisibleForTesting - static @Nullable String readTitle(int index) { - return ChromeSharedPreferences.getInstance().readString(titleKey(index), null); - } - - @VisibleForTesting - static @Nullable String readCustomTitle(int index) { - return ChromeSharedPreferences.getInstance().readString(customTitleKey(index), null); - } - - private static void writeTitle(int index, Tab tab) { - assert !tab.isIncognito(); - writeTitle(index, tab.getTitle()); - } - - @VisibleForTesting - static void writeTitle(int index, String title) { - ChromeSharedPreferences.getInstance().writeString(titleKey(index), title); - } - - @VisibleForTesting - static void writeCustomTitle(int index, String customTitle) { - ChromeSharedPreferences.getInstance().writeString(customTitleKey(index), customTitle); - } - - @VisibleForTesting - static String tabCountKey(int index) { - return ChromePreferenceKeys.MULTI_INSTANCE_TAB_COUNT.createKey(String.valueOf(index)); - } - - @VisibleForTesting - static String tabCountForRelaunchKey(int index) { - return MultiWindowUtils.getTabCountForRelaunchKey(index); - } - - static int readTabCount(int index) { - return ChromeSharedPreferences.getInstance().readInt(tabCountKey(index)); - } - - @VisibleForTesting - static String incognitoTabCountKey(int index) { - return ChromePreferenceKeys.MULTI_INSTANCE_INCOGNITO_TAB_COUNT.createKey( - String.valueOf(index)); - } - - @VisibleForTesting - static int readIncognitoTabCount(int index) { - return ChromeSharedPreferences.getInstance().readInt(incognitoTabCountKey(index)); - } - - @VisibleForTesting - static void writeTabCount(int index, TabModelSelector selector) { + private static void writeTabCount(int index, TabModelSelector selector) { if (!selector.isTabStateInitialized()) return; - SharedPreferencesManager prefs = ChromeSharedPreferences.getInstance(); int tabCount = selector.getModel(false).getCount(); - prefs.writeInt(tabCountKey(index), tabCount); - prefs.writeInt(incognitoTabCountKey(index), selector.getModel(true).getCount()); + int incognitoTabCount = selector.getModel(true).getCount(); + // TODO (crbug.com/466168444): Explore extracting tab count from TabModelSelector for both + // active and inactive instances given that we support headless tab models now. + MultiInstancePersistentStore.writeTabCount(index, tabCount, incognitoTabCount); if (tabCount == 0) { - writeUrl(index, EMPTY_DATA); - writeTitle(index, EMPTY_DATA); + MultiInstancePersistentStore.writeActiveTabUrl(index, EMPTY_DATA); + MultiInstancePersistentStore.writeActiveTabTitle(index, EMPTY_DATA); } } @@ -1661,15 +1593,14 @@ @VisibleForTesting static void removeInstanceInfo(int index, @CloseWindowAppSource int source) { SharedPreferencesManager prefs = ChromeSharedPreferences.getInstance(); - prefs.removeKey(urlKey(index)); - prefs.removeKey(titleKey(index)); - prefs.removeKey(tabCountKey(index)); - prefs.removeKey(tabCountForRelaunchKey(index)); - prefs.removeKey(incognitoTabCountKey(index)); + MultiInstancePersistentStore.removeActiveTabUrl(index); + MultiInstancePersistentStore.removeActiveTabTitle(index); + MultiInstancePersistentStore.removeCustomTitle(index); + MultiInstancePersistentStore.removeTabCount(index); + MultiInstancePersistentStore.removeTabCountForRelaunch(index); prefs.removeKey(incognitoSelectedKey(index)); prefs.removeKey(lastAccessedTimeKey(index)); prefs.removeKey(profileTypeKey(index)); - prefs.removeKey(customTitleKey(index)); prefs.removeKey(closedByUserKey(index)); RecordHistogram.recordEnumeratedHistogram( @@ -1962,13 +1893,14 @@ @Override public void showNameWindowDialog(@NameWindowDialogSource int source) { - String customTitle = readCustomTitle(mInstanceId); - String currentTitle = TextUtils.isEmpty(customTitle) ? readTitle(mInstanceId) : customTitle; + String customTitle = MultiInstancePersistentStore.readCustomTitle(mInstanceId); + String defaultTitle = MultiInstancePersistentStore.readActiveTabTitle(mInstanceId); + String currentTitle = TextUtils.isEmpty(customTitle) ? defaultTitle : customTitle; UiUtils.showNameWindowDialog( mActivity, assumeNonNull(currentTitle), - newTitle -> writeCustomTitle(mInstanceId, newTitle), + newTitle -> mRenameCallback.onResult(new Pair<>(mInstanceId, newTitle)), source); } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/multiwindow/MultiInstancePersistentStore.java b/chrome/android/java/src/org/chromium/chrome/browser/multiwindow/MultiInstancePersistentStore.java index 1a9171b3..54fe4c9 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/multiwindow/MultiInstancePersistentStore.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/multiwindow/MultiInstancePersistentStore.java
@@ -7,6 +7,7 @@ import org.chromium.base.shared_preferences.SharedPreferencesManager; import org.chromium.build.annotations.MonotonicNonNull; import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.Nullable; import org.chromium.chrome.browser.preferences.ChromePreferenceKeys; import org.chromium.chrome.browser.preferences.ChromeSharedPreferences; @@ -18,7 +19,7 @@ * by the user. */ @NullMarked -public class MultiInstancePersistentStore { +class MultiInstancePersistentStore { private static @MonotonicNonNull SharedPreferencesManager sPrefsManager; private MultiInstancePersistentStore() {} @@ -46,7 +47,100 @@ getManager().removeKey(taskIdKey(instanceId)); } + static void writeTabCount(int instanceId, int normalTabCount, int incognitoTabCount) { + getManager().writeInt(normalTabCountKey(instanceId), normalTabCount); + getManager().writeInt(incognitoTabCountKey(instanceId), incognitoTabCount); + } + + static void removeTabCount(int instanceId) { + getManager().removeKey(normalTabCountKey(instanceId)); + getManager().removeKey(incognitoTabCountKey(instanceId)); + } + + static int readNormalTabCount(int instanceId) { + return getManager().readInt(normalTabCountKey(instanceId)); + } + + static int readIncognitoTabCount(int instanceId) { + return getManager().readInt(incognitoTabCountKey(instanceId)); + } + + static int readTabCountForRelaunch(int instanceId) { + return getManager().readInt(tabCountForRelaunchKey(instanceId)); + } + + static void writeTabCountForRelaunchSync(int instanceId, int tabCount) { + getManager().writeIntSync(tabCountForRelaunchKey(instanceId), tabCount); + } + + static void removeTabCountForRelaunch(int instanceId) { + getManager().removeKey(tabCountForRelaunchKey(instanceId)); + } + + static @Nullable String readActiveTabUrl(int instanceId) { + return getManager().readString(urlKey(instanceId), null); + } + + static void writeActiveTabUrl(int instanceId, String url) { + getManager().writeString(urlKey(instanceId), url); + } + + static void removeActiveTabUrl(int instanceId) { + getManager().removeKey(urlKey(instanceId)); + } + + static @Nullable String readActiveTabTitle(int instanceId) { + return getManager().readString(activeTabTitleKey(instanceId), null); + } + + static void writeActiveTabTitle(int instanceId, String title) { + getManager().writeString(activeTabTitleKey(instanceId), title); + } + + static void removeActiveTabTitle(int instanceId) { + getManager().removeKey(activeTabTitleKey(instanceId)); + } + + static @Nullable String readCustomTitle(int instanceId) { + return getManager().readString(customTitleKey(instanceId), null); + } + + static void writeCustomTitle(int instanceId, String title) { + getManager().writeString(customTitleKey(instanceId), title); + } + + static void removeCustomTitle(int instanceId) { + getManager().removeKey(customTitleKey(instanceId)); + } + private static String taskIdKey(int instanceId) { return ChromePreferenceKeys.MULTI_INSTANCE_TASK_MAP.createKey(String.valueOf(instanceId)); } + + private static String normalTabCountKey(int instanceId) { + return ChromePreferenceKeys.MULTI_INSTANCE_TAB_COUNT.createKey(String.valueOf(instanceId)); + } + + private static String incognitoTabCountKey(int instanceId) { + return ChromePreferenceKeys.MULTI_INSTANCE_INCOGNITO_TAB_COUNT.createKey( + String.valueOf(instanceId)); + } + + private static String tabCountForRelaunchKey(int instanceId) { + return ChromePreferenceKeys.MULTI_INSTANCE_TAB_COUNT_FOR_RELAUNCH.createKey( + String.valueOf(instanceId)); + } + + private static String urlKey(int instanceId) { + return ChromePreferenceKeys.MULTI_INSTANCE_URL.createKey(String.valueOf(instanceId)); + } + + private static String activeTabTitleKey(int instanceId) { + return ChromePreferenceKeys.MULTI_INSTANCE_TITLE.createKey(String.valueOf(instanceId)); + } + + private static String customTitleKey(int instanceId) { + return ChromePreferenceKeys.MULTI_INSTANCE_CUSTOM_TITLE.createKey( + String.valueOf(instanceId)); + } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/multiwindow/MultiWindowUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/multiwindow/MultiWindowUtils.java index ba7c1d3e..73f84ba 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/multiwindow/MultiWindowUtils.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/multiwindow/MultiWindowUtils.java
@@ -16,7 +16,6 @@ import android.content.ComponentName; import android.content.Context; import android.content.Intent; -import android.content.SharedPreferences; import android.content.pm.ActivityInfo; import android.content.pm.PackageManager; import android.content.res.Resources; @@ -93,7 +92,6 @@ @NullMarked public class MultiWindowUtils implements ActivityStateListener { public static final int INVALID_TASK_ID = MultiInstanceManager.INVALID_TASK_ID; - private static final int DEFAULT_TAB_COUNT_FOR_RELAUNCH = 0; static final String HISTOGRAM_NUM_ACTIVITIES_DESKTOP_WINDOW = "Android.MultiInstance.NumActivities.DesktopWindow"; @@ -109,6 +107,7 @@ protected static @Nullable Supplier<Activity> sActivitySupplierForTesting; private static @Nullable Integer sMaxInstancesForTesting; + private static @Nullable Integer sIncognitoInstanceCountForTesting; private static @Nullable Integer sInstanceCountForTesting; private static @Nullable Boolean sMultiInstanceApi31EnabledForTesting; private final boolean mMultiInstanceApi31Enabled; @@ -523,6 +522,9 @@ */ // TODO (crbug.com/461553972): Remove this method after Robust Window Management is launched. public static int getIncognitoInstanceCount(boolean activeOnly) { + if (sIncognitoInstanceCountForTesting != null) { + return sIncognitoInstanceCountForTesting; + } int instanceType = PersistedInstanceType.OFF_THE_RECORD; if (activeOnly) { instanceType |= PersistedInstanceType.ACTIVE; @@ -545,7 +547,7 @@ } static boolean isRestorableInstance(int index) { - return MultiInstanceManagerApi31.readTabCount(index) != 0 + return MultiInstancePersistentStore.readNormalTabCount(index) != 0 || MultiInstancePersistentStore.readTaskId(index) != INVALID_TASK_ID; } @@ -1123,39 +1125,17 @@ } } } - - SharedPreferences.Editor editor = ChromeSharedPreferences.getInstance().getEditor(); - String tabCountForRelaunchKey = getTabCountForRelaunchKey(windowId); - editor.putInt(tabCountForRelaunchKey, totalCount); - // The ChromeSharedPreferences.getInstance().writeInt() method uses editor.apply() instead - // of editor.commit(). The editor.apply() method writes data to memory and returns - // immediately, while the actual disk write occurs asynchronously in a background thread. On - // the other hand, editor.commit() writes data directly to disk and waits for the operation - // to complete. Since apply() is asynchronous, if the program is forcibly closed right after - // calling it (e.g., in our case where Chrome is closed and then relaunched), the disk write - // may not finish in time, potentially resulting in data loss. Therefore, editor.commit() is - // used here to ensure data is reliably saved. - editor.commit(); + MultiInstancePersistentStore.writeTabCountForRelaunchSync(windowId, totalCount); } /** * Returns the total number of tabs for relaunch across both regular and incognito browsing - * modes through shared preference key. + * modes from persisted state. * * @param windowId The id of the window. */ - public static int getTabCountForRelaunchFromSharedPrefs(int windowId) { - String tabCountForRelaunchKey = getTabCountForRelaunchKey(windowId); - return ChromeSharedPreferences.getInstance() - .readInt( - tabCountForRelaunchKey, /* defaultValue= */ DEFAULT_TAB_COUNT_FOR_RELAUNCH); - } - - /** Returns the tab count for relaunch key. */ - @VisibleForTesting - static String getTabCountForRelaunchKey(int windowId) { - return ChromePreferenceKeys.MULTI_INSTANCE_TAB_COUNT_FOR_RELAUNCH.createKey( - String.valueOf(windowId)); + public static int getTabCountForRelaunchFromPersistentStore(int windowId) { + return MultiInstancePersistentStore.readTabCountForRelaunch(windowId); } /** @@ -1274,6 +1254,11 @@ ResettersForTesting.register(() -> sInstance = oldValue); } + public static void setIncognitoInstanceCountForTesting(int instanceCount) { + sIncognitoInstanceCountForTesting = instanceCount; + ResettersForTesting.register(() -> sIncognitoInstanceCountForTesting = null); + } + public static void setInstanceCountForTesting(int instanceCount) { sInstanceCountForTesting = instanceCount; ResettersForTesting.register(() -> sInstanceCountForTesting = null);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/privacy/settings/DoNotTrackSettings.java b/chrome/android/java/src/org/chromium/chrome/browser/privacy/settings/DoNotTrackSettings.java index 8d88fd88..73022f4 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/privacy/settings/DoNotTrackSettings.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/privacy/settings/DoNotTrackSettings.java
@@ -15,7 +15,7 @@ import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.preferences.Pref; import org.chromium.chrome.browser.settings.ChromeBaseSettingsFragment; -import org.chromium.chrome.browser.settings.search.BaseSearchIndexProvider; +import org.chromium.chrome.browser.settings.search.ChromeBaseSearchIndexProvider; import org.chromium.components.browser_ui.settings.ChromeSwitchPreference; import org.chromium.components.browser_ui.settings.SettingsFragment; import org.chromium.components.browser_ui.settings.SettingsUtils; @@ -70,7 +70,7 @@ return SettingsFragment.AnimationType.PROPERTY; } - public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = - new BaseSearchIndexProvider( + public static final ChromeBaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = + new ChromeBaseSearchIndexProvider( DoNotTrackSettings.class.getName(), R.xml.do_not_track_preferences); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/privacy/settings/PrivacySettings.java b/chrome/android/java/src/org/chromium/chrome/browser/privacy/settings/PrivacySettings.java index 8d2eed2..9d4eee8 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/privacy/settings/PrivacySettings.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/privacy/settings/PrivacySettings.java
@@ -52,6 +52,7 @@ import org.chromium.chrome.browser.settings.ChromeBaseSettingsFragment; import org.chromium.chrome.browser.settings.ChromeManagedPreferenceDelegate; import org.chromium.chrome.browser.settings.SettingsNavigationFactory; +import org.chromium.chrome.browser.settings.search.ChromeBaseSearchIndexProvider; import org.chromium.chrome.browser.signin.services.IdentityServicesProvider; import org.chromium.chrome.browser.ssl.HttpsFirstModeSettingsFragment; import org.chromium.chrome.browser.sync.settings.GoogleServicesSettings; @@ -575,4 +576,10 @@ public @Nullable String getMainMenuKey() { return "privacy"; } + + // TODO(crbug.com/444470792): Determine what pieces of logic are dynamic and need handling. + // Do specific bundle arguments need to be present? + public static final ChromeBaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = + new ChromeBaseSearchIndexProvider( + PrivacySettings.class.getName(), R.xml.privacy_preferences); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/settings/MainSettings.java b/chrome/android/java/src/org/chromium/chrome/browser/settings/MainSettings.java index 6a59462..846dc282 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/settings/MainSettings.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/settings/MainSettings.java
@@ -57,7 +57,7 @@ import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.safety_hub.SafetyHubMetricUtils; import org.chromium.chrome.browser.search_engines.TemplateUrlServiceFactory; -import org.chromium.chrome.browser.settings.search.BaseSearchIndexProvider; +import org.chromium.chrome.browser.settings.search.ChromeBaseSearchIndexProvider; import org.chromium.chrome.browser.signin.services.IdentityServicesProvider; import org.chromium.chrome.browser.signin.services.ProfileDataCache; import org.chromium.chrome.browser.signin.services.SigninManager; @@ -266,14 +266,10 @@ AccountManagerFacade accountManagerFacade = AccountManagerFacadeProvider.getInstance(); if (ChromeFeatureList.isEnabled(ChromeFeatureList.DEFAULT_BROWSER_PROMO_ANDROID2)) { - // TODO(crbug.com/364906215): Define SettingsPromoCardPreference in the xml once - // SyncPromoPreference is removed. SettingsPromoCardPreference settingsPromoCardPreference = - new SettingsPromoCardPreference( - getContext(), null, TrackerFactory.getTrackerForProfile(getProfile())); - settingsPromoCardPreference.setKey(PREF_SETTINGS_PROMO_CARD); - settingsPromoCardPreference.setOrder(0); - getPreferenceScreen().addPreference(settingsPromoCardPreference); + findPreference(PREF_SETTINGS_PROMO_CARD); + settingsPromoCardPreference.initialize( + TrackerFactory.getTrackerForProfile(getProfile())); } SignInPreference signInPreference = findPreference(PREF_SIGN_IN); @@ -819,7 +815,8 @@ return AnimationType.PROPERTY; } - // TODO (adelm): Mimic logic from #createPreferences under #updateDynamicPreferences. - public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = - new BaseSearchIndexProvider(MainSettings.class.getName(), R.xml.main_preferences); + // TODO(crbug.com/444470792): Mimic logic from #createPreferences under + // #updateDynamicPreferences. + public static final ChromeBaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = + new ChromeBaseSearchIndexProvider(MainSettings.class.getName(), R.xml.main_preferences); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/settings/search/SearchIndexProviderRegistry.java b/chrome/android/java/src/org/chromium/chrome/browser/settings/search/SearchIndexProviderRegistry.java index b7f516b..a5749ec 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/settings/search/SearchIndexProviderRegistry.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/settings/search/SearchIndexProviderRegistry.java
@@ -5,6 +5,7 @@ package org.chromium.chrome.browser.settings.search; import org.chromium.build.annotations.NullMarked; +import org.chromium.components.browser_ui.settings.search.SearchIndexProvider; import java.util.List; @@ -65,5 +66,77 @@ org.chromium.chrome.browser.privacy_sandbox.TopicsManageFragment .SEARCH_INDEX_DATA_PROVIDER, org.chromium.chrome.browser.privacy_sandbox.PrivacySandboxSettingsFragment + .SEARCH_INDEX_DATA_PROVIDER, + org.chromium.components.browser_ui.site_settings.ChosenObjectSettings + .SEARCH_INDEX_DATA_PROVIDER, + org.chromium.components.browser_ui.site_settings.GroupedWebsitesSettings + .SEARCH_INDEX_DATA_PROVIDER, + org.chromium.components.page_info.PageInfoAdPersonalizationSettings + .SEARCH_INDEX_DATA_PROVIDER, + org.chromium.components.page_info.PageInfoCookiesSettings + .SEARCH_INDEX_DATA_PROVIDER, + org.chromium.components.browser_ui.site_settings.RwsCookieSettings + .SEARCH_INDEX_DATA_PROVIDER, + org.chromium.components.browser_ui.site_settings.SingleCategorySettings + .SEARCH_INDEX_DATA_PROVIDER, + org.chromium.components.browser_ui.site_settings.SingleWebsiteSettings + .SEARCH_INDEX_DATA_PROVIDER, + org.chromium.components.browser_ui.site_settings.SiteSettings + .SEARCH_INDEX_DATA_PROVIDER, + org.chromium.components.browser_ui.accessibility.AccessibilitySettings + .SEARCH_INDEX_DATA_PROVIDER, + org.chromium.chrome.browser.image_descriptions.ImageDescriptionsSettings + .SEARCH_INDEX_DATA_PROVIDER, + org.chromium.chrome.browser.prefetch.settings.PreloadPagesSettingsFragment + .SEARCH_INDEX_DATA_PROVIDER, + org.chromium.chrome.browser.safe_browsing.settings.SafeBrowsingSettingsFragment + .SEARCH_INDEX_DATA_PROVIDER, + org.chromium.chrome.browser.safe_browsing.settings + .StandardProtectionSettingsFragment.SEARCH_INDEX_DATA_PROVIDER, + org.chromium.chrome.browser.safety_hub.SafetyHubFragment + .SEARCH_INDEX_DATA_PROVIDER, + org.chromium.chrome.browser.sync.settings.AccountManagementFragment + .SEARCH_INDEX_DATA_PROVIDER, + org.chromium.chrome.browser.autofill.settings.AndroidPaymentAppsFragment + .SEARCH_INDEX_DATA_PROVIDER, + org.chromium.chrome.browser.appearance.settings.AppearanceSettingsFragment + .SEARCH_INDEX_DATA_PROVIDER, + org.chromium.chrome.browser.autofill.settings.AutofillBuyNowPayLaterFragment + .SEARCH_INDEX_DATA_PROVIDER, + org.chromium.chrome.browser.autofill.settings.AutofillCardBenefitsFragment + .SEARCH_INDEX_DATA_PROVIDER, + org.chromium.chrome.browser.autofill.settings.AutofillPaymentMethodsFragment + .SEARCH_INDEX_DATA_PROVIDER, + org.chromium.chrome.browser.autofill.settings.AutofillProfilesFragment + .SEARCH_INDEX_DATA_PROVIDER, + org.chromium.chrome.browser.browsing_data.ClearBrowsingDataFragment + .SEARCH_INDEX_DATA_PROVIDER, + org.chromium.chrome.browser.autofill.settings + .FinancialAccountsManagementFragment.SEARCH_INDEX_DATA_PROVIDER, + org.chromium.chrome.browser.sync.settings.GoogleServicesSettings + .SEARCH_INDEX_DATA_PROVIDER, + org.chromium.chrome.browser.magic_stack.HomeModulesConfigSettings + .SEARCH_INDEX_DATA_PROVIDER, + org.chromium.chrome.browser.ssl.HttpsFirstModeSettingsFragment + .SEARCH_INDEX_DATA_PROVIDER, + org.chromium.chrome.browser.language.settings.LanguageSettings + .SEARCH_INDEX_DATA_PROVIDER, + org.chromium.chrome.browser.autofill.settings + .NonCardPaymentMethodsManagementFragment.SEARCH_INDEX_DATA_PROVIDER, + org.chromium.chrome.browser.commerce.PriceNotificationSettingsFragment + .SEARCH_INDEX_DATA_PROVIDER, + org.chromium.chrome.browser.privacy.settings.PrivacySettings + .SEARCH_INDEX_DATA_PROVIDER, + org.chromium.chrome.browser.safety_check.SafetyCheckSettingsFragment + .SEARCH_INDEX_DATA_PROVIDER, + org.chromium.chrome.browser.tasks.tab_management.TabsSettings + .SEARCH_INDEX_DATA_PROVIDER, + org.chromium.chrome.browser.sync.settings.ManageSyncSettings + .SEARCH_INDEX_DATA_PROVIDER, + org.chromium.chrome.browser.night_mode.settings.ThemeSettingsFragment + .SEARCH_INDEX_DATA_PROVIDER, + org.chromium.chrome.browser.tracing.settings.TracingSettings + .SEARCH_INDEX_DATA_PROVIDER, + org.chromium.chrome.browser.tracing.settings.TracingCategoriesSettings .SEARCH_INDEX_DATA_PROVIDER); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/settings/search/SearchResultsPreferenceFragment.java b/chrome/android/java/src/org/chromium/chrome/browser/settings/search/SearchResultsPreferenceFragment.java index bb01365..ac405fe7 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/settings/search/SearchResultsPreferenceFragment.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/settings/search/SearchResultsPreferenceFragment.java
@@ -20,6 +20,7 @@ import org.chromium.chrome.R; import org.chromium.chrome.browser.settings.ChromeBaseSettingsFragment; import org.chromium.chrome.browser.settings.MainSettings; +import org.chromium.components.browser_ui.settings.search.SettingsIndexData; import java.util.List;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/settings/search/SettingsSearchCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/settings/search/SettingsSearchCoordinator.java index ddc5153e..a6571f2 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/settings/search/SettingsSearchCoordinator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/settings/search/SettingsSearchCoordinator.java
@@ -47,7 +47,9 @@ import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.settings.MainSettings; import org.chromium.chrome.browser.settings.MultiColumnSettings; -import org.chromium.chrome.browser.settings.search.SettingsIndexData.SearchResults; +import org.chromium.components.browser_ui.settings.search.SearchIndexProvider; +import org.chromium.components.browser_ui.settings.search.SettingsIndexData; +import org.chromium.components.browser_ui.settings.search.SettingsIndexData.SearchResults; import org.chromium.components.browser_ui.widget.containment.ContainmentItemDecoration; import org.chromium.components.browser_ui.widget.displaystyle.UiConfig; import org.chromium.components.browser_ui.widget.displaystyle.ViewResizer; @@ -272,7 +274,11 @@ // Allow providers to make runtime modifications (e.g., hide preferences). Sometimes we also // need to update the title of a pref. for (SearchIndexProvider provider : providers) { - provider.updateDynamicPreferences(mActivity, mIndexData, mProfile); + if (provider instanceof ChromeSearchIndexProvider chromeProvider) { + chromeProvider.updateDynamicPreferences(mActivity, mIndexData, mProfile); + } else { + provider.updateDynamicPreferences(mActivity, mIndexData); + } } // Resolve headers and remove any orphaned entries.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/sync/settings/AccountManagementFragment.java b/chrome/android/java/src/org/chromium/chrome/browser/sync/settings/AccountManagementFragment.java index d385b34..70695101 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/sync/settings/AccountManagementFragment.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/sync/settings/AccountManagementFragment.java
@@ -35,6 +35,7 @@ import org.chromium.chrome.browser.settings.ChromeBaseSettingsFragment; import org.chromium.chrome.browser.settings.ChromeManagedPreferenceDelegate; import org.chromium.chrome.browser.settings.SettingsNavigationFactory; +import org.chromium.chrome.browser.settings.search.ChromeBaseSearchIndexProvider; import org.chromium.chrome.browser.signin.services.DisplayableProfileData; import org.chromium.chrome.browser.signin.services.IdentityServicesProvider; import org.chromium.chrome.browser.signin.services.ProfileDataCache; @@ -591,4 +592,10 @@ SigninManager getSigninManager() { return assumeNonNull(IdentityServicesProvider.get().getSigninManager(getProfile())); } + + // TODO(crbug.com/444470792): Determine what pieces of logic are dynamic and need handling. + public static final ChromeBaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = + new ChromeBaseSearchIndexProvider( + AccountManagementFragment.class.getName(), + R.xml.account_management_preferences); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/sync/settings/GoogleServicesSettings.java b/chrome/android/java/src/org/chromium/chrome/browser/sync/settings/GoogleServicesSettings.java index d585c07..80367e3 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/sync/settings/GoogleServicesSettings.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/sync/settings/GoogleServicesSettings.java
@@ -33,6 +33,7 @@ import org.chromium.chrome.browser.privacy.settings.PrivacyPreferencesManagerImpl; import org.chromium.chrome.browser.settings.ChromeBaseSettingsFragment; import org.chromium.chrome.browser.settings.ChromeManagedPreferenceDelegate; +import org.chromium.chrome.browser.settings.search.ChromeBaseSearchIndexProvider; import org.chromium.chrome.browser.signin.services.IdentityServicesProvider; import org.chromium.chrome.browser.signin.services.UnifiedConsentServiceBridge; import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager; @@ -317,4 +318,9 @@ public @Nullable String getMainMenuKey() { return "google_services"; } + + // TODO(crbug.com/444470792): Determine what pieces of logic are dynamic and need handling. + public static final ChromeBaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = + new ChromeBaseSearchIndexProvider( + GoogleServicesSettings.class.getName(), R.xml.google_services_preferences); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/sync/settings/ManageSyncSettings.java b/chrome/android/java/src/org/chromium/chrome/browser/sync/settings/ManageSyncSettings.java index de470785..1bcfdb4 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/sync/settings/ManageSyncSettings.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/sync/settings/ManageSyncSettings.java
@@ -52,6 +52,7 @@ import org.chromium.chrome.browser.settings.ChromeBaseSettingsFragment; import org.chromium.chrome.browser.settings.ChromeManagedPreferenceDelegate; import org.chromium.chrome.browser.settings.SettingsNavigationFactory; +import org.chromium.chrome.browser.settings.search.ChromeBaseSearchIndexProvider; import org.chromium.chrome.browser.signin.services.IdentityServicesProvider; import org.chromium.chrome.browser.signin.services.ProfileDataCache; import org.chromium.chrome.browser.signin.services.SigninManager; @@ -1280,4 +1281,10 @@ private FragmentTransaction beginTransaction() { return assumeNonNull(getFragmentManager()).beginTransaction(); } + + // TODO(crbug.com/444470792): Determine what pieces of logic are dynamic and need handling. + // Deal with the different XMLs used by this pref. + public static final ChromeBaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = + new ChromeBaseSearchIndexProvider( + ManageSyncSettings.class.getName(), R.xml.manage_sync_preferences); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/sync/settings/PersonalizeGoogleServicesSettings.java b/chrome/android/java/src/org/chromium/chrome/browser/sync/settings/PersonalizeGoogleServicesSettings.java index b58a860..488ef6d 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/sync/settings/PersonalizeGoogleServicesSettings.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/sync/settings/PersonalizeGoogleServicesSettings.java
@@ -18,7 +18,7 @@ import org.chromium.chrome.R; import org.chromium.chrome.browser.settings.ChromeBaseSettingsFragment; import org.chromium.chrome.browser.settings.SettingsNavigationFactory; -import org.chromium.chrome.browser.settings.search.BaseSearchIndexProvider; +import org.chromium.chrome.browser.settings.search.ChromeBaseSearchIndexProvider; import org.chromium.chrome.browser.signin.services.IdentityServicesProvider; import org.chromium.chrome.browser.sync.SyncServiceFactory; import org.chromium.chrome.browser.ui.signin.GoogleActivityController; @@ -113,8 +113,8 @@ return AnimationType.PROPERTY; } - public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = - new BaseSearchIndexProvider( + public static final ChromeBaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = + new ChromeBaseSearchIndexProvider( PersonalizeGoogleServicesSettings.class.getName(), R.xml.personalize_google_services_preferences); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabImpl.java index e960a82..bdd4a637 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabImpl.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabImpl.java
@@ -167,6 +167,9 @@ /** Whether the tab is archived. */ private final boolean mIsArchived; + // TODO(crbug.com/466371728): For debugging only. Remove after the bug is fixed. + private boolean mInitializedWithWindowAndroid; + /** The Profile associated with this tab. */ private final Profile mProfile; @@ -1014,8 +1017,13 @@ @Override public boolean loadIfNeeded(@TabLoadIfNeededCaller int caller) { - if (getActivity() == null) { - Log.e(TAG, "Tab couldn't be loaded because Context was null."); + if (getActivity(/* withLogs= */ true) == null) { + Log.e( + TAG, + "Tab couldn't be loaded because Context was null. mIsArchived: " + + mIsArchived + + ", mInitializedWithWindowAndroid: " + + mInitializedWithWindowAndroid); return false; } @@ -1315,28 +1323,45 @@ * WARNING: This method is deprecated. Consider other ways such as passing the dependencies to * the constructor, rather than accessing ChromeActivity from Tab and using getters. * + * @param withLogs Whether to log the activity state. * @return {@link ChromeActivity} that currently contains this {@link Tab} in its {@link * TabModel}. */ @Deprecated - @Nullable ChromeActivity getActivity() { + @Nullable ChromeActivity getActivity(boolean withLogs) { if (getWindowAndroid() == null) { - Log.e(TAG, "WindowAndroid is null when requesting activity."); + if (withLogs) { + Log.e(TAG, "WindowAndroid is null when requesting activity."); + } return null; } Activity activity = ContextUtils.activityFromContext(getWindowAndroid().getContext().get()); if (activity instanceof ChromeActivity chromeActivity) { return chromeActivity; } - if (activity == null) { - Log.e(TAG, "Activity is null when requesting activity."); - } else { - Log.e(TAG, "Activity is not a ChromeActivity when requesting activity."); + if (withLogs) { + if (activity == null) { + Log.e(TAG, "Activity is null when requesting activity."); + } else { + Log.e(TAG, "Activity is not a ChromeActivity when requesting activity."); + } } return null; } /** + * WARNING: This method is deprecated. Consider other ways such as passing the dependencies to + * the constructor, rather than accessing ChromeActivity from Tab and using getters. + * + * @return {@link ChromeActivity} that currently contains this {@link Tab} in its {@link + * TabModel}. + */ + @Deprecated + @Nullable ChromeActivity getActivity() { + return getActivity(/* withLogs= */ false); + } + + /** * Helper method to access the activity context if there is one. * * @return a {@link WeakReference} to the {@link Context} belonging to the current activity. It @@ -1447,8 +1472,9 @@ // models are not associated with BrowserWindowInterface so this shouldn't be an issue // for now. In future we should reconsider whether these tab models should even hold a // TabImpl vs some kind of light weight tab representation. + mInitializedWithWindowAndroid = mWindowAndroid != null; if (ChromeFeatureList.sLoadAllTabsAtStartup.isEnabled() - && mWindowAndroid != null + && mInitializedWithWindowAndroid && !mIsArchived) { if (mWebContentsState != null) { assert webContents == null;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java index 8c51f3d2..6f35f57 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java
@@ -1920,21 +1920,20 @@ assertNonNull(mWindowAndroid.getInsetObserver()) .getSupplierForKeyboardInset(), mWindowAndroid); - if (ChromeFeatureList.sMiniOriginBar.isEnabled()) { - mMiniOriginBarController = - new MiniOriginBarController( - mLocationBar, - mFormFieldFocusedSupplier, - mWindowAndroid.getKeyboardDelegate(), - mActivity, - mControlContainer, - mSuppressToolbarSceneLayerSupplier, - mBrowserControlsSizer, - assertNonNull(mWindowAndroid.getInsetObserver()), - controlContainerTranslationSupplier, - keyboardAccessoryStateSupplier.getIsSheetShowingSupplier(), - this::isUrlBarFocused); - } + + mMiniOriginBarController = + new MiniOriginBarController( + mLocationBar, + mFormFieldFocusedSupplier, + mWindowAndroid.getKeyboardDelegate(), + mActivity, + mControlContainer, + mSuppressToolbarSceneLayerSupplier, + mBrowserControlsSizer, + assertNonNull(mWindowAndroid.getInsetObserver()), + controlContainerTranslationSupplier, + keyboardAccessoryStateSupplier.getIsSheetShowingSupplier(), + this::isUrlBarFocused); } // TODO(b/315204103): add tests
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tracing/settings/TracingCategoriesSettings.java b/chrome/android/java/src/org/chromium/chrome/browser/tracing/settings/TracingCategoriesSettings.java index 38c36921..9e5cc588 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tracing/settings/TracingCategoriesSettings.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tracing/settings/TracingCategoriesSettings.java
@@ -17,6 +17,7 @@ import org.chromium.build.annotations.NullMarked; import org.chromium.build.annotations.Nullable; import org.chromium.chrome.browser.settings.ChromeBaseSettingsFragment; +import org.chromium.chrome.browser.settings.search.ChromeBaseSearchIndexProvider; import org.chromium.chrome.browser.tracing.TracingController; import org.chromium.components.browser_ui.settings.ChromeBaseCheckBoxPreference; import org.chromium.components.browser_ui.settings.EmbeddableSettingsPage; @@ -133,4 +134,9 @@ public @AnimationType int getAnimationType() { return AnimationType.PROPERTY; } + + // TODO(crbug.com/444470792): Determine what pieces of logic are dynamic and need handling. Any + // entries that need adding? + public static final ChromeBaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = + new ChromeBaseSearchIndexProvider(TracingCategoriesSettings.class.getName(), 0); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tracing/settings/TracingSettings.java b/chrome/android/java/src/org/chromium/chrome/browser/tracing/settings/TracingSettings.java index e986c8fb..2ba3509 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tracing/settings/TracingSettings.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tracing/settings/TracingSettings.java
@@ -19,6 +19,7 @@ import org.chromium.chrome.browser.preferences.ChromePreferenceKeys; import org.chromium.chrome.browser.preferences.ChromeSharedPreferences; import org.chromium.chrome.browser.settings.ChromeBaseSettingsFragment; +import org.chromium.chrome.browser.settings.search.ChromeBaseSearchIndexProvider; import org.chromium.chrome.browser.tracing.TracingController; import org.chromium.chrome.browser.tracing.TracingNotificationManager; import org.chromium.components.browser_ui.settings.EmbeddableSettingsPage; @@ -315,4 +316,9 @@ public @AnimationType int getAnimationType() { return AnimationType.PROPERTY; } + + // TODO(crbug.com/444470792): Determine what pieces of logic are dynamic and need handling. + public static final ChromeBaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = + new ChromeBaseSearchIndexProvider( + TracingSettings.class.getName(), R.xml.tracing_preferences); }
diff --git a/chrome/android/javatests/BUILD.gn b/chrome/android/javatests/BUILD.gn index 7c3c1aa..ad72446 100644 --- a/chrome/android/javatests/BUILD.gn +++ b/chrome/android/javatests/BUILD.gn
@@ -1623,6 +1623,7 @@ "//chrome/browser/ntp_customization:java", "//components/browser_ui/http_auth/android:java", "//third_party/androidx:androidx_test_ext_junit_java", + "//third_party/blink/public/mojom:credentialmanagement_mojo_bindings_java", "//ui/android:ui_java", "//ui/android:ui_java_test_support", ]
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/ChromeTabbedActivityTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/ChromeTabbedActivityTest.java index 1bab073..008abe9 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/ChromeTabbedActivityTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/ChromeTabbedActivityTest.java
@@ -60,8 +60,6 @@ import org.chromium.chrome.browser.multiwindow.MultiInstanceManager.PersistedInstanceType; import org.chromium.chrome.browser.multiwindow.MultiWindowUtils; import org.chromium.chrome.browser.night_mode.NightModeStateProvider; -import org.chromium.chrome.browser.preferences.ChromePreferenceKeys; -import org.chromium.chrome.browser.preferences.ChromeSharedPreferences; import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tab.TabLaunchType; import org.chromium.chrome.browser.tab.TabTestUtils; @@ -233,41 +231,6 @@ } @Test - @SmallTest - @MinAndroidSdkLevel(VERSION_CODES.S) - public void testTabModelSelectorObserverOnTabStateInitialized() { - // Get the original value of |mCreatedTabOnStartup|. - boolean createdTabOnStartup = mActivity.getCreatedTabOnStartupForTesting(); - - // Reset the values of |mCreatedTabOnStartup| and |MultiInstanceManager.mTabModelObserver|. - // This tab model selector observer should be registered in MultiInstanceManager on tab - // state initialization irrespective of the value of |mCreatedTabOnStartup|. - mActivity.setCreatedTabOnStartupForTesting(false); - mActivity.getMultiInstanceMangerForTesting().setTabModelObserverForTesting(null); - - var tabModelSelectorObserver = mActivity.getTabModelSelectorObserverForTesting(); - ThreadUtils.runOnUiThreadBlocking(tabModelSelectorObserver::onTabStateInitialized); - Assert.assertTrue( - "Regular tab count should be written to SharedPreferences after tab state" - + " initialization.", - ChromeSharedPreferences.getInstance() - .readIntsWithPrefix(ChromePreferenceKeys.MULTI_INSTANCE_TAB_COUNT) - .size() - > 0); - Assert.assertTrue( - "Incognito tab count should be written to SharedPreferences after tab state" - + " initialization.", - ChromeSharedPreferences.getInstance() - .readIntsWithPrefix( - ChromePreferenceKeys.MULTI_INSTANCE_INCOGNITO_TAB_COUNT) - .size() - > 0); - - // Restore the original value of |mCreatedTabOnStartup|. - mActivity.setCreatedTabOnStartupForTesting(createdTabOnStartup); - } - - @Test @MediumTest @DisabledTest(message = "https://crbug.com/1347506") public void testMultiUrlIntent() {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/ChromeContextMenuPopulatorTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/ChromeContextMenuPopulatorTest.java index ed0f809a..d832db9 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/ChromeContextMenuPopulatorTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/ChromeContextMenuPopulatorTest.java
@@ -132,6 +132,7 @@ @Before public void setUp() { + ChromeContextMenuPopulator.setIsDefaultBrowserForTesting(false); mAutomotiveRule.setIsAutomotive(false); DownloadUtils.setIsDownloadRestrictedByPolicyForTesting(false); NativeLibraryTestUtils.loadNativeLibraryNoBrowserProcess();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/CustomTabContextMenuTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/CustomTabContextMenuTest.java index 1738fe4..c4671875 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/CustomTabContextMenuTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/CustomTabContextMenuTest.java
@@ -62,6 +62,7 @@ @Before public void setUp() { + ChromeContextMenuPopulator.setIsDefaultBrowserForTesting(false); ThreadUtils.runOnUiThreadBlocking(() -> FirstRunStatus.setFirstRunFlowComplete(true)); EmbeddedTestServer testServer =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/multiwindow/MultiInstanceManagerApi31Test.java b/chrome/android/javatests/src/org/chromium/chrome/browser/multiwindow/MultiInstanceManagerApi31Test.java index 3cd20b09..59471722 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/multiwindow/MultiInstanceManagerApi31Test.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/multiwindow/MultiInstanceManagerApi31Test.java
@@ -19,6 +19,7 @@ import androidx.test.runner.lifecycle.Stage; import org.junit.After; +import org.junit.Assert; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -113,6 +114,38 @@ } } + @Test + @SmallTest + public void testTabModelSelectorObserverOnTabStateInitialized() { + ChromeTabbedActivity activity = mActivityTestRule.getActivity(); + + // Get the original value of |mCreatedTabOnStartup|. + boolean createdTabOnStartup = activity.getCreatedTabOnStartupForTesting(); + + // Reset the values of |mCreatedTabOnStartup| and |MultiInstanceManager.mTabModelObserver|. + // This tab model selector observer should be registered in MultiInstanceManager on tab + // state initialization irrespective of the value of |mCreatedTabOnStartup|. + activity.setCreatedTabOnStartupForTesting(false); + activity.getMultiInstanceMangerForTesting().setTabModelObserverForTesting(null); + + var tabModelSelectorObserver = activity.getTabModelSelectorObserverForTesting(); + ThreadUtils.runOnUiThreadBlocking(tabModelSelectorObserver::onTabStateInitialized); + Assert.assertEquals( + "Regular tab count should be written to persistent store after tab state" + + " initialization.", + 1, + MultiInstancePersistentStore.readNormalTabCount(activity.getWindowIdForTesting())); + Assert.assertEquals( + "Incognito tab count should be written to persistent store after tab state" + + " initialization.", + 0, + MultiInstancePersistentStore.readIncognitoTabCount( + activity.getWindowIdForTesting())); + + // Restore the original value of |mCreatedTabOnStartup|. + activity.setCreatedTabOnStartupForTesting(createdTabOnStartup); + } + // Initial state: max limit = 4, active tasks = 4, inactive tasks = 0. // Final state: max limit = 2, active tasks = 2, inactive tasks = 2. @Test
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/multiwindow/MultiInstanceManagerApi31UnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/multiwindow/MultiInstanceManagerApi31UnitTest.java index 5964906b..43c7a9b9 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/multiwindow/MultiInstanceManagerApi31UnitTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/multiwindow/MultiInstanceManagerApi31UnitTest.java
@@ -143,7 +143,10 @@ /** Unit tests for {@link MultiInstanceManagerApi31}. */ @RunWith(BaseRobolectricTestRunner.class) @Config(manifest = Config.NONE) -@EnableFeatures(ChromeFeatureList.ROBUST_WINDOW_MANAGEMENT) +@EnableFeatures({ + ChromeFeatureList.ROBUST_WINDOW_MANAGEMENT, + ChromeFeatureList.INSTANCE_SWITCHER_V2 +}) @DisableFeatures(ChromeFeatureList.ROBUST_WINDOW_MANAGEMENT_EXPERIMENTAL) public class MultiInstanceManagerApi31UnitTest { private static final int INSTANCE_ID_1 = 1; @@ -273,7 +276,8 @@ } private void createInstance(int instanceId, Activity activity) { - MultiInstanceManagerApi31.writeUrl(instanceId, "https://id-" + instanceId + ".com"); + MultiInstancePersistentStore.writeActiveTabUrl( + instanceId, "https://id-" + instanceId + ".com"); ApplicationStatus.onStateChangeForTesting(activity, ActivityState.CREATED); updateTasksWithoutDestroyingActivity(instanceId, activity); addInstanceInfo(instanceId, activity.getTaskId()); @@ -301,7 +305,7 @@ instanceId, taskId, type, - MultiInstanceManagerApi31.readUrl(instanceId), + MultiInstancePersistentStore.readActiveTabUrl(instanceId), /* title= */ "", /* customTitle= */ null, /* tabCount= */ 0, @@ -514,6 +518,7 @@ when(mTabGroupModelFilter.getTabModel()).thenReturn(mNormalTabModel); when(mNormalTabModel.getProfile()).thenReturn(mProfile); when(mTabModelSelector.isTabStateInitialized()).thenReturn(true); + doNothing().when(mMultiInstanceManager).showTargetSelectorDialog(any(), anyInt(), anyInt()); } @After @@ -994,8 +999,7 @@ when(mTabModelSelector.isTabStateInitialized()).thenReturn(true); final String customTitle = "My Custom Title"; - ChromeSharedPreferences.getInstance() - .writeString(MultiInstanceManagerApi31.customTitleKey(INSTANCE_ID_1), customTitle); + MultiInstancePersistentStore.writeCustomTitle(INSTANCE_ID_1, customTitle); triggerSelectTab(tabModelObserver, mTab1); assertFalse( @@ -1004,11 +1008,11 @@ assertEquals( "Title should be from the active normal tab", TITLE1, - MultiInstanceManagerApi31.readTitle(INSTANCE_ID_1)); + MultiInstancePersistentStore.readActiveTabTitle(INSTANCE_ID_1)); assertEquals( "URL should be from the active normal tab", URL1.getSpec(), - MultiInstanceManagerApi31.readUrl(INSTANCE_ID_1)); + MultiInstancePersistentStore.readActiveTabUrl(INSTANCE_ID_1)); // Update url/title as a new normal tab is selected. triggerSelectTab(tabModelObserver, mTab2); @@ -1018,11 +1022,11 @@ assertEquals( "Title should be from the active normal tab", TITLE2, - MultiInstanceManagerApi31.readTitle(INSTANCE_ID_1)); + MultiInstancePersistentStore.readActiveTabTitle(INSTANCE_ID_1)); assertEquals( "URL should be from the active normal tab", URL2.getSpec(), - MultiInstanceManagerApi31.readUrl(INSTANCE_ID_1)); + MultiInstancePersistentStore.readActiveTabUrl(INSTANCE_ID_1)); // Incognito tab doesn't affect url/title when selected. triggerSelectTab(tabModelObserver, mTab3); @@ -1032,11 +1036,11 @@ assertEquals( "Title should be from the active normal tab", TITLE2, - MultiInstanceManagerApi31.readTitle(INSTANCE_ID_1)); + MultiInstancePersistentStore.readActiveTabTitle(INSTANCE_ID_1)); assertEquals( "URL should be from the active normal tab", URL2.getSpec(), - MultiInstanceManagerApi31.readUrl(INSTANCE_ID_1)); + MultiInstancePersistentStore.readActiveTabUrl(INSTANCE_ID_1)); // Nulled-tab doesn't affect url/title either. triggerSelectTab(tabModelObserver, null); @@ -1046,15 +1050,15 @@ assertEquals( "Null tab should not affect the title", TITLE2, - MultiInstanceManagerApi31.readTitle(INSTANCE_ID_1)); + MultiInstancePersistentStore.readActiveTabTitle(INSTANCE_ID_1)); assertEquals( "Null tab should not affect the URL", URL2.getSpec(), - MultiInstanceManagerApi31.readUrl(INSTANCE_ID_1)); + MultiInstancePersistentStore.readActiveTabUrl(INSTANCE_ID_1)); assertEquals( "Custom title should not change when tab changes.", customTitle, - MultiInstanceManagerApi31.readCustomTitle(INSTANCE_ID_1)); + MultiInstancePersistentStore.readCustomTitle(INSTANCE_ID_1)); } @Test @@ -1069,7 +1073,7 @@ assertEquals( "Custom title should be updated in SharedPreferences.", newTitle, - MultiInstanceManagerApi31.readCustomTitle(instanceId)); + MultiInstancePersistentStore.readCustomTitle(instanceId)); } @Test @@ -1108,46 +1112,64 @@ final String normalTabMessage = "Normal tab count does not match"; final String incognitoTabMessage = "Normal tab count does not match"; triggerAddTab(tabModelObserver, mTab1); // normal tab added - assertEquals(normalTabMessage, 1, MultiInstanceManagerApi31.readTabCount(INSTANCE_ID_1)); + assertEquals( + normalTabMessage, + 1, + MultiInstancePersistentStore.readNormalTabCount(INSTANCE_ID_1)); assertEquals( incognitoTabMessage, 0, - MultiInstanceManagerApi31.readIncognitoTabCount(INSTANCE_ID_1)); + MultiInstancePersistentStore.readIncognitoTabCount(INSTANCE_ID_1)); triggerAddTab(tabModelObserver, mTab2); // normal tab added - assertEquals(normalTabMessage, 2, MultiInstanceManagerApi31.readTabCount(INSTANCE_ID_1)); + assertEquals( + normalTabMessage, + 2, + MultiInstancePersistentStore.readNormalTabCount(INSTANCE_ID_1)); assertEquals( incognitoTabMessage, 0, - MultiInstanceManagerApi31.readIncognitoTabCount(INSTANCE_ID_1)); + MultiInstancePersistentStore.readIncognitoTabCount(INSTANCE_ID_1)); triggerAddTab(tabModelObserver, mTab3); // incognito tab added - assertEquals(normalTabMessage, 2, MultiInstanceManagerApi31.readTabCount(INSTANCE_ID_1)); + assertEquals( + normalTabMessage, + 2, + MultiInstancePersistentStore.readNormalTabCount(INSTANCE_ID_1)); assertEquals( incognitoTabMessage, 1, - MultiInstanceManagerApi31.readIncognitoTabCount(INSTANCE_ID_1)); + MultiInstancePersistentStore.readIncognitoTabCount(INSTANCE_ID_1)); triggerOnFinishingTabClosure(tabModelObserver, mTab1); - assertEquals(normalTabMessage, 1, MultiInstanceManagerApi31.readTabCount(INSTANCE_ID_1)); + assertEquals( + normalTabMessage, + 1, + MultiInstancePersistentStore.readNormalTabCount(INSTANCE_ID_1)); assertEquals( incognitoTabMessage, 1, - MultiInstanceManagerApi31.readIncognitoTabCount(INSTANCE_ID_1)); + MultiInstancePersistentStore.readIncognitoTabCount(INSTANCE_ID_1)); triggerTabRemoved(tabModelObserver, mTab3); - assertEquals(normalTabMessage, 1, MultiInstanceManagerApi31.readTabCount(INSTANCE_ID_1)); + assertEquals( + normalTabMessage, + 1, + MultiInstancePersistentStore.readNormalTabCount(INSTANCE_ID_1)); assertEquals( incognitoTabMessage, 0, - MultiInstanceManagerApi31.readIncognitoTabCount(INSTANCE_ID_1)); + MultiInstancePersistentStore.readIncognitoTabCount(INSTANCE_ID_1)); triggerTabRemoved(tabModelObserver, mTab2); - assertEquals(normalTabMessage, 0, MultiInstanceManagerApi31.readTabCount(INSTANCE_ID_1)); + assertEquals( + normalTabMessage, + 0, + MultiInstancePersistentStore.readNormalTabCount(INSTANCE_ID_1)); assertEquals( incognitoTabMessage, 0, - MultiInstanceManagerApi31.readIncognitoTabCount(INSTANCE_ID_1)); + MultiInstancePersistentStore.readIncognitoTabCount(INSTANCE_ID_1)); } @Test @@ -1191,35 +1213,35 @@ assertEquals( "Title should be from the active normal tab", TITLE1, - MultiInstanceManagerApi31.readTitle(INSTANCE_ID_1)); + MultiInstancePersistentStore.readActiveTabTitle(INSTANCE_ID_1)); assertEquals( "URL should be from the active normal tab", URL1.getSpec(), - MultiInstanceManagerApi31.readUrl(INSTANCE_ID_1)); + MultiInstancePersistentStore.readActiveTabUrl(INSTANCE_ID_1)); triggerAddTab(tabModelObserver, mTab2); triggerSelectTab(tabModelObserver, mTab2); assertEquals( "Title should be from the active normal tab", TITLE2, - MultiInstanceManagerApi31.readTitle(INSTANCE_ID_1)); + MultiInstancePersistentStore.readActiveTabTitle(INSTANCE_ID_1)); assertEquals( "URL should be from the active normal tab", URL2.getSpec(), - MultiInstanceManagerApi31.readUrl(INSTANCE_ID_1)); + MultiInstancePersistentStore.readActiveTabUrl(INSTANCE_ID_1)); triggerOnFinishingTabClosure(tabModelObserver, mTab1); triggerTabRemoved(tabModelObserver, mTab2); assertEquals( "Tab count should be zero", 0, - MultiInstanceManagerApi31.readTabCount(INSTANCE_ID_1)); + MultiInstancePersistentStore.readNormalTabCount(INSTANCE_ID_1)); assertTrue( "Title was not cleared", - TextUtils.isEmpty(MultiInstanceManagerApi31.readTitle(INSTANCE_ID_1))); + TextUtils.isEmpty(MultiInstancePersistentStore.readActiveTabTitle(INSTANCE_ID_1))); assertTrue( "URL was not cleared", - TextUtils.isEmpty(MultiInstanceManagerApi31.readUrl(INSTANCE_ID_1))); + TextUtils.isEmpty(MultiInstancePersistentStore.readActiveTabUrl(INSTANCE_ID_1))); } @Test @@ -1266,18 +1288,12 @@ @Test public void testRemoveInstanceInfo() { int index = 1; - String urlKey = MultiInstanceManagerApi31.urlKey(index); - ChromeSharedPreferences.getInstance().writeString(urlKey, ""); - String titleKey = MultiInstanceManagerApi31.titleKey(index); - ChromeSharedPreferences.getInstance().writeString(titleKey, ""); - String customTitleKey = MultiInstanceManagerApi31.customTitleKey(index); - ChromeSharedPreferences.getInstance().writeString(customTitleKey, ""); - String tabCountKey = MultiInstanceManagerApi31.tabCountKey(index); - ChromeSharedPreferences.getInstance().writeInt(tabCountKey, 1); - String tabCountForRelaunch = MultiInstanceManagerApi31.tabCountForRelaunchKey(index); - ChromeSharedPreferences.getInstance().writeInt(tabCountForRelaunch, 1); - String incognitoTabCountKey = MultiInstanceManagerApi31.incognitoTabCountKey(index); - ChromeSharedPreferences.getInstance().writeInt(incognitoTabCountKey, 1); + MultiInstancePersistentStore.writeActiveTabUrl(index, /* url= */ "url"); + MultiInstancePersistentStore.writeActiveTabTitle(index, /* title= */ "title"); + MultiInstancePersistentStore.writeCustomTitle(index, /* title= */ "title"); + MultiInstancePersistentStore.writeTabCount( + index, /* normalTabCount= */ 1, /* incognitoTabCount= */ 1); + MultiInstancePersistentStore.writeTabCountForRelaunchSync(index, /* tabCount= */ 2); String incognitoSelectedKey = MultiInstanceManagerApi31.incognitoSelectedKey(index); ChromeSharedPreferences.getInstance().writeBoolean(incognitoSelectedKey, false); String lastAccessedTimeKey = MultiInstanceManagerApi31.lastAccessedTimeKey(index); @@ -1294,24 +1310,27 @@ MultiInstanceManagerApi31.removeInstanceInfo(index, CloseWindowAppSource.OTHER); histogramWatcher.assertExpected(); - assertFalse( - "Shared preference key should be removed.", - ChromeSharedPreferences.getInstance().contains(urlKey)); - assertFalse( - "Shared preference key should be removed.", - ChromeSharedPreferences.getInstance().contains(titleKey)); - assertFalse( - "Shared preference key should be removed.", - ChromeSharedPreferences.getInstance().contains(customTitleKey)); - assertFalse( - "Shared preference key should be removed.", - ChromeSharedPreferences.getInstance().contains(tabCountKey)); - assertFalse( - "Shared preference key should be removed.", - ChromeSharedPreferences.getInstance().contains(tabCountForRelaunch)); - assertFalse( - "Shared preference key should be removed.", - ChromeSharedPreferences.getInstance().contains(incognitoTabCountKey)); + assertNull( + "Persistent store should be updated.", + MultiInstancePersistentStore.readActiveTabUrl(index)); + assertNull( + "Persistent store should be updated.", + MultiInstancePersistentStore.readActiveTabTitle(index)); + assertNull( + "Persistent store should be updated.", + MultiInstancePersistentStore.readCustomTitle(index)); + assertEquals( + "Persistent store should be updated.", + 0, + MultiInstancePersistentStore.readNormalTabCount(index)); + assertEquals( + "Persistent store should be updated.", + 0, + MultiInstancePersistentStore.readTabCountForRelaunch(index)); + assertEquals( + "Persistent store should be updated.", + 0, + MultiInstancePersistentStore.readIncognitoTabCount(index)); assertFalse( "Shared preference key should be removed.", ChromeSharedPreferences.getInstance().contains(incognitoSelectedKey)); @@ -1386,9 +1405,9 @@ MultiInstancePersistentStore.writeTaskId(instanceId, activity.getTaskId()); // Store minimal data to get the instance recognized. - MultiInstanceManagerApi31.writeUrl(instanceId, "url" + instanceId); - ChromeSharedPreferences.getInstance() - .writeInt(MultiInstanceManagerApi31.tabCountKey(index), 1); + MultiInstancePersistentStore.writeActiveTabUrl(instanceId, "url" + instanceId); + MultiInstancePersistentStore.writeTabCount( + instanceId, /* normalTabCount= */ 1, /* incognitoTabCount= */ 0); return instanceId; } @@ -2477,8 +2496,8 @@ final String customTitle = "Custom Title"; final String defaultTitle = "Default Title"; - MultiInstanceManagerApi31.writeCustomTitle(INSTANCE_ID_1, customTitle); - MultiInstanceManagerApi31.writeTitle(INSTANCE_ID_1, defaultTitle); + MultiInstancePersistentStore.writeCustomTitle(INSTANCE_ID_1, customTitle); + MultiInstancePersistentStore.writeActiveTabTitle(INSTANCE_ID_1, defaultTitle); manager.showNameWindowDialog(NameWindowDialogSource.TAB_STRIP); @@ -2499,9 +2518,8 @@ manager.initialize(INSTANCE_ID_1, TASK_ID_56, SupportedProfileType.MIXED); final String defaultTitle = "Default Title"; - MultiInstanceManagerApi31.writeTitle(INSTANCE_ID_1, defaultTitle); - ChromeSharedPreferences.getInstance() - .removeKey(MultiInstanceManagerApi31.customTitleKey(INSTANCE_ID_1)); + MultiInstancePersistentStore.writeActiveTabTitle(INSTANCE_ID_1, defaultTitle); + MultiInstancePersistentStore.removeCustomTitle(INSTANCE_ID_1); manager.showNameWindowDialog(NameWindowDialogSource.TAB_STRIP); @@ -2521,7 +2539,7 @@ var manager = createMultiInstanceManager(realActivity); manager.initialize(INSTANCE_ID_1, TASK_ID_56, SupportedProfileType.MIXED); final String defaultTitle = "Default Title"; - MultiInstanceManagerApi31.writeTitle(INSTANCE_ID_1, defaultTitle); + MultiInstancePersistentStore.writeActiveTabTitle(INSTANCE_ID_1, defaultTitle); manager.showNameWindowDialog(NameWindowDialogSource.TAB_STRIP); @@ -2538,7 +2556,7 @@ assertEquals( "New custom title should be saved.", newTitle, - MultiInstanceManagerApi31.readCustomTitle(INSTANCE_ID_1)); + MultiInstancePersistentStore.readCustomTitle(INSTANCE_ID_1)); } @Test @@ -2547,7 +2565,7 @@ var manager = createMultiInstanceManager(realActivity); manager.initialize(INSTANCE_ID_1, TASK_ID_56, SupportedProfileType.MIXED); final String defaultTitle = "Default Title"; - MultiInstanceManagerApi31.writeTitle(INSTANCE_ID_1, defaultTitle); + MultiInstancePersistentStore.writeActiveTabTitle(INSTANCE_ID_1, defaultTitle); manager.showNameWindowDialog(NameWindowDialogSource.TAB_STRIP); @@ -2562,6 +2580,94 @@ assertFalse("Dialog should be dismissed.", dialog.isShowing()); assertNull( "Custom title should not be saved if identical to default title.", - MultiInstanceManagerApi31.readCustomTitle(INSTANCE_ID_1)); + MultiInstancePersistentStore.readCustomTitle(INSTANCE_ID_1)); + } + + @Test + @DisableFeatures({ChromeFeatureList.ANDROID_OPEN_INCOGNITO_AS_WINDOW}) + public void testMoveTabsToOtherWindow_dialogShown() { + MultiWindowUtils.setInstanceCountForTesting(2); + List<Tab> tabs = List.of(mTab1, mTab2); + + mMultiInstanceManager.moveTabsToOtherWindow(tabs, NewWindowAppSource.OTHER); + + verify(mMultiInstanceManager, times(1)) + .showTargetSelectorDialog( + any(), + eq(PersistedInstanceType.ANY), + eq(R.string.menu_move_tab_to_other_window)); + } + + @Test + @EnableFeatures({ + ChromeFeatureList.ANDROID_OPEN_INCOGNITO_AS_WINDOW, + }) + public void testMoveTabsToOtherWindow_incognitoTabs_dialogShown() { + MultiWindowUtils.setInstanceCountForTesting(1); + MultiWindowUtils.setIncognitoInstanceCountForTesting(2); + List<Tab> tabs = List.of(mTab1); + when(mTab1.isIncognitoBranded()).thenReturn(true); + + mMultiInstanceManager.moveTabsToOtherWindow(tabs, NewWindowAppSource.OTHER); + + verify(mMultiInstanceManager, times(1)) + .showTargetSelectorDialog( + any(), + eq(PersistedInstanceType.ACTIVE | PersistedInstanceType.OFF_THE_RECORD), + eq(R.string.menu_move_tab_to_other_window)); + } + + @Test + @EnableFeatures({ + ChromeFeatureList.ANDROID_OPEN_INCOGNITO_AS_WINDOW, + }) + public void testMoveTabsToOtherWindow_incognitoTabs_dialogHidden() { + MultiWindowUtils.setIncognitoInstanceCountForTesting(1); + List<Tab> tabs = List.of(mTab1); + when(mTab1.isIncognitoBranded()).thenReturn(true); + doNothing().when(mMultiInstanceManager).moveTabsToNewWindow(tabs, NewWindowAppSource.OTHER); + + mMultiInstanceManager.moveTabsToOtherWindow(tabs, NewWindowAppSource.OTHER); + + verify(mMultiInstanceManager, Mockito.never()) + .showTargetSelectorDialog( + any(), anyInt(), eq(R.string.menu_move_tab_to_other_window)); + verify(mMultiInstanceManager, times(1)).moveTabsToNewWindow(tabs, NewWindowAppSource.OTHER); + } + + @Test + @EnableFeatures({ + ChromeFeatureList.ANDROID_OPEN_INCOGNITO_AS_WINDOW, + }) + public void testMoveTabsToOtherWindow_regularTabs_dialogShown() { + MultiWindowUtils.setInstanceCountForTesting(2); + List<Tab> tabs = List.of(mTab1, mTab2); + when(mTab1.isIncognitoBranded()).thenReturn(false); + + mMultiInstanceManager.moveTabsToOtherWindow(tabs, NewWindowAppSource.OTHER); + + verify(mMultiInstanceManager, times(1)) + .showTargetSelectorDialog( + any(), + eq(PersistedInstanceType.ACTIVE | PersistedInstanceType.REGULAR), + eq(R.string.menu_move_tab_to_other_window)); + } + + @Test + @EnableFeatures({ + ChromeFeatureList.ANDROID_OPEN_INCOGNITO_AS_WINDOW, + }) + public void testMoveTabsToOtherWindow_regularTabs_dialogHidden() { + MultiWindowUtils.setInstanceCountForTesting(1); + List<Tab> tabs = List.of(mTab1, mTab2); + when(mTab1.isIncognitoBranded()).thenReturn(false); + doNothing().when(mMultiInstanceManager).moveTabsToNewWindow(tabs, NewWindowAppSource.OTHER); + + mMultiInstanceManager.moveTabsToOtherWindow(tabs, NewWindowAppSource.OTHER); + + verify(mMultiInstanceManager, Mockito.never()) + .showTargetSelectorDialog( + any(), anyInt(), eq(R.string.menu_move_tab_to_other_window)); + verify(mMultiInstanceManager, times(1)).moveTabsToNewWindow(tabs, NewWindowAppSource.OTHER); } }
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/multiwindow/MultiWindowTestUtils.java b/chrome/android/junit/src/org/chromium/chrome/browser/multiwindow/MultiWindowTestUtils.java index 75e6d9e..010c5ff2 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/multiwindow/MultiWindowTestUtils.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/multiwindow/MultiWindowTestUtils.java
@@ -14,16 +14,17 @@ public class MultiWindowTestUtils { /** * Create a new instance information. + * * @param instanceId Instance (aka window) ID. * @param url URL for the active tab. * @param tabCount The number of tabs in the instance. * @param taskId ID of the task the activity instance runs in. */ public static void createInstance(int instanceId, String url, int tabCount, int taskId) { - MultiInstanceManagerApi31.writeUrl(instanceId, url); + MultiInstancePersistentStore.writeActiveTabUrl(instanceId, url); MultiInstanceManagerApi31.writeLastAccessedTime(instanceId); - SharedPreferencesManager prefs = ChromeSharedPreferences.getInstance(); - prefs.writeInt(MultiInstanceManagerApi31.tabCountKey(instanceId), tabCount); + MultiInstancePersistentStore.writeTabCount( + instanceId, tabCount, /* incognitoTabCount= */ 0); MultiInstancePersistentStore.writeTaskId(instanceId, taskId); }
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/multiwindow/MultiWindowUtilsUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/multiwindow/MultiWindowUtilsUnitTest.java index 4eefe7e..7acf7ab 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/multiwindow/MultiWindowUtilsUnitTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/multiwindow/MultiWindowUtilsUnitTest.java
@@ -760,12 +760,12 @@ public void testGetTabCountForRelaunchFromSharedPrefs() { int windowId1 = 0; int windowId2 = 1; - ChromeSharedPreferences.getInstance() - .writeInt(MultiWindowUtils.getTabCountForRelaunchKey(windowId1), 10); - ChromeSharedPreferences.getInstance() - .writeInt(MultiWindowUtils.getTabCountForRelaunchKey(windowId2), 15); - assertEquals(10, MultiWindowUtils.getTabCountForRelaunchFromSharedPrefs(windowId1), 0.01); - assertEquals(15, MultiWindowUtils.getTabCountForRelaunchFromSharedPrefs(windowId2), 0.01); + MultiInstancePersistentStore.writeTabCountForRelaunchSync(windowId1, /* tabCount= */ 10); + MultiInstancePersistentStore.writeTabCountForRelaunchSync(windowId2, /* tabCount= */ 15); + assertEquals( + 10, MultiWindowUtils.getTabCountForRelaunchFromPersistentStore(windowId1), 0.01); + assertEquals( + 15, MultiWindowUtils.getTabCountForRelaunchFromPersistentStore(windowId2), 0.01); } @Test @@ -1103,8 +1103,6 @@ } private void testRecordTabCountForRelaunchWhenActivityPausedImpl(int windowId) { - String tabCountForRelaunchKey = MultiWindowUtils.getTabCountForRelaunchKey(windowId); - List<TabModel> models = Arrays.asList(mNormalTabModel, mIncognitoTabModel); when(mTabModelSelector.getModels()).thenReturn(models); when(mIncognitoTabModel.getCount()).thenReturn(0); @@ -1122,8 +1120,7 @@ when(mNormalTabModel.iterator()).thenAnswer(inv -> List.of(mTab1, mTab2).iterator()); MultiWindowUtils.recordTabCountForRelaunchWhenActivityPaused(mTabModelSelector, windowId); Assert.assertEquals( - /* expected= */ 2, - ChromeSharedPreferences.getInstance().readInt(tabCountForRelaunchKey)); + /* expected= */ 2, MultiInstancePersistentStore.readTabCountForRelaunch(windowId)); // Test the case of adding a non-NTP tab to the tab model. when(mNormalTabModel.getCount()).thenReturn(3); @@ -1133,25 +1130,21 @@ when(mTab3.getUrl()).thenReturn(TEST_GURL); MultiWindowUtils.recordTabCountForRelaunchWhenActivityPaused(mTabModelSelector, windowId); Assert.assertEquals( - /* expected= */ 3, - ChromeSharedPreferences.getInstance().readInt(tabCountForRelaunchKey)); + /* expected= */ 3, MultiInstancePersistentStore.readTabCountForRelaunch(windowId)); // Test the case of adding a NTP tab to the tab model. when(mTab3.isNativePage()).thenReturn(true); when(mTab3.getUrl()).thenReturn(NTP_GURL); MultiWindowUtils.recordTabCountForRelaunchWhenActivityPaused(mTabModelSelector, windowId); Assert.assertEquals( - /* expected= */ 2, - ChromeSharedPreferences.getInstance().readInt(tabCountForRelaunchKey)); + /* expected= */ 2, MultiInstancePersistentStore.readTabCountForRelaunch(windowId)); } private void writeInstanceInfo( int instanceId, String url, int tabCount, int incognitoTabCount, int taskId) { - MultiInstanceManagerApi31.writeUrl(instanceId, url); - when(mNormalTabModel.getCount()).thenReturn(tabCount); - when(mIncognitoTabModel.getCount()).thenReturn(incognitoTabCount); + MultiInstancePersistentStore.writeActiveTabUrl(instanceId, url); MultiInstanceManagerApi31.writeLastAccessedTime(instanceId); - MultiInstanceManagerApi31.writeTabCount(instanceId, mTabModelSelector); + MultiInstancePersistentStore.writeTabCount(instanceId, tabCount, incognitoTabCount); MultiInstancePersistentStore.writeTaskId(instanceId, taskId); } }
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/tabbed_mode/TabbedAppMenuPropertiesDelegateUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/tabbed_mode/TabbedAppMenuPropertiesDelegateUnitTest.java index 722424f4..c8fdbf6 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/tabbed_mode/TabbedAppMenuPropertiesDelegateUnitTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/tabbed_mode/TabbedAppMenuPropertiesDelegateUnitTest.java
@@ -84,12 +84,11 @@ import org.chromium.chrome.browser.layouts.LayoutStateProvider; import org.chromium.chrome.browser.layouts.LayoutType; import org.chromium.chrome.browser.multiwindow.MultiWindowModeStateDispatcher; +import org.chromium.chrome.browser.multiwindow.MultiWindowTestUtils; import org.chromium.chrome.browser.multiwindow.MultiWindowUtils; import org.chromium.chrome.browser.offlinepages.OfflinePageUtils; import org.chromium.chrome.browser.omaha.UpdateMenuItemHelper; import org.chromium.chrome.browser.pdf.PdfPage; -import org.chromium.chrome.browser.preferences.ChromePreferenceKeys; -import org.chromium.chrome.browser.preferences.ChromeSharedPreferences; import org.chromium.chrome.browser.preferences.Pref; import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.profiles.ProfileManager; @@ -365,10 +364,7 @@ BaseRobolectricTestRule.runAllBackgroundAndUi(); mTabbedAppMenuPropertiesDelegate = Mockito.spy(delegate); - ChromeSharedPreferences.getInstance() - .removeKeysWithPrefix(ChromePreferenceKeys.MULTI_INSTANCE_URL); - ChromeSharedPreferences.getInstance() - .removeKeysWithPrefix(ChromePreferenceKeys.MULTI_INSTANCE_TAB_COUNT); + MultiWindowTestUtils.resetInstanceInfo(); CommerceFeatureUtilsJni.setInstanceForTesting(mCommerceFeatureUtilsJniMock); ShoppingServiceFactory.setShoppingServiceForTesting(mShoppingService); @@ -1463,7 +1459,11 @@ .when(mTabbedAppMenuPropertiesDelegate) .instanceSwitcherWithMultiInstanceEnabled(); - createInstance(0, "https://url0"); + MultiWindowTestUtils.createInstance( + /* instanceId= */ 0, + /* url= */ "https://url0", + /* tabCount= */ 1, + /* taskId= */ 123); // On phone, we do not show 'New Window'. mIsTabletScreen = false; @@ -1485,7 +1485,11 @@ assertTrue(isMenuVisible(modelList, R.id.new_window_menu_id)); for (int i = 0; i < MultiWindowUtils.getMaxInstances(); ++i) { - createInstance(i, "https://url" + i); + MultiWindowTestUtils.createInstance( + /* instanceId= */ i, + /* url= */ "https://url" + i, + /* tabCount= */ 1, + /* taskId= */ i); } MVCListAdapter.ModelList modelList2 = createMenuForMultiWindow(); @@ -1515,12 +1519,14 @@ .when(mTabbedAppMenuPropertiesDelegate) .instanceSwitcherWithMultiInstanceEnabled(); - createInstance(0, "https://url0"); + MultiWindowTestUtils.createInstance( + /* instanceId= */ 0, /* url= */ "https://url0", /* tabCount= */ 1, /* taskId= */ 0); MVCListAdapter.ModelList modelList = createMenuForMultiWindow(); assertFalse(isMenuVisible(modelList, R.id.manage_all_windows_menu_id)); - createInstance(1, "https://url1"); + MultiWindowTestUtils.createInstance( + /* instanceId= */ 1, /* url= */ "https://url1", /* tabCount= */ 1, /* taskId= */ 1); MVCListAdapter.ModelList modelList2 = createMenuForMultiWindow(); assertTrue(isMenuVisible(modelList2, R.id.manage_all_windows_menu_id)); @@ -1892,7 +1898,11 @@ boolean isInMultiDisplayMode, boolean isMultiInstanceRunning) { for (int i = 0; i < currentWindowInstances; ++i) { - createInstance(i, "https://url" + i); + MultiWindowTestUtils.createInstance( + /* instanceId= */ i, + /* url= */ "https://url" + i, + /* tabCount= */ 1, + /* taskId= */ i); } mShadowPackageManager.setSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, isAutomotive); doReturn(isInstanceSwitcherEnabled) @@ -2713,18 +2723,6 @@ return items.toString(); } - private static void createInstance(int index, String url) { - String urlKey = ChromePreferenceKeys.MULTI_INSTANCE_URL.createKey(String.valueOf(index)); - ChromeSharedPreferences.getInstance().writeString(urlKey, url); - String tabCountKey = - ChromePreferenceKeys.MULTI_INSTANCE_TAB_COUNT.createKey(String.valueOf(index)); - ChromeSharedPreferences.getInstance().writeInt(tabCountKey, 1); - String accessTimeKey = - ChromePreferenceKeys.MULTI_INSTANCE_LAST_ACCESSED_TIME.createKey( - String.valueOf(index)); - ChromeSharedPreferences.getInstance().writeLong(accessTimeKey, System.currentTimeMillis()); - } - /** Options for tests that control how Menu is being rendered. */ private static class MenuOptions { private boolean mIsNativePage;
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index b342cc3..663945f6 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd
@@ -9680,6 +9680,9 @@ <message name="IDS_READING_MODE_ENABLE_LINKS_BUTTON_LABEL" desc="Accessibility label for the button that enables all links in reading mode content."> Enable links </message> + <message name="IDS_READING_MODE_IMAGES_LABEL" desc="Accessibility label for the enable images menu item in reading mode."> + Images + </message> <message name="IDS_READING_MODE_DISABLE_IMAGES_BUTTON_LABEL" desc="Accessibility label for the button that disables showing images in reading mode content."> Disable images </message> @@ -9900,6 +9903,15 @@ <message name="IDS_READING_MODE_FONT_LOADING_STRING" desc="Text added to a font name in the Reading Mode font dropdown when the font style hasn't loaded yet."> (loading) </message> + <message name="IDS_READING_MODE_LINE_FOCUS_LABEL" desc="Accessibility label for the line focus menu item in reading mode."> + Line focus + </message> + <message name="IDS_READING_MODE_VIEW_IN_SIDE_PANEL_LABEL" desc="Accessibility label for the view in side panel menu item in reading mode."> + View in side panel + </message> + <message name="IDS_READING_MODE_VIEW_IN_FULL_SCREEN_LABEL" desc="Accessibility label for the view in full screen menu item in reading mode."> + View in full screen + </message> <!-- Google Lens side panel --> <message name="IDS_GOOGLE_LENS_TITLE" desc="Title of the Google Lens side panel">
diff --git a/chrome/app/generated_resources_grd/IDS_READING_MODE_IMAGES_LABEL.png.sha1 b/chrome/app/generated_resources_grd/IDS_READING_MODE_IMAGES_LABEL.png.sha1 new file mode 100644 index 0000000..5fde0391 --- /dev/null +++ b/chrome/app/generated_resources_grd/IDS_READING_MODE_IMAGES_LABEL.png.sha1
@@ -0,0 +1 @@ +8fd7adfaf663dff26cd339865a13206e2c63d0a5 \ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_READING_MODE_LINE_FOCUS_LABEL.png.sha1 b/chrome/app/generated_resources_grd/IDS_READING_MODE_LINE_FOCUS_LABEL.png.sha1 new file mode 100644 index 0000000..3e98136 --- /dev/null +++ b/chrome/app/generated_resources_grd/IDS_READING_MODE_LINE_FOCUS_LABEL.png.sha1
@@ -0,0 +1 @@ +6d1982a82325abc76d0d582f85c82570bcb56cea \ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_READING_MODE_VIEW_IN_FULL_SCREEN_LABEL.png.sha1 b/chrome/app/generated_resources_grd/IDS_READING_MODE_VIEW_IN_FULL_SCREEN_LABEL.png.sha1 new file mode 100644 index 0000000..9fc08d3 --- /dev/null +++ b/chrome/app/generated_resources_grd/IDS_READING_MODE_VIEW_IN_FULL_SCREEN_LABEL.png.sha1
@@ -0,0 +1 @@ +f6d5c3d36eea048ed5058bf653d46bbcc5f44dab \ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_READING_MODE_VIEW_IN_SIDE_PANEL_LABEL.png.sha1 b/chrome/app/generated_resources_grd/IDS_READING_MODE_VIEW_IN_SIDE_PANEL_LABEL.png.sha1 new file mode 100644 index 0000000..e73b91a --- /dev/null +++ b/chrome/app/generated_resources_grd/IDS_READING_MODE_VIEW_IN_SIDE_PANEL_LABEL.png.sha1
@@ -0,0 +1 @@ +d06326e7fa544b3d7658d64dcd7c9a771b5240ee \ No newline at end of file
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index 74a0158..91b46503 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -4574,6 +4574,22 @@ kGlicEntrypointVariationsLabelAndIconAndHighlight, std::size(kGlicEntrypointVariationsLabelAndIconAndHighlight), nullptr}, }; + +const FeatureEntry::FeatureParam kGlicTrustFirstOnboardingArm1Params[] = { + {"arm", "1"}}; +const FeatureEntry::FeatureParam kGlicTrustFirstOnboardingArm2Params[] = { + {"arm", "2"}}; +const FeatureEntry::FeatureParam kGlicTrustFirstOnboardingArm3Params[] = { + {"arm", "3"}}; + +const FeatureEntry::FeatureVariation kGlicTrustFirstOnboardingVariations[] = { + {"- Arm 1: Start Chat", kGlicTrustFirstOnboardingArm1Params, + std::size(kGlicTrustFirstOnboardingArm1Params), nullptr}, + {"- Arm 2: Welcome Screen", kGlicTrustFirstOnboardingArm2Params, + std::size(kGlicTrustFirstOnboardingArm2Params), nullptr}, + {"- Arm 3: In-Flow opt-in", kGlicTrustFirstOnboardingArm3Params, + std::size(kGlicTrustFirstOnboardingArm3Params), nullptr}, +}; #endif // BUILDFLAG(ENABLE_GLIC) const FeatureEntry::FeatureParam kAutofillShowTypePredictionsAsTitle[] = { @@ -5847,6 +5863,10 @@ FEATURE_WITH_PARAMS_VALUE_TYPE(dom_distiller::kReaderModeImprovements, kReaderModeImprovementsChoices, "Reader Mode Improvements")}, + {"reader-mode-support-new-fonts", + flag_descriptions::kReaderModeSupportNewFontsName, + flag_descriptions::kReaderModeSupportNewFontsDescription, kOsAndroid, + FEATURE_VALUE_TYPE(dom_distiller::kReaderModeSupportNewFonts)}, {"reader-mode-use-readability", flag_descriptions::kReaderModeUseReadabilityName, flag_descriptions::kReaderModeUseReadabilityDescription, kOsAndroid, @@ -8017,10 +8037,6 @@ FEATURE_VALUE_TYPE( chrome::android::kMayLaunchUrlUsesSeparateStoragePartition)}, - {"mini-origin-bar", flag_descriptions::kMiniOriginBarName, - flag_descriptions::kMiniOriginBarDescription, kOsAndroid, - FEATURE_VALUE_TYPE(chrome::android::kMiniOriginBar)}, - {"enable-segmentation-platform-android-home-module-ranker-v2", flag_descriptions::kSegmentationPlatformAndroidHomeModuleRankerV2Name, flag_descriptions:: @@ -11620,6 +11636,10 @@ flag_descriptions::kGlicPanelResetSizeAndLocationName, flag_descriptions::kGlicPanelResetSizeAndLocationDescription, kOsDesktop, FEATURE_VALUE_TYPE(features::kGlicPanelResetSizeAndLocationOnOpen)}, + {"glic-print-menu-item", flag_descriptions::kGlicPrintMenuItemName, + flag_descriptions::kGlicPrintMenuItemDescription, + kOsMac | kOsWin | kOsLinux, + FEATURE_VALUE_TYPE(features::kGlicPrintMenuItem)}, {"glic-pre-warming", flag_descriptions::kGlicWarmingName, flag_descriptions::kGlicWarmingDescription, kOsDesktop, FEATURE_WITH_PARAMS_VALUE_TYPE(features::kGlicWarming, @@ -11666,6 +11686,12 @@ {"glic-live-mode-only-glow", flag_descriptions::kGlicLiveModeOnlyGlowName, flag_descriptions::kGlicLiveModeOnlyGlowDescription, kOsDesktop, FEATURE_VALUE_TYPE(features::kGlicLiveModeOnlyGlow)}, + {"glic-trust-first-onboarding", + flag_descriptions::kGlicTrustFirstOnboardingName, + flag_descriptions::kGlicTrustFirstOnboardingDescription, kOsDesktop, + FEATURE_WITH_PARAMS_VALUE_TYPE(features::kGlicTrustFirstOnboarding, + kGlicTrustFirstOnboardingVariations, + "GlicTrustFirstOnboarding")}, #if BUILDFLAG(IS_CHROMEOS) {"glic-use-non-client", flag_descriptions::kGlicUseNonClientName, flag_descriptions::kGlicUseNonClientDescription, kOsCrOS, @@ -13485,6 +13511,10 @@ autofill::features::kAutofillEnableNewFopDisplayAndroid)}, #endif + {"idb-sqlite-backing-store", flag_descriptions::kIdbSqliteBackingStoreName, + flag_descriptions::kIdbSqliteBackingStoreDescription, kOsAll, + FEATURE_VALUE_TYPE(features::kIdbSqliteBackingStore)}, + #if BUILDFLAG(IS_ANDROID) {"android-caret-browsing", flag_descriptions::kAndroidCaretBrowsingName, flag_descriptions::kAndroidCaretBrowsingDescription, kOsAndroid,
diff --git a/chrome/browser/actor/execution_engine_unittest.cc b/chrome/browser/actor/execution_engine_unittest.cc index 832daa14..d8deea1 100644 --- a/chrome/browser/actor/execution_engine_unittest.cc +++ b/chrome/browser/actor/execution_engine_unittest.cc
@@ -84,6 +84,10 @@ constexpr char kActorTaskDurationNotVisibleCompletedHistogram[] = "Actor.Task.Duration.NotVisible.Completed"; +actor::mojom::ActionResultPtr MakeNotImplementedResult() { + return MakeResult(::actor::mojom::ActionResultCode::kNotImplemented); +} + class FakeChromeRenderFrame : public chrome::mojom::ChromeRenderFrame { public: FakeChromeRenderFrame() = default; @@ -378,23 +382,23 @@ TEST_F(ExecutionEngineTest, UiOnPreToolFails) { EXPECT_CALL(*mock_ui_event_dispatcher_, OnPreTool) .WillOnce(UiEventDispatcherCallback<ToolRequest>( - base::BindRepeating(MakeErrorResult))); + base::BindRepeating(MakeNotImplementedResult))); EXPECT_CALL(*mock_ui_event_dispatcher_, OnPostTool).Times(0); EXPECT_FALSE( Act(GURL("http://localhost/"), MakeClickCallback(kFakeContentNodeId))); histograms_.ExpectUniqueSample(kActionResultHistogram, - mojom::ActionResultCode::kError, 1); + mojom::ActionResultCode::kNotImplemented, 1); } TEST_F(ExecutionEngineTest, UiOnPostToolFails) { EXPECT_CALL(*mock_ui_event_dispatcher_, OnPreTool).Times(1); EXPECT_CALL(*mock_ui_event_dispatcher_, OnPostTool) .WillOnce(UiEventDispatcherCallback<ToolRequest>( - base::BindRepeating(MakeErrorResult))); + base::BindRepeating(MakeNotImplementedResult))); EXPECT_FALSE( Act(GURL("http://localhost/"), MakeClickCallback(kFakeContentNodeId))); histograms_.ExpectUniqueSample(kActionResultHistogram, - mojom::ActionResultCode::kError, 1); + mojom::ActionResultCode::kNotImplemented, 1); } TEST_F(ExecutionEngineTest, ActFailsWhenAddTabFails) { @@ -402,11 +406,11 @@ OnActorTaskAsyncChange(VariantWith<AddTab>(_), _)) .WillOnce(UiEventDispatcherCallback< ui::UiEventDispatcher::ActorTaskAsyncChange>( - base::BindRepeating(MakeErrorResult))); + base::BindRepeating(MakeNotImplementedResult))); EXPECT_FALSE( Act(GURL("http://localhost/"), MakeClickCallback(kFakeContentNodeId))); histograms_.ExpectUniqueSample(kActionResultHistogram, - mojom::ActionResultCode::kError, 1); + mojom::ActionResultCode::kNotImplemented, 1); } TEST_F(ExecutionEngineTest, ActFailsWhenTabDestroyed) {
diff --git a/chrome/browser/actor/tools/attempt_form_filling_tool.cc b/chrome/browser/actor/tools/attempt_form_filling_tool.cc index 130ab8bc..5b17595 100644 --- a/chrome/browser/actor/tools/attempt_form_filling_tool.cc +++ b/chrome/browser/actor/tools/attempt_form_filling_tool.cc
@@ -167,9 +167,9 @@ CHECK(service_fill_requests_.empty()); if (!last_observation) { - ACTOR_LOG() << "APC was null during TimeOfUseValidation."; - // Return a generic error for the unexpected state. - return MakeErrorResult(); + return MakeResult(mojom::ActionResultCode::kFormFillingNoLastTabObservation, + /*requires_page_stabilization=*/false, + "AttemptFormFillingTool: last tab observation is null."); } for (const auto& request : tool_fill_requests_) { @@ -305,9 +305,10 @@ uint32_t id = 0; if (!base::StringToUint(response->selected_suggestion_id, &id)) { std::move(invoke_callback) - .Run(MakeResult(mojom::ActionResultCode::kError, - /*requires_page_stabilization=*/false, - "Invalid suggestion ID received.")); + .Run(MakeResult( + mojom::ActionResultCode::kFormFillingInvalidSuggestionId, + /*requires_page_stabilization=*/false, + "Invalid suggestion ID received.")); return; } autofill::ActorFormFillingSelection selection;
diff --git a/chrome/browser/actor/tools/attempt_login_tool.cc b/chrome/browser/actor/tools/attempt_login_tool.cc index 04959a9c..93936ec 100644 --- a/chrome/browser/actor/tools/attempt_login_tool.cc +++ b/chrome/browser/actor/tools/attempt_login_tool.cc
@@ -40,14 +40,13 @@ actor_login::ActorLoginError login_error) { switch (login_error) { case actor_login::ActorLoginError::kServiceBusy: - return mojom::ActionResultCode::kError; + return mojom::ActionResultCode::kLoginTooManyRequests; case actor_login::ActorLoginError::kInvalidTabInterface: return mojom::ActionResultCode::kTabWentAway; case actor_login::ActorLoginError::kFillingNotAllowed: return mojom::ActionResultCode::kLoginFillingNotAllowed; - case actor_login::ActorLoginError::kUnknown: - default: - return mojom::ActionResultCode::kError; + case actor_login::ActorLoginError::kFeatureDisabled: + return mojom::ActionResultCode::kLoginFeatureDisabled; } }
diff --git a/chrome/browser/actor/tools/attempt_login_tool_browsertest.cc b/chrome/browser/actor/tools/attempt_login_tool_browsertest.cc index a7b9698e..6d678e6 100644 --- a/chrome/browser/actor/tools/attempt_login_tool_browsertest.cc +++ b/chrome/browser/actor/tools/attempt_login_tool_browsertest.cc
@@ -402,7 +402,7 @@ std::unique_ptr<ToolRequest> action = MakeAttemptLoginRequest(*active_tab()); ActResultFuture result; actor_task().Act(ToRequestList(action), result.GetCallback()); - ExpectErrorResult(result, mojom::ActionResultCode::kError); + ExpectErrorResult(result, mojom::ActionResultCode::kLoginTooManyRequests); } IN_PROC_BROWSER_TEST_F(ActorAttemptLoginToolTest, CredentialSaved) {
diff --git a/chrome/browser/actor/tools/navigate_tool.cc b/chrome/browser/actor/tools/navigate_tool.cc index 10464d77..5330791e 100644 --- a/chrome/browser/actor/tools/navigate_tool.cc +++ b/chrome/browser/actor/tools/navigate_tool.cc
@@ -142,7 +142,7 @@ auto result = navigation_handle->HasCommitted() && !navigation_handle->IsErrorPage() ? MakeOkResult() - : MakeErrorResult(); + : MakeResult(mojom::ActionResultCode::kNavigateCommittedErrorPage); if (invoke_callback_) { PostResponseTask(std::move(invoke_callback_), std::move(result));
diff --git a/chrome/browser/actor/tools/script_tool_browsertest.cc b/chrome/browser/actor/tools/script_tool_browsertest.cc index 1edd2dd..8d0f7c1 100644 --- a/chrome/browser/actor/tools/script_tool_browsertest.cc +++ b/chrome/browser/actor/tools/script_tool_browsertest.cc
@@ -68,7 +68,7 @@ MakeScriptToolRequest(*main_frame(), "invalid", input_arguments); ActResultFuture result; actor_task().Act(ToRequestList(action), result.GetCallback()); - ExpectErrorResult(result, mojom::ActionResultCode::kError); + ExpectErrorResult(result, mojom::ActionResultCode::kScriptToolNoResponse); } IN_PROC_BROWSER_TEST_F(ActorToolsTestScriptTool, ProvideContext) { @@ -130,7 +130,8 @@ ActResultFuture echo_result_after_clear; actor_task().Act(ToRequestList(echo_action_after_clear), echo_result_after_clear.GetCallback()); - ExpectErrorResult(echo_result_after_clear, mojom::ActionResultCode::kError); + ExpectErrorResult(echo_result_after_clear, + mojom::ActionResultCode::kScriptToolNoResponse); } } // namespace
diff --git a/chrome/browser/actor/tools/tab_management_tool.cc b/chrome/browser/actor/tools/tab_management_tool.cc index 85cba48..b45d87b2 100644 --- a/chrome/browser/actor/tools/tab_management_tool.cc +++ b/chrome/browser/actor/tools/tab_management_tool.cc
@@ -82,7 +82,7 @@ CHECK(target_tab_.has_value()); NOTIMPLEMENTED() << "ActivateTab and CloseTab not yet implemented"; PostResponseTask(std::move(callback_), - MakeResult(mojom::ActionResultCode::kError)); + MakeResult(mojom::ActionResultCode::kNotImplemented)); return; } }
diff --git a/chrome/browser/actor/tools/tab_management_tool_browsertest.cc b/chrome/browser/actor/tools/tab_management_tool_browsertest.cc index c90045f7..290a533 100644 --- a/chrome/browser/actor/tools/tab_management_tool_browsertest.cc +++ b/chrome/browser/actor/tools/tab_management_tool_browsertest.cc
@@ -43,7 +43,7 @@ embedded_test_server()->GetURL("/actor/blank.html"); ASSERT_TRUE(content::NavigateToURL(web_contents(), start_tab_url)); - const int initial_tab_count = browser()->tab_strip_model()->GetTabCount(); + const int initial_tab_count = browser()->tab_strip_model()->count(); std::unique_ptr<ToolRequest> action = MakeCreateTabRequest(browser()->session_id(), /*foreground=*/true); @@ -51,7 +51,7 @@ actor_task().Act(ToRequestList(action), result.GetCallback()); ExpectOkResult(result); - EXPECT_EQ(initial_tab_count + 1, browser()->tab_strip_model()->GetTabCount()); + EXPECT_EQ(initial_tab_count + 1, browser()->tab_strip_model()->count()); EXPECT_EQ(GURL("about:blank"), browser()->tab_strip_model()->GetActiveWebContents()->GetURL()); } @@ -63,7 +63,7 @@ embedded_test_server()->GetURL("/actor/blank.html"); ASSERT_TRUE(content::NavigateToURL(web_contents(), start_tab_url)); - const int initial_tab_count = browser()->tab_strip_model()->GetTabCount(); + const int initial_tab_count = browser()->tab_strip_model()->count(); std::unique_ptr<ToolRequest> action = MakeCreateTabRequest(browser()->session_id(), /*foreground=*/false); @@ -71,7 +71,7 @@ actor_task().Act(ToRequestList(action), result.GetCallback()); ExpectOkResult(result); - EXPECT_EQ(initial_tab_count + 1, browser()->tab_strip_model()->GetTabCount()); + EXPECT_EQ(initial_tab_count + 1, browser()->tab_strip_model()->count()); EXPECT_EQ(start_tab_url, browser()->tab_strip_model()->GetActiveWebContents()->GetURL()); }
diff --git a/chrome/browser/actor/ui/actor_ui_state_manager.cc b/chrome/browser/actor/ui/actor_ui_state_manager.cc index 7019cdc..e2e4c02 100644 --- a/chrome/browser/actor/ui/actor_ui_state_manager.cc +++ b/chrome/browser/actor/ui/actor_ui_state_manager.cc
@@ -103,7 +103,9 @@ // TODO(crbug.com/424495020): Bool may be converted to a map of ui // components:bool depending on what controller returns. void OnUiChangeComplete(UiCompleteCallback complete_callback, bool result) { - std::move(complete_callback).Run(result ? MakeOkResult() : MakeErrorResult()); + std::move(complete_callback) + .Run(result ? MakeOkResult() + : MakeResult(mojom::ActionResultCode::kActorUiError)); } void LogUiChangeError(bool result) {
diff --git a/chrome/browser/actor/ui/event_dispatcher_unittest.cc b/chrome/browser/actor/ui/event_dispatcher_unittest.cc index 8e33d1a..8b7cda7 100644 --- a/chrome/browser/actor/ui/event_dispatcher_unittest.cc +++ b/chrome/browser/actor/ui/event_dispatcher_unittest.cc
@@ -167,7 +167,8 @@ EXPECT_CALL(*mock_state_manager_, OnUiEvent(VariantWith<MouseMove>(_), _)) .WillOnce(WithArgs<1>([&](UiCompleteCallback callback) { task_environment_.FastForwardBy(base::Microseconds(50)); - std::move(callback).Run(MakeErrorResult()); + std::move(callback).Run( + MakeResult(actor::mojom::ActionResultCode::kActorUiError)); })); EXPECT_CALL(*mock_state_manager_, OnUiEvent(VariantWith<MouseClick>(_), _)) .Times(0); @@ -175,7 +176,8 @@ MouseClickType::kLeft, MouseClickCount::kSingle); TestFuture<ActionResultPtr> result; dispatcher_->OnPreTool(tr, result.GetCallback()); - EXPECT_EQ(result.Get()->code, ::actor::mojom::ActionResultCode::kError); + EXPECT_EQ(result.Get()->code, + ::actor::mojom::ActionResultCode::kActorUiError); // MouseMove duration shouldn't be recorded as it failed. histograms_.ExpectTotalCount(kMouseMoveDurationHistogram, 0); @@ -194,13 +196,15 @@ EXPECT_CALL(*mock_state_manager_, OnUiEvent(VariantWith<MouseClick>(_), _)) .WillOnce(WithArgs<1>([&](UiCompleteCallback callback) { task_environment_.FastForwardBy(base::Microseconds(50)); - std::move(callback).Run(MakeErrorResult()); + std::move(callback).Run( + MakeResult(actor::mojom::ActionResultCode::kActorUiError)); })); ClickToolRequest tr(tabs::TabHandle(123), PageTarget(gfx::Point(10, 50)), MouseClickType::kLeft, MouseClickCount::kSingle); TestFuture<ActionResultPtr> result; dispatcher_->OnPreTool(tr, result.GetCallback()); - EXPECT_EQ(result.Get()->code, ::actor::mojom::ActionResultCode::kError); + EXPECT_EQ(result.Get()->code, + ::actor::mojom::ActionResultCode::kActorUiError); // MouseMove duration should be recorded as it was completed. histograms_.ExpectBucketCount(kMouseMoveDurationHistogram,
diff --git a/chrome/browser/android/compositor/layer/toolbar_layer.cc b/chrome/browser/android/compositor/layer/toolbar_layer.cc index f2c7fdb7..6ef5154 100644 --- a/chrome/browser/android/compositor/layer/toolbar_layer.cc +++ b/chrome/browser/android/compositor/layer/toolbar_layer.cc
@@ -77,9 +77,24 @@ url_bar_background_layer_->SetHideLayerAndSubtree(!url_bar_visible); if (url_bar_visible) { ui::NinePatchResource* url_bar_background_resource; - url_bar_background_resource = ui::NinePatchResource::From( - resource_manager_->GetStaticResourceWithTint( - url_bar_background_resource_id, toolbar_textbox_background_color)); + if (base::FeatureList::IsEnabled( + chrome::android::kMvcUpdateViewWhenModelChanged)) { + // Because the ToolbarLayer is not updated every frame, even if visible, + // we need keep the tint in the cache until the layer is destroyed. + url_bar_background_resource = ui::NinePatchResource::From( + resource_manager_->GetAndRetainStaticResourceWithTint( + url_bar_background_resource_id, + toolbar_textbox_background_color)); + DCHECK(last_url_bar_background_resource_id_ == kInvalidResourceId || + last_url_bar_background_resource_id_ == + url_bar_background_resource_id); + last_url_bar_background_resource_id_ = url_bar_background_resource_id; + } else { + url_bar_background_resource = ui::NinePatchResource::From( + resource_manager_->GetStaticResourceWithTint( + url_bar_background_resource_id, + toolbar_textbox_background_color)); + } gfx::Size draw_size(url_bar_background_resource->DrawSize( resource->location_bar_content_rect().size())); @@ -249,7 +264,7 @@ } ToolbarLayer::ToolbarLayer(ui::ResourceManager* resource_manager) - : resource_manager_(resource_manager), + : resource_manager_(resource_manager->GetWeakPtr()), layer_(cc::slim::Layer::Create()), toolbar_layers_(cc::slim::Layer::Create()), progress_bar_layers_(cc::slim::Layer::Create()), @@ -318,6 +333,12 @@ debug_layer_->SetOpacity(0.5f); } -ToolbarLayer::~ToolbarLayer() = default; +ToolbarLayer::~ToolbarLayer() { + if (resource_manager_ && + last_url_bar_background_resource_id_ != kInvalidResourceId) { + resource_manager_->ReleaseStaticResource( + last_url_bar_background_resource_id_); + } +} } // namespace android
diff --git a/chrome/browser/android/compositor/layer/toolbar_layer.h b/chrome/browser/android/compositor/layer/toolbar_layer.h index 6ac8c75..13f62a01 100644 --- a/chrome/browser/android/compositor/layer/toolbar_layer.h +++ b/chrome/browser/android/compositor/layer/toolbar_layer.h
@@ -5,8 +5,8 @@ #ifndef CHROME_BROWSER_ANDROID_COMPOSITOR_LAYER_TOOLBAR_LAYER_H_ #define CHROME_BROWSER_ANDROID_COMPOSITOR_LAYER_TOOLBAR_LAYER_H_ -#include "base/memory/raw_ptr.h" #include "base/memory/scoped_refptr.h" +#include "base/memory/weak_ptr.h" #include "chrome/browser/android/compositor/layer/layer.h" #include "components/viz/common/quads/offset_tag.h" #include "ui/android/resources/resource_manager.h" @@ -68,11 +68,13 @@ ~ToolbarLayer() override; private: + static constexpr int kInvalidResourceId = -1; + int GetIndexOfLayer(scoped_refptr<cc::slim::Layer> layer); scoped_refptr<cc::slim::Layer> ToolbarParentLayer(); - raw_ptr<ui::ResourceManager, DanglingUntriaged> resource_manager_; + base::WeakPtr<ui::ResourceManager> resource_manager_; // Root layer scoped_refptr<cc::slim::Layer> layer_; @@ -81,7 +83,7 @@ // move vertically. scoped_refptr<cc::slim::Layer> toolbar_layers_; - // Layer which are tagged ewith the progress bar's OffsetTag. These layers + // Layers which are tagged with the progress bar's OffsetTag. These layers // move with the same vertical movement as the toolbar_layers, but also move // horizontally from load progress updates. scoped_refptr<cc::slim::Layer> progress_bar_layers_; @@ -93,6 +95,8 @@ scoped_refptr<cc::slim::SolidColorLayer> progress_bar_background_layer_; scoped_refptr<cc::slim::SolidColorLayer> progress_bar_static_background_layer_; scoped_refptr<cc::slim::SolidColorLayer> debug_layer_; + + int last_url_bar_background_resource_id_ = kInvalidResourceId; }; } // namespace android
diff --git a/chrome/browser/ash/android_sms/android_sms_app_manager_impl.cc b/chrome/browser/ash/android_sms/android_sms_app_manager_impl.cc index d461385..b76415d 100644 --- a/chrome/browser/ash/android_sms/android_sms_app_manager_impl.cc +++ b/chrome/browser/ash/android_sms/android_sms_app_manager_impl.cc
@@ -2,15 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "chrome/browser/ash/android_sms/android_sms_app_manager_impl.h" #include <utility> +#include "base/compiler_specific.h" #include "base/functional/bind.h" #include "base/functional/callback.h" #include "base/functional/callback_helpers.h" @@ -172,7 +168,8 @@ std::optional<PwaDomain> AndroidSmsAppManagerImpl::GetInstalledPwaDomainForMigration() { - for (auto* it = std::begin(kDomains); it != std::end(kDomains); ++it) { + for (auto* it = std::begin(kDomains); it != std::end(kDomains); + UNSAFE_TODO(++it)) { if (setup_controller_->GetPwa( GetAndroidMessagesURL(true /* use_install_url */, *it))) { return *it;
diff --git a/chrome/browser/ash/app_list/app_list_sort_browsertest.cc b/chrome/browser/ash/app_list/app_list_sort_browsertest.cc index 073af9c..7d651be 100644 --- a/chrome/browser/ash/app_list/app_list_sort_browsertest.cc +++ b/chrome/browser/ash/app_list/app_list_sort_browsertest.cc
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "ash/app_list/app_list_controller_impl.h" #include "ash/app_list/app_list_model_provider.h" #include "ash/app_list/views/app_list_item_view.h" @@ -20,6 +15,7 @@ #include "ash/public/cpp/test/shell_test_api.h" #include "ash/shell.h" #include "ash/wm/tablet_mode/tablet_mode_controller_test_api.h" +#include "base/compiler_specific.h" #include "base/feature_list.h" #include "base/files/file_util.h" #include "base/functional/callback.h" @@ -1467,7 +1463,8 @@ const sk_sp<SkImage> image = SkImages::RasterFromBitmap(*icon.bitmap()); const sk_sp<SkData> png_data = skia::EncodePngAsSkData(nullptr, image.get()); - icon_file.Write(0, (const char*)png_data->data(), png_data->size()); + UNSAFE_TODO( + icon_file.Write(0, (const char*)png_data->data(), png_data->size())); icon_file.Close(); // Prepare the app manifest file. @@ -1484,7 +1481,8 @@ char manifest_buffer[300]; int count = base::strings::SafeSPrintf(manifest_buffer, kManifestData, app_name.c_str(), json_buffer); - EXPECT_EQ(count, manifest_file.Write(0, manifest_buffer, count)); + UNSAFE_TODO( + EXPECT_EQ(count, manifest_file.Write(0, manifest_buffer, count))); manifest_file.Close(); return extension_path;
diff --git a/chrome/browser/ash/app_list/arc/intent.cc b/chrome/browser/ash/app_list/arc/intent.cc index 46850c9..ae0613b 100644 --- a/chrome/browser/ash/app_list/arc/intent.cc +++ b/chrome/browser/ash/app_list/arc/intent.cc
@@ -2,16 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "chrome/browser/ash/app_list/arc/intent.h" #include <cinttypes> #include <string_view> +#include "base/compiler_specific.h" #include "base/containers/contains.h" #include "base/logging.h" #include "base/memory/ptr_util.h" @@ -135,7 +131,7 @@ // Remove the |package_name| prefix, if activity starts with it. const char* activity_compact_name = activity.find(package_name.c_str()) == 0 - ? activity.c_str() + package_name.length() + ? UNSAFE_TODO(activity.c_str() + package_name.length()) : activity.c_str(); // Construct a string in format:
diff --git a/chrome/browser/ash/app_list/md_icon_normalizer.cc b/chrome/browser/ash/app_list/md_icon_normalizer.cc index 2b194db3..f391d33 100644 --- a/chrome/browser/ash/app_list/md_icon_normalizer.cc +++ b/chrome/browser/ash/app_list/md_icon_normalizer.cc
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "chrome/browser/ash/app_list/md_icon_normalizer.h" #include <algorithm> @@ -15,6 +10,7 @@ #include <utility> #include <vector> +#include "base/compiler_specific.h" #include "base/trace_event/trace_event.h" #include "skia/ext/image_operations.h" #include "third_party/skia/include/core/SkBitmap.h" @@ -134,7 +130,8 @@ : nullptr; for (int x = 0; x < width; x++) { - if (SkColorGetA(nativeRow ? nativeRow[x] : pixmap.getColor(x, y)) > + if (UNSAFE_TODO( + SkColorGetA(nativeRow ? nativeRow[x] : pixmap.getColor(x, y))) > kMaxShadowAlpha) { border_left[y] = x; x_left = std::min(x_left, x); @@ -147,7 +144,8 @@ continue; for (int x = width - 1; x > 0; x--) { - if (SkColorGetA(nativeRow ? nativeRow[x] : pixmap.getColor(x, y)) > + if (UNSAFE_TODO( + SkColorGetA(nativeRow ? nativeRow[x] : pixmap.getColor(x, y))) > kMaxShadowAlpha) { border_right[y] = x; x_right = std::max(x_right, x);
diff --git a/chrome/browser/ash/app_list/search/app_search_data_source.cc b/chrome/browser/ash/app_list/search/app_search_data_source.cc index b3ff4d6d..16d19ee53 100644 --- a/chrome/browser/ash/app_list/search/app_search_data_source.cc +++ b/chrome/browser/ash/app_list/search/app_search_data_source.cc
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "chrome/browser/ash/app_list/search/app_search_data_source.h" #include <algorithm> @@ -15,6 +10,7 @@ #include "ash/constants/web_app_id_constants.h" #include "ash/public/cpp/app_list/internal_app_id_constants.h" +#include "base/compiler_specific.h" #include "base/strings/utf_string_conversions.h" #include "base/task/single_thread_task_runner.h" #include "base/time/clock.h" @@ -69,7 +65,7 @@ // -1 if the app is not a default app. int GetDefaultAppRank(const std::string& app_id) { for (size_t i = 0; i < std::size(ranked_default_app_ids); ++i) { - if (app_id == ranked_default_app_ids[i]) { + if (app_id == UNSAFE_TODO(ranked_default_app_ids[i])) { return i; } }
diff --git a/chrome/browser/ash/app_list/search/files/file_result_unittest.cc b/chrome/browser/ash/app_list/search/files/file_result_unittest.cc index 914c7ce4..675f30d 100644 --- a/chrome/browser/ash/app_list/search/files/file_result_unittest.cc +++ b/chrome/browser/ash/app_list/search/files/file_result_unittest.cc
@@ -2,17 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "chrome/browser/ash/app_list/search/files/file_result.h" #include <optional> #include "ash/public/cpp/app_list/app_list_types.h" #include "ash/public/cpp/image_util.h" +#include "base/compiler_specific.h" #include "base/files/file.h" #include "base/files/file_path.h" #include "base/files/file_util.h" @@ -167,10 +163,11 @@ int access_days_ago[] = {0, 10, 30}; for (int i = 0; i < 3; ++i) { - base::Time last_accessed = now - base::Days(access_days_ago[i]); + base::Time last_accessed = + now - base::Days(UNSAFE_TODO(access_days_ago[i])); double relevance = FileResult::CalculateRelevance(query, path, last_accessed); - EXPECT_THAT(relevance, DoubleNear(expected_scores[i], 0.01)); + UNSAFE_TODO(EXPECT_THAT(relevance, DoubleNear(expected_scores[i], 0.01))); } }
diff --git a/chrome/browser/ash/app_list/search/local_image_search/image_annotation_worker.cc b/chrome/browser/ash/app_list/search/local_image_search/image_annotation_worker.cc index 65da4bb6..e59b112 100644 --- a/chrome/browser/ash/app_list/search/local_image_search/image_annotation_worker.cc +++ b/chrome/browser/ash/app_list/search/local_image_search/image_annotation_worker.cc
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "chrome/browser/ash/app_list/search/local_image_search/image_annotation_worker.h" #include <algorithm> @@ -18,6 +13,7 @@ #include <vector> #include "ash/public/cpp/image_util.h" +#include "base/compiler_specific.h" #include "base/files/file_enumerator.h" #include "base/files/file_path.h" #include "base/files/file_path_watcher.h" @@ -118,9 +114,9 @@ // Checking for RIFF header and WebP identifier as in the // https://developers.google.com/speed/webp/docs/riff_container if (std::string(buffer, 4) == "RIFF" && - std::string(buffer + 8, 4) == "WEBP") { + std::string(UNSAFE_TODO(buffer + 8), 4) == "WEBP") { // Checking the VP8X chunk for animation - if (std::string(buffer + 12, 4) == "VP8X") { + if (std::string(UNSAFE_TODO(buffer + 12), 4) == "VP8X") { // VP8X header is 8 bytes then the flags byte. const char flags = buffer[20]; // The second bit indicates if it's animated. @@ -164,7 +160,7 @@ const uint8_t pngSignature[8] = {0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A}; for (int i = 0; i < 8; ++i) { - if (buffer[i] != pngSignature[i]) { + if (UNSAFE_TODO(buffer[i]) != UNSAFE_TODO(pngSignature[i])) { return false; } }
diff --git a/chrome/browser/ash/app_list/search/omnibox/omnibox_result_unittest.cc b/chrome/browser/ash/app_list/search/omnibox/omnibox_result_unittest.cc index 8039a84..efff493 100644 --- a/chrome/browser/ash/app_list/search/omnibox/omnibox_result_unittest.cc +++ b/chrome/browser/ash/app_list/search/omnibox/omnibox_result_unittest.cc
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "chrome/browser/ash/app_list/search/omnibox/omnibox_result.h" #include <memory> @@ -18,6 +13,7 @@ #include "ash/public/cpp/app_list/app_list_types.h" #include "ash/public/cpp/app_list/vector_icons/vector_icons.h" #include "base/base64.h" +#include "base/compiler_specific.h" #include "base/memory/raw_ptr.h" #include "base/memory/scoped_refptr.h" #include "base/run_loop.h" @@ -134,8 +130,8 @@ return false; for (int i = 0; i < ArraySize; ++i) { - if (result_tags[i].styles != tags[i].styles || - result_tags[i].range != tags[i].range) { + if (result_tags[i].styles != UNSAFE_TODO(tags[i]).styles || + result_tags[i].range != UNSAFE_TODO(tags[i]).range) { return false; } }
diff --git a/chrome/browser/ash/app_list/search/search_controller_unittest.cc b/chrome/browser/ash/app_list/search/search_controller_unittest.cc index f06e670..3f7f88f 100644 --- a/chrome/browser/ash/app_list/search/search_controller_unittest.cc +++ b/chrome/browser/ash/app_list/search/search_controller_unittest.cc
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "chrome/browser/ash/app_list/search/search_controller.h" #include <algorithm> @@ -17,6 +12,7 @@ #include "ash/constants/ash_features.h" #include "ash/constants/ash_pref_names.h" #include "ash/public/cpp/app_list/app_list_types.h" +#include "base/compiler_specific.h" #include "base/containers/to_vector.h" #include "base/memory/raw_ptr.h" #include "base/strings/stringprintf.h" @@ -895,7 +891,8 @@ for (int i = 0; i < 9; ++i) { // The result type needs to be unique. auto provider = std::make_unique<TestSearchProvider>( - result_categories[i], base::Milliseconds(20), search_categories[i]); + UNSAFE_TODO(result_categories[i]), base::Milliseconds(20), + UNSAFE_TODO(search_categories[i])); provider_ptrs.push_back(provider.get()); search_controller_->AddProvider(std::move(provider)); }
diff --git a/chrome/browser/ash/app_list/search/system_info/system_info_card_provider.cc b/chrome/browser/ash/app_list/search/system_info/system_info_card_provider.cc index fd6d740b..c4a21ec 100644 --- a/chrome/browser/ash/app_list/search/system_info/system_info_card_provider.cc +++ b/chrome/browser/ash/app_list/search/system_info/system_info_card_provider.cc
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "chrome/browser/ash/app_list/search/system_info/system_info_card_provider.h" #include <iomanip> @@ -18,6 +13,7 @@ #include "ash/strings/grit/ash_strings.h" #include "ash/webui/settings/public/constants/routes.mojom-forward.h" #include "base/byte_count.h" +#include "base/compiler_specific.h" #include "base/functional/bind.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" @@ -502,7 +498,7 @@ // Store calculated item's size. const int item_index = static_cast<int>(calculation_type); - storage_items_total_bytes_[item_index] = total_bytes; + UNSAFE_TODO(storage_items_total_bytes_[item_index]) = total_bytes; // Mark item as calculated. calculation_state_.set(item_index);
diff --git a/chrome/browser/ash/app_mode/app_launch_utils.cc b/chrome/browser/ash/app_mode/app_launch_utils.cc index 0fb6d20..ead3ab27 100644 --- a/chrome/browser/ash/app_mode/app_launch_utils.cc +++ b/chrome/browser/ash/app_mode/app_launch_utils.cc
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "chrome/browser/ash/app_mode/app_launch_utils.h" #include <cstddef> @@ -18,6 +13,7 @@ #include "ash/constants/ash_switches.h" #include "base/check.h" #include "base/command_line.h" +#include "base/compiler_specific.h" #include "base/notimplemented.h" #include "base/notreached.h" #include "base/values.h" @@ -64,7 +60,7 @@ pref_id++) { const std::string branch_path = test_prefs_to_reset ? (*test_prefs_to_reset)[pref_id] - : kPrefsToReset[pref_id]; + : UNSAFE_TODO(kPrefsToReset[pref_id]); prefs->ClearPrefsWithPrefixSilently(branch_path); } }
diff --git a/chrome/browser/ash/app_mode/kiosk_chrome_app_manager_browsertest.cc b/chrome/browser/ash/app_mode/kiosk_chrome_app_manager_browsertest.cc index 8eaae55..9f5d08f 100644 --- a/chrome/browser/ash/app_mode/kiosk_chrome_app_manager_browsertest.cc +++ b/chrome/browser/ash/app_mode/kiosk_chrome_app_manager_browsertest.cc
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "chrome/browser/ash/app_mode/kiosk_chrome_app_manager.h" #include <stddef.h> @@ -20,6 +15,7 @@ #include "base/check.h" #include "base/check_deref.h" #include "base/command_line.h" +#include "base/compiler_specific.h" #include "base/files/file_path.h" #include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h" @@ -901,12 +897,13 @@ }; for (size_t i = 0; i < std::size(kTestCases); ++i) { - scoped_refptr<extensions::Extension> app = MakeKioskApp( - "App Name", "1.0", kAppId, kTestCases[i].required_platform_version); - EXPECT_EQ(kTestCases[i].expected_compliant, - manager()->IsPlatformCompliantWithApp(app.get())) + scoped_refptr<extensions::Extension> app = + MakeKioskApp("App Name", "1.0", kAppId, + UNSAFE_TODO(kTestCases[i]).required_platform_version); + UNSAFE_TODO(EXPECT_EQ(kTestCases[i].expected_compliant, + manager()->IsPlatformCompliantWithApp(app.get()))) << "Test case: " << i << ", required_platform_version=" - << kTestCases[i].required_platform_version; + << UNSAFE_TODO(kTestCases[i]).required_platform_version; } // If an app is not auto launched with zero delay, it is always compliant. @@ -914,11 +911,11 @@ for (size_t i = 0; i < std::size(kTestCases); ++i) { scoped_refptr<extensions::Extension> app = MakeKioskApp("App Name", "1.0", kNoneAutoLaucnhedAppId, - kTestCases[i].required_platform_version); + UNSAFE_TODO(kTestCases[i]).required_platform_version); EXPECT_TRUE(manager()->IsPlatformCompliantWithApp(app.get())) << "Test case for non auto launch app: " << i << ", required_platform_version=" - << kTestCases[i].required_platform_version; + << UNSAFE_TODO(kTestCases[i]).required_platform_version; } }
diff --git a/chrome/browser/ash/arc/enterprise/cert_store/cert_store_service.cc b/chrome/browser/ash/arc/enterprise/cert_store/cert_store_service.cc index cc6d429..2a4205f 100644 --- a/chrome/browser/ash/arc/enterprise/cert_store/cert_store_service.cc +++ b/chrome/browser/ash/arc/enterprise/cert_store/cert_store_service.cc
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "chrome/browser/ash/arc/enterprise/cert_store/cert_store_service.h" #include <algorithm> @@ -17,6 +12,7 @@ #include <vector> #include "base/base64.h" +#include "base/compiler_specific.h" #include "base/functional/bind.h" #include "base/functional/callback.h" #include "base/functional/callback_helpers.h" @@ -247,8 +243,8 @@ if (!nss_cert) return std::nullopt; - // Passing a nullptr for wincx is a hack but not worth fixing now, see b/193771095 - // Must have a private key in order to access label and ID. + // Passing a nullptr for wincx is a hack but not worth fixing now, see + // b/193771095 Must have a private key in order to access label and ID. SECKEYPrivateKey* private_key = PK11_FindKeyByAnyCert(nss_cert.get(), nullptr /* wincx */); // Potential race condition with null private keys (see b/193771180) @@ -268,7 +264,8 @@ if (!id_item) return std::nullopt; crypto::ScopedSECItem sec_item_destroyer(id_item); - std::string pkcs11_id(id_item->data, id_item->data + id_item->len); + std::string pkcs11_id(id_item->data, + UNSAFE_TODO(id_item->data + id_item->len)); // Generate the placeholder RSA key that will be installed in ARC. auto placeholder_key = crypto::keypair::PrivateKey::GenerateRsa2048();
diff --git a/chrome/browser/ash/arc/enterprise/cert_store/cert_store_service_browsertest.cc b/chrome/browser/ash/arc/enterprise/cert_store/cert_store_service_browsertest.cc index c7f56fc..cddb6ef 100644 --- a/chrome/browser/ash/arc/enterprise/cert_store/cert_store_service_browsertest.cc +++ b/chrome/browser/ash/arc/enterprise/cert_store/cert_store_service_browsertest.cc
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "chrome/browser/ash/arc/enterprise/cert_store/cert_store_service.h" #include <stdint.h> @@ -20,6 +15,7 @@ #include "ash/constants/ash_switches.h" #include "base/base64.h" #include "base/command_line.h" +#include "base/compiler_specific.h" #include "base/functional/bind.h" #include "base/functional/callback_helpers.h" #include "base/memory/raw_ptr.h" @@ -327,7 +323,7 @@ service) { std::vector<uint8_t> client_cert_spki( cert->derPublicKey.data, - cert->derPublicKey.data + cert->derPublicKey.len); + UNSAFE_TODO(cert->derPublicKey.data + cert->derPublicKey.len)); // Mimics the behaviour of the ExtensionPlatformKeysService, which sets the // one-time signing permission when the key is registered for corporate usage.
diff --git a/chrome/browser/ash/arc/fileapi/arc_content_file_system_file_stream_reader_unittest.cc b/chrome/browser/ash/arc/fileapi/arc_content_file_system_file_stream_reader_unittest.cc index aae7311e..59207dd8 100644 --- a/chrome/browser/ash/arc/fileapi/arc_content_file_system_file_stream_reader_unittest.cc +++ b/chrome/browser/ash/arc/fileapi/arc_content_file_system_file_stream_reader_unittest.cc
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "chrome/browser/ash/arc/fileapi/arc_content_file_system_file_stream_reader.h" #include <string.h> @@ -16,6 +11,7 @@ #include <string_view> #include <utility> +#include "base/compiler_specific.h" #include "base/functional/bind.h" #include "base/location.h" #include "chrome/browser/ash/arc/fileapi/arc_file_system_operation_runner.h" @@ -144,8 +140,9 @@ EXPECT_TRUE(ReadData(&reader, buffer.get())); } base::RunLoop().RunUntilIdle(); - EXPECT_EQ(std::string_view(kData + kOffset10, strlen(kData) - kOffset10), - std::string_view(buffer->data(), buffer->size())); + UNSAFE_TODO( + EXPECT_EQ(std::string_view(kData + kOffset10, strlen(kData) - kOffset10), + std::string_view(buffer->data(), buffer->size()))); } TEST_F(ArcContentFileSystemFileStreamReaderTest, ReadRegularFileWithOffsets) { @@ -160,11 +157,12 @@ EXPECT_TRUE(ReadData(&reader2, buffer2.get())); } base::RunLoop().RunUntilIdle(); - EXPECT_EQ(std::string_view(kData + kOffset5, kOffset15 - kOffset5), - std::string_view(buffer1->data(), buffer1->size())); - EXPECT_EQ( + UNSAFE_TODO( + EXPECT_EQ(std::string_view(kData + kOffset5, kOffset15 - kOffset5), + std::string_view(buffer1->data(), buffer1->size()))); + UNSAFE_TODO(EXPECT_EQ( std::string_view(kData + kOffset15, strlen(kData) - kOffset5 - kOffset15), - std::string_view(buffer2->data(), buffer2->size())); + std::string_view(buffer2->data(), buffer2->size()))); } TEST_F(ArcContentFileSystemFileStreamReaderTest, @@ -183,11 +181,12 @@ EXPECT_TRUE(ReadData(&reader2, buffer2.get())); } base::RunLoop().RunUntilIdle(); - EXPECT_EQ(std::string_view(kData + kOffset5, kOffset15 - kOffset5), - std::string_view(buffer1->data(), buffer1->size())); - EXPECT_EQ( + UNSAFE_TODO( + EXPECT_EQ(std::string_view(kData + kOffset5, kOffset15 - kOffset5), + std::string_view(buffer1->data(), buffer1->size()))); + UNSAFE_TODO(EXPECT_EQ( std::string_view(kData + kOffset15, strlen(kData) - kOffset5 - kOffset15), - std::string_view(buffer2->data(), buffer2->size())); + std::string_view(buffer2->data(), buffer2->size()))); } TEST_F(ArcContentFileSystemFileStreamReaderTest, ReadPipe) { @@ -210,8 +209,9 @@ EXPECT_TRUE(ReadData(&reader, buffer.get())); } base::RunLoop().RunUntilIdle(); - EXPECT_EQ(std::string_view(kData + kOffset10, strlen(kData) - kOffset10), - std::string_view(buffer->data(), buffer->size())); + UNSAFE_TODO( + EXPECT_EQ(std::string_view(kData + kOffset10, strlen(kData) - kOffset10), + std::string_view(buffer->data(), buffer->size()))); } TEST_F(ArcContentFileSystemFileStreamReaderTest, ReadPipeWithOffsets) { @@ -226,11 +226,12 @@ EXPECT_TRUE(ReadData(&reader2, buffer2.get())); } base::RunLoop().RunUntilIdle(); - EXPECT_EQ(std::string_view(kData + kOffset5, kOffset15 - kOffset5), - std::string_view(buffer1->data(), buffer1->size())); - EXPECT_EQ( + UNSAFE_TODO( + EXPECT_EQ(std::string_view(kData + kOffset5, kOffset15 - kOffset5), + std::string_view(buffer1->data(), buffer1->size()))); + UNSAFE_TODO(EXPECT_EQ( std::string_view(kData + kOffset15, strlen(kData) - kOffset5 - kOffset15), - std::string_view(buffer2->data(), buffer2->size())); + std::string_view(buffer2->data(), buffer2->size()))); } TEST_F(ArcContentFileSystemFileStreamReaderTest, @@ -248,11 +249,12 @@ EXPECT_TRUE(ReadData(&reader2, buffer2.get())); } base::RunLoop().RunUntilIdle(); - EXPECT_EQ(std::string_view(kData + kOffset5, kOffset15 - kOffset5), - std::string_view(buffer1->data(), buffer1->size())); - EXPECT_EQ( + UNSAFE_TODO( + EXPECT_EQ(std::string_view(kData + kOffset5, kOffset15 - kOffset5), + std::string_view(buffer1->data(), buffer1->size()))); + UNSAFE_TODO(EXPECT_EQ( std::string_view(kData + kOffset15, strlen(kData) - kOffset5 - kOffset15), - std::string_view(buffer2->data(), buffer2->size())); + std::string_view(buffer2->data(), buffer2->size()))); } TEST_F(ArcContentFileSystemFileStreamReaderTest, GetLength) {
diff --git a/chrome/browser/ash/arc/input_overlay/actions/action_move.cc b/chrome/browser/ash/arc/input_overlay/actions/action_move.cc index 48e501d0..5d89646 100644 --- a/chrome/browser/ash/arc/input_overlay/actions/action_move.cc +++ b/chrome/browser/ash/arc/input_overlay/actions/action_move.cc
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "chrome/browser/ash/arc/input_overlay/actions/action_move.h" #include <algorithm> @@ -14,6 +9,7 @@ #include <string_view> #include "base/check_op.h" +#include "base/compiler_specific.h" #include "base/containers/contains.h" #include "base/notimplemented.h" #include "base/strings/utf_string_conversions.h" @@ -501,8 +497,8 @@ const gfx::RectF& content_bounds, const gfx::Transform* rotation_transform) { DCHECK_LT(direction_index, kActionMoveKeysSize); - auto new_move = gfx::Vector2dF(kDirection[direction_index][0], - kDirection[direction_index][1]); + auto new_move = gfx::Vector2dF(UNSAFE_TODO(kDirection[direction_index])[0], + UNSAFE_TODO(kDirection[direction_index])[1]); const float display_scale_factor = touch_injector_->window()->GetHost()->device_scale_factor(); const float scale = display_scale_factor * move_distance_;
diff --git a/chrome/browser/ash/arc/input_overlay/ui/action_label.cc b/chrome/browser/ash/arc/input_overlay/ui/action_label.cc index cc12e4ba..26998fb 100644 --- a/chrome/browser/ash/arc/input_overlay/ui/action_label.cc +++ b/chrome/browser/ash/arc/input_overlay/ui/action_label.cc
@@ -2,16 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "chrome/browser/ash/arc/input_overlay/ui/action_label.h" #include <set> #include "ash/style/style_util.h" +#include "base/compiler_specific.h" #include "base/notimplemented.h" #include "base/strings/utf_string_conversions.h" #include "chrome/app/vector_icons/vector_icons.h" @@ -208,9 +204,9 @@ auto center = touch_point_size_.width() / 2; int offset_to_center = touch_point_size_.width() / 2 - kCrossPadding - label_size.height() / 2; - int x = center + kDirection[index_][0] * offset_to_center - + int x = center + UNSAFE_TODO(kDirection[index_])[0] * offset_to_center - label_size.width() / 2; - int y = center + kDirection[index_][1] * offset_to_center - + int y = center + UNSAFE_TODO(kDirection[index_])[1] * offset_to_center - label_size.height() / 2; SetPosition(gfx::Point(x, y)); GetParent()->SetTouchPointCenter(gfx::Point(center, center));
diff --git a/chrome/browser/ash/arc/intent_helper/arc_intent_helper_mojo_ash.cc b/chrome/browser/ash/arc/intent_helper/arc_intent_helper_mojo_ash.cc index 6f36b49..a4625355 100644 --- a/chrome/browser/ash/arc/intent_helper/arc_intent_helper_mojo_ash.cc +++ b/chrome/browser/ash/arc/intent_helper/arc_intent_helper_mojo_ash.cc
@@ -2,14 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "chrome/browser/ash/arc/intent_helper/arc_intent_helper_mojo_ash.h" #include "base/barrier_closure.h" +#include "base/compiler_specific.h" #include "base/functional/callback.h" #include "chrome/browser/apps/app_service/app_icon/app_icon_factory.h" #include "chrome/browser/ash/app_list/arc/arc_app_list_prefs.h" @@ -146,7 +142,8 @@ for (size_t idx = 0; idx < actions_count; ++idx) { auto action = std::move(actions[idx]); - TextSelectionAction** converted_action = &converted_actions_ptr[idx]; + TextSelectionAction** converted_action = + UNSAFE_TODO(&converted_actions_ptr[idx]); // If action->icon doesn't meet the size condition, skip generating image. if (action->icon->width > kMaxIconSizeInPx ||
diff --git a/chrome/browser/ash/arc/policy/managed_configuration_variables.cc b/chrome/browser/ash/arc/policy/managed_configuration_variables.cc index ba9f599..0a739b88 100644 --- a/chrome/browser/ash/arc/policy/managed_configuration_variables.cc +++ b/chrome/browser/ash/arc/policy/managed_configuration_variables.cc
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "chrome/browser/ash/arc/policy/managed_configuration_variables.h" #include <string> @@ -14,6 +9,7 @@ #include <vector> #include "base/check.h" +#include "base/compiler_specific.h" #include "base/containers/flat_map.h" #include "base/functional/bind.h" #include "base/strings/string_split.h" @@ -193,8 +189,8 @@ DCHECK(search_input.length() >= prefix_size + capture.length()); size_t remaining_size = search_input.length() - (prefix_size + capture.length()); - search_input = - std::string_view(capture.data() + capture.size(), remaining_size); + search_input = std::string_view( + UNSAFE_TODO(capture.data() + capture.size()), remaining_size); } // Output the remaining |search_input|. output.emplace_back(search_input);
diff --git a/chrome/browser/ash/arc/print_spooler/arc_print_spooler_util.cc b/chrome/browser/ash/arc/print_spooler/arc_print_spooler_util.cc index 64b91e56..6129295 100644 --- a/chrome/browser/ash/arc/print_spooler/arc_print_spooler_util.cc +++ b/chrome/browser/ash/arc/print_spooler/arc_print_spooler_util.cc
@@ -2,15 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "chrome/browser/ash/arc/print_spooler/arc_print_spooler_util.h" #include <utility> +#include "base/compiler_specific.h" #include "base/files/file.h" #include "base/files/file_path.h" #include "base/files/file_util.h" @@ -49,9 +45,10 @@ base::File temp(temp_path, base::File::FLAG_OPEN | base::File::FLAG_WRITE); char buf[4096]; int bytes; - while ((bytes = src_file.ReadAtCurrentPos(buf, sizeof(buf))) > 0) { - if (!temp.WriteAtCurrentPosAndCheck( - base::as_bytes(base::span(buf, static_cast<size_t>(bytes))))) { + while ((bytes = UNSAFE_TODO(src_file.ReadAtCurrentPos(buf, sizeof(buf)))) > + 0) { + if (!temp.WriteAtCurrentPosAndCheck(base::as_bytes( + UNSAFE_TODO(base::span(buf, static_cast<size_t>(bytes)))))) { PLOG(ERROR) << "Error while saving PDF to disk."; return base::FilePath(); }
diff --git a/chrome/browser/ash/arc/tracing/arc_tracing_event_matcher.cc b/chrome/browser/ash/arc/tracing/arc_tracing_event_matcher.cc index 72be0f29..1c975e0 100644 --- a/chrome/browser/ash/arc/tracing/arc_tracing_event_matcher.cc +++ b/chrome/browser/ash/arc/tracing/arc_tracing_event_matcher.cc
@@ -2,15 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "chrome/browser/ash/arc/tracing/arc_tracing_event_matcher.h" #include "base/check.h" #include "base/check_op.h" +#include "base/compiler_specific.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_split.h" #include "chrome/browser/ash/arc/tracing/arc_tracing_event.h" @@ -98,7 +94,8 @@ } int64_t value = 0; - if (!base::StringToInt64(event.GetName().data() + name_.size(), &value)) { + if (!base::StringToInt64(UNSAFE_TODO(event.GetName().data() + name_.size()), + &value)) { return std::nullopt; }
diff --git a/chrome/browser/ash/arc/tracing/overview_tracing_handler.cc b/chrome/browser/ash/arc/tracing/overview_tracing_handler.cc index c02ec9a..6504b5f 100644 --- a/chrome/browser/ash/arc/tracing/overview_tracing_handler.cc +++ b/chrome/browser/ash/arc/tracing/overview_tracing_handler.cc
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "chrome/browser/ash/arc/tracing/overview_tracing_handler.h" #include <map> @@ -14,6 +9,7 @@ #include <string_view> #include <vector> +#include "base/compiler_specific.h" #include "base/files/file_util.h" #include "base/functional/bind.h" #include "base/i18n/time_formatting.h" @@ -235,14 +231,14 @@ } c = base::ToLowerASCII(c); if (c == ' ') { - normalized_name[index++] = '_'; + UNSAFE_TODO(normalized_name[index++]) = '_'; continue; } if ((c >= 'a' && c <= 'z') || (c >= '0' && c <= '9')) { - normalized_name[index++] = c; + UNSAFE_TODO(normalized_name[index++]) = c; } } - normalized_name[index] = 0; + UNSAFE_TODO(normalized_name[index]) = 0; const std::string time = base::UnlocalizedTimeFormatWithPattern(timestamp, "yyyy-MM-dd_HH-mm-ss");
diff --git a/chrome/browser/ash/cert_provisioning/cert_provisioning_common.cc b/chrome/browser/ash/cert_provisioning/cert_provisioning_common.cc index e419b21..dde67a65 100644 --- a/chrome/browser/ash/cert_provisioning/cert_provisioning_common.cc +++ b/chrome/browser/ash/cert_provisioning/cert_provisioning_common.cc
@@ -2,17 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "chrome/browser/ash/cert_provisioning/cert_provisioning_common.h" #include <stdint.h> #include <optional> +#include "base/compiler_specific.h" #include "base/feature_list.h" #include "base/functional/callback_helpers.h" #include "base/notreached.h" @@ -326,7 +322,7 @@ size_t length) { net::CertificateList cert_list = net::X509Certificate::CreateCertificateListFromBytes( - base::as_bytes(base::span(data, length)), + base::as_bytes(UNSAFE_TODO(base::span(data, length))), net::X509Certificate::FORMAT_AUTO); if (cert_list.size() != 1) {
diff --git a/chrome/browser/ash/cert_provisioning/cert_provisioning_metrics.cc b/chrome/browser/ash/cert_provisioning/cert_provisioning_metrics.cc index 43b4595..f939540 100644 --- a/chrome/browser/ash/cert_provisioning/cert_provisioning_metrics.cc +++ b/chrome/browser/ash/cert_provisioning/cert_provisioning_metrics.cc
@@ -2,13 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "chrome/browser/ash/cert_provisioning/cert_provisioning_metrics.h" +#include "base/compiler_specific.h" #include "base/metrics/histogram_functions.h" #include "base/notreached.h" #include "chrome/browser/ash/cert_provisioning/cert_provisioning_common.h" @@ -63,11 +59,13 @@ DCHECK(!IsFinalState(prev_state)); DCHECK(IsFinalState(final_state)); base::UmaHistogramEnumeration( - kResult[ProtocolVersionToIdx(protocol_version)][ScopeToIdx(scope)], + UNSAFE_TODO( + kResult[ProtocolVersionToIdx(protocol_version)][ScopeToIdx(scope)]), final_state); if (final_state == CertProvisioningWorkerState::kFailed) { base::UmaHistogramEnumeration( - kResult[ProtocolVersionToIdx(protocol_version)][ScopeToIdx(scope)], + UNSAFE_TODO( + kResult[ProtocolVersionToIdx(protocol_version)][ScopeToIdx(scope)]), prev_state); } } @@ -76,7 +74,9 @@ CertScope scope, CertProvisioningEvent event) { base::UmaHistogramEnumeration( - kEvent[ProtocolVersionToIdx(protocol_version)][ScopeToIdx(scope)], event); + UNSAFE_TODO( + kEvent[ProtocolVersionToIdx(protocol_version)][ScopeToIdx(scope)]), + event); } void RecordDmStatusForDynamic(policy::DeviceManagementStatus status) {
diff --git a/chrome/browser/ash/cert_provisioning/cert_provisioning_worker_dynamic_unittest.cc b/chrome/browser/ash/cert_provisioning/cert_provisioning_worker_dynamic_unittest.cc index bed2d999..ea8dfed 100644 --- a/chrome/browser/ash/cert_provisioning/cert_provisioning_worker_dynamic_unittest.cc +++ b/chrome/browser/ash/cert_provisioning/cert_provisioning_worker_dynamic_unittest.cc
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "chrome/browser/ash/cert_provisioning/cert_provisioning_worker_dynamic.h" #include <stdint.h> @@ -16,6 +11,7 @@ #include <vector> #include "base/base64.h" +#include "base/compiler_specific.h" #include "base/containers/flat_map.h" #include "base/functional/callback.h" #include "base/json/json_string_value_serializer.h" @@ -251,8 +247,8 @@ std::vector<uint8_t> GetCertProfileIdBin() { // -1 because of '\0'. - return std::vector<uint8_t>(kCertProfileId, - kCertProfileId + sizeof(kCertProfileId) - 1); + return std::vector<uint8_t>( + kCertProfileId, UNSAFE_TODO(kCertProfileId + sizeof(kCertProfileId) - 1)); } void VerifyDeleteKeyCalledOnce(CertScope cert_scope) {
diff --git a/chrome/browser/ash/cert_provisioning/cert_provisioning_worker_static_unittest.cc b/chrome/browser/ash/cert_provisioning/cert_provisioning_worker_static_unittest.cc index e799bb5e..bf8a8314 100644 --- a/chrome/browser/ash/cert_provisioning/cert_provisioning_worker_static_unittest.cc +++ b/chrome/browser/ash/cert_provisioning/cert_provisioning_worker_static_unittest.cc
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "chrome/browser/ash/cert_provisioning/cert_provisioning_worker_static.h" #include <stdint.h> @@ -16,6 +11,7 @@ #include <vector> #include "base/base64.h" +#include "base/compiler_specific.h" #include "base/functional/callback.h" #include "base/json/json_string_value_serializer.h" #include "base/json/json_writer.h" @@ -168,8 +164,8 @@ std::vector<uint8_t> GetCertProfileIdBin() { // -1 because of '\0'. - return std::vector<uint8_t>(kCertProfileId, - kCertProfileId + sizeof(kCertProfileId) - 1); + return std::vector<uint8_t>( + kCertProfileId, UNSAFE_TODO(kCertProfileId + sizeof(kCertProfileId) - 1)); } void VerifyDeleteKeyCalledOnce(CertScope cert_scope) {
diff --git a/chrome/browser/ash/child_accounts/usage_time_limit_processor.cc b/chrome/browser/ash/child_accounts/usage_time_limit_processor.cc index 00ecbb23..b1e068c 100644 --- a/chrome/browser/ash/child_accounts/usage_time_limit_processor.cc +++ b/chrome/browser/ash/child_accounts/usage_time_limit_processor.cc
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "chrome/browser/ash/child_accounts/usage_time_limit_processor.h" #include <algorithm> @@ -15,6 +10,7 @@ #include <utility> #include "base/check_deref.h" +#include "base/compiler_specific.h" #include "base/logging.h" #include "base/memory/raw_ptr.h" #include "base/memory/raw_ref.h" @@ -1080,7 +1076,7 @@ Weekday GetWeekday(std::string weekday) { std::ranges::transform(weekday, weekday.begin(), ::tolower); for (int i = 0; i < static_cast<int>(Weekday::kCount); i++) { - if (weekday == kTimeLimitWeekdays[i]) { + if (weekday == UNSAFE_TODO(kTimeLimitWeekdays[i])) { return static_cast<Weekday>(i); } }
diff --git a/chrome/browser/ash/chromebox_for_meetings/xu_camera/xu_camera_service.cc b/chrome/browser/ash/chromebox_for_meetings/xu_camera/xu_camera_service.cc index 98b974cc..1b0e00fc 100644 --- a/chrome/browser/ash/chromebox_for_meetings/xu_camera/xu_camera_service.cc +++ b/chrome/browser/ash/chromebox_for_meetings/xu_camera/xu_camera_service.cc
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "chrome/browser/ash/chromebox_for_meetings/xu_camera/xu_camera_service.h" #include <fcntl.h> @@ -20,6 +15,7 @@ #include <cstdint> #include <utility> +#include "base/compiler_specific.h" #include "base/notreached.h" #include "base/posix/eintr_wrapper.h" #include "base/strings/string_util.h" @@ -305,17 +301,18 @@ int cur = 0; kXuInterface curXuInterface; while ((cur + kSubtypeOffset) < end) { - if (static_cast<int>(data_ptr[cur + kSubtypeOffset]) == - kXUSubtype && + if (static_cast<int>(UNSAFE_TODO( + data_ptr[cur + kSubtypeOffset])) == kXUSubtype && (cur + (int)sizeof(curXuInterface)) < end) { - std::memcpy(&curXuInterface, &data_ptr[cur], - sizeof(curXuInterface)); + UNSAFE_TODO(std::memcpy(&curXuInterface, &data_ptr[cur], + sizeof(curXuInterface))); std::vector<uint8_t> curXuInterface_guid_le( - curXuInterface.kGuidLe, curXuInterface.kGuidLe + kGuidSize); + curXuInterface.kGuidLe, + UNSAFE_TODO(curXuInterface.kGuidLe + kGuidSize)); guid_unitid_map_.insert( {curXuInterface_guid_le, curXuInterface.kUnitId}); } - cur += static_cast<int>(data_ptr[cur]); + cur += static_cast<int>(UNSAFE_TODO(data_ptr[cur])); } } } @@ -763,7 +760,7 @@ uint8_t* valueAsUint8 = reinterpret_cast<uint8_t*>(value); for (size_t i = 0; i < size; ++i) { data.push_back(*valueAsUint8); - valueAsUint8++; + UNSAFE_TODO(valueAsUint8++); } }
diff --git a/chrome/browser/ash/chromebox_for_meetings/xu_camera/xu_camera_service_unittest.cc b/chrome/browser/ash/chromebox_for_meetings/xu_camera/xu_camera_service_unittest.cc index 6a1e829..d1589eb 100644 --- a/chrome/browser/ash/chromebox_for_meetings/xu_camera/xu_camera_service_unittest.cc +++ b/chrome/browser/ash/chromebox_for_meetings/xu_camera/xu_camera_service_unittest.cc
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "chrome/browser/ash/chromebox_for_meetings/xu_camera/xu_camera_service.h" #include <asm-generic/errno.h> @@ -16,6 +11,7 @@ #include <cstdint> #include <optional> +#include "base/compiler_specific.h" #include "base/functional/bind.h" #include "base/run_loop.h" #include "base/test/bind.h" @@ -60,8 +56,9 @@ } // little-endian uint16 const int32_t kValue = 123; // Fake v4l2 value const std::vector<uint8_t> kValueAsUint8() { - return std::vector<uint8_t>((std::uint8_t*)&(kValue), - (std::uint8_t*)&(kValue) + sizeof(std::int32_t)); + return std::vector<uint8_t>( + (std::uint8_t*)&(kValue), + UNSAFE_TODO((std::uint8_t*)&(kValue) + sizeof(std::int32_t))); } mojom::WebcamIdPtr kDevPath() { @@ -102,10 +99,10 @@ static_cast<uvc_xu_control_query*>(query); if (UVC_GET_LEN == control_query->query) { control_query->data[0] = kLen()[0]; - control_query->data[1] = kLen()[1]; + UNSAFE_TODO(control_query->data[1]) = kLen()[1]; } else if (UVC_GET_CUR == control_query->query) { control_query->data[0] = kData()[0]; - control_query->data[1] = kData()[1]; + UNSAFE_TODO(control_query->data[1]) = kData()[1]; } } return 0;
diff --git a/chrome/browser/ash/crosapi/keystore_service_ash.cc b/chrome/browser/ash/crosapi/keystore_service_ash.cc index 745f8307..bbc475b 100644 --- a/chrome/browser/ash/crosapi/keystore_service_ash.cc +++ b/chrome/browser/ash/crosapi/keystore_service_ash.cc
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "chrome/browser/ash/crosapi/keystore_service_ash.h" #include <stdint.h> @@ -16,6 +11,7 @@ #include <utility> #include <vector> +#include "base/compiler_specific.h" #include "base/debug/dump_without_crashing.h" #include "base/memory/scoped_refptr.h" #include "base/notreached.h" @@ -414,7 +410,7 @@ CRYPTO_BUFFER* der_buffer = cert->cert_buffer(); const uint8_t* data = CRYPTO_BUFFER_data(der_buffer); std::vector<uint8_t> der_x509_certificate( - data, data + CRYPTO_BUFFER_len(der_buffer)); + data, UNSAFE_TODO(data + CRYPTO_BUFFER_len(der_buffer))); output.push_back(std::move(der_x509_certificate)); } result_ptr = mojom::KeystoreSelectClientCertificatesResult::NewCertificates( @@ -460,7 +456,7 @@ CRYPTO_BUFFER* der_buffer = cert->cert_buffer(); const uint8_t* data = CRYPTO_BUFFER_data(der_buffer); std::vector<uint8_t> der_x509_certificate( - data, data + CRYPTO_BUFFER_len(der_buffer)); + data, UNSAFE_TODO(data + CRYPTO_BUFFER_len(der_buffer))); output.push_back(std::move(der_x509_certificate)); } result_ptr =
diff --git a/chrome/browser/ash/crosapi/keystore_service_ash_unittest.cc b/chrome/browser/ash/crosapi/keystore_service_ash_unittest.cc index 43b7d69..c9fb83f0 100644 --- a/chrome/browser/ash/crosapi/keystore_service_ash_unittest.cc +++ b/chrome/browser/ash/crosapi/keystore_service_ash_unittest.cc
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "chrome/browser/ash/crosapi/keystore_service_ash.h" #include <initializer_list> @@ -16,6 +11,7 @@ #include <vector> #include "base/base64.h" +#include "base/compiler_specific.h" #include "base/functional/bind.h" #include "base/logging.h" #include "base/no_destructor.h" @@ -129,7 +125,8 @@ const uint8_t* cert_buffer = reinterpret_cast<const uint8_t*>(CRYPTO_BUFFER_data(cert->cert_buffer())); return std::vector<uint8_t>( - cert_buffer, cert_buffer + CRYPTO_BUFFER_len(cert->cert_buffer())); + cert_buffer, + UNSAFE_TODO(cert_buffer + CRYPTO_BUFFER_len(cert->cert_buffer()))); } void AssertBlobEq(const mojom::KeystoreBinaryResultPtr& result,
diff --git a/chrome/browser/ash/customization/customization_document_browsertest.cc b/chrome/browser/ash/customization/customization_document_browsertest.cc index 01123485..ff97e896 100644 --- a/chrome/browser/ash/customization/customization_document_browsertest.cc +++ b/chrome/browser/ash/customization/customization_document_browsertest.cc
@@ -2,16 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "chrome/browser/ash/customization/customization_document.h" #include <stddef.h> #include "base/command_line.h" +#include "base/compiler_specific.h" #include "base/functional/bind.h" #include "base/strings/string_split.h" #include "base/strings/string_util.h" @@ -88,10 +84,11 @@ std::string expected = required; for (size_t i = 0; i < std::size(locale_aliases); ++i) { - if (required != locale_aliases[i].locale_alias) + if (required != UNSAFE_TODO(locale_aliases[i]).locale_alias) { continue; + } - expected = locale_aliases[i].locale_name; + expected = UNSAFE_TODO(locale_aliases[i]).locale_name; break; }
diff --git a/chrome/browser/ash/extensions/autotest_private/autotest_private_api.cc b/chrome/browser/ash/extensions/autotest_private/autotest_private_api.cc index ed61796..df48d89 100644 --- a/chrome/browser/ash/extensions/autotest_private/autotest_private_api.cc +++ b/chrome/browser/ash/extensions/autotest_private/autotest_private_api.cc
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "chrome/browser/ash/extensions/autotest_private/autotest_private_api.h" #include <algorithm> @@ -281,7 +276,7 @@ "Crostini is not available for the current user"; NOINLINE int AccessArray(const int arr[], const int* index) { - return arr[*index]; + return UNSAFE_TODO(arr[*index]); } base::Value::List GetHostPermissions(const Extension* ext, @@ -698,7 +693,7 @@ std::string GetPngDataAsString(scoped_refptr<base::RefCountedMemory> png_data) { // Base64 encode the result so we can return it as a string. std::string base64_png(png_data->front(), - png_data->front() + png_data->size()); + UNSAFE_TODO(png_data->front() + png_data->size())); return base::Base64Encode(base64_png); }
diff --git a/chrome/browser/ash/extensions/file_manager/file_manager_private_apitest.cc b/chrome/browser/ash/extensions/file_manager/file_manager_private_apitest.cc index 4bd5929..5c48eb5 100644 --- a/chrome/browser/ash/extensions/file_manager/file_manager_private_apitest.cc +++ b/chrome/browser/ash/extensions/file_manager/file_manager_private_apitest.cc
@@ -2,19 +2,16 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include <stddef.h> #include <stdint.h> +#include <array> #include <memory> #include <string_view> #include "ash/constants/ash_features.h" #include "base/base64.h" +#include "base/compiler_specific.h" #include "base/files/file_path.h" #include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h" @@ -116,66 +113,74 @@ int disk_info_index; }; -TestDiskInfo kTestDisks[] = {{"file_path1", - false, - "device_label1", - "drive_label1", - "0123", - "vendor1", - "abcd", - "product1", - "FFFF-FFFF", - "storage_device_path1", - ash::DeviceType::kUSB, - 1073741824, - false, - false, - false, - false, - false, - false, - "exfat", - ""}, - {"file_path2", - false, - "device_label2", - "drive_label2", - "4567", - "vendor2", - "cdef", - "product2", - "0FFF-FFFF", - "storage_device_path2", - ash::DeviceType::kMobile, - 47723, - true, - true, - true, - true, - false, - false, - "exfat", - ""}, - {"file_path3", - true, // write_disabled_by_policy - "device_label3", - "drive_label3", - "89ab", - "vendor3", - "ef01", - "product3", - "00FF-FFFF", - "storage_device_path3", - ash::DeviceType::kOpticalDisc, - 0, - true, - false, // is_hardware_read_only - false, - true, - false, - false, - "exfat", - ""}}; +constexpr auto kTestDisks = std::to_array<TestDiskInfo>({ + { + "file_path1", + false, + "device_label1", + "drive_label1", + "0123", + "vendor1", + "abcd", + "product1", + "FFFF-FFFF", + "storage_device_path1", + ash::DeviceType::kUSB, + 1073741824, + false, + false, + false, + false, + false, + false, + "exfat", + "", + }, + { + "file_path2", + false, + "device_label2", + "drive_label2", + "4567", + "vendor2", + "cdef", + "product2", + "0FFF-FFFF", + "storage_device_path2", + ash::DeviceType::kMobile, + 47723, + true, + true, + true, + true, + false, + false, + "exfat", + "", + }, + { + "file_path3", + true, // write_disabled_by_policy + "device_label3", + "drive_label3", + "89ab", + "vendor3", + "ef01", + "product3", + "00FF-FFFF", + "storage_device_path3", + ash::DeviceType::kOpticalDisc, + 0, + true, + false, // is_hardware_read_only + false, + true, + false, + false, + "exfat", + "", + }, +}); const char kLocalMountPointName[] = "local"; @@ -285,39 +290,37 @@ {mp.source_path, mp.mount_path, mp.mount_type, mp.mount_error}); int disk_info_index = mp.disk_info_index; if (mp.disk_info_index >= 0) { - EXPECT_GT(std::size(kTestDisks), static_cast<size_t>(disk_info_index)); - if (static_cast<size_t>(disk_info_index) >= std::size(kTestDisks)) { + EXPECT_GT(kTestDisks.size(), static_cast<size_t>(disk_info_index)); + if (static_cast<size_t>(disk_info_index) >= kTestDisks.size()) { return; } + const TestDiskInfo& disk_info = kTestDisks[disk_info_index]; + std::unique_ptr<Disk> disk = Disk::Builder() .SetDevicePath(mp.source_path) .SetMountPath(mp.mount_path) - .SetWriteDisabledByPolicy( - kTestDisks[disk_info_index].write_disabled_by_policy) - .SetFilePath(kTestDisks[disk_info_index].file_path) - .SetDeviceLabel(kTestDisks[disk_info_index].device_label) - .SetDriveLabel(kTestDisks[disk_info_index].drive_label) - .SetVendorId(kTestDisks[disk_info_index].vendor_id) - .SetVendorName(kTestDisks[disk_info_index].vendor_name) - .SetProductId(kTestDisks[disk_info_index].product_id) - .SetProductName(kTestDisks[disk_info_index].product_name) - .SetFileSystemUUID(kTestDisks[disk_info_index].fs_uuid) - .SetStorageDevicePath( - kTestDisks[disk_info_index].storage_device_path) - .SetDeviceType(kTestDisks[disk_info_index].device_type) - .SetSizeInBytes(kTestDisks[disk_info_index].size_in_bytes) - .SetIsParent(kTestDisks[disk_info_index].is_parent) - .SetIsReadOnlyHardware( - kTestDisks[disk_info_index].is_read_only_hardware) - .SetHasMedia(kTestDisks[disk_info_index].has_media) - .SetOnBootDevice(kTestDisks[disk_info_index].on_boot_device) - .SetOnRemovableDevice( - kTestDisks[disk_info_index].on_removable_device) - .SetIsHidden(kTestDisks[disk_info_index].is_hidden) - .SetFileSystemType(kTestDisks[disk_info_index].file_system_type) - .SetBaseMountPath(kTestDisks[disk_info_index].base_mount_path) + .SetWriteDisabledByPolicy(disk_info.write_disabled_by_policy) + .SetFilePath(disk_info.file_path) + .SetDeviceLabel(disk_info.device_label) + .SetDriveLabel(disk_info.drive_label) + .SetVendorId(disk_info.vendor_id) + .SetVendorName(disk_info.vendor_name) + .SetProductId(disk_info.product_id) + .SetProductName(disk_info.product_name) + .SetFileSystemUUID(disk_info.fs_uuid) + .SetStorageDevicePath(disk_info.storage_device_path) + .SetDeviceType(disk_info.device_type) + .SetSizeInBytes(disk_info.size_in_bytes) + .SetIsParent(disk_info.is_parent) + .SetIsReadOnlyHardware(disk_info.is_read_only_hardware) + .SetHasMedia(disk_info.has_media) + .SetOnBootDevice(disk_info.on_boot_device) + .SetOnRemovableDevice(disk_info.on_removable_device) + .SetIsHidden(disk_info.is_hidden) + .SetFileSystemType(disk_info.file_system_type) + .SetBaseMountPath(disk_info.base_mount_path) .Build(); volumes_.insert(std::move(disk));
diff --git a/chrome/browser/ash/file_manager/copy_or_move_io_task_policy_unittest.cc b/chrome/browser/ash/file_manager/copy_or_move_io_task_policy_unittest.cc index dbe2d16..3b67ecb3 100644 --- a/chrome/browser/ash/file_manager/copy_or_move_io_task_policy_unittest.cc +++ b/chrome/browser/ash/file_manager/copy_or_move_io_task_policy_unittest.cc
@@ -2,11 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - +#include "base/compiler_specific.h" #include "base/files/file_util.h" #include "base/functional/bind.h" #include "base/functional/callback.h" @@ -379,13 +375,13 @@ storage::FileSystemURL GetSourceFileSystemURLForDisabledVolume( const std::string& component) { return source_destination_testing_helper_->GetTestFileSystemURLForVolume( - std::data(kVolumeInfos)[1], component); + UNSAFE_TODO(std::data(kVolumeInfos)[1]), component); } storage::FileSystemURL GetDestinationFileSystemURL( const std::string& component) { return source_destination_testing_helper_->GetTestFileSystemURLForVolume( - std::data(kVolumeInfos)[2], component); + UNSAFE_TODO(std::data(kVolumeInfos)[2]), component); } // Creates one file.
diff --git a/chrome/browser/ash/file_manager/open_with_browser.cc b/chrome/browser/ash/file_manager/open_with_browser.cc index 4c94b58..e763445f6 100644 --- a/chrome/browser/ash/file_manager/open_with_browser.cc +++ b/chrome/browser/ash/file_manager/open_with_browser.cc
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "chrome/browser/ash/file_manager/open_with_browser.h" #include <stddef.h> @@ -14,6 +9,7 @@ #include "ash/constants/web_app_id_constants.h" #include "ash/public/cpp/new_window_delegate.h" #include "base/command_line.h" +#include "base/compiler_specific.h" #include "base/functional/bind.h" #include "base/logging.h" #include "base/metrics/histogram_macros.h" @@ -71,7 +67,8 @@ // Returns true if |file_path| is viewable in the browser (ex. HTML file). bool IsViewableInBrowser(const base::FilePath& file_path) { for (size_t i = 0; i < std::size(kFileExtensionsViewableInBrowser); i++) { - if (file_path.MatchesExtension(kFileExtensionsViewableInBrowser[i])) { + if (file_path.MatchesExtension( + UNSAFE_TODO(kFileExtensionsViewableInBrowser[i]))) { return true; } }
diff --git a/chrome/browser/ash/file_system_provider/content_cache/content_cache_impl_unittest.cc b/chrome/browser/ash/file_system_provider/content_cache/content_cache_impl_unittest.cc index 326ce55..65756d1 100644 --- a/chrome/browser/ash/file_system_provider/content_cache/content_cache_impl_unittest.cc +++ b/chrome/browser/ash/file_system_provider/content_cache/content_cache_impl_unittest.cc
@@ -2,15 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "chrome/browser/ash/file_system_provider/content_cache/content_cache_impl.h" #include <memory> +#include "base/compiler_specific.h" #include "base/files/file_path.h" #include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h" @@ -96,7 +92,7 @@ base::MakeRefCounted<net::IOBufferWithSize>(size); std::vector<uint8_t> rand_bytes = base::RandBytesAsVector(size); for (int i = 0; i < size; i++) { - buffer->data()[i] = rand_bytes[i]; + UNSAFE_TODO(buffer->data()[i]) = rand_bytes[i]; } return buffer; }
diff --git a/chrome/browser/ash/file_system_provider/content_cache/local_fd.cc b/chrome/browser/ash/file_system_provider/content_cache/local_fd.cc index 4848fc53..fb3909e 100644 --- a/chrome/browser/ash/file_system_provider/content_cache/local_fd.cc +++ b/chrome/browser/ash/file_system_provider/content_cache/local_fd.cc
@@ -2,13 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "chrome/browser/ash/file_system_provider/content_cache/local_fd.h" +#include "base/compiler_specific.h" #include "base/files/file_error_or.h" #include "base/logging.h" @@ -30,7 +26,7 @@ path, base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_WRITE); } - if (file->Write(offset, buffer->data(), length) != length) { + if (UNSAFE_TODO(file->Write(offset, buffer->data(), length)) != length) { PLOG(ERROR) << "Failed to write bytes to file"; return base::unexpected(base::File::FILE_ERROR_FAILED); }
diff --git a/chrome/browser/ash/file_system_provider/fake_provided_file_system.cc b/chrome/browser/ash/file_system_provider/fake_provided_file_system.cc index 155b2f8..02d9a37 100644 --- a/chrome/browser/ash/file_system_provider/fake_provided_file_system.cc +++ b/chrome/browser/ash/file_system_provider/fake_provided_file_system.cc
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "chrome/browser/ash/file_system_provider/fake_provided_file_system.h" #include <stddef.h> @@ -14,6 +9,7 @@ #include <memory> #include <utility> +#include "base/compiler_specific.h" #include "base/functional/bind.h" #include "base/functional/callback_helpers.h" #include "base/task/single_thread_task_runner.h" @@ -341,7 +337,8 @@ const FakeEntry* const entry = entry_it->second.get(); std::vector<int> task_ids; while (current_offset < *entry->metadata->size && current_length) { - buffer->data()[current_offset - offset] = entry->contents[current_offset]; + UNSAFE_TODO(buffer->data()[current_offset - offset]) = + entry->contents[current_offset]; const bool has_more = (current_offset + 1 < *entry->metadata->size) && (current_length - 1); const int task_id = tracker_.PostTask(
diff --git a/chrome/browser/ash/file_system_provider/fileapi/buffering_file_stream_reader.cc b/chrome/browser/ash/file_system_provider/fileapi/buffering_file_stream_reader.cc index b7c7802..e8ffe7b 100644 --- a/chrome/browser/ash/file_system_provider/fileapi/buffering_file_stream_reader.cc +++ b/chrome/browser/ash/file_system_provider/fileapi/buffering_file_stream_reader.cc
@@ -2,16 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "chrome/browser/ash/file_system_provider/fileapi/buffering_file_stream_reader.h" #include <algorithm> #include <utility> +#include "base/compiler_specific.h" #include "base/functional/bind.h" #include "net/base/io_buffer.h" #include "net/base/net_errors.h" @@ -80,9 +76,9 @@ int buffer_length) { const int read_bytes = std::min(buffer_length, preloaded_bytes_); - memcpy(buffer->data(), - preloading_buffer_->data() + preloading_buffer_offset_, - read_bytes); + UNSAFE_TODO(memcpy(buffer->data(), + preloading_buffer_->data() + preloading_buffer_offset_, + read_bytes)); preloading_buffer_offset_ += read_bytes; preloaded_bytes_ -= read_bytes;
diff --git a/chrome/browser/ash/file_system_provider/fileapi/buffering_file_stream_writer.cc b/chrome/browser/ash/file_system_provider/fileapi/buffering_file_stream_writer.cc index 5224f0a..d7a33cd 100644 --- a/chrome/browser/ash/file_system_provider/fileapi/buffering_file_stream_writer.cc +++ b/chrome/browser/ash/file_system_provider/fileapi/buffering_file_stream_writer.cc
@@ -2,16 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "chrome/browser/ash/file_system_provider/fileapi/buffering_file_stream_writer.h" #include <algorithm> #include <utility> +#include "base/compiler_specific.h" #include "base/functional/bind.h" #include "net/base/io_buffer.h" #include "net/base/net_errors.h" @@ -96,9 +92,8 @@ int buffer_offset, int buffer_length) { DCHECK_GE(intermediate_buffer_length_, buffer_length + buffered_bytes_); - memcpy(intermediate_buffer_->data() + buffered_bytes_, - buffer->data() + buffer_offset, - buffer_length); + UNSAFE_TODO(memcpy(intermediate_buffer_->data() + buffered_bytes_, + buffer->data() + buffer_offset, buffer_length)); buffered_bytes_ += buffer_length; }
diff --git a/chrome/browser/ash/file_system_provider/fileapi/file_stream_reader_unittest.cc b/chrome/browser/ash/file_system_provider/fileapi/file_stream_reader_unittest.cc index 6c72f31..d36ee060 100644 --- a/chrome/browser/ash/file_system_provider/fileapi/file_stream_reader_unittest.cc +++ b/chrome/browser/ash/file_system_provider/fileapi/file_stream_reader_unittest.cc
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "chrome/browser/ash/file_system_provider/fileapi/file_stream_reader.h" #include <stddef.h> @@ -16,6 +11,7 @@ #include <string> #include <vector> +#include "base/compiler_specific.h" #include "base/files/file.h" #include "base/files/file_path.h" #include "base/files/scoped_temp_dir.h" @@ -118,8 +114,8 @@ const std::string mount_point_name = file_system_info.mount_path().BaseName().AsUTF8Unsafe(); - file_url_ = CreateFileSystemURL(mount_point_name, - base::FilePath(kFakeFilePath + 1)); + file_url_ = CreateFileSystemURL( + mount_point_name, base::FilePath(UNSAFE_TODO(kFakeFilePath + 1))); ASSERT_TRUE(file_url_.is_valid()); wrong_file_url_ = CreateFileSystemURL( mount_point_name, base::FilePath(FILE_PATH_LITERAL("im-not-here.txt"))); @@ -220,8 +216,8 @@ EXPECT_EQ(length, logger.results()[0]); std::string buffer_as_string(io_buffer->data(), length); - std::string expected_buffer(fake_file_->contents.data() + initial_offset, - length); + std::string expected_buffer( + UNSAFE_TODO(fake_file_->contents.data() + initial_offset), length); EXPECT_EQ(expected_buffer, buffer_as_string); }
diff --git a/chrome/browser/ash/file_system_provider/fileapi/file_stream_writer_unittest.cc b/chrome/browser/ash/file_system_provider/fileapi/file_stream_writer_unittest.cc index 32bf69c8..8ed1c6b 100644 --- a/chrome/browser/ash/file_system_provider/fileapi/file_stream_writer_unittest.cc +++ b/chrome/browser/ash/file_system_provider/fileapi/file_stream_writer_unittest.cc
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "chrome/browser/ash/file_system_provider/fileapi/file_stream_writer.h" #include <stddef.h> @@ -16,6 +11,7 @@ #include <string> #include <vector> +#include "base/compiler_specific.h" #include "base/files/file.h" #include "base/files/file_path.h" #include "base/files/scoped_temp_dir.h" @@ -96,8 +92,8 @@ const std::string mount_point_name = file_system_info.mount_path().BaseName().AsUTF8Unsafe(); - file_url_ = CreateFileSystemURL(mount_point_name, - base::FilePath(kFakeFilePath + 1)); + file_url_ = CreateFileSystemURL( + mount_point_name, base::FilePath(UNSAFE_TODO(kFakeFilePath + 1))); ASSERT_TRUE(file_url_.is_valid()); wrong_file_url_ = CreateFileSystemURL( mount_point_name, base::FilePath(FILE_PATH_LITERAL("im-not-here.txt")));
diff --git a/chrome/browser/ash/file_system_provider/fileapi/provider_async_file_util_unittest.cc b/chrome/browser/ash/file_system_provider/fileapi/provider_async_file_util_unittest.cc index a4e7607..6a017406 100644 --- a/chrome/browser/ash/file_system_provider/fileapi/provider_async_file_util_unittest.cc +++ b/chrome/browser/ash/file_system_provider/fileapi/provider_async_file_util_unittest.cc
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "chrome/browser/ash/file_system_provider/fileapi/provider_async_file_util.h" #include <stdint.h> @@ -16,6 +11,7 @@ #include <utility> #include <vector> +#include "base/compiler_specific.h" #include "base/files/file.h" #include "base/files/file_path.h" #include "base/files/file_util.h" @@ -198,7 +194,7 @@ file_url_ = CreateFileSystemURL( mount_point_name_, - base::FilePath(kFakeFilePath + /*No leading slash.=*/1)); + base::FilePath(UNSAFE_TODO(kFakeFilePath + /*No leading slash.=*/1))); ASSERT_TRUE(file_url_.is_valid()); directory_url_ = CreateFileSystemURL( mount_point_name_, base::FilePath(FILE_PATH_LITERAL("hello"))); @@ -367,8 +363,8 @@ ASSERT_TRUE(logger.result()); EXPECT_EQ(base::File::FILE_OK, *logger.result()); EXPECT_EQ(1U, logger.read_directory_list().size()); - EXPECT_EQ(base::FilePath(kFakeFilePath + /*No leading slash.=*/1), - logger.read_directory_list()[0].name.path()); + UNSAFE_TODO(EXPECT_EQ(base::FilePath(kFakeFilePath + /*No leading slash.=*/1), + logger.read_directory_list()[0].name.path())); } TEST_F(FileSystemProviderProviderAsyncFileUtilTest, Touch) {
diff --git a/chrome/browser/ash/file_system_provider/mount_path_util.cc b/chrome/browser/ash/file_system_provider/mount_path_util.cc index a39cecc..087ce7b9 100644 --- a/chrome/browser/ash/file_system_provider/mount_path_util.cc +++ b/chrome/browser/ash/file_system_provider/mount_path_util.cc
@@ -2,17 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "chrome/browser/ash/file_system_provider/mount_path_util.h" #include <stddef.h> #include <vector> +#include "base/compiler_specific.h" #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" #include "chrome/browser/ash/file_manager/path_util.h" @@ -78,8 +74,10 @@ if (components[0] != FILE_PATH_LITERAL("/")) return false; - if (components[1] != kProvidedMountPointRoot + 1 /* no leading slash */) + if (components[1] != + UNSAFE_TODO(kProvidedMountPointRoot + 1 /* no leading slash */)) { return false; + } return true; }
diff --git a/chrome/browser/ash/file_system_provider/operations/read_file.cc b/chrome/browser/ash/file_system_provider/operations/read_file.cc index 3bedfea..c54caa9 100644 --- a/chrome/browser/ash/file_system_provider/operations/read_file.cc +++ b/chrome/browser/ash/file_system_provider/operations/read_file.cc
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "chrome/browser/ash/file_system_provider/operations/read_file.h" #include <stddef.h> @@ -15,6 +10,7 @@ #include <string> #include <utility> +#include "base/compiler_specific.h" #include "base/trace_event/trace_event.h" #include "chrome/common/extensions/api/file_system_provider.h" #include "chrome/common/extensions/api/file_system_provider_internal.h" @@ -41,7 +37,8 @@ if (chunk_size > static_cast<size_t>(buffer_length) - buffer_offset) return -1; - memcpy(buffer->data() + buffer_offset, params->data.data(), chunk_size); + UNSAFE_TODO( + memcpy(buffer->data() + buffer_offset, params->data.data(), chunk_size)); return chunk_size; }
diff --git a/chrome/browser/ash/file_system_provider/operations/write_file.cc b/chrome/browser/ash/file_system_provider/operations/write_file.cc index 5866dd0..a957319 100644 --- a/chrome/browser/ash/file_system_provider/operations/write_file.cc +++ b/chrome/browser/ash/file_system_provider/operations/write_file.cc
@@ -2,15 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "chrome/browser/ash/file_system_provider/operations/write_file.h" #include <utility> +#include "base/compiler_specific.h" #include "base/containers/span.h" #include "base/trace_event/trace_event.h" #include "base/values.h" @@ -53,9 +49,8 @@ DCHECK(buffer_.get()); base::Value::Dict options_as_value = options.ToValue(); - options_as_value.Set( - "data", - base::Value(base::as_bytes(base::span(buffer_->data(), length_)))); + options_as_value.Set("data", base::Value(base::as_bytes(UNSAFE_TODO( + base::span(buffer_->data(), length_))))); base::Value::List event_args; event_args.Append(std::move(options_as_value));
diff --git a/chrome/browser/ash/fileapi/diversion_file_manager.cc b/chrome/browser/ash/fileapi/diversion_file_manager.cc index 1a1690c..5251959f 100644 --- a/chrome/browser/ash/fileapi/diversion_file_manager.cc +++ b/chrome/browser/ash/fileapi/diversion_file_manager.cc
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "chrome/browser/ash/fileapi/diversion_file_manager.h" #include <fcntl.h> @@ -17,6 +12,7 @@ #include <optional> #include <utility> +#include "base/compiler_specific.h" #include "base/containers/circular_deque.h" #include "base/functional/callback.h" #include "base/memory/weak_ptr.h" @@ -461,7 +457,7 @@ 0); } - data_ptr += n; + UNSAFE_TODO(data_ptr += n); data_len -= static_cast<int>(n); offset = base::ClampAdd(offset, static_cast<int64_t>(n)); }
diff --git a/chrome/browser/ash/fileapi/external_file_url_loader_factory.cc b/chrome/browser/ash/fileapi/external_file_url_loader_factory.cc index 19c334a..b0b3f7d1 100644 --- a/chrome/browser/ash/fileapi/external_file_url_loader_factory.cc +++ b/chrome/browser/ash/fileapi/external_file_url_loader_factory.cc
@@ -2,15 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/377326291): Fix and remove. -#pragma allow_unsafe_buffers -#endif - #include "chrome/browser/ash/fileapi/external_file_url_loader_factory.h" #include <algorithm> +#include "base/compiler_specific.h" #include "base/files/file_path.h" #include "base/functional/bind.h" #include "base/task/sequenced_task_runner.h" @@ -52,7 +48,8 @@ class MojoPipeIOBuffer : public net::IOBuffer { public: MojoPipeIOBuffer(void* data, size_t size) - : net::IOBuffer(base::span(static_cast<char*>(data), size)) {} + : net::IOBuffer(UNSAFE_TODO(base::span(static_cast<char*>(data), size))) { + } MojoPipeIOBuffer(const MojoPipeIOBuffer&) = delete; MojoPipeIOBuffer& operator=(const MojoPipeIOBuffer&) = delete;
diff --git a/chrome/browser/ash/fileapi/file_system_backend_unittest.cc b/chrome/browser/ash/fileapi/file_system_backend_unittest.cc index be6dbf4..71fbd3a 100644 --- a/chrome/browser/ash/fileapi/file_system_backend_unittest.cc +++ b/chrome/browser/ash/fileapi/file_system_backend_unittest.cc
@@ -2,17 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "chrome/browser/ash/fileapi/file_system_backend.h" #include <stddef.h> #include <set> +#include "base/compiler_specific.h" #include "base/files/file_path.h" #include "chrome/browser/ash/fileapi/file_system_backend_delegate.h" #include "chromeos/ash/components/dbus/cros_disks/cros_disks_client.h" @@ -266,19 +262,21 @@ for (size_t i = 0; i < std::size(kTestCases); ++i) { // Initialize virtual path with a value. base::FilePath virtual_path(FPL("/mount")); - base::FilePath local_path(kTestCases[i].local_path); - EXPECT_EQ(kTestCases[i].success, - backend.GetVirtualPath(local_path, &virtual_path)) - << "Resolving " << kTestCases[i].local_path; + base::FilePath local_path(UNSAFE_TODO(kTestCases[i]).local_path); + UNSAFE_TODO(EXPECT_EQ(kTestCases[i].success, + backend.GetVirtualPath(local_path, &virtual_path))) + << "Resolving " << UNSAFE_TODO(kTestCases[i]).local_path; // There are no guarantees for |virtual_path| value if |GetVirtualPath| // fails. - if (!kTestCases[i].success) + if (!UNSAFE_TODO(kTestCases[i]).success) { continue; + } - base::FilePath expected_virtual_path(kTestCases[i].virtual_path); + base::FilePath expected_virtual_path( + UNSAFE_TODO(kTestCases[i]).virtual_path); EXPECT_EQ(expected_virtual_path, virtual_path) - << "Resolving " << kTestCases[i].local_path; + << "Resolving " << UNSAFE_TODO(kTestCases[i]).local_path; } }
diff --git a/chrome/browser/ash/image_source/image_source.cc b/chrome/browser/ash/image_source/image_source.cc index f044da9..59ed3d34 100644 --- a/chrome/browser/ash/image_source/image_source.cc +++ b/chrome/browser/ash/image_source/image_source.cc
@@ -2,17 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "chrome/browser/ash/image_source/image_source.h" #include <stddef.h> #include <vector> +#include "base/compiler_specific.h" #include "base/files/file_util.h" #include "base/functional/bind.h" #include "base/location.h" @@ -106,8 +102,9 @@ return false; for (size_t i = 0; i < std::size(kAllowlistedDirectories); i++) { - if (components[0] == kAllowlistedDirectories[i]) + if (components[0] == UNSAFE_TODO(kAllowlistedDirectories[i])) { return true; + } } return false; }
diff --git a/chrome/browser/ash/input_method/assistive_suggester_client_filter.cc b/chrome/browser/ash/input_method/assistive_suggester_client_filter.cc index 99a0191..19572a75c 100644 --- a/chrome/browser/ash/input_method/assistive_suggester_client_filter.cc +++ b/chrome/browser/ash/input_method/assistive_suggester_client_filter.cc
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "chrome/browser/ash/input_method/assistive_suggester_client_filter.h" #include <algorithm> @@ -15,6 +10,7 @@ #include "ash/constants/ash_features.h" #include "ash/public/cpp/window_properties.h" +#include "base/compiler_specific.h" #include "base/functional/callback.h" #include "base/hash/hash.h" #include "base/strings/string_util.h" @@ -150,8 +146,8 @@ return false; } for (size_t i = 0; i < N; i++) { - auto domain = expected_domains_and_paths[i][0]; - auto path_prefix = expected_domains_and_paths[i][1]; + auto domain = UNSAFE_TODO(expected_domains_and_paths[i])[0]; + auto path_prefix = UNSAFE_TODO(expected_domains_and_paths[i])[1]; if (AtDomainWithPathPrefix(url, domain, path_prefix)) { return true; } @@ -166,7 +162,7 @@ return false; } for (size_t i = 0; i < N; i++) { - auto expected_url = expected_urls[i]; + auto expected_url = UNSAFE_TODO(expected_urls[i]); if (base::CompareCaseInsensitiveASCII(url->spec(), expected_url) == 0) { return true; } @@ -179,14 +175,15 @@ WindowProperties w) { if (!w.arc_package_name.empty() && std::find(expected_app_ids_or_package_names, - expected_app_ids_or_package_names + N, - w.arc_package_name) != expected_app_ids_or_package_names + N) { + UNSAFE_TODO(expected_app_ids_or_package_names + N), + w.arc_package_name) != + UNSAFE_TODO(expected_app_ids_or_package_names + N)) { return true; } if (!w.app_id.empty() && std::find(expected_app_ids_or_package_names, - expected_app_ids_or_package_names + N, - w.app_id) != expected_app_ids_or_package_names + N) { + UNSAFE_TODO(expected_app_ids_or_package_names + N), w.app_id) != + UNSAFE_TODO(expected_app_ids_or_package_names + N)) { return true; } return false;
diff --git a/chrome/browser/ash/input_method/input_method_engine_browsertests.cc b/chrome/browser/ash/input_method/input_method_engine_browsertests.cc index dbe190f..2b5bcfe2 100644 --- a/chrome/browser/ash/input_method/input_method_engine_browsertests.cc +++ b/chrome/browser/ash/input_method/input_method_engine_browsertests.cc
@@ -2,17 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include <stddef.h> #include <memory> #include <string_view> #include "ash/shell.h" +#include "base/compiler_specific.h" #include "base/functional/bind.h" #include "base/functional/callback_helpers.h" #include "base/memory/raw_ptr.h" @@ -476,17 +472,20 @@ }; for (size_t i = 0; i < std::size(kMediaKeyCases); ++i) { - SCOPED_TRACE(std::string("KeyDown, ") + kMediaKeyCases[i].code); + UNSAFE_TODO( + SCOPED_TRACE(std::string("KeyDown, ") + kMediaKeyCases[i].code)); KeyEventDoneCallback callback(ui::ime::KeyEventHandledState::kNotHandled); const std::string expected_value = base::StringPrintf( "onKeyEvent::true:keydown:%s:%s:false:false:false:false:false", - kMediaKeyCases[i].key, kMediaKeyCases[i].code); + UNSAFE_TODO(kMediaKeyCases[i]).key, + UNSAFE_TODO(kMediaKeyCases[i]).code); ExtensionTestMessageListener keyevent_listener(expected_value); - ui::KeyEvent key_event( - ui::EventType::kKeyPressed, kMediaKeyCases[i].keycode, - ui::KeycodeConverter::CodeStringToDomCode(kMediaKeyCases[i].code), - ui::EF_NONE); + ui::KeyEvent key_event(ui::EventType::kKeyPressed, + UNSAFE_TODO(kMediaKeyCases[i]).keycode, + ui::KeycodeConverter::CodeStringToDomCode( + UNSAFE_TODO(kMediaKeyCases[i]).code), + ui::EF_NONE); TextInputMethod::KeyEventDoneCallback keyevent_callback = base::BindOnce(&KeyEventDoneCallback::Run, base::Unretained(&callback)); engine_handler->ProcessKeyEvent(key_event, std::move(keyevent_callback));
diff --git a/chrome/browser/ash/input_method/input_method_manager_impl.cc b/chrome/browser/ash/input_method/input_method_manager_impl.cc index f5400f4..b951daf 100644 --- a/chrome/browser/ash/input_method/input_method_manager_impl.cc +++ b/chrome/browser/ash/input_method/input_method_manager_impl.cc
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "chrome/browser/ash/input_method/input_method_manager_impl.h" #include <stdint.h> @@ -20,6 +15,7 @@ #include "ash/constants/ash_features.h" #include "base/check.h" #include "base/check_deref.h" +#include "base/compiler_specific.h" #include "base/containers/contains.h" #include "base/feature_list.h" #include "base/functional/bind.h" @@ -1084,7 +1080,7 @@ // Create a set of layouts that do not use positional shortcuts. non_positional_layouts_.reserve(kNonPositionalLayoutsLength); for (size_t i = 0; i < kNonPositionalLayoutsLength; i++) { - non_positional_layouts_.emplace(kNonPositionalLayouts[i]); + non_positional_layouts_.emplace(UNSAFE_TODO(kNonPositionalLayouts[i])); } }
diff --git a/chrome/browser/ash/login/demo_mode/demo_setup_browsertest.cc b/chrome/browser/ash/login/demo_mode/demo_setup_browsertest.cc index 22334a43..4bb0f3c 100644 --- a/chrome/browser/ash/login/demo_mode/demo_setup_browsertest.cc +++ b/chrome/browser/ash/login/demo_mode/demo_setup_browsertest.cc
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include <string> #include <string_view> @@ -15,6 +10,7 @@ #include "ash/constants/ash_switches.h" #include "ash/public/cpp/login_accelerators.h" #include "base/command_line.h" +#include "base/compiler_specific.h" #include "base/containers/flat_map.h" #include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h" @@ -1163,7 +1159,7 @@ ASSERT_EQ(CountNumberOfStepsInUi(), numSteps); for (int i = 0; i < numSteps; i++) { - demoSetupScreen->SetCurrentSetupStepForTest(orderedSteps[i]); + demoSetupScreen->SetCurrentSetupStepForTest(UNSAFE_TODO(orderedSteps[i])); ASSERT_EQ(CountStepsInUi("pending"), numSteps - i - 1); ASSERT_EQ(CountStepsInUi("active"), 1); ASSERT_EQ(CountStepsInUi("completed"), i);
diff --git a/chrome/browser/ash/login/oobe_localization_browsertest.cc b/chrome/browser/ash/login/oobe_localization_browsertest.cc index 6a32052..ef6d715e 100644 --- a/chrome/browser/ash/login/oobe_localization_browsertest.cc +++ b/chrome/browser/ash/login/oobe_localization_browsertest.cc
@@ -2,13 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include <stddef.h> +#include "base/compiler_specific.h" #include "base/functional/bind.h" #include "base/memory/raw_ptr.h" #include "base/run_loop.h" @@ -402,10 +398,10 @@ RunLocalizationTest(); } -INSTANTIATE_TEST_SUITE_P( +UNSAFE_TODO(INSTANTIATE_TEST_SUITE_P( All, OobeLocalizationTest, testing::Range(&oobe_localization_test_parameters[0], &oobe_localization_test_parameters[std::size( - oobe_localization_test_parameters)])); + oobe_localization_test_parameters)]))); } // namespace ash
diff --git a/chrome/browser/ash/login/oobe_quick_start/connectivity/target_device_connection_broker_impl_unittest.cc b/chrome/browser/ash/login/oobe_quick_start/connectivity/target_device_connection_broker_impl_unittest.cc index 7df6b2b6..2b80feb 100644 --- a/chrome/browser/ash/login/oobe_quick_start/connectivity/target_device_connection_broker_impl_unittest.cc +++ b/chrome/browser/ash/login/oobe_quick_start/connectivity/target_device_connection_broker_impl_unittest.cc
@@ -2,17 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "chrome/browser/ash/login/oobe_quick_start/connectivity/target_device_connection_broker_impl.h" #include <array> #include "base/base64.h" #include "base/command_line.h" +#include "base/compiler_specific.h" #include "base/functional/bind.h" #include "base/memory/raw_ptr.h" #include "base/test/metrics/histogram_tester.h" @@ -604,8 +600,8 @@ // The remaining advertising info fields are base64-encoded. Decode them // before proceeding. - std::vector<uint8_t> advertising_info = Base64DecodeForgiving( - base::span<uint8_t>(endpoint_info.begin() + i, endpoint_info.end())); + std::vector<uint8_t> advertising_info = Base64DecodeForgiving(UNSAFE_TODO( + base::span<uint8_t>(endpoint_info.begin() + i, endpoint_info.end()))); ASSERT_EQ(advertising_info.size(), 60u); i = 0;
diff --git a/chrome/browser/ash/login/quick_unlock/quick_unlock_utils.cc b/chrome/browser/ash/login/quick_unlock/quick_unlock_utils.cc index 5390b8d..c24b8f1 100644 --- a/chrome/browser/ash/login/quick_unlock/quick_unlock_utils.cc +++ b/chrome/browser/ash/login/quick_unlock/quick_unlock_utils.cc
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "chrome/browser/ash/login/quick_unlock/quick_unlock_utils.h" #include <string> @@ -17,6 +12,7 @@ #include "ash/constants/ash_switches.h" #include "base/check.h" #include "base/command_line.h" +#include "base/compiler_specific.h" #include "base/containers/contains.h" #include "base/containers/fixed_flat_map.h" #include "base/feature_list.h" @@ -128,9 +124,12 @@ old_instance_ = g_instance; g_instance = this; std::fill(pin_purposes_enabled_by_policy_, - pin_purposes_enabled_by_policy_ + kNumOfPurposes, false); - std::fill(fingerprint_purposes_enabled_by_policy_, - fingerprint_purposes_enabled_by_policy_ + kNumOfPurposes, false); + UNSAFE_TODO(pin_purposes_enabled_by_policy_ + kNumOfPurposes), + false); + std::fill( + fingerprint_purposes_enabled_by_policy_, + UNSAFE_TODO(fingerprint_purposes_enabled_by_policy_ + kNumOfPurposes), + false); } TestApi::~TestApi() { @@ -150,7 +149,8 @@ if (purpose != Purpose::kAny) { pin_purposes_enabled_by_policy_[static_cast<int>(Purpose::kAny)] = true; } - pin_purposes_enabled_by_policy_[static_cast<int>(purpose)] = true; + UNSAFE_TODO(pin_purposes_enabled_by_policy_[static_cast<int>(purpose)]) = + true; } void TestApi::EnableFingerprintByPolicy(Purpose purpose) { @@ -158,15 +158,19 @@ fingerprint_purposes_enabled_by_policy_[static_cast<int>(Purpose::kAny)] = true; } - fingerprint_purposes_enabled_by_policy_[static_cast<int>(purpose)] = true; + UNSAFE_TODO( + fingerprint_purposes_enabled_by_policy_[static_cast<int>(purpose)]) = + true; } bool TestApi::IsPinEnabledByPolicy(Purpose purpose) { - return pin_purposes_enabled_by_policy_[static_cast<int>(purpose)]; + return UNSAFE_TODO( + pin_purposes_enabled_by_policy_[static_cast<int>(purpose)]); } bool TestApi::IsFingerprintEnabledByPolicy(Purpose purpose) { - return fingerprint_purposes_enabled_by_policy_[static_cast<int>(purpose)]; + return UNSAFE_TODO( + fingerprint_purposes_enabled_by_policy_[static_cast<int>(purpose)]); } bool IsFingerprintDisabledByPolicy(const PrefService* pref_service,
diff --git a/chrome/browser/ash/login/screens/theme_selection_screen_browsertest.cc b/chrome/browser/ash/login/screens/theme_selection_screen_browsertest.cc index b4c96063..bf1b6df8 100644 --- a/chrome/browser/ash/login/screens/theme_selection_screen_browsertest.cc +++ b/chrome/browser/ash/login/screens/theme_selection_screen_browsertest.cc
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "chrome/browser/ash/login/screens/theme_selection_screen.h" #include "ash/constants/ash_pref_names.h" @@ -15,6 +10,7 @@ #include "ash/shell.h" #include "ash/style/dark_light_mode_controller_impl.h" #include "ash/wm/tablet_mode/tablet_mode_controller.h" +#include "base/compiler_specific.h" #include "base/test/metrics/histogram_tester.h" #include "base/test/test_future.h" #include "chrome/browser/ash/login/screens/guest_tos_screen.h" @@ -166,8 +162,8 @@ test::OobeJS().ExpectVisiblePath(selected_option_path); test::OobeJS().ClickOnPath(selected_option_path); - auto selectedOption = - selected_option_path.begin()[selected_option_path.size() - 1]; + auto selectedOption = UNSAFE_TODO( + selected_option_path.begin()[selected_option_path.size() - 1]); ThemeSelectionScreen::SelectedTheme theme = ThemeSelectionScreen::SelectedTheme::kDark; if (selectedOption == kDarkThemeButton) { @@ -252,7 +248,7 @@ test::OobeJS().ExpectVisiblePath(GetParam()); test::OobeJS().ClickOnPath(GetParam()); - auto selectedOption = GetParam().begin()[GetParam().size() - 1]; + auto selectedOption = UNSAFE_TODO(GetParam().begin()[GetParam().size() - 1]); if (selectedOption == kDarkThemeButton) { EXPECT_EQ(profile->GetPrefs()->GetBoolean(prefs::kDarkModeEnabled), true); EXPECT_EQ(profile->GetPrefs()->GetInteger(prefs::kDarkModeScheduleType), 0);
diff --git a/chrome/browser/ash/login/signin/signin_error_notifier_unittest.cc b/chrome/browser/ash/login/signin/signin_error_notifier_unittest.cc index 3b601101..1b2fc872 100644 --- a/chrome/browser/ash/login/signin/signin_error_notifier_unittest.cc +++ b/chrome/browser/ash/login/signin/signin_error_notifier_unittest.cc
@@ -2,13 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ash/public/cpp/token_handle_store.h" -#include "chrome/browser/ash/login/signin/token_handle_store_factory.h" -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "chrome/browser/ash/login/signin/signin_error_notifier.h" #include <stddef.h> @@ -16,9 +9,12 @@ #include <memory> #include <string> +#include "ash/public/cpp/token_handle_store.h" +#include "base/compiler_specific.h" #include "base/memory/ptr_util.h" #include "build/build_config.h" #include "chrome/browser/ash/login/signin/signin_error_notifier_factory.h" +#include "chrome/browser/ash/login/signin/token_handle_store_factory.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/notifications/notification_display_service_tester.h" #include "chrome/browser/signin/identity_test_environment_profile_adaptor.h" @@ -245,12 +241,13 @@ for (size_t i = 0; i < std::size(table); ++i) { GoogleServiceAuthError error; - if (table[i] == GoogleServiceAuthError::SCOPE_LIMITED_UNRECOVERABLE_ERROR) { + if (UNSAFE_TODO(table[i]) == + GoogleServiceAuthError::SCOPE_LIMITED_UNRECOVERABLE_ERROR) { error = GoogleServiceAuthError::FromScopeLimitedUnrecoverableErrorReason( GoogleServiceAuthError::ScopeLimitedUnrecoverableErrorReason:: kInvalidGrantRaptError); } else { - error = GoogleServiceAuthError(table[i]); + error = GoogleServiceAuthError(UNSAFE_TODO(table[i])); } SetAuthError(account_id, error); std::optional<message_center::Notification> notification =
diff --git a/chrome/browser/ash/login/test/device_state_mixin.cc b/chrome/browser/ash/login/test/device_state_mixin.cc index ebe9d94..3294d7d 100644 --- a/chrome/browser/ash/login/test/device_state_mixin.cc +++ b/chrome/browser/ash/login/test/device_state_mixin.cc
@@ -2,17 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "chrome/browser/ash/login/test/device_state_mixin.h" #include <utility> #include <vector> #include "ash/constants/ash_paths.h" +#include "base/compiler_specific.h" #include "base/files/file_util.h" #include "base/functional/callback.h" #include "base/json/json_writer.h" @@ -63,8 +59,8 @@ const std::string& name = it.first; const std::string& value = it.second; attr_entry->set_name(name); - attr_entry->mutable_value()->assign(value.data(), - value.data() + value.size()); + attr_entry->mutable_value()->assign( + value.data(), UNSAFE_TODO(value.data() + value.size())); } return install_attrs; }
diff --git a/chrome/browser/ash/login/test/js_checker.cc b/chrome/browser/ash/login/test/js_checker.cc index 176ea69..9744787 100644 --- a/chrome/browser/ash/login/test/js_checker.cc +++ b/chrome/browser/ash/login/test/js_checker.cc
@@ -2,15 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "chrome/browser/ash/login/test/js_checker.h" #include <string_view> +#include "base/compiler_specific.h" #include "base/functional/callback_helpers.h" #include "base/json/string_escape.h" #include "base/strings/string_util.h" @@ -75,7 +71,7 @@ std::initializer_list<std::string_view>::const_iterator it = element_ids.begin(); result.append("//").append(std::string(*it)); - for (it++; it < element_ids.end(); it++) { + for (UNSAFE_TODO(it++); it < element_ids.end(); UNSAFE_TODO(it++)) { result.append("/").append(std::string(*it)); } return result; @@ -573,8 +569,8 @@ std::initializer_list<std::string_view>::const_iterator it = element_ids.begin(); auto result = base::StringPrintf(kGetElement, std::string(*it).c_str()); - for (it++; it < element_ids.end(); it++) { - result.append(base::StringPrintf(kShadowRoot, std::string(*it).c_str())); + for (UNSAFE_TODO(it++); it < element_ids.end(); UNSAFE_TODO(it++)) { + result.append(base::StringPrintf(kShadowRoot, std::string(*it).c_str())); } return result; }
diff --git a/chrome/browser/ash/login/users/avatar/user_image_manager_test_util.cc b/chrome/browser/ash/login/users/avatar/user_image_manager_test_util.cc index f160e32..0a0123e9 100644 --- a/chrome/browser/ash/login/users/avatar/user_image_manager_test_util.cc +++ b/chrome/browser/ash/login/users/avatar/user_image_manager_test_util.cc
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "chrome/browser/ash/login/users/avatar/user_image_manager_test_util.h" #include <stddef.h> @@ -14,6 +9,7 @@ #include <string> +#include "base/compiler_specific.h" #include "base/files/file_util.h" #include "base/test/test_future.h" #include "base/threading/thread_restrictions.h" @@ -48,7 +44,7 @@ uint8_t* first_data = reinterpret_cast<uint8_t*>(first_bitmap->getPixels()); uint8_t* second_data = reinterpret_cast<uint8_t*>(second_bitmap->getPixels()); for (size_t i = 0; i < size; ++i) { - if (first_data[i] != second_data[i]) { + if (UNSAFE_TODO(first_data[i]) != UNSAFE_TODO(second_data[i])) { return false; } }
diff --git a/chrome/browser/ash/login/users/default_user_image/default_user_images.cc b/chrome/browser/ash/login/users/default_user_image/default_user_images.cc index a1753e55..b94e7d49 100644 --- a/chrome/browser/ash/login/users/default_user_image/default_user_images.cc +++ b/chrome/browser/ash/login/users/default_user_image/default_user_images.cc
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "chrome/browser/ash/login/users/default_user_image/default_user_images.h" #include <algorithm> @@ -17,6 +12,7 @@ #include "ash/constants/ash_features.h" #include "ash/public/cpp/default_user_image.h" #include "base/command_line.h" +#include "base/compiler_specific.h" #include "base/logging.h" #include "base/notimplemented.h" #include "base/rand_util.h" @@ -238,10 +234,11 @@ } for (const int index : kCurrentImageIndexes) { - if (kDefaultImageInfo[index].eligibility != Eligibility::kEligible) { + if (UNSAFE_TODO(kDefaultImageInfo[index]).eligibility != + Eligibility::kEligible) { return false; } - if (kDefaultImageInfo[index].description_message_id == 0) { + if (UNSAFE_TODO(kDefaultImageInfo[index]).description_message_id == 0) { // All current and new images must have a description. return false; } @@ -373,11 +370,11 @@ auto scale_factor_prefix = GetUrlPrefixForScaleFactor(adjusted_scale_factor); return GURL(base::StrCat({kGstaticImagePrefix, scale_factor_prefix, - kDefaultImageInfo[index].path})); + UNSAFE_TODO(kDefaultImageInfo[index]).path})); } int GetDefaultImageResourceId(int index) { - return kDefaultImageInfo[index].resource_id; + return UNSAFE_TODO(kDefaultImageInfo[index]).resource_id; } const gfx::ImageSkia& GetStubDefaultImage() { @@ -386,7 +383,7 @@ } int GetRandomDefaultImageIndex() { - return kCurrentImageIndexes[base::RandInt( + return UNSAFE_TODO(kCurrentImageIndexes)[base::RandInt( 0, std::size(kCurrentImageIndexes) - 1)]; } @@ -396,14 +393,16 @@ bool IsInCurrentImageSet(int index) { return IsValidIndex(index) && - kDefaultImageInfo[index].eligibility == Eligibility::kEligible; + UNSAFE_TODO(kDefaultImageInfo[index]).eligibility == + Eligibility::kEligible; } DefaultUserImage GetDefaultUserImage( int index, ui::ResourceScaleFactor scale_factor /*= ui::k200Percent*/) { DCHECK(IsValidIndex(index)); - int description_message_id = kDefaultImageInfo[index].description_message_id; + int description_message_id = + UNSAFE_TODO(kDefaultImageInfo[index]).description_message_id; std::u16string title = description_message_id ? l10n_util::GetStringUTF16(description_message_id) : std::u16string(); @@ -439,7 +438,7 @@ return std::nullopt; } - const auto& source_info_ids = kDefaultImageSourceInfoIds[index]; + const auto& source_info_ids = UNSAFE_TODO(kDefaultImageSourceInfoIds[index]); return DeprecatedSourceInfo( l10n_util::GetStringUTF16(source_info_ids.author_id), GURL(l10n_util::GetStringUTF16(source_info_ids.website_id)));
diff --git a/chrome/browser/ash/login/users/wallpaper_policy_browsertest.cc b/chrome/browser/ash/login/users/wallpaper_policy_browsertest.cc index 0604e88..f15794f 100644 --- a/chrome/browser/ash/login/users/wallpaper_policy_browsertest.cc +++ b/chrome/browser/ash/login/users/wallpaper_policy_browsertest.cc
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include <stdint.h> #include <memory> @@ -262,7 +257,7 @@ const AccountId& account_id = login_manager_.users()[user_number].account_id; policy::UserPolicyBuilder* builder = - user_policy_builders_[user_number].get(); + UNSAFE_TODO(user_policy_builders_[user_number]).get(); if (!filename.empty()) { builder->payload().mutable_wallpaperimage()->set_value( ConstructPolicy(filename));
diff --git a/chrome/browser/ash/login/version_info_updater.cc b/chrome/browser/ash/login/version_info_updater.cc index 0b681f5..07d9b0f 100644 --- a/chrome/browser/ash/login/version_info_updater.cc +++ b/chrome/browser/ash/login/version_info_updater.cc
@@ -2,16 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "chrome/browser/ash/login/version_info_updater.h" #include <string_view> #include <vector> +#include "base/compiler_specific.h" #include "base/functional/bind.h" #include "base/functional/callback_helpers.h" #include "base/strings/string_util.h" @@ -112,8 +108,8 @@ auto callback = base::BindRepeating(&VersionInfoUpdater::UpdateEnterpriseInfo, base::Unretained(this)); for (unsigned int i = 0; i < std::size(kReportingFlags); ++i) { - subscriptions_.push_back( - cros_settings_->AddSettingsObserver(kReportingFlags[i], callback)); + subscriptions_.push_back(cros_settings_->AddSettingsObserver( + UNSAFE_TODO(kReportingFlags[i]), callback)); } // Update device bluetooth info.
diff --git a/chrome/browser/ash/network_change_manager/network_change_manager_client_unittest.cc b/chrome/browser/ash/network_change_manager/network_change_manager_client_unittest.cc index e9a93d0..95701eb4 100644 --- a/chrome/browser/ash/network_change_manager/network_change_manager_client_unittest.cc +++ b/chrome/browser/ash/network_change_manager/network_change_manager_client_unittest.cc
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "chrome/browser/ash/network_change_manager/network_change_manager_client.h" #include <stddef.h> @@ -14,6 +9,7 @@ #include <memory> #include <string> +#include "base/compiler_specific.h" #include "base/strings/string_split.h" #include "base/value_iterators.h" #include "chromeos/ash/components/network/network_handler_test_helper.h" @@ -107,8 +103,9 @@ for (size_t i = 0; i < std::size(type_mappings); ++i) { NetworkChangeNotifier::ConnectionType type = NetworkChangeManagerClient::ConnectionTypeFromShill( - type_mappings[i].shill_type, type_mappings[i].technology); - EXPECT_EQ(type_mappings[i].connection_type, type); + UNSAFE_TODO(type_mappings[i]).shill_type, + UNSAFE_TODO(type_mappings[i]).technology); + UNSAFE_TODO(EXPECT_EQ(type_mappings[i].connection_type, type)); } } @@ -406,18 +403,19 @@ TEST_F(NetworkChangeManagerClientUpdateTest, UpdateDefaultNetwork) { for (size_t i = 0; i < std::size(test_cases); ++i) { - SCOPED_TRACE(test_cases[i].test_description); - SetNotifierState(test_cases[i].initial_state); - SetDefaultNetworkState(test_cases[i].default_network_state); + UNSAFE_TODO(SCOPED_TRACE(test_cases[i].test_description)); + SetNotifierState(UNSAFE_TODO(test_cases[i]).initial_state); + SetDefaultNetworkState(UNSAFE_TODO(test_cases[i]).default_network_state); bool dns_changed = false, ip_changed = false, type_changed = false, subtype_changed = false; ProcessDefaultNetworkUpdate(&dns_changed, &ip_changed, &type_changed, &subtype_changed); - VerifyNotifierState(test_cases[i].expected_state); - EXPECT_EQ(test_cases[i].expected_dns_changed, dns_changed); - EXPECT_EQ(test_cases[i].expected_ip_changed, ip_changed); - EXPECT_EQ(test_cases[i].expected_type_changed, type_changed); - EXPECT_EQ(test_cases[i].expected_subtype_changed, subtype_changed); + VerifyNotifierState(UNSAFE_TODO(test_cases[i]).expected_state); + UNSAFE_TODO(EXPECT_EQ(test_cases[i].expected_dns_changed, dns_changed)); + UNSAFE_TODO(EXPECT_EQ(test_cases[i].expected_ip_changed, ip_changed)); + UNSAFE_TODO(EXPECT_EQ(test_cases[i].expected_type_changed, type_changed)); + UNSAFE_TODO( + EXPECT_EQ(test_cases[i].expected_subtype_changed, subtype_changed)); } }
diff --git a/chrome/browser/ash/os_feedback/chrome_os_feedback_delegate.cc b/chrome/browser/ash/os_feedback/chrome_os_feedback_delegate.cc index e869ec96..2a13d558 100644 --- a/chrome/browser/ash/os_feedback/chrome_os_feedback_delegate.cc +++ b/chrome/browser/ash/os_feedback/chrome_os_feedback_delegate.cc
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "chrome/browser/ash/os_feedback/chrome_os_feedback_delegate.h" #include <optional> @@ -20,6 +15,7 @@ #include "ash/webui/os_feedback_ui/backend/histogram_util.h" #include "ash/webui/os_feedback_ui/mojom/os_feedback_ui.mojom.h" #include "ash/webui/system_apps/public/system_web_app_type.h" +#include "base/compiler_specific.h" #include "base/functional/bind.h" #include "base/logging.h" #include "base/memory/ref_counted.h" @@ -247,7 +243,7 @@ scoped_refptr<base::RefCountedMemory> png_data = GetScreenshotData(); if (png_data && png_data.get()) { std::vector<uint8_t> data(png_data->data(), - png_data->data() + png_data->size()); + UNSAFE_TODO(png_data->data() + png_data->size())); std::move(callback).Run(data); } else { std::vector<uint8_t> empty_data;
diff --git a/chrome/browser/ash/ownership/owner_key_loader.cc b/chrome/browser/ash/ownership/owner_key_loader.cc index ddb67df1..697aa3e6 100644 --- a/chrome/browser/ash/ownership/owner_key_loader.cc +++ b/chrome/browser/ash/ownership/owner_key_loader.cc
@@ -2,17 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "chrome/browser/ash/ownership/owner_key_loader.h" #include <string> #include <utility> #include "base/check_is_test.h" +#include "base/compiler_specific.h" #include "base/feature_list.h" #include "base/functional/callback_helpers.h" #include "base/task/thread_pool.h" @@ -142,8 +138,9 @@ scoped_refptr<ownership::PublicKey> public_key = base::MakeRefCounted<ownership::PublicKey>( /*is_persisted=*/false, - std::vector<uint8_t>(sec_pub_key_der->data, - sec_pub_key_der->data + sec_pub_key_der->len)); + std::vector<uint8_t>( + sec_pub_key_der->data, + UNSAFE_TODO(sec_pub_key_der->data + sec_pub_key_der->len))); scoped_refptr<ownership::PrivateKey> private_key = base::MakeRefCounted<ownership::PrivateKey>(std::move(sec_priv_key));
diff --git a/chrome/browser/ash/ownership/owner_key_loader_unittest.cc b/chrome/browser/ash/ownership/owner_key_loader_unittest.cc index 28f0590..31cffc3 100644 --- a/chrome/browser/ash/ownership/owner_key_loader_unittest.cc +++ b/chrome/browser/ash/ownership/owner_key_loader_unittest.cc
@@ -2,17 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "chrome/browser/ash/ownership/owner_key_loader.h" #include <memory> #include <vector> #include "ash/constants/ash_features.h" +#include "base/compiler_specific.h" #include "base/memory/raw_ptr.h" #include "base/test/metrics/histogram_tester.h" #include "base/test/scoped_feature_list.h" @@ -49,8 +45,9 @@ SECKEY_ConvertToPublicKey(key.get())); SECItem* public_key_bytes = PK11_DEREncodePublicKey(public_key.get()); - std::vector<uint8_t> bytes(public_key_bytes->data, - public_key_bytes->data + public_key_bytes->len); + std::vector<uint8_t> bytes( + public_key_bytes->data, + UNSAFE_TODO(public_key_bytes->data + public_key_bytes->len)); SECITEM_FreeItem(public_key_bytes, PR_TRUE); return bytes;
diff --git a/chrome/browser/ash/platform_keys/platform_keys_service_browsertest.cc b/chrome/browser/ash/platform_keys/platform_keys_service_browsertest.cc index 3e3fbe7..d52cfc7 100644 --- a/chrome/browser/ash/platform_keys/platform_keys_service_browsertest.cc +++ b/chrome/browser/ash/platform_keys/platform_keys_service_browsertest.cc
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "chrome/browser/ash/platform_keys/platform_keys_service.h" #include <memory> @@ -17,6 +12,7 @@ #include <vector> #include "base/command_line.h" +#include "base/compiler_specific.h" #include "base/containers/span.h" #include "base/functional/bind.h" #include "base/functional/callback.h" @@ -252,9 +248,9 @@ CERTCertificate* cert = out_cert->get(); ASSERT_TRUE(cert); ASSERT_GT(cert->derPublicKey.len, 0U); - *out_spki_der = - std::vector<uint8_t>(cert->derPublicKey.data, - cert->derPublicKey.data + cert->derPublicKey.len); + *out_spki_der = std::vector<uint8_t>( + cert->derPublicKey.data, + UNSAFE_TODO(cert->derPublicKey.data + cert->derPublicKey.len)); } private:
diff --git a/chrome/browser/ash/platform_keys/platform_keys_service_nss.cc b/chrome/browser/ash/platform_keys/platform_keys_service_nss.cc index 94b92b0..f6c0219 100644 --- a/chrome/browser/ash/platform_keys/platform_keys_service_nss.cc +++ b/chrome/browser/ash/platform_keys/platform_keys_service_nss.cc
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include <cert.h> #include <certdb.h> #include <cryptohi.h> @@ -91,7 +86,8 @@ // Returns a vector containing bytes from `value` or an empty vector if `value` // is nullptr. std::vector<uint8_t> ScopedSECItemToBytes(const crypto::ScopedSECItem& value) { - return value ? std::vector<uint8_t>(value->data, value->data + value->len) + return value ? std::vector<uint8_t>(value->data, + UNSAFE_TODO(value->data + value->len)) : std::vector<uint8_t>(); } @@ -1956,7 +1952,8 @@ const uint8_t* public_key_uint8 = reinterpret_cast<const uint8_t*>(state->public_key_spki_der_.data()); std::vector<uint8_t> public_key_vector( - public_key_uint8, public_key_uint8 + state->public_key_spki_der_.size()); + public_key_uint8, + UNSAFE_TODO(public_key_uint8 + state->public_key_spki_der_.size())); if (cert_db->GetPrivateSlot().get()) { crypto::ScopedSECKEYPrivateKey rsa_key = @@ -2105,8 +2102,9 @@ std::string attribute_value_str; if (attribute_value->len > 0) { - attribute_value_str.assign(attribute_value->data, - attribute_value->data + attribute_value->len); + attribute_value_str.assign( + attribute_value->data, + UNSAFE_TODO(attribute_value->data + attribute_value->len)); } state->OnSuccess(FROM_HERE, ScopedSECItemToBytes(attribute_value));
diff --git a/chrome/browser/ash/plugin_vm/plugin_vm_diagnostics.cc b/chrome/browser/ash/plugin_vm/plugin_vm_diagnostics.cc index d07fe386..a301289 100644 --- a/chrome/browser/ash/plugin_vm/plugin_vm_diagnostics.cc +++ b/chrome/browser/ash/plugin_vm/plugin_vm_diagnostics.cc
@@ -2,17 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "chrome/browser/ash/plugin_vm/plugin_vm_diagnostics.h" #include <string> #include <string_view> #include <utility> +#include "base/compiler_specific.h" #include "base/memory/raw_ptr.h" #include "base/strings/strcat.h" #include "base/strings/string_util.h" @@ -47,7 +43,7 @@ CHECK_GE(uppercase.size(), 1u); std::string_view uppercase_first_char(uppercase.c_str(), 1); - std::string_view uppercase_remaining(uppercase.c_str() + 1, + std::string_view uppercase_remaining(UNSAFE_TODO(uppercase.c_str() + 1), uppercase.length() - 1); return base::StrCat(
diff --git a/chrome/browser/ash/policy/core/device_local_account_browsertest.cc b/chrome/browser/ash/policy/core/device_local_account_browsertest.cc index 2f6f066b..c0479651 100644 --- a/chrome/browser/ash/policy/core/device_local_account_browsertest.cc +++ b/chrome/browser/ash/policy/core/device_local_account_browsertest.cc
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "chrome/browser/ash/policy/core/device_local_account.h" #include <stddef.h> @@ -28,6 +23,7 @@ #include "ash/system/session/logout_confirmation_controller.h" #include "ash/system/session/logout_confirmation_dialog.h" #include "base/command_line.h" +#include "base/compiler_specific.h" #include "base/files/file_path.h" #include "base/files/file_util.h" #include "base/functional/bind.h" @@ -587,7 +583,7 @@ session_locales_proto->mutable_value()->Clear(); for (size_t i = 0; i < array_size; ++i) { session_locales_proto->mutable_value()->add_entries( - recommended_locales[i]); + UNSAFE_TODO(recommended_locales[i])); } } @@ -1068,7 +1064,8 @@ em::StringListPolicyProto* startup_urls_proto = device_local_account_policy_.payload().mutable_restoreonstartupurls(); for (size_t i = 0; i < std::size(kStartupURLs); ++i) { - startup_urls_proto->mutable_value()->add_entries(kStartupURLs[i]); + startup_urls_proto->mutable_value()->add_entries( + UNSAFE_TODO(kStartupURLs[i])); } UploadAndInstallDeviceLocalAccountPolicy(); AddPublicSessionToDevicePolicy(kAccountId1); @@ -1089,8 +1086,8 @@ int expected_tab_count = static_cast<int>(std::size(kStartupURLs)); EXPECT_EQ(expected_tab_count, tabs->count()); for (int i = 0; i < expected_tab_count && i < tabs->count(); ++i) { - EXPECT_EQ(GURL(kStartupURLs[i]), - tabs->GetWebContentsAt(i)->GetVisibleURL()); + UNSAFE_TODO(EXPECT_EQ(GURL(kStartupURLs[i]), + tabs->GetWebContentsAt(i)->GetVisibleURL())); } // Verify that the session is not considered to be logged in with a GAIA @@ -1874,14 +1871,14 @@ // Verify that the list starts with the recommended locales, in correct order. for (size_t i = 0; i < std::size(kRecommendedLocales1); ++i) { - EXPECT_EQ(kRecommendedLocales1[i], locales[i].language_code); + UNSAFE_TODO(EXPECT_EQ(kRecommendedLocales1[i], locales[i].language_code)); } // Verify that the recommended locales do not appear again in the remainder of // the list. std::set<std::string> recommended_locales; for (size_t i = 0; i < std::size(kRecommendedLocales1); ++i) { - recommended_locales.insert(kRecommendedLocales1[i]); + recommended_locales.insert(UNSAFE_TODO(kRecommendedLocales1[i])); } for (size_t i = std::size(kRecommendedLocales1); i < locales.size(); ++i) { const std::string& locale = locales[i].language_code; @@ -1909,7 +1906,7 @@ EXPECT_LT(std::size(kRecommendedLocales2), locales.size()); for (size_t i = 0; i < std::size(kRecommendedLocales2); ++i) { const std::string& locale = locales[i].language_code; - EXPECT_EQ(kRecommendedLocales2[i], locale); + UNSAFE_TODO(EXPECT_EQ(kRecommendedLocales2[i], locale)); } // Verify that the first new recommended locale is selected.
diff --git a/chrome/browser/ash/policy/core/user_cloud_policy_manager_ash_browsertest.cc b/chrome/browser/ash/policy/core/user_cloud_policy_manager_ash_browsertest.cc index a6cbb1cb..85ce409 100644 --- a/chrome/browser/ash/policy/core/user_cloud_policy_manager_ash_browsertest.cc +++ b/chrome/browser/ash/policy/core/user_cloud_policy_manager_ash_browsertest.cc
@@ -2,16 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include <memory> #include <string> #include <utility> #include <vector> +#include "base/compiler_specific.h" #include "base/containers/flat_set.h" #include "base/values.h" #include "chrome/browser/ash/login/test/logged_in_user_mixin.h" @@ -196,8 +192,8 @@ const int expected_tab_count = static_cast<int>(std::size(kStartupURLs)); EXPECT_EQ(expected_tab_count, tabs->count()); for (int i = 0; i < expected_tab_count && i < tabs->count(); ++i) { - EXPECT_EQ(GURL(kStartupURLs[i]), - tabs->GetWebContentsAt(i)->GetVisibleURL()); + UNSAFE_TODO(EXPECT_EQ(GURL(kStartupURLs[i]), + tabs->GetWebContentsAt(i)->GetVisibleURL())); } // User should be marked as requiring policy.
diff --git a/chrome/browser/ash/policy/handlers/device_quirks_policy_browsertest.cc b/chrome/browser/ash/policy/handlers/device_quirks_policy_browsertest.cc index aec8e3b..fd20a45 100644 --- a/chrome/browser/ash/policy/handlers/device_quirks_policy_browsertest.cc +++ b/chrome/browser/ash/policy/handlers/device_quirks_policy_browsertest.cc
@@ -2,11 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - +#include "base/compiler_specific.h" #include "base/files/file_util.h" #include "base/functional/bind.h" #include "base/run_loop.h" @@ -44,8 +40,9 @@ // Create fake icc file. path = path.Append(quirks::IdToFileName(kProductId)); - bool all_written = base::WriteFile( - path, base::span<const uint8_t>(kFakeIccData, sizeof(kFakeIccData))); + bool all_written = + base::WriteFile(path, UNSAFE_TODO(base::span<const uint8_t>( + kFakeIccData, sizeof(kFakeIccData)))); ASSERT_TRUE(all_written); }
diff --git a/chrome/browser/ash/policy/off_hours/device_off_hours_controller_unittest.cc b/chrome/browser/ash/policy/off_hours/device_off_hours_controller_unittest.cc index 04cca2b..39ee908 100644 --- a/chrome/browser/ash/policy/off_hours/device_off_hours_controller_unittest.cc +++ b/chrome/browser/ash/policy/off_hours/device_off_hours_controller_unittest.cc
@@ -2,16 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "chrome/browser/ash/policy/off_hours/device_off_hours_controller.h" #include <string> #include <utility> +#include "base/compiler_specific.h" #include "base/logging.h" #include "base/memory/ptr_util.h" #include "base/test/power_monitor_test.h" @@ -78,9 +74,11 @@ em::WeeklyTimeIntervalProto interval_proto; em::WeeklyTimeProto* start = interval_proto.mutable_start(); em::WeeklyTimeProto* end = interval_proto.mutable_end(); - start->set_day_of_week(kWeekdays[weekly_time_interval.start().day_of_week()]); + start->set_day_of_week( + UNSAFE_TODO(kWeekdays[weekly_time_interval.start().day_of_week()])); start->set_time(weekly_time_interval.start().milliseconds()); - end->set_day_of_week(kWeekdays[weekly_time_interval.end().day_of_week()]); + end->set_day_of_week( + UNSAFE_TODO(kWeekdays[weekly_time_interval.end().day_of_week()])); end->set_time(weekly_time_interval.end().milliseconds()); return interval_proto; }
diff --git a/chrome/browser/ash/policy/off_hours/off_hours_policy_applier_unittest.cc b/chrome/browser/ash/policy/off_hours/off_hours_policy_applier_unittest.cc index ca05eab..fecb5f8 100644 --- a/chrome/browser/ash/policy/off_hours/off_hours_policy_applier_unittest.cc +++ b/chrome/browser/ash/policy/off_hours/off_hours_policy_applier_unittest.cc
@@ -2,15 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "chrome/browser/ash/policy/off_hours/off_hours_policy_applier.h" #include <utility> +#include "base/compiler_specific.h" #include "chromeos/ash/components/policy/weekly_time/weekly_time.h" #include "chromeos/ash/components/policy/weekly_time/weekly_time_interval.h" #include "components/policy/proto/chrome_device_policy.pb.h" @@ -58,9 +54,11 @@ em::WeeklyTimeIntervalProto interval_proto; em::WeeklyTimeProto* start = interval_proto.mutable_start(); em::WeeklyTimeProto* end = interval_proto.mutable_end(); - start->set_day_of_week(kWeekdays[weekly_time_interval.start().day_of_week()]); + start->set_day_of_week( + UNSAFE_TODO(kWeekdays[weekly_time_interval.start().day_of_week()])); start->set_time(weekly_time_interval.start().milliseconds()); - end->set_day_of_week(kWeekdays[weekly_time_interval.end().day_of_week()]); + end->set_day_of_week( + UNSAFE_TODO(kWeekdays[weekly_time_interval.end().day_of_week()])); end->set_time(weekly_time_interval.end().milliseconds()); return interval_proto; }
diff --git a/chrome/browser/ash/policy/off_hours/off_hours_proto_parser_unittest.cc b/chrome/browser/ash/policy/off_hours/off_hours_proto_parser_unittest.cc index 30977ba..2180068 100644 --- a/chrome/browser/ash/policy/off_hours/off_hours_proto_parser_unittest.cc +++ b/chrome/browser/ash/policy/off_hours/off_hours_proto_parser_unittest.cc
@@ -2,16 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "chrome/browser/ash/policy/off_hours/off_hours_proto_parser.h" #include <optional> #include <utility> +#include "base/compiler_specific.h" #include "base/test/simple_test_clock.h" #include "base/values.h" #include "chromeos/ash/components/policy/weekly_time/weekly_time.h" @@ -64,9 +60,11 @@ em::WeeklyTimeIntervalProto interval_proto; em::WeeklyTimeProto* start = interval_proto.mutable_start(); em::WeeklyTimeProto* end = interval_proto.mutable_end(); - start->set_day_of_week(kWeekdays[weekly_time_interval.start().day_of_week()]); + start->set_day_of_week( + UNSAFE_TODO(kWeekdays[weekly_time_interval.start().day_of_week()])); start->set_time(weekly_time_interval.start().milliseconds()); - end->set_day_of_week(kWeekdays[weekly_time_interval.end().day_of_week()]); + end->set_day_of_week( + UNSAFE_TODO(kWeekdays[weekly_time_interval.end().day_of_week()])); end->set_time(weekly_time_interval.end().milliseconds()); return interval_proto; }
diff --git a/chrome/browser/ash/policy/reporting/arc_app_install_event_log_manager_unittest.cc b/chrome/browser/ash/policy/reporting/arc_app_install_event_log_manager_unittest.cc index a1d7db5..9185e81 100644 --- a/chrome/browser/ash/policy/reporting/arc_app_install_event_log_manager_unittest.cc +++ b/chrome/browser/ash/policy/reporting/arc_app_install_event_log_manager_unittest.cc
@@ -2,17 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "chrome/browser/ash/policy/reporting/arc_app_install_event_log_manager.h" #include <iterator> #include <map> #include <vector> +#include "base/compiler_specific.h" #include "base/files/file_path.h" #include "base/files/file_util.h" #include "base/json/json_string_value_serializer.h" @@ -206,9 +202,9 @@ void AddLogEntry(int app_index) { ASSERT_GE(app_index, 0); ASSERT_LT(app_index, static_cast<int>(std::size(kPackageNames))); - const std::string package_name = kPackageNames[app_index]; + const std::string package_name = UNSAFE_TODO(kPackageNames[app_index]); events_[package_name].push_back(event_); - manager_->Add({kPackageNames[app_index]}, event_); + manager_->Add({UNSAFE_TODO(kPackageNames[app_index])}, event_); FlushNonDelayedTasks(); event_.set_timestamp(event_.timestamp() + 1000); }
diff --git a/chrome/browser/ash/policy/reporting/arc_app_install_event_log_unittest.cc b/chrome/browser/ash/policy/reporting/arc_app_install_event_log_unittest.cc index c576f8b..a96920df 100644 --- a/chrome/browser/ash/policy/reporting/arc_app_install_event_log_unittest.cc +++ b/chrome/browser/ash/policy/reporting/arc_app_install_event_log_unittest.cc
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "chrome/browser/ash/policy/reporting/arc_app_install_event_log.h" #include <stddef.h> @@ -15,6 +10,7 @@ #include <memory> #include <sstream> +#include "base/compiler_specific.h" #include "base/files/file.h" #include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h" @@ -483,12 +479,13 @@ file_name_, base::File::FLAG_OPEN | base::File::FLAG_READ | base::File::FLAG_WRITE); int64_t version; - EXPECT_EQ(static_cast<ssize_t>(sizeof(version)), - file->Read(0, reinterpret_cast<char*>(&version), sizeof(version))); - --version; - EXPECT_EQ( + UNSAFE_TODO(EXPECT_EQ( static_cast<ssize_t>(sizeof(version)), - file->Write(0, reinterpret_cast<const char*>(&version), sizeof(version))); + file->Read(0, reinterpret_cast<char*>(&version), sizeof(version)))); + --version; + UNSAFE_TODO(EXPECT_EQ(static_cast<ssize_t>(sizeof(version)), + file->Write(0, reinterpret_cast<const char*>(&version), + sizeof(version)))); file.reset(); ArcAppInstallEventLog log(file_name_);
diff --git a/chrome/browser/ash/policy/reporting/metrics_reporting/fatal_crash/fatal_crash_events_observer_unittest.cc b/chrome/browser/ash/policy/reporting/metrics_reporting/fatal_crash/fatal_crash_events_observer_unittest.cc index aff1ff8..08e4a58 100644 --- a/chrome/browser/ash/policy/reporting/metrics_reporting/fatal_crash/fatal_crash_events_observer_unittest.cc +++ b/chrome/browser/ash/policy/reporting/metrics_reporting/fatal_crash/fatal_crash_events_observer_unittest.cc
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "chrome/browser/ash/policy/reporting/metrics_reporting/fatal_crash/fatal_crash_events_observer.h" #include <atomic> @@ -19,6 +14,7 @@ #include <vector> #include "ash/test/ash_test_base.h" +#include "base/compiler_specific.h" #include "base/files/file_path.h" #include "base/files/file_util.h" #include "base/memory/scoped_refptr.h" @@ -638,7 +634,7 @@ .session_type = FatalCrashTelemetry::SESSION_TYPE_GUEST}}; for (size_t i = 0; i < std::size(kSessionTypes); ++i) { - SimulateUserLogin(kUserEmail, kSessionTypes[i].user_type, + SimulateUserLogin(kUserEmail, UNSAFE_TODO(kSessionTypes[i]).user_type, is_user_affiliated()); auto crash_event_info = NewCrashEventInfo(is_uploaded()); if (is_uploaded()) { @@ -652,8 +648,8 @@ const auto fatal_crash_telemetry = WaitForFatalCrashTelemetry(std::move(crash_event_info)); ASSERT_TRUE(fatal_crash_telemetry.has_session_type()); - EXPECT_EQ(fatal_crash_telemetry.session_type(), - kSessionTypes[i].session_type); + UNSAFE_TODO(EXPECT_EQ(fatal_crash_telemetry.session_type(), + kSessionTypes[i].session_type)); ClearLogin(); } }
diff --git a/chrome/browser/ash/policy/reporting/single_install_event_log.h b/chrome/browser/ash/policy/reporting/single_install_event_log.h index 792fbd6..e583843f 100644 --- a/chrome/browser/ash/policy/reporting/single_install_event_log.h +++ b/chrome/browser/ash/policy/reporting/single_install_event_log.h
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #ifndef CHROME_BROWSER_ASH_POLICY_REPORTING_SINGLE_INSTALL_EVENT_LOG_H_ #define CHROME_BROWSER_ASH_POLICY_REPORTING_SINGLE_INSTALL_EVENT_LOG_H_ @@ -17,6 +12,7 @@ #include <memory> #include <string> +#include "base/compiler_specific.h" #include "base/containers/heap_array.h" #include "base/containers/span.h" #include "base/files/file.h" @@ -179,14 +175,15 @@ base::HeapArray<char>* package_buffer) { if (!file->IsValid()) return false; - if (file->ReadAtCurrentPos(reinterpret_cast<char*>(size), sizeof(*size)) != - sizeof(*size) || + if (UNSAFE_TODO(file->ReadAtCurrentPos(reinterpret_cast<char*>(size), + sizeof(*size))) != sizeof(*size) || *size < 0 || *size > kMaxBufferSize) { return false; } *package_buffer = base::HeapArray<char>::Uninit(*size); - if (file->ReadAtCurrentPos((*package_buffer).data(), *size) != *size) { + if (UNSAFE_TODO(file->ReadAtCurrentPos((*package_buffer).data(), *size)) != + *size) { return false; } return true; @@ -197,20 +194,21 @@ base::File* file, SingleInstallEventLog<T>* log) { int64_t incomplete; - if (file->ReadAtCurrentPos(reinterpret_cast<char*>(&incomplete), - sizeof(incomplete)) != sizeof(incomplete)) { + if (UNSAFE_TODO(file->ReadAtCurrentPos(reinterpret_cast<char*>(&incomplete), + sizeof(incomplete))) != + sizeof(incomplete)) { return false; } log->incomplete_ = incomplete; ssize_t entries; - if (file->ReadAtCurrentPos(reinterpret_cast<char*>(&entries), - sizeof(entries)) != sizeof(entries)) { + if (UNSAFE_TODO(file->ReadAtCurrentPos(reinterpret_cast<char*>(&entries), + sizeof(entries))) != sizeof(entries)) { return false; } for (ssize_t i = 0; i < entries; ++i) { ssize_t size; - if (file->ReadAtCurrentPos(reinterpret_cast<char*>(&size), sizeof(size)) != - sizeof(size) || + if (UNSAFE_TODO(file->ReadAtCurrentPos(reinterpret_cast<char*>(&size), + sizeof(size))) != sizeof(size) || size < 0 || size > kMaxBufferSize) { log->incomplete_ = true; return false; @@ -224,7 +222,7 @@ } auto buffer = base::HeapArray<char>::Uninit(size); - if (file->ReadAtCurrentPos(buffer.data(), size) != size) { + if (UNSAFE_TODO(file->ReadAtCurrentPos(buffer.data(), size)) != size) { log->incomplete_ = true; return false; }
diff --git a/chrome/browser/ash/policy/reporting/single_install_event_log_fuzzer.cc b/chrome/browser/ash/policy/reporting/single_install_event_log_fuzzer.cc index 75983906..be71e6b 100644 --- a/chrome/browser/ash/policy/reporting/single_install_event_log_fuzzer.cc +++ b/chrome/browser/ash/policy/reporting/single_install_event_log_fuzzer.cc
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include <stddef.h> #include <stdint.h> #include <unistd.h> @@ -15,6 +10,7 @@ #include "base/check.h" #include "base/check_op.h" +#include "base/compiler_specific.h" #include "base/files/file.h" #include "base/files/scoped_file.h" #include "base/logging.h" @@ -32,8 +28,8 @@ base::File pipe_read_end = base::File(base::ScopedFD(pipefd[0])); base::File pipe_write_end = base::File(base::ScopedFD(pipefd[1])); if (size) { - CHECK(pipe_write_end.WriteAtCurrentPos(reinterpret_cast<const char*>(data), - size)); + UNSAFE_TODO(CHECK(pipe_write_end.WriteAtCurrentPos( + reinterpret_cast<const char*>(data), size))); } return pipe_read_end; }
diff --git a/chrome/browser/ash/policy/skyvault/migration_coordinator.cc b/chrome/browser/ash/policy/skyvault/migration_coordinator.cc index e15062b..6aa53a6 100644 --- a/chrome/browser/ash/policy/skyvault/migration_coordinator.cc +++ b/chrome/browser/ash/policy/skyvault/migration_coordinator.cc
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "chrome/browser/ash/policy/skyvault/migration_coordinator.h" #include <memory> @@ -14,6 +9,7 @@ #include "base/base_paths.h" #include "base/check_is_test.h" +#include "base/compiler_specific.h" #include "base/files/file_path.h" #include "base/files/file_util.h" #include "base/functional/bind.h" @@ -128,7 +124,8 @@ std::string log_entry = absl::StrFormat("%s - %s\n", file_path.AsUTF8Unsafe(), FormatErrorMessage(destination, error)); - error_log_file.WriteAtCurrentPos(log_entry.c_str(), log_entry.size()); + UNSAFE_TODO( + error_log_file.WriteAtCurrentPos(log_entry.c_str(), log_entry.size())); } } // namespace
diff --git a/chrome/browser/ash/policy/status_collector/child_status_collector_unittest.cc b/chrome/browser/ash/policy/status_collector/child_status_collector_unittest.cc index d69ea7a..24ba5659 100644 --- a/chrome/browser/ash/policy/status_collector/child_status_collector_unittest.cc +++ b/chrome/browser/ash/policy/status_collector/child_status_collector_unittest.cc
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "chrome/browser/ash/policy/status_collector/child_status_collector.h" #include <stddef.h> @@ -17,6 +12,7 @@ #include <utility> #include <vector> +#include "base/compiler_specific.h" #include "base/environment.h" #include "base/functional/bind.h" #include "base/functional/callback.h" @@ -251,7 +247,7 @@ void SimulateStateChanges(DeviceStateTransitions* states, int len) { for (int i = 0; i < len; i++) { - switch (states[i]) { + switch (UNSAFE_TODO(states[i])) { case DeviceStateTransitions::kEnterIdleState: { power_manager::ScreenIdleState state; state.set_off(true);
diff --git a/chrome/browser/ash/policy/status_collector/device_status_collector.cc b/chrome/browser/ash/policy/status_collector/device_status_collector.cc index 44a7097..39a1f99 100644 --- a/chrome/browser/ash/policy/status_collector/device_status_collector.cc +++ b/chrome/browser/ash/policy/status_collector/device_status_collector.cc
@@ -2,11 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "chrome/browser/ash/policy/status_collector/device_status_collector.h" #include <inttypes.h> @@ -31,6 +26,7 @@ #include "ash/constants/ash_features.h" #include "base/check.h" #include "base/check_op.h" +#include "base/compiler_specific.h" #include "base/containers/circular_deque.h" #include "base/files/file_enumerator.h" #include "base/files/file_util.h" @@ -281,7 +277,8 @@ std::string temperature_string; int32_t temperature = 0; if (base::ReadFileToString(temperature_path, &temperature_string) && - sscanf(temperature_string.c_str(), "%d", &temperature) == 1) { + UNSAFE_TODO(sscanf(temperature_string.c_str(), "%d", &temperature)) == + 1) { has_data = true; // CPU temp in millidegree Celsius to Celsius temperature /= 1000; @@ -2062,9 +2059,9 @@ // We only care about the first four numbers: user_time, nice_time, // sys_time, and idle_time. uint64_t user = 0, nice = 0, system = 0, idle = 0; - int vals = sscanf(stats.c_str(), - "cpu %" SCNu64 " %" SCNu64 " %" SCNu64 " %" SCNu64, &user, - &nice, &system, &idle); + int vals = UNSAFE_TODO(sscanf( + stats.c_str(), "cpu %" SCNu64 " %" SCNu64 " %" SCNu64 " %" SCNu64, + &user, &nice, &system, &idle)); DCHECK_EQ(4, vals); // The values returned from /proc/stat are cumulative totals, so calculate @@ -2418,7 +2415,8 @@ // Determine the type enum constant for |device|. size_t type_idx = 0; for (; type_idx < std::size(kDeviceTypeMap); ++type_idx) { - if ((*device)->type() == kDeviceTypeMap[type_idx].type_string) { + if ((*device)->type() == + UNSAFE_TODO(kDeviceTypeMap[type_idx]).type_string) { break; } } @@ -2430,7 +2428,7 @@ } em::NetworkInterface* interface = status->add_network_interfaces(); - interface->set_type(kDeviceTypeMap[type_idx].type_constant); + interface->set_type(UNSAFE_TODO(kDeviceTypeMap[type_idx]).type_constant); if (!(*device)->mac_address().empty()) { interface->set_mac_address((*device)->mac_address()); } @@ -2513,8 +2511,10 @@ em::NetworkState::UNKNOWN; const std::string connection_state_string(state->connection_state()); for (size_t i = 0; i < std::size(kConnectionStateMap); ++i) { - if (connection_state_string == kConnectionStateMap[i].state_string) { - connection_state_enum = kConnectionStateMap[i].state_constant; + if (connection_state_string == + UNSAFE_TODO(kConnectionStateMap[i]).state_string) { + connection_state_enum = + UNSAFE_TODO(kConnectionStateMap[i]).state_constant; break; } }
diff --git a/chrome/browser/ash/power/auto_screen_brightness/light_samples_observer_unittest.cc b/chrome/browser/ash/power/auto_screen_brightness/light_samples_observer_unittest.cc index 8b8e839..906b369 100644 --- a/chrome/browser/ash/power/auto_screen_brightness/light_samples_observer_unittest.cc +++ b/chrome/browser/ash/power/auto_screen_brightness/light_samples_observer_unittest.cc
@@ -2,16 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "chrome/browser/ash/power/auto_screen_brightness/light_samples_observer.h" #include <memory> #include <utility> +#include "base/compiler_specific.h" #include "base/functional/bind.h" #include "base/run_loop.h" #include "base/test/metrics/histogram_tester.h" @@ -46,7 +42,7 @@ if (is_color_sensor) { for (size_t i = 0; i < std::size(kIlluminanceColorChannels); ++i) { - illuminance_data.id = kIlluminanceColorChannels[i]; + illuminance_data.id = UNSAFE_TODO(kIlluminanceColorChannels[i]); illuminance_data.sample_data = kFakeColorSampleData; channels_data.push_back(std::move(illuminance_data)); }
diff --git a/chrome/browser/ash/system_logs/single_log_file_log_source.cc b/chrome/browser/ash/system_logs/single_log_file_log_source.cc index f3f3707..8f57e93 100644 --- a/chrome/browser/ash/system_logs/single_log_file_log_source.cc +++ b/chrome/browser/ash/system_logs/single_log_file_log_source.cc
@@ -2,13 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "chrome/browser/ash/system_logs/single_log_file_log_source.h" +#include "base/compiler_specific.h" #include "base/files/file_path.h" #include "base/files/file_util.h" #include "base/functional/bind.h" @@ -173,7 +169,7 @@ std::string new_result_string; new_result_string.resize(size_to_read); size_t size_read = - file_.ReadAtCurrentPos(&new_result_string[0], size_to_read); + UNSAFE_TODO(file_.ReadAtCurrentPos(&new_result_string[0], size_to_read)); new_result_string.resize(size_read); const bool file_was_rotated = file_inode_ != GetInodeValue(GetLogFilePath());
diff --git a/chrome/browser/ash/system_web_apps/apps/help_app/help_app_integration_browsertest.cc b/chrome/browser/ash/system_web_apps/apps/help_app/help_app_integration_browsertest.cc index 8ea9c596..126484cd 100644 --- a/chrome/browser/ash/system_web_apps/apps/help_app/help_app_integration_browsertest.cc +++ b/chrome/browser/ash/system_web_apps/apps/help_app/help_app_integration_browsertest.cc
@@ -750,7 +750,7 @@ // There should be only be one regular browser with one tab. EXPECT_EQ(1u, chrome::GetTotalBrowserCount()); - EXPECT_EQ(1, browser()->tab_strip_model()->GetTabCount()); + EXPECT_EQ(1, browser()->tab_strip_model()->count()); WaitForTestSystemAppInstall(); content::WebContents* web_contents = LaunchApp(SystemWebAppType::HELP); @@ -782,7 +782,7 @@ // There should still be two browser windows. EXPECT_EQ(2u, chrome::GetTotalBrowserCount()); // The regular browser should only have 2 tabs. - EXPECT_EQ(2, browser()->tab_strip_model()->GetTabCount()); + EXPECT_EQ(2, browser()->tab_strip_model()->count()); // After opening the URL, the regular browser should be the most recently // active browser. EXPECT_EQ(browser(), chrome::FindLastActive()); @@ -802,7 +802,7 @@ // There should be only be one regular browser with one tab. EXPECT_EQ(1u, chrome::GetTotalBrowserCount()); - EXPECT_EQ(1, browser()->tab_strip_model()->GetTabCount()); + EXPECT_EQ(1, browser()->tab_strip_model()->count()); WaitForTestSystemAppInstall(); content::WebContents* web_contents = LaunchApp(SystemWebAppType::HELP); @@ -836,7 +836,7 @@ // There should still be two browser windows. EXPECT_EQ(2u, chrome::GetTotalBrowserCount()); // The regular browser should only have 2 tabs. - EXPECT_EQ(2, browser()->tab_strip_model()->GetTabCount()); + EXPECT_EQ(2, browser()->tab_strip_model()->count()); // After opening the URL, the regular browser should be the most recently // active browser. EXPECT_EQ(browser(), chrome::FindLastActive()); @@ -855,7 +855,7 @@ // There should be only be one regular browser with one tab. EXPECT_EQ(1u, chrome::GetTotalBrowserCount()); // The regular browser should only have 1 tab. - EXPECT_EQ(1, browser()->tab_strip_model()->GetTabCount()); + EXPECT_EQ(1, browser()->tab_strip_model()->count()); // The tab should be the default "about:blank" URL. EXPECT_TRUE(GetActiveWebContents()->GetVisibleURL().IsAboutBlank()); @@ -906,7 +906,7 @@ // There should only be 1 regular browser. EXPECT_EQ(1u, chrome::GetTotalBrowserCount()); // The regular browser should still only have 1 tab. - EXPECT_EQ(1, browser()->tab_strip_model()->GetTabCount()); + EXPECT_EQ(1, browser()->tab_strip_model()->count()); // The tab should still be the default "about:blank" URL. EXPECT_TRUE(GetActiveWebContents()->GetVisibleURL().IsAboutBlank()); }
diff --git a/chrome/browser/ash/tether/fake_tether_service.cc b/chrome/browser/ash/tether/fake_tether_service.cc index c3280dd5..f2ac285 100644 --- a/chrome/browser/ash/tether/fake_tether_service.cc +++ b/chrome/browser/ash/tether/fake_tether_service.cc
@@ -2,13 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "chrome/browser/ash/tether/fake_tether_service.h" +#include "base/compiler_specific.h" #include "base/strings/string_number_conversions.h" namespace ash { @@ -53,7 +49,8 @@ void FakeTetherService::StopTetherIfNecessary() { for (int i = 0; i < num_tether_networks_; ++i) { - network_state_handler()->RemoveTetherNetworkState(kTetherGuidPrefix + i); + network_state_handler()->RemoveTetherNetworkState( + UNSAFE_TODO(kTetherGuidPrefix + i)); } }
diff --git a/chrome/browser/autofill/android/BUILD.gn b/chrome/browser/autofill/android/BUILD.gn index 2757c0b93..c7c00f8 100644 --- a/chrome/browser/autofill/android/BUILD.gn +++ b/chrome/browser/autofill/android/BUILD.gn
@@ -82,7 +82,6 @@ "//chrome/browser/preferences:java", "//chrome/browser/profiles/android:java", "//chrome/browser/settings:java", - "//chrome/browser/settings:search_java", "//chrome/browser/signin/services/android:java", "//chrome/browser/sync/android:java", "//chrome/browser/ui/android/edge_to_edge:java",
diff --git a/chrome/browser/autofill/android/java/src/org/chromium/chrome/browser/autofill/options/AutofillOptionsFragment.java b/chrome/browser/autofill/android/java/src/org/chromium/chrome/browser/autofill/options/AutofillOptionsFragment.java index c0efcbb..dfb75fc 100644 --- a/chrome/browser/autofill/android/java/src/org/chromium/chrome/browser/autofill/options/AutofillOptionsFragment.java +++ b/chrome/browser/autofill/android/java/src/org/chromium/chrome/browser/autofill/options/AutofillOptionsFragment.java
@@ -20,7 +20,7 @@ import org.chromium.build.annotations.Nullable; import org.chromium.chrome.browser.autofill.R; import org.chromium.chrome.browser.settings.ChromeBaseSettingsFragment; -import org.chromium.chrome.browser.settings.search.BaseSearchIndexProvider; +import org.chromium.chrome.browser.settings.search.ChromeBaseSearchIndexProvider; import org.chromium.components.browser_ui.settings.SettingsFragment; import org.chromium.components.browser_ui.settings.SettingsUtils; import org.chromium.components.browser_ui.settings.TextMessagePreference; @@ -176,7 +176,7 @@ return "autofill_options"; } - public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = - new BaseSearchIndexProvider( + public static final ChromeBaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = + new ChromeBaseSearchIndexProvider( AutofillOptionsFragment.class.getName(), R.xml.autofill_options_preferences); }
diff --git a/chrome/browser/browser_process_impl.cc b/chrome/browser/browser_process_impl.cc index 3cf8d49..2a0e7ed 100644 --- a/chrome/browser/browser_process_impl.cc +++ b/chrome/browser/browser_process_impl.cc
@@ -301,13 +301,20 @@ active_primary_accounts_metrics_recorder_( std::make_unique<signin::ActivePrimaryAccountsMetricsRecorder>( *local_state_)), - platform_part_(std::make_unique<BrowserProcessPlatformPart>()) { + platform_part_(std::make_unique<BrowserProcessPlatformPart>()), + network_time_tracker_(startup_data->chrome_feature_list_creator() + ->TakeNetworkTimeTracker()) { CHECK(!g_browser_process); g_browser_process = this; DCHECK(browser_policy_connector_); DCHECK(local_state_); DCHECK(startup_data); + + // The network time tracker is created (so that other early objects can + // subscribe to it) but it is not yet initialized. + CHECK(network_time_tracker_); + // Most work should be done in Init(). } @@ -1094,7 +1101,6 @@ } network_time::NetworkTimeTracker* BrowserProcessImpl::network_time_tracker() { - CreateNetworkTimeTracker(); return network_time_tracker_.get(); } @@ -1456,7 +1462,7 @@ platform_part_->PreMainMessageLoopRun(); - CreateNetworkTimeTracker(); + InitializeNetworkTimeTracker(); CreateNetworkQualityObserver(); @@ -1627,15 +1633,11 @@ } #endif // !BUILDFLAG(IS_ANDROID) -void BrowserProcessImpl::CreateNetworkTimeTracker() { - if (network_time_tracker_) { - return; - } - network_time_tracker_ = std::make_unique<network_time::NetworkTimeTracker>( - base::WrapUnique(new base::DefaultClock()), - base::WrapUnique(new base::DefaultTickClock()), local_state(), - system_network_context_manager()->GetSharedURLLoaderFactory(), - std::nullopt); +void BrowserProcessImpl::InitializeNetworkTimeTracker() { + CHECK(!network_time_tracker_->is_initialized()); + network_time_tracker_->Initialize( + local_state(), + system_network_context_manager()->GetSharedURLLoaderFactory()); } void BrowserProcessImpl::ApplyDefaultBrowserPolicy() {
diff --git a/chrome/browser/browser_process_impl.h b/chrome/browser/browser_process_impl.h index 947fad5..71f268c 100644 --- a/chrome/browser/browser_process_impl.h +++ b/chrome/browser/browser_process_impl.h
@@ -269,7 +269,7 @@ void CreateStatusTray(); void CreateBackgroundModeManager(); void CreateGCMDriver(); - void CreateNetworkTimeTracker(); + void InitializeNetworkTimeTracker(); void ApplyDefaultBrowserPolicy();
diff --git a/chrome/browser/browser_process_platform_part_ash_browsertest.cc b/chrome/browser/browser_process_platform_part_ash_browsertest.cc index e1229c6..9e03201 100644 --- a/chrome/browser/browser_process_platform_part_ash_browsertest.cc +++ b/chrome/browser/browser_process_platform_part_ash_browsertest.cc
@@ -125,7 +125,7 @@ EXPECT_NO_FATAL_FAILURE( WaitForLoadStopForBrowserWindowInterface(new_browser)); auto* const tab_strip_model = new_browser->GetTabStripModel(); - EXPECT_EQ(1, tab_strip_model->GetTabCount()); + EXPECT_EQ(1, tab_strip_model->count()); EXPECT_EQ(GURL(url::kAboutBlankURL), tab_strip_model->GetWebContentsAt(0)->GetVisibleURL()); } @@ -177,7 +177,7 @@ EXPECT_NO_FATAL_FAILURE( WaitForLoadStopForBrowserWindowInterface(pref_urls_opened_browser)); tab_strip_model = pref_urls_opened_browser->GetTabStripModel(); - EXPECT_EQ(3, tab_strip_model->GetTabCount()); + EXPECT_EQ(3, tab_strip_model->count()); EXPECT_EQ(restore_url_1, tab_strip_model->GetWebContentsAt(0)->GetVisibleURL()); EXPECT_EQ(restore_url_2, @@ -194,7 +194,7 @@ EXPECT_NO_FATAL_FAILURE( WaitForLoadStopForBrowserWindowInterface(new_browser)); tab_strip_model = new_browser->GetTabStripModel(); - EXPECT_EQ(1, tab_strip_model->GetTabCount()); + EXPECT_EQ(1, tab_strip_model->count()); EXPECT_EQ(GURL(chrome::kChromeUINewTabURL), tab_strip_model->GetWebContentsAt(0)->GetVisibleURL()); } @@ -267,7 +267,7 @@ EXPECT_NO_FATAL_FAILURE( WaitForLoadStopForBrowserWindowInterface(pref_urls_opened_browser)); tab_strip_model = pref_urls_opened_browser->GetTabStripModel(); - EXPECT_EQ(3, tab_strip_model->GetTabCount()); + EXPECT_EQ(3, tab_strip_model->count()); EXPECT_EQ(restore_url_1, tab_strip_model->GetWebContentsAt(0)->GetVisibleURL()); EXPECT_EQ(restore_url_2, @@ -284,7 +284,7 @@ EXPECT_NO_FATAL_FAILURE( WaitForLoadStopForBrowserWindowInterface(new_browser)); tab_strip_model = new_browser->GetTabStripModel(); - EXPECT_EQ(1, tab_strip_model->GetTabCount()); + EXPECT_EQ(1, tab_strip_model->count()); EXPECT_EQ(GURL(chrome::kChromeUINewTabURL), tab_strip_model->GetWebContentsAt(0)->GetVisibleURL()); }
diff --git a/chrome/browser/commerce/android/java/src/org/chromium/chrome/browser/commerce/PriceNotificationSettingsFragment.java b/chrome/browser/commerce/android/java/src/org/chromium/chrome/browser/commerce/PriceNotificationSettingsFragment.java index 579736a..b907501 100644 --- a/chrome/browser/commerce/android/java/src/org/chromium/chrome/browser/commerce/PriceNotificationSettingsFragment.java +++ b/chrome/browser/commerce/android/java/src/org/chromium/chrome/browser/commerce/PriceNotificationSettingsFragment.java
@@ -26,6 +26,7 @@ import org.chromium.chrome.browser.preferences.Pref; import org.chromium.chrome.browser.preferences.PrefServiceUtil; import org.chromium.chrome.browser.settings.ChromeBaseSettingsFragment; +import org.chromium.chrome.browser.settings.search.ChromeBaseSearchIndexProvider; import org.chromium.chrome.browser.signin.services.IdentityServicesProvider; import org.chromium.components.browser_ui.notifications.BaseNotificationManagerProxyFactory; import org.chromium.components.browser_ui.notifications.NotificationProxyUtils; @@ -203,4 +204,10 @@ public @AnimationType int getAnimationType() { return AnimationType.PROPERTY; } + + // TODO(crbug.com/444470792): Determine what pieces of logic are dynamic and need handling. + public static final ChromeBaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = + new ChromeBaseSearchIndexProvider( + PriceNotificationSettingsFragment.class.getName(), + R.xml.price_notification_preferences); }
diff --git a/chrome/browser/contextual_tasks/contextual_tasks_composebox_handler.cc b/chrome/browser/contextual_tasks/contextual_tasks_composebox_handler.cc index 181adab..113060e 100644 --- a/chrome/browser/contextual_tasks/contextual_tasks_composebox_handler.cc +++ b/chrome/browser/contextual_tasks/contextual_tasks_composebox_handler.cc
@@ -120,6 +120,11 @@ ContextualSearchWebContentsHelper::GetOrCreateForWebContents( web_ui_controller_->GetWebUIWebContents()); contextual_search_web_contents_helper->session_handle()) { + // If there is an auto-added tab, the user sending the query means we should + // upload it. + UploadSnapshotTabContextIfPresent(); + + // Create a client to aim message and send it to the page. auto create_client_to_aim_request_info = std::make_unique<contextual_search::ContextualSearchContextController:: CreateClientToAimRequestInfo>();
diff --git a/chrome/browser/devtools/global_confirm_info_bar_browsertest.cc b/chrome/browser/devtools/global_confirm_info_bar_browsertest.cc index dd7bf96..7d22c72 100644 --- a/chrome/browser/devtools/global_confirm_info_bar_browsertest.cc +++ b/chrome/browser/devtools/global_confirm_info_bar_browsertest.cc
@@ -85,7 +85,7 @@ } // Returns the number of tabs in the current window. - int GetTabCount() { return browser()->tab_strip_model()->GetTabCount(); } + int GetTabCount() { return browser()->tab_strip_model()->count(); } #endif // BUILDFLAG(IS_ANDROID) };
diff --git a/chrome/browser/educational_tip/java/src/org/chromium/chrome/browser/educational_tip/EducationTipModuleActionDelegate.java b/chrome/browser/educational_tip/java/src/org/chromium/chrome/browser/educational_tip/EducationTipModuleActionDelegate.java index e0d515cb..26c445996 100644 --- a/chrome/browser/educational_tip/java/src/org/chromium/chrome/browser/educational_tip/EducationTipModuleActionDelegate.java +++ b/chrome/browser/educational_tip/java/src/org/chromium/chrome/browser/educational_tip/EducationTipModuleActionDelegate.java
@@ -50,7 +50,7 @@ /** * Returns the total number of tabs for relaunch across both regular and incognito browsing - * modes through shared preference key. + * modes from persisted state. */ - int getTabCountForRelaunchFromSharedPrefs(); + int getTabCountForRelaunchFromPersistentStore(); }
diff --git a/chrome/browser/educational_tip/java/src/org/chromium/chrome/browser/educational_tip/EducationalTipCardProviderSignalHandler.java b/chrome/browser/educational_tip/java/src/org/chromium/chrome/browser/educational_tip/EducationalTipCardProviderSignalHandler.java index acb98ee0..cb91208 100644 --- a/chrome/browser/educational_tip/java/src/org/chromium/chrome/browser/educational_tip/EducationalTipCardProviderSignalHandler.java +++ b/chrome/browser/educational_tip/java/src/org/chromium/chrome/browser/educational_tip/EducationalTipCardProviderSignalHandler.java
@@ -156,7 +156,7 @@ return normalModel.getCount() + incognitoModel.getCount(); } - return actionDelegate.getTabCountForRelaunchFromSharedPrefs(); + return actionDelegate.getTabCountForRelaunchFromPersistentStore(); } /** Returns a value of 1.0f if a synced tab group exists. Otherwise, it returns 0.0f. */
diff --git a/chrome/browser/educational_tip/junit/src/org/chromium/chrome/browser/educational_tip/EducationalTipCardProviderSignalHandlerUnitTest.java b/chrome/browser/educational_tip/junit/src/org/chromium/chrome/browser/educational_tip/EducationalTipCardProviderSignalHandlerUnitTest.java index d99ad95..0f3dd0e6 100644 --- a/chrome/browser/educational_tip/junit/src/org/chromium/chrome/browser/educational_tip/EducationalTipCardProviderSignalHandlerUnitTest.java +++ b/chrome/browser/educational_tip/junit/src/org/chromium/chrome/browser/educational_tip/EducationalTipCardProviderSignalHandlerUnitTest.java
@@ -278,13 +278,13 @@ // Test cases when tab state is not initialized. when(mTabModelSelector.isTabStateInitialized()).thenReturn(false); - when(mActionDelegate.getTabCountForRelaunchFromSharedPrefs()).thenReturn(10); + when(mActionDelegate.getTabCountForRelaunchFromPersistentStore()).thenReturn(10); inputContext = EducationalTipCardProviderSignalHandler.createInputContext( ModuleType.TAB_GROUP_PROMO, mActionDelegate, mProfile, mTracker); assertEquals(10, inputContext.getEntryValue("number_of_tabs").floatValue, 0.01); - when(mActionDelegate.getTabCountForRelaunchFromSharedPrefs()).thenReturn(15); + when(mActionDelegate.getTabCountForRelaunchFromPersistentStore()).thenReturn(15); inputContext = EducationalTipCardProviderSignalHandler.createInputContext( ModuleType.TAB_GROUP_PROMO, mActionDelegate, mProfile, mTracker);
diff --git a/chrome/browser/enterprise/idle/action.cc b/chrome/browser/enterprise/idle/action.cc index 396ff373..14f4c7c 100644 --- a/chrome/browser/enterprise/idle/action.cc +++ b/chrome/browser/enterprise/idle/action.cc
@@ -309,7 +309,7 @@ if (model->profile() != profile) { return true; } - for (int i = 0; i < model->GetTabCount(); i++) { + for (int i = 0; i < model->count(); i++) { model->GetWebContentsAt(i)->GetController().Reload( content::ReloadType::NORMAL, /*check_for_repost=*/true);
diff --git a/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl_unittest.cc b/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl_unittest.cc index 78b4db7..1f7cb0a88 100644 --- a/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl_unittest.cc +++ b/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl_unittest.cc
@@ -2271,7 +2271,10 @@ EXPECT_THAT(profile_store_->stored_passwords(), testing::SizeIs(1)); EXPECT_THAT(account_store_->stored_passwords(), testing::SizeIs(1)); - EXPECT_THAT(passkey_model->GetAllPasskeys(), SizeIs(1)); + EXPECT_THAT(passkey_model->GetPasskeys( + webauthn::PasskeyModel::AnyRp(), + webauthn::PasskeyModel::ShadowedCredentials::kInclude), + SizeIs(1)); ExpectAuthentication(delegate, /*successful=*/true); base::MockCallback<base::OnceCallback<void(bool)>> callback; @@ -2280,7 +2283,10 @@ task_environment()->RunUntilIdle(); EXPECT_THAT(profile_store_->stored_passwords(), testing::IsEmpty()); EXPECT_THAT(account_store_->stored_passwords(), testing::IsEmpty()); - EXPECT_THAT(passkey_model->GetAllPasskeys(), testing::IsEmpty()); + EXPECT_THAT(passkey_model->GetPasskeys( + webauthn::PasskeyModel::AnyRp(), + webauthn::PasskeyModel::ShadowedCredentials::kInclude), + IsEmpty()); } TEST_F(PasswordsPrivateDelegateImplTest, @@ -2332,7 +2338,10 @@ task_environment()->RunUntilIdle(); EXPECT_THAT(profile_store_->stored_passwords(), testing::SizeIs(1)); EXPECT_THAT(account_store_->stored_passwords(), testing::SizeIs(1)); - EXPECT_THAT(passkey_model->GetAllPasskeys(), SizeIs(1)); + EXPECT_THAT(passkey_model->GetPasskeys( + webauthn::PasskeyModel::AnyRp(), + webauthn::PasskeyModel::ShadowedCredentials::kInclude), + SizeIs(1)); } #endif
diff --git a/chrome/browser/extensions/api/proxy/proxy_apitest.cc b/chrome/browser/extensions/api/proxy/proxy_apitest.cc index 66523c3..82984c0 100644 --- a/chrome/browser/extensions/api/proxy/proxy_apitest.cc +++ b/chrome/browser/extensions/api/proxy/proxy_apitest.cc
@@ -48,8 +48,6 @@ ASSERT_TRUE(pref != nullptr); EXPECT_TRUE(pref->IsExtensionControlled()); - // TODO(https://crbug.com/1348219) This should call - // `PrefService::GetDict`. ProxyConfigDictionary dict( pref_service->GetDict(proxy_config::prefs::kProxy).Clone());
diff --git a/chrome/browser/extensions/external_provider_impl_chromeos_unittest.cc b/chrome/browser/extensions/external_provider_impl_chromeos_unittest.cc index b9d29418..f1e9708 100644 --- a/chrome/browser/extensions/external_provider_impl_chromeos_unittest.cc +++ b/chrome/browser/extensions/external_provider_impl_chromeos_unittest.cc
@@ -91,7 +91,8 @@ } else { external_externsions_overrides_ = std::make_unique<base::ScopedPathOverride>( - chrome::DIR_EXTERNAL_EXTENSIONS, data_dir().Append("external")); + chrome::DIR_EXTERNAL_EXTENSIONS, + data_dir().Append("external_app")); } // This switch is set when creating a TestingProfile, but needs to be
diff --git a/chrome/browser/extensions/external_provider_impl_unittest.cc b/chrome/browser/extensions/external_provider_impl_unittest.cc index 5f2937ee..2f4dbf0 100644 --- a/chrome/browser/extensions/external_provider_impl_unittest.cc +++ b/chrome/browser/extensions/external_provider_impl_unittest.cc
@@ -38,6 +38,7 @@ #include "extensions/browser/extension_registrar.h" #include "extensions/browser/extension_registry.h" #include "extensions/browser/pref_names.h" +#include "extensions/browser/test_extension_registry_observer.h" #include "extensions/browser/updater/extension_cache_fake.h" #include "extensions/browser/updater/extension_downloader_test_helper.h" #include "net/test/embedded_test_server/embedded_test_server.h" @@ -84,14 +85,14 @@ }; #if BUILDFLAG(GOOGLE_CHROME_BRANDING) -const char kExternalAppId[] = "kekdneafjmhmndejhmbcadfiiofngffo"; +const char kExternalExtensionId[] = "ghpipljflpbfljcfjlhfbfcpoklobpji"; #endif #if BUILDFLAG(IS_WIN) -const char kExternalAppCrxPath[] = - "external\\kekdneafjmhmndejhmbcadfiiofngffo.crx"; -const wchar_t kExternalAppRegistryKey[] = - L"Software\\Google\\Chrome\\Extensions\\kekdneafjmhmndejhmbcadfiiofngffo"; +const char kExternalExtensionCrxPath[] = + "external\\ghpipljflpbfljcfjlhfbfcpoklobpji.crx"; +const wchar_t kExternalExtensionRegistryKey[] = + L"Software\\Google\\Chrome\\Extensions\\ghpipljflpbfljcfjlhfbfcpoklobpji"; #endif class ExternalProviderImplTest : public ExtensionServiceTestBase { @@ -155,20 +156,22 @@ #if BUILDFLAG(IS_WIN) EXPECT_NO_FATAL_FAILURE( registry_override_manager_.OverrideRegistry(HKEY_CURRENT_USER)); - EXPECT_EQ(ERROR_SUCCESS, - external_extension_key_.Create( - HKEY_CURRENT_USER, kExternalAppRegistryKey, KEY_ALL_ACCESS)); - EXPECT_EQ(ERROR_SUCCESS, - external_extension_key_.WriteValue( - L"path", - data_dir().AppendASCII(kExternalAppCrxPath).value().c_str())); + EXPECT_EQ( + ERROR_SUCCESS, + external_extension_key_.Create( + HKEY_CURRENT_USER, kExternalExtensionRegistryKey, KEY_ALL_ACCESS)); + EXPECT_EQ( + ERROR_SUCCESS, + external_extension_key_.WriteValue( + L"path", + data_dir().AppendASCII(kExternalExtensionCrxPath).value().c_str())); EXPECT_EQ(ERROR_SUCCESS, external_extension_key_.WriteValue(L"version", L"1")); #else external_externsions_overrides_ = std::make_unique<base::ScopedPathOverride>( chrome::DIR_EXTERNAL_EXTENSIONS, - data_dir().AppendASCII("external")); + data_dir().AppendASCII("external_extension")); #endif } @@ -272,6 +275,8 @@ } // namespace #if BUILDFLAG(GOOGLE_CHROME_BRANDING) +#if !BUILDFLAG(IS_ANDROID) +// The in-app payments app is not bundled on Android, see crbug.com/409396604. TEST_F(ExternalProviderImplTest, InAppPayments) { InitServiceWithExternalProviders(); @@ -280,6 +285,7 @@ EXPECT_TRUE(registry()->GetInstalledExtension(kInAppPaymentsApp.app_id)); EXPECT_TRUE(registrar()->IsExtensionEnabled(kInAppPaymentsApp.app_id)); } +#endif // !BUILDFLAG(IS_ANDROID) TEST_F(ExternalProviderImplTest, BlockedExternalUserProviders) { OverrideExternalExtensionsPath(); @@ -287,19 +293,23 @@ AwaitCheckForExternalUpdates(); - EXPECT_FALSE(registry()->GetInstalledExtension(kExternalAppId)); + EXPECT_FALSE(registry()->GetInstalledExtension(kExternalExtensionId)); } TEST_F(ExternalProviderImplTest, NotBlockedExternalUserProviders) { OverrideExternalExtensionsPath(); InitServiceWithExternalProviders(false); + TestExtensionRegistryObserver observer(registry()); AwaitCheckForExternalUpdates(); + observer.WaitForExtensionInstalled(); - EXPECT_TRUE(registry()->GetInstalledExtension(kExternalAppId)); + EXPECT_TRUE(registry()->GetInstalledExtension(kExternalExtensionId)); } #endif // BUILDFLAG(GOOGLE_CHROME_BRANDING) +// Desktop Android does not support web apps. +#if BUILDFLAG(ENABLE_EXTENSIONS) TEST_F(ExternalProviderImplTest, WebAppMigrationFlag) { InitService(); @@ -344,5 +354,6 @@ EXPECT_TRUE(registry()->GetInstalledExtension(kGoodApp.app_id)); } } +#endif // BUILDFLAG(ENABLE_EXTENSIONS) } // namespace extensions
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json index 8abbb4b..af7ee32c 100644 --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json
@@ -4065,13 +4065,6 @@ "expiry_milestone": 135 }, { - "name": "enable-multi-capture-notification-update", - "owners": [ - "simonha@google.com" - ], - "expiry_milestone": 145 - }, - { "name": "enable-navigation-capture-refactor-android", "owners": [ "muratori@google.org", "lt-web-apps-team@google.com" ], "expiry_milestone": 150 @@ -5702,6 +5695,14 @@ "owners": [ "carlosk@chromium.org", "vollick@chromium.org", "//chrome/browser/glic/OWNERS" ], "expiry_milestone": 146 }, + { + "name": "glic-print-menu-item", + "owners": [ + "basiaz@google.com", + "//chrome/browser/glic/OWNERS" + ], + "expiry_milestone": 149 + }, { "name": "glic-side-panel", "owners": [ @@ -5716,6 +5717,15 @@ "expiry_milestone": 150 }, { + "name": "glic-trust-first-onboarding", + "owners": [ + "tommasin@chromium.org", + "zalmashni@google.com", + "//chrome/browser/glic/OWNERS" + ], + "expiry_milestone": 152 + }, + { "name": "glic-unified-fre-screen", "owners": [ "michelleabreo@google.com", @@ -6026,6 +6036,11 @@ "expiry_milestone": 138 }, { + "name": "idb-sqlite-backing-store", + "owners": ["evanstade@microsoft.com", "abhishek.shanthkumar@microsoft.com", "//content/browser/indexed_db/OWNERS"], + "expiry_milestone": 160 + }, + { "name": "identity-confirmation-snackbar", "owners": ["jood@google.com", "treib@chromium.org", "chrome-sync-dev@google.com", "chrome-signin-team@google.com"], "expiry_milestone": 139 @@ -6261,11 +6276,6 @@ "expiry_milestone": 150 }, { - "name": "ios-manage-account-storage", - "owners": [ "olivierrobin@google.com", "bling-squid-squad@google.com" ], - "expiry_milestone": 140 - }, - { "name": "ios-one-tap-mini-map-remove-section-breaks", "owners": [ "olivierrobin@google.com", "bling-flags@google.com" ], "expiry_milestone": 145 @@ -7078,11 +7088,6 @@ "expiry_milestone": 150 }, { - "name": "mini-origin-bar", - "owners": [ "pnoland@chromium.org", "chrome-mobile-search@google.com" ], - "expiry_milestone": 147 - }, - { "name": "minutes-delay-to-restore-gaia-cookies-if-deleted", "owners": ["jlebel@chromium.org", "chrome-signin-team@google.com"], // Used for automated testing of Gaia cookie restoration in iOS. @@ -7224,14 +7229,6 @@ "expiry_milestone": 150 }, { - "name": "non-modal-sign-in-promo", - "owners": [ - "kanouche@google.com", - "bling-mony-pod@google.com" - ], - "expiry_milestone": 145 - }, - { "name": "notebook-lm-app-preinstall", "owners": [ "alancutter@google.com", "crosdev-commerce-eng@google.com" ], "expiry_milestone": 146 @@ -8912,6 +8909,11 @@ "expiry_milestone": 150 }, { + "name" : "reader-mode-support-new-fonts", + "owners": ["wylieb@google.com", "fernandex@google.com", "evanluo@google.com", "chrome-reader-mode-team@google.com", "bling-flags@google.com"], + "expiry_milestone": 150 + }, + { "name": "reader-mode-translation-enabled", "owners": ["fernandex@google.com", "qpubert@google.com", "bling-flags@google.com"], "expiry_milestone": 150 @@ -9570,14 +9572,6 @@ "expiry_milestone" : 150 }, { - "name": "sign-in-button-no-avatar", - "owners": [ - "pabouchard@google.com", - "bling-mony-pod@google.com" - ], - "expiry_milestone": 138 - }, - { "name": "signature-based-sri", "owners": [ "mkwst@chromium.org" ], "expiry_milestone": 150 @@ -9976,14 +9970,6 @@ "expiry_milestone": 150 }, { - "name": "tailored-non-modal-db-promo", - "owners": [ - "pabouchard@google.com", - "bling-mony-pod@google.com" - ], - "expiry_milestone": 141 - }, - { "name": "taiyaki", "owners": [ "jlebel@google.com", "dgn@google.com", "chrome-regionalcapabilities@google.com"
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index 95d8c20..3ec5cc53 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -1387,6 +1387,9 @@ "Glic Panel Reset Size and Location"; inline constexpr char kGlicPanelResetSizeAndLocationDescription[] = "Enables resetting the panel size and position on every open."; +inline constexpr char kGlicPrintMenuItemName[] = "Glic Print Menu Item"; +inline constexpr char kGlicPrintMenuItemDescription[] = + "Enables showing the Glic print contextual menu item."; inline constexpr char kGlicWarmingName[] = "Glic Pre-Warming"; inline constexpr char kGlicWarmingDescription[] = "Enables the pre-warming of the Glic panel's web client."; @@ -1416,6 +1419,10 @@ inline constexpr char kGlicDaisyChainNewTabsDescription[] = "Daisy chains new tabs if the active tab when the new tab was create has an" " open glic side panel"; +inline constexpr char kGlicTrustFirstOnboardingName[] = + "Glic Trust First Onboarding"; +inline constexpr char kGlicTrustFirstOnboardingDescription[] = + "Enables the Trust First Onboarding experiment for Glic."; inline constexpr char kGlicUnifiedFreScreenName[] = "Glic Unified Fre Screen"; inline constexpr char kGlicUnifiedFreScreenDescription[] = "Moves the first-run-experience (fre) screen into the side panel."; @@ -5560,11 +5567,6 @@ inline constexpr char kMigrateAccountPrefsOnMobileDescription[] = "Migrate account prefs on Mobile to the single-json implementation."; -inline constexpr char kMiniOriginBarName[] = "Mini Origin Bar"; -inline constexpr char kMiniOriginBarDescription[] = - "Show a mini origin bar above the keyboard when focusing a form field. " - "Applicable to bottom toolbar on Android only."; - inline constexpr char kNavBarColorAnimationName[] = "NavBarColorAnimation"; inline constexpr char kNavBarColorAnimationDescription[] = "Enables animations for color changes to the OS navigation bar."; @@ -5678,6 +5680,11 @@ "Reader Mode improvements"; inline constexpr char kReaderModeImprovementsDescription[] = "Collection of improvements to reader mode for android."; +inline constexpr char kReaderModeSupportNewFontsName[] = + "Reader Mode support new fonts"; +inline constexpr char kReaderModeSupportNewFontsDescription[] = + "Enables new accessible font options in Reader Mode."; + inline constexpr char kReaderModeUseReadabilityName[] = "Reader Mode use readability"; inline constexpr char kReaderModeUseReadabilityDescription[] = @@ -7465,6 +7472,12 @@ inline constexpr char kHybridChargerNotificationsDescription[] = "Displays helpful notifications for devices with Hybrid Chargers."; +inline constexpr char kIdbSqliteBackingStoreName[] = "IDB SQLite Backing Store"; +inline constexpr char kIdbSqliteBackingStoreDescription[] = + "Uses a SQLite-powered backing store for IndexedDB. No data is migrated " + "from existing backing stores, including LevelDB stores or SQLite stores " + "with older schemas; use at your own peril."; + inline constexpr char kImeAssistMultiWordName[] = "Enable assistive multi word suggestions"; inline constexpr char kImeAssistMultiWordDescription[] =
diff --git a/chrome/browser/flags/android/chrome_feature_list.cc b/chrome/browser/flags/android/chrome_feature_list.cc index de32c0f..be7b88e6 100644 --- a/chrome/browser/flags/android/chrome_feature_list.cc +++ b/chrome/browser/flags/android/chrome_feature_list.cc
@@ -357,7 +357,6 @@ &kMagicStackAndroid, &kMayLaunchUrlUsesSeparateStoragePartition, &kMediaIndicatorsAndroid, - &kMiniOriginBar, &kMostVisitedTilesCustomization, &kMostVisitedTilesReselect, &kMultiInstanceApplicationStatusCleanup, @@ -701,7 +700,6 @@ // default. BASE_FEATURE(kMayLaunchUrlUsesSeparateStoragePartition, base::FEATURE_DISABLED_BY_DEFAULT); BASE_FEATURE(kMediaIndicatorsAndroid, base::FEATURE_DISABLED_BY_DEFAULT); -BASE_FEATURE(kMiniOriginBar, base::FEATURE_ENABLED_BY_DEFAULT); BASE_FEATURE(kMostVisitedTilesCustomization, base::FEATURE_ENABLED_BY_DEFAULT); BASE_FEATURE(kMostVisitedTilesReselect, base::FEATURE_DISABLED_BY_DEFAULT); BASE_FEATURE(kMultiInstanceApplicationStatusCleanup, 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 ff7c105..bfd58c91 100644 --- a/chrome/browser/flags/android/chrome_feature_list.h +++ b/chrome/browser/flags/android/chrome_feature_list.h
@@ -190,7 +190,6 @@ BASE_DECLARE_FEATURE(kMagicStackAndroid); BASE_DECLARE_FEATURE(kMayLaunchUrlUsesSeparateStoragePartition); BASE_DECLARE_FEATURE(kMediaIndicatorsAndroid); -BASE_DECLARE_FEATURE(kMiniOriginBar); BASE_DECLARE_FEATURE(kMostVisitedTilesCustomization); BASE_DECLARE_FEATURE(kMostVisitedTilesReselect); BASE_DECLARE_FEATURE(kMultiInstanceApplicationStatusCleanup);
diff --git a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java index fd8f0ea960..fb94a5df9 100644 --- a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java +++ b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java
@@ -487,7 +487,6 @@ public static final String MAYLAUNCHURL_USES_SEPARATE_STORAGE_PARTITION = "MayLaunchUrlUsesSeparateStoragePartition"; public static final String MEDIA_INDICATORS_ANDROID = "MediaIndicatorsAndroid"; - public static final String MINI_ORIGIN_BAR = "MiniOriginBar"; public static final String MOST_VISITED_TILES_CUSTOMIZATION = "MostVisitedTilesCustomization"; public static final String MOST_VISITED_TILES_RESELECT = "MostVisitedTilesReselect"; public static final String MULTI_INSTANCE_APPLICATION_STATUS_CLEANUP = @@ -747,7 +746,7 @@ public static final CachedFlag sAndroidNewMediaPicker = newCachedFlag(ANDROID_NEW_MEDIA_PICKER, false); public static final CachedFlag sAndroidOpenIncognitoAsWindow = - newCachedFlag(ANDROID_OPEN_INCOGNITO_AS_WINDOW, BuildConfig.IS_DESKTOP_ANDROID, true); + newCachedFlag(ANDROID_OPEN_INCOGNITO_AS_WINDOW, BuildConfig.IS_DESKTOP_ANDROID); public static final CachedFlag sAndroidProgressBarVisualUpdate = newCachedFlag( ANDROID_PROGRESS_BAR_VISUAL_UPDATE, @@ -964,7 +963,6 @@ MALICIOUS_APK_DOWNLOAD_CHECK, /* defaultValue= */ false, /* defaultValueInTests= */ true); - public static final CachedFlag sMiniOriginBar = newCachedFlag(MINI_ORIGIN_BAR, true, true); public static final CachedFlag sMostVisitedTilesCustomization = newCachedFlag( MOST_VISITED_TILES_CUSTOMIZATION, @@ -1052,7 +1050,7 @@ public static final CachedFlag sTabStripDensityChangeAndroid = newCachedFlag(TAB_STRIP_DENSITY_CHANGE_ANDROID, true); public static final CachedFlag sTabStripIncognitoMigration = - newCachedFlag(TAB_STRIP_INCOGNITO_MIGRATION, BuildConfig.IS_DESKTOP_ANDROID, true); + newCachedFlag(TAB_STRIP_INCOGNITO_MIGRATION, BuildConfig.IS_DESKTOP_ANDROID); public static final CachedFlag sTabWindowManagerReportIndicesMismatch = newCachedFlag(TAB_WINDOW_MANAGER_REPORT_INDICES_MISMATCH, true); public static final CachedFlag sTabletTabStripAnimation = @@ -1217,7 +1215,6 @@ sLockTopControlsOnLargeTabletsV2, sMagicStackAndroid, sMaliciousApkDownloadCheck, - sMiniOriginBar, sMostVisitedTilesCustomization, sMostVisitedTilesReselect, sMultiInstanceApplicationStatusCleanup,
diff --git a/chrome/browser/glic/glic_settings_util_interactive_uitest.cc b/chrome/browser/glic/glic_settings_util_interactive_uitest.cc index 288c7438..4aca10e 100644 --- a/chrome/browser/glic/glic_settings_util_interactive_uitest.cc +++ b/chrome/browser/glic/glic_settings_util_interactive_uitest.cc
@@ -81,9 +81,8 @@ Do([this, f] { f(browser()->profile()); }), InstrumentTab(kSettingsTab), WaitForWebContentsReady( kSettingsTab, chrome::GetSettingsUrl(chrome::kGlicSettingsSubpage)), - CheckResult( - [this] { return browser()->tab_strip_model()->GetTabCount(); }, 3, - "CheckTabCount")); + CheckResult([this] { return browser()->tab_strip_model()->count(); }, 3, + "CheckTabCount")); } auto SetFRECompletion(glic::prefs::FreStatus status) {
diff --git a/chrome/browser/glic/host/glic_actor_interactive_uitest_common.cc b/chrome/browser/glic/host/glic_actor_interactive_uitest_common.cc index 5a19bd8..4f4f619 100644 --- a/chrome/browser/glic/host/glic_actor_interactive_uitest_common.cc +++ b/chrome/browser/glic/host/glic_actor_interactive_uitest_common.cc
@@ -205,7 +205,7 @@ MultiStep GlicActorUiTest::CreateTask(actor::TaskId& out_task, std::string_view title) { return Steps( - Do([this, &out_task, title = std::string(title)]() mutable { + Do([this, &out_task, title = std::string(title)]() { content::WebContents* glic_contents = GetGlicContents(); const int result = content::EvalJs( @@ -372,7 +372,7 @@ } MultiStep GlicActorUiTest::StopActorTask() { - return Steps(Do([this, &task_id = task_id_]() mutable { + return Steps(Do([this, &task_id = task_id_]() { content::WebContents* glic_contents = GetGlicContents(); std::string script = content::JsReplace( "client.browser.stopActorTask($1);", task_id.value()); @@ -383,8 +383,7 @@ MultiStep GlicActorUiTest::PauseActorTask() { return Steps(Do( - [this, &task_id = task_id_, - &tab_handle = tab_handle_]() mutable { + [this, &task_id = task_id_, &tab_handle = tab_handle_]() { content::WebContents* glic_contents = GetGlicContents(); std::string script = content::JsReplace( "client.browser.pauseActorTask($1, /* pauseReason= " @@ -450,7 +449,7 @@ } MultiStep GlicActorUiTest::InterruptActorTask() { - return Steps(Do([this, &task_id = task_id_]() mutable { + return Steps(Do([this, &task_id = task_id_]() { content::WebContents* glic_contents = GetGlicContents(); std::string script = content::JsReplace( "client.browser.interruptActorTask($1);", task_id.value()); @@ -467,7 +466,7 @@ EXPECT_NE(expected_state, mojom::ActorTaskState::kStopped); return Steps( - Do([this, &task_id = task_id_, expected_state]() mutable { + Do([this, &task_id = task_id_, expected_state]() { content::WebContents* glic_contents = GetGlicContents(); std::string script = content::JsReplace( R"js( @@ -482,7 +481,7 @@ MultiStep GlicActorUiTest::PrepareForStopStateChange() { return Steps( - Do([this, &task_id = task_id_]() mutable { + Do([this, &task_id = task_id_]() { content::WebContents* glic_contents = GetGlicContents(); std::string script = content::JsReplace( "window.taskStateObs = " @@ -506,7 +505,7 @@ } MultiStep GlicActorUiTest::ActivateTaskTab() { - return Steps(Do([this, &tab_handle = tab_handle_]() mutable { + return Steps(Do([this, &tab_handle = tab_handle_]() { content::WebContents* glic_contents = GetGlicContents(); std::string script = content::JsReplace("client.browser.activateTab('$1');", @@ -518,7 +517,7 @@ MultiStep GlicActorUiTest::WaitForTaskTabForeground(bool expected_foreground) { return Steps( - Do([this, &tab_handle = tab_handle_, expected_foreground]() mutable { + Do([this, &tab_handle = tab_handle_, expected_foreground]() { content::WebContents* glic_contents = GetGlicContents(); std::string script = content::JsReplace( R"js(
diff --git a/chrome/browser/glic/host/glic_api_browsertest.cc b/chrome/browser/glic/host/glic_api_browsertest.cc index 0572592..5f38647 100644 --- a/chrome/browser/glic/host/glic_api_browsertest.cc +++ b/chrome/browser/glic/host/glic_api_browsertest.cc
@@ -957,10 +957,9 @@ ASSERT_TRUE(guest_frame); ExecuteJsTest(); ASSERT_TRUE(base::test::RunUntil([&]() { - return InProcessBrowserTest::browser()->tab_strip_model()->GetTabCount() == - 2; + return InProcessBrowserTest::browser()->tab_strip_model()->count() == 2; })) << "Timed out waiting for tab count to increase. Tab count = " - << InProcessBrowserTest::browser()->tab_strip_model()->GetTabCount(); + << InProcessBrowserTest::browser()->tab_strip_model()->count(); // The guest frame shouldn't change. ASSERT_EQ(guest_frame, FindGlicGuestMainFrame());
diff --git a/chrome/browser/glic/host/glic_cookie_synchronizer.cc b/chrome/browser/glic/host/glic_cookie_synchronizer.cc index d8b87f07..ce4625b2 100644 --- a/chrome/browser/glic/host/glic_cookie_synchronizer.cc +++ b/chrome/browser/glic/host/glic_cookie_synchronizer.cc
@@ -277,13 +277,16 @@ CompleteAuth(false); return; } + signin::MultiloginParameters parameters = { + gaia::MultiloginMode::MULTILOGIN_UPDATE_COOKIE_ACCOUNTS_ORDER, + {primary_account_id}}; + if (base::FeatureList::IsEnabled(features::kGlicIgnoreOfflineState)) { + parameters.wait_on_connectivity = false; + } cookie_loader_ = identity_manager_->GetAccountsCookieMutator() ->SetAccountsInCookieForPartition( - this, - {gaia::MultiloginMode::MULTILOGIN_UPDATE_COOKIE_ACCOUNTS_ORDER, - {primary_account_id}}, - gaia::GaiaSource::kChromeGlic, + this, parameters, gaia::GaiaSource::kChromeGlic, base::BindOnce(&GlicCookieSynchronizer::OnAuthFinished, GetWeakPtr())); }
diff --git a/chrome/browser/glic/host/glic_ui.cc b/chrome/browser/glic/host/glic_ui.cc index 7e72a13..b4ad6ef3 100644 --- a/chrome/browser/glic/host/glic_ui.cc +++ b/chrome/browser/glic/host/glic_ui.cc
@@ -198,6 +198,10 @@ !command_line->HasSwitch(::switches::kGlicSkipReloadAfterNavigation); source->AddBoolean("reloadAfterNavigation", reload_after_navigation); + source->AddBoolean( + "ignoreOfflineState", + base::FeatureList::IsEnabled(features::kGlicIgnoreOfflineState)); + source->AddBoolean("enableDebug", base::FeatureList::IsEnabled(features::kGlicDebugWebview));
diff --git a/chrome/browser/glic/host/glic_ui_interactive_uitest.cc b/chrome/browser/glic/host/glic_ui_interactive_uitest.cc index e91ad77f..770dfa5 100644 --- a/chrome/browser/glic/host/glic_ui_interactive_uitest.cc +++ b/chrome/browser/glic/host/glic_ui_interactive_uitest.cc
@@ -383,8 +383,11 @@ class GlicUiDisconnectedUiTest : public GlicUiInteractiveUiTestBase { public: GlicUiDisconnectedUiTest() - : GlicUiInteractiveUiTestBase(TestParams(/*connected=*/false)) {} + : GlicUiInteractiveUiTestBase(TestParams(/*connected=*/false)) { + feature_list_.InitAndDisableFeature(features::kGlicIgnoreOfflineState); + } ~GlicUiDisconnectedUiTest() override = default; + base::test::ScopedFeatureList feature_list_; }; IN_PROC_BROWSER_TEST_F(GlicUiDisconnectedUiTest, DisconnectedPanelShown) {
diff --git a/chrome/browser/glic/test_support/interactive_glic_test.h b/chrome/browser/glic/test_support/interactive_glic_test.h index d546ef9..e76d841 100644 --- a/chrome/browser/glic/test_support/interactive_glic_test.h +++ b/chrome/browser/glic/test_support/interactive_glic_test.h
@@ -763,7 +763,7 @@ auto CheckTabCount(int expected_count) { return Api::CheckResult( - [this] { return browser()->tab_strip_model()->GetTabCount(); }, + [this] { return browser()->tab_strip_model()->count(); }, expected_count, "CheckTabCount"); }
diff --git a/chrome/browser/glic/widget/glic_floating_ui.cc b/chrome/browser/glic/widget/glic_floating_ui.cc index cfb457d..eeb80951 100644 --- a/chrome/browser/glic/widget/glic_floating_ui.cc +++ b/chrome/browser/glic/widget/glic_floating_ui.cc
@@ -41,6 +41,11 @@ return {features::kGlicMultiInstanceFloatyWidth.Get(), features::kGlicMultiInstanceFloatyHeight.Get()}; } + +gfx::Size GlicFloatingUi::GetCompositeViewDefaultSize() { + return {features::kGlicCompositeViewWidth.Get(), + features::kGlicCompositeViewHeight.Get()}; +} // end static GlicFloatingUi::GlicFloatingUi(Profile* profile, @@ -392,7 +397,14 @@ } gfx::Size GlicFloatingUi::GetMaximumDialogSize() { - return GetGlicWidget()->GetClientAreaBoundsInScreen().size(); + // Print preview might be the widest model dialog we support for now, use its + // min size if FLoaty is smaller than that. + gfx::Size floaty_size = GetGlicWidget()->GetClientAreaBoundsInScreen().size(); + gfx::Size default_size = GetCompositeViewDefaultSize(); + if (floaty_size.width() >= default_size.width()) { + return floaty_size; + } + return default_size; } gfx::NativeView GlicFloatingUi::GetHostView() const {
diff --git a/chrome/browser/glic/widget/glic_floating_ui.h b/chrome/browser/glic/widget/glic_floating_ui.h index 810f42f..2af6721 100644 --- a/chrome/browser/glic/widget/glic_floating_ui.h +++ b/chrome/browser/glic/widget/glic_floating_ui.h
@@ -52,6 +52,7 @@ ~GlicFloatingUi() override; static gfx::Size GetDefaultSize(); + static gfx::Size GetCompositeViewDefaultSize(); // GlicUiEmbedder: void OnClientReady() override;
diff --git a/chrome/browser/image_descriptions/android/java/src/org/chromium/chrome/browser/image_descriptions/ImageDescriptionsSettings.java b/chrome/browser/image_descriptions/android/java/src/org/chromium/chrome/browser/image_descriptions/ImageDescriptionsSettings.java index dcabcb4..195cc8e 100644 --- a/chrome/browser/image_descriptions/android/java/src/org/chromium/chrome/browser/image_descriptions/ImageDescriptionsSettings.java +++ b/chrome/browser/image_descriptions/android/java/src/org/chromium/chrome/browser/image_descriptions/ImageDescriptionsSettings.java
@@ -17,6 +17,7 @@ import org.chromium.build.annotations.Nullable; import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.settings.ProfileDependentSetting; +import org.chromium.chrome.browser.settings.search.ChromeBaseSearchIndexProvider; import org.chromium.components.browser_ui.settings.ChromeSwitchPreference; import org.chromium.components.browser_ui.settings.CustomDividerFragment; import org.chromium.components.browser_ui.settings.EmbeddableSettingsPage; @@ -124,4 +125,9 @@ public @AnimationType int getAnimationType() { return AnimationType.PROPERTY; } + + // TODO(crbug.com/444470792): Determine what pieces of logic are dynamic and need handling. + public static final ChromeBaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = + new ChromeBaseSearchIndexProvider( + ImageDescriptionsSettings.class.getName(), R.xml.image_descriptions_preference); }
diff --git a/chrome/browser/incognito/android/java/src/org/chromium/chrome/browser/incognito/IncognitoUtils.java b/chrome/browser/incognito/android/java/src/org/chromium/chrome/browser/incognito/IncognitoUtils.java index 3b9a8d6..3542be0 100644 --- a/chrome/browser/incognito/android/java/src/org/chromium/chrome/browser/incognito/IncognitoUtils.java +++ b/chrome/browser/incognito/android/java/src/org/chromium/chrome/browser/incognito/IncognitoUtils.java
@@ -9,7 +9,6 @@ import org.jni_zero.JniType; import org.jni_zero.NativeMethods; -import org.chromium.base.ContextUtils; import org.chromium.base.ResettersForTesting; import org.chromium.build.annotations.NullMarked; import org.chromium.build.annotations.Nullable; @@ -19,7 +18,6 @@ import org.chromium.chrome.browser.profiles.ProfileKey; import org.chromium.chrome.browser.profiles.ProfileKeyUtil; import org.chromium.chrome.browser.profiles.ProfileManager; -import org.chromium.ui.base.DeviceFormFactor; /** Utilities for working with incognito tabs spread across multiple activities. */ @NullMarked @@ -74,9 +72,8 @@ * @return Whether incognito tabs should open in a separate window. */ public static boolean shouldOpenIncognitoAsWindow() { - return ChromeFeatureList.sAndroidOpenIncognitoAsWindow.isEnabled() - && DeviceFormFactor.isNonMultiDisplayContextOnTablet( - ContextUtils.getApplicationContext()); + // TODO(crbug.com/435211685): Enable this feature only for eligible devices. + return ChromeFeatureList.sAndroidOpenIncognitoAsWindow.isEnabled(); } /**
diff --git a/chrome/browser/language/android/java/src/org/chromium/chrome/browser/language/settings/LanguageSettings.java b/chrome/browser/language/android/java/src/org/chromium/chrome/browser/language/settings/LanguageSettings.java index 11ad755..e8741758 100644 --- a/chrome/browser/language/android/java/src/org/chromium/chrome/browser/language/settings/LanguageSettings.java +++ b/chrome/browser/language/android/java/src/org/chromium/chrome/browser/language/settings/LanguageSettings.java
@@ -31,6 +31,7 @@ import org.chromium.chrome.browser.settings.ChromeBaseSettingsFragment; import org.chromium.chrome.browser.settings.ChromeManagedPreferenceDelegate; import org.chromium.chrome.browser.settings.SettingsNavigationFactory; +import org.chromium.chrome.browser.settings.search.ChromeBaseSearchIndexProvider; import org.chromium.chrome.browser.translate.TranslateBridge; import org.chromium.components.browser_ui.settings.ChromeSwitchPreference; import org.chromium.components.browser_ui.settings.SettingsUtils; @@ -96,7 +97,7 @@ * * @return Whether or not to show the detailed language preferences. */ - private boolean shouldShowDetailedPreferences() { + private static boolean shouldShowDetailedPreferences() { return ChromeFeatureList.isEnabled(ChromeFeatureList.DETAILED_LANGUAGE_SETTINGS) || GlobalAppLocaleController.getInstance().isOverridden(); } @@ -454,4 +455,13 @@ public @Nullable String getMainMenuKey() { return "languages"; } + + // TODO(crbug.com/444470792): Verify if these are the prefs to be removed and if dynamic ones + // need to be handled. + public static final ChromeBaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = + new ChromeBaseSearchIndexProvider( + LanguageSettings.class.getName(), + shouldShowDetailedPreferences() + ? R.xml.languages_preferences + : R.xml.languages_detailed_preferences); }
diff --git a/chrome/browser/magic_stack/android/java/src/org/chromium/chrome/browser/magic_stack/HomeModulesConfigSettings.java b/chrome/browser/magic_stack/android/java/src/org/chromium/chrome/browser/magic_stack/HomeModulesConfigSettings.java index cc64cf3..fa7dcb2d 100644 --- a/chrome/browser/magic_stack/android/java/src/org/chromium/chrome/browser/magic_stack/HomeModulesConfigSettings.java +++ b/chrome/browser/magic_stack/android/java/src/org/chromium/chrome/browser/magic_stack/HomeModulesConfigSettings.java
@@ -16,6 +16,7 @@ import org.chromium.build.annotations.Nullable; import org.chromium.chrome.browser.magic_stack.ModuleDelegate.ModuleType; import org.chromium.chrome.browser.settings.ChromeBaseSettingsFragment; +import org.chromium.chrome.browser.settings.search.ChromeBaseSearchIndexProvider; import org.chromium.components.browser_ui.settings.ChromeSwitchPreference; import org.chromium.components.browser_ui.settings.SettingsFragment; @@ -81,4 +82,9 @@ public @Nullable String getMainMenuKey() { return "home_modules_config"; } + + // TODO(crbug.com/444470792): Determine what pieces of logic are dynamic and need handling. Any + // entries that need adding? + public static final ChromeBaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = + new ChromeBaseSearchIndexProvider(HomeModulesConfigSettings.class.getName(), 0); }
diff --git a/chrome/browser/metrics/chrome_feature_list_creator.cc b/chrome/browser/metrics/chrome_feature_list_creator.cc index d2fe800..ad3a403 100644 --- a/chrome/browser/metrics/chrome_feature_list_creator.cc +++ b/chrome/browser/metrics/chrome_feature_list_creator.cc
@@ -12,6 +12,8 @@ #include "base/memory/scoped_refptr.h" #include "base/metrics/histogram_functions.h" #include "base/path_service.h" +#include "base/time/default_clock.h" +#include "base/time/default_tick_clock.h" #include "base/time/time.h" #include "base/trace_event/trace_event.h" #include "chrome/browser/about_flags.h" @@ -25,6 +27,7 @@ #include "chrome/common/chrome_switches.h" #include "chrome/installer/util/initial_preferences.h" #include "components/content_settings/core/common/features.h" +#include "components/network_time/network_time_tracker.h" #include "components/prefs/json_pref_store.h" #include "components/prefs/pref_registry_simple.h" #include "components/privacy_sandbox/privacy_sandbox_features.h" @@ -36,6 +39,7 @@ #include "content/public/common/content_switch_dependent_feature_overrides.h" #include "content/public/common/content_switches.h" #include "services/network/public/cpp/network_switches.h" +#include "services/network/public/cpp/shared_url_loader_factory.h" #include "ui/base/resource/resource_bundle.h" #if BUILDFLAG(IS_WIN) @@ -95,7 +99,9 @@ } // namespace -ChromeFeatureListCreator::ChromeFeatureListCreator() = default; +ChromeFeatureListCreator::ChromeFeatureListCreator() { + CreateNetworkTimeTracker(); +} ChromeFeatureListCreator::~ChromeFeatureListCreator() = default; @@ -147,6 +153,12 @@ return std::move(browser_policy_connector_); } +std::unique_ptr<network_time::NetworkTimeTracker> +ChromeFeatureListCreator::TakeNetworkTimeTracker() { + CHECK(network_time_tracker_); + return std::move(network_time_tracker_); +} + #if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_CHROMEOS) std::unique_ptr<installer::InitialPreferences> ChromeFeatureListCreator::TakeInitialPrefs() { @@ -245,6 +257,21 @@ flags_ui::kAddSentinels); } +void ChromeFeatureListCreator::CreateNetworkTimeTracker() { + // The NetworkTimeTracker is needed before the PrefService and + // URLLoaderFactory can be fully initialized, so we only partially create it + // now (we pass nullptr for both values). The PrefService and URLLoaderFactory + // will be provided later, via the Initialize() method invoked by the + // BrowserProcessImpl constructor. + network_time_tracker_ = std::make_unique<network_time::NetworkTimeTracker>( + std::make_unique<base::DefaultClock>(), + std::make_unique<base::DefaultTickClock>(), + /*pref_service=*/nullptr, + /*url_loader_factory=*/nullptr, + /*network_time_pref_delegate=*/std::nullopt); + CHECK(!network_time_tracker_->is_initialized()); +} + void ChromeFeatureListCreator::SetUpFieldTrials( const std::string& command_line_variation_ids) { browser_field_trials_ =
diff --git a/chrome/browser/metrics/chrome_feature_list_creator.h b/chrome/browser/metrics/chrome_feature_list_creator.h index 5d9decf..c2f0224 100644 --- a/chrome/browser/metrics/chrome_feature_list_creator.h +++ b/chrome/browser/metrics/chrome_feature_list_creator.h
@@ -25,6 +25,10 @@ class InitialPreferences; } // namespace installer +namespace network_time { +class NetworkTimeTracker; +} // namespace network_time + class ChromeMetricsServicesManagerClient; // The ChromeFeatureListCreator creates the FeatureList and classes required for @@ -68,6 +72,9 @@ std::unique_ptr<policy::ChromeBrowserPolicyConnector> TakeChromeBrowserPolicyConnector(); + // Passes ownership of the |network_time_tracker_| to the caller. + std::unique_ptr<network_time::NetworkTimeTracker> TakeNetworkTimeTracker(); + #if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_CHROMEOS) std::unique_ptr<installer::InitialPreferences> TakeInitialPrefs(); #endif @@ -76,6 +83,10 @@ policy::ChromeBrowserPolicyConnector* browser_policy_connector() { return browser_policy_connector_.get(); } + network_time::NetworkTimeTracker* network_time_tracker() { + CHECK(network_time_tracker_); + return network_time_tracker_.get(); + } const std::string& actual_locale() { return actual_locale_; } ChromeBrowserFieldTrials* browser_field_trials() { @@ -94,6 +105,7 @@ private: void CreatePrefService(); void ConvertFlagsToSwitches(); + void CreateNetworkTimeTracker(); // Sets up the field trials and related initialization. Call only after // about:flags have been converted to switches. However, @@ -126,6 +138,8 @@ raw_ptr<ChromeMetricsServicesManagerClient, AcrossTasksDanglingUntriaged> metrics_services_manager_client_; + std::unique_ptr<network_time::NetworkTimeTracker> network_time_tracker_; + std::unique_ptr<metrics_services_manager::MetricsServicesManager> metrics_services_manager_;
diff --git a/chrome/browser/metrics/family_link_user_metrics_provider_unittest.cc b/chrome/browser/metrics/family_link_user_metrics_provider_unittest.cc index ae153a9..75dec1ed 100644 --- a/chrome/browser/metrics/family_link_user_metrics_provider_unittest.cc +++ b/chrome/browser/metrics/family_link_user_metrics_provider_unittest.cc
@@ -117,8 +117,8 @@ // Default supervised user service, as in production. virtual std::unique_ptr<KeyedService> BuildSupervisedUserService( content::BrowserContext* browser_context) { - Profile* profile = Profile::FromBrowserContext(browser_context); - return SupervisedUserServiceFactory::BuildInstanceFor(profile); + return SupervisedUserServiceFactory::BuildInstanceFor( + Profile::FromBrowserContext(browser_context)); } void SetFamilyRole(Profile* profile, kidsmanagement::FamilyRole family_role) { @@ -527,7 +527,7 @@ // Test fixture for verifying that the content filters are correctly // reflected in the metrics. Content filters are mutually exclusive with // Family-Link supervision and cannot be applied to these profiles. -class FamilyLinkUserMetricsProviderWithContentFiltersTest +class FamilyLinkUserMetricsProviderWithContentFiltersAndroidTest : public FamilyLinkUserMetricsProviderTest, public testing::WithParamInterface<ContentFiltersTestCase> { protected: @@ -540,9 +540,7 @@ email_addresses_[i], profile_names_[i]); // Services are lazily created, so we need to access them to force their - // creation. That'll trigger the ::BuildSupervisedUserService factory, - // which will bind fake content filters observers to this text fixture - // instance. + // creation. CHECK(SupervisedUserServiceFactory::GetInstance()->GetForProfile( unsupervised_profile)); } @@ -556,27 +554,7 @@ /*is_opted_in_to_parental_supervision=*/false); } - std::unique_ptr<ContentFiltersObserverBridge> CreateBridge( - std::string_view setting_name, - base::RepeatingClosure on_enabled, - base::RepeatingClosure on_disabled, - base::RepeatingCallback<bool()> is_subject_to_parental_controls) { - std::unique_ptr<FakeContentFiltersObserverBridge> bridge = - std::make_unique<FakeContentFiltersObserverBridge>( - setting_name, on_enabled, on_disabled, - is_subject_to_parental_controls); - if (setting_name == kBrowserContentFiltersSettingName) { - browser_content_filters_observers_.push_back(bridge.get()); - } else if (setting_name == kSearchContentFiltersSettingName) { - search_content_filters_observers_.push_back(bridge.get()); - } - return bridge; - } - - // Builds the `SupervisedUserService` and captures the content observers onto - // this text fixture instance. Binding memory managed by foreign object (the - // service) to raw_ptr is fine, because raw_ptr handles will be destroyed - // before profile manager, that transitively owns the content observers. + // Builds the `SupervisedUserService` with fake content filters observers. std::unique_ptr<KeyedService> BuildSupervisedUserService( content::BrowserContext* browser_context) override { Profile* profile = Profile::FromBrowserContext(browser_context); @@ -603,24 +581,29 @@ *profile->GetPrefs(), platform_delegate->GetCountryCode(), platform_delegate->GetChannel())), std::make_unique<SupervisedUserServicePlatformDelegate>(*profile), - base::BindRepeating( - &FamilyLinkUserMetricsProviderWithContentFiltersTest::CreateBridge, - base::Unretained(this))); + std::make_unique<FakeContentFiltersObserverBridge>( + kBrowserContentFiltersSettingName, *profile->GetPrefs()), + std::make_unique<FakeContentFiltersObserverBridge>( + kSearchContentFiltersSettingName, *profile->GetPrefs())); } // Enables or disables the browser content filters for all profiles. void SetBrowserContentFilters(bool enabled) { - for (FakeContentFiltersObserverBridge* observer : - browser_content_filters_observers_) { - observer->SetEnabled(enabled); + for (Profile* profile : + test_profile_manager()->profile_manager()->GetLoadedProfiles()) { + SupervisedUserServiceFactory::GetForProfile(profile) + ->GetBrowserContentFiltersObserverWeakPtrForTesting() + ->SetEnabledForTesting(enabled); } } // Enables or disables the search content filters for all profiles. void SetSearchContentFilters(bool enabled) { - for (FakeContentFiltersObserverBridge* observer : - search_content_filters_observers_) { - observer->SetEnabled(enabled); + for (Profile* profile : + test_profile_manager()->profile_manager()->GetLoadedProfiles()) { + SupervisedUserServiceFactory::GetForProfile(profile) + ->GetSearchContentFiltersObserverWeakPtrForTesting() + ->SetEnabledForTesting(enabled); } } @@ -632,18 +615,9 @@ kPropagateDeviceContentFiltersToSupervisedUser}; std::vector<std::string> email_addresses_{kTestEmail, kTestEmail1}; std::vector<std::string> profile_names_{kTestProfile, kTestProfile1}; - - // These are internal components of the `SupervisedUserService` and are used - // to simulate changes to the android content filters. Both are owned by the - // `SupervisedUserService`. The reason for they're held in vectors is that - // content filters are applied at device level, for all profiles at once. - std::vector<raw_ptr<FakeContentFiltersObserverBridge>> - browser_content_filters_observers_; - std::vector<raw_ptr<FakeContentFiltersObserverBridge>> - search_content_filters_observers_; }; -TEST_P(FamilyLinkUserMetricsProviderWithContentFiltersTest, +TEST_P(FamilyLinkUserMetricsProviderWithContentFiltersAndroidTest, AllFiltersDisabled) { CreateProfiles(GetParam().profile_count); @@ -659,7 +633,7 @@ /*expected_count=*/0); } -TEST_P(FamilyLinkUserMetricsProviderWithContentFiltersTest, +TEST_P(FamilyLinkUserMetricsProviderWithContentFiltersAndroidTest, SearchFilterEnabled) { CreateProfiles(GetParam().profile_count); SetSearchContentFilters(true); @@ -676,7 +650,7 @@ /*expected_count=*/1); } -TEST_P(FamilyLinkUserMetricsProviderWithContentFiltersTest, +TEST_P(FamilyLinkUserMetricsProviderWithContentFiltersAndroidTest, ContentFiltersEnabled) { CreateProfiles(GetParam().profile_count); SetBrowserContentFilters(true); @@ -694,7 +668,8 @@ /*expected_bucket_count=*/1); } -TEST_P(FamilyLinkUserMetricsProviderWithContentFiltersTest, AllFiltersEnabled) { +TEST_P(FamilyLinkUserMetricsProviderWithContentFiltersAndroidTest, + AllFiltersEnabled) { CreateProfiles(GetParam().profile_count); SetBrowserContentFilters(true); SetSearchContentFilters(true); @@ -714,7 +689,7 @@ INSTANTIATE_TEST_SUITE_P( , - FamilyLinkUserMetricsProviderWithContentFiltersTest, + FamilyLinkUserMetricsProviderWithContentFiltersAndroidTest, testing::ValuesIn<ContentFiltersTestCase>({ {1, "SingleProfile"}, {2, "MultipleProfiles"},
diff --git a/chrome/browser/new_tab_page/new_tab_page_realbox_interactive_uitest.cc b/chrome/browser/new_tab_page/new_tab_page_realbox_interactive_uitest.cc index b367ff9..18a8ea6 100644 --- a/chrome/browser/new_tab_page/new_tab_page_realbox_interactive_uitest.cc +++ b/chrome/browser/new_tab_page/new_tab_page_realbox_interactive_uitest.cc
@@ -160,17 +160,6 @@ } } - // TODO(crbug.com/452000330): Pull this out into the common Web UI interaction - // utility helper. - auto WaitForAndScrollToElement( - const ui::ElementIdentifier& ntp_id, - const WebContentsInteractionTestUtil::DeepQuery& query) { - auto steps = Steps(WaitForElementToRender(ntp_id, query), - ScrollIntoView(ntp_id, query)); - AddDescriptionPrefix(steps, __func__); - return steps; - } - protected: ui::MockOsSettingsProvider& os_settings_provider() { return os_settings_provider_;
diff --git a/chrome/browser/new_tab_page/ntp_promo/ntp_promo_interactive_uitest.cc b/chrome/browser/new_tab_page/ntp_promo/ntp_promo_interactive_uitest.cc index 02fd769..bd612428 100644 --- a/chrome/browser/new_tab_page/ntp_promo/ntp_promo_interactive_uitest.cc +++ b/chrome/browser/new_tab_page/ntp_promo/ntp_promo_interactive_uitest.cc
@@ -254,15 +254,6 @@ } } - auto WaitForAndScrollToElement( - const ui::ElementIdentifier& ntp_id, - const WebContentsInteractionTestUtil::DeepQuery& query) { - auto steps = Steps(WaitForElementToRender(ntp_id, query), - ScrollIntoView(ntp_id, query)); - AddDescriptionPrefix(steps, __func__); - return steps; - } - auto GetPromoIconPath() const { return GetFirstPromoPath() + kPromoIconId; } auto WaitForPromoIcon(std::string_view expected_icon) {
diff --git a/chrome/browser/ntp_customization/BUILD.gn b/chrome/browser/ntp_customization/BUILD.gn index f4cd2962..3a0c6ce 100644 --- a/chrome/browser/ntp_customization/BUILD.gn +++ b/chrome/browser/ntp_customization/BUILD.gn
@@ -235,6 +235,7 @@ "junit/src/org/chromium/chrome/browser/ntp_customization/theme/chrome_colors/NtpChromeColorsLayoutViewBinderUnitTest.java", "junit/src/org/chromium/chrome/browser/ntp_customization/theme/chrome_colors/NtpThemeColorInfoUnitTest.java", "junit/src/org/chromium/chrome/browser/ntp_customization/theme/chrome_colors/NtpThemeColorUtilsUnitTest.java", + "junit/src/org/chromium/chrome/browser/ntp_customization/theme/daily_refresh/NtpThemeDailyRefreshManagerUnitTest.java", "junit/src/org/chromium/chrome/browser/ntp_customization/theme/theme_collections/NtpSingleThemeCollectionCoordinatorUnitTest.java", "junit/src/org/chromium/chrome/browser/ntp_customization/theme/theme_collections/NtpThemeCollectionBridgeUnitTest.java", "junit/src/org/chromium/chrome/browser/ntp_customization/theme/theme_collections/NtpThemeCollectionManagerUnitTest.java", @@ -250,6 +251,7 @@ ":java_resources", "//base:base_java", "//base:base_java_test_support", + "//base:base_java_test_support_uncommon", "//base:base_junit_test_support", "//chrome/android:chrome_java", "//chrome/browser/composeplate/android:java_resources",
diff --git a/chrome/browser/ntp_customization/junit/src/org/chromium/chrome/browser/ntp_customization/theme/daily_refresh/NtpThemeDailyRefreshManagerUnitTest.java b/chrome/browser/ntp_customization/junit/src/org/chromium/chrome/browser/ntp_customization/theme/daily_refresh/NtpThemeDailyRefreshManagerUnitTest.java index 9e6a2e71..199e0e9 100644 --- a/chrome/browser/ntp_customization/junit/src/org/chromium/chrome/browser/ntp_customization/theme/daily_refresh/NtpThemeDailyRefreshManagerUnitTest.java +++ b/chrome/browser/ntp_customization/junit/src/org/chromium/chrome/browser/ntp_customization/theme/daily_refresh/NtpThemeDailyRefreshManagerUnitTest.java
@@ -14,7 +14,6 @@ import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; -import org.mockito.Mock; import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; import org.robolectric.annotation.Config; @@ -36,8 +35,6 @@ @Rule public MockitoRule mMockitoJUnit = MockitoJUnit.rule(); @Rule public FakeTimeTestRule mFakeTime = new FakeTimeTestRule(); - @Mock private NtpCustomizationUtils mNtpCustomizationUtils; - private NtpThemeDailyRefreshManager mManager; @Before @@ -66,34 +63,44 @@ @Test public void testIsDailyRefreshEnabled_Disabled() { - mNtpCustomizationUtils.setIsChromeColorDailyRefreshEnabledToSharedPreference(false); + NtpCustomizationUtils.setIsChromeColorDailyRefreshEnabledToSharedPreference(false); assertFalse(mManager.isDailyRefreshEnabled(NtpBackgroundImageType.CHROME_COLOR)); } @Test public void testIsDailyRefreshEnabled_NotChromeColor() { + NtpCustomizationUtils.setIsChromeColorDailyRefreshEnabledToSharedPreference(true); assertFalse(mManager.isDailyRefreshEnabled(NtpBackgroundImageType.IMAGE_FROM_DISK)); } @Test public void testIsDailyRefreshEnabled_Within24Hours() { NtpCustomizationUtils.setIsChromeColorDailyRefreshEnabledToSharedPreference(true); - assertFalse(mManager.isDailyRefreshEnabled(NtpBackgroundImageType.CHROME_COLOR)); - } + NtpCustomizationUtils.setDailyRefreshTimestampToSharedPreference( + TimeUtils.currentTimeMillis()); - @Test - public void testIsDailyRefreshEnabled_After24Hours() { - NtpCustomizationUtils.setIsChromeColorDailyRefreshEnabledToSharedPreference(true); - mFakeTime.advanceMillis(TimeUtils.MILLISECONDS_PER_DAY + 10); - assertTrue(mManager.isDailyRefreshEnabled(NtpBackgroundImageType.CHROME_COLOR)); + assertFalse(mManager.isDailyRefreshEnabled(NtpBackgroundImageType.CHROME_COLOR)); } @Test @Features.EnableFeatures({ ChromeFeatureList.NEW_TAB_PAGE_CUSTOMIZATION_V2 + ":force_daily_refresh/true" }) - public void testIsDailyRefreshEnabled_ForceUpdate() { + public void testIsDailyRefreshEnabled_Within24Hours_ForceUpdate() { NtpCustomizationUtils.setIsChromeColorDailyRefreshEnabledToSharedPreference(true); + NtpCustomizationUtils.setDailyRefreshTimestampToSharedPreference( + TimeUtils.currentTimeMillis()); + + assertTrue(mManager.isDailyRefreshEnabled(NtpBackgroundImageType.CHROME_COLOR)); + } + + @Test + public void testIsDailyRefreshEnabled_After24Hours() { + NtpCustomizationUtils.setIsChromeColorDailyRefreshEnabledToSharedPreference(true); + NtpCustomizationUtils.setDailyRefreshTimestampToSharedPreference( + TimeUtils.currentTimeMillis()); + mFakeTime.advanceMillis(TimeUtils.MILLISECONDS_PER_DAY + 10); + assertTrue(mManager.isDailyRefreshEnabled(NtpBackgroundImageType.CHROME_COLOR)); }
diff --git a/chrome/browser/password_manager/actor_login/internal/actor_login_delegate_impl.cc b/chrome/browser/password_manager/actor_login/internal/actor_login_delegate_impl.cc index e86e6eb..046d7717 100644 --- a/chrome/browser/password_manager/actor_login/internal/actor_login_delegate_impl.cc +++ b/chrome/browser/password_manager/actor_login/internal/actor_login_delegate_impl.cc
@@ -146,8 +146,9 @@ if (!base::FeatureList::IsEnabled(password_manager::features::kActorLogin)) { base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask( - FROM_HERE, base::BindOnce(std::move(callback), - base::unexpected(ActorLoginError::kUnknown))); + FROM_HERE, + base::BindOnce(std::move(callback), + base::unexpected(ActorLoginError::kFeatureDisabled))); return; }
diff --git a/chrome/browser/password_manager/actor_login/internal/actor_login_delegate_impl_unittest.cc b/chrome/browser/password_manager/actor_login/internal/actor_login_delegate_impl_unittest.cc index 3d87f25..4b59b84 100644 --- a/chrome/browser/password_manager/actor_login/internal/actor_login_delegate_impl_unittest.cc +++ b/chrome/browser/password_manager/actor_login/internal/actor_login_delegate_impl_unittest.cc
@@ -315,9 +315,7 @@ future.GetCallback()); ASSERT_FALSE(future.Get().has_value()); - // When the ActorLogin features is disabled, the delegate returns - // `ActorLoginError::kUnknown`. - EXPECT_EQ(future.Get().error(), ActorLoginError::kUnknown); + EXPECT_EQ(future.Get().error(), ActorLoginError::kFeatureDisabled); } TEST_F(ActorLoginDelegateImplTest, AttemptLogin_FeatureOn) {
diff --git a/chrome/browser/policy/configuration_policy_handler_list_factory.cc b/chrome/browser/policy/configuration_policy_handler_list_factory.cc index 002c52c..bdd48ba2 100644 --- a/chrome/browser/policy/configuration_policy_handler_list_factory.cc +++ b/chrome/browser/policy/configuration_policy_handler_list_factory.cc
@@ -2236,11 +2236,11 @@ base::Value::Type::BOOLEAN }, #endif // !BUILDFLAG(IS_MAC) && BUILDFLAG(ENABLE_EXTENSIONS) -#if !BUILDFLAG(IS_CHROMEOS) && BUILDFLAG(ENABLE_EXTENSIONS) +#if !BUILDFLAG(IS_CHROMEOS) && BUILDFLAG(ENABLE_EXTENSIONS_CORE) { key::kBlockExternalExtensions, extensions::pref_names::kBlockExternalExtensions, base::Value::Type::BOOLEAN }, -#endif // !BUILDFLAG(IS_CHROMEOS) && BUILDFLAG(ENABLE_EXTENSIONS) +#endif // !BUILDFLAG(IS_CHROMEOS) && BUILDFLAG(ENABLE_EXTENSIONS_CORE) #if BUILDFLAG(ENABLE_EXTENSIONS) { key::kExtensionExtendedBackgroundLifetimeForPortConnectionsToUrls, @@ -3368,12 +3368,12 @@ handlers->AddHandler(std::make_unique<StringMappingListPolicyHandler>( key::kExtensionAllowedTypes, extensions::pref_names::kAllowedTypes, base::BindRepeating(GetExtensionAllowedTypesMap))); -#endif // BUILDFLAG(ENABLE_EXTENSIONS_CORE) -#if BUILDFLAG(ENABLE_EXTENSIONS) handlers->AddHandler(std::make_unique<IntRangePolicyHandler>( key::kExtensionUnpublishedAvailability, extensions::pref_names::kExtensionUnpublishedAvailability, /*min=*/0, /*max=*/1, /*clamp=*/false)); +#endif // BUILDFLAG(ENABLE_EXTENSIONS_CORE) +#if BUILDFLAG(ENABLE_EXTENSIONS) handlers->AddHandler(std::make_unique<ExtensionDeveloperModePolicyHandler>()); handlers->AddHandler(std::make_unique<SimplePolicyHandler>( key::kExtensionInstallCloudPolicyChecksEnabled,
diff --git a/chrome/browser/prefetch/android/java/src/org/chromium/chrome/browser/prefetch/settings/PreloadPagesSettingsFragment.java b/chrome/browser/prefetch/android/java/src/org/chromium/chrome/browser/prefetch/settings/PreloadPagesSettingsFragment.java index 76335bf..4f62633 100644 --- a/chrome/browser/prefetch/android/java/src/org/chromium/chrome/browser/prefetch/settings/PreloadPagesSettingsFragment.java +++ b/chrome/browser/prefetch/android/java/src/org/chromium/chrome/browser/prefetch/settings/PreloadPagesSettingsFragment.java
@@ -15,6 +15,7 @@ import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.settings.ChromeManagedPreferenceDelegate; import org.chromium.chrome.browser.settings.SettingsNavigationFactory; +import org.chromium.chrome.browser.settings.search.ChromeBaseSearchIndexProvider; import org.chromium.components.browser_ui.settings.ManagedPreferenceDelegate; /** Fragment containing Preload Pages settings. */ @@ -106,4 +107,10 @@ public @AnimationType int getAnimationType() { return AnimationType.PROPERTY; } + + // TODO(crbug.com/444470792): Determine what pieces of logic are dynamic and need handling. For + // this one, it's going to be the disclaimer text. But check for other prefs. + public static final ChromeBaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = + new ChromeBaseSearchIndexProvider( + PreloadPagesSettingsFragment.class.getName(), R.xml.preload_pages_preferences); }
diff --git a/chrome/browser/preloading/prefetch/zero_suggest_prefetch/zero_suggest_prefetch_tab_helper_browsertest.cc b/chrome/browser/preloading/prefetch/zero_suggest_prefetch/zero_suggest_prefetch_tab_helper_browsertest.cc index c944c0d..2f4803e4 100644 --- a/chrome/browser/preloading/prefetch/zero_suggest_prefetch/zero_suggest_prefetch_tab_helper_browsertest.cc +++ b/chrome/browser/preloading/prefetch/zero_suggest_prefetch/zero_suggest_prefetch_tab_helper_browsertest.cc
@@ -138,7 +138,7 @@ browser(), GURL(chrome::kChromeUINewTabPageURL), WindowOpenDisposition::CURRENT_TAB, ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP)); - ASSERT_EQ(1, browser()->tab_strip_model()->GetTabCount()); + ASSERT_EQ(1, browser()->tab_strip_model()->count()); testing::Mock::VerifyAndClearExpectations(controller_); } @@ -152,7 +152,7 @@ browser(), GURL(chrome::kChromeUINewTabPageURL), WindowOpenDisposition::NEW_FOREGROUND_TAB, ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP)); - ASSERT_EQ(2, browser()->tab_strip_model()->GetTabCount()); + ASSERT_EQ(2, browser()->tab_strip_model()->count()); testing::Mock::VerifyAndClearExpectations(controller_); } @@ -189,7 +189,7 @@ EXPECT_TRUE(ui_test_utils::NavigateToURLWithDisposition( browser(), GURL(srp_url), WindowOpenDisposition::CURRENT_TAB, ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP)); - ASSERT_EQ(1, browser()->tab_strip_model()->GetTabCount()); + ASSERT_EQ(1, browser()->tab_strip_model()->count()); testing::Mock::VerifyAndClearExpectations(controller_); } @@ -202,7 +202,7 @@ EXPECT_TRUE(ui_test_utils::NavigateToURLWithDisposition( browser(), GURL(srp_url), WindowOpenDisposition::NEW_BACKGROUND_TAB, ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP)); - ASSERT_EQ(2, browser()->tab_strip_model()->GetTabCount()); + ASSERT_EQ(2, browser()->tab_strip_model()->count()); testing::Mock::VerifyAndClearExpectations(controller_); } @@ -215,7 +215,7 @@ EXPECT_TRUE(ui_test_utils::NavigateToURLWithDisposition( browser(), GURL(srp_url), WindowOpenDisposition::NEW_FOREGROUND_TAB, ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP)); - ASSERT_EQ(3, browser()->tab_strip_model()->GetTabCount()); + ASSERT_EQ(3, browser()->tab_strip_model()->count()); testing::Mock::VerifyAndClearExpectations(controller_); } @@ -251,7 +251,7 @@ EXPECT_TRUE(ui_test_utils::NavigateToURLWithDisposition( browser(), GURL(web_url), WindowOpenDisposition::CURRENT_TAB, ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP)); - ASSERT_EQ(1, browser()->tab_strip_model()->GetTabCount()); + ASSERT_EQ(1, browser()->tab_strip_model()->count()); testing::Mock::VerifyAndClearExpectations(controller_); } @@ -264,7 +264,7 @@ EXPECT_TRUE(ui_test_utils::NavigateToURLWithDisposition( browser(), GURL(web_url), WindowOpenDisposition::NEW_BACKGROUND_TAB, ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP)); - ASSERT_EQ(2, browser()->tab_strip_model()->GetTabCount()); + ASSERT_EQ(2, browser()->tab_strip_model()->count()); testing::Mock::VerifyAndClearExpectations(controller_); } @@ -277,7 +277,7 @@ EXPECT_TRUE(ui_test_utils::NavigateToURLWithDisposition( browser(), GURL(web_url), WindowOpenDisposition::NEW_FOREGROUND_TAB, ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP)); - ASSERT_EQ(3, browser()->tab_strip_model()->GetTabCount()); + ASSERT_EQ(3, browser()->tab_strip_model()->count()); testing::Mock::VerifyAndClearExpectations(controller_); }
diff --git a/chrome/browser/privacy/BUILD.gn b/chrome/browser/privacy/BUILD.gn index 1ee7fa8..d26f3e7 100644 --- a/chrome/browser/privacy/BUILD.gn +++ b/chrome/browser/privacy/BUILD.gn
@@ -32,7 +32,6 @@ "//chrome/browser/preferences:java", "//chrome/browser/profiles/android:java", "//chrome/browser/settings:java", - "//chrome/browser/settings:search_java", "//components/browser_ui/settings/android:java", "//components/browser_ui/widget/android:java", "//components/minidump_uploader:minidump_uploader_java",
diff --git a/chrome/browser/privacy/java/src/org/chromium/chrome/browser/privacy/secure_dns/SecureDnsSettings.java b/chrome/browser/privacy/java/src/org/chromium/chrome/browser/privacy/secure_dns/SecureDnsSettings.java index 94261d97..b2d9971 100644 --- a/chrome/browser/privacy/java/src/org/chromium/chrome/browser/privacy/secure_dns/SecureDnsSettings.java +++ b/chrome/browser/privacy/java/src/org/chromium/chrome/browser/privacy/secure_dns/SecureDnsSettings.java
@@ -17,7 +17,7 @@ import org.chromium.chrome.browser.privacy.secure_dns.SecureDnsProviderPreference.State; import org.chromium.chrome.browser.settings.ChromeBaseSettingsFragment; import org.chromium.chrome.browser.settings.ChromeManagedPreferenceDelegate; -import org.chromium.chrome.browser.settings.search.BaseSearchIndexProvider; +import org.chromium.chrome.browser.settings.search.ChromeBaseSearchIndexProvider; import org.chromium.components.browser_ui.settings.ChromeSwitchPreference; import org.chromium.components.browser_ui.settings.SettingsUtils; import org.chromium.net.SecureDnsMode; @@ -175,7 +175,7 @@ return AnimationType.PROPERTY; } - public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = - new BaseSearchIndexProvider( + public static final ChromeBaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = + new ChromeBaseSearchIndexProvider( SecureDnsSettings.class.getName(), R.xml.secure_dns_settings); }
diff --git a/chrome/browser/privacy_sandbox/android/BUILD.gn b/chrome/browser/privacy_sandbox/android/BUILD.gn index afb3548f..c8c74ea 100644 --- a/chrome/browser/privacy_sandbox/android/BUILD.gn +++ b/chrome/browser/privacy_sandbox/android/BUILD.gn
@@ -57,7 +57,6 @@ "//chrome/browser/preferences:java", "//chrome/browser/profiles/android:java", "//chrome/browser/settings:java", - "//chrome/browser/settings:search_java", "//chrome/browser/ui/android/edge_to_edge:java", "//chrome/browser/ui/messages/android:java", "//components/browser_ui/bottomsheet/android:java",
diff --git a/chrome/browser/privacy_sandbox/android/java/src/org/chromium/chrome/browser/privacy_sandbox/AdMeasurementFragment.java b/chrome/browser/privacy_sandbox/android/java/src/org/chromium/chrome/browser/privacy_sandbox/AdMeasurementFragment.java index d80abf3..23ddae4 100644 --- a/chrome/browser/privacy_sandbox/android/java/src/org/chromium/chrome/browser/privacy_sandbox/AdMeasurementFragment.java +++ b/chrome/browser/privacy_sandbox/android/java/src/org/chromium/chrome/browser/privacy_sandbox/AdMeasurementFragment.java
@@ -18,7 +18,7 @@ import org.chromium.chrome.browser.preferences.Pref; import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.settings.ChromeManagedPreferenceDelegate; -import org.chromium.chrome.browser.settings.search.BaseSearchIndexProvider; +import org.chromium.chrome.browser.settings.search.ChromeBaseSearchIndexProvider; import org.chromium.components.browser_ui.settings.ChromeSwitchPreference; import org.chromium.components.browser_ui.settings.ClickableSpansTextMessagePreference; import org.chromium.components.browser_ui.settings.SettingsFragment; @@ -133,7 +133,7 @@ return SettingsFragment.AnimationType.PROPERTY; } - public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = - new BaseSearchIndexProvider( + public static final ChromeBaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = + new ChromeBaseSearchIndexProvider( AdMeasurementFragment.class.getName(), R.xml.ad_measurement_preference); }
diff --git a/chrome/browser/privacy_sandbox/android/java/src/org/chromium/chrome/browser/privacy_sandbox/FledgeAllSitesFragment.java b/chrome/browser/privacy_sandbox/android/java/src/org/chromium/chrome/browser/privacy_sandbox/FledgeAllSitesFragment.java index c382f0d4..824bf5e 100644 --- a/chrome/browser/privacy_sandbox/android/java/src/org/chromium/chrome/browser/privacy_sandbox/FledgeAllSitesFragment.java +++ b/chrome/browser/privacy_sandbox/android/java/src/org/chromium/chrome/browser/privacy_sandbox/FledgeAllSitesFragment.java
@@ -16,7 +16,7 @@ import org.chromium.base.supplier.ObservableSupplierImpl; import org.chromium.build.annotations.NullMarked; import org.chromium.build.annotations.Nullable; -import org.chromium.chrome.browser.settings.search.BaseSearchIndexProvider; +import org.chromium.chrome.browser.settings.search.ChromeBaseSearchIndexProvider; import org.chromium.chrome.browser.ui.messages.snackbar.Snackbar; import org.chromium.components.browser_ui.settings.SettingsFragment; import org.chromium.components.favicon.LargeIconBridge; @@ -116,6 +116,6 @@ return SettingsFragment.AnimationType.PROPERTY; } - public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = - new BaseSearchIndexProvider(FledgeAllSitesFragment.class.getName()); + public static final ChromeBaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = + new ChromeBaseSearchIndexProvider(FledgeAllSitesFragment.class.getName(), 0); }
diff --git a/chrome/browser/privacy_sandbox/android/java/src/org/chromium/chrome/browser/privacy_sandbox/FledgeBlockedSitesFragment.java b/chrome/browser/privacy_sandbox/android/java/src/org/chromium/chrome/browser/privacy_sandbox/FledgeBlockedSitesFragment.java index 2afbeeb0..f1f49a5 100644 --- a/chrome/browser/privacy_sandbox/android/java/src/org/chromium/chrome/browser/privacy_sandbox/FledgeBlockedSitesFragment.java +++ b/chrome/browser/privacy_sandbox/android/java/src/org/chromium/chrome/browser/privacy_sandbox/FledgeBlockedSitesFragment.java
@@ -15,7 +15,7 @@ import org.chromium.base.supplier.ObservableSupplierImpl; import org.chromium.build.annotations.NullMarked; import org.chromium.build.annotations.Nullable; -import org.chromium.chrome.browser.settings.search.BaseSearchIndexProvider; +import org.chromium.chrome.browser.settings.search.ChromeBaseSearchIndexProvider; import org.chromium.chrome.browser.ui.messages.snackbar.Snackbar; import org.chromium.components.browser_ui.settings.SettingsFragment; import org.chromium.components.browser_ui.settings.SettingsUtils; @@ -126,7 +126,7 @@ return SettingsFragment.AnimationType.PROPERTY; } - public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = - new BaseSearchIndexProvider( + public static final ChromeBaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = + new ChromeBaseSearchIndexProvider( FledgeBlockedSitesFragment.class.getName(), R.xml.block_list_preference); }
diff --git a/chrome/browser/privacy_sandbox/android/java/src/org/chromium/chrome/browser/privacy_sandbox/FledgeFragment.java b/chrome/browser/privacy_sandbox/android/java/src/org/chromium/chrome/browser/privacy_sandbox/FledgeFragment.java index 6000884d9..1099f66 100644 --- a/chrome/browser/privacy_sandbox/android/java/src/org/chromium/chrome/browser/privacy_sandbox/FledgeFragment.java +++ b/chrome/browser/privacy_sandbox/android/java/src/org/chromium/chrome/browser/privacy_sandbox/FledgeFragment.java
@@ -20,8 +20,7 @@ import org.chromium.chrome.browser.preferences.Pref; import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.settings.ChromeManagedPreferenceDelegate; -import org.chromium.chrome.browser.settings.search.BaseSearchIndexProvider; -import org.chromium.chrome.browser.settings.search.SettingsIndexData; +import org.chromium.chrome.browser.settings.search.ChromeBaseSearchIndexProvider; import org.chromium.chrome.browser.ui.messages.snackbar.Snackbar; import org.chromium.components.browser_ui.settings.ChromeBasePreference; import org.chromium.components.browser_ui.settings.ChromeSwitchPreference; @@ -29,6 +28,7 @@ import org.chromium.components.browser_ui.settings.SettingsFragment; import org.chromium.components.browser_ui.settings.SettingsUtils; import org.chromium.components.browser_ui.settings.TextMessagePreference; +import org.chromium.components.browser_ui.settings.search.SettingsIndexData; import org.chromium.components.embedder_support.util.UrlConstants; import org.chromium.components.favicon.LargeIconBridge; import org.chromium.components.prefs.PrefService; @@ -293,8 +293,9 @@ return SettingsFragment.AnimationType.PROPERTY; } - public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = - new BaseSearchIndexProvider(FledgeFragment.class.getName(), R.xml.fledge_preference) { + public static final ChromeBaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = + new ChromeBaseSearchIndexProvider( + FledgeFragment.class.getName(), R.xml.fledge_preference) { @Override public void updateDynamicPreferences(Context context, SettingsIndexData indexData) { // We do not remove FLEDGE_TOGGLE_PREFERENCE. This is the "Site-suggested ads"
diff --git a/chrome/browser/privacy_sandbox/android/java/src/org/chromium/chrome/browser/privacy_sandbox/FledgeLearnMoreFragment.java b/chrome/browser/privacy_sandbox/android/java/src/org/chromium/chrome/browser/privacy_sandbox/FledgeLearnMoreFragment.java index e4169d9e..263c5ac 100644 --- a/chrome/browser/privacy_sandbox/android/java/src/org/chromium/chrome/browser/privacy_sandbox/FledgeLearnMoreFragment.java +++ b/chrome/browser/privacy_sandbox/android/java/src/org/chromium/chrome/browser/privacy_sandbox/FledgeLearnMoreFragment.java
@@ -13,7 +13,7 @@ import org.chromium.base.supplier.ObservableSupplierImpl; import org.chromium.build.annotations.NullMarked; import org.chromium.build.annotations.Nullable; -import org.chromium.chrome.browser.settings.search.BaseSearchIndexProvider; +import org.chromium.chrome.browser.settings.search.ChromeBaseSearchIndexProvider; import org.chromium.components.browser_ui.settings.SettingsFragment; import org.chromium.components.browser_ui.settings.SettingsUtils; import org.chromium.components.browser_ui.settings.TextMessagePreference; @@ -70,7 +70,7 @@ return SettingsFragment.AnimationType.PROPERTY; } - public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = - new BaseSearchIndexProvider( + public static final ChromeBaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = + new ChromeBaseSearchIndexProvider( FledgeLearnMoreFragment.class.getName(), R.xml.fledge_learn_more_preference); }
diff --git a/chrome/browser/privacy_sandbox/android/java/src/org/chromium/chrome/browser/privacy_sandbox/PrivacySandboxSettingsFragment.java b/chrome/browser/privacy_sandbox/android/java/src/org/chromium/chrome/browser/privacy_sandbox/PrivacySandboxSettingsFragment.java index a54fe647..d0fb3d2 100644 --- a/chrome/browser/privacy_sandbox/android/java/src/org/chromium/chrome/browser/privacy_sandbox/PrivacySandboxSettingsFragment.java +++ b/chrome/browser/privacy_sandbox/android/java/src/org/chromium/chrome/browser/privacy_sandbox/PrivacySandboxSettingsFragment.java
@@ -14,11 +14,11 @@ import org.chromium.build.annotations.NullMarked; import org.chromium.build.annotations.Nullable; import org.chromium.chrome.browser.profiles.Profile; -import org.chromium.chrome.browser.settings.search.BaseSearchIndexProvider; -import org.chromium.chrome.browser.settings.search.SettingsIndexData; +import org.chromium.chrome.browser.settings.search.ChromeBaseSearchIndexProvider; import org.chromium.components.browser_ui.settings.ChromeBasePreference; import org.chromium.components.browser_ui.settings.SettingsFragment; import org.chromium.components.browser_ui.settings.SettingsUtils; +import org.chromium.components.browser_ui.settings.search.SettingsIndexData; /** Settings fragment for privacy sandbox settings. */ @NullMarked @@ -100,8 +100,8 @@ return SettingsFragment.AnimationType.PROPERTY; } - public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = - new BaseSearchIndexProvider( + public static final ChromeBaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = + new ChromeBaseSearchIndexProvider( PrivacySandboxSettingsFragment.class.getName(), R.xml.privacy_sandbox_preferences) { @Override
diff --git a/chrome/browser/privacy_sandbox/android/java/src/org/chromium/chrome/browser/privacy_sandbox/TopicsBlockedFragment.java b/chrome/browser/privacy_sandbox/android/java/src/org/chromium/chrome/browser/privacy_sandbox/TopicsBlockedFragment.java index f3d4569b..b42a8e1 100644 --- a/chrome/browser/privacy_sandbox/android/java/src/org/chromium/chrome/browser/privacy_sandbox/TopicsBlockedFragment.java +++ b/chrome/browser/privacy_sandbox/android/java/src/org/chromium/chrome/browser/privacy_sandbox/TopicsBlockedFragment.java
@@ -15,7 +15,7 @@ import org.chromium.base.supplier.ObservableSupplierImpl; import org.chromium.build.annotations.NullMarked; import org.chromium.build.annotations.Nullable; -import org.chromium.chrome.browser.settings.search.BaseSearchIndexProvider; +import org.chromium.chrome.browser.settings.search.ChromeBaseSearchIndexProvider; import org.chromium.chrome.browser.ui.messages.snackbar.Snackbar; import org.chromium.components.browser_ui.settings.SettingsFragment; import org.chromium.components.browser_ui.settings.SettingsUtils; @@ -114,7 +114,7 @@ return SettingsFragment.AnimationType.PROPERTY; } - public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = - new BaseSearchIndexProvider( + public static final ChromeBaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = + new ChromeBaseSearchIndexProvider( TopicsBlockedFragment.class.getName(), R.xml.block_list_preference); }
diff --git a/chrome/browser/privacy_sandbox/android/java/src/org/chromium/chrome/browser/privacy_sandbox/TopicsFragment.java b/chrome/browser/privacy_sandbox/android/java/src/org/chromium/chrome/browser/privacy_sandbox/TopicsFragment.java index 5b76b91..af6a21b 100644 --- a/chrome/browser/privacy_sandbox/android/java/src/org/chromium/chrome/browser/privacy_sandbox/TopicsFragment.java +++ b/chrome/browser/privacy_sandbox/android/java/src/org/chromium/chrome/browser/privacy_sandbox/TopicsFragment.java
@@ -20,7 +20,7 @@ import org.chromium.chrome.browser.preferences.Pref; import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.settings.ChromeManagedPreferenceDelegate; -import org.chromium.chrome.browser.settings.search.BaseSearchIndexProvider; +import org.chromium.chrome.browser.settings.search.ChromeBaseSearchIndexProvider; import org.chromium.chrome.browser.ui.messages.snackbar.Snackbar; import org.chromium.components.browser_ui.settings.ChromeSwitchPreference; import org.chromium.components.browser_ui.settings.ClickableSpansTextMessagePreference; @@ -291,6 +291,7 @@ return SettingsFragment.AnimationType.PROPERTY; } - public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = - new BaseSearchIndexProvider(TopicsFragment.class.getName(), R.xml.topics_preference); + public static final ChromeBaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = + new ChromeBaseSearchIndexProvider( + TopicsFragment.class.getName(), R.xml.topics_preference); }
diff --git a/chrome/browser/privacy_sandbox/android/java/src/org/chromium/chrome/browser/privacy_sandbox/TopicsManageFragment.java b/chrome/browser/privacy_sandbox/android/java/src/org/chromium/chrome/browser/privacy_sandbox/TopicsManageFragment.java index 4eaf4798..1c22c2c 100644 --- a/chrome/browser/privacy_sandbox/android/java/src/org/chromium/chrome/browser/privacy_sandbox/TopicsManageFragment.java +++ b/chrome/browser/privacy_sandbox/android/java/src/org/chromium/chrome/browser/privacy_sandbox/TopicsManageFragment.java
@@ -15,7 +15,7 @@ import org.chromium.base.supplier.ObservableSupplierImpl; import org.chromium.build.annotations.NullMarked; import org.chromium.build.annotations.Nullable; -import org.chromium.chrome.browser.settings.search.BaseSearchIndexProvider; +import org.chromium.chrome.browser.settings.search.ChromeBaseSearchIndexProvider; import org.chromium.components.browser_ui.settings.SettingsFragment; import org.chromium.components.browser_ui.settings.SettingsUtils; import org.chromium.ui.modaldialog.DialogDismissalCause; @@ -164,7 +164,7 @@ return SettingsFragment.AnimationType.PROPERTY; } - public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = - new BaseSearchIndexProvider( + public static final ChromeBaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = + new ChromeBaseSearchIndexProvider( TopicsManageFragment.class.getName(), R.xml.topics_manage_preference); }
diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu.cc b/chrome/browser/renderer_context_menu/render_view_context_menu.cc index 4baf5fe..ffdc88b 100644 --- a/chrome/browser/renderer_context_menu/render_view_context_menu.cc +++ b/chrome/browser/renderer_context_menu/render_view_context_menu.cc
@@ -850,7 +850,7 @@ #endif // BUILDFLAG(GOOGLE_CHROME_BRANDING) } -bool IsGlicWindow(RenderViewContextMenu* menu, +bool IsGlicWindow(const RenderViewContextMenu* menu, content::BrowserContext* browser_context) { #if BUILDFLAG(ENABLE_GLIC) if (glic::GlicEnabling::IsEnabledByFlags()) { @@ -1185,6 +1185,15 @@ if (!media_image && content_type_->SupportsGroup(ContextMenuContentType::ITEM_GROUP_PRINT)) { AppendPrintItem(); + } else { +#if BUILDFLAG(ENABLE_GLIC) + + if (IsGlicWindow(this, browser_context_) && + base::FeatureList::IsEnabled(features::kGlicPrintMenuItem) && + glic::GlicEnabling::IsMultiInstanceEnabled()) { + AppendPrintItem(); + } +#endif // BUILDFLAG(ENABLE_GLIC) } // ITEM_GROUP_SMART_SELECTION is for selected text that is not a link. @@ -4006,6 +4015,15 @@ } bool RenderViewContextMenu::IsPrintPreviewEnabled() const { +#if BUILDFLAG(ENABLE_GLIC) + if (IsGlicWindow(this, browser_context_) && + base::FeatureList::IsEnabled(features::kGlicPrintMenuItem) && + glic::GlicEnabling::IsMultiInstanceEnabled()) { + return GetPrefs(browser_context_)->GetBoolean(prefs::kPrintingEnabled) && + (source_web_contents_ && !source_web_contents_->IsCrashed()); + } +#endif // BUILDFLAG(ENABLE_GLIC) + if (params_.media_type != ContextMenuDataMediaType::kNone && !(params_.media_flags & ContextMenuData::kMediaCanPrint)) { return false;
diff --git a/chrome/browser/resources/app_settings/uninstall_button.ts b/chrome/browser/resources/app_settings/uninstall_button.ts index bff0882..f7f7d77 100644 --- a/chrome/browser/resources/app_settings/uninstall_button.ts +++ b/chrome/browser/resources/app_settings/uninstall_button.ts
@@ -11,6 +11,7 @@ import {BrowserProxy} from 'chrome://resources/cr_components/app_management/browser_proxy.js'; import {AppManagementUserAction} from 'chrome://resources/cr_components/app_management/constants.js'; import {recordAppManagementUserAction} from 'chrome://resources/cr_components/app_management/util.js'; +import {assertNotReachedCase} from 'chrome://resources/js/assert.js'; import {CrLitElement} from 'chrome://resources/lit/v3_0/lit.rollup.js'; import {getCss} from './uninstall_button.css.js'; @@ -45,8 +46,8 @@ /** * Returns true if the button should be disabled due to app install type. * - * If the compiler complains about the "lack of ending return statement", - * you maybe just added a new InstallReason and need to add a new case. + * If the compiler complains about the "Argument ... is not assignable to + * parameter of type 'never', you need to add a new 'case' below. */ protected getDisableState_(): boolean { switch (this.app.installReason) { @@ -63,6 +64,8 @@ case InstallReason.kSubApp: case InstallReason.kCommandLine: return false; + default: + assertNotReachedCase(this.app.installReason); } }
diff --git a/chrome/browser/resources/bluetooth_internals/devices_page.ts b/chrome/browser/resources/bluetooth_internals/devices_page.ts index d538da6..858325d 100644 --- a/chrome/browser/resources/bluetooth_internals/devices_page.ts +++ b/chrome/browser/resources/bluetooth_internals/devices_page.ts
@@ -8,6 +8,8 @@ */ import './device_table.js'; +import {assertNotReachedCase} from 'chrome://resources/js/assert.js'; + import type {DeviceInfo} from './device.mojom-webui.js'; import type {DeviceCollection} from './device_collection.js'; import type {DeviceTableElement} from './device_table.js'; @@ -81,6 +83,8 @@ this.scanBtn_.disabled = true; this.scanBtn_.textContent = 'Stopping...'; break; + default: + assertNotReachedCase(status); } } }
diff --git a/chrome/browser/resources/bluetooth_internals/value_control.ts b/chrome/browser/resources/bluetooth_internals/value_control.ts index 281fa9a..62a396c 100644 --- a/chrome/browser/resources/bluetooth_internals/value_control.ts +++ b/chrome/browser/resources/bluetooth_internals/value_control.ts
@@ -6,7 +6,7 @@ * Javascript for ValueControl, served from chrome://bluetooth-internals/. */ -import {assert} from 'chrome://resources/js/assert.js'; +import {assert, assertNotReachedCase} from 'chrome://resources/js/assert.js'; import {CustomElement} from 'chrome://resources/js/custom_element.js'; import {GattResult, Property} from './device.mojom-webui.js'; @@ -63,14 +63,14 @@ case ValueDataType.HEXADECIMAL: this.setValueFromHex_(newValue); break; - case ValueDataType.UTF8: this.setValueFromUtf8_(newValue); break; - case ValueDataType.DECIMAL: this.setValueFromDecimal_(newValue); break; + default: + assertNotReachedCase(valueDataType); } } @@ -81,12 +81,12 @@ switch (valueDataType) { case ValueDataType.HEXADECIMAL: return this.toHex_(); - case ValueDataType.UTF8: return this.toUtf8_(); - case ValueDataType.DECIMAL: return this.toDecimal_(); + default: + assertNotReachedCase(valueDataType); } }
diff --git a/chrome/browser/resources/bookmarks/command_manager.ts b/chrome/browser/resources/bookmarks/command_manager.ts index c6135de..7d3fc0b 100644 --- a/chrome/browser/resources/bookmarks/command_manager.ts +++ b/chrome/browser/resources/bookmarks/command_manager.ts
@@ -18,7 +18,7 @@ import type {CrDialogElement} from 'chrome://resources/cr_elements/cr_dialog/cr_dialog.js'; import type {CrLazyRenderLitElement} from 'chrome://resources/cr_elements/cr_lazy_render/cr_lazy_render_lit.js'; import {getToastManager} from 'chrome://resources/cr_elements/cr_toast/cr_toast_manager.js'; -import {assert, assertNotReached} from 'chrome://resources/js/assert.js'; +import {assert, assertNotReached, assertNotReachedCase} from 'chrome://resources/js/assert.js'; import {EventTracker} from 'chrome://resources/js/event_tracker.js'; import {KeyboardShortcutList} from 'chrome://resources/js/keyboard_shortcut_list.js'; import {loadTimeData} from 'chrome://resources/js/load_time_data.js'; @@ -268,8 +268,21 @@ case Command.IMPORT: case Command.HELP_CENTER: return true; + case Command.COPY: + case Command.CUT: + case Command.DESELECT_ALL: + case Command.OPEN: + case Command.OPEN_BOOKMARK: + case Command.OPEN_FOLDER: + case Command.PASTE: + case Command.REDO: + case Command.SELECT_ALL: + case Command.UNDO: + case Command.MAX_VALUE: + return false; + default: + assertNotReachedCase(command); } - assertNotReached(); } protected isCommandEnabled_(command: Command, itemIds: Set<string>): boolean { @@ -462,8 +475,12 @@ case Command.HELP_CENTER: window.open('https://support.google.com/chrome/?p=bookmarks'); break; + case Command.OPEN_BOOKMARK: + case Command.OPEN_FOLDER: + case Command.MAX_VALUE: + break; default: - assertNotReached(); + assertNotReachedCase(command); } this.recordCommandHistogram_( itemIds, 'BookmarkManager.CommandExecuted', command); @@ -674,6 +691,8 @@ case Command.OPEN_SPLIT_VIEW: label = 'menuOpenSplitView'; break; + default: + break; } if (label !== null) { return loadTimeData.getString(label); @@ -697,6 +716,8 @@ return this.getPluralizedOpenAllString_( 'menuOpenAllNewTabGroup', 'menuOpenNewTabGroup', 'menuOpenAllNewTabGroupWithCount'); + default: + break; } assertNotReached(); @@ -758,10 +779,12 @@ Command.ADD_BOOKMARK, Command.ADD_FOLDER, ]; + case MenuSource.NUM_VALUES: case MenuSource.NONE: return []; + default: + assertNotReachedCase(this.menuSource_); } - assertNotReached(); } protected showDividerAfter_(command: Command): boolean { @@ -774,8 +797,9 @@ return this.globalCanEdit_; case Command.PASTE: return this.globalCanEdit_ || this.isSingleBookmark_(this.menuIds_); + default: + return false; } - return false; } private recordCommandHistogram_(
diff --git a/chrome/browser/resources/certificate_manager/navigation.ts b/chrome/browser/resources/certificate_manager/navigation.ts index 0c2e641..11ac37c 100644 --- a/chrome/browser/resources/certificate_manager/navigation.ts +++ b/chrome/browser/resources/certificate_manager/navigation.ts
@@ -6,7 +6,7 @@ * @fileoverview Page navigation utility code. */ -import {assert, assertNotReached} from '//resources/js/assert.js'; +import {assert, assertNotReached, assertNotReachedCase} from '//resources/js/assert.js'; import type {PolymerElement} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {dedupingMixin} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js'; @@ -50,6 +50,8 @@ case Page.CLIENT_CERTS: case Page.CRS_CERTS: return false; + default: + assertNotReachedCase(this.page); } } } @@ -145,7 +147,7 @@ // LINT.IfChange(PageHistogramEnum) - private pageToMetricInt(page: Page) { + private pageToMetricInt(page: Page): number { // These values are persisted to logs. Entries should not be renumbered and // numeric values should never be reused. switch (page) { @@ -165,6 +167,8 @@ // </if> case Page.USER_CERTS: return 6; + default: + assertNotReachedCase(page); } }
diff --git a/chrome/browser/resources/commerce/product_specifications/app.ts b/chrome/browser/resources/commerce/product_specifications/app.ts index 460e1331..36b62f6 100644 --- a/chrome/browser/resources/commerce/product_specifications/app.ts +++ b/chrome/browser/resources/commerce/product_specifications/app.ts
@@ -29,7 +29,7 @@ import type {CrButtonElement} from 'chrome://resources/cr_elements/cr_button/cr_button.js'; import {CrFeedbackOption} from 'chrome://resources/cr_elements/cr_feedback_buttons/cr_feedback_buttons.js'; import type {CrToastElement} from 'chrome://resources/cr_elements/cr_toast/cr_toast.js'; -import {assert} from 'chrome://resources/js/assert.js'; +import {assert, assertNotReachedCase} from 'chrome://resources/js/assert.js'; import {EventTracker} from 'chrome://resources/js/event_tracker.js'; import {loadTimeData} from 'chrome://resources/js/load_time_data.js'; import {OpenWindowProxyImpl} from 'chrome://resources/js/open_window_proxy.js'; @@ -711,6 +711,10 @@ case SectionType.SUGGESTED: recordValue = CompareTableColumnAction.ADD_FROM_SUGGESTED; break; + case SectionType.NONE: + break; + default: + assertNotReachedCase(e.detail.urlSection); } chrome.metricsPrivate.recordEnumerationValue( COLUMN_MODIFICATION_HISTOGRAM_NAME, recordValue, @@ -750,6 +754,10 @@ case SectionType.SUGGESTED: recordValue = CompareTableColumnAction.UPDATE_FROM_SUGGESTED; break; + case SectionType.NONE: + break; + default: + assertNotReachedCase(e.detail.urlSection); } chrome.metricsPrivate.recordEnumerationValue( COLUMN_MODIFICATION_HISTOGRAM_NAME, recordValue, @@ -921,6 +929,8 @@ this.shoppingApi_.setProductSpecificationsUserFeedback( UserFeedback.kThumbsDown); return; + default: + assertNotReachedCase(e.detail.value); } }
diff --git a/chrome/browser/resources/compose/app.ts b/chrome/browser/resources/compose/app.ts index 7b851f4..c5f635be 100644 --- a/chrome/browser/resources/compose/app.ts +++ b/chrome/browser/resources/compose/app.ts
@@ -24,7 +24,7 @@ import type {CrFeedbackButtonsElement} from '//resources/cr_elements/cr_feedback_buttons/cr_feedback_buttons.js'; import {CrFeedbackOption} from '//resources/cr_elements/cr_feedback_buttons/cr_feedback_buttons.js'; import {I18nMixin} from '//resources/cr_elements/i18n_mixin.js'; -import {assert} from '//resources/js/assert.js'; +import {assert, assertNotReachedCase} from '//resources/js/assert.js'; import {EventTracker} from '//resources/js/event_tracker.js'; import {loadTimeData} from '//resources/js/load_time_data.js'; import {isMac} from '//resources/js/platform.js'; @@ -345,7 +345,7 @@ declare private redoEnabled_: boolean; declare private feedbackEnabled_: boolean; private userHasModifiedState_: boolean = false; - private lastTriggerElement_: TriggerElement; + private lastTriggerElement_: TriggerElement|null = null; declare private outputComplete_: boolean; declare private hasOutput_: boolean; declare private displayedText_: string; @@ -524,18 +524,17 @@ private onClose_(e: Event) { switch ((e.target as HTMLElement).id) { - case 'firstRunCloseButton': { + case 'firstRunCloseButton': this.apiProxy_.closeUi(CloseReason.kFirstRunCloseButton); break; - } - case 'closeButtonMSBB': { + case 'closeButtonMSBB': this.apiProxy_.closeUi(CloseReason.kMSBBCloseButton); break; - } - case 'closeButton': { + case 'closeButton': this.apiProxy_.closeUi(CloseReason.kCloseButton); break; - } + default: + break; } } @@ -799,6 +798,10 @@ case TriggerElement.REDO: this.$.redoButton.focus(); break; + case null: + break; + default: + assertNotReachedCase(this.lastTriggerElement_); } this.screenReaderAnnounce_( @@ -1063,6 +1066,8 @@ case CrFeedbackOption.THUMBS_DOWN: this.apiProxy_.setUserFeedback(UserFeedback.kUserFeedbackNegative); return; + default: + assertNotReachedCase(e.detail.value); } } } @@ -1076,6 +1081,8 @@ return CrFeedbackOption.THUMBS_UP; case UserFeedback.kUserFeedbackNegative: return CrFeedbackOption.THUMBS_DOWN; + default: + assertNotReachedCase(userFeedback); } }
diff --git a/chrome/browser/resources/contextual_tasks/BUILD.gn b/chrome/browser/resources/contextual_tasks/BUILD.gn index e7dda69..e49e99a6d 100644 --- a/chrome/browser/resources/contextual_tasks/BUILD.gn +++ b/chrome/browser/resources/contextual_tasks/BUILD.gn
@@ -20,6 +20,7 @@ "composebox.ts", "composebox.html.ts", "contextual_tasks_browser_proxy.ts", + "icons.html.ts", "post_message_handler.ts", "top_toolbar.ts", "top_toolbar.html.ts",
diff --git a/chrome/browser/resources/contextual_tasks/app.html.ts b/chrome/browser/resources/contextual_tasks/app.html.ts index e97fedb..e6400a1 100644 --- a/chrome/browser/resources/contextual_tasks/app.html.ts +++ b/chrome/browser/resources/contextual_tasks/app.html.ts
@@ -14,7 +14,6 @@ ${this.isShownInTab_ ? '' : html` <top-toolbar .title="${this.threadTitle_}" .attachedTabs="${this.contextTabs_}" - @signin-click="${this.removeGsc_}" @new-thread-click="${this.onNewThreadClick_}" @thread-history-click="${this.onThreadHistoryClick_}"> </top-toolbar>
diff --git a/chrome/browser/resources/contextual_tasks/app.ts b/chrome/browser/resources/contextual_tasks/app.ts index aa95cd7..1c82a4ff 100644 --- a/chrome/browser/resources/contextual_tasks/app.ts +++ b/chrome/browser/resources/contextual_tasks/app.ts
@@ -65,18 +65,11 @@ new PostMessageHandler(this.$.threadFrame, this.browserProxy_); } - // TODO(crbug.com/454388385): Remove this once the authentication flow is - // implemented. Removing the gsc param renders the OGB header, which allows - // the user to press "Sign In" to authenticate. - protected removeGsc_() { - const url = new URL(this.threadUrl_); - url.searchParams.delete('gsc'); - this.threadUrl_ = url.toString(); - } - protected async onNewThreadClick_() { chrome.metricsPrivate.recordUserAction( 'ContextualTasks.WebUI.UserAction.OpenNewThread'); + chrome.metricsPrivate.recordBoolean( + 'ContextualTasks.WebUI.UserAction.OpenNewThread', true); const {url} = await this.browserProxy_.handler.getThreadUrl(); this.threadUrl_ = url.url; } @@ -84,6 +77,8 @@ protected async onThreadHistoryClick_() { chrome.metricsPrivate.recordUserAction( 'ContextualTasks.WebUI.UserAction.OpenThreadHistory'); + chrome.metricsPrivate.recordBoolean( + 'ContextualTasks.WebUI.UserAction.OpenThreadHistory', true); const {threads} = await this.browserProxy_.handler.showThreadHistory(); this.historyThreads_ = threads; // TODO(crbug.com/445469925): Display the threads in a drawer.
diff --git a/chrome/browser/resources/contextual_tasks/icons.html.ts b/chrome/browser/resources/contextual_tasks/icons.html.ts new file mode 100644 index 0000000..0cc0309 --- /dev/null +++ b/chrome/browser/resources/contextual_tasks/icons.html.ts
@@ -0,0 +1,27 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import '//resources/cr_elements/cr_icon/cr_iconset.js'; + +import {getTrustedHTML} from '//resources/js/static_types.js'; + +const div = document.createElement('div'); +div.innerHTML = getTrustedHTML` +<cr-iconset name="contextual_tasks"> + <svg> + <defs> + <g id="edit_square"> + <path d="M 5.101562 20.773438 C 4.585938 20.773438 4.144531 20.589844 3.777344 20.222656 C 3.410156 19.855469 3.226562 19.414062 3.226562 18.898438 L 3.226562 5.101562 C 3.226562 4.585938 3.410156 4.144531 3.777344 3.777344 C 4.144531 3.410156 4.585938 3.226562 5.101562 3.226562 L 13.949219 3.226562 L 12.074219 5.101562 L 5.101562 5.101562 L 5.101562 18.898438 L 18.898438 18.898438 L 18.898438 11.886719 L 20.773438 10.011719 L 20.773438 18.898438 C 20.773438 19.414062 20.589844 19.855469 20.222656 20.222656 C 19.855469 20.589844 19.414062 20.773438 18.898438 20.773438 Z M 12 12 Z M 9.0625 14.9375 L 9.0625 10.773438 L 18.273438 1.5625 C 18.464844 1.371094 18.675781 1.230469 18.898438 1.144531 C 19.125 1.054688 19.355469 1.011719 19.59375 1.011719 C 19.847656 1.011719 20.085938 1.054688 20.3125 1.144531 C 20.539062 1.230469 20.746094 1.371094 20.9375 1.5625 L 22.425781 3.074219 C 22.601562 3.265625 22.734375 3.476562 22.824219 3.699219 C 22.917969 3.925781 22.960938 4.160156 22.960938 4.398438 C 22.960938 4.640625 22.921875 4.871094 22.835938 5.09375 C 22.753906 5.316406 22.617188 5.519531 22.425781 5.710938 L 13.226562 14.9375 Z M 21.113281 4.398438 L 19.613281 2.886719 Z M 10.9375 13.0625 L 12.4375 13.0625 L 18.300781 7.1875 L 17.550781 6.4375 L 16.789062 5.699219 L 10.9375 11.539062 Z M 17.550781 6.4375 L 16.789062 5.699219 L 17.550781 6.4375 L 18.300781 7.1875 Z M 17.550781 6.4375"/> + </g> + <g id="schedule_auto"> + <path d="M 12 12 Z M 12 2.25 C 13.347656 2.25 14.617188 2.507812 15.800781 3.019531 C 16.988281 3.53125 18.019531 4.226562 18.898438 5.105469 C 19.773438 5.984375 20.46875 7.015625 20.980469 8.203125 C 21.492188 9.386719 21.75 10.652344 21.75 12 C 21.75 13.347656 21.492188 14.617188 20.980469 15.800781 C 20.46875 16.988281 19.773438 18.019531 18.894531 18.898438 C 18.015625 19.773438 16.984375 20.46875 15.796875 20.980469 C 14.613281 21.492188 13.347656 21.75 12 21.75 L 11.789062 21.75 L 11.789062 19.875 L 12 19.875 C 14.191406 19.875 16.050781 19.109375 17.582031 17.582031 C 19.109375 16.050781 19.875 14.191406 19.875 12 C 19.875 9.808594 19.109375 7.949219 17.582031 6.417969 C 16.050781 4.890625 14.191406 4.125 12 4.125 C 9.808594 4.125 7.949219 4.890625 6.417969 6.417969 C 4.890625 7.949219 4.125 9.808594 4.125 12 L 4.125 12.210938 L 2.25 12.210938 L 2.25 12 C 2.25 10.652344 2.507812 9.382812 3.019531 8.199219 C 3.53125 7.011719 4.226562 5.980469 5.105469 5.101562 C 5.984375 4.226562 7.015625 3.53125 8.203125 3.019531 C 9.386719 2.507812 10.652344 2.25 12 2.25 Z M 5.460938 22.988281 C 5.445312 22.988281 5.378906 22.9375 5.265625 22.839844 C 5 21.832031 4.503906 20.960938 3.773438 20.226562 C 3.039062 19.492188 2.171875 18.996094 1.160156 18.734375 C 1.128906 18.714844 1.078125 18.652344 1.011719 18.535156 C 1.011719 18.503906 1.0625 18.4375 1.160156 18.339844 C 2.167969 18.078125 3.039062 17.578125 3.773438 16.847656 C 4.507812 16.117188 5.003906 15.246094 5.265625 14.238281 C 5.285156 14.203125 5.347656 14.152344 5.464844 14.085938 C 5.496094 14.085938 5.5625 14.136719 5.660156 14.234375 C 5.941406 15.242188 6.441406 16.113281 7.164062 16.847656 C 7.886719 17.582031 8.753906 18.082031 9.761719 18.34375 C 9.796875 18.34375 9.847656 18.40625 9.914062 18.539062 C 9.914062 18.554688 9.863281 18.621094 9.765625 18.734375 C 8.757812 19 7.886719 19.496094 7.152344 20.226562 C 6.417969 20.960938 5.917969 21.828125 5.65625 22.839844 C 5.65625 22.871094 5.59375 22.921875 5.460938 22.988281 Z M 15.273438 16.601562 L 16.601562 15.273438 L 12.949219 11.621094 L 12.949219 7.074219 L 11.074219 7.074219 L 11.074219 12.375 Z M 15.273438 16.601562"/> + </g> + </defs> + </svg> +</cr-iconset>`; + +const iconsets = div.querySelectorAll('cr-iconset'); +for (const iconset of iconsets) { + document.head.appendChild(iconset); +}
diff --git a/chrome/browser/resources/contextual_tasks/top_toolbar.css b/chrome/browser/resources/contextual_tasks/top_toolbar.css index c5fa5ac..bef888cb 100644 --- a/chrome/browser/resources/contextual_tasks/top_toolbar.css +++ b/chrome/browser/resources/contextual_tasks/top_toolbar.css
@@ -19,23 +19,25 @@ } .leftSide { - display: flex; align-items: center; + display: flex; + font-size: 16px; + flex-grow: 1; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; } .toolbarLogo { - background-image: url(chrome://resources/cr_components/searchbox/icons/chrome_product.svg); - background-position: center; - background-repeat: no-repeat; - background-size: contain; box-sizing: border-box; + display: inline-block; margin: 0 12px 0 8px; - width: 32px; - height: 32px; + min-width: 32px; + min-height: 32px; } .rightSide { - flex-grow: 1; + flex-shrink: 0; } #rightButtonContainer { @@ -76,7 +78,7 @@ } cr-icon-button { - --cr-icon-button-margin-start: 8px; + --cr-icon-button-margin-start: 12px; } cr-icon-button[hidden] {
diff --git a/chrome/browser/resources/contextual_tasks/top_toolbar.html.ts b/chrome/browser/resources/contextual_tasks/top_toolbar.html.ts index 1d1977b..c88bfefa 100644 --- a/chrome/browser/resources/contextual_tasks/top_toolbar.html.ts +++ b/chrome/browser/resources/contextual_tasks/top_toolbar.html.ts
@@ -10,24 +10,31 @@ export function getHtml(this: TopToolbarElement) { return html`<!--_html_template_start_--> <div class="leftSide"> - <div class="toolbarLogo"></div> - <span>${this.title}</span> + <if expr="_google_chrome"> + <img id="topToolbarLogo" + src="chrome://resources/cr_components/searchbox/icons/google_g_gradient.svg" + class="toolbarLogo"> + </if> + <if expr="not _google_chrome"> + <img id="topToolbarLogo" + src="chrome://resources/cr_components/searchbox/icons/chrome_product.svg" + class="toolbarLogo"> + </if> + ${this.title} </div> <div class="rightSide"> <div id="rightButtonContainer"> - <!-- TODO(crbug.com/454388385): Remove this once the authentication flow - is implemented. --> - <button @click="${this.onSigninClick_}">Press for sign in</button> - <cr-icon-button @click="${this.onNewThreadClick_}" iron-icon="cr:add" - title="New Thread"> - </cr-icon-button> - <cr-icon-button @click="${this.onThreadHistoryClick_}" - iron-icon="cr:history" title="Thread History"> - </cr-icon-button> <cr-icon-button id="sources" iron-icon="cr:attachment" ?hidden="${this.shouldHideSourcesButton_()}" title="Sources" @click="${this.onSourcesClick_}"> </cr-icon-button> + <cr-icon-button @click="${this.onNewThreadClick_}" + iron-icon="contextual_tasks:edit_square" + title="New Thread"> + </cr-icon-button> + <cr-icon-button @click="${this.onThreadHistoryClick_}" + iron-icon="contextual_tasks:schedule_auto" title="Thread History"> + </cr-icon-button> <cr-icon-button id="more" iron-icon="cr:more-vert" title="More" @click="${this.onMoreClick_}"> </cr-icon-button>
diff --git a/chrome/browser/resources/contextual_tasks/top_toolbar.ts b/chrome/browser/resources/contextual_tasks/top_toolbar.ts index 31a7e30..4f5a1f2 100644 --- a/chrome/browser/resources/contextual_tasks/top_toolbar.ts +++ b/chrome/browser/resources/contextual_tasks/top_toolbar.ts
@@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import './icons.html.js'; import '//resources/cr_elements/cr_icon/cr_icon.js'; import '//resources/cr_elements/cr_icon_button/cr_icon_button.js'; import '//resources/cr_elements/cr_action_menu/cr_action_menu.js'; @@ -23,6 +24,7 @@ $: { menu: CrLazyRenderLitElement<CrActionMenuElement>, sourcesMenu: CrLazyRenderLitElement<CrActionMenuElement>, + topToolbarLogo: HTMLImageElement, }; } @@ -37,8 +39,9 @@ static override get properties() { return { - title: {type: String}, attachedTabs_: {type: Array}, + logoImageUrl_: {type: String}, + title: {type: String}, }; } @@ -50,13 +53,11 @@ return getHtml.bind(this)(); } - protected onSigninClick_() { - this.fire('signin-click'); - } - protected onCloseButtonClick_() { chrome.metricsPrivate.recordUserAction( 'ContextualTasks.WebUI.UserAction.CloseSidePanel'); + chrome.metricsPrivate.recordBoolean( + 'ContextualTasks.WebUI.UserAction.CloseSidePanel', true); this.browserProxy_.handler.closeSidePanel(); } @@ -80,6 +81,8 @@ this.$.sourcesMenu.get().close(); chrome.metricsPrivate.recordUserAction( 'ContextualTasks.WebUI.UserAction.TabFromSourcesMenuClicked'); + chrome.metricsPrivate.recordBoolean( + 'ContextualTasks.WebUI.UserAction.TabFromSourcesMenuClicked', true); this.browserProxy_.handler.onTabClickedFromSourcesMenu(tab.tabId, tab.url); } @@ -87,6 +90,8 @@ this.$.menu.get().close(); chrome.metricsPrivate.recordUserAction( 'ContextualTasks.WebUI.UserAction.OpenInNewTab'); + chrome.metricsPrivate.recordBoolean( + 'ContextualTasks.WebUI.UserAction.OpenInNewTab', true); this.browserProxy_.handler.moveTaskUiToNewTab(); } @@ -94,6 +99,8 @@ this.$.menu.get().close(); chrome.metricsPrivate.recordUserAction( 'ContextualTasks.WebUI.UserAction.OpenMyActivity'); + chrome.metricsPrivate.recordBoolean( + 'ContextualTasks.WebUI.UserAction.OpenMyActivity', true); this.browserProxy_.handler.openMyActivityUi(); } @@ -101,6 +108,8 @@ this.$.menu.get().close(); chrome.metricsPrivate.recordUserAction( 'ContextualTasks.WebUI.UserAction.OpenHelp'); + chrome.metricsPrivate.recordBoolean( + 'ContextualTasks.WebUI.UserAction.OpenHelp', true); this.browserProxy_.handler.openHelpUi(); }
diff --git a/chrome/browser/resources/extensions/detail_view.ts b/chrome/browser/resources/extensions/detail_view.ts index 2d9386c..c5e788e 100644 --- a/chrome/browser/resources/extensions/detail_view.ts +++ b/chrome/browser/resources/extensions/detail_view.ts
@@ -24,7 +24,7 @@ import type {CrToggleElement} from 'chrome://resources/cr_elements/cr_toggle/cr_toggle.js'; import {I18nMixinLit} from 'chrome://resources/cr_elements/i18n_mixin_lit.js'; import type {CrTooltipIconElement} from 'chrome://resources/cr_elements/policy/cr_tooltip_icon.js'; -import {assert, assertNotReached} from 'chrome://resources/js/assert.js'; +import {assert, assertNotReached, assertNotReachedCase} from 'chrome://resources/js/assert.js'; import {focusWithoutInk} from 'chrome://resources/js/focus_without_ink.js'; import {loadTimeData} from 'chrome://resources/js/load_time_data.js'; import {CrLitElement} from 'chrome://resources/lit/v3_0/lit.rollup.js'; @@ -366,6 +366,8 @@ chrome.metricsPrivate.recordUserAction( 'Extensions.Mv2Deprecation.Unsupported.RemoveExtension.DetailPage'); break; + default: + assertNotReachedCase(this.mv2ExperimentStage_); } this.delegate.deleteItem(this.data.id); @@ -551,7 +553,7 @@ return this.data.isAffectedByMV2Deprecation && this.data.disableReasons.unsupportedManifestVersion; default: - assertNotReached(); + assertNotReachedCase(this.mv2ExperimentStage_); } } @@ -576,6 +578,8 @@ case Mv2ExperimentStage.DISABLE_WITH_REENABLE: case Mv2ExperimentStage.UNSUPPORTED: return !this.data.mustRemainInstalled; + default: + assertNotReachedCase(this.mv2ExperimentStage_); } } @@ -595,6 +599,8 @@ // show the menu if the action should be visible. For UNSUPPORTED, this // is when the recommendationsUrl is non-empty. return !!this.data.recommendationsUrl; + default: + assertNotReachedCase(this.mv2ExperimentStage_); } } @@ -610,6 +616,8 @@ case Mv2ExperimentStage.DISABLE_WITH_REENABLE: case Mv2ExperimentStage.UNSUPPORTED: return !!this.data.recommendationsUrl; + default: + assertNotReachedCase(this.mv2ExperimentStage_); } } @@ -679,6 +687,8 @@ chrome.metricsPrivate.recordUserAction( 'Extensions.Mv2Deprecation.Unsupported.FindAlternativeForExtension.DetailPage'); break; + default: + assertNotReachedCase(this.mv2ExperimentStage_); } this.$.actionMenu.close(); @@ -714,7 +724,7 @@ case Mv2ExperimentStage.UNSUPPORTED: return this.i18n('mv2DeprecationMessageDisabledHeader'); default: - assertNotReached(); + assertNotReachedCase(this.mv2ExperimentStage_); } } @@ -746,7 +756,7 @@ attrs: ['aria-description'], }); default: - assertNotReached(); + assertNotReachedCase(this.mv2ExperimentStage_); } } @@ -762,7 +772,7 @@ case Mv2ExperimentStage.UNSUPPORTED: return 'extensions-icons:extension_off'; default: - assertNotReached(); + assertNotReachedCase(this.mv2ExperimentStage_); } }
diff --git a/chrome/browser/resources/extensions/error_page.ts b/chrome/browser/resources/extensions/error_page.ts index 16e77d5..671a754 100644 --- a/chrome/browser/resources/extensions/error_page.ts +++ b/chrome/browser/resources/extensions/error_page.ts
@@ -10,7 +10,7 @@ import './code_section.js'; import './shared_style.css.js'; -import {assert, assertNotReached} from 'chrome://resources/js/assert.js'; +import {assert, assertNotReachedCase} from 'chrome://resources/js/assert.js'; import {FocusOutlineManager} from 'chrome://resources/js/focus_outline_manager.js'; import {focusWithoutInk} from 'chrome://resources/js/focus_without_ink.js'; import {loadTimeData} from 'chrome://resources/js/load_time_data.js'; @@ -56,7 +56,8 @@ item: ManifestError|RuntimeError, log: string, warn: string, error: string): string { if (item.type === chrome.developerPrivate.ErrorType.RUNTIME) { - switch ((item as RuntimeError).severity) { + const severity = (item as RuntimeError).severity; + switch (severity) { case chrome.developerPrivate.ErrorLevel.LOG: return log; case chrome.developerPrivate.ErrorLevel.WARN: @@ -64,7 +65,7 @@ case chrome.developerPrivate.ErrorLevel.ERROR: return error; default: - assertNotReached(); + assertNotReachedCase(severity); } } assert(item.type === chrome.developerPrivate.ErrorType.MANIFEST); @@ -243,6 +244,8 @@ runtimeError.stackTrace[0] : null; break; + default: + assertNotReachedCase(error.type); } assert(this.delegate); this.delegate.requestFileSource(args).then(code => this.code_ = code);
diff --git a/chrome/browser/resources/extensions/item_list.ts b/chrome/browser/resources/extensions/item_list.ts index df1b992..9cbac6f0 100644 --- a/chrome/browser/resources/extensions/item_list.ts +++ b/chrome/browser/resources/extensions/item_list.ts
@@ -9,6 +9,7 @@ import {getInstance as getAnnouncerInstance} from 'chrome://resources/cr_elements/cr_a11y_announcer/cr_a11y_announcer.js'; import {I18nMixinLit} from 'chrome://resources/cr_elements/i18n_mixin_lit.js'; +import {assertNotReachedCase} from 'chrome://resources/js/assert.js'; import {loadTimeData} from 'chrome://resources/js/load_time_data.js'; import {CrLitElement} from 'chrome://resources/lit/v3_0/lit.rollup.js'; import type {PropertyValues} from 'chrome://resources/lit/v3_0/lit.rollup.js'; @@ -234,6 +235,8 @@ case Mv2ExperimentStage.UNSUPPORTED: return extension.isAffectedByMV2Deprecation && extension.disableReasons.unsupportedManifestVersion; + default: + assertNotReachedCase(this.mv2ExperimentStage_); } }); } @@ -295,6 +298,8 @@ // extension is affected by the MV2 deprecation. return !this.isMv2DeprecationNoticeDismissed && this.mv2DeprecatedExtensions_?.length !== 0; + default: + assertNotReachedCase(this.mv2ExperimentStage_); } }
diff --git a/chrome/browser/resources/extensions/item_mixin.ts b/chrome/browser/resources/extensions/item_mixin.ts index eeea508..2043fb3a 100644 --- a/chrome/browser/resources/extensions/item_mixin.ts +++ b/chrome/browser/resources/extensions/item_mixin.ts
@@ -4,7 +4,7 @@ import type {CrLitElement} from '//resources/lit/v3_0/lit.rollup.js'; import {getToastManager} from 'chrome://resources/cr_elements/cr_toast/cr_toast_manager.js'; -import {assert, assertNotReached} from 'chrome://resources/js/assert.js'; +import {assert, assertNotReached, assertNotReachedCase} from 'chrome://resources/js/assert.js'; import {loadTimeData} from 'chrome://resources/js/load_time_data.js'; import type {ItemDelegate} from './item.js'; @@ -50,8 +50,12 @@ case ExtensionType.EXTENSION: case ExtensionType.SHARED_MODULE: return extensionLabel; + case ExtensionType.THEME: + assertNotReached( + 'Don\'t send themes to the chrome://extensions page'); + default: + assertNotReachedCase(type, 'Item type is not App or Extension.'); } - assertNotReached('Item type is not App or Extension.'); } /**
diff --git a/chrome/browser/resources/extensions/item_util.ts b/chrome/browser/resources/extensions/item_util.ts index 1589602..0ae4de80 100644 --- a/chrome/browser/resources/extensions/item_util.ts +++ b/chrome/browser/resources/extensions/item_util.ts
@@ -4,7 +4,7 @@ import '/strings.m.js'; -import {assertNotReached} from 'chrome://resources/js/assert.js'; +import {assertNotReached, assertNotReachedCase} from 'chrome://resources/js/assert.js'; import {loadTimeData} from 'chrome://resources/js/load_time_data.js'; import {Mv2ExperimentStage} from './mv2_deprecation_util.js'; @@ -79,7 +79,7 @@ case chrome.developerPrivate.ExtensionState.DISABLED: return false; default: - assertNotReached(); + assertNotReachedCase(state); } } @@ -140,7 +140,7 @@ case chrome.developerPrivate.Location.INSTALLED_BY_DEFAULT: return SourceType.INSTALLED_BY_DEFAULT; default: - assertNotReached(item.location); + assertNotReachedCase(item.location); } } @@ -161,7 +161,7 @@ // chrome.developerPrivate.ExtensionInfo's |locationText| instead. return ''; default: - assertNotReached(); + assertNotReachedCase(source); } } @@ -192,7 +192,7 @@ return SafetyCheckWarningReason.NO_PRIVACY_PRACTICE; } default: { - assertNotReached(); + assertNotReachedCase(reason); } } } @@ -248,8 +248,12 @@ case ExtensionType.EXTENSION: case ExtensionType.SHARED_MODULE: return extensionEnabled; + case ExtensionType.THEME: + assertNotReached('Don\'t send themes to the chrome://extensions page'); + default: + assertNotReachedCase( + extensionsDataType, 'Item type is not App or Extension.'); } - assertNotReached('Item type is not App or Extension.'); } /**
diff --git a/chrome/browser/resources/extensions/manager.ts b/chrome/browser/resources/extensions/manager.ts index 6f86d76..3ce9e81 100644 --- a/chrome/browser/resources/extensions/manager.ts +++ b/chrome/browser/resources/extensions/manager.ts
@@ -26,7 +26,7 @@ import {getToastManager} from 'chrome://resources/cr_elements/cr_toast/cr_toast_manager.js'; import type {CrViewManagerElement} from 'chrome://resources/cr_elements/cr_view_manager/cr_view_manager.js'; import {I18nMixinLit} from 'chrome://resources/cr_elements/i18n_mixin_lit.js'; -import {assert, assertNotReached} from 'chrome://resources/js/assert.js'; +import {assert, assertNotReached, assertNotReachedCase} from 'chrome://resources/js/assert.js'; import {loadTimeData} from 'chrome://resources/js/load_time_data.js'; import {PromiseResolver} from 'chrome://resources/js/promise_resolver.js'; import {CrLitElement} from 'chrome://resources/lit/v3_0/lit.rollup.js'; @@ -402,7 +402,7 @@ case ExtensionType.THEME: assertNotReached('Don\'t send themes to the chrome://extensions page'); default: - assertNotReached(); + assertNotReachedCase(item.type); } }
diff --git a/chrome/browser/resources/extensions/mv2_deprecation_panel.ts b/chrome/browser/resources/extensions/mv2_deprecation_panel.ts index 0e16d564..74120fee 100644 --- a/chrome/browser/resources/extensions/mv2_deprecation_panel.ts +++ b/chrome/browser/resources/extensions/mv2_deprecation_panel.ts
@@ -10,7 +10,7 @@ import {I18nMixinLit} from '//resources/cr_elements/i18n_mixin_lit.js'; import {AnchorAlignment} from 'chrome://resources/cr_elements/cr_action_menu/cr_action_menu.js'; import type {CrActionMenuElement} from 'chrome://resources/cr_elements/cr_action_menu/cr_action_menu.js'; -import {assert, assertNotReached} from 'chrome://resources/js/assert.js'; +import {assert, assertNotReached, assertNotReachedCase} from 'chrome://resources/js/assert.js'; import {sanitizeInnerHtml} from 'chrome://resources/js/parse_html_subset.js'; import {PluralStringProxyImpl} from 'chrome://resources/js/plural_string_proxy.js'; import {CrLitElement} from 'chrome://resources/lit/v3_0/lit.rollup.js'; @@ -123,7 +123,7 @@ 'p=unsupported_extensions'; break; default: - assertNotReached(); + assertNotReachedCase(this.mv2ExperimentStage); } this.headerString_ = @@ -160,6 +160,8 @@ case Mv2ExperimentStage.DISABLE_WITH_REENABLE: case Mv2ExperimentStage.UNSUPPORTED: return !extension.mustRemainInstalled; + default: + assertNotReachedCase(this.mv2ExperimentStage); } } @@ -176,6 +178,8 @@ return true; case Mv2ExperimentStage.UNSUPPORTED: return !!extension.recommendationsUrl; + default: + assertNotReachedCase(this.mv2ExperimentStage); } } @@ -193,6 +197,8 @@ case Mv2ExperimentStage.UNSUPPORTED: return !!this.extensionWithActionMenuOpened_ && !!this.extensionWithActionMenuOpened_.recommendationsUrl; + default: + assertNotReachedCase(this.mv2ExperimentStage); } } @@ -209,6 +215,8 @@ return true; case Mv2ExperimentStage.UNSUPPORTED: return false; + default: + assertNotReachedCase(this.mv2ExperimentStage); } } @@ -226,6 +234,8 @@ case Mv2ExperimentStage.DISABLE_WITH_REENABLE: case Mv2ExperimentStage.UNSUPPORTED: return false; + default: + assertNotReachedCase(this.mv2ExperimentStage); } } @@ -284,6 +294,8 @@ chrome.metricsPrivate.recordUserAction( 'Extensions.Mv2Deprecation.Unsupported.Dismissed'); break; + default: + assertNotReachedCase(this.mv2ExperimentStage); } assert(this.delegate); @@ -322,6 +334,8 @@ chrome.metricsPrivate.recordUserAction( 'Extensions.Mv2Deprecation.Unsupported.RemoveExtension'); break; + default: + assertNotReachedCase(this.mv2ExperimentStage); } this.$.actionMenu.close(); @@ -360,6 +374,8 @@ chrome.metricsPrivate.recordUserAction( 'Extensions.Mv2Deprecation.Unsupported.FindAlternativeForExtension'); break; + default: + assertNotReachedCase(this.mv2ExperimentStage); } const recommendationsUrl: string|undefined = @@ -401,6 +417,8 @@ break; case Mv2ExperimentStage.UNSUPPORTED: assertNotReached(); + default: + assertNotReachedCase(this.mv2ExperimentStage); } this.$.actionMenu.close();
diff --git a/chrome/browser/resources/extensions/navigation_helper.ts b/chrome/browser/resources/extensions/navigation_helper.ts index bb3cd6ed..6e0a6cd 100644 --- a/chrome/browser/resources/extensions/navigation_helper.ts +++ b/chrome/browser/resources/extensions/navigation_helper.ts
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import {assert} from 'chrome://resources/js/assert.js'; +import {assert, assertNotReachedCase} from 'chrome://resources/js/assert.js'; /** @@ -209,6 +209,8 @@ case Page.ERRORS: path = '/?errors=' + entry.extensionId; break; + default: + assertNotReachedCase(entry.page); } assert(path); const state = {url: path};
diff --git a/chrome/browser/resources/extensions/runtime_host_permissions.ts b/chrome/browser/resources/extensions/runtime_host_permissions.ts index aeba195a..1116b5b 100644 --- a/chrome/browser/resources/extensions/runtime_host_permissions.ts +++ b/chrome/browser/resources/extensions/runtime_host_permissions.ts
@@ -16,7 +16,7 @@ import type {CrActionMenuElement} from 'chrome://resources/cr_elements/cr_action_menu/cr_action_menu.js'; import type {CrDialogElement} from 'chrome://resources/cr_elements/cr_dialog/cr_dialog.js'; -import {assert} from 'chrome://resources/js/assert.js'; +import {assert, assertNotReachedCase} from 'chrome://resources/js/assert.js'; import {focusWithoutInk} from 'chrome://resources/js/focus_without_ink.js'; import {CrLitElement} from 'chrome://resources/lit/v3_0/lit.rollup.js'; @@ -156,6 +156,8 @@ chrome.metricsPrivate.recordUserAction( 'Extensions.Settings.Hosts.OnAllSitesSelected'); break; + default: + assertNotReachedCase(access); } }
diff --git a/chrome/browser/resources/glic/app_router.ts b/chrome/browser/resources/glic/app_router.ts index 0ec1c21..1d5b8176 100644 --- a/chrome/browser/resources/glic/app_router.ts +++ b/chrome/browser/resources/glic/app_router.ts
@@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import {assertNotReachedCase} from '//resources/js/assert.js'; import {loadTimeData} from '//resources/js/load_time_data.js'; import {FreAppController} from '/fre/fre_app_controller.js'; import {getRequiredElement} from 'chrome://resources/js/util.js'; @@ -75,6 +76,8 @@ } this.freContainer.hidden = false; break; + default: + assertNotReachedCase(this.currentView); } }
diff --git a/chrome/browser/resources/glic/glic_api_impl/host/conversions.ts b/chrome/browser/resources/glic/glic_api_impl/host/conversions.ts index 5bacb478..45a3d4b 100644 --- a/chrome/browser/resources/glic/glic_api_impl/host/conversions.ts +++ b/chrome/browser/resources/glic/glic_api_impl/host/conversions.ts
@@ -563,8 +563,9 @@ return WebClientModeMojo.kAudio; case WebClientMode.TEXT: return WebClientModeMojo.kText; + default: + return WebClientModeMojo.kUnknown; } - return WebClientModeMojo.kUnknown; } export function captureRegionResultToClient(
diff --git a/chrome/browser/resources/glic/glic_api_impl/host/host_from_client.ts b/chrome/browser/resources/glic/glic_api_impl/host/host_from_client.ts index ebf77c20..77fa68c5 100644 --- a/chrome/browser/resources/glic/glic_api_impl/host/host_from_client.ts +++ b/chrome/browser/resources/glic/glic_api_impl/host/host_from_client.ts
@@ -714,8 +714,9 @@ case 'geolocation': return this.handler.openOsPermissionSettingsMenu( ContentSettingsType.GEOLOCATION); + default: + return Promise.resolve(); } - return Promise.resolve(); } glicBrowserGetOsMicrophonePermissionStatus(): Promise<{enabled: boolean}> {
diff --git a/chrome/browser/resources/glic/glic_app_controller.ts b/chrome/browser/resources/glic/glic_app_controller.ts index b347c8a..0121f374 100644 --- a/chrome/browser/resources/glic/glic_app_controller.ts +++ b/chrome/browser/resources/glic/glic_app_controller.ts
@@ -3,6 +3,7 @@ // found in the LICENSE file. import {loadTimeData} from '//resources/js/load_time_data.js'; +import {assert, assertNotReachedCase} from 'chrome://resources/js/assert.js'; import {getRequiredElement} from 'chrome://resources/js/util.js'; import type {BrowserProxyImpl} from './browser_proxy.js'; @@ -146,10 +147,12 @@ this.online(); }); window.addEventListener('offline', () => { - this.offline(); + if (!this.isOnline()) { + this.offline(); + } }); - if (navigator.onLine && !this.simulateNoConnection) { + if (this.isOnline()) { this.setState(WebUiState.kBeginLoad); } else { this.setState(WebUiState.kOffline); @@ -243,6 +246,7 @@ this.showPanel('guestPanel'); break; case 'guestError': + case 'guestCaaError': this.setState(WebUiState.kGuestError); break; case 'regular': @@ -255,6 +259,8 @@ case 'loadError': this.setState(WebUiState.kError); break; + default: + assertNotReachedCase(type); } } @@ -440,6 +446,7 @@ this.trackLoadingStageEnd(); const readyState = this.profileReadyState; + assert(readyState !== undefined); switch (readyState) { case ProfileReadyState.kIneligible: case ProfileReadyState.kUnknownError: @@ -455,6 +462,8 @@ return; case ProfileReadyState.kReady: break; + default: + assertNotReachedCase(readyState); } // Blocking on cookie syncing here introduces latency, we should consider @@ -475,6 +484,8 @@ case PrepareForClientResult.kRequiresSignIn: this.setState(WebUiState.kSignIn); return; + default: + assertNotReachedCase(result); } // Load the web client only after cookie sync is complete. @@ -650,8 +661,9 @@ case WebUiState.kShowLoading: case WebUiState.kHoldLoading: return; + default: + this.setState(WebUiState.kReady); } - this.setState(WebUiState.kReady); break; case WebClientState.UNRESPONSIVE: this.trackUnresponsiveState( @@ -664,6 +676,10 @@ this.guestResizeEnabled = false; this.setState(WebUiState.kError); break; + case WebClientState.UNINITIALIZED: + break; + default: + assertNotReachedCase(state); } } @@ -763,6 +779,8 @@ this.setState(WebUiState.kBeginLoad); } break; + default: + assertNotReachedCase(this.profileReadyState); } } } @@ -770,4 +788,10 @@ openDisabledByAdminLink(): void { this.browserProxy.handler.openDisabledByAdminLinkAndClosePanel(); } + + isOnline() { + return loadTimeData.getBoolean('ignoreOfflineState') ? + true : + navigator.onLine && !this.simulateNoConnection; + } }
diff --git a/chrome/browser/resources/glic/observable.ts b/chrome/browser/resources/glic/observable.ts index 1a9d340..890a7bdd 100644 --- a/chrome/browser/resources/glic/observable.ts +++ b/chrome/browser/resources/glic/observable.ts
@@ -5,6 +5,10 @@ // Note: this code is made to conform to glic_api's Observable, but can also be // used independently. +function assertNotReachedCase(_param: never, message?: string): never { + throw new Error('Assertion failed' + (message ? `: ${message}` : '')); +} + /** Allows control of a subscription to an ObservableValue. */ export declare interface Subscriber { unsubscribe(): void; @@ -57,6 +61,8 @@ case 'complete': case 'error': throw new Error('Observable is not active'); + default: + assertNotReachedCase(this.state_); } this.subscribers.forEach((sub) => { // Ignore if removed since forEach was called. @@ -79,6 +85,8 @@ case 'complete': case 'error': throw new Error('Observable is not active'); + default: + assertNotReachedCase(this.state_); } let loggedWarning = false; const hadSubscribers = this.hasActiveSubscription(); @@ -113,6 +121,8 @@ case 'complete': case 'error': throw new Error('Observable is not active'); + default: + assertNotReachedCase(this.state_); } const hadSubscribers = this.hasActiveSubscription(); this.subscribers.forEach((sub) => { @@ -165,6 +175,8 @@ case 'error': observer.error?.(this.errorValue!); return {unsubscribe: () => {}}; + default: + assertNotReachedCase(this.state_); } const newSub = new ObservableSubscription(observer, this.onUnsubscribe.bind(this));
diff --git a/chrome/browser/resources/glic/webview.ts b/chrome/browser/resources/glic/webview.ts index d099393..74402e9f 100644 --- a/chrome/browser/resources/glic/webview.ts +++ b/chrome/browser/resources/glic/webview.ts
@@ -268,6 +268,8 @@ } return; } + default: + break; } console.warn(`Webview permission request was denied: ${e.permission}`); e.request.deny();
diff --git a/chrome/browser/resources/history/app.ts b/chrome/browser/resources/history/app.ts index 6ae453ac..59221faa 100644 --- a/chrome/browser/resources/history/app.ts +++ b/chrome/browser/resources/history/app.ts
@@ -33,7 +33,7 @@ import type {CrPageSelectorElement} from 'chrome://resources/cr_elements/cr_page_selector/cr_page_selector.js'; import {FindShortcutMixinLit} from 'chrome://resources/cr_elements/find_shortcut_mixin_lit.js'; import {WebUiListenerMixinLit} from 'chrome://resources/cr_elements/web_ui_listener_mixin_lit.js'; -import {assert} from 'chrome://resources/js/assert.js'; +import {assert, assertNotReachedCase} from 'chrome://resources/js/assert.js'; import {EventTracker} from 'chrome://resources/js/event_tracker.js'; import {loadTimeData} from 'chrome://resources/js/load_time_data.js'; import {hasKeyModifiers} from 'chrome://resources/js/util.js'; @@ -540,24 +540,25 @@ 'History.SearchResultClicked.Index', clampedIndex, maxIndex); switch (e.detail.resultType) { - case HistoryResultType.TRADITIONAL: { + case HistoryResultType.TRADITIONAL: this.browserService_.recordHistogram( 'History.SearchResultClicked.Index.Traditional', clampedIndex, maxIndex); break; - } - case HistoryResultType.GROUPED: { + case HistoryResultType.GROUPED: this.browserService_.recordHistogram( 'History.SearchResultClicked.Index.Grouped', clampedIndex, maxIndex); break; - } - case HistoryResultType.EMBEDDINGS: { + case HistoryResultType.EMBEDDINGS: this.browserService_.recordHistogram( 'History.SearchResultClicked.Index.Embeddings', clampedIndex, maxIndex); break; - } + case HistoryResultType.END: + break; + default: + assertNotReachedCase(e.detail.resultType); } }
diff --git a/chrome/browser/resources/history/side_bar.ts b/chrome/browser/resources/history/side_bar.ts index 1aebcba..c9c997c 100644 --- a/chrome/browser/resources/history/side_bar.ts +++ b/chrome/browser/resources/history/side_bar.ts
@@ -183,6 +183,8 @@ loadTimeData.getString('sidebarFooterGAALink'), '_blank', e as MouseEvent); break; + default: + break; } }
diff --git a/chrome/browser/resources/pdf/elements/ink_annotation_text_mixin.ts b/chrome/browser/resources/pdf/elements/ink_annotation_text_mixin.ts index b26af80..1ebca53e 100644 --- a/chrome/browser/resources/pdf/elements/ink_annotation_text_mixin.ts +++ b/chrome/browser/resources/pdf/elements/ink_annotation_text_mixin.ts
@@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import {assertNotReachedCase} from 'chrome://resources/js/assert.js'; import type {CrLitElement} from 'chrome://resources/lit/v3_0/lit.rollup.js'; import type {Color, TextAttributes} from '../constants.js'; @@ -78,6 +79,8 @@ return 'ink2TextFontSerif'; case TextTypeface.MONOSPACE: return 'ink2TextFontMonospace'; + default: + assertNotReachedCase(typeface); } }
diff --git a/chrome/browser/resources/pdf/elements/ink_brush_selector.ts b/chrome/browser/resources/pdf/elements/ink_brush_selector.ts index d4ede3b..0b39bad 100644 --- a/chrome/browser/resources/pdf/elements/ink_brush_selector.ts +++ b/chrome/browser/resources/pdf/elements/ink_brush_selector.ts
@@ -5,6 +5,7 @@ import 'chrome://resources/cr_elements/cr_radio_group/cr_radio_group.js'; import './selectable_icon_button.js'; +import {assertNotReachedCase} from 'chrome://resources/js/assert.js'; import {loadTimeData} from 'chrome://resources/js/load_time_data.js'; import {CrLitElement} from 'chrome://resources/lit/v3_0/lit.rollup.js'; @@ -71,6 +72,8 @@ case AnnotationBrushType.PEN: record(UserAction.SELECT_INK2_BRUSH_PEN); break; + default: + assertNotReachedCase(newType); } } @@ -84,6 +87,8 @@ 'pdf-ink:ink-highlighter'; case AnnotationBrushType.PEN: return isCurrentType ? 'pdf-ink:ink-pen-fill' : 'pdf-ink:ink-pen'; + default: + assertNotReachedCase(type); } } @@ -95,6 +100,8 @@ return loadTimeData.getString('annotationHighlighter'); case AnnotationBrushType.PEN: return loadTimeData.getString('annotationPen'); + default: + assertNotReachedCase(type); } } }
diff --git a/chrome/browser/resources/pdf/elements/ink_text_box.ts b/chrome/browser/resources/pdf/elements/ink_text_box.ts index 5ec3d2cb..71dba4e2 100644 --- a/chrome/browser/resources/pdf/elements/ink_text_box.ts +++ b/chrome/browser/resources/pdf/elements/ink_text_box.ts
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import {assert} from 'chrome://resources/js/assert.js'; +import {assert, assertNotReachedCase} from 'chrome://resources/js/assert.js'; import {EventTracker} from 'chrome://resources/js/event_tracker.js'; import {CrLitElement} from 'chrome://resources/lit/v3_0/lit.rollup.js'; import type {PropertyValues} from 'chrome://resources/lit/v3_0/lit.rollup.js'; @@ -37,6 +37,8 @@ return 'Times, serif'; case TextTypeface.MONOSPACE: return '"Courier New", monospace'; + default: + assertNotReachedCase(typeface); } } @@ -471,6 +473,8 @@ case 'ArrowRight': moveX = this.keyDownCount_; break; + default: + break; } this.onMove_(target, moveX, moveY); }
diff --git a/chrome/browser/resources/pdf/elements/text_styles_selector.ts b/chrome/browser/resources/pdf/elements/text_styles_selector.ts index 7f3485c20..bfd23e4a 100644 --- a/chrome/browser/resources/pdf/elements/text_styles_selector.ts +++ b/chrome/browser/resources/pdf/elements/text_styles_selector.ts
@@ -5,6 +5,7 @@ import 'chrome://resources/cr_elements/cr_icon_button/cr_icon_button.js'; import {I18nMixinLit} from 'chrome://resources/cr_elements/i18n_mixin_lit.js'; +import {assertNotReachedCase} from 'chrome://resources/js/assert.js'; import {CrLitElement} from 'chrome://resources/lit/v3_0/lit.rollup.js'; import type {TextAttributes, TextStyles} from '../constants.js'; @@ -67,6 +68,8 @@ return this.i18n('ink2TextStyleBold'); case TextStyle.ITALIC: return this.i18n('ink2TextStyleItalic'); + default: + assertNotReachedCase(style); } }
diff --git a/chrome/browser/resources/pdf/elements/viewer_pdf_sidenav.ts b/chrome/browser/resources/pdf/elements/viewer_pdf_sidenav.ts index 5a41797..dc268f4 100644 --- a/chrome/browser/resources/pdf/elements/viewer_pdf_sidenav.ts +++ b/chrome/browser/resources/pdf/elements/viewer_pdf_sidenav.ts
@@ -8,7 +8,7 @@ import './viewer_thumbnail_bar.js'; import 'chrome://resources/cr_elements/cr_icon_button/cr_icon_button.js'; -import {assert} from 'chrome://resources/js/assert.js'; +import {assert, assertNotReachedCase} from 'chrome://resources/js/assert.js'; import {loadTimeData} from 'chrome://resources/js/load_time_data.js'; import {CrLitElement} from 'chrome://resources/lit/v3_0/lit.rollup.js'; import type {PropertyValues} from 'chrome://resources/lit/v3_0/lit.rollup.js'; @@ -129,7 +129,9 @@ protected onTabClick_(e: Event) { const tabId = (e.currentTarget as HTMLElement).dataset['tabId']; assert(tabId !== undefined); - switch (Number.parseInt(tabId, 10)) { + + const tabIdNumber = Number.parseInt(tabId, 10) as TabId; + switch (tabIdNumber) { case TabId.THUMBNAIL: record(UserAction.SELECT_SIDENAV_THUMBNAILS); this.selectedTab_ = 0; @@ -144,6 +146,9 @@ record(UserAction.SELECT_SIDENAV_ATTACHMENT); this.selectedTab_ = this.tabs_.length - 1; break; + + default: + assertNotReachedCase(tabIdNumber); } }
diff --git a/chrome/browser/resources/pdf/elements/viewer_thumbnail_bar.ts b/chrome/browser/resources/pdf/elements/viewer_thumbnail_bar.ts index a2b1f8cb..33727d89 100644 --- a/chrome/browser/resources/pdf/elements/viewer_thumbnail_bar.ts +++ b/chrome/browser/resources/pdf/elements/viewer_thumbnail_bar.ts
@@ -237,6 +237,8 @@ e.preventDefault(); this.clickThumbnailForPage(this.activePage - 1); break; + default: + break; } }
diff --git a/chrome/browser/resources/pdf/pdf_internal_plugin_wrapper.ts b/chrome/browser/resources/pdf/pdf_internal_plugin_wrapper.ts index 8e9c60c..0f221c0 100644 --- a/chrome/browser/resources/pdf/pdf_internal_plugin_wrapper.ts +++ b/chrome/browser/resources/pdf/pdf_internal_plugin_wrapper.ts
@@ -43,6 +43,8 @@ message as unknown as {caretBrowsingEnabled: boolean}; caretBrowsingEnabled = caretBrowsingEnabledData.caretBrowsingEnabled; break; + default: + break; } channel.port1.postMessage(message); @@ -105,6 +107,9 @@ } } break; + + default: + break; } plugin.postMessage(e.data); @@ -265,6 +270,8 @@ e.preventDefault(); } break; + default: + break; } });
diff --git a/chrome/browser/resources/pdf/pdf_scripting_api.ts b/chrome/browser/resources/pdf/pdf_scripting_api.ts index 5aebeac3..c4641a6 100644 --- a/chrome/browser/resources/pdf/pdf_scripting_api.ts +++ b/chrome/browser/resources/pdf/pdf_scripting_api.ts
@@ -132,6 +132,8 @@ this.keyEventCallback_(deserializeKeyEvent(event.data.keyEvent)); } break; + default: + break; } }, false); }
diff --git a/chrome/browser/resources/pdf/pdf_viewer.ts b/chrome/browser/resources/pdf/pdf_viewer.ts index 28fd350..0ed991e2 100644 --- a/chrome/browser/resources/pdf/pdf_viewer.ts +++ b/chrome/browser/resources/pdf/pdf_viewer.ts
@@ -25,7 +25,7 @@ import {PdfHelpBubbleProxyImpl} from 'chrome://resources/cr_components/help_bubble/pdf_help_bubble_proxy.js'; import type {CrToastElement} from 'chrome://resources/cr_elements/cr_toast/cr_toast.js'; -import {assert, assertNotReached} from 'chrome://resources/js/assert.js'; +import {assert, assertNotReached, assertNotReachedCase} from 'chrome://resources/js/assert.js'; import {loadTimeData} from 'chrome://resources/js/load_time_data.js'; import type {LoadTimeDataRaw} from 'chrome://resources/js/load_time_data.js'; import {listenOnce} from 'chrome://resources/js/util.js'; @@ -570,7 +570,10 @@ this.isInTextAnnotationMode_()) { this.maybeCreateTextAnnotation_(); } - // </if> + return; + // </if> + default: + break; } // Handle toolbar related key events. @@ -629,6 +632,8 @@ return; // </if> not is_macosx // </if> enable_pdf_ink2 + default: + break; } } @@ -1015,9 +1020,10 @@ case 'Paste': record(UserAction.PASTE); return; + default: + assertNotReached( + 'Unknown executedEditCommand data received: ' + editCommand); } - assertNotReached( - 'Unknown executedEditCommand data received: ' + editCommand); // <if expr="enable_pdf_ink2"> case 'finishInkStroke': const modifiedData = data as unknown as {modified: boolean}; @@ -1113,8 +1119,9 @@ } return; // </if> + default: + assertNotReached('Unknown message type received: ' + data.type); } - assertNotReached('Unknown message type received: ' + data.type); } forceFit(view: FittingType): void { @@ -1858,6 +1865,8 @@ // test. record(UserAction.SAVE_SEARCHIFIED); break; + default: + assertNotReachedCase(requestType); } }
diff --git a/chrome/browser/resources/pdf/pdf_viewer_print.ts b/chrome/browser/resources/pdf/pdf_viewer_print.ts index 163ec6e4..028775af 100644 --- a/chrome/browser/resources/pdf/pdf_viewer_print.ts +++ b/chrome/browser/resources/pdf/pdf_viewer_print.ts
@@ -133,6 +133,8 @@ this.$.zoomToolbar.fitToggleFromHotKey(); } return; + default: + break; } // Give print preview a chance to handle the key event. @@ -276,9 +278,9 @@ position.x += positionData.x; this.viewport.setPosition(position); return true; + default: + return false; } - - return false; } override setLoadState(loadState: LoadState) { @@ -288,7 +290,7 @@ } } - override handlePluginMessage(e: CustomEvent) { + override handlePluginMessage(e: CustomEvent<MessageData>) { const data = e.detail; switch (data.type.toString()) { case 'documentDimensions': @@ -323,8 +325,9 @@ case 'setIsEditing': // These messages are not relevant in Print Preview. return; + default: + assertNotReached('Unknown message type received: ' + data.type); } - assertNotReached('Unknown message type received: ' + data.type); } /**
diff --git a/chrome/browser/resources/privacy_sandbox/internals/cr_frame_list.ts b/chrome/browser/resources/privacy_sandbox/internals/cr_frame_list.ts index 6f3eae9..49f9271 100644 --- a/chrome/browser/resources/privacy_sandbox/internals/cr_frame_list.ts +++ b/chrome/browser/resources/privacy_sandbox/internals/cr_frame_list.ts
@@ -186,6 +186,8 @@ case 'ArrowDown': delta = 1; break; + default: + break; } if (!delta) {
diff --git a/chrome/browser/resources/side_panel/bookmarks/power_bookmarks_context_menu.ts b/chrome/browser/resources/side_panel/bookmarks/power_bookmarks_context_menu.ts index 1a05b40..c1943c4 100644 --- a/chrome/browser/resources/side_panel/bookmarks/power_bookmarks_context_menu.ts +++ b/chrome/browser/resources/side_panel/bookmarks/power_bookmarks_context_menu.ts
@@ -12,7 +12,7 @@ import type {PriceTrackingBrowserProxy} from '//resources/cr_components/commerce/price_tracking_browser_proxy.js'; import {PriceTrackingBrowserProxyImpl} from '//resources/cr_components/commerce/price_tracking_browser_proxy.js'; import type {CrActionMenuElement} from '//resources/cr_elements/cr_action_menu/cr_action_menu.js'; -import {assert} from 'chrome://resources/js/assert.js'; +import {assert, assertNotReachedCase} from 'chrome://resources/js/assert.js'; import {loadTimeData} from 'chrome://resources/js/load_time_data.js'; import type {DomRepeatEvent} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {afterNextRender, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; @@ -394,6 +394,11 @@ })); } break; + case MenuItemId.DIVIDER: + case MenuItemId.EDIT: + break; + default: + assertNotReachedCase(event.model.item.id); } this.$.menu.close(); }
diff --git a/chrome/browser/resources/side_panel/read_anything/app/app_style_updater.ts b/chrome/browser/resources/side_panel/read_anything/app/app_style_updater.ts index 23d2c5e..b6bfa0b 100644 --- a/chrome/browser/resources/side_panel/read_anything/app/app_style_updater.ts +++ b/chrome/browser/resources/side_panel/read_anything/app/app_style_updater.ts
@@ -11,8 +11,6 @@ const MIN_WIDTH_OVERFLOW = 'fit-content'; // Empty state colors. const EMPTY_STATE_HEADING = 'var(--color-read-anything-foreground'; -const EMPTY_STATE_BODY_DARK = 'var(--google-grey-500)'; -const EMPTY_STATE_BODY_LIGHT = 'var(--google-grey-700)'; const EMPTY_STATE_BODY_DEFAULT = 'var(--color-side-panel-card-secondary-foreground)'; // Container colors. @@ -174,10 +172,8 @@ switch (colorSuffix) { case ColorSuffix.DEFAULT: return EMPTY_STATE_BODY_DEFAULT; - case ColorSuffix.DARK: - return EMPTY_STATE_BODY_DARK; default: - return EMPTY_STATE_BODY_LIGHT; + return EMPTY_STATE_HEADING + `${colorSuffix})`; } }
diff --git a/chrome/browser/resources/side_panel/read_anything/app/icons.html b/chrome/browser/resources/side_panel/read_anything/app/icons.html index 7688678..36a65cc 100644 --- a/chrome/browser/resources/side_panel/read_anything/app/icons.html +++ b/chrome/browser/resources/side_panel/read_anything/app/icons.html
@@ -72,6 +72,15 @@ d="M2.4 14.4V13.2C2.93333 13.2 3.45 13.1611 3.95 13.0833C4.46111 12.9944 4.96111 12.8556 5.45 12.6667C4.89444 12.5111 4.44444 12.2056 4.1 11.75C3.76667 11.2833 3.6 10.7611 3.6 10.1833V8.8H6.4V6.8H8.58333L6.28333 2.7L7.31667 2.1L9.61667 6.21667C9.83889 6.61667 9.83889 7.01667 9.61667 7.41667C9.39444 7.80556 9.05 8 8.58333 8H7.6V9C7.6 9.27778 7.5 9.51667 7.3 9.71667C7.11111 9.90556 6.87778 10 6.6 10H4.8V10.1833C4.8 10.5278 4.91111 10.8333 5.13333 11.1C5.35556 11.3556 5.63889 11.5111 5.98333 11.5667L6.28333 11.6167C6.76111 11.7056 7.03333 11.9889 7.1 12.4667C7.17778 12.9444 7.00556 13.2889 6.58333 13.5C5.92778 13.8222 5.25 14.0556 4.55 14.2C3.85 14.3333 3.13333 14.4 2.4 14.4ZM10.55 12.4L9.68333 11.5667C9.79444 11.4556 9.87778 11.3278 9.93333 11.1833C10 11.0389 10.0333 10.8833 10.0333 10.7167C10.0333 10.55 10 10.3944 9.93333 10.25C9.87778 10.1056 9.79444 9.97778 9.68333 9.86667L10.55 9.03333C10.7722 9.25556 10.9389 9.51111 11.05 9.8C11.1722 10.0778 11.2333 10.3833 11.2333 10.7167C11.2333 11.0389 11.1722 11.3444 11.05 11.6333C10.9389 11.9222 10.7722 12.1778 10.55 12.4ZM12.2333 14.1167L11.4 13.2333C11.7222 12.9111 11.9722 12.5389 12.15 12.1167C12.3389 11.6833 12.4333 11.2167 12.4333 10.7167C12.4333 10.2167 12.3389 9.75556 12.15 9.33333C11.9722 8.9 11.7222 8.52222 11.4 8.2L12.2333 7.31667C12.6667 7.75 13.0056 8.26111 13.25 8.85C13.5056 9.42778 13.6333 10.05 13.6333 10.7167C13.6333 11.3833 13.5056 12.0111 13.25 12.6C13.0056 13.1778 12.6667 13.6833 12.2333 14.1167Z"> </path> </g> + <g id="line-focus" viewBox="0 0 16 16"> + <path d="M7.4 14.4V12.8H8.6V14.4H7.4ZM1.6 8.6V7.4H3.2V8.6H1.6ZM12.8 8.6V7.4H14.4V8.6H12.8ZM12.1 12.95L10.9667 11.8167L11.8167 10.9667L12.95 12.1L12.1 12.95ZM3.9 12.95L3.05 12.1L4.18333 10.9667L5.03333 11.8167L3.9 12.95ZM8 11.2C7.11111 11.2 6.35556 10.8889 5.73333 10.2667C5.11111 9.64444 4.8 8.88889 4.8 8C4.8 7.51111 4.9 7.05 5.1 6.61667C5.31111 6.17222 5.61111 5.80556 6 5.51667V2.4H10V5.51667C10.3889 5.80556 10.6833 6.17222 10.8833 6.61667C11.0944 7.05 11.2 7.51111 11.2 8C11.2 8.88889 10.8889 9.64444 10.2667 10.2667C9.64445 10.8889 8.88889 11.2 8 11.2ZM7.2 4.91667C7.33333 4.87222 7.46667 4.84444 7.6 4.83333C7.73333 4.81111 7.86667 4.8 8 4.8C8.13333 4.8 8.26667 4.81111 8.4 4.83333C8.53333 4.84444 8.66667 4.87222 8.8 4.91667V3.6H7.2V4.91667ZM8.01667 10C8.57222 10 9.03889 9.80556 9.41667 9.41667C9.80556 9.02778 10 8.55556 10 8C10 7.44444 9.80556 6.97222 9.41667 6.58333C9.03889 6.19444 8.57222 6 8.01667 6C7.45 6 6.97222 6.19444 6.58333 6.58333C6.19444 6.96111 6 7.43333 6 8C6 8.55556 6.19444 9.02778 6.58333 9.41667C6.97222 9.80556 7.45 10 8.01667 10Z"></path> + </g> + <g id="view-side-panel" viewBox="0 0 16 16"> + <path d="M3.6 12.8C3.26667 12.8 2.98333 12.6833 2.75 12.45C2.51667 12.2167 2.4 11.9333 2.4 11.6V4.4C2.4 4.06667 2.51667 3.78333 2.75 3.55C2.98333 3.31667 3.26667 3.2 3.6 3.2H6.8V4.4H3.6V11.6H6.8V12.8H3.6ZM8 14.4V1.6H9.2V3.2H12.4C12.7333 3.2 13.0167 3.31667 13.25 3.55C13.4833 3.78333 13.6 4.06667 13.6 4.4V11.6C13.6 11.9333 13.4833 12.2167 13.25 12.45C13.0167 12.6833 12.7333 12.8 12.4 12.8H9.2V14.4H8ZM3.6 11.6V4.4V11.6Z"></path> + </g> + <g id="view-fullscreen" viewBox="0 0 16 16"> + <path d="M2.4 13.6V10.4H3.6V12.4H5.6V13.6H2.4ZM10.4 13.6V12.4H12.4V10.4H13.6V13.6H10.4ZM2.4 5.6V2.4H5.6V3.6H3.6V5.6H2.4ZM12.4 5.6V3.6H10.4V2.4H13.6V5.6H12.4Z"></path> + </g> </svg> </cr-iconset> <cr-iconset name="read-anything-20" size="20">
diff --git a/chrome/browser/resources/side_panel/read_anything/read_aloud/speech_controller.ts b/chrome/browser/resources/side_panel/read_anything/read_aloud/speech_controller.ts index 1fadd23..b7d164f8 100644 --- a/chrome/browser/resources/side_panel/read_anything/read_aloud/speech_controller.ts +++ b/chrome/browser/resources/side_panel/read_anything/read_aloud/speech_controller.ts
@@ -299,6 +299,11 @@ // Ensure we're updating Read Aloud state if there's no text to // speak. this.onSpeechFinished_(); + + // Return to avoid speech getting stuck in an indeterminate state. + // It is preferable to end speech immediately after a play button + // press than a playback state with a spinner that never terminates. + return; } } } @@ -447,7 +452,20 @@ if (isInvalidHighlightForWordHighlighting( utteranceTextForWordBoundary.trim())) { this.wordBoundaries_.resetToDefaultState(); - return this.skipCurrentPosition_(isInterrupted, isMovingBackward); + const skippedPosition = + this.skipCurrentPosition_(isInterrupted, isMovingBackward); + // If we paused at the end of a sentence that is the end of the + // available text, resume speech from the beginning. Otherwise, speech + // will abruptly end immediately after a play button press with nothing + // being spoken. + if (!skippedPosition && + getReadAloudModel().getCurrentTextSegments().length === 0) { + getReadAloudModel().resetSpeechToBeginning(); + return this.highlightAndPlayMessage_(isInterrupted, isMovingBackward); + } + + return skippedPosition; + } else { this.playText_(utteranceTextForWordBoundary); }
diff --git a/chrome/browser/resources/signin/managed_user_profile_notice/managed_user_profile_notice_app.ts b/chrome/browser/resources/signin/managed_user_profile_notice/managed_user_profile_notice_app.ts index 56b8842..db963f78 100644 --- a/chrome/browser/resources/signin/managed_user_profile_notice/managed_user_profile_notice_app.ts +++ b/chrome/browser/resources/signin/managed_user_profile_notice/managed_user_profile_notice_app.ts
@@ -13,6 +13,7 @@ import {I18nMixinLit} from 'chrome://resources/cr_elements/i18n_mixin_lit.js'; import {WebUiListenerMixinLit} from 'chrome://resources/cr_elements/web_ui_listener_mixin_lit.js'; +import {assertNotReachedCase} from 'chrome://resources/js/assert.js'; import {loadTimeData} from 'chrome://resources/js/load_time_data.js'; import {CrLitElement} from 'chrome://resources/lit/v3_0/lit.rollup.js'; import type {PropertyValues} from 'chrome://resources/lit/v3_0/lit.rollup.js'; @@ -293,6 +294,8 @@ return this.i18n('closeLabel'); case State.TIMEOUT: return this.i18n('retryLabel'); + default: + assertNotReachedCase(this.currentState_); } }
diff --git a/chrome/browser/resources/suggest_internals/request.ts b/chrome/browser/resources/suggest_internals/request.ts index 59b2656..f68df38 100644 --- a/chrome/browser/resources/suggest_internals/request.ts +++ b/chrome/browser/resources/suggest_internals/request.ts
@@ -133,6 +133,9 @@ break; case 'X-Client-Data': urlType = 'webserver.gws.ClientDataHeader'; + break; + default: + break; } return `"${ groups
diff --git a/chrome/browser/resources/tab_search/auto_tab_groups/auto_tab_groups_page.ts b/chrome/browser/resources/tab_search/auto_tab_groups/auto_tab_groups_page.ts index 8754f9f1..47ee4e5 100644 --- a/chrome/browser/resources/tab_search/auto_tab_groups/auto_tab_groups_page.ts +++ b/chrome/browser/resources/tab_search/auto_tab_groups/auto_tab_groups_page.ts
@@ -12,7 +12,7 @@ import './auto_tab_groups_results.js'; import {CrFeedbackOption} from 'chrome://resources/cr_elements/cr_feedback_buttons/cr_feedback_buttons.js'; -import {assert, assertNotReached} from 'chrome://resources/js/assert.js'; +import {assert, assertNotReachedCase} from 'chrome://resources/js/assert.js'; import {loadTimeData} from 'chrome://resources/js/load_time_data.js'; import {CrLitElement} from 'chrome://resources/lit/v3_0/lit.rollup.js'; @@ -294,6 +294,8 @@ this.apiProxy_.setUserFeedback( this.session_.sessionId, UserFeedback.kUserFeedBackNegative); break; + default: + assertNotReachedCase(event.detail.value); } if (event.detail.value === CrFeedbackOption.THUMBS_DOWN) { // Show feedback dialog @@ -359,7 +361,7 @@ case TabOrganizationState.kFailure: return this.getFailureTitle_(); default: - assertNotReached('Invalid tab organization state'); + assertNotReachedCase(this.state_, 'Invalid tab organization state'); } }
diff --git a/chrome/browser/resources/tab_search/selectable_lazy_list.ts b/chrome/browser/resources/tab_search/selectable_lazy_list.ts index 2b848686..98eeffd6 100644 --- a/chrome/browser/resources/tab_search/selectable_lazy_list.ts +++ b/chrome/browser/resources/tab_search/selectable_lazy_list.ts
@@ -224,6 +224,8 @@ case 'End': this.selected = this.lastSelectableIndex_; break; + default: + break; } }
diff --git a/chrome/browser/resources/tab_search/tab_organization_selector.ts b/chrome/browser/resources/tab_search/tab_organization_selector.ts index 593d06e..ae5c93b 100644 --- a/chrome/browser/resources/tab_search/tab_organization_selector.ts +++ b/chrome/browser/resources/tab_search/tab_organization_selector.ts
@@ -7,6 +7,7 @@ import '/strings.m.js'; import './tab_organization_selector_button.js'; +import {assertNotReachedCase} from 'chrome://resources/js/assert.js'; import {loadTimeData} from 'chrome://resources/js/load_time_data.js'; import {PluralStringProxyImpl} from 'chrome://resources/js/plural_string_proxy.js'; import type {PropertyValues} from 'chrome://resources/lit/v3_0/lit.rollup.js'; @@ -125,6 +126,10 @@ this.$.declutterButton.focus(); } break; + case TabOrganizationFeature.kNone: + break; + default: + assertNotReachedCase(this.selectedState_); } } else if ( changedPrivateProperties.has('disableDeclutter_') &&
diff --git a/chrome/browser/resources/usb_internals/descriptor_panel.ts b/chrome/browser/resources/usb_internals/descriptor_panel.ts index 85bc1e6..4b86b8e 100644 --- a/chrome/browser/resources/usb_internals/descriptor_panel.ts +++ b/chrome/browser/resources/usb_internals/descriptor_panel.ts
@@ -2311,6 +2311,8 @@ directionInputElement = inputTableRow.querySelector('#query-request-type'); break; + default: + break; } assert(directionInputElement); directionInputElement.addEventListener('change', () => { @@ -2438,8 +2440,9 @@ return 'CLASS'; case 2: return 'VENDOR'; + default: + return ''; } - return ''; default: return ''; } @@ -2470,8 +2473,9 @@ return 'ENDPOINT'; case 3: return 'OTHER'; + default: + return ''; } - return ''; default: return ''; } @@ -2499,8 +2503,9 @@ return 'Host-to-Device'; case CONTROL_TRANSFER_DIRECTION_DEVICE_TO_HOST: return 'Device-to-Host'; + default: + return 'Device-to-Host'; } - return 'Device-to-Host'; default: return 'Device-to-Host'; } @@ -2833,6 +2838,8 @@ case UsbTransferStatus.PERMISSION_DENIED: failReason = 'Permission denied'; break; + default: + break; } // Response data will be null if |status| is neither COMPLETED, BABBLE, or // SHORT_PACKET. Throws an error to stop rendering response data. @@ -3075,8 +3082,9 @@ return `${classCode} (Application Specific)`; case 0xFF: return `${classCode} (Vendor Specific)`; + default: + return `${classCode}`; } - return `${classCode}`; } /**
diff --git a/chrome/browser/resources/usb_internals/devices_page.ts b/chrome/browser/resources/usb_internals/devices_page.ts index c1f503c..b08c5d51d 100644 --- a/chrome/browser/resources/usb_internals/devices_page.ts +++ b/chrome/browser/resources/usb_internals/devices_page.ts
@@ -12,13 +12,21 @@ import type {CrTreeElement} from 'chrome://resources/cr_elements/cr_tree/cr_tree.js'; import type {CrTreeItemElement} from 'chrome://resources/cr_elements/cr_tree/cr_tree_item.js'; -import {assert} from 'chrome://resources/js/assert.js'; +import {assert, assertNotReachedCase} from 'chrome://resources/js/assert.js'; import {DescriptorPanel, renderClassCodeWithDescription} from './descriptor_panel.js'; import type {UsbAlternateInterfaceInfo, UsbConfigurationInfo, UsbDeviceInfo, UsbEndpointInfo, UsbInterfaceInfo} from './usb_device.mojom-webui.js'; import {UsbDeviceRemote, UsbTransferDirection, UsbTransferType} from './usb_device.mojom-webui.js'; import type {UsbDeviceManagerRemote} from './usb_manager.mojom-webui.js'; +enum InspectorPanelType { + BOS_DESCRIPTOR = 'bos-descriptor', + CONFIGURATION_DESCRIPTOR = 'configuration-descriptor', + DEVICE_DESCRIPTOR = 'device-descriptor', + STRING_DESCRIPTOR = 'string-descriptor', + TESTING_TOOL = 'testing-tool', +} + /** * Page that contains a tab header and a tab panel displaying devices table. */ @@ -176,21 +184,23 @@ guid, /*blocked_interface_classes=*/[], usbDevice.$.bindNewPipeAndPassReceiver(), /*device_client=*/ null); - const deviceDescriptorPanel = - initialInspectorPanel(tabPanel, 'device-descriptor', usbDevice, guid); + const deviceDescriptorPanel = initialInspectorPanel( + tabPanel, InspectorPanelType.DEVICE_DESCRIPTOR, usbDevice, guid); const configurationDescriptorPanel = initialInspectorPanel( - tabPanel, 'configuration-descriptor', usbDevice, guid); + tabPanel, InspectorPanelType.CONFIGURATION_DESCRIPTOR, usbDevice, guid); - const stringDescriptorPanel = - initialInspectorPanel(tabPanel, 'string-descriptor', usbDevice, guid); + const stringDescriptorPanel = initialInspectorPanel( + tabPanel, InspectorPanelType.STRING_DESCRIPTOR, usbDevice, guid); deviceDescriptorPanel.setStringDescriptorPanel(stringDescriptorPanel); configurationDescriptorPanel.setStringDescriptorPanel( stringDescriptorPanel); - initialInspectorPanel(tabPanel, 'bos-descriptor', usbDevice, guid); + initialInspectorPanel( + tabPanel, InspectorPanelType.BOS_DESCRIPTOR, usbDevice, guid); - initialInspectorPanel(tabPanel, 'testing-tool', usbDevice, guid); + initialInspectorPanel( + tabPanel, InspectorPanelType.TESTING_TOOL, usbDevice, guid); document.body.dispatchEvent(new CustomEvent( 'device-tab-initialized-for-test', {bubbles: true, composed: true})); @@ -333,6 +343,8 @@ case UsbTransferDirection.OUTBOUND: itemLabel += ' (OUTBOUND)'; break; + default: + assertNotReachedCase(endpoint.direction); } const endpointItem = customTreeItem(itemLabel); @@ -351,6 +363,8 @@ case UsbTransferType.INTERRUPT: usbTransferType = 'INTERRUPT'; break; + default: + assertNotReachedCase(endpoint.type); } endpointItem.add(customTreeItem(`USB Transfer Type: ${usbTransferType}`)); @@ -365,8 +379,8 @@ * Initialize a descriptor panel. */ function initialInspectorPanel( - tabPanel: HTMLElement, panelType: string, usbDevice: UsbDeviceRemote, - guid: string): DescriptorPanel { + tabPanel: HTMLElement, panelType: InspectorPanelType, + usbDevice: UsbDeviceRemote, guid: string): DescriptorPanel { const button = tabPanel.querySelector<HTMLElement>(`.${panelType}-button`); assert(button); const displayElement = @@ -374,12 +388,14 @@ assert(displayElement); const descriptorPanel = new DescriptorPanel(usbDevice, displayElement); switch (panelType) { - case 'string-descriptor': + case InspectorPanelType.STRING_DESCRIPTOR: descriptorPanel.initialStringDescriptorPanel(guid); break; - case 'testing-tool': + case InspectorPanelType.TESTING_TOOL: descriptorPanel.initialTestingToolPanel(); break; + default: + break; } button.addEventListener('click', async () => { @@ -389,18 +405,20 @@ if (!displayElement.hidden) { switch (panelType) { - case 'device-descriptor': + case InspectorPanelType.DEVICE_DESCRIPTOR: await descriptorPanel.getDeviceDescriptor(); break; - case 'configuration-descriptor': + case InspectorPanelType.CONFIGURATION_DESCRIPTOR: await descriptorPanel.getConfigurationDescriptor(); break; - case 'string-descriptor': + case InspectorPanelType.STRING_DESCRIPTOR: await descriptorPanel.getAllLanguageCodes(); break; - case 'bos-descriptor': + case InspectorPanelType.BOS_DESCRIPTOR: await descriptorPanel.getBosDescriptor(); break; + default: + break; } } });
diff --git a/chrome/browser/resources/webui_browser/extension_element.ts b/chrome/browser/resources/webui_browser/extension_element.ts index 17180909..c706eddd 100644 --- a/chrome/browser/resources/webui_browser/extension_element.ts +++ b/chrome/browser/resources/webui_browser/extension_element.ts
@@ -65,6 +65,9 @@ break; case 'touch': sourceType = MenuSourceType.kTouch; + break; + default: + break; } this.bar.onContextMenu(sourceType, this.extensionId); }
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 a5b475b..28c608f 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
@@ -23,6 +23,7 @@ import org.chromium.chrome.browser.safe_browsing.metrics.UserAction; import org.chromium.chrome.browser.settings.ChromeManagedPreferenceDelegate; import org.chromium.chrome.browser.settings.SettingsNavigationFactory; +import org.chromium.chrome.browser.settings.search.ChromeBaseSearchIndexProvider; import org.chromium.components.browser_ui.settings.ManagedPreferenceDelegate; /** Fragment containing Safe Browsing settings. */ @@ -298,4 +299,10 @@ public @AnimationType int getAnimationType() { return AnimationType.PROPERTY; } + + // TODO(crbug.com/444470792): Determine what pieces of logic are dynamic and need handling. If + // it's only the summary, it could be worth explicitly defining it in the XML. + public static final ChromeBaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = + new ChromeBaseSearchIndexProvider( + SafeBrowsingSettingsFragment.class.getName(), R.xml.safe_browsing_preferences); }
diff --git a/chrome/browser/safe_browsing/android/java/src/org/chromium/chrome/browser/safe_browsing/settings/StandardProtectionSettingsFragment.java b/chrome/browser/safe_browsing/android/java/src/org/chromium/chrome/browser/safe_browsing/settings/StandardProtectionSettingsFragment.java index 468e218..7a2b8493 100644 --- a/chrome/browser/safe_browsing/android/java/src/org/chromium/chrome/browser/safe_browsing/settings/StandardProtectionSettingsFragment.java +++ b/chrome/browser/safe_browsing/android/java/src/org/chromium/chrome/browser/safe_browsing/settings/StandardProtectionSettingsFragment.java
@@ -14,6 +14,7 @@ import org.chromium.build.annotations.Nullable; import org.chromium.chrome.browser.safe_browsing.SafeBrowsingState; import org.chromium.chrome.browser.settings.ChromeManagedPreferenceDelegate; +import org.chromium.chrome.browser.settings.search.ChromeBaseSearchIndexProvider; import org.chromium.components.browser_ui.settings.ChromeSwitchPreference; import org.chromium.components.browser_ui.settings.ManagedPreferenceDelegate; @@ -101,4 +102,10 @@ public @AnimationType int getAnimationType() { return AnimationType.PROPERTY; } + + // TODO(crbug.com/444470792): Determine what pieces of logic are dynamic and need handling. + public static final ChromeBaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = + new ChromeBaseSearchIndexProvider( + StandardProtectionSettingsFragment.class.getName(), + R.xml.standard_protection_preferences); }
diff --git a/chrome/browser/safety_check/android/java/src/org/chromium/chrome/browser/safety_check/SafetyCheckSettingsFragment.java b/chrome/browser/safety_check/android/java/src/org/chromium/chrome/browser/safety_check/SafetyCheckSettingsFragment.java index 41d3380..ee8c50268 100644 --- a/chrome/browser/safety_check/android/java/src/org/chromium/chrome/browser/safety_check/SafetyCheckSettingsFragment.java +++ b/chrome/browser/safety_check/android/java/src/org/chromium/chrome/browser/safety_check/SafetyCheckSettingsFragment.java
@@ -18,6 +18,7 @@ import org.chromium.build.annotations.NullMarked; import org.chromium.build.annotations.Nullable; import org.chromium.chrome.browser.settings.ChromeBaseSettingsFragment; +import org.chromium.chrome.browser.settings.search.ChromeBaseSearchIndexProvider; import org.chromium.components.browser_ui.settings.EmbeddableSettingsPage; import org.chromium.components.browser_ui.settings.SettingsUtils; import org.chromium.ui.widget.ButtonCompat; @@ -160,4 +161,9 @@ public @AnimationType int getAnimationType() { return AnimationType.PROPERTY; } + + // TODO(crbug.com/444470792): Determine what pieces of logic are dynamic and need handling. + public static final ChromeBaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = + new ChromeBaseSearchIndexProvider( + SafetyCheckSettingsFragment.class.getName(), R.xml.safety_check_preferences); }
diff --git a/chrome/browser/safety_hub/android/java/src/org/chromium/chrome/browser/safety_hub/SafetyHubFragment.java b/chrome/browser/safety_hub/android/java/src/org/chromium/chrome/browser/safety_hub/SafetyHubFragment.java index 356055b..d5d8df76 100644 --- a/chrome/browser/safety_hub/android/java/src/org/chromium/chrome/browser/safety_hub/SafetyHubFragment.java +++ b/chrome/browser/safety_hub/android/java/src/org/chromium/chrome/browser/safety_hub/SafetyHubFragment.java
@@ -30,6 +30,7 @@ import org.chromium.chrome.browser.safety_hub.SafetyHubMetricUtils.LifecycleEvent; import org.chromium.chrome.browser.safety_hub.SafetyHubModuleMediator.ModuleOption; import org.chromium.chrome.browser.safety_hub.SafetyHubModuleMediator.ModuleState; +import org.chromium.chrome.browser.settings.search.ChromeBaseSearchIndexProvider; import org.chromium.chrome.browser.signin.services.IdentityServicesProvider; import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager; import org.chromium.components.browser_ui.settings.SettingsUtils; @@ -374,4 +375,9 @@ public @Nullable String getMainMenuKey() { return "safety_hub"; } + + // TODO(crbug.com/444470792): Determine what pieces of logic are dynamic and need handling. + public static final ChromeBaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = + new ChromeBaseSearchIndexProvider( + SafetyHubFragment.class.getName(), R.xml.safety_hub_preferences); }
diff --git a/chrome/browser/segmentation_platform/client_util/local_tab_handler.cc b/chrome/browser/segmentation_platform/client_util/local_tab_handler.cc index 05ad9e54..d469293 100644 --- a/chrome/browser/segmentation_platform/client_util/local_tab_handler.cc +++ b/chrome/browser/segmentation_platform/client_util/local_tab_handler.cc
@@ -120,7 +120,7 @@ } const TabStripModel* const tab_strip_model = browser->GetTabStripModel(); - for (int i = 0; i < tab_strip_model->GetTabCount(); ++i) { + for (int i = 0; i < tab_strip_model->count(); ++i) { content::WebContents* const web_contents = tab_strip_model->GetWebContentsAt(i); auto* const tab_delegate =
diff --git a/chrome/browser/settings/BUILD.gn b/chrome/browser/settings/BUILD.gn index d2733bc..f9009ad 100644 --- a/chrome/browser/settings/BUILD.gn +++ b/chrome/browser/settings/BUILD.gn
@@ -13,16 +13,15 @@ android_library("search_java") { sources = [ - "search/java/src/org/chromium/chrome/browser/settings/search/BaseSearchIndexProvider.java", - "search/java/src/org/chromium/chrome/browser/settings/search/PreferenceParser.java", - "search/java/src/org/chromium/chrome/browser/settings/search/SearchIndexProvider.java", - "search/java/src/org/chromium/chrome/browser/settings/search/SettingsIndexData.java", + "search/java/src/org/chromium/chrome/browser/settings/search/ChromeBaseSearchIndexProvider.java", + "search/java/src/org/chromium/chrome/browser/settings/search/ChromeSearchIndexProvider.java", ] deps = [ "//base:base_java", "//chrome/browser/flags:java", "//chrome/browser/profiles/android:java", + "//components/browser_ui/settings/android:java", "//content/public/android:content_java", "//third_party/androidx:androidx_annotation_annotation_java", "//third_party/androidx:androidx_preference_preference_java", @@ -123,22 +122,3 @@ testonly = true sources = [ "android/java/res/xml/test_settings_fragment.xml" ] } - -robolectric_library("junit_tests") { - sources = [ - "search/junit/src/org/chromium/chrome/browser/settings/search/BaseSearchIndexProviderTest.java", - "search/junit/src/org/chromium/chrome/browser/settings/search/PreferenceParserTest.java", - "search/junit/src/org/chromium/chrome/browser/settings/search/SettingsIndexDataTest.java", - ] - - deps = [ - ":search_java", - "//base:base_java_test_support", - "//base:base_junit_test_support", - "//chrome/android:chrome_java", - "//chrome/browser/flags:java", - "//chrome/browser/ui/android/night_mode:java", - "//third_party/androidx:androidx_preference_preference_java", - "//third_party/junit", - ] -}
diff --git a/chrome/browser/settings/search/java/src/org/chromium/chrome/browser/settings/search/ChromeBaseSearchIndexProvider.java b/chrome/browser/settings/search/java/src/org/chromium/chrome/browser/settings/search/ChromeBaseSearchIndexProvider.java new file mode 100644 index 0000000..177b4c2 --- /dev/null +++ b/chrome/browser/settings/search/java/src/org/chromium/chrome/browser/settings/search/ChromeBaseSearchIndexProvider.java
@@ -0,0 +1,23 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.settings.search; + +import org.chromium.build.annotations.NullMarked; +import org.chromium.components.browser_ui.settings.search.BaseSearchIndexProvider; + +/** + * A specialization of {@link BaseSearchIndexProvider} for Chrome-layer fragments that rely on the + * profile. + * + * <p>It implements {@link ChromeSearchIndexProvider} to allow Profile access. + */ +@NullMarked +public class ChromeBaseSearchIndexProvider extends BaseSearchIndexProvider + implements ChromeSearchIndexProvider { + + public ChromeBaseSearchIndexProvider(String fragmentName, int xmlRes) { + super(fragmentName, xmlRes); + } +}
diff --git a/chrome/browser/settings/search/java/src/org/chromium/chrome/browser/settings/search/ChromeSearchIndexProvider.java b/chrome/browser/settings/search/java/src/org/chromium/chrome/browser/settings/search/ChromeSearchIndexProvider.java new file mode 100644 index 0000000..e07b2a5c --- /dev/null +++ b/chrome/browser/settings/search/java/src/org/chromium/chrome/browser/settings/search/ChromeSearchIndexProvider.java
@@ -0,0 +1,30 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.settings.search; + +import android.content.Context; + +import org.chromium.build.annotations.NullMarked; +import org.chromium.chrome.browser.profiles.Profile; +import org.chromium.components.browser_ui.settings.search.SearchIndexProvider; +import org.chromium.components.browser_ui.settings.search.SettingsIndexData; + +/** Interface for Chrome preferences that have data for indexing. */ +@NullMarked +public interface ChromeSearchIndexProvider extends SearchIndexProvider { + /** + * Update preferences dynamically with Profile access. + * + * @param context The {@link Context} used to access application resources. + * @param indexData The central {@link SettingsIndexData} object to be populated. + * @param profile The current {@link Profile}. + */ + default void updateDynamicPreferences( + Context context, SettingsIndexData indexData, Profile profile) { + // Default behavior: Fallback to the component-level method + // (in case a Chrome fragment doesn't actually need the profile) + updateDynamicPreferences(context, indexData); + } +}
diff --git a/chrome/browser/settings/search/junit/src/org/chromium/chrome/browser/settings/search/BaseSearchIndexProviderTest.java b/chrome/browser/settings/search/junit/src/org/chromium/chrome/browser/settings/search/BaseSearchIndexProviderTest.java deleted file mode 100644 index 00803ac4..0000000 --- a/chrome/browser/settings/search/junit/src/org/chromium/chrome/browser/settings/search/BaseSearchIndexProviderTest.java +++ /dev/null
@@ -1,149 +0,0 @@ -// Copyright 2025 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package org.chromium.chrome.browser.settings.search; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -import android.content.Context; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; - -import org.chromium.base.ContextUtils; -import org.chromium.base.test.BaseRobolectricTestRunner; -import org.chromium.base.test.util.Features.EnableFeatures; -import org.chromium.chrome.R; -import org.chromium.chrome.browser.appearance.settings.AppearanceSettingsFragment; -import org.chromium.chrome.browser.flags.ChromeFeatureList; -import org.chromium.chrome.browser.night_mode.settings.ThemeSettingsFragment; -import org.chromium.chrome.browser.settings.MainSettings; - -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -/** - * Unit tests for {@link BaseSearchIndexProvider}. - * - * <p>These tests validate the core architectural behavior of the default search provider. - */ -@RunWith(BaseRobolectricTestRunner.class) -@EnableFeatures({ChromeFeatureList.SEARCH_IN_SETTINGS}) -public class BaseSearchIndexProviderTest { - - private Context mContext; - private SettingsIndexData mIndexData; - - private BaseSearchIndexProvider mMainSettingsProvider; - private BaseSearchIndexProvider mAppearanceSettingsProvider; - private BaseSearchIndexProvider mThemeSettingsProvider; - - @Before - public void setUp() { - mContext = ContextUtils.getApplicationContext(); - mIndexData = new SettingsIndexData(); - - mMainSettingsProvider = - new BaseSearchIndexProvider(MainSettings.class.getName(), R.xml.main_preferences); - mAppearanceSettingsProvider = - new BaseSearchIndexProvider( - AppearanceSettingsFragment.class.getName(), R.xml.appearance_preferences); - mThemeSettingsProvider = - new BaseSearchIndexProvider( - ThemeSettingsFragment.class.getName(), - org.chromium.chrome.browser.night_mode.R.xml.theme_preferences); - } - - @Test - public void testRegisterFragmentHeaders_buildsParentMapRecursively() { - Map<String, SearchIndexProvider> providerMap = new HashMap<>(); - providerMap.put(mMainSettingsProvider.getPrefFragmentName(), mMainSettingsProvider); - providerMap.put( - mAppearanceSettingsProvider.getPrefFragmentName(), mAppearanceSettingsProvider); - providerMap.put(mThemeSettingsProvider.getPrefFragmentName(), mThemeSettingsProvider); - Set<String> processedFragments = new HashSet<>(); - - mMainSettingsProvider.registerFragmentHeaders( - mContext, mIndexData, providerMap, processedFragments); - - Map<String, List<String>> parentMap = mIndexData.getChildFragmentToParentKeysForTesting(); - assertFalse("Parent map should not be empty after registration.", parentMap.isEmpty()); - - String appearanceFragmentName = AppearanceSettingsFragment.class.getName(); - String expectedAppearanceParentKey = - PreferenceParser.createUniqueId(MainSettings.class.getName(), "appearance"); - - assertTrue( - "Map should contain a link to AppearanceSettingsFragment.", - parentMap.containsKey(appearanceFragmentName)); - assertEquals( - "AppearanceSettings' parent preference should be 'appearance'.", - expectedAppearanceParentKey, - parentMap.get(appearanceFragmentName).get(0)); - - String themeFragmentName = ThemeSettingsFragment.class.getName(); - String expectedThemeParentKey = - PreferenceParser.createUniqueId( - AppearanceSettingsFragment.class.getName(), "ui_theme"); - - assertTrue( - "Map should contain a link to the grandchild ThemeSettingsFragment.", - parentMap.containsKey(themeFragmentName)); - assertEquals( - "ThemeSettings' parent preference should be 'ui_theme'.", - expectedThemeParentKey, - parentMap.get(themeFragmentName).get(0)); - } - - @Test - public void testInitPreferenceXml_addsEntriesFromXml() { - mAppearanceSettingsProvider.initPreferenceXml(mContext, mIndexData); - - Map<String, SettingsIndexData.Entry> entries = mIndexData.getEntriesForTesting(); - assertFalse("Index should not be empty after indexing.", entries.isEmpty()); - - final String originalThemeKey = "ui_theme"; - final String uniqueThemeKey = - PreferenceParser.createUniqueId( - AppearanceSettingsFragment.class.getName(), originalThemeKey); - - SettingsIndexData.Entry themeEntry = entries.get(uniqueThemeKey); - assertNotNull("'ui_theme' should be indexed from appearance_preferences.", themeEntry); - assertEquals("Key should match the preference key.", originalThemeKey, themeEntry.key); - assertEquals( - "Title should match the string resource.", - mContext.getString(R.string.theme_settings), - themeEntry.title); - assertEquals( - "Parent fragment name should be correctly set to the provider's fragment.", - AppearanceSettingsFragment.class.getName(), - themeEntry.parentFragment); - } - - @Test - public void testProviderWithNoXml_doesNothing() { - BaseSearchIndexProvider providerWithNoXml = - new BaseSearchIndexProvider("some.fragment.Name"); - Map<String, SearchIndexProvider> providerMap = new HashMap<>(); - Set<String> processedFragments = new HashSet<>(); - - providerWithNoXml.initPreferenceXml(mContext, mIndexData); - assertTrue( - "Provider with no XML should not add any entries.", - mIndexData.getEntriesForTesting().isEmpty()); - - providerWithNoXml.registerFragmentHeaders( - mContext, mIndexData, providerMap, processedFragments); - assertTrue( - "Provider with no XML should not add any parent-child links.", - mIndexData.getChildFragmentToParentKeysForTesting().isEmpty()); - } -}
diff --git a/chrome/browser/settings/search/junit/src/org/chromium/chrome/browser/settings/search/PreferenceParserTest.java b/chrome/browser/settings/search/junit/src/org/chromium/chrome/browser/settings/search/PreferenceParserTest.java deleted file mode 100644 index fe8ddb41..0000000 --- a/chrome/browser/settings/search/junit/src/org/chromium/chrome/browser/settings/search/PreferenceParserTest.java +++ /dev/null
@@ -1,130 +0,0 @@ -// Copyright 2025 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package org.chromium.chrome.browser.settings.search; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; - -import android.content.Context; -import android.os.Bundle; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; - -import org.chromium.base.ContextUtils; -import org.chromium.base.test.BaseRobolectricTestRunner; -import org.chromium.base.test.util.Features.EnableFeatures; -import org.chromium.build.annotations.Nullable; -import org.chromium.chrome.R; -import org.chromium.chrome.browser.flags.ChromeFeatureList; -import org.chromium.chrome.browser.privacy.settings.PrivacySettings; -import org.chromium.chrome.browser.settings.MainSettings; - -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -/** Unit tests for {@link PreferenceParser}. */ -@RunWith(BaseRobolectricTestRunner.class) -@EnableFeatures({ChromeFeatureList.SEARCH_IN_SETTINGS}) -public class PreferenceParserTest { - - private Context mContext; - - @Before - public void setUp() { - mContext = ContextUtils.getApplicationContext(); - } - - @Test - public void testParsePreferences_parsesBasicAttributesCorrectly() throws Exception { - List<Bundle> parsedMetadata = - PreferenceParser.parsePreferences(mContext, R.xml.main_preferences); - assertNotNull("The parsed metadata should not be null.", parsedMetadata); - assertTrue( - "Should have parsed a reasonable number of preferences.", - parsedMetadata.size() > 10); - - @Nullable Bundle privacyBundle = findBundleByKey(parsedMetadata, "privacy"); - assertNotNull("The 'privacy' preference should be found.", privacyBundle); - - // Verify the basic attributes are correctly parsed. - assertEquals( - mContext.getString(R.string.prefs_privacy_security), - privacyBundle.getString(PreferenceParser.METADATA_TITLE)); - assertEquals( - PrivacySettings.class.getName(), - privacyBundle.getString(PreferenceParser.METADATA_FRAGMENT)); - } - - @Test - public void testParsePreferences_handlesPreferenceWithNoFragment() throws Exception { - List<Bundle> parsedMetadata = - PreferenceParser.parsePreferences(mContext, R.xml.main_preferences); - @Nullable Bundle notificationsBundle = findBundleByKey(parsedMetadata, "notifications"); - assertNotNull("The 'notifications' preference should be found.", notificationsBundle); - - assertNull( - "The 'notifications' preference should not have a fragment attribute.", - notificationsBundle.getString(PreferenceParser.METADATA_FRAGMENT)); - } - - @Test - public void testParseAndRegisterHeaders_addsParentLinks() { - SettingsIndexData indexData = new SettingsIndexData(); - Map<String, SearchIndexProvider> providerMap = new HashMap<>(); - providerMap.put( - PrivacySettings.class.getName(), - new BaseSearchIndexProvider( - PrivacySettings.class.getName(), R.xml.privacy_preferences)); - Set<String> processedFragments = new HashSet<>(); - - PreferenceParser.parseAndRegisterHeaders( - mContext, - R.xml.main_preferences, - MainSettings.class.getName(), - indexData, - providerMap, - processedFragments); - - Map<String, List<String>> parentMap = indexData.getChildFragmentToParentKeysForTesting(); - assertFalse("The parent-child map should not be empty after parsing.", parentMap.isEmpty()); - - String privacyFragmentName = PrivacySettings.class.getName(); - assertTrue( - "Map should contain an entry for PrivacySettings.", - parentMap.containsKey(privacyFragmentName)); - - List<String> privacyParents = parentMap.get(privacyFragmentName); - assertEquals( - "PrivacySettings should have one parent in this context.", - 1, - privacyParents.size()); - assertEquals( - "The parent of PrivacySettings should be the 'privacy' preference.", - PreferenceParser.createUniqueId(MainSettings.class.getName(), "privacy"), - privacyParents.get(0)); - - assertTrue( - "The parsed fragment should be marked as processed.", - processedFragments.contains(MainSettings.class.getName())); - } - - @Nullable - private Bundle findBundleByKey(List<Bundle> metadata, String key) { - for (Bundle bundle : metadata) { - if (key.equals(bundle.getString(PreferenceParser.METADATA_KEY))) { - return bundle; - } - } - return null; - } -}
diff --git a/chrome/browser/signin/e2e_tests/live_sign_in_test.cc b/chrome/browser/signin/e2e_tests/live_sign_in_test.cc index 3ab67bf..4d7c242 100644 --- a/chrome/browser/signin/e2e_tests/live_sign_in_test.cc +++ b/chrome/browser/signin/e2e_tests/live_sign_in_test.cc
@@ -682,7 +682,7 @@ MANUAL_WebSignInFromExistingChromeSignInTab) { base::HistogramTester histogram_tester; sign_in_functions.StartSignInFromSettings(); - int current_tab_count = browser()->tab_strip_model()->GetTabCount(); + int current_tab_count = browser()->tab_strip_model()->count(); std::optional<TestAccountSigninCredentials> test_account = GetTestAccounts()->GetAccount("TEST_ACCOUNT_1"); @@ -693,11 +693,11 @@ WindowOpenDisposition::CURRENT_TAB, ui::PAGE_TRANSITION_TYPED, false); browser()->tab_strip_model()->GetActiveWebContents()->OpenURL( params, /*navigation_handle_callback=*/{}); - ASSERT_EQ(current_tab_count, browser()->tab_strip_model()->GetTabCount()); + ASSERT_EQ(current_tab_count, browser()->tab_strip_model()->count()); sign_in_functions.SignInFromCurrentPage( browser()->tab_strip_model()->GetActiveWebContents(), *test_account, 0); - ASSERT_EQ(current_tab_count, browser()->tab_strip_model()->GetTabCount()); + ASSERT_EQ(current_tab_count, browser()->tab_strip_model()->count()); // The user should not be signed-in in the browser. EXPECT_FALSE(identity_manager()->HasPrimaryAccount(ConsentLevel::kSignin));
diff --git a/chrome/browser/ssl/android/java/src/org/chromium/chrome/browser/ssl/HttpsFirstModeSettingsFragment.java b/chrome/browser/ssl/android/java/src/org/chromium/chrome/browser/ssl/HttpsFirstModeSettingsFragment.java index 8013055e..3a06edd 100644 --- a/chrome/browser/ssl/android/java/src/org/chromium/chrome/browser/ssl/HttpsFirstModeSettingsFragment.java +++ b/chrome/browser/ssl/android/java/src/org/chromium/chrome/browser/ssl/HttpsFirstModeSettingsFragment.java
@@ -22,6 +22,7 @@ import org.chromium.chrome.browser.safe_browsing.AdvancedProtectionStatusManagerAndroidBridge; import org.chromium.chrome.browser.settings.ChromeBaseSettingsFragment; import org.chromium.chrome.browser.settings.ChromeManagedPreferenceDelegate; +import org.chromium.chrome.browser.settings.search.ChromeBaseSearchIndexProvider; import org.chromium.components.browser_ui.settings.ChromeBasePreference; import org.chromium.components.browser_ui.settings.ChromeSwitchPreference; import org.chromium.components.browser_ui.settings.SettingsUtils; @@ -195,4 +196,10 @@ public @AnimationType int getAnimationType() { return AnimationType.PROPERTY; } + + // TODO(crbug.com/444470792): Determine what pieces of logic are dynamic and need handling. + public static final ChromeBaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = + new ChromeBaseSearchIndexProvider( + HttpsFirstModeSettingsFragment.class.getName(), + R.xml.https_first_mode_settings); }
diff --git a/chrome/browser/supervised_user/android/supervised_user_service_test_bridge.cc b/chrome/browser/supervised_user/android/supervised_user_service_test_bridge.cc index 256d220..9f603736 100644 --- a/chrome/browser/supervised_user/android/supervised_user_service_test_bridge.cc +++ b/chrome/browser/supervised_user/android/supervised_user_service_test_bridge.cc
@@ -31,9 +31,7 @@ content::BrowserContext* browser_context) { Profile* profile = Profile::FromBrowserContext(browser_context); - // Test Supervised User Service also substitutes the content filters with - // fakes. - return std::make_unique<TestSupervisedUserService>( + return std::make_unique<SupervisedUserService>( IdentityManagerFactory::GetForProfile(profile), profile->GetDefaultStoragePartition() ->GetURLLoaderFactoryForBrowserProcess(), @@ -47,15 +45,14 @@ *profile->GetPrefs(), std::make_unique<FakeURLFilterDelegate>(), std::make_unique<safe_search_api::FakeURLCheckerClient>()), std::make_unique<SupervisedUserServicePlatformDelegate>(*profile), - InitialSupervisionState::kUnsupervised); +#if BUILDFLAG(IS_ANDROID) + std::make_unique<ContentFiltersObserverBridge>( + kBrowserContentFiltersSettingName, *profile->GetPrefs()), + std::make_unique<ContentFiltersObserverBridge>( + kSearchContentFiltersSettingName, *profile->GetPrefs()) +#endif // BUILDFLAG(IS_ANDROID) + ); } - -TestSupervisedUserService* GetTestSupervisedUserService(Profile* profile) { - return static_cast<TestSupervisedUserService*>( - SupervisedUserServiceFactory::GetInstance()->GetForBrowserContext( - profile)); -} - } // namespace static void JNI_SupervisedUserServiceTestBridge_Init(JNIEnv* env, @@ -67,17 +64,19 @@ static void JNI_SupervisedUserServiceTestBridge_EnableBrowserContentFilters( JNIEnv* env, Profile* profile) { - GetTestSupervisedUserService(profile) - ->browser_content_filters_observer_weak_ptr() - ->SetEnabled(true); + SupervisedUserServiceFactory::GetInstance() + ->GetForBrowserContext(profile) + ->GetBrowserContentFiltersObserverWeakPtrForTesting() + ->SetEnabledForTesting(true); } static void JNI_SupervisedUserServiceTestBridge_EnableSearchContentFilters( JNIEnv* env, Profile* profile) { - GetTestSupervisedUserService(profile) - ->search_content_filters_observer_weak_ptr() - ->SetEnabled(true); + SupervisedUserServiceFactory::GetInstance() + ->GetForBrowserContext(profile) + ->GetSearchContentFiltersObserverWeakPtrForTesting() + ->SetEnabledForTesting(true); } } // namespace supervised_user
diff --git a/chrome/browser/supervised_user/classify_url_navigation_throttle_unittest.cc b/chrome/browser/supervised_user/classify_url_navigation_throttle_unittest.cc index 7d4b937ec..d7306305 100644 --- a/chrome/browser/supervised_user/classify_url_navigation_throttle_unittest.cc +++ b/chrome/browser/supervised_user/classify_url_navigation_throttle_unittest.cc
@@ -74,7 +74,7 @@ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory = profile->GetDefaultStoragePartition() ->GetURLLoaderFactoryForBrowserProcess(); - return std::make_unique<supervised_user::TestSupervisedUserService>( + return std::make_unique<SupervisedUserService>( IdentityManagerFactory::GetForProfile(profile), profile->GetDefaultStoragePartition() ->GetURLLoaderFactoryForBrowserProcess(), @@ -86,13 +86,19 @@ SyncServiceFactory::GetInstance()->GetForProfile(profile), std::make_unique<MockSupervisedUserURLFilter>( *profile->GetPrefs(), std::make_unique<FakeURLFilterDelegate>(), - std::make_unique< - supervised_user::KidsChromeManagementURLCheckerClient>( + std::make_unique<KidsChromeManagementURLCheckerClient>( identity_manager, url_loader_factory, *profile->GetPrefs(), platform_delegate->GetCountryCode(), platform_delegate->GetChannel())), - std::make_unique<SupervisedUserServicePlatformDelegate>(*profile), - InitialSupervisionState::kUnsupervised); + std::make_unique<SupervisedUserServicePlatformDelegate>(*profile) +#if BUILDFLAG(IS_ANDROID) + , + std::make_unique<FakeContentFiltersObserverBridge>( + kBrowserContentFiltersSettingName, *profile->GetPrefs()), + std::make_unique<FakeContentFiltersObserverBridge>( + kSearchContentFiltersSettingName, *profile->GetPrefs()) +#endif // BUILDFLAG(IS_ANDROID) + ); } class ClassifyUrlNavigationThrottleTest @@ -166,11 +172,8 @@ SupervisedUserServiceFactory::GetForProfile(profile())->GetURLFilter()); } - TestSupervisedUserService* GetSupervisedUserService() { - // Cast is safe: TestSupervisedUserService is created with TestingProfile - // (see ::GetTestingFactories()). - return static_cast<TestSupervisedUserService*>( - SupervisedUserServiceFactory::GetForProfile(profile())); + SupervisedUserService* GetSupervisedUserService() { + return SupervisedUserServiceFactory::GetForProfile(profile()); } base::HistogramTester* histogram_tester() { return &histogram_tester_; } @@ -287,8 +290,8 @@ #if BUILDFLAG(IS_ANDROID) case SupervisionMode::kLocalSupervision: GetSupervisedUserService() - ->browser_content_filters_observer_weak_ptr() - ->SetEnabled(true); + ->GetBrowserContentFiltersObserverWeakPtrForTesting() + ->SetEnabledForTesting(true); break; #endif // BUILDFLAG(IS_ANDROID) }
diff --git a/chrome/browser/supervised_user/kids_profile_interactive_uitest.cc b/chrome/browser/supervised_user/kids_profile_interactive_uitest.cc index a4eec88..5fb0371 100644 --- a/chrome/browser/supervised_user/kids_profile_interactive_uitest.cc +++ b/chrome/browser/supervised_user/kids_profile_interactive_uitest.cc
@@ -46,7 +46,7 @@ std::string_view iframe_name) { content::WebContents* web_contents = nullptr; TabStripModel* const tab_strip_model = browser.tab_strip_model(); - for (int i = 0; i < tab_strip_model->GetTabCount(); ++i) { + for (int i = 0; i < tab_strip_model->count(); ++i) { const std::u16string wc_title = tab_strip_model->GetTabAtIndex(i) ->GetTabFeatures() ->tab_ui_helper()
diff --git a/chrome/browser/supervised_user/supervised_user_navigation_observer_android_browsertest.cc b/chrome/browser/supervised_user/supervised_user_navigation_observer_android_browsertest.cc index 3ff2d44..54b78817 100644 --- a/chrome/browser/supervised_user/supervised_user_navigation_observer_android_browsertest.cc +++ b/chrome/browser/supervised_user/supervised_user_navigation_observer_android_browsertest.cc
@@ -65,13 +65,13 @@ content::WebContents* web_contents() { return chrome_test_utils::GetActiveWebContents(this); } - base::WeakPtr<FakeContentFiltersObserverBridge> search_content_filter() { + base::WeakPtr<ContentFiltersObserverBridge> search_content_filter() { return supervised_user_service() - ->search_content_filters_observer_weak_ptr(); + ->GetSearchContentFiltersObserverWeakPtrForTesting(); } - base::WeakPtr<FakeContentFiltersObserverBridge> browser_content_filter() { + base::WeakPtr<ContentFiltersObserverBridge> browser_content_filter() { return supervised_user_service() - ->browser_content_filters_observer_weak_ptr(); + ->GetBrowserContentFiltersObserverWeakPtrForTesting(); } MockUrlCheckerClient* url_checker_client() { return url_checker_client_; } base::HistogramTester& histogram_tester() { return histogram_tester_; } @@ -116,7 +116,7 @@ std::make_unique<MockUrlCheckerClient>(); url_checker_client_ = url_checker_client.get(); - return std::make_unique<TestSupervisedUserService>( + return std::make_unique<SupervisedUserService>( IdentityManagerFactory::GetForProfile(profile), profile->GetDefaultStoragePartition() ->GetURLLoaderFactoryForBrowserProcess(), @@ -130,13 +130,15 @@ *profile->GetPrefs(), std::make_unique<FakeURLFilterDelegate>(), std::move(url_checker_client)), std::make_unique<SupervisedUserServicePlatformDelegate>(*profile), - InitialSupervisionState::kUnsupervised); + std::make_unique<FakeContentFiltersObserverBridge>( + kBrowserContentFiltersSettingName, *profile->GetPrefs()), + std::make_unique<FakeContentFiltersObserverBridge>( + kSearchContentFiltersSettingName, *profile->GetPrefs())); } - TestSupervisedUserService* supervised_user_service() { - return static_cast<TestSupervisedUserService*>( - SupervisedUserServiceFactory::GetInstance()->GetForProfile( - GetProfile())); + SupervisedUserService* supervised_user_service() { + return SupervisedUserServiceFactory::GetInstance()->GetForProfile( + GetProfile()); } base::HistogramTester histogram_tester_; @@ -163,7 +165,7 @@ // feature consistency. IN_PROC_BROWSER_TEST_F(SupervisedUserNavigationObserverAndroidBrowserTest, LoadSafeSearchResultsWithSearchContentFilterPreset) { - search_content_filter()->SetEnabled(true); + search_content_filter()->SetEnabledForTesting(true); GURL url = embedded_test_server()->GetURL("google.com", "/search?q=cat"); // The final url will be different: with safe search query params. @@ -177,7 +179,7 @@ // params are appended. IN_PROC_BROWSER_TEST_F(SupervisedUserNavigationObserverAndroidBrowserTest, PreexistingSafeSearchParamsAreRemovedBeforeAppending) { - search_content_filter()->SetEnabled(true); + search_content_filter()->SetEnabledForTesting(true); GURL url = embedded_test_server()->GetURL("google.com", "/search?safe=off&ssui=on&q=cat"); @@ -194,19 +196,19 @@ IN_PROC_BROWSER_TEST_F(SupervisedUserNavigationObserverAndroidBrowserTest, ReloadSearchResultAfterSearchContentFilterIsEnabled) { // Verify that the observer is attached. - ASSERT_NE(SupervisedUserNavigationObserver::FromWebContents(web_contents()), - nullptr); + ASSERT_NE(nullptr, + SupervisedUserNavigationObserver::FromWebContents(web_contents())); GURL url = embedded_test_server()->GetURL("google.com", "/search?q=cat"); EXPECT_TRUE(content::NavigateToURL(web_contents(), url)); content::TestNavigationObserver navigation_observer(web_contents()); - search_content_filter()->SetEnabled(true); + search_content_filter()->SetEnabledForTesting(true); navigation_observer.Wait(); // Key part: the search results are reloaded with extra query params. - EXPECT_EQ(web_contents()->GetLastCommittedURL(), - url.spec() + "&safe=active&ssui=on"); + EXPECT_EQ(url.spec() + "&safe=active&ssui=on", + web_contents()->GetLastCommittedURL()); } // Tests if no-approval interstitial is shown when the browser content filter @@ -218,7 +220,7 @@ content::TestNavigationObserver navigation_observer(web_contents()); // Turn the filtering on. That will trigger a url check which is resolved to // restricted. - browser_content_filter()->SetEnabled(true); + browser_content_filter()->SetEnabledForTesting(true); navigation_observer.Wait(); } @@ -238,8 +240,8 @@ SupervisedUserNavigationObserverNoApprovalsInterstitialAndroidBrowserTest, ShowInterstitialPage) { // Verify that the observer is attached. - ASSERT_NE(SupervisedUserNavigationObserver::FromWebContents(web_contents()), - nullptr); + ASSERT_NE(nullptr, + SupervisedUserNavigationObserver::FromWebContents(web_contents())); GURL url = embedded_test_server()->GetURL("/supervised_user/simple.html"); // In this test, all classifications are restricted after enabling the @@ -252,15 +254,14 @@ // Navigate to a simple page and verify the title. The page is not filtered. ASSERT_TRUE(content::NavigateToURL(web_contents(), url)); - ASSERT_EQ(web_contents()->GetTitle(), u"Supervised User test: simple page"); + ASSERT_EQ(u"Supervised User test: simple page", web_contents()->GetTitle()); EnableBrowserFilteringAndWaitForInterstitial(); - EXPECT_EQ(web_contents()->GetTitle(), u"Site blocked"); + EXPECT_EQ(u"Site blocked", web_contents()->GetTitle()); // Learn more button is specific to this interstitial. - EXPECT_EQ(content::ExecJs(web_contents(), - "document.getElementById('learn-more-button');"), - true); + EXPECT_TRUE(content::ExecJs(web_contents(), + "document.getElementById('learn-more-button');")); } // Clicks the learn more button on the interstitial page and verifies that the @@ -269,8 +270,8 @@ SupervisedUserNavigationObserverNoApprovalsInterstitialAndroidBrowserTest, GoToHelpCenterPage) { // Verify that the observer is attached. - ASSERT_NE(SupervisedUserNavigationObserver::FromWebContents(web_contents()), - nullptr); + ASSERT_NE(nullptr, + SupervisedUserNavigationObserver::FromWebContents(web_contents())); // In this test, all classifications are restricted after enabling the // browser content filter. @@ -284,11 +285,11 @@ ASSERT_TRUE(content::NavigateToURL( web_contents(), embedded_test_server()->GetURL("/supervised_user/simple.html"))); - ASSERT_EQ(web_contents()->GetTitle(), u"Supervised User test: simple page"); + ASSERT_EQ(u"Supervised User test: simple page", web_contents()->GetTitle()); // After filters are enabled, the interstitial page is shown. EnableBrowserFilteringAndWaitForInterstitial(); - EXPECT_EQ(web_contents()->GetTitle(), u"Site blocked"); + EXPECT_EQ(u"Site blocked", web_contents()->GetTitle()); // Navigation to google.com pages is expected to be always allowed. GURL help_center_url = GURL(kDeviceFiltersHelpCenterUrl); @@ -307,8 +308,8 @@ // This expectation verifies that the help center page was attempted to be // loaded (test don't have internet) - EXPECT_EQ(web_contents()->GetTitle(), - base::UTF8ToUTF16(help_center_url.GetHost())); + EXPECT_EQ(base::UTF8ToUTF16(help_center_url.GetHost()), + web_contents()->GetTitle()); } // Clicks the back button on the interstitial page and verifies that the @@ -327,7 +328,7 @@ // In this test to facilitate the back button click, one url is allowed but // others are not. All navigations are subject to classification in this test. - browser_content_filter()->SetEnabled(true); + browser_content_filter()->SetEnabledForTesting(true); // Three classification calls are expected: // 1. when the page is first loaded @@ -347,13 +348,13 @@ // Navigate to a simple page and verify the title. The page is not filtered. ASSERT_TRUE(content::NavigateToURL(web_contents(), allowed_url)); - ASSERT_EQ(web_contents()->GetTitle(), u"Supervised User test: simple page"); + ASSERT_EQ(u"Supervised User test: simple page", web_contents()->GetTitle()); // Navigate to blocked url. The navigation is not successful even though the // url is committed, because the interstitial blocks it. EXPECT_FALSE(content::NavigateToURL(web_contents(), blocked_url)); - EXPECT_EQ(web_contents()->GetTitle(), u"Site blocked"); - EXPECT_EQ(web_contents()->GetLastCommittedURL(), blocked_url); + EXPECT_EQ(u"Site blocked", web_contents()->GetTitle()); + EXPECT_EQ(blocked_url, web_contents()->GetLastCommittedURL()); // After clicking the back button, the previous page is available back again. histogram_tester().ExpectTotalCount("ManagedMode.BlockingInterstitialCommand", @@ -363,8 +364,8 @@ "ManagedMode.BlockingInterstitialCommand", SupervisedUserInterstitial::Commands::BACK, 1); - EXPECT_EQ(web_contents()->GetTitle(), u"Supervised User test: simple page"); - EXPECT_EQ(web_contents()->GetLastCommittedURL(), allowed_url); + EXPECT_EQ(u"Supervised User test: simple page", web_contents()->GetTitle()); + EXPECT_EQ(allowed_url, web_contents()->GetLastCommittedURL()); } } // namespace
diff --git a/chrome/browser/supervised_user/supervised_user_service_android_browsertest.cc b/chrome/browser/supervised_user/supervised_user_service_android_browsertest.cc index 616e3fe..84803bf 100644 --- a/chrome/browser/supervised_user/supervised_user_service_android_browsertest.cc +++ b/chrome/browser/supervised_user/supervised_user_service_android_browsertest.cc
@@ -62,13 +62,14 @@ class SupervisedUserServiceBootstrapAndroidBrowserTestBase : public AndroidBrowserTest { protected: - // Creates a fake content filters observer bridge for testing, and binds it to - // this test fixture. - virtual std::unique_ptr<ContentFiltersObserverBridge> CreateBridge( - std::string_view setting_name, - base::RepeatingClosure on_enabled, - base::RepeatingClosure on_disabled, - base::RepeatingCallback<bool()> is_subject_to_parental_controls) = 0; + SupervisedUserServiceBootstrapAndroidBrowserTestBase() = default; + SupervisedUserServiceBootstrapAndroidBrowserTestBase( + bool initial_browser_content_filters_value, + bool initial_search_content_filters_value) + : initial_browser_content_filters_value_( + initial_browser_content_filters_value), + initial_search_content_filters_value_( + initial_search_content_filters_value) {} // Called just before supervised user service is created. Much like // SetUpLocalStatePrefService, but called after prefs are registered. @@ -80,9 +81,8 @@ MockUrlCheckerClient* url_checker_client() { return url_checker_client_; } base::HistogramTester& histogram_tester() { return histogram_tester_; } - TestSupervisedUserService* GetTestSupervisedUserService() { - return static_cast<TestSupervisedUserService*>( - SupervisedUserServiceFactory::GetForProfile(GetProfile())); + SupervisedUserService* GetSupervisedUserService() { + return SupervisedUserServiceFactory::GetForProfile(GetProfile()); } private: @@ -136,7 +136,22 @@ std::make_unique<MockUrlCheckerClient>(); url_checker_client_ = url_checker_client.get(); - return std::make_unique<TestSupervisedUserService>( + // Create the bridge and configure its initial value before passing + // ownership to the SupervisedUserService. + std::unique_ptr<FakeContentFiltersObserverBridge> browser_bridge = + std::make_unique<FakeContentFiltersObserverBridge>( + kBrowserContentFiltersSettingName, *profile->GetPrefs()); + browser_bridge->SetEnabledForTesting( + initial_browser_content_filters_value_); + + // Create the bridge and configure its initial value before passing + // ownership to the SupervisedUserService. + std::unique_ptr<FakeContentFiltersObserverBridge> search_bridge = + std::make_unique<FakeContentFiltersObserverBridge>( + kSearchContentFiltersSettingName, *profile->GetPrefs()); + search_bridge->SetEnabledForTesting(initial_search_content_filters_value_); + + return std::make_unique<SupervisedUserService>( IdentityManagerFactory::GetForProfile(profile), profile->GetDefaultStoragePartition() ->GetURLLoaderFactoryForBrowserProcess(), @@ -149,12 +164,13 @@ std::make_unique<SupervisedUserURLFilter>( *profile->GetPrefs(), std::make_unique<FakeURLFilterDelegate>(), std::move(url_checker_client)), - std::make_unique<SupervisedUserServicePlatformDelegate>(*profile), - base::BindRepeating( - &SupervisedUserServiceBootstrapAndroidBrowserTestBase::CreateBridge, - base::Unretained(this))); + std::move(platform_delegate), std::move(browser_bridge), + std::move(search_bridge)); } + bool initial_browser_content_filters_value_ = false; + bool initial_search_content_filters_value_ = false; + base::HistogramTester histogram_tester_; raw_ptr<MockUrlCheckerClient> url_checker_client_; base::test::ScopedFeatureList scoped_feature_list_{ @@ -168,17 +184,6 @@ // Determines the value of search device filter on browser startup. bool initial_search_content_filters_value; - // Returns the initial value for the given content filters setting. - bool ResolveInitialValueForFilter(std::string_view setting_name) const { - if (setting_name == kBrowserContentFiltersSettingName) { - return initial_browser_content_filters_value; - } - if (setting_name == kSearchContentFiltersSettingName) { - return initial_search_content_filters_value; - } - NOTREACHED() << "Unsupported setting name: " << setting_name; - } - // Returns true if incognito should be blocked based on the initial values of // the content filters settings. bool ShouldBlockIncognito() const { @@ -193,20 +198,16 @@ : public SupervisedUserServiceBootstrapAndroidBrowserTestBase, public ::testing::WithParamInterface<BootstrapServiceTestCase> { protected: - std::unique_ptr<ContentFiltersObserverBridge> CreateBridge( - std::string_view setting_name, - base::RepeatingClosure on_enabled, - base::RepeatingClosure on_disabled, - base::RepeatingCallback<bool()> is_subject_to_parental_controls) - override { - return std::make_unique<FakeContentFiltersObserverBridge>( - setting_name, on_enabled, on_disabled, is_subject_to_parental_controls, - GetParam().ResolveInitialValueForFilter(setting_name)); - } + SupervisedUserServiceBootstrapAndroidBrowserTest() + : SupervisedUserServiceBootstrapAndroidBrowserTestBase( + GetParam().initial_browser_content_filters_value, + GetParam().initial_search_content_filters_value) {} }; IN_PROC_BROWSER_TEST_P(SupervisedUserServiceBootstrapAndroidBrowserTest, IncognitoIsBlockedWhenAnyFilterIsEnabled) { + ASSERT_NE(nullptr, SupervisedUserServiceFactory::GetForProfile(GetProfile())); + policy::IncognitoModeAvailability expected_incognito_mode_availability = GetParam().ShouldBlockIncognito() ? policy::IncognitoModeAvailability::kDisabled @@ -214,10 +215,10 @@ // TODO(http://crbug.com/433234589): this test could actually try to open // incognito (to no avail). - EXPECT_EQ(static_cast<policy::IncognitoModeAvailability>( + EXPECT_EQ(expected_incognito_mode_availability, + static_cast<policy::IncognitoModeAvailability>( GetProfile()->GetPrefs()->GetInteger( - policy::policy_prefs::kIncognitoModeAvailability)), - expected_incognito_mode_availability); + policy::policy_prefs::kIncognitoModeAvailability))); } IN_PROC_BROWSER_TEST_P(SupervisedUserServiceBootstrapAndroidBrowserTest, @@ -314,13 +315,13 @@ FamilyLinkOverridesLocalSupervision) { SupervisedUserService* service = SupervisedUserServiceFactory::GetForProfile(GetProfile()); - bool is_initiall_supervised_locally = + bool is_initially_supervised_locally = GetParam().initial_browser_content_filters_value || GetParam().initial_search_content_filters_value; // Local supervision is initially enabled/disabled based on the test case, but // Family Link supervision is always disabled. - ASSERT_EQ(service->IsSupervisedLocally(), is_initiall_supervised_locally); + ASSERT_EQ(is_initially_supervised_locally, service->IsSupervisedLocally()); ASSERT_FALSE(IsSubjectToParentalControls(*GetProfile()->GetPrefs())); EnableParentalControls(*GetProfile()->GetPrefs()); @@ -329,7 +330,7 @@ // always enabled, and if there was a conflict, it's recorded. histogram_tester().ExpectBucketCount( "SupervisedUsers.FamilyLinkSupervisionConflict", 1, - is_initiall_supervised_locally ? 1 : 0); + is_initially_supervised_locally ? 1 : 0); EXPECT_FALSE(service->IsSupervisedLocally()); EXPECT_TRUE(IsSubjectToParentalControls(*GetProfile()->GetPrefs())); } @@ -361,17 +362,6 @@ class SupervisedUserServiceBootstrapAndroidBrowserWithSupervisedUserTest : public SupervisedUserServiceBootstrapAndroidBrowserTestBase { protected: - std::unique_ptr<ContentFiltersObserverBridge> CreateBridge( - std::string_view setting_name, - base::RepeatingClosure on_enabled, - base::RepeatingClosure on_disabled, - base::RepeatingCallback<bool()> is_subject_to_parental_controls) - override { - return std::make_unique<FakeContentFiltersObserverBridge>( - setting_name, on_enabled, on_disabled, is_subject_to_parental_controls, - /*initial_value=*/false); - } - void SetUpPrefs(PrefService* local_state) override { EnableParentalControls(*local_state); } @@ -421,7 +411,7 @@ IN_PROC_BROWSER_TEST_F( SupervisedUserServiceBootstrapAndroidBrowserWithSupervisedUserTest, FamilyLinkIsImmuneToLocalSupervision) { - TestSupervisedUserService* service = GetTestSupervisedUserService(); + SupervisedUserService* service = GetSupervisedUserService(); // Local supervision is initially disabled and Family Link supervision is // initially enabled. @@ -429,18 +419,16 @@ ASSERT_TRUE(IsSubjectToParentalControls(*GetProfile()->GetPrefs())); // Try turning the knob on the local supervision (browser filtering). - service->browser_content_filters_observer_weak_ptr()->OnChange( - /*env=*/nullptr, - /*enabled=*/true); + service->GetBrowserContentFiltersObserverWeakPtrForTesting() + ->SetEnabledForTesting(true); EXPECT_FALSE(service->IsSupervisedLocally()); EXPECT_TRUE(IsSubjectToParentalControls(*GetProfile()->GetPrefs())); histogram_tester().ExpectBucketCount( "SupervisedUsers.FamilyLinkSupervisionConflict", 1, 1); // Try turning the knob on the local supervision (search filtering). - service->search_content_filters_observer_weak_ptr()->OnChange( - /*env=*/nullptr, - /*enabled=*/true); + service->GetSearchContentFiltersObserverWeakPtrForTesting() + ->SetEnabledForTesting(true); EXPECT_FALSE(service->IsSupervisedLocally()); EXPECT_TRUE(IsSubjectToParentalControls(*GetProfile()->GetPrefs())); histogram_tester().ExpectBucketCount( @@ -450,19 +438,7 @@ // Tests the aspect where the Family Link supervision is disabled and the // content filters are not set. class SupervisedUserServiceBootstrapAndroidBrowserWithRegularUserTest - : public SupervisedUserServiceBootstrapAndroidBrowserTestBase { - protected: - std::unique_ptr<ContentFiltersObserverBridge> CreateBridge( - std::string_view setting_name, - base::RepeatingClosure on_enabled, - base::RepeatingClosure on_disabled, - base::RepeatingCallback<bool()> is_subject_to_parental_controls) - override { - return std::make_unique<FakeContentFiltersObserverBridge>( - setting_name, on_enabled, on_disabled, is_subject_to_parental_controls, - /*initial_value=*/false); - } -}; + : public SupervisedUserServiceBootstrapAndroidBrowserTestBase {}; IN_PROC_BROWSER_TEST_F( SupervisedUserServiceBootstrapAndroidBrowserWithRegularUserTest,
diff --git a/chrome/browser/supervised_user/supervised_user_service_factory.cc b/chrome/browser/supervised_user/supervised_user_service_factory.cc index 215b2ce5..6de615d1 100644 --- a/chrome/browser/supervised_user/supervised_user_service_factory.cc +++ b/chrome/browser/supervised_user/supervised_user_service_factory.cc
@@ -98,8 +98,12 @@ std::move(platform_delegate) #if BUILDFLAG(IS_ANDROID) , - base::BindRepeating( - &supervised_user::ContentFiltersObserverBridge::Create) + std::make_unique<supervised_user::ContentFiltersObserverBridge>( + supervised_user::kBrowserContentFiltersSettingName, + *profile->GetPrefs()), + std::make_unique<supervised_user::ContentFiltersObserverBridge>( + supervised_user::kSearchContentFiltersSettingName, + *profile->GetPrefs()) #endif // BUILDFLAG(IS_ANDROID) ); }
diff --git a/chrome/browser/supervised_user/supervised_user_test_util.h b/chrome/browser/supervised_user/supervised_user_test_util.h index 173abad..f68f2a5 100644 --- a/chrome/browser/supervised_user/supervised_user_test_util.h +++ b/chrome/browser/supervised_user/supervised_user_test_util.h
@@ -13,9 +13,9 @@ #include "chrome/browser/profiles/profile_key.h" #include "chrome/browser/signin/identity_manager_factory.h" #include "chrome/browser/supervised_user/android/supervised_user_service_platform_delegate.h" +#include "chrome/browser/supervised_user/supervised_user_content_filters_service_factory.h" #include "chrome/browser/supervised_user/supervised_user_service_factory.h" #include "chrome/browser/supervised_user/supervised_user_settings_service_factory.h" -#include "chrome/browser/supervised_user/supervised_user_content_filters_service_factory.h" #include "chrome/browser/sync/sync_service_factory.h" #include "components/keyed_service/core/keyed_service_factory.h" #include "components/supervised_user/core/browser/kids_chrome_management_url_checker_client.h" @@ -93,6 +93,7 @@ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory = profile->GetDefaultStoragePartition() ->GetURLLoaderFactoryForBrowserProcess(); + return std::make_unique<supervised_user::SupervisedUserService>( IdentityManagerFactory::GetForProfile(profile), profile->GetDefaultStoragePartition() @@ -113,8 +114,12 @@ std::make_unique<SupervisedUserServicePlatformDelegate>(*profile) #if BUILDFLAG(IS_ANDROID) , - base::BindRepeating( - &supervised_user::ContentFiltersObserverBridge::Create) + std::make_unique<supervised_user::ContentFiltersObserverBridge>( + supervised_user::kBrowserContentFiltersSettingName, + *profile->GetPrefs()), + std::make_unique<supervised_user::ContentFiltersObserverBridge>( + supervised_user::kSearchContentFiltersSettingName, + *profile->GetPrefs()) #endif // BUILDFLAG(IS_ANDROID) ); }
diff --git a/chrome/browser/sync/test/integration/single_client_nigori_sync_test.cc b/chrome/browser/sync/test/integration/single_client_nigori_sync_test.cc index 5fedf33f..2f2f5f4 100644 --- a/chrome/browser/sync/test/integration/single_client_nigori_sync_test.cc +++ b/chrome/browser/sync/test/integration/single_client_nigori_sync_test.cc
@@ -427,25 +427,6 @@ GetSyncTestModes(), testing::PrintToStringParamName()); -// Some tests are flaky on Chromeos when run with IP Protection enabled. -// TODO(crbug.com/40935754): Fix flakes. -class SingleClientNigoriCrossUserSharingPublicPrivateKeyPairSyncTestNoIpProt - : public SingleClientNigoriCrossUserSharingPublicPrivateKeyPairSyncTest { - public: - SingleClientNigoriCrossUserSharingPublicPrivateKeyPairSyncTestNoIpProt() { - feature_list_.InitAndDisableFeature( - net::features::kEnableIpProtectionProxy); - } - - private: - base::test::ScopedFeatureList feature_list_; -}; - -INSTANTIATE_TEST_SUITE_P( - /* no prefix */, - SingleClientNigoriCrossUserSharingPublicPrivateKeyPairSyncTestNoIpProt, - GetSyncTestModes(), - testing::PrintToStringParamName()); IN_PROC_BROWSER_TEST_P(SingleClientNigoriSyncTest, ShouldCommitKeystoreNigoriWhenReceivedDefault) { @@ -1060,7 +1041,7 @@ } IN_PROC_BROWSER_TEST_P( - SingleClientNigoriCrossUserSharingPublicPrivateKeyPairSyncTestNoIpProt, + SingleClientNigoriCrossUserSharingPublicPrivateKeyPairSyncTest, PRE_ShouldSyncCrossUserSharingPublicPrivateKeyPair) { const std::vector<std::vector<uint8_t>>& keystore_keys = GetFakeServer()->GetKeystoreKeys(); @@ -1080,7 +1061,7 @@ } IN_PROC_BROWSER_TEST_P( - SingleClientNigoriCrossUserSharingPublicPrivateKeyPairSyncTestNoIpProt, + SingleClientNigoriCrossUserSharingPublicPrivateKeyPairSyncTest, ShouldSyncCrossUserSharingPublicPrivateKeyPair) { ASSERT_TRUE(SetupSync()); sync_pb::NigoriSpecifics specifics;
diff --git a/chrome/browser/sync/test/integration/single_client_webauthn_credentials_sync_test.cc b/chrome/browser/sync/test/integration/single_client_webauthn_credentials_sync_test.cc index 598c9b6e..0467de4c 100644 --- a/chrome/browser/sync/test/integration/single_client_webauthn_credentials_sync_test.cc +++ b/chrome/browser/sync/test/integration/single_client_webauthn_credentials_sync_test.cc
@@ -51,7 +51,6 @@ using testing::Optional; using testing::UnorderedElementsAre; using testing::UnorderedElementsAreArray; - using webauthn_credentials_helper::EntityHasCurrentHiddenTime; using webauthn_credentials_helper::EntityHasDisplayName; using webauthn_credentials_helper::EntityHasHidden; @@ -72,6 +71,8 @@ using webauthn_credentials_helper::PasskeySpecificsEq; using webauthn_credentials_helper::PasskeySyncActiveChecker; using webauthn_credentials_helper::ServerPasskeysMatchChecker; +using AnyRp = ::webauthn::PasskeyModel::AnyRp; +using ShadowedCredentials = ::webauthn::PasskeyModel::ShadowedCredentials; constexpr int kSingleProfile = 0; constexpr char kUsername1[] = "anya"; @@ -273,7 +274,7 @@ ElementsAre(EntityHasSyncId(passkey.sync_id()))) .Wait()); - EXPECT_THAT(GetModel().GetAllPasskeys(), + EXPECT_THAT(GetModel().GetPasskeys(AnyRp(), ShadowedCredentials::kInclude), ElementsAre(PasskeySpecificsEq(passkey))); EXPECT_THAT(passkey, PasskeyHasRpId(kTestRpId)); @@ -322,11 +323,13 @@ new_passkey.newly_shadowed_credential_ids(), UnorderedElementsAre(passkey1a.credential_id(), passkey1b.credential_id(), passkey1c.credential_id())); - EXPECT_THAT(GetModel().GetPasskeysForRelyingPartyId(passkey1a.rp_id()), - UnorderedElementsAre(PasskeyHasSyncId(passkey3.sync_id()), - PasskeyHasSyncId(new_passkey.sync_id()))); - EXPECT_THAT(GetModel().GetPasskeysForRelyingPartyId(passkey2.rp_id()), - ElementsAre(PasskeyHasSyncId(passkey2.sync_id()))); + EXPECT_THAT( + GetModel().GetPasskeys(passkey1a.rp_id(), ShadowedCredentials::kExclude), + UnorderedElementsAre(PasskeyHasSyncId(passkey3.sync_id()), + PasskeyHasSyncId(new_passkey.sync_id()))); + EXPECT_THAT( + GetModel().GetPasskeys(passkey2.rp_id(), ShadowedCredentials::kExclude), + ElementsAre(PasskeyHasSyncId(passkey2.sync_id()))); } // Tests CreatePasskey from a pre-constructed WebAuthnCredentialSpecifics. @@ -340,7 +343,7 @@ EXPECT_TRUE(ServerPasskeysMatchChecker( ElementsAre(EntityHasSyncId(passkey.sync_id()))) .Wait()); - EXPECT_THAT(GetModel().GetAllPasskeys(), + EXPECT_THAT(GetModel().GetPasskeys(AnyRp(), ShadowedCredentials::kInclude), ElementsAre(PasskeySpecificsEq(passkey))); EXPECT_THAT(passkey, PasskeyHasRpId(kTestRpId)); } @@ -381,11 +384,13 @@ new_passkey.newly_shadowed_credential_ids(), UnorderedElementsAre(passkey1a.credential_id(), passkey1b.credential_id(), passkey1c.credential_id())); - EXPECT_THAT(GetModel().GetPasskeysForRelyingPartyId(passkey1a.rp_id()), - UnorderedElementsAre(PasskeyHasSyncId(passkey3.sync_id()), - PasskeyHasSyncId(new_passkey.sync_id()))); - EXPECT_THAT(GetModel().GetPasskeysForRelyingPartyId(passkey2.rp_id()), - ElementsAre(PasskeyHasSyncId(passkey2.sync_id()))); + EXPECT_THAT( + GetModel().GetPasskeys(passkey1a.rp_id(), ShadowedCredentials::kExclude), + UnorderedElementsAre(PasskeyHasSyncId(passkey3.sync_id()), + PasskeyHasSyncId(new_passkey.sync_id()))); + EXPECT_THAT( + GetModel().GetPasskeys(passkey2.rp_id(), ShadowedCredentials::kExclude), + ElementsAre(PasskeyHasSyncId(passkey2.sync_id()))); } // Adding a remote passkey should sync to the client. @@ -423,9 +428,10 @@ PasskeyHasSyncId(sync_id2))) .Wait()); - EXPECT_THAT(GetModel().GetPasskeysForRelyingPartyId(passkey1a.rp_id()), - UnorderedElementsAre(PasskeyHasSyncId(sync_id1a), - PasskeyHasSyncId(sync_id1b))); + EXPECT_THAT( + GetModel().GetPasskeys(passkey1a.rp_id(), ShadowedCredentials::kExclude), + UnorderedElementsAre(PasskeyHasSyncId(sync_id1a), + PasskeyHasSyncId(sync_id1b))); EXPECT_THAT(GetModel().GetPasskeyByCredentialId(passkey1a.rp_id(), passkey1a.credential_id()), Optional(PasskeyHasSyncId(sync_id1a))); @@ -436,7 +442,7 @@ GetModel().GetPasskeyByCredentialId(kRpId2, passkey1a.credential_id()), std::nullopt); - EXPECT_THAT(GetModel().GetPasskeysForRelyingPartyId(kRpId2), + EXPECT_THAT(GetModel().GetPasskeys(kRpId2, ShadowedCredentials::kExclude), ElementsAre(PasskeyHasSyncId(sync_id2))); } @@ -462,16 +468,18 @@ PasskeyHasSyncId(sync_id2))) .Wait()); - EXPECT_THAT(GetModel().GetPasskeysForRelyingPartyId(passkey1.rp_id()), - ElementsAre(PasskeyHasSyncId(sync_id1))); + EXPECT_THAT( + GetModel().GetPasskeys(passkey1.rp_id(), ShadowedCredentials::kExclude), + ElementsAre(PasskeyHasSyncId(sync_id1))); EXPECT_THAT(GetModel().GetPasskeyByCredentialId(passkey1.rp_id(), passkey1.credential_id()), Optional(PasskeyHasSyncId(sync_id1))); EXPECT_EQ(GetModel().GetPasskeyByCredentialId( passkey1_shadow.rp_id(), passkey1_shadow.credential_id()), std::nullopt); - EXPECT_THAT(GetModel().GetPasskeysForRelyingPartyId(passkey2.rp_id()), - ElementsAre(PasskeyHasSyncId(sync_id2))); + EXPECT_THAT( + GetModel().GetPasskeys(passkey2.rp_id(), ShadowedCredentials::kExclude), + ElementsAre(PasskeyHasSyncId(sync_id2))); EXPECT_THAT( GetModel().GetPasskeyByCredentialId(kRpId2, passkey2.credential_id()), Optional(PasskeyHasSyncId(sync_id2))); @@ -681,7 +689,8 @@ .Wait()); GetModel().DeleteAllPasskeys(); - EXPECT_TRUE(GetModel().GetAllPasskeys().empty()); + EXPECT_TRUE( + GetModel().GetPasskeys(AnyRp(), ShadowedCredentials::kInclude).empty()); EXPECT_TRUE(ServerPasskeysMatchChecker(IsEmpty()).Wait()); } @@ -689,12 +698,14 @@ DeleteAllPasskeysEmptyStore) { ASSERT_TRUE(SetupSync()); - EXPECT_TRUE(GetModel().GetAllPasskeys().empty()); + EXPECT_TRUE( + GetModel().GetPasskeys(AnyRp(), ShadowedCredentials::kInclude).empty()); EXPECT_TRUE(ServerPasskeysMatchChecker(IsEmpty()).Wait()); GetModel().DeleteAllPasskeys(); - EXPECT_TRUE(GetModel().GetAllPasskeys().empty()); + EXPECT_TRUE( + GetModel().GetPasskeys(AnyRp(), ShadowedCredentials::kInclude).empty()); EXPECT_TRUE(ServerPasskeysMatchChecker(IsEmpty()).Wait()); } @@ -708,17 +719,19 @@ EXPECT_TRUE(ServerPasskeysMatchChecker( ElementsAre(EntityHasSyncId(passkey.sync_id()))) .Wait()); - EXPECT_THAT(GetModel().GetAllPasskeys(), + EXPECT_THAT(GetModel().GetPasskeys(AnyRp(), ShadowedCredentials::kInclude), ElementsAre(PasskeyHasSyncId(passkey.sync_id()))); GetModel().DeletePasskey(passkey.credential_id(), FROM_HERE); - EXPECT_TRUE(GetModel().GetAllPasskeys().empty()); + EXPECT_TRUE( + GetModel().GetPasskeys(AnyRp(), ShadowedCredentials::kInclude).empty()); } IN_PROC_BROWSER_TEST_P(SingleClientWebAuthnCredentialsSyncTest, DeletingPasskeysPersistsOverRestarts) { ASSERT_TRUE(SetupClients()); ASSERT_TRUE(GetClient(0)->AwaitSyncTransportActive()); - EXPECT_TRUE(GetModel().GetAllPasskeys().empty()); + EXPECT_TRUE( + GetModel().GetPasskeys(AnyRp(), ShadowedCredentials::kInclude).empty()); } IN_PROC_BROWSER_TEST_P(SingleClientWebAuthnCredentialsSyncTest, @@ -744,7 +757,7 @@ EntityHasCurrentHiddenTime()))) .Wait()); const std::vector<sync_pb::WebauthnCredentialSpecifics> passkeys = - GetModel().GetAllPasskeys(); + GetModel().GetPasskeys(AnyRp(), ShadowedCredentials::kInclude); ASSERT_EQ(passkeys.size(), 1u); EXPECT_TRUE(passkeys[0].hidden()); @@ -764,7 +777,7 @@ ServerPasskeysMatchChecker(UnorderedElementsAre(EntityHasHidden(false))) .Wait()); const std::vector<sync_pb::WebauthnCredentialSpecifics> passkeys = - GetModel().GetAllPasskeys(); + GetModel().GetPasskeys(AnyRp(), ShadowedCredentials::kInclude); ASSERT_EQ(passkeys.size(), 1u); EXPECT_FALSE(passkeys[0].hidden()); @@ -810,7 +823,7 @@ .Wait()); EXPECT_TRUE(change_checker.Wait()); const std::vector<sync_pb::WebauthnCredentialSpecifics> passkeys = - GetModel().GetAllPasskeys(); + GetModel().GetPasskeys(AnyRp(), ShadowedCredentials::kInclude); ASSERT_EQ(passkeys.size(), 1u); EXPECT_FALSE(passkeys[0].edited_by_user()); EXPECT_EQ(passkeys[0].user_name(), kUsername2); @@ -844,7 +857,7 @@ // Local model should now contain the new blob. const std::vector<sync_pb::WebauthnCredentialSpecifics> passkeys = - GetModel().GetAllPasskeys(); + GetModel().GetPasskeys(AnyRp(), ShadowedCredentials::kInclude); ASSERT_EQ(passkeys.size(), 1u); EXPECT_EQ(passkeys[0].encrypted(), new_encrypted_blob); @@ -886,7 +899,7 @@ .Wait()); EXPECT_TRUE(change_checker.Wait()); const std::vector<sync_pb::WebauthnCredentialSpecifics> passkeys = - GetModel().GetAllPasskeys(); + GetModel().GetPasskeys(AnyRp(), ShadowedCredentials::kInclude); ASSERT_EQ(passkeys.size(), 1u); EXPECT_TRUE(passkeys[0].edited_by_user()); EXPECT_EQ(passkeys[0].user_name(), kUsername2); @@ -906,7 +919,7 @@ EntityHasDisplayName(kDisplayName2)))) .Wait()); const std::vector<sync_pb::WebauthnCredentialSpecifics> updated_passkeys = - GetModel().GetAllPasskeys(); + GetModel().GetPasskeys(AnyRp(), ShadowedCredentials::kInclude); ASSERT_EQ(updated_passkeys.size(), 1u); EXPECT_TRUE(updated_passkeys[0].edited_by_user()); EXPECT_EQ(updated_passkeys[0].user_name(), kUsername2); @@ -939,7 +952,7 @@ EXPECT_TRUE(ServerPasskeysMatchChecker( ElementsAre(EntityHasSyncId(passkey.sync_id()))) .Wait()); - EXPECT_THAT(GetModel().GetAllPasskeys(), + EXPECT_THAT(GetModel().GetPasskeys(AnyRp(), ShadowedCredentials::kInclude), ElementsAre(PasskeyHasSyncId(passkey.sync_id()))); EXPECT_TRUE(GetModel().UpdatePasskey(passkey.credential_id(), { @@ -954,7 +967,7 @@ ASSERT_TRUE(SetupClients()); ASSERT_TRUE(GetClient(0)->AwaitSyncTransportActive()); const std::vector<sync_pb::WebauthnCredentialSpecifics> passkeys = - GetModel().GetAllPasskeys(); + GetModel().GetPasskeys(AnyRp(), ShadowedCredentials::kInclude); ASSERT_EQ(passkeys.size(), 1u); EXPECT_FALSE(passkeys[0].edited_by_user()); EXPECT_EQ(passkeys[0].user_name(), kUsername1); @@ -1143,7 +1156,8 @@ ASSERT_TRUE(GetClient(0)->DisableSyncForAllDatatypes()); ASSERT_TRUE(GetClient(0)->AwaitSyncTransportActive()); - EXPECT_TRUE(GetModel().GetAllPasskeys().empty()); + EXPECT_TRUE( + GetModel().GetPasskeys(AnyRp(), ShadowedCredentials::kInclude).empty()); } // The unconsented primary account isn't supported on ChromeOS. @@ -1244,7 +1258,7 @@ // The passkey should not have been deleted yet, since // `kHiddenPasskeyLifetime` hasn't passed yet. - EXPECT_THAT(GetModel().GetAllPasskeys(), + EXPECT_THAT(GetModel().GetPasskeys(AnyRp(), ShadowedCredentials::kInclude), UnorderedElementsAre(PasskeyHasSyncId(new_passkey.sync_id()), PasskeyHasSyncId(old_passkey.sync_id()))); } @@ -1255,7 +1269,7 @@ ASSERT_TRUE(GetClient(0)->AwaitSyncTransportActive()); // After loading the browser, the old passkey should have been deleted. - EXPECT_THAT(GetModel().GetAllPasskeys(), + EXPECT_THAT(GetModel().GetPasskeys(AnyRp(), ShadowedCredentials::kInclude), UnorderedElementsAre(PasskeyHasDisplayName("New"))); }
diff --git a/chrome/browser/sync/test/integration/webauthn_credentials_helper.cc b/chrome/browser/sync/test/integration/webauthn_credentials_helper.cc index b87b48b3..31e7a02 100644 --- a/chrome/browser/sync/test/integration/webauthn_credentials_helper.cc +++ b/chrome/browser/sync/test/integration/webauthn_credentials_helper.cc
@@ -94,7 +94,11 @@ *os << "Waiting for local passkeys to match: "; testing::StringMatchResultListener result_listener; const bool matches = testing::ExplainMatchResult( - matcher_, GetModel(profile_).GetAllPasskeys(), &result_listener); + matcher_, + GetModel(profile_).GetPasskeys( + webauthn::PasskeyModel::AnyRp(), + webauthn::PasskeyModel::ShadowedCredentials::kInclude), + &result_listener); *os << result_listener.str(); return matches; }
diff --git a/chrome/browser/tabmodel/BUILD.gn b/chrome/browser/tabmodel/BUILD.gn index 2402d943..e3384bb 100644 --- a/chrome/browser/tabmodel/BUILD.gn +++ b/chrome/browser/tabmodel/BUILD.gn
@@ -120,6 +120,7 @@ "android/java/src/org/chromium/chrome/browser/tabmodel/AccumulatingTabCreatorUnitTest.java", "android/java/src/org/chromium/chrome/browser/tabmodel/ArchivedTabCountSupplierUnitTest.java", "android/java/src/org/chromium/chrome/browser/tabmodel/IncognitoTabGroupModelFilterImplUnitTest.java", + "android/java/src/org/chromium/chrome/browser/tabmodel/IncognitoTabModelImplUnitTest.java", "android/java/src/org/chromium/chrome/browser/tabmodel/MultiTabMetadataUnitTest.java", "android/java/src/org/chromium/chrome/browser/tabmodel/ReadOnlyIteratorUnitTest.java", "android/java/src/org/chromium/chrome/browser/tabmodel/TabClosureParamsUnitTest.java",
diff --git a/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/IncognitoTabModelImpl.java b/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/IncognitoTabModelImpl.java index ca1bf36c..444ef441 100644 --- a/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/IncognitoTabModelImpl.java +++ b/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/IncognitoTabModelImpl.java
@@ -128,6 +128,9 @@ for (Callback<TabModelInternal> delegateModelObserver : mDelegateModelObservers) { delegateModelObserver.onResult(mDelegateModel); } + for (IncognitoTabModelObserver observer : mIncognitoObservers) { + observer.onIncognitoModelCreated(); + } } /**
diff --git a/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/IncognitoTabModelImplUnitTest.java b/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/IncognitoTabModelImplUnitTest.java new file mode 100644 index 0000000..38b5c22 --- /dev/null +++ b/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/IncognitoTabModelImplUnitTest.java
@@ -0,0 +1,78 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.tabmodel; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.inOrder; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InOrder; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; +import org.robolectric.annotation.Config; + +import org.chromium.base.test.BaseRobolectricTestRunner; +import org.chromium.chrome.browser.profiles.Profile; +import org.chromium.chrome.browser.tab.MockTab; +import org.chromium.chrome.browser.tab.TabCreationState; +import org.chromium.chrome.browser.tab.TabLaunchType; +import org.chromium.chrome.browser.tabmodel.IncognitoTabModelImpl.IncognitoTabModelDelegate; +import org.chromium.chrome.test.util.browser.tabmodel.MockTabModel; + +/** Unit tests for {@link IncognitoTabModelImpl}. */ +@RunWith(BaseRobolectricTestRunner.class) +@Config(manifest = Config.NONE) +public class IncognitoTabModelImplUnitTest { + @Rule public MockitoRule mMockitoRule = MockitoJUnit.rule(); + + @Mock private IncognitoTabModelDelegate mIncognitoTabModelDelegate; + @Mock private Profile mProfile; + @Mock private IncognitoTabModelObserver mIncognitoTabModelObserver; + @Mock private TabCreator mTabCreator; + + private IncognitoTabModelImpl mIncognitoTabModel; + private MockTabModel mMockTabModel; + + @Before + public void setUp() { + mMockTabModel = spy(new MockTabModel(mProfile, null)); + mIncognitoTabModelDelegate = + new IncognitoTabModelDelegate() { + @Override + public TabModelInternal createTabModel() { + return mMockTabModel; + } + + @Override + public TabCreator getIncognitoTabCreator() { + return mTabCreator; + } + }; + when(mProfile.isOffTheRecord()).thenReturn(true); + + mIncognitoTabModel = new IncognitoTabModelImpl(mIncognitoTabModelDelegate); + mIncognitoTabModel.addIncognitoObserver(mIncognitoTabModelObserver); + } + + @Test + public void testOnIncognitoModelCreatedCalledBeforeWasFirstTabCreated() { + MockTab tab = new MockTab(1, mProfile); + mIncognitoTabModel.addTab( + tab, 0, TabLaunchType.FROM_CHROME_UI, TabCreationState.LIVE_IN_FOREGROUND); + + InOrder inOrder = inOrder(mIncognitoTabModelObserver, mMockTabModel); + inOrder.verify(mIncognitoTabModelObserver).onIncognitoModelCreated(); + inOrder.verify(mMockTabModel) + .addTab(tab, 0, TabLaunchType.FROM_CHROME_UI, TabCreationState.LIVE_IN_FOREGROUND); + inOrder.verify(mIncognitoTabModelObserver).wasFirstTabCreated(); + assertEquals(1, mMockTabModel.getCount()); + } +}
diff --git a/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/IncognitoTabModelObserver.java b/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/IncognitoTabModelObserver.java index 11eaf4a2..12e5059 100644 --- a/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/IncognitoTabModelObserver.java +++ b/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/IncognitoTabModelObserver.java
@@ -25,6 +25,9 @@ void onBeforeIncognitoTabModelSelected(); } + /** Called when the Incognito {@link TabModel} is created. */ + default void onIncognitoModelCreated() {} + /** Called when the first tab of the {@link IncognitoTabModel} is created. */ default void wasFirstTabCreated() {}
diff --git a/chrome/browser/thumbnail/cc/thumbnail_cache.cc b/chrome/browser/thumbnail/cc/thumbnail_cache.cc index ccc10aac..f4e65a49 100644 --- a/chrome/browser/thumbnail/cc/thumbnail_cache.cc +++ b/chrome/browser/thumbnail/cc/thumbnail_cache.cc
@@ -90,9 +90,6 @@ cache_(default_cache_size), ui_resource_provider_(nullptr) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - memory_pressure_listener_registration_ = - std::make_unique<base::MemoryPressureListenerRegistration>( - FROM_HERE, base::MemoryPressureListenerTag::kThumbnailCache, this); ScheduleRecordCacheMetrics(base::Minutes(1)); } @@ -616,10 +613,4 @@ GURL url) : capture_time_(current_time), url_(std::move(url)) {} -void ThumbnailCache::OnMemoryPressure(base::MemoryPressureLevel level) { - if (level == base::MEMORY_PRESSURE_LEVEL_CRITICAL) { - cache_.Clear(); - } -} - } // namespace thumbnail
diff --git a/chrome/browser/thumbnail/cc/thumbnail_cache.h b/chrome/browser/thumbnail/cc/thumbnail_cache.h index d6725f2b..7938b3d 100644 --- a/chrome/browser/thumbnail/cc/thumbnail_cache.h +++ b/chrome/browser/thumbnail/cc/thumbnail_cache.h
@@ -14,7 +14,6 @@ #include "base/files/file_path.h" #include "base/functional/bind.h" -#include "base/memory/memory_pressure_listener.h" #include "base/memory/scoped_refptr.h" #include "base/memory/weak_ptr.h" #include "base/observer_list.h" @@ -48,7 +47,7 @@ virtual void OnFinishedThumbnailRead(TabId tab_id) = 0; }; -class ThumbnailCache : ThumbnailDelegate, public base::MemoryPressureListener { +class ThumbnailCache : ThumbnailDelegate { public: ThumbnailCache(size_t default_cache_size, size_t compression_queue_max_size, @@ -159,8 +158,6 @@ void NotifyObserversOfThumbnailRead(TabId tab_id); void RemoveOnMatchedTimeStamp(TabId tab_id, const base::Time& time_stamp); - void OnMemoryPressure(base::MemoryPressureLevel level) override; - // Default priority as most of the time there is a placeholder available. const scoped_refptr<base::SequencedTaskRunner> etc1_file_sequenced_task_runner_; @@ -191,8 +188,6 @@ base::WeakPtr<ui::UIResourceProvider> ui_resource_provider_; SEQUENCE_CHECKER(sequence_checker_); - std::unique_ptr<base::MemoryPressureListenerRegistration> - memory_pressure_listener_registration_; base::WeakPtrFactory<ThumbnailCache> weak_factory_{this}; };
diff --git a/chrome/browser/touch_to_fill/autofill/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/payments/TouchToFillPaymentMethodViewTest.java b/chrome/browser/touch_to_fill/autofill/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/payments/TouchToFillPaymentMethodViewTest.java index ddf8cdbf..f0fa8f4 100644 --- a/chrome/browser/touch_to_fill/autofill/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/payments/TouchToFillPaymentMethodViewTest.java +++ b/chrome/browser/touch_to_fill/autofill/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/payments/TouchToFillPaymentMethodViewTest.java
@@ -144,7 +144,6 @@ import org.chromium.base.test.util.CommandLineFlags; import org.chromium.base.test.util.CriteriaHelper; import org.chromium.base.test.util.DisabledTest; -import org.chromium.base.test.util.DoNotBatch; import org.chromium.base.test.util.Features.DisableFeatures; import org.chromium.base.test.util.Features.EnableFeatures; import org.chromium.base.test.util.ScalableTimeout; @@ -190,7 +189,6 @@ /** Tests for {@link TouchToFillPaymentMethodView} */ @RunWith(ChromeJUnit4ClassRunner.class) -@DoNotBatch(reason = "The methods of ChromeAccessibilityUtil don't seem to work with batching.") @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) public class TouchToFillPaymentMethodViewTest { /** An observer used to record events that occur with respect to the bottom sheet. */
diff --git a/chrome/browser/ui/android/multiwindow/java/src/org/chromium/chrome/browser/multiwindow/UiUtils.java b/chrome/browser/ui/android/multiwindow/java/src/org/chromium/chrome/browser/multiwindow/UiUtils.java index 2ac1b91..a82bb5e 100644 --- a/chrome/browser/ui/android/multiwindow/java/src/org/chromium/chrome/browser/multiwindow/UiUtils.java +++ b/chrome/browser/ui/android/multiwindow/java/src/org/chromium/chrome/browser/multiwindow/UiUtils.java
@@ -24,7 +24,6 @@ import com.google.android.material.textfield.TextInputEditText; import org.chromium.base.Callback; -import org.chromium.base.ContextUtils; import org.chromium.base.metrics.RecordUserAction; import org.chromium.build.annotations.NullMarked; import org.chromium.build.annotations.Nullable; @@ -32,7 +31,6 @@ import org.chromium.chrome.browser.ui.favicon.FaviconUtils; import org.chromium.components.browser_ui.widget.RoundedIconGenerator; import org.chromium.components.favicon.LargeIconBridge; -import org.chromium.ui.base.DeviceFormFactor; import org.chromium.ui.modaldialog.DialogDismissalCause; import org.chromium.ui.modelutil.PropertyModel; import org.chromium.url.GURL; @@ -128,9 +126,7 @@ // IncognitoUtils function @Deprecated public static boolean isIncognitoAsWindowEnabled() { - return ChromeFeatureList.sAndroidOpenIncognitoAsWindow.isEnabled() - && DeviceFormFactor.isNonMultiDisplayContextOnTablet( - ContextUtils.getApplicationContext()); + return ChromeFeatureList.sAndroidOpenIncognitoAsWindow.isEnabled(); } /**
diff --git a/chrome/browser/ui/android/night_mode/java/src/org/chromium/chrome/browser/night_mode/settings/ThemeSettingsFragment.java b/chrome/browser/ui/android/night_mode/java/src/org/chromium/chrome/browser/night_mode/settings/ThemeSettingsFragment.java index 3dfb149a..35ce999 100644 --- a/chrome/browser/ui/android/night_mode/java/src/org/chromium/chrome/browser/night_mode/settings/ThemeSettingsFragment.java +++ b/chrome/browser/ui/android/night_mode/java/src/org/chromium/chrome/browser/night_mode/settings/ThemeSettingsFragment.java
@@ -21,6 +21,7 @@ import org.chromium.chrome.browser.night_mode.WebContentsDarkModeMessageController; import org.chromium.chrome.browser.preferences.ChromeSharedPreferences; import org.chromium.chrome.browser.settings.ChromeBaseSettingsFragment; +import org.chromium.chrome.browser.settings.search.ChromeBaseSearchIndexProvider; import org.chromium.components.browser_ui.settings.CustomDividerFragment; import org.chromium.components.browser_ui.settings.SettingsUtils; @@ -100,4 +101,9 @@ public @Nullable String getMainMenuKey() { return "ui_theme"; } + + // TODO(crbug.com/444470792): Determine what pieces of logic are dynamic and need handling. + public static final ChromeBaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = + new ChromeBaseSearchIndexProvider( + ThemeSettingsFragment.class.getName(), R.xml.theme_preferences); }
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarCoordinator.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarCoordinator.java index dd9f6333..e4ae9dfb 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarCoordinator.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/LocationBarCoordinator.java
@@ -525,6 +525,9 @@ mStatusCoordinator.destroy(); mStatusCoordinator = null; + mOmniboxDropdownEmbedderImpl.destroy(); + mOmniboxDropdownEmbedderImpl = null; + if (mFuseboxCoordinator != null) { mFuseboxCoordinator.destroy(); mFuseboxCoordinator = null;
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/OmniboxSuggestionsDropdownEmbedderImpl.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/OmniboxSuggestionsDropdownEmbedderImpl.java index b4c9ebf..11c688d 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/OmniboxSuggestionsDropdownEmbedderImpl.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/OmniboxSuggestionsDropdownEmbedderImpl.java
@@ -367,4 +367,8 @@ mWindowInsetsCompat = windowInsetsCompat; return result; } + + public void destroy() { + mContext.unregisterComponentCallbacks(this); + } }
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/fusebox/FuseboxAttachmentModelList.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/fusebox/FuseboxAttachmentModelList.java index d3f564e..7ee38c6 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/fusebox/FuseboxAttachmentModelList.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/fusebox/FuseboxAttachmentModelList.java
@@ -15,6 +15,7 @@ import org.chromium.chrome.browser.omnibox.fusebox.FuseboxAttachmentRecyclerViewAdapter.FuseboxAttachmentType; import org.chromium.chrome.browser.ui.theme.BrandedColorScheme; import org.chromium.components.contextual_search.FileUploadStatus; +import org.chromium.components.omnibox.OmniboxFeatures; import org.chromium.ui.modelutil.MVCListAdapter.ListItem; import org.chromium.ui.modelutil.MVCListAdapter.ModelList; @@ -30,8 +31,7 @@ */ @NullMarked public class FuseboxAttachmentModelList extends ModelList implements FileUploadObserver { - - static final int MAX_ATTACHMENTS = 10; + static final int MAX_ATTACHMENTS = OmniboxFeatures.sMultiattachmentFusebox.getValue() ? 10 : 1; private final Set<Integer> mAttachedTabIds = new ArraySet<>(); private @Nullable ComposeBoxQueryControllerBridge mComposeBoxQueryControllerBridge; private @BrandedColorScheme int mBrandedColorScheme;
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/fusebox/FuseboxAttachmentModelListUnitTest.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/fusebox/FuseboxAttachmentModelListUnitTest.java index fa5fbc4b..0eccdde0 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/fusebox/FuseboxAttachmentModelListUnitTest.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/fusebox/FuseboxAttachmentModelListUnitTest.java
@@ -31,6 +31,7 @@ import org.chromium.chrome.browser.omnibox.fusebox.FuseboxAttachmentRecyclerViewAdapter.FuseboxAttachmentType; import org.chromium.chrome.browser.tab.Tab; import org.chromium.components.contextual_search.FileUploadStatus; +import org.chromium.components.omnibox.OmniboxFeatures; import java.util.concurrent.atomic.AtomicBoolean; @@ -54,6 +55,7 @@ @Before public void setUp() { + OmniboxFeatures.sMultiattachmentFusebox.setForTesting(true); mFuseboxAttachmentModelList = new FuseboxAttachmentModelList(); mFuseboxAttachmentModelList.setComposeBoxQueryControllerBridge( mComposeBoxQueryControllerBridge);
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/fusebox/FuseboxMediator.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/fusebox/FuseboxMediator.java index 23c242b..0bf8a99 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/fusebox/FuseboxMediator.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/fusebox/FuseboxMediator.java
@@ -73,7 +73,6 @@ public static final String EXTRA_IS_INCOGNITO_BRANDED = "EXTRA_IS_INCOGNITO_BRANDED"; public static final String EXTRA_ATTACHMENT_TAB_IDS = "TAB_IDS"; public static final String EXTRA_ALLOWED_SELECTION_COUNT = "ALLOWED_SELECTION_COUNT"; - private static final int SELECTION_MAX = 10; private final Context mContext; private final Profile mProfile; @@ -364,16 +363,17 @@ void onTabPickerClicked() { mPopup.dismiss(); FuseboxMetrics.notifyAttachmentButtonUsed(FuseboxAttachmentButtonType.TAB_PICKER); - if (mModelList.getRemainingAttachments() < 1) { + int remainingAttachments = mModelList.getRemainingAttachments(); + if (remainingAttachments < 1) { warnForMaxAttachments(); return; } Intent intent; - ArrayList<Integer> preselectedIds = new ArrayList<>(mModelList.getAttachedTabIds()); + ArrayList<Integer> preselectedTabIds = new ArrayList<>(mModelList.getAttachedTabIds()); try { intent = new Intent(mContext, Class.forName(CHROME_ITEM_PICKER_ACTIVITY_CLASS)) - .putIntegerArrayListExtra(EXTRA_PRESELECTED_TAB_IDS, preselectedIds); + .putIntegerArrayListExtra(EXTRA_PRESELECTED_TAB_IDS, preselectedTabIds); ProfileIntentUtils.addProfileToIntent(mProfile, intent); TabModelSelector tabModelSelector = mTabModelSelectorSupplier.get(); @@ -387,8 +387,8 @@ return; } - int nonTabSelectionCount = mModelList.size() - preselectedIds.size(); - intent.putExtra(EXTRA_ALLOWED_SELECTION_COUNT, SELECTION_MAX - nonTabSelectionCount); + int maxAllowedTabs = preselectedTabIds.size() + remainingAttachments; + intent.putExtra(EXTRA_ALLOWED_SELECTION_COUNT, maxAllowedTabs); mWindowAndroid.showCancelableIntent( intent, this::onTabPickerResult, R.string.low_memory_error); @@ -680,8 +680,6 @@ } void setUseCompactUi(boolean useCompactUi) { - if (mModel.get(FuseboxProperties.COMPACT_UI) == useCompactUi) return; - boolean fuseboxActive = mModel.get(FuseboxProperties.ATTACHMENTS_TOOLBAR_VISIBLE); mFuseboxStateSupplier.set( fuseboxActive
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/fusebox/FuseboxMediatorUnitTest.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/fusebox/FuseboxMediatorUnitTest.java index 58e0ada..3f270a7 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/fusebox/FuseboxMediatorUnitTest.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/fusebox/FuseboxMediatorUnitTest.java
@@ -131,6 +131,7 @@ @Before public void setUp() { + OmniboxFeatures.sMultiattachmentFusebox.setForTesting(true); mTabModelSelectorSupplier = new ObservableSupplierImpl<>(mTabModelSelector); mAutocompleteRequestTypeSupplier = new ObservableSupplierImpl<>(AutocompleteRequestType.SEARCH); @@ -834,42 +835,57 @@ } @Test - public void onTabPickerClicked_launchesTabPickerActivity() throws ClassNotFoundException { - mMediator.onTabPickerClicked(); + public void onTabPickerClicked_launchesTabPickerActivity() { + mModel.get(FuseboxProperties.POPUP_TAB_PICKER_CLICKED).run(); - // Verify popup is dismissed verify(mPopup).dismiss(); - - // Verify intent is shown verify(mWindowAndroid).showCancelableIntent(mIntentCaptor.capture(), any(), any()); Intent intent = mIntentCaptor.getValue(); - assertEquals( FuseboxMediator.CHROME_ITEM_PICKER_ACTIVITY_CLASS, intent.getComponent().getClassName()); assertNotNull(intent.getIntegerArrayListExtra(FuseboxMediator.EXTRA_PRESELECTED_TAB_IDS)); + assertEquals( + FuseboxAttachmentModelList.MAX_ATTACHMENTS, + intent.getIntExtra(FuseboxMediator.EXTRA_ALLOWED_SELECTION_COUNT, -1)); } @Test - public void onTabPickerClicked_sendsPreselectedTabIds() throws ClassNotFoundException { - // Setup tabs and add them as attachments - Tab tab1 = mockTab(101, true); - Tab tab2 = mockTab(102, false); + public void onTabPickerClicked_sendsPreselectedTabIds() { + Tab tab1 = mockTab(101, /* webContentsReady= */ true); + Tab tab2 = mockTab(102, /* webContentsReady= */ false); addTabAttachment(tab1); addTabAttachment(tab2); - mMediator.onTabPickerClicked(); + mModel.get(FuseboxProperties.POPUP_TAB_PICKER_CLICKED).run(); - // Capture the intent and verify its extras verify(mWindowAndroid).showCancelableIntent(mIntentCaptor.capture(), any(), any()); Intent intent = mIntentCaptor.getValue(); ArrayList<Integer> preselectedIds = intent.getIntegerArrayListExtra(FuseboxMediator.EXTRA_PRESELECTED_TAB_IDS); - assertNotNull(preselectedIds); assertEquals(2, preselectedIds.size()); - assertTrue(preselectedIds.contains(101)); - assertTrue(preselectedIds.contains(102)); + assertTrue(preselectedIds.contains(tab1.getId())); + assertTrue(preselectedIds.contains(tab2.getId())); + assertEquals( + FuseboxAttachmentModelList.MAX_ATTACHMENTS, + intent.getIntExtra(FuseboxMediator.EXTRA_ALLOWED_SELECTION_COUNT, -1)); + } + + @Test + public void onTabPickerClicked_sendsAllowedSelectionCount() { + addTabAttachment(mockTab(101, /* webContentsReady= */ true)); + addAttachment("title1", "token1", FuseboxAttachmentType.ATTACHMENT_IMAGE); + addAttachment("title2", "token2", FuseboxAttachmentType.ATTACHMENT_FILE); + + mModel.get(FuseboxProperties.POPUP_TAB_PICKER_CLICKED).run(); + + verify(mWindowAndroid).showCancelableIntent(mIntentCaptor.capture(), any(), any()); + Intent intent = mIntentCaptor.getValue(); + int allowedSelectionCount = + intent.getIntExtra(FuseboxMediator.EXTRA_ALLOWED_SELECTION_COUNT, -1); + // The image and file attachments should count against the max, the tab should not. + assertEquals(FuseboxAttachmentModelList.MAX_ATTACHMENTS - 2, allowedSelectionCount); } @Test @@ -880,10 +896,10 @@ assertEquals(FuseboxAttachmentModelList.MAX_ATTACHMENTS, mAttachments.size()); - mockTab(101, true); - mockTab(102, false); - mockTab(103, true); - mockTab(104, false); + mockTab(101, /* webContentsReady= */ true); + mockTab(102, /* webContentsReady= */ false); + mockTab(103, /* webContentsReady= */ true); + mockTab(104, /* webContentsReady= */ false); Set<Integer> newlySelectedIds = new HashSet<>(); newlySelectedIds.add(102); newlySelectedIds.add(103); @@ -904,8 +920,8 @@ @Test public void testOnTabPickerResult_modelListNotEmpty_activatesAiMode() { - mockTab(101, true); - mockTab(102, false); + mockTab(101, /* webContentsReady= */ true); + mockTab(102, /* webContentsReady= */ false); ArrayList<Integer> selectedTabIds = new ArrayList<>(Arrays.asList(101, 102)); Intent resultIntent = createTabPickerResultIntent(selectedTabIds);
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/styles/OmniboxResourceProvider.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/styles/OmniboxResourceProvider.java index f0e308faf..4b0dace 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/styles/OmniboxResourceProvider.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/styles/OmniboxResourceProvider.java
@@ -743,21 +743,21 @@ @BrandedColorScheme int brandedColorScheme) { boolean isIncognito = convertBrandedColorSchemeToIncognitoOrDayNightAdaptive(brandedColorScheme); - return IncognitoColors.getTextSmallPrimary(isIncognito); + return IncognitoColors.getTextMediumThickPrimary(isIncognito); } /** Resolves the text appearance for the AI Mode chip. This includes a vivid color. */ public static @StyleRes int getAiModeButtonTextRes(@BrandedColorScheme int brandedColorScheme) { boolean isIncognito = convertBrandedColorSchemeToIncognitoOrDayNightAdaptive(brandedColorScheme); - return IncognitoColors.getTextSmallAccent1(isIncognito); + return IncognitoColors.getTextMediumThickAccent1(isIncognito); } /** Resolves the text appearance for the hint chip, somewhat faded out. */ public static @StyleRes int getAiModeHintTextRes(@BrandedColorScheme int brandedColorScheme) { boolean isIncognito = convertBrandedColorSchemeToIncognitoOrDayNightAdaptive(brandedColorScheme); - return IncognitoColors.getTextSmallSecondary(isIncognito); + return IncognitoColors.getTextMediumThickSecondary(isIncognito); } /** Resolves the text appearance for menu items in the popup. */
diff --git a/chrome/browser/ui/android/settings_promo_card/java/src/org/chromium/chrome/browser/ui/settings_promo_card/SettingsPromoCardPreference.java b/chrome/browser/ui/android/settings_promo_card/java/src/org/chromium/chrome/browser/ui/settings_promo_card/SettingsPromoCardPreference.java index aa4a478..4254cdc9 100644 --- a/chrome/browser/ui/android/settings_promo_card/java/src/org/chromium/chrome/browser/ui/settings_promo_card/SettingsPromoCardPreference.java +++ b/chrome/browser/ui/android/settings_promo_card/java/src/org/chromium/chrome/browser/ui/settings_promo_card/SettingsPromoCardPreference.java
@@ -18,18 +18,20 @@ /** A preference that displays a settings promo card. */ @NullMarked public class SettingsPromoCardPreference extends Preference { - private final @Nullable SettingsPromoCardProvider mProvider; + private @Nullable SettingsPromoCardProvider mProvider; - /** Construct and initialize SettingsPromoCardPreference to be shown in main settings. */ - public SettingsPromoCardPreference( - Context context, @Nullable AttributeSet attrs, Tracker tracker) { + /** Constructor for inflating from XML. */ + public SettingsPromoCardPreference(Context context, @Nullable AttributeSet attrs) { super(context, attrs); setVisible(false); setLayoutResource(R.layout.settings_promo_card); + } + /** Initialize the preference. */ + public void initialize(Tracker tracker) { mProvider = new DefaultBrowserPromoCard( - context, + getContext(), DefaultBrowserPromoUtils.getInstance(), tracker, this::onPromoCardUpdated);
diff --git a/chrome/browser/ui/android/settings_promo_card/java/src/org/chromium/chrome/browser/ui/settings_promo_card/SettingsPromoCardPreferenceTest.java b/chrome/browser/ui/android/settings_promo_card/java/src/org/chromium/chrome/browser/ui/settings_promo_card/SettingsPromoCardPreferenceTest.java index ffd6b5d1e..2bcac286 100644 --- a/chrome/browser/ui/android/settings_promo_card/java/src/org/chromium/chrome/browser/ui/settings_promo_card/SettingsPromoCardPreferenceTest.java +++ b/chrome/browser/ui/android/settings_promo_card/java/src/org/chromium/chrome/browser/ui/settings_promo_card/SettingsPromoCardPreferenceTest.java
@@ -61,8 +61,8 @@ when(mMockDefaultBrowserPromoUtils.shouldShowNonRoleManagerPromo(any())).thenReturn(true); when(mTestTracker.shouldTriggerHelpUi(any())).thenReturn(false); - SettingsPromoCardPreference preference = - new SettingsPromoCardPreference(mActivity, null, mTestTracker); + SettingsPromoCardPreference preference = new SettingsPromoCardPreference(mActivity, null); + preference.initialize(mTestTracker); View itemView = new FrameLayout(mActivity); PreferenceViewHolder viewHolder = PreferenceViewHolder.createInstanceForTests(itemView); preference.onBindViewHolder(viewHolder); @@ -75,8 +75,8 @@ when(mTestTracker.shouldTriggerHelpUi(any())).thenReturn(true); when(mMockDefaultBrowserPromoUtils.shouldShowNonRoleManagerPromo(any())).thenReturn(true); - SettingsPromoCardPreference preference = - new SettingsPromoCardPreference(mActivity, null, mTestTracker); + SettingsPromoCardPreference preference = new SettingsPromoCardPreference(mActivity, null); + preference.initialize(mTestTracker); Assert.assertFalse(preference.isVisible()); when(mMockDefaultBrowserPromoUtils.shouldShowNonRoleManagerPromo(any())).thenReturn(false);
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ToolbarPositionController.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ToolbarPositionController.java index a1ee9e3..47eec9d7 100644 --- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ToolbarPositionController.java +++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ToolbarPositionController.java
@@ -601,7 +601,6 @@ boolean isFormFieldFocusedWithKeyboardVisible, boolean doesUserPreferTopToolbar, @ControlsPosition int currentPosition) { - boolean miniOriginBarEnabled = ChromeFeatureList.sMiniOriginBar.isEnabled(); boolean allowBottomAnchoredFocusedOmnibox = ChromeFeatureList.sAndroidBottomToolbarV2.isEnabled(); boolean forceBottomForFocusedOmnibox = @@ -616,7 +615,6 @@ || tabSwitcherShowing || (isOmniboxFocused && !allowBottomAnchoredFocusedOmnibox) || isFindInPageShowing - || (isFormFieldFocusedWithKeyboardVisible && !miniOriginBarEnabled) || doesUserPreferTopToolbar)) { newControlsPosition = ControlsPosition.TOP; } else {
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ToolbarPositionControllerTest.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ToolbarPositionControllerTest.java index 2e34c733..3ca98fa9 100644 --- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ToolbarPositionControllerTest.java +++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ToolbarPositionControllerTest.java
@@ -546,35 +546,10 @@ assertControlsAtBottom(); } - @Test - @Config(qualifiers = "sw400dp") - @EnableFeatures(ChromeFeatureList.ANDROID_BOTTOM_TOOLBAR) - @DisableFeatures(ChromeFeatureList.MINI_ORIGIN_BAR) - public void testUpdatePositionChangesWithFormFieldFocusState() { - setUserToolbarAnchorPreference(/* showToolbarOnTop= */ false); - assertControlsAtBottom(); - verify(mControlContainerView).setVisibility(View.INVISIBLE); - - mIsFormFieldFocused.onNodeAttributeUpdated(true, false); - mKeyboardVisibilityDelegate.setVisibilityForTests(true); - assertEquals(0, mBrowserControlsSizer.getTopControlOffset()); - assertControlsAtTop(); - verify(mControlContainerView, times(1)).setVisibility(View.INVISIBLE); - - mKeyboardVisibilityDelegate.setVisibilityForTests(false); - assertEquals(TOOLBAR_HEIGHT, mBrowserControlsSizer.getBottomControlOffset()); - assertControlsAtBottom(); - - mKeyboardVisibilityDelegate.setVisibilityForTests(true); - assertControlsAtTop(); - - mIsFormFieldFocused.onNodeAttributeUpdated(false, false); - assertControlsAtBottom(); - } @Test @Config(qualifiers = "sw400dp") - @EnableFeatures({ChromeFeatureList.ANDROID_BOTTOM_TOOLBAR, ChromeFeatureList.MINI_ORIGIN_BAR}) + @EnableFeatures({ChromeFeatureList.ANDROID_BOTTOM_TOOLBAR}) public void testUpdatePositionFormField_MiniOriginBar() { setUserToolbarAnchorPreference(/* showToolbarOnTop= */ false); assertControlsAtBottom(); @@ -668,7 +643,6 @@ @Test @EnableFeatures(ChromeFeatureList.ANDROID_BOTTOM_TOOLBAR) @DisableFeatures({ - ChromeFeatureList.MINI_ORIGIN_BAR, ChromeFeatureList.ANDROID_BOTTOM_TOOLBAR_V2 }) public void testCalculateStateTransition() { @@ -753,7 +727,7 @@ ControlsPosition.BOTTOM)); assertEquals( - StateTransition.SNAP_TO_TOP, + StateTransition.NONE, ToolbarPositionController.calculateStateTransition( prefStateChanged, ntpShowing, @@ -969,7 +943,7 @@ } @Test - @EnableFeatures({ChromeFeatureList.ANDROID_BOTTOM_TOOLBAR, ChromeFeatureList.MINI_ORIGIN_BAR}) + @EnableFeatures({ChromeFeatureList.ANDROID_BOTTOM_TOOLBAR}) public void testControlContainerTranslationAdjustments() { setUserToolbarAnchorPreference(/* showToolbarOnTop= */ false); mIsFormFieldFocused.onNodeAttributeUpdated(true, false); @@ -1036,7 +1010,7 @@ } @Test - @EnableFeatures({ChromeFeatureList.ANDROID_BOTTOM_TOOLBAR, ChromeFeatureList.MINI_ORIGIN_BAR}) + @EnableFeatures({ChromeFeatureList.ANDROID_BOTTOM_TOOLBAR}) public void testParentLayoutInLayoutDuringPositionChange() { setUserToolbarAnchorPreference(/* showToolbarOnTop= */ false); assertControlsAtBottom(); @@ -1056,7 +1030,7 @@ } @Test - @EnableFeatures({ChromeFeatureList.ANDROID_BOTTOM_TOOLBAR, ChromeFeatureList.MINI_ORIGIN_BAR}) + @EnableFeatures({ChromeFeatureList.ANDROID_BOTTOM_TOOLBAR}) public void testOnToEdgeChange() { int topInset = 50; @@ -1071,7 +1045,7 @@ } @Test - @EnableFeatures({ChromeFeatureList.ANDROID_BOTTOM_TOOLBAR, ChromeFeatureList.MINI_ORIGIN_BAR}) + @EnableFeatures({ChromeFeatureList.ANDROID_BOTTOM_TOOLBAR}) public void testControlContainerHeightAdjustments() { setUserToolbarAnchorPreference(/* showToolbarOnTop= */ false); mIsFormFieldFocused.onNodeAttributeUpdated(true, false);
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/settings/AdaptiveToolbarSettingsFragment.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/settings/AdaptiveToolbarSettingsFragment.java index 93171789..b896f31 100644 --- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/settings/AdaptiveToolbarSettingsFragment.java +++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/settings/AdaptiveToolbarSettingsFragment.java
@@ -15,7 +15,7 @@ import org.chromium.build.annotations.Nullable; import org.chromium.chrome.browser.omnibox.voice.VoiceRecognitionUtil; import org.chromium.chrome.browser.settings.ChromeBaseSettingsFragment; -import org.chromium.chrome.browser.settings.search.BaseSearchIndexProvider; +import org.chromium.chrome.browser.settings.search.ChromeBaseSearchIndexProvider; import org.chromium.chrome.browser.toolbar.R; import org.chromium.chrome.browser.toolbar.adaptive.AdaptiveToolbarButtonVariant; import org.chromium.chrome.browser.toolbar.adaptive.AdaptiveToolbarFeatures; @@ -150,8 +150,8 @@ return "toolbar_shortcut"; } - public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = - new BaseSearchIndexProvider( + public static final ChromeBaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = + new ChromeBaseSearchIndexProvider( AdaptiveToolbarSettingsFragment.class.getName(), R.xml.adaptive_toolbar_preference); }
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/menu_button/MenuButtonMediator.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/menu_button/MenuButtonMediator.java index 3bd57c50..f33f5761 100644 --- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/menu_button/MenuButtonMediator.java +++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/menu_button/MenuButtonMediator.java
@@ -297,7 +297,6 @@ mPropertyModel.set( MenuButtonProperties.THEME, new ThemeProperty(activityFocusTintList, brandedColorScheme)); - updateBackground(brandedColorScheme); } /**
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/settings/AddressBarSettingsFragment.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/settings/AddressBarSettingsFragment.java index 99a4ba29..cdfcf33 100644 --- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/settings/AddressBarSettingsFragment.java +++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/settings/AddressBarSettingsFragment.java
@@ -19,7 +19,7 @@ import org.chromium.build.annotations.Nullable; import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.settings.ChromeBaseSettingsFragment; -import org.chromium.chrome.browser.settings.search.BaseSearchIndexProvider; +import org.chromium.chrome.browser.settings.search.ChromeBaseSearchIndexProvider; import org.chromium.chrome.browser.toolbar.R; import org.chromium.components.browser_ui.settings.SettingsUtils; import org.chromium.ui.base.DeviceFormFactor; @@ -108,7 +108,7 @@ return "address_bar"; } - public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = - new BaseSearchIndexProvider( + public static final ChromeBaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = + new ChromeBaseSearchIndexProvider( AddressBarSettingsFragment.class.getName(), R.xml.address_bar_settings); }
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarPhone.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarPhone.java index 854b872..d91bfe2 100644 --- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarPhone.java +++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarPhone.java
@@ -1679,7 +1679,8 @@ /** Called whenever the location bar background view's bounds or its NTP offset changes. */ private void onLocationBarBackgroundViewBoundsChanged() { - if (!ChromeFeatureList.sToolbarPhoneAnimationRefactor.isEnabled()) { + if (!ChromeFeatureList.sToolbarPhoneAnimationRefactor.isEnabled() + || mUrlFocusChangeInProgress) { return; } updateLocationBarBackgroundViewBounds(); @@ -2300,7 +2301,9 @@ mBrandColorTransitionAnimation.cancel(); } - mUrlFocusChangeInProgress = true; + // If the refactored animations are enabled, this will instead be set when the transition + // actually starts (in the next update cycle). + mUrlFocusChangeInProgress = !ChromeFeatureList.sToolbarPhoneAnimationRefactor.isEnabled(); // Hide the optional button immediately when animating in the suggestions list (since other // toolbar buttons are also hidden immediately) or restore it when omnibox focus is lost. if (animatingSuggestionsListOnNtp()) { @@ -2611,6 +2614,11 @@ updateLocationBarFocusChangeFraction(); updateToolbarAndLocationBarColorForFocusChange(); updateLocationBarBackgroundBounds(mLocationBarBackgroundBounds, mVisualState); + + // Intentionally set last, as this is used to suppress updates in some helpers that are + // called above. Not set in #onFocusTransitionStart as that is called on the next update + // cycle, which may be too late. + mUrlFocusChangeInProgress = true; } private void updateLocationBarNtpOffset(boolean expanded) { @@ -3065,7 +3073,11 @@ startLoadingPhaseFromNtpToWebpage(newVisualState); mVisualState = newVisualState; - if (ChromeFeatureList.sToolbarPhoneAnimationRefactor.isEnabled()) { + if (ChromeFeatureList.sToolbarPhoneAnimationRefactor.isEnabled() + && !mUrlFocusChangeInProgress) { + // The bounds may change if navigating to/from a NTP, so update here accordingly. If a + // focus change animation is in progress, however, allow the bounds change to be + // handled by the transition instead. updateLocationBarBackgroundBounds(mLocationBarBackgroundBounds, newVisualState); }
diff --git a/chrome/browser/ui/ash/wm/coral_browsertest.cc b/chrome/browser/ui/ash/wm/coral_browsertest.cc index 47e4d18b..964cbab 100644 --- a/chrome/browser/ui/ash/wm/coral_browsertest.cc +++ b/chrome/browser/ui/ash/wm/coral_browsertest.cc
@@ -595,7 +595,7 @@ ASSERT_EQ(GetBirchChipsNum(), 2u); // Closing the first browser with all items in groups. - EXPECT_EQ(8, browser->GetTabStripModel()->GetTabCount()); + EXPECT_EQ(8, browser->GetTabStripModel()->count()); CloseBrowserAndNativeWindowSynchronously(browser); // Two chips are removed. @@ -807,7 +807,7 @@ auto* new_desk = desks_controller->GetDeskAtIndex(1); // Move the browser window to another desk. - ASSERT_EQ(8, regular_browser->GetTabStripModel()->GetTabCount()); + ASSERT_EQ(8, regular_browser->GetTabStripModel()->count()); auto* browser_window = regular_browser->GetWindow()->GetNativeWindow(); desks_controller->MoveWindowFromActiveDeskTo( browser_window, new_desk, browser_window->GetRootWindow(),
diff --git a/chrome/browser/ui/ash/wm/snap_group_browsertest.cc b/chrome/browser/ui/ash/wm/snap_group_browsertest.cc index 8d26813c..b28a530 100644 --- a/chrome/browser/ui/ash/wm/snap_group_browsertest.cc +++ b/chrome/browser/ui/ash/wm/snap_group_browsertest.cc
@@ -280,7 +280,7 @@ IN_PROC_BROWSER_TEST_F(SnapGroupBrowserTest, DoNotBreakGroupOnTabDragging) { aura::Window* window1 = browser()->window()->GetNativeWindow(); chrome::AddTabAt(browser(), GURL(chrome::kChromeUITabSearchURL), -1, true); - ASSERT_EQ(2, browser()->tab_strip_model()->GetTabCount()); + ASSERT_EQ(2, browser()->tab_strip_model()->count()); aura::Window* window2 = CreateBrowser(browser()->profile())->window()->GetNativeWindow(); @@ -313,7 +313,7 @@ IN_PROC_BROWSER_TEST_F(SnapGroupBrowserTest, DoNotBreakGroupOnTabDetaching) { aura::Window* window1 = browser()->window()->GetNativeWindow(); chrome::AddTabAt(browser(), GURL(chrome::kChromeUITabSearchURL), -1, true); - ASSERT_EQ(2, browser()->tab_strip_model()->GetTabCount()); + ASSERT_EQ(2, browser()->tab_strip_model()->count()); aura::Window* window2 = CreateBrowser(browser()->profile())->window()->GetNativeWindow();
diff --git a/chrome/browser/ui/bookmarks/bookmark_browsertest.cc b/chrome/browser/ui/bookmarks/bookmark_browsertest.cc index 598d1c54..77b12ed7 100644 --- a/chrome/browser/ui/bookmarks/bookmark_browsertest.cc +++ b/chrome/browser/ui/bookmarks/bookmark_browsertest.cc
@@ -281,17 +281,15 @@ EXPECT_EQ(page1->url(), incognito_folder->children()[0]->url()); EXPECT_EQ(page2->url(), incognito_folder->children()[1]->url()); - const int browser_tabs = browser()->tab_strip_model()->GetTabCount(); - const int incognito_tabs = - incognito_browser->tab_strip_model()->GetTabCount(); + const int browser_tabs = browser()->tab_strip_model()->count(); + const int incognito_tabs = incognito_browser->tab_strip_model()->count(); bookmarks::OpenAllIfAllowed(incognito_browser, {incognito_folder}, WindowOpenDisposition::NEW_BACKGROUND_TAB, bookmarks::OpenAllBookmarksContext::kInGroup); - EXPECT_EQ(incognito_tabs, - incognito_browser->tab_strip_model()->GetTabCount()); - EXPECT_EQ(browser_tabs + 2, browser()->tab_strip_model()->GetTabCount()); + EXPECT_EQ(incognito_tabs, incognito_browser->tab_strip_model()->count()); + EXPECT_EQ(browser_tabs + 2, browser()->tab_strip_model()->count()); } IN_PROC_BROWSER_TEST_F(BookmarkBrowsertest, @@ -490,7 +488,7 @@ incognito_model->bookmark_bar_node(); auto close_all_tabs_except_first = [](Browser* browser) { - int num_tabs = browser->tab_strip_model()->GetTabCount(); + int num_tabs = browser->tab_strip_model()->count(); for (int i = 0; i < num_tabs - 1; ++i) { browser->tab_strip_model()->CloseWebContentsAt(num_tabs - 1 - i, 0); } @@ -505,9 +503,8 @@ close_all_tabs_except_first(incognito_browser); bookmarks::OpenAllIfAllowed(regular_browser, {bbar}, WindowOpenDisposition::NEW_BACKGROUND_TAB); - int num_tabs_regular = regular_browser->tab_strip_model()->GetTabCount(); - int num_tabs_incognito = - incognito_browser->tab_strip_model()->GetTabCount(); + int num_tabs_regular = regular_browser->tab_strip_model()->count(); + int num_tabs_incognito = incognito_browser->tab_strip_model()->count(); EXPECT_EQ(num_tabs_regular, 5); EXPECT_EQ(num_tabs_incognito, 1); } @@ -528,9 +525,8 @@ }); // new browser needs to be opened EXPECT_NE(regular_browser2, nullptr); - int num_tabs_regular = regular_browser->tab_strip_model()->GetTabCount(); - int num_tabs_regular2 = - regular_browser2->GetTabStripModel()->GetTabCount(); + int num_tabs_regular = regular_browser->tab_strip_model()->count(); + int num_tabs_regular2 = regular_browser2->GetTabStripModel()->count(); EXPECT_EQ(num_tabs_regular, 1); EXPECT_EQ(num_tabs_regular2, 4); CloseBrowserSynchronously(regular_browser2); @@ -542,8 +538,7 @@ close_all_tabs_except_first(incognito_browser); bookmarks::OpenAllIfAllowed(regular_browser, {bbar}, WindowOpenDisposition::OFF_THE_RECORD); - int num_tabs_incognito = - incognito_browser->tab_strip_model()->GetTabCount(); + int num_tabs_incognito = incognito_browser->tab_strip_model()->count(); EXPECT_EQ(num_tabs_incognito, 3); } }; @@ -558,9 +553,8 @@ close_all_tabs_except_first(incognito_browser); bookmarks::OpenAllIfAllowed(incognito_browser, {incognito_bbar}, WindowOpenDisposition::NEW_BACKGROUND_TAB); - int num_tabs_regular = regular_browser->tab_strip_model()->GetTabCount(); - int num_tabs_incognito = - incognito_browser->tab_strip_model()->GetTabCount(); + int num_tabs_regular = regular_browser->tab_strip_model()->count(); + int num_tabs_incognito = incognito_browser->tab_strip_model()->count(); EXPECT_EQ(num_tabs_regular, 3); EXPECT_EQ(num_tabs_incognito, 3); } @@ -581,11 +575,9 @@ }); // new browser needs to be opened EXPECT_NE(incognito_browser2, nullptr); - int num_tabs_regular = regular_browser->tab_strip_model()->GetTabCount(); - int num_tabs_incognito = - incognito_browser->tab_strip_model()->GetTabCount(); - int num_tabs_incognito2 = - incognito_browser2->GetTabStripModel()->GetTabCount(); + int num_tabs_regular = regular_browser->tab_strip_model()->count(); + int num_tabs_incognito = incognito_browser->tab_strip_model()->count(); + int num_tabs_incognito2 = incognito_browser2->GetTabStripModel()->count(); EXPECT_EQ(num_tabs_regular, 3); EXPECT_EQ(num_tabs_incognito, 1); EXPECT_EQ(num_tabs_incognito2, 2);
diff --git a/chrome/browser/ui/browser_commands.cc b/chrome/browser/ui/browser_commands.cc index 51f8ccd..cb9dff2 100644 --- a/chrome/browser/ui/browser_commands.cc +++ b/chrome/browser/ui/browser_commands.cc
@@ -1517,7 +1517,7 @@ tab_strip_model->GetTabGroupForTab(current_index); // Find the next tab group and focus its first tab. - int count = tab_strip_model->GetTabCount(); + int count = tab_strip_model->count(); for (int i = 1; i < count; ++i) { int new_index = (current_index + i) % count; std::optional<tab_groups::TabGroupId> new_group_id = @@ -1542,7 +1542,7 @@ tab_strip_model->GetTabGroupForTab(current_index); // Find the next tab group and focus its first tab. - int count = tab_strip_model->GetTabCount(); + int count = tab_strip_model->count(); for (int i = 1; i < count; ++i) { int offset = count - i; int new_index = (current_index + offset) % count;
diff --git a/chrome/browser/ui/browser_commands_browsertest.cc b/chrome/browser/ui/browser_commands_browsertest.cc index 6b4e0019..ba17ea3 100644 --- a/chrome/browser/ui/browser_commands_browsertest.cc +++ b/chrome/browser/ui/browser_commands_browsertest.cc
@@ -315,7 +315,7 @@ ui::PAGE_TRANSITION_LINK, false)); } - EXPECT_EQ(kTabCount, GetTabStripModel(browser())->GetTabCount()); + EXPECT_EQ(kTabCount, GetTabStripModel(browser())->count()); // Add second last tab to split view with the last tab. GetTabStripModel(browser())->AddToNewSplit( @@ -329,7 +329,7 @@ EXPECT_TRUE(chrome::ExecuteCommand(browser(), IDC_CLOSE_TAB)); EXPECT_FALSE(GetTabStripModel(browser())->IsActiveTabSplit()); - EXPECT_EQ(2, GetTabStripModel(browser())->GetTabCount()); + EXPECT_EQ(2, GetTabStripModel(browser())->count()); } // All tabs in the selection model get closed. @@ -342,7 +342,7 @@ ui::PAGE_TRANSITION_LINK, false)); } - EXPECT_EQ(kTabCount, GetTabStripModel(browser())->GetTabCount()); + EXPECT_EQ(kTabCount, GetTabStripModel(browser())->count()); // Add second last tab to split view with the last tab. GetTabStripModel(browser())->AddToNewSplit( @@ -360,7 +360,7 @@ // Only one, non-split tab should remain. EXPECT_FALSE(GetTabStripModel(browser())->IsActiveTabSplit()); - EXPECT_EQ(1, GetTabStripModel(browser())->GetTabCount()); + EXPECT_EQ(1, GetTabStripModel(browser())->count()); } // Check that the ThirdPartyCookieBreakageIndicator UKM is sent on Reload.
diff --git a/chrome/browser/ui/extensions/extensions_menu_view_model.cc b/chrome/browser/ui/extensions/extensions_menu_view_model.cc index 1fb5b3a9..c915251 100644 --- a/chrome/browser/ui/extensions/extensions_menu_view_model.cc +++ b/chrome/browser/ui/extensions/extensions_menu_view_model.cc
@@ -9,6 +9,7 @@ #include "base/metrics/user_metrics_action.h" #include "chrome/browser/extensions/extension_action_runner.h" #include "chrome/browser/extensions/extension_tab_util.h" +#include "chrome/browser/extensions/extension_ui_util.h" #include "chrome/browser/extensions/tab_helper.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser_window/public/browser_window_interface.h" @@ -16,6 +17,7 @@ #include "chrome/browser/ui/toolbar/toolbar_action_view_model.h" #include "chrome/browser/ui/toolbar/toolbar_actions_model.h" #include "chrome/browser/ui/views/extensions/extensions_menu_view_platform_delegate_views.h" +#include "chrome/grit/generated_resources.h" #include "components/tabs/public/tab_interface.h" #include "content/public/browser/navigation_controller.h" #include "content/public/browser/web_contents.h" @@ -30,6 +32,44 @@ using PermissionsManager = extensions::PermissionsManager; using SitePermissionsHelper = extensions::SitePermissionsHelper; +// The state of the main page in the menu, corresponding to the current site's +// access restrictions. +enum class MainPageState { + // Site is restricted to all extensions. + kRestrictedSite, + // Site is restricted all non-enterprise extensions by policy. + kPolicyBlockedSite, + // User blocked all extensions access to the site. + kUserBlockedSite, + // User can customize each extension's access to the site. + kUserCustomizedSite, +}; + +// Returns the state for the main page based on the current `web_contents` URL +// and the profile's user settings. +MainPageState GetMainPageState(Profile& profile, + const ToolbarActionsModel& toolbar_model, + content::WebContents& web_contents) { + const GURL& url = web_contents.GetLastCommittedURL(); + if (toolbar_model.IsRestrictedUrl(url)) { + return MainPageState::kRestrictedSite; + } + + if (toolbar_model.IsPolicyBlockedHost(url)) { + return MainPageState::kPolicyBlockedSite; + } + + PermissionsManager::UserSiteSetting site_setting = + PermissionsManager::Get(&profile)->GetUserSiteSetting( + web_contents.GetPrimaryMainFrame()->GetLastCommittedOrigin()); + if (site_setting == + PermissionsManager::UserSiteSetting::kBlockAllExtensions) { + return MainPageState::kUserBlockedSite; + } + + return MainPageState::kUserCustomizedSite; +} + // Returns the extension corresponding to `extension_id` on `profile`. const extensions::Extension* GetExtension( Profile& profile, @@ -549,6 +589,59 @@ false); } +ExtensionsMenuViewModel::SiteSettings +ExtensionsMenuViewModel::GetSiteSettings() { + content::WebContents* web_contents = GetActiveWebContents(); + Profile* profile = browser_->GetProfile(); + auto has_enterprise_extensions = [&]() { + return std::any_of( + toolbar_model_->action_ids().begin(), + toolbar_model_->action_ids().end(), + [profile](const ToolbarActionsModel::ActionId extension_id) { + auto* extension = GetExtension(*profile, extension_id); + return extensions::ExtensionSystem::Get(profile) + ->management_policy() + ->HasEnterpriseForcedAccess(*extension); + }); + }; + + ExtensionsMenuViewModel::SiteSettings site_settings; + site_settings.current_site = + extensions::ui_util::GetFormattedHostForDisplay(*web_contents); + + MainPageState state = + GetMainPageState(*profile, *toolbar_model_, *web_contents); + switch (state) { + case MainPageState::kRestrictedSite: + site_settings.label_id = + IDS_EXTENSIONS_MENU_SITE_SETTINGS_NOT_ALLOWED_LABEL; + site_settings.is_toggle_visible = false; + site_settings.is_toggle_on = false; + site_settings.is_tooltip_visible = false; + break; + case MainPageState::kPolicyBlockedSite: + site_settings.label_id = + IDS_EXTENSIONS_MENU_SITE_SETTINGS_NOT_ALLOWED_LABEL; + site_settings.is_toggle_visible = false; + site_settings.is_toggle_on = false; + site_settings.is_tooltip_visible = has_enterprise_extensions(); + break; + case MainPageState::kUserBlockedSite: + site_settings.label_id = IDS_EXTENSIONS_MENU_SITE_SETTINGS_LABEL; + site_settings.is_toggle_visible = true; + site_settings.is_toggle_on = false; + site_settings.is_tooltip_visible = has_enterprise_extensions(); + break; + case MainPageState::kUserCustomizedSite: + site_settings.label_id = IDS_EXTENSIONS_MENU_SITE_SETTINGS_LABEL; + site_settings.is_toggle_visible = true; + site_settings.is_toggle_on = true; + site_settings.is_tooltip_visible = false; + break; + } + return site_settings; +} + ExtensionsMenuViewModel::MenuItemInfo ExtensionsMenuViewModel::GetMenuItemInfo( ToolbarActionViewModel* action_model) { Profile* profile = browser_->GetProfile();
diff --git a/chrome/browser/ui/extensions/extensions_menu_view_model.h b/chrome/browser/ui/extensions/extensions_menu_view_model.h index 5fc8411..9421214 100644 --- a/chrome/browser/ui/extensions/extensions_menu_view_model.h +++ b/chrome/browser/ui/extensions/extensions_menu_view_model.h
@@ -30,6 +30,22 @@ public TabListInterfaceObserver, public content::WebContentsObserver { public: + // Holds the information for the site settings in the extension's menu. This + // will be used by the platform delegate as needed. + struct SiteSettings { + // The text to display for the current site (e.g. "example.com"). + std::u16string current_site; + // The resource ID for the text label. + int label_id; + // Whether the toggle to block all extensions on this site is visible. + bool is_toggle_visible; + // The state of the toggle (false if extensions are blocked). + bool is_toggle_on; + // Whether to show a tooltip explaining why the setting is in its current + // state (e.g. if controlled by enterprise policy). + bool is_tooltip_visible; + }; + // Holds the information about how the extension's menu item should look like. // This will be used by the platform delegate as needed. struct MenuItemInfo { @@ -105,6 +121,9 @@ // Reloads the current web contents. void ReloadWebContents(); + // Returns the site settings for the current web contents. + SiteSettings GetSiteSettings(); + // Returns the menu item info for extension with `model`. MenuItemInfo GetMenuItemInfo(ToolbarActionViewModel* model);
diff --git a/chrome/browser/ui/extensions/extensions_menu_view_model_browsertest.cc b/chrome/browser/ui/extensions/extensions_menu_view_model_browsertest.cc index e2bf1bd..9c31c4e 100644 --- a/chrome/browser/ui/extensions/extensions_menu_view_model_browsertest.cc +++ b/chrome/browser/ui/extensions/extensions_menu_view_model_browsertest.cc
@@ -9,10 +9,12 @@ #include "chrome/browser/extensions/extension_tab_util.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/extensions/extensions_menu_view_platform_delegate.h" +#include "chrome/grit/generated_resources.h" #include "components/crx_file/id_util.h" #include "content/public/browser/web_contents.h" #include "content/public/test/browser_test.h" #include "extensions/browser/extension_registrar.h" +#include "extensions/browser/extension_util.h" #include "extensions/browser/permissions/permissions_updater.h" #include "extensions/browser/permissions/scripting_permissions_modifier.h" #include "extensions/browser/permissions/site_permissions_helper.h" @@ -432,3 +434,68 @@ EXPECT_TRUE( permissions_helper()->ShowAccessRequestsInToolbar(extension->id())); } + +// Tests that the extensions menu view model correctly gets the site setting for +// the current site. +IN_PROC_BROWSER_TEST_F(ExtensionsMenuViewModelBrowserTest, GetSiteSettings) { + // Add an extension that requests host permissions. + AddExtensionWithHostPermission("Extension", "<all_urls>"); + + // Navigate to a site that the extension requests access to. + const GURL url = + embedded_test_server()->GetURL("example.com", "/simple.html"); + ASSERT_TRUE(NavigateToURL(GetActiveWebContents(), url)); + + // Verify the site settings when the user can customize the site's access. + ExtensionsMenuViewModel::SiteSettings site_settings = + menu_model()->GetSiteSettings(); + EXPECT_EQ(site_settings.label_id, IDS_EXTENSIONS_MENU_SITE_SETTINGS_LABEL); + EXPECT_TRUE(site_settings.is_toggle_visible); + EXPECT_TRUE(site_settings.is_toggle_on); + EXPECT_FALSE(site_settings.is_tooltip_visible); + + // Update the user site setting to block all extensions on the current site. + menu_model()->UpdateSiteSetting( + PermissionsManager::UserSiteSetting::kBlockAllExtensions); + + // Verify the site settings when the user has blocked access to the current + // site. + site_settings = menu_model()->GetSiteSettings(); + EXPECT_EQ(site_settings.label_id, IDS_EXTENSIONS_MENU_SITE_SETTINGS_LABEL); + EXPECT_TRUE(site_settings.is_toggle_visible); + EXPECT_FALSE(site_settings.is_toggle_on); + EXPECT_FALSE(site_settings.is_tooltip_visible); + + // Navigate to restricted site. + const GURL restricted_url("chrome://extensions"); + ASSERT_TRUE(NavigateToURL(GetActiveWebContents(), restricted_url)); + + // Verify the site setting when the site is restricted + site_settings = menu_model()->GetSiteSettings(); + EXPECT_EQ(site_settings.label_id, + IDS_EXTENSIONS_MENU_SITE_SETTINGS_NOT_ALLOWED_LABEL); + EXPECT_FALSE(site_settings.is_toggle_visible); + EXPECT_FALSE(site_settings.is_toggle_on); + EXPECT_FALSE(site_settings.is_tooltip_visible); + + // Navigate to a policy blocked site. + URLPattern default_policy_blocked_pattern = + URLPattern(URLPattern::SCHEME_ALL, "*://*.policy-blocked.com/*"); + extensions::URLPatternSet default_allowed_hosts; + extensions::URLPatternSet default_blocked_hosts; + default_blocked_hosts.AddPattern(default_policy_blocked_pattern); + extensions::PermissionsData::SetDefaultPolicyHostRestrictions( + extensions::util::GetBrowserContextId(profile()), default_blocked_hosts, + default_allowed_hosts); + const GURL policy_blocked_url = + embedded_test_server()->GetURL("policy-blocked.com", "/simple.html"); + ASSERT_TRUE(NavigateToURL(GetActiveWebContents(), policy_blocked_url)); + + // Verify the site setting when the site is policy blocked. + site_settings = menu_model()->GetSiteSettings(); + EXPECT_EQ(site_settings.label_id, + IDS_EXTENSIONS_MENU_SITE_SETTINGS_NOT_ALLOWED_LABEL); + EXPECT_FALSE(site_settings.is_toggle_visible); + EXPECT_FALSE(site_settings.is_toggle_on); + EXPECT_FALSE(site_settings.is_tooltip_visible); +}
diff --git a/chrome/browser/ui/read_anything/read_anything_controller.cc b/chrome/browser/ui/read_anything/read_anything_controller.cc index 0e55972b..2120ce54 100644 --- a/chrome/browser/ui/read_anything/read_anything_controller.cc +++ b/chrome/browser/ui/read_anything/read_anything_controller.cc
@@ -4,20 +4,49 @@ #include "chrome/browser/ui/read_anything/read_anything_controller.h" +#include "base/functional/bind.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_window/public/browser_window_features.h" #include "chrome/browser/ui/tabs/public/tab_features.h" #include "chrome/browser/ui/tabs/tab_model.h" -#include "base/functional/bind.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/browser/ui/views/side_panel/side_panel_entry_id.h" #include "chrome/browser/ui/views/side_panel/side_panel_ui.h" #include "chrome/common/webui_url_constants.h" #include "chrome/grit/generated_resources.h" +#include "content/public/browser/navigation_handle.h" +#include "content/public/browser/page.h" #include "content/public/browser/web_contents.h" #include "ui/accessibility/accessibility_features.h" +/////////////////////////////////////////////////////////////////////////////// +// WebContentsObserverInstance + +WebContentsObserverInstance::WebContentsObserverInstance( + content::WebContents* web_contents, + base::RepeatingClosure primary_page_changed_callback, + base::RepeatingCallback<void(content::Visibility)> + visibility_changed_callback) + : content::WebContentsObserver(web_contents), + primary_page_changed_callback_(primary_page_changed_callback), + visibility_changed_callback_(visibility_changed_callback) {} + +WebContentsObserverInstance::~WebContentsObserverInstance() = default; + +// content::WebContentsObserver: +void WebContentsObserverInstance::PrimaryPageChanged(content::Page& page) { + primary_page_changed_callback_.Run(); +} + +void WebContentsObserverInstance::OnVisibilityChanged( + content::Visibility visibility) { + visibility_changed_callback_.Run(visibility); +} + +/////////////////////////////////////////////////////////////////////////////// +// ReadAnythingController + DEFINE_USER_DATA(ReadAnythingController); WEB_CONTENTS_USER_DATA_KEY_IMPL(ReadAnythingControllerGlue); @@ -47,6 +76,13 @@ tab_subscriptions_.push_back( tab_->RegisterWillDetach(base::BindRepeating( &ReadAnythingController::TabWillDetach, weak_factory_.GetWeakPtr()))); + + main_page_observer_ = std::make_unique<WebContentsObserverInstance>( + /*web_contents=*/tab_->GetContents(), + /*primary_page_changed_callback=*/ + base::BindRepeating(&ReadAnythingController::OnMainPagePrimaryPageChanged, + base::Unretained(this)), + /*visibility_changed_callback=*/base::DoNothing()); } ReadAnythingController::~ReadAnythingController() { @@ -57,8 +93,9 @@ tab_->GetBrowserWindowInterface()->GetTabStripModel()->RemoveObserver(this); } - if (web_contents()) { - web_contents()->RemoveUserData(ReadAnythingControllerGlue::UserDataKey()); + if (ra_web_ui_observer_ && ra_web_ui_observer_->web_contents()) { + ra_web_ui_observer_->web_contents()->RemoveUserData( + ReadAnythingControllerGlue::UserDataKey()); } } @@ -112,6 +149,10 @@ return is_active_tab_; } +int ReadAnythingController::GetNavCounterForTesting() const { + return nav_counter_; +} + // Returns the SidePanelUI for the active tab if the tab is active and has a // browser window interface. Returns nullptr otherwise. SidePanelUI* ReadAnythingController::GetSidePanelUI() { @@ -132,7 +173,14 @@ GURL(chrome::kChromeUIUntrustedReadAnythingSidePanelURL), profile, IDS_READING_MODE_TITLE, /*esc_closes_ui=*/false); - Observe(web_ui_wrapper_->web_contents()); + + ra_web_ui_observer_ = std::make_unique<WebContentsObserverInstance>( + /*web_contents=*/web_ui_wrapper_->web_contents(), base::DoNothing(), + /*primary_page_changed_callback=*/ + base::BindRepeating( + &ReadAnythingController::OnReadAnythingVisibilityChanged, + /*visibility_changed_callback=*/base::Unretained(this))); + ReadAnythingControllerGlue::CreateForWebContents( web_ui_wrapper_->web_contents(), this); } @@ -190,7 +238,13 @@ return PresentationState::kInactive; } -void ReadAnythingController::OnVisibilityChanged( +void ReadAnythingController::OnMainPagePrimaryPageChanged() { + // TODO(crbug.com/460136558): Implement showing/hiding when this function + // gets called. Update tests to check if RM is visible / hidden instead of + // nav_counter check. + nav_counter_++; +} +void ReadAnythingController::OnReadAnythingVisibilityChanged( content::Visibility visibility) { if (visibility == content::Visibility::VISIBLE) { has_shown_ui_ = true;
diff --git a/chrome/browser/ui/read_anything/read_anything_controller.h b/chrome/browser/ui/read_anything/read_anything_controller.h index 0612c02..c2112ae 100644 --- a/chrome/browser/ui/read_anything/read_anything_controller.h +++ b/chrome/browser/ui/read_anything/read_anything_controller.h
@@ -17,6 +17,7 @@ #include "chrome/browser/ui/webui/side_panel/read_anything/read_anything_untrusted_ui.h" #include "chrome/browser/ui/webui/top_chrome/webui_contents_wrapper.h" #include "components/tabs/public/tab_interface.h" +#include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents_observer.h" #include "content/public/browser/web_contents_user_data.h" #include "ui/base/unowned_user_data/scoped_unowned_user_data.h" @@ -24,6 +25,32 @@ class ReadAnythingController; class TabStripModel; +// A helper class to observe a specific WebContents, so the ReadAnything +// Controller can observe multiple WebContents. Event callbacks are configured +// by the instantiator. +class WebContentsObserverInstance : public content::WebContentsObserver { + public: + WebContentsObserverInstance( + content::WebContents* web_contents, + base::RepeatingClosure primary_page_changed_callback, + base::RepeatingCallback<void(content::Visibility)> + visibility_changed_callback); + + WebContentsObserverInstance(const WebContentsObserverInstance&) = delete; + WebContentsObserverInstance& operator=(const WebContentsObserverInstance&) = + delete; + ~WebContentsObserverInstance() override; + + // content::WebContentsObserver: + void PrimaryPageChanged(content::Page& page) override; + void OnVisibilityChanged(content::Visibility visibility) override; + + private: + base::RepeatingClosure primary_page_changed_callback_; + base::RepeatingCallback<void(content::Visibility)> + visibility_changed_callback_; +}; + // Allows the Reading Mode WebUI (namely, the ReadAnythingUntrustedPageHandler) // to lookup the ReadAnythingController from the WebUI's WebContents. class ReadAnythingControllerGlue @@ -51,8 +78,7 @@ // // It acts as the primary entry point for all Reading Mode commands and is // responsible for orchestrating the display of the Reading Mode UI. -class ReadAnythingController : public TabStripModelObserver, - content::WebContentsObserver { +class ReadAnythingController : public TabStripModelObserver { public: using Observer = ReadAnythingLifecycleObserver; @@ -92,6 +118,8 @@ // TODO(crbug.com/447418049): Open immersive reading mode via this entrypoint. void ToggleReadAnythingSidePanel(SidePanelOpenTrigger trigger); + int GetNavCounterForTesting() const; + // Returns the current presentation state of the Reading Mode feature. PresentationState GetPresentationState() const; @@ -121,9 +149,6 @@ const TabStripModelChange& change, const TabStripSelectionChange& selection_change) override; - // content::WebContentsObserver: - void OnVisibilityChanged(content::Visibility visibility) override; - // Called by other host views of the Reading Mode WebUI to return ownership of // the WebUIContentsWrapper to this controller. void TransferWebUiOwnership( @@ -135,10 +160,24 @@ void TabWillDetach(tabs::TabInterface* tab, tabs::TabInterface::DetachReason reason); + std::unique_ptr<WebContentsObserverInstance> main_page_observer_; + std::unique_ptr<WebContentsObserverInstance> ra_web_ui_observer_; + + // Callback for when main_page_observer_ receives a PrimaryPageChanged event. + void OnMainPagePrimaryPageChanged(); + + // Callback for when ra_web_ui_observer_ receives a OnVisibilityChanged + // event. + void OnReadAnythingVisibilityChanged(content::Visibility visibility); + // Returns the SidePanelUI for the active tab if it can be shown. // Otherwise, returns nullptr. SidePanelUI* GetSidePanelUI(); + // TODO(crbug.com/460136558): Used for tests, remove when implementing + // OnTabNavigation. + int nav_counter_ = 0; + raw_ptr<tabs::TabInterface> tab_ = nullptr; ui::ScopedUnownedUserData<ReadAnythingController> scoped_unowned_user_data_;
diff --git a/chrome/browser/ui/read_anything/read_anything_controller_browsertest.cc b/chrome/browser/ui/read_anything/read_anything_controller_browsertest.cc index d724f22..ee6afbb2b 100644 --- a/chrome/browser/ui/read_anything/read_anything_controller_browsertest.cc +++ b/chrome/browser/ui/read_anything/read_anything_controller_browsertest.cc
@@ -22,6 +22,7 @@ #include "chrome/browser/ui/views/side_panel/side_panel_web_ui_view.h" #include "chrome/browser/ui/webui/top_chrome/webui_contents_wrapper.h" #include "chrome/test/base/in_process_browser_test.h" +#include "chrome/test/base/ui_test_utils.h" #include "content/public/test/browser_test.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/accessibility/accessibility_features.h" @@ -354,3 +355,44 @@ EXPECT_EQ(web_contents1, web_contents2); } + +IN_PROC_BROWSER_TEST_F(ReadAnythingControllerBrowserTest, + WebContentsObserverPrimaryPageChangedCrossNavigation) { + tabs::TabInterface* tab = browser()->tab_strip_model()->GetActiveTab(); + ASSERT_TRUE(tab); + + auto* controller = ReadAnythingController::From(tab); + ASSERT_TRUE(controller); + + ASSERT_EQ(controller->GetNavCounterForTesting(), 1); + + GURL url("about:blank"); + ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url)); + + ASSERT_EQ(controller->GetNavCounterForTesting(), 2); + + GURL url2("https://www.example.com"); + ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url2)); + + ASSERT_EQ(controller->GetNavCounterForTesting(), 3); +} + +IN_PROC_BROWSER_TEST_F( + ReadAnythingControllerBrowserTest, + WebContentsObserverPrimaryPageChangedFragmentNavigation) { + tabs::TabInterface* tab = browser()->tab_strip_model()->GetActiveTab(); + ASSERT_TRUE(tab); + + auto* controller = ReadAnythingController::From(tab); + ASSERT_TRUE(controller); + + GURL url("about:blank"); + ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url)); + + ASSERT_EQ(controller->GetNavCounterForTesting(), 2); + + GURL same_doc_url("about:blank#same"); + ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), same_doc_url)); + + ASSERT_EQ(controller->GetNavCounterForTesting(), 2); +}
diff --git a/chrome/browser/ui/startup/startup_browser_creator_browsertest.cc b/chrome/browser/ui/startup/startup_browser_creator_browsertest.cc index a4dd9b0e..72932f6 100644 --- a/chrome/browser/ui/startup/startup_browser_creator_browsertest.cc +++ b/chrome/browser/ui/startup/startup_browser_creator_browsertest.cc
@@ -1288,7 +1288,7 @@ const auto wait_for_load_stop_for_browser = [](BrowserWindowInterface* browser) { TabStripModel* const tab_strip_model = browser->GetTabStripModel(); - for (int i = 0; i < tab_strip_model->GetTabCount(); ++i) { + for (int i = 0; i < tab_strip_model->count(); ++i) { content::WebContents* const contents = tab_strip_model->GetWebContentsAt(i); EXPECT_TRUE(content::WaitForLoadStop(contents)); @@ -1314,7 +1314,7 @@ EXPECT_NO_FATAL_FAILURE( wait_for_load_stop_for_browser(pref_urls_opened_browser)); tab_strip_model = pref_urls_opened_browser->GetTabStripModel(); - EXPECT_EQ(2, tab_strip_model->GetTabCount()); + EXPECT_EQ(2, tab_strip_model->count()); EXPECT_EQ(t1_url, tab_strip_model->GetWebContentsAt(0)->GetVisibleURL()); EXPECT_EQ(t2_url, tab_strip_model->GetWebContentsAt(1)->GetVisibleURL()); EXPECT_EQ(0, tab_strip_model->active_index());
diff --git a/chrome/browser/ui/tabs/organization/tab_declutter_controller.cc b/chrome/browser/ui/tabs/organization/tab_declutter_controller.cc index 1d86117..fb796f5 100644 --- a/chrome/browser/ui/tabs/organization/tab_declutter_controller.cc +++ b/chrome/browser/ui/tabs/organization/tab_declutter_controller.cc
@@ -189,7 +189,7 @@ int excluded_tab_count = 0; if (!excluded_urls_.empty()) { - for (int index = 0; index < tab_strip_model_->GetTabCount(); index++) { + for (int index = 0; index < tab_strip_model_->count(); index++) { if (excluded_urls_.contains(tab_strip_model_->GetTabAtIndex(index) ->GetContents() ->GetLastCommittedURL() @@ -369,7 +369,7 @@ return false; } - const int total_tab_count = tab_strip_model_->GetTabCount(); + const int total_tab_count = tab_strip_model_->count(); if (total_tab_count < kMinTabCountForInactiveTabNudge) { return false;
diff --git a/chrome/browser/ui/tabs/organization/tab_declutter_controller_interactive_uitest.cc b/chrome/browser/ui/tabs/organization/tab_declutter_controller_interactive_uitest.cc index 1d42253..4f9f295b 100644 --- a/chrome/browser/ui/tabs/organization/tab_declutter_controller_interactive_uitest.cc +++ b/chrome/browser/ui/tabs/organization/tab_declutter_controller_interactive_uitest.cc
@@ -344,12 +344,12 @@ std::vector<tabs::TabInterface*> stale_tabs = tab_declutter_controller()->GetStaleTabs(); - int initial_tab_count = browser()->tab_strip_model()->GetTabCount(); + int initial_tab_count = browser()->tab_strip_model()->count(); int stale_tab_count = stale_tabs.size(); tab_declutter_controller()->DeclutterTabs(stale_tabs, {}); // Verify that the number of tabs has decreased by the number of stale tabs. - int remaining_tab_count = browser()->tab_strip_model()->GetTabCount(); + int remaining_tab_count = browser()->tab_strip_model()->count(); EXPECT_EQ(remaining_tab_count, initial_tab_count - stale_tab_count); } IN_PROC_BROWSER_TEST_F(TabDeclutterControllerBrowserTest, @@ -368,13 +368,13 @@ std::vector<tabs::TabInterface*> stale_tabs = tab_declutter_controller()->GetStaleTabs(); - EXPECT_EQ(browser_two->tab_strip_model()->GetTabCount(), 1); + EXPECT_EQ(browser_two->tab_strip_model()->count(), 1); browser_two->browser_window_features() ->tab_declutter_controller() ->DeclutterTabs(stale_tabs, {}); // Verify that the number of tabs has not decreased in second browser. - EXPECT_EQ(browser_two->tab_strip_model()->GetTabCount(), 1); + EXPECT_EQ(browser_two->tab_strip_model()->count(), 1); } IN_PROC_BROWSER_TEST_F(TabDeclutterControllerBrowserTest, @@ -474,8 +474,7 @@ content::WebContents* content = browser() ->tab_strip_model() - ->GetTabAtIndex(browser()->tab_strip_model()->GetTabCount() - 1 - - i) + ->GetTabAtIndex(browser()->tab_strip_model()->count() - 1 - i) ->GetContents(); content::TestNavigationObserver observer(content); content->GetController().LoadURLWithParams( @@ -594,11 +593,11 @@ std::vector<tabs::TabInterface*> stale_tabs = tab_declutter_controller()->GetStaleTabs(); - int initial_tab_count = browser()->tab_strip_model()->GetTabCount(); + int initial_tab_count = browser()->tab_strip_model()->count(); int stale_tab_count = stale_tabs.size(); tab_declutter_controller()->DeclutterTabs(stale_tabs, {duplicate_url_1}); // Verify that the number of tabs has decreased by the number of stale tabs. - int remaining_tab_count = browser()->tab_strip_model()->GetTabCount(); + int remaining_tab_count = browser()->tab_strip_model()->count(); EXPECT_EQ(remaining_tab_count, initial_tab_count - (stale_tab_count + 2)); }
diff --git a/chrome/browser/ui/tabs/organization/tab_organization.cc b/chrome/browser/ui/tabs/organization/tab_organization.cc index 6b65757..5bb5c391 100644 --- a/chrome/browser/ui/tabs/organization/tab_organization.cc +++ b/chrome/browser/ui/tabs/organization/tab_organization.cc
@@ -205,13 +205,13 @@ // grouped tab. If this group is already in the leftmost position then leave // it there. Else move the group at the index of that tab. int move_index = tab_strip_model->IndexOfFirstNonPinnedTab(); - while (move_index < tab_strip_model->GetTabCount() && + while (move_index < tab_strip_model->count() && (tab_strip_model->GetTabGroupForTab(move_index).has_value() && tab_strip_model->GetTabGroupForTab(move_index).value() != group_id_.value())) { move_index++; } - CHECK(move_index < tab_strip_model->GetTabCount()); + CHECK(move_index < tab_strip_model->count()); if (tab_strip_model->GetTabGroupForTab(move_index) != group_id_.value()) { tab_strip_model->MoveGroupTo(group_id_.value(), move_index);
diff --git a/chrome/browser/ui/tabs/tab_strip_api/tab_strip_service_impl_browsertest.cc b/chrome/browser/ui/tabs/tab_strip_api/tab_strip_service_impl_browsertest.cc index 2348f1d..36093df 100644 --- a/chrome/browser/ui/tabs/tab_strip_api/tab_strip_service_impl_browsertest.cc +++ b/chrome/browser/ui/tabs/tab_strip_api/tab_strip_service_impl_browsertest.cc
@@ -466,7 +466,7 @@ mojo::Remote<TabStripService> remote; tab_strip_service_mojo_handler_->Accept(remote.BindNewPipeAndPassReceiver()); - const int starting_num_tabs = GetTabStripModel()->GetTabCount(); + const int starting_num_tabs = GetTabStripModel()->count(); base::RunLoop create_loop; remote->CreateTabAt(tabs_api::Position(0), @@ -479,7 +479,7 @@ create_loop.Run(); // We should now have one more tab than when we first started. - ASSERT_EQ(starting_num_tabs + 1, GetTabStripModel()->GetTabCount()); + ASSERT_EQ(starting_num_tabs + 1, GetTabStripModel()->count()); const auto* interface = GetTabStripModel()->GetTabAtIndex(0); base::RunLoop close_loop; @@ -494,7 +494,7 @@ close_loop.Run(); // We should be back to where we started. - ASSERT_EQ(starting_num_tabs, GetTabStripModel()->GetTabCount()); + ASSERT_EQ(starting_num_tabs, GetTabStripModel()->count()); } IN_PROC_BROWSER_TEST_F(TabStripServiceImplBrowserTest, ActivateTab) {
diff --git a/chrome/browser/ui/tabs/tab_strip_model.cc b/chrome/browser/ui/tabs/tab_strip_model.cc index 07ed833..4830817 100644 --- a/chrome/browser/ui/tabs/tab_strip_model.cc +++ b/chrome/browser/ui/tabs/tab_strip_model.cc
@@ -728,7 +728,7 @@ void TabStripModel::UpdateSelectionModelForDetach( gfx::Range tab_indices, std::optional<int> next_selected_index) { - const bool closed_all_tabs = (GetTabCount() == 0); + const bool closed_all_tabs = (count() == 0); bool active_tab_removed = tab_indices.Contains(gfx::Range(active_index())); if (closed_all_tabs) { @@ -2351,10 +2351,6 @@ *GetSplitData(split_id)->visual_data()); } -int TabStripModel::GetTabCount() const { - return contents_data_->TabCountRecursive(); -} - TabStripModel::TabIterator TabStripModel::begin() const { return contents_data_->begin(); }
diff --git a/chrome/browser/ui/tabs/tab_strip_model.h b/chrome/browser/ui/tabs/tab_strip_model.h index 96dd408..5197ca6 100644 --- a/chrome/browser/ui/tabs/tab_strip_model.h +++ b/chrome/browser/ui/tabs/tab_strip_model.h
@@ -227,10 +227,6 @@ // Retrieve the number of WebContentses/emptiness of the TabStripModel. int count() const; - // TODO(crbug.com/417291958) remove this function since its the same as - // count(). - int GetTabCount() const; - bool empty() const; // Retrieve the Profile associated with this TabStripModel.
diff --git a/chrome/browser/ui/views/OWNERS b/chrome/browser/ui/views/OWNERS index e106138..3b7ffe8 100644 --- a/chrome/browser/ui/views/OWNERS +++ b/chrome/browser/ui/views/OWNERS
@@ -11,6 +11,7 @@ # The find-owners plugin does not support groups, so the actual c/b/ui/views # reviewers are listed below but tagged with {LAST_RESORT_SUGGESTION} so that # Gerrit will preferentially suggest the review alias above. +agale@chromium.org #{LAST_RESORT_SUGGESTION} corising@chromium.org #{LAST_RESORT_SUGGESTION} dfried@chromium.org #{LAST_RESORT_SUGGESTION} dljames@chromium.org #{LAST_RESORT_SUGGESTION}
diff --git a/chrome/browser/ui/views/bookmarks/saved_tab_groups/saved_tab_group_bar_browsertest.cc b/chrome/browser/ui/views/bookmarks/saved_tab_groups/saved_tab_group_bar_browsertest.cc index e32b9e14..af43562 100644 --- a/chrome/browser/ui/views/bookmarks/saved_tab_groups/saved_tab_group_bar_browsertest.cc +++ b/chrome/browser/ui/views/bookmarks/saved_tab_groups/saved_tab_group_bar_browsertest.cc
@@ -82,7 +82,7 @@ ASSERT_TRUE(saved_group); EXPECT_EQ(group_id, saved_group->local_group_id()); - const int original_model_count = model->GetTabCount(); + const int original_model_count = model->count(); const base::Uuid guid = saved_group->saved_guid(); std::optional<LocalTabGroupID> opened_group_id = service->OpenTabGroup( guid, std::make_unique<TabGroupActionContextDesktop>(
diff --git a/chrome/browser/ui/views/extensions/extensions_menu_main_page_view.cc b/chrome/browser/ui/views/extensions/extensions_menu_main_page_view.cc index 1a1ff2c1..12e2304 100644 --- a/chrome/browser/ui/views/extensions/extensions_menu_main_page_view.cc +++ b/chrome/browser/ui/views/extensions/extensions_menu_main_page_view.cc
@@ -242,17 +242,14 @@ } void ExtensionsMenuMainPageView::UpdateSiteSettings( - const std::u16string& current_site, - int label_id, - bool is_tooltip_visible, - bool is_toggle_visible, - bool is_toggle_on) { - site_settings_label_->SetText( - l10n_util::GetStringFUTF16(label_id, current_site)); - site_settings_tooltip_->SetVisible(is_tooltip_visible); - site_settings_toggle_->SetVisible(is_toggle_visible); - site_settings_toggle_->SetIsOn(is_toggle_on); - site_settings_toggle_->SetTooltipText(GetSiteSettingToggleText(is_toggle_on)); + ExtensionsMenuViewModel::SiteSettings site_settings) { + site_settings_label_->SetText(l10n_util::GetStringFUTF16( + site_settings.label_id, site_settings.current_site)); + site_settings_tooltip_->SetVisible(site_settings.is_tooltip_visible); + site_settings_toggle_->SetVisible(site_settings.is_toggle_visible); + site_settings_toggle_->SetIsOn(site_settings.is_toggle_on); + site_settings_toggle_->SetTooltipText( + GetSiteSettingToggleText(site_settings.is_toggle_on)); } void ExtensionsMenuMainPageView::ShowReloadSection() { @@ -283,6 +280,7 @@ views::AsViewClass<views::Label>(extension_items[kRequestEntryLabelIndex]) ->SetText(name); requests_entries_view_->ReorderChildView(request_entry, index); + return; } // Otherwise, add a new request entry.
diff --git a/chrome/browser/ui/views/extensions/extensions_menu_main_page_view.h b/chrome/browser/ui/views/extensions/extensions_menu_main_page_view.h index 90a3fc3..ca461ea 100644 --- a/chrome/browser/ui/views/extensions/extensions_menu_main_page_view.h +++ b/chrome/browser/ui/views/extensions/extensions_menu_main_page_view.h
@@ -61,11 +61,7 @@ std::vector<ExtensionMenuItemView*> GetMenuItems() const; // Updates the site settings views with the given parameters. - void UpdateSiteSettings(const std::u16string& current_site, - int label_id, - bool is_tooltip_visible, - bool is_toggle_visible, - bool is_toggle_on); + void UpdateSiteSettings(ExtensionsMenuViewModel::SiteSettings site_settings); // Shows the reload section in the menu. Takes precedence over the requests // section.
diff --git a/chrome/browser/ui/views/extensions/extensions_menu_view_platform_delegate_views.cc b/chrome/browser/ui/views/extensions/extensions_menu_view_platform_delegate_views.cc index 452123b8..dfd8823 100644 --- a/chrome/browser/ui/views/extensions/extensions_menu_view_platform_delegate_views.cc +++ b/chrome/browser/ui/views/extensions/extensions_menu_view_platform_delegate_views.cc
@@ -45,7 +45,8 @@ using PermissionsManager = extensions::PermissionsManager; using SitePermissionsHelper = extensions::SitePermissionsHelper; -// Returns the state for the main page in the menu. +// TODO(crbug.com/449814184): Remove once all usages have been moved to +// extensions enu view model. Returns the state for the main page in the menu. enum class MainPageState { // Site is restricted to all extensions. kRestrictedSite, @@ -57,6 +58,8 @@ kUserCustomizedSite, }; +// TODO(crbug.com/449814184): Remove once all usages have been moved to +// extensions enu view model. MainPageState GetMainPageState(Profile& profile, const ToolbarActionsModel& toolbar_model, content::WebContents& web_contents) { @@ -488,66 +491,26 @@ ExtensionsMenuMainPageView* main_page, content::WebContents* web_contents) { CHECK(web_contents); - auto has_enterprise_extensions = [&]() { - return std::any_of( - toolbar_model_->action_ids().begin(), - toolbar_model_->action_ids().end(), - [this](const ToolbarActionsModel::ActionId extension_id) { - auto* extension = GetExtension(browser_, extension_id); - return extensions::ExtensionSystem::Get(browser_->profile()) - ->management_policy() - ->HasEnterpriseForcedAccess(*extension); - }); - }; - auto reload_required = [web_contents]() { - return extensions::TabHelper::FromWebContents(web_contents) - ->IsReloadRequired(); - }; - std::u16string current_site = - extensions::ui_util::GetFormattedHostForDisplay(*web_contents); - int site_settings_label_id; - bool is_site_settings_toggle_visible = false; - bool is_site_settings_toggle_on = false; - bool is_site_settings_tooltip_visible = false; + ExtensionsMenuViewModel::SiteSettings site_settings = + menu_model_->GetSiteSettings(); + main_page->UpdateSiteSettings(site_settings); + + // TODO(crbug.com/449814184): Move reload section and requests section + // computation to the menu view model. bool is_reload_required = false; bool can_have_requests = false; MainPageState state = GetMainPageState(*browser_->profile(), *toolbar_model_, *web_contents); - switch (state) { - case MainPageState::kRestrictedSite: - site_settings_label_id = - IDS_EXTENSIONS_MENU_SITE_SETTINGS_NOT_ALLOWED_LABEL; - is_site_settings_toggle_visible = false; - is_site_settings_toggle_on = false; - break; - case MainPageState::kPolicyBlockedSite: - site_settings_label_id = - IDS_EXTENSIONS_MENU_SITE_SETTINGS_NOT_ALLOWED_LABEL; - is_site_settings_toggle_visible = false; - is_site_settings_toggle_on = false; - is_site_settings_tooltip_visible = has_enterprise_extensions(); - break; - case MainPageState::kUserBlockedSite: - site_settings_label_id = IDS_EXTENSIONS_MENU_SITE_SETTINGS_LABEL; - is_site_settings_toggle_visible = true; - is_site_settings_toggle_on = false; - is_site_settings_tooltip_visible = has_enterprise_extensions(); - is_reload_required = reload_required(); - break; - case MainPageState::kUserCustomizedSite: - site_settings_label_id = IDS_EXTENSIONS_MENU_SITE_SETTINGS_LABEL; - is_site_settings_toggle_visible = true; - is_site_settings_toggle_on = true; - is_reload_required = reload_required(); - can_have_requests = true; - break; + if (state == MainPageState::kUserBlockedSite || + state == MainPageState::kUserCustomizedSite) { + is_reload_required = extensions::TabHelper::FromWebContents(web_contents) + ->IsReloadRequired(); } - - main_page->UpdateSiteSettings( - current_site, site_settings_label_id, is_site_settings_tooltip_visible, - is_site_settings_toggle_visible, is_site_settings_toggle_on); + if (state == MainPageState::kUserCustomizedSite) { + can_have_requests = true; + } if (is_reload_required) { main_page->ShowReloadSection();
diff --git a/chrome/browser/ui/views/frame/browser_caption_button_container_win.cc b/chrome/browser/ui/views/frame/browser_caption_button_container_win.cc index 0100067..24e56516 100644 --- a/chrome/browser/ui/views/frame/browser_caption_button_container_win.cc +++ b/chrome/browser/ui/views/frame/browser_caption_button_container_win.cc
@@ -83,7 +83,7 @@ /* adjust_width_for_height */ false, views::MinimumFlexSizeRule::kScaleToZero)); - if (frame_view_->browser_view()->AppUsesWindowControlsOverlay()) { + if (frame_view_->GetBrowserView()->AppUsesWindowControlsOverlay()) { UpdateButtonToolTipsForWindowControlsOverlay(); } } @@ -98,7 +98,7 @@ // The native window that encompasses Web Contents gets the mouse events meant // for the caption buttons, so returning HTClient allows these buttons to be // highlighted on hover. - if (frame_view_->browser_view()->IsWindowControlsOverlayEnabled() && + if (frame_view_->GetBrowserView()->IsWindowControlsOverlayEnabled() && (HitTestCaptionButton(minimize_button_, point) || HitTestCaptionButton(maximize_button_, point) || HitTestCaptionButton(restore_button_, point) || @@ -121,7 +121,7 @@ } void BrowserCaptionButtonContainer::OnWindowControlsOverlayEnabledChanged() { - if (frame_view_->browser_view()->IsWindowControlsOverlayEnabled()) { + if (frame_view_->GetBrowserView()->IsWindowControlsOverlayEnabled()) { SetBackground( views::CreateSolidBackground(frame_view_->GetTitlebarColor())); @@ -136,7 +136,7 @@ } void BrowserCaptionButtonContainer::OnThemeChanged() { - if (frame_view_->browser_view()->IsWindowControlsOverlayEnabled()) { + if (frame_view_->GetBrowserView()->IsWindowControlsOverlayEnabled()) { SetBackground( views::CreateSolidBackground(frame_view_->GetTitlebarColor())); } @@ -159,7 +159,7 @@ UpdateButtons(); - if (frame_view_->browser_view()->IsWindowControlsOverlayEnabled()) { + if (frame_view_->GetBrowserView()->IsWindowControlsOverlayEnabled()) { SetBackground( views::CreateSolidBackground(frame_view_->GetTitlebarColor())); // BrowserView paints to a layer, so this must do the same to ensure that it @@ -180,7 +180,7 @@ } void BrowserCaptionButtonContainer::UpdateButtons() { - if (!ShouldBrowserCustomDrawTitlebar(frame_view_->browser_view())) { + if (!ShouldBrowserCustomDrawTitlebar(frame_view_->GetBrowserView())) { minimize_button_->SetVisible(false); maximize_button_->SetVisible(false); restore_button_->SetVisible(false); @@ -188,10 +188,10 @@ return; } - minimize_button_->SetVisible(frame_view_->browser_view()->CanMinimize()); + minimize_button_->SetVisible(frame_view_->GetBrowserView()->CanMinimize()); const bool is_maximized = frame_view_->IsMaximized(); - const bool can_maximize = frame_view_->browser_view()->CanMaximize(); + const bool can_maximize = frame_view_->GetBrowserView()->CanMaximize(); restore_button_->SetVisible(is_maximized && can_maximize); maximize_button_->SetVisible(!is_maximized && can_maximize); @@ -207,7 +207,7 @@ void BrowserCaptionButtonContainer:: UpdateButtonToolTipsForWindowControlsOverlay() { - if (frame_view_->browser_view()->IsWindowControlsOverlayEnabled()) { + if (frame_view_->GetBrowserView()->IsWindowControlsOverlayEnabled()) { minimize_button_->SetTooltipText( minimize_button_->GetViewAccessibility().GetCachedName()); maximize_button_->SetTooltipText(
diff --git a/chrome/browser/ui/views/frame/browser_frame_header_chromeos.cc b/chrome/browser/ui/views/frame/browser_frame_header_chromeos.cc index 31a95bd..0f1c53b 100644 --- a/chrome/browser/ui/views/frame/browser_frame_header_chromeos.cc +++ b/chrome/browser/ui/views/frame/browser_frame_header_chromeos.cc
@@ -164,7 +164,7 @@ auto* browser_frame_view = static_cast<BrowserFrameViewChromeOS*>(view()); web_app::AppBrowserController* app_browser_controller = - browser_frame_view->browser_view()->browser()->app_controller(); + browser_frame_view->GetBrowserView()->browser()->app_controller(); // Please note, `app_browser_controller` may be null for non-PWA windows. if (!app_browser_controller ||
diff --git a/chrome/browser/ui/views/frame/browser_frame_view.cc b/chrome/browser/ui/views/frame/browser_frame_view.cc index c9375bc..9310784 100644 --- a/chrome/browser/ui/views/frame/browser_frame_view.cc +++ b/chrome/browser/ui/views/frame/browser_frame_view.cc
@@ -43,7 +43,6 @@ #include "ui/views/controls/label.h" #include "ui/views/view.h" #include "ui/views/view_class_properties.h" -#include "ui/views/view_observer.h" #include "ui/views/window/hit_test_utils.h" #if BUILDFLAG(IS_WIN) @@ -110,34 +109,6 @@ END_METADATA } // namespace -// Tracks the browser view and clears out the pointer when it is destroyed. -// Because of the way widgets are torn down, there will be a brief moment where -// the frame exists but the contents view does not, so maintaining a reference -// from the frame to the contents view that is never cleared is unsafe. -// -// Dereferences of `BrowserFrameView::browser_view()` would have previously -// been UAFs in this situation; now they will be explicit null dereferences -// (which is safer). -// -// See https://crbug.com/465209325 for an example of this happening. -class BrowserFrameView::BrowserViewWatcher : public views::ViewObserver { - public: - BrowserViewWatcher(BrowserFrameView& frame, BrowserView* browser_view) - : frame_(frame) { - observation_.Observe(browser_view); - } - ~BrowserViewWatcher() override = default; - - void OnViewIsDeleting(View* observed_view) override { - frame_->browser_view_ = nullptr; - observation_.Reset(); - } - - private: - const raw_ref<BrowserFrameView> frame_; - base::ScopedObservation<views::View, views::ViewObserver> observation_{this}; -}; - gfx::Rect BrowserFrameView::BoundsAndMargins::ToEnclosingRect() const { gfx::RectF temp = bounds; temp.Outset(margins); @@ -146,10 +117,7 @@ BrowserFrameView::BrowserFrameView(BrowserWidget* browser_widget, BrowserView* browser_view) - : browser_widget_(browser_widget), - browser_view_(browser_view), - browser_view_watcher_( - std::make_unique<BrowserViewWatcher>(*this, browser_view)) { + : browser_widget_(browser_widget), browser_view_(browser_view) { DCHECK(browser_widget_); DCHECK(browser_view_); if (base::CommandLine::ForCurrentProcess()->HasSwitch( @@ -188,6 +156,11 @@ return params; } +BrowserView* BrowserFrameView::GetBrowserView() const { + return const_cast<BrowserView*>( + static_cast<const BrowserView*>(browser_view_.view())); +} + void BrowserFrameView::OnBrowserViewInitViewsComplete() { UpdateMinimumSize(); } @@ -228,7 +201,7 @@ bool BrowserFrameView::HasVisibleBackgroundTabShapes( BrowserFrameActiveState active_state) const { - DCHECK(browser_view_->GetSupportsTabStrip()); + DCHECK(GetBrowserView()->GetSupportsTabStrip()); const bool active = ShouldPaintAsActiveForState(active_state); const std::optional<int> bg_id = GetCustomBackgroundId(active_state); @@ -246,7 +219,7 @@ // Inactive tab background images are copied from the active ones, so in the // inactive case, check the active image as well. if (!active) { - const int active_id = browser_view_->GetIncognito() + const int active_id = GetBrowserView()->GetIncognito() ? IDR_THEME_TAB_BACKGROUND_INCOGNITO : IDR_THEME_TAB_BACKGROUND; if (tp->HasCustomImage(active_id)) { @@ -285,7 +258,7 @@ std::optional<int> BrowserFrameView::GetCustomBackgroundId( BrowserFrameActiveState active_state) const { const ui::ThemeProvider* tp = GetThemeProvider(); - const bool incognito = browser_view_->GetIncognito(); + const bool incognito = GetBrowserView()->GetIncognito(); const bool active = ShouldPaintAsActiveForState(active_state); const int active_id = incognito ? IDR_THEME_TAB_BACKGROUND_INCOGNITO : IDR_THEME_TAB_BACKGROUND; @@ -376,7 +349,8 @@ gfx::ImageSkia BrowserFrameView::GetFrameOverlayImage( BrowserFrameActiveState active_state) const { - if (browser_view_->GetIncognito() || !browser_view_->GetIsNormalType()) { + if (GetBrowserView()->GetIncognito() || + !GetBrowserView()->GetIsNormalType()) { return gfx::ImageSkia(); } @@ -430,7 +404,7 @@ } int BrowserFrameView::GetSystemMenuY() const { - if (!browser_view()->GetTabStripVisible()) { + if (!GetBrowserView()->GetTabStripVisible()) { return GetTopInset(false); } @@ -438,7 +412,7 @@ // position when in vertical tabs mode since the top element will now be the // toolbar instead of the tabstrip. return GetBoundsForTabStripRegion( - browser_view()->tab_strip_view()->GetMinimumSize()) + GetBrowserView()->tab_strip_view()->GetMinimumSize()) .bottom() - GetLayoutConstant(TABSTRIP_TOOLBAR_OVERLAP); }
diff --git a/chrome/browser/ui/views/frame/browser_frame_view.h b/chrome/browser/ui/views/frame/browser_frame_view.h index 275bc5f..247341e4 100644 --- a/chrome/browser/ui/views/frame/browser_frame_view.h +++ b/chrome/browser/ui/views/frame/browser_frame_view.h
@@ -18,6 +18,7 @@ #include "ui/gfx/geometry/rect_f.h" #include "ui/gfx/geometry/size.h" #include "ui/gfx/geometry/size_f.h" +#include "ui/views/view_tracker.h" #include "ui/views/window/frame_view.h" class BrowserView; @@ -61,7 +62,11 @@ BrowserFrameView& operator=(const BrowserFrameView&) = delete; ~BrowserFrameView() override; - BrowserView* browser_view() const { return browser_view_; } + // Returns the browser view, or null if it does not exist. The browser view is + // destructed before the frame, so any methods which might be called during + // teardown should check for null. + BrowserView* GetBrowserView() const; + BrowserWidget* browser_widget() const { return browser_widget_; } // Called after BrowserView has initialized its child views. This is a useful @@ -260,9 +265,7 @@ // The BrowserView hosted within `frame_`. Have to watch to reset this so it // doesn't dangle. - raw_ptr<BrowserView> browser_view_ = nullptr; - class BrowserViewWatcher; - std::unique_ptr<BrowserViewWatcher> browser_view_watcher_; + views::ViewTracker browser_view_; // Subscription to receive notifications when the frame's PaintAsActive state // changes.
diff --git a/chrome/browser/ui/views/frame/browser_frame_view_chromeos.cc b/chrome/browser/ui/views/frame/browser_frame_view_chromeos.cc index 68a66c9..fb89c21 100644 --- a/chrome/browser/ui/views/frame/browser_frame_view_chromeos.cc +++ b/chrome/browser/ui/views/frame/browser_frame_view_chromeos.cc
@@ -207,7 +207,7 @@ BrowserFrameViewChromeOS::~BrowserFrameViewChromeOS() { if (auto* immersive_controller = - ImmersiveModeController::From(browser_view()->browser())) { + ImmersiveModeController::From(GetBrowserView()->browser())) { immersive_controller->RemoveObserver(this); } @@ -221,7 +221,7 @@ } void BrowserFrameViewChromeOS::Init() { - Browser* browser = browser_view()->browser(); + Browser* browser = GetBrowserView()->browser(); const bool is_close_button_enabled = !(browser->app_controller() && @@ -232,7 +232,7 @@ browser_widget(), is_close_button_enabled)); // Initializing the TabIconView is expensive, so only do it if we need to. - if (browser_view()->ShouldShowWindowIcon()) { + if (GetBrowserView()->ShouldShowWindowIcon()) { AddChildView(views::Builder<TabIconView>() .CopyAddressTo(&window_icon_) .SetModel(this) @@ -266,7 +266,7 @@ UpdateBorderlessModeEnabled(); } - ImmersiveModeController::From(browser_view()->browser())->AddObserver(this); + ImmersiveModeController::From(GetBrowserView()->browser())->AddObserver(this); } BrowserLayoutParams BrowserFrameViewChromeOS::GetBrowserLayoutParams() const { @@ -284,7 +284,7 @@ const auto caption_bounds = caption_button_container_->bounds(); // When the tabstrip is present, the caption button container is cut down to // the preferred height of the tabstrip. - const int tabstrip_height = browser_view()->GetTabStripHeight(); + const int tabstrip_height = GetBrowserView()->GetTabStripHeight(); const int height = tabstrip_height ? tabstrip_height : caption_bounds.height(); params.trailing_exclusion.content = @@ -308,8 +308,8 @@ const int x = GetToolbarLeftInset(); const int available_width = caption_button_container_->x() - x; int painted_height = GetTopInset(false); - if (browser_view()->GetTabStripVisible()) { - painted_height += browser_view()->GetTabStripHeight(); + if (GetBrowserView()->GetTabStripVisible()) { + painted_height += GetBrowserView()->GetTabStripHeight(); } return gfx::Rect(x, 0, std::max(0, available_width), painted_height); } @@ -319,9 +319,9 @@ return false; } - if (browser_view()->browser()->is_type_app_popup() && - !browser_view()->AppUsesWindowControlsOverlay() && - !browser_view()->AppUsesBorderlessMode()) { + if (GetBrowserView()->browser()->is_type_app_popup() && + !GetBrowserView()->AppUsesWindowControlsOverlay() && + !GetBrowserView()->AppUsesBorderlessMode()) { return false; } @@ -335,31 +335,31 @@ // When immersive fullscreen unrevealed, tabstrip is offscreen with normal // tabstrip bounds, the top inset should reach this topmost edge. const auto* const immersive_controller = - ImmersiveModeController::From(browser_view()->browser()); + ImmersiveModeController::From(GetBrowserView()->browser()); if (immersive_controller->IsEnabled() && !immersive_controller->IsRevealed()) { - return (-1) * browser_view()->GetTabStripHeight(); + return (-1) * GetBrowserView()->GetTabStripHeight(); } // The header isn't painted for restored popup/app windows in overview mode, // but the inset is still calculated below, so the overview code can align // the window content with a fake header. if (!GetOverviewMode() || browser_widget()->IsFullscreen() || - browser_view()->GetTabStripVisible() || - browser_view()->webui_tab_strip()) { + GetBrowserView()->GetTabStripVisible() || + GetBrowserView()->webui_tab_strip()) { return 0; } } - if (browser_view()->GetTabStripVisible()) { + if (GetBrowserView()->GetTabStripVisible()) { return 0; } - Browser* browser = browser_view()->browser(); + Browser* browser = GetBrowserView()->browser(); int header_height = frame_header_ ? frame_header_->GetHeaderHeight() : 0; const gfx::Size toolbar_size = - browser_view()->GetWebAppFrameToolbarPreferredSize(); + GetBrowserView()->GetWebAppFrameToolbarPreferredSize(); if (!toolbar_size.IsEmpty()) { header_height = std::max(header_height, toolbar_size.height()); } @@ -379,7 +379,7 @@ BrowserFrameActiveState active_state) const { // Web apps apply a theme color if specified by the extension/manifest. std::optional<SkColor> frame_theme_color = - browser_view()->browser()->app_controller()->GetThemeColor(); + GetBrowserView()->browser()->app_controller()->GetThemeColor(); const SkColor frame_color = frame_theme_color.value_or(GetFrameColor(active_state)); const SkColor active_caption_color = @@ -397,13 +397,13 @@ SkColor BrowserFrameViewChromeOS::GetFrameColor( BrowserFrameActiveState active_state) const { - if (!UsePackagedAppHeaderStyle(browser_view()->browser())) { + if (!UsePackagedAppHeaderStyle(GetBrowserView()->browser())) { return BrowserFrameView::GetFrameColor(active_state); } std::optional<SkColor> color; - if (browser_view()->GetIsWebAppType()) { - color = browser_view()->browser()->app_controller()->GetThemeColor(); + if (GetBrowserView()->GetIsWebAppType()) { + color = GetBrowserView()->browser()->app_controller()->GetThemeColor(); } SkColor fallback_color = chromeos::kDefaultFrameColor; @@ -462,7 +462,7 @@ View::ConvertPointToTarget(this, browser_widget()->client_view(), &client_point); gfx::Rect tabstrip_shadow_bounds( - browser_view() + GetBrowserView() ->tab_strip_view() ->GetViewByElementId(kTabStripElementId) ->bounds()); @@ -483,9 +483,9 @@ } void BrowserFrameViewChromeOS::WindowControlsOverlayEnabledChanged() { - bool enabled = browser_view()->IsWindowControlsOverlayEnabled(); + bool enabled = GetBrowserView()->IsWindowControlsOverlayEnabled(); caption_button_container_->OnWindowControlsOverlayEnabledChanged( - enabled, GetFrameHeaderColor(browser_view()->IsActive())); + enabled, GetFrameHeaderColor(GetBrowserView()->IsActive())); } void BrowserFrameViewChromeOS::UpdateWindowIcon() { @@ -501,7 +501,7 @@ browser_widget()->GetNativeWindow()->SetProperty( chromeos::kWindowOverviewTitleKey, - browser_view()->browser()->GetWindowTitleForCurrentTab( + GetBrowserView()->browser()->GetWindowTitleForCurrentTab( /*include_app_name=*/false)); } @@ -519,12 +519,12 @@ void BrowserFrameViewChromeOS::UpdateBorderlessModeEnabled() { caption_button_container_->UpdateBorderlessModeEnabled( - browser_view()->IsBorderlessModeEnabled()); + GetBrowserView()->IsBorderlessModeEnabled()); } bool BrowserFrameViewChromeOS::AppIsPwaWithBorderlessDisplayMode() const { - return browser_view()->GetIsWebAppType() && - browser_view()->AppUsesBorderlessMode(); + return GetBrowserView()->GetIsWebAppType() && + GetBrowserView()->AppUsesBorderlessMode(); } void BrowserFrameViewChromeOS::Layout(PassKey) { @@ -536,8 +536,8 @@ } int painted_height = GetTopInset(false); - if (browser_view()->GetTabStripVisible()) { - painted_height += browser_view()->GetTabStripHeight(); + if (GetBrowserView()->GetTabStripVisible()) { + painted_height += GetBrowserView()->GetTabStripHeight(); } if (frame_header_) { @@ -565,7 +565,7 @@ gfx::Size BrowserFrameViewChromeOS::GetMinimumSize() const { // System web apps (e.g. Settings) may have a fixed minimum size. - Browser* browser = browser_view()->browser(); + Browser* browser = GetBrowserView()->browser(); if (ash::IsSystemWebApp(browser)) { gfx::Size minimum_size = ash::GetSystemWebAppMinimumWindowSize(browser); if (!minimum_size.IsEmpty()) { @@ -575,7 +575,7 @@ // The minimum size of a borderless window is only limited by the window's // `highlight_border_overlay_`. - if (browser_view()->IsBorderlessModeEnabled()) { + if (GetBrowserView()->IsBorderlessModeEnabled()) { // `CalculateImageSourceSize()` returns the minimum size needed to draw the // highlight border, which in turn is the minimum size of a borderless // window. @@ -587,18 +587,18 @@ const int min_frame_width = frame_header_ ? frame_header_->GetMinimumHeaderWidth() : 0; int min_width = std::max(min_frame_width, min_client_view_size.width()); - if (browser_view()->GetTabStripVisible()) { + if (GetBrowserView()->GetTabStripVisible()) { // Ensure that the minimum width is enough to hold a minimum width tab strip // at its usual insets. const int min_tabstrip_width = - browser_view()->tab_strip_view()->GetMinimumSize().width(); + GetBrowserView()->tab_strip_view()->GetMinimumSize().width(); min_width = std::max(min_width, min_tabstrip_width + GetTabStripLeftInset() + GetTabStripRightInset()); } int min_height = min_client_view_size.height(); - if (browser_view()->IsWindowControlsOverlayEnabled()) { + if (GetBrowserView()->IsWindowControlsOverlayEnabled()) { // Ensure that the minimum height is at least the height of the caption // button container, which contains the WCO toggle and other windowing // controls. @@ -619,14 +619,14 @@ void BrowserFrameViewChromeOS::OnThemeChanged() { OnUpdateFrameColor(); caption_button_container_->OnWindowControlsOverlayEnabledChanged( - browser_view()->IsWindowControlsOverlayEnabled(), - GetFrameHeaderColor(browser_view()->IsActive())); + GetBrowserView()->IsWindowControlsOverlayEnabled(), + GetFrameHeaderColor(GetBrowserView()->IsActive())); BrowserFrameView::OnThemeChanged(); MaybeAnimateThemeChanged(); } void BrowserFrameViewChromeOS::ChildPreferredSizeChanged(views::View* child) { - if (browser_view()->initialized()) { + if (GetBrowserView()->initialized()) { InvalidateLayout(); browser_widget()->GetRootView()->DeprecatedLayoutImmediately(); } @@ -644,13 +644,13 @@ // TopContainerView and hence |rect| should not be claimed here. See // BrowserFrameViewChromeOS::OnImmersiveRevealStarted(). const bool should_leave_to_top_container = - ImmersiveModeController::From(browser_view()->browser())->IsRevealed(); + ImmersiveModeController::From(GetBrowserView()->browser())->IsRevealed(); return !should_leave_to_top_container; } views::View::Views BrowserFrameViewChromeOS::GetChildrenInZOrder() { - if (ShouldDrawFrameHeader(browser_view()->browser()) && frame_header_) { + if (ShouldDrawFrameHeader(GetBrowserView()->browser()) && frame_header_) { return frame_header_->GetAdjustedChildrenInZOrder(this); } @@ -672,7 +672,7 @@ } int BrowserFrameViewChromeOS::GetFrameHeaderImageYInset() { - return browser_view()->GetThemeOffsetFromBrowserView().y(); + return GetBrowserView()->GetThemeOffsetFromBrowserView().y(); } gfx::ImageSkia BrowserFrameViewChromeOS::GetFrameHeaderOverlayImage( @@ -709,8 +709,8 @@ } void BrowserFrameViewChromeOS::OnTabletModeToggled(bool enabled) { - if (!enabled && - ImmersiveModeController::From(browser_view()->browser())->IsRevealed()) { + if (!enabled && ImmersiveModeController::From(GetBrowserView()->browser()) + ->IsRevealed()) { // Before updating the caption buttons state below (which triggers a // relayout), we want to move the caption buttons from the // TopContainerView back to this view. @@ -722,7 +722,7 @@ caption_button_container_->UpdateCaptionButtonState(true /*=animate*/); auto* const immersive_mode_controller = - ImmersiveModeController::From(browser_view()->browser()); + ImmersiveModeController::From(GetBrowserView()->browser()); const bool was_immersive = immersive_mode_controller->IsEnabled(); // Set the immersive mode to what it should be because an immersive mode may @@ -747,14 +747,14 @@ bool BrowserFrameViewChromeOS::ShouldTabIconViewAnimate() const { // Web apps use their app icon and shouldn't show a throbber. - if (browser_view()->GetIsWebAppType()) { + if (GetBrowserView()->GetIsWebAppType()) { return false; } // This function is queried during the creation of the window as the // TabIconView we host is initialized, so we need to null check the selected // WebContents because in this condition there is not yet a selected tab. - content::WebContents* current_tab = browser_view()->GetActiveWebContents(); + content::WebContents* current_tab = GetBrowserView()->GetActiveWebContents(); return current_tab && current_tab->ShouldShowLoadingUI(); } @@ -823,7 +823,7 @@ // fullscreen states (fullscreen <> pinneed), the immersive mode is updated // in `BrowserView::FullscreenStateChanged`. if (!is_fullscreen && !was_fullscreen) { - ImmersiveModeController::From(browser_view()->browser()) + ImmersiveModeController::From(GetBrowserView()->browser()) ->SetEnabled(ShouldEnableImmersiveModeController()); } @@ -861,7 +861,7 @@ // https://crbug.com/840242. To fix this, we'll make the caption buttons // temporarily children of the TopContainerView while they're all painting to // their layers. - auto* container = browser_view()->top_container(); + auto* container = GetBrowserView()->top_container(); container->AddChildViewAt(caption_button_container_.get(), 0); container->DeprecatedLayoutImmediately(); @@ -879,7 +879,7 @@ } void BrowserFrameViewChromeOS::OnAppUpdate(const apps::AppUpdate& update) { - Browser* browser = browser_view()->browser(); + Browser* browser = GetBrowserView()->browser(); if (!browser->app_controller() || browser->app_controller()->app_id() != update.AppId() || @@ -910,10 +910,10 @@ (IsSnapped() || browser_widget()->IsMaximized())) { // Snapped or maximized browser windows that doesn't have tabstrip uses // immersive frame to hide frame in tablet mode. - return !browser_view()->GetSupportsTabStrip(); + return !GetBrowserView()->GetSupportsTabStrip(); } - const auto* fullscreen_controller = browser_view() + const auto* fullscreen_controller = GetBrowserView() ->browser() ->GetFeatures() .exclusive_access_manager() @@ -987,7 +987,7 @@ } // Show the caption buttons for packaged apps which support immersive mode. - if (UsePackagedAppHeaderStyle(browser_view()->browser())) { + if (UsePackagedAppHeaderStyle(GetBrowserView()->browser())) { return true; } @@ -1040,7 +1040,7 @@ // We need to paint when the top-of-window views are revealed in immersive // fullscreen. auto* const immersive_mode_controller = - ImmersiveModeController::From(browser_view()->browser()); + ImmersiveModeController::From(GetBrowserView()->browser()); if (immersive_mode_controller->IsEnabled()) { return immersive_mode_controller->IsRevealed(); } @@ -1051,17 +1051,17 @@ void BrowserFrameViewChromeOS::OnAddedToOrRemovedFromOverview() { const bool should_show_caption_buttons = GetShowCaptionButtons(); caption_button_container_->SetVisible(should_show_caption_buttons); - if (browser_view()->GetIsWebAppType()) { + if (GetBrowserView()->GetIsWebAppType()) { // The WebAppFrameToolbarView is part of the BrowserView, so make sure the // BrowserView is re-layed out to take into account these changes. - browser_view()->InvalidateLayout(); + GetBrowserView()->InvalidateLayout(); } } std::unique_ptr<chromeos::FrameHeader> BrowserFrameViewChromeOS::CreateFrameHeader() { std::unique_ptr<chromeos::FrameHeader> header; - Browser* browser = browser_view()->browser(); + Browser* browser = GetBrowserView()->browser(); if (!UsePackagedAppHeaderStyle(browser)) { header = std::make_unique<BrowserFrameHeaderChromeOS>( browser_widget(), this, this, caption_button_container_); @@ -1077,11 +1077,11 @@ void BrowserFrameViewChromeOS::UpdateTopViewInset() { // In immersive fullscreen mode, the top view inset property should be 0. const bool immersive = - ImmersiveModeController::From(browser_view()->browser())->IsEnabled(); - const bool tab_strip_visible = browser_view()->GetTabStripVisible(); + ImmersiveModeController::From(GetBrowserView()->browser())->IsEnabled(); + const bool tab_strip_visible = GetBrowserView()->GetTabStripVisible(); const int inset = (tab_strip_visible || immersive || (AppIsPwaWithBorderlessDisplayMode() && - browser_view()->IsBorderlessModeEnabled())) + GetBrowserView()->IsBorderlessModeEnabled())) ? 0 : GetTopInset(/*restored=*/false); browser_widget()->GetNativeWindow()->SetProperty(aura::client::kTopViewInset, @@ -1092,7 +1092,7 @@ // We only show the profile indicator for the teleported browser windows // between multi-user sessions. Note that you can't teleport an incognito // window. - Browser* browser = browser_view()->browser(); + Browser* browser = GetBrowserView()->browser(); if (browser->profile()->IsIncognitoProfile()) { return false; } @@ -1105,12 +1105,12 @@ // TODO(http://crbug.com/1059514): This check shouldn't be necessary. Provide // an appropriate affordance for the profile icon with the webUI tabstrip and // remove this block. - if (!browser_view()->GetTabStripVisible()) { + if (!GetBrowserView()->GetTabStripVisible()) { return false; } #endif // BUILDFLAG(ENABLE_WEBUI_TAB_STRIP) - return ShouldShowAvatar(browser_view()->GetNativeWindow()); + return ShouldShowAvatar(GetBrowserView()->GetNativeWindow()); } void BrowserFrameViewChromeOS::UpdateProfileIcons() { @@ -1123,7 +1123,7 @@ } gfx::Image image( - GetAvatarImageForContext(browser_view()->browser()->profile())); + GetAvatarImageForContext(GetBrowserView()->browser()->profile())); profile_indicator_icon_->SetSize(image.Size()); profile_indicator_icon_->SetIcon(image); @@ -1160,7 +1160,7 @@ frame_header_->SetHeaderCornerRadius(window_radii.upper_left()); } - if (browser_view()->IsWindowControlsOverlayEnabled()) { + if (GetBrowserView()->IsWindowControlsOverlayEnabled()) { // With window controls overlay enabled, the caption_button_container is // drawn above the client view. The container has a background that extends // over the curvature of the top-right corner, requiring its rounding. @@ -1175,7 +1175,7 @@ void BrowserFrameViewChromeOS::LayoutProfileIndicator() { DCHECK(profile_indicator_icon_); const int frame_height = - GetTopInset(false) + browser_view()->GetTabStripHeight(); + GetTopInset(false) + GetBrowserView()->GetTabStripHeight(); profile_indicator_icon_->SetPosition( gfx::Point(kProfileIndicatorPadding, (frame_height - profile_indicator_icon_->height()) / 2)); @@ -1195,7 +1195,7 @@ } auto* const immersive_controller = - ImmersiveModeController::From(browser_view()->browser()); + ImmersiveModeController::From(GetBrowserView()->browser()); // In fullscreen view, but not in immersive mode. Hide the caption buttons. if (!immersive_controller || !immersive_controller->IsEnabled()) { @@ -1218,11 +1218,11 @@ } void BrowserFrameViewChromeOS::MaybeAnimateThemeChanged() { - if (!browser_view()) { + if (!GetBrowserView()) { return; } - Browser* browser = browser_view()->browser(); + Browser* browser = GetBrowserView()->browser(); // Theme change events are only animated for system web apps which explicitly // request the behavior. @@ -1233,7 +1233,7 @@ return; } - views::WebView* web_view = browser_view()->contents_web_view(); + views::WebView* web_view = GetBrowserView()->contents_web_view(); ui::Layer* layer = GetNativeViewLayer(web_view); content::RenderWidgetHost* render_widget_host = GetRenderWidgetHost(web_view); if (!layer || !render_widget_host) { @@ -1253,11 +1253,11 @@ theme_changed_animation_callback_.Reset(base::BindOnce( [](const base::WeakPtr<BrowserFrameViewChromeOS>& self, base::TimeTicks theme_changed_time, bool success) { - if (!self || !self->browser_view()) { + if (!self || !self->GetBrowserView()) { return; } - views::WebView* web_view = self->browser_view()->contents_web_view(); + views::WebView* web_view = self->GetBrowserView()->contents_web_view(); ui::Layer* layer = GetNativeViewLayer(web_view); if (!layer) { return; @@ -1299,8 +1299,8 @@ bool BrowserFrameViewChromeOS::UseWebUITabStrip() const { return WebUITabStripContainerView::UseTouchableTabStrip( - browser_view()->browser()) && - browser_view()->GetSupportsTabStrip(); + GetBrowserView()->browser()) && + GetBrowserView()->GetSupportsTabStrip(); } const aura::Window* BrowserFrameViewChromeOS::GetFrameWindow() const {
diff --git a/chrome/browser/ui/views/frame/browser_frame_view_mac.mm b/chrome/browser/ui/views/frame/browser_frame_view_mac.mm index 51cde73..d5a149c 100644 --- a/chrome/browser/ui/views/frame/browser_frame_view_mac.mm +++ b/chrome/browser/ui/views/frame/browser_frame_view_mac.mm
@@ -119,8 +119,8 @@ void BrowserFrameViewMac::OnFullscreenStateChanged() { // Record the start of a browser fullscreen session. Content fullscreen is // ignored. - if (browser_view()->IsFullscreen() && - !fullscreen_utils::IsInContentFullscreen(browser_view()->browser())) { + if (GetBrowserView()->IsFullscreen() && + !fullscreen_utils::IsInContentFullscreen(GetBrowserView()->browser())) { fullscreen_session_start_ = base::TimeTicks::Now(); // Add a backstop to emit the metric 24 hours from now. Any session lasting @@ -135,17 +135,17 @@ EmitFullscreenSessionHistograms(); } - if (browser_view()->UsesImmersiveFullscreenMode()) { - ImmersiveModeController::From(browser_view()->browser()) - ->SetEnabled(browser_view()->IsFullscreen()); + if (GetBrowserView()->UsesImmersiveFullscreenMode()) { + ImmersiveModeController::From(GetBrowserView()->browser()) + ->SetEnabled(GetBrowserView()->IsFullscreen()); UpdateFullscreenTopUI(); - // browser_view()->DeprecatedLayoutImmediately() is not needed since top + // GetBrowserView()->DeprecatedLayoutImmediately() is not needed since top // chrome is in another widget. return; } - if (browser_view()->IsFullscreen()) { + if (GetBrowserView()->IsFullscreen()) { [fullscreen_toolbar_controller_ enterFullscreenMode]; } else { // Exiting tab fullscreen requires updating Top UI. @@ -155,7 +155,7 @@ UpdateFullscreenTopUI(); [fullscreen_toolbar_controller_ exitFullscreenMode]; } - browser_view()->DeprecatedLayoutImmediately(); + GetBrowserView()->DeprecatedLayoutImmediately(); } bool BrowserFrameViewMac::CaptionButtonsOnLeadingEdge() const { @@ -192,7 +192,7 @@ // the tab strip. Normally, we would naturally have an inset from either the // caption buttons or the tab search button. if (browser_widget()->IsFullscreen()) { - if (!browser_view()->UsesImmersiveFullscreenMode()) { + if (!GetBrowserView()->UsesImmersiveFullscreenMode()) { bounds.Inset( gfx::Insets::TLBR(0, GetLayoutConstant(TOOLBAR_CORNER_RADIUS), 0, 0)); } @@ -222,7 +222,7 @@ BrowserLayoutParams BrowserFrameViewMac::GetBrowserLayoutParams() const { auto params = BrowserFrameView::GetBrowserLayoutParams(); - if (browser_view()->IsFullscreen()) { + if (GetBrowserView()->IsFullscreen()) { // No insets for caption buttons in fullscreen, since caption buttons are on // a separate pane that slides in. However, preserve the height of the // caption area to ensure that the toolbar renders correctly (this is kind @@ -241,7 +241,7 @@ } void BrowserFrameViewMac::UpdateFullscreenTopUI() { - Browser* browser = browser_view()->browser(); + Browser* browser = GetBrowserView()->browser(); // Update to the new toolbar style if needed. FullscreenToolbarStyle new_style; if (fullscreen_utils::IsInContentFullscreen(browser)) { @@ -251,10 +251,10 @@ new_style = GetUserPreferredToolbarStyle(always_show); } - if (browser_view()->UsesImmersiveFullscreenMode()) { + if (GetBrowserView()->UsesImmersiveFullscreenMode()) { remote_cocoa::mojom::NativeWidgetNSWindow* ns_window_mojo = views::NativeWidgetMacNSWindowHost::GetFromNativeWindow( - browser_view()->GetWidget()->GetNativeWindow()) + GetBrowserView()->GetWidget()->GetNativeWindow()) ->GetNSWindowMojo(); static constexpr auto kStyleMap = base::MakeFixedFlatMap<FullscreenToolbarStyle, @@ -276,12 +276,12 @@ // Update the immersive controller about content fullscreen changes. if (mapped_style == remote_cocoa::mojom::ToolbarVisibilityStyle::kNone) { - ImmersiveModeController::From(browser_view()->browser()) + ImmersiveModeController::From(GetBrowserView()->browser()) ->OnContentFullscreenChanged(true); } else if (old_style.has_value() && old_style == remote_cocoa::mojom::ToolbarVisibilityStyle::kNone) { - ImmersiveModeController::From(browser_view()->browser()) + ImmersiveModeController::From(GetBrowserView()->browser()) ->OnContentFullscreenChanged(false); } @@ -303,14 +303,14 @@ // Re-layout if toolbar style changes in fullscreen mode. if (browser_widget()->IsFullscreen()) { - browser_view()->DeprecatedLayoutImmediately(); + GetBrowserView()->DeprecatedLayoutImmediately(); } } void BrowserFrameViewMac::OnAlwaysShowToolbarInFullscreenChanged( const webapps::AppId& app_id, bool show) { - if (web_app::AppBrowserController::IsForWebApp(browser_view()->browser(), + if (web_app::AppBrowserController::IsForWebApp(GetBrowserView()->browser(), app_id)) { UpdateFullscreenTopUI(); } @@ -366,7 +366,7 @@ // immersive fullscreen, it is drawn in a way that isn't detected by the // DCHECK in Label. As such, disable the DCHECK. window_title_label.SetSkipSubpixelRenderingOpacityCheck( - ImmersiveModeController::From(browser_view()->browser())->IsEnabled()); + ImmersiveModeController::From(GetBrowserView()->browser())->IsEnabled()); } /////////////////////////////////////////////////////////////////////////////// @@ -413,7 +413,7 @@ } void BrowserFrameViewMac::WindowControlsOverlayEnabledChanged() { - if (browser_view()->IsWindowControlsOverlayEnabled()) { + if (GetBrowserView()->IsWindowControlsOverlayEnabled()) { caption_button_placeholder_container_ = AddChildView(std::make_unique<CaptionButtonPlaceholderContainer>()); UpdateCaptionButtonPlaceholderContainerBackground(); @@ -426,8 +426,8 @@ gfx::Size BrowserFrameViewMac::GetMinimumSize() const { gfx::Size client_size = browser_widget()->client_view()->GetMinimumSize(); - if (browser_view()->browser()->is_type_normal()) { - client_size.SetToMax(browser_view()->tab_strip_view()->GetMinimumSize()); + if (GetBrowserView()->browser()->is_type_normal()) { + client_size.SetToMax(GetBrowserView()->tab_strip_view()->GetMinimumSize()); } // macOS apps generally don't allow their windows to get shorter than a @@ -451,8 +451,9 @@ // Tabbed immersive fullscreen paints its own background. In this case we // allow painting of the frame's children, which fixes a flickering bug: // 1400287. - if (browser_view()->UsesImmersiveFullscreenTabbedMode() || - !ImmersiveModeController::From(browser_view()->browser())->IsRevealed()) { + if (GetBrowserView()->UsesImmersiveFullscreenTabbedMode() || + !ImmersiveModeController::From(GetBrowserView()->browser()) + ->IsRevealed()) { BrowserFrameView::PaintChildren(info); } } @@ -463,8 +464,8 @@ // In popups, the titlebar is system-drawn and the caption buttons aren't part // of the client area. - if (browser_view()->browser()->is_type_popup() || - browser_view()->browser()->is_type_devtools()) { + if (GetBrowserView()->browser()->is_type_popup() || + GetBrowserView()->browser()->is_type_devtools()) { return result; } @@ -512,23 +513,23 @@ // views::View: void BrowserFrameViewMac::OnPaint(gfx::Canvas* canvas) { - if (!browser_view()->GetIsNormalType() && - !browser_view()->GetIsWebAppType()) { + if (!GetBrowserView()->GetIsNormalType() && + !GetBrowserView()->GetIsWebAppType()) { return; } SkColor frame_color = GetFrameColor(BrowserFrameActiveState::kUseCurrent); canvas->DrawColor(frame_color); - auto* theme_service = - ThemeServiceFactory::GetForProfile(browser_view()->browser()->profile()); + auto* theme_service = ThemeServiceFactory::GetForProfile( + GetBrowserView()->browser()->profile()); if (!theme_service->UsingSystemTheme()) { PaintThemedFrame(canvas); } } void BrowserFrameViewMac::Layout(PassKey) { - if (browser_view()->IsWindowControlsOverlayEnabled()) { + if (GetBrowserView()->IsWindowControlsOverlayEnabled()) { LayoutWindowControlsOverlay(); } LayoutSuperclass<BrowserFrameView>(this); @@ -555,7 +556,7 @@ // further modification is necessary. See // TopContainerBackground::PaintThemeCustomImage for details. gfx::Point theme_image_offset = - browser_view()->GetThemeOffsetFromBrowserView(); + GetBrowserView()->GetThemeOffsetFromBrowserView(); gfx::ImageSkia image = GetFrameImage(); canvas->TileImageInt(image, theme_image_offset.x(), theme_image_offset.y(), 0, @@ -567,9 +568,9 @@ } int BrowserFrameViewMac::TopUIFullscreenYOffset() const { - if (!browser_view()->GetTabStripVisible() || - !browser_view()->IsFullscreen() || - browser_view()->UsesImmersiveFullscreenMode()) { + if (!GetBrowserView()->GetTabStripVisible() || + !GetBrowserView()->IsFullscreen() || + GetBrowserView()->UsesImmersiveFullscreenMode()) { return 0; } @@ -593,7 +594,7 @@ void BrowserFrameViewMac::LayoutWindowControlsOverlay() { const int frame_available_height = - browser_view()->GetWebAppFrameToolbarPreferredSize().height() + + GetBrowserView()->GetWebAppFrameToolbarPreferredSize().height() + 2 * kWebAppMenuMargin; gfx::Rect container_bounds = GetCaptionButtonBounds().ToEnclosingRect(); container_bounds.set_height(frame_available_height);
diff --git a/chrome/browser/ui/views/frame/browser_frame_view_unittest.cc b/chrome/browser/ui/views/frame/browser_frame_view_unittest.cc index ecffa3d..1a04f900f 100644 --- a/chrome/browser/ui/views/frame/browser_frame_view_unittest.cc +++ b/chrome/browser/ui/views/frame/browser_frame_view_unittest.cc
@@ -83,8 +83,8 @@ const gfx::Rect frame_bounds = frame_view_->bounds(); gfx::RectF tabstrip_bounds_in_frame_coords( - frame_view_->browser_view()->tabstrip()->GetLocalBounds()); - views::View::ConvertRectToTarget(frame_view_->browser_view()->tabstrip(), + frame_view_->GetBrowserView()->tabstrip()->GetLocalBounds()); + views::View::ConvertRectToTarget(frame_view_->GetBrowserView()->tabstrip(), frame_view_, &tabstrip_bounds_in_frame_coords); const gfx::Rect tabstrip_bounds = @@ -101,7 +101,7 @@ // first tab). EXPECT_TRUE(frame_view_->HitTestRect(gfx::Rect( tabstrip_bounds.x() + 10, tabstrip_bounds.bottom() - 10, 1, 1))); - EXPECT_TRUE(frame_view_->browser_view()->HitTestRect(gfx::Rect( + EXPECT_TRUE(frame_view_->GetBrowserView()->HitTestRect(gfx::Rect( tabstrip_bounds.x() + 10, tabstrip_bounds.bottom() - 10, 1, 1))); // Tabs extend to the top of the tabstrip everywhere in this test context on
diff --git a/chrome/browser/ui/views/frame/browser_frame_view_win.cc b/chrome/browser/ui/views/frame/browser_frame_view_win.cc index 93cd8e3..2f8cd7c 100644 --- a/chrome/browser/ui/views/frame/browser_frame_view_win.cc +++ b/chrome/browser/ui/views/frame/browser_frame_view_win.cc
@@ -242,7 +242,7 @@ params.trailing_exclusion.content = gfx::SizeF(width() - caption.x(), caption.bottom() - top); // In overlay mode, the icon is present but hidden. - if (window_icon_ && !browser_view()->IsWindowControlsOverlayEnabled()) { + if (window_icon_ && !GetBrowserView()->IsWindowControlsOverlayEnabled()) { const auto& icon = window_icon_->bounds(); params.leading_exclusion.content = gfx::SizeF(icon.right(), icon.bottom() - top); @@ -258,7 +258,7 @@ // Because we don't set WS_EX_LAYOUTRTL (which would conflict with Chrome's // own RTL layout logic), Windows always draws the caption buttons on the // right, even when we want to be RTL. See crbug.com/560619. - return !ShouldBrowserCustomDrawTitlebar(browser_view()) && + return !ShouldBrowserCustomDrawTitlebar(GetBrowserView()) && base::i18n::IsRTL(); } @@ -279,7 +279,7 @@ if (IsMaximized()) { x += kMaximizedLeftMargin; } - if (browser_view()->IsWindowControlsOverlayEnabled()) { + if (GetBrowserView()->IsWindowControlsOverlayEnabled()) { x = 0; } else if (window_icon_) { // Add extra padding to the left of the toolbar to account for the window @@ -293,10 +293,10 @@ } int BrowserFrameViewWin::GetTopInset(bool restored) const { - if (browser_view()->GetTabStripVisible() || IsWebUITabStrip()) { + if (GetBrowserView()->GetTabStripVisible() || IsWebUITabStrip()) { return TopAreaHeight(restored); } - return ShouldBrowserCustomDrawTitlebar(browser_view()) + return ShouldBrowserCustomDrawTitlebar(GetBrowserView()) ? TitlebarHeight(restored) : 0; } @@ -325,7 +325,7 @@ } gfx::Size BrowserFrameViewWin::GetMinimumSize() const { - gfx::Size min_size(browser_view()->GetMinimumSize()); + gfx::Size min_size(GetBrowserView()->GetMinimumSize()); min_size.Enlarge(0, GetTopInset(false)); gfx::Size titlebar_min_size( @@ -381,7 +381,7 @@ gfx::Rect BrowserFrameViewWin::GetWindowBoundsForClientBounds( const gfx::Rect& client_bounds) const { HWND hwnd = views::HWNDForWidget(browser_widget()); - if (!browser_view()->GetTabStripVisible() && hwnd) { + if (!GetBrowserView()->GetTabStripVisible() && hwnd) { // If we don't have a tabstrip, we're either a popup or an app window, in // which case we have a standard size non-client area and can just use // AdjustWindowRectEx to obtain it. We check for a non-null window handle in @@ -406,8 +406,8 @@ // For app windows and popups without a custom titlebar we haven't customized // the frame at all so Windows can figure it out. - if (!ShouldBrowserCustomDrawTitlebar(browser_view()) && - !browser_view()->GetIsNormalType()) { + if (!ShouldBrowserCustomDrawTitlebar(GetBrowserView()) && + !GetBrowserView()->GetIsNormalType()) { return HTNOWHERE; } @@ -421,7 +421,7 @@ // pixels at the end of the top and bottom edges trigger diagonal resizing. constexpr int kResizeCornerWidth = 16; - const int top_border_thickness = browser_view()->GetIsWebAppType() + const int top_border_thickness = GetBrowserView()->GetIsWebAppType() ? FrameTopBorderThickness(false) : GetLayoutConstant(TAB_STRIP_PADDING); @@ -527,7 +527,7 @@ void BrowserFrameViewWin::OnThemeChanged() { BrowserFrameView::OnThemeChanged(); - if (!ShouldBrowserCustomDrawTitlebar(browser_view())) { + if (!ShouldBrowserCustomDrawTitlebar(GetBrowserView())) { SetSystemMicaTitlebarAttributes(); } } @@ -538,11 +538,11 @@ } // Web apps use their app icon and shouldn't show a throbber. - if (browser_view()->GetIsWebAppType()) { + if (GetBrowserView()->GetIsWebAppType()) { return false; } - content::WebContents* current_tab = browser_view()->GetActiveWebContents(); + content::WebContents* current_tab = GetBrowserView()->GetActiveWebContents(); return current_tab && current_tab->ShouldShowLoadingUI(); } @@ -557,7 +557,7 @@ bool BrowserFrameViewWin::IsWebUITabStrip() const { return WebUITabStripContainerView::UseTouchableTabStrip( - browser_view()->browser()); + GetBrowserView()->browser()); } /////////////////////////////////////////////////////////////////////////////// @@ -565,7 +565,7 @@ void BrowserFrameViewWin::OnPaint(gfx::Canvas* canvas) { TRACE_EVENT0("views.frame", "BrowserFrameViewWin::OnPaint"); - if (ShouldBrowserCustomDrawTitlebar(browser_view())) { + if (ShouldBrowserCustomDrawTitlebar(GetBrowserView())) { PaintTitlebar(canvas); } } @@ -574,7 +574,7 @@ TRACE_EVENT0("views.frame", "BrowserFrameViewWin::Layout"); LayoutCaptionButtons(); - if (!browser_view()->IsWindowControlsOverlayEnabled()) { + if (!GetBrowserView()->IsWindowControlsOverlayEnabled()) { LayoutTitleBar(); } LayoutClientView(); @@ -607,7 +607,7 @@ const bool is_fullscreen = (browser_widget()->IsFullscreen() || IsMaximized()) && !restored; if (!is_fullscreen) { - if (browser_view()->GetTabStripVisible()) { + if (GetBrowserView()->GetTabStripVisible()) { // Restored windows have a smaller top resize handle than the system // default. When maximized, the OS sizes the window such that the border // extends beyond the screen edges. In that case, we must return the @@ -641,7 +641,7 @@ // inset in order to avoid overlapping the monitor above. // See comments in BrowserDesktopWindowTreeHostWin::GetClientAreaInsets(). const bool needs_no_border = - (ShouldBrowserCustomDrawTitlebar(browser_view()) && + (ShouldBrowserCustomDrawTitlebar(GetBrowserView()) && browser_widget()->IsMaximized()) || browser_widget()->IsFullscreen(); if (needs_no_border && !restored) { @@ -681,11 +681,11 @@ // Adding 2 dip of vertical padding puts at least 1 dip of space on the top // and bottom of the element. constexpr int kVerticalPadding = 2; - if (!browser_view()->GetWebAppFrameToolbarPreferredSize().IsEmpty()) { - maximized_height = - std::max(maximized_height, - browser_view()->GetWebAppFrameToolbarPreferredSize().height() + - kVerticalPadding); + if (!GetBrowserView()->GetWebAppFrameToolbarPreferredSize().IsEmpty()) { + maximized_height = std::max( + maximized_height, + GetBrowserView()->GetWebAppFrameToolbarPreferredSize().height() + + kVerticalPadding); } return maximized_height; } @@ -705,10 +705,10 @@ } int BrowserFrameViewWin::GetFrameHeight() const { - if (browser_view()->GetTabStripVisible()) { + if (GetBrowserView()->GetTabStripVisible()) { // TODO(crbug.com/437915973): Account for the vertical tab region when using // GetMinimumSize(). - return browser_view()->tab_strip_view()->GetMinimumSize().height() - + return GetBrowserView()->tab_strip_view()->GetMinimumSize().height() - WindowTopY() - GetLayoutConstant(TABSTRIP_TOOLBAR_OVERLAP); } return IsMaximized() ? TitlebarMaximizedVisualHeight() @@ -734,7 +734,7 @@ } int total_width = caption_button_container_->size().width(); - if (!ShouldBrowserCustomDrawTitlebar(browser_view())) { + if (!ShouldBrowserCustomDrawTitlebar(GetBrowserView())) { if (!system_caption_buttons_width.has_value()) { system_caption_buttons_width = caption_button_metrics_->GetCaptionButtonWidth(); @@ -747,36 +747,36 @@ bool BrowserFrameViewWin::ShouldShowWindowIcon(TitlebarType type) const { if (type == TitlebarType::kCustom && - !ShouldBrowserCustomDrawTitlebar(browser_view())) { + !ShouldBrowserCustomDrawTitlebar(GetBrowserView())) { return false; } if (type == TitlebarType::kSystem && - ShouldBrowserCustomDrawTitlebar(browser_view())) { + ShouldBrowserCustomDrawTitlebar(GetBrowserView())) { return false; } if (browser_widget()->IsFullscreen()) { return false; } - return browser_view()->ShouldShowWindowIcon(); + return GetBrowserView()->ShouldShowWindowIcon(); } bool BrowserFrameViewWin::ShouldShowWindowTitle(TitlebarType type) const { if (type == TitlebarType::kCustom && - !ShouldBrowserCustomDrawTitlebar(browser_view())) { + !ShouldBrowserCustomDrawTitlebar(GetBrowserView())) { return false; } if (type == TitlebarType::kSystem && - ShouldBrowserCustomDrawTitlebar(browser_view())) { + ShouldBrowserCustomDrawTitlebar(GetBrowserView())) { return false; } if (browser_widget()->IsFullscreen()) { return false; } - return browser_view()->ShouldShowWindowTitle(); + return GetBrowserView()->ShouldShowWindowTitle(); } void BrowserFrameViewWin::TabletModeChanged() { - if (!ShouldBrowserCustomDrawTitlebar(browser_view())) { + if (!ShouldBrowserCustomDrawTitlebar(GetBrowserView())) { SetSystemMicaTitlebarAttributes(); } } @@ -791,8 +791,8 @@ sizeof(dark_titlebar_enabled)); const DWM_SYSTEMBACKDROP_TYPE dwm_backdrop_type = - browser_view()->GetTabStripVisible() ? DWMSBT_TABBEDWINDOW - : DWMSBT_MAINWINDOW; + GetBrowserView()->GetTabStripVisible() ? DWMSBT_TABBEDWINDOW + : DWMSBT_MAINWINDOW; DwmSetWindowAttribute(views::HWNDForWidget(browser_widget()), DWMWA_SYSTEMBACKDROP_TYPE, &dwm_backdrop_type, sizeof(dwm_backdrop_type)); @@ -843,9 +843,9 @@ // TODO(crbug.com/437915973): Account for the vertical tab region when using // GetMinimumSize(). const int titlebar_height = - browser_view()->GetTabStripVisible() + GetBrowserView()->GetTabStripVisible() ? GetBoundsForTabStripRegion( - browser_view()->tab_strip_view()->GetMinimumSize()) + GetBrowserView()->tab_strip_view()->GetMinimumSize()) .bottom() : TitlebarHeight(false); const gfx::Rect titlebar_rect = gfx::ToEnclosingRect( @@ -915,7 +915,7 @@ } if (show_title && window_title_) { - window_title_->SetText(browser_view()->GetWindowTitle()); + window_title_->SetText(GetBrowserView()->GetWindowTitle()); const int max_text_width = std::max(0, next_trailing_x - next_leading_x); LayoutWebAppWindowTitle( gfx::Rect(next_leading_x, window_icon_bounds.y(), max_text_width, @@ -933,12 +933,12 @@ caption_button_container_->GetPreferredSize(); const int system_caption_buttons_width = - ShouldBrowserCustomDrawTitlebar(browser_view()) + ShouldBrowserCustomDrawTitlebar(GetBrowserView()) ? 0 : caption_button_metrics_->GetCaptionButtonWidth(); const int height = - !browser_view()->GetWebAppFrameToolbarPreferredSize().IsEmpty() + !GetBrowserView()->GetWebAppFrameToolbarPreferredSize().IsEmpty() ? (TitlebarHeight(false) - WindowTopY()) : GetFrameHeight(); @@ -952,8 +952,8 @@ void BrowserFrameViewWin::LayoutClientView() { client_view_bounds_ = GetLocalBounds(); int top_inset = GetTopInset(false); - if (browser_view()->IsWindowControlsOverlayEnabled() || - !browser_view()->GetWebAppFrameToolbarPreferredSize().IsEmpty()) { + if (GetBrowserView()->IsWindowControlsOverlayEnabled() || + !GetBrowserView()->GetWebAppFrameToolbarPreferredSize().IsEmpty()) { top_inset = browser_widget()->IsFullscreen() ? 0 : WindowTopY(); } client_view_bounds_.Inset(gfx::Insets::TLBR(top_inset, 0, 0, 0)); @@ -982,7 +982,7 @@ HICON big_icon = nullptr; gfx::ImageSkia icon = - browser_view()->GetWindowIcon().Rasterize(GetColorProvider()); + GetBrowserView()->GetWindowIcon().Rasterize(GetColorProvider()); if (!icon.isNull()) { // Keep previous icons alive as long as they are referenced by the HWND.
diff --git a/chrome/browser/ui/views/frame/browser_root_view.cc b/chrome/browser/ui/views/frame/browser_root_view.cc index bb4b70a..e61a6ae 100644 --- a/chrome/browser/ui/views/frame/browser_root_view.cc +++ b/chrome/browser/ui/views/frame/browser_root_view.cc
@@ -599,7 +599,7 @@ // If the insertion point is off the end of the actual tab count, something // went wrong between when the drop was calculated and now. Bail. - if (drop_info->index->index > model->GetTabCount()) { + if (drop_info->index->index > model->count()) { return; }
diff --git a/chrome/browser/ui/views/frame/browser_view_focus_uitest.cc b/chrome/browser/ui/views/frame/browser_view_focus_uitest.cc index 8a2c2d9..920784d 100644 --- a/chrome/browser/ui/views/frame/browser_view_focus_uitest.cc +++ b/chrome/browser/ui/views/frame/browser_view_focus_uitest.cc
@@ -310,7 +310,7 @@ // Close the right tab, then create another split. browser()->tab_strip_model()->CloseWebContentsAt(1, TabCloseTypes::CLOSE_NONE); - ASSERT_EQ(1, browser()->tab_strip_model()->GetTabCount()); + ASSERT_EQ(1, browser()->tab_strip_model()->count()); ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url)); ASSERT_TRUE(AddTabAtIndex(1, url, ui::PAGE_TRANSITION_TYPED)); browser()->tab_strip_model()->AddToNewSplit(
diff --git a/chrome/browser/ui/views/frame/layout/browser_view_layout.h b/chrome/browser/ui/views/frame/layout/browser_view_layout.h index ad779b0..11d7765 100644 --- a/chrome/browser/ui/views/frame/layout/browser_view_layout.h +++ b/chrome/browser/ui/views/frame/layout/browser_view_layout.h
@@ -97,12 +97,6 @@ // for popups. static constexpr int kMainBrowserContentsMinimumWidth = 500; - // The width of the vertical tab strip. - // - // TODO(https://crbug.com/439961053): This shouldn't be hard-coded and should - // be reported by the vertical tabstrip itself. - static constexpr int kMinVerticalTabStripWidth = 240; - BrowserViewLayout(const BrowserViewLayout&) = delete; BrowserViewLayout& operator=(const BrowserViewLayout&) = delete;
diff --git a/chrome/browser/ui/views/frame/layout/browser_view_layout_impl_old.cc b/chrome/browser/ui/views/frame/layout/browser_view_layout_impl_old.cc index c2f3576..88870ae6 100644 --- a/chrome/browser/ui/views/frame/layout/browser_view_layout_impl_old.cc +++ b/chrome/browser/ui/views/frame/layout/browser_view_layout_impl_old.cc
@@ -31,6 +31,12 @@ namespace { +// The width of the vertical tab strip. +// +// TODO(https://crbug.com/439961053): This shouldn't be hard-coded and should +// be reported by the vertical tabstrip itself. +static constexpr int kMinVerticalTabStripWidth = 240; + // The number of pixels the constrained window should overlap the bottom // of the omnibox. const int kConstrainedWindowOverlap = 3;
diff --git a/chrome/browser/ui/views/frame/layout/browser_view_tabbed_layout_impl.cc b/chrome/browser/ui/views/frame/layout/browser_view_tabbed_layout_impl.cc index 558288b..0a04af3 100644 --- a/chrome/browser/ui/views/frame/layout/browser_view_tabbed_layout_impl.cc +++ b/chrome/browser/ui/views/frame/layout/browser_view_tabbed_layout_impl.cc
@@ -99,8 +99,8 @@ return std::make_pair(gfx::Size(), views().tab_strip_region_view->GetMinimumSize()); case TabStripType::kVertical: { - auto result = views().vertical_tab_strip_container->GetMinimumSize(); - result.set_width(std::max(result.width(), kMinVerticalTabStripWidth)); + const auto result = + views().vertical_tab_strip_container->GetMinimumSize(); return std::make_pair(result, gfx::Size()); } case TabStripType::kWebUi: @@ -263,19 +263,38 @@ views().browser_view)) { gfx::Rect vertical_tab_strip_bounds; if (tab_strip_type == TabStripType::kVertical) { - const int vertical_tab_strip_width = std::max( - kMinVerticalTabStripWidth, - views().vertical_tab_strip_container->GetPreferredSize().width()); + // TODO(https://crbug.com/466106626): Handle collapsed vertical tabstrip. + const int min_normal_vertical_tab_strip_width = base::ClampCeil( + params.leading_exclusion.ContentWithPadding().width()); + const int preferred_vertical_tab_strip_width = + views().vertical_tab_strip_container->GetPreferredSize().width(); vertical_tab_strip_bounds = gfx::Rect( params.visual_client_area.x(), params.visual_client_area.y(), - vertical_tab_strip_width, params.visual_client_area.height()); - params.Inset(gfx::Insets::TLBR(0, vertical_tab_strip_width, 0, 0)); + std::max(min_normal_vertical_tab_strip_width, + preferred_vertical_tab_strip_width), + params.visual_client_area.height()); + params.Inset( + gfx::Insets::TLBR(0, vertical_tab_strip_bounds.width(), 0, 0)); } layout.AddChild(views().vertical_tab_strip_container, vertical_tab_strip_bounds, tab_strip_type == TabStripType::kVertical); } + // When the tabstrip isn't at the top, the top container is laid out before + // all side panels. + if (tab_strip_type != TabStripType::kHorizontal && + IsParentedTo(views().top_container, views().browser_view)) { + auto& top_container_layout = + layout.AddChild(views().top_container, gfx::Rect()); + const gfx::Rect top_container_local_bounds = CalculateTopContainerLayout( + top_container_layout, + params.InLocalCoordinates(params.visual_client_area), needs_exclusion); + top_container_layout.bounds = + GetTopContainerBoundsInParent(top_container_local_bounds, params); + params.SetTop(top_container_layout.bounds.bottom()); + } + // Figure out whether the toolbar-height side panel should show and by how // much. const bool has_toolbar_height_side_panel = IsParentedToAndVisible( @@ -368,8 +387,10 @@ layout.AddChild(views().main_shadow_overlay, params.visual_client_area, show_shadow_overlay); - // Lay out top container. - if (IsParentedTo(views().top_container, views().browser_view)) { + // Lay out top container. The top container is laid out after the + // toolbar-height side panel with a horizontal tabstrip. + if (tab_strip_type == TabStripType::kHorizontal && + IsParentedTo(views().top_container, views().browser_view)) { auto& top_container_layout = layout.AddChild(views().top_container, gfx::Rect()); const gfx::Rect top_container_local_bounds = CalculateTopContainerLayout(
diff --git a/chrome/browser/ui/views/frame/opaque_browser_frame_view.cc b/chrome/browser/ui/views/frame/opaque_browser_frame_view.cc index aa0493a9..c389eac 100644 --- a/chrome/browser/ui/views/frame/opaque_browser_frame_view.cc +++ b/chrome/browser/ui/views/frame/opaque_browser_frame_view.cc
@@ -155,7 +155,7 @@ void OpaqueBrowserFrameView::InitViews() { web_app::AppBrowserController* controller = - browser_view()->browser()->app_controller(); + GetBrowserView()->browser()->app_controller(); if (controller && controller->IsWindowControlsOverlayEnabled()) { caption_button_placeholder_container_ = @@ -212,7 +212,7 @@ IDS_ACCNAME_CLOSE, VIEW_ID_CLOSE_BUTTON); // Initializing the TabIconView is expensive, so only do it if we need to. - if (browser_view()->ShouldShowWindowIcon()) { + if (GetBrowserView()->ShouldShowWindowIcon()) { AddChildView(views::Builder<TabIconView>() .CopyAddressTo(&window_icon_) .SetModel(this) @@ -229,8 +229,8 @@ // The window title appears above the web app frame toolbar (if present), // which surrounds the title with minimal-ui buttons on the left, // and other controls (such as the app menu button) on the right. - window_title_ = new views::Label(browser_view()->GetWindowTitle()); - window_title_->SetVisible(browser_view()->ShouldShowWindowTitle()); + window_title_ = new views::Label(GetBrowserView()->GetWindowTitle()); + window_title_->SetVisible(GetBrowserView()->ShouldShowWindowTitle()); window_title_->SetSubpixelRenderingEnabled(false); window_title_->SetHorizontalAlignment(gfx::ALIGN_LEFT); window_title_->SetID(VIEW_ID_WINDOW_TITLE); @@ -238,7 +238,7 @@ } #if BUILDFLAG(IS_WIN) - if (browser_view()->AppUsesWindowControlsOverlay()) { + if (GetBrowserView()->AppUsesWindowControlsOverlay()) { UpdateCaptionButtonToolTipsForWindowControlsOverlay(); } #endif @@ -305,7 +305,7 @@ } void OpaqueBrowserFrameView::WindowControlsOverlayEnabledChanged() { - bool enabled = browser_view()->IsWindowControlsOverlayEnabled(); + bool enabled = GetBrowserView()->IsWindowControlsOverlayEnabled(); if (enabled) { caption_button_placeholder_container_ = AddChildView(std::make_unique<CaptionButtonPlaceholderContainer>()); @@ -384,7 +384,7 @@ // The native window that encompasses Web Contents gets the mouse events meant // for the caption buttons, so returning HTClient allows these buttons to be // highlighted on hover. - if (browser_view()->IsWindowControlsOverlayEnabled() && + if (GetBrowserView()->IsWindowControlsOverlayEnabled() && (HitTestCaptionButton(minimize_button_, point) || HitTestCaptionButton(maximize_button_, point) || HitTestCaptionButton(restore_button_, point) || @@ -406,7 +406,7 @@ return HTMINBUTTON; } - if (browser_view()->IsWindowControlsOverlayEnabled() && + if (GetBrowserView()->IsWindowControlsOverlayEnabled() && caption_button_placeholder_container_ && caption_button_placeholder_container_->GetMirroredBounds().Contains( point)) { @@ -478,7 +478,7 @@ // This function is queried during the creation of the window as the // TabIconView we host is initialized, so we need to null check the selected // WebContents because in this condition there is not yet a selected tab. - WebContents* current_tab = browser_view()->GetActiveWebContents(); + WebContents* current_tab = GetBrowserView()->GetActiveWebContents(); return current_tab && current_tab->ShouldShowLoadingUI(); } @@ -498,7 +498,7 @@ views::WidgetDelegate* delegate = browser_widget()->widget_delegate(); return GetShowWindowTitleBar() && delegate && delegate->ShouldShowWindowIcon() && - !browser_view()->IsWindowControlsOverlayEnabled(); + !GetBrowserView()->IsWindowControlsOverlayEnabled(); } bool OpaqueBrowserFrameView::ShouldShowWindowTitle() const { @@ -527,7 +527,7 @@ } gfx::Size OpaqueBrowserFrameView::GetBrowserViewMinimumSize() const { - return browser_view() ? browser_view()->GetMinimumSize() : gfx::Size(); + return GetBrowserView() ? GetBrowserView()->GetMinimumSize() : gfx::Size(); } bool OpaqueBrowserFrameView::ShouldShowCaptionButtons() const { @@ -535,15 +535,15 @@ } bool OpaqueBrowserFrameView::IsRegularOrGuestSession() const { - return browser_view()->GetRegularOrGuestSession(); + return GetBrowserView()->GetRegularOrGuestSession(); } bool OpaqueBrowserFrameView::CanMaximize() const { - return browser_view()->CanMaximize(); + return GetBrowserView()->CanMaximize(); } bool OpaqueBrowserFrameView::CanMinimize() const { - return browser_view()->CanMinimize(); + return GetBrowserView()->CanMinimize(); } bool OpaqueBrowserFrameView::IsMaximized() const { @@ -559,41 +559,42 @@ } bool OpaqueBrowserFrameView::IsTabStripVisible() const { - return browser_view()->GetTabStripVisible(); + return GetBrowserView()->GetTabStripVisible(); } bool OpaqueBrowserFrameView::GetBorderlessModeEnabled() const { - return browser_view()->IsBorderlessModeEnabled(); + return GetBrowserView()->IsBorderlessModeEnabled(); } bool OpaqueBrowserFrameView::IsToolbarVisible() const { - return browser_view()->IsToolbarVisible() && - !browser_view()->toolbar()->GetPreferredSize().IsEmpty(); + return GetBrowserView()->IsToolbarVisible() && + !GetBrowserView()->toolbar()->GetPreferredSize().IsEmpty(); } int OpaqueBrowserFrameView::GetTabStripHeight() const { - return browser_view()->GetTabStripHeight(); + return GetBrowserView()->GetTabStripHeight(); } gfx::Size OpaqueBrowserFrameView::GetTabstripMinimumSize() const { - return browser_view()->tab_strip_view()->GetMinimumSize(); + return GetBrowserView()->tab_strip_view()->GetMinimumSize(); } int OpaqueBrowserFrameView::GetTopAreaHeight() const { int top_height = layout_->NonClientTopHeight(false); const gfx::Rect web_app_toolbar_bounds = GetBoundsForWebAppFrameToolbar( - browser_view()->GetWebAppFrameToolbarPreferredSize()); + GetBrowserView()->GetWebAppFrameToolbarPreferredSize()); + const bool should_draw_tabstrip = GetBrowserView()->ShouldDrawTabStrip(); if (!web_app_toolbar_bounds.IsEmpty()) { top_height = std::max({top_height, web_app_toolbar_bounds.bottom(), - layout_->FrameEdgeInsets(false).top() + - GetTabstripMinimumSize().height()}); - } else { - if (browser_view()->ShouldDrawTabStrip()) { - top_height = std::max( - top_height, - GetBoundsForTabStripRegion(GetTabstripMinimumSize()).bottom() - - GetLayoutConstant(TABSTRIP_TOOLBAR_OVERLAP)); + layout_->FrameEdgeInsets(false).top()}); + if (should_draw_tabstrip) { + top_height = std::max(top_height, GetTabstripMinimumSize().height()); } + } else if (should_draw_tabstrip) { + top_height = + std::max(top_height, + GetBoundsForTabStripRegion(GetTabstripMinimumSize()).bottom() - + GetLayoutConstant(TABSTRIP_TOOLBAR_OVERLAP)); } return top_height; } @@ -618,7 +619,7 @@ void OpaqueBrowserFrameView::UpdateWindowControlsOverlay( const gfx::Rect& bounding_rect) { - content::WebContents* web_contents = browser_view()->GetActiveWebContents(); + content::WebContents* web_contents = GetBrowserView()->GetActiveWebContents(); if (web_contents) { web_contents->UpdateWindowControlsOverlay(bounding_rect); } @@ -635,7 +636,7 @@ #endif int OpaqueBrowserFrameView::WebAppButtonHeight() const { - return browser_view()->GetWebAppFrameToolbarPreferredSize().height(); + return GetBrowserView()->GetWebAppFrameToolbarPreferredSize().height(); } /////////////////////////////////////////////////////////////////////////////// @@ -660,7 +661,7 @@ frame_background_->set_is_active(active); frame_background_->set_theme_image(GetFrameImage()); frame_background_->set_theme_image_inset( - browser_view()->GetThemeOffsetFromBrowserView()); + GetBrowserView()->GetThemeOffsetFromBrowserView()); frame_background_->set_theme_overlay_image(GetFrameOverlayImage()); frame_background_->set_top_area_height(GetTopAreaHeight()); @@ -692,7 +693,7 @@ // Custom tab bar mode draws the toolbar as a unified part of the titlebar, so // it shouldn't have a client edge. - if (!browser_view()->toolbar()->custom_tab_bar()) { + if (!GetBrowserView()->toolbar()->custom_tab_bar()) { PaintClientEdge(canvas); } } @@ -757,7 +758,7 @@ views::Button::STATE_PRESSED, ui::ImageModel::FromImageSkia(*tp->GetImageSkiaNamed(pushed_image_id))); button->SetFocusBehavior(FocusBehavior::ACCESSIBLE_ONLY); - if (browser_view()->GetIsNormalType()) { + if (GetBrowserView()->GetIsNormalType()) { // Get a custom processed version of the theme's background image so // that it appears to draw contiguously across all of the caption // buttons. @@ -866,7 +867,7 @@ menu_runner_ = std::make_unique<views::MenuRunner>( browser_widget()->GetSystemMenuModel(), views::MenuRunner::HAS_MNEMONICS); menu_runner_->RunMenuAt( - browser_view()->GetWidget(), window_icon_->button_controller(), + GetBrowserView()->GetWidget(), window_icon_->button_controller(), window_icon_->GetBoundsInScreen(), views::MenuAnchorPosition::kTopLeft, ui::mojom::MenuSourceType::kMouse); #endif @@ -917,7 +918,7 @@ } void OpaqueBrowserFrameView::PaintClientEdge(gfx::Canvas* canvas) const { - const bool tabstrip_visible = browser_view()->ShouldDrawTabStrip(); + const bool tabstrip_visible = GetBrowserView()->ShouldDrawTabStrip(); const gfx::Rect client_bounds = layout_->CalculateClientAreaBounds(width(), height()); @@ -935,7 +936,7 @@ static constexpr int kLocationBarBorderThickness = 1; const SkColor location_bar_border_color = GetColorProvider()->GetColor(kColorLocationBarBorderOpaque); - const int toolbar_height = browser_view()->toolbar()->height(); + const int toolbar_height = GetBrowserView()->toolbar()->height(); gfx::Rect side(client_bounds.x() - kLocationBarBorderThickness, client_bounds.y(), kLocationBarBorderThickness, @@ -957,7 +958,7 @@ #if BUILDFLAG(IS_WIN) void OpaqueBrowserFrameView:: UpdateCaptionButtonToolTipsForWindowControlsOverlay() { - if (browser_view()->IsWindowControlsOverlayEnabled()) { + if (GetBrowserView()->IsWindowControlsOverlayEnabled()) { minimize_button_->SetTooltipText( minimize_button_->GetViewAccessibility().GetCachedName()); maximize_button_->SetTooltipText(
diff --git a/chrome/browser/ui/views/frame/picture_in_picture_browser_frame_view.cc b/chrome/browser/ui/views/frame/picture_in_picture_browser_frame_view.cc index bd6e26bd..1f419206 100644 --- a/chrome/browser/ui/views/frame/picture_in_picture_browser_frame_view.cc +++ b/chrome/browser/ui/views/frame/picture_in_picture_browser_frame_view.cc
@@ -203,7 +203,7 @@ // some reason, then just manually close the window to prevent // getting into a state where the back to tab button no longer // closes the window. - frame_view.browser_view()->Close(); + frame_view.GetBrowserView()->Close(); } } @@ -759,7 +759,7 @@ #endif const std::optional<blink::mojom::PictureInPictureWindowOptions> pip_options = - browser_view()->GetDocumentPictureInPictureOptions(); + GetBrowserView()->GetDocumentPictureInPictureOptions(); // If the request includes pip options with an inner width and height, then we // need to recompute the outer size now that we can compute the correct @@ -803,7 +803,7 @@ GetMinimumSize() + gfx::Size(insets.width(), insets.height()), excluded_margin); - browser_view()->browser()->set_override_bounds(window_bounds); + GetBrowserView()->browser()->set_override_bounds(window_bounds); } gfx::Rect PictureInPictureBrowserFrameView::GetBoundsForClientView() const { @@ -919,7 +919,7 @@ widget_observation_.Observe(GetWidget()); window_event_observer_ = std::make_unique<WindowEventObserver>(this); child_dialog_observer_helper_ = - std::make_unique<ChildDialogObserverHelper>(this, browser_view()); + std::make_unique<ChildDialogObserverHelper>(this, GetBrowserView()); // Creates an animation container to ensure all the animations update at the // same time. @@ -1579,7 +1579,7 @@ } gfx::Size PictureInPictureBrowserFrameView::ComputeDialogPadding() const { - auto* host = browser_view()->GetWebContentsModalDialogHost(); + auto* host = GetBrowserView()->GetWebContentsModalDialogHost(); if (!host) { return gfx::Size(); }
diff --git a/chrome/browser/ui/views/frame/picture_in_picture_browser_frame_view_interactive_uitest.cc b/chrome/browser/ui/views/frame/picture_in_picture_browser_frame_view_interactive_uitest.cc index 946d1b9..9b149cd 100644 --- a/chrome/browser/ui/views/frame/picture_in_picture_browser_frame_view_interactive_uitest.cc +++ b/chrome/browser/ui/views/frame/picture_in_picture_browser_frame_view_interactive_uitest.cc
@@ -1077,10 +1077,12 @@ // The window title for the document picture-in-picture window should use the // title from the opener page. - EXPECT_EQ( - u"Document Picture-in-Picture", - pip_frame_view()->browser_view()->browser()->GetWindowTitleForCurrentTab( - /*include_app_name=*/false)); + EXPECT_EQ(u"Document Picture-in-Picture", + pip_frame_view() + ->GetBrowserView() + ->browser() + ->GetWindowTitleForCurrentTab( + /*include_app_name=*/false)); } #if BUILDFLAG(IS_LINUX) @@ -1551,7 +1553,7 @@ SetUpDocumentPIP({}, kPictureInPictureDocumentPipPage)); content::WebContents* pip_web_contents = pip_frame_view() - ->browser_view() + ->GetBrowserView() ->browser() ->tab_strip_model() ->GetActiveWebContents();
diff --git a/chrome/browser/ui/views/frame/picture_in_picture_browser_frame_view_linux.cc b/chrome/browser/ui/views/frame/picture_in_picture_browser_frame_view_linux.cc index cc73feba..e0791488 100644 --- a/chrome/browser/ui/views/frame/picture_in_picture_browser_frame_view_linux.cc +++ b/chrome/browser/ui/views/frame/picture_in_picture_browser_frame_view_linux.cc
@@ -134,7 +134,7 @@ frame_background_->set_theme_image(GetFrameImage()); frame_background_->set_theme_image_inset( - browser_view()->GetThemeOffsetFromBrowserView()); + GetBrowserView()->GetThemeOffsetFromBrowserView()); frame_background_->set_theme_overlay_image(GetFrameOverlayImage()); frame_background_->set_top_area_height(GetTopAreaHeight()); PaintRestoredFrameBorderLinux(
diff --git a/chrome/browser/ui/views/frame/vertical_tab_strip_region_view.cc b/chrome/browser/ui/views/frame/vertical_tab_strip_region_view.cc index 31f61db..3d8b6c4 100644 --- a/chrome/browser/ui/views/frame/vertical_tab_strip_region_view.cc +++ b/chrome/browser/ui/views/frame/vertical_tab_strip_region_view.cc
@@ -4,6 +4,8 @@ #include "chrome/browser/ui/views/frame/vertical_tab_strip_region_view.h" +#include <algorithm> + #include "base/callback_list.h" #include "base/functional/bind.h" #include "chrome/browser/ui/browser_actions.h" @@ -102,6 +104,21 @@ kResizeAreaWidth, bounds().height())); } +gfx::Size VerticalTabStripRegionView::CalculatePreferredSize( + const views::SizeBounds& available_size) const { + // TODO(https://crbug.com/439961053): Preferred size when not collapsed should + // be based on user preference, but hard-code for now. + constexpr int kNonCollapsedSize = 240; + + gfx::Size preferred_size = + AccessiblePaneView::CalculatePreferredSize(available_size); + if (!state_controller_->IsCollapsed()) { + preferred_size.set_width( + std::max(preferred_size.width(), kNonCollapsedSize)); + } + return preferred_size; +} + void VerticalTabStripRegionView::OnResize(int resize_amount, bool done_resizing) {}
diff --git a/chrome/browser/ui/views/frame/vertical_tab_strip_region_view.h b/chrome/browser/ui/views/frame/vertical_tab_strip_region_view.h index 289c0722..3f829147 100644 --- a/chrome/browser/ui/views/frame/vertical_tab_strip_region_view.h +++ b/chrome/browser/ui/views/frame/vertical_tab_strip_region_view.h
@@ -78,6 +78,8 @@ // views::View: void Layout(PassKey) override; + gfx::Size CalculatePreferredSize( + const views::SizeBounds& available_size) const override; // views::ResizeAreaDelegate: void OnResize(int resize_amount, bool done_resizing) override;
diff --git a/chrome/browser/ui/views/frame/windows_caption_button.cc b/chrome/browser/ui/views/frame/windows_caption_button.cc index d035e92a..a6bf2c0c 100644 --- a/chrome/browser/ui/views/frame/windows_caption_button.cc +++ b/chrome/browser/ui/views/frame/windows_caption_button.cc
@@ -58,11 +58,11 @@ // TODO(bsep): The sizes in this function are for 1x device scale and don't // match Windows button sizes at hidpi. int height = WindowFrameUtil::kWindowsCaptionButtonHeightRestored; - if (!frame_view_->browser_view()->webui_tab_strip() && + if (!frame_view_->GetBrowserView()->webui_tab_strip() && frame_view_->IsMaximized()) { int maximized_height = - frame_view_->browser_view()->ShouldDrawTabStrip() - ? frame_view_->browser_view()->GetTabStripHeight() + frame_view_->GetBrowserView()->ShouldDrawTabStrip() + ? frame_view_->GetBrowserView()->GetTabStripHeight() : frame_view_->TitlebarMaximizedVisualHeight(); constexpr int kMaximizedBottomMargin = 2; maximized_height -= kMaximizedBottomMargin;
diff --git a/chrome/browser/ui/views/overlay/video_overlay_window_views.cc b/chrome/browser/ui/views/overlay/video_overlay_window_views.cc index eb7e9f8..7202d7f1 100644 --- a/chrome/browser/ui/views/overlay/video_overlay_window_views.cc +++ b/chrome/browser/ui/views/overlay/video_overlay_window_views.cc
@@ -1518,7 +1518,17 @@ top_controls_bounds.bottom_left(), {bounds.width(), bounds.height() - (2 * top_controls_bounds.height())}); - title_view_->SetSize(bounds.size()); + // TODO(crbug.com/433972713): Set to default behavior once fix is confirmed. + if (base::FeatureList::IsEnabled( + media::kVideoPipDisplaySmoothnessOptimization)) { + title_view_->SetBoundsRect( + {top_controls_bounds.x(), top_controls_bounds.y(), + top_controls_bounds.width() - kOriginRightMargin, + kFaviconTopMargin + kFaviconSize.height()}); + } else { + title_view_->SetSize(bounds.size()); + } + playback_controls_container_view_->SetSize(bounds.size()); vc_controls_container_view_->SetSize(bounds.size()); controls_top_scrim_view_->SetBoundsRect(
diff --git a/chrome/browser/ui/views/performance_controls/memory_saver_bubble_view_unittest.cc b/chrome/browser/ui/views/performance_controls/memory_saver_bubble_view_unittest.cc index 4202aac..877105e 100644 --- a/chrome/browser/ui/views/performance_controls/memory_saver_bubble_view_unittest.cc +++ b/chrome/browser/ui/views/performance_controls/memory_saver_bubble_view_unittest.cc
@@ -163,7 +163,7 @@ TabStripModel* tab_strip_model = browser()->tab_strip_model(); content::WebContents* web_contents = browser()->tab_strip_model()->GetActiveWebContents(); - EXPECT_EQ(2, tab_strip_model->GetTabCount()); + EXPECT_EQ(2, tab_strip_model->count()); SetTabDiscardState(0, true); SetTabDiscardState(1, true);
diff --git a/chrome/browser/ui/views/performance_controls/memory_saver_chip_view_unittest.cc b/chrome/browser/ui/views/performance_controls/memory_saver_chip_view_unittest.cc index 76430a3..5225e90 100644 --- a/chrome/browser/ui/views/performance_controls/memory_saver_chip_view_unittest.cc +++ b/chrome/browser/ui/views/performance_controls/memory_saver_chip_view_unittest.cc
@@ -187,7 +187,7 @@ browser()->tab_strip_model()->GetWebContentsAt(0); content::WebContents* web_contents_1 = browser()->tab_strip_model()->GetWebContentsAt(1); - EXPECT_EQ(2, tab_strip_model->GetTabCount()); + EXPECT_EQ(2, tab_strip_model->count()); SetTabDiscardState(0, true); EXPECT_TRUE(GetPageActionView()->ShouldShowLabel());
diff --git a/chrome/browser/ui/views/performance_controls/memory_saver_interactive_ui_test.cc b/chrome/browser/ui/views/performance_controls/memory_saver_interactive_ui_test.cc index 68d8ffa2f..c9a215e 100644 --- a/chrome/browser/ui/views/performance_controls/memory_saver_interactive_ui_test.cc +++ b/chrome/browser/ui/views/performance_controls/memory_saver_interactive_ui_test.cc
@@ -675,7 +675,7 @@ PressButton(MemorySaverBubbleView::kMemorySaverDialogCancelButton), WaitForHide(MemorySaverBubbleView::kMemorySaverDialogBodyElementId), Check(base::BindLambdaForTesting( - [&]() { return browser()->tab_strip_model()->GetTabCount() == 3; })), + [&]() { return browser()->tab_strip_model()->count() == 3; })), InstrumentTab(kPerformanceSettingsTab, 2), WaitForWebContentsReady( kPerformanceSettingsTab,
diff --git a/chrome/browser/ui/views/side_panel/side_panel_animation_coordinator_browsertest.cc b/chrome/browser/ui/views/side_panel/side_panel_animation_coordinator_browsertest.cc index 178791b..b78935e 100644 --- a/chrome/browser/ui/views/side_panel/side_panel_animation_coordinator_browsertest.cc +++ b/chrome/browser/ui/views/side_panel/side_panel_animation_coordinator_browsertest.cc
@@ -65,7 +65,7 @@ }; IN_PROC_BROWSER_TEST_F(SidePanelAnimationCoordinatorBrowserTest, - AnimationProgressedWithMismatchedAnimationIds) { + AnimationEndsWithMismatchedAnimationTypes) { SidePanelAnimationCoordinator* animation_coordinator = GetAnimationCoordinator();
diff --git a/chrome/browser/ui/views/tabs/dragging/tab_drag_context.h b/chrome/browser/ui/views/tabs/dragging/tab_drag_context.h index c4e8352..2d3df8e 100644 --- a/chrome/browser/ui/views/tabs/dragging/tab_drag_context.h +++ b/chrome/browser/ui/views/tabs/dragging/tab_drag_context.h
@@ -77,8 +77,6 @@ virtual void OwnDragController( std::unique_ptr<TabDragController> controller) = 0; - virtual views::ScrollView* GetScrollView() = 0; - // Releases ownership of the current TabDragController. [[nodiscard]] virtual std::unique_ptr<TabDragController> ReleaseDragController() = 0;
diff --git a/chrome/browser/ui/views/tabs/dragging/test/mock_tab_drag_context.h b/chrome/browser/ui/views/tabs/dragging/test/mock_tab_drag_context.h index fa880acd..dc452e3 100644 --- a/chrome/browser/ui/views/tabs/dragging/test/mock_tab_drag_context.h +++ b/chrome/browser/ui/views/tabs/dragging/test/mock_tab_drag_context.h
@@ -42,7 +42,6 @@ OwnDragController, (std::unique_ptr<TabDragController> controller), (override)); - MOCK_METHOD(views::ScrollView*, GetScrollView, (), (override)); MOCK_METHOD(std::unique_ptr<TabDragController>, ReleaseDragController, (),
diff --git a/chrome/browser/ui/views/tabs/tab_search_container.cc b/chrome/browser/ui/views/tabs/tab_search_container.cc index 977ee9b8..99ea130 100644 --- a/chrome/browser/ui/views/tabs/tab_search_container.cc +++ b/chrome/browser/ui/views/tabs/tab_search_container.cc
@@ -560,7 +560,7 @@ DeclutterTriggerCTRBucket TabSearchContainer::GetDeclutterTriggerBucket( bool clicked) { const auto total_tab_count = - tab_declutter_controller_->tab_strip_model()->GetTabCount(); + tab_declutter_controller_->tab_strip_model()->count(); const auto stale_tab_count = tab_declutter_controller_->GetStaleTabs().size(); if (total_tab_count < 15) {
diff --git a/chrome/browser/ui/views/tabs/tab_strip.cc b/chrome/browser/ui/views/tabs/tab_strip.cc index aaf0fa8..94a11bc3 100644 --- a/chrome/browser/ui/views/tabs/tab_strip.cc +++ b/chrome/browser/ui/views/tabs/tab_strip.cc
@@ -803,10 +803,6 @@ } } - views::ScrollView* GetScrollView() override { - return views::ScrollView::GetScrollViewForContents(tab_strip_); - } - private: // Animates tabs after a drag has ended, then hands them back to // `tab_container_`.
diff --git a/chrome/browser/ui/views/tabs/tab_strip_action_container.cc b/chrome/browser/ui/views/tabs/tab_strip_action_container.cc index 60dce2dc..1017fcc9 100644 --- a/chrome/browser/ui/views/tabs/tab_strip_action_container.cc +++ b/chrome/browser/ui/views/tabs/tab_strip_action_container.cc
@@ -826,7 +826,7 @@ DeclutterTriggerCTRBucket TabStripActionContainer::GetDeclutterTriggerBucket( bool clicked) { const auto total_tab_count = - tab_declutter_controller_->tab_strip_model()->GetTabCount(); + tab_declutter_controller_->tab_strip_model()->count(); const auto stale_tab_count = tab_declutter_controller_->GetStaleTabs().size(); if (total_tab_count < 15) {
diff --git a/chrome/browser/ui/views/tabs/vertical/vertical_tab_strip_bottom_container_interactive_uitest.cc b/chrome/browser/ui/views/tabs/vertical/vertical_tab_strip_bottom_container_interactive_uitest.cc index 1e265dd..e15b76d1 100644 --- a/chrome/browser/ui/views/tabs/vertical/vertical_tab_strip_bottom_container_interactive_uitest.cc +++ b/chrome/browser/ui/views/tabs/vertical/vertical_tab_strip_bottom_container_interactive_uitest.cc
@@ -35,14 +35,14 @@ IN_PROC_BROWSER_TEST_F(VerticalTabStripBottomContainerInteractiveUiTest, VerifyNewTabButton) { RunTestSequence( - CheckResult( - [this]() { return browser()->tab_strip_model()->GetTabCount(); }, 1), + CheckResult([this]() { return browser()->tab_strip_model()->count(); }, + 1), WaitForShow(kVerticalTabStripBottomContainerElementId), EnsurePresent(kNewTabButtonElementId), PressButton(kNewTabButtonElementId, ui::test::InteractionTestUtil::InputType::kDontCare), - CheckResult( - [this]() { return browser()->tab_strip_model()->GetTabCount(); }, 2)); + CheckResult([this]() { return browser()->tab_strip_model()->count(); }, + 2)); } // This test checks that we can click the tab group button in the bottom @@ -50,8 +50,8 @@ IN_PROC_BROWSER_TEST_F(VerticalTabStripBottomContainerInteractiveUiTest, VerifyTabGroupButton) { RunTestSequence( - CheckResult( - [this]() { return browser()->tab_strip_model()->GetTabCount(); }, 1), + CheckResult([this]() { return browser()->tab_strip_model()->count(); }, + 1), WaitForShow(kVerticalTabStripBottomContainerElementId), EnsurePresent(kSavedTabGroupButtonElementId), PressButton(kSavedTabGroupButtonElementId, @@ -59,8 +59,8 @@ EnsurePresent(tab_groups::STGEverythingMenu::kCreateNewTabGroup), SelectMenuItem(tab_groups::STGEverythingMenu::kCreateNewTabGroup), WaitForShow(kTabGroupEditorBubbleId), - CheckResult( - [this]() { return browser()->tab_strip_model()->GetTabCount(); }, 2)); + CheckResult([this]() { return browser()->tab_strip_model()->count(); }, + 2)); } } // namespace base::test
diff --git a/chrome/browser/ui/views/tabs/vertical/vertical_tab_strip_controller_interactive_uitest.cc b/chrome/browser/ui/views/tabs/vertical/vertical_tab_strip_controller_interactive_uitest.cc index c9f7a90..dfbc9b8 100644 --- a/chrome/browser/ui/views/tabs/vertical/vertical_tab_strip_controller_interactive_uitest.cc +++ b/chrome/browser/ui/views/tabs/vertical/vertical_tab_strip_controller_interactive_uitest.cc
@@ -58,8 +58,8 @@ WaitForShow(TabMenuModel::kAddNewTabAdjacentMenuItem), SelectMenuItem(TabMenuModel::kAddNewTabAdjacentMenuItem)), // Verify functionality of command in the Tab Context Menu. - CheckResult( - [this]() { return browser()->tab_strip_model()->GetTabCount(); }, 2)); + CheckResult([this]() { return browser()->tab_strip_model()->count(); }, + 2)); } IN_PROC_BROWSER_TEST_F(VerticalTabStripControllerInteractiveUiTest,
diff --git a/chrome/browser/ui/views/user_education/ios_promo_bubble_view.cc b/chrome/browser/ui/views/user_education/ios_promo_bubble_view.cc index be3888c0..88e8bf5 100644 --- a/chrome/browser/ui/views/user_education/ios_promo_bubble_view.cc +++ b/chrome/browser/ui/views/user_education/ios_promo_bubble_view.cc
@@ -16,6 +16,7 @@ #include "chrome/browser/ui/views/user_education/impl/browser_user_education_context.h" #include "chrome/grit/generated_resources.h" #include "chrome/grit/theme_resources.h" +#include "components/desktop_to_mobile_promos/desktop_to_mobile_promos_metrics.h" #include "components/desktop_to_mobile_promos/promos_types.h" #include "components/sync_device_info/device_info.h" #include "components/user_education/views/help_bubble_views.h" @@ -38,6 +39,10 @@ #include "ui/views/view.h" #include "url/gurl.h" +using desktop_to_mobile_promos::DesktopPromoActionType; +using desktop_to_mobile_promos::DesktopPromoBubbleType; +using desktop_to_mobile_promos::LogDesktopPromoAction; +using desktop_to_mobile_promos::LogDesktopPromoBubbleCreated; using user_education::CustomHelpBubbleUi; namespace { @@ -127,6 +132,7 @@ BubbleType promo_bubble_type = (service && service->GetIOSDeviceToRemind()) ? BubbleType::kReminder : BubbleType::kQRCode; + auto* const anchor_element = params.anchor_element.get(); return std::make_unique<IOSPromoBubbleView>( profile, promo_type, promo_bubble_type, @@ -166,6 +172,8 @@ SetButtonStyle(ui::mojom::DialogButton::kCancel, ui::ButtonStyle::kDefault); SetCloseCallback( base::BindOnce(&IOSPromoBubbleView::OnDismissal, base::Unretained(this))); + + LogDesktopPromoBubbleCreated(promo_type_, promo_bubble_type_); } IOSPromoBubbleView::~IOSPromoBubbleView() = default; @@ -189,12 +197,17 @@ } bool IOSPromoBubbleView::Cancel() { + LogDesktopPromoAction(promo_type_, promo_bubble_type_, + DesktopPromoActionType::kCancel); + NotifyUserAction(CustomHelpBubbleUi::UserAction::kCancel); return true; } bool IOSPromoBubbleView::Accept() { - // TODO(crbug.com/438769954): Record metrics. + LogDesktopPromoAction(promo_type_, promo_bubble_type_, + DesktopPromoActionType::kAccept); + switch (promo_bubble_type_) { case BubbleType::kReminder: { // Send the reminder to the iOS device and update the promo bubble with @@ -205,6 +218,7 @@ if (!ios_device_info_) { return true; } + trigger_service->SetReminderForIOSDevice(promo_type_, ios_device_info_->guid()); promo_bubble_type_ = BubbleType::kReminderConfirmation; @@ -247,6 +261,9 @@ set_fixed_width(views::LayoutProvider::Get()->GetDistanceMetric(metric)); } void IOSPromoBubbleView::OnDismissal() { + LogDesktopPromoAction(promo_type_, promo_bubble_type_, + DesktopPromoActionType::kDismiss); + NotifyUserAction(CustomHelpBubbleUi::UserAction::kDismiss); } @@ -293,6 +310,8 @@ SetCloseCallback( base::BindOnce(&IOSPromoBubbleView::OnDismissal, base::Unretained(this))); + LogDesktopPromoBubbleCreated(promo_type_, promo_bubble_type_); + // Trigger a resize and layout pass. GetWidget()->UpdateWindowTitle(); SizeToContents();
diff --git a/chrome/browser/ui/views/user_education/ios_promo_bubble_view_unittest.cc b/chrome/browser/ui/views/user_education/ios_promo_bubble_view_unittest.cc index 973d21c..f135e63e 100644 --- a/chrome/browser/ui/views/user_education/ios_promo_bubble_view_unittest.cc +++ b/chrome/browser/ui/views/user_education/ios_promo_bubble_view_unittest.cc
@@ -8,6 +8,7 @@ #include "base/containers/contains.h" #include "base/memory/weak_ptr.h" +#include "base/test/metrics/histogram_tester.h" #include "base/test/mock_callback.h" #include "base/test/scoped_feature_list.h" #include "chrome/browser/profiles/profile.h" @@ -15,6 +16,7 @@ #include "chrome/browser/ui/promos/ios_promo_trigger_service_factory.h" #include "chrome/test/base/testing_profile.h" #include "chrome/test/views/chrome_views_test_base.h" +#include "components/desktop_to_mobile_promos/desktop_to_mobile_promos_metrics.h" #include "components/desktop_to_mobile_promos/features.h" #include "components/desktop_to_mobile_promos/promos_types.h" #include "components/sync/protocol/sync_enums.pb.h" @@ -125,6 +127,9 @@ Profile* GetProfile() { return profile_.get(); } + // Getter for the histograms tester. + base::HistogramTester* histograms() { return &histogram_; } + protected: void CreateAndShowBubble(PromoType promo_type = PromoType::kLens, BubbleType bubble_type = BubbleType::kQRCode) { @@ -142,6 +147,7 @@ widget->Show(); } + base::HistogramTester histogram_; base::test::ScopedFeatureList scoped_feature_list_; std::unique_ptr<TestingProfile> profile_; raw_ptr<views::View> anchor_view_; @@ -166,6 +172,10 @@ bubble_view_ = nullptr; bubble_widget_->Close(); run_loop.Run(); + + histograms()->ExpectUniqueSample( + "UserEducation.DesktopToIOSPromo.Lens.QRCode.Action", + desktop_to_mobile_promos::DesktopPromoActionType::kDismiss, 1); } // Tests that clicking the Cancel button calls NotifyUserAction with kCancel. @@ -177,6 +187,10 @@ bubble_view_->Cancel(); + histograms()->ExpectUniqueSample( + "UserEducation.DesktopToIOSPromo.Lens.QRCode.Action", + desktop_to_mobile_promos::DesktopPromoActionType::kCancel, 1); + bubble_view_ = nullptr; bubble_widget_->CloseNow(); } @@ -201,6 +215,10 @@ CreateAndShowBubble(PromoType::kLens, BubbleType::kReminder); + histograms()->ExpectBucketCount( + "UserEducation.DesktopToIOSPromo.Lens.BubbleView.Created", + desktop_to_mobile_promos::DesktopPromoBubbleType::kReminder, 1); + // The bubble should be dismissed after the second accept. base::RunLoop run_loop; EXPECT_CALL(user_action_callback_, @@ -212,10 +230,23 @@ EXPECT_FALSE(bubble_view_->Accept()); EXPECT_FALSE(bubble_widget_->IsClosed()); + histograms()->ExpectUniqueSample( + "UserEducation.DesktopToIOSPromo.Lens.Reminder.Action", + desktop_to_mobile_promos::DesktopPromoActionType::kAccept, 1); + + histograms()->ExpectBucketCount( + "UserEducation.DesktopToIOSPromo.Lens.BubbleView.Created", + desktop_to_mobile_promos::DesktopPromoBubbleType::kReminderConfirmation, + 1); + // Click Accept (Second time - "Got it"). Now it should be in // kReminderConfirmation state. Expect it to return true (close bubble). EXPECT_TRUE(bubble_view_->Accept()); + histograms()->ExpectUniqueSample( + "UserEducation.DesktopToIOSPromo.Lens.ReminderConfirmation.Action", + desktop_to_mobile_promos::DesktopPromoActionType::kAccept, 1); + // Close triggers dismissal. bubble_view_ = nullptr; bubble_widget_->Close(); @@ -227,6 +258,10 @@ TEST_F(IOSPromoBubbleViewTest, AcceptOpensUrl_QRCode) { CreateAndShowBubble(PromoType::kLens, BubbleType::kQRCode); + histograms()->ExpectUniqueSample( + "UserEducation.DesktopToIOSPromo.Lens.BubbleView.Created", + desktop_to_mobile_promos::DesktopPromoBubbleType::kQRCode, 1); + base::MockCallback<IOSPromoBubbleView::OpenUrlCallback> mock_callback; bubble_view_->SetOpenUrlCallbackForTesting(mock_callback.Get()); @@ -243,6 +278,10 @@ // Click Accept. Expect it to return true (close bubble). EXPECT_TRUE(bubble_view_->Accept()); + histograms()->ExpectUniqueSample( + "UserEducation.DesktopToIOSPromo.Lens.QRCode.Action", + desktop_to_mobile_promos::DesktopPromoActionType::kAccept, 1); + // Expect dismissal on close. base::RunLoop run_loop; EXPECT_CALL(user_action_callback_,
diff --git a/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.cc b/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.cc index a0888e7..2c25748 100644 --- a/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.cc +++ b/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.cc
@@ -587,7 +587,7 @@ [&app_id, &result](BrowserWindowInterface* browser) { const TabStripModel* const tab_strip_model = browser->GetTabStripModel(); - for (int i = 0; i < tab_strip_model->GetTabCount(); i++) { + for (int i = 0; i < tab_strip_model->count(); i++) { content::WebContents* const web_contents = tab_strip_model->GetWebContentsAt(i); const webapps::AppId* const web_contents_id = @@ -3283,7 +3283,7 @@ site](BrowserWindowInterface* browser) { const TabStripModel* const tab_strip_model = browser->GetTabStripModel(); - for (int i = 0; i < tab_strip_model->GetTabCount(); i++) { + for (int i = 0; i < tab_strip_model->count(); i++) { auto site_config = GetSiteConfiguration(site); content::WebContents* const web_contents = tab_strip_model->GetWebContentsAt(i); @@ -3939,7 +3939,7 @@ const TabStripModel* const tab_strip_model = browser->GetTabStripModel(); - for (int i = 0; i < tab_strip_model->GetTabCount(); i++) { + for (int i = 0; i < tab_strip_model->count(); i++) { const webapps::AppId* app_id = WebAppTabHelper::GetAppId(tab_strip_model->GetWebContentsAt(i)); if (app_id && *app_id == GetAppIdBySiteMode(site)) { @@ -3969,7 +3969,7 @@ const TabStripModel* const tab_strip_model = browser->GetTabStripModel(); - for (int i = 0; i < tab_strip_model->GetTabCount(); i++) { + for (int i = 0; i < tab_strip_model->count(); i++) { const GURL committed_url = tab_strip_model->GetWebContentsAt(i)->GetLastCommittedURL(); found_urls.push_back(committed_url.possibly_invalid_spec());
diff --git a/chrome/browser/ui/web_applications/web_app_engagement_browsertest.cc b/chrome/browser/ui/web_applications/web_app_engagement_browsertest.cc index 7a78321..4aff4ce0 100644 --- a/chrome/browser/ui/web_applications/web_app_engagement_browsertest.cc +++ b/chrome/browser/ui/web_applications/web_app_engagement_browsertest.cc
@@ -483,13 +483,8 @@ /*tabLaunches=*/0); } -// TODO(crbug.com/40884336): Flaky on Mac. -#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_CHROMEOS) -#define MAYBE_DefaultApp DISABLED_DefaultApp -#else -#define MAYBE_DefaultApp DefaultApp -#endif -IN_PROC_BROWSER_TEST_F(WebAppEngagementBrowserTest, MAYBE_DefaultApp) { +// TODO(crbug.com/40884336): Flaky on all platforms. +IN_PROC_BROWSER_TEST_F(WebAppEngagementBrowserTest, DISABLED_DefaultApp) { base::HistogramTester tester; ASSERT_TRUE(embedded_test_server()->Start());
diff --git a/chrome/browser/ui/webui/cr_components/searchbox/contextual_searchbox_handler.cc b/chrome/browser/ui/webui/cr_components/searchbox/contextual_searchbox_handler.cc index f6a176a..585e4b7 100644 --- a/chrome/browser/ui/webui/cr_components/searchbox/contextual_searchbox_handler.cc +++ b/chrome/browser/ui/webui/cr_components/searchbox/contextual_searchbox_handler.cc
@@ -329,6 +329,18 @@ return {}; } +void ContextualSearchboxHandler::UploadSnapshotTabContextIfPresent() { + if (!tab_context_snapshot_.has_value()) { + return; + } + + auto [context_token, page_content_data] = + std::move(tab_context_snapshot_.value()); + tab_context_snapshot_.reset(); + + UploadTabContext(context_token, std::move(page_content_data)); +} + void ContextualSearchboxHandler::OnAddTabContextTokenCreated( int32_t tab_id, bool delay_upload, @@ -586,18 +598,6 @@ } } -void ContextualSearchboxHandler::UploadSnapshotTabContextIfPresent() { - if (!tab_context_snapshot_.has_value()) { - return; - } - - auto [context_token, page_content_data] = - std::move(tab_context_snapshot_.value()); - tab_context_snapshot_.reset(); - - UploadTabContext(context_token, std::move(page_content_data)); -} - void ContextualSearchboxHandler::OpenUrl( GURL url, const WindowOpenDisposition disposition) {
diff --git a/chrome/browser/ui/webui/cr_components/searchbox/contextual_searchbox_handler.h b/chrome/browser/ui/webui/cr_components/searchbox/contextual_searchbox_handler.h index ac3366ca..197d5291 100644 --- a/chrome/browser/ui/webui/cr_components/searchbox/contextual_searchbox_handler.h +++ b/chrome/browser/ui/webui/cr_components/searchbox/contextual_searchbox_handler.h
@@ -149,6 +149,10 @@ std::vector<base::UnguessableToken> GetUploadedContextTokens(); + protected: + // Helper function that uploads the cached tab context if it exists. + void UploadSnapshotTabContextIfPresent(); + private: void OnAddTabContextTokenCreated(int32_t tab_id, bool delay_upload, @@ -171,9 +175,6 @@ const base::UnguessableToken& context_token, std::unique_ptr<lens::ContextualInputData> page_content_data); - // Helper function that uploads the cached tab context if it exists. - void UploadSnapshotTabContextIfPresent(); - void OpenUrl(GURL url, const WindowOpenDisposition disposition); void OnPreviewReceived(GetTabPreviewCallback callback,
diff --git a/chrome/browser/ui/webui/extensions_zero_state_promo/extensions_zero_state_promo_interactive_uitest.cc b/chrome/browser/ui/webui/extensions_zero_state_promo/extensions_zero_state_promo_interactive_uitest.cc index 37d41806..2635a6f 100644 --- a/chrome/browser/ui/webui/extensions_zero_state_promo/extensions_zero_state_promo_interactive_uitest.cc +++ b/chrome/browser/ui/webui/extensions_zero_state_promo/extensions_zero_state_promo_interactive_uitest.cc
@@ -259,9 +259,8 @@ ClickElement(kZeroStatePromoWebUiIphId, kDismissButton, ExecuteJsMode::kFireAndForget), WaitForHide(CustomWebUIHelpBubble::kWebViewIdForTesting), - CheckResult( - [this] { return browser()->tab_strip_model()->GetTabCount(); }, 1, - "CheckTabCount"), + CheckResult([this] { return browser()->tab_strip_model()->count(); }, 1, + "CheckTabCount"), CheckZeroStatePromoClosedReason( user_education::FeaturePromoClosedReason::kDismiss)); } @@ -418,9 +417,8 @@ ClickElement(kZeroStatePromoWebUiIphId, kDismissButton, ExecuteJsMode::kFireAndForget), WaitForHide(CustomWebUIHelpBubble::kWebViewIdForTesting), - CheckResult( - [this] { return browser()->tab_strip_model()->GetTabCount(); }, 1, - "CheckTabCount"), + CheckResult([this] { return browser()->tab_strip_model()->count(); }, 1, + "CheckTabCount"), CheckZeroStatePromoClosedReason( user_education::FeaturePromoClosedReason::kDismiss)); } @@ -577,9 +575,8 @@ ClickElement(kZeroStatePromoWebUiIphId, kDismissButton, ExecuteJsMode::kFireAndForget), WaitForHide(CustomWebUIHelpBubble::kWebViewIdForTesting), - CheckResult( - [this] { return browser()->tab_strip_model()->GetTabCount(); }, 1, - "CheckTabCount"), + CheckResult([this] { return browser()->tab_strip_model()->count(); }, 1, + "CheckTabCount"), CheckZeroStatePromoClosedReason( user_education::FeaturePromoClosedReason::kDismiss)); } @@ -759,9 +756,8 @@ ClickElement(kZeroStatePromoWebUiIphId, kDismissButton, ExecuteJsMode::kFireAndForget), WaitForHide(CustomWebUIHelpBubble::kWebViewIdForTesting), - CheckResult( - [this] { return browser()->tab_strip_model()->GetTabCount(); }, 1, - "CheckTabCount"), + CheckResult([this] { return browser()->tab_strip_model()->count(); }, 1, + "CheckTabCount"), CheckZeroStatePromoClosedReason( user_education::FeaturePromoClosedReason::kDismiss)); } @@ -781,9 +777,8 @@ ClickElement(kZeroStatePromoWebUiIphId, kGotItButton, ExecuteJsMode::kFireAndForget), WaitForHide(CustomWebUIHelpBubble::kWebViewIdForTesting), - CheckResult( - [this] { return browser()->tab_strip_model()->GetTabCount(); }, 1, - "CheckTabCount"), + CheckResult([this] { return browser()->tab_strip_model()->count(); }, 1, + "CheckTabCount"), CheckZeroStatePromoClosedReason( user_education::FeaturePromoClosedReason::kDismiss)); }
diff --git a/chrome/browser/ui/webui/history_clusters/history_clusters_handler_browsertest.cc b/chrome/browser/ui/webui/history_clusters/history_clusters_handler_browsertest.cc index 4791cd6..bc6d06d 100644 --- a/chrome/browser/ui/webui/history_clusters/history_clusters_handler_browsertest.cc +++ b/chrome/browser/ui/webui/history_clusters/history_clusters_handler_browsertest.cc
@@ -92,7 +92,7 @@ IN_PROC_BROWSER_TEST_F(HistoryClustersHandlerBrowserTest, OpenVisitUrlsInTabGroup) { auto* tab_strip_model = browser()->tab_strip_model(); - ASSERT_EQ(1, tab_strip_model->GetTabCount()); + ASSERT_EQ(1, tab_strip_model->count()); std::vector<mojom::URLVisitPtr> visits; auto visit1 = mojom::URLVisit::New(); @@ -103,7 +103,7 @@ visits.push_back(std::move(visit2)); handler_->OpenVisitUrlsInTabGroup(std::move(visits), std::nullopt); - ASSERT_EQ(3, tab_strip_model->GetTabCount()); + ASSERT_EQ(3, tab_strip_model->count()); ASSERT_EQ(tab_strip_model->GetTabGroupForTab(1).value(), tab_strip_model->GetTabGroupForTab(2).value()); @@ -118,7 +118,7 @@ IN_PROC_BROWSER_TEST_F(HistoryClustersHandlerBrowserTest, DISABLED_OpenVisitUrlsInTabGroupHardCap) { auto* tab_strip_model = browser()->tab_strip_model(); - ASSERT_EQ(1, tab_strip_model->GetTabCount()); + ASSERT_EQ(1, tab_strip_model->count()); std::vector<mojom::URLVisitPtr> visits; for (size_t i = 0; i < 50; ++i) { @@ -129,13 +129,13 @@ // Verify that we open 32 at maximum. Including the NTP, that's 33 total. handler_->OpenVisitUrlsInTabGroup(std::move(visits), std::nullopt); - ASSERT_EQ(33, tab_strip_model->GetTabCount()); + ASSERT_EQ(33, tab_strip_model->count()); } IN_PROC_BROWSER_TEST_F(HistoryClustersHandlerBrowserTest, RecordUIVisitActions) { auto* tab_strip_model = browser()->tab_strip_model(); - ASSERT_EQ(1, tab_strip_model->GetTabCount()); + ASSERT_EQ(1, tab_strip_model->count()); base::HistogramTester histogram_tester; @@ -170,7 +170,7 @@ IN_PROC_BROWSER_TEST_F(HistoryClustersHandlerBrowserTest, RecordUIClusterActions) { auto* tab_strip_model = browser()->tab_strip_model(); - ASSERT_EQ(1, tab_strip_model->GetTabCount()); + ASSERT_EQ(1, tab_strip_model->count()); base::HistogramTester histogram_tester; @@ -195,7 +195,7 @@ IN_PROC_BROWSER_TEST_F(HistoryClustersHandlerBrowserTest, RecordUIRelatedSearchActions) { auto* tab_strip_model = browser()->tab_strip_model(); - ASSERT_EQ(1, tab_strip_model->GetTabCount()); + ASSERT_EQ(1, tab_strip_model->count()); base::HistogramTester histogram_tester; @@ -217,7 +217,7 @@ IN_PROC_BROWSER_TEST_F(HistoryClustersHandlerBrowserTest, RecordUnsuccessfulOutcome) { auto* tab_strip_model = browser()->tab_strip_model(); - ASSERT_EQ(1, tab_strip_model->GetTabCount()); + ASSERT_EQ(1, tab_strip_model->count()); base::HistogramTester histogram_tester;
diff --git a/chrome/browser/ui/webui/settings/saved_info_handler.cc b/chrome/browser/ui/webui/settings/saved_info_handler.cc index 5fc2a00..b6d93f7b 100644 --- a/chrome/browser/ui/webui/settings/saved_info_handler.cc +++ b/chrome/browser/ui/webui/settings/saved_info_handler.cc
@@ -100,12 +100,16 @@ base::Value::Dict dict; auto* passwords_presenter = password_observation_.GetSource(); if (passwords_presenter) { - size_t password_count = passwords_presenter->GetSavedPasswords().size(); + const size_t password_count = passwords_presenter->GetSavedPasswords().size(); dict.Set("passwordCount", static_cast<int>(password_count)); } auto* passkey_model = passkey_observation_.GetSource(); if (passkey_model) { - size_t passkey_count = passkey_model->GetAllPasskeys().size(); + const size_t passkey_count = + passkey_model + ->GetPasskeys(webauthn::PasskeyModel::AnyRp(), + webauthn::PasskeyModel::ShadowedCredentials::kInclude) + .size(); dict.Set("passkeyCount", static_cast<int>(passkey_count)); } return dict;
diff --git a/chrome/browser/ui/webui/side_panel/read_anything/read_anything_untrusted_ui.cc b/chrome/browser/ui/webui/side_panel/read_anything/read_anything_untrusted_ui.cc index 8443062..95cc642 100644 --- a/chrome/browser/ui/webui/side_panel/read_anything/read_anything_untrusted_ui.cc +++ b/chrome/browser/ui/webui/side_panel/read_anything/read_anything_untrusted_ui.cc
@@ -103,6 +103,7 @@ IDS_READING_MODE_DECREASE_FONT_SIZE_ANNOUNCEMENT}, {"disableLinksLabel", IDS_READING_MODE_DISABLE_LINKS_BUTTON_LABEL}, {"enableLinksLabel", IDS_READING_MODE_ENABLE_LINKS_BUTTON_LABEL}, + {"imagesLabel", IDS_READING_MODE_IMAGES_LABEL}, {"disableImagesLabel", IDS_READING_MODE_DISABLE_IMAGES_BUTTON_LABEL}, {"enableImagesLabel", IDS_READING_MODE_ENABLE_IMAGES_BUTTON_LABEL}, {"readingModeToolbarLabel", IDS_READING_MODE_TOOLBAR_LABEL}, @@ -150,6 +151,9 @@ {"languageMenuDownloadFailed", IDS_READING_MODE_LANGUAGE_MENU_DOWNLOAD_FAILED}, {"cantUseReadAloud", IDS_READING_MODE_CANT_USE_READ_ALOUD}, + {"lineFocusLabel", IDS_READING_MODE_LINE_FOCUS_LABEL}, + {"viewInSidePanelLabel", IDS_READING_MODE_VIEW_IN_SIDE_PANEL_LABEL}, + {"viewInFullScreenLabel", IDS_READING_MODE_VIEW_IN_FULL_SCREEN_LABEL}, }; for (const auto& str : kLocalizedStrings) { webui::AddLocalizedString(source, str.name, str.id);
diff --git a/chrome/browser/ui/webui/tab_search/tab_search_page_handler_unittest.cc b/chrome/browser/ui/webui/tab_search/tab_search_page_handler_unittest.cc index 0ed84e9..e85dcd1 100644 --- a/chrome/browser/ui/webui/tab_search/tab_search_page_handler_unittest.cc +++ b/chrome/browser/ui/webui/tab_search/tab_search_page_handler_unittest.cc
@@ -1285,17 +1285,16 @@ CloseTab(4); EXPECT_EQ(handler()->stale_tabs_for_testing().size(), 6u); - fake_tab_strip_model()->AddToNewGroup( - {fake_tab_strip_model()->GetTabCount() - 1}); + fake_tab_strip_model()->AddToNewGroup({fake_tab_strip_model()->count() - 1}); EXPECT_EQ(handler()->duplicate_tabs_for_testing()[duplicate_tabs_url].size(), 4u); - fake_tab_strip_model()->SetTabPinned( - fake_tab_strip_model()->GetTabCount() - 2, true); + fake_tab_strip_model()->SetTabPinned(fake_tab_strip_model()->count() - 2, + true); EXPECT_EQ(handler()->duplicate_tabs_for_testing()[duplicate_tabs_url].size(), 3u); - CloseTab(fake_tab_strip_model()->GetTabCount() - 2); + CloseTab(fake_tab_strip_model()->count() - 2); EXPECT_EQ(handler()->duplicate_tabs_for_testing()[duplicate_tabs_url].size(), 2u); } @@ -1347,17 +1346,16 @@ auto navigation_simulator = content::NavigationSimulator::CreateBrowserInitiated( - new_url, - fake_tab_strip_model() - ->GetTabAtIndex(fake_tab_strip_model()->GetTabCount() - 1) - ->GetContents()); + new_url, fake_tab_strip_model() + ->GetTabAtIndex(fake_tab_strip_model()->count() - 1) + ->GetContents()); navigation_simulator->Commit(); EXPECT_EQ(handler()->duplicate_tabs_for_testing()[duplicate_tabs_url].size(), 4u); fake_tab_strip_model()->DiscardWebContentsAt( - fake_tab_strip_model()->GetTabCount() - 2, + fake_tab_strip_model()->count() - 2, content::WebContents::Create( content::WebContents::CreateParams(testing_profile()))); EXPECT_EQ(handler()->duplicate_tabs_for_testing()[duplicate_tabs_url].size(),
diff --git a/chrome/browser/ui/webui/tab_search/tab_search_ui_browsertest.cc b/chrome/browser/ui/webui/tab_search/tab_search_ui_browsertest.cc index beca7c6..1290b83 100644 --- a/chrome/browser/ui/webui/tab_search/tab_search_ui_browsertest.cc +++ b/chrome/browser/ui/webui/tab_search/tab_search_ui_browsertest.cc
@@ -100,7 +100,7 @@ // Flaky - see https://crbug.com/40932977 IN_PROC_BROWSER_TEST_F(TabSearchUIBrowserTest, DISABLED_SwitchToTabAction) { - int tab_count = browser()->tab_strip_model()->GetTabCount(); + int tab_count = browser()->tab_strip_model()->count(); tabs::TabHandle tab_id = browser()->tab_strip_model()->GetTabAtIndex(tab_count - 1)->GetHandle(); ASSERT_EQ(tab_id, GetActiveTab()->GetHandle()); @@ -121,7 +121,7 @@ // TODO(https://crbug.com/401303184): Disabled due to excessive flakiness. IN_PROC_BROWSER_TEST_F(TabSearchUIBrowserTest, DISABLED_CloseTabAction) { - ASSERT_EQ(4, browser()->tab_strip_model()->GetTabCount()); + ASSERT_EQ(4, browser()->tab_strip_model()->count()); tabs::TabHandle tab_id = browser()->tab_strip_model()->GetTabAtIndex(0)->GetHandle(); @@ -137,7 +137,7 @@ tab_item_button_js + ".click()", content::EXECUTE_SCRIPT_DEFAULT_OPTIONS, ISOLATED_WORLD_ID_CHROME_INTERNAL)); - int tab_count = browser()->tab_strip_model()->GetTabCount(); + int tab_count = browser()->tab_strip_model()->count(); ASSERT_EQ(3, tab_count); std::vector<tabs::TabHandle> open_tab_ids(tab_count); @@ -155,7 +155,7 @@ CloseTabSearchAsBrowserTabDoesNotCrash) { AppendTab(chrome::kChromeUITabSearchURL); auto* tab_strip_model = browser()->tab_strip_model(); - ASSERT_EQ(5, tab_strip_model->GetTabCount()); + ASSERT_EQ(5, tab_strip_model->count()); content::WebContents* tab_contents = tab_strip_model->GetWebContentsAt(4); const tabs::TabHandle tab_id = tab_strip_model->GetTabAtIndex(4)->GetHandle(); @@ -181,11 +181,11 @@ page_handler->CloseTab(tab_id.raw_value()); tab_contents->DispatchBeforeUnload(false /* auto_cancel */); close_observer.Wait(); - ASSERT_EQ(4, tab_strip_model->GetTabCount()); + ASSERT_EQ(4, tab_strip_model->count()); // Check to make sure the browser tab hosting Tab Search has been closed but // the rest remain. - int tab_count = tab_strip_model->GetTabCount(); + int tab_count = tab_strip_model->count(); ASSERT_EQ(4, tab_count); std::vector<tabs::TabHandle> open_tab_ids(tab_count);
diff --git a/chrome/browser/ui/webui/tab_strip/tab_strip_page_handler_unittest.cc b/chrome/browser/ui/webui/tab_strip/tab_strip_page_handler_unittest.cc index de3fa321..96751aa 100644 --- a/chrome/browser/ui/webui/tab_strip/tab_strip_page_handler_unittest.cc +++ b/chrome/browser/ui/webui/tab_strip/tab_strip_page_handler_unittest.cc
@@ -462,8 +462,8 @@ int new_index = 1; handler()->MoveGroup(group_id.ToString(), new_index); - ASSERT_EQ(2, new_browser.get()->tab_strip_model()->GetTabCount()); - ASSERT_EQ(2, browser()->tab_strip_model()->GetTabCount()); + ASSERT_EQ(2, new_browser.get()->tab_strip_model()->count()); + ASSERT_EQ(2, browser()->tab_strip_model()->count()); // Close all tabs before destructing. new_browser.get()->tab_strip_model()->CloseAllTabs(); @@ -697,7 +697,7 @@ browser()->tab_strip_model()->GetWebContentsAt(0)), false /* closed_by_swiped */); - ASSERT_EQ(1, browser()->tab_strip_model()->GetTabCount()); + ASSERT_EQ(1, browser()->tab_strip_model()->count()); } TEST_F(TabStripPageHandlerTest, RemoveTabIfInvalidContextMenu) {
diff --git a/chrome/browser/web_applications/commands/navigate_and_trigger_install_dialog_command_browsertest.cc b/chrome/browser/web_applications/commands/navigate_and_trigger_install_dialog_command_browsertest.cc index 013960b5..76dcb7894 100644 --- a/chrome/browser/web_applications/commands/navigate_and_trigger_install_dialog_command_browsertest.cc +++ b/chrome/browser/web_applications/commands/navigate_and_trigger_install_dialog_command_browsertest.cc
@@ -35,7 +35,7 @@ ASSERT_TRUE(NavigateAndAwaitInstallabilityCheck(browser(), test_url)); // The browser should have one tab. - EXPECT_EQ(1, browser()->tab_strip_model()->GetTabCount()); + EXPECT_EQ(1, browser()->tab_strip_model()->count()); content::TestNavigationObserver navigation_observer(test_url); navigation_observer.StartWatchingNewWebContents(); @@ -49,7 +49,7 @@ })); navigation_observer.Wait(); // The browser should now have 2 tabs. - EXPECT_EQ(2, browser()->tab_strip_model()->GetTabCount()); + EXPECT_EQ(2, browser()->tab_strip_model()->count()); // The active tab should be the |test_url| we navigated to. EXPECT_EQ(test_url, chrome_test_utils::GetActiveWebContents(this)->GetVisibleURL());
diff --git a/chrome/browser/webauthn/chrome_web_authentication_delegate.cc b/chrome/browser/webauthn/chrome_web_authentication_delegate.cc index 111570a..a07bd77 100644 --- a/chrome/browser/webauthn/chrome_web_authentication_delegate.cc +++ b/chrome/browser/webauthn/chrome_web_authentication_delegate.cc
@@ -195,8 +195,9 @@ PasskeyModelFactory::GetInstance()->GetForProfile( Profile::FromBrowserContext(web_contents->GetBrowserContext())); bool is_passkey_deleted = false; - for (const auto& passkey : - passkey_store->GetPasskeysForRelyingPartyId(relying_party_id)) { + for (const auto& passkey : passkey_store->GetPasskeys( + relying_party_id, + webauthn::PasskeyModel::ShadowedCredentials::kExclude)) { if (std::vector<uint8_t>(passkey.user_id().begin(), passkey.user_id().end()) == user_id && !base::Contains(all_accepted_credentials_ids, @@ -241,7 +242,9 @@ PasskeyModelFactory::GetInstance()->GetForProfile( Profile::FromBrowserContext(web_contents->GetBrowserContext())); std::vector<sync_pb::WebauthnCredentialSpecifics> passkeys = - passkey_store->GetPasskeysForRelyingPartyId(relying_party_id); + passkey_store->GetPasskeys( + relying_party_id, + webauthn::PasskeyModel::ShadowedCredentials::kExclude); const auto passkey_it = std::ranges::find_if(passkeys, [&user_id](const auto& passkey) { return std::vector<uint8_t>(passkey.user_id().begin(), @@ -505,8 +508,9 @@ PasskeyModelFactory::GetInstance()->GetForProfile( Profile::FromBrowserContext(web_contents->GetBrowserContext())); bool is_passkey_updated = false; - for (const auto& passkey : - passkey_store->GetPasskeysForRelyingPartyId(relying_party_id)) { + for (const auto& passkey : passkey_store->GetPasskeys( + relying_party_id, + webauthn::PasskeyModel::ShadowedCredentials::kExclude)) { if (std::vector<uint8_t>(passkey.user_id().begin(), passkey.user_id().end()) == user_id && (passkey.user_name() != name ||
diff --git a/chrome/browser/webauthn/enclave_authenticator_browsertest.cc b/chrome/browser/webauthn/enclave_authenticator_browsertest.cc index c43a036..6486fd9 100644 --- a/chrome/browser/webauthn/enclave_authenticator_browsertest.cc +++ b/chrome/browser/webauthn/enclave_authenticator_browsertest.cc
@@ -1603,7 +1603,9 @@ EXPECT_EQ(script_result, "\"webauthn: OK\""); passkey_model().RemoveObserver(&passkey_model_observer); EXPECT_TRUE(passkey_model_observer.did_update); - auto passkeys = passkey_model().GetAllPasskeys(); + auto passkeys = passkey_model().GetPasskeys( + webauthn::PasskeyModel::AnyRp(), + webauthn::PasskeyModel::ShadowedCredentials::kInclude); ASSERT_EQ(passkeys.size(), 1u); // The update time should be in the last 10 minutes. EXPECT_LT((base::Time::Now() - @@ -1952,7 +1954,7 @@ model_observer()->SetStepToObserve( AuthenticatorRequestDialogModel::Step::kMechanismSelection); model_observer()->WaitForStep(); - ASSERT_EQ(browser()->tab_strip_model()->GetTabCount(), 1); + ASSERT_EQ(browser()->tab_strip_model()->count(), 1); // No credentials should be displayed since tapping on them won't work. EXPECT_FALSE( @@ -1977,7 +1979,7 @@ ASSERT_TRUE(message_queue.WaitForMessage(&script_result)); EXPECT_TRUE(script_result.starts_with("\"error NotAllowedError")) << script_result; - EXPECT_EQ(browser()->tab_strip_model()->GetTabCount(), 2); + EXPECT_EQ(browser()->tab_strip_model()->count(), 2); } IN_PROC_BROWSER_TEST_F(EnclaveAuthenticatorBrowserTest, @@ -2076,7 +2078,7 @@ kGetAssertionUvDiscouragedWithGoogleRp); delegate_observer()->WaitForUI(); - ASSERT_EQ(browser()->tab_strip_model()->GetTabCount(), 1); + ASSERT_EQ(browser()->tab_strip_model()->count(), 1); // The sign in button is not visible. const auto sign_in_again_mech = std::ranges::find_if(dialog_model()->mechanisms, [](const auto& m) { @@ -4179,7 +4181,9 @@ ASSERT_TRUE(queue.WaitForMessage(&script_result)); EXPECT_EQ(script_result, "\"largeblob true\""); - const auto passkeys = passkey_model().GetAllPasskeys(); + const auto passkeys = passkey_model().GetPasskeys( + webauthn::PasskeyModel::AnyRp(), + webauthn::PasskeyModel::ShadowedCredentials::kInclude); ASSERT_EQ(passkeys.size(), 1u); const std::string cred_id_b64 = base::Base64Encode(passkeys[0].credential_id());
diff --git a/chrome/browser/webauthn/gpm_enclave_controller.cc b/chrome/browser/webauthn/gpm_enclave_controller.cc index edb11b10..271d8f7 100644 --- a/chrome/browser/webauthn/gpm_enclave_controller.cc +++ b/chrome/browser/webauthn/gpm_enclave_controller.cc
@@ -414,7 +414,8 @@ Profile* const profile = GetProfile(); webauthn::PasskeyModel* passkey_model = PasskeyModelFactory::GetInstance()->GetForProfile(profile); - creds_ = passkey_model->GetPasskeysForRelyingPartyId(rp_id_); + creds_ = passkey_model->GetPasskeys( + rp_id_, webauthn::PasskeyModel::ShadowedCredentials::kExclude); if (base::FeatureList::IsEnabled(device::kWebAuthnSignalApiHidePasskeys)) { std::erase_if(creds_, [](const auto& cred) { return cred.hidden(); }); }
diff --git a/chrome/browser/webauthn/gpm_enclave_transaction.cc b/chrome/browser/webauthn/gpm_enclave_transaction.cc index 8d83720..5ef84af 100644 --- a/chrome/browser/webauthn/gpm_enclave_transaction.cc +++ b/chrome/browser/webauthn/gpm_enclave_transaction.cc
@@ -233,7 +233,8 @@ weak_ptr_factory_.GetWeakPtr()); std::vector<std::vector<uint8_t>> existing_credential_ids; std::ranges::transform( - passkey_model_->GetPasskeysForRelyingPartyId(rp_id_), + passkey_model_->GetPasskeys( + rp_id_, webauthn::PasskeyModel::ShadowedCredentials::kExclude), std::back_inserter(existing_credential_ids), [](const sync_pb::WebauthnCredentialSpecifics& cred) { const std::string& cred_id = cred.credential_id(); @@ -247,7 +248,8 @@ CHECK(selected_credential_id_); std::unique_ptr<sync_pb::WebauthnCredentialSpecifics> selected_credential; std::vector<sync_pb::WebauthnCredentialSpecifics> credentials = - passkey_model_->GetPasskeysForRelyingPartyId(rp_id_); + passkey_model_->GetPasskeys( + rp_id_, webauthn::PasskeyModel::ShadowedCredentials::kExclude); for (auto& cred : credentials) { if (std::ranges::equal(base::as_byte_span(cred.credential_id()), base::span(*selected_credential_id_))) {
diff --git a/chrome/browser/webauthn/passkey_unlock_manager.cc b/chrome/browser/webauthn/passkey_unlock_manager.cc index 3beed00..6a3c649 100644 --- a/chrome/browser/webauthn/passkey_unlock_manager.cc +++ b/chrome/browser/webauthn/passkey_unlock_manager.cc
@@ -179,7 +179,11 @@ } void PasskeyUnlockManager::UpdateHasPasskeys() { - has_passkeys_ = !passkey_model()->GetAllPasskeys().empty(); + has_passkeys_ = + !passkey_model() + ->GetPasskeys(webauthn::PasskeyModel::AnyRp(), + webauthn::PasskeyModel::ShadowedCredentials::kInclude) + .empty(); } void PasskeyUnlockManager::UpdateSyncState() { @@ -286,8 +290,12 @@ } void PasskeyUnlockManager::RecordPasskeyCountHistogram() { - base::UmaHistogramCounts1000("WebAuthentication.PasskeyCount", - passkey_model()->GetAllPasskeys().size()); + base::UmaHistogramCounts1000( + "WebAuthentication.PasskeyCount", + passkey_model() + ->GetPasskeys(webauthn::PasskeyModel::AnyRp(), + webauthn::PasskeyModel::ShadowedCredentials::kInclude) + .size()); } void PasskeyUnlockManager::MaybeRecordDelayedPasskeyReadinessHistogram() {
diff --git a/chrome/browser/webauthn/webauthn_immediate_mediation_interactive_uitest.cc b/chrome/browser/webauthn/webauthn_immediate_mediation_interactive_uitest.cc index a493d6a..17ecea8 100644 --- a/chrome/browser/webauthn/webauthn_immediate_mediation_interactive_uitest.cc +++ b/chrome/browser/webauthn/webauthn_immediate_mediation_interactive_uitest.cc
@@ -252,7 +252,12 @@ &cred_id2_base64); AddPasskey(kUser2, cred_id2); - ASSERT_EQ(passkey_model().GetAllPasskeys().size(), 2u); + ASSERT_EQ( + passkey_model() + .GetPasskeys(webauthn::PasskeyModel::AnyRp(), + webauthn::PasskeyModel::ShadowedCredentials::kInclude) + .size(), + 2u); RunTestSequence( GetStepsUntilButtonClick(kGetImmediateButton),
diff --git a/chrome/browser_exposed_mojom_targets.gni b/chrome/browser_exposed_mojom_targets.gni index 72982a97..bdc3201 100644 --- a/chrome/browser_exposed_mojom_targets.gni +++ b/chrome/browser_exposed_mojom_targets.gni
@@ -286,6 +286,7 @@ "//storage/browser/quota:mojo_bindings", "//third_party/blink/public/mojom:android_mojo_bindings", "//third_party/blink/public/mojom:color_scheme_mojo_bindings", + "//third_party/blink/public/mojom:credentialmanagement_mojo_bindings", "//third_party/blink/public/mojom:embedded_frame_sink_mojo_bindings", "//third_party/blink/public/mojom:memory_usage_monitor_linux_mojo_bindings", "//third_party/blink/public/mojom:mojom_core",
diff --git a/chrome/build/android-arm32.pgo.txt b/chrome/build/android-arm32.pgo.txt index 42d3ac7..1bc82618 100644 --- a/chrome/build/android-arm32.pgo.txt +++ b/chrome/build/android-arm32.pgo.txt
@@ -1 +1 @@ -chrome-android32-main-1764935987-8e4066e93972449f367d36f71c51e8edcf4c0437-7703dd1340a02421129672e37433541fdde3a7e5.profdata +chrome-android32-main-1764957587-ad35dc24c24ef15415dfcb79722959817c4c5c32-6dc32bc32794872c2f03f47131b94ba0bfa8590a.profdata
diff --git a/chrome/build/android-desktop-x64.pgo.txt b/chrome/build/android-desktop-x64.pgo.txt index a41b180..92e9d51 100644 --- a/chrome/build/android-desktop-x64.pgo.txt +++ b/chrome/build/android-desktop-x64.pgo.txt
@@ -1 +1 @@ -chrome-android-desktop-x64-main-1764935987-1a7e5941e093377e8e2b36619cbf72f8d4e48c02-7703dd1340a02421129672e37433541fdde3a7e5.profdata +chrome-android-desktop-x64-main-1764957587-3010bbe42591174bc696af8b3f8b9f30f3368296-6dc32bc32794872c2f03f47131b94ba0bfa8590a.profdata
diff --git a/chrome/build/mac-arm.pgo.txt b/chrome/build/mac-arm.pgo.txt index 42bac66..1a4886f 100644 --- a/chrome/build/mac-arm.pgo.txt +++ b/chrome/build/mac-arm.pgo.txt
@@ -1 +1 @@ -chrome-mac-arm-main-1764943156-c32feb0e40f98ca0ae983c0033ff66a90ed97159-8987173fdf096cb3ba312cd19421356a9609497e.profdata +chrome-mac-arm-main-1764957587-a146e85fb2f67f1ccb19bb8882bddb0e531217a3-6dc32bc32794872c2f03f47131b94ba0bfa8590a.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt index 6d2ed9fc..d989ce1 100644 --- a/chrome/build/win32.pgo.txt +++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@ -chrome-win32-main-1764914351-7cb792a554723e22df6d665a85c58415b07a05e3-dcdceb2c1fea01f2db67d688776cc6c32ea8c3ee.profdata +chrome-win32-main-1764935987-5211c54ecb9e1dd5d0258ba3dbbe29a6b0817c45-7703dd1340a02421129672e37433541fdde3a7e5.profdata
diff --git a/chrome/common/actor.mojom b/chrome/common/actor.mojom index 77bb4859..4ab5054a 100644 --- a/chrome/common/actor.mojom +++ b/chrome/common/actor.mojom
@@ -151,8 +151,9 @@ enum ActionResultCode { kOk = 0, + // DEPRECATED. Use explicit error codes instead. // A generic error that does not have a more specific code. Avoid using this. - kError = 10, + // kError = 10, // Actions are not allowed on the current URL. kUrlBlocked = 11, @@ -249,6 +250,10 @@ // The renderer process crashed. kRendererCrashed = 39, + // Only used as place holder for planned but unimplemented features. Do not + // use as a generic error code. + kNotImplemented = 40, + // Please see the comment above about adding new values. /////////////////////////////////////////////////////////////////////// @@ -261,6 +266,9 @@ // The navigation failed before it started. kNavigateFailedToStart = 101, + // The navigation committed to an error page. + kNavigateCommittedErrorPage = 102, + // Please see the comment above about adding new values. /////////////////////////////////////////////////////////////////////// @@ -420,6 +428,12 @@ // cancelled it). kLoginDeviceReauthFailed = 907, + // The login attempt failed because the feature is disabled. + kLoginFeatureDisabled = 908, + + // Multiple login requests were made at the same time. + kLoginTooManyRequests = 909, + // Please see the comment above about adding new values. /////////////////////////////////////////////////////////////////////// @@ -450,6 +464,26 @@ // An error occurred during autofill. kFormFillingUnknownAutofillError = 1104, + // No tab observation was found when the TOCTOU check was performed. + kFormFillingNoLastTabObservation = 1105, + + // The suggestion ID selected by the user was invalid. + kFormFillingInvalidSuggestionId = 1106, + + /////////////////////////////////////////////////////////////////////// + // Codes 1200-1299: Errors for script tool. + + // The document did not return a response for the script tool. + kScriptToolNoResponse = 1200, + + // Please see the comment above about adding new values. + + /////////////////////////////////////////////////////////////////////// + // Codes 1300-1399: Errors for Chrome UI. + + // The Chrome Actor UI could not be shown. + kActorUiError = 1300, + // Please see the comment above about adding new values. };
diff --git a/chrome/common/actor/action_result.cc b/chrome/common/actor/action_result.cc index 7615728..9184b3b 100644 --- a/chrome/common/actor/action_result.cc +++ b/chrome/common/actor/action_result.cc
@@ -48,10 +48,6 @@ /*execution_end_time=*/base::TimeTicks::Now()); } -mojom::ActionResultPtr MakeErrorResult() { - return MakeResult(mojom::ActionResultCode::kError); -} - mojom::ActionResultPtr MakeResult(mojom::ActionResultCode code, bool requires_page_stabilization, std::string_view msg) {
diff --git a/chrome/common/actor/action_result.h b/chrome/common/actor/action_result.h index 2edb00d7..13fd11b 100644 --- a/chrome/common/actor/action_result.h +++ b/chrome/common/actor/action_result.h
@@ -36,10 +36,6 @@ mojom::ActionResultPtr MakeOkResult(bool requires_page_stabilization = true); -// TODO(crbug.com/409558980): Replace generic errors with tool-specific ones, -// and remove this function. -mojom::ActionResultPtr MakeErrorResult(); - // TODO(b/459615712): Rename this to MakeErrorResult to make it clear that this // shouldn't be used for successful results as the default page_stabilization // argument makes this error-prone. This is runtime asserted inside.
diff --git a/chrome/common/chrome_features.cc b/chrome/common/chrome_features.cc index 1736aae..a8e3576 100644 --- a/chrome/common/chrome_features.cc +++ b/chrome/common/chrome_features.cc
@@ -471,6 +471,11 @@ // main app. BASE_FEATURE(kGlicUnifiedFreScreen, base::FEATURE_DISABLED_BY_DEFAULT); +// Controls the Glic Trust First Onboarding experience. +BASE_FEATURE(kGlicTrustFirstOnboarding, base::FEATURE_DISABLED_BY_DEFAULT); + +const base::FeatureParam<int> kGlicTrustFirstOnboardingArmParam{ + &kGlicTrustFirstOnboarding, "arm", 1 /* kStartChat */}; #if BUILDFLAG(ENABLE_GLIC) // Controls whether the Glic feature is enabled. // IMPORTANT: this feature should never be expired! It is used as the main @@ -864,6 +869,10 @@ BASE_FEATURE(kGlicFaviconDataUrls, base::FEATURE_DISABLED_BY_DEFAULT); +// Whether Glic should ignore the offline network status, and assume it is +// online. +BASE_FEATURE(kGlicIgnoreOfflineState, base::FEATURE_ENABLED_BY_DEFAULT); + BASE_FEATURE(kGlicExtensions, base::FEATURE_ENABLED_BY_DEFAULT); BASE_FEATURE(kGlicMultitabUnderlines, base::FEATURE_ENABLED_BY_DEFAULT); @@ -939,6 +948,13 @@ &kGlicMetricsSession, "glic-metrics-session-start-timeout", base::Seconds(5)}; +BASE_FEATURE(kGlicPrintMenuItem, base::FEATURE_ENABLED_BY_DEFAULT); + +const base::FeatureParam<int> kGlicCompositeViewWidth{ + &kGlicPrintMenuItem, "glic-composite-view-width", 800}; + +const base::FeatureParam<int> kGlicCompositeViewHeight{ + &kGlicPrintMenuItem, "glic-composite-view-height", 480}; #endif // BUILDFLAG(ENABLE_GLIC) BASE_FEATURE(kGlicActorAutofill, base::FEATURE_DISABLED_BY_DEFAULT);
diff --git a/chrome/common/chrome_features.h b/chrome/common/chrome_features.h index 85895f79..a1b281c 100644 --- a/chrome/common/chrome_features.h +++ b/chrome/common/chrome_features.h
@@ -348,6 +348,11 @@ COMPONENT_EXPORT(CHROME_FEATURES) BASE_DECLARE_FEATURE(kGlicUnifiedFreScreen); +COMPONENT_EXPORT(CHROME_FEATURES) +BASE_DECLARE_FEATURE(kGlicTrustFirstOnboarding); + +extern const base::FeatureParam<int> kGlicTrustFirstOnboardingArmParam; + #if BUILDFLAG(ENABLE_GLIC) // Controls whether the Glic feature is enabled. // IMPORTANT: this feature should never be expired! It is used as the main @@ -617,6 +622,9 @@ BASE_DECLARE_FEATURE(kGlicFaviconDataUrls); COMPONENT_EXPORT(CHROME_FEATURES) +BASE_DECLARE_FEATURE(kGlicIgnoreOfflineState); + +COMPONENT_EXPORT(CHROME_FEATURES) BASE_DECLARE_FEATURE(kGlicMultitabUnderlines); COMPONENT_EXPORT(CHROME_FEATURES) @@ -656,6 +664,12 @@ COMPONENT_EXPORT(CHROME_FEATURES) BASE_DECLARE_FEATURE(kGlicLiveModeOnlyGlow); +COMPONENT_EXPORT(CHROME_FEATURES) +BASE_DECLARE_FEATURE(kGlicPrintMenuItem); +COMPONENT_EXPORT(CHROME_FEATURES) +extern const base::FeatureParam<int> kGlicCompositeViewWidth; +COMPONENT_EXPORT(CHROME_FEATURES) +extern const base::FeatureParam<int> kGlicCompositeViewHeight; #endif // BUILDFLAG(ENABLE_GLIC) COMPONENT_EXPORT(CHROME_FEATURES) BASE_DECLARE_FEATURE(kGlicExtensions);
diff --git a/chrome/installer/mac/internal b/chrome/installer/mac/internal index 27b07a5..47bf099 160000 --- a/chrome/installer/mac/internal +++ b/chrome/installer/mac/internal
@@ -1 +1 @@ -Subproject commit 27b07a5c4a105a8b4508c61bc9aa6dc52b519907 +Subproject commit 47bf0993574233a3bbd271c8318d0299e542d1f5
diff --git a/chrome/renderer/actor/drag_and_release_tool.cc b/chrome/renderer/actor/drag_and_release_tool.cc index 7df6bc9..987faf8 100644 --- a/chrome/renderer/actor/drag_and_release_tool.cc +++ b/chrome/renderer/actor/drag_and_release_tool.cc
@@ -4,6 +4,7 @@ #include "chrome/renderer/actor/drag_and_release_tool.h" +#include "base/notimplemented.h" #include "base/time/time.h" #include "base/types/expected.h" #include "chrome/common/actor/action_result.h" @@ -226,7 +227,12 @@ if (resolved_from->GetWidget(*this) != resolved_to->GetWidget(*this)) { // Drag across widgets (i.e. between frame and popup) isn't currently // supported. - return base::unexpected(MakeErrorResult()); + static constexpr std::string_view kErrorMessage = + "Drag across widgets is not supported."; + NOTIMPLEMENTED() << kErrorMessage; + return base::unexpected(MakeResult(mojom::ActionResultCode::kNotImplemented, + /*requires_page_stabilization=*/false, + kErrorMessage)); } // TODO(b/450018073): This should be checking the targets for time-of-use
diff --git a/chrome/renderer/actor/script_tool.cc b/chrome/renderer/actor/script_tool.cc index 0c7637b0..4de4252 100644 --- a/chrome/renderer/actor/script_tool.cc +++ b/chrome/renderer/actor/script_tool.cc
@@ -25,9 +25,8 @@ mojom::ActionResultPtr OnToolExecuted( base::expected<blink::WebString, blink::WebDocument::ScriptToolError> response) { - // TODO(khushalsagar): Add script tool errors and propagate up the stack. if (!response.has_value()) { - return MakeResult(mojom::ActionResultCode::kError); + return MakeResult(mojom::ActionResultCode::kScriptToolNoResponse); } auto result = MakeOkResult();
diff --git a/chrome/renderer/actor/select_tool.cc b/chrome/renderer/actor/select_tool.cc index 00f94f5..27afdb9 100644 --- a/chrome/renderer/actor/select_tool.cc +++ b/chrome/renderer/actor/select_tool.cc
@@ -72,8 +72,12 @@ CHECK(frame_->GetWebFrame()->FrameWidget()); if (target_->is_coordinate_dip()) { - NOTIMPLEMENTED() << "Coordinate-based target is not yet supported."; - return base::unexpected(MakeErrorResult()); + static constexpr std::string_view kErrorMessage = + "Coordinate-based target is not yet supported."; + NOTIMPLEMENTED() << kErrorMessage; + return base::unexpected(MakeResult(mojom::ActionResultCode::kNotImplemented, + /*requires_page_stabilization=*/false, + kErrorMessage)); } auto resolved_target = ValidateAndResolveTarget();
diff --git a/chrome/services/sharing/nearby/platform/input_file.cc b/chrome/services/sharing/nearby/platform/input_file.cc index 13f32e58..4c96116 100644 --- a/chrome/services/sharing/nearby/platform/input_file.cc +++ b/chrome/services/sharing/nearby/platform/input_file.cc
@@ -4,9 +4,10 @@ #include "chrome/services/sharing/nearby/platform/input_file.h" +#include <optional> #include <vector> -#include "base/compiler_specific.h" +#include "base/containers/span.h" #include "base/logging.h" #include "base/notimplemented.h" #include "third_party/abseil-cpp/absl/time/time.h" @@ -44,12 +45,14 @@ } std::vector<char> buf(size); - int num_bytes_read = UNSAFE_TODO(file_.ReadAtCurrentPos(buf.data(), size)); - - if (num_bytes_read < 0 || num_bytes_read > GetTotalSize()) + const std::optional<size_t> bytes_read = + file_.ReadAtCurrentPos(base::as_writable_byte_span(buf)); + if (!bytes_read || + base::checked_cast<int64_t>(*bytes_read) > GetTotalSize()) { return Exception::kIo; + } - return ExceptionOr<ByteArray>(ByteArray(buf.data(), num_bytes_read)); + return ExceptionOr<ByteArray>(ByteArray(buf.data(), *bytes_read)); } Exception InputFile::Close() {
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index 0ad5ba0..423410b6 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -9388,6 +9388,7 @@ "../browser/extensions/extension_service_unittest.cc", "../browser/extensions/extension_tab_util_unittest.cc", "../browser/extensions/external_policy_loader_unittest.cc", + "../browser/extensions/external_provider_impl_unittest.cc", "../browser/extensions/forced_extensions/force_installed_metrics_unittest.cc", "../browser/extensions/forced_extensions/force_installed_test_base.cc", "../browser/extensions/forced_extensions/force_installed_test_base.h", @@ -9548,7 +9549,6 @@ "../browser/extensions/extension_user_script_loader_unittest.cc", "../browser/extensions/extension_util_unittest.cc", "../browser/extensions/extension_web_ui_unittest.cc", - "../browser/extensions/external_provider_impl_unittest.cc", "../browser/extensions/favicon/favicon_util_unittest.cc", "../browser/extensions/initial_external_extension_loader_unittest.cc", "../browser/extensions/manifest_v2_experiment_manager_unittest.cc",
diff --git a/chrome/test/data/extensions/external/kekdneafjmhmndejhmbcadfiiofngffo.crx b/chrome/test/data/extensions/external_app/kekdneafjmhmndejhmbcadfiiofngffo.crx similarity index 100% rename from chrome/test/data/extensions/external/kekdneafjmhmndejhmbcadfiiofngffo.crx rename to chrome/test/data/extensions/external_app/kekdneafjmhmndejhmbcadfiiofngffo.crx Binary files differ
diff --git a/chrome/test/data/extensions/external/kekdneafjmhmndejhmbcadfiiofngffo.json b/chrome/test/data/extensions/external_app/kekdneafjmhmndejhmbcadfiiofngffo.json similarity index 100% rename from chrome/test/data/extensions/external/kekdneafjmhmndejhmbcadfiiofngffo.json rename to chrome/test/data/extensions/external_app/kekdneafjmhmndejhmbcadfiiofngffo.json
diff --git a/chrome/test/data/extensions/external/kekdneafjmhmndejhmbcadfiiofngffo.pem b/chrome/test/data/extensions/external_app/kekdneafjmhmndejhmbcadfiiofngffo.pem similarity index 100% rename from chrome/test/data/extensions/external/kekdneafjmhmndejhmbcadfiiofngffo.pem rename to chrome/test/data/extensions/external_app/kekdneafjmhmndejhmbcadfiiofngffo.pem
diff --git a/chrome/test/data/extensions/external_extension/ghpipljflpbfljcfjlhfbfcpoklobpji.crx b/chrome/test/data/extensions/external_extension/ghpipljflpbfljcfjlhfbfcpoklobpji.crx new file mode 100644 index 0000000..43f21b2 --- /dev/null +++ b/chrome/test/data/extensions/external_extension/ghpipljflpbfljcfjlhfbfcpoklobpji.crx Binary files differ
diff --git a/chrome/test/data/extensions/external_extension/ghpipljflpbfljcfjlhfbfcpoklobpji.json b/chrome/test/data/extensions/external_extension/ghpipljflpbfljcfjlhfbfcpoklobpji.json new file mode 100644 index 0000000..71915ae --- /dev/null +++ b/chrome/test/data/extensions/external_extension/ghpipljflpbfljcfjlhfbfcpoklobpji.json
@@ -0,0 +1,4 @@ +{ + "external_crx": "ghpipljflpbfljcfjlhfbfcpoklobpji.crx", + "external_version": "1" +}
diff --git a/chrome/test/data/extensions/external_extension/ghpipljflpbfljcfjlhfbfcpoklobpji.pem b/chrome/test/data/extensions/external_extension/ghpipljflpbfljcfjlhfbfcpoklobpji.pem new file mode 100644 index 0000000..d32ddd90 --- /dev/null +++ b/chrome/test/data/extensions/external_extension/ghpipljflpbfljcfjlhfbfcpoklobpji.pem
@@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDV1M/4ZM/uQoLM +OzJpzK/AqH2fQaJP1jqckf9t40f7KmxYUKRqzr47DpWcVOW79LWP+lAXdGuZkYtj +ZvRT9EeJIedCJ7K4acmhsnU2hsfStFs9lQba/3/I33UBS2RX4XRZTDZLlQvwtlzW +dzkAUiZNObTj2zf4FLTZa6gVExt00pOvqEJo8s7o+QxuZqy4d8wVtb6kLimHVo1/ +eIpsCgbIYCHJ+aB0rvc5WdVl6Wro0Fp0oFvnBKUVl3ZiR1xooJyXBiNBP/dOfaPS +db67/3C9GahbKdbRz6Zydb9+ABNUKJznpIO+R6KUfCibS14m/bk2TD9OJM1EJoS1 +LTunxuQFAgMBAAECggEANUGgHILrQLGjBv+1YiFfIpI0W25K4Sx/g5BfODyzqEwc +GPDYyls8iNPskjeY0jOz5qyWtwjBZcmYmETDlIdSK8bcZJ8jhYefdtzOEasG6KUP +1mof/3pEFsEE0LI4xyR5SGZRXYi9JRIeVDH0ae6L6I73TQrDyU9K7Z3BCqKsI298 +S0wC3pBCri4ge2JMj11BdDUX75Zeq355FkiBUsalsP06PYcdZHr14LKpBow/BsJl +MigcsHx6DxkfH8PhoZZzYov8ZLz0kegGgDWAL/3iYjV79VklyDqhW2iDv5A697j/ +e/ymnhxItK+bFjunMiGZDg/pu+8d8MWGi4PY3duSbwKBgQDxj7T1iHDi3iNGasHF +XBT/7B5uIkaNdR4D3GQxYh4EuPRHgs1FJlLgg09gjiMXjQYU4QWxR91/ii7gG4Gb +7oPb5YT1OddGJvEHbc9rxcdeAcchC/3CrdXenUiRJElKnp8ZZRMUVR09MnTsMlvu +IQiFmDMga9TOuzKIrbWBIZEeIwKBgQDinMoKkHyB3QqKEf+StmQGEWHckcWiZNdb +7iIZ1A5dNHXE45lAQ/63jffMBLZrxzvU4RnngUPC3EeTqrfFdQWIfYG6y8f/gWSQ +SBLbq54ZRTuUlppLh7H0d+oTPVmdDcZxOxAuygXdAxrGF+KX9zPZEnMOHtC6vkFX +GNDUnndTtwKBgCBwfQuwHADLdg9BzO3VFNjde6Sso67heHtqQGZFV+Sodd2Ymjpc +ECsoVyOPUvUZsiRhp6MMFJnJE8xyxTAMktaX9wf7kYZROnMV8xH1CHX+ZSBx/M0F +DUCM/K7JIbKMpK8DXNGRMJEEUqFZjfDnrL5MFymWcYilqP6j3UkPGe7jAoGAGjFT +LQtsSLpa2ICiELwiLY1eyVbUCCQtvEN3D5MyIdXJcvt3oDT7wQ2Ywa0dxLFfmgh2 +rQqE4YYCg+/sk9clz5PqJcQeFstG62JZQ6i/el5FN7R8mxRRHlep55VkwUFxWW8h +PLc/HD+anaDvIO+Cv6lhQRWQvLT26nFE2f6C/lsCgYBlJwlw2gZU/66us8caIEzY +dldSZzPUlCzHM5L7ad3kaB9cBELpEvZAy/z+jtB18J2eaXFtFYM1ulETVf47pOxA +yVdyIt00SqjsRjOUVA8B2ygTK/PcScUV2u3yFEXfyJDGjj7iwegzRsEJLz8PnFsd +dGQRxO0oOSkyWsfa9WSU3Q== +-----END PRIVATE KEY-----
diff --git a/chrome/test/data/webui/contextual_tasks/BUILD.gn b/chrome/test/data/webui/contextual_tasks/BUILD.gn index e7092cfd..015ed00 100644 --- a/chrome/test/data/webui/contextual_tasks/BUILD.gn +++ b/chrome/test/data/webui/contextual_tasks/BUILD.gn
@@ -15,6 +15,7 @@ "contextual_tasks_webview_browsertest.ts", "post_message_handler_test.ts", "test_utils.ts", + "top_toolbar_test.ts", ] static_files = [ "test.html" ]
diff --git a/chrome/test/data/webui/contextual_tasks/contextual_tasks_browsertest.cc b/chrome/test/data/webui/contextual_tasks/contextual_tasks_browsertest.cc index 52057ab..adb7766d 100644 --- a/chrome/test/data/webui/contextual_tasks/contextual_tasks_browsertest.cc +++ b/chrome/test/data/webui/contextual_tasks/contextual_tasks_browsertest.cc
@@ -33,6 +33,10 @@ RunTest("contextual_tasks/post_message_handler_test.js", "mocha.run();"); } +IN_PROC_BROWSER_TEST_F(ContextualTasksBrowserTest, TopToolbarTest) { + RunTest("contextual_tasks/top_toolbar_test.js", "mocha.run();"); +} + #if BUILDFLAG(USE_JAVASCRIPT_COVERAGE) // TODO(crbug.com/40284073): Test fails with JS coverage turned on. Since the // webview needs to make a request to test the request headers, disabling this
diff --git a/chrome/test/data/webui/contextual_tasks/top_toolbar_test.ts b/chrome/test/data/webui/contextual_tasks/top_toolbar_test.ts new file mode 100644 index 0000000..a5202b1b --- /dev/null +++ b/chrome/test/data/webui/contextual_tasks/top_toolbar_test.ts
@@ -0,0 +1,31 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'chrome://contextual-tasks/top_toolbar.js'; + +import type {TopToolbarElement} from 'chrome://contextual-tasks/top_toolbar.js'; +import {assertEquals} from 'chrome://webui-test/chai_assert.js'; + +suite('TopToolbarTest', () => { + let topToolbar: TopToolbarElement; + + setup(() => { + document.body.innerHTML = window.trustedTypes!.emptyHTML; + topToolbar = document.createElement('top-toolbar'); + document.body.appendChild(topToolbar); + }); + + + test('shows correct logo', () => { + assertEquals( + topToolbar.$.topToolbarLogo.src, + // <if expr="_google_chrome"> + 'chrome://resources/cr_components/searchbox/icons/google_g_gradient.svg', + // </if> + // <if expr="not _google_chrome"> + 'chrome://resources/cr_components/searchbox/icons/chrome_product.svg', + // </if> + ); + }); +});
diff --git a/chrome/test/data/webui/glic/test_client/sections/action.ts b/chrome/test/data/webui/glic/test_client/sections/action.ts index b4b0b8a6..4d9de3f 100644 --- a/chrome/test/data/webui/glic/test_client/sections/action.ts +++ b/chrome/test/data/webui/glic/test_client/sections/action.ts
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import type {SelectCredentialDialogRequest} from '/glic/glic_api/glic_api.js'; +import type {SelectCredentialDialogRequest, Subscriber} from '/glic/glic_api/glic_api.js'; import {UserGrantedPermissionDuration} from '/glic/glic_api/glic_api.js'; import {client, logMessage} from '../client.js'; @@ -32,6 +32,18 @@ } }); +let credentialHandlerSubscriber: Subscriber|undefined; + +function initCredentialHandlingIfNeeded() { + if (credentialHandlerSubscriber) { + return; + } + + credentialHandlerSubscriber = + client.browser?.selectCredentialDialogRequestHandler?.().subscribe( + showCredentialPicker); +} + $.createActorTask.addEventListener('click', async () => { logMessage('Starting Create Actor Task'); try { @@ -41,6 +53,11 @@ } catch (error) { $.actionStatus.innerText = `Error in Create Actor Task: ${error}`; } + + // We only handle credentials when running interactively, which is why we set + // up the handling here. If we did this on load, then we'd interfere with + // automated tests which need to do their own custom handling. + initCredentialHandlingIfNeeded(); }); $.stopActorTask.addEventListener('click', () => { @@ -67,6 +84,8 @@ return; } + client.browser?.uninterruptActorTask?.(lastCredentialRequest.taskId); + const select = $.selectCredential; lastCredentialRequest.onDialogClosed({ @@ -94,6 +113,7 @@ lastCredentialRequest = request; $.credentialSelection.style.display = 'block'; + client.browser?.interruptActorTask?.(request.taskId); } $.credentialOnce.addEventListener('click', () => { @@ -103,8 +123,3 @@ $.credentialAlways.addEventListener('click', () => { pickCredential(false); }); - -client.getInitialized().then(() => { - client.browser!.selectCredentialDialogRequestHandler?.().subscribe( - showCredentialPicker); -});
diff --git a/chrome/test/data/webui/side_panel/read_anything/app_style_updater_test.ts b/chrome/test/data/webui/side_panel/read_anything/app_style_updater_test.ts index 70bdd1c88..1b5247c 100644 --- a/chrome/test/data/webui/side_panel/read_anything/app_style_updater_test.ts +++ b/chrome/test/data/webui/side_panel/read_anything/app_style_updater_test.ts
@@ -186,12 +186,12 @@ const expectedSepiaDarkPreviousHighlight = 'rgb(100, 100, 255)'; const expectedDefaultEmptyHeading = 'rgb(100, 5, 100)'; const expectedDefaultEmptyBody = 'rgb(100, 100, 100)'; - const expectedYellowEmptyBody = 'rgb(6, 6, 37)'; - const expectedDarkEmptyBody = 'rgb(6, 37, 6)'; - const expectedHighContrastEmptyBody = 'rgb(11, 11, 11)'; - const expectedLowContrastEmptyBody = 'rgb(11, 11, 12)'; - const expectedSepiaLightEmptyBody = 'rgb(37, 6, 37)'; - const expectedSepiaDarkEmptyBody = 'rgb(37, 37, 6)'; + const expectedYellowEmptyBody = 'rgb(255, 0, 255)'; + const expectedDarkEmptyBody = 'rgb(255, 255, 0)'; + const expectedHighContrastEmptyBody = 'rgb(0, 0, 0)'; + const expectedLowContrastEmptyBody = 'rgb(255, 0, 0)'; + const expectedSepiaLightEmptyBody = 'rgb(0, 255, 0)'; + const expectedSepiaDarkEmptyBody = 'rgb(0, 0, 255)'; const expectedDefaultLink = 'rgb(6, 37, 37)'; const expectedYellowLink = 'rgb(37, 6, 6)'; const expectedDarkLink = 'rgb(37, 6, 37)'; @@ -447,7 +447,7 @@ const expectedBlueForeground = 'rgb(4, 5, 6)'; const expectedBlueCurrentHighlight = 'rgb(7, 8, 9)'; const expectedBluePreviousHighlight = 'rgb(10, 11, 12)'; - const expectedBlueEmptyBody = 'rgb(13, 14, 15)'; + const expectedBlueEmptyBody = 'rgb(4, 5, 6)'; const expectedBlueLink = 'rgb(16, 17, 18)'; const expectedBlueLinkVisited = 'rgb(19, 20, 21)'; updateStyles({
diff --git a/chrome/test/data/webui/side_panel/read_anything/speech_controller_test.ts b/chrome/test/data/webui/side_panel/read_anything/speech_controller_test.ts index 1d99dc2b..040111c 100644 --- a/chrome/test/data/webui/side_panel/read_anything/speech_controller_test.ts +++ b/chrome/test/data/webui/side_panel/read_anything/speech_controller_test.ts
@@ -29,11 +29,12 @@ // TODO: crbug.com/440400392- Move all tests relying on chrome.readingMode // for text segmentation to use TestReadAloudModelBrowserProxy instead. - function onPlayPauseToggle(text: string) { + function onPlayPauseToggle(text: string): HTMLElement { setContent(text, readAloudModel); const element = document.createElement('p'); element.textContent = text; speechController.onPlayPauseToggle(element); + return element; } setup(() => { @@ -573,6 +574,48 @@ await metrics.whenCalled('recordSpeechStopSource')); }); + test( + 'resume after audio ends but before speech onend restarts speech', + async () => { + const text = 'You caught me unaware, now my fate is tied with yours.'; + setContent(text, readAloudModel); + + // Simulate reaching the end of speech as soon as moveSpeechForward is + // called. + readAloudModel.moveSpeechForward = () => { + readAloudModel.setCurrentTextSegments([]); + }; + + readAloudModel.resetSpeechToBeginning = () => { + setContent(text, readAloudModel); + }; + + // Start playing speech. + const element = onPlayPauseToggle(text); + let spoken = await speech.whenCalled('speak'); + spoken.onstart(new SpeechSynthesisEvent('start', {utterance: spoken})); + + // Fire a word boundary event at the very end. + spoken.onboundary(createWordBoundaryEvent(spoken, text.length - 1, 1)); + assertTrue(wordBoundaries.hasBoundaries()); + speech.reset(); + + // Pause speech. + speechController.onPlayPauseToggle(element); + assertFalse(speechController.isSpeechActive()); + assertEquals(1, speech.getCallCount('pause')); + speech.reset(); + + // Resume speech. This should cause speech to restart from the + // beginning of the utterance. + speechController.onPlayPauseToggle(element); + + // Speech should restart from the beginning. + spoken = await speech.whenCalled('speak'); + assertEquals(text, spoken.text); + assertTrue(speechController.isSpeechActive()); + }); + test('onNextGranularityClick propagates change', () => { speechController.onNextGranularityClick(); assertEquals(1, readAloudModel.getCallCount('moveSpeechForward'));
diff --git a/chrome/test/interaction/interactive_browser_window_test.cc b/chrome/test/interaction/interactive_browser_window_test.cc index 6505c27..032b147 100644 --- a/chrome/test/interaction/interactive_browser_window_test.cc +++ b/chrome/test/interaction/interactive_browser_window_test.cc
@@ -787,6 +787,16 @@ } InteractiveBrowserWindowTestApi::MultiStep +InteractiveBrowserWindowTestApi::WaitForAndScrollToElement( + ui::ElementIdentifier web_contents, + const DeepQuery& where) { + auto steps = Steps(WaitForElementVisible(web_contents, where), + ScrollIntoView(web_contents, where)); + AddDescriptionPrefix(steps, __func__); + return steps; +} + +InteractiveBrowserWindowTestApi::MultiStep InteractiveBrowserWindowTestApi::WaitForElementVisible( ui::ElementIdentifier web_contents, const DeepQuery& where) {
diff --git a/chrome/test/interaction/interactive_browser_window_test.h b/chrome/test/interaction/interactive_browser_window_test.h index 34e14be..54bb10c0 100644 --- a/chrome/test/interaction/interactive_browser_window_test.h +++ b/chrome/test/interaction/interactive_browser_window_test.h
@@ -418,6 +418,11 @@ [[nodiscard]] StepBuilder ScrollIntoView(ui::ElementIdentifier web_contents, const DeepQuery& where); + // Waits for the element to render and then scrolls it into view. + [[nodiscard]] MultiStep WaitForAndScrollToElement( + ui::ElementIdentifier web_contents, + const DeepQuery& where); + // Waits until the intersection of the element's bounds and the window bounds // are nonempty. [[nodiscard]] MultiStep WaitForElementVisible(
diff --git a/chrome/test/interaction/webcontents_interaction_test_util_browsertest.cc b/chrome/test/interaction/webcontents_interaction_test_util_browsertest.cc index 13976257..5ac955e1 100644 --- a/chrome/test/interaction/webcontents_interaction_test_util_browsertest.cc +++ b/chrome/test/interaction/webcontents_interaction_test_util_browsertest.cc
@@ -1662,10 +1662,10 @@ auto util = WebContentsInteractionTestUtil::ForExistingTabInBrowser( browser(), kWebContentsElementId); auto* const model = browser()->tab_strip_model(); - const int count = model->GetTabCount(); + const int count = model->count(); const int index = model->active_index(); util->LoadPageInNewTab(url, false); - EXPECT_EQ(count + 1, model->GetTabCount()); + EXPECT_EQ(count + 1, model->count()); EXPECT_EQ(index, model->active_index()); } @@ -1676,10 +1676,10 @@ auto util = WebContentsInteractionTestUtil::ForExistingTabInBrowser( browser(), kWebContentsElementId); auto* const model = browser()->tab_strip_model(); - const int count = model->GetTabCount(); + const int count = model->count(); const int index = model->active_index(); util->LoadPageInNewTab(url, true); - EXPECT_EQ(count + 1, model->GetTabCount()); + EXPECT_EQ(count + 1, model->count()); EXPECT_EQ(index + 1, model->active_index()); }
diff --git a/clank b/clank index 4e03d7f..11ba6df 160000 --- a/clank +++ b/clank
@@ -1 +1 @@ -Subproject commit 4e03d7f1d820432e53f07bc1767ccf69e771c62d +Subproject commit 11ba6df62aa898c8ee3e52e1dc7ead2903903eb4
diff --git a/components/autofill/android/BUILD.gn b/components/autofill/android/BUILD.gn index 99d7c3b..be728f90 100644 --- a/components/autofill/android/BUILD.gn +++ b/components/autofill/android/BUILD.gn
@@ -265,10 +265,14 @@ "java/src/org/chromium/components/autofill/LoyaltyCard.java", "java/src/org/chromium/components/autofill/PaymentsPayload.java", "java/src/org/chromium/components/autofill/SubKeyRequester.java", + "java/src/org/chromium/components/autofill/autofill_ai/AttributeInstance.java", + "java/src/org/chromium/components/autofill/autofill_ai/AttributeType.java", + "java/src/org/chromium/components/autofill/autofill_ai/EntityType.java", ] srcjar_deps = [ ":autofill_core_browser_java_enums", ":main_autofill_jni_headers", + "//components/autofill/core/browser:autofill_ai_core_browser_java_enums", ] resources_package = "org.chromium.components.autofill" } @@ -285,6 +289,9 @@ "java/src/org/chromium/components/autofill/LoyaltyCard.java", "java/src/org/chromium/components/autofill/PaymentsPayload.java", "java/src/org/chromium/components/autofill/SubKeyRequester.java", + "java/src/org/chromium/components/autofill/autofill_ai/AttributeInstance.java", + "java/src/org/chromium/components/autofill/autofill_ai/AttributeType.java", + "java/src/org/chromium/components/autofill/autofill_ai/EntityType.java", ] }
diff --git a/components/autofill/android/java/src/org/chromium/components/autofill/autofill_ai/AttributeInstance.java b/components/autofill/android/java/src/org/chromium/components/autofill/autofill_ai/AttributeInstance.java new file mode 100644 index 0000000..7e9d5c3 --- /dev/null +++ b/components/autofill/android/java/src/org/chromium/components/autofill/autofill_ai/AttributeInstance.java
@@ -0,0 +1,87 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.components.autofill.autofill_ai; + +import org.jni_zero.CalledByNative; +import org.jni_zero.JNINamespace; +import org.jni_zero.JniType; + +import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.Nullable; + +import java.time.LocalDate; + +/** Represents information of an Autofill AI attribute instance. */ +@JNINamespace("autofill") +@NullMarked +public class AttributeInstance { + /** + * Entity attributes hold either a raw string value (such as passport numbers) or date values. + */ + public sealed interface AttributeValue permits StringValue, DateValue {} + + public static final class StringValue implements AttributeValue { + private final String mValue; + + public StringValue(String value) { + mValue = value; + } + + @CalledByNative + public String getValue() { + return mValue; + } + } + + public static final class DateValue implements AttributeValue { + private final @Nullable LocalDate mDate; + + public DateValue(String day, String month, String year) { + if (day.isEmpty() || month.isEmpty() || year.isEmpty()) { + this.mDate = null; + } else { + this.mDate = + LocalDate.of( + Integer.parseInt(day), + Integer.parseInt(month), + Integer.parseInt(year)); + } + } + + @CalledByNative + public String getDay() { + return mDate != null ? Integer.toString(mDate.getDayOfMonth()) : ""; + } + + @CalledByNative + public String getMonth() { + return mDate != null ? Integer.toString(mDate.getMonthValue()) : ""; + } + + @CalledByNative + public String getYear() { + return mDate != null ? Integer.toString(mDate.getYear()) : ""; + } + } + + public final AttributeType attributeType; + public final @Nullable AttributeValue attributeValue; + + @CalledByNative + public AttributeInstance( + AttributeType attributeType, + @JniType("std::u16string") String day, + @JniType("std::u16string") String month, + @JniType("std::u16string") String year) { + this.attributeType = attributeType; + this.attributeValue = new DateValue(day, month, year); + } + + @CalledByNative + public AttributeInstance(AttributeType attributeType, @JniType("std::u16string") String value) { + this.attributeType = attributeType; + this.attributeValue = new StringValue(value); + } +}
diff --git a/components/autofill/android/java/src/org/chromium/components/autofill/autofill_ai/AttributeType.java b/components/autofill/android/java/src/org/chromium/components/autofill/autofill_ai/AttributeType.java new file mode 100644 index 0000000..6495a8bc0 --- /dev/null +++ b/components/autofill/android/java/src/org/chromium/components/autofill/autofill_ai/AttributeType.java
@@ -0,0 +1,31 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.components.autofill.autofill_ai; + +import org.jni_zero.CalledByNative; +import org.jni_zero.JNINamespace; + +import org.chromium.build.annotations.NullMarked; + +/** Represents information of an Autofill AI attribute type. */ +@JNINamespace("autofill") +@NullMarked +public class AttributeType { + // This maps to a C++ enum which defines the name/type of the attribute. + public final @AttributeTypeName int typeName; + // The name of the attribute as displayed to the user. + public final String typeNameAsString; + // The `dataType` defined whether the input rendered for the attribute should be a country + // selector, a date picker or a simple text field. + public final @DataType int dataType; + + @CalledByNative + public AttributeType( + @AttributeTypeName int typeName, String typeNameAsString, @DataType int dataType) { + this.typeName = typeName; + this.typeNameAsString = typeNameAsString; + this.dataType = dataType; + } +}
diff --git a/components/autofill/android/java/src/org/chromium/components/autofill/autofill_ai/EntityType.java b/components/autofill/android/java/src/org/chromium/components/autofill/autofill_ai/EntityType.java new file mode 100644 index 0000000..651b050 --- /dev/null +++ b/components/autofill/android/java/src/org/chromium/components/autofill/autofill_ai/EntityType.java
@@ -0,0 +1,48 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.components.autofill.autofill_ai; + +import org.jni_zero.CalledByNative; +import org.jni_zero.JNINamespace; + +import org.chromium.build.annotations.NullMarked; + +/** + * Represents information of an Autofill AI entity type, used in the management page to build the + * UI. + */ +@JNINamespace("autofill") +@NullMarked +public class EntityType { + // This maps to a C++ enum which defines the name/type of the entity. + public final @EntityTypeName int typeName; + // When `isReadOnly` is true, this entity type does not allow adding, deleting or editing. + public final Boolean isReadOnly; + // Used to sort entity types and groups and as title of each entity group in the list of + // entities. + public final String typeNameAsString; + // Used as title in the add entity dialog. + public final String addEntityTypeString; + // Used as title in the edit entity dialog. + public final String editEntityTypeString; + // Used as title in the delete entity dialog. + public final String deleteEntityTypeString; + + @CalledByNative + public EntityType( + @EntityTypeName int typeName, + Boolean isReadOnly, + String typeNameAsString, + String addEntityTypeString, + String editEntityTypeString, + String deleteEntityTypeString) { + this.typeName = typeName; + this.isReadOnly = isReadOnly; + this.typeNameAsString = typeNameAsString; + this.addEntityTypeString = addEntityTypeString; + this.editEntityTypeString = editEntityTypeString; + this.deleteEntityTypeString = deleteEntityTypeString; + } +}
diff --git a/components/autofill/core/browser/BUILD.gn b/components/autofill/core/browser/BUILD.gn index a86f075..f75bad8 100644 --- a/components/autofill/core/browser/BUILD.gn +++ b/components/autofill/core/browser/BUILD.gn
@@ -1142,6 +1142,16 @@ ] } +if (is_android) { + java_cpp_enum("autofill_ai_core_browser_java_enums") { + sources = [ + "$target_gen_dir/data_model/autofill_ai/entity_type_names.h", + "data_model/autofill_ai/entity_type.h", + ] + deps = [ ":entity_schema_enums_and_functions" ] + } +} + static_library("test_support") { testonly = true sources = [
diff --git a/components/autofill/core/browser/data_model/autofill_ai/entity_type.h b/components/autofill/core/browser/data_model/autofill_ai/entity_type.h index feced053..ac3bbfa 100644 --- a/components/autofill/core/browser/data_model/autofill_ai/entity_type.h +++ b/components/autofill/core/browser/data_model/autofill_ai/entity_type.h
@@ -43,6 +43,7 @@ class AttributeType final { public: // The underlying representation of the data stored in this attribute. + // GENERATED_JAVA_ENUM_PACKAGE: org.chromium.components.autofill.autofill_ai enum class DataType { kCountry, kDate,
diff --git a/components/autofill/core/browser/data_model/autofill_ai/transpile_entity_schema.py b/components/autofill/core/browser/data_model/autofill_ai/transpile_entity_schema.py index f04cdf3..886b951a 100755 --- a/components/autofill/core/browser/data_model/autofill_ai/transpile_entity_schema.py +++ b/components/autofill/core/browser/data_model/autofill_ai/transpile_entity_schema.py
@@ -62,8 +62,10 @@ for entity in schema for attribute in entity['attributes'] ) + yield f'// GENERATED_JAVA_ENUM_PACKAGE: org.chromium.components.autofill.autofill_ai' yield f'enum class EntityTypeName {{ {", ".join(add_kMaxValue(entities))} }};' yield '' + yield f'// GENERATED_JAVA_ENUM_PACKAGE: org.chromium.components.autofill.autofill_ai' yield f'enum class AttributeTypeName {{ {", ".join(add_kMaxValue(attributes))} }};'
diff --git a/components/browser_ui/accessibility/android/java/src/org/chromium/components/browser_ui/accessibility/AccessibilitySettings.java b/components/browser_ui/accessibility/android/java/src/org/chromium/components/browser_ui/accessibility/AccessibilitySettings.java index c604584..f80a15b 100644 --- a/components/browser_ui/accessibility/android/java/src/org/chromium/components/browser_ui/accessibility/AccessibilitySettings.java +++ b/components/browser_ui/accessibility/android/java/src/org/chromium/components/browser_ui/accessibility/AccessibilitySettings.java
@@ -22,6 +22,7 @@ import org.chromium.components.browser_ui.settings.EmbeddableSettingsPage; import org.chromium.components.browser_ui.settings.SettingsFragment; import org.chromium.components.browser_ui.settings.SettingsUtils; +import org.chromium.components.browser_ui.settings.search.BaseSearchIndexProvider; import org.chromium.components.browser_ui.site_settings.AllSiteSettings; import org.chromium.components.browser_ui.site_settings.SingleCategorySettings; import org.chromium.components.browser_ui.site_settings.SiteSettingsCategory; @@ -251,4 +252,9 @@ public boolean hasDivider() { return false; } + + // TODO(crbug.com/444470792): Determine what pieces of logic are dynamic and need handling. + public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = + new BaseSearchIndexProvider( + AccessibilitySettings.class.getName(), R.xml.accessibility_preferences); }
diff --git a/components/browser_ui/settings/android/BUILD.gn b/components/browser_ui/settings/android/BUILD.gn index 11293455..46f8b68 100644 --- a/components/browser_ui/settings/android/BUILD.gn +++ b/components/browser_ui/settings/android/BUILD.gn
@@ -17,6 +17,10 @@ "java/src/org/chromium/components/browser_ui/settings/SettingsFragment.java", "java/src/org/chromium/components/browser_ui/settings/SettingsNavigation.java", "java/src/org/chromium/components/browser_ui/settings/SettingsUtils.java", + "java/src/org/chromium/components/browser_ui/settings/search/BaseSearchIndexProvider.java", + "java/src/org/chromium/components/browser_ui/settings/search/PreferenceParser.java", + "java/src/org/chromium/components/browser_ui/settings/search/SearchIndexProvider.java", + "java/src/org/chromium/components/browser_ui/settings/search/SettingsIndexData.java", "widget/java/src/org/chromium/components/browser_ui/settings/ButtonPreference.java", "widget/java/src/org/chromium/components/browser_ui/settings/CardPreference.java", "widget/java/src/org/chromium/components/browser_ui/settings/CardWithButtonPreference.java", @@ -158,11 +162,17 @@ robolectric_library("junit") { testonly = true - sources = [ "java/src/org/chromium/components/browser_ui/settings/ManagedPreferencesUtilsTest.java" ] + sources = [ + "java/src/org/chromium/components/browser_ui/settings/ManagedPreferencesUtilsTest.java", + "junit/src/org/chromium/components/browser_ui/settings/search/BaseSearchIndexProviderTest.java", + "junit/src/org/chromium/components/browser_ui/settings/search/PreferenceParserTest.java", + "junit/src/org/chromium/components/browser_ui/settings/search/SettingsIndexDataTest.java", + ] deps = [ ":java", ":java_resources", + ":java_test_resources", ":managed_prefs_java_resources", ":test_support_java", "//base:base_java", @@ -211,6 +221,9 @@ android_resources("java_test_resources") { testonly = true sources = [ + "java/res_test/xml/test_search_child_prefs.xml", + "java/res_test/xml/test_search_grandchild_prefs.xml", + "java/res_test/xml/test_search_root_prefs.xml", "widget/java_test_resources/res/layout/chrome_managed_preference_with_custom_layout.xml", "widget/java_test_resources/res/xml/test_chrome_base_checkbox_preference_screen.xml", "widget/java_test_resources/res/xml/test_chrome_base_preference_screen.xml",
diff --git a/components/browser_ui/settings/android/java/res_test/xml/test_search_child_prefs.xml b/components/browser_ui/settings/android/java/res_test/xml/test_search_child_prefs.xml new file mode 100644 index 0000000..931e6fe --- /dev/null +++ b/components/browser_ui/settings/android/java/res_test/xml/test_search_child_prefs.xml
@@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +Copyright 2025 The Chromium Authors +Use of this source code is governed by a BSD-style license that can be +found in the LICENSE file. +--> + +<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"> + <!-- A preference to be indexed --> + <CheckBoxPreference + android:key="child_checkbox_pref" + android:title="Child Setting Title" + android:summary="Child Summary" /> + + <!-- A preference that links to the Grandchild Fragment --> + <Preference + android:key="link_to_grandchild" + android:title="Go to Grandchild" + android:fragment="org.chromium.TestGrandchildFragment" /> +</PreferenceScreen>
diff --git a/components/browser_ui/settings/android/java/res_test/xml/test_search_grandchild_prefs.xml b/components/browser_ui/settings/android/java/res_test/xml/test_search_grandchild_prefs.xml new file mode 100644 index 0000000..cc51579 --- /dev/null +++ b/components/browser_ui/settings/android/java/res_test/xml/test_search_grandchild_prefs.xml
@@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +Copyright 2025 The Chromium Authors +Use of this source code is governed by a BSD-style license that can be +found in the LICENSE file. +--> + +<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"> + <Preference + android:key="grandchild_item" + android:title="Grandchild Item" /> +</PreferenceScreen>
diff --git a/components/browser_ui/settings/android/java/res_test/xml/test_search_root_prefs.xml b/components/browser_ui/settings/android/java/res_test/xml/test_search_root_prefs.xml new file mode 100644 index 0000000..fe7a8695 --- /dev/null +++ b/components/browser_ui/settings/android/java/res_test/xml/test_search_root_prefs.xml
@@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +Copyright 2025 The Chromium Authors +Use of this source code is governed by a BSD-style license that can be +found in the LICENSE file. +--> + +<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"> + <!-- Scenario 1: Simple Preference outside a category --> + <Preference + android:key="root_item_1" + android:title="Root Item" /> + + <!-- Scenario 2: PreferenceCategory (Header) --> + <PreferenceCategory + android:title="Test Header Group"> + + <!-- Scenario 3: Preference with Fragment inside a category --> + <Preference + android:key="link_to_child" + android:title="Go to Child" + android:fragment="org.chromium.TestChildFragment" /> + + </PreferenceCategory> +</PreferenceScreen>
diff --git a/chrome/browser/settings/search/java/src/org/chromium/chrome/browser/settings/search/BaseSearchIndexProvider.java b/components/browser_ui/settings/android/java/src/org/chromium/components/browser_ui/settings/search/BaseSearchIndexProvider.java similarity index 97% rename from chrome/browser/settings/search/java/src/org/chromium/chrome/browser/settings/search/BaseSearchIndexProvider.java rename to components/browser_ui/settings/android/java/src/org/chromium/components/browser_ui/settings/search/BaseSearchIndexProvider.java index 3e0c214..ce4c494 100644 --- a/chrome/browser/settings/search/java/src/org/chromium/chrome/browser/settings/search/BaseSearchIndexProvider.java +++ b/components/browser_ui/settings/android/java/src/org/chromium/components/browser_ui/settings/search/BaseSearchIndexProvider.java
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package org.chromium.chrome.browser.settings.search; +package org.chromium.components.browser_ui.settings.search; import android.content.Context;
diff --git a/chrome/browser/settings/search/java/src/org/chromium/chrome/browser/settings/search/PreferenceParser.java b/components/browser_ui/settings/android/java/src/org/chromium/components/browser_ui/settings/search/PreferenceParser.java similarity index 98% rename from chrome/browser/settings/search/java/src/org/chromium/chrome/browser/settings/search/PreferenceParser.java rename to components/browser_ui/settings/android/java/src/org/chromium/components/browser_ui/settings/search/PreferenceParser.java index 7f781c37..f73651a0 100644 --- a/chrome/browser/settings/search/java/src/org/chromium/chrome/browser/settings/search/PreferenceParser.java +++ b/components/browser_ui/settings/android/java/src/org/chromium/components/browser_ui/settings/search/PreferenceParser.java
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package org.chromium.chrome.browser.settings.search; +package org.chromium.components.browser_ui.settings.search; import android.content.Context; import android.content.res.TypedArray;
diff --git a/chrome/browser/settings/search/java/src/org/chromium/chrome/browser/settings/search/SearchIndexProvider.java b/components/browser_ui/settings/android/java/src/org/chromium/components/browser_ui/settings/search/SearchIndexProvider.java similarity index 75% rename from chrome/browser/settings/search/java/src/org/chromium/chrome/browser/settings/search/SearchIndexProvider.java rename to components/browser_ui/settings/android/java/src/org/chromium/components/browser_ui/settings/search/SearchIndexProvider.java index c55f7f0..b79037b 100644 --- a/chrome/browser/settings/search/java/src/org/chromium/chrome/browser/settings/search/SearchIndexProvider.java +++ b/components/browser_ui/settings/android/java/src/org/chromium/components/browser_ui/settings/search/SearchIndexProvider.java
@@ -2,12 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package org.chromium.chrome.browser.settings.search; +package org.chromium.components.browser_ui.settings.search; import android.content.Context; import org.chromium.build.annotations.NullMarked; -import org.chromium.chrome.browser.profiles.Profile; import java.util.Map; import java.util.Set; @@ -52,17 +51,4 @@ * @param indexData The central {@link SettingsIndexData} object to be populated. */ default void updateDynamicPreferences(Context context, SettingsIndexData indexData) {} - - /** - * Similar to {@link #updateDynamicPreferences(Context, SettingsIndexData)} but takes in the - * profile. This is for fragments that rely on the profile. - * - * @param context The {@link Context} used to access application resources. - * @param indexData The central {@link SettingsIndexData} object to be populated. - * @param profile The current {@link Profile}. - */ - default void updateDynamicPreferences( - Context context, SettingsIndexData indexData, Profile profile) { - updateDynamicPreferences(context, indexData); - } }
diff --git a/chrome/browser/settings/search/java/src/org/chromium/chrome/browser/settings/search/SettingsIndexData.java b/components/browser_ui/settings/android/java/src/org/chromium/components/browser_ui/settings/search/SettingsIndexData.java similarity index 99% rename from chrome/browser/settings/search/java/src/org/chromium/chrome/browser/settings/search/SettingsIndexData.java rename to components/browser_ui/settings/android/java/src/org/chromium/components/browser_ui/settings/search/SettingsIndexData.java index e16a63fd..708e7d87 100644 --- a/chrome/browser/settings/search/java/src/org/chromium/chrome/browser/settings/search/SettingsIndexData.java +++ b/components/browser_ui/settings/android/java/src/org/chromium/components/browser_ui/settings/search/SettingsIndexData.java
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package org.chromium.chrome.browser.settings.search; +package org.chromium.components.browser_ui.settings.search; import android.os.Bundle; import android.text.TextUtils;
diff --git a/components/browser_ui/settings/android/junit/src/org/chromium/components/browser_ui/settings/search/BaseSearchIndexProviderTest.java b/components/browser_ui/settings/android/junit/src/org/chromium/components/browser_ui/settings/search/BaseSearchIndexProviderTest.java new file mode 100644 index 0000000..d4edf49a --- /dev/null +++ b/components/browser_ui/settings/android/junit/src/org/chromium/components/browser_ui/settings/search/BaseSearchIndexProviderTest.java
@@ -0,0 +1,136 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.components.browser_ui.settings.search; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import android.content.Context; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.chromium.base.ContextUtils; +import org.chromium.base.test.BaseRobolectricTestRunner; +import org.chromium.components.browser_ui.settings.test.R; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * Unit tests for {@link BaseSearchIndexProvider}. + * + * <p>These tests validate the core architectural behavior of the default search provider. + */ +@RunWith(BaseRobolectricTestRunner.class) +public class BaseSearchIndexProviderTest { + + private Context mContext; + private SettingsIndexData mIndexData; + + private static final String FRAGMENT_ROOT = "org.chromium.TestRootFragment"; + private static final String FRAGMENT_CHILD = "org.chromium.TestChildFragment"; + private static final String FRAGMENT_GRANDCHILD = "org.chromium.TestGrandchildFragment"; + + private BaseSearchIndexProvider mRootProvider; + private BaseSearchIndexProvider mChildProvider; + private BaseSearchIndexProvider mGrandchildProvider; + + @Before + public void setUp() { + mContext = ContextUtils.getApplicationContext(); + mIndexData = new SettingsIndexData(); + + mRootProvider = new BaseSearchIndexProvider(FRAGMENT_ROOT, R.xml.test_search_root_prefs); + mChildProvider = new BaseSearchIndexProvider(FRAGMENT_CHILD, R.xml.test_search_child_prefs); + mGrandchildProvider = + new BaseSearchIndexProvider( + FRAGMENT_GRANDCHILD, R.xml.test_search_grandchild_prefs); + } + + @Test + public void testRegisterFragmentHeaders_buildsParentMapRecursively() { + Map<String, SearchIndexProvider> providerMap = new HashMap<>(); + providerMap.put(mRootProvider.getPrefFragmentName(), mRootProvider); + providerMap.put(mChildProvider.getPrefFragmentName(), mChildProvider); + providerMap.put(mGrandchildProvider.getPrefFragmentName(), mGrandchildProvider); + Set<String> processedFragments = new HashSet<>(); + + mRootProvider.registerFragmentHeaders( + mContext, mIndexData, providerMap, processedFragments); + + Map<String, List<String>> parentMap = mIndexData.getChildFragmentToParentKeysForTesting(); + assertFalse("Parent map should not be empty after registration.", parentMap.isEmpty()); + + // Verify Root -> Child link + // "link_to_child" is defined in test_search_root_prefs.xml + String expectedChildParentKey = + PreferenceParser.createUniqueId(FRAGMENT_ROOT, "link_to_child"); + + assertTrue( + "Map should contain a link to the Child Fragment.", + parentMap.containsKey(FRAGMENT_CHILD)); + assertEquals( + "Child's parent preference should be the key from root XML.", + expectedChildParentKey, + parentMap.get(FRAGMENT_CHILD).get(0)); + + // Verify Child -> Grandchild link + // "link_to_grandchild" is defined in test_search_child_prefs.xml + String expectedGrandchildParentKey = + PreferenceParser.createUniqueId(FRAGMENT_CHILD, "link_to_grandchild"); + + assertTrue( + "Map should contain a link to the Grandchild Fragment.", + parentMap.containsKey(FRAGMENT_GRANDCHILD)); + assertEquals( + "Grandchild's parent preference should be the key from child XML.", + expectedGrandchildParentKey, + parentMap.get(FRAGMENT_GRANDCHILD).get(0)); + } + + @Test + public void testInitPreferenceXml_addsEntriesFromXml() { + mChildProvider.initPreferenceXml(mContext, mIndexData); + + Map<String, SettingsIndexData.Entry> entries = mIndexData.getEntriesForTesting(); + assertFalse("Index should not be empty after indexing.", entries.isEmpty()); + + // "child_checkbox_pref" is defined in test_search_child_prefs.xml + final String originalKey = "child_checkbox_pref"; + final String uniqueKey = PreferenceParser.createUniqueId(FRAGMENT_CHILD, originalKey); + + SettingsIndexData.Entry entry = entries.get(uniqueKey); + assertNotNull("Preference should be indexed.", entry); + assertEquals("Key should match.", originalKey, entry.key); + assertEquals("Title should match the string resource.", "Child Setting Title", entry.title); + assertEquals("Parent fragment name should be set.", FRAGMENT_CHILD, entry.parentFragment); + } + + @Test + public void testProviderWithNoXml_doesNothing() { + BaseSearchIndexProvider providerWithNoXml = + new BaseSearchIndexProvider("some.fragment.Name"); + Map<String, SearchIndexProvider> providerMap = new HashMap<>(); + Set<String> processedFragments = new HashSet<>(); + + providerWithNoXml.initPreferenceXml(mContext, mIndexData); + assertTrue( + "Provider with no XML should not add any entries.", + mIndexData.getEntriesForTesting().isEmpty()); + + providerWithNoXml.registerFragmentHeaders( + mContext, mIndexData, providerMap, processedFragments); + assertTrue( + "Provider with no XML should not add any parent-child links.", + mIndexData.getChildFragmentToParentKeysForTesting().isEmpty()); + } +}
diff --git a/components/browser_ui/settings/android/junit/src/org/chromium/components/browser_ui/settings/search/PreferenceParserTest.java b/components/browser_ui/settings/android/junit/src/org/chromium/components/browser_ui/settings/search/PreferenceParserTest.java new file mode 100644 index 0000000..a09e39d5d --- /dev/null +++ b/components/browser_ui/settings/android/junit/src/org/chromium/components/browser_ui/settings/search/PreferenceParserTest.java
@@ -0,0 +1,126 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.components.browser_ui.settings.search; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +import android.content.Context; +import android.os.Bundle; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.chromium.base.ContextUtils; +import org.chromium.base.test.BaseRobolectricTestRunner; +import org.chromium.build.annotations.Nullable; +import org.chromium.components.browser_ui.settings.test.R; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** Unit tests for {@link PreferenceParser}. */ +@RunWith(BaseRobolectricTestRunner.class) +public class PreferenceParserTest { + + private Context mContext; + + private static final String FRAGMENT_MAIN = "org.chromium.TestMainFragment"; + private static final String FRAGMENT_CHILD = "org.chromium.TestChildFragment"; + + @Before + public void setUp() { + mContext = ContextUtils.getApplicationContext(); + } + + @Test + public void testParsePreferences_parsesBasicAttributesCorrectly() throws Exception { + List<Bundle> parsedMetadata = + PreferenceParser.parsePreferences(mContext, R.xml.test_search_root_prefs); + assertNotNull("The parsed metadata should not be null.", parsedMetadata); + + // In test_search_root_prefs.xml, we have "link_to_child" + @Nullable Bundle childBundle = findBundleByKey(parsedMetadata, "link_to_child"); + assertNotNull("The 'link_to_child' preference should be found.", childBundle); + + // Verify the basic attributes are correctly parsed. + assertEquals("Go to Child", childBundle.getString(PreferenceParser.METADATA_TITLE)); + assertEquals(FRAGMENT_CHILD, childBundle.getString(PreferenceParser.METADATA_FRAGMENT)); + } + + @Test + public void testParsePreferences_handlesPreferenceWithNoFragment() throws Exception { + List<Bundle> parsedMetadata = + PreferenceParser.parsePreferences(mContext, R.xml.test_search_root_prefs); + + // In test_search_root_prefs.xml, "root_item_1" has no android:fragment attribute. + @Nullable Bundle simpleBundle = findBundleByKey(parsedMetadata, "root_item_1"); + assertNotNull("The 'root_item_1' preference should be found.", simpleBundle); + + assertNull( + "The 'root_item_1' preference should not have a fragment attribute.", + simpleBundle.getString(PreferenceParser.METADATA_FRAGMENT)); + } + + @Test + public void testParseAndRegisterHeaders_addsParentLinks() { + SettingsIndexData indexData = new SettingsIndexData(); + Map<String, SearchIndexProvider> providerMap = new HashMap<>(); + + // Simulate a provider for the child fragment + providerMap.put( + FRAGMENT_CHILD, + new BaseSearchIndexProvider(FRAGMENT_CHILD, R.xml.test_search_child_prefs)); + + Set<String> processedFragments = new HashSet<>(); + + PreferenceParser.parseAndRegisterHeaders( + mContext, + R.xml.test_search_root_prefs, + FRAGMENT_MAIN, + indexData, + providerMap, + processedFragments); + + Map<String, List<String>> parentMap = indexData.getChildFragmentToParentKeysForTesting(); + assertFalse("The parent-child map should not be empty after parsing.", parentMap.isEmpty()); + + assertTrue( + "Map should contain an entry for the Child Fragment.", + parentMap.containsKey(FRAGMENT_CHILD)); + + List<String> childParents = parentMap.get(FRAGMENT_CHILD); + assertEquals( + "Child Fragment should have one parent in this context.", 1, childParents.size()); + + String expectedUniqueId = PreferenceParser.createUniqueId(FRAGMENT_MAIN, "link_to_child"); + + assertEquals( + "The parent of the Child Fragment should be the 'link_to_child' preference.", + expectedUniqueId, + childParents.get(0)); + + assertTrue( + "The parsed root fragment should be marked as processed.", + processedFragments.contains(FRAGMENT_MAIN)); + } + + @Nullable + private Bundle findBundleByKey(List<Bundle> metadata, String key) { + for (Bundle bundle : metadata) { + if (key.equals(bundle.getString(PreferenceParser.METADATA_KEY))) { + return bundle; + } + } + return null; + } +}
diff --git a/chrome/browser/settings/search/junit/src/org/chromium/chrome/browser/settings/search/SettingsIndexDataTest.java b/components/browser_ui/settings/android/junit/src/org/chromium/components/browser_ui/settings/search/SettingsIndexDataTest.java similarity index 99% rename from chrome/browser/settings/search/junit/src/org/chromium/chrome/browser/settings/search/SettingsIndexDataTest.java rename to components/browser_ui/settings/android/junit/src/org/chromium/components/browser_ui/settings/search/SettingsIndexDataTest.java index 1d899498..66eaa723 100644 --- a/chrome/browser/settings/search/junit/src/org/chromium/chrome/browser/settings/search/SettingsIndexDataTest.java +++ b/components/browser_ui/settings/android/junit/src/org/chromium/components/browser_ui/settings/search/SettingsIndexDataTest.java
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package org.chromium.chrome.browser.settings.search; +package org.chromium.components.browser_ui.settings.search; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse;
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 decfae81b..f25f916b 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
@@ -31,6 +31,7 @@ import org.chromium.components.browser_ui.settings.CustomDividerFragment; import org.chromium.components.browser_ui.settings.EmbeddableSettingsPage; import org.chromium.components.browser_ui.settings.ManagedPreferencesUtils; +import org.chromium.components.browser_ui.settings.search.BaseSearchIndexProvider; import org.chromium.components.browser_ui.util.TraceEventVectorDrawableCompat; import java.util.ArrayList; @@ -360,4 +361,9 @@ public @AnimationType int getAnimationType() { return AnimationType.PROPERTY; } + + // TODO(crbug.com/444470792): Determine what entries need to be created and added under + // #updateDynamicPreferences. + public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = + new BaseSearchIndexProvider(ChosenObjectSettings.class.getName(), 0); }
diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/GroupedWebsitesSettings.java b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/GroupedWebsitesSettings.java index e427af8..eb415c0 100644 --- a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/GroupedWebsitesSettings.java +++ b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/GroupedWebsitesSettings.java
@@ -29,6 +29,7 @@ import org.chromium.components.browser_ui.settings.EmbeddableSettingsPage; import org.chromium.components.browser_ui.settings.SettingsUtils; import org.chromium.components.browser_ui.settings.TextMessagePreference; +import org.chromium.components.browser_ui.settings.search.BaseSearchIndexProvider; import org.chromium.components.browsing_data.DeleteBrowsingDataAction; /** Shows the permissions and other settings for a group of websites. */ @@ -312,4 +313,9 @@ public @AnimationType int getAnimationType() { return AnimationType.PROPERTY; } + + // TODO(crbug.com/444470792): Determine which prefs need creation in updateDynamicPreferences. + public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = + new BaseSearchIndexProvider( + GroupedWebsitesSettings.class.getName(), R.xml.grouped_websites_preferences); }
diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/RwsCookieSettings.java b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/RwsCookieSettings.java index b9f632a..fd2e39c 100644 --- a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/RwsCookieSettings.java +++ b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/RwsCookieSettings.java
@@ -24,6 +24,7 @@ import org.chromium.components.browser_ui.settings.ManagedPreferenceDelegate; import org.chromium.components.browser_ui.settings.SettingsUtils; import org.chromium.components.browser_ui.settings.TextMessagePreference; +import org.chromium.components.browser_ui.settings.search.BaseSearchIndexProvider; import org.chromium.components.content_settings.CookieControlsMode; import org.chromium.components.prefs.PrefService; import org.chromium.components.user_prefs.UserPrefs; @@ -175,4 +176,9 @@ public @AnimationType int getAnimationType() { return AnimationType.PROPERTY; } + + // TODO(crbug.com/444470792): Determine what pieces of logic are dynamic and need handling. + public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = + new BaseSearchIndexProvider( + RwsCookieSettings.class.getName(), R.xml.rws_cookie_settings); }
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 92586ca..3852976 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
@@ -67,6 +67,7 @@ import org.chromium.components.browser_ui.settings.SettingsFragment; import org.chromium.components.browser_ui.settings.SettingsNavigation; import org.chromium.components.browser_ui.settings.SettingsUtils; +import org.chromium.components.browser_ui.settings.search.BaseSearchIndexProvider; import org.chromium.components.browser_ui.site_settings.AddExceptionPreference.SiteAddedCallback; import org.chromium.components.browser_ui.site_settings.AutoDarkMetrics.AutoDarkSettingsChangeSource; import org.chromium.components.browser_ui.styles.SemanticColorUtils; @@ -2004,4 +2005,9 @@ public @SettingsFragment.AnimationType int getAnimationType() { return SettingsFragment.AnimationType.PROPERTY; } + + // TODO(crbug.com/444470792): Determine what pieces of logic are dynamic and need handling. + public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = + new BaseSearchIndexProvider( + SingleCategorySettings.class.getName(), R.xml.website_preferences); }
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 ab4b83ca..f5376fd 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
@@ -43,6 +43,7 @@ import org.chromium.components.browser_ui.settings.ManagedPreferencesUtils; import org.chromium.components.browser_ui.settings.SettingsUtils; import org.chromium.components.browser_ui.settings.TextMessagePreference; +import org.chromium.components.browser_ui.settings.search.BaseSearchIndexProvider; import org.chromium.components.browsing_data.DeleteBrowsingDataAction; import org.chromium.components.content_settings.ContentSetting; import org.chromium.components.content_settings.ContentSettingsType; @@ -1920,4 +1921,9 @@ public @AnimationType int getAnimationType() { return AnimationType.PROPERTY; } + + // TODO(crbug.com/444470792): Determine what pieces of logic are dynamic and need handling. + public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = + new BaseSearchIndexProvider( + SingleWebsiteSettings.class.getName(), R.xml.single_website_preferences); }
diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SiteSettings.java b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SiteSettings.java index 89db616f..ebaa5bd3 100644 --- a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SiteSettings.java +++ b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SiteSettings.java
@@ -21,6 +21,7 @@ import org.chromium.components.browser_ui.settings.CustomDividerFragment; import org.chromium.components.browser_ui.settings.EmbeddableSettingsPage; import org.chromium.components.browser_ui.settings.SettingsUtils; +import org.chromium.components.browser_ui.settings.search.BaseSearchIndexProvider; import org.chromium.components.browser_ui.site_settings.SiteSettingsCategory.Type; import org.chromium.components.content_settings.ContentSetting; import org.chromium.components.content_settings.CookieControlsMode; @@ -270,4 +271,9 @@ public @Nullable String getMainMenuKey() { return "content_settings"; } + + // TODO(crbug.com/444470792): Determine what pieces of logic are dynamic and need handling. + public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = + new BaseSearchIndexProvider( + SiteSettings.class.getName(), R.xml.site_settings_preferences); }
diff --git a/components/browser_ui/styles/android/java/src/org/chromium/components/browser_ui/styles/IncognitoColors.java b/components/browser_ui/styles/android/java/src/org/chromium/components/browser_ui/styles/IncognitoColors.java index e141d4b..eae9eaaae 100644 --- a/components/browser_ui/styles/android/java/src/org/chromium/components/browser_ui/styles/IncognitoColors.java +++ b/components/browser_ui/styles/android/java/src/org/chromium/components/browser_ui/styles/IncognitoColors.java
@@ -96,24 +96,24 @@ : R.style.TextAppearance_TextMedium_Primary; } - /** Returns the correct text appearance style res for primary colored small text. */ - public static @StyleRes int getTextSmallPrimary(boolean isIncognito) { + /** Returns the correct text appearance style res for TODO colored TODO text. */ + public static @StyleRes int getTextMediumThickPrimary(boolean isIncognito) { return isIncognito - ? R.style.TextAppearance_TextSmall_Primary_Baseline_Light - : R.style.TextAppearance_TextSmall_Primary; + ? R.style.TextAppearance_TextMediumThick_Primary_Baseline_Light + : R.style.TextAppearance_TextMediumThick_Primary; } - /** Returns the correct text appearance style res for accent1 colored small text. */ - public static @StyleRes int getTextSmallAccent1(boolean isIncognito) { + /** Returns the correct text appearance style res for TODO colored TODO text. */ + public static @StyleRes int getTextMediumThickAccent1(boolean isIncognito) { return isIncognito - ? R.style.TextAppearance_TextSmall_Blue_Baseline_Light - : R.style.TextAppearance_TextSmall_Accent1; + ? R.style.TextAppearance_TextMediumThick_Blue_Baseline_Light + : R.style.TextAppearance_TextMediumThick_Accent1; } - /** Returns the correct text appearance style res for secondary colored small text. */ - public static @StyleRes int getTextSmallSecondary(boolean isIncognito) { + /** Returns the correct text appearance style res for TODO colored TODO text. */ + public static @StyleRes int getTextMediumThickSecondary(boolean isIncognito) { return isIncognito - ? R.style.TextAppearance_TextSmall_Secondary_Baseline_Light - : R.style.TextAppearance_TextSmall_Secondary; + ? R.style.TextAppearance_TextMediumThick_Secondary_Baseline_Light + : R.style.TextAppearance_TextMediumThick_Secondary; } }
diff --git a/components/continuous_search/renderer/BUILD.gn b/components/continuous_search/renderer/BUILD.gn index 3080ccb4..41aa2e11 100644 --- a/components/continuous_search/renderer/BUILD.gn +++ b/components/continuous_search/renderer/BUILD.gn
@@ -12,6 +12,7 @@ deps = [ "//base", + "//build:buildflag_header_h", "//components/continuous_search/common", "//components/continuous_search/common/public/mojom", "//content/public/renderer",
diff --git a/components/continuous_search/renderer/config.cc b/components/continuous_search/renderer/config.cc index b9a7b7d..51492423 100644 --- a/components/continuous_search/renderer/config.cc +++ b/components/continuous_search/renderer/config.cc
@@ -4,8 +4,6 @@ #include "components/continuous_search/renderer/config.h" -#include "base/feature_list.h" -#include "base/metrics/field_trial_params.h" #include "base/no_destructor.h" namespace continuous_search { @@ -19,27 +17,7 @@ } // namespace -BASE_FEATURE(kRelatedSearchesExtraction, base::FEATURE_ENABLED_BY_DEFAULT); - -Config::Config() { - std::string id_value = base::GetFieldTrialParamValueByFeature( - kRelatedSearchesExtraction, "related_searches_id"); - if (!id_value.empty()) { - related_searches_id = id_value; - } - - std::string anchor_value = base::GetFieldTrialParamValueByFeature( - kRelatedSearchesExtraction, "related_searches_anchor_classname"); - if (!anchor_value.empty()) { - related_searches_anchor_classname = anchor_value; - } - - std::string title_value = base::GetFieldTrialParamValueByFeature( - kRelatedSearchesExtraction, "related_searches_title_classname"); - if (!title_value.empty()) { - related_searches_title_classname = title_value; - } -} +Config::Config() = default; Config::Config(const Config& other) = default; Config::~Config() = default;
diff --git a/components/continuous_search/renderer/config.h b/components/continuous_search/renderer/config.h index 4f55087e..6c07b0e 100644 --- a/components/continuous_search/renderer/config.h +++ b/components/continuous_search/renderer/config.h
@@ -7,13 +7,9 @@ #include <string> -#include "base/feature_list.h" +#include "build/build_config.h" namespace continuous_search { - -BASE_DECLARE_FEATURE(kRelatedSearchesExtraction); - -// Config for the search results extractor. struct Config { // The ID of the related searches container. #if BUILDFLAG(IS_ANDROID)
diff --git a/components/credential_management/android/third_party_credential_manager_bridge.cc b/components/credential_management/android/third_party_credential_manager_bridge.cc index 4bf0e42..94f1b91 100644 --- a/components/credential_management/android/third_party_credential_manager_bridge.cc +++ b/components/credential_management/android/third_party_credential_manager_bridge.cc
@@ -126,6 +126,13 @@ base::OnceCallback<void(PasswordCredentialResponse)> on_complete = base::BindOnce(&OnPasswordCredentialReceived, origin, std::move(completion_callback)); + // The only currently supported credential option is passwords, so if + // passwords are not requested there is nothing to return. + // See crbug.com/465717534. + if (!include_passwords) { + std::move(on_complete).Run(PasswordCredentialResponse(false, u"", u"")); + return; + } jni_delegate_->Get(is_auto_select_allowed, include_passwords, federations, origin, std::move(on_complete)); }
diff --git a/components/credential_management/android/third_party_credential_manager_bridge_unittest.cc b/components/credential_management/android/third_party_credential_manager_bridge_unittest.cc index 2792472..2bcfd83 100644 --- a/components/credential_management/android/third_party_credential_manager_bridge_unittest.cc +++ b/components/credential_management/android/third_party_credential_manager_bridge_unittest.cc
@@ -13,6 +13,7 @@ #include "base/functional/callback_helpers.h" #include "base/run_loop.h" #include "base/test/mock_callback.h" +#include "base/test/test_future.h" #include "base/types/pass_key.h" #include "components/credential_management/android/password_credential_response.h" #include "content/public/browser/browser_thread.h" @@ -131,6 +132,19 @@ run_loop.Run(); } +TEST_F(ThirdPartyCredentialManagerBridgeTest, + TestGetCallWithoutPasswordsFails) { + base::test::TestFuture<password_manager::CredentialManagerError, + const std::optional<password_manager::CredentialInfo>&> + future; + + bridge()->Get(/*is_auto_select_allowed=*/true, /*include_passwords=*/false, + /*federations=*/{}, kTestOrigin, future.GetCallback()); + ASSERT_TRUE(future.Wait()); + EXPECT_EQ(future.Get<0>(), password_manager::CredentialManagerError::UNKNOWN); + EXPECT_FALSE(future.Get<1>().has_value()); +} + TEST_F(ThirdPartyCredentialManagerBridgeTest, TestSuccessfulStoreCall) { base::RunLoop run_loop; base::MockCallback<StoreCallback> mock_callback;
diff --git a/components/cronet/gn2bp/gn_utils.py b/components/cronet/gn2bp/gn_utils.py index aa096c1..e2ebd94 100644 --- a/components/cronet/gn2bp/gn_utils.py +++ b/components/cronet/gn2bp/gn_utils.py
@@ -531,7 +531,10 @@ return target target.testonly = desc.get('testonly', False) - + if target.type == "executable" and desc.get("crate_root", None): + # Find a more decisive way to figure out that this is a rust executable. + # TODO: Add a metadata to the executable from Chromium side. + target.type = "rust_executable" deps = desc.get("deps", []) build_only_deps = [] if custom_processor is not None: @@ -550,10 +553,6 @@ target.arch[arch].sources.update(source for source in desc.get('sources', []) if not source.startswith("//out")) - elif target.type == "rust_executable": - target.arch[arch].sources.update(source - for source in desc.get('sources', []) - if not source.startswith("//out")) elif target.is_linker_unit_type(): target.arch[arch].sources.update(source for source in desc.get('sources', []) @@ -684,7 +683,7 @@ # targets above), are bubbled upward without creating an equivalent # GN target. pass - elif target.type in ["rust_library", "rust_proc_macro"]: + elif target.type in ["rust_library", "rust_proc_macro", "rust_executable"]: target.arch[arch].sources.update(source for source in desc.get('sources', []) if not source.startswith("//out")) @@ -716,10 +715,7 @@ target.arch[arch].rust_flags.extend( self.build_script_outputs.get(label_without_toolchain(gn_target_name), {}).get(chromium_arch, list())) - if target.type == "executable" and target.crate_root: - # Find a more decisive way to figure out that this is a rust executable. - # TODO: Add a metadata to the executable from Chromium side. - target.type = "rust_executable" + if "-frtti" in target.arch[arch].cflags: target.rtti = True
diff --git a/components/data_sharing/data_sharing_internals/resources/data_sharing_internals.ts b/components/data_sharing/data_sharing_internals/resources/data_sharing_internals.ts index 8c2f1c5..5615a677d 100644 --- a/components/data_sharing/data_sharing_internals/resources/data_sharing_internals.ts +++ b/components/data_sharing/data_sharing_internals/resources/data_sharing_internals.ts
@@ -4,7 +4,7 @@ import 'chrome://resources/cr_elements/cr_tab_box/cr_tab_box.js'; -import {assert} from 'chrome://resources/js/assert.js'; +import {assert, assertNotReachedCase} from 'chrome://resources/js/assert.js'; import {getRequiredElement} from 'chrome://resources/js/util.js'; import type {Time} from 'chrome://resources/mojo/mojo/public/mojom/base/time.mojom-webui.js'; @@ -105,6 +105,8 @@ return 'Invitee'; case MemberRole.kFormerMember: return 'FormerMember'; + default: + assertNotReachedCase(role); } }
diff --git a/components/desktop_to_mobile_promos/BUILD.gn b/components/desktop_to_mobile_promos/BUILD.gn index 9ef29b8..a4b3efad 100644 --- a/components/desktop_to_mobile_promos/BUILD.gn +++ b/components/desktop_to_mobile_promos/BUILD.gn
@@ -4,6 +4,8 @@ source_set("desktop_to_mobile_promos") { sources = [ + "desktop_to_mobile_promos_metrics.cc", + "desktop_to_mobile_promos_metrics.h", "features.cc", "features.h", "pref_names.h",
diff --git a/components/desktop_to_mobile_promos/desktop_to_mobile_promos_metrics.cc b/components/desktop_to_mobile_promos/desktop_to_mobile_promos_metrics.cc new file mode 100644 index 0000000..31ccb9a3 --- /dev/null +++ b/components/desktop_to_mobile_promos/desktop_to_mobile_promos_metrics.cc
@@ -0,0 +1,68 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/desktop_to_mobile_promos/desktop_to_mobile_promos_metrics.h" + +#include "base/metrics/histogram_functions.h" +#include "base/notreached.h" +#include "base/strings/strcat.h" + +namespace desktop_to_mobile_promos { + +std::string PromoTypeToString(PromoType type) { + switch (type) { + case PromoType::kPassword: + return "Password"; + case PromoType::kEnhancedBrowsing: + return "EnhancedBrowsing"; + case PromoType::kLens: + return "Lens"; + case PromoType::kAddress: + return "Address"; + case PromoType::kPayment: + return "Payment"; + } +} + +std::string BubbleTypeToString(BubbleType type) { + switch (type) { + case BubbleType::kQRCode: + return "QRCode"; + case BubbleType::kReminder: + return "Reminder"; + case BubbleType::kReminderConfirmation: + return "ReminderConfirmation"; + } +} + +DesktopPromoBubbleType BubbleTypeToDesktopPromoBubbleType(BubbleType type) { + switch (type) { + case BubbleType::kReminder: + return DesktopPromoBubbleType::kReminder; + case BubbleType::kQRCode: + return DesktopPromoBubbleType::kQRCode; + case BubbleType::kReminderConfirmation: + return DesktopPromoBubbleType::kReminderConfirmation; + } +} + +void LogDesktopPromoBubbleCreated(PromoType promo_type, + BubbleType bubble_type) { + base::UmaHistogramEnumeration( + base::StrCat({"UserEducation.DesktopToIOSPromo.", + PromoTypeToString(promo_type), ".BubbleView.Created"}), + BubbleTypeToDesktopPromoBubbleType(bubble_type)); +} + +void LogDesktopPromoAction(PromoType promo_type, + BubbleType bubble_type, + DesktopPromoActionType action) { + base::UmaHistogramEnumeration( + base::StrCat({"UserEducation.DesktopToIOSPromo.", + PromoTypeToString(promo_type), ".", + BubbleTypeToString(bubble_type), ".Action"}), + action); +} + +} // namespace desktop_to_mobile_promos
diff --git a/components/desktop_to_mobile_promos/desktop_to_mobile_promos_metrics.h b/components/desktop_to_mobile_promos/desktop_to_mobile_promos_metrics.h new file mode 100644 index 0000000..95bdb81c --- /dev/null +++ b/components/desktop_to_mobile_promos/desktop_to_mobile_promos_metrics.h
@@ -0,0 +1,42 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_DESKTOP_TO_MOBILE_PROMOS_DESKTOP_TO_MOBILE_PROMOS_METRICS_H_ +#define COMPONENTS_DESKTOP_TO_MOBILE_PROMOS_DESKTOP_TO_MOBILE_PROMOS_METRICS_H_ + +#include "components/desktop_to_mobile_promos/promos_types.h" + +namespace desktop_to_mobile_promos { + +// Enum for the IOS.Desktop.{PromoType}.BubbleView.Created histogram. +// These values are persisted to logs. Entries should not be renumbered and +// numeric values should never be reused. +enum class DesktopPromoBubbleType { + kReminder = 0, + kQRCode = 1, + kReminderConfirmation = 2, + kMaxValue = kReminderConfirmation, +}; + +// Enum for the IOS.Desktop.{PromoType}.{BubbleType}.Action histogram. +// These values are persisted to logs. Entries should not be renumbered and +// numeric values should never be reused. +enum class DesktopPromoActionType { + kAccept = 0, + kCancel = 1, + kDismiss = 2, + kMaxValue = kDismiss, +}; + +// Logs the creation of the promo bubble. +void LogDesktopPromoBubbleCreated(PromoType promo_type, BubbleType bubble_type); + +// Logs the action taken on the promo bubble. +void LogDesktopPromoAction(PromoType promo_type, + BubbleType bubble_type, + DesktopPromoActionType action); + +} // namespace desktop_to_mobile_promos + +#endif // COMPONENTS_DESKTOP_TO_MOBILE_PROMOS_DESKTOP_TO_MOBILE_PROMOS_METRICS_H_
diff --git a/components/dom_distiller/core/android/java/src/org/chromium/components/dom_distiller/core/DomDistillerFeatures.java b/components/dom_distiller/core/android/java/src/org/chromium/components/dom_distiller/core/DomDistillerFeatures.java index a82aad5..c2639de 100644 --- a/components/dom_distiller/core/android/java/src/org/chromium/components/dom_distiller/core/DomDistillerFeatures.java +++ b/components/dom_distiller/core/android/java/src/org/chromium/components/dom_distiller/core/DomDistillerFeatures.java
@@ -38,9 +38,15 @@ && sReaderModeUseReadabilityUseHeuristic.getValue(); } + /** Returns whether to provide new accessible font options in the bottom sheet. */ + public static boolean shouldShowNewAccessibleFontOptions() { + return sReaderModeDistillInApp.isEnabled() && sReaderModeSupportNewFonts.isEnabled(); + } + // Feature names -- alphabetical ordering. public static final String READER_MODE_DISTILL_IN_APP = "ReaderModeDistillInApp"; public static final String READER_MODE_IMPROVEMENTS = "ReaderModeImprovements"; + public static final String READER_MODE_SUPPORT_NEW_FONTS = "ReaderModeSupportNewFonts"; public static final String READER_MODE_USE_READABILITY = "ReaderModeUseReadability"; // Feature flags -- alphabetical ordering. @@ -48,6 +54,8 @@ newMutableFlagWithSafeDefault(READER_MODE_DISTILL_IN_APP, /* defaultValue= */ false); public static final MutableFlagWithSafeDefault sReaderModeImprovements = newMutableFlagWithSafeDefault(READER_MODE_IMPROVEMENTS, /* defaultValue= */ false); + public static final MutableFlagWithSafeDefault sReaderModeSupportNewFonts = + newMutableFlagWithSafeDefault(READER_MODE_SUPPORT_NEW_FONTS, /* defaultValue= */ false); public static final MutableFlagWithSafeDefault sReaderModeUseReadability = newMutableFlagWithSafeDefault(READER_MODE_USE_READABILITY, /* defaultValue= */ false);
diff --git a/components/dom_distiller/core/dom_distiller_features.cc b/components/dom_distiller/core/dom_distiller_features.cc index 261dee6..274f17d5 100644 --- a/components/dom_distiller/core/dom_distiller_features.cc +++ b/components/dom_distiller/core/dom_distiller_features.cc
@@ -71,6 +71,10 @@ : 0; } +#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS) +BASE_FEATURE(kReaderModeSupportNewFonts, base::FEATURE_DISABLED_BY_DEFAULT); +#endif + #if BUILDFLAG(IS_ANDROID) // Feature declarations below -- alphabetical order. BASE_FEATURE(kReaderModeDistillInApp, base::FEATURE_DISABLED_BY_DEFAULT); @@ -81,7 +85,7 @@ static jlong JNI_DomDistillerFeatureMap_GetNativeMap(JNIEnv* env) { static const base::Feature* const kFeaturesExposedToJava[] = { &kReaderModeDistillInApp, &kReaderModeImprovements, - &kReaderModeUseReadability}; + &kReaderModeSupportNewFonts, &kReaderModeUseReadability}; static base::NoDestructor<base::android::FeatureMap> kFeatureMap( kFeaturesExposedToJava); return reinterpret_cast<jlong>(kFeatureMap.get());
diff --git a/components/dom_distiller/core/dom_distiller_features.h b/components/dom_distiller/core/dom_distiller_features.h index 4204c4a..3f93555 100644 --- a/components/dom_distiller/core/dom_distiller_features.h +++ b/components/dom_distiller/core/dom_distiller_features.h
@@ -27,6 +27,11 @@ COMPONENT_EXPORT(DOM_DISTILLER_FEATURES) int GetMinimumAllowableDistilledContentLength(); +#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS) +COMPONENT_EXPORT(DOM_DISTILLER_FEATURES) +BASE_DECLARE_FEATURE(kReaderModeSupportNewFonts); +#endif + #if BUILDFLAG(IS_ANDROID) // Feature declarations below -- alphabetical order. COMPONENT_EXPORT(DOM_DISTILLER_FEATURES)
diff --git a/components/embedder_support/android/java/src/org/chromium/components/embedder_support/util/PasswordEchoSettingState.java b/components/embedder_support/android/java/src/org/chromium/components/embedder_support/util/PasswordEchoSettingState.java index 0861052..505d914 100644 --- a/components/embedder_support/android/java/src/org/chromium/components/embedder_support/util/PasswordEchoSettingState.java +++ b/components/embedder_support/android/java/src/org/chromium/components/embedder_support/util/PasswordEchoSettingState.java
@@ -7,9 +7,7 @@ import android.content.ContentResolver; import android.database.ContentObserver; import android.net.Uri; -import android.os.Build; import android.os.Handler; -import android.os.flagging.AconfigPackage; import android.provider.Settings; import androidx.annotation.VisibleForTesting; @@ -75,10 +73,8 @@ return sSplitEnabledForTesting; } - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.BAKLAVA) { - return AconfigPackage.load("com.android.systemui") - .getBooleanFlagValue("split_show_passwords_to_touch_and_physical", false); - } + // TODO(crbug.com/466343369): Implement the logic to check if the split setting feature is + // enabled on the platform side. return false; }
diff --git a/components/live_caption/translation_util.cc b/components/live_caption/translation_util.cc index defbcbe7..769a7a5 100644 --- a/components/live_caption/translation_util.cc +++ b/components/live_caption/translation_util.cc
@@ -3,6 +3,8 @@ // found in the LICENSE file. #include "components/live_caption/translation_util.h" +#include <utility> + #include "base/strings/strcat.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" @@ -49,16 +51,16 @@ return sentences; } -bool ContainsTrailingSpace(const std::string& str) { +bool ContainsTrailingSpace(std::string_view str) { return !str.empty() && base::IsAsciiWhitespace(str.back()); } -std::string RemoveTrailingSpace(const std::string& str) { +std::string RemoveTrailingSpace(std::string_view str) { if (ContainsTrailingSpace(str)) { - return str.substr(0, str.length() - 1); + return std::string(str.substr(0, str.length() - 1)); } - return str; + return std::string(str); } std::string RemovePunctuationToLower(std::string str) { @@ -67,11 +69,11 @@ return base::ToLowerASCII(str); } -std::string GetTranslationCacheKey(const std::string& source_language, - const std::string& target_language, - const std::string& transcription) { +std::string GetTranslationCacheKey(std::string_view source_language, + std::string_view target_language, + std::string_view transcription) { return base::StrCat({source_language, target_language, "|", - RemovePunctuationToLower(transcription)}); + RemovePunctuationToLower(std::string(transcription))}); } bool IsIdeographicLocale(const std::string& locale) { @@ -104,20 +106,21 @@ std::string cached_translation; std::string string_to_translate; bool cached_translation_found = true; - for (const std::string& sentence : sentences) { + for (std::string_view sentence : sentences) { if (cached_translation_found) { - std::string trailing_space = - ContainsTrailingSpace(sentence) - ? sentence.substr(sentence.length() - 1, sentence.length()) - : std::string(); + std::string_view trailing_space; + if (ContainsTrailingSpace(sentence)) { + trailing_space = + sentence.substr(sentence.length() - 1, sentence.length()); + } auto translation_cache_key = GetTranslationCacheKey( source_language, target_language, trailing_space.empty() ? sentence : RemoveTrailingSpace(sentence)); - auto iter = translation_cache_.find(translation_cache_key); - if (iter != translation_cache_.end()) { + if (auto iter = translation_cache_.find(translation_cache_key); + iter != translation_cache_.end()) { cached_translation += iter->second; if (!trailing_space.empty()) { - cached_translation += trailing_space; + base::StrAppend(&cached_translation, {trailing_space}); } continue; @@ -128,9 +131,9 @@ string_to_translate = base::StrCat({string_to_translate, sentence}); } if (cached_translation_found) { - return std::make_pair("", cached_translation); + return {"", std::move(cached_translation)}; } else { - return std::make_pair(string_to_translate, cached_translation); + return {std::move(string_to_translate), std::move(cached_translation)}; } } @@ -148,7 +151,8 @@ // Sentences are always cached without the trailing space. std::string sentence = RemoveTrailingSpace(original_sentences[i]); translation_cache_.insert( - {GetTranslationCacheKey(source_language, target_language, sentence), + {GetTranslationCacheKey(source_language, target_language, + std::move(sentence)), RemoveTrailingSpace(translated_sentences[i])}); } }
diff --git a/components/live_caption/translation_util.h b/components/live_caption/translation_util.h index 2a22f28..f9e7ee8 100644 --- a/components/live_caption/translation_util.h +++ b/components/live_caption/translation_util.h
@@ -21,14 +21,14 @@ // sentence. std::vector<std::string> SplitSentences(const std::string& text, const std::string& locale); -bool ContainsTrailingSpace(const std::string& str); +bool ContainsTrailingSpace(std::string_view str); -std::string RemoveTrailingSpace(const std::string& str); +std::string RemoveTrailingSpace(std::string_view str); std::string RemovePunctuationToLower(std::string str); -std::string GetTranslationCacheKey(const std::string& source_language, - const std::string& target_language, - const std::string& transcription); +std::string GetTranslationCacheKey(std::string_view source_language, + std::string_view target_language, + std::string_view transcription); bool IsIdeographicLocale(const std::string& locale); // Used to cache translations to avoid retranslating the same string. The key
diff --git a/components/metrics/metrics_log_store.h b/components/metrics/metrics_log_store.h index 23fd233..39819df 100644 --- a/components/metrics/metrics_log_store.h +++ b/components/metrics/metrics_log_store.h
@@ -70,8 +70,6 @@ // Saves |log_data| as the given |log_type|. Before being stored, the data // will be compressed, and a hash and signature will be computed. - // TODO(crbug.com/40119012): Remove this function, and use StoreLogInfo() - // everywhere instead. void StoreLog(const std::string& log_data, MetricsLog::LogType log_type, const LogMetadata& log_metadata,
diff --git a/components/metrics/unsent_log_store.h b/components/metrics/unsent_log_store.h index 479c0fd8..4335027 100644 --- a/components/metrics/unsent_log_store.h +++ b/components/metrics/unsent_log_store.h
@@ -149,20 +149,18 @@ void TrimAndPersistUnsentLogs(bool overwrite_in_memory_store) override; void LoadPersistedUnsentLogs() override; - // Adds a log to the list. |log_metadata| refers to metadata associated with - // the log. Before being stored, the data will be compressed, and a hash and - // signature will be computed. - // TODO(crbug.com/40119012): Remove this function, and use StoreLogInfo() - // everywhere instead. + // Creates a LogInfo from the passed `log_data` (by compressing, hashing, and + // signing it) and stores it (see StoreLogInfo() below). `log_metadata` refers + // to metadata associated with the log. void StoreLog(const std::string& log_data, const LogMetadata& log_metadata, MetricsLogsEventManager::CreateReason reason); - // Adds a log to the list, represented by a LogInfo object. This is useful - // if the LogInfo instance needs to be created outside the main thread - // (since creating a LogInfo from log data requires heavy work). Note that we - // also pass the size of the log data before being compressed. This is simply - // for calculating and emitting some metrics, and is otherwise unused. + // Adds a log to the store, represented by a LogInfo object. Calling this + // directly is particularly useful if the LogInfo instance needs to be created + // outside the main thread (since creating a LogInfo from log data requires + // heavy work). Note that `uncompressed_log_size` is only used for metrics + // purposes. void StoreLogInfo(std::unique_ptr<LogInfo> log_info, size_t uncompressed_log_size, MetricsLogsEventManager::CreateReason reason);
diff --git a/components/network_time/network_time_tracker.cc b/components/network_time/network_time_tracker.cc index 7704174..c2cdf63a 100644 --- a/components/network_time/network_time_tracker.cc +++ b/components/network_time/network_time_tracker.cc
@@ -192,14 +192,45 @@ base::span<const uint8_t> pubkey) : server_url_(kTimeServiceURL), max_response_size_(1024), - backoff_(kBackoffInterval.Get()), - url_loader_factory_(std::move(url_loader_factory)), query_signer_(kKeyVersion, pubkey.empty() ? kPubKey : pubkey), clock_(std::move(clock)), tick_clock_(std::move(tick_clock)), - pref_service_(pref_service), time_query_completed_(false), fetch_behavior_(fetch_behavior) { + // If `pref_service` is null, defer the remaining initialization. This allows + // the NetworkTimeTracker to be created, and subscribed-to, very early in + // startup, before the PrefService, NetworkService, FieldTrials, etc are + // fully initialized. + if (pref_service) { + Initialize(pref_service, std::move(url_loader_factory)); + } +} + +NetworkTimeTracker::~NetworkTimeTracker() { + DCHECK(thread_checker_.CalledOnValidThread()); + for (auto& observer : observers_) { + observer.OnNetworkTimeTrackerDestroyed(this); + } + CHECK(observers_.empty()); +} + +void NetworkTimeTracker::Initialize( + PrefService* pref_service, + scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory) { + DCHECK(thread_checker_.CalledOnValidThread()); + CHECK(!is_initialized()); + CHECK(pref_service); + pref_service_ = pref_service; + + url_loader_factory_ = std::move(url_loader_factory); + + // Set the backoff interval to the default value. This is done here, instead + // of in the constructor, because the backoff interval is a feature parameter + // whose value is not known until the feature list is initialized. + backoff_ = kBackoffInterval.Get(); + + // Finish initialization by checking whether network time mapping data is + // available in the prefs, and if so, use it to initialize the time tracker. const base::Value::Dict& time_mapping = pref_service_->GetDict(prefs::kNetworkTimeMapping); std::optional<double> time_js = time_mapping.FindDouble(kPrefTime); @@ -233,17 +264,10 @@ } } + // Start the loop to check the time. QueueCheckTime(base::Seconds(0)); } -NetworkTimeTracker::~NetworkTimeTracker() { - DCHECK(thread_checker_.CalledOnValidThread()); - for (auto& observer : observers_) { - observer.OnNetworkTimeTrackerDestroyed(this); - } - CHECK(observers_.empty()); -} - void NetworkTimeTracker::UpdateNetworkTime(base::Time network_time, base::TimeDelta resolution, base::TimeDelta latency, @@ -300,7 +324,8 @@ } bool NetworkTimeTracker::AreTimeFetchesEnabled() const { - return base::FeatureList::IsEnabled(kNetworkTimeServiceQuerying); + return is_initialized() && + base::FeatureList::IsEnabled(kNetworkTimeServiceQuerying); } NetworkTimeTracker::FetchBehavior NetworkTimeTracker::GetFetchBehavior() const {
diff --git a/components/network_time/network_time_tracker.h b/components/network_time/network_time_tracker.h index 4a2f7cf..33e741ab 100644 --- a/components/network_time/network_time_tracker.h +++ b/components/network_time/network_time_tracker.h
@@ -125,12 +125,25 @@ static void RegisterPrefs(PrefRegistrySimple* registry); - // Constructor. Arguments may be stubbed out for tests. |url_loader_factory| - // must be non-null unless the kNetworkTimeServiceQuerying is disabled. - // Otherwise, time is available only if |UpdateNetworkTime| is called. - // If |fetch_behavior| is not nullopt, it will control the behavior of the - // NetworkTimeTracker, if it is nullopt, it will be controlled via a feature - // parameter. + // Constructor. Arguments may be stubbed out for tests. + // + // * The |pref_service| may be passed as nullptr to the constructor, deferring + // its provision to the Initialize() method. + // + // * The |url_loader_factory| may be passed as nullptr to the constructor and + // the Initialize() method, if |kNetworkTimeServiceQuerying| is disabled. + // In this case, explicitly calling UpdateNetworkTime() will be the only + // way to set network time. + // + // * If |fetch_behavior| is not nullopt, it will control the behavior of the + // NetworkTimeTracker, if it is nullopt, it will be controlled via a feature + // parameter. + // + // The NetworkTimeTracker requires |pref_service| to be provided either in + // the constructor or via the Initialize() method (it is an error to call + // Initialize() with a nullptr |pref_service| or to call it after having + // already provided a non-nullptr |pref_service| to the constructor). The + // |url_loader_factory| pointer provided with the |pref_service| will be used. NetworkTimeTracker( std::unique_ptr<base::Clock> clock, std::unique_ptr<const base::TickClock> tick_clock, @@ -144,6 +157,19 @@ ~NetworkTimeTracker(); + // Returns true if the NetworkTimeTracker has been fully initialized, i.e. if + // it has been constructed or Initialize()-ed with a non-null PrefService*. + bool is_initialized() const { return pref_service_ != nullptr; } + + // Sets the PrefService and SharedURLLoaderFactory to be used by the + // NetworkTimeTracker, if not provided in the constructor. This will start + // the NetworkTimeTracker. |pref_service| must not be nullptr. + // |url_loader_factory| may be nullptr, if |kNetworkTimeServiceQuerying| is + // disabled. + void Initialize( + PrefService* pref_service, + scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory); + // Sets |network_time| to an estimate of the true time. Returns // NETWORK_TIME_AVAILABLE if time is available. If |uncertainty| is // non-NULL, it will be set to an estimate of the error range. @@ -153,11 +179,11 @@ // reason. // // Network time may be available on startup if deserialized from a pref. - // Failing that, a call to |UpdateNetworkTime| is required to make time - // available to callers of |GetNetworkTime|. Subsequently, network time may + // Failing that, a call to UpdateNetworkTime() is required to make time + // available to callers of GetNetworkTime(). Subsequently, network time may // become unavailable if |NetworkTimeTracker| has reason to believe it is no // longer accurate. Consumers should even be prepared to handle the case - // where calls to |GetNetworkTime| never once succeeds. + // where calls to GetNetworkTime() never once succeeds. NetworkTimeResult GetNetworkTime(base::Time* network_time, base::TimeDelta* uncertainty) const;
diff --git a/components/omnibox/common/android/java/src/org/chromium/components/omnibox/OmniboxFeatures.java b/components/omnibox/common/android/java/src/org/chromium/components/omnibox/OmniboxFeatures.java index 27171d8..cd0d326 100644 --- a/components/omnibox/common/android/java/src/org/chromium/components/omnibox/OmniboxFeatures.java +++ b/components/omnibox/common/android/java/src/org/chromium/components/omnibox/OmniboxFeatures.java
@@ -149,6 +149,9 @@ public static final BooleanCachedFeatureParam sCompactFusebox = newBooleanParam(sOmniboxMultimodalInput, "compact_fusebox", false); + public static final BooleanCachedFeatureParam sMultiattachmentFusebox = + newBooleanParam(sOmniboxMultimodalInput, "multi_context", false); + public static final CachedFlag sMultilineEditField = newFlag(OmniboxFeatureList.MULTILINE_EDIT_FIELD, FeatureState.ENABLED_IN_TEST);
diff --git a/components/page_info/android/BUILD.gn b/components/page_info/android/BUILD.gn index fa29dfb..ddb1ecf8 100644 --- a/components/page_info/android/BUILD.gn +++ b/components/page_info/android/BUILD.gn
@@ -99,6 +99,7 @@ ":page_info_action_enum_java", "//base:base_java", "//build/android:build_java", + "//chrome/browser/settings:search_java", "//components/browser_ui/settings/android:java", "//components/browser_ui/site_settings/android:java", "//components/browser_ui/styles/android:java",
diff --git a/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoAdPersonalizationSettings.java b/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoAdPersonalizationSettings.java index 797cf45..6e36370b 100644 --- a/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoAdPersonalizationSettings.java +++ b/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoAdPersonalizationSettings.java
@@ -11,6 +11,7 @@ import org.chromium.build.annotations.NullMarked; import org.chromium.build.annotations.Nullable; import org.chromium.components.browser_ui.settings.SettingsUtils; +import org.chromium.components.browser_ui.settings.search.BaseSearchIndexProvider; import org.chromium.components.browser_ui.site_settings.BaseSiteSettingsFragment; import java.util.List; @@ -91,4 +92,12 @@ } return false; } + + // TODO(crbug.com/444470792): This is probably a simple pref. Maybe logic from + // #onCreatePreferences + // needs to be mimicked under #updateDynamicPreferences. + public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = + new BaseSearchIndexProvider( + PageInfoAdPersonalizationSettings.class.getName(), + R.xml.page_info_ad_personalization_preference); }
diff --git a/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoCookiesSettings.java b/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoCookiesSettings.java index 85b1d33..adfc749 100644 --- a/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoCookiesSettings.java +++ b/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoCookiesSettings.java
@@ -27,6 +27,7 @@ import org.chromium.components.browser_ui.settings.ChromeSwitchPreference; import org.chromium.components.browser_ui.settings.SettingsUtils; import org.chromium.components.browser_ui.settings.TextMessagePreference; +import org.chromium.components.browser_ui.settings.search.BaseSearchIndexProvider; import org.chromium.components.browser_ui.site_settings.BaseSiteSettingsFragment; import org.chromium.components.browser_ui.site_settings.ForwardingManagedPreferenceDelegate; import org.chromium.components.browser_ui.site_settings.RwsCookieInfo; @@ -431,4 +432,9 @@ return true; } + + // TODO(crbug.com/444470792): Determine what pieces of logic are dynamic and need handling. + public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = + new BaseSearchIndexProvider( + PageInfoCookiesSettings.class.getName(), R.xml.page_info_cookie_preference); }
diff --git a/components/password_manager/content/common/credential_manager_mojom_traits.h b/components/password_manager/content/common/credential_manager_mojom_traits.h index ee9576e..69441c94 100644 --- a/components/password_manager/content/common/credential_manager_mojom_traits.h +++ b/components/password_manager/content/common/credential_manager_mojom_traits.h
@@ -8,6 +8,7 @@ #include <optional> #include <string> +#include "base/component_export.h" #include "components/password_manager/core/common/credential_manager_types.h" #include "mojo/public/cpp/bindings/struct_traits.h" #include "third_party/blink/public/mojom/credentialmanagement/credential_manager.mojom.h" @@ -15,8 +16,8 @@ namespace mojo { template <> -struct EnumTraits<blink::mojom::CredentialType, - password_manager::CredentialType> { +struct COMPONENT_EXPORT(CREDENTIALMANAGEMENT_MOJOM) + EnumTraits<blink::mojom::CredentialType, password_manager::CredentialType> { static blink::mojom::CredentialType ToMojom( password_manager::CredentialType input); static bool FromMojom(blink::mojom::CredentialType input, @@ -24,8 +25,9 @@ }; template <> -struct EnumTraits<blink::mojom::CredentialManagerError, - password_manager::CredentialManagerError> { +struct COMPONENT_EXPORT(CREDENTIALMANAGEMENT_MOJOM) + EnumTraits<blink::mojom::CredentialManagerError, + password_manager::CredentialManagerError> { static blink::mojom::CredentialManagerError ToMojom( password_manager::CredentialManagerError input); static bool FromMojom(blink::mojom::CredentialManagerError input, @@ -33,8 +35,9 @@ }; template <> -struct EnumTraits<blink::mojom::CredentialMediationRequirement, - password_manager::CredentialMediationRequirement> { +struct COMPONENT_EXPORT(CREDENTIALMANAGEMENT_MOJOM) + EnumTraits<blink::mojom::CredentialMediationRequirement, + password_manager::CredentialMediationRequirement> { static blink::mojom::CredentialMediationRequirement ToMojom( password_manager::CredentialMediationRequirement input); static bool FromMojom( @@ -43,8 +46,9 @@ }; template <> -struct StructTraits<blink::mojom::CredentialInfoDataView, - password_manager::CredentialInfo> { +struct COMPONENT_EXPORT(CREDENTIALMANAGEMENT_MOJOM) + StructTraits<blink::mojom::CredentialInfoDataView, + password_manager::CredentialInfo> { static password_manager::CredentialType type( const password_manager::CredentialInfo& r) { return r.type;
diff --git a/components/password_manager/core/browser/actor_login/actor_login_types.h b/components/password_manager/core/browser/actor_login/actor_login_types.h index 5736e84..e06c5646 100644 --- a/components/password_manager/core/browser/actor_login/actor_login_types.h +++ b/components/password_manager/core/browser/actor_login/actor_login_types.h
@@ -81,7 +81,7 @@ #endif }; -enum ActorLoginError { +enum class ActorLoginError { // Only one request at a time is allowed per `WebContents` (i.e per tab) kServiceBusy, // The provided `TabInterface` was invalid (e.g. no associated `WebContents` @@ -89,8 +89,8 @@ kInvalidTabInterface, // Filling is disallowed (e.g. because of a policy) kFillingNotAllowed, - // There was an error of unknown type. - kUnknown, + // The feature is disabled. + kFeatureDisabled, }; using CredentialsOrError =
diff --git a/components/password_manager/core/browser/actor_login/internal/actor_login_metrics.cc b/components/password_manager/core/browser/actor_login/internal/actor_login_metrics.cc index 571d51f..49cc84e 100644 --- a/components/password_manager/core/browser/actor_login/internal/actor_login_metrics.cc +++ b/components/password_manager/core/browser/actor_login/internal/actor_login_metrics.cc
@@ -39,7 +39,7 @@ case ActorLoginError::kFillingNotAllowed: RecordGetCredentialsResult(GetCredentialsResult::kErrorFillingNotAllowed); break; - case ActorLoginError::kUnknown: + case ActorLoginError::kFeatureDisabled: RecordGetCredentialsResult(GetCredentialsResult::kErrorUnknown); break; } @@ -88,7 +88,7 @@ case ActorLoginError::kFillingNotAllowed: RecordAttemptLoginResult(AttemptLoginResult::kErrorFillingNotAllowed); break; - case ActorLoginError::kUnknown: + case ActorLoginError::kFeatureDisabled: RecordAttemptLoginResult(AttemptLoginResult::kErrorUnknown); break; }
diff --git a/components/password_manager/core/browser/affiliation/passkey_affiliation_source_adapter.cc b/components/password_manager/core/browser/affiliation/passkey_affiliation_source_adapter.cc index 49d6731..15b9719 100644 --- a/components/password_manager/core/browser/affiliation/passkey_affiliation_source_adapter.cc +++ b/components/password_manager/core/browser/affiliation/passkey_affiliation_source_adapter.cc
@@ -54,7 +54,9 @@ } std::vector<sync_pb::WebauthnCredentialSpecifics> passkeys = - passkey_model_->GetAllPasskeys(); + passkey_model_->GetPasskeys( + webauthn::PasskeyModel::AnyRp(), + webauthn::PasskeyModel::ShadowedCredentials::kInclude); std::vector<FacetURI> result; result.reserve(passkeys.size()); for (const sync_pb::WebauthnCredentialSpecifics& passkey : passkeys) {
diff --git a/components/password_manager/core/browser/ui/saved_passwords_presenter.cc b/components/password_manager/core/browser/ui/saved_passwords_presenter.cc index 26e0bf5..1d66bfe 100644 --- a/components/password_manager/core/browser/ui/saved_passwords_presenter.cc +++ b/components/password_manager/core/browser/ui/saved_passwords_presenter.cc
@@ -678,8 +678,10 @@ std::vector<PasskeyCredential> passkeys; #if !BUILDFLAG(IS_ANDROID) if (passkey_store_) { - passkeys = PasskeyCredential::FromCredentialSpecifics( - passkey_store_->GetAllPasskeys()); + passkeys = + PasskeyCredential::FromCredentialSpecifics(passkey_store_->GetPasskeys( + webauthn::PasskeyModel::AnyRp(), + webauthn::PasskeyModel::ShadowedCredentials::kInclude)); } #endif // !BUILDFLAG(IS_ANDROID)
diff --git a/components/password_manager/core/browser/ui/saved_passwords_presenter_unittest.cc b/components/password_manager/core/browser/ui/saved_passwords_presenter_unittest.cc index 502de15..a5f83a7 100644 --- a/components/password_manager/core/browser/ui/saved_passwords_presenter_unittest.cc +++ b/components/password_manager/core/browser/ui/saved_passwords_presenter_unittest.cc
@@ -1107,7 +1107,11 @@ EXPECT_CALL(completion_callback, Run(true)).Times(1); presenter().DeleteAllData(completion_callback.Get()); RunUntilIdle(); - EXPECT_TRUE(passkey_store().GetAllPasskeys().empty()); + EXPECT_TRUE( + passkey_store() + .GetPasskeys(webauthn::PasskeyModel::AnyRp(), + webauthn::PasskeyModel::ShadowedCredentials::kInclude) + .empty()); EXPECT_TRUE(store().IsEmpty()); }
diff --git a/components/payments/content/payment_request.cc b/components/payments/content/payment_request.cc index f2d8ff2..7ac81387 100644 --- a/components/payments/content/payment_request.cc +++ b/components/payments/content/payment_request.cc
@@ -45,6 +45,7 @@ #include "content/public/common/content_features.h" #include "services/metrics/public/cpp/ukm_source_id.h" #include "services/network/public/cpp/is_potentially_trustworthy.h" +#include "third_party/blink/public/common/features.h" namespace payments { namespace { @@ -856,6 +857,22 @@ client_->OnPayerDetailChange(std::move(payer_info)); } +void PaymentRequest::OnUserAuthAnotherWay() { + // If |client_| is not bound, then the object is already being destroyed as + // a result of a renderer event. + if (!client_.is_bound()) { + return; + } + + RecordFirstAbortReason(JourneyLogger::ABORT_REASON_ABORTED_BY_USER); + + // This sends an error to the renderer, which informs the API user. + client_->OnError(mojom::PaymentErrorReason::NOT_ALLOWED_ERROR, + errors::kWebAuthnOperationTimedOutOrNotAllowed); + + ResetAndDeleteThis(); +} + void PaymentRequest::OnUserCancelled() { // If |client_| is not bound, then the object is already being destroyed as // a result of a renderer event. @@ -864,16 +881,24 @@ RecordFirstAbortReason(JourneyLogger::ABORT_REASON_ABORTED_BY_USER); - // This sends an error to the renderer, which informs the API user. - // If SPC flag is enabled, use NotAllowedError instead. - bool is_spc_enabled = spec_->IsSecurePaymentConfirmationRequested(); - client_->OnError( - is_spc_enabled ? mojom::PaymentErrorReason::NOT_ALLOWED_ERROR - : mojom::PaymentErrorReason::USER_CANCEL, - is_spc_enabled - ? errors::kWebAuthnOperationTimedOutOrNotAllowed - : (!reject_show_error_message_.empty() ? reject_show_error_message_ - : errors::kUserCancelled)); + if (base::FeatureList::IsEnabled( + blink::features::kSecurePaymentConfirmationUxRefresh)) { + client_->OnError( + mojom::PaymentErrorReason::USER_CANCEL, + (!reject_show_error_message_.empty() ? reject_show_error_message_ + : errors::kUserCancelled)); + } else { + // This sends an error to the renderer, which informs the API user. + // If SPC flag is enabled, use NotAllowedError instead. + bool is_spc_enabled = spec_->IsSecurePaymentConfirmationRequested(); + client_->OnError( + is_spc_enabled ? mojom::PaymentErrorReason::NOT_ALLOWED_ERROR + : mojom::PaymentErrorReason::USER_CANCEL, + is_spc_enabled + ? errors::kWebAuthnOperationTimedOutOrNotAllowed + : (!reject_show_error_message_.empty() ? reject_show_error_message_ + : errors::kUserCancelled)); + } ResetAndDeleteThis(); }
diff --git a/components/payments/content/payment_request.h b/components/payments/content/payment_request.h index 53b7e74..289cdb1 100644 --- a/components/payments/content/payment_request.h +++ b/components/payments/content/payment_request.h
@@ -117,6 +117,12 @@ void OnShippingAddressSelected(mojom::PaymentAddressPtr address) override; void OnPayerInfoSelected(mojom::PayerDetailPtr payer_info) override; + // Called when the user wants to authenticate in a different way. This is + // different from cancel as this signals that the user still wants to continue + // with the payment transaction. Will destroy this object and close any + // related connections. Only used for SecurePaymentConfirmation currently. + void OnUserAuthAnotherWay(); + // Called when the user explicitly cancelled the flow. Will destroy this // object and close any related connections. void OnUserCancelled();
diff --git a/components/payments/content/secure_payment_confirmation_model.h b/components/payments/content/secure_payment_confirmation_model.h index 1e508a27..1ebc0c6b 100644 --- a/components/payments/content/secure_payment_confirmation_model.h +++ b/components/payments/content/secure_payment_confirmation_model.h
@@ -10,6 +10,7 @@ #include "base/memory/raw_ptr.h" #include "base/memory/weak_ptr.h" +#include "components/payments/content/payment_app.h" #include "third_party/skia/include/core/SkBitmap.h" namespace payments { @@ -27,6 +28,15 @@ SecurePaymentConfirmationModel& operator=( const SecurePaymentConfirmationModel& other) = delete; + // Header logos. + const std::vector<PaymentApp::PaymentEntityLogo*> header_logos() const { + return header_logos_; + } + void set_header_logos( + const std::vector<PaymentApp::PaymentEntityLogo*> header_logos) { + header_logos_ = header_logos; + } + // Title, e.g. "Use TouchID to verify and complete your purchase?" const std::u16string& title() const { return title_; } void set_title(const std::u16string& title) { title_ = title; } @@ -60,12 +70,21 @@ instrument_label_ = instrument_label; } - // Label for the instrument row value, e.g. "****4444" + // Label for the instrument row value, e.g. "Chase Card" const std::u16string& instrument_value() const { return instrument_value_; } void set_instrument_value(const std::u16string& instrument_value) { instrument_value_ = instrument_value; } + // Sub-label for the instrument row value, e.g. "****4444" + const std::u16string& instrument_details_value() const { + return instrument_details_value_; + } + void set_instrument_details_value( + const std::u16string& instrument_details_value) { + instrument_details_value_ = instrument_details_value; + } + // Instrument icon. const SkBitmap* instrument_icon() const { return instrument_icon_; } void set_instrument_icon(const SkBitmap* instrument_icon) { @@ -159,6 +178,8 @@ base::WeakPtr<SecurePaymentConfirmationModel> GetWeakPtr(); private: + std::vector<PaymentApp::PaymentEntityLogo*> header_logos_; + std::u16string title_; std::u16string description_; @@ -168,6 +189,7 @@ std::u16string instrument_label_; std::u16string instrument_value_; + std::u16string instrument_details_value_; raw_ptr<const SkBitmap> instrument_icon_ = nullptr; std::u16string total_label_;
diff --git a/components/payments/content/secure_payment_confirmation_model_unittest.cc b/components/payments/content/secure_payment_confirmation_model_unittest.cc index 3b07b3a6..ef9bd25 100644 --- a/components/payments/content/secure_payment_confirmation_model_unittest.cc +++ b/components/payments/content/secure_payment_confirmation_model_unittest.cc
@@ -18,12 +18,14 @@ TEST_F(SecurePaymentConfirmationModelTest, SmokeTest) { SecurePaymentConfirmationModel model; + std::vector<PaymentApp::PaymentEntityLogo*> header_logos; std::u16string title(u"Use Touch ID to verify and complete your purchase?"); std::u16string merchant_label(u"Store"); std::u16string merchant_name(u"Test Merchant"); std::u16string merchant_origin(u"merchant.com"); std::u16string instrument_label(u"Payment"); - std::u16string instrument_value(u"Mastercard ****4444"); + std::u16string instrument_value(u"Mastercard"); + std::u16string instrument_details_value(u"****4444"); SkBitmap instrument_icon; std::u16string total_label(u"Total"); std::u16string total_value(u"$20.00 USD"); @@ -33,6 +35,9 @@ std::u16string opt_out_link_text(u"Opt Out Link"); std::u16string relying_party_id(u"example.test"); + model.set_header_logos(header_logos); + EXPECT_EQ(header_logos, model.header_logos()); + model.set_title(title); EXPECT_EQ(title, model.title()); @@ -51,6 +56,9 @@ model.set_instrument_value(instrument_value); EXPECT_EQ(instrument_value, model.instrument_value()); + model.set_instrument_details_value(instrument_details_value); + EXPECT_EQ(instrument_details_value, model.instrument_details_value()); + model.set_instrument_icon(&instrument_icon); EXPECT_EQ(&instrument_icon, model.instrument_icon());
diff --git a/components/policy/resources/templates/policy_definitions/Extensions/BlockExternalExtensions.yaml b/components/policy/resources/templates/policy_definitions/Extensions/BlockExternalExtensions.yaml index ca36934..e0bd24e 100644 --- a/components/policy/resources/templates/policy_definitions/Extensions/BlockExternalExtensions.yaml +++ b/components/policy/resources/templates/policy_definitions/Extensions/BlockExternalExtensions.yaml
@@ -13,6 +13,8 @@ features: dynamic_refresh: false per_profile: true +future_on: +- android items: - caption: Block installation of external extensions value: true
diff --git a/components/policy/resources/templates/policy_definitions/Extensions/ExtensionUnpublishedAvailability.yaml b/components/policy/resources/templates/policy_definitions/Extensions/ExtensionUnpublishedAvailability.yaml index 7d68a38e..d7dea44 100644 --- a/components/policy/resources/templates/policy_definitions/Extensions/ExtensionUnpublishedAvailability.yaml +++ b/components/policy/resources/templates/policy_definitions/Extensions/ExtensionUnpublishedAvailability.yaml
@@ -19,6 +19,8 @@ supported_on: - chrome.*:115- - chrome_os:115- +future_on: +- android features: dynamic_refresh: true per_profile: true
diff --git a/components/policy/test/data/pref_mapping/BlockExternalExtensions.json b/components/policy/test/data/pref_mapping/BlockExternalExtensions.json index 6e536a34..ad9c1f2 100644 --- a/components/policy/test/data/pref_mapping/BlockExternalExtensions.json +++ b/components/policy/test/data/pref_mapping/BlockExternalExtensions.json
@@ -3,7 +3,8 @@ "os": [ "win", "linux", - "mac" + "mac", + "desktop_android" ], "simple_policy_pref_mapping_test": { "pref_name": "extensions.block_external_extensions",
diff --git a/components/policy/test/data/pref_mapping/ExtensionUnpublishedAvailability.json b/components/policy/test/data/pref_mapping/ExtensionUnpublishedAvailability.json index 2189b82..59648e2c 100644 --- a/components/policy/test/data/pref_mapping/ExtensionUnpublishedAvailability.json +++ b/components/policy/test/data/pref_mapping/ExtensionUnpublishedAvailability.json
@@ -4,7 +4,8 @@ "win", "linux", "mac", - "chromeos" + "chromeos", + "desktop_android" ], "simple_policy_pref_mapping_test": { "pref_name": "extensions.unpublished_availability",
diff --git a/components/privacy_sandbox/masked_domain_list/BUILD.gn b/components/privacy_sandbox/masked_domain_list/BUILD.gn deleted file mode 100644 index 3e2dba2..0000000 --- a/components/privacy_sandbox/masked_domain_list/BUILD.gn +++ /dev/null
@@ -1,9 +0,0 @@ -# Copyright 2023 The Chromium Authors -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import("//third_party/protobuf/proto_library.gni") - -proto_library("masked_domain_list_proto") { - sources = [ "masked_domain_list.proto" ] -}
diff --git a/components/privacy_sandbox/masked_domain_list/OWNERS b/components/privacy_sandbox/masked_domain_list/OWNERS deleted file mode 100644 index d5d8d289..0000000 --- a/components/privacy_sandbox/masked_domain_list/OWNERS +++ /dev/null
@@ -1,3 +0,0 @@ -aakallam@chromium.org -miketaylr@chromium.org -rizvis@google.com
diff --git a/components/privacy_sandbox/masked_domain_list/masked_domain_list.proto b/components/privacy_sandbox/masked_domain_list/masked_domain_list.proto deleted file mode 100644 index d6bb486d..0000000 --- a/components/privacy_sandbox/masked_domain_list/masked_domain_list.proto +++ /dev/null
@@ -1,57 +0,0 @@ -syntax = "proto2"; - -package masked_domain_list; - -option optimize_for = LITE_RUNTIME; - -// Resource that is used in a 3rd party context. -message Resource { - reserved 2; - - enum Experiment { - EXPERIMENT_UNKNOWN = 0; - EXPERIMENT_EXTERNAL_REGULAR = 1; - } - - optional string domain = 1; - repeated Experiment experiments = 3 [packed = true]; - - // If true, clients not part of an experiment group will ignore this Resource. - optional bool exclude_default_group = 4; - - // Non-zero IDs of experiment groups that include this Resource. - repeated int64 experiment_group_ids = 5 [deprecated = true]; -} - -// Contains ownership information about resources that are used in a 3rd party -// context and domains that should treat those resources as 1st party. -message ResourceOwner { - // Required. - optional string owner_name = 1; - - // Sites that are all under the same ownership. - // Requests to this owner's resources from pages on these sites will - // not go through the Privacy Proxy. - repeated string owned_properties = 2; - - // Resources that are used in a 3rd party context. - repeated Resource owned_resources = 3; -} - -// Contains information to create rules based on the Public Suffix List. -message PublicSuffixListRule { - // Privately-owned domain listed on the PSL. - optional string private_domain = 1; -} - -message MaskedDomainList { - repeated ResourceOwner resource_owners = 1; - // Public Suffix List rules that modify the MDL. - // This field is deprecated and will be removed in the future. - // - // NOTE: As of Chrome Stable M134, this field is ignored in the Chrome client, - // but it is still used by prior versions. Thus, it should not be removed from - // the proto until it is safe to do so - repeated PublicSuffixListRule public_suffix_list_rules = 2 - [deprecated = true]; -}
diff --git a/components/regional_capabilities/access/country_access_reason.h b/components/regional_capabilities/access/country_access_reason.h index 289e0fc..fff1806 100644 --- a/components/regional_capabilities/access/country_access_reason.h +++ b/components/regional_capabilities/access/country_access_reason.h
@@ -57,6 +57,7 @@ // Used by Private Metrics to include the profile country in private metrics // reports. + // Access Request: crbug.com/461922774. kPrivateUserMetricsReporting, };
diff --git a/components/signin/internal/identity_manager/accounts_cookie_mutator_impl.cc b/components/signin/internal/identity_manager/accounts_cookie_mutator_impl.cc index b9c43d93..bbb96904 100644 --- a/components/signin/internal/identity_manager/accounts_cookie_mutator_impl.cc +++ b/components/signin/internal/identity_manager/accounts_cookie_mutator_impl.cc
@@ -78,7 +78,8 @@ return std::make_unique<MultiloginHelperWrapper>( std::make_unique<OAuthMultiloginHelper>( signin_client_, partition_delegate, token_service_, parameters.mode, - accounts, /*external_cc_result=*/std::string(), source, + parameters.wait_on_connectivity, accounts, + /*external_cc_result=*/std::string(), source, std::move(set_accounts_in_cookies_completed_callback))); }
diff --git a/components/signin/internal/identity_manager/gaia_cookie_manager_service.cc b/components/signin/internal/identity_manager/gaia_cookie_manager_service.cc index b46f43b..cd75a8a 100644 --- a/components/signin/internal/identity_manager/gaia_cookie_manager_service.cc +++ b/components/signin/internal/identity_manager/gaia_cookie_manager_service.cc
@@ -843,8 +843,8 @@ oauth_multilogin_helper_ = std::make_unique<signin::OAuthMultiloginHelper>( signin_client_, this, token_service_, request.GetMultiloginMode(), - request.GetAccounts(), external_cc_result_fetcher_.GetExternalCcResult(), - request.source(), + /*wait_on_connectivity=*/true, request.GetAccounts(), + external_cc_result_fetcher_.GetExternalCcResult(), request.source(), base::BindOnce(&GaiaCookieManagerService::OnSetAccountsFinished, weak_ptr_factory_.GetWeakPtr())); }
diff --git a/components/signin/internal/identity_manager/oauth_multilogin_helper.cc b/components/signin/internal/identity_manager/oauth_multilogin_helper.cc index 360cd0a..b738f9f 100644 --- a/components/signin/internal/identity_manager/oauth_multilogin_helper.cc +++ b/components/signin/internal/identity_manager/oauth_multilogin_helper.cc
@@ -136,6 +136,7 @@ AccountsCookieMutator::PartitionDelegate* partition_delegate, ProfileOAuth2TokenService* token_service, gaia::MultiloginMode mode, + bool wait_on_connectivity, const std::vector<AccountIdGaiaIdPair>& accounts, const std::string& external_cc_result, const gaia::GaiaSource& gaia_source, @@ -144,6 +145,7 @@ partition_delegate_(partition_delegate), token_service_(token_service), mode_(mode), + wait_on_connectivity_(wait_on_connectivity), accounts_(accounts), external_cc_result_(external_cc_result), gaia_source_(gaia_source), @@ -206,7 +208,8 @@ base::BindOnce(&OAuthMultiloginHelper::OnMultiloginTokensSuccess, base::Unretained(this)), base::BindOnce(&OAuthMultiloginHelper::OnMultiloginTokensFailure, - base::Unretained(this))); + base::Unretained(this)), + /*retry_waits_on_connectivity=*/wait_on_connectivity_); } void OAuthMultiloginHelper::OnMultiloginTokensSuccess( @@ -215,9 +218,14 @@ CHECK_EQ(tokens.size(), accounts_.size()); tokens_ = std::move(tokens); token_fetcher_.reset(); - signin_client_->DelayNetworkCall( + auto callback = base::BindOnce(&OAuthMultiloginHelper::StartFetchingMultiLogin, - weak_ptr_factory_.GetWeakPtr())); + weak_ptr_factory_.GetWeakPtr()); + if (wait_on_connectivity_) { + signin_client_->DelayNetworkCall(std::move(callback)); + } else { + std::move(callback).Run(); + } } void OAuthMultiloginHelper::OnMultiloginTokensFailure(
diff --git a/components/signin/internal/identity_manager/oauth_multilogin_helper.h b/components/signin/internal/identity_manager/oauth_multilogin_helper.h index 2e554aa..6912314 100644 --- a/components/signin/internal/identity_manager/oauth_multilogin_helper.h +++ b/components/signin/internal/identity_manager/oauth_multilogin_helper.h
@@ -62,6 +62,7 @@ AccountsCookieMutator::PartitionDelegate* partition_delegate, ProfileOAuth2TokenService* token_service, gaia::MultiloginMode mode, + bool wait_on_connectivity, const std::vector<AccountIdGaiaIdPair>& accounts, const std::string& external_cc_result, const gaia::GaiaSource& gaia_source, @@ -126,6 +127,7 @@ int fetcher_retries_ = 0; gaia::MultiloginMode mode_; + const bool wait_on_connectivity_ = true; // Account IDs to set in the cookie. const std::vector<AccountIdGaiaIdPair> accounts_; // See GaiaCookieManagerService::ExternalCcResultFetcher for details.
diff --git a/components/signin/internal/identity_manager/oauth_multilogin_helper_unittest.cc b/components/signin/internal/identity_manager/oauth_multilogin_helper_unittest.cc index 5ceba65..80ccaaff4 100644 --- a/components/signin/internal/identity_manager/oauth_multilogin_helper_unittest.cc +++ b/components/signin/internal/identity_manager/oauth_multilogin_helper_unittest.cc
@@ -407,7 +407,8 @@ OAuthMultiloginHelper* CreateHelper( const std::vector<OAuthMultiloginHelper::AccountIdGaiaIdPair> accounts, - bool set_external_cc_result = false) { + bool set_external_cc_result = false, + bool wait_on_connectivity = true) { #if BUILDFLAG(ENABLE_DICE_SUPPORT) // `bound_session_delegate_` is owned by `OAuthMultiloginHelper`, ensures it // resets before creating a new helper to avoid dangling pointers. @@ -415,7 +416,8 @@ #endif // BUILDFLAG(ENABLE_DICE_SUPPORT) helper_ = std::make_unique<OAuthMultiloginHelper>( &test_signin_client_, this, token_service(), - gaia::MultiloginMode::MULTILOGIN_UPDATE_COOKIE_ACCOUNTS_ORDER, accounts, + gaia::MultiloginMode::MULTILOGIN_UPDATE_COOKIE_ACCOUNTS_ORDER, + wait_on_connectivity, accounts, set_external_cc_result ? kExternalCcResult : std::string(), gaia::GaiaSource::kChrome, base::BindOnce(&OAuthMultiloginHelperTest::OnOAuthMultiloginFinished, @@ -563,6 +565,41 @@ EXPECT_EQ(result_, SetAccountsInCookieResult::kSuccess); } +// Same as Success, but simulates making a request while offline and +// wait_on_connectivity=false, which allows sending the request anyway. +TEST_F(OAuthMultiloginHelperTest, SuccessOffline) { + test_signin_client_.SetNetworkCallsDelayed(true); + token_service()->UpdateCredentials(kAccountId, "refresh_token"); + CreateHelper({{kAccountId, kGaiaId}}, false, /*wait_on_connectivity=*/false); + + EXPECT_CALL( + *cookie_manager(), + SetCanonicalCookie(CookieMatcher("SID", "SID_value", ".google.fr"), + CookieSourceMatcher("google.fr"), _, _)) + .WillOnce(RunSetCookieCallbackWithSuccess); + + // Issue access token. + OAuth2AccessTokenConsumer::TokenResponse success_response; + success_response.access_token = kAccessToken; + token_service()->IssueAllTokensForAccount(kAccountId, success_response); + + // Multilogin call. + EXPECT_EQ(result_, std::nullopt); + const network::ResourceRequest* multilogin_request = nullptr; + ASSERT_TRUE(url_loader()->IsPending(multilogin_url(), &multilogin_request)); + EXPECT_EQ(multilogin_request->headers.GetHeader(kAuthorizationHeaderName), + CreateMultiBearerAuthorizationHeader( + {gaia::MultiloginAccountAuthCredentials(kGaiaId, kAccessToken, + kNoAssertion)})); +#if BUILDFLAG(ENABLE_DICE_SUPPORT) + EXPECT_CALL(*bound_session_delegate(), BeforeSetCookies); + EXPECT_CALL(*bound_session_delegate(), OnCookiesSet); +#endif // BUILDFLAG(ENABLE_DICE_SUPPORT) + url_loader()->AddResponse(multilogin_url(), kMultiloginSuccessResponse); + EXPECT_FALSE(url_loader()->IsPending(multilogin_url())); + EXPECT_EQ(result_, SetAccountsInCookieResult::kSuccess); +} + // Success, but the response does not contain any cookies. TEST_F(OAuthMultiloginHelperTest, SuccessWithNoCookies) { token_service()->UpdateCredentials(kAccountId, "refresh_token");
diff --git a/components/signin/internal/identity_manager/oauth_multilogin_token_fetcher.cc b/components/signin/internal/identity_manager/oauth_multilogin_token_fetcher.cc index 84b7e8d..fadfa883 100644 --- a/components/signin/internal/identity_manager/oauth_multilogin_token_fetcher.cc +++ b/components/signin/internal/identity_manager/oauth_multilogin_token_fetcher.cc
@@ -35,13 +35,15 @@ std::vector<AccountParams> account_params, std::string ephemeral_public_key, SuccessCallback success_callback, - FailureCallback failure_callback) + FailureCallback failure_callback, + bool retry_waits_on_connectivity) : signin_client_(signin_client), token_service_(token_service), account_params_(std::move(account_params)), ephemeral_public_key_(std::move(ephemeral_public_key)), success_callback_(std::move(success_callback)), - failure_callback_(std::move(failure_callback)) { + failure_callback_(std::move(failure_callback)), + retry_waits_on_connectivity_(retry_waits_on_connectivity) { DCHECK(signin_client_); DCHECK(token_service_); DCHECK(!account_params_.empty()); @@ -128,10 +130,16 @@ auto it = std::ranges::find(account_params_, account_id, &AccountParams::account_id); CHECK(it != account_params_.end()); - // Fetching fresh access tokens requires network. - signin_client_->DelayNetworkCall( + auto callback = base::BindOnce(&OAuthMultiloginTokenFetcher::StartFetchingToken, - weak_ptr_factory_.GetWeakPtr(), *it)); + weak_ptr_factory_.GetWeakPtr(), *it); + if (retry_waits_on_connectivity_) { + // Fetching fresh access tokens requires network. + signin_client_->DelayNetworkCall(std::move(callback)); + } else { + // But chrome may not accurately know network connectivity. + std::move(callback).Run(); + } return; } RecordGetAccessTokenFinished(error);
diff --git a/components/signin/internal/identity_manager/oauth_multilogin_token_fetcher.h b/components/signin/internal/identity_manager/oauth_multilogin_token_fetcher.h index 8ce3ea9..16bd56b 100644 --- a/components/signin/internal/identity_manager/oauth_multilogin_token_fetcher.h +++ b/components/signin/internal/identity_manager/oauth_multilogin_token_fetcher.h
@@ -48,7 +48,8 @@ std::vector<AccountParams> account_params, std::string ephemeral_public_key, SuccessCallback success_callback, - FailureCallback failure_callback); + FailureCallback failure_callback, + bool retry_waits_on_connectivity = true); OAuthMultiloginTokenFetcher(const OAuthMultiloginTokenFetcher&) = delete; OAuthMultiloginTokenFetcher& operator=(const OAuthMultiloginTokenFetcher&) = @@ -78,6 +79,7 @@ std::vector<std::unique_ptr<OAuthMultiloginTokenRequest>> token_requests_; base::flat_map<CoreAccountId, OAuthMultiloginTokenResponse> token_responses_; std::set<CoreAccountId> retried_requests_; // Requests are retried once. + const bool retry_waits_on_connectivity_ = true; base::WeakPtrFactory<OAuthMultiloginTokenFetcher> weak_ptr_factory_{this}; };
diff --git a/components/signin/public/base/multilogin_parameters.h b/components/signin/public/base/multilogin_parameters.h index b270208..a08988d 100644 --- a/components/signin/public/base/multilogin_parameters.h +++ b/components/signin/public/base/multilogin_parameters.h
@@ -30,6 +30,11 @@ gaia::MultiloginMode mode = gaia::MultiloginMode::MULTILOGIN_UPDATE_COOKIE_ACCOUNTS_ORDER; std::vector<CoreAccountId> accounts_to_send; + // Whether to wait for a connected network state before sending the request. + // This is the historical default, but network state can be unreliable, so + // using this is not advised. + // TODO(crbug.com/466303351): Remove all uses of DelayNetworkCall(). + bool wait_on_connectivity = true; }; std::ostream& operator<<(std::ostream& out, const MultiloginParameters& p);
diff --git a/components/supervised_user/core/browser/android/BUILD.gn b/components/supervised_user/core/browser/android/BUILD.gn index e50ad26..d256647 100644 --- a/components/supervised_user/core/browser/android/BUILD.gn +++ b/components/supervised_user/core/browser/android/BUILD.gn
@@ -26,6 +26,7 @@ ":content_filters_observer_bridge", "//base", "//base/test:test_support", + "//components/prefs:test_support", "//components/supervised_user/core/common:features", "//testing/gmock", "//testing/gtest",
diff --git a/components/supervised_user/core/browser/android/content_filters_observer_bridge.cc b/components/supervised_user/core/browser/android/content_filters_observer_bridge.cc index a926ffc..786536d 100644 --- a/components/supervised_user/core/browser/android/content_filters_observer_bridge.cc +++ b/components/supervised_user/core/browser/android/content_filters_observer_bridge.cc
@@ -47,25 +47,10 @@ } } // namespace -std::unique_ptr<ContentFiltersObserverBridge> -ContentFiltersObserverBridge::Create( - std::string_view setting_name, - base::RepeatingClosure on_enabled, - base::RepeatingClosure on_disabled, - base::RepeatingCallback<bool()> is_subject_to_parental_controls) { - return std::make_unique<ContentFiltersObserverBridge>( - setting_name, on_enabled, on_disabled, is_subject_to_parental_controls); -} - ContentFiltersObserverBridge::ContentFiltersObserverBridge( std::string_view setting_name, - base::RepeatingClosure on_enabled, - base::RepeatingClosure on_disabled, - base::RepeatingCallback<bool()> is_subject_to_parental_controls) - : setting_name_(setting_name), - on_enabled_(on_enabled), - on_disabled_(on_disabled), - is_subject_to_parental_controls_(is_subject_to_parental_controls) {} + const PrefService& pref_service) + : setting_name_(setting_name), pref_service_(pref_service) {} ContentFiltersObserverBridge::~ContentFiltersObserverBridge() { if (bridge_) { @@ -75,12 +60,18 @@ } } -void ContentFiltersObserverBridge::OnChange(JNIEnv* env, bool enabled) { - // Warning: callsites can pass env=nullptr. Update them before utilizing *env. +void ContentFiltersObserverBridge::SetEnabledForTesting(bool enabled) { + SetEnabled(enabled); +} +void ContentFiltersObserverBridge::OnChange(JNIEnv* env, bool enabled) { LOG(INFO) << "ContentFiltersObserverBridge received onChange for setting " << setting_name_ << " with value " << (enabled ? "enabled" : "disabled"); + SetEnabled(enabled); +} + +void ContentFiltersObserverBridge::SetEnabled(bool enabled) { if (!IsFeatureEnabledForSetting(setting_name_)) { LOG(INFO) << "ContentFiltersObserverBridge change ignored: feature disabled"; @@ -91,7 +82,7 @@ // accounts. if (base::FeatureList::IsEnabled( kSupervisedUserOverrideLocalSupervisionForFamilyLinkAccounts) && - is_subject_to_parental_controls_.Run() && enabled) { + IsSubjectToParentalControls(*pref_service_) && enabled) { base::UmaHistogramEnumeration(kSupervisionConflictHistogramName, SupervisionHasConflict::kHasConflict); LOG(INFO) @@ -100,10 +91,16 @@ } enabled_ = enabled; - if (enabled) { - on_enabled_.Run(); + NotifyObservers(); +} + +void ContentFiltersObserverBridge::NotifyObservers() { + if (enabled_) { + observer_list_.Notify(&Observer::OnContentFiltersObserverEnabled, + setting_name_); } else { - on_disabled_.Run(); + observer_list_.Notify(&Observer::OnContentFiltersObserverDisabled, + setting_name_); } } @@ -135,8 +132,16 @@ return enabled_; } -void ContentFiltersObserverBridge::SetEnabled(bool enabled) { - enabled_ = enabled; +void ContentFiltersObserverBridge::AddObserver(Observer* observer) { + observer_list_.AddObserver(observer); +} +void ContentFiltersObserverBridge::RemoveObserver(Observer* observer) { + observer_list_.RemoveObserver(observer); +} + +base::WeakPtr<ContentFiltersObserverBridge> +ContentFiltersObserverBridge::GetWeakPtr() { + return weak_ptr_factory_.GetWeakPtr(); } } // namespace supervised_user
diff --git a/components/supervised_user/core/browser/android/content_filters_observer_bridge.h b/components/supervised_user/core/browser/android/content_filters_observer_bridge.h index bbe5b1d..d08228b 100644 --- a/components/supervised_user/core/browser/android/content_filters_observer_bridge.h +++ b/components/supervised_user/core/browser/android/content_filters_observer_bridge.h
@@ -11,37 +11,35 @@ #include "base/android/jni_string.h" #include "base/android/scoped_java_ref.h" -#include "base/functional/callback.h" +#include "base/memory/raw_ref.h" +#include "base/observer_list.h" + +// Required to veto Android Parental Control changes if the user is already +// subject to parental controls. +class PrefService; namespace supervised_user { -// Bridge between the C++ and Java sides for a content filters observer. Used to -// observe the Android's secure settings, can be a component of a service. -// observer. Instances of FakeContentFiltersObserverBridge for testing purposes -// are available from SupervisedUserTestEnvironment. +// Forward-declared to go around dependency-cycle. +bool IsSubjectToParentalControls(const PrefService& pref_service); + +// Bridge between the C++ and Java sides for a content filters observer. Used +// to observe the Android's secure settings, can be a component of a service. +// observer. Instances of FakeContentFiltersObserverBridge for testing +// purposes are available from SupervisedUserTestEnvironment. class ContentFiltersObserverBridge { public: - // Factory for creating ContentFiltersObserverBridge instances. They should - // accept the setting name, two callbacks to be called when the setting is - // enabled or disabled and the user prefs. - using Factory = - base::RepeatingCallback<std::unique_ptr<ContentFiltersObserverBridge>( - std::string_view, - base::RepeatingClosure, - base::RepeatingClosure, - base::RepeatingCallback<bool()>)>; + // Observers will receive notifications about changes to underlying settings + // storage. + class Observer { + public: + virtual void OnContentFiltersObserverEnabled( + std::string_view setting_name) {} + virtual void OnContentFiltersObserverDisabled( + std::string_view setting_name) {} + }; - // Creates a ContentFiltersObserverBridge instance. - static std::unique_ptr<ContentFiltersObserverBridge> Create( - std::string_view setting_name, - base::RepeatingClosure on_enabled, - base::RepeatingClosure on_disabled, - base::RepeatingCallback<bool()> is_subject_to_parental_controls); - - ContentFiltersObserverBridge( - std::string_view setting_name, - base::RepeatingClosure on_enabled, - base::RepeatingClosure on_disabled, - base::RepeatingCallback<bool()> is_subject_to_parental_controls); + ContentFiltersObserverBridge(std::string_view setting_name, + const PrefService& pref_service); ContentFiltersObserverBridge(const ContentFiltersObserverBridge&) = delete; ContentFiltersObserverBridge& operator=(const ContentFiltersObserverBridge&) = @@ -53,24 +51,35 @@ virtual void Shutdown(); // Called after creating the bridge and when the setting is enabled or - // disabled. + // disabled. Triggers observers. void OnChange(JNIEnv* env, bool enabled); // Reads the last broadcasted value of the setting from the Java side. bool IsEnabled() const; + void AddObserver(Observer* observer); + void RemoveObserver(Observer* observer); + + void SetEnabledForTesting(bool enabled); + + base::WeakPtr<ContentFiltersObserverBridge> GetWeakPtr(); + protected: - virtual void SetEnabled(bool enabled); + void SetEnabled(bool enabled); + + // Notifies observers about the current state of the setting. + void NotifyObservers(); private: - // This value is set exclusively from Java, and reflects the last broadcasted - // value of the setting. + // In prod environment set from Java via JNI and reflects the current state + // of the setting in the operating system. In test environment that removes + // Java native storage backend, it might be controlled explicitly. bool enabled_ = false; std::string setting_name_; - base::RepeatingClosure on_enabled_; - base::RepeatingClosure on_disabled_; - base::RepeatingCallback<bool()> is_subject_to_parental_controls_; + raw_ref<const PrefService> pref_service_; base::android::ScopedJavaGlobalRef<jobject> bridge_; + base::ObserverList<Observer>::Unchecked observer_list_; + base::WeakPtrFactory<ContentFiltersObserverBridge> weak_ptr_factory_{this}; }; } // namespace supervised_user
diff --git a/components/supervised_user/core/browser/android/content_filters_observer_bridge_unittest.cc b/components/supervised_user/core/browser/android/content_filters_observer_bridge_unittest.cc index b4a84ed2..6a24bca 100644 --- a/components/supervised_user/core/browser/android/content_filters_observer_bridge_unittest.cc +++ b/components/supervised_user/core/browser/android/content_filters_observer_bridge_unittest.cc
@@ -5,6 +5,7 @@ #include "components/supervised_user/core/browser/android/content_filters_observer_bridge.h" #include "base/test/scoped_feature_list.h" +#include "components/prefs/testing_pref_service.h" #include "components/supervised_user/core/common/features.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -14,20 +15,36 @@ class ContentFiltersObserverBridgeTest : public testing::Test {}; +class MockObserver : public ContentFiltersObserverBridge::Observer { + public: + MOCK_METHOD(void, + OnContentFiltersObserverEnabled, + (std::string_view), + (override)); + MOCK_METHOD(void, + OnContentFiltersObserverDisabled, + (std::string_view), + (override)); +}; + TEST_F(ContentFiltersObserverBridgeTest, WithFeatureDisabledCallbacksAreNotCalled) { base::test::ScopedFeatureList scoped_feature_list; scoped_feature_list.InitAndDisableFeature( kPropagateDeviceContentFiltersToSupervisedUser); - ContentFiltersObserverBridge bridge( - "test_setting", base::BindRepeating([]() { - CHECK(false) << "Callback called when feature is disabled"; - }), - base::BindRepeating( - []() { CHECK(false) << "Callback called when feature is disabled"; }), - base::BindRepeating([]() { return false; })); + TestingPrefServiceSimple pref_service; + MockObserver observer; + std::string_view setting_name = "test_setting"; + + EXPECT_CALL(observer, OnContentFiltersObserverEnabled(setting_name)).Times(0); + EXPECT_CALL(observer, OnContentFiltersObserverDisabled(setting_name)) + .Times(0); + + ContentFiltersObserverBridge bridge(setting_name, pref_service); + + bridge.AddObserver(&observer); bridge.Init(); bridge.Shutdown(); }
diff --git a/components/supervised_user/core/browser/supervised_user_log_record_unittest.cc b/components/supervised_user/core/browser/supervised_user_log_record_unittest.cc index 4ba3130..5b7def62 100644 --- a/components/supervised_user/core/browser/supervised_user_log_record_unittest.cc +++ b/components/supervised_user/core/browser/supervised_user_log_record_unittest.cc
@@ -104,8 +104,7 @@ void CreateParentUser(kidsmanagement::FamilyRole family_role) { CreateRegularUser(); supervised_user_test_environment_.pref_service()->SetString( - prefs::kFamilyLinkUserMemberRole, - supervised_user::FamilyRoleToString(family_role)); + prefs::kFamilyLinkUserMemberRole, FamilyRoleToString(family_role)); } void CreateSupervisedUser(bool is_subject_to_parental_controls, @@ -121,8 +120,7 @@ is_opted_in_to_parental_supervision); GetIdentityTestEnv()->UpdateAccountInfoForAccount(account_info); - supervised_user::EnableParentalControls( - *supervised_user_test_environment_.pref_service()); + EnableParentalControls(*supervised_user_test_environment_.pref_service()); // Set the Family Link `Permissions` switch to default value. In prod it's // done by the `SupervisedUserPrefStore`, but that requires fully // operational Profile. @@ -146,13 +144,15 @@ #if BUILDFLAG(IS_ANDROID) void EnableSearchContentFilters() { - supervised_user_test_environment_.search_content_filters_observer() - ->SetEnabled(true); + supervised_user_test_environment_.service() + ->GetSearchContentFiltersObserverWeakPtrForTesting() + ->SetEnabledForTesting(true); } void EnableBrowserContentFilters() { - supervised_user_test_environment_.browser_content_filters_observer() - ->SetEnabled(true); + supervised_user_test_environment_.service() + ->GetBrowserContentFiltersObserverWeakPtrForTesting() + ->SetEnabledForTesting(true); } #endif // BUILDFLAG(IS_ANDROID)
diff --git a/components/supervised_user/core/browser/supervised_user_metrics_service_unittest.cc b/components/supervised_user/core/browser/supervised_user_metrics_service_unittest.cc index b5f24ef7..1a4db287 100644 --- a/components/supervised_user/core/browser/supervised_user_metrics_service_unittest.cc +++ b/components/supervised_user/core/browser/supervised_user_metrics_service_unittest.cc
@@ -177,11 +177,14 @@ << "Create test environment first with CreateTestEnvironment()."; if (GetFieldTrialName() == "AndroidDeviceSearchContentFilters") { - test_environment_->search_content_filters_observer()->SetEnabled(enabled); + test_environment_->service() + ->GetSearchContentFiltersObserverWeakPtrForTesting() + ->SetEnabledForTesting(enabled); return; } else if (GetFieldTrialName() == "AndroidDeviceBrowserContentFilters") { - test_environment_->browser_content_filters_observer()->SetEnabled( - enabled); + test_environment_->service() + ->GetBrowserContentFiltersObserverWeakPtrForTesting() + ->SetEnabledForTesting(enabled); return; } @@ -287,7 +290,6 @@ } } - const PeriodicalWebFilterTypeTestParams kPeriodicalWebFilterTypeTestParams[] = { {"Unsupervised", InitialSupervisionState::kUnsupervised,
diff --git a/components/supervised_user/core/browser/supervised_user_service.cc b/components/supervised_user/core/browser/supervised_user_service.cc index 9108b83c..602ef6a 100644 --- a/components/supervised_user/core/browser/supervised_user_service.cc +++ b/components/supervised_user/core/browser/supervised_user_service.cc
@@ -186,8 +186,10 @@ std::unique_ptr<SupervisedUserService::PlatformDelegate> platform_delegate #if BUILDFLAG(IS_ANDROID) , - ContentFiltersObserverBridge::Factory - content_filters_observer_bridge_factory + std::unique_ptr<ContentFiltersObserverBridge> + browser_content_filters_observer, + std::unique_ptr<ContentFiltersObserverBridge> + search_content_filters_observer #endif ) : user_prefs_(user_prefs), @@ -202,27 +204,9 @@ #if BUILDFLAG(IS_ANDROID) , browser_content_filters_observer_( - content_filters_observer_bridge_factory.Run( - kBrowserContentFiltersSettingName, - base::BindRepeating( - &SupervisedUserService::EnableBrowserContentFilters, - base::Unretained(this)), - base::BindRepeating( - &SupervisedUserService::DisableBrowserContentFilters, - base::Unretained(this)), - base::BindRepeating(&IsSubjectToParentalControls, - base::Unretained(user_prefs_)))), + std::move(browser_content_filters_observer)), search_content_filters_observer_( - content_filters_observer_bridge_factory.Run( - kSearchContentFiltersSettingName, - base::BindRepeating( - &SupervisedUserService::EnableSearchContentFilters, - base::Unretained(this)), - base::BindRepeating( - &SupervisedUserService::DisableSearchContentFilters, - base::Unretained(this)), - base::BindRepeating(&IsSubjectToParentalControls, - base::Unretained(user_prefs_)))) + std::move(search_content_filters_observer)) #endif // BUILDFLAG(IS_ANDROID) { CHECK(settings_service_->IsReady()) @@ -230,6 +214,8 @@ "a dependency of this service."; #if BUILDFLAG(IS_ANDROID) + browser_content_filters_observer_->AddObserver(this); + search_content_filters_observer_->AddObserver(this); browser_content_filters_observer_->Init(); search_content_filters_observer_->Init(); #endif // BUILDFLAG(IS_ANDROID) @@ -397,7 +383,9 @@ did_shutdown_ = true; #if BUILDFLAG(IS_ANDROID) + browser_content_filters_observer_->RemoveObserver(this); browser_content_filters_observer_->Shutdown(); + search_content_filters_observer_->RemoveObserver(this); search_content_filters_observer_->Shutdown(); #endif // BUILDFLAG(IS_ANDROID) @@ -423,6 +411,28 @@ } } // namespace +void SupervisedUserService::OnContentFiltersObserverEnabled( + std::string_view setting_name) { + if (setting_name == kBrowserContentFiltersSettingName) { + EnableBrowserContentFilters(); + } else if (setting_name == kSearchContentFiltersSettingName) { + EnableSearchContentFilters(); + } else { + NOTREACHED(); + } +} + +void SupervisedUserService::OnContentFiltersObserverDisabled( + std::string_view setting_name) { + if (setting_name == kBrowserContentFiltersSettingName) { + DisableBrowserContentFilters(); + } else if (setting_name == kSearchContentFiltersSettingName) { + DisableSearchContentFilters(); + } else { + NOTREACHED(); + } +} + void SupervisedUserService::EnableSearchContentFilters() { if (!IsEligibleForContentFilters(user_prefs_.get())) { return; @@ -492,14 +502,14 @@ UpdateURLFilter(); } -ContentFiltersObserverBridge* -SupervisedUserService::browser_content_filters_observer() { - return browser_content_filters_observer_.get(); +base::WeakPtr<ContentFiltersObserverBridge> +SupervisedUserService::GetBrowserContentFiltersObserverWeakPtrForTesting() { + return browser_content_filters_observer_->GetWeakPtr(); } -ContentFiltersObserverBridge* -SupervisedUserService::search_content_filters_observer() { - return search_content_filters_observer_.get(); +base::WeakPtr<ContentFiltersObserverBridge> +SupervisedUserService::GetSearchContentFiltersObserverWeakPtrForTesting() { + return search_content_filters_observer_->GetWeakPtr(); } #endif // BUILDFLAG(IS_ANDROID)
diff --git a/components/supervised_user/core/browser/supervised_user_service.h b/components/supervised_user/core/browser/supervised_user_service.h index 9d005961..3aca198 100644 --- a/components/supervised_user/core/browser/supervised_user_service.h +++ b/components/supervised_user/core/browser/supervised_user_service.h
@@ -81,7 +81,12 @@ // * `profile.managed_user_id` for url filtering, remove approvals and custodian // data, // * `incognito.mode_availability` for incognito mode. -class SupervisedUserService : public KeyedService { +class SupervisedUserService : public KeyedService +#if BUILDFLAG(IS_ANDROID) + , + public ContentFiltersObserverBridge::Observer +#endif +{ public: // Delegate encapsulating platform-specific logic that is invoked from this // service. @@ -143,6 +148,12 @@ // ProfileKeyedService override: void Shutdown() override; +#if BUILDFLAG(IS_ANDROID) + // ContentFiltersObserverBridge::Observer: + void OnContentFiltersObserverEnabled(std::string_view setting_name) override; + void OnContentFiltersObserverDisabled(std::string_view setting_name) override; +#endif // BUILDFLAG(IS_ANDROID) + #if BUILDFLAG(IS_CHROMEOS) bool signout_required_after_supervision_enabled() { return signout_required_after_supervision_enabled_; @@ -166,15 +177,18 @@ std::unique_ptr<SupervisedUserService::PlatformDelegate> platform_delegate #if BUILDFLAG(IS_ANDROID) , - ContentFiltersObserverBridge::Factory - content_filters_observer_bridge_factory + std::unique_ptr<ContentFiltersObserverBridge> + browser_content_filters_observer, + std::unique_ptr<ContentFiltersObserverBridge> + search_content_filters_observer #endif ); - protected: #if BUILDFLAG(IS_ANDROID) - ContentFiltersObserverBridge* browser_content_filters_observer(); - ContentFiltersObserverBridge* search_content_filters_observer(); + base::WeakPtr<ContentFiltersObserverBridge> + GetBrowserContentFiltersObserverWeakPtrForTesting(); + base::WeakPtr<ContentFiltersObserverBridge> + GetSearchContentFiltersObserverWeakPtrForTesting(); #endif // BUILDFLAG(IS_ANDROID) private:
diff --git a/components/supervised_user/core/browser/supervised_user_service_unittest.cc b/components/supervised_user/core/browser/supervised_user_service_unittest.cc index 34a29c7..5599cd0 100644 --- a/components/supervised_user/core/browser/supervised_user_service_unittest.cc +++ b/components/supervised_user/core/browser/supervised_user_service_unittest.cc
@@ -433,12 +433,14 @@ : public SupervisedUserServiceWebFilterTypeTransitionsTest { protected: void SetBrowserFilterEnabled(bool enabled) { - supervised_user_test_environment_->browser_content_filters_observer() - ->SetEnabled(enabled); + supervised_user_test_environment_->service() + ->GetBrowserContentFiltersObserverWeakPtrForTesting() + ->SetEnabledForTesting(enabled); } void SetSearchFilterEnabled(bool enabled) { - supervised_user_test_environment_->search_content_filters_observer() - ->SetEnabled(enabled); + supervised_user_test_environment_->service() + ->GetSearchContentFiltersObserverWeakPtrForTesting() + ->SetEnabledForTesting(enabled); } bool IsSupervisedLocally() const { return supervised_user_test_environment_->service()->IsSupervisedLocally();
diff --git a/components/supervised_user/core/browser/supervised_user_test_environment.cc b/components/supervised_user/core/browser/supervised_user_test_environment.cc index 35f9710..cc1c28d 100644 --- a/components/supervised_user/core/browser/supervised_user_test_environment.cc +++ b/components/supervised_user/core/browser/supervised_user_test_environment.cc
@@ -87,21 +87,6 @@ settings_service.SetLocalSetting(content_pack_setting, std::move(dict_to_insert)); } - -#if BUILDFLAG(IS_ANDROID) -std::unique_ptr<ContentFiltersObserverBridge> -CreateFakeContentFiltersObserverBridge( - InitialSupervisionState initial_state, - std::string_view setting_name, - base::RepeatingClosure on_enabled, - base::RepeatingClosure on_disabled, - base::RepeatingCallback<bool()> is_subject_to_parental_controls) { - return std::make_unique<FakeContentFiltersObserverBridge>( - setting_name, on_enabled, on_disabled, is_subject_to_parental_controls, - /*enabled=*/initial_state == - InitialSupervisionState::kSupervisedWithAllContentFilters); -} -#endif } // namespace SupervisedUserSettingsService* InitializeSettingsServiceForTesting( @@ -169,17 +154,14 @@ break; case InitialSupervisionState::kFamilyLinkAllowAllSites: EnableParentalControls(*syncable_pref_service_); - settings_service_.SetLocalSetting(supervised_user::kSafeSitesEnabled, - base::Value(false)); + settings_service_.SetLocalSetting(kSafeSitesEnabled, base::Value(false)); break; case InitialSupervisionState::kFamilyLinkCertainSites: EnableParentalControls(*syncable_pref_service_); - settings_service_.SetLocalSetting(supervised_user::kSafeSitesEnabled, - base::Value(false)); + settings_service_.SetLocalSetting(kSafeSitesEnabled, base::Value(false)); settings_service_.SetLocalSetting( supervised_user::kContentPackDefaultFilteringBehavior, - base::Value( - static_cast<int>(supervised_user::FilteringBehavior::kBlock))); + base::Value(static_cast<int>(FilteringBehavior::kBlock))); break; default: break; @@ -210,6 +192,23 @@ std::make_unique<MetricsServiceAccessorDelegateMock>(), initial_state) {} +#if BUILDFLAG(IS_ANDROID) +namespace { +std::unique_ptr<ContentFiltersObserverBridge> MakeContentFiltersObserverBridge( + std::string_view setting_name, + const PrefService& user_prefs, + InitialSupervisionState initial_state) { + std::unique_ptr<ContentFiltersObserverBridge> bridge = + std::make_unique<FakeContentFiltersObserverBridge>(setting_name, + user_prefs); + bridge->SetEnabledForTesting( + initial_state == + InitialSupervisionState::kSupervisedWithAllContentFilters); + return bridge; +} +} // namespace +#endif // BUILDFLAG(IS_ANDROID) + SupervisedUserTestEnvironment::SupervisedUserTestEnvironment( std::unique_ptr<MetricsServiceAccessorDelegateMock> metrics_service_accessor_delegate, @@ -219,8 +218,7 @@ url_checker_client_ = client.get(); pref_store_environment_.ConfigureInitialValues(initial_state); - - service_ = std::make_unique<TestSupervisedUserService>( + service_ = std::make_unique<SupervisedUserService>( identity_test_env_.identity_manager(), test_url_loader_factory_.GetSafeWeakWrapper(), *pref_store_environment_.pref_service(), @@ -229,7 +227,18 @@ std::make_unique<SupervisedUserURLFilter>( *pref_store_environment_.pref_service(), std::make_unique<FakeURLFilterDelegate>(), std::move(client)), - std::make_unique<FakePlatformDelegate>(), initial_state); + std::make_unique<FakePlatformDelegate>() +#if BUILDFLAG(IS_ANDROID) + , + MakeContentFiltersObserverBridge(kBrowserContentFiltersSettingName, + *pref_store_environment_.pref_service(), + initial_state), + MakeContentFiltersObserverBridge(kSearchContentFiltersSettingName, + *pref_store_environment_.pref_service(), + initial_state) +#endif // BUILDFLAG(IS_ANDROID) + ); + metrics_service_ = std::make_unique<SupervisedUserMetricsService>( pref_store_environment_.pref_service(), *service_.get(), std::make_unique<SupervisedUserMetricsServiceExtensionDelegateFake>(), @@ -252,34 +261,29 @@ WebFilterType web_filter_type, SupervisedUserSettingsService& settings_service) { switch (web_filter_type) { - case supervised_user::WebFilterType::kAllowAllSites: + case WebFilterType::kAllowAllSites: settings_service.SetLocalSetting( - supervised_user::kContentPackDefaultFilteringBehavior, - base::Value( - static_cast<int>(supervised_user::FilteringBehavior::kAllow))); - settings_service.SetLocalSetting(supervised_user::kSafeSitesEnabled, - base::Value(false)); + kContentPackDefaultFilteringBehavior, + base::Value(static_cast<int>(FilteringBehavior::kAllow))); + settings_service.SetLocalSetting(kSafeSitesEnabled, base::Value(false)); break; - case supervised_user::WebFilterType::kTryToBlockMatureSites: + case WebFilterType::kTryToBlockMatureSites: settings_service.SetLocalSetting( - supervised_user::kContentPackDefaultFilteringBehavior, - base::Value( - static_cast<int>(supervised_user::FilteringBehavior::kAllow))); - settings_service.SetLocalSetting(supervised_user::kSafeSitesEnabled, - base::Value(true)); + kContentPackDefaultFilteringBehavior, + base::Value(static_cast<int>(FilteringBehavior::kAllow))); + settings_service.SetLocalSetting(kSafeSitesEnabled, base::Value(true)); break; - case supervised_user::WebFilterType::kCertainSites: + case WebFilterType::kCertainSites: settings_service.SetLocalSetting( - supervised_user::kContentPackDefaultFilteringBehavior, - base::Value( - static_cast<int>(supervised_user::FilteringBehavior::kBlock))); + kContentPackDefaultFilteringBehavior, + base::Value(static_cast<int>(FilteringBehavior::kBlock))); // Value of kSupervisedUserSafeSites is not important here. break; - case supervised_user::WebFilterType::kDisabled: + case WebFilterType::kDisabled: NOTREACHED() << "To disable the URL filter, use " "supervised_user::DisableParentalControls(.)"; - case supervised_user::WebFilterType::kMixed: + case WebFilterType::kMixed: NOTREACHED() << "That value is not intended to be set, but is rather " "used to indicate multiple settings used in profiles " "in metrics."; @@ -303,8 +307,7 @@ std::string_view host, bool allowlist, SupervisedUserSettingsService& service) { - SetManualFilter(supervised_user::kContentPackManualBehaviorHosts, host, - allowlist, service); + SetManualFilter(kContentPackManualBehaviorHosts, host, allowlist, service); } void SupervisedUserTestEnvironment::SetManualFilterForUrl(std::string_view url, @@ -316,14 +319,13 @@ std::string_view url, bool allowlist, SupervisedUserSettingsService& service) { - SetManualFilter(supervised_user::kContentPackManualBehaviorURLs, url, - allowlist, service); + SetManualFilter(kContentPackManualBehaviorURLs, url, allowlist, service); } SupervisedUserURLFilter* SupervisedUserTestEnvironment::url_filter() const { return service()->GetURLFilter(); } -TestSupervisedUserService* SupervisedUserTestEnvironment::service() const { +SupervisedUserService* SupervisedUserTestEnvironment::service() const { return service_.get(); } PrefService* SupervisedUserTestEnvironment::pref_service() { @@ -340,134 +342,24 @@ } #if BUILDFLAG(IS_ANDROID) - -base::WeakPtr<FakeContentFiltersObserverBridge> -SupervisedUserTestEnvironment::browser_content_filters_observer() { - return service_->browser_content_filters_observer_weak_ptr(); -} -base::WeakPtr<FakeContentFiltersObserverBridge> -SupervisedUserTestEnvironment::search_content_filters_observer() { - return service_->search_content_filters_observer_weak_ptr(); -} - FakeContentFiltersObserverBridge::FakeContentFiltersObserverBridge( std::string_view setting_name, - base::RepeatingClosure on_enabled, - base::RepeatingClosure on_disabled, - base::RepeatingCallback<bool()> is_subject_to_parental_controls, - bool initial_value) - : ContentFiltersObserverBridge(setting_name, - on_enabled, - on_disabled, - is_subject_to_parental_controls) { - initial_value_ = initial_value; -} - + const PrefService& pref_service) + : ContentFiltersObserverBridge(setting_name, pref_service) {} FakeContentFiltersObserverBridge::~FakeContentFiltersObserverBridge() = default; void FakeContentFiltersObserverBridge::Init() { - // Imitates behavior of the real bridge: it always notifies on creation. - SetEnabled(initial_value_); - OnChange(/*env=*/nullptr, initial_value_); + // Freshly initialized real java bridge would notify all observers. + NotifyObservers(); } void FakeContentFiltersObserverBridge::Shutdown() { // Do nothing, specifically do not destroy the java bridge from super. } - -void FakeContentFiltersObserverBridge::SetEnabled(bool enabled) { - // Imitates behavior of the real bridge: it does not notify if the value - // did not change. - if (enabled == IsEnabled()) { - return; - } - - ContentFiltersObserverBridge::SetEnabled(enabled); - // This is fine: JNIEnv is not used, because OnChange notifies native code. - OnChange(/*env=*/nullptr, enabled); -} - -base::WeakPtr<FakeContentFiltersObserverBridge> -FakeContentFiltersObserverBridge::GetWeakPtr() { - return weak_ptr_factory_.GetWeakPtr(); -} #endif // BUILDFLAG(IS_ANDROID) MetricsServiceAccessorDelegateMock::MetricsServiceAccessorDelegateMock() = default; MetricsServiceAccessorDelegateMock::~MetricsServiceAccessorDelegateMock() = default; - -TestSupervisedUserService::TestSupervisedUserService( - signin::IdentityManager* identity_manager, - scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, - PrefService& user_prefs, - SupervisedUserSettingsService& settings_service, - SupervisedUserContentFiltersService* content_filters_service, - syncer::SyncService* sync_service, - std::unique_ptr<SupervisedUserURLFilter> url_filter, - std::unique_ptr<SupervisedUserService::PlatformDelegate> platform_delegate -#if BUILDFLAG(IS_ANDROID) - , - ContentFiltersObserverBridge::Factory - content_filters_observer_bridge_factory -#endif - ) - : SupervisedUserService(identity_manager, - url_loader_factory, - user_prefs, - settings_service, - content_filters_service, - sync_service, - std::move(url_filter), - std::move(platform_delegate) -#if BUILDFLAG(IS_ANDROID) - , - content_filters_observer_bridge_factory -#endif - ) { -} - -TestSupervisedUserService::TestSupervisedUserService( - signin::IdentityManager* identity_manager, - scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, - PrefService& user_prefs, - SupervisedUserSettingsService& settings_service, - SupervisedUserContentFiltersService* content_filters_service, - syncer::SyncService* sync_service, - std::unique_ptr<SupervisedUserURLFilter> url_filter, - std::unique_ptr<SupervisedUserService::PlatformDelegate> platform_delegate, - InitialSupervisionState initial_state) - : SupervisedUserService( - identity_manager, - url_loader_factory, - user_prefs, - settings_service, - content_filters_service, - sync_service, - std::move(url_filter), - std::move(platform_delegate) -#if BUILDFLAG(IS_ANDROID) - , - base::BindRepeating(&CreateFakeContentFiltersObserverBridge, - initial_state) -#endif - ) { -} - -#if BUILDFLAG(IS_ANDROID) -base::WeakPtr<FakeContentFiltersObserverBridge> -TestSupervisedUserService::browser_content_filters_observer_weak_ptr() { - return static_cast<FakeContentFiltersObserverBridge*>( - browser_content_filters_observer()) - ->GetWeakPtr(); -} -base::WeakPtr<FakeContentFiltersObserverBridge> -TestSupervisedUserService::search_content_filters_observer_weak_ptr() { - return static_cast<FakeContentFiltersObserverBridge*>( - search_content_filters_observer()) - ->GetWeakPtr(); -} -#endif // BUILDFLAG( - } // namespace supervised_user
diff --git a/components/supervised_user/core/browser/supervised_user_test_environment.h b/components/supervised_user/core/browser/supervised_user_test_environment.h index 7fd0d02a..e0f583b 100644 --- a/components/supervised_user/core/browser/supervised_user_test_environment.h +++ b/components/supervised_user/core/browser/supervised_user_test_environment.h
@@ -112,22 +112,17 @@ }; #if BUILDFLAG(IS_ANDROID) -// Fake implementation of ContentFiltersObserverBridge for testing. Imitates -// events that would normally be produced by the Android's secure settings -// (which store content filter settings). Content bridge is initialized with -// "disabled" setting. +// Fake implementation of ContentFiltersObserverBridge for testing stripped from +// the Java class backend. Imitates events that would normally be produced by +// the Android's secure settings (which store content filter settings). Content +// bridge is initialized with "disabled" setting. Use "SetEnabledForTesting" to +// simulate the changing value of the setting. class FakeContentFiltersObserverBridge final : public ContentFiltersObserverBridge { public: - // Matching constructor of ContentFiltersObserverBridge. Setting the initial - // value to true helps to test scenarios when the browser is started with the - // setting already enabled. - FakeContentFiltersObserverBridge( - std::string_view setting_name, - base::RepeatingClosure on_enabled, - base::RepeatingClosure on_disabled, - base::RepeatingCallback<bool()> is_subject_to_parental_controls, - bool initial_value = false); + // Matching constructor of ContentFiltersObserverBridge. + FakeContentFiltersObserverBridge(std::string_view setting_name, + const PrefService& pref_service); FakeContentFiltersObserverBridge(const FakeContentFiltersObserverBridge&) = delete; FakeContentFiltersObserverBridge& operator=( @@ -137,62 +132,9 @@ // Override to suppress initialization of the java bridge. void Init() override; void Shutdown() override; - - // Set mocked value and trigger native code callbacks. - void SetEnabled(bool enabled) override; - - base::WeakPtr<FakeContentFiltersObserverBridge> GetWeakPtr(); - - private: - bool initial_value_ = false; - base::WeakPtrFactory<FakeContentFiltersObserverBridge> weak_ptr_factory_{ - this}; }; #endif // BUILDFLAG(IS_ANDROID) -// Offers access to the protected constructor of SupervisedUserService, used -// to inject fake content filters observers (with initial values described in -// initial_state) -class TestSupervisedUserService : public SupervisedUserService { - public: - // Matching constructor of SupervisedUserService. - TestSupervisedUserService( - signin::IdentityManager* identity_manager, - scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, - PrefService& user_prefs, - SupervisedUserSettingsService& settings_service, - SupervisedUserContentFiltersService* content_filters_service, - syncer::SyncService* sync_service, - std::unique_ptr<SupervisedUserURLFilter> url_filter, - std::unique_ptr<SupervisedUserService::PlatformDelegate> platform_delegate -#if BUILDFLAG(IS_ANDROID) - , - ContentFiltersObserverBridge::Factory - content_filters_observer_bridge_factory -#endif - ); - - // Constructor that takes the initial state of supervision. - TestSupervisedUserService( - signin::IdentityManager* identity_manager, - scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, - PrefService& user_prefs, - SupervisedUserSettingsService& settings_service, - SupervisedUserContentFiltersService* content_filters_service, - syncer::SyncService* sync_service, - std::unique_ptr<SupervisedUserURLFilter> url_filter, - std::unique_ptr<SupervisedUserService::PlatformDelegate> - platform_delegate, - InitialSupervisionState initial_state); - -#if BUILDFLAG(IS_ANDROID) - base::WeakPtr<FakeContentFiltersObserverBridge> - browser_content_filters_observer_weak_ptr(); - base::WeakPtr<FakeContentFiltersObserverBridge> - search_content_filters_observer_weak_ptr(); -#endif // BUILDFLAG(IS_ANDROID) -}; - // Configures a handy set of components that form supervised user features, for // unit testing. This is a lightweight, unit-test oriented alternative to a // TestingProfile with enabled supervision. @@ -215,18 +157,11 @@ ~SupervisedUserTestEnvironment(); SupervisedUserURLFilter* url_filter() const; - TestSupervisedUserService* service() const; + SupervisedUserService* service() const; PrefService* pref_service(); sync_preferences::TestingPrefServiceSyncable* pref_service_syncable(); safe_search_api::FakeURLCheckerClient* url_checker_client(); -#if BUILDFLAG(IS_ANDROID) - base::WeakPtr<FakeContentFiltersObserverBridge> - browser_content_filters_observer(); - base::WeakPtr<FakeContentFiltersObserverBridge> - search_content_filters_observer(); -#endif // BUILDFLAG(IS_ANDROID) - // Simulators of parental controls. Instance methods use services from this // test environment, while static methods are suitable for heavier testing // profile use. @@ -262,7 +197,7 @@ syncer::MockSyncService sync_service_; // Core services under test - std::unique_ptr<TestSupervisedUserService> service_; + std::unique_ptr<SupervisedUserService> service_; std::unique_ptr<SupervisedUserMetricsService> metrics_service_; // The objects are actually owned by the service_, but are referenced here for
diff --git a/components/viz/service/display/direct_renderer.cc b/components/viz/service/display/direct_renderer.cc index e7218b2..19e71c4a 100644 --- a/components/viz/service/display/direct_renderer.cc +++ b/components/viz/service/display/direct_renderer.cc
@@ -292,6 +292,27 @@ output_surface_->GetDisplayTransform()); overlay_processor_->SetViewportSize(device_viewport_size); + // Before ProcessForOverlay calls into the hardware to ask about whether the + // overlay setup can be handled, we need to set up the primary plane. + std::optional<OverlayCandidate> primary_plane; + if (output_surface_->capabilities().renderer_allocates_images) { + primary_plane = overlay_processor_->ProcessOutputSurfaceAsOverlay( + device_viewport_size, surface_resource_size, frame_si_format, + frame_color_space, + current_frame()->root_render_pass->has_transparent_background, + 1.0f /*opacity*/, GetPrimaryPlaneOverlayTestingMailbox()); + + if (current_frame()->display_color_spaces.SupportsHDR() && + current_frame()->root_render_pass->content_color_usage == + gfx::ContentColorUsage::kHDR) { + primary_plane->hdr_metadata.extended_range.emplace(); + // TODO(crbug.com/40263227): Track the actual brightness of the + // content. For now, assume that all HDR content is 1,000 nits. + primary_plane->hdr_metadata.extended_range->desired_headroom = + gfx::HdrMetadataExtendedRange::kDefaultHdrHeadroom; + } + } + // Attempt to replace some or all of the quads of the root render pass with // overlays. base::ElapsedTimer overlay_processing_timer; @@ -299,25 +320,8 @@ resource_provider_, render_passes_in_draw_order, output_surface_->color_matrix(), render_pass_filters_, render_pass_backdrop_filters_, std::move(surface_damage_rect_list), - OverlayProcessorInterface::PrimaryPlaneParams{ - .viewport_size = device_viewport_size, - .resource_size_in_pixels = surface_resource_size, - .supports_hdr = - current_frame()->display_color_spaces.SupportsHDR() && - render_passes_in_draw_order->back()->content_color_usage == - gfx::ContentColorUsage::kHDR, - .is_opaque = !render_passes_in_draw_order->back() - ->has_transparent_background, -#if BUILDFLAG(IS_OZONE) - .si_format = frame_si_format, - .color_space = frame_color_space, - .overlay_testing_mailbox = - output_surface_->capabilities().renderer_allocates_images - ? GetPrimaryPlaneOverlayTestingMailbox() - : gpu::Mailbox(), -#endif - }, - ¤t_frame()->overlay_list, ¤t_frame()->root_damage_rect, + primary_plane, ¤t_frame()->overlay_list, + ¤t_frame()->root_damage_rect, ¤t_frame()->root_content_bounds); auto overlay_processing_time = overlay_processing_timer.Elapsed(); @@ -1222,10 +1226,8 @@ return gfx::Rect(); } -#if BUILDFLAG(IS_OZONE) gpu::Mailbox DirectRenderer::GetPrimaryPlaneOverlayTestingMailbox() { NOTREACHED(); } -#endif } // namespace viz
diff --git a/components/viz/service/display/direct_renderer.h b/components/viz/service/display/direct_renderer.h index da3bd0e..5da72e7 100644 --- a/components/viz/service/display/direct_renderer.h +++ b/components/viz/service/display/direct_renderer.h
@@ -195,11 +195,9 @@ // 0 < n <= capabilities_.number_of_buffers. virtual void EnsureMinNumberOfBuffers(int n) {} -#if BUILDFLAG(IS_OZONE) // Gets a mailbox that can be used for overlay testing the primary plane. This // does not need to be the next mailbox that will be swapped. virtual gpu::Mailbox GetPrimaryPlaneOverlayTestingMailbox(); -#endif // Return the bounding rect of previously drawn delegated ink trail. gfx::Rect GetDelegatedInkTrailDamageRect();
diff --git a/components/viz/service/display/overlay_ca_unittest.cc b/components/viz/service/display/overlay_ca_unittest.cc index 667cad7a..c84e749 100644 --- a/components/viz/service/display/overlay_ca_unittest.cc +++ b/components/viz/service/display/overlay_ca_unittest.cc
@@ -194,14 +194,12 @@ output_surface_ = nullptr; } - OverlayProcessorInterface::PrimaryPlaneParams GetDefaultPrimaryPlane( - const gfx::Size& primary_plane_size) { - return OverlayProcessorInterface::PrimaryPlaneParams{ - .viewport_size = primary_plane_size, - .resource_size_in_pixels = primary_plane_size, - .supports_hdr = false, - .is_opaque = true, - }; + std::optional<OverlayCandidate>& GetDefaultPrimaryPlane( + const gfx::Size& size) { + primary_plane_ = OverlayProcessorInterface::ProcessOutputSurfaceAsOverlay( + size, size, SinglePlaneFormat::kRGBA_8888, + gfx::ColorSpace::CreateSRGB(), false, 1.0, gpu::Mailbox()); + return primary_plane_; } std::unique_ptr<SkiaOutputSurface> output_surface_;
diff --git a/components/viz/service/display/overlay_dc_unittest.cc b/components/viz/service/display/overlay_dc_unittest.cc index ab07a00..59003d14 100644 --- a/components/viz/service/display/overlay_dc_unittest.cc +++ b/components/viz/service/display/overlay_dc_unittest.cc
@@ -2594,6 +2594,8 @@ overlay_processor_->SetViewportSize(gfx::Size(256, 256)); EXPECT_TRUE(overlay_processor_->IsOverlaySupported()); + + output_surface_plane_ = GetDefaultPrimaryPlane(gfx::Size(256, 256)); } void TearDown() override { @@ -2601,16 +2603,14 @@ OverlayProcessorTestBase::TearDown(); } - OverlayProcessorInterface::PrimaryPlaneParams GetDefaultPrimaryPlane( + std::optional<OverlayCandidate> GetDefaultPrimaryPlane( const gfx::Size& primary_plane_size) { - return OverlayProcessorInterface::PrimaryPlaneParams{ - .viewport_size = primary_plane_size, - .resource_size_in_pixels = primary_plane_size, - .supports_hdr = false, - .is_opaque = true, - }; + return overlay_processor_->ProcessOutputSurfaceAsOverlay( + primary_plane_size, primary_plane_size, SinglePlaneFormat::kBGRA_8888, + gfx::ColorSpace::CreateSRGB(), false, 1.0, gpu::Mailbox()); } + std::optional<OverlayCandidate> output_surface_plane_; std::unique_ptr<OverlayProcessorWin> overlay_processor_; gfx::Rect damage_rect_; std::vector<gfx::Rect> content_bounds_; @@ -2752,11 +2752,12 @@ &damage_rect_); } + output_surface_plane_ = + GetDefaultPrimaryPlane(render_passes->back()->output_rect.size()); overlay_processor_->ProcessForOverlays( resource_provider_.get(), render_passes, SkM44(), std::move(surface_damage_rect_list_in_root_space), - GetDefaultPrimaryPlane(render_passes->back()->output_rect.size()), - candidates, &damage_rect_, &content_bounds_); + output_surface_plane_, candidates, &damage_rect_, &content_bounds_); } private: @@ -3075,6 +3076,10 @@ EXPECT_THAT(overlays, testing::ElementsAreArray({ test::OverlayIsFullScreen(), })); + + // Check that the next call to `AdjustOutputSurfaceOverlay` clears the primary + // plane. + EXPECT_FALSE(output_surface_plane_.has_value()); } INSTANTIATE_TEST_SUITE_P( @@ -3130,6 +3135,12 @@ DelegationResult TryProcessForDelegatedOverlays( AggregatedRenderPassList& pass_list, SurfaceDamageRectList surface_damage_rect_list = {}) { + if (!output_surface_plane_) { + // Reset the output surface plane in case we're calling + // |TryProcessForDelegatedOverlays| multiple times. + output_surface_plane_ = OverlayCandidate(); + } + const gfx::Rect original_root_surface_damage = pass_list.back()->damage_rect; @@ -3150,9 +3161,8 @@ overlay_processor_->ProcessForOverlays( resource_provider_.get(), &pass_list, GetIdentityColorMatrix(), render_pass_filters, render_pass_backdrop_filters, - std::move(surface_damage_rect_list), - GetDefaultPrimaryPlane(pass_list.back()->output_rect.size()), - &candidates, &damage_rect_, &content_bounds_); + std::move(surface_damage_rect_list), output_surface_plane_, &candidates, + &damage_rect_, &content_bounds_); const bool delegation_succeeded = std::ranges::none_of( candidates,
diff --git a/components/viz/service/display/overlay_processor_android.cc b/components/viz/service/display/overlay_processor_android.cc index c269c79..ababf9a 100644 --- a/components/viz/service/display/overlay_processor_android.cc +++ b/components/viz/service/display/overlay_processor_android.cc
@@ -197,10 +197,6 @@ NOTREACHED(); } -bool OverlayProcessorAndroid::ShouldCreatePrimaryPlane() const { - return false; -} - void OverlayProcessorAndroid::TakeOverlayCandidates( OverlayCandidateList* candidate_list) { overlay_candidates_.swap(*candidate_list);
diff --git a/components/viz/service/display/overlay_processor_android.h b/components/viz/service/display/overlay_processor_android.h index 1e5f196..aae6860 100644 --- a/components/viz/service/display/overlay_processor_android.h +++ b/components/viz/service/display/overlay_processor_android.h
@@ -63,8 +63,6 @@ void InsertPrimaryPlane(OverlayCandidate primary_plane, OverlayCandidateList& candidates) override; - bool ShouldCreatePrimaryPlane() const override; - private: // OverlayProcessor needs to send overlay candidate information to the gpu // thread. These two methods are scheduled on the gpu thread to setup and
diff --git a/components/viz/service/display/overlay_processor_delegated.cc b/components/viz/service/display/overlay_processor_delegated.cc index 237f490..a91a864 100644 --- a/components/viz/service/display/overlay_processor_delegated.cc +++ b/components/viz/service/display/overlay_processor_delegated.cc
@@ -70,7 +70,7 @@ const DisplayResourceProvider* resource_provider, AggregatedRenderPassList* render_pass_list, SurfaceDamageRectList* surface_damage_rect_list, - const std::optional<OverlayCandidate>& primary_plane, + std::optional<OverlayCandidate>& primary_plane, OverlayCandidateList* candidates, std::vector<gfx::Rect>* content_bounds) { DCHECK(candidates->empty()); @@ -187,7 +187,7 @@ const OverlayProcessorInterface::FilterOperationsMap& render_pass_backdrop_filters, SurfaceDamageRectList surface_damage_rect_list, - const PrimaryPlaneParams& primary_plane_params, + std::optional<OverlayCandidate>& primary_plane, CandidateList* candidates, gfx::Rect* damage_rect, std::vector<gfx::Rect>* content_bounds) { @@ -196,9 +196,6 @@ DebugLogBeforeDelegation(*damage_rect, surface_damage_rect_list); - std::optional<OverlayCandidate> primary_plane = - CreatePrimaryPlane(primary_plane_params); - success = AttemptWithStrategies( output_color_matrix, render_pass_filters, render_pass_backdrop_filters, resource_provider, render_passes, &surface_damage_rect_list, @@ -220,6 +217,10 @@ // This is only relevant when delegating. unassigned_damage_ = gfx::RectF(); + CHECK(primary_plane); + render_passes->back()->has_transparent_background |= + !primary_plane->is_opaque; + // TODO(crbug.com/40775556) : Damage propagation will allow us to remove the // primary plan entirely in the case of full delegation. InsertPrimaryPlane(std::move(primary_plane).value(), *candidates);
diff --git a/components/viz/service/display/overlay_processor_delegated.h b/components/viz/service/display/overlay_processor_delegated.h index fc72a310..2fa78ead 100644 --- a/components/viz/service/display/overlay_processor_delegated.h +++ b/components/viz/service/display/overlay_processor_delegated.h
@@ -54,7 +54,7 @@ const FilterOperationsMap& render_pass_filters, const FilterOperationsMap& render_pass_backdrop_filters, SurfaceDamageRectList surface_damage_rect_list, - const PrimaryPlaneParams& primary_plane_params, + std::optional<OverlayCandidate>& primary_plane, CandidateList* overlay_candidates, gfx::Rect* damage_rect, std::vector<gfx::Rect>* content_bounds) final; @@ -79,7 +79,7 @@ const DisplayResourceProvider* resource_provider, AggregatedRenderPassList* render_pass_list, SurfaceDamageRectList* surface_damage_rect_list, - const std::optional<OverlayCandidate>& primary_plane, + std::optional<OverlayCandidate>& primary_plane, OverlayCandidateList* candidates, std::vector<gfx::Rect>* content_bounds);
diff --git a/components/viz/service/display/overlay_processor_interface.cc b/components/viz/service/display/overlay_processor_interface.cc index 61c62a8..a534000 100644 --- a/components/viz/service/display/overlay_processor_interface.cc +++ b/components/viz/service/display/overlay_processor_interface.cc
@@ -186,9 +186,14 @@ return false; } -// static -OverlayCandidate OverlayProcessorInterface::CreatePrimaryPlane( - const PrimaryPlaneParams& params) { +OverlayCandidate OverlayProcessorInterface::ProcessOutputSurfaceAsOverlay( + const gfx::Size& viewport_size, + const gfx::Size& resource_size, + const SharedImageFormat si_format, + const gfx::ColorSpace& color_space, + bool has_alpha, + float opacity, + const gpu::Mailbox& mailbox) { OverlayCandidate overlay_plane; overlay_plane.is_root_render_pass = true; #if BUILDFLAG(IS_APPLE) || BUILDFLAG(IS_WIN) @@ -196,40 +201,27 @@ #else overlay_plane.transform = gfx::OverlayTransform::OVERLAY_TRANSFORM_NONE; #endif - overlay_plane.is_opaque = params.is_opaque; - overlay_plane.opacity = 1.0f; + overlay_plane.uv_rect = gfx::RectF( + 0.f, 0.f, + viewport_size.width() / static_cast<float>(resource_size.width()), + viewport_size.height() / static_cast<float>(resource_size.height())); + overlay_plane.resource_size_in_pixels = resource_size; + overlay_plane.format = si_format; + overlay_plane.color_space = color_space; + overlay_plane.is_opaque = !has_alpha; + overlay_plane.opacity = opacity; + overlay_plane.mailbox = mailbox; overlay_plane.priority_hint = gfx::OverlayPriorityHint::kRegular; overlay_plane.rounded_corners = gfx::RRectF(); // Adjust transformation and display_rect based on display rotation. - overlay_plane.display_rect = gfx::RectF(params.viewport_size); - overlay_plane.resource_size_in_pixels = params.resource_size_in_pixels; - overlay_plane.uv_rect = gfx::RectF( - 0.f, 0.f, - overlay_plane.display_rect.width() / - static_cast<float>(overlay_plane.resource_size_in_pixels.width()), - overlay_plane.display_rect.height() / - static_cast<float>(overlay_plane.resource_size_in_pixels.height())); + overlay_plane.display_rect = + gfx::RectF(viewport_size.width(), viewport_size.height()); #if BUILDFLAG(ALWAYS_ENABLE_BLENDING_FOR_PRIMARY) // On Chromecast, always use RGBA as the scanout format for the primary plane. overlay_plane.is_opaque = false; #endif - -#if BUILDFLAG(IS_OZONE) - overlay_plane.format = params.si_format; - overlay_plane.color_space = params.color_space; - overlay_plane.mailbox = params.overlay_testing_mailbox; -#endif - - if (params.supports_hdr) { - overlay_plane.hdr_metadata.extended_range.emplace(); - // TODO(crbug.com/40263227): Track the actual brightness of the - // content. For now, assume that all HDR content is 1,000 nits. - overlay_plane.hdr_metadata.extended_range->desired_headroom = - gfx::HdrMetadataExtendedRange::kDefaultHdrHeadroom; - } - return overlay_plane; } @@ -238,7 +230,7 @@ AggregatedRenderPassList* render_passes, const SkM44& output_color_matrix, SurfaceDamageRectList surface_damage_rect_list, - const PrimaryPlaneParams& primary_plane_params, + std::optional<OverlayCandidate>& primary_plane, CandidateList* overlay_candidates, gfx::Rect* damage_rect, std::vector<gfx::Rect>* content_bounds) { @@ -246,7 +238,7 @@ ProcessForOverlays(resource_provider, render_passes, output_color_matrix, /*render_pass_filters=*/{}, /*render_pass_backdrop_filters=*/{}, - surface_damage_rect_list, primary_plane_params, + surface_damage_rect_list, primary_plane, overlay_candidates, damage_rect, content_bounds); }
diff --git a/components/viz/service/display/overlay_processor_interface.h b/components/viz/service/display/overlay_processor_interface.h index a414ecc..6cf92ad 100644 --- a/components/viz/service/display/overlay_processor_interface.h +++ b/components/viz/service/display/overlay_processor_interface.h
@@ -66,6 +66,18 @@ bool has_occluding_surface_damage, bool zero_damage_rect); + // TODO(weiliangc): Eventually the asymmetry between primary plane and + // non-primary places should be internalized and should not have a special + // API. + static OverlayCandidate ProcessOutputSurfaceAsOverlay( + const gfx::Size& viewport_size, + const gfx::Size& resource_size, + const SharedImageFormat si_format, + const gfx::ColorSpace& color_space, + bool has_alpha, + float opacity, + const gpu::Mailbox& mailbox); + static std::unique_ptr<OverlayProcessorInterface> CreateOverlayProcessor( OutputSurface* output_surface, gpu::SurfaceHandle surface_handle, @@ -90,23 +102,6 @@ // processor. virtual bool NeedsSurfaceDamageRectList() const = 0; - struct PrimaryPlaneParams { - const gfx::Size viewport_size; - const gfx::Size resource_size_in_pixels; - bool supports_hdr = false; - bool is_opaque = false; - -#if BUILDFLAG(IS_OZONE) - // Ozone requires checking for overlay support with an actual buffer. To - // create the primary plane, `OverlayProcessorOzone` will use an existing - // `overlay_testing_mailbox` (usually, the last swapped primary plane - // buffer) or will make a dummy buffer using `si_format` and `color_space`. - const SharedImageFormat si_format; - const gfx::ColorSpace color_space; - const gpu::Mailbox overlay_testing_mailbox; -#endif - }; - // Attempts to replace quads from the specified root render pass with overlays // or CALayers. This must be called every frame. // TODO(crbug.com/444264038): Delete this overload when the RPDQ refactor is @@ -118,7 +113,7 @@ const FilterOperationsMap& render_pass_filters, const FilterOperationsMap& render_pass_backdrop_filters, SurfaceDamageRectList surface_damage_rect_list, - const PrimaryPlaneParams& primary_plane_params, + std::optional<OverlayCandidate>& primary_plane, CandidateList* overlay_candidates, gfx::Rect* damage_rect, std::vector<gfx::Rect>* content_bounds) = 0; @@ -127,7 +122,7 @@ AggregatedRenderPassList* render_passes, const SkM44& output_color_matrix, SurfaceDamageRectList surface_damage_rect_list, - const PrimaryPlaneParams& primary_plane_params, + std::optional<OverlayCandidate>& primary_plane, CandidateList* overlay_candidates, gfx::Rect* damage_rect, std::vector<gfx::Rect>* content_bounds); @@ -181,8 +176,6 @@ protected: OverlayProcessorInterface() = default; - - static OverlayCandidate CreatePrimaryPlane(const PrimaryPlaneParams& params); }; } // namespace viz
diff --git a/components/viz/service/display/overlay_processor_mac.cc b/components/viz/service/display/overlay_processor_mac.cc index 76fa8119..0cbe45f 100644 --- a/components/viz/service/display/overlay_processor_mac.cc +++ b/components/viz/service/display/overlay_processor_mac.cc
@@ -48,7 +48,7 @@ const OverlayProcessorInterface::FilterOperationsMap& render_pass_backdrop_filters, SurfaceDamageRectList surface_damage_rect_list, - const PrimaryPlaneParams& primary_plane_params, + std::optional<OverlayCandidate>& primary_plane, CandidateList* candidates, gfx::Rect* damage_rect, std::vector<gfx::Rect>* content_bounds) { @@ -79,9 +79,13 @@ &render_pass->quad_list, render_pass_filters, render_pass_backdrop_filters, candidates); + CHECK(primary_plane); + render_pass->has_transparent_background |= !primary_plane->is_opaque; + // Mac doesn't use the plane_z_order field and it needs to have primary // plane last in the list of overlays. - candidates->push_back(CreatePrimaryPlane(primary_plane_params)); + candidates->push_back(std::move(primary_plane).value()); + primary_plane.reset(); } }
diff --git a/components/viz/service/display/overlay_processor_mac.h b/components/viz/service/display/overlay_processor_mac.h index cb41887..7cbe033 100644 --- a/components/viz/service/display/overlay_processor_mac.h +++ b/components/viz/service/display/overlay_processor_mac.h
@@ -57,7 +57,7 @@ const FilterOperationsMap& render_pass_filters, const FilterOperationsMap& render_pass_backdrop_filters, SurfaceDamageRectList surface_damage_rect_list, - const PrimaryPlaneParams& primary_plane_params, + std::optional<OverlayCandidate>& primary_plane, CandidateList* overlay_candidates, gfx::Rect* damage_rect, std::vector<gfx::Rect>* content_bounds) override;
diff --git a/components/viz/service/display/overlay_processor_ozone.cc b/components/viz/service/display/overlay_processor_ozone.cc index 692e835ac..f34718c 100644 --- a/components/viz/service/display/overlay_processor_ozone.cc +++ b/components/viz/service/display/overlay_processor_ozone.cc
@@ -498,14 +498,6 @@ candidates.insert(insert_positon, std::move(primary_plane)); } -bool OverlayProcessorOzone::ShouldCreatePrimaryPlane() const { -#if BUILDFLAG(IS_CASTOS) - return false; -#else - return true; -#endif -} - bool OverlayProcessorOzone::SetNativePixmapForCandidate( ui::OverlaySurfaceCandidate* candidate, const gpu::Mailbox& mailbox,
diff --git a/components/viz/service/display/overlay_processor_ozone.h b/components/viz/service/display/overlay_processor_ozone.h index e3caead..4d9420a4 100644 --- a/components/viz/service/display/overlay_processor_ozone.h +++ b/components/viz/service/display/overlay_processor_ozone.h
@@ -69,8 +69,6 @@ void InsertPrimaryPlane(OverlayCandidate primary_plane, OverlayCandidateList& candidates) override; - bool ShouldCreatePrimaryPlane() const override; - private: // Populates |native_pixmap| and |native_pixmap_unique_id| in |candidate| // based on |mailbox|. |is_primary| should be true if this is the primary
diff --git a/components/viz/service/display/overlay_processor_stub.h b/components/viz/service/display/overlay_processor_stub.h index 25d1519f..411f00c 100644 --- a/components/viz/service/display/overlay_processor_stub.h +++ b/components/viz/service/display/overlay_processor_stub.h
@@ -33,7 +33,7 @@ const FilterOperationsMap& render_pass_filters, const FilterOperationsMap& render_pass_backdrop_filters, SurfaceDamageRectList surface_damage_rect_list, - const PrimaryPlaneParams& primary_plane_params, + std::optional<OverlayCandidate>& primary_plane, CandidateList* overlay_candidates, gfx::Rect* damage_rect, std::vector<gfx::Rect>* content_bounds) final {}
diff --git a/components/viz/service/display/overlay_processor_using_strategy.cc b/components/viz/service/display/overlay_processor_using_strategy.cc index c1eb0d1..385ddbd 100644 --- a/components/viz/service/display/overlay_processor_using_strategy.cc +++ b/components/viz/service/display/overlay_processor_using_strategy.cc
@@ -363,13 +363,15 @@ const OverlayProcessorInterface::FilterOperationsMap& render_pass_backdrop_filters, SurfaceDamageRectList surface_damage_rect_list, - const PrimaryPlaneParams& primary_plane_params, + std::optional<OverlayCandidate>& primary_plane, CandidateList* candidates, gfx::Rect* damage_rect, std::vector<gfx::Rect>* content_bounds) { #if BUILDFLAG(IS_CHROMEOS) // TODO(b/181974042): Remove when color space is plumbed. - primary_plane_color_space_ = primary_plane_params.color_space; + if (primary_plane) { + primary_plane_color_space_ = primary_plane->color_space; + } #endif TRACE_EVENT0("viz", "OverlayProcessorUsingStrategy::ProcessForOverlays"); DCHECK(candidates->empty()); @@ -392,10 +394,6 @@ // contents. bool skip_because_copy_request = BlockForCopyRequests(render_pass); - std::optional<OverlayCandidate> primary_plane; - if (ShouldCreatePrimaryPlane()) { - primary_plane = CreatePrimaryPlane(primary_plane_params); - } if (!skip_because_copy_request && !disable_overlay()) { success = AttemptWithStrategies( output_color_matrix, render_pass_filters, render_pass_backdrop_filters, @@ -455,10 +453,6 @@ candidates.push_back(std::move(primary_plane)); } -bool OverlayProcessorUsingStrategy::ShouldCreatePrimaryPlane() const { - return true; -} - void OverlayProcessorUsingStrategy::ClearOverlayCombinationCache() { overlay_combination_cache_.ClearCache(); }
diff --git a/components/viz/service/display/overlay_processor_using_strategy.h b/components/viz/service/display/overlay_processor_using_strategy.h index 36d34df..46d3d3e 100644 --- a/components/viz/service/display/overlay_processor_using_strategy.h +++ b/components/viz/service/display/overlay_processor_using_strategy.h
@@ -72,7 +72,7 @@ const FilterOperationsMap& render_pass_filters, const FilterOperationsMap& render_pass_backdrop_filters, SurfaceDamageRectList surface_damage_rect_list, - const PrimaryPlaneParams& primary_plane_params, + std::optional<OverlayCandidate>& primary_plane, CandidateList* overlay_candidates, gfx::Rect* damage_rect, std::vector<gfx::Rect>* content_bounds) @@ -148,11 +148,8 @@ // confirmed in `OverlayProcessorOzone::ReceiveHardwareCapabilities`. int max_overlays_considered_ = 1; - protected: - // TODO Can be removed if OverlayProcessorAndroid is removed. - virtual bool ShouldCreatePrimaryPlane() const; - #if BUILDFLAG(IS_CHROMEOS) + protected: // TODO(b/181974042): Remove when color space is plumbed. gfx::ColorSpace primary_plane_color_space_; #endif
diff --git a/components/viz/service/display/overlay_processor_win.cc b/components/viz/service/display/overlay_processor_win.cc index 97f37f9..5e17fa2 100644 --- a/components/viz/service/display/overlay_processor_win.cc +++ b/components/viz/service/display/overlay_processor_win.cc
@@ -190,7 +190,7 @@ const OverlayProcessorInterface::FilterOperationsMap& render_pass_backdrop_filters, SurfaceDamageRectList surface_damage_rect_list_in_root_space, - const PrimaryPlaneParams& primary_plane_params, + std::optional<OverlayCandidate>& primary_plane, CandidateList* candidates, gfx::Rect* root_damage_rect, std::vector<gfx::Rect>* content_bounds) { @@ -204,7 +204,6 @@ render_pass_filters, render_pass_backdrop_filters, surface_damage_rect_list_in_root_space, candidates, root_damage_rect); - std::optional<OverlayCandidate> primary_plane; if (status != DelegationStatus::kFullDelegation) { // Fall back to promoting overlays from the output surface plane. ProcessOverlaysFromOutputSurfacePlane( @@ -212,7 +211,7 @@ render_pass_filters, render_pass_backdrop_filters, surface_damage_rect_list_in_root_space, candidates, root_damage_rect); - primary_plane = CreatePrimaryPlane(primary_plane_params); + CHECK(primary_plane); primary_plane->is_opaque = !render_passes->back()->has_transparent_background; primary_plane->layer_id = gfx::OverlayLayerId::MakeVizInternalRenderPass(
diff --git a/components/viz/service/display/overlay_processor_win.h b/components/viz/service/display/overlay_processor_win.h index 66c3ad4..f0f01f59 100644 --- a/components/viz/service/display/overlay_processor_win.h +++ b/components/viz/service/display/overlay_processor_win.h
@@ -66,7 +66,7 @@ const FilterOperationsMap& render_pass_filters, const FilterOperationsMap& render_pass_backdrop_filters, SurfaceDamageRectList surface_damage_rect_list_in_root_space, - const PrimaryPlaneParams& primary_plane_params, + std::optional<OverlayCandidate>& primary_plane, OverlayCandidateList* overlay_candidates, gfx::Rect* root_damage_rect, std::vector<gfx::Rect>* content_bounds) override;
diff --git a/components/viz/service/display/overlay_unittest.cc b/components/viz/service/display/overlay_unittest.cc index abc4f5e2..99ba3395 100644 --- a/components/viz/service/display/overlay_unittest.cc +++ b/components/viz/service/display/overlay_unittest.cc
@@ -102,6 +102,7 @@ const gfx::Rect kOverlayClipRect(0, 0, 128, 128); const gfx::PointF kUVTopLeft(0.1f, 0.2f); const gfx::PointF kUVBottomRight(1.0f, 1.0f); +const SharedImageFormat kDefaultSIFormat = SinglePlaneFormat::kRGBA_8888; const OverlayCandidateFactory::OverlayContext kTestOverlayContext; class TimeTicksOverride { @@ -152,7 +153,7 @@ const FilterOperationsMap& render_pass_filters, const FilterOperationsMap& render_pass_backdrop_filters, SurfaceDamageRectList surface_damage_rect_list, - const PrimaryPlaneParams& primary_plane_params, + std::optional<OverlayCandidate>& primary_plane, CandidateList* overlay_candidates, gfx::Rect* damage_rect, std::vector<gfx::Rect>* content_bounds) override { @@ -163,7 +164,7 @@ OverlayProcessorUsingStrategy::ProcessForOverlays( resource_provider, render_passes, output_color_matrix, render_pass_filters, render_pass_backdrop_filters, - surface_damage_rect_list, primary_plane_params, overlay_candidates, + surface_damage_rect_list, primary_plane, overlay_candidates, damage_rect, content_bounds); } @@ -309,7 +310,7 @@ const FilterOperationsMap& render_pass_filters, const FilterOperationsMap& render_pass_backdrop_filters, SurfaceDamageRectList surface_damage_rect_list, - const PrimaryPlaneParams& primary_plane_params, + std::optional<OverlayCandidate>& primary_plane, CandidateList* overlay_candidates, gfx::Rect* damage_rect, std::vector<gfx::Rect>* content_bounds) override { @@ -320,7 +321,7 @@ OverlayProcessorUsingStrategy::ProcessForOverlays( resource_provider, render_passes, output_color_matrix, render_pass_filters, render_pass_backdrop_filters, - surface_damage_rect_list, primary_plane_params, overlay_candidates, + surface_damage_rect_list, primary_plane, overlay_candidates, damage_rect, content_bounds); } @@ -916,24 +917,18 @@ return resource_factory_->resource_provider(); } - OverlayProcessorInterface::PrimaryPlaneParams GetDefaultPrimaryPlane() { - return OverlayProcessorInterface::PrimaryPlaneParams{ - .viewport_size = kDisplaySize, - .resource_size_in_pixels = kDisplaySize, - .supports_hdr = false, - .is_opaque = true, -#if BUILDFLAG(IS_OZONE) - .si_format = SinglePlaneFormat::kRGBA_8888, - .color_space = gfx::ColorSpace::CreateSRGB(), - .overlay_testing_mailbox = gpu::Mailbox(), -#endif - }; + std::optional<OverlayCandidate>& GetDefaultPrimaryPlane() { + primary_plane_ = OverlayProcessorInterface::ProcessOutputSurfaceAsOverlay( + kDisplaySize, kDisplaySize, kDefaultSIFormat, + gfx::ColorSpace::CreateSRGB(), false, 1.0, gpu::Mailbox()); + return primary_plane_; } std::unique_ptr<TestResourceFactory> resource_factory_; std::unique_ptr<OverlayProcessorType> overlay_processor_; gfx::Rect damage_rect_; std::vector<gfx::Rect> content_bounds_; + std::optional<OverlayCandidate> primary_plane_; }; template <typename OverlayProcessorType> @@ -3835,9 +3830,14 @@ pass_list.push_back(std::move(pass)); SurfaceDamageRectList surface_damage_rect_list; + std::optional<OverlayCandidate> output_surface_plane = + overlay_processor_->ProcessOutputSurfaceAsOverlay( + kDisplaySize, kDisplaySize, kDefaultSIFormat, gfx::ColorSpace(), + false /* has_alpha */, 1.0f /* opacity */, gpu::Mailbox()); + overlay_processor_->ProcessForOverlays( resource_provider(), &pass_list, GetIdentityColorMatrix(), - std::move(surface_damage_rect_list), GetDefaultPrimaryPlane(), + std::move(surface_damage_rect_list), output_surface_plane, &candidate_list, &damage_rect_, &content_bounds_); ASSERT_EQ(1U, test::NumOverlaysExcludingPrimaryPlane(candidate_list)); @@ -4209,8 +4209,8 @@ overlay_processor_->ProcessForOverlays( resource_provider(), &pass_list, GetIdentityColorMatrix(), - std::move(surface_damage_rect_list), GetDefaultPrimaryPlane(), - &candidate_list, &damage_rect_, &content_bounds_); + std::move(surface_damage_rect_list), primary_plane_, &candidate_list, + &damage_rect_, &content_bounds_); ASSERT_EQ(1U, pass_list.size()); ASSERT_EQ(1U, pass_list.front()->quad_list.size()); EXPECT_EQ(SkColors::kTransparent, static_cast<SolidColorDrawQuad*>( @@ -4235,8 +4235,8 @@ overlay_processor_->ProcessForOverlays( resource_provider(), &pass_list, GetIdentityColorMatrix(), - std::move(surface_damage_rect_list), GetDefaultPrimaryPlane(), - &candidate_list, &damage_rect_, &content_bounds_); + std::move(surface_damage_rect_list), primary_plane_, &candidate_list, + &damage_rect_, &content_bounds_); EXPECT_EQ(0U, content_bounds_.size()); } @@ -4252,8 +4252,8 @@ overlay_processor_->ProcessForOverlays( resource_provider(), &pass_list, GetIdentityColorMatrix(), - std::move(surface_damage_rect_list), GetDefaultPrimaryPlane(), - &candidate_list, &damage_rect_, &content_bounds_); + std::move(surface_damage_rect_list), primary_plane_, &candidate_list, + &damage_rect_, &content_bounds_); EXPECT_EQ(1U, content_bounds_.size()); EXPECT_TRUE(content_bounds_[0].IsEmpty()); @@ -4280,8 +4280,8 @@ overlay_processor_->ProcessForOverlays( resource_provider(), &pass_list, GetIdentityColorMatrix(), - std::move(surface_damage_rect_list), GetDefaultPrimaryPlane(), - &candidate_list, &damage_rect_, &content_bounds_); + std::move(surface_damage_rect_list), primary_plane_, &candidate_list, + &damage_rect_, &content_bounds_); EXPECT_EQ(1U, content_bounds_.size()); EXPECT_TRUE(content_bounds_[0].IsEmpty()); @@ -4301,8 +4301,8 @@ overlay_processor_->ProcessForOverlays( resource_provider(), &pass_list, GetIdentityColorMatrix(), - std::move(surface_damage_rect_list), GetDefaultPrimaryPlane(), - &candidate_list, &damage_rect_, &content_bounds_); + std::move(surface_damage_rect_list), primary_plane_, &candidate_list, + &damage_rect_, &content_bounds_); EXPECT_EQ(1U, content_bounds_.size()); EXPECT_EQ(kOverlayTopLeftRect, content_bounds_[0]); @@ -4324,8 +4324,8 @@ overlay_processor_->ProcessForOverlays( resource_provider(), &pass_list, GetIdentityColorMatrix(), - std::move(surface_damage_rect_list), GetDefaultPrimaryPlane(), - &candidate_list, &damage_rect_, &content_bounds_); + std::move(surface_damage_rect_list), primary_plane_, &candidate_list, + &damage_rect_, &content_bounds_); EXPECT_EQ(1U, content_bounds_.size()); EXPECT_EQ(kOverlayRect, content_bounds_[0]); @@ -4353,8 +4353,8 @@ overlay_processor_->ProcessForOverlays( resource_provider(), &pass_list, GetIdentityColorMatrix(), - std::move(surface_damage_rect_list), GetDefaultPrimaryPlane(), - &candidate_list, &damage_rect_, &content_bounds_); + std::move(surface_damage_rect_list), primary_plane_, &candidate_list, + &damage_rect_, &content_bounds_); EXPECT_EQ(1U, content_bounds_.size()); EXPECT_EQ(gfx::Rect(0, 0, 11, 11), content_bounds_[0]); @@ -4383,8 +4383,8 @@ overlay_processor_->ProcessForOverlays( resource_provider(), &pass_list, GetIdentityColorMatrix(), - std::move(surface_damage_rect_list), GetDefaultPrimaryPlane(), - &candidate_list, &damage_rect_, &content_bounds_); + std::move(surface_damage_rect_list), primary_plane_, &candidate_list, + &damage_rect_, &content_bounds_); EXPECT_EQ(1U, content_bounds_.size()); EXPECT_EQ(kOverlayRect, content_bounds_[0]); @@ -4402,8 +4402,8 @@ overlay_processor_->ProcessForOverlays( resource_provider(), &pass_list, GetIdentityColorMatrix(), - std::move(surface_damage_rect_list), GetDefaultPrimaryPlane(), - &candidate_list, &damage_rect_, &content_bounds_); + std::move(surface_damage_rect_list), primary_plane_, &candidate_list, + &damage_rect_, &content_bounds_); ASSERT_TRUE(candidate_list.empty()); EXPECT_TRUE(content_bounds_.empty()); @@ -4427,8 +4427,8 @@ overlay_processor_->ProcessForOverlays( resource_provider(), &pass_list, GetIdentityColorMatrix(), - std::move(surface_damage_rect_list), GetDefaultPrimaryPlane(), - &candidate_list, &damage_rect_, &content_bounds_); + std::move(surface_damage_rect_list), primary_plane_, &candidate_list, + &damage_rect_, &content_bounds_); ASSERT_EQ(1U, content_bounds_.size()); EXPECT_TRUE(content_bounds_.front().IsEmpty()); @@ -4458,11 +4458,15 @@ AggregatedRenderPassList pass_list; pass_list.push_back(std::move(pass)); + std::optional<OverlayCandidate> output_surface_plane = + overlay_processor_->ProcessOutputSurfaceAsOverlay( + kDisplaySize, kDisplaySize, kDefaultSIFormat, gfx::ColorSpace(), + false /* has_alpha */, 1.0f /* opacity */, gpu::Mailbox()); SurfaceDamageRectList surface_damage_rect_list; overlay_processor_->ProcessForOverlays( resource_provider(), &pass_list, GetIdentityColorMatrix(), - std::move(surface_damage_rect_list), GetDefaultPrimaryPlane(), + std::move(surface_damage_rect_list), output_surface_plane, &candidate_list, &damage_rect_, &content_bounds_); EXPECT_EQ(0U, content_bounds_.size()); @@ -4793,6 +4797,10 @@ SurfaceDamageRectList surface_damage_rect_list; render_pass_list.push_back(std::move(root_pass)); + std::optional<OverlayCandidate> output_surface_plane = + overlay_processor_->ProcessOutputSurfaceAsOverlay( + kDisplaySize, kDisplaySize, kDefaultSIFormat, gfx::ColorSpace(), + false /* has_alpha */, 1.0f /* opacity */, gpu::Mailbox()); // Choose 5 here for testing purpose, this value will not change constexpr int kDisableOverlayTestVectorSize = @@ -4835,7 +4843,7 @@ OverlayCandidateList candidate_list; overlay_processor_->ProcessForOverlays( resource_provider(), &render_pass_list, GetIdentityColorMatrix(), - surface_damage_rect_list, GetDefaultPrimaryPlane(), &candidate_list, + surface_damage_rect_list, output_surface_plane, &candidate_list, &damage_rect_, &content_bounds_); EXPECT_EQ(expected_overlays[i], @@ -6376,10 +6384,14 @@ OverlayCandidateList candidate_list; AggregatedRenderPassList pass_list; pass_list.push_back(std::move(pass)); + std::optional<OverlayCandidate> output_surface_plane = + overlay_processor_->ProcessOutputSurfaceAsOverlay( + kDisplaySize, kDisplaySize, kDefaultSIFormat, gfx::ColorSpace(), + false /* has_alpha */, 1.0f /* opacity */, gpu::Mailbox()); overlay_processor_->ProcessForOverlays( resource_provider(), &pass_list, GetIdentityColorMatrix(), - std::move(surface_damage_rect_list), GetDefaultPrimaryPlane(), + std::move(surface_damage_rect_list), output_surface_plane, &candidate_list, &damage_rect_, &content_bounds_); if (promoted) {
diff --git a/components/viz/service/display/skia_renderer.cc b/components/viz/service/display/skia_renderer.cc index 441ad99..610490f5 100644 --- a/components/viz/service/display/skia_renderer.cc +++ b/components/viz/service/display/skia_renderer.cc
@@ -4248,8 +4248,11 @@ buffer_queue_->EnsureMinNumberOfBuffers(n); } -#if BUILDFLAG(IS_OZONE) gpu::Mailbox SkiaRenderer::GetPrimaryPlaneOverlayTestingMailbox() { +#if BUILDFLAG(IS_WIN) + // Windows dcomp uses a swap chain for primary plane instead of BufferQueue. + return gpu::Mailbox(); +#else // For the purpose of testing the overlay configuration, the mailbox for ANY // buffer from BufferQueue is good enough because they're all created with // identical properties. @@ -4259,8 +4262,11 @@ // previous frame's mailbox.) CHECK(buffer_queue_); return buffer_queue_->GetLastSwappedBuffer(); +#endif } +#if BUILDFLAG(IS_OZONE) + DBG_FLAG_FBOOL("delegated.overlay.background_candidate.colored", toggle_background_overlay_color) // False by default.
diff --git a/components/viz/service/display/skia_renderer.h b/components/viz/service/display/skia_renderer.h index c66201d..50f159c 100644 --- a/components/viz/service/display/skia_renderer.h +++ b/components/viz/service/display/skia_renderer.h
@@ -73,9 +73,7 @@ gfx::Rect GetCurrentFramebufferDamage() const override; void Reshape(const OutputSurface::ReshapeParams& reshape_params) override; void EnsureMinNumberOfBuffers(int n) override; -#if BUILDFLAG(IS_OZONE) gpu::Mailbox GetPrimaryPlaneOverlayTestingMailbox() override; -#endif protected: bool CanPartialSwap() override;
diff --git a/components/viz/service/frame_sinks/external_begin_frame_source_mac.cc b/components/viz/service/frame_sinks/external_begin_frame_source_mac.cc index fb4bcd4..1868f0fb 100644 --- a/components/viz/service/frame_sinks/external_begin_frame_source_mac.cc +++ b/components/viz/service/frame_sinks/external_begin_frame_source_mac.cc
@@ -423,10 +423,7 @@ base::TimeDelta ExternalBeginFrameSourceMac::GetMinimumFrameInterval() { if (display_link_mac_) { - auto refresh_rate = display_link_mac_->GetRefreshRate(); - if (refresh_rate) { - return base::Seconds(1) / refresh_rate; - } + return display_link_mac_->GetRefreshInterval(); } return BeginFrameArgs::DefaultInterval();
diff --git a/components/webauthn/android/BUILD.gn b/components/webauthn/android/BUILD.gn index c364ae9..3e7ad5d 100644 --- a/components/webauthn/android/BUILD.gn +++ b/components/webauthn/android/BUILD.gn
@@ -98,6 +98,7 @@ "//third_party/androidx:androidx_core_core_java", "//third_party/blink/public/common:common_java", "//third_party/blink/public/mojom:android_mojo_bindings_java", + "//third_party/blink/public/mojom:credentialmanagement_mojo_bindings_java", "//third_party/jni_zero:jni_zero_java", "//ui/android:ui_no_recycler_view_java", "//url:gurl_java", @@ -137,6 +138,7 @@ "//third_party/android_deps:guava_android_java", "//third_party/androidx:androidx_annotation_annotation_java", "//third_party/blink/public/mojom:android_mojo_bindings_java", + "//third_party/blink/public/mojom:credentialmanagement_mojo_bindings_java", "//third_party/jni_zero:jni_zero_java", "//third_party/junit", "//url:gurl_java", @@ -240,6 +242,7 @@ "//third_party/androidx:androidx_test_runner_java", "//third_party/blink/public/common:common_java", "//third_party/blink/public/mojom:android_mojo_bindings_java", + "//third_party/blink/public/mojom:credentialmanagement_mojo_bindings_java", "//third_party/google-truth:google_truth_java", "//third_party/jni_zero:jni_zero_java", "//third_party/junit",
diff --git a/components/webauthn/core/browser/import/passkey_importer_unittest.cc b/components/webauthn/core/browser/import/passkey_importer_unittest.cc index 7e2287c..5778e07 100644 --- a/components/webauthn/core/browser/import/passkey_importer_unittest.cc +++ b/components/webauthn/core/browser/import/passkey_importer_unittest.cc
@@ -103,7 +103,10 @@ // Duplicate passkey should be reported as imported, but not actually added // to the model. EXPECT_EQ(passkeys_imported, 1); - EXPECT_THAT(passkey_model_->GetAllPasskeys(), SizeIs(1)); + EXPECT_THAT( + passkey_model_->GetPasskeys(PasskeyModel::AnyRp(), + PasskeyModel::ShadowedCredentials::kInclude), + SizeIs(1)); } TEST_F(PasskeyImporterTest, ProcessesConflictingPasskeys) { @@ -123,7 +126,10 @@ {CreatePasskey(kRpId, kUserId), CreatePasskey(kRpId, kUserId2)}); int passkeys_imported = FinishImport(/*selected_passkey_ids=*/{}); EXPECT_EQ(passkeys_imported, 2); - EXPECT_THAT(passkey_model_->GetAllPasskeys(), SizeIs(2)); + EXPECT_THAT( + passkey_model_->GetPasskeys(PasskeyModel::AnyRp(), + PasskeyModel::ShadowedCredentials::kInclude), + SizeIs(2)); } TEST_F(PasskeyImporterTest, ImportsIncomingConflictingPasskey) { @@ -135,7 +141,10 @@ {CreatePasskey(kRpId, kUserId), CreatePasskey(kRpId, kUserId2)}); int passkeys_imported = FinishImport(/*selected_passkey_ids=*/{0}); EXPECT_EQ(passkeys_imported, 2); - EXPECT_THAT(passkey_model_->GetAllPasskeys(), SizeIs(3)); + EXPECT_THAT( + passkey_model_->GetPasskeys(PasskeyModel::AnyRp(), + PasskeyModel::ShadowedCredentials::kInclude), + SizeIs(3)); } TEST_F(PasskeyImporterTest, IgnoresNotSelectedConflictingPasskey) { @@ -147,7 +156,10 @@ {CreatePasskey(kRpId, kUserId), CreatePasskey(kRpId, kUserId2)}); int passkeys_imported = FinishImport(/*selected_passkey_ids=*/{}); EXPECT_EQ(passkeys_imported, 1); - EXPECT_THAT(passkey_model_->GetAllPasskeys(), SizeIs(2)); + EXPECT_THAT( + passkey_model_->GetPasskeys(PasskeyModel::AnyRp(), + PasskeyModel::ShadowedCredentials::kInclude), + SizeIs(2)); } TEST_F(PasskeyImporterTest, DoesNotImportInvalidPasskeys) { @@ -158,7 +170,10 @@ int passkeys_imported = FinishImport(/*selected_passkey_ids=*/{}); EXPECT_EQ(passkeys_imported, 0); - EXPECT_THAT(passkey_model_->GetAllPasskeys(), IsEmpty()); + EXPECT_THAT( + passkey_model_->GetPasskeys(PasskeyModel::AnyRp(), + PasskeyModel::ShadowedCredentials::kInclude), + IsEmpty()); } } // namespace
diff --git a/components/webauthn/core/browser/passkey_model.h b/components/webauthn/core/browser/passkey_model.h index 554207b7..c28494b 100644 --- a/components/webauthn/core/browser/passkey_model.h +++ b/components/webauthn/core/browser/passkey_model.h
@@ -122,10 +122,6 @@ std::string_view credential_id, ShadowedCredentials shadowed_credentials) const = 0; - // Returns the list of all passkeys, including those that are shadowed. - virtual std::vector<sync_pb::WebauthnCredentialSpecifics> GetAllPasskeys() - const = 0; - // Returns the passkey matching the given Relying Party and credential ID, if // any. Shadowed entities, which aren't suitable for generating assertions, // are ignored. @@ -140,11 +136,6 @@ GetPasskeyByUserId(const std::string& rp_id, const std::string& user_id) const = 0; - // Returns all passkeys for the given Relying Party ID. Shadowed entities, - // which aren't suitable for generating assertions, are ignored. - virtual std::vector<sync_pb::WebauthnCredentialSpecifics> - GetPasskeysForRelyingPartyId(const std::string& rp_id) const = 0; - // Deletes the passkey with the given `credential_id`. If the passkey is the // head of the shadow chain, then all passkeys for the same (user id, rp id) // are deleted as well. `location` is used for logging purposes and
diff --git a/components/webauthn/core/browser/passkey_sync_bridge.cc b/components/webauthn/core/browser/passkey_sync_bridge.cc index e563136a..6a92acd 100644 --- a/components/webauthn/core/browser/passkey_sync_bridge.cc +++ b/components/webauthn/core/browser/passkey_sync_bridge.cc
@@ -311,14 +311,6 @@ return std::nullopt; } -std::vector<sync_pb::WebauthnCredentialSpecifics> -PasskeySyncBridge::GetAllPasskeys() const { - std::vector<sync_pb::WebauthnCredentialSpecifics> passkeys; - std::ranges::transform(data_, std::back_inserter(passkeys), - [](const auto& pair) { return pair.second; }); - return passkeys; -} - std::optional<sync_pb::WebauthnCredentialSpecifics> PasskeySyncBridge::GetPasskeyByCredentialId( const std::string& rp_id, @@ -368,18 +360,6 @@ return std::nullopt; } -std::vector<sync_pb::WebauthnCredentialSpecifics> -PasskeySyncBridge::GetPasskeysForRelyingPartyId( - const std::string& rp_id) const { - std::vector<sync_pb::WebauthnCredentialSpecifics> passkeys; - for (const auto& passkey : data_) { - if (passkey.second.rp_id() == rp_id) { - passkeys.emplace_back(passkey.second); - } - } - return passkey_model_utils::FilterShadowedCredentials(passkeys); -} - bool PasskeySyncBridge::DeletePasskey(const std::string& credential_id, const base::Location& location) { // Find the credential with the given |credential_id|.
diff --git a/components/webauthn/core/browser/passkey_sync_bridge.h b/components/webauthn/core/browser/passkey_sync_bridge.h index 7451d341..959e396 100644 --- a/components/webauthn/core/browser/passkey_sync_bridge.h +++ b/components/webauthn/core/browser/passkey_sync_bridge.h
@@ -80,16 +80,12 @@ std::variant<AnyRp, std::string_view> rp_id, std::string_view credential_id, ShadowedCredentials shadowed_credentials) const override; - std::vector<sync_pb::WebauthnCredentialSpecifics> GetAllPasskeys() - const override; std::optional<sync_pb::WebauthnCredentialSpecifics> GetPasskeyByCredentialId( const std::string& rp_id, const std::string& credential_id) const override; std::optional<sync_pb::WebauthnCredentialSpecifics> GetPasskeyByUserId( const std::string& rp_id, const std::string& user_id) const override; - std::vector<sync_pb::WebauthnCredentialSpecifics> - GetPasskeysForRelyingPartyId(const std::string& rp_id) const override; bool DeletePasskey(const std::string& credential_id, const base::Location& location) override; bool HidePasskey(const std::string& credential_id,
diff --git a/components/webauthn/core/browser/test_passkey_model.cc b/components/webauthn/core/browser/test_passkey_model.cc index 4bb558a..8c05b5b 100644 --- a/components/webauthn/core/browser/test_passkey_model.cc +++ b/components/webauthn/core/browser/test_passkey_model.cc
@@ -90,11 +90,6 @@ return std::nullopt; } -std::vector<sync_pb::WebauthnCredentialSpecifics> -TestPasskeyModel::GetAllPasskeys() const { - return credentials_; -} - std::optional<sync_pb::WebauthnCredentialSpecifics> TestPasskeyModel::GetPasskeyByCredentialId( const std::string& rp_id, @@ -135,15 +130,6 @@ return result.front(); } -std::vector<sync_pb::WebauthnCredentialSpecifics> -TestPasskeyModel::GetPasskeysForRelyingPartyId(const std::string& rp_id) const { - std::vector<sync_pb::WebauthnCredentialSpecifics> passkeys; - std::ranges::copy_if( - credentials_, std::back_inserter(passkeys), - [&rp_id](const auto& passkey) { return passkey.rp_id() == rp_id; }); - return passkey_model_utils::FilterShadowedCredentials(passkeys); -} - sync_pb::WebauthnCredentialSpecifics TestPasskeyModel::CreatePasskey( std::string_view rp_id, const UserEntity& user_entity,
diff --git a/components/webauthn/core/browser/test_passkey_model.h b/components/webauthn/core/browser/test_passkey_model.h index cc8b9e6b..c390ce20 100644 --- a/components/webauthn/core/browser/test_passkey_model.h +++ b/components/webauthn/core/browser/test_passkey_model.h
@@ -38,16 +38,12 @@ std::variant<AnyRp, std::string_view> rp_id, std::string_view credential_id, ShadowedCredentials shadowed_credentials) const override; - std::vector<sync_pb::WebauthnCredentialSpecifics> GetAllPasskeys() - const override; std::optional<sync_pb::WebauthnCredentialSpecifics> GetPasskeyByCredentialId( const std::string& rp_id, const std::string& credential_id) const override; std::optional<sync_pb::WebauthnCredentialSpecifics> GetPasskeyByUserId( const std::string& rp_id, const std::string& user_id) const override; - std::vector<sync_pb::WebauthnCredentialSpecifics> - GetPasskeysForRelyingPartyId(const std::string& rp_id) const override; bool DeletePasskey(const std::string& credential_id, const base::Location& location) override; bool HidePasskey(const std::string& credential_id,
diff --git a/components/webauthn/ios/passkey_tab_helper.mm b/components/webauthn/ios/passkey_tab_helper.mm index 785d322..62892dd 100644 --- a/components/webauthn/ios/passkey_tab_helper.mm +++ b/components/webauthn/ios/passkey_tab_helper.mm
@@ -270,7 +270,8 @@ } std::vector<sync_pb::WebauthnCredentialSpecifics> passkeys = - passkey_model_->GetPasskeysForRelyingPartyId(params.RpId()); + passkey_model_->GetPasskeys(params.RpId(), + PasskeyModel::ShadowedCredentials::kExclude); for (const auto& passkey : passkeys) { if (exclude_credentials.contains(passkey.credential_id())) { return true; @@ -283,7 +284,8 @@ PasskeyTabHelper::GetFilteredPasskeys( const AssertionRequestParams& params) const { std::vector<sync_pb::WebauthnCredentialSpecifics> passkeys = - passkey_model_->GetPasskeysForRelyingPartyId(params.RpId()); + passkey_model_->GetPasskeys(params.RpId(), + PasskeyModel::ShadowedCredentials::kExclude); if (passkeys.empty()) { return passkeys; }
diff --git a/components/webauthn/ios/passkey_tab_helper_unittest.mm b/components/webauthn/ios/passkey_tab_helper_unittest.mm index 76d524bc..8d1811d 100644 --- a/components/webauthn/ios/passkey_tab_helper_unittest.mm +++ b/components/webauthn/ios/passkey_tab_helper_unittest.mm
@@ -257,7 +257,8 @@ // Make sure 2 distinct passkeys were added. std::vector<sync_pb::WebauthnCredentialSpecifics> passkeys = - passkey_model_->GetPasskeysForRelyingPartyId(kRpId); + passkey_model_->GetPasskeys(kRpId, + PasskeyModel::ShadowedCredentials::kExclude); EXPECT_EQ(passkeys.size(), 2u); // Empty allow credentials list, expect no filtering.
diff --git a/components/webui/flags/resources/app.ts b/components/webui/flags/resources/app.ts index c782d0c..9fab317 100644 --- a/components/webui/flags/resources/app.ts +++ b/components/webui/flags/resources/app.ts
@@ -283,6 +283,8 @@ case 'Escape': this.$.search.blur(); break; + default: + break; } }); }
diff --git a/content/browser/android/content_feature_map.cc b/content/browser/android/content_feature_map.cc index 44df17e..0f162a42 100644 --- a/content/browser/android/content_feature_map.cc +++ b/content/browser/android/content_feature_map.cc
@@ -34,6 +34,7 @@ &features::kAccessibilityCheckJavaNodeCacheFreshness, &features::kAccessibilityDeprecateJavaNodeCache, &features::kAccessibilityDeprecateTypeAnnounce, + &features::kAccessibilityExtendedSelection, &features::kAccessibilityImproveLiveRegionAnnounce, &features::kAccessibilityMagnificationFollowsFocus, &features::kAccessibilityRequestLayoutBasedActions,
diff --git a/content/browser/file_system/file_system_browsertest.cc b/content/browser/file_system/file_system_browsertest.cc index 04eb589f..872ec83 100644 --- a/content/browser/file_system/file_system_browsertest.cc +++ b/content/browser/file_system/file_system_browsertest.cc
@@ -4,8 +4,6 @@ #include <stdint.h> -#include <algorithm> - #include "base/command_line.h" #include "base/files/file_path.h" #include "base/functional/bind.h" @@ -15,7 +13,6 @@ #include "base/run_loop.h" #include "base/task/single_thread_task_runner.h" #include "base/test/bind.h" -#include "base/test/scoped_feature_list.h" #include "base/test/thread_test_helper.h" #include "content/browser/web_contents/web_contents_impl.h" #include "content/public/browser/browser_context.h" @@ -28,7 +25,6 @@ #include "content/public/test/content_browser_test.h" #include "content/public/test/content_browser_test_utils.h" #include "content/shell/browser/shell.h" -#include "storage/browser/quota/quota_features.h" #include "storage/browser/quota/quota_manager.h" using storage::QuotaManager; @@ -37,14 +33,10 @@ // This browser test is aimed towards exercising the File System API bindings // and the actual implementation that lives in the browser side. -class FileSystemBrowserTest - : public ContentBrowserTest, - public testing::WithParamInterface<std::tuple<bool, bool>> { +class FileSystemBrowserTest : public ContentBrowserTest, + public testing::WithParamInterface<bool> { public: - FileSystemBrowserTest() { - feature_list_.InitWithFeatureState(storage::features::kStaticStorageQuota, - should_report_static_quota()); - } + FileSystemBrowserTest() { is_incognito_ = GetParam(); } void SetUpOnMainThread() override { ASSERT_TRUE(embedded_test_server()->Start()); @@ -67,28 +59,16 @@ } } - int64_t GetTotalDiskSpaceOr(int64_t default_value) { - base::ScopedAllowBlockingForTesting allow_blocking; - return base::SysInfo::AmountOfTotalDiskSpace( - browser()->web_contents()->GetBrowserContext()->GetPath()) - .value_or(default_value); - } - Shell* browser() { return browser_; } - bool is_incognito() { return testing::get<0>(GetParam()); } - bool should_report_static_quota() { return testing::get<1>(GetParam()); } + bool is_incognito() { return is_incognito_; } protected: bool is_incognito_; raw_ptr<Shell> browser_ = nullptr; - base::test::ScopedFeatureList feature_list_; }; -INSTANTIATE_TEST_SUITE_P(All, - FileSystemBrowserTest, - ::testing::Combine(::testing::Bool(), - ::testing::Bool())); +INSTANTIATE_TEST_SUITE_P(All, FileSystemBrowserTest, ::testing::Bool()); class FileSystemBrowserTestWithLowQuota : public FileSystemBrowserTest { public: @@ -124,8 +104,7 @@ INSTANTIATE_TEST_SUITE_P(All, FileSystemBrowserTestWithLowQuota, - ::testing::Combine(::testing::Bool(), - ::testing::Bool())); + ::testing::Bool()); IN_PROC_BROWSER_TEST_P(FileSystemBrowserTest, RequestTest) { SimpleTest(embedded_test_server()->GetURL("/fileapi/request_test.html")); @@ -136,22 +115,7 @@ } IN_PROC_BROWSER_TEST_P(FileSystemBrowserTestWithLowQuota, QuotaTest) { - const int64_t kMeg = 1000 * 1024; - const int64_t kGiB = 1024 * 1024 * 1024; - - // Reported quota is the lower of 10 GiB or disk size rounded up to the - // nearest 1 GiB. - int64_t disk_size = GetTotalDiskSpaceOr(INT64_MAX); - int64_t disk_quota_GiB = std::min(int64_t{10}, (disk_size + kGiB - 1) / kGiB); - - // Incognito reports a static quota of 1 GiB because it calculates on ram, not - // on disk size. TODO(crbug.com/464484739): Set to disk_quota_GiB when fixed. - const int64_t quota = should_report_static_quota() - ? (is_incognito() ? 1 : disk_quota_GiB) * kGiB - : 5 * kMeg; - - SimpleTest(embedded_test_server()->GetURL("/fileapi/quota_test.html?quota=" + - base::NumberToString(quota))); + SimpleTest(embedded_test_server()->GetURL("/fileapi/quota_test.html")); } } // namespace content
diff --git a/content/browser/indexed_db/instance/bucket_context.cc b/content/browser/indexed_db/instance/bucket_context.cc index aa6d5aff..6e2f457f 100644 --- a/content/browser/indexed_db/instance/bucket_context.cc +++ b/content/browser/indexed_db/instance/bucket_context.cc
@@ -69,6 +69,7 @@ #include "content/browser/indexed_db/instance/pending_connection.h" #include "content/browser/indexed_db/instance/sqlite/backing_store_impl.h" #include "content/browser/indexed_db/status.h" +#include "content/public/common/content_features.h" #include "mojo/public/cpp/bindings/pending_associated_receiver.h" #include "mojo/public/cpp/bindings/pending_associated_remote.h" #include "mojo/public/cpp/bindings/pending_receiver.h" @@ -177,10 +178,6 @@ } // namespace -// TODO(crbug.com/40253999): Move to blink when needed there. -// This flag unconditionally enables the SQLite backing store. Used for testing. -BASE_FEATURE(kIdbSqliteBackingStore, base::FEATURE_DISABLED_BY_DEFAULT); - // This flag enables the SQLite backing store for in-memory contexts. BASE_FEATURE(kIdbSqliteBackingStoreInMemoryContexts, base::FEATURE_DISABLED_BY_DEFAULT); @@ -216,7 +213,7 @@ receivers_.set_disconnect_handler(base::BindRepeating( &BucketContext::OnReceiverDisconnected, base::Unretained(this))); should_use_sqlite_ = g_should_use_sqlite_for_testing.value_or( - base::FeatureList::IsEnabled(kIdbSqliteBackingStore) || + base::FeatureList::IsEnabled(features::kIdbSqliteBackingStore) || (in_memory() && base::FeatureList::IsEnabled(kIdbSqliteBackingStoreInMemoryContexts))); }
diff --git a/content/browser/resources/private_aggregation/private_aggregation_internals.ts b/content/browser/resources/private_aggregation/private_aggregation_internals.ts index 5d13a1b6..a3f12eaa 100644 --- a/content/browser/resources/private_aggregation/private_aggregation_internals.ts +++ b/content/browser/resources/private_aggregation/private_aggregation_internals.ts
@@ -4,7 +4,7 @@ import './private_aggregation_internals_table.js'; -import {assert} from 'chrome://resources/js/assert.js'; +import {assert, assertNotReachedCase} from 'chrome://resources/js/assert.js'; import type {AggregatableReportRequestID, ObserverInterface, WebUIAggregatableReport} from './private_aggregation_internals.mojom-webui.js'; import {Factory as PrivateAggregationInternalsFactory, HandlerRemote as PrivateAggregationInternalsHandlerRemote, ObserverReceiver, ReportStatus} from './private_aggregation_internals.mojom-webui.js'; @@ -170,7 +170,7 @@ } } -function reportStatusToText(status: ReportStatus) { +function reportStatusToText(status: ReportStatus): string { switch (status) { case ReportStatus.kPending: return 'Pending'; @@ -180,6 +180,8 @@ return 'Failed to assemble'; case ReportStatus.kFailedToSend: return 'Failed to send'; + default: + assertNotReachedCase(status); } }
diff --git a/content/public/android/java/src/org/chromium/content_public/browser/ContentFeatureList.java b/content/public/android/java/src/org/chromium/content_public/browser/ContentFeatureList.java index a300166..91ca0a0 100644 --- a/content/public/android/java/src/org/chromium/content_public/browser/ContentFeatureList.java +++ b/content/public/android/java/src/org/chromium/content_public/browser/ContentFeatureList.java
@@ -29,6 +29,8 @@ public static final String ACCESSIBILITY_DEPRECATE_TYPE_ANNOUNCE = "AccessibilityDeprecateTypeAnnounce"; + public static final String ACCESSIBILITY_EXTENDED_SELECTION = "AccessibilityExtendedSelection"; + public static final String ACCESSIBILITY_IMPROVE_LIVE_REGION_ANNOUNCE = "AccessibilityImproveLiveRegionAnnounce";
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityEventsTest.java b/content/public/android/javatests/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityEventsTest.java index ed3ec01e..5e623ccf 100644 --- a/content/public/android/javatests/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityEventsTest.java +++ b/content/public/android/javatests/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityEventsTest.java
@@ -335,6 +335,7 @@ @Test @SmallTest + @EnableFeatures(ContentFeatureList.ACCESSIBILITY_EXTENDED_SELECTION) public void test_ariaComboboxFocus() { performTest("aria-combo-box-focus.html", "aria-combo-box-focus-expected-android.txt"); } @@ -633,12 +634,14 @@ @Test @SmallTest + @EnableFeatures(ContentFeatureList.ACCESSIBILITY_EXTENDED_SELECTION) public void test_caretBrowsingDisabled() { performTest("caret-browsing-disabled.html", "caret-browsing-disabled-expected-android.txt"); } @Test @SmallTest + @EnableFeatures(ContentFeatureList.ACCESSIBILITY_EXTENDED_SELECTION) public void test_caretBrowsingEnabled() { performTest("caret-browsing-enabled.html", "caret-browsing-enabled-expected-android.txt"); } @@ -1320,12 +1323,14 @@ @Test @SmallTest + @EnableFeatures(ContentFeatureList.ACCESSIBILITY_EXTENDED_SELECTION) public void test_textSelectionChanged() { performTest("text-selection-changed.html", "text-selection-changed-expected-android.txt"); } @Test @SmallTest + @EnableFeatures(ContentFeatureList.ACCESSIBILITY_EXTENDED_SELECTION) public void test_textSelectionInsideHiddenElement() { performTest( "text-selection-inside-hidden-element.html", @@ -1334,6 +1339,7 @@ @Test @SmallTest + @EnableFeatures(ContentFeatureList.ACCESSIBILITY_EXTENDED_SELECTION) public void test_textSelectionInsideVideo() { performTest( "text-selection-inside-video.html",
diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc index 3f3d9848..b2b60f28 100644 --- a/content/public/common/content_features.cc +++ b/content/public/common/content_features.cc
@@ -509,6 +509,10 @@ BASE_FEATURE(kIdbPrioritizeForegroundClients, base::FEATURE_DISABLED_BY_DEFAULT); +// This flag unconditionally enables the SQLite backing store. Used for +// about:flags. +BASE_FEATURE(kIdbSqliteBackingStore, base::FEATURE_DISABLED_BY_DEFAULT); + // Controls whether we ignore duplicate navigations or not, in favor of // preserving the already ongoing navigation. BASE_FEATURE(kIgnoreDuplicateNavs, base::FEATURE_DISABLED_BY_DEFAULT);
diff --git a/content/public/common/content_features.h b/content/public/common/content_features.h index d454572f..4e26671f 100644 --- a/content/public/common/content_features.h +++ b/content/public/common/content_features.h
@@ -153,6 +153,7 @@ CONTENT_EXPORT BASE_DECLARE_FEATURE(kFractionalScrollOffsets); CONTENT_EXPORT BASE_DECLARE_FEATURE(kGuestViewMPArch); CONTENT_EXPORT BASE_DECLARE_FEATURE(kIdbPrioritizeForegroundClients); +CONTENT_EXPORT BASE_DECLARE_FEATURE(kIdbSqliteBackingStore); CONTENT_EXPORT BASE_DECLARE_FEATURE(kIgnoreDuplicateNavs); CONTENT_EXPORT BASE_DECLARE_FEATURE_PARAM(std::string, kIgnoreDuplicateNavsOrigins);
diff --git a/content/test/data/accessibility/event/aria-combo-box-focus-expected-android.txt b/content/test/data/accessibility/event/aria-combo-box-focus-expected-android.txt index 35302fa..c3b4abd 100644 --- a/content/test/data/accessibility/event/aria-combo-box-focus-expected-android.txt +++ b/content/test/data/accessibility/event/aria-combo-box-focus-expected-android.txt
@@ -1,2 +1,2 @@ TYPE_VIEW_TEXT_SELECTION_CHANGED - [0, 0] -TYPE_VIEW_TEXT_SELECTION_CHANGED - [0, 0] \ No newline at end of file +TYPE_VIEW_TEXT_SELECTION_CHANGED \ No newline at end of file
diff --git a/content/test/data/accessibility/event/caret-browsing-disabled-expected-android.txt b/content/test/data/accessibility/event/caret-browsing-disabled-expected-android.txt index 70b8f1d..d3a2e2c 100644 --- a/content/test/data/accessibility/event/caret-browsing-disabled-expected-android.txt +++ b/content/test/data/accessibility/event/caret-browsing-disabled-expected-android.txt
@@ -1,2 +1,2 @@ -TYPE_VIEW_TEXT_SELECTION_CHANGED - [1, 1] -TYPE_VIEW_TEXT_SELECTION_CHANGED - [1, 3] \ No newline at end of file +TYPE_VIEW_TEXT_SELECTION_CHANGED +TYPE_VIEW_TEXT_SELECTION_CHANGED \ No newline at end of file
diff --git a/content/test/data/accessibility/event/caret-browsing-enabled-expected-android.txt b/content/test/data/accessibility/event/caret-browsing-enabled-expected-android.txt index 70b8f1d..d3a2e2c 100644 --- a/content/test/data/accessibility/event/caret-browsing-enabled-expected-android.txt +++ b/content/test/data/accessibility/event/caret-browsing-enabled-expected-android.txt
@@ -1,2 +1,2 @@ -TYPE_VIEW_TEXT_SELECTION_CHANGED - [1, 1] -TYPE_VIEW_TEXT_SELECTION_CHANGED - [1, 3] \ No newline at end of file +TYPE_VIEW_TEXT_SELECTION_CHANGED +TYPE_VIEW_TEXT_SELECTION_CHANGED \ No newline at end of file
diff --git a/content/test/data/accessibility/event/text-selection-changed-expected-android.txt b/content/test/data/accessibility/event/text-selection-changed-expected-android.txt index ca76f3ea..4e3daddf 100644 --- a/content/test/data/accessibility/event/text-selection-changed-expected-android.txt +++ b/content/test/data/accessibility/event/text-selection-changed-expected-android.txt
@@ -1,3 +1,3 @@ -TYPE_VIEW_TEXT_SELECTION_CHANGED - [0, 1] +TYPE_VIEW_TEXT_SELECTION_CHANGED TYPE_VIEW_TEXT_SELECTION_CHANGED - [2, 3] TYPE_VIEW_TEXT_SELECTION_CHANGED - [0, 0] \ No newline at end of file
diff --git a/content/test/data/accessibility/event/text-selection-inside-hidden-element-expected-android.txt b/content/test/data/accessibility/event/text-selection-inside-hidden-element-expected-android.txt index b707183..f2148e2 100644 --- a/content/test/data/accessibility/event/text-selection-inside-hidden-element-expected-android.txt +++ b/content/test/data/accessibility/event/text-selection-inside-hidden-element-expected-android.txt
@@ -1 +1 @@ -TYPE_VIEW_TEXT_SELECTION_CHANGED - [0, 0] +TYPE_VIEW_TEXT_SELECTION_CHANGED
diff --git a/content/test/data/accessibility/event/text-selection-inside-video-expected-android.txt b/content/test/data/accessibility/event/text-selection-inside-video-expected-android.txt index b707183..f2148e2 100644 --- a/content/test/data/accessibility/event/text-selection-inside-video-expected-android.txt +++ b/content/test/data/accessibility/event/text-selection-inside-video-expected-android.txt
@@ -1 +1 @@ -TYPE_VIEW_TEXT_SELECTION_CHANGED - [0, 0] +TYPE_VIEW_TEXT_SELECTION_CHANGED
diff --git a/content/test/data/fileapi/quota_test.js b/content/test/data/fileapi/quota_test.js index ee2713c..2af9c73e 100644 --- a/content/test/data/fileapi/quota_test.js +++ b/content/test/data/fileapi/quota_test.js
@@ -41,12 +41,11 @@ }, function(e) { fail('Open for 1st truncate:' + fileErrorToString(e)); } ); } -function quotaSuccess(result, expectedQuota) { +function quotaSuccess(result) { if (result.usage != 0) fail('Usage is not zero: ' + result.usage); - if (result.quota != expectedQuota) - fail( - 'Estimated quota is not ' + expectedQuota + ': ' + result.quota); + if (result.quota != 5000 * 1024) + fail('Quota is not 5000KiB: ' + result.quota); window.webkitRequestFileSystem( window.TEMPORARY, @@ -56,17 +55,10 @@ } function test() { - const params = new URLSearchParams(window.location.search); - const expectedQuota = Number(params.get('quota')); - if (isNaN(expectedQuota) || expectedQuota < 0) { - fail('Missing or invalid "quota" URL parameter.'); - return; - } - if (navigator.storage) { debug('Querying usage and quota.'); navigator.storage.estimate() - .then(result => quotaSuccess(result, expectedQuota)) + .then(quotaSuccess) .catch(unexpectedErrorCallback); } else { debug('This test requires navigator.storage.');
diff --git a/docs/website b/docs/website index d9a0c17..105a469 160000 --- a/docs/website +++ b/docs/website
@@ -1 +1 @@ -Subproject commit d9a0c174b535ee5165fb8ef278324be9efa49352 +Subproject commit 105a46915f47f94998e4a3084520835f24ea5a6c
diff --git a/extensions/renderer/api/messaging/native_renderer_messaging_service.cc b/extensions/renderer/api/messaging/native_renderer_messaging_service.cc index 52146fe..95f6ddb 100644 --- a/extensions/renderer/api/messaging/native_renderer_messaging_service.cc +++ b/extensions/renderer/api/messaging/native_renderer_messaging_service.cc
@@ -324,7 +324,7 @@ return nullptr; MessagingPerContextData* data = GetPerContextData<MessagingPerContextData>( - script_context->v8_context(), kCreateIfMissing); + script_context->v8_context(), CreatePerContextData::kCreateIfMissing); if (!data) return nullptr; @@ -359,7 +359,7 @@ return v8::Local<v8::Promise>(); MessagingPerContextData* data = GetPerContextData<MessagingPerContextData>( - script_context->v8_context(), kCreateIfMissing); + script_context->v8_context(), CreatePerContextData::kCreateIfMissing); MessagePortScope* scope = GetMessagePortScope(script_context->GetRenderFrame()); @@ -411,7 +411,7 @@ CHECK(script_context); MessagingPerContextData* data = GetPerContextData<MessagingPerContextData>( - script_context->v8_context(), kDontCreateIfMissing); + script_context->v8_context(), CreatePerContextData::kDontCreateIfMissing); if (!data) return; @@ -594,7 +594,7 @@ return true; v8::HandleScope handle_scope(script_context->isolate()); MessagingPerContextData* data = GetPerContextData<MessagingPerContextData>( - script_context->v8_context(), kDontCreateIfMissing); + script_context->v8_context(), CreatePerContextData::kDontCreateIfMissing); return data && base::Contains(data->ports, port_id); } @@ -754,7 +754,7 @@ } MessagingPerContextData* data = GetPerContextData<MessagingPerContextData>( - v8_context, kDontCreateIfMissing); + v8_context, CreatePerContextData::kDontCreateIfMissing); DCHECK(data); data->ports.erase(port_id); } @@ -778,8 +778,8 @@ else DCHECK_NE(port_id.context_id, script_context->context_id()); - MessagingPerContextData* data = - GetPerContextData<MessagingPerContextData>(context, kCreateIfMissing); + MessagingPerContextData* data = GetPerContextData<MessagingPerContextData>( + context, CreatePerContextData::kCreateIfMissing); DCHECK(data); DCHECK(!base::Contains(data->ports, port_id)); @@ -800,7 +800,7 @@ v8::Isolate* isolate = script_context->isolate(); MessagingPerContextData* data = GetPerContextData<MessagingPerContextData>( - script_context->v8_context(), kDontCreateIfMissing); + script_context->v8_context(), CreatePerContextData::kDontCreateIfMissing); DCHECK(data); DCHECK(base::Contains(data->ports, port_id));
diff --git a/extensions/renderer/api/messaging/one_time_message_handler.cc b/extensions/renderer/api/messaging/one_time_message_handler.cc index 7d9d4fa8..0505dfa 100644 --- a/extensions/renderer/api/messaging/one_time_message_handler.cc +++ b/extensions/renderer/api/messaging/one_time_message_handler.cc
@@ -140,8 +140,8 @@ v8::Local<v8::Context> context = isolate->GetCurrentContext(); OneTimeMessageContextData* data = - GetPerContextData<OneTimeMessageContextData>(context, - kDontCreateIfMissing); + GetPerContextData<OneTimeMessageContextData>( + context, CreatePerContextData::kDontCreateIfMissing); if (!data) return; @@ -353,8 +353,9 @@ ClearCallbackDataForPortId(ScriptContext* script_context, const PortId& port_id) { OneTimeMessageContextData* data = - GetPerContextData<OneTimeMessageContextData>(script_context->v8_context(), - kDontCreateIfMissing); + GetPerContextData<OneTimeMessageContextData>( + script_context->v8_context(), + CreatePerContextData::kDontCreateIfMissing); if (!data) { return; } @@ -368,8 +369,9 @@ const PortId& port_id, const OneTimeMessageHandler::CallbackID& callback_id) { OneTimeMessageContextData* data = - GetPerContextData<OneTimeMessageContextData>(script_context->v8_context(), - kDontCreateIfMissing); + GetPerContextData<OneTimeMessageContextData>( + script_context->v8_context(), + CreatePerContextData::kDontCreateIfMissing); if (!data) { return; } @@ -387,8 +389,9 @@ v8::HandleScope handle_scope(isolate); OneTimeMessageContextData* data = - GetPerContextData<OneTimeMessageContextData>(script_context->v8_context(), - kDontCreateIfMissing); + GetPerContextData<OneTimeMessageContextData>( + script_context->v8_context(), + CreatePerContextData::kDontCreateIfMissing); if (!data) { return 0; @@ -416,8 +419,9 @@ v8::HandleScope handle_scope(isolate); OneTimeMessageContextData* data = - GetPerContextData<OneTimeMessageContextData>(script_context->v8_context(), - kDontCreateIfMissing); + GetPerContextData<OneTimeMessageContextData>( + script_context->v8_context(), + CreatePerContextData::kDontCreateIfMissing); if (!data) return false; return port_id.is_opener ? base::Contains(data->openers, port_id) @@ -443,8 +447,8 @@ DCHECK_EQ(script_context->context_id(), new_port_id.context_id); OneTimeMessageContextData* data = - GetPerContextData<OneTimeMessageContextData>(script_context->v8_context(), - kCreateIfMissing); + GetPerContextData<OneTimeMessageContextData>( + script_context->v8_context(), CreatePerContextData::kCreateIfMissing); DCHECK(data); v8::Local<v8::Promise> promise; @@ -516,7 +520,8 @@ v8::Local<v8::Context> context = script_context->v8_context(); OneTimeMessageContextData* data = - GetPerContextData<OneTimeMessageContextData>(context, kCreateIfMissing); + GetPerContextData<OneTimeMessageContextData>( + context, CreatePerContextData::kCreateIfMissing); DCHECK(data); DCHECK(!base::Contains(data->receivers, target_port_id)); OneTimeReceiver& receiver = data->receivers[target_port_id]; @@ -604,8 +609,9 @@ v8::Local<v8::Context> context, const PortId& port_id) { OneTimeMessageContextData* data = - GetPerContextData<OneTimeMessageContextData>(script_context->v8_context(), - kDontCreateIfMissing); + GetPerContextData<OneTimeMessageContextData>( + script_context->v8_context(), + CreatePerContextData::kDontCreateIfMissing); if (!data) { return; } @@ -637,8 +643,8 @@ bool handled = false; OneTimeMessageContextData* data = - GetPerContextData<OneTimeMessageContextData>(context, - kDontCreateIfMissing); + GetPerContextData<OneTimeMessageContextData>( + context, CreatePerContextData::kDontCreateIfMissing); if (!data) return handled; @@ -729,8 +735,8 @@ bool handled = false; OneTimeMessageContextData* data = - GetPerContextData<OneTimeMessageContextData>(v8_context, - kDontCreateIfMissing); + GetPerContextData<OneTimeMessageContextData>( + v8_context, CreatePerContextData::kDontCreateIfMissing); if (!data) return handled; @@ -783,8 +789,8 @@ bool handled = false; OneTimeMessageContextData* data = - GetPerContextData<OneTimeMessageContextData>(context, - kDontCreateIfMissing); + GetPerContextData<OneTimeMessageContextData>( + context, CreatePerContextData::kDontCreateIfMissing); if (!data) return handled; @@ -811,8 +817,8 @@ v8::Local<v8::Context> v8_context = script_context->v8_context(); OneTimeMessageContextData* data = - GetPerContextData<OneTimeMessageContextData>(v8_context, - kDontCreateIfMissing); + GetPerContextData<OneTimeMessageContextData>( + v8_context, CreatePerContextData::kDontCreateIfMissing); if (!data) return handled; @@ -890,8 +896,8 @@ // because the listener did not indicate it would reply asynchronously), it // might be good to surface an error. OneTimeMessageContextData* data = - GetPerContextData<OneTimeMessageContextData>(context, - kDontCreateIfMissing); + GetPerContextData<OneTimeMessageContextData>( + context, CreatePerContextData::kDontCreateIfMissing); if (!data) return; @@ -1023,8 +1029,9 @@ // be called after context invalidation. v8::HandleScope handle_scope(script_context->isolate()); OneTimeMessageContextData* data = - GetPerContextData<OneTimeMessageContextData>(script_context->v8_context(), - kDontCreateIfMissing); + GetPerContextData<OneTimeMessageContextData>( + script_context->v8_context(), + CreatePerContextData::kDontCreateIfMissing); // ScriptContext invalidation and PerContextData cleanup happen "around" the // same time, but there aren't strict guarantees about ordering. It's possible // the data was collected. @@ -1097,8 +1104,8 @@ // The promise may reject after the context or the channel has been closed. // Fail gracefully. OneTimeMessageContextData* data = - GetPerContextData<OneTimeMessageContextData>(context, - kDontCreateIfMissing); + GetPerContextData<OneTimeMessageContextData>( + context, CreatePerContextData::kDontCreateIfMissing); if (!data) { return; } @@ -1152,8 +1159,8 @@ v8::Local<v8::Context> context = isolate->GetCurrentContext(); OneTimeMessageContextData* data = - GetPerContextData<OneTimeMessageContextData>(context, - kDontCreateIfMissing); + GetPerContextData<OneTimeMessageContextData>( + context, CreatePerContextData::kDontCreateIfMissing); // Dispatching can invalidate the context so if it is then we won't be able to // inform the message sender. @@ -1270,8 +1277,8 @@ // The context could be tearing down by the time the event is fully // dispatched. OneTimeMessageContextData* data = - GetPerContextData<OneTimeMessageContextData>(context, - kDontCreateIfMissing); + GetPerContextData<OneTimeMessageContextData>( + context, CreatePerContextData::kDontCreateIfMissing); if (!data) return;
diff --git a/extensions/renderer/api/messaging/send_message_tester.cc b/extensions/renderer/api/messaging/send_message_tester.cc index 908126dd..195e94cc 100644 --- a/extensions/renderer/api/messaging/send_message_tester.cc +++ b/extensions/renderer/api/messaging/send_message_tester.cc
@@ -37,7 +37,8 @@ v8::Local<v8::Value> output; TestSendMessageOrRequest(args, expected_message, expected_target, - expected_port_status, SEND_MESSAGE, output); + expected_port_status, + SendMessageTester::Method::kSendMessage, output); return output; } @@ -50,7 +51,8 @@ v8::Local<v8::Value> output; TestSendMessageOrRequest(args, expected_message, expected_target, - expected_port_status, SEND_REQUEST, output); + expected_port_status, + SendMessageTester::Method::kSendRequest, output); return output; } @@ -68,8 +70,9 @@ MessageTarget::ForNativeApp(expected_application_name)); v8::Local<v8::Value> output; - TestSendMessageOrRequest(args, expected_message, expected_target, - expected_port_status, SEND_NATIVE_MESSAGE, output); + TestSendMessageOrRequest( + args, expected_message, expected_target, expected_port_status, + SendMessageTester::Method::kSendNativeMessage, output); return output; } @@ -123,17 +126,17 @@ mojom::ChannelType channel_type = mojom::ChannelType::kSendMessage; const char* method_name = nullptr; switch (method) { - case SEND_MESSAGE: + case SendMessageTester::Method::kSendMessage: method_name = "sendMessage"; expected_channel = messaging_util::kSendMessageChannel; channel_type = mojom::ChannelType::kSendMessage; break; - case SEND_REQUEST: + case SendMessageTester::Method::kSendRequest: method_name = "sendRequest"; expected_channel = messaging_util::kSendRequestChannel; channel_type = mojom::ChannelType::kSendRequest; break; - case SEND_NATIVE_MESSAGE: + case SendMessageTester::Method::kSendNativeMessage: method_name = "sendNativeMessage"; channel_type = mojom::ChannelType::kNative; // sendNativeMessage doesn't have name channels so we don't need to change
diff --git a/extensions/renderer/api/messaging/send_message_tester.h b/extensions/renderer/api/messaging/send_message_tester.h index 806d095..8ec3553 100644 --- a/extensions/renderer/api/messaging/send_message_tester.h +++ b/extensions/renderer/api/messaging/send_message_tester.h
@@ -60,10 +60,10 @@ const MessageTarget& expected_target); private: - enum Method { - SEND_REQUEST, - SEND_MESSAGE, - SEND_NATIVE_MESSAGE, + enum class Method { + kSendRequest, + kSendMessage, + kSendNativeMessage, }; // Common handler for testing sendMessage and sendRequest.
diff --git a/extensions/renderer/bindings/api_binding_util.cc b/extensions/renderer/bindings/api_binding_util.cc index 648d0549..da66db9 100644 --- a/extensions/renderer/bindings/api_binding_util.cc +++ b/extensions/renderer/bindings/api_binding_util.cc
@@ -117,8 +117,8 @@ } void InvalidateContext(v8::Local<v8::Context> context) { - ContextInvalidationData* data = - GetPerContextData<ContextInvalidationData>(context, kCreateIfMissing); + ContextInvalidationData* data = GetPerContextData<ContextInvalidationData>( + context, CreatePerContextData::kCreateIfMissing); if (!data) return; @@ -145,9 +145,9 @@ v8::Local<v8::Context> context, base::OnceClosure on_invalidated) : on_invalidated_(std::move(on_invalidated)), - context_invalidation_data_( - GetPerContextData<ContextInvalidationData>(context, - kCreateIfMissing)) { + context_invalidation_data_(GetPerContextData<ContextInvalidationData>( + context, + CreatePerContextData::kCreateIfMissing)) { // We should never add an invalidation observer to an invalid context. DCHECK(context_invalidation_data_); DCHECK(context_invalidation_data_->is_context_valid());
diff --git a/extensions/renderer/bindings/api_event_handler.cc b/extensions/renderer/bindings/api_event_handler.cc index 83ce4351..c29aa2d6 100644 --- a/extensions/renderer/bindings/api_event_handler.cc +++ b/extensions/renderer/bindings/api_event_handler.cc
@@ -81,8 +81,8 @@ } v8::Local<v8::Context> context = isolate->GetCurrentContext(); - APIEventPerContextData* data = - APIEventPerContextData::GetFrom(context, kDontCreateIfMissing); + APIEventPerContextData* data = APIEventPerContextData::GetFrom( + context, CreatePerContextData::kDontCreateIfMissing); DCHECK(data); v8::Local<v8::Object> dispatch_data = info.Data().As<v8::Object>(); @@ -153,8 +153,8 @@ // context directly. v8::Context::Scope context_scope(context); - APIEventPerContextData* data = - APIEventPerContextData::GetFrom(context, kCreateIfMissing); + APIEventPerContextData* data = APIEventPerContextData::GetFrom( + context, CreatePerContextData::kCreateIfMissing); DCHECK(data->emitters.find(event_name) == data->emitters.end()); APIEventListeners::ListenersUpdated updated = @@ -184,8 +184,8 @@ v8::Local<v8::Object> APIEventHandler::CreateAnonymousEventInstance( v8::Local<v8::Context> context) { v8::Context::Scope context_scope(context); - APIEventPerContextData* data = - APIEventPerContextData::GetFrom(context, kCreateIfMissing); + APIEventPerContextData* data = APIEventPerContextData::GetFrom( + context, CreatePerContextData::kCreateIfMissing); bool supports_filters = false; // Anonymous events are not tracked, and thus don't need a name or a context @@ -210,8 +210,8 @@ void APIEventHandler::InvalidateCustomEvent(v8::Local<v8::Context> context, v8::Local<v8::Object> event) { EventEmitter* emitter = nullptr; - APIEventPerContextData* data = - APIEventPerContextData::GetFrom(context, kDontCreateIfMissing); + APIEventPerContextData* data = APIEventPerContextData::GetFrom( + context, CreatePerContextData::kDontCreateIfMissing); // This could happen if a port (or JS) invalidates an event following // context destruction. // TODO(devlin): Is it better to fail gracefully here, or track all these @@ -276,8 +276,8 @@ mojom::EventFilteringInfoPtr filter, v8::Local<v8::Function> on_dispatched_callback, v8::Local<v8::Function> listener_error_callback) { - APIEventPerContextData* data = - APIEventPerContextData::GetFrom(context, kDontCreateIfMissing); + APIEventPerContextData* data = APIEventPerContextData::GetFrom( + context, CreatePerContextData::kDontCreateIfMissing); if (!data) { return; } @@ -357,16 +357,16 @@ v8::Local<v8::Context> context, const std::string& event_name, v8::Local<v8::Function> massager) { - APIEventPerContextData* data = - APIEventPerContextData::GetFrom(context, kCreateIfMissing); + APIEventPerContextData* data = APIEventPerContextData::GetFrom( + context, CreatePerContextData::kCreateIfMissing); DCHECK(!base::Contains(data->massagers, event_name)); data->massagers[event_name].Reset(v8::Isolate::GetCurrent(), massager); } bool APIEventHandler::HasListenerForEvent(const std::string& event_name, v8::Local<v8::Context> context) { - APIEventPerContextData* data = - APIEventPerContextData::GetFrom(context, kDontCreateIfMissing); + APIEventPerContextData* data = APIEventPerContextData::GetFrom( + context, CreatePerContextData::kDontCreateIfMissing); if (!data) { return false; } @@ -386,8 +386,8 @@ void APIEventHandler::InvalidateContext(v8::Local<v8::Context> context) { DCHECK(gin::PerContextData::From(context)) << "Trying to invalidate an already-invalid context."; - APIEventPerContextData* data = - APIEventPerContextData::GetFrom(context, kDontCreateIfMissing); + APIEventPerContextData* data = APIEventPerContextData::GetFrom( + context, CreatePerContextData::kDontCreateIfMissing); if (!data) { return; }
diff --git a/extensions/renderer/bindings/exception_handler.cc b/extensions/renderer/bindings/exception_handler.cc index 762085f..75e8cebc 100644 --- a/extensions/renderer/bindings/exception_handler.cc +++ b/extensions/renderer/bindings/exception_handler.cc
@@ -117,8 +117,8 @@ void ExceptionHandler::SetHandlerForContext(v8::Local<v8::Context> context, v8::Local<v8::Function> handler) { ExceptionHandlerPerContextData* data = - GetPerContextData<ExceptionHandlerPerContextData>(context, - kCreateIfMissing); + GetPerContextData<ExceptionHandlerPerContextData>( + context, CreatePerContextData::kCreateIfMissing); DCHECK(data); data->custom_handler.Reset(v8::Isolate::GetCurrent(), handler); } @@ -148,8 +148,8 @@ v8::Local<v8::Function> ExceptionHandler::GetCustomHandler( v8::Local<v8::Context> context) { ExceptionHandlerPerContextData* data = - GetPerContextData<ExceptionHandlerPerContextData>(context, - kDontCreateIfMissing); + GetPerContextData<ExceptionHandlerPerContextData>( + context, CreatePerContextData::kDontCreateIfMissing); return data ? data->custom_handler.Get(v8::Isolate::GetCurrent()) : v8::Local<v8::Function>(); }
diff --git a/extensions/renderer/bindings/get_per_context_data.h b/extensions/renderer/bindings/get_per_context_data.h index 12f25af..0b7ab99 100644 --- a/extensions/renderer/bindings/get_per_context_data.h +++ b/extensions/renderer/bindings/get_per_context_data.h
@@ -10,7 +10,7 @@ namespace extensions { -enum CreatePerContextData { kCreateIfMissing, kDontCreateIfMissing }; +enum class CreatePerContextData { kCreateIfMissing, kDontCreateIfMissing }; template <typename PerContextData, typename... ConstructorArgs> PerContextData* GetPerContextData(v8::Local<v8::Context> context, @@ -22,7 +22,7 @@ auto* data = static_cast<PerContextData*>( per_context_data->GetUserData(PerContextData::kPerContextDataKey)); - if (!data && should_create == kCreateIfMissing) { + if (!data && should_create == CreatePerContextData::kCreateIfMissing) { auto created_data = std::make_unique<PerContextData>(constructor_args...); data = created_data.get(); per_context_data->SetUserData(PerContextData::kPerContextDataKey,
diff --git a/extensions/renderer/extension_interaction_provider.cc b/extensions/renderer/extension_interaction_provider.cc index f2f4237..dc7c44a 100644 --- a/extensions/renderer/extension_interaction_provider.cc +++ b/extensions/renderer/extension_interaction_provider.cc
@@ -69,7 +69,8 @@ bool created_from_token) : v8_context_(v8_context), created_from_token_(created_from_token) { ExtensionInteractionData* per_context_data = - GetPerContextData<ExtensionInteractionData>(v8_context, kCreateIfMissing); + GetPerContextData<ExtensionInteractionData>( + v8_context, CreatePerContextData::kCreateIfMissing); DCHECK(per_context_data); if (created_from_token_) per_context_data->token_interaction_count++; @@ -79,8 +80,8 @@ ExtensionInteractionProvider::Scope::ScopedWorkerInteraction:: ~ScopedWorkerInteraction() { ExtensionInteractionData* per_context_data = - GetPerContextData<ExtensionInteractionData>(v8_context_, - kDontCreateIfMissing); + GetPerContextData<ExtensionInteractionData>( + v8_context_, CreatePerContextData::kDontCreateIfMissing); // If |v8_context_| was invalidated (e.g. because of JS running), bail out. if (!per_context_data) return; @@ -106,8 +107,8 @@ // Service Worker based context: if (worker_thread_util::IsWorkerThread()) { ExtensionInteractionData* per_context_data = - GetPerContextData<ExtensionInteractionData>(v8_context, - kDontCreateIfMissing); + GetPerContextData<ExtensionInteractionData>( + v8_context, CreatePerContextData::kDontCreateIfMissing); if (per_context_data && (per_context_data->interaction_count > 0 || per_context_data->token_interaction_count > 0)) { return true; @@ -128,8 +129,8 @@ v8::Local<v8::Context> v8_context) const { if (worker_thread_util::IsWorkerThread()) { ExtensionInteractionData* per_context_data = - GetPerContextData<ExtensionInteractionData>(v8_context, - kDontCreateIfMissing); + GetPerContextData<ExtensionInteractionData>( + v8_context, CreatePerContextData::kDontCreateIfMissing); const bool has_extension_api_interaction = per_context_data && per_context_data->interaction_count > 0; // Only create token for Service Workers when we have an interaction taking
diff --git a/extensions/renderer/programmatic_script_injector.cc b/extensions/renderer/programmatic_script_injector.cc index 1b0a9091..6834edb 100644 --- a/extensions/renderer/programmatic_script_injector.cc +++ b/extensions/renderer/programmatic_script_injector.cc
@@ -174,7 +174,7 @@ void ProgrammaticScriptInjector::OnWillNotInject(InjectFailureReason reason) { std::string error; switch (reason) { - case NOT_ALLOWED: + case ScriptInjector::InjectFailureReason::kNotAllowed: if (!CanShowUrlInError()) { error = manifest_errors::kCannotAccessPage; } else if (!origin_for_about_error_.empty()) { @@ -186,8 +186,9 @@ manifest_errors::kCannotAccessPageWithUrl, url_.spec()); } break; - case EXTENSION_REMOVED: // no special error here. - case WONT_INJECT: + case ScriptInjector::InjectFailureReason::kExtensionRemoved: // no special + // error here. + case ScriptInjector::InjectFailureReason::kWontInject: break; } Finish(error);
diff --git a/extensions/renderer/script_injection.cc b/extensions/renderer/script_injection.cc index fc9cb7e..d81887f 100644 --- a/extensions/renderer/script_injection.cc +++ b/extensions/renderer/script_injection.cc
@@ -96,7 +96,7 @@ ScriptInjection::~ScriptInjection() { if (!complete_) - NotifyWillNotInject(ScriptInjector::WONT_INJECT); + NotifyWillNotInject(ScriptInjector::InjectFailureReason::kWontInject); TRACE_EVENT_END("extensions", perfetto::Track::FromPointer(this), ChromeTrackEvent::kRenderProcessHost, @@ -114,21 +114,21 @@ // Fenced frames do not navigate to about:blank by default the way iframes // do. They cannot accept script injections until they perform an initial // navigation. - NotifyWillNotInject(ScriptInjector::NOT_ALLOWED); - return INJECTION_FINISHED; // We're done. + NotifyWillNotInject(ScriptInjector::InjectFailureReason::kNotAllowed); + return InjectionResult::kFinished; // We're done. } if (current_location < run_location_) - return INJECTION_WAITING; // Wait for the right location. + return InjectionResult::kWaiting; // Wait for the right location. if (request_id_ != kInvalidRequestId) { // We're waiting for permission right now, try again later. - return INJECTION_WAITING; + return InjectionResult::kWaiting; } if (!injection_host_) { - NotifyWillNotInject(ScriptInjector::EXTENSION_REMOVED); - return INJECTION_FINISHED; // We're done. + NotifyWillNotInject(ScriptInjector::InjectFailureReason::kExtensionRemoved); + return InjectionResult::kFinished; // We're done. } blink::WebLocalFrame* web_frame = render_frame_->GetWebFrame(); @@ -136,17 +136,18 @@ injection_host_.get(), web_frame, ExtensionFrameHelper::Get(render_frame_)->tab_id())) { case PermissionsData::PageAccess::kDenied: - NotifyWillNotInject(ScriptInjector::NOT_ALLOWED); - return INJECTION_FINISHED; // We're done. + NotifyWillNotInject(ScriptInjector::InjectFailureReason::kNotAllowed); + return InjectionResult::kFinished; // We're done. case PermissionsData::PageAccess::kWithheld: RequestPermissionFromBrowser(std::move(async_updated_callback)); - return INJECTION_WAITING; // Wait around for permission. + return InjectionResult::kWaiting; // Wait around for permission. case PermissionsData::PageAccess::kAllowed: InjectionResult result = Inject(scripts_run_info); // If the injection is blocked, we need to set the manager so we can // notify it upon completion. - if (result == INJECTION_BLOCKED) + if (result == InjectionResult::kBlocked) { async_completion_callback_ = std::move(async_updated_callback); + } return result; } @@ -156,8 +157,8 @@ ScriptInjection::InjectionResult ScriptInjection::OnPermissionGranted( ScriptsRunInfo* scripts_run_info) { if (!injection_host_) { - NotifyWillNotInject(ScriptInjector::EXTENSION_REMOVED); - return INJECTION_FINISHED; + NotifyWillNotInject(ScriptInjector::InjectFailureReason::kExtensionRemoved); + return InjectionResult::kFinished; } return Inject(scripts_run_info); @@ -209,7 +210,7 @@ // be run in multiple rules, and the script has already run. // See crbug.com/631247. if (!should_inject_js && !should_inject_or_remove_css) { - return INJECTION_FINISHED; + return InjectionResult::kFinished; } if (should_inject_js) @@ -227,7 +228,7 @@ ++scripts_run_info->num_blocking_js; } - return complete_ ? INJECTION_FINISHED : INJECTION_BLOCKED; + return complete_ ? InjectionResult::kFinished : InjectionResult::kBlocked; } void ScriptInjection::InjectJs(std::set<std::string>* executing_scripts,
diff --git a/extensions/renderer/script_injection.h b/extensions/renderer/script_injection.h index b746869..3f27b30 100644 --- a/extensions/renderer/script_injection.h +++ b/extensions/renderer/script_injection.h
@@ -32,10 +32,10 @@ // and contains the implementation to do so. class ScriptInjection { public: - enum InjectionResult { - INJECTION_FINISHED, - INJECTION_BLOCKED, - INJECTION_WAITING + enum class InjectionResult { + kFinished, + kBlocked, + kWaiting, }; // Represents the purpose of calling StatusUpdatedCallback. @@ -65,20 +65,21 @@ ~ScriptInjection(); // Try to inject the script at the `current_location`. This returns - // INJECTION_FINISHED if injection has injected or will never inject, returns - // INJECTION_BLOCKED if injection is running asynchronously and has not - // finished yet, returns INJECTION_WAITING if injections is delayed (either - // for permission purposes or because `current_location` is not the designated - // `run_location_`). - // If INJECTION_BLOCKED or INJECTION_WAITING is returned, - // `async_updated_callback` will be called upon the status updated. + // InjectionResult::kFinished if injection has injected or will never inject, + // returns InjectionResult::kBlocked if injection is running asynchronously + // and has not finished yet, returns InjectionResult::kWaiting if injections + // is delayed (either for permission purposes or because `current_location` is + // not the designated `run_location_`). If InjectionResult::kBlocked or + // InjectionResult::kWaiting is returned, `async_updated_callback` will be + // called upon the status updated. InjectionResult TryToInject(mojom::RunLocation current_location, ScriptsRunInfo* scripts_run_info, StatusUpdatedCallback async_updated_callback); // Called when permission for the given injection has been granted. - // Returns INJECTION_FINISHED if injection has injected or will never inject, - // returns INJECTION_BLOCKED if injection is ran asynchronously. + // Returns InjectionResult::kFinished if injection has injected or will never + // inject, returns InjectionResult::kBlocked if injection is ran + // asynchronously. InjectionResult OnPermissionGranted(ScriptsRunInfo* scripts_run_info); // Resets the pointer of the injection host when the host is gone. @@ -109,8 +110,8 @@ void HandlePermission(StatusUpdatedCallback async_updated_callback, bool granted); - // Injects the script. Returns INJECTION_FINISHED if injection has finished, - // otherwise INJECTION_BLOCKED. + // Injects the script. Returns InjectionResult::kFinished if injection has + // finished, otherwise InjectionResult::kBlocked. InjectionResult Inject(ScriptsRunInfo* scripts_run_info); // Inject any JS scripts into the frame for the injection.
diff --git a/extensions/renderer/script_injection_manager.cc b/extensions/renderer/script_injection_manager.cc index 0a359b8..628db75 100644 --- a/extensions/renderer/script_injection_manager.cc +++ b/extensions/renderer/script_injection_manager.cc
@@ -419,13 +419,13 @@ run_location, scripts_run_info, base::BindOnce(&ScriptInjectionManager::OnInjectionStatusUpdated, base::Unretained(this)))) { - case ScriptInjection::INJECTION_WAITING: + case ScriptInjection::InjectionResult::kWaiting: pending_injections_.push_back(std::move(injection)); break; - case ScriptInjection::INJECTION_BLOCKED: + case ScriptInjection::InjectionResult::kBlocked: running_injections_.push_back(std::move(injection)); break; - case ScriptInjection::INJECTION_FINISHED: + case ScriptInjection::InjectionResult::kFinished: break; } } @@ -505,8 +505,9 @@ mojom::RunLocation::kRunDeferred); ScriptInjection::InjectionResult res = script_injection->OnPermissionGranted(&scripts_run_info); - if (res == ScriptInjection::INJECTION_BLOCKED) + if (res == ScriptInjection::InjectionResult::kBlocked) { running_injections_.push_back(std::move(script_injection)); + } scripts_run_info.LogRun(activity_logging_enabled_); }
diff --git a/extensions/renderer/script_injector.h b/extensions/renderer/script_injector.h index d8b66ca..3dfc58f7 100644 --- a/extensions/renderer/script_injector.h +++ b/extensions/renderer/script_injector.h
@@ -33,10 +33,10 @@ class ScriptInjector { public: // The possible reasons for not injecting the script. - enum InjectFailureReason { - EXTENSION_REMOVED, // The extension was removed before injection. - NOT_ALLOWED, // The script is not allowed to inject. - WONT_INJECT // The injection won't inject because the user rejected + enum class InjectFailureReason { + kExtensionRemoved, // The extension was removed before injection. + kNotAllowed, // The script is not allowed to inject. + kWontInject, // The injection won't inject because the user rejected // (or just did not accept) the injection. };
diff --git a/gpu/config/gpu_control_list.cc b/gpu/config/gpu_control_list.cc index bae4693e..0735239 100644 --- a/gpu/config/gpu_control_list.cc +++ b/gpu/config/gpu_control_list.cc
@@ -31,13 +31,12 @@ // Break a version string into segments. Return true if each segment is // a valid number, and not all segment is 0. -bool ProcessVersionString(const std::string& version_string, +bool ProcessVersionString(std::string_view version_string, char splitter, std::vector<std::string>* version) { DCHECK(version); - *version = base::SplitString( - version_string, std::string(1, splitter), - base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); + *version = base::SplitString(version_string, std::string_view(&splitter, 1), + base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); if (version->size() == 0) return false; // If the splitter is '-', we assume it's a date with format "mm-dd-yyyy"; @@ -66,8 +65,8 @@ // Return 0 if number = number_ref, // 1 if number > number_ref, // -1 if number < number_ref. -int CompareNumericalNumberStrings( - const std::string& number, const std::string& number_ref) { +int CompareNumericalNumberStrings(std::string_view number, + std::string_view number_ref) { unsigned value1 = 0; unsigned value2 = 0; bool valid = base::StringToUint(number, &value1); @@ -89,8 +88,8 @@ // If number_ref is xxx, it's considered as xxx* // For example: CompareLexicalNumberStrings("121", "12") returns 0, // CompareLexicalNumberStrings("12", "121") returns -1. -int CompareLexicalNumberStrings( - const std::string& number, const std::string& number_ref) { +int CompareLexicalNumberStrings(std::string_view number, + std::string_view number_ref) { for (size_t i = 0; i < number_ref.length(); ++i) { unsigned value1 = 0; if (i < number.length()) @@ -105,7 +104,7 @@ } // A mismatch is identified only if both |input| and |pattern| are not empty. -bool StringMismatch(const std::string& input, const std::string& pattern) { +bool StringMismatch(std::string_view input, std::string_view pattern) { if (input.empty() || pattern.empty()) return false; static crash_reporter::CrashKeyString<128> crash_key( @@ -114,16 +113,16 @@ return !RE2::FullMatch(input, pattern); } -bool StringMismatch(const std::string& input, const char* pattern) { +bool StringMismatch(std::string_view input, const char* pattern) { if (!pattern) return false; - std::string pattern_string(pattern); + std::string_view pattern_string(pattern); return StringMismatch(input, pattern_string); } } // namespace -bool GpuControlList::Version::Contains(const std::string& version_string, +bool GpuControlList::Version::Contains(std::string_view version_string, char splitter) const { if (op == kUnknown) return false; @@ -205,10 +204,9 @@ } // static -int GpuControlList::Version::Compare( - const std::vector<std::string>& version, - const std::vector<std::string>& version_ref, - VersionStyle version_style) { +int GpuControlList::Version::Compare(base::span<const std::string> version, + base::span<const std::string> version_ref, + VersionStyle version_style) { DCHECK(version.size() > 0 && version_ref.size() > 0); DCHECK(version_style != kVersionStyleUnknown); for (size_t i = 0; i < version_ref.size(); ++i) { @@ -227,7 +225,7 @@ } bool GpuControlList::More::GLVersionInfoMismatch( - const std::string& gl_version_string) const { + std::string_view gl_version_string) const { if (gl_version_string.empty()) { return false; } @@ -250,15 +248,15 @@ } void GpuControlList::Entry::LogControlListMatch( - const std::string& control_list_logging_name) const { + std::string_view control_list_logging_name) const { static const char kControlListMatchMessage[] = "Control list match for rule #%u in %s."; VLOG(1) << base::StringPrintf(kControlListMatchMessage, id, - control_list_logging_name.c_str()); + control_list_logging_name); } bool GpuControlList::DriverInfo::Contains( - const std::vector<GPUInfo::GPUDevice>& gpus) const { + base::span<const GPUInfo::GPUDevice> gpus) const { for (auto& gpu : gpus) { if (StringMismatch(gpu.driver_vendor, driver_vendor)) continue; @@ -400,7 +398,7 @@ } bool GpuControlList::IntelConditions::Contains( - const std::vector<GPUInfo::GPUDevice>& candidates, + base::span<const GPUInfo::GPUDevice> candidates, const GPUInfo& gpu_info) const { if (intel_gpu_series_list.size() > 0) { DCHECK(!intel_gpu_generation.IsSpecified()); @@ -461,7 +459,7 @@ GpuControlList::Conditions::Conditions(const Conditions& other) = default; bool GpuControlList::Conditions::Contains(OsType target_os_type, - const std::string& target_os_version, + std::string_view target_os_version, const GPUInfo& gpu_info) const { DCHECK(target_os_type != kOsAny); if (os_type != kOsAny) { @@ -592,7 +590,7 @@ } bool GpuControlList::Entry::Contains(OsType target_os_type, - const std::string& target_os_version, + std::string_view target_os_version, const GPUInfo& gpu_info) const { static crash_reporter::CrashKeyString<8> crash_key( "GpuControlList::Entry::id"); @@ -690,13 +688,13 @@ GpuControlList::~GpuControlList() = default; std::set<int32_t> GpuControlList::MakeDecision(GpuControlList::OsType os, - const std::string& os_version, + std::string_view os_version, const GPUInfo& gpu_info) { return MakeDecision(os, os_version, gpu_info, 0); } std::set<int32_t> GpuControlList::MakeDecision(GpuControlList::OsType os, - const std::string& os_version, + std::string_view os_version, const GPUInfo& gpu_info, uint32_t target_test_group) { active_entries_.clear(); @@ -712,7 +710,7 @@ if (os == kOsAny) os = GetOsType(); - std::string processed_os_version = os_version; + std::string processed_os_version(os_version); if (processed_os_version.empty()) { #if BUILDFLAG(IS_WIN) base::win::OSInfo::VersionNumber version_number = @@ -771,8 +769,9 @@ } std::vector<uint32_t> GpuControlList::GetEntryIDsFromIndices( - const std::vector<uint32_t>& entry_indices) const { + base::span<const uint32_t> entry_indices) const { std::vector<uint32_t> ids; + ids.reserve(entry_indices.size()); for (auto index : entry_indices) { ids.push_back(entries_[index].id); } @@ -804,8 +803,8 @@ } void GpuControlList::GetReasons(base::Value::List& problem_list, - const std::string& tag, - const std::vector<uint32_t>& entries) const { + std::string_view tag, + base::span<const uint32_t> entries) const { for (auto index : entries) { const Entry& entry = entries_[index]; base::Value::Dict problem; @@ -859,7 +858,7 @@ // static GpuControlList::GLType GpuControlList::ProcessANGLEGLRenderer( - const std::string& gl_renderer, + std::string_view gl_renderer, std::string* vendor, std::string* renderer, std::string* version) { @@ -890,14 +889,14 @@ } } -void GpuControlList::AddSupportedFeature( - const std::string& feature_name, int feature_id) { - feature_map_[feature_id] = feature_name; +void GpuControlList::AddSupportedFeature(std::string_view feature_name, + int feature_id) { + feature_map_[feature_id] = std::string(feature_name); } // static bool GpuControlList::AreEntryIndicesValid( - const std::vector<uint32_t>& entry_indices, + base::span<const uint32_t> entry_indices, size_t total_entries) { for (auto index : entry_indices) { if (index >= total_entries)
diff --git a/gpu/config/gpu_control_list.h b/gpu/config/gpu_control_list.h index 5d05fdc..aa29beb 100644 --- a/gpu/config/gpu_control_list.h +++ b/gpu/config/gpu_control_list.h
@@ -119,9 +119,9 @@ bool IsSpecified() const { return op != kUnknown; } - bool Contains(const std::string& version_string, char splitter) const; + bool Contains(std::string_view version_string, char splitter) const; - bool Contains(const std::string& version_string) const { + bool Contains(std::string_view version_string) const { return Contains(version_string, '.'); } @@ -135,8 +135,8 @@ // If "version_style" is Lexical, the first segment is compared // numerically, all other segments are compared lexically. // Lexical is used for AMD Linux driver versions only. - static int Compare(const std::vector<std::string>& version, - const std::vector<std::string>& version_ref, + static int Compare(base::span<const std::string> version, + base::span<const std::string> version_ref, VersionStyle version_style); }; @@ -144,7 +144,7 @@ const char* driver_vendor; Version driver_version; - bool Contains(const std::vector<GPUInfo::GPUDevice>& gpus) const; + bool Contains(base::span<const GPUInfo::GPUDevice> gpus) const; }; struct GPU_CONFIG_EXPORT GLStrings { @@ -181,7 +181,7 @@ // Return true if GL_VERSION string does not fit the entry info // on GL version. - bool GLVersionInfoMismatch(const std::string& gl_version_string) const; + bool GLVersionInfoMismatch(std::string_view gl_version_string) const; bool Contains(const GPUInfo& gpu_info) const; }; @@ -195,7 +195,7 @@ base::raw_span<const IntelGpuSeriesType> intel_gpu_series_list; Version intel_gpu_generation; - bool Contains(const std::vector<GPUInfo::GPUDevice>& candidates, + bool Contains(base::span<const GPUInfo::GPUDevice> candidates, const GPUInfo& gpu_info) const; }; @@ -231,7 +231,7 @@ Conditions(const Conditions& other); bool Contains(OsType os_type, - const std::string& os_version, + std::string_view os_version, const GPUInfo& gpu_info) const; // Determines whether we needs more gpu info to make the blocklisting @@ -260,7 +260,7 @@ RAW_PTR_EXCLUSION base::span<const Conditions> exceptions; bool Contains(OsType os_type, - const std::string& os_version, + std::string_view os_version, const GPUInfo& gpu_info) const; bool AppliesToTestGroup(uint32_t target_test_group) const; @@ -273,8 +273,7 @@ // Logs a control list match for this rule in the list identified by // |control_list_logging_name|. - void LogControlListMatch( - const std::string& control_list_logging_name) const; + void LogControlListMatch(std::string_view control_list_logging_name) const; }; explicit GpuControlList(base::span<const GpuControlList::Entry> data); @@ -286,13 +285,13 @@ // If os is kOsAny, use the current OS; if os_version is empty, use the // current OS version. std::set<int32_t> MakeDecision(OsType os, - const std::string& os_version, + std::string_view os_version, const GPUInfo& gpu_info); // Same as the above function, but instead of using the entries with no // "test_group" specified or "test_group" = 0, using the entries with // "test_group" = |target_test_group|. std::set<int32_t> MakeDecision(OsType os, - const std::string& os_version, + std::string_view os_version, const GPUInfo& gpu_info, uint32_t target_test_group); @@ -300,7 +299,7 @@ const std::vector<uint32_t>& GetActiveEntries() const; // Return corresponding entry IDs from entry indices. std::vector<uint32_t> GetEntryIDsFromIndices( - const std::vector<uint32_t>& entry_indices) const; + base::span<const uint32_t> entry_indices) const; // Collects all disabled extensions. std::vector<std::string> GetDisabledExtensions(); @@ -316,8 +315,8 @@ // The use case is we compute the entries from GPU process and send them to // browser process, and call GetReasons() in browser process. void GetReasons(base::Value::List& problem_list, - const std::string& tag, - const std::vector<uint32_t>& entries) const; + std::string_view tag, + base::span<const uint32_t> entries) const; // Return the largest entry id. This is used for histogramming. uint32_t max_entry_id() const; @@ -331,24 +330,24 @@ size_t num_entries() const; // Register a feature to FeatureMap. - void AddSupportedFeature(const std::string& feature_name, int feature_id); + void AddSupportedFeature(std::string_view feature_name, int feature_id); // Enables logging of control list decisions. - void EnableControlListLogging(const std::string& control_list_logging_name) { + void EnableControlListLogging(std::string_view control_list_logging_name) { control_list_logging_enabled_ = true; control_list_logging_name_ = control_list_logging_name; } protected: // Return false if an entry index goes beyond |total_entries|. - static bool AreEntryIndicesValid(const std::vector<uint32_t>& entry_indices, + static bool AreEntryIndicesValid(base::span<const uint32_t> entry_indices, size_t total_entries); private: // Returns kGLTypeNone if gl_renderer is empty. // Returns kGLTypeGLES if gl_renderer isn't in the format of ANGLE(_,_,_). // Returns kGLTypeANGLE_VULKAN or kGLTypeANGLE_GLES otherwise. - static GLType ProcessANGLEGLRenderer(const std::string& gl_renderer, + static GLType ProcessANGLEGLRenderer(std::string_view gl_renderer, std::string* vendor = nullptr, std::string* renderer = nullptr, std::string* version = nullptr);
diff --git a/internal b/internal index d0f96e7..1006762 160000 --- a/internal +++ b/internal
@@ -1 +1 @@ -Subproject commit d0f96e734c0973ba26686d8571a7701bb4be2a17 +Subproject commit 10067623e5b28dcbed49736689d2c9bc61aed9ac
diff --git a/ios/chrome/app/credential_provider_migrator_app_agent.mm b/ios/chrome/app/credential_provider_migrator_app_agent.mm index 5d17975d..916ddae 100644 --- a/ios/chrome/app/credential_provider_migrator_app_agent.mm +++ b/ios/chrome/app/credential_provider_migrator_app_agent.mm
@@ -138,6 +138,9 @@ } } +- (void)passkeyModelDidChange { +} + #pragma mark - Private // Returns whether multiple profiles have at least one scene connected.
diff --git a/ios/chrome/browser/ai_prototyping/test/BUILD.gn b/ios/chrome/browser/ai_prototyping/test/BUILD.gn new file mode 100644 index 0000000..77de289 --- /dev/null +++ b/ios/chrome/browser/ai_prototyping/test/BUILD.gn
@@ -0,0 +1,43 @@ +# Copyright 2025 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +source_set("eg_app_support+eg2") { + configs += [ "//build/config/ios:xctest_config" ] + testonly = true + sources = [ + "page_context_app_interface.h", + "page_context_app_interface.mm", + ] + deps = [ + "//base", + "//base/test:test_support", + "//components/optimization_guide/proto:optimization_guide_proto", + "//ios/chrome/browser/intelligence/proto_wrappers", + "//ios/chrome/browser/shared/model/browser", + "//ios/chrome/browser/shared/model/web_state_list", + "//ios/chrome/test/app:test_support", + ] +} + +source_set("eg_test_support+eg2") { + configs += [ "//build/config/ios:xctest_config" ] + testonly = true + sources = [ + "page_context_app_interface.h", + "page_context_app_interface_stub.mm", + ] + deps = [ "//ios/testing/earl_grey:eg_test_support+eg2" ] +} + +source_set("eg2_tests") { + configs += [ "//build/config/ios:xctest_config" ] + testonly = true + sources = [ "page_context_extraction_egtest.mm" ] + deps = [ + ":eg_test_support+eg2", + "//ios/chrome/test/earl_grey:eg_test_support+eg2", + "//ios/testing/earl_grey:eg_test_support+eg2", + ] + frameworks = [ "UIKit.framework" ] +}
diff --git a/ios/chrome/browser/ai_prototyping/test/DEPS b/ios/chrome/browser/ai_prototyping/test/DEPS new file mode 100644 index 0000000..d0484249 --- /dev/null +++ b/ios/chrome/browser/ai_prototyping/test/DEPS
@@ -0,0 +1,3 @@ +include_rules = [ + "+ios/chrome/browser/intelligence/proto_wrappers", +]
diff --git a/ios/chrome/browser/ai_prototyping/test/page_context_app_interface.h b/ios/chrome/browser/ai_prototyping/test/page_context_app_interface.h new file mode 100644 index 0000000..ae15d73 --- /dev/null +++ b/ios/chrome/browser/ai_prototyping/test/page_context_app_interface.h
@@ -0,0 +1,24 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_AI_PROTOTYPING_TEST_PAGE_CONTEXT_APP_INTERFACE_H_ +#define IOS_CHROME_BROWSER_AI_PROTOTYPING_TEST_PAGE_CONTEXT_APP_INTERFACE_H_ + +#import <Foundation/Foundation.h> + +// App interface for capturing annotated page context for testing. +@interface PageContextAppInterface : NSObject + +// Triggers the capture of the annotated page context. ++ (void)triggerPageContextCapture; + +// Returns whether the page context capture has completed. ++ (BOOL)isPageContextCaptureComplete; + +// Returns the page context capture result. ++ (NSString*)pageContextResult; + +@end + +#endif // IOS_CHROME_BROWSER_AI_PROTOTYPING_TEST_PAGE_CONTEXT_APP_INTERFACE_H_
diff --git a/ios/chrome/browser/ai_prototyping/test/page_context_app_interface.mm b/ios/chrome/browser/ai_prototyping/test/page_context_app_interface.mm new file mode 100644 index 0000000..832f829 --- /dev/null +++ b/ios/chrome/browser/ai_prototyping/test/page_context_app_interface.mm
@@ -0,0 +1,128 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/chrome/browser/ai_prototyping/test/page_context_app_interface.h" + +#import "base/functional/bind.h" +#import "base/functional/callback.h" +#import "base/no_destructor.h" +#import "base/test/ios/wait_util.h" +#import "base/types/expected.h" +#import "components/optimization_guide/proto/features/common_quality_data.pb.h" +#import "ios/chrome/browser/intelligence/proto_wrappers/page_context_wrapper.h" +#import "ios/chrome/browser/shared/model/browser/browser.h" +#import "ios/chrome/browser/shared/model/web_state_list/web_state_list.h" +#import "ios/chrome/test/app/chrome_test_util.h" + +namespace { +// Helper function to convert PageContextWrapperError enum to a readable string. +NSString* StringFromPageContextWrapperError(PageContextWrapperError error) { + switch (error) { + case PageContextWrapperError::kGenericError: + return @"Generic Error"; + case PageContextWrapperError::kAPCError: + return @"Annotated Page Content (APC) Error"; + case PageContextWrapperError::kScreenshotError: + return @"Screenshot Error"; + case PageContextWrapperError::kPDFDataError: + return @"PDF Data Error"; + case PageContextWrapperError::kForceDetachError: + return @"Force Detach Error (Webpage Protected)"; + case PageContextWrapperError::kTimeout: + return @"Timeout Error"; + case PageContextWrapperError::kInnerTextError: + return @"InnerText Error"; + } +} +} // namespace + +@interface PageContextAppInterface () +// Whether the page context capture has completed. +@property(nonatomic, assign) BOOL pageContextCaptureComplete; +// The page context capture result. +@property(nonatomic, copy) NSString* pageContextResult; +@end + +@implementation PageContextAppInterface { + // Holds the PageContextWrapper instance. + PageContextWrapper* _pageContextWrapper; +} + +- (instancetype)init { + self = [super init]; + if (self) { + [self reset]; + } + return self; +} + ++ (instancetype)sharedInstance { + static PageContextAppInterface* instance = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + instance = [[self alloc] init]; + }); + return instance; +} + ++ (void)triggerPageContextCapture { + [[PageContextAppInterface sharedInstance] captureAnnotatedPageContext]; +} + ++ (BOOL)isPageContextCaptureComplete { + return [[PageContextAppInterface sharedInstance] pageContextCaptureComplete]; +} + ++ (NSString*)pageContextResult { + return [[PageContextAppInterface sharedInstance] pageContextResult]; +} + +#pragma mark - Helper + +- (void)captureAnnotatedPageContext { + [self reset]; + + dispatch_async(dispatch_get_main_queue(), ^{ + base::OnceCallback<void(PageContextWrapperCallbackResponse)> + page_context_completion_callback = + base::BindOnce(^(PageContextWrapperCallbackResponse response) { + if (response.has_value()) { + const std::string& serialized_string = + response.value()->SerializeAsString(); + // TODO(crbug.com/465016086): Store page context locally or + // upload it based on the test args. + self.pageContextResult = [NSString + stringWithCString:serialized_string.c_str() + encoding:[NSString defaultCStringEncoding]]; + } else { + self.pageContextResult = [NSString + stringWithFormat:@"Error: %@", + StringFromPageContextWrapperError( + response.error())]; + } + self->_pageContextWrapper = nil; + self.pageContextCaptureComplete = YES; + }); + + self->_pageContextWrapper = [[PageContextWrapper alloc] + initWithWebState:chrome_test_util::GetCurrentBrowser() + ->GetWebStateList() + ->GetActiveWebState() + completionCallback:std::move(page_context_completion_callback)]; + + [self->_pageContextWrapper setShouldGetAnnotatedPageContent:YES]; + [self->_pageContextWrapper setShouldGetSnapshot:YES]; + [self->_pageContextWrapper setShouldGetFullPagePDF:YES]; + [self->_pageContextWrapper + populatePageContextFieldsAsyncWithTimeout:base::Seconds(30)]; + }); +} + +- (void)reset { + _pageContextWrapper = nil; + self.pageContextCaptureComplete = NO; + self.pageContextResult = nil; +} + +@end
diff --git a/ios/chrome/browser/ai_prototyping/test/page_context_app_interface_stub.mm b/ios/chrome/browser/ai_prototyping/test/page_context_app_interface_stub.mm new file mode 100644 index 0000000..c5bb0a74 --- /dev/null +++ b/ios/chrome/browser/ai_prototyping/test/page_context_app_interface_stub.mm
@@ -0,0 +1,9 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/chrome/browser/ai_prototyping/test/page_context_app_interface.h" + +#import "ios/testing/earl_grey/earl_grey_test.h" + +GREY_STUB_CLASS_IN_APP_MAIN_QUEUE(PageContextAppInterface)
diff --git a/ios/chrome/browser/ai_prototyping/test/page_context_extraction_egtest.mm b/ios/chrome/browser/ai_prototyping/test/page_context_extraction_egtest.mm new file mode 100644 index 0000000..842c9a2 --- /dev/null +++ b/ios/chrome/browser/ai_prototyping/test/page_context_extraction_egtest.mm
@@ -0,0 +1,46 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import <XCTest/XCTest.h> + +#import "ios/chrome/browser/ai_prototyping/test/page_context_app_interface.h" +#import "ios/chrome/test/earl_grey/chrome_actions.h" +#import "ios/chrome/test/earl_grey/chrome_earl_grey.h" +#import "ios/chrome/test/earl_grey/chrome_earl_grey_ui.h" +#import "ios/chrome/test/earl_grey/chrome_matchers.h" +#import "ios/chrome/test/earl_grey/chrome_test_case.h" +#import "ios/testing/earl_grey/earl_grey_test.h" +#import "url/gurl.h" + +// Test case for page context extraction. +@interface PageContextExtraction : ChromeTestCase +@end + +@implementation PageContextExtraction + +// Tests that the page context is extracted correctly. +- (void)testExtractPageContext { + // TODO(crbug.com/465016086): Add implementation to load list of urls. + + // Navigate to a site and wait for the site to complete loading before + // capturing page context. + [ChromeEarlGrey loadURL:GURL("https://www.youtube.com/") + waitForCompletion:YES]; + [PageContextAppInterface triggerPageContextCapture]; + + GREYCondition* condition = [GREYCondition + conditionWithName:@"Page context extraction completed" + block:^BOOL { + return + [PageContextAppInterface isPageContextCaptureComplete]; + }]; + + BOOL success = [condition waitWithTimeout:30]; + XCTAssertTrue(success, @"Test timed out waiting for page context."); + + NSString* pageContextString = [PageContextAppInterface pageContextResult]; + NSLog(@"Captured Page Context: %@", pageContextString); +} + +@end
diff --git a/ios/chrome/browser/bookmarks/ui_bundled/home/bookmarks_coordinator.mm b/ios/chrome/browser/bookmarks/ui_bundled/home/bookmarks_coordinator.mm index 2a9ca93..bc6c5be 100644 --- a/ios/chrome/browser/bookmarks/ui_bundled/home/bookmarks_coordinator.mm +++ b/ios/chrome/browser/bookmarks/ui_bundled/home/bookmarks_coordinator.mm
@@ -251,14 +251,12 @@ URL:bookmarkedURL editAction:editAction]]; - // Show non-modal sign-in promo for bookmarks if the feature is enabled. - if (IsNonModalSignInPromoEnabled()) { - id<NonModalSignInPromoCommands> nonModalSignInPromoHandler = - HandlerForProtocol(self.browser->GetCommandDispatcher(), - NonModalSignInPromoCommands); - [nonModalSignInPromoHandler - showNonModalSignInPromoWithType:SignInPromoType::kBookmark]; - } + // Show non-modal sign-in promo for bookmarks. + id<NonModalSignInPromoCommands> nonModalSignInPromoHandler = + HandlerForProtocol(self.browser->GetCommandDispatcher(), + NonModalSignInPromoCommands); + [nonModalSignInPromoHandler + showNonModalSignInPromoWithType:SignInPromoType::kBookmark]; default_browser::NotifyBookmarkAddOrEdit( feature_engagement::TrackerFactory::GetForProfile(
diff --git a/ios/chrome/browser/browser_view/ui_bundled/browser_coordinator.mm b/ios/chrome/browser/browser_view/ui_bundled/browser_coordinator.mm index 3cf32b2..9b8f984c 100644 --- a/ios/chrome/browser/browser_view/ui_bundled/browser_coordinator.mm +++ b/ios/chrome/browser/browser_view/ui_bundled/browser_coordinator.mm
@@ -4774,7 +4774,7 @@ #pragma mark - NonModalSignInPromoCommands - (void)showNonModalSignInPromoWithType:(SignInPromoType)promoType { - if (IsNonModalSignInPromoEnabled() && !self.nonModalSignInPromoCoordinator) { + if (!self.nonModalSignInPromoCoordinator) { self.nonModalSignInPromoCoordinator = [[NonModalSignInPromoCoordinator alloc] initWithBaseViewController:self.viewController
diff --git a/ios/chrome/browser/composebox/coordinator/composebox_input_plate_mediator.mm b/ios/chrome/browser/composebox/coordinator/composebox_input_plate_mediator.mm index 78819b94..7712396 100644 --- a/ios/chrome/browser/composebox/coordinator/composebox_input_plate_mediator.mm +++ b/ios/chrome/browser/composebox/coordinator/composebox_input_plate_mediator.mm
@@ -189,6 +189,8 @@ BOOL _isUpdatingCompactMode; // Whether the omnibox has text inputted. BOOL _hasText; + // Whether a successful navigation has started. + BOOL _inNavigation; } - (instancetype) @@ -249,9 +251,12 @@ _aimEligibilityService = nullptr; _composeboxObserverBridge.reset(); if (_contextualSearchSession) { - _contextualSearchSession->NotifySessionAbandoned(); + if (!_inNavigation) { + _contextualSearchSession->NotifySessionAbandoned(); + } _contextualSearchSession.reset(); } + _inNavigation = NO; _webStateList = nil; _items = nil; _URLLoader = nil; @@ -435,6 +440,8 @@ ui::PAGE_TRANSITION_GENERATED, /*destination_url_entered_without_scheme=*/false, _isIncognito); + _inNavigation = YES; + [self.URLLoader loadURLParams:params]; } @@ -1155,7 +1162,10 @@ } switch (_modeHolder.mode) { case ComposeboxMode::kRegularSearch: + _inNavigation = YES; [self.URLLoader loadURLParams:URLLoadParams]; + [self.metricsRecorder recordAutocompleteRequestTypeAtNavigation: + AutocompleteRequestType::kSearch]; break; case ComposeboxMode::kAIM: [self.metricsRecorder recordAutocompleteRequestTypeAtNavigation:
diff --git a/ios/chrome/browser/composebox/ui/composebox_input_plate_view_controller.mm b/ios/chrome/browser/composebox/ui/composebox_input_plate_view_controller.mm index 95273ed..b35d1fe41 100644 --- a/ios/chrome/browser/composebox/ui/composebox_input_plate_view_controller.mm +++ b/ios/chrome/browser/composebox/ui/composebox_input_plate_view_controller.mm
@@ -94,6 +94,9 @@ /// The size of the close icon in the context indicator buttons. const CGFloat kCloseIndicatorSize = 10.0f; +/// The index of the attachment section in the carousel. +const NSInteger kCarouselAttachmentSectionIndex = 0; + /// The image for the send button. UIImage* SendButtonImage(BOOL highlighted, ComposeboxTheme* theme) { NSArray<UIColor*>* palette = @[ @@ -319,6 +322,7 @@ completion:^{ [weakSelf updateCarouselFade]; [weakSelf updateSendButtonStateIfNeeded]; + [weakSelf scrollToLast]; }]; } @@ -646,6 +650,38 @@ contentOffsetX + boundsWidth >= contentWidth; } +/// Scrolls the last item in `_carouselView` into view. +- (void)scrollToLast { + if (!_carouselView) { + return; + } + // Ensure the content width actually overflows. If not, no-op. + CGFloat contentOffsetX = _carouselView.contentOffset.x; + CGFloat contentWidth = _carouselView.contentSize.width; + CGFloat boundsWidth = _carouselView.bounds.size.width; + if (contentOffsetX + boundsWidth >= contentWidth) { + return; + } + + BOOL attachmentSectionIsPresent = [_carouselView numberOfSections] != 0; + if (!attachmentSectionIsPresent) { + return; + } + NSInteger lastItemIndex = + [_carouselView numberOfItemsInSection:kCarouselAttachmentSectionIndex] - + 1; + if (lastItemIndex < 0) { + return; + } + NSIndexPath* lastItemIndexPath = + [NSIndexPath indexPathForItem:lastItemIndex + inSection:kCarouselAttachmentSectionIndex]; + [_carouselView + scrollToItemAtIndexPath:lastItemIndexPath + atScrollPosition:UICollectionViewScrollPositionCenteredHorizontally + animated:YES]; +} + /// Initiates the glow animation around the input plate. - (void)triggerGlowEffect { if (!_glowEffectView) {
diff --git a/ios/chrome/browser/credential_provider/model/credential_provider_migrator_unittest.mm b/ios/chrome/browser/credential_provider/model/credential_provider_migrator_unittest.mm index 60fc30fd..0ced9ed 100644 --- a/ios/chrome/browser/credential_provider/model/credential_provider_migrator_unittest.mm +++ b/ios/chrome/browser/credential_provider/model/credential_provider_migrator_unittest.mm
@@ -32,6 +32,8 @@ using ::testing::_; using ::testing::IsEmpty; using ::testing::SizeIs; +using AnyRp = ::webauthn::PasskeyModel::AnyRp; +using ShadowedCredentials = ::webauthn::PasskeyModel::ShadowedCredentials; NSData* StringToData(std::string str) { return [NSData dataWithBytes:str.data() length:str.length()]; @@ -190,7 +192,7 @@ // Verify that the credential is migrated. std::vector<sync_pb::WebauthnCredentialSpecifics> passkeys = - test_passkey_model_.GetAllPasskeys(); + test_passkey_model_.GetPasskeys(AnyRp(), ShadowedCredentials::kInclude); EXPECT_THAT(passkeys, SizeIs(1)); EXPECT_EQ(passkeys[0].sync_id(), expected.sync_id()); EXPECT_EQ(passkeys[0].credential_id(), expected.credential_id()); @@ -237,7 +239,8 @@ // Verify that we still have only 1 passkey and that its last used time was // updated. - passkeys = test_passkey_model_.GetAllPasskeys(); + passkeys = + test_passkey_model_.GetPasskeys(AnyRp(), ShadowedCredentials::kInclude); EXPECT_THAT(passkeys, SizeIs(1)); EXPECT_EQ(passkeys[0].last_used_time_windows_epoch_micros(), credential.lastUsedTime); @@ -292,7 +295,9 @@ EXPECT_EQ(store.credentials.count, 0u); // Verify that the credential is not migrated. - EXPECT_THAT(test_passkey_model_.GetAllPasskeys(), IsEmpty()); + EXPECT_THAT( + test_passkey_model_.GetPasskeys(AnyRp(), ShadowedCredentials::kInclude), + IsEmpty()); } class CredentialProviderMigratorWithSignalAPITest @@ -343,7 +348,7 @@ // Verify the passkey was migrated and is not hidden. std::vector<sync_pb::WebauthnCredentialSpecifics> passkeys = - test_passkey_model_.GetAllPasskeys(); + test_passkey_model_.GetPasskeys(AnyRp(), ShadowedCredentials::kInclude); EXPECT_THAT(passkeys, SizeIs(1)); EXPECT_FALSE(passkeys[0].hidden()); EXPECT_FALSE(passkeys[0].has_hidden_time()); @@ -382,7 +387,8 @@ EXPECT_EQ(store.credentials.count, 0u); // Verify we still have only 1 passkey, but it's hidden now. - passkeys = test_passkey_model_.GetAllPasskeys(); + passkeys = + test_passkey_model_.GetPasskeys(AnyRp(), ShadowedCredentials::kInclude); EXPECT_THAT(passkeys, SizeIs(1)); EXPECT_TRUE(passkeys[0].hidden()); EXPECT_EQ(passkeys[0].hidden_time(), kJan1st2024); @@ -421,7 +427,7 @@ // Verify the passkey was migrated and has the initial names. std::vector<sync_pb::WebauthnCredentialSpecifics> passkeys = - test_passkey_model_.GetAllPasskeys(); + test_passkey_model_.GetPasskeys(AnyRp(), ShadowedCredentials::kInclude); EXPECT_THAT(passkeys, SizeIs(1)); EXPECT_EQ(passkeys[0].user_name(), "username"); EXPECT_EQ(passkeys[0].user_display_name(), "userDisplayName"); @@ -461,7 +467,8 @@ // Verify there is still 1 passkey, but with an updated username and the same // user display name. - passkeys = test_passkey_model_.GetAllPasskeys(); + passkeys = + test_passkey_model_.GetPasskeys(AnyRp(), ShadowedCredentials::kInclude); EXPECT_THAT(passkeys, SizeIs(1)); EXPECT_EQ(passkeys[0].user_name(), "newUsername"); EXPECT_EQ(passkeys[0].user_display_name(), "userDisplayName");
diff --git a/ios/chrome/browser/drive/model/BUILD.gn b/ios/chrome/browser/drive/model/BUILD.gn index 82daa822..cd24dfd 100644 --- a/ios/chrome/browser/drive/model/BUILD.gn +++ b/ios/chrome/browser/drive/model/BUILD.gn
@@ -120,18 +120,6 @@ ] } -source_set("manage_storage_url_util") { - sources = [ - "manage_storage_url_util.h", - "manage_storage_url_util.mm", - ] - deps = [ - "//base", - "//net", - "//url", - ] -} - source_set("metrics") { sources = [ "drive_metrics.h",
diff --git a/ios/chrome/browser/drive/model/drive_availability.h b/ios/chrome/browser/drive/model/drive_availability.h index 3ad72c3..a0e4a3d 100644 --- a/ios/chrome/browser/drive/model/drive_availability.h +++ b/ios/chrome/browser/drive/model/drive_availability.h
@@ -9,7 +9,9 @@ namespace signin { class IdentityManager; } - +namespace web { +class WebState; +} namespace drive { class DriveService; @@ -20,6 +22,14 @@ drive::DriveService* drive_service, PrefService* pref_service); +// Returns whether the Choose from Drive entry point can be presented for the +// given WebState. +bool IsChooseFromDriveAvailable(web::WebState* web_state, + bool is_incognito, + signin::IdentityManager* identity_manager, + drive::DriveService* drive_service, + PrefService* pref_service); + } // namespace drive #endif // IOS_CHROME_BROWSER_DRIVE_MODEL_DRIVE_AVAILABILITY_H_
diff --git a/ios/chrome/browser/drive/model/drive_availability.mm b/ios/chrome/browser/drive/model/drive_availability.mm index 2ca94d32..7f74ce0f 100644 --- a/ios/chrome/browser/drive/model/drive_availability.mm +++ b/ios/chrome/browser/drive/model/drive_availability.mm
@@ -6,6 +6,7 @@ #import <Foundation/Foundation.h> +#import "base/metrics/histogram_functions.h" #import "components/prefs/pref_service.h" #import "components/signin/public/identity_manager/identity_manager.h" #import "ios/chrome/browser/drive/model/drive_policy.h" @@ -13,6 +14,26 @@ #import "ios/chrome/browser/shared/model/prefs/pref_names.h" #import "ios/chrome/browser/shared/public/features/features.h" +namespace { + +// LINT.IfChange(FilePickerDriveDisplayed) + +// Whether the Drive element was displayed, and the reason why it was not. +enum class FilePickerDriveDisplayed { + kDisplayed = 0, + kNoWebState = 1, + kDisabled = 2, + kOTR = 3, + kNotSignedIn = 4, + kDisabledByPolicy = 5, + kDriveServiceNotSupported = 6, + kMaxValue = kDriveServiceNotSupported, +}; + +// LINT.ThenChange(//tools/metrics/histograms/metadata/ios/enums.xml:IOSFilePickerDriveDisplayed) + +} // namespace + namespace drive { bool IsSaveToDriveAvailable(bool is_incognito, @@ -46,4 +67,61 @@ return true; } +bool IsChooseFromDriveAvailable(web::WebState* web_state, + bool is_incognito, + signin::IdentityManager* identity_manager, + drive::DriveService* drive_service, + PrefService* pref_service) { + // Check WebState still exists. + if (!web_state) { + base::UmaHistogramEnumeration("IOS.FilePicker.Drive.Displayed", + FilePickerDriveDisplayed::kNoWebState); + return false; + } + + // Check flag is enabled. + if (!base::FeatureList::IsEnabled(kIOSChooseFromDrive)) { + base::UmaHistogramEnumeration("IOS.FilePicker.Drive.Displayed", + FilePickerDriveDisplayed::kDisabled); + return false; + } + + // Check WebState is not Incognito. + if (is_incognito) { + base::UmaHistogramEnumeration("IOS.FilePicker.Drive.Displayed", + FilePickerDriveDisplayed::kOTR); + return false; + } + + // Check user is signed in. + if (!identity_manager || + !identity_manager->HasPrimaryAccount(signin::ConsentLevel::kSignin)) { + base::UmaHistogramEnumeration("IOS.FilePicker.Drive.Displayed", + FilePickerDriveDisplayed::kNotSignedIn); + return false; + } + + // Check enterprise policy. + CHECK(pref_service); + if (pref_service->GetInteger( + prefs::kIosChooseFromDriveFilePickerPolicySettings) == + static_cast<int>(ChooseFromDrivePolicySettings::kDisabled)) { + base::UmaHistogramEnumeration("IOS.FilePicker.Drive.Displayed", + FilePickerDriveDisplayed::kDisabledByPolicy); + return false; + } + + // Check if DriveService is supported. + if (!drive_service || !drive_service->IsSupported()) { + base::UmaHistogramEnumeration( + "IOS.FilePicker.Drive.Displayed", + FilePickerDriveDisplayed::kDriveServiceNotSupported); + return false; + } + + base::UmaHistogramEnumeration("IOS.FilePicker.Drive.Displayed", + FilePickerDriveDisplayed::kDisplayed); + return true; +} + } // namespace drive
diff --git a/ios/chrome/browser/drive/model/manage_storage_url_util.h b/ios/chrome/browser/drive/model/manage_storage_url_util.h deleted file mode 100644 index 54a5bfd4..0000000 --- a/ios/chrome/browser/drive/model/manage_storage_url_util.h +++ /dev/null
@@ -1,15 +0,0 @@ -// Copyright 2024 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef IOS_CHROME_BROWSER_DRIVE_MODEL_MANAGE_STORAGE_URL_UTIL_H_ -#define IOS_CHROME_BROWSER_DRIVE_MODEL_MANAGE_STORAGE_URL_UTIL_H_ - -#import <string_view> - -class GURL; - -// Returns a URL to let user with email `user_email` manage their Drive storage. -GURL GenerateManageDriveStorageUrl(std::string_view user_email); - -#endif // IOS_CHROME_BROWSER_DRIVE_MODEL_MANAGE_STORAGE_URL_UTIL_H_
diff --git a/ios/chrome/browser/drive/model/manage_storage_url_util.mm b/ios/chrome/browser/drive/model/manage_storage_url_util.mm deleted file mode 100644 index b203026..0000000 --- a/ios/chrome/browser/drive/model/manage_storage_url_util.mm +++ /dev/null
@@ -1,39 +0,0 @@ -// Copyright 2024 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import "ios/chrome/browser/drive/model/manage_storage_url_util.h" - -#import "net/base/url_util.h" -#import "url/gurl.h" - -namespace { - -// URL template to redirect a user to the URL given as the `continue` query -// parameter, using the Google account given as the `Email` query parameter. -// This way, if the URL given as the `continue` query parameter is -// `kManageStorageURL`, the user will be redirected to manage the storage -// of the account associated with the given email. -constexpr char kAccountChooserRedirectionUrlTemplate[] = - "https://accounts.google.com/AccountChooser"; -constexpr char kAccountChooserRedirectionUrlEmailParameterName[] = "Email"; -constexpr char kAccountChooserRedirectionUrlContinueParameterName[] = - "continue"; -// URL to let the user manage their Drive storage. -constexpr char kManageStorageURL[] = "https://one.google.com/storage"; - -} // namespace - -GURL GenerateManageDriveStorageUrl(std::string_view user_email) { - // The user email is used to switch to the appropriate account before loading - // the "Manage Storage" web page. - GURL result(kAccountChooserRedirectionUrlTemplate); - // Set 'Email' query parameter. - result = net::AppendQueryParameter( - result, kAccountChooserRedirectionUrlEmailParameterName, user_email); - // Set 'continue' query parameter. - result = net::AppendQueryParameter( - result, kAccountChooserRedirectionUrlContinueParameterName, - kManageStorageURL); - return result; -}
diff --git a/ios/chrome/browser/flags/about_flags.mm b/ios/chrome/browser/flags/about_flags.mm index 7d0c3945..68d74a13 100644 --- a/ios/chrome/browser/flags/about_flags.mm +++ b/ios/chrome/browser/flags/about_flags.mm
@@ -1539,9 +1539,6 @@ flags_ui::kOsIos, FEATURE_VALUE_TYPE( autofill::features::debug::kAutofillShowTypePredictions)}, - {"sign-in-button-no-avatar", flag_descriptions::kSignInButtonNoAvatarName, - flag_descriptions::kSignInButtonNoAvatarDescription, flags_ui::kOsIos, - FEATURE_VALUE_TYPE(kSignInButtonNoAvatar)}, {"ntp-background-customization", flag_descriptions::kNTPBackgroundCustomizationName, flag_descriptions::kNTPBackgroundCustomizationDescription, @@ -2231,10 +2228,6 @@ flag_descriptions::kAutofillEnableCardBenefitsForBmoDescription, flags_ui::kOsIos, FEATURE_VALUE_TYPE(autofill::features::kAutofillEnableCardBenefitsForBmo)}, - {"ios-manage-account-storage", - flag_descriptions::kIOSManageAccountStorageName, - flag_descriptions::kIOSManageAccountStorageDescription, flags_ui::kOsIos, - FEATURE_VALUE_TYPE(kIOSManageAccountStorage)}, {"download-auto-deletion", flag_descriptions::kDownloadAutoDeletionName, flag_descriptions::kDownloadAutoDeletionDescription, flags_ui::kOsIos, FEATURE_VALUE_TYPE(kDownloadAutoDeletionFeatureEnabled)}, @@ -2293,9 +2286,6 @@ flag_descriptions::kLensUnaryApiSalientTextEnabledName, flag_descriptions::kLensUnaryApiSalientTextEnabledDescription, flags_ui::kOsIos, FEATURE_VALUE_TYPE(kLensUnaryApiSalientTextEnabled)}, - {"non-modal-sign-in-promo", flag_descriptions::kNonModalSignInPromoName, - flag_descriptions::kNonModalSignInPromoDescription, flags_ui::kOsIos, - FEATURE_VALUE_TYPE(kNonModalSignInPromo)}, {"autofill-save-card-bottomsheet", flag_descriptions::kAutofillSaveCardBottomSheetName, flag_descriptions::kAutofillSaveCardBottomSheetDescription, @@ -2467,6 +2457,10 @@ flag_descriptions::kReaderModeReadabilityHeuristicName, flag_descriptions::kReaderModeReadabilityHeuristicDescription, flags_ui::kOsIos, FEATURE_VALUE_TYPE(kEnableReadabilityHeuristic)}, + {"reader-mode-support-new-fonts", + flag_descriptions::kReaderModeSupportNewFontsName, + flag_descriptions::kReaderModeSupportNewFontsDescription, flags_ui::kOsIos, + FEATURE_VALUE_TYPE(dom_distiller::kReaderModeSupportNewFonts)}, {"reader-mode-badge-support", flag_descriptions::kReaderModeBadgeSupportName, flag_descriptions::kReaderModeBadgeSupportDescription, flags_ui::kOsIos,
diff --git a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc index 64315f0..2e04ffd 100644 --- a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc +++ b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc
@@ -795,10 +795,6 @@ "When enabled, the two-bubble design is used for the Keyboard Accessory " "view."; -const char kIOSManageAccountStorageName[] = "Allow managing Account storage."; -const char kIOSManageAccountStorageDescription[] = - "Add entry points to manage Google One account storage."; - const char kIOSOmniboxAimServerEligibilityEnName[] = "AIM Server Eligibility EN locales"; const char kIOSOmniboxAimServerEligibilityEnDescription[] = @@ -1459,6 +1455,10 @@ const char kReaderModeReadabilityHeuristicDescription[] = "Enables Readability heuristic for Reader Mode UI."; +const char kReaderModeSupportNewFontsName[] = "Reader Mode support new fonts"; +const char kReaderModeSupportNewFontsDescription[] = + "Enables new accessible font options in Reader Mode."; + const char kReaderModeTranslationName[] = "Enables Reader Mode Translation"; const char kReaderModeTranslationDescription[] = "Enables translation of web pages in Reader Mode."; @@ -1574,11 +1574,6 @@ "Show tab group in grid on start if the last activation is within a " "specific time interval"; -const char kSignInButtonNoAvatarName[] = - "Display sign-in button without avatar"; -const char kSignInButtonNoAvatarDescription[] = - "When enabled, the sign-in button is shown without an avatar on the NTP."; - const char kSkipDefaultBrowserPromoInFirstRunName[] = "Skip the FRE Default Browser Promo in EEA"; const char kSkipDefaultBrowserPromoInFirstRunDescription[] =
diff --git a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h index e79760e..604408e2 100644 --- a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h +++ b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h
@@ -481,9 +481,6 @@ extern const char kIOSKeyboardAccessoryTwoBubbleName[]; extern const char kIOSKeyboardAccessoryTwoBubbleDescription[]; -extern const char kIOSManageAccountStorageName[]; -extern const char kIOSManageAccountStorageDescription[]; - extern const char kIOSOmniboxAimServerEligibilityEnName[]; extern const char kIOSOmniboxAimServerEligibilityEnDescription[]; @@ -874,6 +871,9 @@ extern const char kReaderModeReadabilityHeuristicName[]; extern const char kReaderModeReadabilityHeuristicDescription[]; +extern const char kReaderModeSupportNewFontsName[]; +extern const char kReaderModeSupportNewFontsDescription[]; + extern const char kReaderModeTranslationName[]; extern const char kReaderModeTranslationDescription[]; @@ -944,9 +944,6 @@ extern const char kShowTabGroupInGridOnStartName[]; extern const char kShowTabGroupInGridOnStartDescription[]; -extern const char kSignInButtonNoAvatarName[]; -extern const char kSignInButtonNoAvatarDescription[]; - extern const char kSkipDefaultBrowserPromoInFirstRunName[]; extern const char kSkipDefaultBrowserPromoInFirstRunDescription[];
diff --git a/ios/chrome/browser/ntp/ui_bundled/new_tab_page_header_view.mm b/ios/chrome/browser/ntp/ui_bundled/new_tab_page_header_view.mm index cce8e3d..79fd15f 100644 --- a/ios/chrome/browser/ntp/ui_bundled/new_tab_page_header_view.mm +++ b/ios/chrome/browser/ntp/ui_bundled/new_tab_page_header_view.mm
@@ -800,17 +800,13 @@ UIImage* icon = DefaultSymbolTemplateWithPointSize( kPencilSymbol, - IsSignInButtonNoAvatarEnabled() - ? ntp_home::kCustomizationMenuIconSizeWhenSignInButtonHasNoAvatar - : ntp_home::kCustomizationMenuIconSize); + ntp_home::kCustomizationMenuIconSizeWhenSignInButtonHasNoAvatar); configuration.image = icon; configuration.background.cornerRadius = ntp_home::kCustomizationMenuButtonCornerRadius; customizationMenuButton.configuration = configuration; - UIColor* unthemedTintColor = [UIColor - colorNamed:(IsSignInButtonNoAvatarEnabled() ? kBlue600Color - : kTextSecondaryColor)]; + UIColor* unthemedTintColor = [UIColor colorNamed:kBlue600Color]; customizationMenuButton.configurationUpdateHandler = CreateThemedButtonConfigurationUpdateHandler( unthemedTintColor, ^UIColor*(NewTabPageColorPalette* palette) { @@ -820,11 +816,6 @@ return [UIColor colorWithDynamicProvider:^UIColor*( UITraitCollection* traits) { - if (!IsSignInButtonNoAvatarEnabled()) { - return [[UIColor - colorNamed:@"fake_omnibox_solid_background_color"] - colorWithAlphaComponent:0.8]; - } return traits.userInterfaceStyle == UIUserInterfaceStyleDark ? [UIColor colorNamed:kTabGroupFaviconBackgroundColor]
diff --git a/ios/chrome/browser/ntp/ui_bundled/new_tab_page_header_view_controller.mm b/ios/chrome/browser/ntp/ui_bundled/new_tab_page_header_view_controller.mm index b24f71a7..6d57f826 100644 --- a/ios/chrome/browser/ntp/ui_bundled/new_tab_page_header_view_controller.mm +++ b/ios/chrome/browser/ntp/ui_bundled/new_tab_page_header_view_controller.mm
@@ -84,11 +84,6 @@ // The maximum point size of the font for the Identity Disc button. const CGFloat kIdentityDiscMaxFontSize = 24; -// The extra space between the avatar icon and the background for the sign in -// button. This is used when IsNTPBackgroundCustomizationEnabled() == YES and -// IsSignInButtonNoAvatarEnabled() == NO; -const CGFloat kIdentityDiscAvatarBackgroundSpacing = 5; - } // namespace @interface NewTabPageHeaderViewController () < @@ -394,10 +389,6 @@ DCHECK(self.identityDiscButton); DCHECK(self.identityDiscImage); DCHECK(self.identityDiscButton.accessibilityLabel); - if (!IsSignInButtonNoAvatarEnabled()) { - DCHECK([self.identityDiscButton imageForState:UIControlStateNormal] || - self.identityDiscButton.configuration.image); - } [self maybeShowSwitchAccountsIPH]; } @@ -589,16 +580,12 @@ if (!IsNTPBackgroundCustomizationEnabled()) { UIImage* icon = DefaultSymbolTemplateWithPointSize( kPencilSymbol, - IsSignInButtonNoAvatarEnabled() - ? ntp_home::kCustomizationMenuIconSizeWhenSignInButtonHasNoAvatar - : ntp_home::kCustomizationMenuIconSize); + ntp_home::kCustomizationMenuIconSizeWhenSignInButtonHasNoAvatar); [customizationMenuButton setImage:icon forState:UIControlStateNormal]; customizationMenuButton.backgroundColor = [self defaultButtonBackgroundColor]; - UIColor* tintColor = [UIColor - colorNamed:(IsSignInButtonNoAvatarEnabled() ? kBlue600Color - : kTextSecondaryColor)]; + UIColor* tintColor = [UIColor colorNamed:kBlue600Color]; customizationMenuButton.tintColor = tintColor; customizationMenuButton.layer.cornerRadius = @@ -630,9 +617,7 @@ button.accessibilityLabel = self.identityDiscAccessibilityLabel; button.clipsToBounds = YES; - BOOL useOldExperience = !IsNTPBackgroundCustomizationEnabled() && - !IsSignInButtonNoAvatarEnabled(); - if (self.isSignedIn || useOldExperience) { + if (self.isSignedIn) { UIImage* image = self.identityDiscImage; button.configuration = nil; [button setImage:image forState:UIControlStateNormal]; @@ -647,7 +632,6 @@ button.layer.cornerRadius = 0; if (!IsNTPBackgroundCustomizationEnabled()) { - CHECK(IsSignInButtonNoAvatarEnabled()); [button setImage:nil forState:UIControlStateNormal]; UIButtonConfiguration* buttonConfiguration = [UIButtonConfiguration plainButtonConfiguration]; @@ -692,47 +676,23 @@ UIColor* backgroundColor = colorPalette ? colorPalette.headerButtonColor : [self defaultButtonBackgroundColor]; - // The default avatar icon does not have a background. - if (colorPalette || IsSignInButtonNoAvatarEnabled()) { - buttonConfiguration.background.backgroundColor = backgroundColor; - } + buttonConfiguration.background.backgroundColor = backgroundColor; } - if (IsSignInButtonNoAvatarEnabled()) { - buttonConfiguration.cornerStyle = UIButtonConfigurationCornerStyleCapsule; - buttonConfiguration.contentInsets = NSDirectionalEdgeInsetsMake( - kPillVerticalPadding, kPillHorizontalPadding, kPillVerticalPadding, - kPillHorizontalPadding); + buttonConfiguration.cornerStyle = UIButtonConfigurationCornerStyleCapsule; + buttonConfiguration.contentInsets = + NSDirectionalEdgeInsetsMake(kPillVerticalPadding, kPillHorizontalPadding, + kPillVerticalPadding, kPillHorizontalPadding); - NSDictionary* attributes = @{ - NSFontAttributeName : PreferredFontForTextStyle( - UIFontTextStyleSubheadline, UIFontWeightSemibold, - kIdentityDiscMaxFontSize), - NSForegroundColorAttributeName : foregroundColor, - }; - buttonConfiguration.attributedTitle = [[NSAttributedString alloc] - initWithString:l10n_util::GetNSString(IDS_IOS_SIGNIN_BUTTON_TEXT) - attributes:attributes]; - } else { - buttonConfiguration.image = self.identityDiscImage; - buttonConfiguration.baseForegroundColor = foregroundColor; - - // UIBackgroundConfiguration requires a background inset, but it's easier to - // think about the amount of space desired between the avatar and the - // background, an "outset" from the avatar. So use that amount to calculate - // the inset from the button edges. - CGFloat rawInsetAmount = (_identityDiscWidthConstraint.constant - - buttonConfiguration.image.size.width) / - 2 - - kIdentityDiscAvatarBackgroundSpacing; - // Make sure that the background isn't larger than the view. - CGFloat insetAmount = MAX(rawInsetAmount, 0); - buttonConfiguration.background.backgroundInsets = - NSDirectionalEdgeInsetsMake(insetAmount, insetAmount, insetAmount, - insetAmount); - buttonConfiguration.background.cornerRadius = - buttonConfiguration.image.size.width; - } + NSDictionary* attributes = @{ + NSFontAttributeName : PreferredFontForTextStyle(UIFontTextStyleSubheadline, + UIFontWeightSemibold, + kIdentityDiscMaxFontSize), + NSForegroundColorAttributeName : foregroundColor, + }; + buttonConfiguration.attributedTitle = [[NSAttributedString alloc] + initWithString:l10n_util::GetNSString(IDS_IOS_SIGNIN_BUTTON_TEXT) + attributes:attributes]; button.configuration = buttonConfiguration; } @@ -989,10 +949,7 @@ self.isSignedIn = NO; self.identityDiscAccessibilityLabel = - IsSignInButtonNoAvatarEnabled() - ? l10n_util::GetNSString(IDS_IOS_SIGN_IN_BUTTON_ACCESSIBILITY_LABEL) - : l10n_util::GetNSString( - IDS_IOS_IDENTITY_DISC_SIGNED_OUT_ACCESSIBILITY_LABEL); + l10n_util::GetNSString(IDS_IOS_SIGN_IN_BUTTON_ACCESSIBILITY_LABEL); // `self.identityDiscButton` should not be updated if the view has not been // created yet. @@ -1064,10 +1021,6 @@ - (UIColor*)defaultButtonBackgroundColor { return [UIColor colorWithDynamicProvider:^UIColor*(UITraitCollection* traits) { - if (!IsSignInButtonNoAvatarEnabled()) { - return [[UIColor colorNamed:@"fake_omnibox_solid_background_color"] - colorWithAlphaComponent:0.8]; - } return traits.userInterfaceStyle == UIUserInterfaceStyleDark ? [UIColor colorNamed:kTabGroupFaviconBackgroundColor] : [[UIColor colorNamed:kSolidWhiteColor] @@ -1116,8 +1069,7 @@ // Activates or deactivates the identity disc constraints based on sign-in // state. - (void)updateIdentityDiscConstraints { - BOOL showSignInButtonWithoutAvatar = - IsSignInButtonNoAvatarEnabled() && !self.isSignedIn; + BOOL showSignInButtonWithoutAvatar = !self.isSignedIn; CGFloat dimension = ntp_home::kIdentityAvatarDimension + kMarginMultiplier * ntp_home::kHeaderIconMargin;
diff --git a/ios/chrome/browser/ntp/ui_bundled/new_tab_page_header_view_controller_unittest.mm b/ios/chrome/browser/ntp/ui_bundled/new_tab_page_header_view_controller_unittest.mm index 2c0af3e..b70842b 100644 --- a/ios/chrome/browser/ntp/ui_bundled/new_tab_page_header_view_controller_unittest.mm +++ b/ios/chrome/browser/ntp/ui_bundled/new_tab_page_header_view_controller_unittest.mm
@@ -40,8 +40,6 @@ // Tests the header view when the user is signed out. TEST_F(NewTabPageHeaderViewControllerUnitTest, TestSignedOut) { - base::test::ScopedFeatureList feature_list(kSignInButtonNoAvatar); - [view_controller_ loadViewIfNeeded]; EXPECT_NE(nil, view_controller_.identityDiscButton);
diff --git a/ios/chrome/browser/overlays/ui_bundled/infobar_banner/passwords/password_infobar_banner_overlay_mediator.mm b/ios/chrome/browser/overlays/ui_bundled/infobar_banner/passwords/password_infobar_banner_overlay_mediator.mm index 322bbdc..6b71f00 100644 --- a/ios/chrome/browser/overlays/ui_bundled/infobar_banner/passwords/password_infobar_banner_overlay_mediator.mm +++ b/ios/chrome/browser/overlays/ui_bundled/infobar_banner/passwords/password_infobar_banner_overlay_mediator.mm
@@ -90,11 +90,9 @@ [super finishDismissal]; - // Check if the feature is enabled before showing the promo - if (IsNonModalSignInPromoEnabled()) { - [self.nonModalSignInPromoHandler - showNonModalSignInPromoWithType:SignInPromoType::kPassword]; - } + // Shows the promo. + [self.nonModalSignInPromoHandler + showNonModalSignInPromoWithType:SignInPromoType::kPassword]; } #pragma mark - Private
diff --git a/ios/chrome/browser/save_to_drive/ui_bundled/BUILD.gn b/ios/chrome/browser/save_to_drive/ui_bundled/BUILD.gn index a2620aa9..5889ded 100644 --- a/ios/chrome/browser/save_to_drive/ui_bundled/BUILD.gn +++ b/ios/chrome/browser/save_to_drive/ui_bundled/BUILD.gn
@@ -26,7 +26,6 @@ "//ios/chrome/browser/drive/model:drive_service", "//ios/chrome/browser/drive/model:drive_service_factory", "//ios/chrome/browser/drive/model:drive_tab_helper", - "//ios/chrome/browser/drive/model:manage_storage_url_util", "//ios/chrome/browser/drive/model:metrics", "//ios/chrome/browser/shared/coordinator/chrome_coordinator", "//ios/chrome/browser/shared/model/browser",
diff --git a/ios/chrome/browser/save_to_drive/ui_bundled/save_to_drive_coordinator.mm b/ios/chrome/browser/save_to_drive/ui_bundled/save_to_drive_coordinator.mm index b343dd1..2b9feae 100644 --- a/ios/chrome/browser/save_to_drive/ui_bundled/save_to_drive_coordinator.mm +++ b/ios/chrome/browser/save_to_drive/ui_bundled/save_to_drive_coordinator.mm
@@ -16,7 +16,6 @@ #import "ios/chrome/browser/download/model/download_manager_tab_helper.h" #import "ios/chrome/browser/drive/model/drive_metrics.h" #import "ios/chrome/browser/drive/model/drive_service_factory.h" -#import "ios/chrome/browser/drive/model/manage_storage_url_util.h" #import "ios/chrome/browser/google_one/shared/google_one_entry_point.h" #import "ios/chrome/browser/save_to_drive/ui_bundled/file_destination_picker_view_controller.h" #import "ios/chrome/browser/save_to_drive/ui_bundled/save_to_drive_mediator.h" @@ -230,24 +229,12 @@ } [_mediator willShowManageStorage]; CommandDispatcher* dispatcher = self.browser->GetCommandDispatcher(); - if (base::FeatureList::IsEnabled(kIOSManageAccountStorage)) { - id<GoogleOneCommands> googleOneHandler = - HandlerForProtocol(dispatcher, GoogleOneCommands); - [googleOneHandler - showGoogleOneForIdentity:identity - entryPoint:GoogleOneEntryPoint::kSaveToDriveAlert - baseViewController:_accountPickerCoordinator.viewController]; - return; - } - // The uploading identity's user email is used to switch to the uploading - // account before loading the "Manage Storage" web page. - GURL manageStorageURL = GenerateManageDriveStorageUrl( - base::SysNSStringToUTF8(identity.userEmail)); - OpenNewTabCommand* newTabCommand = - [OpenNewTabCommand commandWithURLFromChrome:manageStorageURL]; - id<ApplicationCommands> applicationHandler = - HandlerForProtocol(dispatcher, ApplicationCommands); - [applicationHandler openURLInNewTab:newTabCommand]; + id<GoogleOneCommands> googleOneHandler = + HandlerForProtocol(dispatcher, GoogleOneCommands); + [googleOneHandler + showGoogleOneForIdentity:identity + entryPoint:GoogleOneEntryPoint::kSaveToDriveAlert + baseViewController:_accountPickerCoordinator.viewController]; } #pragma mark - AccountPickerCommands
diff --git a/ios/chrome/browser/save_to_drive/ui_bundled/save_to_drive_egtest.mm b/ios/chrome/browser/save_to_drive/ui_bundled/save_to_drive_egtest.mm index bbdef79d..301c8f9 100644 --- a/ios/chrome/browser/save_to_drive/ui_bundled/save_to_drive_egtest.mm +++ b/ios/chrome/browser/save_to_drive/ui_bundled/save_to_drive_egtest.mm
@@ -164,16 +164,6 @@ "--%s=%s", commandLineSwitch.c_str(), commandLineValue.c_str())); } if ([self isRunningTest:@selector(testDriveFullStorage)]) { - configuration.features_disabled.push_back(kIOSManageAccountStorage); - const std::string commandLineSwitch = - std::string(kTestDriveFileUploaderCommandLineSwitch); - const std::string commandLineValue = - std::string(kTestDriveFileUploaderCommandLineSwitchFullStorage); - configuration.additional_args.push_back(base::StringPrintf( - "--%s=%s", commandLineSwitch.c_str(), commandLineValue.c_str())); - } - if ([self isRunningTest:@selector(testDriveFullStorageG1)]) { - configuration.features_enabled.push_back(kIOSManageAccountStorage); const std::string commandLineSwitch = std::string(kTestDriveFileUploaderCommandLineSwitch); const std::string commandLineValue = @@ -308,44 +298,9 @@ kWaitForDownloadTimeout]; } -// Tests that if the storage is full, an alert is displayed and user can open a -// tab to manage their storage. -- (void)testDriveFullStorage { - // Sign-in. - FakeSystemIdentity* fakeIdentity = [FakeSystemIdentity fakeIdentity1]; - [SigninEarlGrey signinWithFakeIdentity:fakeIdentity]; - // Load a page with a download button and tap the download button. - [ChromeEarlGrey loadURL:self.testServer->GetURL("/")]; - [ChromeEarlGrey waitForWebStateContainingText:"Download"]; - [ChromeEarlGrey tapWebStateElementWithID:@"download"]; - // Check that the "Drive" button is presented and tap it. - [ChromeEarlGrey waitForUIElementToAppearWithMatcher:SaveEllipsisButton()]; - [[EarlGrey selectElementWithMatcher:SaveEllipsisButton()] - performAction:grey_tap()]; - // Wait for the account picker to appear, select "Drive" and tap "Save". - [ChromeEarlGrey waitForUIElementToAppearWithMatcher:AccountPicker()]; - [ChromeEarlGrey - waitForUIElementToAppearWithMatcher:FileDestinationDriveButton()]; - [[EarlGrey selectElementWithMatcher:FileDestinationDriveButton()] - performAction:grey_tap()]; - [[EarlGrey selectElementWithMatcher:AccountPickerPrimaryButton()] - performAction:grey_tap()]; - - // Wait for the alert to appear and tap it. - [ChromeEarlGrey waitForUIElementToAppearWithMatcher:ManageStorageButton()]; - [[EarlGrey selectElementWithMatcher:ManageStorageButton()] - performAction:grey_tap()]; - - // Wait for the account picker to disappear and a new tab to be opened. - // Note: this will open an external URL, so just ignore the result as soon - // as the tab is created. - [ChromeEarlGrey waitForUIElementToDisappearWithMatcher:AccountPicker()]; - [ChromeEarlGrey waitForMainTabCount:2]; -} - // Tests that if the storage is full, an alert is displayed and user can open G1 // settings to manage their storage. -- (void)testDriveFullStorageG1 { +- (void)testDriveFullStorage { [GoogleOneAppInterface overrideGoogleOneController]; // Sign-in. FakeSystemIdentity* fakeIdentity = [FakeSystemIdentity fakeIdentity1];
diff --git a/ios/chrome/browser/save_to_photos/ui_bundled/BUILD.gn b/ios/chrome/browser/save_to_photos/ui_bundled/BUILD.gn index 845b55e..4f65207 100644 --- a/ios/chrome/browser/save_to_photos/ui_bundled/BUILD.gn +++ b/ios/chrome/browser/save_to_photos/ui_bundled/BUILD.gn
@@ -21,7 +21,6 @@ "//ios/chrome/browser/account_picker/ui_bundled:account_picker_logger", "//ios/chrome/browser/authentication/ui_bundled/signin:constants", "//ios/chrome/browser/authentication/ui_bundled/signin:signin_headers", - "//ios/chrome/browser/drive/model:manage_storage_url_util", "//ios/chrome/browser/photos/model", "//ios/chrome/browser/photos/model:metrics", "//ios/chrome/browser/photos/model:photos_service_factory",
diff --git a/ios/chrome/browser/save_to_photos/ui_bundled/save_to_photos_mediator.mm b/ios/chrome/browser/save_to_photos/ui_bundled/save_to_photos_mediator.mm index 2a293d6..41249e8 100644 --- a/ios/chrome/browser/save_to_photos/ui_bundled/save_to_photos_mediator.mm +++ b/ios/chrome/browser/save_to_photos/ui_bundled/save_to_photos_mediator.mm
@@ -19,7 +19,6 @@ #import "components/signin/public/identity_manager/identity_manager.h" #import "components/strings/grit/components_strings.h" #import "ios/chrome/browser/account_picker/ui_bundled/account_picker_configuration.h" -#import "ios/chrome/browser/drive/model/manage_storage_url_util.h" #import "ios/chrome/browser/google_one/shared/google_one_entry_point.h" #import "ios/chrome/browser/photos/model/photos_metrics.h" #import "ios/chrome/browser/photos/model/photos_service.h" @@ -246,21 +245,10 @@ base::RecordAction( base::UserMetricsAction("MobileSaveToPhotosManageStorage")); - if (base::FeatureList::IsEnabled(kIOSManageAccountStorage)) { - // At this point nothing should be presented. - [_googleOneHandler - showGoogleOneForIdentity:identity - entryPoint:GoogleOneEntryPoint::kSaveToPhotosAlert - baseViewController:nil]; - } else { - // The uploading identity's user email is used to switch to the uploading - // account before loading the "Manage Storage" web page. - GURL manageStorageURL = GenerateManageDriveStorageUrl( - base::SysNSStringToUTF8(identity.userEmail)); - OpenNewTabCommand* newTabCommand = - [OpenNewTabCommand commandWithURLFromChrome:manageStorageURL]; - [_applicationHandler openURLInNewTab:newTabCommand]; - } + [_googleOneHandler + showGoogleOneForIdentity:identity + entryPoint:GoogleOneEntryPoint::kSaveToPhotosAlert + baseViewController:nil]; base::UmaHistogramEnumeration( kSaveToPhotosActionsHistogram, SaveToPhotosActions::kFailureOutOfStorageDidManageStorage);
diff --git a/ios/chrome/browser/settings/ui_bundled/cells/BUILD.gn b/ios/chrome/browser/settings/ui_bundled/cells/BUILD.gn index e2da4774..34205e3 100644 --- a/ios/chrome/browser/settings/ui_bundled/cells/BUILD.gn +++ b/ios/chrome/browser/settings/ui_bundled/cells/BUILD.gn
@@ -16,8 +16,6 @@ "passphrase_error_item.mm", "safe_browsing_header_item.h", "safe_browsing_header_item.mm", - "settings_check_cell.h", - "settings_check_cell.mm", "settings_check_item.h", "settings_check_item.mm", "settings_image_detail_text_item.h",
diff --git a/ios/chrome/browser/settings/ui_bundled/cells/settings_check_cell.h b/ios/chrome/browser/settings/ui_bundled/cells/settings_check_cell.h deleted file mode 100644 index f8a0802..0000000 --- a/ios/chrome/browser/settings/ui_bundled/cells/settings_check_cell.h +++ /dev/null
@@ -1,60 +0,0 @@ -// Copyright 2020 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef IOS_CHROME_BROWSER_SETTINGS_UI_BUNDLED_CELLS_SETTINGS_CHECK_CELL_H_ -#define IOS_CHROME_BROWSER_SETTINGS_UI_BUNDLED_CELLS_SETTINGS_CHECK_CELL_H_ - -#import <UIKit/UIKit.h> - -#import "ios/chrome/browser/shared/ui/table_view/cells/legacy_table_view_cell.h" - -// Cell representation for SettingsCheckItem. -// +---------------------------------------------------------+ -// | +--------+ +---------+ | -// | | | One line title |trailing | | -// | | leading| |image | | -// | | image | Multiline detail text |spinner | | -// | | | Multiline detail text |or button| | -// | +--------+ +---------+ | -// +---------------------------------------------------------+ -@interface SettingsCheckCell : LegacyTableViewCell - -// Button which is used as an anchor to show popover with additional -// information. -@property(nonatomic, readonly, strong) UIButton* infoButton; - -// Shows `activityIndicator` and starts animation. It will hide `imageView` if -// it was shown. -- (void)showActivityIndicator; - -// Hides `activityIndicator` and stops animation. -- (void)hideActivityIndicator; - -// Sets the `trailingImage` and tint `trailingColor` for it that should be -// displayed at the trailing edge of the cell. If set to nil, `trailingImage` -// will be hidden, otherwise `imageView` will be shown and `activityIndicator` -// will be hidden. -- (void)setTrailingImage:(UIImage*)trailingImage - withTintColor:(UIColor*)tintColor; - -// Sets the `image` that should be displayed at the leading edge of the cell -// with a `tintColor`. If set to nil, the icon will be hidden and the rest of -// the content will expand to fill the full width of the cell. The image view -// will be configured with a `backgroundColor` and a `cornerRadius`. -- (void)setLeadingIconImage:(UIImage*)image - tintColor:(UIColor*)tintColor - backgroundColor:(UIColor*)backgroundColor - cornerRadius:(CGFloat)cornerRadius; - -// Shows/Hides `infoButton`. -- (void)setInfoButtonHidden:(BOOL)hidden; - -// If `enabled`, `infoButton` image's tint color is set to blue otherwise to -// [UIColor colorNamed:kTextSecondaryColor]. Also, enable/disable the -// `infoButton` based on `enabled`. -- (void)setInfoButtonEnabled:(BOOL)enabled; - -@end - -#endif // IOS_CHROME_BROWSER_SETTINGS_UI_BUNDLED_CELLS_SETTINGS_CHECK_CELL_H_
diff --git a/ios/chrome/browser/settings/ui_bundled/cells/settings_check_cell.mm b/ios/chrome/browser/settings/ui_bundled/cells/settings_check_cell.mm deleted file mode 100644 index a5d076e72..0000000 --- a/ios/chrome/browser/settings/ui_bundled/cells/settings_check_cell.mm +++ /dev/null
@@ -1,364 +0,0 @@ -// Copyright 2020 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import "ios/chrome/browser/settings/ui_bundled/cells/settings_check_cell.h" - -#import "base/check.h" -#import "base/ios/ios_util.h" -#import "ios/chrome/browser/shared/ui/symbols/symbols.h" -#import "ios/chrome/browser/shared/ui/util/uikit_ui_util.h" -#import "ios/chrome/common/ui/colors/semantic_color_names.h" -#import "ios/chrome/common/ui/table_view/table_view_cells_constants.h" -#import "ios/chrome/common/ui/util/constraints_ui_util.h" -#import "ios/chrome/grit/ios_strings.h" -#import "ui/base/l10n/l10n_util.h" - -namespace { -const CGFloat kSymbolSize = 22; -} - -@interface SettingsCheckCell () - -// The image view for the trailing image. -@property(nonatomic, strong) UIImageView* trailingImageView; - -// UIActivityIndicatorView spinning while check is running. -@property(nonatomic, readonly, strong) - UIActivityIndicatorView* activityIndicator; - -// Image view for the leading image. -@property(nonatomic, strong) UIImageView* leadingImageView; - -// Constraint that is used to define trailing text constraint without -// `trailingImageView` `activityIndicator` and `infoButton`. -@property(nonatomic, strong) - NSLayoutConstraint* textNoTrailingContentsConstraint; - -// Constraint that is used to define trailing text constraint with either -// `trailingImageView` or `activityIndicator` or `infoButton` showing. -@property(nonatomic, strong) - NSLayoutConstraint* textWithTrailingContentsConstraint; - -// Constraint used for leading text constraint without `leadingImage`. -@property(nonatomic, strong) NSLayoutConstraint* textNoLeadingImageConstraint; - -// Constraint used for leading text constraint with `leadingImage` showing. -@property(nonatomic, strong) NSLayoutConstraint* textWithLeadingImageConstraint; - -@end - -@implementation SettingsCheckCell { - UIView* _leadingIconBackground; -} - -@synthesize textLabel = _textLabel; -@synthesize detailTextLabel = _detailTextLabel; - -- (instancetype)initWithStyle:(UITableViewCellStyle)style - reuseIdentifier:(NSString*)reuseIdentifier { - self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; - if (self) { - UIView* contentView = self.contentView; - - // Attributes of row contents in order or appearance (if present). - - // `_leadingImageView` attributes - _leadingIconBackground = [[UIView alloc] init]; - _leadingIconBackground.translatesAutoresizingMaskIntoConstraints = NO; - _leadingIconBackground.hidden = NO; - [contentView addSubview:_leadingIconBackground]; - - _leadingImageView = [[UIImageView alloc] init]; - _leadingImageView.translatesAutoresizingMaskIntoConstraints = NO; - _leadingImageView.tintColor = [UIColor colorNamed:kTextPrimaryColor]; - _leadingImageView.contentMode = UIViewContentModeCenter; - [contentView addSubview:_leadingImageView]; - - AddSameCenterConstraints(_leadingImageView, _leadingIconBackground); - - // Text attributes. - // `_textLabel` attributes. - _textLabel = [[UILabel alloc] init]; - _textLabel.translatesAutoresizingMaskIntoConstraints = NO; - _textLabel.font = [UIFont preferredFontForTextStyle:UIFontTextStyleBody]; - _textLabel.adjustsFontForContentSizeCategory = YES; - _textLabel.textColor = [UIColor colorNamed:kTextPrimaryColor]; - [contentView addSubview:_textLabel]; - // `detailText` attributes. - _detailTextLabel = [[UILabel alloc] init]; - _detailTextLabel.numberOfLines = 0; - _detailTextLabel.translatesAutoresizingMaskIntoConstraints = NO; - _detailTextLabel.font = - [UIFont preferredFontForTextStyle:UIFontTextStyleFootnote]; - _detailTextLabel.adjustsFontForContentSizeCategory = YES; - _detailTextLabel.textColor = [UIColor colorNamed:kTextSecondaryColor]; - [contentView addSubview:_detailTextLabel]; - - // Only `_trailingImageView` or `_activityIndicator` or `_infoButton` is - // shown, not all at once. `trailingImage` attributes. - _trailingImageView = [[UIImageView alloc] init]; - _trailingImageView.translatesAutoresizingMaskIntoConstraints = NO; - _trailingImageView.tintColor = [UIColor colorNamed:kTextPrimaryColor]; - _trailingImageView.hidden = YES; - [contentView addSubview:_trailingImageView]; - // `activityIndictor` attributes. - // Creates default activity indicator. Color depends on appearance. - _activityIndicator = [[UIActivityIndicatorView alloc] init]; - _activityIndicator.translatesAutoresizingMaskIntoConstraints = NO; - _activityIndicator.hidden = YES; - [contentView addSubview:_activityIndicator]; - // `_infoButton` attribues. - _infoButton = [UIButton buttonWithType:UIButtonTypeSystem]; - _infoButton.translatesAutoresizingMaskIntoConstraints = NO; - _infoButton.hidden = YES; - UIImage* image = DefaultSymbolWithPointSize(kInfoCircleSymbol, kSymbolSize); - [_infoButton setImage:image forState:UIControlStateNormal]; - [_infoButton setTintColor:[UIColor colorNamed:kBlueColor]]; - [contentView addSubview:_infoButton]; - - // Constraints. - UILayoutGuide* textLayoutGuide = [[UILayoutGuide alloc] init]; - [self.contentView addLayoutGuide:textLayoutGuide]; - - _textNoTrailingContentsConstraint = [textLayoutGuide.trailingAnchor - constraintEqualToAnchor:contentView.trailingAnchor - constant:-kTableViewHorizontalSpacing]; - - _textWithTrailingContentsConstraint = [textLayoutGuide.trailingAnchor - constraintEqualToAnchor:_trailingImageView.leadingAnchor - constant:-kTableViewImagePadding]; - - _textNoLeadingImageConstraint = [textLayoutGuide.leadingAnchor - constraintEqualToAnchor:contentView.leadingAnchor - constant:kTableViewHorizontalSpacing]; - - _textWithLeadingImageConstraint = [textLayoutGuide.leadingAnchor - constraintEqualToAnchor:_leadingIconBackground.trailingAnchor - constant:kTableViewImagePadding]; - - NSLayoutConstraint* heightConstraint = [self.contentView.heightAnchor - constraintGreaterThanOrEqualToConstant:kChromeTableViewCellHeight]; - - // Set up the constraints assuming that the icon image and activity - // indicator are hidden. - [NSLayoutConstraint activateConstraints:@[ - heightConstraint, - _textNoTrailingContentsConstraint, - - // Constraints for `_trailingImageView` (same position as - // `_activityIndictor`). - [_trailingImageView.trailingAnchor - constraintEqualToAnchor:self.contentView.trailingAnchor - constant:-kTableViewHorizontalSpacing], - [_trailingImageView.widthAnchor - constraintEqualToConstant:kTableViewIconImageSize], - [_trailingImageView.heightAnchor - constraintEqualToAnchor:_trailingImageView.widthAnchor], - [_trailingImageView.centerYAnchor - constraintEqualToAnchor:textLayoutGuide.centerYAnchor], - [_trailingImageView.leadingAnchor - constraintEqualToAnchor:_activityIndicator.leadingAnchor], - - // Constraints for `_infoButton` (same position as - // `_trailingImageView`). - [_infoButton.trailingAnchor - constraintEqualToAnchor:self.contentView.trailingAnchor - constant:-kTableViewHorizontalSpacing], - [_infoButton.widthAnchor - constraintEqualToConstant:kTableViewIconImageSize], - [_infoButton.heightAnchor - constraintEqualToAnchor:_infoButton.widthAnchor], - [_infoButton.centerYAnchor - constraintEqualToAnchor:textLayoutGuide.centerYAnchor], - [_infoButton.leadingAnchor - constraintEqualToAnchor:_activityIndicator.leadingAnchor], - - // Constraints for `_activityIndictor` (same position as - // `_trailingImageView`). - [_activityIndicator.trailingAnchor - constraintEqualToAnchor:self.contentView.trailingAnchor - constant:-kTableViewHorizontalSpacing], - [_activityIndicator.widthAnchor - constraintEqualToConstant:kTableViewIconImageSize], - [_activityIndicator.heightAnchor - constraintEqualToAnchor:_activityIndicator.widthAnchor], - [_activityIndicator.centerYAnchor - constraintEqualToAnchor:textLayoutGuide.centerYAnchor], - - // Constraints for `_leadingIconBackground`. - [_leadingIconBackground.leadingAnchor - constraintEqualToAnchor:self.contentView.leadingAnchor - constant:kTableViewHorizontalSpacing], - [_leadingIconBackground.widthAnchor - constraintEqualToConstant:kTableViewIconImageSize], - [_leadingIconBackground.heightAnchor - constraintEqualToAnchor:_leadingIconBackground.widthAnchor], - [_leadingIconBackground.centerYAnchor - constraintEqualToAnchor:textLayoutGuide.centerYAnchor], - - // Constraints for `_textLabel` and `_detailTextLabel`. - [textLayoutGuide.centerYAnchor - constraintEqualToAnchor:self.contentView.centerYAnchor], - [textLayoutGuide.leadingAnchor - constraintEqualToAnchor:_textLabel.leadingAnchor], - [textLayoutGuide.leadingAnchor - constraintEqualToAnchor:_detailTextLabel.leadingAnchor], - [textLayoutGuide.trailingAnchor - constraintEqualToAnchor:_textLabel.trailingAnchor], - [textLayoutGuide.trailingAnchor - constraintEqualToAnchor:_detailTextLabel.trailingAnchor], - [textLayoutGuide.topAnchor constraintEqualToAnchor:_textLabel.topAnchor], - [textLayoutGuide.bottomAnchor - constraintEqualToAnchor:_detailTextLabel.bottomAnchor], - [_textLabel.bottomAnchor - constraintEqualToAnchor:_detailTextLabel.topAnchor], - ]]; - // Make sure there are top and bottom margins of at least `margin`. - AddOptionalVerticalPadding(self.contentView, textLayoutGuide, - kTableViewTwoLabelsCellVerticalSpacing); - } - return self; -} - -- (void)showActivityIndicator { - if (!self.activityIndicator.hidden) { - return; - } - self.trailingImageView.hidden = YES; - self.infoButton.hidden = YES; - self.activityIndicator.hidden = NO; - [self.activityIndicator startAnimating]; - [self updateTrailingImageTextConstraints]; -} - -- (void)hideActivityIndicator { - if (self.activityIndicator.hidden) { - return; - } - - [self.activityIndicator stopAnimating]; - self.activityIndicator.hidden = YES; - [self updateTrailingImageTextConstraints]; -} - -- (void)setTrailingImage:(UIImage*)trailingImage - withTintColor:(UIColor*)trailingImageColor { - self.trailingImageView.tintColor = trailingImageColor; - BOOL hidden = !trailingImage; - self.trailingImageView.image = trailingImage; - if (hidden == self.trailingImageView.hidden) { - return; - } - self.trailingImageView.hidden = hidden; - if (!hidden) { - self.activityIndicator.hidden = YES; - self.infoButton.hidden = YES; - } - [self updateTrailingImageTextConstraints]; -} - -- (void)setLeadingIconImage:(UIImage*)image - tintColor:(UIColor*)tintColor - backgroundColor:(UIColor*)backgroundColor - cornerRadius:(CGFloat)cornerRadius { - self.leadingImageView.image = image; - self.leadingImageView.tintColor = tintColor; - - _leadingIconBackground.backgroundColor = backgroundColor; - _leadingIconBackground.layer.cornerRadius = cornerRadius; - - BOOL hidden = !image; - _leadingIconBackground.hidden = hidden; - // Update the leading text constraint based on `image` being provided. - if (hidden) { - _textWithLeadingImageConstraint.active = NO; - _textNoLeadingImageConstraint.active = YES; - } else { - _textNoLeadingImageConstraint.active = NO; - _textWithLeadingImageConstraint.active = YES; - } -} - -- (void)setInfoButtonHidden:(BOOL)hidden { - if (hidden == self.infoButton.hidden) { - return; - } - - self.infoButton.hidden = hidden; - if (hidden) { - self.accessibilityCustomActions = nil; - } else { - self.accessibilityCustomActions = [self createAccessibilityActions]; - self.trailingImageView.hidden = YES; - self.activityIndicator.hidden = YES; - } - [self updateTrailingImageTextConstraints]; -} - -- (void)setInfoButtonEnabled:(BOOL)enabled { - self.infoButton.enabled = enabled; - if (enabled) { - [self.infoButton setTintColor:[UIColor colorNamed:kBlueColor]]; - } else { - [self.infoButton setTintColor:[UIColor colorNamed:kTextSecondaryColor]]; - } -} - -#pragma mark - Private Methods - -// Updates the constraints around the trailing image for when `trailingImage` or -// `activityIndicator` or `infoButton` is shown or hidden. -- (void)updateTrailingImageTextConstraints { - // Active proper `textLayoutGuide` trailing constraint to show - // `trailingImageView` or `activityIndicator` or `infoButton`. - if (self.activityIndicator.hidden && self.trailingImageView.hidden && - self.infoButton.hidden) { - _textWithTrailingContentsConstraint.active = NO; - _textNoTrailingContentsConstraint.active = YES; - } else { - _textNoTrailingContentsConstraint.active = NO; - _textWithTrailingContentsConstraint.active = YES; - } -} - -#pragma mark - UITableViewCell - -- (void)prepareForReuse { - [super prepareForReuse]; - - self.textLabel.text = nil; - self.accessibilityCustomActions = nil; - [self setInfoButtonEnabled:YES]; - [self.infoButton removeTarget:nil - action:nil - forControlEvents:UIControlEventAllEvents]; - self.detailTextLabel.text = nil; - self.accessibilityTraits = UIAccessibilityTraitNone; - [self setTrailingImage:nil withTintColor:nil]; - [self setLeadingIconImage:nil - tintColor:nil - backgroundColor:nil - cornerRadius:0]; - [self hideActivityIndicator]; -} - -#pragma mark - Accessibility - -// Creates custom accessibility actions. -- (NSArray*)createAccessibilityActions { - UIAccessibilityCustomAction* tapButtonAction = - [[UIAccessibilityCustomAction alloc] - initWithName:l10n_util::GetNSString( - IDS_IOS_INFO_BUTTON_ACCESSIBILITY_HINT) - target:self - selector:@selector(handleInfoButtonTapForCell)]; - return @[ tapButtonAction ]; -} - -// Handles accessibility action for tapping outside the info button. -- (void)handleInfoButtonTapForCell { - [self.infoButton sendActionsForControlEvents:UIControlEventTouchUpInside]; -} - -@end
diff --git a/ios/chrome/browser/settings/ui_bundled/cells/settings_check_item.h b/ios/chrome/browser/settings/ui_bundled/cells/settings_check_item.h index 287ce6c..20c5472 100644 --- a/ios/chrome/browser/settings/ui_bundled/cells/settings_check_item.h +++ b/ios/chrome/browser/settings/ui_bundled/cells/settings_check_item.h
@@ -16,7 +16,7 @@ kSevereWarning, // There is a high priority warning (red icon). }; -// SettingsCheckItem is a model class that uses SettingsCheckCell. +// SettingsCheckItem is a model class to configure a cell doing a check. @interface SettingsCheckItem : TableViewItem // The text to display. @@ -36,9 +36,6 @@ // The background color of the icon. @property(nonatomic, strong) UIColor* leadingIconBackgroundColor; -// The corner radius of the UIImage view. -@property(nonatomic, assign) CGFloat leadingIconCornerRadius; - // The image to display on the trailing side of `text` (required). If this image // should be tinted to match the text color (e.g. in dark mode), the provided // image should have rendering mode UIImageRenderingModeAlwaysTemplate. Don't @@ -51,11 +48,11 @@ // Controls visibility of `activityIndicator`, if set false `trailingImage` or // `infoButton` will be hidden and `activityIndicator` will be shown. This -// property has the highest priority. +// property has the highest priority. Default is NO. @property(nonatomic, assign, getter=isIndicatorHidden) BOOL indicatorHidden; // Controls visibility of `infoButton`. This property has no effect in case -// `trailingImage` is provided or `indicatorHidden` is false. +// `trailingImage` is provided or `indicatorHidden` is false. Default is NO. @property(nonatomic, assign, getter=isInfoButtonHidden) BOOL infoButtonHidden; // The properties to configure the infoButton action. @@ -64,7 +61,7 @@ @property(nonatomic, assign) NSInteger infoButtonTag; // Disabled cell are automatically drawn with dimmed text and without -// `trailingImage` or `activityIndicator`. +// `trailingImage` or `activityIndicator`. Default is NO. @property(nonatomic, assign, getter=isEnabled) BOOL enabled; // The WarningState of the item.
diff --git a/ios/chrome/browser/settings/ui_bundled/cells/settings_check_item.mm b/ios/chrome/browser/settings/ui_bundled/cells/settings_check_item.mm index 773958e..46669c7c 100644 --- a/ios/chrome/browser/settings/ui_bundled/cells/settings_check_item.mm +++ b/ios/chrome/browser/settings/ui_bundled/cells/settings_check_item.mm
@@ -4,9 +4,14 @@ #import "ios/chrome/browser/settings/ui_bundled/cells/settings_check_item.h" -#import "ios/chrome/browser/settings/ui_bundled/cells/settings_check_cell.h" #import "ios/chrome/browser/shared/ui/symbols/symbols.h" +#import "ios/chrome/browser/shared/ui/table_view/content_configuration/activity_indicator_content_configuration.h" +#import "ios/chrome/browser/shared/ui/table_view/content_configuration/colorful_symbol_content_configuration.h" +#import "ios/chrome/browser/shared/ui/table_view/content_configuration/image_content_configuration.h" +#import "ios/chrome/browser/shared/ui/table_view/content_configuration/info_button_content_configuration.h" +#import "ios/chrome/browser/shared/ui/table_view/content_configuration/table_view_cell_content_configuration.h" #import "ios/chrome/common/ui/colors/semantic_color_names.h" +#import "ios/chrome/common/ui/table_view/table_view_cells_constants.h" namespace { @@ -20,42 +25,74 @@ - (instancetype)initWithType:(NSInteger)type { self = [super initWithType:type]; if (self) { - self.cellClass = [SettingsCheckCell class]; + self.cellClass = [LegacyTableViewCell class]; } return self; } #pragma mark - TableViewItem -- (void)configureCell:(SettingsCheckCell*)cell +- (void)configureCell:(LegacyTableViewCell*)cell withStyler:(ChromeTableViewStyler*)styler { [super configureCell:cell withStyler:styler]; - cell.textLabel.text = self.text; - cell.detailTextLabel.text = self.detailText; - [cell setInfoButtonHidden:self.infoButtonHidden]; - [cell setInfoButtonEnabled:self.enabled]; - self.indicatorHidden ? [cell hideActivityIndicator] - : [cell showActivityIndicator]; + + TableViewCellContentConfiguration* configuration = + [[TableViewCellContentConfiguration alloc] init]; + configuration.title = self.text; + configuration.titleNumberOfLines = 1; + configuration.subtitle = self.detailText; + configuration.textDisabled = !self.enabled; + + if (self.leadingIcon) { + ColorfulSymbolContentConfiguration* symbolConfiguration = + [[ColorfulSymbolContentConfiguration alloc] init]; + symbolConfiguration.symbolImage = self.leadingIcon; + symbolConfiguration.symbolTintColor = + self.enabled ? self.leadingIconTintColor + : [UIColor colorNamed:kTextSecondaryColor]; + symbolConfiguration.symbolBackgroundColor = self.leadingIconBackgroundColor; + + configuration.leadingConfiguration = symbolConfiguration; + } + + if (!self.indicatorHidden) { + ActivityIndicatorContentConfiguration* activityConfiguration = + [[ActivityIndicatorContentConfiguration alloc] init]; + + configuration.trailingConfiguration = activityConfiguration; + } else if (self.trailingImage) { + ImageContentConfiguration* imageConfiguration = + [[ImageContentConfiguration alloc] init]; + imageConfiguration.image = self.trailingImage; + imageConfiguration.imageTintColor = + self.enabled ? self.trailingImageTintColor + : [UIColor colorNamed:kTextSecondaryColor]; + imageConfiguration.imageSize = + CGSizeMake(kTableViewIconImageSize, kTableViewIconImageSize); + + configuration.trailingConfiguration = imageConfiguration; + } else if (!self.infoButtonHidden && self.infoButtonTarget) { + InfoButtonContentConfiguration* infoButtonConfiguration = + [[InfoButtonContentConfiguration alloc] init]; + infoButtonConfiguration.target = self.infoButtonTarget; + infoButtonConfiguration.selector = self.infoButtonSelector; + infoButtonConfiguration.tag = self.infoButtonTag; + infoButtonConfiguration.enabled = self.enabled; + + infoButtonConfiguration.selectedForVoiceOver = NO; + + configuration.trailingConfiguration = infoButtonConfiguration; + } + + cell.contentConfiguration = configuration; + + cell.isAccessibilityElement = YES; + if (self.enabled) { - [cell setLeadingIconImage:self.leadingIcon - tintColor:self.leadingIconTintColor - backgroundColor:self.leadingIconBackgroundColor - cornerRadius:self.leadingIconCornerRadius]; - [cell setTrailingImage:self.trailingImage - withTintColor:self.trailingImageTintColor]; - cell.textLabel.textColor = [UIColor colorNamed:kTextPrimaryColor]; cell.accessibilityTraits &= ~UIAccessibilityTraitNotEnabled; } else { - [cell setLeadingIconImage:self.leadingIcon - tintColor:[UIColor colorNamed:kTextSecondaryColor] - backgroundColor:self.leadingIconBackgroundColor - cornerRadius:self.leadingIconCornerRadius]; - [cell setTrailingImage:self.trailingImage - withTintColor:[UIColor colorNamed:kTextSecondaryColor]]; - cell.textLabel.textColor = [UIColor colorNamed:kTextSecondaryColor]; cell.accessibilityTraits |= UIAccessibilityTraitNotEnabled; } - cell.isAccessibilityElement = YES; if (self.detailText) { cell.accessibilityLabel = @@ -63,12 +100,12 @@ } else { cell.accessibilityLabel = self.text; } - if (self.infoButtonTarget) { - [cell.infoButton addTarget:self.infoButtonTarget - action:self.infoButtonSelector - forControlEvents:UIControlEventTouchUpInside]; - cell.infoButton.tag = self.infoButtonTag; - } +} + +- (LegacyTableViewCell*)cellForTableView:(UITableView*)tableView { + [TableViewCellContentConfiguration legacyRegisterCellForTableView:tableView]; + return + [TableViewCellContentConfiguration legacyDequeueTableViewCell:tableView]; } #pragma mark - Setters
diff --git a/ios/chrome/browser/settings/ui_bundled/cells/settings_check_item_unittest.mm b/ios/chrome/browser/settings/ui_bundled/cells/settings_check_item_unittest.mm index 94930be..558aff8 100644 --- a/ios/chrome/browser/settings/ui_bundled/cells/settings_check_item_unittest.mm +++ b/ios/chrome/browser/settings/ui_bundled/cells/settings_check_item_unittest.mm
@@ -5,7 +5,10 @@ #import "ios/chrome/browser/settings/ui_bundled/cells/settings_check_item.h" #import "base/apple/foundation_util.h" -#import "ios/chrome/browser/settings/ui_bundled/cells/settings_check_cell.h" +#import "ios/chrome/browser/shared/ui/table_view/cells/legacy_table_view_cell.h" +#import "ios/chrome/browser/shared/ui/table_view/content_configuration/activity_indicator_content_configuration.h" +#import "ios/chrome/browser/shared/ui/table_view/content_configuration/info_button_content_configuration.h" +#import "ios/chrome/browser/shared/ui/table_view/content_configuration/table_view_cell_content_configuration.h" #import "ios/chrome/browser/shared/ui/table_view/legacy_chrome_table_view_styler.h" #import "ios/chrome/common/ui/colors/semantic_color_names.h" #import "testing/gtest/include/gtest/gtest.h" @@ -29,16 +32,19 @@ item.detailText = detailText; id cell = [[[item cellClass] alloc] init]; - ASSERT_TRUE([cell isMemberOfClass:[SettingsCheckCell class]]); + ASSERT_TRUE([cell isMemberOfClass:[LegacyTableViewCell class]]); - SettingsCheckCell* CheckCell = - base::apple::ObjCCastStrict<SettingsCheckCell>(cell); - EXPECT_FALSE(CheckCell.textLabel.text); - EXPECT_FALSE(CheckCell.detailTextLabel.text); + LegacyTableViewCell* checkCell = + base::apple::ObjCCastStrict<LegacyTableViewCell>(cell); + EXPECT_FALSE(checkCell.contentConfiguration); [item configureCell:cell withStyler:[[ChromeTableViewStyler alloc] init]]; - EXPECT_NSEQ(text, CheckCell.textLabel.text); - EXPECT_NSEQ(detailText, CheckCell.detailTextLabel.text); + + TableViewCellContentConfiguration* contentConfiguration = + base::apple::ObjCCastStrict<TableViewCellContentConfiguration>( + checkCell.contentConfiguration); + EXPECT_NSEQ(text, contentConfiguration.title); + EXPECT_NSEQ(detailText, contentConfiguration.subtitle); } // Tests that cell is configured properly based on infoButtonHidden property of @@ -50,17 +56,29 @@ item.enabled = YES; item.indicatorHidden = YES; item.infoButtonHidden = NO; + // Target is required for the info button to be shown. + item.infoButtonTarget = [[NSObject alloc] init]; id cell = [[[item cellClass] alloc] init]; - SettingsCheckCell* CheckCell = - base::apple::ObjCCastStrict<SettingsCheckCell>(cell); + LegacyTableViewCell* checkCell = + base::apple::ObjCCastStrict<LegacyTableViewCell>(cell); [item configureCell:cell withStyler:[[ChromeTableViewStyler alloc] init]]; - EXPECT_FALSE(CheckCell.infoButton.hidden); + + TableViewCellContentConfiguration* contentConfiguration = + base::apple::ObjCCastStrict<TableViewCellContentConfiguration>( + checkCell.contentConfiguration); + EXPECT_TRUE([contentConfiguration.trailingConfiguration + isKindOfClass:[InfoButtonContentConfiguration class]]); item.infoButtonHidden = YES; [item configureCell:cell withStyler:[[ChromeTableViewStyler alloc] init]]; - EXPECT_TRUE(CheckCell.infoButton.hidden); + + contentConfiguration = + base::apple::ObjCCastStrict<TableViewCellContentConfiguration>( + checkCell.contentConfiguration); + EXPECT_FALSE([contentConfiguration.trailingConfiguration + isKindOfClass:[InfoButtonContentConfiguration class]]); } // Tests that infoButton won't be shown in case of a conflict. @@ -71,16 +89,23 @@ item.enabled = YES; item.indicatorHidden = NO; item.infoButtonHidden = NO; + // Target is required for the info button to be shown. + item.infoButtonTarget = [[NSObject alloc] init]; id cell = [[[item cellClass] alloc] init]; - SettingsCheckCell* CheckCell = - base::apple::ObjCCastStrict<SettingsCheckCell>(cell); + LegacyTableViewCell* checkCell = + base::apple::ObjCCastStrict<LegacyTableViewCell>(cell); [item configureCell:cell withStyler:[[ChromeTableViewStyler alloc] init]]; - EXPECT_TRUE(CheckCell.infoButton.hidden); + + TableViewCellContentConfiguration* contentConfiguration = + base::apple::ObjCCastStrict<TableViewCellContentConfiguration>( + checkCell.contentConfiguration); + EXPECT_TRUE([contentConfiguration.trailingConfiguration + isKindOfClass:[ActivityIndicatorContentConfiguration class]]); } -// Tests that infoButton would be greyed out when the item is not enabled. +// Tests that infoButton would be disabled when the item is not enabled. TEST_F(SettingsCheckItemTest, InfoButtonVisibilityWhenDisabled) { SettingsCheckItem* item = [[SettingsCheckItem alloc] initWithType:0]; item.text = @"Test Text"; @@ -88,15 +113,24 @@ item.enabled = NO; item.indicatorHidden = YES; item.infoButtonHidden = NO; + // Target is required for the info button to be shown. + item.infoButtonTarget = [[NSObject alloc] init]; id cell = [[[item cellClass] alloc] init]; - SettingsCheckCell* CheckCell = - base::apple::ObjCCastStrict<SettingsCheckCell>(cell); + LegacyTableViewCell* checkCell = + base::apple::ObjCCastStrict<LegacyTableViewCell>(cell); [item configureCell:cell withStyler:[[ChromeTableViewStyler alloc] init]]; - EXPECT_FALSE(CheckCell.infoButton.hidden); - EXPECT_NSEQ(CheckCell.infoButton.tintColor, - [UIColor colorNamed:kTextSecondaryColor]); + + TableViewCellContentConfiguration* contentConfiguration = + base::apple::ObjCCastStrict<TableViewCellContentConfiguration>( + checkCell.contentConfiguration); + EXPECT_TRUE([contentConfiguration.trailingConfiguration + isKindOfClass:[InfoButtonContentConfiguration class]]); + InfoButtonContentConfiguration* infoButtonConfiguration = + base::apple::ObjCCastStrict<InfoButtonContentConfiguration>( + contentConfiguration.trailingConfiguration); + EXPECT_FALSE(infoButtonConfiguration.enabled); } } // namespace
diff --git a/ios/chrome/browser/settings/ui_bundled/google_services/manage_sync_settings_mediator.mm b/ios/chrome/browser/settings/ui_bundled/google_services/manage_sync_settings_mediator.mm index cda232a..982737c 100644 --- a/ios/chrome/browser/settings/ui_bundled/google_services/manage_sync_settings_mediator.mm +++ b/ios/chrome/browser/settings/ui_bundled/google_services/manage_sync_settings_mediator.mm
@@ -499,16 +499,13 @@ [model addItem:item toSectionWithIdentifier:ManageAndSignOutSectionIdentifier]; - if (base::FeatureList::IsEnabled(kIOSManageAccountStorage)) { - // Manage account storage item. - item = [[TableViewTextItem alloc] initWithType:ManageAccountStorageType]; - item.text = - GetNSString(IDS_IOS_GOOGLE_ACCOUNT_SETTINGS_MANAGE_STORAGE_ITEM); - item.textColor = [UIColor colorNamed:kBlueColor]; - item.accessibilityTraits |= UIAccessibilityTraitButton; - [model addItem:item - toSectionWithIdentifier:ManageAndSignOutSectionIdentifier]; - } + // Manage account storage item. + item = [[TableViewTextItem alloc] initWithType:ManageAccountStorageType]; + item.text = GetNSString(IDS_IOS_GOOGLE_ACCOUNT_SETTINGS_MANAGE_STORAGE_ITEM); + item.textColor = [UIColor colorNamed:kBlueColor]; + item.accessibilityTraits |= UIAccessibilityTraitButton; + [model addItem:item + toSectionWithIdentifier:ManageAndSignOutSectionIdentifier]; // Manage accounts on this device item. item = [[TableViewTextItem alloc] initWithType:ManageAccountsItemType];
diff --git a/ios/chrome/browser/settings/ui_bundled/google_services/manage_sync_settings_mediator_unittest.mm b/ios/chrome/browser/settings/ui_bundled/google_services/manage_sync_settings_mediator_unittest.mm index 61ffc58..725e6d83 100644 --- a/ios/chrome/browser/settings/ui_bundled/google_services/manage_sync_settings_mediator_unittest.mm +++ b/ios/chrome/browser/settings/ui_bundled/google_services/manage_sync_settings_mediator_unittest.mm
@@ -159,7 +159,6 @@ // for a signed in account along with manage accounts items. TEST_F(ManageSyncSettingsMediatorTest, CheckSignOutSectionItemsForSignedInAccount) { - feature_list_.InitAndDisableFeature(kIOSManageAccountStorage); CreateManageSyncSettingsMediator(); sync_service_->SetSignedIn(signin::ConsentLevel::kSignin); @@ -173,33 +172,37 @@ ASSERT_GE([items count], 2u); EXPECT_EQ(ManageGoogleAccountItemType, base::apple::ObjCCastStrict<TableViewItem>(items[0]).type); - EXPECT_EQ(ManageAccountsItemType, + EXPECT_EQ(ManageAccountStorageType, base::apple::ObjCCastStrict<TableViewItem>(items[1]).type); + EXPECT_EQ(ManageAccountsItemType, + base::apple::ObjCCastStrict<TableViewItem>(items[2]).type); EXPECT_NSEQ(l10n_util::GetNSString( IDS_IOS_GOOGLE_ACCOUNT_SETTINGS_MANAGE_GOOGLE_ACCOUNT_ITEM), base::apple::ObjCCastStrict<TableViewTextItem>(items[0]).text); EXPECT_NSEQ(l10n_util::GetNSString( - IDS_IOS_GOOGLE_ACCOUNT_SETTINGS_MANAGE_ACCOUNTS_ITEM), + IDS_IOS_GOOGLE_ACCOUNT_SETTINGS_MANAGE_STORAGE_ITEM), base::apple::ObjCCastStrict<TableViewTextItem>(items[1]).text); + EXPECT_NSEQ(l10n_util::GetNSString( + IDS_IOS_GOOGLE_ACCOUNT_SETTINGS_MANAGE_ACCOUNTS_ITEM), + base::apple::ObjCCastStrict<TableViewTextItem>(items[2]).text); // The "Sign out" item only exists in this section if // kSeparateProfilesForManagedAccounts is disabled. if (!AreSeparateProfilesForManagedAccountsEnabled()) { - ASSERT_EQ([items count], 3u); + ASSERT_EQ([items count], 4u); EXPECT_EQ(SignOutItemType, base::apple::ObjCCastStrict<TableViewItem>(items[2]).type); EXPECT_NSEQ( l10n_util::GetNSString(IDS_IOS_GOOGLE_ACCOUNT_SETTINGS_SIGN_OUT_ITEM), base::apple::ObjCCastStrict<TableViewTextItem>(items[2]).text); } else { - ASSERT_EQ([items count], 2u); + ASSERT_EQ([items count], 3u); } } // Tests the signout section items when manage storage is enabled. TEST_F(ManageSyncSettingsMediatorTest, CheckSignOutSectionItemsForSignedInNotSyncingAccountWithStorage) { - feature_list_.InitAndEnableFeature(kIOSManageAccountStorage); CreateManageSyncSettingsMediator(); sync_service_->SetSignedIn(signin::ConsentLevel::kSignin);
diff --git a/ios/chrome/browser/settings/ui_bundled/password/password_checkup/password_checkup_view_controller.mm b/ios/chrome/browser/settings/ui_bundled/password/password_checkup/password_checkup_view_controller.mm index 73b433c..58be055 100644 --- a/ios/chrome/browser/settings/ui_bundled/password/password_checkup/password_checkup_view_controller.mm +++ b/ios/chrome/browser/settings/ui_bundled/password/password_checkup/password_checkup_view_controller.mm
@@ -13,7 +13,6 @@ #import "ios/chrome/browser/net/model/crurl.h" #import "ios/chrome/browser/passwords/model/password_checkup_metrics.h" #import "ios/chrome/browser/passwords/model/password_checkup_utils.h" -#import "ios/chrome/browser/settings/ui_bundled/cells/settings_check_cell.h" #import "ios/chrome/browser/settings/ui_bundled/cells/settings_check_item.h" #import "ios/chrome/browser/settings/ui_bundled/password/password_checkup/password_checkup_commands.h" #import "ios/chrome/browser/settings/ui_bundled/password/password_checkup/password_checkup_constants.h"
diff --git a/ios/chrome/browser/settings/ui_bundled/password/password_settings/BUILD.gn b/ios/chrome/browser/settings/ui_bundled/password/password_settings/BUILD.gn index b53d13e4..0a2dcfa9 100644 --- a/ios/chrome/browser/settings/ui_bundled/password/password_settings/BUILD.gn +++ b/ios/chrome/browser/settings/ui_bundled/password/password_settings/BUILD.gn
@@ -56,6 +56,7 @@ "//ios/chrome/browser/signin/model:trusted_vault_factory", "//ios/chrome/browser/sync/model", "//ios/chrome/browser/webauthn/model", + "//ios/chrome/common/credential_provider", "//ios/chrome/common/ui/elements:branded_navigation_item_title_view", "//ios/chrome/common/ui/reauthentication", "//ui/base", @@ -132,6 +133,7 @@ "//components/webauthn/core/browser", "//components/webauthn/core/browser:test_support", "//ios/chrome/app/strings", + "//ios/chrome/browser/credential_provider/model:features", "//ios/chrome/browser/passwords/model:store_factory", "//ios/chrome/browser/passwords/model/metrics", "//ios/chrome/browser/settings/ui_bundled/password:features",
diff --git a/ios/chrome/browser/settings/ui_bundled/password/password_settings/password_settings_consumer.h b/ios/chrome/browser/settings/ui_bundled/password/password_settings/password_settings_consumer.h index c2e8eda80..e14ac37 100644 --- a/ios/chrome/browser/settings/ui_bundled/password/password_settings/password_settings_consumer.h +++ b/ios/chrome/browser/settings/ui_bundled/password/password_settings/password_settings_consumer.h
@@ -39,7 +39,7 @@ - (void)setCanDeleteAllCredentials:(BOOL)canDeleteAllCredentials; -- (void)setCanExportPasswords:(BOOL)canExportPasswords; +- (void)setCanExportCredentials:(BOOL)canExportCredentials; - (void)setCanBulkMove:(BOOL)canBulkMove localPasswordsCount:(int)count;
diff --git a/ios/chrome/browser/settings/ui_bundled/password/password_settings/password_settings_coordinator.mm b/ios/chrome/browser/settings/ui_bundled/password/password_settings/password_settings_coordinator.mm index 9b1c677..b1217ab 100644 --- a/ios/chrome/browser/settings/ui_bundled/password/password_settings/password_settings_coordinator.mm +++ b/ios/chrome/browser/settings/ui_bundled/password/password_settings/password_settings_coordinator.mm
@@ -194,6 +194,9 @@ _reauthModule = password_manager::BuildReauthenticationModule(); + webauthn::PasskeyModel* passkeyModel = + IOSPasskeyModelFactory::GetForProfile(self.browser->GetProfile()); + _savedPasswordsPresenter = std::make_unique<password_manager::SavedPasswordsPresenter>( IOSChromeAffiliationServiceFactory::GetForProfile(profile), @@ -201,7 +204,7 @@ profile, ServiceAccessType::EXPLICIT_ACCESS), IOSChromeAccountPasswordStoreFactory::GetForProfile( profile, ServiceAccessType::EXPLICIT_ACCESS), - IOSPasskeyModelFactory::GetForProfile(profile)); + passkeyModel); _identity = AuthenticationServiceFactory::GetForProfile(profile)->GetPrimaryIdentity( @@ -209,6 +212,7 @@ _mediator = [[PasswordSettingsMediator alloc] initWithReauthenticationModule:_reauthModule savedPasswordsPresenter:_savedPasswordsPresenter.get() + passkeyModel:passkeyModel bulkMovePasswordsToAccountHandler:self exportHandler:self prefService:profile->GetPrefs()
diff --git a/ios/chrome/browser/settings/ui_bundled/password/password_settings/password_settings_mediator.h b/ios/chrome/browser/settings/ui_bundled/password/password_settings/password_settings_mediator.h index bb0202a..687a501a 100644 --- a/ios/chrome/browser/settings/ui_bundled/password/password_settings/password_settings_mediator.h +++ b/ios/chrome/browser/settings/ui_bundled/password/password_settings/password_settings_mediator.h
@@ -22,6 +22,10 @@ class SyncService; } +namespace webauthn { +class PasskeyModel; +} + class PrefService; class TrustedVaultClientBackend; @@ -48,6 +52,7 @@ initWithReauthenticationModule:(id<ReauthenticationProtocol>)reauthModule savedPasswordsPresenter: (password_manager::SavedPasswordsPresenter*)passwordPresenter + passkeyModel:(webauthn::PasskeyModel*)passkeyModel bulkMovePasswordsToAccountHandler: (id<BulkMoveLocalPasswordsToAccountHandler>) bulkMovePasswordsToAccountHandler
diff --git a/ios/chrome/browser/settings/ui_bundled/password/password_settings/password_settings_mediator.mm b/ios/chrome/browser/settings/ui_bundled/password/password_settings/password_settings_mediator.mm index ae64af1..b337cbde 100644 --- a/ios/chrome/browser/settings/ui_bundled/password/password_settings/password_settings_mediator.mm +++ b/ios/chrome/browser/settings/ui_bundled/password/password_settings/password_settings_mediator.mm
@@ -23,12 +23,14 @@ #import "components/sync/base/user_selectable_type.h" #import "components/sync/service/sync_service_utils.h" #import "components/sync/service/sync_user_settings.h" +#import "ios/chrome/browser/credential_provider/model/features.h" #import "ios/chrome/browser/settings/ui_bundled/password/password_exporter.h" #import "ios/chrome/browser/settings/ui_bundled/password/saved_passwords_presenter_observer.h" #import "ios/chrome/browser/settings/ui_bundled/utils/password_auto_fill_status_manager.h" #import "ios/chrome/browser/signin/model/system_identity.h" #import "ios/chrome/browser/signin/model/trusted_vault_client_backend.h" #import "ios/chrome/browser/sync/model/sync_observer_bridge.h" +#import "ios/chrome/common/credential_provider/passkey_model_observer_bridge.h" #import "ios/chrome/common/ui/reauthentication/reauthentication_protocol.h" #import "ios/chrome/grit/ios_strings.h" #import "ui/base/l10n/l10n_util.h" @@ -57,6 +59,7 @@ } // namespace @interface PasswordSettingsMediator () <IdentityManagerObserverBridgeDelegate, + PasskeyModelObserverDelegate, PasswordAutoFillStatusObserver, PasswordExporterDelegate, PrefObserverDelegate, @@ -73,6 +76,12 @@ // Service which gives us a view on users' saved passwords. raw_ptr<password_manager::SavedPasswordsPresenter> _savedPasswordsPresenter; + // Provides access to passkeys stored in user's account. + raw_ptr<webauthn::PasskeyModel> _passkeyModel; + + // Observer for the PasskeyModel. + std::unique_ptr<PasskeyModelObserverBridge> _passkeyObserverBridge; + // Allows reading and writing user preferences. raw_ptr<PrefService> _prefService; @@ -116,6 +125,9 @@ // Whether or not there are any passwords saved. BOOL _hasSavedPasswords; + // Whether or not there are any passkeys saved. + BOOL _hasSavedPasskeys; + // Whether or not the password exporter is ready to be activated. BOOL _exporterIsReady; } @@ -124,6 +136,7 @@ initWithReauthenticationModule:(id<ReauthenticationProtocol>)reauthModule savedPasswordsPresenter: (password_manager::SavedPasswordsPresenter*)passwordPresenter + passkeyModel:(webauthn::PasskeyModel*)passkeyModel bulkMovePasswordsToAccountHandler: (id<BulkMoveLocalPasswordsToAccountHandler>) bulkMovePasswordsToAccountHandler @@ -144,6 +157,12 @@ std::make_unique<SavedPasswordsPresenterObserverBridge>( self, _savedPasswordsPresenter); _savedPasswordsPresenter->Init(); + + _passkeyModel = passkeyModel; + CHECK(_passkeyModel); + _passkeyObserverBridge = + std::make_unique<PasskeyModelObserverBridge>(self, _passkeyModel.get()); + _bulkMovePasswordsToAccountHandler = bulkMovePasswordsToAccountHandler; _exportHandler = exportHandler; _prefService = prefService; @@ -182,6 +201,7 @@ // will not behave correctly on load. _exporterIsReady = _passwordExporter.exportState == ExportState::IDLE; [self savedPasswordsDidChange]; + [self passkeysDidChange]; [self.consumer setSavingPasswordsEnabled:_prefService->GetBoolean( kCredentialsEnableService) @@ -250,6 +270,8 @@ DCHECK(_passwordsPresenterObserver); _savedPasswordsPresenter->RemoveObserver(_passwordsPresenterObserver.get()); _passwordsPresenterObserver.reset(); + _passkeyObserverBridge.reset(); + _passkeyModel = nullptr; [[PasswordAutoFillStatusManager sharedManager] removeObserver:self]; _prefObserverBridge.reset(); _prefChangeRegistrar.reset(); @@ -425,6 +447,22 @@ // TODO(crbug.com/430876032): Update GPM Pin section properly. } +#pragma mark - PasskeyModelObserverDelegate + +- (void)passkeyModelDidChange { + [self passkeysDidChange]; +} + +- (void)passkeyModelIsReady:(webauthn::PasskeyModel*)passkeyModel { + [self passkeysDidChange]; +} + +- (void)passKeyModelShuttingDown:(webauthn::PasskeyModel*)passkeyModel { + _passkeyObserverBridge.reset(); + _passkeyModel = nullptr; + [self passkeysDidChange]; +} + #pragma mark - Private // Returns the on-device encryption state according to the sync service. @@ -453,7 +491,9 @@ // Pushes the current state of the exporter to the consumer. - (void)pushExportStateToConsumer { - [self.consumer setCanExportPasswords:_hasSavedPasswords && _exporterIsReady]; + BOOL hasExportableData = + _hasSavedPasswords || (_hasSavedPasskeys && CredentialExchangeEnabled()); + [self.consumer setCanExportCredentials:hasExportableData && _exporterIsReady]; } // Computes the amount of local passwords and passes that on to the consumer. @@ -535,4 +575,14 @@ })); } +// Called when the PasskeyModel changes or becomes ready. +- (void)passkeysDidChange { + _hasSavedPasskeys = + !_passkeyModel + ->GetPasskeys(webauthn::PasskeyModel::AnyRp{}, + webauthn::PasskeyModel::ShadowedCredentials::kExclude) + .empty(); + [self pushExportStateToConsumer]; +} + @end
diff --git a/ios/chrome/browser/settings/ui_bundled/password/password_settings/password_settings_mediator_unittest.mm b/ios/chrome/browser/settings/ui_bundled/password/password_settings/password_settings_mediator_unittest.mm index 40d8c487b..fe1a89c5 100644 --- a/ios/chrome/browser/settings/ui_bundled/password/password_settings/password_settings_mediator_unittest.mm +++ b/ios/chrome/browser/settings/ui_bundled/password/password_settings/password_settings_mediator_unittest.mm
@@ -18,6 +18,7 @@ #import "components/sync/test/mock_sync_service.h" #import "components/webauthn/core/browser/passkey_sync_bridge.h" #import "components/webauthn/core/browser/test_passkey_model.h" +#import "ios/chrome/browser/credential_provider/model/features.h" #import "ios/chrome/browser/passwords/model/ios_chrome_profile_password_store_factory.h" #import "ios/chrome/browser/shared/model/profile/test/test_profile_ios.h" #import "ios/chrome/browser/signin/model/fake_system_identity.h" @@ -168,6 +169,7 @@ mediator_ = [[PasswordSettingsMediator alloc] initWithReauthenticationModule:reauth_module_ savedPasswordsPresenter:presenter_.get() + passkeyModel:passkey_model_ bulkMovePasswordsToAccountHandler: bulk_move_passwords_to_account_handler_ exportHandler:export_handler_ @@ -361,3 +363,16 @@ AddPasskey(); [[consumer_ verify] setCanBulkMove:NO localPasswordsCount:2]; } + +#if BUILDFLAG(IOS_CREDENTIAL_EXCHANGE_ENABLED) +// Tests that the export button is enabled/disabled based on passkey presence +// when the Credential Exchange feature is enabled. +TEST_F(PasswordSettingsMediatorTest, UpdatesExportStateWhenPasskeysChange) { + CreateMediator(); + + [[consumer_ verify] setCanExportCredentials:NO]; + + AddPasskey(); + [[consumer_ verify] setCanExportCredentials:YES]; +} +#endif
diff --git a/ios/chrome/browser/settings/ui_bundled/password/password_settings/password_settings_view_controller.mm b/ios/chrome/browser/settings/ui_bundled/password/password_settings/password_settings_view_controller.mm index 998d082..e70a7fad 100644 --- a/ios/chrome/browser/settings/ui_bundled/password/password_settings/password_settings_view_controller.mm +++ b/ios/chrome/browser/settings/ui_bundled/password/password_settings/password_settings_view_controller.mm
@@ -132,8 +132,8 @@ // Whether the credential delete button should be enabled. BOOL _canDeleteAllCredentials; - // Whether the exporter should be enabled. - BOOL _canExportPasswords; + // Whether credentials are available for export. + BOOL _canExportCredentials; // Whether automatic passkey upgrades is enabled. BOOL _automaticPasskeyUpgradesEnabled; @@ -361,7 +361,7 @@ break; } case ItemTypeExportPasswordsButton: { - if (_canExportPasswords) { + if (_canExportCredentials) { [self.presentationDelegate startExportFlow]; } break; @@ -395,7 +395,7 @@ case ItemTypeDeleteCredentialsButton: return _canDeleteAllCredentials; case ItemTypeExportPasswordsButton: - return _canExportPasswords; + return _canExportCredentials; case ItemTypeSavePasswordsSwitch: return NO; case ItemTypePasswordsInOtherApps: @@ -717,12 +717,11 @@ [self updateDeleteAllCredentialsSection]; } -- (void)setCanExportPasswords:(BOOL)canExportPasswords { - if (_canExportPasswords == canExportPasswords) { +- (void)setCanExportCredentials:(BOOL)canExportCredentials { + if (_canExportCredentials == canExportCredentials) { return; } - - _canExportPasswords = canExportPasswords; + _canExportCredentials = canExportCredentials; [self updateExportPasswordsButton]; } @@ -1253,7 +1252,7 @@ return; } - if (_canExportPasswords) { + if (_canExportCredentials) { _exportPasswordsItem.textColor = [UIColor colorNamed:kBlueColor]; _exportPasswordsItem.accessibilityTraits &= ~UIAccessibilityTraitNotEnabled; } else {
diff --git a/ios/chrome/browser/settings/ui_bundled/password/password_settings/password_settings_view_controller_unittest.mm b/ios/chrome/browser/settings/ui_bundled/password/password_settings/password_settings_view_controller_unittest.mm index 26144b2..add4336c 100644 --- a/ios/chrome/browser/settings/ui_bundled/password/password_settings/password_settings_view_controller_unittest.mm +++ b/ios/chrome/browser/settings/ui_bundled/password/password_settings/password_settings_view_controller_unittest.mm
@@ -103,7 +103,7 @@ [controller() setCanChangeGPMPin:YES]; [controller() setOnDeviceEncryptionState: PasswordSettingsOnDeviceEncryptionStateOptedIn]; - [controller() setCanExportPasswords:YES]; + [controller() setCanExportCredentials:YES]; [controller() setCanDeleteAllCredentials:YES]; // Verify the order. @@ -348,7 +348,8 @@ TEST_F(PasswordSettingsViewControllerTest, ExportButtonDisabledWhenUserNotEligible) { - [controller() setCanExportPasswords:NO]; + [controller() setCanExportCredentials:NO]; + EXPECT_TRUE(GetTableViewItem(SectionIdentifierExportPasswordsButton, /*item=*/0) .accessibilityTraits & @@ -357,7 +358,8 @@ TEST_F(PasswordSettingsViewControllerTest, ExportButtonEnabledWhenUserEligible) { - [controller() setCanExportPasswords:YES]; + [controller() setCanExportCredentials:YES]; + EXPECT_FALSE(GetTableViewItem(SectionIdentifierExportPasswordsButton, /*item=*/0) .accessibilityTraits &
diff --git a/ios/chrome/browser/settings/ui_bundled/privacy/privacy_safe_browsing_mediator.mm b/ios/chrome/browser/settings/ui_bundled/privacy/privacy_safe_browsing_mediator.mm index b457fdc..c3a0b8e 100644 --- a/ios/chrome/browser/settings/ui_bundled/privacy/privacy_safe_browsing_mediator.mm +++ b/ios/chrome/browser/settings/ui_bundled/privacy/privacy_safe_browsing_mediator.mm
@@ -29,7 +29,6 @@ #import "ios/chrome/browser/shared/ui/symbols/symbols.h" #import "ios/chrome/browser/shared/ui/table_view/cells/table_view_detail_icon_item.h" #import "ios/chrome/browser/shared/ui/table_view/cells/table_view_info_button_item.h" -#import "ios/chrome/browser/shared/ui/table_view/cells/table_view_info_button_item_delegate.h" #import "ios/chrome/browser/shared/ui/util/uikit_ui_util.h" #import "ios/chrome/browser/welcome_back/model/features.h" #import "ios/chrome/common/ui/colors/semantic_color_names.h" @@ -53,8 +52,7 @@ } // namespace -@interface PrivacySafeBrowsingMediator () <BooleanObserver, - TableViewInfoButtonItemDelegate> +@interface PrivacySafeBrowsingMediator () <BooleanObserver> // Preference value for the enhanced safe browsing feature. @property(nonatomic, strong, readonly) @@ -260,7 +258,6 @@ DefaultSymbolWithConfiguration(kCheckmarkSymbol, configuration); infoButtonItem.iconTintColor = [self iconTintColorForItemType:type]; infoButtonItem.accessibilityIdentifier = accessibilityIdentifier; - infoButtonItem.accessibilityDelegate = self; infoButtonItem.target = self; infoButtonItem.selector = @selector(didTapInfoButton:); infoButtonItem.tag = type; @@ -360,12 +357,6 @@ return; } - [self showAdditionalInfoForItemType:itemType]; -} - -// Displays the screens with additional infos for `itemType`. -- (void)showAdditionalInfoForItemType:(ItemType)itemType { - // Info button tap logic when not in enterprise mode. switch (itemType) { case ItemTypeSafeBrowsingEnhancedProtection: base::RecordAction(base::UserMetricsAction( @@ -432,14 +423,6 @@ } } -#pragma mark - TableViewInfoButtonItemDelegate - -- (void)handleTappedInfoButtonForItem:(TableViewItem*)item { - ItemType itemType = static_cast<ItemType>(item.type); - CHECK(![self shouldEnterprisePopOverDisplay:itemType]); - [self showAdditionalInfoForItemType:itemType]; -} - #pragma mark - BooleanObserver - (void)booleanDidChange:(id<ObservableBoolean>)observableBoolean {
diff --git a/ios/chrome/browser/settings/ui_bundled/settings_table_view_controller.mm b/ios/chrome/browser/settings/ui_bundled/settings_table_view_controller.mm index eae5a30..0714cd6 100644 --- a/ios/chrome/browser/settings/ui_bundled/settings_table_view_controller.mm +++ b/ios/chrome/browser/settings/ui_bundled/settings_table_view_controller.mm
@@ -933,8 +933,6 @@ _safetyCheckItem.leadingIconBackgroundColor = [UIColor colorNamed:kBlue500Color]; _safetyCheckItem.leadingIconTintColor = UIColor.whiteColor; - _safetyCheckItem.leadingIconCornerRadius = - kColorfulBackgroundSymbolCornerRadius; _safetyCheckItem.accessibilityIdentifier = kSettingsSafetyCheckCellId; // Check if an issue state should be shown for updates. if (!IsAppUpToDate() && PreviousSafetyCheckIssueFound()) {
diff --git a/ios/chrome/browser/settings/ui_bundled/table_cell_catalog_view_controller.mm b/ios/chrome/browser/settings/ui_bundled/table_cell_catalog_view_controller.mm index f386dbc..0fbd8df 100644 --- a/ios/chrome/browser/settings/ui_bundled/table_cell_catalog_view_controller.mm +++ b/ios/chrome/browser/settings/ui_bundled/table_cell_catalog_view_controller.mm
@@ -14,7 +14,6 @@ #import "ios/chrome/browser/reading_list/ui_bundled/reading_list_table_view_item.h" #import "ios/chrome/browser/settings/ui_bundled/address_bar_preference/cells/address_bar_options_item.h" #import "ios/chrome/browser/settings/ui_bundled/cells/inline_promo_item.h" -#import "ios/chrome/browser/settings/ui_bundled/cells/settings_check_cell.h" #import "ios/chrome/browser/settings/ui_bundled/cells/settings_check_item.h" #import "ios/chrome/browser/settings/ui_bundled/cells/settings_image_detail_text_item.h" #import "ios/chrome/browser/settings/ui_bundled/cells/sync_switch_item.h" @@ -467,11 +466,14 @@ [[TableViewInfoButtonItem alloc] initWithType:ItemTypeTableViewInfoButtonWithDetailText]; tableViewInfoButtonItemWithDetailText.text = @"Info button item"; - tableViewInfoButtonItemWithDetailText.detailText = @"Detail text"; + tableViewInfoButtonItemWithDetailText.detailText = + @"Button is not activated by VoiceOver"; tableViewInfoButtonItemWithDetailText.statusText = @"Status"; tableViewInfoButtonItemWithDetailText.target = self; tableViewInfoButtonItemWithDetailText.selector = @selector(didTapManagedUIInfoButton:); + tableViewInfoButtonItemWithDetailText.accessibilityActivationPointOnButton = + NO; [model addItem:tableViewInfoButtonItemWithDetailText toSectionWithIdentifier:SectionIdentifierSettings]; @@ -571,6 +573,8 @@ checkWithInfoButton.enabled = YES; checkWithInfoButton.indicatorHidden = YES; checkWithInfoButton.infoButtonHidden = NO; + checkWithInfoButton.infoButtonTarget = self; + checkWithInfoButton.infoButtonSelector = @selector(didTapCheckInfoButton:); [model addItem:checkWithInfoButton toSectionWithIdentifier:SectionIdentifierSettings]; @@ -774,16 +778,7 @@ }); } } - UITableViewCell* cell = [super tableView:tableView - cellForRowAtIndexPath:indexPath]; - if (itemType == ItemTypeCheck6) { - SettingsCheckCell* checkCell = - base::apple::ObjCCastStrict<SettingsCheckCell>(cell); - [checkCell.infoButton addTarget:self - action:@selector(didTapCheckInfoButton:) - forControlEvents:UIControlEventTouchUpInside]; - } - return cell; + return [super tableView:tableView cellForRowAtIndexPath:indexPath]; } @end
diff --git a/ios/chrome/browser/shared/public/features/features.h b/ios/chrome/browser/shared/public/features/features.h index 52395bd1..ee8f21792 100644 --- a/ios/chrome/browser/shared/public/features/features.h +++ b/ios/chrome/browser/shared/public/features/features.h
@@ -473,9 +473,6 @@ // Feature flag enabling the client folder implementation of Save to Drive. BASE_DECLARE_FEATURE(kIOSSaveToDriveClientFolder); -// Feature flag enabling account storage management. -BASE_DECLARE_FEATURE(kIOSManageAccountStorage); - // Feature flag to enable feed background refresh. // Use IsFeedBackgroundRefreshEnabled() instead of this constant directly. BASE_DECLARE_FEATURE(kEnableFeedBackgroundRefresh); @@ -489,7 +486,6 @@ // Feature flag to enable the content notifications. BASE_DECLARE_FEATURE(kContentPushNotifications); - // Feature flag to enable Content Notification Provisional without any // conditions. BASE_DECLARE_FEATURE(kContentNotificationProvisionalIgnoreConditions); @@ -931,12 +927,6 @@ // Returns true if the IPH gesture recognition improvements are enabled. bool IsIPHGestureRecognitionImprovementEnabled(); -// Feature flag for enabling the non-modal sign-in promo. -BASE_DECLARE_FEATURE(kNonModalSignInPromo); - -// Returns whether the non-modal sign-in promo is enabled. -bool IsNonModalSignInPromoEnabled(); - // Feature flag to remove section breaks when detecting addresses. BASE_DECLARE_FEATURE(kIOSOneTapMiniMapRemoveSectionsBreaks); @@ -980,12 +970,6 @@ // providesAppNotificationSettings. BASE_DECLARE_FEATURE(kIOSProvidesAppNotificationSettings); -// Feature flag for enabling the sign-in button without avatar. -BASE_DECLARE_FEATURE(kSignInButtonNoAvatar); - -// Returns whether the sign-in button without avatar is enabled. -bool IsSignInButtonNoAvatarEnabled(); - // Feature flag to enable background customization on the NTP. BASE_DECLARE_FEATURE(kNTPBackgroundCustomization);
diff --git a/ios/chrome/browser/shared/public/features/features.mm b/ios/chrome/browser/shared/public/features/features.mm index f97c32f..649b6a4 100644 --- a/ios/chrome/browser/shared/public/features/features.mm +++ b/ios/chrome/browser/shared/public/features/features.mm
@@ -389,8 +389,6 @@ BASE_FEATURE(kIOSSaveToDriveClientFolder, base::FEATURE_DISABLED_BY_DEFAULT); -BASE_FEATURE(kIOSManageAccountStorage, base::FEATURE_ENABLED_BY_DEFAULT); - BASE_FEATURE(kEnableFeedBackgroundRefresh, base::FEATURE_DISABLED_BY_DEFAULT); BASE_FEATURE(kEnableFeedAblation, base::FEATURE_DISABLED_BY_DEFAULT); @@ -943,12 +941,6 @@ kIPHGestureRecognitionAblation, kIPHGestureRecognitionImprovement, false); } -BASE_FEATURE(kNonModalSignInPromo, base::FEATURE_ENABLED_BY_DEFAULT); - -bool IsNonModalSignInPromoEnabled() { - return base::FeatureList::IsEnabled(kNonModalSignInPromo); -} - BASE_FEATURE(kIOSOneTapMiniMapRestrictions, base::FEATURE_DISABLED_BY_DEFAULT); const char kIOSOneTapMiniMapRestrictionCrossValidateParamName[] = @@ -1005,12 +997,6 @@ BASE_FEATURE(kIOSProvidesAppNotificationSettings, base::FEATURE_DISABLED_BY_DEFAULT); -BASE_FEATURE(kSignInButtonNoAvatar, base::FEATURE_ENABLED_BY_DEFAULT); - -bool IsSignInButtonNoAvatarEnabled() { - return base::FeatureList::IsEnabled(kSignInButtonNoAvatar); -} - BASE_FEATURE(kNTPBackgroundCustomization, base::FEATURE_DISABLED_BY_DEFAULT); bool IsNTPBackgroundCustomizationEnabled() {
diff --git a/ios/chrome/browser/shared/ui/table_view/cells/BUILD.gn b/ios/chrome/browser/shared/ui/table_view/cells/BUILD.gn index 8024a74..8a0638d 100644 --- a/ios/chrome/browser/shared/ui/table_view/cells/BUILD.gn +++ b/ios/chrome/browser/shared/ui/table_view/cells/BUILD.gn
@@ -38,7 +38,6 @@ "table_view_image_item.mm", "table_view_info_button_item.h", "table_view_info_button_item.mm", - "table_view_info_button_item_delegate.h", "table_view_item.h", "table_view_item.mm", "table_view_link_header_footer_item.h",
diff --git a/ios/chrome/browser/shared/ui/table_view/cells/legacy_table_view_cell.mm b/ios/chrome/browser/shared/ui/table_view/cells/legacy_table_view_cell.mm index b92947a..3b9d01c 100644 --- a/ios/chrome/browser/shared/ui/table_view/cells/legacy_table_view_cell.mm +++ b/ios/chrome/browser/shared/ui/table_view/cells/legacy_table_view_cell.mm
@@ -118,4 +118,19 @@ return [super accessibilityActivationPoint]; } +- (NSArray<UIAccessibilityCustomAction*>*)accessibilityCustomActions { + NSMutableArray<UIAccessibilityCustomAction*>* actions = + [NSMutableArray array]; + if ([self.contentView conformsToProtocol:@protocol(ChromeContentView)]) { + UIView<ChromeContentView>* chromeContentView = + static_cast<UIView<ChromeContentView>*>(self.contentView); + if (chromeContentView.accessibilityCustomActions.count > 0) { + [actions + addObjectsFromArray:chromeContentView.accessibilityCustomActions]; + } + } + [actions addObjectsFromArray:[super accessibilityCustomActions]]; + return actions; +} + @end
diff --git a/ios/chrome/browser/shared/ui/table_view/cells/table_view_cell.mm b/ios/chrome/browser/shared/ui/table_view/cells/table_view_cell.mm index 87dba1e..9374d87 100644 --- a/ios/chrome/browser/shared/ui/table_view/cells/table_view_cell.mm +++ b/ios/chrome/browser/shared/ui/table_view/cells/table_view_cell.mm
@@ -85,4 +85,19 @@ return [super accessibilityActivationPoint]; } +- (NSArray<UIAccessibilityCustomAction*>*)accessibilityCustomActions { + NSMutableArray<UIAccessibilityCustomAction*>* actions = + [NSMutableArray array]; + if ([self.contentView conformsToProtocol:@protocol(ChromeContentView)]) { + UIView<ChromeContentView>* chromeContentView = + static_cast<UIView<ChromeContentView>*>(self.contentView); + if (chromeContentView.accessibilityCustomActions.count > 0) { + [actions + addObjectsFromArray:chromeContentView.accessibilityCustomActions]; + } + } + [actions addObjectsFromArray:[super accessibilityCustomActions]]; + return actions; +} + @end
diff --git a/ios/chrome/browser/shared/ui/table_view/cells/table_view_info_button_item.h b/ios/chrome/browser/shared/ui/table_view/cells/table_view_info_button_item.h index 46589e3..19f406f5 100644 --- a/ios/chrome/browser/shared/ui/table_view/cells/table_view_info_button_item.h +++ b/ios/chrome/browser/shared/ui/table_view/cells/table_view_info_button_item.h
@@ -9,8 +9,6 @@ #import "ios/chrome/browser/shared/ui/table_view/cells/table_view_item.h" -@protocol TableViewInfoButtonItemDelegate; - // TableViewInfoButtonItem is a model class that uses TableViewInfoButtonCell. @interface TableViewInfoButtonItem : TableViewItem @@ -46,10 +44,6 @@ @property(nonatomic, assign) SEL selector; @property(nonatomic, assign) NSInteger tag; -// Accessibility delegate for custom accessibility actions. -@property(nonatomic, weak) id<TableViewInfoButtonItemDelegate> - accessibilityDelegate; - // Boolean for if the accessibility activation point should be on the button of // cell. The default value is YES. If value is changed to NO, the activation // point will be on the center of the cell.
diff --git a/ios/chrome/browser/shared/ui/table_view/cells/table_view_info_button_item.mm b/ios/chrome/browser/shared/ui/table_view/cells/table_view_info_button_item.mm index fabfaad..ba72ac8 100644 --- a/ios/chrome/browser/shared/ui/table_view/cells/table_view_info_button_item.mm +++ b/ios/chrome/browser/shared/ui/table_view/cells/table_view_info_button_item.mm
@@ -5,7 +5,6 @@ #import "ios/chrome/browser/shared/ui/table_view/cells/table_view_info_button_item.h" #import "ios/chrome/browser/shared/ui/table_view/cells/legacy_table_view_cell.h" -#import "ios/chrome/browser/shared/ui/table_view/cells/table_view_info_button_item_delegate.h" #import "ios/chrome/browser/shared/ui/table_view/content_configuration/colorful_symbol_content_configuration.h" #import "ios/chrome/browser/shared/ui/table_view/content_configuration/info_button_content_configuration.h" #import "ios/chrome/browser/shared/ui/table_view/content_configuration/table_view_cell_content_configuration.h" @@ -37,9 +36,6 @@ contentConfiguration.subtitleColor = self.detailTextColor; contentConfiguration.trailingText = self.statusText; - if (self.accessibilityDelegate) { - cell.accessibilityCustomActions = [self createAccessibilityActions]; - } cell.selectionStyle = UITableViewCellSelectionStyleNone; if (self.iconImage) { @@ -75,29 +71,4 @@ [TableViewCellContentConfiguration legacyDequeueTableViewCell:tableView]; } -#pragma mark - Accessibility - -// Creates custom accessibility actions. -- (NSArray*)createAccessibilityActions { - NSMutableArray* customActions = [[NSMutableArray alloc] init]; - - // Custom action for when the activation point is on the center of row. - if (!self.accessibilityActivationPointOnButton) { - UIAccessibilityCustomAction* tapButtonAction = - [[UIAccessibilityCustomAction alloc] - initWithName:l10n_util::GetNSString( - IDS_IOS_INFO_BUTTON_ACCESSIBILITY_HINT) - target:self - selector:@selector(handleTappedInfoButtonForItem)]; - [customActions addObject:tapButtonAction]; - } - - return customActions; -} - -// Handles accessibility action for tapping outside the info button. -- (void)handleTappedInfoButtonForItem { - [self.accessibilityDelegate handleTappedInfoButtonForItem:self]; -} - @end
diff --git a/ios/chrome/browser/shared/ui/table_view/cells/table_view_info_button_item_delegate.h b/ios/chrome/browser/shared/ui/table_view/cells/table_view_info_button_item_delegate.h deleted file mode 100644 index bd3db84..0000000 --- a/ios/chrome/browser/shared/ui/table_view/cells/table_view_info_button_item_delegate.h +++ /dev/null
@@ -1,17 +0,0 @@ -// Copyright 2022 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef IOS_CHROME_BROWSER_SHARED_UI_TABLE_VIEW_CELLS_TABLE_VIEW_INFO_BUTTON_ITEM_DELEGATE_H_ -#define IOS_CHROME_BROWSER_SHARED_UI_TABLE_VIEW_CELLS_TABLE_VIEW_INFO_BUTTON_ITEM_DELEGATE_H_ - -@class TableViewItem; - -@protocol TableViewInfoButtonItemDelegate <NSObject> - -// Handles the info button tap inside the cell. -- (void)handleTappedInfoButtonForItem:(TableViewItem*)item; - -@end - -#endif // IOS_CHROME_BROWSER_SHARED_UI_TABLE_VIEW_CELLS_TABLE_VIEW_INFO_BUTTON_ITEM_DELEGATE_H_
diff --git a/ios/chrome/browser/shared/ui/table_view/content_configuration/BUILD.gn b/ios/chrome/browser/shared/ui/table_view/content_configuration/BUILD.gn index 18d00ca..be46c91 100644 --- a/ios/chrome/browser/shared/ui/table_view/content_configuration/BUILD.gn +++ b/ios/chrome/browser/shared/ui/table_view/content_configuration/BUILD.gn
@@ -4,6 +4,10 @@ source_set("content_configuration") { sources = [ + "activity_indicator_content_configuration.h", + "activity_indicator_content_configuration.mm", + "activity_indicator_content_view.h", + "activity_indicator_content_view.mm", "colorful_symbol_content_configuration.h", "colorful_symbol_content_configuration.mm", "colorful_symbol_content_view.h", @@ -54,6 +58,7 @@ source_set("unit_tests") { testonly = true sources = [ + "activity_indicator_content_configuration_unittest.mm", "colorful_symbol_content_configuration_unittest.mm", "favicon_content_configuration_unittest.mm", "image_content_configuration_unittest.mm",
diff --git a/ios/chrome/browser/shared/ui/table_view/content_configuration/activity_indicator_content_configuration.h b/ios/chrome/browser/shared/ui/table_view/content_configuration/activity_indicator_content_configuration.h new file mode 100644 index 0000000..9729c73 --- /dev/null +++ b/ios/chrome/browser/shared/ui/table_view/content_configuration/activity_indicator_content_configuration.h
@@ -0,0 +1,34 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_SHARED_UI_TABLE_VIEW_CONTENT_CONFIGURATION_ACTIVITY_INDICATOR_CONTENT_CONFIGURATION_H_ +#define IOS_CHROME_BROWSER_SHARED_UI_TABLE_VIEW_CONTENT_CONFIGURATION_ACTIVITY_INDICATOR_CONTENT_CONFIGURATION_H_ + +#import <UIKit/UIKit.h> + +#import "ios/chrome/browser/shared/ui/table_view/content_configuration/chrome_content_configuration.h" + +// Configuration object for a TableView cell holding an activity indicator. +// It is using a ActivityIndicatorCellContentView as content view. +@interface ActivityIndicatorContentConfiguration + : NSObject <ChromeContentConfiguration> + +// The updates to properties must be reflected in the copy method. +// LINT.IfChange(Copy) + +// The style of the activity indicator. Default is +// UIActivityIndicatorViewStyleMedium. +@property(nonatomic, assign) UIActivityIndicatorViewStyle style; + +// The color of the activity indicator. +@property(nonatomic, strong) UIColor* color; + +// Whether the activity indicator should be animating. Default is YES. +@property(nonatomic, assign) BOOL animating; + +// LINT.ThenChange(activity_indicator_content_configuration.mm:Copy) + +@end + +#endif // IOS_CHROME_BROWSER_SHARED_UI_TABLE_VIEW_CONTENT_CONFIGURATION_ACTIVITY_INDICATOR_CONTENT_CONFIGURATION_H_
diff --git a/ios/chrome/browser/shared/ui/table_view/content_configuration/activity_indicator_content_configuration.mm b/ios/chrome/browser/shared/ui/table_view/content_configuration/activity_indicator_content_configuration.mm new file mode 100644 index 0000000..cae6a91 --- /dev/null +++ b/ios/chrome/browser/shared/ui/table_view/content_configuration/activity_indicator_content_configuration.mm
@@ -0,0 +1,60 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/chrome/browser/shared/ui/table_view/content_configuration/activity_indicator_content_configuration.h" + +#import "ios/chrome/browser/shared/ui/table_view/cells/table_view_cell.h" +#import "ios/chrome/browser/shared/ui/table_view/content_configuration/activity_indicator_content_view.h" +#import "ios/chrome/common/ui/table_view/table_view_cells_constants.h" + +namespace { +constexpr CGFloat kViewSize = 30; +} // namespace + +@implementation ActivityIndicatorContentConfiguration + +- (instancetype)init { + self = [super init]; + if (self) { + _style = UIActivityIndicatorViewStyleMedium; + _animating = YES; + } + return self; +} + +#pragma mark - ChromeContentConfiguration + +- (UIView<ChromeContentView>*)makeChromeContentView { + return [[ActivityIndicatorCellContentView alloc] initWithConfiguration:self]; +} + +- (CGSize)contentSize { + return CGSizeMake(kViewSize, kViewSize); +} + +#pragma mark - UIContentConfiguration + +- (UIView<UIContentView>*)makeContentView { + return [self makeChromeContentView]; +} + +- (instancetype)updatedConfigurationForState:(id<UIConfigurationState>)state { + return self; +} + +#pragma mark - NSCopying + +- (id)copyWithZone:(NSZone*)zone { + ActivityIndicatorContentConfiguration* copy = + [[ActivityIndicatorContentConfiguration allocWithZone:zone] init]; + // The updates to properties must be reflected in the copy method. + // LINT.IfChange(Copy) + copy.style = self.style; + copy.color = self.color; + copy.animating = self.animating; + // LINT.ThenChange(activity_indicator_content_configuration.h:Copy) + return copy; +} + +@end
diff --git a/ios/chrome/browser/shared/ui/table_view/content_configuration/activity_indicator_content_configuration_unittest.mm b/ios/chrome/browser/shared/ui/table_view/content_configuration/activity_indicator_content_configuration_unittest.mm new file mode 100644 index 0000000..861e5a4 --- /dev/null +++ b/ios/chrome/browser/shared/ui/table_view/content_configuration/activity_indicator_content_configuration_unittest.mm
@@ -0,0 +1,31 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/chrome/browser/shared/ui/table_view/content_configuration/activity_indicator_content_configuration.h" + +#import "testing/gtest/include/gtest/gtest.h" +#import "testing/platform_test.h" + +using ActivityIndicatorContentConfigurationTest = PlatformTest; + +// Tests that the content size is correct for +// ActivityIndicatorContentConfiguration. +TEST_F(ActivityIndicatorContentConfigurationTest, ContentSize) { + ActivityIndicatorContentConfiguration* config = + [[ActivityIndicatorContentConfiguration alloc] init]; + + CGSize content_size = [config contentSize]; + + UIView* content_view = [config makeContentView]; + [content_view setNeedsLayout]; + [content_view layoutIfNeeded]; + + CGSize compressed_size = + [content_view systemLayoutSizeFittingSize:UILayoutFittingCompressedSize]; + + EXPECT_EQ(content_size.width, 30); + EXPECT_EQ(content_size.height, 30); + EXPECT_EQ(content_size.width, compressed_size.width); + EXPECT_EQ(content_size.height, compressed_size.height); +}
diff --git a/ios/chrome/browser/shared/ui/table_view/content_configuration/activity_indicator_content_view.h b/ios/chrome/browser/shared/ui/table_view/content_configuration/activity_indicator_content_view.h new file mode 100644 index 0000000..dcf75af --- /dev/null +++ b/ios/chrome/browser/shared/ui/table_view/content_configuration/activity_indicator_content_view.h
@@ -0,0 +1,27 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_SHARED_UI_TABLE_VIEW_CONTENT_CONFIGURATION_ACTIVITY_INDICATOR_CONTENT_VIEW_H_ +#define IOS_CHROME_BROWSER_SHARED_UI_TABLE_VIEW_CONTENT_CONFIGURATION_ACTIVITY_INDICATOR_CONTENT_VIEW_H_ + +#import <UIKit/UIKit.h> + +#import "ios/chrome/browser/shared/ui/table_view/content_configuration/chrome_content_view.h" + +@class ActivityIndicatorContentConfiguration; + +@interface ActivityIndicatorCellContentView : UIView <ChromeContentView> + +/// Initializes with `configuration`. +- (instancetype)initWithConfiguration: + (ActivityIndicatorContentConfiguration*)configuration + NS_DESIGNATED_INITIALIZER; + +- (instancetype)initWithFrame:(CGRect)frame NS_UNAVAILABLE; +- (instancetype)init NS_UNAVAILABLE; +- (instancetype)initWithCoder:(NSCoder*)coder NS_UNAVAILABLE; + +@end + +#endif // IOS_CHROME_BROWSER_SHARED_UI_TABLE_VIEW_CONTENT_CONFIGURATION_ACTIVITY_INDICATOR_CONTENT_VIEW_H_
diff --git a/ios/chrome/browser/shared/ui/table_view/content_configuration/activity_indicator_content_view.mm b/ios/chrome/browser/shared/ui/table_view/content_configuration/activity_indicator_content_view.mm new file mode 100644 index 0000000..ddfbddc --- /dev/null +++ b/ios/chrome/browser/shared/ui/table_view/content_configuration/activity_indicator_content_view.mm
@@ -0,0 +1,92 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/chrome/browser/shared/ui/table_view/content_configuration/activity_indicator_content_view.h" + +#import "base/apple/foundation_util.h" +#import "ios/chrome/browser/shared/ui/table_view/content_configuration/activity_indicator_content_configuration.h" +#import "ios/chrome/common/ui/table_view/table_view_cells_constants.h" +#import "ios/chrome/common/ui/util/constraints_ui_util.h" + +@implementation ActivityIndicatorCellContentView { + ActivityIndicatorContentConfiguration* _configuration; + UIActivityIndicatorView* _activityIndicator; + + NSLayoutConstraint* _heightConstraint; + NSLayoutConstraint* _widthConstraint; +} + +- (instancetype)initWithConfiguration: + (ActivityIndicatorContentConfiguration*)configuration { + self = [super initWithFrame:CGRectZero]; + if (self) { + _configuration = [configuration copy]; + + // The correct value will be set when the config is applied. + _widthConstraint = [self.widthAnchor constraintEqualToConstant:0]; + _heightConstraint = [self.heightAnchor constraintEqualToConstant:0]; + + [self setupViews]; + [self applyConfiguration]; + + self.translatesAutoresizingMaskIntoConstraints = NO; + + [NSLayoutConstraint + activateConstraints:@[ _widthConstraint, _heightConstraint ]]; + } + return self; +} + +#pragma mark - ChromeContentView + +- (BOOL)hasCustomAccessibilityActivationPoint { + return NO; +} + +#pragma mark - UIContentView + +- (id<UIContentConfiguration>)configuration { + return _configuration; +} + +- (void)setConfiguration:(id<UIContentConfiguration>)configuration { + ActivityIndicatorContentConfiguration* chromeConfiguration = + base::apple::ObjCCastStrict<ActivityIndicatorContentConfiguration>( + configuration); + _configuration = [chromeConfiguration copy]; + [self applyConfiguration]; +} + +- (BOOL)supportsConfiguration:(id<UIContentConfiguration>)configuration { + return [configuration + isMemberOfClass:ActivityIndicatorContentConfiguration.class]; +} + +#pragma mark - Private + +// Updates the content view with the current configuration. +- (void)applyConfiguration { + _heightConstraint.constant = [_configuration contentSize].height; + _widthConstraint.constant = [_configuration contentSize].width; + _activityIndicator.activityIndicatorViewStyle = _configuration.style; + if (_configuration.color) { + _activityIndicator.color = _configuration.color; + } + if (_configuration.animating) { + [_activityIndicator startAnimating]; + } else { + [_activityIndicator stopAnimating]; + } +} + +// Adds and configures the subviews. +- (void)setupViews { + _activityIndicator = [[UIActivityIndicatorView alloc] init]; + _activityIndicator.translatesAutoresizingMaskIntoConstraints = NO; + [self addSubview:_activityIndicator]; + + AddSameCenterConstraints(_activityIndicator, self); +} + +@end
diff --git a/ios/chrome/browser/shared/ui/table_view/content_configuration/info_button_content_configuration.h b/ios/chrome/browser/shared/ui/table_view/content_configuration/info_button_content_configuration.h index c04bd4c..909813a9 100644 --- a/ios/chrome/browser/shared/ui/table_view/content_configuration/info_button_content_configuration.h +++ b/ios/chrome/browser/shared/ui/table_view/content_configuration/info_button_content_configuration.h
@@ -26,7 +26,8 @@ // The tag for the button. @property(nonatomic, assign) NSInteger tag; -// Whether the button should be the target of VoiceOver taps. Default is YES. +// Whether the button should be the target of VoiceOver taps. Default is YES. If +// NO, a custom action will be provided to trigger a touch on the button. @property(nonatomic, assign) BOOL selectedForVoiceOver; // LINT.ThenChange(info_button_content_configuration.mm:Copy)
diff --git a/ios/chrome/browser/shared/ui/table_view/content_configuration/info_button_content_view.mm b/ios/chrome/browser/shared/ui/table_view/content_configuration/info_button_content_view.mm index 79f7f129..073825a 100644 --- a/ios/chrome/browser/shared/ui/table_view/content_configuration/info_button_content_view.mm +++ b/ios/chrome/browser/shared/ui/table_view/content_configuration/info_button_content_view.mm
@@ -10,6 +10,8 @@ #import "ios/chrome/common/ui/colors/semantic_color_names.h" #import "ios/chrome/common/ui/table_view/table_view_cells_constants.h" #import "ios/chrome/common/ui/util/constraints_ui_util.h" +#import "ios/chrome/grit/ios_strings.h" +#import "ui/base/l10n/l10n_util.h" namespace { const CGFloat kInfoSymbolSize = 22; @@ -94,6 +96,19 @@ CGRectGetMidY(frameInScreenCoordinates)); } +- (NSArray<UIAccessibilityCustomAction*>*)accessibilityCustomActions { + if (!_configuration.selectedForVoiceOver) { + UIAccessibilityCustomAction* tapButtonAction = + [[UIAccessibilityCustomAction alloc] + initWithName:l10n_util::GetNSString( + IDS_IOS_INFO_BUTTON_ACCESSIBILITY_HINT) + target:self + selector:@selector(handleButtonVoiceOverActivation)]; + return @[ tapButtonAction ]; + } + return [super accessibilityCustomActions]; +} + #pragma mark - Private // Updates the content view with the current configuration. @@ -108,4 +123,9 @@ _infoButton.enabled = _configuration.enabled; } +// Simulates a tap on the button. +- (void)handleButtonVoiceOverActivation { + [_infoButton sendActionsForControlEvents:UIControlEventTouchUpInside]; +} + @end
diff --git a/ios/chrome/browser/shared/ui/table_view/content_configuration/table_view_cell_content_view.mm b/ios/chrome/browser/shared/ui/table_view/content_configuration/table_view_cell_content_view.mm index 068505c5..21a0ebb 100644 --- a/ios/chrome/browser/shared/ui/table_view/content_configuration/table_view_cell_content_view.mm +++ b/ios/chrome/browser/shared/ui/table_view/content_configuration/table_view_cell_content_view.mm
@@ -459,4 +459,19 @@ return [super accessibilityActivationPoint]; } +- (NSArray<UIAccessibilityCustomAction*>*)accessibilityCustomActions { + NSMutableArray<UIAccessibilityCustomAction*>* actions = + [NSMutableArray array]; + if (_trailingContentView.accessibilityCustomActions.count > 0) { + [actions + addObjectsFromArray:_trailingContentView.accessibilityCustomActions]; + } + if (_leadingContentView.accessibilityCustomActions.count > 0) { + [actions arrayByAddingObjectsFromArray:_leadingContentView + .accessibilityCustomActions]; + } + [actions addObjectsFromArray:[super accessibilityCustomActions]]; + return actions; +} + @end
diff --git a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/tab_grid_coordinator.mm b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/tab_grid_coordinator.mm index 3967ed7..eddd8ae 100644 --- a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/tab_grid_coordinator.mm +++ b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/tab_grid_coordinator.mm
@@ -751,6 +751,12 @@ determineTabGridTransitionTypeWithAnimationEnabled:animationEnabled]; Browser* browser = isIncognito ? self.incognitoBrowser : self.regularBrowser; + if (!browser) { + // The browser can be nil here, for example when switching account. Do not + // try to call the completion block as the code assumes there is a browser. + // See crbug.com/466376004. + return; + } web::WebState* activeWebState = browser->GetWebStateList()->GetActiveWebState(); BOOL isRegularBrowserNTP = !isIncognito && activeWebState &&
diff --git a/ios/chrome/common/credential_provider/passkey_model_observer_bridge.h b/ios/chrome/common/credential_provider/passkey_model_observer_bridge.h index bbedbf9..0741ce2 100644 --- a/ios/chrome/common/credential_provider/passkey_model_observer_bridge.h +++ b/ios/chrome/common/credential_provider/passkey_model_observer_bridge.h
@@ -11,6 +11,7 @@ @protocol PasskeyModelObserverDelegate - (void)passKeyModelShuttingDown:(webauthn::PasskeyModel*)passkeyModel; - (void)passkeyModelIsReady:(webauthn::PasskeyModel*)passkeyModel; +- (void)passkeyModelDidChange; @end // This class observes a passkey model which is not ready yet with the sole
diff --git a/ios/chrome/common/credential_provider/passkey_model_observer_bridge.mm b/ios/chrome/common/credential_provider/passkey_model_observer_bridge.mm index be5184b..8e4399f 100644 --- a/ios/chrome/common/credential_provider/passkey_model_observer_bridge.mm +++ b/ios/chrome/common/credential_provider/passkey_model_observer_bridge.mm
@@ -23,7 +23,9 @@ // webauthn::PasskeyModel::Observer: void PasskeyModelObserverBridge::OnPasskeysChanged( - const std::vector<webauthn::PasskeyModelChange>& changes) {} + const std::vector<webauthn::PasskeyModelChange>& changes) { + [observer_ passkeyModelDidChange]; +} void PasskeyModelObserverBridge::OnPasskeyModelShuttingDown() { scoped_observation_.Reset();
diff --git a/ios/chrome/test/earl_grey/BUILD.gn b/ios/chrome/test/earl_grey/BUILD.gn index 84e8d1a..7d486c3 100644 --- a/ios/chrome/test/earl_grey/BUILD.gn +++ b/ios/chrome/test/earl_grey/BUILD.gn
@@ -77,6 +77,7 @@ configs += [ "//build/config/ios:xctest_config" ] testonly = true sources = [ + "CALayer+EGResetInfiniteDuration.mm", "accessibility_util.h", "accessibility_util.mm", "chrome_actions_app_interface.h", @@ -121,6 +122,7 @@ "//ios/chrome/app:app_internal", "//ios/chrome/app/application_delegate:app_state", "//ios/chrome/app/strings", + "//ios/chrome/browser/ai_prototyping/test:eg_app_support+eg2", "//ios/chrome/browser/authentication/test:eg_app_support+eg2", "//ios/chrome/browser/authentication/ui_bundled/cells", "//ios/chrome/browser/autofill/model",
diff --git a/ios/chrome/test/earl_grey/CALayer+EGResetInfiniteDuration.mm b/ios/chrome/test/earl_grey/CALayer+EGResetInfiniteDuration.mm new file mode 100644 index 0000000..3dd1531 --- /dev/null +++ b/ios/chrome/test/earl_grey/CALayer+EGResetInfiniteDuration.mm
@@ -0,0 +1,62 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import <Foundation/Foundation.h> +#import <QuartzCore/QuartzCore.h> +#import <UIKit/UIKit.h> +#import <objc/runtime.h> + +namespace { + +// Swizzles the given methods in the given class. +static void SwizzleInstanceMethod(Class cls, + SEL original_selector, + SEL swizzled_selector) { + Method original_method = class_getInstanceMethod(cls, original_selector); + Method swizzled_method = class_getInstanceMethod(cls, swizzled_selector); + + BOOL did_add_method = class_addMethod( + cls, original_selector, method_getImplementation(swizzled_method), + method_getTypeEncoding(swizzled_method)); + + if (did_add_method) { + class_replaceMethod(cls, swizzled_selector, + method_getImplementation(original_method), + method_getTypeEncoding(original_method)); + } else { + method_exchangeImplementations(original_method, swizzled_method); + } +} + +} // namespace + +// A swizzle category that resets the duration to zero of animations when they +// are added to the layer, if the duration was INFINITY. This ensures that +// Earl Grey does not try to track them. These animations seem to be related +// to SwiftUI. +@interface CALayer (EGResetInfiniteDuration) +@end + +@implementation CALayer (EGResetInfiniteDuration) + ++ (void)load { + SwizzleInstanceMethod([self class], @selector(addAnimation:forKey:), + @selector(swizzledInfiniteDuration_addAnimation: + forKey:)); +} + +- (void)swizzledInfiniteDuration_addAnimation:(CAAnimation*)animation + forKey:(NSString*)key { + if (animation.duration == +INFINITY) { + // Reset duration of `CAMatchPropertyAnimation` and `CAMatchMoveAnimation` + // from infinite to zero so that Earl Grey does not track them infinitely, + // until a 10 second timeout is hit. + animation.duration = 0; + } + + // Call the original implementation. + [self swizzledInfiniteDuration_addAnimation:animation forKey:key]; +} + +@end
diff --git a/ios/chrome/test/earl_grey2/BUILD.gn b/ios/chrome/test/earl_grey2/BUILD.gn index 69e5525..fb0e1e2c 100644 --- a/ios/chrome/test/earl_grey2/BUILD.gn +++ b/ios/chrome/test/earl_grey2/BUILD.gn
@@ -187,6 +187,7 @@ xcode_test_application_name = "ios_chrome_eg2tests" deps = [ + "//ios/chrome/browser/ai_prototyping/test:eg2_tests", "//ios/chrome/browser/autofill/ui_bundled/authentication:eg2_tests", "//ios/chrome/browser/autofill/ui_bundled/bottom_sheet:eg2_tests", "//ios/chrome/browser/autofill/ui_bundled/form_input_accessory:eg2_tests",
diff --git a/ios_internal b/ios_internal index 0e7f589..9ff06ac 160000 --- a/ios_internal +++ b/ios_internal
@@ -1 +1 @@ -Subproject commit 0e7f5890f35d56c7b441abc8bb45d50cc7d77163 +Subproject commit 9ff06ac623af71709d9872aeb472d71b60f3b744
diff --git a/media/base/media_switches.cc b/media/base/media_switches.cc index 143f88a..48b4ebc 100644 --- a/media/base/media_switches.cc +++ b/media/base/media_switches.cc
@@ -352,6 +352,13 @@ // Enables the animation of the Picture-in-Picture window creation. BASE_FEATURE(kPictureInPictureShowWindowAnimation, base::FEATURE_ENABLED_BY_DEFAULT); + +// Enables video Picture-in-Picture display smoothness optimization. +// +// Ensures that the video PiP window title view is properly sized to only fit +// the favicon and origin. +BASE_FEATURE(kVideoPipDisplaySmoothnessOptimization, + base::FEATURE_ENABLED_BY_DEFAULT); #endif // !BUILDFLAG(IS_ANDROID) // Enables user control over muting tab audio from the tab strip.
diff --git a/media/base/media_switches.h b/media/base/media_switches.h index 90d737c..1fc90dc 100644 --- a/media/base/media_switches.h +++ b/media/base/media_switches.h
@@ -273,6 +273,7 @@ #if !BUILDFLAG(IS_ANDROID) MEDIA_EXPORT BASE_DECLARE_FEATURE(kPictureInPictureOcclusionTracking); MEDIA_EXPORT BASE_DECLARE_FEATURE(kPictureInPictureShowWindowAnimation); +MEDIA_EXPORT BASE_DECLARE_FEATURE(kVideoPipDisplaySmoothnessOptimization); #endif // !BUILDFLAG(IS_ANDROID) MEDIA_EXPORT BASE_DECLARE_FEATURE(kPlatformAudioEncoder); MEDIA_EXPORT BASE_DECLARE_FEATURE(kEnableRtcpReporting);
diff --git a/media/renderers/win/media_foundation_renderer.cc b/media/renderers/win/media_foundation_renderer.cc index e9864ae7..761f119 100644 --- a/media/renderers/win/media_foundation_renderer.cc +++ b/media/renderers/win/media_foundation_renderer.cc
@@ -6,6 +6,7 @@ #include <Audioclient.h> #include <mferror.h> +#include <winuser.h> #include <memory> #include <optional> @@ -55,6 +56,7 @@ constexpr uint32_t kGpuVendorIdNvidia = 0x10de; constexpr uint32_t kGpuVendorIdAmd = 0x1002; constexpr uint32_t kGpuVendorIdNone = 0x0000; +constexpr int kGpuVendorIdUnknown = -1; constexpr uint32_t kGpuBitmaskIntel = 0x001; constexpr uint32_t kGpuBitmaskNvidia = 0x001 << 1; @@ -98,6 +100,14 @@ kMaxValue = kOtherOther }; +// Reported to UMA. Do NOT change or reuse existing values. +enum class ActiveGpuDisplayInfo { + kUnknown = 0, + kLikelyBuiltIn = 1, // Likely built-in display + kLikelyExternal = 2, // Likely external display + kMaxValue = kLikelyExternal +}; + // The |g_video_window_class| atom obtained is used as the |lpClassName| // parameter in CreateWindowEx(). // https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-createwindowexa @@ -227,6 +237,17 @@ adapter_desc.AdapterLuid.LowPart == active_gpu_luid.LowPart) { continue; } + // Ignore software renderer based GPUs. See gpu/config/gpu_info.cc + if (adapter_desc.VendorId == 0x0000 || adapter_desc.VendorId == 0xFFFF || + adapter_desc.VendorId == 0x15ad || + (adapter_desc.VendorId == 0x1414 && + adapter_desc.DeviceId == 0x008c)) { + DVLOG(3) << __func__ << ": Adapter " << i << " Vendor ID: 0x" + << std::hex << adapter_desc.VendorId << ", Device ID: 0x" + << std::hex << adapter_desc.DeviceId + << " is a software renderer!"; + continue; + } vendor_ids.push_back(adapter_desc.VendorId); DVLOG(3) << __func__ << ": Adapter " << i << " Vendor ID: 0x" << std::hex << adapter_desc.VendorId; @@ -266,6 +287,65 @@ return count; } +ActiveGpuDisplayInfo GetActiveGpuDisplayInfo(const LUID& active_gpu_luid) { + UINT32 num_paths = 0; + UINT32 num_modes = 0; + + // Get required buffer sizes for active paths + LONG status = GetDisplayConfigBufferSizes(QDC_ONLY_ACTIVE_PATHS, &num_paths, + &num_modes); + + if (status != ERROR_SUCCESS) { + DVLOG(1) << __func__ << ": GetDisplayConfigBufferSizes failed: " << status; + return ActiveGpuDisplayInfo::kUnknown; + } + + std::vector<DISPLAYCONFIG_PATH_INFO> paths(num_paths); + std::vector<DISPLAYCONFIG_MODE_INFO> modes(num_modes); + + // Query the display configuration + status = QueryDisplayConfig(QDC_ONLY_ACTIVE_PATHS, &num_paths, paths.data(), + &num_modes, modes.data(), nullptr); + + if (status != ERROR_SUCCESS) { + DVLOG(1) << __func__ << ": QueryDisplayConfig failed: " << status; + return ActiveGpuDisplayInfo::kUnknown; + } + + // Iterate through paths and retrieve target device info + for (UINT32 i = 0; i < num_paths; ++i) { + DISPLAYCONFIG_PATH_INFO& current_path = paths[i]; + DISPLAYCONFIG_TARGET_DEVICE_NAME target_name = {}; + target_name.header.size = sizeof(target_name); + target_name.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_NAME; + target_name.header.adapterId = current_path.targetInfo.adapterId; + target_name.header.id = current_path.targetInfo.id; + + status = DisplayConfigGetDeviceInfo(&target_name.header); + if (status != ERROR_SUCCESS) { + continue; + } + + if (active_gpu_luid.HighPart == target_name.header.adapterId.HighPart && + active_gpu_luid.LowPart == target_name.header.adapterId.LowPart) { + // Check specifically for embedded types to infer "built-in" + if (target_name.outputTechnology == + DISPLAYCONFIG_OUTPUT_TECHNOLOGY_LVDS || + target_name.outputTechnology == + DISPLAYCONFIG_OUTPUT_TECHNOLOGY_DISPLAYPORT_EMBEDDED || + target_name.outputTechnology == + DISPLAYCONFIG_OUTPUT_TECHNOLOGY_INTERNAL) { + DVLOG(3) << __func__ << ": This is likely a BUILT-IN display."; + return ActiveGpuDisplayInfo::kLikelyBuiltIn; + } else { + DVLOG(3) << __func__ << ": This is likely an EXTERNAL display."; + return ActiveGpuDisplayInfo::kLikelyExternal; + } + } + } + return ActiveGpuDisplayInfo::kUnknown; +} + void ReportGpuInfoUma(const std::string& uma_prefix, IMFDXGIDeviceManager* dxgi_device_manager) { // For some tests, this can be nullptr. @@ -282,6 +362,10 @@ GpuOrDisplayCount::kUnknown); base::UmaHistogramEnumeration(uma_prefix + ".ActiveGpuInfo", ActiveGpuInfo::kNone); + base::UmaHistogramSparse(uma_prefix + ".ActiveGpuVendorId", + kGpuVendorIdUnknown); + base::UmaHistogramSparse(uma_prefix + ".NonActiveGpuVendorId", + kGpuVendorIdUnknown); } else { const auto all_nonactive_gpus = GetNonActiveGpuVendorIds(active_gpu_luid); const auto nonactive_gpu_count = all_nonactive_gpus.size(); @@ -290,11 +374,15 @@ const auto active_gpu_info = static_cast<ActiveGpuInfo>( GpuVendorIdToBitmask(active_gpu_vendor_id) | (GpuVendorIdToBitmask(nonactive_gpu_id) << kMakeGpuNonActive)); + const auto active_gpu_display_info = + GetActiveGpuDisplayInfo(active_gpu_luid); DVLOG(3) << __func__ << ": nonactive_gpu_count=" << nonactive_gpu_count << ", active_gpu_vendor_id=" << active_gpu_vendor_id << ", nonactive_gpu_id=" << nonactive_gpu_id - << ", active_gpu_info=" << static_cast<uint32_t>(active_gpu_info); + << ", active_gpu_info=" << static_cast<uint32_t>(active_gpu_info) + << ", active_gpu_display_info=" + << static_cast<uint32_t>(active_gpu_display_info); base::UmaHistogramEnumeration(uma_prefix + ".GpuCount", nonactive_gpu_count > 0 @@ -302,6 +390,14 @@ : GpuOrDisplayCount::kOne); base::UmaHistogramEnumeration(uma_prefix + ".ActiveGpuInfo", active_gpu_info); + base::UmaHistogramEnumeration(uma_prefix + ".ActiveGpuDisplayInfo", + active_gpu_display_info); + base::UmaHistogramSparse(uma_prefix + ".ActiveGpuVendorId", + active_gpu_vendor_id); + if (nonactive_gpu_id != kGpuVendorIdNone) { + base::UmaHistogramSparse(uma_prefix + ".NonActiveGpuVendorId", + nonactive_gpu_id); + } } const auto display_count = GetTotalDisplayCount();
diff --git a/mojo/public/rust/mojom_parser/ast.rs b/mojo/public/rust/mojom_parser/ast.rs index 1deb16a..a2e7b82a 100644 --- a/mojo/public/rust/mojom_parser/ast.rs +++ b/mojo/public/rust/mojom_parser/ast.rs
@@ -7,7 +7,8 @@ //! This module provides the ability to represent Mojom types and values as //! rust enums. -use std::collections::HashMap; +use std::collections::BTreeMap; +use std::sync::Arc; // FOR_RELEASE: The current AST is dead simple: standard recursive data // structures. We'll probably need an intermediate one as well to represent data @@ -35,13 +36,14 @@ UInt64, String, Enum { is_valid: Predicate<u32> }, - Union { variants: HashMap<u32, MojomType> }, + Union { variants: BTreeMap<u32, MojomType> }, // `field_names` is only for debugging; it should have the same // length as `fields` Struct { field_names: Vec<String>, fields: Vec<MojomType> }, // Mojom has separate sized/unsized array types; we could have two variants here, but // rust's type system can't enforce that the length is correct so there's little point. Array { element_type: Box<MojomType>, num_elements: Option<usize> }, + Map { key_type: Box<MojomType>, value_type: Box<MojomType> }, } /// Representation of a value of a MojomType. These are what get encoded/decoded @@ -49,7 +51,7 @@ // FOR_RELEASE: For the first iteration of the parser where we don't worry // about trying to be zero-copy, we just have this type own all its data. // We should migrate to a view type when we figure out how. -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, PartialEq, PartialOrd, Ord, Eq, Hash)] pub enum MojomValue { Bool(bool), Int8(i8), @@ -60,12 +62,14 @@ UInt32(u32), Int64(i64), UInt64(u64), - String(String), + String(MojomString), Enum(u32), Union(u32, Box<MojomValue>), Struct(Vec<String>, Vec<MojomValue>), // Invariant: all MojomValues in the array are the same type. Array(Vec<MojomValue>), + // We use a BTreeMap so that we get a consistent ordering when serializing. + Map(BTreeMap<MojomValue, MojomValue>), } /**************************************************************** */ @@ -107,7 +111,7 @@ Pointer { nested_data_type: PackedStructuredType }, /// A 128-bit value (not a pointer!) which contains a tag and a 64-bit value /// (which may be a pointer). - Union { variants: HashMap<u32, MojomWireType> }, + Union { variants: BTreeMap<u32, MojomWireType> }, } /// This type represents an element in the body of a struct, array, or union. @@ -170,11 +174,16 @@ num_elements_in_value: usize, }, Array { - element_type: Box<MojomWireType>, + // This uses Arc instead of Box so we can cheaply clone it during (de)parsing + element_type: Arc<MojomWireType>, array_type: PackedArrayType, }, Union { - variants: HashMap<u32, MojomWireType>, + variants: BTreeMap<u32, MojomWireType>, + }, + Map { + key_type: Arc<MojomWireType>, + value_type: Arc<MojomWireType>, }, } @@ -248,8 +257,8 @@ } /**************************************************************** */ -// Helper types that don't logically appear as part of the AST, -// but which are needed to satisfy the compiler +// Helper types and impls that don't logically appear as part of +// the AST, but which are needed to satisfy the compiler. /*************************************************************** */ /// A function which returns boolean. This is its own type so that @@ -281,3 +290,34 @@ (self.f)(arg) } } + +#[derive(Debug, Clone, PartialEq, PartialOrd, Ord, Eq, Hash)] +pub struct MojomString(Vec<u8>); + +impl MojomString { + pub fn to_bytes(&self) -> &[u8] { + &self.0 + } + + pub fn into_bytes(self) -> Vec<u8> { + self.0 + } + + pub fn to_string_lossy(&self) -> std::borrow::Cow<'_, str> { + String::from_utf8_lossy(&self.0) + } + + pub fn from_str(s: &str) -> Self { + MojomString(s.as_bytes().to_vec()) + } + + pub fn from_bytes(v: Vec<u8>) -> Self { + MojomString(v) + } +} + +impl From<String> for MojomString { + fn from(s: String) -> Self { + MojomString(s.into_bytes()) + } +}
diff --git a/mojo/public/rust/mojom_parser/deparse_values.rs b/mojo/public/rust/mojom_parser/deparse_values.rs index c0444c1..b68e981 100644 --- a/mojo/public/rust/mojom_parser/deparse_values.rs +++ b/mojo/public/rust/mojom_parser/deparse_values.rs
@@ -5,7 +5,8 @@ use crate::ast::*; use anyhow::{bail, Context, Result}; -use std::collections::HashMap; +use std::collections::BTreeMap; +use std::sync::Arc; fn get_field_at_ordinal(field_values: &[MojomValue], ordinal: Ordinal) -> Result<&MojomValue> { let field_value = field_values.get(ordinal).with_context(|| { @@ -53,6 +54,7 @@ // FOR_RELEASE: Should we care about which type of array this was originally? | (PackedStructuredType::Array { .. }, MojomValue::Array { .. }) | (PackedStructuredType::Array { .. }, MojomValue::String { .. }) + | (PackedStructuredType::Map { .. }, MojomValue::Map { .. }) | (PackedStructuredType::Union { .. }, MojomValue::Union { .. }) => true, _ => false, } @@ -107,14 +109,19 @@ packed_fields: &'a [StructuredBodyElementOwned], }, Array { - elements: &'a Vec<MojomValue>, - element_type: &'a Box<MojomWireType>, + contents: &'a MojomValue, + element_type: &'a Arc<MojomWireType>, array_type: &'a PackedArrayType, }, Union { tag: u32, value: &'a Box<MojomValue>, - variants: &'a HashMap<u32, MojomWireType>, + variants: &'a BTreeMap<u32, MojomWireType>, + }, + Map { + values_map: &'a BTreeMap<MojomValue, MojomValue>, + key_type: &'a Arc<MojomWireType>, + value_type: &'a Arc<MojomWireType>, }, } /// Information about a nested struct/array, which we will emit later @@ -152,10 +159,21 @@ fn deparse_array( data: &mut Vec<u8>, - element_values: &Vec<MojomValue>, - element_type: &Box<MojomWireType>, + contents: &MojomValue, + element_type: &Arc<MojomWireType>, array_type: &PackedArrayType, ) -> Result<()> { + let element_values = match (array_type, contents) { + (PackedArrayType::String, MojomValue::String(string)) => { + return deparse_string(data, string); + } + ( + PackedArrayType::SizedArray(_) | PackedArrayType::UnsizedArray, + MojomValue::Array(element_values), + ) => element_values, + _ => bail!("deparse_array: Got mismatched type and value: {array_type:?} vs. {contents:?}"), + }; + let num_elements = element_values.len(); if let PackedArrayType::SizedArray(expected_num_elements) = array_type @@ -186,7 +204,7 @@ enclosing_nested_data_list: Option<&mut Vec<NestedDataInfo<'a>>>, tag: u32, value: &'a Box<MojomValue>, - variants: &'a HashMap<u32, MojomWireType>, + variants: &'a BTreeMap<u32, MojomWireType>, ) -> Result<()> { // Write the union's header let expected_wire_type = variants @@ -208,6 +226,63 @@ ) } +fn deparse_map( + data: &mut Vec<u8>, + values_map: &BTreeMap<MojomValue, MojomValue>, + key_type: &Arc<MojomWireType>, + value_type: &Arc<MojomWireType>, +) -> Result<()> { + // FOR_RELEASE: These clones are way too expensive for production. We could + // avoid them by: + // 1. Using an Arc<[MojomValue]> or similar + // 2. Packing maps differently in the first place (having pack.rs create the + // struct body for us) + // 3. Having the deparser take things by value + // I'm delaying the fix because we might want to do (3) anyway, which solves the + // problem easily. If not, we'll have to choose (1) and (2) + let (keys, values) = values_map.iter().map(|(k, v)| (k.clone(), v.clone())).unzip(); + let field_values = vec![MojomValue::Array(keys), MojomValue::Array(values)]; + let packed_fields = [ + StructuredBodyElement::SingleValue( + 0, + MojomWireType::Pointer { + nested_data_type: PackedStructuredType::Array { + // This clone is cheap because it's in an Arc + element_type: key_type.clone(), + array_type: PackedArrayType::UnsizedArray, + }, + }, + ), + StructuredBodyElement::SingleValue( + 1, + MojomWireType::Pointer { + nested_data_type: PackedStructuredType::Array { + // This clone is cheap because it's in an Arc + element_type: value_type.clone(), + array_type: PackedArrayType::UnsizedArray, + }, + }, + ), + ]; + deparse_struct(data, &field_values, &packed_fields) +} + +fn deparse_string(data: &mut Vec<u8>, value: &MojomString) -> Result<()> { + let bytes = value.to_bytes(); + let num_bytes: u32 = bytes + .len() + .try_into() + .with_context(|| "Mojom cannot serialize strings of more than 2^32 bytes")?; + // Write header size (8 + num elements) and number of elements + data.extend(u32::to_le_bytes(8 + num_bytes)); + data.extend(u32::to_le_bytes(num_bytes)); + + // Write the actual string, then pad to 8 byte alignment + data.extend(bytes); + pad_to_alignment(data, 8); + Ok(()) +} + /// Deparse the fields of a struct (or union) after having parsed its header /// /// See the documentation of parse_union in parse_values.rs for an explanation @@ -282,10 +357,10 @@ packed_fields: packed_field_types, }, ( - MojomValue::Array(nested_data_fields), + MojomValue::Array(_) | MojomValue::String(_), PackedStructuredType::Array { element_type, array_type }, ) => NestedData::Array { - elements: nested_data_fields, + contents: nested_data_value, element_type, array_type, }, @@ -293,6 +368,10 @@ MojomValue::Union(tag, value), PackedStructuredType::Union { variants, .. }, ) => NestedData::Union { tag: *tag, value, variants }, + ( + MojomValue::Map(values_map), + PackedStructuredType::Map { key_type, value_type }, + ) => NestedData::Map { values_map, key_type, value_type }, _ => bail!( "Unexpected type for nested data: Expected {:?}, got {:?}", nested_data_type, @@ -357,12 +436,15 @@ NestedData::Struct { field_values, packed_fields } => { deparse_struct(data, field_values, packed_fields)? } - NestedData::Array { elements, element_type, array_type } => { - deparse_array(data, elements, element_type, array_type)? + NestedData::Array { contents, element_type, array_type } => { + deparse_array(data, contents, element_type, array_type)? } NestedData::Union { tag, value, variants } => { deparse_union(data, None, tag, value, variants)? } + NestedData::Map { values_map, key_type, value_type } => { + deparse_map(data, values_map, key_type, value_type)? + } } } @@ -392,8 +474,8 @@ nested_data_type: PackedStructuredType::Array { element_type, array_type }, .. }, - MojomValue::Array(elements), - ) => deparse_array(&mut data, elements, element_type, array_type)?, + MojomValue::Array(_) | MojomValue::String(_), + ) => deparse_array(&mut data, value, element_type, array_type)?, ( MojomWireType::Union { variants, .. } | MojomWireType::Pointer { @@ -402,6 +484,13 @@ }, MojomValue::Union(tag, value), ) => deparse_union(&mut data, None, *tag, value, variants)?, + ( + MojomWireType::Pointer { + nested_data_type: PackedStructuredType::Map { key_type, value_type }, + .. + }, + MojomValue::Map(values_map), + ) => deparse_map(&mut data, values_map, key_type, value_type)?, _ => { // This will fail, just calling for the error message let wire_elt: StructuredBodyElementMixed =
diff --git a/mojo/public/rust/mojom_parser/errors.rs b/mojo/public/rust/mojom_parser/errors.rs index d610c62..560f8ed 100644 --- a/mojo/public/rust/mojom_parser/errors.rs +++ b/mojo/public/rust/mojom_parser/errors.rs
@@ -46,6 +46,10 @@ InvalidDiscriminant { value: u32 }, /// Indicates that a sized array had an incorrect number of elements WrongArraySize { expected: usize, actual: usize }, + /// Indicates that a map had a duplicate key + DuplicateMapKey { dup: crate::ast::MojomValue }, + /// Indicates that the key and value arrays for a map were different lengths + MismatchedMap { key_len: usize, value_len: usize }, } impl ParsingError { @@ -96,6 +100,14 @@ pub fn wrong_array_size(offset: usize, expected: usize, actual: usize) -> ParsingError { ParsingError { offset, ty: ParsingErrorType::WrongArraySize { expected, actual } } } + + pub fn duplicate_map_key(offset: usize, dup: crate::ast::MojomValue) -> ParsingError { + ParsingError { offset, ty: ParsingErrorType::DuplicateMapKey { dup } } + } + + pub fn mismatched_map(offset: usize, key_len: usize, value_len: usize) -> ParsingError { + ParsingError { offset, ty: ParsingErrorType::MismatchedMap { key_len, value_len } } + } } // These messages necessarily refer to details of the binary format, and so they @@ -163,6 +175,12 @@ f, "Expected array to have {expected} elements, but it had {actual} elements." ), + ParsingErrorType::DuplicateMapKey { dup } => { + write!(f, "The following map key appeared more than once: {dup:?}") + } + ParsingErrorType::MismatchedMap { key_len, value_len } => { + write!(f, "Map had {key_len} keys and {value_len} values.") + } } } }
diff --git a/mojo/public/rust/mojom_parser/lib_pub.rs b/mojo/public/rust/mojom_parser/lib_pub.rs index f38de6e..ef934e5 100644 --- a/mojo/public/rust/mojom_parser/lib_pub.rs +++ b/mojo/public/rust/mojom_parser/lib_pub.rs
@@ -12,6 +12,6 @@ "//mojo/public/rust/mojom_parser:parsing_attribute"; } -pub use mojom_parser_core::{deserialize, serialize}; +pub use mojom_parser_core::{deserialize, serialize, MojomString}; pub use mojom_parser_core::{MojomParse, PrimitiveEnum}; pub use parsing_attribute::{MojomParse, PrimitiveEnum};
diff --git a/mojo/public/rust/mojom_parser/pack.rs b/mojo/public/rust/mojom_parser/pack.rs index 6a8977b..f0224762 100644 --- a/mojo/public/rust/mojom_parser/pack.rs +++ b/mojo/public/rust/mojom_parser/pack.rs
@@ -19,7 +19,8 @@ // bitfields.) use crate::ast::*; -use std::collections::HashMap; +use std::collections::BTreeMap; +use std::sync::Arc; /// Return the number of bytes we need to skip to reach the given alignment. fn bytes_to_align(current_offset: usize, required_alignment: usize) -> usize { @@ -150,7 +151,7 @@ }; } -fn pack_union_variants(variants: &HashMap<u32, MojomType>) -> HashMap<u32, MojomWireType> { +fn pack_union_variants(variants: &BTreeMap<u32, MojomType>) -> BTreeMap<u32, MojomWireType> { variants .iter() .map(|(tag, ty)| { @@ -181,7 +182,7 @@ MojomWireType::Pointer { nested_data_type: PackedStructuredType::Array { - element_type: Box::new(pack_mojom_type(element_type)), + element_type: Arc::new(pack_mojom_type(element_type)), array_type, }, } @@ -189,10 +190,16 @@ // Strings are packed as byte arrays MojomType::String => MojomWireType::Pointer { nested_data_type: PackedStructuredType::Array { - element_type: Box::new(pack_mojom_type(&MojomType::UInt8)), + element_type: Arc::new(pack_mojom_type(&MojomType::UInt8)), array_type: PackedArrayType::String, }, }, + MojomType::Map { key_type, value_type } => MojomWireType::Pointer { + nested_data_type: PackedStructuredType::Map { + key_type: Arc::new(pack_mojom_type(key_type)), + value_type: Arc::new(pack_mojom_type(value_type)), + }, + }, MojomType::Bool => MojomWireType::Leaf { leaf_type: PackedLeafType::Bool }, MojomType::Int8 => MojomWireType::Leaf { leaf_type: PackedLeafType::Int8 }, MojomType::Int16 => MojomWireType::Leaf { leaf_type: PackedLeafType::Int16 },
diff --git a/mojo/public/rust/mojom_parser/parse_primitives.rs b/mojo/public/rust/mojom_parser/parse_primitives.rs index ae33d8c..dec408c1 100644 --- a/mojo/public/rust/mojom_parser/parse_primitives.rs +++ b/mojo/public/rust/mojom_parser/parse_primitives.rs
@@ -64,12 +64,31 @@ remaining_bytes: data.remaining_bytes.len(), }, }; - data.remaining_bytes = - data.remaining_bytes.get((bytes_to_parse as usize)..).ok_or_else(mk_err)?; + data.remaining_bytes = data.remaining_bytes.get(bytes_to_parse..).ok_or_else(mk_err)?; data.bytes_parsed += bytes_to_parse; Ok(()) } +/// Returns a vector containing the next `bytes_to_parse` bytes, assuming they +/// exist. +pub fn parse_raw_bytes<'a, 'b>( + data: &'a mut ParserData<'b>, + bytes_to_parse: usize, +) -> ParsingResult<&'b [u8]> { + let mk_err = || ParsingError { + offset: data.bytes_parsed(), + ty: ParsingErrorType::NotEnoughData { + tried_to_parse: format!("raw bytes"), + expected_size: bytes_to_parse, + remaining_bytes: data.remaining_bytes.len(), + }, + }; + let (head, tail) = data.remaining_bytes.split_at_checked(bytes_to_parse).ok_or_else(mk_err)?; + data.remaining_bytes = tail; + data.bytes_parsed += bytes_to_parse; + Ok(head) +} + // Declares a function named $name, which takes a byte slice (&[u8]), reads the // first $size_in_bytes entries, and interprets them as a value of type // $target_type, assuming they are in little-endian order.
diff --git a/mojo/public/rust/mojom_parser/parse_values.rs b/mojo/public/rust/mojom_parser/parse_values.rs index a20d51bd..5333ec1f 100644 --- a/mojo/public/rust/mojom_parser/parse_values.rs +++ b/mojo/public/rust/mojom_parser/parse_values.rs
@@ -19,7 +19,8 @@ use crate::ast::*; use crate::errors::*; use crate::parse_primitives::*; -use std::collections::HashMap; +use std::collections::BTreeMap; +use std::sync::Arc; /// Parse a type without nested data, i.e. anything but a struct or array fn parse_leaf_element(data: &mut ParserData, ty: &PackedLeafType) -> ParsingResult<MojomValue> { @@ -61,6 +62,28 @@ } } +/// Check if the parsed keys for a map have duplicates, and error out if so +fn check_for_duplicate_keys(offset: usize, keys: &[MojomValue]) -> ParsingResult<()> { + // Check by inserting the keys into a hashset. + // insert returns false if the value was already present. + // Note that inserting references still compares the underlying values. + let mut unique_keys = std::collections::HashSet::new(); + let mut dup = MojomValue::Bool(false); + let dup_exists = keys.iter().any(|item| { + if !unique_keys.insert(item) { + dup = item.clone(); + true + } else { + false + } + }); + if dup_exists { + Err(ParsingError::duplicate_map_key(offset, dup)) + } else { + Ok(()) + } +} + // Mojom structs and arrays are never nested inside each other. Instead, they // are represented by a pointer with an offset to the actual data which appears // later in the message. @@ -133,7 +156,7 @@ fn parse_array( data: &mut ParserData, - element_type: &Box<MojomWireType>, + element_type: &Arc<MojomWireType>, array_type: &PackedArrayType, ) -> ParsingResult<MojomValue> { // Parse the array header @@ -152,6 +175,12 @@ )); } + // If this array represents a string, we don't need to do fancy parsing + // of the body, just grab the bytes and call it a day. + if *array_type == PackedArrayType::String { + return parse_string(data, size_in_bytes, num_elements); + } + // Make up dummy field names for debugging. let field_names = (0..num_elements).map(|idx| format!("Array_Element_{idx}")).collect::<Vec<_>>(); @@ -166,6 +195,7 @@ array_body.into_iter(), num_elements, )?; + Ok(MojomValue::Array(parsed_fields)) } @@ -195,7 +225,7 @@ fn parse_union<'a>( data: &mut ParserData, enclosing_nested_data_list: Option<&mut Vec<NestedDataInfo<'a>>>, - variants: &'a HashMap<u32, MojomWireType>, + variants: &'a BTreeMap<u32, MojomWireType>, ) -> ParsingResult<(u32, Option<MojomValue>)> { // Parse the union header let size_in_bytes = parse_size(data, false)?; @@ -239,6 +269,88 @@ Ok((tag, ret)) } +fn parse_map( + data: &mut ParserData, + key_type: &Arc<MojomWireType>, + value_type: &Arc<MojomWireType>, +) -> ParsingResult<MojomValue> { + let initial_bytes_parsed = data.bytes_parsed(); + // Maps are encoded as a struct containing a pair of arrays, one for + // the keys and one for the corresponding values. + let field_names = ["map_keys".to_string(), "map_values".to_string()]; + // FOR_RELEASE: This code is duplicated in deparse_values, maybe abstract + // it out. + let fields = [ + StructuredBodyElement::SingleValue( + 0, + MojomWireType::Pointer { + nested_data_type: PackedStructuredType::Array { + // This clone is cheap because it's in an Arc + element_type: key_type.clone(), + array_type: PackedArrayType::UnsizedArray, + }, + }, + ), + StructuredBodyElement::SingleValue( + 1, + MojomWireType::Pointer { + nested_data_type: PackedStructuredType::Array { + // This clone is cheap because it's in an Arc + element_type: value_type.clone(), + array_type: PackedArrayType::UnsizedArray, + }, + }, + ), + ]; + let parsed_arrays = parse_struct(data, &field_names, &fields, 2)?; + let parsed_fields = match parsed_arrays { + MojomValue::Struct(_, fields) => fields, + _ => panic!( + "Tried to parse a map like a struct, but got a non-struct MojomValue: {:?}", + parsed_arrays + ), + }; + let [keys, values] = parsed_fields.try_into().unwrap(); + match (keys, values) { + (MojomValue::Array(keys), MojomValue::Array(values)) => { + if keys.len() != values.len() { + return Err(ParsingError::mismatched_map( + initial_bytes_parsed, + keys.len(), + values.len(), + )); + } + // Map bodies are 24 bytes, and the key array immediately follows them. + let key_offset = initial_bytes_parsed + 24; + check_for_duplicate_keys(key_offset, &keys)?; + let map_val = keys.into_iter().zip(values).collect(); + Ok(MojomValue::Map(map_val)) + } + elts => { + panic!("Tried to parse a map like a struct, but got non-array elements: {:?} ", elts) + } + } +} + +/// Parse a string embedded in the mojom message. We don't do any validation of +/// the bytes (since mojom doesn't provide any guarantees), so this is as +/// simple as grabbing the bytes and ensuring the header was correct. +fn parse_string( + data: &mut ParserData, + size_in_bytes: usize, + num_elements: usize, +) -> ParsingResult<MojomValue> { + let string_contents = parse_raw_bytes(data, num_elements)?.to_vec(); + // Array header size should be the size of the header (8) + the number of bytes + if size_in_bytes != num_elements + 8 { + return Err(ParsingError::wrong_size(data.bytes_parsed(), size_in_bytes, num_elements + 8)); + } + // Array bodies always end at 8 byte alignment, though it's not + // reflected in the header's reported size. + skip_to_alignment(data, 8)?; + Ok(MojomValue::String(MojomString::from_bytes(string_contents))) +} + /// Parse the body of a struct, array, or union, having already consumed its /// header to figure out its expected size and what fields it has. /// @@ -397,6 +509,9 @@ PackedStructuredType::Union { variants } => parse_union(data, None, variants)? .1 .expect("Parsing nested union should always return a value"), + PackedStructuredType::Map { key_type, value_type } => { + parse_map(data, key_type, value_type)? + } }; if let Some(tag) = nested_data.union_discriminant { parsed_data = MojomValue::Union(tag, Box::new(parsed_data)) @@ -435,6 +550,9 @@ PackedStructuredType::Union { .. } => { panic!("Standalone unions are never behind pointers") } + PackedStructuredType::Map { key_type, value_type } => { + parse_map(&mut data, key_type, value_type) + } }, MojomWireType::Union { variants } => Ok(parse_union(&mut data, None, variants)? .1
diff --git a/mojo/public/rust/mojom_parser/parsing_attribute.rs b/mojo/public/rust/mojom_parser/parsing_attribute.rs index 4a2f733..0bd3615 100644 --- a/mojo/public/rust/mojom_parser/parsing_attribute.rs +++ b/mojo/public/rust/mojom_parser/parsing_attribute.rs
@@ -179,11 +179,11 @@ } use mojom_parser_core::*; - use std::collections::HashMap; + use std::collections::BTreeMap; impl MojomParse for #name { fn mojom_type() -> MojomType { - let variants : HashMap<u32, MojomType> = [ + let variants : BTreeMap<u32, MojomType> = [ #(#mojom_type_fields),* ].into(); MojomType::Union { variants }
diff --git a/mojo/public/rust/mojom_parser/parsing_trait.rs b/mojo/public/rust/mojom_parser/parsing_trait.rs index df8007f..87df022916 100644 --- a/mojo/public/rust/mojom_parser/parsing_trait.rs +++ b/mojo/public/rust/mojom_parser/parsing_trait.rs
@@ -3,9 +3,9 @@ // found in the LICENSE file. //! FOR_RELASE: Docs - use crate::ast::*; use crate::pack::pack_mojom_type; +use std::collections::HashMap; /// This trait allows a type to be serialized/deserialized into a Mojom message. pub trait MojomParse: @@ -81,7 +81,7 @@ /// Implements the MojomParse trait for a leaf type. (Ab)uses the fact that /// MojomType and MojomValue use identically-named variants. -macro_rules! mojom_parse_leaf_impl { +macro_rules! mojomparse_leaf_impl { ($target_type:ty, $variant:ident) => { impl MojomParse for $target_type { fn mojom_type() -> MojomType { @@ -113,17 +113,17 @@ }; } -mojom_parse_leaf_impl!(u8, UInt8); -mojom_parse_leaf_impl!(u16, UInt16); -mojom_parse_leaf_impl!(u32, UInt32); -mojom_parse_leaf_impl!(u64, UInt64); -mojom_parse_leaf_impl!(i8, Int8); -mojom_parse_leaf_impl!(i16, Int16); -mojom_parse_leaf_impl!(i32, Int32); -mojom_parse_leaf_impl!(i64, Int64); +mojomparse_leaf_impl!(u8, UInt8); +mojomparse_leaf_impl!(u16, UInt16); +mojomparse_leaf_impl!(u32, UInt32); +mojomparse_leaf_impl!(u64, UInt64); +mojomparse_leaf_impl!(i8, Int8); +mojomparse_leaf_impl!(i16, Int16); +mojomparse_leaf_impl!(i32, Int32); +mojomparse_leaf_impl!(i64, Int64); -mojom_parse_leaf_impl!(bool, Bool); -mojom_parse_leaf_impl!(String, String); +mojomparse_leaf_impl!(bool, Bool); +mojomparse_leaf_impl!(MojomString, String); // Implement MojomParse for any type that implements PrimitiveEnum and the other // requirements for MojomParse. All requirements are derived by @@ -205,3 +205,63 @@ MojomType::Array { element_type: Box::new(T::mojom_type()), num_elements: Some(N) } } } + +// Implement MojomParse for Maps +// Currently this is only implemented for HashMap, since that's +// probably what most users will want, but we can extend it to +// other map types if we need to. + +impl<K, V> From<HashMap<K, V>> for MojomValue +where + K: MojomParse + Eq + std::hash::Hash, + V: MojomParse, +{ + fn from(value: HashMap<K, V>) -> MojomValue { + let hashmap = value.into_iter().map(|(k, v)| (k.into(), v.into())).collect(); + MojomValue::Map(hashmap) + } +} + +impl<K, V> TryFrom<MojomValue> for HashMap<K, V> +where + K: MojomParse + Eq + std::hash::Hash, + V: MojomParse, +{ + type Error = anyhow::Error; + + fn try_from(value: MojomValue) -> anyhow::Result<Self> { + if let MojomValue::Map(hashmap) = value { + let converted_map: Self = hashmap + .into_iter() + // Map to Result<(K, V)> + .map(|(k, v)| { + let ret: anyhow::Result<(K, V)> = Ok((k.try_into()?, v.try_into()?)); + ret + }) + // Fail if any of the conversions failed + // FOR_RELEASE: It would be nice to use Itertools::process_results + // instead of collecting here + .collect::<Result<_, _>>()?; + return Ok(converted_map); + } else { + anyhow::bail!( + "Cannot construct a value of type {} from this MojomValue: {:?}", + std::any::type_name::<Self>(), + value + ); + } + } +} + +impl<K, V> MojomParse for HashMap<K, V> +where + K: MojomParse + Eq + std::hash::Hash, + V: MojomParse, +{ + fn mojom_type() -> MojomType { + MojomType::Map { + key_type: Box::new(K::mojom_type()), + value_type: Box::new(V::mojom_type()), + } + } +}
diff --git a/mojo/public/rust/mojom_parser/test/test_mojomparse.rs b/mojo/public/rust/mojom_parser/test/test_mojomparse.rs index a6eff65..e9beb018 100644 --- a/mojo/public/rust/mojom_parser/test/test_mojomparse.rs +++ b/mojo/public/rust/mojom_parser/test/test_mojomparse.rs
@@ -24,6 +24,7 @@ use mojom_parser_core::*; use parser_unittests_rust::parser_unittests::*; +use std::collections::HashMap; use std::sync::LazyLock; /// Represents a type defined in a Mojom file. @@ -1004,7 +1005,7 @@ ($element_type:expr, $num_elements:expr) => { MojomWireType::Pointer { nested_data_type: PackedStructuredType::Array { - element_type: Box::new($element_type), + element_type: std::sync::Arc::new($element_type), array_type: if let Some(n) = $num_elements { PackedArrayType::SizedArray(n) } else { @@ -1334,3 +1335,442 @@ ), ); } + +macro_rules! map { + ($key_type:expr, $value_type:expr) => { + MojomType::Map { key_type: Box::new($key_type), value_type: Box::new($value_type) } + }; +} + +macro_rules! packed_map { + ($key_type:expr, $value_type:expr) => { + MojomWireType::Pointer { + nested_data_type: PackedStructuredType::Map { + key_type: std::sync::Arc::new($key_type), + value_type: std::sync::Arc::new($value_type), + }, + } + }; +} + +// Mojom Definition: +// map<uint8, uint8> +static MAP_U8_U8_TY: LazyLock<TestType> = LazyLock::new(|| TestType { + type_name: "map<uint8, uint8>", + base_type: map!(MojomType::UInt8, MojomType::UInt8), + packed_type: packed_map!(bare_leaf!(PackedLeafType::UInt8), bare_leaf!(PackedLeafType::UInt8)), +}); + +fn map_u8_u8_mojom(elts: HashMap<u8, u8>) -> MojomValue { + MojomValue::Map( + elts.into_iter().map(|(k, v)| (MojomValue::UInt8(k), MojomValue::UInt8(v))).collect(), + ) +} + +// Mojom Definition: +// map<bool, uint16> +static MAP_BOOL_U16_TY: LazyLock<TestType> = LazyLock::new(|| TestType { + type_name: "map<bool, uint16>", + base_type: map!(MojomType::Bool, MojomType::UInt16), + packed_type: packed_map!(bare_leaf!(PackedLeafType::Bool), bare_leaf!(PackedLeafType::UInt16)), +}); + +fn map_bool_u16_mojom(elts: HashMap<bool, u16>) -> MojomValue { + MojomValue::Map( + elts.into_iter().map(|(k, v)| (MojomValue::Bool(k), MojomValue::UInt16(v))).collect(), + ) +} + +// Mojom Definition: +// map<TestEnum, int32> +static MAP_ENUM_I32_TY: LazyLock<TestType> = LazyLock::new(|| TestType { + type_name: "map<TestEnum, int32>", + base_type: map!(MojomType::Enum { is_valid: TEST_ENUM_PRED }, MojomType::Int32), + packed_type: packed_map!( + bare_leaf!(PackedLeafType::Enum { is_valid: TEST_ENUM_PRED }), + bare_leaf!(PackedLeafType::Int32) + ), +}); + +fn map_enum_i32_mojom(elts: HashMap<TestEnum, i32>) -> MojomValue { + MojomValue::Map( + elts.into_iter().map(|(k, v)| (MojomValue::Enum(k.into()), MojomValue::Int32(v))).collect(), + ) +} + +// Mojom Definition: +// map<int8, FourInts> +static MAP_I8_FOURINTS_TY: LazyLock<TestType> = LazyLock::new(|| TestType { + type_name: "map<int8, FourInts>", + base_type: map!(MojomType::Int8, FOUR_INTS_TY.base_type.clone()), + packed_type: packed_map!(bare_leaf!(PackedLeafType::Int8), FOUR_INTS_TY.packed_type.clone()), +}); + +fn map_i8_fourints_mojom(elts: HashMap<i8, FourInts>) -> MojomValue { + MojomValue::Map( + elts.into_iter().map(|(k, v)| (MojomValue::Int8(k), MojomValue::from(v))).collect(), + ) +} + +// Mojom Definition: +// map<int8, NestedUnion> +static MAP_I8_NESTEDUNION_TY: LazyLock<TestType> = LazyLock::new(|| TestType { + type_name: "map<int8, NestedUnion>", + base_type: map!(MojomType::Int8, NESTED_UNION_TY.base_type.clone()), + packed_type: packed_map!(bare_leaf!(PackedLeafType::Int8), NESTED_UNION_TY.packed_type.clone()), +}); + +fn map_i8_nestedunion_mojom(elts: HashMap<i8, NestedUnion>) -> MojomValue { + MojomValue::Map( + elts.into_iter().map(|(k, v)| (MojomValue::Int8(k), MojomValue::from(v))).collect(), + ) +} + +// Mojom Definition: +// map<int8, map<int16, uint32>> +static MAP_I8_MAP_I16_U32_TY: LazyLock<TestType> = LazyLock::new(|| TestType { + type_name: "map<int8, map<int16, uint32>>", + base_type: map!(MojomType::Int8, map!(MojomType::Int16, MojomType::UInt32)), + packed_type: packed_map!( + bare_leaf!(PackedLeafType::Int8), + packed_map!(bare_leaf!(PackedLeafType::Int16), bare_leaf!(PackedLeafType::UInt32)) + ), +}); + +fn map_i8_map_i16_u32_mojom(elts: HashMap<i8, HashMap<i16, u32>>) -> MojomValue { + MojomValue::Map( + elts.into_iter().map(|(k, v)| (MojomValue::Int8(k), MojomValue::from(v))).collect(), + ) +} + +// Mojom Definition: +// struct Maps { +// map<uint8, uint8> eights; +// map<bool, uint16> bools; +// map<TestEnum, int32> enums; +// map<int8, FourInts> to_struct; +// map<int8, NestedUnion> to_union; +// map<int8, map<int16, uint32>> to_map; +// } +static MAPS_TY: LazyLock<TestType> = LazyLock::new(|| TestType { + type_name: "Maps", + base_type: wrap_struct_fields_type(vec![ + ("eights".to_string(), MAP_U8_U8_TY.base_type.clone()), + ("bools".to_string(), MAP_BOOL_U16_TY.base_type.clone()), + ("enums".to_string(), MAP_ENUM_I32_TY.base_type.clone()), + ("to_struct".to_string(), MAP_I8_FOURINTS_TY.base_type.clone()), + ("to_union".to_string(), MAP_I8_NESTEDUNION_TY.base_type.clone()), + ("to_map".to_string(), MAP_I8_MAP_I16_U32_TY.base_type.clone()), + ]), + packed_type: wrap_packed_struct_fields( + vec![ + ("eights".to_string(), MAP_U8_U8_TY.as_struct_field(0)), + ("bools".to_string(), MAP_BOOL_U16_TY.as_struct_field(1)), + ("enums".to_string(), MAP_ENUM_I32_TY.as_struct_field(2)), + ("to_struct".to_string(), MAP_I8_FOURINTS_TY.as_struct_field(3)), + ("to_union".to_string(), MAP_I8_NESTEDUNION_TY.as_struct_field(4)), + ("to_map".to_string(), MAP_I8_MAP_I16_U32_TY.as_struct_field(5)), + ], + 6, + ), +}); + +fn maps_mojom( + eights: HashMap<u8, u8>, + bools: HashMap<bool, u16>, + enums: HashMap<TestEnum, i32>, + to_struct: HashMap<i8, FourInts>, + to_union: HashMap<i8, NestedUnion>, + to_map: HashMap<i8, HashMap<i16, u32>>, +) -> MojomValue { + wrap_struct_fields_value(vec![ + ("eights".to_string(), map_u8_u8_mojom(eights)), + ("bools".to_string(), map_bool_u16_mojom(bools)), + ("enums".to_string(), map_enum_i32_mojom(enums)), + ("to_struct".to_string(), map_i8_fourints_mojom(to_struct)), + ("to_union".to_string(), map_i8_nestedunion_mojom(to_union)), + ("to_map".to_string(), map_i8_map_i16_u32_mojom(to_map)), + ]) +} + +#[gtest(MojomParser, TestMaps)] +fn test_maps() { + let eights_data = [(1, 2), (3, 4)]; + MAP_U8_U8_TY.validate_mojomparse::<HashMap<u8, u8>>( + eights_data.clone().into(), + map_u8_u8_mojom(eights_data.clone().into()), + ); + + let bools_data = [(true, 10), (false, 20)]; + MAP_BOOL_U16_TY.validate_mojomparse::<HashMap<bool, u16>>( + bools_data.clone().into(), + map_bool_u16_mojom(bools_data.clone().into()), + ); + + let enums_data = [(TestEnum::Zero, -1), (TestEnum::Seven, -2)]; + MAP_ENUM_I32_TY.validate_mojomparse::<HashMap<TestEnum, i32>>( + enums_data.clone().into(), + map_enum_i32_mojom(enums_data.clone().into()), + ); + + let to_struct_data = [(5, FourInts { a: 1, b: 2, c: 3, d: 4 })]; + MAP_I8_FOURINTS_TY.validate_mojomparse::<HashMap<i8, FourInts>>( + to_struct_data.clone().into(), + map_i8_fourints_mojom(to_struct_data.clone().into()), + ); + + let to_union_data = [(-8, NestedUnion::n(50)), (-9, NestedUnion::u(BaseUnion::n1(10)))]; + MAP_I8_NESTEDUNION_TY.validate_mojomparse::<HashMap<i8, NestedUnion>>( + to_union_data.clone().into(), + map_i8_nestedunion_mojom(to_union_data.clone().into()), + ); + + let to_map_data = + [(1, [(10, 100), (20, 200)].into()), (2, [(30, 300), (40, 400), (50, 500)].into())]; + MAP_I8_MAP_I16_U32_TY.validate_mojomparse::<HashMap<i8, HashMap<i16, u32>>>( + to_map_data.clone().into(), + map_i8_map_i16_u32_mojom(to_map_data.clone().into()), + ); + + MAPS_TY.validate_mojomparse( + Maps { + eights: eights_data.clone().into(), + bools: bools_data.clone().into(), + enums: enums_data.clone().into(), + to_struct: to_struct_data.clone().into(), + to_union: to_union_data.clone().into(), + to_map: to_map_data.clone().into(), + }, + maps_mojom( + eights_data.into(), + bools_data.into(), + enums_data.into(), + to_struct_data.into(), + to_union_data.into(), + to_map_data.into(), + ), + ); +} + +// Mojom definition: string +static STRING_TY: LazyLock<TestType> = LazyLock::new(|| TestType { + type_name: "string", + base_type: MojomType::String, + packed_type: MojomWireType::Pointer { + nested_data_type: PackedStructuredType::Array { + element_type: std::sync::Arc::new(MojomWireType::Leaf { + leaf_type: PackedLeafType::UInt8, + }), + array_type: PackedArrayType::String, + }, + }, +}); + +// Mojom Definition: array<string> +static ARRAY_STRING_TY: LazyLock<TestType> = LazyLock::new(|| TestType { + type_name: "array<string>", + base_type: array!(MojomType::String, None), + packed_type: packed_array!(STRING_TY.packed_type.clone(), None), +}); + +// Mojom Definition: map<uint8, string> +static MAP_U8_STRING_TY: LazyLock<TestType> = LazyLock::new(|| TestType { + type_name: "map<uint8, string>", + base_type: map!(MojomType::UInt8, MojomType::String), + packed_type: packed_map!(bare_leaf!(PackedLeafType::UInt8), STRING_TY.packed_type.clone()), +}); + +// Mojom Definition: map<string, int16> +static MAP_STRING_I16_TY: LazyLock<TestType> = LazyLock::new(|| TestType { + type_name: "map<string, int16>", + base_type: map!(MojomType::String, MojomType::Int16), + packed_type: packed_map!(STRING_TY.packed_type.clone(), bare_leaf!(PackedLeafType::Int16)), +}); + +// Mojom Definition: +// struct Strings { +// string str; +// array<string> arr; +// map<uint8, string> to_str; +// map<string, int16> from_str; +// HoldsComplexTypes u; +// } +static STRINGS_TY: LazyLock<TestType> = LazyLock::new(|| TestType { + type_name: "Strings", + base_type: wrap_struct_fields_type(vec![ + ("str".to_string(), STRING_TY.base_type.clone()), + ("arr".to_string(), ARRAY_STRING_TY.base_type.clone()), + ("to_str".to_string(), MAP_U8_STRING_TY.base_type.clone()), + ("from_str".to_string(), MAP_STRING_I16_TY.base_type.clone()), + ]), + packed_type: wrap_packed_struct_fields( + vec![ + ("str".to_string(), STRING_TY.as_struct_field(0)), + ("arr".to_string(), ARRAY_STRING_TY.as_struct_field(1)), + ("to_str".to_string(), MAP_U8_STRING_TY.as_struct_field(2)), + ("from_str".to_string(), MAP_STRING_I16_TY.as_struct_field(3)), + ], + 4, + ), +}); + +fn mojomvalue_from_str(str: &str) -> MojomValue { + MojomValue::String(MojomString::from_str(str)) +} + +fn strings_mojom( + str: &str, + arr: Vec<&str>, + to_str: HashMap<u8, &str>, + from_str: HashMap<&str, i16>, +) -> MojomValue { + wrap_struct_fields_value(vec![ + ("str".to_string(), mojomvalue_from_str(str)), + ("arr".to_string(), MojomValue::Array(arr.into_iter().map(mojomvalue_from_str).collect())), + ( + "to_str".to_string(), + MojomValue::Map( + to_str + .into_iter() + .map(|(k, v)| (MojomValue::UInt8(k), mojomvalue_from_str(v))) + .collect(), + ), + ), + ( + "from_str".to_string(), + MojomValue::Map( + from_str + .into_iter() + .map(|(k, v)| (mojomvalue_from_str(k), MojomValue::Int16(v))) + .collect(), + ), + ), + ]) +} + +#[gtest(MojomParser, TestStrings)] +fn test_strings() { + STRINGS_TY.validate_mojomparse( + Strings { + str: MojomString::from_str("test"), + arr: vec![MojomString::from_str("a"), MojomString::from_str("b")], + to_str: [(1, MojomString::from_str("one")), (2, MojomString::from_str("two"))].into(), + from_str: [(MojomString::from_str("three"), 3), (MojomString::from_str("four"), 4)] + .into(), + }, + strings_mojom( + "test", + vec!["a", "b"], + [(1, "one"), (2, "two")].into(), + [("three", 3), ("four", 4)].into(), + ), + ); + + STRINGS_TY.validate_mojomparse( + Strings { + str: MojomString::from_str(""), + arr: vec![], + to_str: HashMap::new(), + from_str: HashMap::new(), + }, + strings_mojom("", vec![], HashMap::new(), HashMap::new()), + ); +} + +// Mojom Definition: +// union HoldsComplexTypes { +// string str; +// array<int8> arr; +// map<int8, int8> m; +// } +static HOLDS_COMPLEX_TYPES_TY: LazyLock<TestType> = LazyLock::new(|| TestType { + type_name: "HoldsComplexTypes", + base_type: MojomType::Union { + variants: [ + (0, STRING_TY.base_type.clone()), + (1, ARRAY_INT16_TY.base_type.clone()), + (2, MAP_U8_U8_TY.base_type.clone()), + ] + .into(), + }, + packed_type: MojomWireType::Union { + variants: [ + (0, STRING_TY.as_union_field()), + (1, ARRAY_INT16_TY.as_union_field()), + (2, MAP_U8_U8_TY.as_union_field()), + ] + .into(), + }, +}); + +fn holds_complex_types_mojom_str(str: &str) -> MojomValue { + MojomValue::Union(0, Box::new(MojomValue::String(MojomString::from_str(str)))) +} + +fn holds_complex_types_mojom_arr(arr: Vec<i16>) -> MojomValue { + MojomValue::Union( + 1, + Box::new(MojomValue::Array(arr.into_iter().map(MojomValue::Int16).collect())), + ) +} + +fn holds_complex_types_mojom_m(map: HashMap<u8, u8>) -> MojomValue { + MojomValue::Union( + 2, + Box::new(MojomValue::Map( + map.into_iter().map(|(k, v)| (MojomValue::UInt8(k), MojomValue::UInt8(v))).collect(), + )), + ) +} + +static COMPLEX_UNION_HOLDER_TY: LazyLock<TestType> = LazyLock::new(|| TestType { + type_name: "ComplexUnionHolder", + base_type: wrap_struct_fields_type(vec![( + "u".to_string(), + HOLDS_COMPLEX_TYPES_TY.base_type.clone(), + )]), + packed_type: wrap_packed_struct_fields( + vec![("u".to_string(), HOLDS_COMPLEX_TYPES_TY.as_struct_field(0))], + 1, + ), +}); + +#[gtest(MojomParser, TestComplexUnion)] +fn test_complex_union() { + // Test both the union and the union inside a struct + HOLDS_COMPLEX_TYPES_TY.validate_mojomparse( + HoldsComplexTypes::str(MojomString::from_str("hello")), + holds_complex_types_mojom_str("hello"), + ); + + COMPLEX_UNION_HOLDER_TY.validate_mojomparse( + ComplexUnionHolder { u: HoldsComplexTypes::str(MojomString::from_str("eek")) }, + wrap_struct_fields_value(vec![("u".to_string(), holds_complex_types_mojom_str("eek"))]), + ); + + HOLDS_COMPLEX_TYPES_TY.validate_mojomparse( + HoldsComplexTypes::arr(vec![1, 2, 3]), + holds_complex_types_mojom_arr(vec![1, 2, 3]), + ); + + COMPLEX_UNION_HOLDER_TY.validate_mojomparse( + ComplexUnionHolder { u: HoldsComplexTypes::arr(vec![99, 222, 301, 282]) }, + wrap_struct_fields_value(vec![( + "u".to_string(), + holds_complex_types_mojom_arr(vec![99, 222, 301, 282]), + )]), + ); + + HOLDS_COMPLEX_TYPES_TY.validate_mojomparse( + HoldsComplexTypes::m([(1, 10), (2, 20)].into()), + holds_complex_types_mojom_m([(1, 10), (2, 20)].into()), + ); + + COMPLEX_UNION_HOLDER_TY.validate_mojomparse( + ComplexUnionHolder { u: HoldsComplexTypes::m([(19, 120), (29, 210)].into()) }, + wrap_struct_fields_value(vec![( + "u".to_string(), + holds_complex_types_mojom_m([(19, 120), (29, 210)].into()), + )]), + ); +}
diff --git a/mojo/public/rust/mojom_parser/test/test_parser.rs b/mojo/public/rust/mojom_parser/test/test_parser.rs index 29531cc..ed57e96 100644 --- a/mojo/public/rust/mojom_parser/test/test_parser.rs +++ b/mojo/public/rust/mojom_parser/test/test_parser.rs
@@ -19,6 +19,8 @@ "//mojo/public/rust/mojom_parser:validation_parser"; } +use std::iter; + use mojom_parser_core::*; use parser_unittests_rust::parser_unittests::*; use rust_gtest_interop::prelude::*; @@ -621,3 +623,277 @@ Ok(()) } + +// Note that tests involving maps are especially tricky, because semantically +// the order of (key, value) pairs doesn't matter, but since we do exact +// comparisons it matters when we specify the wire data here. +// Our implementation uses a BTreeMap to guarantee that we always serialize in +// a sorted order. +#[gtest(MojomParser, TestMapParsing)] +fn test_map_parsing() -> anyhow::Result<()> { + use std::collections::HashMap; + + validate_parsing::<HashMap<i8, i8>>( + [(1, 10), (3, 40), (8, 99)].into(), + concat!( + // Map header + "[u4]24 [u4]0 [dist8]keys_ptr [dist8]values_ptr ", + // keys array + "[anchr]keys_ptr ", + "[u4]11 [u4]3 ", // Keys header: size, num_elements + "[s1]1 [s1]3 [s1]8 [u1]0 [u4]0 ", + // values array + "[anchr]values_ptr ", + "[u4]11 [u4]3 ", // Values header: size, num_elements + "[s1]10 [s1]40 [s1]99 [u1]0 [u4]0 ", + ), + )?; + + // Empty maps are fine + validate_parsing::<HashMap<i8, i8>>( + [].into(), + concat!( + // Map struct + "[u4]24 [u4]0 [dist8]keys_ptr [dist8]values_ptr ", + // keys array + "[anchr]keys_ptr [u4]8 [u4]0 ", + // values array + "[anchr]values_ptr [u4]8 [u4]0 ", + ), + )?; + + // Mismatched sizes are not fine + validate_parsing_failure::<HashMap<i8, i8>>(concat!( + // Map struct + "[u4]24 [u4]0 [dist8]keys_ptr [dist8]values_ptr ", + // keys array + "[anchr]keys_ptr [u4]9 [u4]1 ", + "[s1]1 [s1]0 [s2]0 [s4]0 ", + // values array + "[anchr]values_ptr [u4]8 [u4]0 ", + ))?; + validate_parsing_failure::<HashMap<i8, i8>>(concat!( + // Map struct + "[u4]24 [u4]0 [dist8]keys_ptr [dist8]values_ptr ", + // keys array + "[anchr]keys_ptr [u4]9 [u4]1 ", + "[s1]1 [s1]0 [s2]0 [s4]0 ", + // values array + "[anchr]values_ptr [u4]10 [u4]2 ", + "[s1]2 [s1]3 [s2]0 [s4]0 ", + ))?; + + // Nor are duplicate keys + validate_parsing_failure::<HashMap<i8, i8>>(concat!( + // Map struct + "[u4]24 [u4]0 [dist8]keys_ptr [dist8]values_ptr ", + // keys array + "[anchr]keys_ptr [u4]10 [u4]2 ", + "[s1]1 [s1]1 [s2]0 [s4]0 ", + // values array + "[anchr]values_ptr [u4]10 [u4]2 ", + "[s1]2 [s1]3 [s2]0 [s4]0 ", + ))?; + + validate_parsing::<HashMap<bool, u16>>( + [(false, 1020), (true, 3040)].into(), + concat!( + // Map header + "[u4]24 [u4]0 [dist8]keys_ptr [dist8]values_ptr ", + // keys array + "[anchr]keys_ptr ", + "[u4]9 [u4]2 [b]00000010 [u1]0 [u2]0 [u4]0 ", + // values array + "[anchr]values_ptr ", + "[u4]12 [u4]2 [u2]1020 [u2]3040 [u4]0", + ), + )?; + + validate_parsing::<HashMap<TestEnum, i32>>( + [(TestEnum::Seven, -2), (TestEnum::Four, -3), (TestEnum::Zero, -1), (TestEnum::Three, -3)] + .into(), + concat!( + // Map header + "[u4]24 [u4]0 [dist8]keys_ptr [dist8]values_ptr ", + // keys array + "[anchr]keys_ptr ", + // Note that keys are sorted in ascending order + "[u4]24 [u4]4 [u4]0 [u4]3 [u4]4 [u4]7 ", + // values array + "[anchr]values_ptr ", + // And the values are sorted to match + "[u4]24 [u4]4 [s4]-1 [s4]-3 [s4]-3 [s4]-2 ", + ), + )?; + + validate_parsing::<HashMap<i8, FourInts>>( + [(1, FourInts { a: 1, b: 2, c: 3, d: 4 }), (5, FourInts { a: 5, b: 6, c: 7, d: 8 })].into(), + concat!( + // Map header + "[u4]24 [u4]0 [dist8]keys_ptr [dist8]values_ptr ", + // keys array + "[anchr]keys_ptr [u4]10 [u4]2 [s1]1 [s1]5 [u2]0 [u4]0 ", + // values array + "[anchr]values_ptr ", + "[u4]24 [u4]2 [dist8]v0 [dist8]v1 ", + "[anchr]v0 [u4]24 [u4]0 [s1]1 [u1]0 [s2]2 [s4]3 [s8]4 ", + "[anchr]v1 [u4]24 [u4]0 [s1]5 [u1]0 [s2]6 [s4]7 [s8]8 ", + ), + )?; + + validate_parsing::<HashMap<i8, NestedUnion>>( + [ + (-1, NestedUnion::n(10)), + (-2, NestedUnion::u(BaseUnion::e1(TestEnum::Seven))), + (-3, NestedUnion::n(23)), + ] + .into(), + concat!( + // Map header + "[u4]24 [u4]0 [dist8]keys_ptr [dist8]values_ptr ", + // keys array + "[anchr]keys_ptr [u4]11 [u4]3 [s1]-3 [s1]-2 [s1]-1 [s1]0 [u4]0 ", + // values array + "[anchr]values_ptr ", + "[u4]56 [u4]3 ", + "[u4]16 [u4]0 [u8]23 ", + "[u4]16 [u4]1 [dist8]v1 ", + "[u4]16 [u4]0 [u8]10 ", + "[anchr]v1 [u4]16 [u4]2 [u8]7", + ), + )?; + + validate_parsing::<HashMap<i8, HashMap<i16, u32>>>( + [(1, [(10, 100), (20, 200)].into()), (2, [(30, 300), (40, 400), (50, 500)].into())].into(), + concat!( + // Toplevel map header + "[u4]24 [u4]0 [dist8]keys_ptr [dist8]values_ptr ", + // Toplevel keys array + "[anchr]keys_ptr [u4]10 [u4]2 [s1]1 [s1]2 [u2]0 [u4]0 ", + // Toplevel values array + "[anchr]values_ptr ", + "[u4]24 [u4]2 [dist8]v0 [dist8]v1 ", + // First nested map + "[anchr]v0 [u4]24 [u4]0 [dist8]v0_keys [dist8]v0_values ", + "[anchr]v0_keys [u4]12 [u4]2 [s2]10 [s2]20 [u4]0 ", + "[anchr]v0_values [u4]16 [u4]2 [u4]100 [u4]200 ", + // Second nested map + "[anchr]v1 [u4]24 [u4]0 [dist8]v1_keys [dist8]v1_values ", + "[anchr]v1_keys [u4]14 [u4]3 [s2]30 [s2]40 [s2]50 [u2]0 ", + "[anchr]v1_values [u4]20 [u4]3 [u4]300 [u4]400 [u4]500 [u4]0 ", + ), + )?; + + Ok(()) +} + +// Create the expected wire format representation of string. +fn str_wire_format(str: &str) -> String { + let size = 8 + str.len(); + let num_chars = str.len(); + let padding = (8 - (str.len() % 8)) % 8; + let body: String = + str.as_bytes().iter().fold("".to_string(), |acc, b| format!("{acc} [u1]{b}")); + let padding: String = iter::repeat_n("[u1]0 ", padding).collect(); + format!("[u4]{size} [u4]{num_chars} {body} {padding}") +} + +#[gtest(MojomParser, TestStringParsing)] +fn test_string_parsing() -> anyhow::Result<()> { + use std::collections::HashMap; + + validate_parsing::<MojomString>(MojomString::from_str("hello"), &str_wire_format("hello"))?; + + validate_parsing::<Vec<MojomString>>( + vec![ + MojomString::from_str("life"), + MojomString::from_str("universe"), + MojomString::from_str("everything"), + ], + &format!( + "{} {} {} {} {} {} {} {}", + "[u4]32 [u4]3 ", + "[dist8]life_ptr [dist8]universe_ptr [dist8]everything_ptr", + "[anchr]life_ptr", + &str_wire_format("life"), + "[anchr]universe_ptr", + &str_wire_format("universe"), + "[anchr]everything_ptr", + &str_wire_format("everything"), + ), + )?; + + validate_parsing::<HashMap<u8, MojomString>>( + [(10, MojomString::from_str("ten")), (20, MojomString::from_str("twenty"))].into(), + &format!( + "{} {} {} {} {} {} {} {} {}", + "[u4]24 [u4]0 [dist8]keys_ptr [dist8]values_ptr ", + "[anchr]keys_ptr ", + "[u4]10 [u4]2 [u1]10 [u1]20 [u2]0 [u4]0 ", + "[anchr]values_ptr ", + "[u4]24 [u4]2 [dist8]ten_ptr [dist8]twenty_ptr ", + "[anchr]ten_ptr ", + &str_wire_format("ten"), + "[anchr]twenty_ptr ", + &str_wire_format("twenty"), + ), + )?; + + validate_parsing::<HashMap<MojomString, i16>>( + [("three".to_string().into(), 3), ("four".to_string().into(), 4)].into(), + &format!( + "{} {} {} {} {} {} {} {} {}", + "[u4]24 [u4]0 [dist8]keys_ptr [dist8]values_ptr ", + "[anchr]keys_ptr ", + "[u4]24 [u4]2 [dist8]four_ptr [dist8]three_ptr ", + "[anchr]four_ptr ", + &str_wire_format("four"), + "[anchr]three_ptr ", + &str_wire_format("three"), + "[anchr]values_ptr ", + "[u4]12 [u4]2 [s2]4 [s2]3 [u4]0 ", + ), + )?; + Ok(()) +} + +#[gtest(MojomParser, TestComplexUnionParsing)] +fn test_complex_union_parsing() -> anyhow::Result<()> { + // HoldsComplexTypes: string + validate_parsing::<HoldsComplexTypes>( + HoldsComplexTypes::str(MojomString::from_str("union_string")), + &format!( + "[u4]16 [u4]0 [dist8]union_str_ptr [anchr]union_str_ptr {}", + &str_wire_format("union_string") + ), + )?; + + validate_parsing::<ComplexUnionHolder>( + ComplexUnionHolder { u: HoldsComplexTypes::str(MojomString::from_str("union_string")) }, + &format!( + "[u4]24 [u4]0 [u4]16 [u4]0 [dist8]union_str_ptr [anchr]union_str_ptr {}", + &str_wire_format("union_string") + ), + )?; + + // HoldsComplexTypes: array<int16> + validate_parsing::<HoldsComplexTypes>( + HoldsComplexTypes::arr(vec![-10, -20, -30]), + concat!( + "[u4]16 [u4]1 [dist8]union_arr_ptr ", + "[anchr]union_arr_ptr [u4]14 [u4]3 [s2]-10 [s2]-20 [s2]-30 [u2]0" + ), + )?; + + // HoldsComplexTypes: map<uint8, uint8> + validate_parsing::<HoldsComplexTypes>( + HoldsComplexTypes::m([(100, 1), (101, 2)].into()), + concat!( + "[u4]16 [u4]2 [dist8]union_map_ptr ", + "[anchr]union_map_ptr [u4]24 [u4]0 [dist8]keys_ptr [dist8]values_ptr ", + "[anchr]keys_ptr [u4]10 [u4]2 [u1]100 [u1]101 [u2]0 [u4]0 ", + "[anchr]values_ptr [u4]10 [u4]2 [u1]1 [u1]2 [u2]0 [u4]0 ", + ), + )?; + Ok(()) +}
diff --git a/mojo/public/rust/mojom_parser/test_util/parser_unittests.test-mojom b/mojo/public/rust/mojom_parser/test_util/parser_unittests.test-mojom index 13e1ec5..ecd6cc65 100644 --- a/mojo/public/rust/mojom_parser/test_util/parser_unittests.test-mojom +++ b/mojo/public/rust/mojom_parser/test_util/parser_unittests.test-mojom
@@ -161,4 +161,32 @@ array<FourInts> fourints; array<array<uint8>> nested; array<array<uint8, 2>, 3> nested_sized; +}; + +struct Maps { + map<uint8, uint8> eights; + map<bool, uint16> bools; + map<TestEnum, int32> enums; + map<int8, FourInts> to_struct; + map<int8, NestedUnion> to_union; + map<int8, map<int16, uint32>> to_map; +}; + +struct Strings { + string str; + array<string> arr; + map<uint8, string> to_str; + map<string, int16> from_str; +}; + +// Now that we have arrays, maps, and strings, we should +// make sure a union can hold all of them properly. +union HoldsComplexTypes { + string str; + array<int16> arr; + map<uint8, uint8> m; +}; + +struct ComplexUnionHolder { + HoldsComplexTypes u; }; \ No newline at end of file
diff --git a/mojo/public/tools/bindings/generators/mojom_rust_generator.py b/mojo/public/tools/bindings/generators/mojom_rust_generator.py index 576cd3c..3484f63 100644 --- a/mojo/public/tools/bindings/generators/mojom_rust_generator.py +++ b/mojo/public/tools/bindings/generators/mojom_rust_generator.py
@@ -23,7 +23,7 @@ mojom.UINT64: "u64", mojom.FLOAT: "f32", mojom.DOUBLE: "f64", - mojom.STRING: "String", + mojom.STRING: "MojomString", } @@ -40,6 +40,11 @@ else: return f"Vec<{elt_ty}>" + if mojom.IsMapKind(ty): + key_ty = _MojomTypeToRustType(ty.key_kind) + value_ty = _MojomTypeToRustType(ty.value_kind) + return f"HashMap<{key_ty}, {value_ty}>" + if ty not in _mojom_primitive_type_to_rust_type: # Raising from a jinja2 call won't display the error message print(f"Mojom type {ty} is either undefined, "
diff --git a/mojo/public/tools/bindings/generators/rust_templates/enum.tmpl b/mojo/public/tools/bindings/generators/rust_templates/enum.tmpl index ca73220..1a96bf6 100644 --- a/mojo/public/tools/bindings/generators/rust_templates/enum.tmpl +++ b/mojo/public/tools/bindings/generators/rust_templates/enum.tmpl
@@ -2,7 +2,7 @@ {%set pub = "pub " if is_pub else ""%} -#[derive(Debug, PartialEq, Clone, PrimitiveEnum)] +#[derive(Debug, PartialEq, Clone, PrimitiveEnum, Hash, Eq)] pub enum {{name}} { {%- for field in enum.fields %} {{field.name}} = {{field.numeric_value}},
diff --git a/mojo/public/tools/bindings/generators/rust_templates/module.tmpl b/mojo/public/tools/bindings/generators/rust_templates/module.tmpl index 8e9c7b0..a51aea4e 100644 --- a/mojo/public/tools/bindings/generators/rust_templates/module.tmpl +++ b/mojo/public/tools/bindings/generators/rust_templates/module.tmpl
@@ -14,6 +14,8 @@ } use mojom_parser::*; +#[allow(unused_imports)] +use std::collections::HashMap; {%- for enum in module.enums %} {{declare_enum(enum.name, enum)}}
diff --git a/net/base/features.cc b/net/base/features.cc index 4c0224f..ef13fad 100644 --- a/net/base/features.cc +++ b/net/base/features.cc
@@ -276,156 +276,6 @@ base::FEATURE_DISABLED_BY_DEFAULT); #endif -// IP protection experiment configuration settings -BASE_FEATURE(kEnableIpProtectionProxy, - "EnableIpPrivacyProxy", - base::FEATURE_DISABLED_BY_DEFAULT); - -const base::FeatureParam<std::string> kIpPrivacyTokenServer{ - &kEnableIpProtectionProxy, /*name=*/"IpPrivacyTokenServer", - /*default_value=*/"https://prod.ipprotectionauth.goog"}; - -const base::FeatureParam<std::string> kIpPrivacyTokenServerGetInitialDataPath{ - &kEnableIpProtectionProxy, - /*name=*/"IpPrivacyTokenServerGetInitialDataPath", - /*default_value=*/"/v1/ipblinding/getInitialData"}; - -const base::FeatureParam<std::string> kIpPrivacyTokenServerGetTokensPath{ - &kEnableIpProtectionProxy, /*name=*/"IpPrivacyTokenServerGetTokensPath", - /*default_value=*/"/v1/ipblinding/auth"}; - -const base::FeatureParam<std::string> kIpPrivacyTokenServerGetProxyConfigPath{ - &kEnableIpProtectionProxy, - /*name=*/"IpPrivacyTokenServerGetProxyConfigPath", - /*default_value=*/"/v1/ipblinding/getProxyConfig"}; - -const base::FeatureParam<int> kIpPrivacyAuthTokenCacheBatchSize{ - &kEnableIpProtectionProxy, /*name=*/"IpPrivacyAuthTokenCacheBatchSize", - /*default_value=*/64}; - -const base::FeatureParam<int> kIpPrivacyAuthTokenCacheLowWaterMark{ - &kEnableIpProtectionProxy, /*name=*/"IpPrivacyAuthTokenCacheLowWaterMark", - /*default_value=*/16}; - -const base::FeatureParam<base::TimeDelta> kIpPrivacyProxyListFetchInterval{ - &kEnableIpProtectionProxy, /*name=*/"IpPrivacyProxyListFetchInterval", - /*default_value=*/base::Hours(1)}; - -const base::FeatureParam<base::TimeDelta> kIpPrivacyProxyListMinFetchInterval{ - &kEnableIpProtectionProxy, /*name=*/"IpPrivacyProxyMinListFetchInterval", - /*default_value=*/base::Minutes(1)}; - -const base::FeatureParam<base::TimeDelta> kIpPrivacyProxyListFetchIntervalFuzz{ - &kEnableIpProtectionProxy, /*name=*/"IpPrivacyProxyListFetchIntervalFuzz", - /*default_value=*/base::Minutes(30)}; - -const base::FeatureParam<bool> kIpPrivacyDirectOnly{ - &kEnableIpProtectionProxy, /*name=*/"IpPrivacyDirectOnly", - /*default_value=*/false}; - -const base::FeatureParam<bool> kIpPrivacyIncludeOAuthTokenInGetProxyConfig{ - &kEnableIpProtectionProxy, - /*name=*/"IpPrivacyIncludeOAuthTokenInGetProxyConfig", - /*default_value=*/false}; - -const base::FeatureParam<std::string> kIpPrivacyProxyAHostnameOverride{ - &kEnableIpProtectionProxy, /*name=*/"IpPrivacyProxyAHostnameOverride", - /*default_value=*/""}; - -const base::FeatureParam<std::string> kIpPrivacyProxyBHostnameOverride{ - &kEnableIpProtectionProxy, /*name=*/"IpPrivacyProxyBHostnameOverride", - /*default_value=*/""}; - -const base::FeatureParam<bool> kIpPrivacyAddHeaderToProxiedRequests{ - &kEnableIpProtectionProxy, /*name=*/"IpPrivacyAddHeaderToProxiedRequests", - /*default_value=*/false}; - -const base::FeatureParam<base::TimeDelta> kIpPrivacyExpirationFuzz{ - &kEnableIpProtectionProxy, /*name=*/"IpPrivacyExpirationFuzz", - /*default_value=*/base::Minutes(15)}; - -const base::FeatureParam<base::TimeDelta> - kIpPrivacyTryGetAuthTokensNotEligibleBackoff{ - &kEnableIpProtectionProxy, - /*name=*/"IpPrivacyTryGetAuthTokensNotEligibleBackoff", - /*default_value=*/base::Hours(1)}; - -const base::FeatureParam<base::TimeDelta> - kIpPrivacyTryGetAuthTokensTransientBackoff{ - &kEnableIpProtectionProxy, - /*name=*/"IpPrivacyTryGetAuthTokensTransientBackoff", - /*default_value=*/base::Seconds(5)}; - -const base::FeatureParam<base::TimeDelta> kIpPrivacyTryGetAuthTokensBugBackoff{ - &kEnableIpProtectionProxy, /*name=*/"IpPrivacyTryGetAuthTokensBugBackoff", - /*default_value=*/base::Minutes(10)}; - -const base::FeatureParam<double> kIpPrivacyBackoffJitter{ - &kEnableIpProtectionProxy, /*name=*/"IpPrivacyBackoffJitter", - /*default_value=*/0.25}; - -const base::FeatureParam<bool> kIpPrivacyRestrictTopLevelSiteSchemes{ - &kEnableIpProtectionProxy, - /*name=*/"IpPrivacyRestrictTopLevelSiteSchemes", - /*default_value=*/true}; - -const base::FeatureParam<bool> kIpPrivacyUseQuicProxies{ - &kEnableIpProtectionProxy, - /*name=*/"IpPrivacyUseQuicProxies", - /*default_value=*/false}; - -const base::FeatureParam<bool> kIpPrivacyUseQuicProxiesOnly{ - &kEnableIpProtectionProxy, - /*name=*/"IpPrivacyUseQuicProxiesOnly", - /*default_value=*/false}; - -const base::FeatureParam<bool> kIpPrivacyFallbackToDirect{ - &kEnableIpProtectionProxy, - /*name=*/"IpPrivacyFallbackToDirect", - /*default_value=*/true}; - -const base::FeatureParam<int> kIpPrivacyDebugExperimentArm{ - &kEnableIpProtectionProxy, - /*name=*/"IpPrivacyDebugExperimentArm", - /*default_value=*/0}; - -const base::FeatureParam<bool> kIpPrivacyAlwaysCreateCore{ - &kEnableIpProtectionProxy, - /*name=*/"IpPrivacyAlwaysCreateCore", - /*default_value=*/false}; - -const base::FeatureParam<bool> kIpPrivacyOnlyInIncognito{ - &kEnableIpProtectionProxy, - /*name=*/"IpPrivacyOnlyInIncognito", - /*default_value=*/false}; - -const base::FeatureParam<bool> kIpPrivacyEnableUserBypass{ - &kEnableIpProtectionProxy, - /*name=*/"IpPrivacyEnableUserBypass", - /*default_value=*/false}; - -const base::FeatureParam<bool> kIpPrivacyDisableForEnterpriseByDefault{ - &kEnableIpProtectionProxy, - /*name=*/"IpPrivacyDisableForEnterpriseByDefault", - /*default_value=*/false}; - -const base::FeatureParam<bool> kIpPrivacyEnableIppInDevTools{ - &kEnableIpProtectionProxy, - /*name=*/"IpPrivacyEnableIppInDevTools", - /*default_value=*/true}; - -const base::FeatureParam<bool> kIpPrivacyEnableIppPanelInDevTools{ - &kEnableIpProtectionProxy, - /*name=*/"IpPrivacyEnableIppPanelInDevTools", - /*default_value=*/false}; - -const base::FeatureParam<std::string> kIpPrivacyUnconditionalProxyDomainList{ - &kEnableIpProtectionProxy, - /*name=*/"IpPrivacyUnconditionalProxyDomainList", /*default_value=*/""}; - -BASE_FEATURE(kEnableIpPrivacyProxyAdvancedFallbackLogic, - base::FEATURE_ENABLED_BY_DEFAULT); - BASE_FEATURE(kExcludeLargeBodyReports, "ExcludeLargeReportBodies", base::FEATURE_ENABLED_BY_DEFAULT);
diff --git a/net/base/features.h b/net/base/features.h index 6cbb05b..521faa6 100644 --- a/net/base/features.h +++ b/net/base/features.h
@@ -356,183 +356,6 @@ // A flag to make multiport context creation asynchronous. NET_EXPORT BASE_DECLARE_FEATURE(kAsyncMultiPortPath); -// Enables custom proxy configuration for the IP Protection experimental proxy. -NET_EXPORT BASE_DECLARE_FEATURE(kEnableIpProtectionProxy); - -// Sets the name of the IP protection auth token server. -NET_EXPORT extern const base::FeatureParam<std::string> kIpPrivacyTokenServer; - -// Sets the path component of the IP protection auth token server URL used for -// getting initial token signing data. -NET_EXPORT extern const base::FeatureParam<std::string> - kIpPrivacyTokenServerGetInitialDataPath; - -// Sets the path component of the IP protection auth token server URL used for -// getting blind-signed tokens. -NET_EXPORT extern const base::FeatureParam<std::string> - kIpPrivacyTokenServerGetTokensPath; - -// Sets the path component of the IP protection auth token server URL used for -// getting proxy configuration. -NET_EXPORT extern const base::FeatureParam<std::string> - kIpPrivacyTokenServerGetProxyConfigPath; - -// Sets the batch size to fetch new auth tokens for IP protection. -NET_EXPORT extern const base::FeatureParam<int> - kIpPrivacyAuthTokenCacheBatchSize; - -// Sets the cache low-water-mark for auth tokens for IP protection. -NET_EXPORT extern const base::FeatureParam<int> - kIpPrivacyAuthTokenCacheLowWaterMark; - -// Sets the normal time between fetches of the IP protection proxy list. -NET_EXPORT extern const base::FeatureParam<base::TimeDelta> - kIpPrivacyProxyListFetchInterval; - -// Sets the minimum time between fetches of the IP protection proxy list, such -// as when a re-fetch is forced due to an error. -NET_EXPORT extern const base::FeatureParam<base::TimeDelta> - kIpPrivacyProxyListMinFetchInterval; - -// Fetches of the IP Protection proxy list will have a random time in the range -// of plus or minus this delta added to their interval. -NET_EXPORT extern const base::FeatureParam<base::TimeDelta> - kIpPrivacyProxyListFetchIntervalFuzz; - -// Overrides the ProxyA hostname normally set by the proxylist fetch. -NET_EXPORT extern const base::FeatureParam<std::string> - kIpPrivacyProxyAHostnameOverride; - -// Overrides the ProxyB hostname normally set by the proxylist fetch. -NET_EXPORT extern const base::FeatureParam<std::string> - kIpPrivacyProxyBHostnameOverride; - -// Controls whether IP Protection _proxying_ is bypassed by not including any -// of the proxies in the proxy list. This supports experimental comparison of -// connections that _would_ have been proxied, but were not. -NET_EXPORT extern const base::FeatureParam<bool> kIpPrivacyDirectOnly; - -// If true, pass OAuth token to Phosphor in GetProxyConfig API for IP -// Protection. This is used by E2E tests to ensure a stable geo for tokens -// and proxy config. -NET_EXPORT extern const base::FeatureParam<bool> - kIpPrivacyIncludeOAuthTokenInGetProxyConfig; - -// Controls whether a header ("IP-Protection: 1") should be added to proxied -// network requests. -NET_EXPORT extern const base::FeatureParam<bool> - kIpPrivacyAddHeaderToProxiedRequests; - -// Token expirations will have a random time between 5 seconds and this delta -// subtracted from their expiration, in order to even out the load on the token -// servers. -NET_EXPORT extern const base::FeatureParam<base::TimeDelta> - kIpPrivacyExpirationFuzz; - -// Backoff time applied when fetching tokens from the IP Protection auth -// token server encounters an error indicating that the primary account is not -// eligible (e.g., user is signed in but not eligible for IP protection) or -// a 403 (FORBIDDEN) status code (e.g., quota exceeded). -NET_EXPORT extern const base::FeatureParam<base::TimeDelta> - kIpPrivacyTryGetAuthTokensNotEligibleBackoff; - -// Backoff time applied when fetching tokens from the IP Protection auth -// token server encounters a transient error, such as a failure to fetch -// an OAuth token for a primary account or a network issue. -NET_EXPORT extern const base::FeatureParam<base::TimeDelta> - kIpPrivacyTryGetAuthTokensTransientBackoff; - -// Backoff time applied when fetching tokens from the IP Protection auth -// token server encounters a 400 (BAD REQUEST) or 401 (UNAUTHORIZED) status code -// which suggests a bug. -NET_EXPORT extern const base::FeatureParam<base::TimeDelta> - kIpPrivacyTryGetAuthTokensBugBackoff; - -// Jitter (as a percentage) to apply to backoff time calculations. -NET_EXPORT extern const base::FeatureParam<double> kIpPrivacyBackoffJitter; - -// If true, only proxy traffic when the top-level site uses the http:// or -// https:// schemes. This prevents attempts to proxy from top-level sites with -// chrome://, chrome-extension://, or other non-standard schemes, in addition to -// top-level sites using less common schemes like blob:// and data://. -NET_EXPORT extern const base::FeatureParam<bool> - kIpPrivacyRestrictTopLevelSiteSchemes; - -// If true, IP protection will attempt to use QUIC to connect to proxies, -// falling back to HTTPS. If false, it will only use HTTPs. -NET_EXPORT extern const base::FeatureParam<bool> kIpPrivacyUseQuicProxies; - -// If true, IP protection will only use QUIC to connect to proxies, with no -// fallback to HTTPS. This is intended for development of the QUIC -// functionality. -NET_EXPORT extern const base::FeatureParam<bool> kIpPrivacyUseQuicProxiesOnly; - -// Fallback to direct when connections to IP protection proxies fail. This -// defaults to true and is intended for development of the QUIC functionality. -NET_EXPORT extern const base::FeatureParam<bool> kIpPrivacyFallbackToDirect; - -// Identifier for an experiment arm, to be sent to IP Protection proxies and the -// token server in the `Ip-Protection-Debug-Experiment-Arm` header. The default -// value, 0, is not sent. -NET_EXPORT extern const base::FeatureParam<int> kIpPrivacyDebugExperimentArm; - -// When enabled and an IP protection delegate can be be created in the -// `NetworkContext`, a `IpProtectionProxyDelegate` will ALWAYS be created even -// for `NetworkContexts` that do not participate in IP protection. This is -// necessary for the WebView traffic experiment. By default, this feature param -// is false and will not create a delegate when IP protection is not enabled. -// Further, this also prevents the unnecessary instantiation of the -// `IpProtectionCore` for a `NetworkContext` that does not participate in IP -// protection. -NET_EXPORT extern const base::FeatureParam<bool> kIpPrivacyAlwaysCreateCore; - -// Enables IP protection in incognito mode only. The default value of this -// feature is false, which maintains the existing behavior when -// `kEnableIpProtectionProxy` is enabled, IPP is enabled in both regular and -// incognito browsing sessions. When set to true, the main profile Network -// Context won't proxy traffic using IP Protection. -NET_EXPORT extern const base::FeatureParam<bool> kIpPrivacyOnlyInIncognito; - -// Enables the ability to detect when a user has requests being actively -// proxied by IP Protection and thus allowing the user to made aware and offer -// the ability to bypass IP Protection via the User Bypass UX. -NET_EXPORT extern const base::FeatureParam<bool> kIpPrivacyEnableUserBypass; - -// If true, IP Protection will be disabled by default for enterprise users. -// Otherwise, IP Protection will be enabled by default for enterprise users (but -// can still be opted out of via enterprise policy). This is intended to be used -// as a kill-switch in case significant enterprise breakage is encountered -// during the IP Protection rollout. Note that this has no effect unless the -// `kEnableIpProtectionProxy` feature is enabled. -// TODO(https://crbug.com/41496985): Remove this feature a few milestones after -// launch assuming no major enterprise breakage is encountered. -NET_EXPORT extern const base::FeatureParam<bool> - kIpPrivacyDisableForEnterpriseByDefault; - -// Enables the ability for IP Protected requests to be marked and inspected -// within the DevTools panel. Requests sent through IP Protection will include -// an icon besides the Network entry, as well as be able to be filtered within -// the Network panel. Tracked at https://crbug.com/425645896. -NET_EXPORT extern const base::FeatureParam<bool> kIpPrivacyEnableIppInDevTools; - -// Enables the ability for IP protection features to be gated in the Privacy -// and Security Panel within DevTools. When this flag is enabled, the IP -// Protection section will be shown in the Privacy and Security section of the -// DevTools panel allowing users to view proxied requests and bypass IP -// Protection locally. -// Do not remove or enable this flag for all users until crbug.com/442349180 -// is resolved. -NET_EXPORT extern const base::FeatureParam<bool> - kIpPrivacyEnableIppPanelInDevTools; - -// A comma-separated list of domains (eTLD+1) for which all requests will be -// proxied. -NET_EXPORT extern const base::FeatureParam<std::string> - kIpPrivacyUnconditionalProxyDomainList; - -// Enables more advanced handling of IP Protection proxy request failures. -NET_EXPORT BASE_DECLARE_FEATURE(kEnableIpPrivacyProxyAdvancedFallbackLogic); - // Maximum report body size (KB) to include in serialized reports. Bodies // exceeding this are omitted when kExcludeLargeBodyReports is enabled. Use // Reporting.ReportBodySize UMA histogram to monitor report body sizes and
diff --git a/net/extras/sqlite/sqlite_persistent_cookie_store.cc b/net/extras/sqlite/sqlite_persistent_cookie_store.cc index 281db96d3..b73dd62 100644 --- a/net/extras/sqlite/sqlite_persistent_cookie_store.cc +++ b/net/extras/sqlite/sqlite_persistent_cookie_store.cc
@@ -400,10 +400,10 @@ class PendingOperation { public: - enum OperationType { - COOKIE_ADD, - COOKIE_UPDATEACCESS, - COOKIE_DELETE, + enum class OperationType { + kAdd, + kUpdateLastAccessTime, + kDelete, }; PendingOperation(OperationType op, const CanonicalCookie& cc) @@ -499,20 +499,20 @@ namespace { // Possible values for the 'priority' column. -enum DBCookiePriority { - kCookiePriorityLow = 0, - kCookiePriorityMedium = 1, - kCookiePriorityHigh = 2, +enum class DBCookiePriority { + kLow = 0, + kMedium = 1, + kHigh = 2, }; DBCookiePriority CookiePriorityToDBCookiePriority(CookiePriority value) { switch (value) { - case COOKIE_PRIORITY_LOW: - return kCookiePriorityLow; - case COOKIE_PRIORITY_MEDIUM: - return kCookiePriorityMedium; - case COOKIE_PRIORITY_HIGH: - return kCookiePriorityHigh; + case CookiePriority::COOKIE_PRIORITY_LOW: + return DBCookiePriority::kLow; + case CookiePriority::COOKIE_PRIORITY_MEDIUM: + return DBCookiePriority::kMedium; + case CookiePriority::COOKIE_PRIORITY_HIGH: + return DBCookiePriority::kHigh; } NOTREACHED(); @@ -520,12 +520,12 @@ CookiePriority DBCookiePriorityToCookiePriority(DBCookiePriority value) { switch (value) { - case kCookiePriorityLow: - return COOKIE_PRIORITY_LOW; - case kCookiePriorityMedium: - return COOKIE_PRIORITY_MEDIUM; - case kCookiePriorityHigh: - return COOKIE_PRIORITY_HIGH; + case DBCookiePriority::kLow: + return CookiePriority::COOKIE_PRIORITY_LOW; + case DBCookiePriority::kMedium: + return CookiePriority::COOKIE_PRIORITY_MEDIUM; + case DBCookiePriority::kHigh: + return CookiePriority::COOKIE_PRIORITY_HIGH; } NOTREACHED(); @@ -1253,17 +1253,17 @@ void SQLitePersistentCookieStore::Backend::AddCookie( const CanonicalCookie& cc) { - BatchOperation(PendingOperation::COOKIE_ADD, cc); + BatchOperation(PendingOperation::OperationType::kAdd, cc); } void SQLitePersistentCookieStore::Backend::UpdateCookieAccessTime( const CanonicalCookie& cc) { - BatchOperation(PendingOperation::COOKIE_UPDATEACCESS, cc); + BatchOperation(PendingOperation::OperationType::kUpdateLastAccessTime, cc); } void SQLitePersistentCookieStore::Backend::DeleteCookie( const CanonicalCookie& cc) { - BatchOperation(PendingOperation::COOKIE_DELETE, cc); + BatchOperation(PendingOperation::OperationType::kDelete, cc); } void SQLitePersistentCookieStore::Backend::BatchOperation( @@ -1288,12 +1288,14 @@ PendingOperationsForKey& ops_for_key = iter_and_result.first->second; if (!iter_and_result.second) { // Insert failed -> already have ops. - if (po->op() == PendingOperation::COOKIE_DELETE) { + if (po->op() == PendingOperation::OperationType::kDelete) { // A delete op makes all the previous ones irrelevant. ops_for_key.clear(); - } else if (po->op() == PendingOperation::COOKIE_UPDATEACCESS) { + } else if (po->op() == + PendingOperation::OperationType::kUpdateLastAccessTime) { if (!ops_for_key.empty() && - ops_for_key.back()->op() == PendingOperation::COOKIE_UPDATEACCESS) { + ops_for_key.back()->op() == + PendingOperation::OperationType::kUpdateLastAccessTime) { // If access timestamp is updated twice in a row, can dump the earlier // one. ops_for_key.pop_back(); @@ -1385,7 +1387,7 @@ } switch (po->op()) { - case PendingOperation::COOKIE_ADD: + case PendingOperation::OperationType::kAdd: add_statement.Reset(true); add_statement.BindTime(0, po->cc().CreationDate()); add_statement.BindString(1, po->cc().Domain()); @@ -1416,7 +1418,8 @@ add_statement.BindBool(11, po->cc().IsPersistent()); add_statement.BindBool(12, po->cc().IsPersistent()); add_statement.BindInt( - 13, CookiePriorityToDBCookiePriority(po->cc().Priority())); + 13, static_cast<int>( + CookiePriorityToDBCookiePriority(po->cc().Priority()))); add_statement.BindInt( 14, CookieSameSiteToDBCookieSameSite(po->cc().SameSite())); add_statement.BindInt(15, static_cast<int>(po->cc().SourceScheme())); @@ -1433,7 +1436,7 @@ } break; - case PendingOperation::COOKIE_UPDATEACCESS: + case PendingOperation::OperationType::kUpdateLastAccessTime: update_access_statement.Reset(true); update_access_statement.BindTime(0, po->cc().LastAccessDate()); update_access_statement.BindString(1, po->cc().Name()); @@ -1453,7 +1456,7 @@ } break; - case PendingOperation::COOKIE_DELETE: + case PendingOperation::OperationType::kDelete: delete_statement.Reset(true); delete_statement.BindString(0, po->cc().Name()); delete_statement.BindString(1, po->cc().Domain());
diff --git a/net/http/http_network_transaction.cc b/net/http/http_network_transaction.cc index 17b7431..bafd6a8 100644 --- a/net/http/http_network_transaction.cc +++ b/net/http/http_network_transaction.cc
@@ -1394,13 +1394,6 @@ auth_controllers_[HttpAuth::AUTH_SERVER]->AddAuthorizationHeader( &request_headers_); - bool is_proxied_request = - proxy_info_.is_for_ip_protection() && !proxy_info_.is_direct(); - if (features::kIpPrivacyAddHeaderToProxiedRequests.Get() && - is_proxied_request) { - request_headers_.SetHeader("IP-Protection", "1"); - } - request_headers_.MergeFrom(request_->extra_headers); if (modify_headers_callbacks_) {
diff --git a/net/http/http_network_transaction_unittest.cc b/net/http/http_network_transaction_unittest.cc index ed8ee74..f27e9e41 100644 --- a/net/http/http_network_transaction_unittest.cc +++ b/net/http/http_network_transaction_unittest.cc
@@ -28428,341 +28428,6 @@ } }; -// Test that for requests sent through an IP Protection proxy, the -// 'IP-Protection' header is sent as expected when the feature is enabled. -TEST_P(HttpNetworkTransactionTest, - HttpsNestedProxyIpProtectionRequestHeaderAddedWhenEnabled) { - base::test::ScopedFeatureList scoped_feature_list; - scoped_feature_list.InitAndEnableFeatureWithParameters( - features::kEnableIpProtectionProxy, - {{features::kIpPrivacyAddHeaderToProxiedRequests.name, "true"}}); - - HttpRequestInfo request; - request.method = "GET"; - request.url = GURL("https://www.example.org/"); - request.traffic_annotation = - MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS); - - session_deps_.proxy_resolution_service = - ConfiguredProxyResolutionService::CreateFixedForTest( - "https://not-used:70", TRAFFIC_ANNOTATION_FOR_TESTS); - session_deps_.proxy_delegate = std::make_unique<IpProtectionProxyDelegate>(); - auto* proxy_delegate = static_cast<IpProtectionProxyDelegate*>( - session_deps_.proxy_delegate.get()); - proxy_delegate->set_proxy_chain(nested_proxy_chain_); - session_deps_.proxy_resolution_service->SetProxyDelegate(proxy_delegate); - session_deps_.net_log = NetLog::Get(); - std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_)); - - const std::string kProxyServer1AuthHeaderValue = - IpProtectionProxyDelegate::GetAuthorizationHeaderValue(proxy_server_1_); - const std::string kProxyServer2AuthHeaderValue = - IpProtectionProxyDelegate::GetAuthorizationHeaderValue(proxy_server_2_); - - const std::string kProxyServer2Connect = base::StringPrintf( - "CONNECT proxy2.test:71 HTTP/1.1\r\n" - "Host: proxy2.test:71\r\n" - "Proxy-Connection: keep-alive\r\n" - "User-Agent: test-ua\r\n" - "Authorization: %s\r\n\r\n", - kProxyServer1AuthHeaderValue.c_str()); - const std::string kEndpointConnect = base::StringPrintf( - "CONNECT www.example.org:443 HTTP/1.1\r\n" - "Host: www.example.org:443\r\n" - "Proxy-Connection: keep-alive\r\n" - "User-Agent: test-ua\r\n" - "Authorization: %s\r\n\r\n", - kProxyServer2AuthHeaderValue.c_str()); - - MockWrite data_writes[] = { - MockWrite(kProxyServer2Connect), - MockWrite(kEndpointConnect), - MockWrite("GET / HTTP/1.1\r\n" - "Host: www.example.org\r\n" - "Connection: keep-alive\r\n" - "IP-Protection: 1\r\n\r\n"), - }; - - MockRead data_reads[] = { - MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"), - MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"), - MockRead("HTTP/1.1 200\r\n\r\n"), - MockRead(SYNCHRONOUS, OK), - }; - - StaticSocketDataProvider data(data_reads, data_writes); - session_deps_.socket_factory->AddSocketDataProvider(&data); - - SSLSocketDataProvider ssl(ASYNC, OK); - session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); - - SSLSocketDataProvider ssl2(ASYNC, OK); - session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2); - - SSLSocketDataProvider ssl3(ASYNC, OK); - session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl3); - - TestCompletionCallback callback; - - HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get()); - - int rv = trans.Start(&request, callback.callback(), - NetLogWithSource::Make(NetLogSourceType::NONE)); - EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); - - rv = callback.WaitForResult(); - EXPECT_THAT(rv, IsOk()); - - const HttpResponseInfo* response = trans.GetResponseInfo(); - ASSERT_TRUE(response); - ASSERT_TRUE(response->headers); - EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine()); -} - -// Test that for direct requests that are marked as being for IP Protection, the -// 'IP-Protection' header is not sent even when the feature is enabled. This -// test should be removed once `kIpPrivacyDirectOnly` is. -TEST_P(HttpNetworkTransactionTest, - HttpsNestedProxyIpProtectionRequestHeaderNotAddedForIpProtectionDirect) { - base::test::ScopedFeatureList scoped_feature_list; - scoped_feature_list.InitAndEnableFeatureWithParameters( - features::kEnableIpProtectionProxy, - {{features::kIpPrivacyAddHeaderToProxiedRequests.name, "true"}, - {features::kIpPrivacyDirectOnly.name, "true"}}); - - HttpRequestInfo request; - request.method = "GET"; - request.url = GURL("https://www.example.org/"); - request.traffic_annotation = - MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS); - - const auto kIpProtectionDirectChain = - ProxyChain::ForIpProtection(std::vector<ProxyServer>()); - - session_deps_.proxy_resolution_service = - ConfiguredProxyResolutionService::CreateFixedForTest( - "https://not-used:70", TRAFFIC_ANNOTATION_FOR_TESTS); - session_deps_.proxy_delegate = std::make_unique<IpProtectionProxyDelegate>(); - auto* proxy_delegate = static_cast<IpProtectionProxyDelegate*>( - session_deps_.proxy_delegate.get()); - proxy_delegate->set_proxy_chain(kIpProtectionDirectChain); - session_deps_.proxy_resolution_service->SetProxyDelegate(proxy_delegate); - session_deps_.net_log = NetLog::Get(); - std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_)); - - MockWrite data_writes[] = { - MockWrite("GET / HTTP/1.1\r\n" - "Host: www.example.org\r\n" - "Connection: keep-alive\r\n\r\n"), - }; - - MockRead data_reads[] = { - MockRead("HTTP/1.1 200\r\n\r\n"), - MockRead(SYNCHRONOUS, OK), - }; - - StaticSocketDataProvider data(data_reads, data_writes); - session_deps_.socket_factory->AddSocketDataProvider(&data); - - SSLSocketDataProvider ssl(ASYNC, OK); - session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); - - TestCompletionCallback callback; - - HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get()); - - int rv = trans.Start(&request, callback.callback(), - NetLogWithSource::Make(NetLogSourceType::NONE)); - EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); - - rv = callback.WaitForResult(); - EXPECT_THAT(rv, IsOk()); - - const HttpResponseInfo* response = trans.GetResponseInfo(); - ASSERT_TRUE(response); - ASSERT_TRUE(response->headers); - EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine()); -} - -// Test that for requests sent through an IP Protection proxy, the -// 'IP-Protection' header is not sent if the feature is disabled. -TEST_P(HttpNetworkTransactionTest, - HttpsNestedProxyIpProtectionRequestHeaderNotAddedIfFeatureDisabled) { - base::test::ScopedFeatureList scoped_feature_list; - scoped_feature_list.InitAndEnableFeatureWithParameters( - features::kEnableIpProtectionProxy, - {{features::kIpPrivacyAddHeaderToProxiedRequests.name, "false"}}); - - HttpRequestInfo request; - request.method = "GET"; - request.url = GURL("https://www.example.org/"); - request.traffic_annotation = - MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS); - - session_deps_.proxy_resolution_service = - ConfiguredProxyResolutionService::CreateFixedForTest( - "https://not-used:70", TRAFFIC_ANNOTATION_FOR_TESTS); - session_deps_.proxy_delegate = std::make_unique<IpProtectionProxyDelegate>(); - auto* proxy_delegate = static_cast<IpProtectionProxyDelegate*>( - session_deps_.proxy_delegate.get()); - proxy_delegate->set_proxy_chain(nested_proxy_chain_); - session_deps_.proxy_resolution_service->SetProxyDelegate(proxy_delegate); - session_deps_.net_log = NetLog::Get(); - std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_)); - - const std::string kProxyServer1AuthHeaderValue = - IpProtectionProxyDelegate::GetAuthorizationHeaderValue(proxy_server_1_); - const std::string kProxyServer2AuthHeaderValue = - IpProtectionProxyDelegate::GetAuthorizationHeaderValue(proxy_server_2_); - - const std::string kProxyServer2Connect = base::StringPrintf( - "CONNECT proxy2.test:71 HTTP/1.1\r\n" - "Host: proxy2.test:71\r\n" - "Proxy-Connection: keep-alive\r\n" - "User-Agent: test-ua\r\n" - "Authorization: %s\r\n\r\n", - kProxyServer1AuthHeaderValue.c_str()); - const std::string kEndpointConnect = base::StringPrintf( - "CONNECT www.example.org:443 HTTP/1.1\r\n" - "Host: www.example.org:443\r\n" - "Proxy-Connection: keep-alive\r\n" - "User-Agent: test-ua\r\n" - "Authorization: %s\r\n\r\n", - kProxyServer2AuthHeaderValue.c_str()); - - MockWrite data_writes[] = { - MockWrite(kProxyServer2Connect), - MockWrite(kEndpointConnect), - MockWrite("GET / HTTP/1.1\r\n" - "Host: www.example.org\r\n" - "Connection: keep-alive\r\n\r\n"), - }; - - MockRead data_reads[] = { - MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"), - MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"), - MockRead("HTTP/1.1 200\r\n\r\n"), - MockRead(SYNCHRONOUS, OK), - }; - - StaticSocketDataProvider data(data_reads, data_writes); - session_deps_.socket_factory->AddSocketDataProvider(&data); - - SSLSocketDataProvider ssl(ASYNC, OK); - session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl); - - SSLSocketDataProvider ssl2(ASYNC, OK); - session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2); - - SSLSocketDataProvider ssl3(ASYNC, OK); - session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl3); - - TestCompletionCallback callback; - - HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get()); - - int rv = trans.Start(&request, callback.callback(), - NetLogWithSource::Make(NetLogSourceType::NONE)); - EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); - - rv = callback.WaitForResult(); - EXPECT_THAT(rv, IsOk()); - - const HttpResponseInfo* response = trans.GetResponseInfo(); - ASSERT_TRUE(response); - ASSERT_TRUE(response->headers); - EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine()); -} - -// Test that for a request that fails to be sent through an IP Protection proxy, -// after we fallback to direct the 'IP-Protection' header is not added to the -// request headers. -TEST_P(HttpNetworkTransactionTest, - HttpsNestedProxyIpProtectionRequestHeaderNotAddedAfterFallback) { - base::test::ScopedFeatureList scoped_feature_list; - scoped_feature_list.InitAndEnableFeatureWithParameters( - features::kEnableIpProtectionProxy, - {{features::kIpPrivacyAddHeaderToProxiedRequests.name, "true"}}); - HttpRequestInfo request; - request.method = "GET"; - request.url = GURL("https://www.example.org/"); - request.traffic_annotation = - MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS); - - session_deps_.proxy_resolution_service = - ConfiguredProxyResolutionService::CreateFixedForTest( - "https://not-used:70", TRAFFIC_ANNOTATION_FOR_TESTS); - session_deps_.proxy_delegate = std::make_unique<IpProtectionProxyDelegate>(); - auto* proxy_delegate = static_cast<IpProtectionProxyDelegate*>( - session_deps_.proxy_delegate.get()); - proxy_delegate->set_proxy_chain(nested_proxy_chain_); - session_deps_.proxy_resolution_service->SetProxyDelegate(proxy_delegate); - session_deps_.net_log = NetLog::Get(); - std::unique_ptr<HttpNetworkSession> session(CreateSession(&session_deps_)); - - const std::string kProxyServer1AuthHeaderValue = - IpProtectionProxyDelegate::GetAuthorizationHeaderValue(proxy_server_1_); - - const std::string kProxyServer2Connect = base::StringPrintf( - "CONNECT proxy2.test:71 HTTP/1.1\r\n" - "Host: proxy2.test:71\r\n" - "Proxy-Connection: keep-alive\r\n" - "User-Agent: test-ua\r\n" - "Authorization: %s\r\n\r\n", - kProxyServer1AuthHeaderValue.c_str()); - - MockWrite data_writes1[] = { - MockWrite(kProxyServer2Connect), - }; - - MockRead data_reads1[] = { - MockRead("HTTP/1.1 401 Not Authorized\r\n\r\n"), - MockRead(SYNCHRONOUS, OK), - }; - - StaticSocketDataProvider data1(data_reads1, data_writes1); - session_deps_.socket_factory->AddSocketDataProvider(&data1); - - SSLSocketDataProvider ssl1(ASYNC, OK); - session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1); - - // The proxy delegate should implement falling back to direct after an error, - // and we don't expect any proxying or an IP Protection request header on the - // GET. - MockWrite data_writes2[] = { - MockWrite("GET / HTTP/1.1\r\n" - "Host: www.example.org\r\n" - "Connection: keep-alive\r\n\r\n"), - }; - - MockRead data_reads2[] = { - MockRead("HTTP/1.1 200\r\n\r\n"), - MockRead(SYNCHRONOUS, OK), - }; - - StaticSocketDataProvider data2(data_reads2, data_writes2); - session_deps_.socket_factory->AddSocketDataProvider(&data2); - - SSLSocketDataProvider ssl2(ASYNC, OK); - session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl2); - - TestCompletionCallback callback; - - HttpNetworkTransaction trans(DEFAULT_PRIORITY, session.get()); - - int rv = trans.Start(&request, callback.callback(), - NetLogWithSource::Make(NetLogSourceType::NONE)); - EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); - - rv = callback.WaitForResult(); - EXPECT_THAT(rv, IsOk()); - - const HttpResponseInfo* response = trans.GetResponseInfo(); - ASSERT_TRUE(response); - ASSERT_TRUE(response->headers); - EXPECT_EQ("HTTP/1.1 200", response->headers->GetStatusLine()); -} - TEST_P(HttpNetworkTransactionTest, EarlyHintsWithAltSvcHeader) { base::test::ScopedFeatureList feature_list; feature_list.InitWithFeatures(
diff --git a/net/url_request/url_request_http_job.cc b/net/url_request/url_request_http_job.cc index 6537c74..361d29f 100644 --- a/net/url_request/url_request_http_job.cc +++ b/net/url_request/url_request_http_job.cc
@@ -2043,7 +2043,11 @@ } auto& proxy_chain = response_info_->proxy_chain; - bool direct_only = features::kIpPrivacyDirectOnly.Get(); + + // TODO: crbug.com/458071609 - Delete this default value placeholder for + // features::kIpPrivacyDirectOnly when cleaning up IPP histograms. + bool direct_only = false; + if (proxy_chain.is_for_ip_protection()) { base::UmaHistogramTimes("Net.HttpJob.IpProtection.TotalTimeNotCached3", total_time);
diff --git a/net/url_request/url_request_http_job_unittest.cc b/net/url_request/url_request_http_job_unittest.cc index 4ee1e03..64725a00 100644 --- a/net/url_request/url_request_http_job_unittest.cc +++ b/net/url_request/url_request_http_job_unittest.cc
@@ -364,118 +364,6 @@ .empty()); } -// Test that the IP Protection-specific metrics get recorded as expected when -// the direct-only param is enabled. -TEST_F(URLRequestHttpJobWithProxyTest, - IpProtectionDirectOnlyProxyMetricsRecorded) { - base::test::ScopedFeatureList scoped_feature_list; - scoped_feature_list.InitAndEnableFeatureWithParameters( - net::features::kEnableIpProtectionProxy, - {{net::features::kIpPrivacyDirectOnly.name, "true"}}); - const auto kIpProtectionDirectChain = - ProxyChain::ForIpProtection(std::vector<ProxyServer>()); - - std::unique_ptr<ProxyResolutionService> proxy_resolution_service = - ConfiguredProxyResolutionService::CreateFixedForTest( - "https://not-used:70", TRAFFIC_ANNOTATION_FOR_TESTS); - auto proxy_delegate = std::make_unique<TestProxyDelegate>(); - proxy_delegate->set_proxy_chain(kIpProtectionDirectChain); - proxy_resolution_service->SetProxyDelegate(proxy_delegate.get()); - - MockWrite writes[] = {MockWrite(kSimpleGetMockWrite)}; - - MockRead reads[] = {MockRead("HTTP/1.1 200 OK\r\n" - "Content-Length: 12\r\n\r\n"), - MockRead("Test Content")}; - - StaticSocketDataProvider socket_data(reads, writes); - - URLRequestHttpJobWithProxy http_job_with_proxy( - std::move(proxy_resolution_service)); - http_job_with_proxy.socket_factory_.AddSocketDataProvider(&socket_data); - - TestDelegate delegate; - base::HistogramTester histogram_tester; - std::unique_ptr<URLRequest> request = - http_job_with_proxy.context_->CreateRequest( - GURL("http://www.example.com"), DEFAULT_PRIORITY, &delegate, - TRAFFIC_ANNOTATION_FOR_TESTS); - - request->Start(); - ASSERT_TRUE(request->is_pending()); - delegate.RunUntilComplete(); - - EXPECT_THAT(delegate.request_status(), IsOk()); - EXPECT_EQ(kIpProtectionDirectChain, request->proxy_chain()); - EXPECT_EQ(12, request->received_response_content_length()); - EXPECT_EQ(CountWriteBytes(writes), request->GetTotalSentBytes()); - EXPECT_EQ(CountReadBytes(reads), request->GetTotalReceivedBytes()); - - histogram_tester.ExpectUniqueSample("Net.HttpJob.IpProtection.BytesSent", - std::size(kSimpleGetMockWrite), - /*expected_bucket_count=*/1); - - histogram_tester.ExpectUniqueSample( - "Net.HttpJob.IpProtection.PrefilterBytesRead.Net", - /*sample=*/12, /*expected_bucket_count=*/1); - - histogram_tester.ExpectUniqueSample( - "Net.HttpJob.IpProtection.JobResult", - /*sample=*/URLRequestHttpJob::IpProtectionJobResult::kProtectionSuccess, - /*expected_bucket_count=*/1); -} - -// Test that IP Protection-specific metrics are NOT recorded for direct requests -// when the direct-only param is disabled. -TEST_F(URLRequestHttpJobWithProxyTest, IpProtectionDirectProxyMetricsRecorded) { - base::test::ScopedFeatureList scoped_feature_list; - scoped_feature_list.InitAndEnableFeatureWithParameters( - net::features::kEnableIpProtectionProxy, - {{net::features::kIpPrivacyDirectOnly.name, "false"}}); - const auto kIpProtectionDirectChain = - ProxyChain::ForIpProtection(std::vector<ProxyServer>()); - - std::unique_ptr<ProxyResolutionService> proxy_resolution_service = - ConfiguredProxyResolutionService::CreateFixedForTest( - "https://not-used:70", TRAFFIC_ANNOTATION_FOR_TESTS); - auto proxy_delegate = std::make_unique<TestProxyDelegate>(); - proxy_delegate->set_proxy_chain(kIpProtectionDirectChain); - proxy_resolution_service->SetProxyDelegate(proxy_delegate.get()); - - MockWrite writes[] = {MockWrite(kSimpleGetMockWrite)}; - - MockRead reads[] = {MockRead("HTTP/1.1 200 OK\r\n" - "Content-Length: 12\r\n\r\n"), - MockRead("Test Content")}; - - StaticSocketDataProvider socket_data(reads, writes); - - URLRequestHttpJobWithProxy http_job_with_proxy( - std::move(proxy_resolution_service)); - http_job_with_proxy.socket_factory_.AddSocketDataProvider(&socket_data); - - TestDelegate delegate; - base::HistogramTester histogram_tester; - std::unique_ptr<URLRequest> request = - http_job_with_proxy.context_->CreateRequest( - GURL("http://www.example.com"), DEFAULT_PRIORITY, &delegate, - TRAFFIC_ANNOTATION_FOR_TESTS); - - request->Start(); - ASSERT_TRUE(request->is_pending()); - delegate.RunUntilComplete(); - - EXPECT_THAT(delegate.request_status(), IsOk()); - EXPECT_EQ(kIpProtectionDirectChain, request->proxy_chain()); - EXPECT_EQ(12, request->received_response_content_length()); - EXPECT_EQ(CountWriteBytes(writes), request->GetTotalSentBytes()); - EXPECT_EQ(CountReadBytes(reads), request->GetTotalReceivedBytes()); - - histogram_tester.ExpectTotalCount("Net.HttpJob.IpProtection.BytesSent", 0); - histogram_tester.ExpectTotalCount( - "Net.HttpJob.IpProtection.PrefilterBytesRead.Net", 0); -} - class URLRequestHttpJobTest : public TestWithTaskEnvironment { protected: URLRequestHttpJobTest() {
diff --git a/remoting/host/base/switches.cc b/remoting/host/base/switches.cc index 0d8cbd20..09e120e8 100644 --- a/remoting/host/base/switches.cc +++ b/remoting/host/base/switches.cc
@@ -33,6 +33,8 @@ const char kEnableWtmpdb[] = "enable-wtmpdb"; #endif +const char kEnableCorpMessaging[] = "enable-corp-messaging"; + #if BUILDFLAG(IS_WIN) const char kEvaluateD3D[] = "d3d-support"; const char kEvaluate3dDisplayMode[] = "3d-display-mode";
diff --git a/remoting/host/base/switches.h b/remoting/host/base/switches.h index 433b361..def352a 100644 --- a/remoting/host/base/switches.h +++ b/remoting/host/base/switches.h
@@ -46,6 +46,9 @@ extern const char kEnableWtmpdb[]; #endif +// Indicates whether Corp Messaging should be enabled for signaling. +extern const char kEnableCorpMessaging[]; + // Values for kEvaluateCapabilitySwitchName. #if BUILDFLAG(IS_WIN) // Executes EvaluateD3D() function.
diff --git a/remoting/host/remoting_me2me_host.cc b/remoting/host/remoting_me2me_host.cc index 21294e83..1722ff8 100644 --- a/remoting/host/remoting_me2me_host.cc +++ b/remoting/host/remoting_me2me_host.cc
@@ -1748,6 +1748,14 @@ zombie_host_detector_ = std::make_unique<ZombieHostDetector>(base::BindOnce( &HostProcess::OnZombieStateDetected, base::Unretained(this))); +#if BUILDFLAG(IS_LINUX) + // TODO: joedow - Remove Linux scope after this codepath has been stabilized. + const base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess(); + if (is_corp_host_ && cmd_line->HasSwitch(kEnableCorpMessaging)) { + // TODO: joedow - Create CorpSignalStrategy instance here. + } +#endif + auto ftl_signal_strategy = std::make_unique<FtlSignalStrategy>( std::make_unique<OAuthTokenGetterProxy>( oauth_token_getter_->GetWeakPtr()),
diff --git a/remoting/proto/messaging_service.h b/remoting/proto/messaging_service.h index cb1a609..940b093 100644 --- a/remoting/proto/messaging_service.h +++ b/remoting/proto/messaging_service.h
@@ -35,6 +35,11 @@ IqStanzaStruct(const IqStanzaStruct&); IqStanzaStruct& operator=(const IqStanzaStruct&); ~IqStanzaStruct(); + + // Provides proof that the host is authorized to respond to client messages. + std::string messaging_authz_token; + // The IqStanza XML in serialized form. + std::string xml; }; struct PingPongStruct {
diff --git a/services/on_device_model/ml/BUILD.gn b/services/on_device_model/ml/BUILD.gn index 67ee35a..237f1fe 100644 --- a/services/on_device_model/ml/BUILD.gn +++ b/services/on_device_model/ml/BUILD.gn
@@ -86,9 +86,6 @@ if (!is_fuchsia && build_with_tflite_lib) { deps += [ "//services/on_device_model/safety:bert_safety_model" ] } - if (is_win || is_mac || is_linux) { - deps += [ "//third_party/xnnpack" ] - } public_deps = [ ":api", ":ml_holder_no_internal",
diff --git a/services/on_device_model/ml/DEPS b/services/on_device_model/ml/DEPS index f06f8ee..539fd67 100644 --- a/services/on_device_model/ml/DEPS +++ b/services/on_device_model/ml/DEPS
@@ -3,5 +3,4 @@ "+components/optimization_guide/machine_learning_tflite_buildflags.h", "+components/translate/core/language_detection", "+third_party/rust/chromium_crates_io/vendor/llguidance-v1/llguidance.h", - "+third_party/xnnpack", ]
diff --git a/services/on_device_model/ml/on_device_model_executor.cc b/services/on_device_model/ml/on_device_model_executor.cc index 0eb8ab9..91953d52 100644 --- a/services/on_device_model/ml/on_device_model_executor.cc +++ b/services/on_device_model/ml/on_device_model_executor.cc
@@ -35,10 +35,6 @@ #include "services/on_device_model/public/mojom/on_device_model.mojom.h" #include "services/on_device_model/public/mojom/on_device_model_service.mojom.h" -#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN) || BUILDFLAG(IS_LINUX) -#include "third_party/xnnpack/src/include/xnnpack.h" // nogncheck -#endif - #if BUILDFLAG(IS_MAC) #include "base/apple/foundation_util.h" #endif @@ -71,45 +67,6 @@ &optimization_guide::features::kOptimizationGuideOnDeviceModel, "on_device_model_allow_fp16", true}; -#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN) || BUILDFLAG(IS_LINUX) -// This is a copy of the XNNPackCacheHeader struct from -// third_party/tflite/src/tensorflow/lite/delegates/xnnpack/weight_cache.h -// We can't include that header directly because of linter issues. -// TODO(crbug.com/447174993): Remove once xnnpack includes cb018b2d. -struct XNNPackCacheHeader { - enum : uint64_t { kInvalidHeader = 0, kVersion = 1 }; - uint64_t version; - uint8_t xnnpack_build_identifier[32]; - uint64_t buffer_list_offset; - uint64_t buffer_list_size; -}; - -// Truncates the given xnnpack cache file if it is not compatible with the -// current build. -void MaybeDeleteCacheFile(base::File& cache_file) { - if (!cache_file.IsValid()) { - return; - } - XNNPackCacheHeader header; - if (cache_file.GetLength() < static_cast<int64_t>(sizeof(header))) { - return; - } - // SAFETY: `header` is stack-allocated and guaranteed to be non-null. - auto header_span = UNSAFE_BUFFERS( - base::span(reinterpret_cast<uint8_t*>(&header), sizeof(header))); - if (!cache_file.ReadAndCheck(0, header_span)) { - return; - } - if (header.version == XNNPackCacheHeader::kVersion && - xnn_experimental_check_build_identifier( - header.xnnpack_build_identifier, - sizeof(header.xnnpack_build_identifier))) { - return; - } - cache_file.SetLength(0); -} -#endif // BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN) || BUILDFLAG(IS_LINUX) - // Helper to bind object methods as weak task-posting callback functions. template <typename R, typename C, typename... Args> std::function<R(Args...)> CreateWeakCallbackFn(R (C::*method)(Args...), @@ -765,21 +722,6 @@ data.model_path = weights_path_str.data(); data.sentencepiece_model_path = sp_model_path_str.data(); } - - // Xnnpack doesn't delete the old cache file when it needs to be rebuilt - // due to its build identifier changing, which will happen during browser - // updates. This manually checks if the cache's build identifier matches the - // current build, and if not, truncates it. This is a temporary fix until - // xnnpack is updated with cb018b2d. - // TODO(crbug.com/447174993): Remove once xnnpack includes cb018b2d. -#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN) || BUILDFLAG(IS_LINUX) - if (params->backend_type == ml::ModelBackendType::kCpuBackend) { - MaybeDeleteCacheFile(assets.cache); - } - MaybeDeleteCacheFile(assets.encoder_cache); - MaybeDeleteCacheFile(assets.adapter_cache); -#endif // BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN) || BUILDFLAG(IS_LINUX) - // TODO(crbug.com/400998489): Cache files are experimental for now. data.cache_file = params->backend_type == ml::ModelBackendType::kCpuBackend && assets.cache.IsValid()
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index 8da77b6..82911be2 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -207,6 +207,21 @@ ] } ], + "AccessibilityExtendedSelection": [ + { + "platforms": [ + "android" + ], + "experiments": [ + { + "name": "Enabled", + "enable_features": [ + "AccessibilityExtendedSelection" + ] + } + ] + } + ], "AccessibilityImproveLiveRegionAnnounce": [ { "platforms": [ @@ -942,22 +957,6 @@ ] } ], - "AndroidOpenIncognitoAsWindow": [ - { - "platforms": [ - "android" - ], - "experiments": [ - { - "name": "Enabled_20251204", - "enable_features": [ - "AndroidOpenIncognitoAsWindow", - "TabStripIncognitoMigration" - ] - } - ] - } - ], "AndroidPinnedTabs": [ { "platforms": [ @@ -2594,7 +2593,7 @@ ] } ], - "AutofillEnableCvcStorageIOS": [ + "AutofillEnableCvcStorage": [ { "platforms": [ "ios" @@ -12653,6 +12652,24 @@ ] } ], + "HeliosZeroStateSuggestions": [ + { + "platforms": [ + "ios" + ], + "experiments": [ + { + "name": "Enabled", + "params": { + "ZeroStateSuggestionsPlacementAskGemini": "true" + }, + "enable_features": [ + "ZeroStateSuggestions" + ] + } + ] + } + ], "HelpAppLauncherSearch": [ { "platforms": [ @@ -14560,6 +14577,21 @@ ] } ], + "InitializePoliciesForSignedInUserInNewEntryPoints": [ + { + "platforms": [ + "android" + ], + "experiments": [ + { + "name": "Enabled", + "enable_features": [ + "InitializePoliciesForSignedInUserInNewEntryPoints" + ] + } + ] + } + ], "InlineFullscreenPerfExperiment": [ { "platforms": [ @@ -24485,27 +24517,6 @@ ] } ], - "StaticStorageQuota": [ - { - "platforms": [ - "android", - "android_webview", - "chromeos", - "ios", - "linux", - "mac", - "windows" - ], - "experiments": [ - { - "name": "Enabled", - "enable_features": [ - "StaticStorageQuota" - ] - } - ] - } - ], "StickyActivationTest": [ { "platforms": [ @@ -26352,6 +26363,23 @@ ] } ], + "UserValueDefaultBrowserStrings": [ + { + "platforms": [ + "linux", + "mac", + "windows" + ], + "experiments": [ + { + "name": "Enabled", + "enable_features": [ + "UserValueDefaultBrowserStrings" + ] + } + ] + } + ], "V8CodeFlushing": [ { "platforms": [
diff --git a/third_party/angle b/third_party/angle index 1196966..91d4642 160000 --- a/third_party/angle +++ b/third_party/angle
@@ -1 +1 @@ -Subproject commit 1196966d01b599b2fb99b4e511b65014a2f5a3a8 +Subproject commit 91d464283d745216a6ba807c8cfa33b7379e0fb7
diff --git a/third_party/blink/public/mojom/BUILD.gn b/third_party/blink/public/mojom/BUILD.gn index f46dd569..e6d7ade29 100644 --- a/third_party/blink/public/mojom/BUILD.gn +++ b/third_party/blink/public/mojom/BUILD.gn
@@ -287,6 +287,7 @@ public_deps = [ ":android_mojo_bindings", ":color_scheme_mojo_bindings", + ":credentialmanagement_mojo_bindings", ":mojom_mhtml_load_result", ":script_type_mojo_bindings", ":web_feature_mojo_bindings", @@ -1125,8 +1126,6 @@ "blob/file_backed_blob_factory.mojom", "blob/serialized_blob.mojom", "contacts/contacts_manager.mojom", - "credentialmanagement/credential_manager.mojom", - "credentialmanagement/credential_type_flags.mojom", "digital_goods/digital_goods.mojom", "document_metadata/document_metadata.mojom", "facilitated_payments/payment_link_handler.mojom", @@ -1147,6 +1146,7 @@ ] public_deps = [ + ":credentialmanagement_mojo_bindings", "//components/digital_goods/mojom", "//components/payments/mojom", "//components/schema_org/common:mojom", @@ -1242,33 +1242,8 @@ traits_sources = [ "authenticator_mojom_traits.cc" ] traits_public_deps = [ "//base", - "//device/fido", - ] - }, - { - types = [ - { - mojom = "blink.mojom.CredentialType" - cpp = "::password_manager::CredentialType" - }, - { - mojom = "blink.mojom.CredentialMediationRequirement" - cpp = "::password_manager::CredentialMediationRequirement" - }, - { - mojom = "blink.mojom.CredentialInfo" - cpp = "::password_manager::CredentialInfo" - }, - { - mojom = "blink.mojom.CredentialManagerError" - cpp = "::password_manager::CredentialManagerError" - }, - ] - traits_headers = [ "//components/password_manager/content/common/credential_manager_mojom_traits.h" ] - traits_sources = [ "//components/password_manager/content/common/credential_manager_mojom_traits.cc" ] - traits_public_deps = [ - "//base", "//components/password_manager/core/common", + "//device/fido", ] }, ] @@ -1932,3 +1907,54 @@ export_define = "BLINK_COMMON_IMPLEMENTATION=1" export_header = "third_party/blink/public/common/common_export.h" } + +mojom_component("credentialmanagement_mojo_bindings") { + generate_java = true + + sources = [ + "credentialmanagement/credential_manager.mojom", + "credentialmanagement/credential_type_flags.mojom", + ] + + public_deps = [ + "//mojo/public/mojom/base", + "//url/mojom:url_mojom_gurl", + "//url/mojom:url_mojom_scheme_host_port", + ] + + cpp_typemaps = [ + { + types = [ + { + mojom = "blink.mojom.CredentialType" + cpp = "::password_manager::CredentialType" + }, + { + mojom = "blink.mojom.CredentialMediationRequirement" + cpp = "::password_manager::CredentialMediationRequirement" + }, + { + mojom = "blink.mojom.CredentialInfo" + cpp = "::password_manager::CredentialInfo" + }, + { + mojom = "blink.mojom.CredentialManagerError" + cpp = "::password_manager::CredentialManagerError" + }, + ] + traits_headers = [ "//components/password_manager/content/common/credential_manager_mojom_traits.h" ] + traits_sources = [ "//components/password_manager/content/common/credential_manager_mojom_traits.cc" ] + traits_public_deps = [ + "//base", + "//components/password_manager/core/common", + ] + }, + ] + + macro_prefix = "CREDENTIALMANAGEMENT_MOJOM" + output_prefix = "credentialmanagement_mojom" + + export_class_attribute_blink = "PLATFORM_EXPORT" + export_define_blink = "BLINK_PLATFORM_IMPLEMENTATION=1" + export_header_blink = "third_party/blink/renderer/platform/platform_export.h" +}
diff --git a/third_party/blink/renderer/core/animation/animation.cc b/third_party/blink/renderer/core/animation/animation.cc index 8a4e1dce..8a2eca67 100644 --- a/third_party/blink/renderer/core/animation/animation.cc +++ b/third_party/blink/renderer/core/animation/animation.cc
@@ -1558,7 +1558,6 @@ // 2. If the play state of animation is paused, abort these steps. if (pending_pause_ || CalculateAnimationPlayState() == V8AnimationPlayState::Enum::kPaused) { - SetPausedForTrigger(false); return; } @@ -1594,8 +1593,6 @@ } } - SetPausedForTrigger(false); - // 6. If seek time is resolved, // If has finite timeline is true, // Set animation's start time to seek time.
diff --git a/third_party/blink/renderer/core/animation/css/css_animations.cc b/third_party/blink/renderer/core/animation/css/css_animations.cc index 4db30ca4..74c5a62 100644 --- a/third_party/blink/renderer/core/animation/css/css_animations.cc +++ b/third_party/blink/renderer/core/animation/css/css_animations.cc
@@ -2363,13 +2363,20 @@ animation->SetTriggerActionPlayState( entry.play_state_list[entry.name_index % entry.play_state_list.size()]); - if (!entry.trigger_attachments) { + if (entry.trigger_attachments) { + // Pause the trigger in anticipation of later finding the attached + // trigger. This allows the animation to show up in getAnimations. + animation->pause(); + animation->SetPausedForTrigger(true); + if (RuntimeEnabledFeatures::LimitTriggerAttachmentUpdatesEnabled()) { + element->GetDocument() + .GetDocumentAnimations() + .AddPendingTriggerAttachmentUpdate(animation); + } + } else { animation->play(); - } else if (RuntimeEnabledFeatures::LimitTriggerAttachmentUpdatesEnabled()) { - element->GetDocument() - .GetDocumentAnimations() - .AddPendingTriggerAttachmentUpdate(animation); } + if (inert_animation->Paused()) { animation->pause(); }
diff --git a/third_party/blink/renderer/core/css/OWNERS b/third_party/blink/renderer/core/css/OWNERS index 5897f27..9386bd2 100644 --- a/third_party/blink/renderer/core/css/OWNERS +++ b/third_party/blink/renderer/core/css/OWNERS
@@ -1,5 +1,6 @@ andruud@chromium.org futhark@chromium.org +kbabbitt@microsoft.com moonira@google.com sakhapov@chromium.org sesse@chromium.org
diff --git a/third_party/blink/renderer/core/dom/OWNERS b/third_party/blink/renderer/core/dom/OWNERS index 9037fe6..8e1f6b1 100644 --- a/third_party/blink/renderer/core/dom/OWNERS +++ b/third_party/blink/renderer/core/dom/OWNERS
@@ -3,7 +3,6 @@ dbaron@chromium.org dom@chromium.org xiaochengh@chromium.org -dizhangg@chromium.org per-file *_mojom_traits*.*=set noparent per-file *_mojom_traits*.*=file://ipc/SECURITY_OWNERS
diff --git a/third_party/blink/renderer/core/dom/document.cc b/third_party/blink/renderer/core/dom/document.cc index 51e309d..79441f3 100644 --- a/third_party/blink/renderer/core/dom/document.cc +++ b/third_party/blink/renderer/core/dom/document.cc
@@ -10147,7 +10147,8 @@ return nullptr; } Document* doc = parseHTMLInternal(context, compliant_html, exception_state); - SanitizerAPI::SanitizeUnsafeInternal(doc, options, exception_state); + SanitizerAPI::SanitizeUnsafeInternal( + /*context_element*/ doc, /*root_element*/ doc, options, exception_state); return doc; } @@ -10158,7 +10159,8 @@ ExceptionState& exception_state) { CHECK(RuntimeEnabledFeatures::SanitizerAPIEnabled()); Document* doc = parseHTMLInternal(context, html, exception_state); - SanitizerAPI::SanitizeSafeInternal(doc, options, exception_state); + SanitizerAPI::SanitizeSafeInternal( + /*context_element*/ doc, /*root_element*/ doc, options, exception_state); return doc; }
diff --git a/third_party/blink/renderer/core/dom/element.cc b/third_party/blink/renderer/core/dom/element.cc index 6076438..d05a21c3 100644 --- a/third_party/blink/renderer/core/dom/element.cc +++ b/third_party/blink/renderer/core/dom/element.cc
@@ -8751,6 +8751,8 @@ const String& html, ParseDeclarativeShadowRoots parse_declarative_shadows, ForceHtml force_html, + std::variant<std::monostate, SetHTMLOptions*, SetHTMLUnsafeOptions*> + options, ExceptionState& exception_state) { if (html.empty() && !HasNonInBodyInsertionMode()) { setTextContent(html); @@ -8765,7 +8767,25 @@ } if (DocumentFragment* fragment = CreateFragmentForInnerOuterHTML( html, this, kAllowScriptingContent, parse_declarative_shadows, - force_html, registry, exception_state)) { + force_html, + std::holds_alternative<std::monostate>(options) + ? ForceInertTemplate::kDontForce + : ForceInertTemplate::kForce, + registry, exception_state)) { + if (std::holds_alternative<SetHTMLOptions*>(options)) { + CHECK(RuntimeEnabledFeatures::SanitizerAPIEnabled()); + SanitizerAPI::SanitizeSafeInternal(this, fragment, + std::get<SetHTMLOptions*>(options), + exception_state); + } else if (std::holds_alternative<SetHTMLUnsafeOptions*>(options)) { + CHECK(RuntimeEnabledFeatures::SanitizerAPIEnabled()); + SanitizerAPI::SanitizeUnsafeInternal( + this, fragment, std::get<SetHTMLUnsafeOptions*>(options), + exception_state); + } else { + CHECK(std::holds_alternative<std::monostate>(options)); + // No options; nothing to do. + } ContainerNode* container = this; bool swap_dom_parts{false}; if (template_element) { @@ -8790,7 +8810,8 @@ void Element::SetInnerHTMLWithoutTrustedTypes(const String& html, ExceptionState& exception_state) { SetInnerHTMLInternal(html, ParseDeclarativeShadowRoots::kDontParse, - ForceHtml::kDontForce, exception_state); + ForceHtml::kDontForce, std::monostate{}, + exception_state); } void Element::setInnerHTML( @@ -8830,6 +8851,7 @@ DocumentFragment* fragment = CreateFragmentForInnerOuterHTML( html, parent, kAllowScriptingContent, ParseDeclarativeShadowRoots::kDontParse, ForceHtml::kDontForce, + ForceInertTemplate::kDontForce, RuntimeEnabledFeatures::ScopedCustomElementRegistryEnabled() ? customElementRegistry() : GetDocument().customElementRegistry(), @@ -9093,6 +9115,7 @@ DocumentFragment* fragment = CreateFragmentForInnerOuterHTML( markup, context_element, kAllowScriptingContent, ParseDeclarativeShadowRoots::kDontParse, ForceHtml::kDontForce, + ForceInertTemplate::kDontForce, RuntimeEnabledFeatures::ScopedCustomElementRegistryEnabled() ? customElementRegistry() : GetDocument().customElementRegistry(), @@ -12974,7 +12997,7 @@ ExceptionState& exception_state) { UseCounter::Count(GetDocument(), WebFeature::kHTMLUnsafeMethods); SetInnerHTMLInternal(html, ParseDeclarativeShadowRoots::kParse, - ForceHtml::kForce, exception_state); + ForceHtml::kForce, std::monostate{}, exception_state); } void Element::setHTMLUnsafe(const V8UnionStringOrTrustedHTML* html, @@ -12986,7 +13009,7 @@ return; } SetInnerHTMLInternal(compliant_html, ParseDeclarativeShadowRoots::kParse, - ForceHtml::kForce, exception_state); + ForceHtml::kForce, std::monostate{}, exception_state); } void Element::setHTMLUnsafe(const V8UnionStringOrTrustedHTML* html, @@ -12999,8 +13022,7 @@ return; } SetInnerHTMLInternal(compliant_html, ParseDeclarativeShadowRoots::kParse, - ForceHtml::kForce, exception_state); - SanitizerAPI::SanitizeUnsafeInternal(this, options, exception_state); + ForceHtml::kForce, options, exception_state); } void Element::setHTML(const String& html, @@ -13008,8 +13030,7 @@ ExceptionState& exception_state) { CHECK(RuntimeEnabledFeatures::SanitizerAPIEnabled()); SetInnerHTMLInternal(html, ParseDeclarativeShadowRoots::kParse, - ForceHtml::kForce, exception_state); - SanitizerAPI::SanitizeSafeInternal(this, options, exception_state); + ForceHtml::kForce, options, exception_state); } void Element::SetNamedTriggers(NamedAnimationTriggerMap&& named_triggers) {
diff --git a/third_party/blink/renderer/core/dom/element.h b/third_party/blink/renderer/core/dom/element.h index b2fbeee..b8612fd 100644 --- a/third_party/blink/renderer/core/dom/element.h +++ b/third_party/blink/renderer/core/dom/element.h
@@ -2460,6 +2460,12 @@ const String&, ParseDeclarativeShadowRoots parse_declarative_shadows, ForceHtml force_html_over_xml, + // When called from SetHTML or SetHTMLUnsafe, SetInnerHTMLInternal must + // process their options dictionary, which you can pass into |options|. + // When called from a method without options, like the classic innerHTML + // setter, you can pass std::monostate{} to designate no options. + std::variant<std::monostate, SetHTMLOptions*, SetHTMLUnsafeOptions*> + options, ExceptionState&); ElementRareDataVector* GetElementRareData() const;
diff --git a/third_party/blink/renderer/core/dom/events/event_dispatcher.cc b/third_party/blink/renderer/core/dom/events/event_dispatcher.cc index bac15363..46495b3 100644 --- a/third_party/blink/renderer/core/dom/events/event_dispatcher.cc +++ b/third_party/blink/renderer/core/dom/events/event_dispatcher.cc
@@ -230,19 +230,23 @@ } } - // 6. Let isActivationEvent be true, if event is a MouseEvent object and + // 6.4. Let isActivationEvent be true, if event is a MouseEvent object and // event's type attribute is "click", and false otherwise. // // We need to include non-standard textInput event for HTMLInputElement. const bool is_activation_event = is_click || event_->type() == event_type_names::kTextInput; - // 7. Let activationTarget be target, if isActivationEvent is true and target - // has activation behavior, and null otherwise. + // 6.5. If isActivationEvent is true and target has activation behavior, then + // set activationTarget to target. Node* activation_target = is_activation_event && node_->HasActivationBehavior() ? node_ : nullptr; - // A part of step 9 loop. + // A part of step 6.9 loop. + // + // 6.9.6.1. If isActivationEvent is true, event's bubbles attribute is true, + // activationTarget is null, and parent has activation behavior, then set + // activationTarget to parent. if (is_activation_event && !activation_target && event_->bubbles()) { wtf_size_t size = event_->GetEventPath().size(); for (wtf_size_t i = 1; i < size; ++i) { @@ -263,8 +267,8 @@ inspector_event_dispatch_event::Data, *event_, document.GetAgent().isolate()); EventDispatchHandlingState* pre_dispatch_event_handler_result = nullptr; - if (DispatchEventPreProcess(activation_target, - pre_dispatch_event_handler_result) == + if (DispatchEventLegacyPreActivationBehavior( + activation_target, pre_dispatch_event_handler_result) == kContinueDispatching) { if (DispatchEventAtCapturing() == kContinueDispatching) { DispatchEventAtBubbling(); @@ -278,15 +282,16 @@ return result; } -inline EventDispatchContinuation EventDispatcher::DispatchEventPreProcess( +inline EventDispatchContinuation +EventDispatcher::DispatchEventLegacyPreActivationBehavior( Node* activation_target, EventDispatchHandlingState*& pre_dispatch_event_handler_result) { - // 11. If activationTarget is non-null and activationTarget has + // 12. If activationTarget is non-null and activationTarget has // legacy-pre-activation behavior, then run activationTarget's // legacy-pre-activation behavior. if (activation_target) { pre_dispatch_event_handler_result = - activation_target->PreDispatchEventHandler(*event_); + activation_target->LegacyPreActivationBehavior(*event_); } return (event_->GetEventPath().IsEmpty() || event_->PropagationStopped()) @@ -305,15 +310,24 @@ event_->PropagationStopped()) return kDoneDispatching; + // https://dom.spec.whatwg.org/#concept-event-dispatch + // 6.13. For each struct of event's path, in reverse order: for (wtf_size_t i = event_->GetEventPath().size(); i > 0; --i) { const NodeEventContext& event_context = event_->GetEventPath()[i - 1]; if (event_context.CurrentTargetSameAsTarget()) { + // 6.13.1. If struct's shadow-adjusted target is non-null, then set + // event's eventPhase attribute to AT_TARGET. event_->SetEventPhase(Event::PhaseType::kAtTarget); event_->SetFireOnlyCaptureListenersAtTarget(true); + // 6.13.3. Invoke with struct, event, "capturing", and + // legacyOutputDidListenersThrowFlag if given. event_context.HandleLocalEvents(*event_); event_->SetFireOnlyCaptureListenersAtTarget(false); } else { + // 6.13.2. Otherwise, set event's eventPhase attribute to CAPTURING_PHASE. event_->SetEventPhase(Event::PhaseType::kCapturingPhase); + // 6.13.3. Invoke with struct, event, "capturing", and + // legacyOutputDidListenersThrowFlag if given. event_context.HandleLocalEvents(*event_); } if (event_->PropagationStopped()) @@ -327,19 +341,31 @@ // Trigger bubbling event handlers, starting at the bottom and working our way // up. On the first one, the target, change the event phase to AT_TARGET and // fire only the bubble listeners on it. + + // https://dom.spec.whatwg.org/#concept-event-dispatch + // 6.14. For each struct of event's path. wtf_size_t size = event_->GetEventPath().size(); for (wtf_size_t i = 0; i < size; ++i) { const NodeEventContext& event_context = event_->GetEventPath()[i]; if (event_context.CurrentTargetSameAsTarget()) { + // 6.14.1. If struct's shadow-adjusted target is non-null, then set + // event's eventPhase attribute to AT_TARGET. + // // TODO(hayato): Need to check cancelBubble() also here? event_->SetEventPhase(Event::PhaseType::kAtTarget); event_->SetFireOnlyNonCaptureListenersAtTarget(true); + // 6.14.3. Invoke with struct, event, "bubbling", and + // legacyOutputDidListenersThrowFlag if given. event_context.HandleLocalEvents(*event_); event_->SetFireOnlyNonCaptureListenersAtTarget(false); } else if (event_->bubbles() && !event_->cancelBubble()) { + // 6.14.2.2. Set event's eventPhase attribute to BUBBLING_PHASE. event_->SetEventPhase(Event::PhaseType::kBubblingPhase); + // 6.14.3. Invoke with struct, event, "bubbling", and + // legacyOutputDidListenersThrowFlag if given. event_context.HandleLocalEvents(*event_); } else { + // 6.14.1.1. If event's bubbles attribute is false, then continue. continue; } if (event_->PropagationStopped()) @@ -355,16 +381,19 @@ Node* activation_target, EventDispatchHandlingState* pre_dispatch_event_handler_result) { event_->SetTarget(&EventPath::EventTargetRespectingTargetRules(*node_)); - // https://dom.spec.whatwg.org/#concept-event-dispatch - // 14. Unset event’s dispatch flag, stop propagation flag, and stop immediate + // This is a continuation of + // https://dom.spec.whatwg.org/#concept-event-dispatch. + + // 7. Set event's eventPhase attribute to NONE. + event_->SetEventPhase(Event::PhaseType::kNone); + + // 8. Set event's currentTarget attribute to null. + event_->SetCurrentTarget(nullptr); + + // 10. Unset event's dispatch flag, stop propagation flag, and stop immediate // propagation flag. event_->SetStopPropagation(false); event_->SetStopImmediatePropagation(false); - // 15. Set event’s eventPhase attribute to NONE. - event_->SetEventPhase(Event::PhaseType::kNone); - // TODO(rakina): investigate this and move it to the bottom of step 16 - // 17. Set event’s currentTarget attribute to null. - event_->SetCurrentTarget(nullptr); auto* mouse_event = DynamicTo<MouseEvent>(event_); bool is_click = @@ -375,11 +404,17 @@ if (AXObjectCache* cache = node_->GetDocument().ExistingAXObjectCache()) cache->HandleClicked(event_->RawTarget()->ToNode()); - // Pass the data from the PreDispatchEventHandler to the - // PostDispatchEventHandler. - // This may dispatch an event, and node_ and event_ might be altered. + // Pass the data from `Node::LegacyPreActivationBehavior()` to + // `Node::RunActivationBehavior(). + // + // This may dispatch an event, and `node_` and `event_` might be altered. + // + // Note that this runs only a subset of the behavior that the DOM & HTML + // Standards refer to as "activation behavior". See the documentation above + // `Node::RunActivationBehavior()` for more information on how activation + // behavior is implemented in Blink. if (activation_target) { - activation_target->PostDispatchEventHandler( + activation_target->RunActivationBehavior( *event_, pre_dispatch_event_handler_result); } // TODO(tkent): Is it safe to kick DefaultEventHandler() with such altered
diff --git a/third_party/blink/renderer/core/dom/events/event_dispatcher.h b/third_party/blink/renderer/core/dom/events/event_dispatcher.h index c66674f..650d571 100644 --- a/third_party/blink/renderer/core/dom/events/event_dispatcher.h +++ b/third_party/blink/renderer/core/dom/events/event_dispatcher.h
@@ -68,7 +68,14 @@ private: EventDispatcher(Node&, Event&); - EventDispatchContinuation DispatchEventPreProcess( + // This is the Blink equivalent to the DOM Standard's + // legacy-pre-activation behavior [1]. It is mostly the same, except it is + // called under a broader set of conditions. See the documentation above + // `Node::LegacyPreActivationBehavior()`. + // + // [1]: + // https://dom.spec.whatwg.org/#eventtarget-legacy-pre-activation-behavior. + EventDispatchContinuation DispatchEventLegacyPreActivationBehavior( Node* activation_target, EventDispatchHandlingState*&); EventDispatchContinuation DispatchEventAtCapturing();
diff --git a/third_party/blink/renderer/core/dom/node.h b/third_party/blink/renderer/core/dom/node.h index 717cb6d..8b7244b7 100644 --- a/third_party/blink/renderer/core/dom/node.h +++ b/third_party/blink/renderer/core/dom/node.h
@@ -940,13 +940,72 @@ void RemoveAllEventListeners() override; void RemoveAllEventListenersRecursively(); - // Handlers to do/undo actions on the target node before an event is - // dispatched to it and after the event has been dispatched. The data pointer - // is handed back by the preDispatch and passed to postDispatch. - virtual EventDispatchHandlingState* PreDispatchEventHandler(Event&) { + // This is the Blink equivalent to the DOM Standard's legacy-pre-activation + // behavior [1]. It is mostly the same, except it is called under a broader + // set of conditions. Specifically, the spec only calls this hook for + // "activation events", which are "click" MouseEvents, and only radio button + // & checkbox `<input>` elements provide legacy-pre-activation behavior (see + // [2]). Blink limits this method to "click" and "textinput" events for + // internal non-standard reasons, but still only radio button & checkbox + // `<input>` provide this pre-activation behavior. + // + // NOTE: This method is considered a legacy hold-over. Do not add new + // overrides of it. + // + // This method's return value is passed to `RunActivationBehavior()`. + // + // [1]: + // https://dom.spec.whatwg.org/#eventtarget-legacy-pre-activation-behavior. + // [2]: + // https://html.spec.whatwg.org/#the-input-element:legacy-pre-activation-behavior + virtual EventDispatchHandlingState* LegacyPreActivationBehavior(Event&) { return nullptr; } - virtual void PostDispatchEventHandler(Event&, EventDispatchHandlingState*) {} + // This is the Blink equivalent of a small subset of the many per-element + // implementations of the "activation behavior" hook [1]. Concrete + // implementations of this method only represent a subset of the spec's + // activation behavior hooks, due to the quirky, all-too disjointed way that + // Blink implements activation behavior. + // + // Specifically, the HTML Standard reduces many kinds of user interactions to + // a synthetic click event [2] that gets dispatched on the activated element. + // This is because "click" MouseEvents (also called "activation events") are + // the only kind of event that, when dispatched, also run an element's + // activation behavior hook. + // + // Blink, on the other hand, kind of inverts this model. Blink responds to + // user interactions and their associated (non-click) events *directly*, + // without first firing a synthetic click at the activation target. During + // this, for all trusted events (not limited to "click" events), Blink runs + // the event target's `DefaultEventHandler()` implementation, and leaves it to + // subclasses to filter which events / interaction types it is interested in; + // these are the same events/interactions that the HTML Standard reduces to + // synthetic click events to trigger activation behavior. This means, much of + // what the spec refers to as "activation behavior", actually lives in the + // `DefaultEventHandler()` implementation. + // + // After Node subclasses handle these events, they ultimately delegate to + // the base class implementation of `Node::DefaultEventHandler()`. That + // implementation converts (only) click events into synthetic DOMActivate + // events, and fires *those* at the target. This is where more of what the + // spec calls "activation behavior" lives in Blink—inside subclass + // implementations of `DefaultEventHandler()` that specifically respond to + // DOMActivate events. + // + // The remaining portion of what the spec calls "activation behavior" lives + // exactly where it should, in this method below, which is only called for + // "activation events", which are "click" MouseEvents (and "textinput" events, + // for internal non-standard reasons). + // + // This method's consumes the `EventDispatchHandlingState` that the + // `LegacyPreActivationBehavior()` steps return. + // + // [1]: + // https://dom.spec.whatwg.org/#eventtarget-legacy-pre-activation-behavior. + // [2]: https://html.spec.whatwg.org/C#activation:fire-a-click-event + // [3]: + // https://html.spec.whatwg.org/C#the-input-element:legacy-pre-activation-behavior + virtual void RunActivationBehavior(Event&, EventDispatchHandlingState*) {} void DispatchScopedEvent(Event&);
diff --git a/third_party/blink/renderer/core/dom/shadow_root.cc b/third_party/blink/renderer/core/dom/shadow_root.cc index 97acaa12..e8146c55 100644 --- a/third_party/blink/renderer/core/dom/shadow_root.cc +++ b/third_party/blink/renderer/core/dom/shadow_root.cc
@@ -155,8 +155,8 @@ if (DocumentFragment* fragment = CreateFragmentForInnerOuterHTML( html, &host(), kAllowScriptingContent, Element::ParseDeclarativeShadowRoots::kDontParse, - Element::ForceHtml::kDontForce, customElementRegistry(), - exception_state)) { + Element::ForceHtml::kDontForce, ForceInertTemplate::kDontForce, + customElementRegistry(), exception_state)) { ReplaceChildrenWithFragment(this, fragment, exception_state); } } @@ -184,10 +184,11 @@ if (DocumentFragment* fragment = CreateFragmentForInnerOuterHTML( compliant_html, &host(), kAllowScriptingContent, Element::ParseDeclarativeShadowRoots::kParse, - Element::ForceHtml::kDontForce, customElementRegistry(), - exception_state)) { + Element::ForceHtml::kDontForce, ForceInertTemplate::kForce, + customElementRegistry(), exception_state)) { if (RuntimeEnabledFeatures::SanitizerAPIEnabled()) { - SanitizerAPI::SanitizeUnsafeInternal(fragment, nullptr, exception_state); + SanitizerAPI::SanitizeUnsafeInternal(this, fragment, nullptr, + exception_state); } ReplaceChildrenWithFragment(this, fragment, exception_state); } @@ -205,10 +206,11 @@ if (DocumentFragment* fragment = CreateFragmentForInnerOuterHTML( compliant_html, &host(), kAllowScriptingContent, Element::ParseDeclarativeShadowRoots::kParse, - Element::ForceHtml::kDontForce, customElementRegistry(), - exception_state)) { + Element::ForceHtml::kDontForce, ForceInertTemplate::kForce, + customElementRegistry(), exception_state)) { if (RuntimeEnabledFeatures::SanitizerAPIEnabled()) { - SanitizerAPI::SanitizeUnsafeInternal(fragment, options, exception_state); + SanitizerAPI::SanitizeUnsafeInternal(this, fragment, options, + exception_state); } ReplaceChildrenWithFragment(this, fragment, exception_state); } @@ -220,10 +222,11 @@ if (DocumentFragment* fragment = CreateFragmentForInnerOuterHTML( html, &host(), kAllowScriptingContent, Element::ParseDeclarativeShadowRoots::kParse, - Element::ForceHtml::kDontForce, customElementRegistry(), - exception_state)) { + Element::ForceHtml::kDontForce, ForceInertTemplate::kForce, + customElementRegistry(), exception_state)) { if (RuntimeEnabledFeatures::SanitizerAPIEnabled()) { - SanitizerAPI::SanitizeSafeInternal(fragment, options, exception_state); + SanitizerAPI::SanitizeSafeInternal(this, fragment, options, + exception_state); } ReplaceChildrenWithFragment(this, fragment, exception_state); }
diff --git a/third_party/blink/renderer/core/editing/serializers/serialization.cc b/third_party/blink/renderer/core/editing/serializers/serialization.cc index d677f44..f3e34f1 100644 --- a/third_party/blink/renderer/core/editing/serializers/serialization.cc +++ b/third_party/blink/renderer/core/editing/serializers/serialization.cc
@@ -679,6 +679,7 @@ ParserContentPolicy parser_content_policy, Element::ParseDeclarativeShadowRoots parse_declarative_shadows, Element::ForceHtml force_html, + ForceInertTemplate force_inert, CustomElementRegistry* registry, ExceptionState& exception_state) { DCHECK(context_element); @@ -689,7 +690,8 @@ } Document& document = - IsA<HTMLTemplateElement>(*context_element) + (IsA<HTMLTemplateElement>(*context_element) || + force_inert == ForceInertTemplate::kForce) ? context_element->GetDocument().EnsureTemplateDocument() : context_element->GetDocument(); DocumentFragment* fragment = DocumentFragment::Create(document); @@ -820,7 +822,7 @@ DocumentFragment* fragment = CreateFragmentForInnerOuterHTML( markup, element, parser_content_policy, Element::ParseDeclarativeShadowRoots::kDontParse, - Element::ForceHtml::kDontForce, + Element::ForceHtml::kDontForce, ForceInertTemplate::kDontForce, RuntimeEnabledFeatures::ScopedCustomElementRegistryEnabled() ? element->customElementRegistry() : element->GetDocument().customElementRegistry(),
diff --git a/third_party/blink/renderer/core/editing/serializers/serialization.h b/third_party/blink/renderer/core/editing/serializers/serialization.h index 7546e99..67db6e9 100644 --- a/third_party/blink/renderer/core/editing/serializers/serialization.h +++ b/third_party/blink/renderer/core/editing/serializers/serialization.h
@@ -49,6 +49,10 @@ enum ChildrenOnly { kIncludeNode, kChildrenOnly }; +// ForceInertTemplate specifies whether the HTML parser should parse into an +// inert (non-active) template document. +enum class ForceInertTemplate { kDontForce, kForce }; + using ShadowRootSet = HeapHashSet<Member<ShadowRoot>>; struct ShadowRootInclusion final { STACK_ALLOCATED(); @@ -93,6 +97,7 @@ ParserContentPolicy, Element::ParseDeclarativeShadowRoots parse_declarative_shadows, Element::ForceHtml force_html, + ForceInertTemplate force_inert, CustomElementRegistry* registry, ExceptionState&); DocumentFragment* CreateFragmentForTransformToFragment(
diff --git a/third_party/blink/renderer/core/html/forms/checkbox_input_type.cc b/third_party/blink/renderer/core/html/forms/checkbox_input_type.cc index d337054a..43cfb74 100644 --- a/third_party/blink/renderer/core/html/forms/checkbox_input_type.cc +++ b/third_party/blink/renderer/core/html/forms/checkbox_input_type.cc
@@ -69,7 +69,7 @@ } } -ClickHandlingState* CheckboxInputType::WillDispatchClick() { +ClickHandlingState* CheckboxInputType::LegacyPreActivationBehavior() { // An event handler can use preventDefault or "return false" to reverse the // checking we do here. The ClickHandlingState object contains what we need // to undo what we did here in didDispatchClick. @@ -79,17 +79,30 @@ state->checked = GetElement().Checked(); state->indeterminate = GetElement().indeterminate(); - if (state->indeterminate) - GetElement().setIndeterminate(false); - + // https://html.spec.whatwg.org/C#the-input-element:legacy-pre-activation-behavior: + // + // The legacy-pre-activation behavior for input elements are these steps: + // + // 1. If this element's type attribute is in the Checkbox state, then set + // this element's checkedness to its opposite value (i.e. true if it is + // false, false if it is true) and set this element's indeterminate IDL + // attribute to false. + // + // Note it is not clear if the ordering of these two operations is important, + // since we technically do them in the opposite order than the spec. This + // should only be observable if `SetChecked()` fires an event whose handlers + // can read the indeterminate state. + GetElement().setIndeterminate(false); GetElement().SetChecked(!state->checked, TextFieldEventBehavior::kDispatchChangeEvent); + is_in_click_handler_ = true; return state; } -void CheckboxInputType::DidDispatchClick(Event& event, - const ClickHandlingState& state) { +void CheckboxInputType::RunInputActivationBehavior( + Event& event, + const ClickHandlingState& state) { if (event.defaultPrevented() || event.DefaultHandled()) { GetElement().setIndeterminate(state.indeterminate); GetElement().SetChecked(state.checked); @@ -98,6 +111,16 @@ // This is needed in order to match :user-valid/:user-invalid GetElement().SetUserHasEditedTheField(); } + // https://html.spec.whatwg.org/C#checkbox-state-(type=checkbox):input-activation-behavior. + // + // The input activation behavior is to run the following steps: + // + // 1. If the element is not connected, then return (this check is done in + // `DispatchInputAndChangeEventIfNeeded()` below). + // 2. Fire an event named input at the element with the bubbles and + // composed attributes initialized to true. + // 3. Fire an event named change at the element with the bubbles attribute + // initialized to true. GetElement().DispatchInputAndChangeEventIfNeeded(); } is_in_click_handler_ = false;
diff --git a/third_party/blink/renderer/core/html/forms/checkbox_input_type.h b/third_party/blink/renderer/core/html/forms/checkbox_input_type.h index 5c15aa7..ef21fb4 100644 --- a/third_party/blink/renderer/core/html/forms/checkbox_input_type.h +++ b/third_party/blink/renderer/core/html/forms/checkbox_input_type.h
@@ -46,8 +46,10 @@ AppearanceValue AutoAppearance() const override; String ValueMissingText() const override; void HandleKeyupEvent(KeyboardEvent&) override; - ClickHandlingState* WillDispatchClick() override; - void DidDispatchClick(Event&, const ClickHandlingState&) override; + // https://html.spec.whatwg.org/#the-input-element:legacy-pre-activation-behavior. + ClickHandlingState* LegacyPreActivationBehavior() override; + // https://html.spec.whatwg.org/C#checkbox-state-(type=checkbox):input-activation-behavior. + void RunInputActivationBehavior(Event&, const ClickHandlingState&) override; bool ShouldAppearIndeterminate() const override; };
diff --git a/third_party/blink/renderer/core/html/forms/html_input_element.cc b/third_party/blink/renderer/core/html/forms/html_input_element.cc index 9f1ba2e..ab4a43e 100644 --- a/third_party/blink/renderer/core/html/forms/html_input_element.cc +++ b/third_party/blink/renderer/core/html/forms/html_input_element.cc
@@ -1459,7 +1459,7 @@ SetAutofillState(WebAutofillState::kNotFilled); } -EventDispatchHandlingState* HTMLInputElement::PreDispatchEventHandler( +EventDispatchHandlingState* HTMLInputElement::LegacyPreActivationBehavior( Event& event) { if (event.type() == event_type_names::kTextInput && input_type_view_->ShouldSubmitImplicitly(event)) { @@ -1474,16 +1474,26 @@ mouse_event->button() != static_cast<int16_t>(WebPointerProperties::Button::kLeft)) return nullptr; - return input_type_view_->WillDispatchClick(); + return input_type_view_->LegacyPreActivationBehavior(); } -void HTMLInputElement::PostDispatchEventHandler( +void HTMLInputElement::RunActivationBehavior( Event& event, EventDispatchHandlingState* state) { - if (!state) + if (!state) { return; - input_type_view_->DidDispatchClick(event, - *static_cast<ClickHandlingState*>(state)); + } + + // https://html.spec.whatwg.org/C#the-input-element:activation-behaviour. + // + // The activation behavior for input elements element, given event, are these + // steps: + // + // [...] + // 2. Run element's input activation behavior, if any, and do nothing + // otherwise. + input_type_view_->RunInputActivationBehavior( + event, *static_cast<ClickHandlingState*>(state)); } void HTMLInputElement::DefaultEventHandler(Event& evt) {
diff --git a/third_party/blink/renderer/core/html/forms/html_input_element.h b/third_party/blink/renderer/core/html/forms/html_input_element.h index 66a0036..52e0158 100644 --- a/third_party/blink/renderer/core/html/forms/html_input_element.h +++ b/third_party/blink/renderer/core/html/forms/html_input_element.h
@@ -446,8 +446,8 @@ void ResetImpl() final; - EventDispatchHandlingState* PreDispatchEventHandler(Event&) final; - void PostDispatchEventHandler(Event&, EventDispatchHandlingState*) final; + EventDispatchHandlingState* LegacyPreActivationBehavior(Event&) final; + void RunActivationBehavior(Event&, EventDispatchHandlingState*) final; bool IsURLAttribute(const Attribute&) const final; bool HasLegalLinkAttribute(const QualifiedName&) const final;
diff --git a/third_party/blink/renderer/core/html/forms/input_type_view.cc b/third_party/blink/renderer/core/html/forms/input_type_view.cc index 56bd4df..fab886c 100644 --- a/third_party/blink/renderer/core/html/forms/input_type_view.cc +++ b/third_party/blink/renderer/core/html/forms/input_type_view.cc
@@ -187,11 +187,12 @@ void InputTypeView::StepAttributeChanged() {} -ClickHandlingState* InputTypeView::WillDispatchClick() { +ClickHandlingState* InputTypeView::LegacyPreActivationBehavior() { return nullptr; } -void InputTypeView::DidDispatchClick(Event&, const ClickHandlingState&) {} +void InputTypeView::RunInputActivationBehavior(Event&, + const ClickHandlingState&) {} void InputTypeView::UpdateView() {}
diff --git a/third_party/blink/renderer/core/html/forms/input_type_view.h b/third_party/blink/renderer/core/html/forms/input_type_view.h index 8d22e1af..5e072fa6 100644 --- a/third_party/blink/renderer/core/html/forms/input_type_view.h +++ b/third_party/blink/renderer/core/html/forms/input_type_view.h
@@ -89,8 +89,10 @@ virtual void HandleClickEvent(MouseEvent&); virtual void HandleMouseDownEvent(MouseEvent&); - virtual ClickHandlingState* WillDispatchClick(); - virtual void DidDispatchClick(Event&, const ClickHandlingState&); + // https://html.spec.whatwg.org/C#the-input-element:legacy-pre-activation-behavior. + virtual ClickHandlingState* LegacyPreActivationBehavior(); + // https://html.spec.whatwg.org/C#input-activation-behavior. + virtual void RunInputActivationBehavior(Event&, const ClickHandlingState&); virtual void HandleKeydownEvent(KeyboardEvent&); virtual void HandleKeypressEvent(KeyboardEvent&); virtual void HandleKeyupEvent(KeyboardEvent&);
diff --git a/third_party/blink/renderer/core/html/forms/radio_input_type.cc b/third_party/blink/renderer/core/html/forms/radio_input_type.cc index 53a4ea5..560dcf0af 100644 --- a/third_party/blink/renderer/core/html/forms/radio_input_type.cc +++ b/third_party/blink/renderer/core/html/forms/radio_input_type.cc
@@ -247,7 +247,7 @@ return GetElement().Checked(); } -ClickHandlingState* RadioInputType::WillDispatchClick() { +ClickHandlingState* RadioInputType::LegacyPreActivationBehavior() { // An event handler can use preventDefault or "return false" to reverse the // selection we do here. The ClickHandlingState object contains what we need // to undo what we did here in didDispatchClick. @@ -259,6 +259,14 @@ ClickHandlingState* state = MakeGarbageCollected<ClickHandlingState>(); + // https://html.spec.whatwg.org/C#the-input-element:legacy-pre-activation-behavior: + // + // The legacy-pre-activation behavior for input elements are these steps: + // + // 2. If this element's type attribute is in the Radio Button state, then + // get a reference to the element in this element's radio button group + // that has its checkedness set to true, if any, and then set this + // element's checkedness to true. state->checked = GetElement().Checked(); state->checked_radio_button = CheckedRadioButtonForGroup(); GetElement().SetChecked(true, TextFieldEventBehavior::kDispatchChangeEvent); @@ -266,8 +274,9 @@ return state; } -void RadioInputType::DidDispatchClick(Event& event, - const ClickHandlingState& state) { +void RadioInputType::RunInputActivationBehavior( + Event& event, + const ClickHandlingState& state) { if (event.defaultPrevented() || event.DefaultHandled()) { // Restore the original selected radio button if possible. // Make sure it is still a radio button and only do the restoration if it @@ -282,6 +291,15 @@ checked_radio_button->SetChecked(true); } } else if (state.checked != GetElement().Checked()) { + // https://html.spec.whatwg.org/C#radio-button-state-(type=radio):input-activation-behavior. + // + // The input activation behavior is to run the following steps: + // + // 1. If the element is not connected, then return. + // 2. Fire an event named input at the element with the bubbles and + // composed attributes initialized to true. + // 3. Fire an event named change at the element with the bubbles attribute + // initialized to true. GetElement().DispatchInputAndChangeEventIfNeeded(); } is_in_click_handler_ = false;
diff --git a/third_party/blink/renderer/core/html/forms/radio_input_type.h b/third_party/blink/renderer/core/html/forms/radio_input_type.h index 1aa6848..43c1169 100644 --- a/third_party/blink/renderer/core/html/forms/radio_input_type.h +++ b/third_party/blink/renderer/core/html/forms/radio_input_type.h
@@ -59,8 +59,10 @@ Element::UpdateBehavior update_behavior = Element::UpdateBehavior::kStyleAndLayout) const override; bool ShouldSendChangeEventAfterCheckedChanged() override; - ClickHandlingState* WillDispatchClick() override; - void DidDispatchClick(Event&, const ClickHandlingState&) override; + // https://html.spec.whatwg.org/C#the-input-element:legacy-pre-activation-behavior. + ClickHandlingState* LegacyPreActivationBehavior() override; + // https://html.spec.whatwg.org/C#radio-button-state-(type=radio):input-activation-behavior. + void RunInputActivationBehavior(Event&, const ClickHandlingState&) override; bool ShouldAppearIndeterminate() const override; HTMLInputElement* FindNextFocusableRadioButtonInGroup(HTMLInputElement*,
diff --git a/third_party/blink/renderer/core/html/forms/text_field_input_type.cc b/third_party/blink/renderer/core/html/forms/text_field_input_type.cc index 204d542..f3f387f 100644 --- a/third_party/blink/renderer/core/html/forms/text_field_input_type.cc +++ b/third_party/blink/renderer/core/html/forms/text_field_input_type.cc
@@ -65,16 +65,6 @@ return To<HTMLInputElement>(OwnerShadowHost()); } - EventDispatchHandlingState* PreDispatchEventHandler(Event& event) override { - // Chromium opens autofill popup in a mousedown event listener - // associated to the document. We don't want to open it in this case - // because we opens a datalist chooser later. - // FIXME: We should dispatch mousedown events even in such case. - if (event.type() == event_type_names::kMousedown) - event.stopPropagation(); - return nullptr; - } - void DefaultEventHandler(Event& event) override { DCHECK(GetDocument().IsActive()); if (event.type() != event_type_names::kClick)
diff --git a/third_party/blink/renderer/core/input/scroll_manager.cc b/third_party/blink/renderer/core/input/scroll_manager.cc index e462509..bee2cc6 100644 --- a/third_party/blink/renderer/core/input/scroll_manager.cc +++ b/third_party/blink/renderer/core/input/scroll_manager.cc
@@ -106,7 +106,7 @@ Node* cur_node = cur_box->GetNode(); if (cur_node) { - if (CanScroll(*cur_node, /* for_autoscroll */ false)) { + if (CanScroll(*cur_node)) { result.chain.push_front(cur_node->GetDomNodeId()); // If `cur_node` is scrollable, respect its overscroll-behavior to // determine whether the scroll should bubble to parent elements. @@ -139,7 +139,7 @@ return result; } -bool ScrollManager::CanScroll(const Node& current_node, bool for_autoscroll) { +bool ScrollManager::CanScroll(const Node& current_node) { LayoutBox* scrolling_box = current_node.GetLayoutBox(); if (auto* element = DynamicTo<Element>(current_node)) scrolling_box = element->GetLayoutBoxForScrolling(); @@ -148,23 +148,20 @@ // We need to always add the global root scroller even if it isn't scrollable // since we can always pinch-zoom and scroll as well as for overscroll - // effects. If autoscrolling, ignore this condition because we latch on - // to the deepest autoscrollable node. - if (scrolling_box->IsGlobalRootScroller() && !for_autoscroll) + // effects. + if (scrolling_box->IsGlobalRootScroller()) { return true; + } // If this is the main LayoutView of an active viewport (outermost main // frame), and it's not the root scroller, that means we have a non-default // root scroller on the page. In this case, attempts to scroll the LayoutView // should cause panning of the visual viewport as well so ensure it gets added // to the scroll chain. See LTHI::ApplyScroll for the equivalent behavior in - // CC. Node::NativeApplyScroll contains a special handler for this case. If - // autoscrolling, ignore this condition because we latch on to the deepest - // autoscrollable node. + // CC. Node::NativeApplyScroll contains a special handler for this case. if (IsA<LayoutView>(scrolling_box) && current_node.GetDocument().IsInMainFrame() && - frame_->GetPage()->GetVisualViewport().IsActiveViewport() && - !for_autoscroll) { + frame_->GetPage()->GetVisualViewport().IsActiveViewport()) { return true; }
diff --git a/third_party/blink/renderer/core/input/scroll_manager.h b/third_party/blink/renderer/core/input/scroll_manager.h index ac53f5b..9cb2cdd 100644 --- a/third_party/blink/renderer/core/input/scroll_manager.h +++ b/third_party/blink/renderer/core/input/scroll_manager.h
@@ -106,7 +106,7 @@ ScrollChainResult RecomputeScrollChain( const Node& start_node, mojom::blink::ScrollDirection direction); - bool CanScroll(const Node& current_node, bool for_autoscroll); + bool CanScroll(const Node& current_node); const Member<LocalFrame> frame_;
diff --git a/third_party/blink/renderer/core/sanitizer/sanitizer.cc b/third_party/blink/renderer/core/sanitizer/sanitizer.cc index f00478e..11da633 100644 --- a/third_party/blink/renderer/core/sanitizer/sanitizer.cc +++ b/third_party/blink/renderer/core/sanitizer/sanitizer.cc
@@ -796,6 +796,7 @@ // TODO(vogelheim): This is hideously inefficient, but very easy to implement. // We'll use this for now, so we can fully build out tests & other // infrastructure, and worry about efficiency later. + CHECK(!root->GetDocument().IsActive()); Sanitizer* safe = MakeGarbageCollected<Sanitizer>(); safe->setFrom(*this); safe->removeUnsafe(); @@ -803,6 +804,7 @@ } void Sanitizer::SanitizeUnsafe(Node* root) const { + CHECK(!root->GetDocument().IsActive()); Sanitize(root, /*safe*/ false); }
diff --git a/third_party/blink/renderer/core/sanitizer/sanitizer_api.cc b/third_party/blink/renderer/core/sanitizer/sanitizer_api.cc index 45968d79..a173cd8 100644 --- a/third_party/blink/renderer/core/sanitizer/sanitizer_api.cc +++ b/third_party/blink/renderer/core/sanitizer/sanitizer_api.cc
@@ -8,6 +8,7 @@ #include "third_party/blink/renderer/bindings/core/v8/v8_set_html_unsafe_options.h" #include "third_party/blink/renderer/bindings/core/v8/v8_union_sanitizer_sanitizerconfig_sanitizerpresets.h" #include "third_party/blink/renderer/core/dom/container_node.h" +#include "third_party/blink/renderer/core/dom/document.h" #include "third_party/blink/renderer/core/dom/element.h" #include "third_party/blink/renderer/core/html_names.h" #include "third_party/blink/renderer/core/sanitizer/sanitizer.h" @@ -20,19 +21,23 @@ // But because SetHTMLOptions and SetHTMLUnsafeOptions are unrelated types (as // far as C++ is concerned) they cannot easily be merged. -void SanitizerAPI::SanitizeSafeInternal(ContainerNode* element, +void SanitizerAPI::SanitizeSafeInternal(const ContainerNode* context_element, + ContainerNode* root_element, SetHTMLOptions* options, ExceptionState& exception_state) { + // Per spec, we need to parse & sanitize into an inert (non-active) document. + CHECK(!root_element->GetDocument().IsActive()); + if (exception_state.HadException()) { - element->setTextContent(""); + root_element->setTextContent(""); return; } - if (element->IsElementNode()) { - const Element* real_element = To<Element>(element); + if (context_element->IsElementNode()) { + const Element* real_element = To<Element>(context_element); if (real_element->TagQName() == html_names::kScriptTag || real_element->TagQName() == svg_names::kScriptTag) { - element->setTextContent(""); + root_element->setTextContent(""); return; } } @@ -66,14 +71,18 @@ } CHECK(sanitizer); - sanitizer->SanitizeSafe(element); + sanitizer->SanitizeSafe(root_element); } -void SanitizerAPI::SanitizeUnsafeInternal(ContainerNode* element, +void SanitizerAPI::SanitizeUnsafeInternal(const ContainerNode* context_element, + ContainerNode* root_element, SetHTMLUnsafeOptions* options, ExceptionState& exception_state) { + // Per spec, we need to parse & sanitize into an inert (non-active) document. + CHECK(!root_element->GetDocument().IsActive()); + if (exception_state.HadException()) { - element->setTextContent(""); + root_element->setTextContent(""); return; } @@ -106,7 +115,7 @@ } CHECK(sanitizer); - sanitizer->SanitizeUnsafe(element); + sanitizer->SanitizeUnsafe(root_element); } } // namespace blink
diff --git a/third_party/blink/renderer/core/sanitizer/sanitizer_api.h b/third_party/blink/renderer/core/sanitizer/sanitizer_api.h index b2e17787..3afd7a8e 100644 --- a/third_party/blink/renderer/core/sanitizer/sanitizer_api.h +++ b/third_party/blink/renderer/core/sanitizer/sanitizer_api.h
@@ -16,10 +16,12 @@ class SanitizerAPI final { public: - static void SanitizeSafeInternal(ContainerNode* element, + static void SanitizeSafeInternal(const ContainerNode* context_element, + ContainerNode* root_element, SetHTMLOptions* options, ExceptionState& exception_state); - static void SanitizeUnsafeInternal(ContainerNode* element, + static void SanitizeUnsafeInternal(const ContainerNode* context_element, + ContainerNode* root_element, SetHTMLUnsafeOptions* options, ExceptionState& exception_state); };
diff --git a/third_party/blink/renderer/platform/fonts/shaping/shape_result_test.cc b/third_party/blink/renderer/platform/fonts/shaping/shape_result_test.cc index 45bf42ad..eb888932 100644 --- a/third_party/blink/renderer/platform/fonts/shaping/shape_result_test.cc +++ b/third_party/blink/renderer/platform/fonts/shaping/shape_result_test.cc
@@ -83,7 +83,7 @@ } const Font* GetFont(FontType type) const { - return UNSAFE_TODO(fonts_holder->fonts[static_cast<size_t>(type)]); + return fonts_holder->fonts.at(static_cast<size_t>(type)); } FontCachePurgePreventer font_cache_purge_preventer; @@ -99,7 +99,7 @@ {20, 30, CreateShapeResult(TextDirection::kLtr)}, {30, 38, CreateShapeResult(TextDirection::kLtr)}, }}; - result->CopyRanges(&ranges[0], num_ranges); + result->CopyRanges(ranges.data(), num_ranges); std::array<Vector<ShapeResultTestGlyphInfo>, num_ranges> glyphs; for (unsigned i = 0; i < num_ranges; i++) @@ -136,7 +136,7 @@ {7, 10, CreateShapeResult(TextDirection::kRtl)}, {10, 15, CreateShapeResult(TextDirection::kRtl)}, }}; - result->CopyRanges(&ranges[0], num_ranges); + result->CopyRanges(ranges.data(), num_ranges); std::array<Vector<ShapeResultTestGlyphInfo>, num_ranges> glyphs; for (unsigned i = 0; i < num_ranges; i++) @@ -214,7 +214,7 @@ {20, 23, CreateShapeResult(TextDirection::kLtr)}, {25, 31, CreateShapeResult(TextDirection::kLtr)}, }); - result->CopyRanges(&ranges[0], 3); + result->CopyRanges(ranges.data(), 3); std::array<Vector<ShapeResultTestGlyphInfo>, 3> glyphs; ComputeGlyphResults(*ranges[0].target, &glyphs[0]); ComputeGlyphResults(*ranges[1].target, &glyphs[1]);
diff --git a/third_party/blink/renderer/platform/image-decoders/image_decoder.cc b/third_party/blink/renderer/platform/image-decoders/image_decoder.cc index c9d94ec6..17e7491c 100644 --- a/third_party/blink/renderer/platform/image-decoders/image_decoder.cc +++ b/third_party/blink/renderer/platform/image-decoders/image_decoder.cc
@@ -543,7 +543,7 @@ cc::ImageHeaderMetadata image_metadata{}; image_metadata.image_type = FileExtensionToImageType(FilenameExtension()); image_metadata.yuv_subsampling = GetYUVSubsampling(); - image_metadata.hdr_metadata = GetHDRMetadata(); + image_metadata.hdr_metadata = GetHDRMetadata().value_or(gfx::HDRMetadata()); image_metadata.image_size = size_; image_metadata.has_embedded_color_profile = HasEmbeddedColorProfile(); return image_metadata;
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5 index 09f83a9..416396f8 100644 --- a/third_party/blink/renderer/platform/runtime_enabled_features.json5 +++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -3778,7 +3778,7 @@ }, { name: "PaintTimingMixin", - status: "experimental", + status: "stable", }, { name: "PaintTimingRecordTimingForDetachedPaintedElements",
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index 68391cf..e080a1d0 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -5114,7 +5114,7 @@ crbug.com/40267498 virtual/fragmented-oof-in-cb/external/wpt/css/css-break/out-of-flow-in-multicolumn-093.html [ Failure ] crbug.com/40267498 virtual/fragmented-oof-in-cb/external/wpt/css/css-break/out-of-flow-in-multicolumn-114.html [ Failure ] crbug.com/40267498 virtual/fragmented-oof-in-cb/external/wpt/css/css-break/out-of-flow-in-multicolumn-115.html [ Failure ] -crbug.com/40267498 virtual/fragmented-oof-in-cb/external/wpt/css/css-break/out-of-flow-in-multicolumn-119.html [ Crash Failure ] +crbug.com/40267498 virtual/fragmented-oof-in-cb/external/wpt/css/css-break/out-of-flow-in-multicolumn-119.html [ Crash Failure Timeout ] crbug.com/40267498 virtual/fragmented-oof-in-cb/external/wpt/css/css-break/overflow-clip-015.html [ Failure ] crbug.com/40267498 virtual/fragmented-oof-in-cb/external/wpt/css/css-break/overflow-clip-016.html [ Failure ] crbug.com/40267498 virtual/fragmented-oof-in-cb/external/wpt/css/css-break/overflowing-block-print.html [ Failure ] @@ -10058,3 +10058,6 @@ # Gardener 2025-12-04 crbug.com/465643000 external/wpt/css/css-masking/clip-path/clip-path-inline-003.html [ Pass Failure ] + +# Gardener 2025-12-05 +crbug.com/466134898 http/tests/devtools/sources/debugger-pause/debugger-eval-on-call-frame-inside-iframe.js [ Timeout Pass ]
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/the-iframe-element/srcdoc-lifecycle-crash-crbug-1472607.https-expected.txt b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/the-iframe-element/srcdoc-lifecycle-crash-crbug-1472607.https-expected.txt new file mode 100644 index 0000000..9a674fcf --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/the-iframe-element/srcdoc-lifecycle-crash-crbug-1472607.https-expected.txt
@@ -0,0 +1,5 @@ +This is a testharness.js-based test. +[FAIL] requestStorageAccess() from about:blank Document before it gets replaced with a srcdoc resource does not crash the host process + promise_test: Unhandled rejection with value: object "NotAllowedError: document shutdown" +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/the-iframe-element/srcdoc-lifecycle-crash-crbug-1472607.https.html b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/the-iframe-element/srcdoc-lifecycle-crash-crbug-1472607.https.html new file mode 100644 index 0000000..0e17af2 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/the-iframe-element/srcdoc-lifecycle-crash-crbug-1472607.https.html
@@ -0,0 +1,60 @@ +<!doctype html> +<meta charset=utf-8> +<title>Chromium regression test for a Promise-related lifecycle crash in about:srcdoc iframes</title> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script src=/resources/testdriver.js></script> +<script src=/resources/testdriver-vendor.js></script> + +<body> +<script> +promise_test(async t => { + await test_driver.set_permission({ name: 'storage-access' }, 'granted'); +}, "common setup"); + +// In Chromium, this test would previously crash the renderer process. See +// documentation below. +promise_test(async t => { + const new_iframe = document.createElement('iframe'); + // Having this come before `append()` keeps the iframe on the "initial empty + // Document" (see [1]) while the about:srcdoc navigation loads asynchronously. + // + // [1]: https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/core/dom/document.h;l=2574;drc=69640c83afac0bde8247ceac5fe259f13a5265a7. + new_iframe.srcdoc = 'stuff'; + document.body.append(new_iframe); + + // It is not clear why this is needed, but it appears to reliably slow the + // *next*/last `requestStorageAccess()` call down such that the IPC coming + // from the browser to resolve its promise comes after the about:srcdoc + // navigation commits (and after the initial empty document is detached). + // + // If for some reason the about:srcdoc navigation commits after this first + // call to `requestStorageAccess()` resolves, then the next assert will fail. + await new_iframe.contentDocument.requestStorageAccess(); + + assert_equals(new_iframe.contentDocument.URL, "about:blank"); + // Now we're set up to trigger the Chromium bug that this test is exercising. + // The series of events that we're relying on, and trying to trigger, is: + // 1. Call `requestStorageAccess()` from the initial empty about:blank + // Document, before it gets replaced by a same-origin navigation (to + // about:srcdoc in this case). + // 2. While waiting for the Promise to resolve, the Document gets replaced by + // the navigation. This new Document shares a Window with the old + // now-detached initial one (per spec) since it is the first same-origin + // navigation after the initial empty Document, and those "special" in + // that they are done with replacement, and share the same Window. + // 3. After the navigation commits and the initial empty about:blank Document + // is replaced, the `requestStorageAccess()` Promise finally resolves. The + // callback runs in the renderer, since the lifetime of the callback is + // tied to the Window. + // + // In Chromium, this previously put us in a weird state where the callback ran + // against a live Window, but was associated with a detached Document, which + // bucked some assumptions and crashed the renderer; see + // https://crbug.com/40937729. The root cause of this is discussed here: + // https://docs.google.com/document/d/1wmvqbNZGtp1QluxW1sntZd_W1o1XsHlQd-ywNqwyu-Y/edit. + return new_iframe.contentDocument.requestStorageAccess(); +}, "requestStorageAccess() from about:blank Document before it gets " + + "replaced with a srcdoc resource does not crash the host process"); +</script> +</body>
diff --git a/third_party/blink/web_tests/external/wpt/largest-contentful-paint/web-font-styled-text-resize-swap-after-interaction.html b/third_party/blink/web_tests/external/wpt/largest-contentful-paint/web-font-styled-text-resize-swap-after-interaction.html index 71affbb..3ba02ba 100644 --- a/third_party/blink/web_tests/external/wpt/largest-contentful-paint/web-font-styled-text-resize-swap-after-interaction.html +++ b/third_party/blink/web_tests/external/wpt/largest-contentful-paint/web-font-styled-text-resize-swap-after-interaction.html
@@ -66,9 +66,9 @@ // Verify web font is downloaded. assert_own_property(window, 'PerformanceResourceTiming', "ResourceTiming not supported"); - const fontResourceEntries = performance.getEntriesByType('resource').filter( - (entry) => entry.name.endsWith('/fonts/AD.woff')); - assert_equals(fontResourceEntries.length, 1, 'Web font should be downloaded.'); + let url = '/fonts/AD.woff'; + var absoluteURL = new URL(url, location.href).href; + assert_equals(performance.getEntriesByName(absoluteURL).length, 1, 'Web font should be downloaded.'); // Verify web font is available. assert_true(document.fonts.check('16px ADTestFaceInteraction'), 'Font should be the web font added');
diff --git a/third_party/blink/web_tests/external/wpt/sanitizer-api/sanitizer-inert-document.tentative.html b/third_party/blink/web_tests/external/wpt/sanitizer-api/sanitizer-inert-document.tentative.html new file mode 100644 index 0000000..ca38ee2 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/sanitizer-api/sanitizer-inert-document.tentative.html
@@ -0,0 +1,79 @@ +<!DOCTYPE html> +<html> +<head> +<title>Test whether fragment created for sanitization is inert.</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +</head> +<body> +<div id="test"></div> +<script> +promise_test(t => { + return new Promise((resolve, fail) => { + globalThis.failsafe = fail; + globalThis.resolvesafe = resolve; + + const div = document.createElement("div"); + document.getElementById("test").appendChild(div); + div.setHTML(`<img src="data:image/png," onerror="globalThis.failsafe('shouldnt load')">`); + + const div2 = document.createElement("div"); + document.getElementById("test").appendChild(div2); + div2.innerHTML = `<img src="data:image/png," onerror="globalThis.resolvesafe('shoud load')">`; + }); +}, "Test whether setHTML executes the fail handler."); + +promise_test(t => { + return new Promise((resolve, fail) => { + globalThis.failunsafe = fail; + globalThis.resolveunsafe = resolve; + + const div = document.createElement("div"); + document.getElementById("test").appendChild(div); + div.setHTMLUnsafe( + `<img src="data:image/png," onerror="globalThis.failunsafe()">`, + {sanitizer: {removeElements: ["img"]}}); + + const div2 = document.createElement("div"); + document.getElementById("test").appendChild(div2); + div2.innerHTML = `<img src="data:image/png," onerror="globalThis.resolveunsafe()">`; + }); +}, "Test whether setHTMLUnsafe executes the fail handler."); + +const url = "/fetch/metadata/resources/record-header.py?file=image"; +const options = {sanitizer: {removeElements: ["img"]}}; + +promise_test(t => { + return new Promise((resolve, fail) => { + const div = document.createElement("div"); + document.getElementById("test").appendChild(div); + div.setHTML(`<img src="${url}">`, options); + fetch(url + "&retrieve=true") + .then(response => response.text()) + .then(text => { + if (text.includes("No header has been recorded")) + resolve() + else + fail("The server observed a request. It shouldn't have."); + }); + }); +}, "Test whether setHTML loads the image."); + +promise_test(t => { + return new Promise((resolve, fail) => { + const div = document.createElement("div"); + document.getElementById("test").appendChild(div); + div.setHTMLUnsafe(`<img src="${url}">`, options); + fetch(url + "&retrieve=true") + .then(response => response.text()) + .then(text => { + if (text.includes("No header has been recorded")) + resolve() + else + fail("The server observed a request. It shouldn't have."); + }); + }); +}, "Test whether setHTMLUnsafe loads the image."); +</script> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/scroll-animations/animation-trigger/animation-trigger-untriggered-animations-exposed.tentative.html b/third_party/blink/web_tests/external/wpt/scroll-animations/animation-trigger/animation-trigger-untriggered-animations-exposed.tentative.html index 7f971e2..62227cc050 100644 --- a/third_party/blink/web_tests/external/wpt/scroll-animations/animation-trigger/animation-trigger-untriggered-animations-exposed.tentative.html +++ b/third_party/blink/web_tests/external/wpt/scroll-animations/animation-trigger/animation-trigger-untriggered-animations-exposed.tentative.html
@@ -20,18 +20,18 @@ transform: translateX(-50px); } } - .target { + #subject { height: 100px; - width: 100%; - background-color: blue; - animation: slide-in 3s; + width: 100px; + background-color: purple; timeline-trigger: --trigger view() contain 0% contain 100%; - animation-trigger: --trigger; } .target { height: 100px; width: 100%; background-color: blue; + animation: slide-in 3s; + color: white; } .space { height: 250px; @@ -45,20 +45,28 @@ animation-fill-mode: none; } + .valid { + animation-trigger: --trigger play-once; + } + .invalid { + animation-trigger: --nonexistent-trigger play-once; + } + </style> <div id="scroller" class="scroller"> <div class="space"></div> <div id="subject"></div> <div class="space"></div> - <div id="active_target" class="active target"></div> - <div id="idle_target" class="idle target"></div> + <div id="active_target" class="active valid target">Active</div> + <div id="idle_target" class="idle valid target">Idle</div> + <div id="invalid_target" class="invalid target">Invalid</div> </div> <script> promise_test(async () => { - assert_equals(idle_target.getAnimations().length, 1, - "idle target has an animation"); - assert_equals(active_target.getAnimations().length, 1, - "active target has an animation"); + for (const target of document.querySelectorAll(".target")) { + assert_equals(target.getAnimations().length, 1, + `animation on ${target.id} is exposed`); + } }, "getAnimations includes an untriggered " + "'fill-mode: none' and 'fill-mode: both' animations."); </script>
diff --git a/third_party/blink/web_tests/external/wpt/storage/buckets/buckets_storage_policy.tentative.https.any.js b/third_party/blink/web_tests/external/wpt/storage/buckets/buckets_storage_policy.tentative.https.any.js index 0476902..918364d 100644 --- a/third_party/blink/web_tests/external/wpt/storage/buckets/buckets_storage_policy.tentative.https.any.js +++ b/third_party/blink/web_tests/external/wpt/storage/buckets/buckets_storage_policy.tentative.https.any.js
@@ -8,11 +8,11 @@ return Math.max(1, Math.min(Number.MAX_SAFE_INTEGER, Math.floor(quota))); } -async function testQuota(quota, name) { +async function testQuota(storageKeyQuota, quota, name) { const safeQuota = sanitizeQuota(quota); const bucket = await navigator.storageBuckets.open(name, { quota: safeQuota }); const estimateQuota = (await bucket.estimate()).quota; - assert_equals(estimateQuota, safeQuota); + assert_equals(estimateQuota, Math.min(safeQuota, storageKeyQuota)); } promise_test(async testCase => { @@ -20,9 +20,13 @@ const storageKeyQuota = (await navigator.storage.estimate()).quota; - testQuota(1, 'one'); - testQuota(storageKeyQuota / 4, 'quarter'); - testQuota(storageKeyQuota / 2, 'half'); - testQuota(storageKeyQuota - 1, 'one_less'); - testQuota(storageKeyQuota, 'origin_quota'); -}, 'Bucket quota is properly set as long as it is within the storage quota'); + testQuota(storageKeyQuota, 1, 'one'); + testQuota(storageKeyQuota, storageKeyQuota / 4, 'quarter'); + testQuota(storageKeyQuota, storageKeyQuota / 2, 'half'); + testQuota(storageKeyQuota, storageKeyQuota - 1, 'one_less'); + testQuota(storageKeyQuota, storageKeyQuota, 'origin_quota'); + testQuota(storageKeyQuota, storageKeyQuota + 1, 'one_more'); + testQuota(storageKeyQuota, storageKeyQuota * 2, 'twice'); + testQuota(storageKeyQuota, storageKeyQuota * 4, 'four_times'); + testQuota(storageKeyQuota, Number.MAX_SAFE_INTEGER, 'max_safe_int'); +}, 'For an individual bucket, the quota is the minimum of the requested quota and the StorageKey quota.');
diff --git a/third_party/blink/web_tests/external/wpt/storage/buckets/storage_bucket_object.tentative.https.any.js b/third_party/blink/web_tests/external/wpt/storage/buckets/storage_bucket_object.tentative.https.any.js index fda31df..52f1693c 100644 --- a/third_party/blink/web_tests/external/wpt/storage/buckets/storage_bucket_object.tentative.https.any.js +++ b/third_party/blink/web_tests/external/wpt/storage/buckets/storage_bucket_object.tentative.https.any.js
@@ -31,7 +31,7 @@ await inboxCache.put(cacheKey, new Response('bread x 2')) const estimate2 = await bucket.estimate(); - assert_greater_than(estimate2.quota, 0); + assert_equals(estimate.quota, estimate2.quota); assert_less_than(estimate.usage, estimate2.usage); }, 'estimate() should retrieve quota usage');
diff --git a/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-expected.txt b/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-expected.txt index cfc2468..81853f08 100644 --- a/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-expected.txt +++ b/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-expected.txt
@@ -5408,6 +5408,8 @@ getter element getter id getter loadTime + getter paintTime + getter presentationTime getter renderTime getter size getter url @@ -6777,6 +6779,8 @@ getter loadTime getter naturalHeight getter naturalWidth + getter paintTime + getter presentationTime getter renderTime getter url method constructor @@ -6802,6 +6806,8 @@ attribute @@toStringTag getter blockingDuration getter firstUIEventTimestamp + getter paintTime + getter presentationTime getter renderStart getter scripts getter styleAndLayoutStart @@ -6862,7 +6868,10 @@ method getEntriesByType interface PerformancePaintTiming : PerformanceEntry attribute @@toStringTag + getter paintTime + getter presentationTime method constructor + method toJSON interface PerformanceResourceTiming : PerformanceEntry attribute @@toStringTag getter connectEnd
diff --git a/third_party/chromite b/third_party/chromite index 9f275ec..eec00b3 160000 --- a/third_party/chromite +++ b/third_party/chromite
@@ -1 +1 @@ -Subproject commit 9f275ec850a249ec3e4d4221e21e729b7ca2eb0a +Subproject commit eec00b35328af2e160bfc59e1c7f85c75cf049dd
diff --git a/third_party/depot_tools b/third_party/depot_tools index f0d44b0..e0a877e 160000 --- a/third_party/depot_tools +++ b/third_party/depot_tools
@@ -1 +1 @@ -Subproject commit f0d44b0b80f8d5c98e2ee72f5e35379fa249f2e5 +Subproject commit e0a877ed8f3f1685b9ca9bcadb1430bf5640ffc7
diff --git a/third_party/devtools-frontend/src b/third_party/devtools-frontend/src index 4d4076e..7f8f2c8 160000 --- a/third_party/devtools-frontend/src +++ b/third_party/devtools-frontend/src
@@ -1 +1 @@ -Subproject commit 4d4076e1e451ad48e061b65e36e6a23d694352eb +Subproject commit 7f8f2c84b5c6c49132f6cb4e47be53d3d9142603
diff --git a/third_party/jni_zero/README.md b/third_party/jni_zero/README.md index 2b6e41be..caaa21d 100644 --- a/third_party/jni_zero/README.md +++ b/third_party/jni_zero/README.md
@@ -55,16 +55,18 @@ the declaration of the corresponding static methods you wish to have implemented. 2. Call native functions using `${OriginalClassName}Jni.get().${method}()` -3. In C++ code, #include the header `${OriginalClassName}_jni.h`. (The path will - depend on the location of the `generate_jni` BUILD rule that lists your Java - source code.) - -Note: Include this header from only a single `.cc` file as the header defines -functions. That `.cc` must implement your native code by defining non-member -functions named `JNI_${OriginalClassName}_${UpperCamelCaseMethod}` for static -methods and member functions named -`${OriginalClassName}::${UpperCamelCaseMethod}` for non-static methods. Member -functions need be declared in the header file as well. +3. In C++ code, add: `#include "${OriginalClassName}_jni.h"` + * The path will depend on the location of the `generate_jni` build rule + that lists your Java source code. + * The header should generally be included last, as it must appear after + headers that define types used in `@JniType` annotations. +4. Add `DEFINE_JNI(JavaClassName)` to the bottom of your `.cc` file +5. Implement the native methods. + * If unsure of what the signatures should look like, inspect the generated + `_jni.h` file. + * The naming scheme is + * Non-class methods: `JNI_${ClassName}_${UpperCamelCaseMethod}` + * Class methods: `${OriginalClassName}::${UpperCamelCaseMethod}` #### Example: **Java** @@ -100,6 +102,8 @@ **C++** ```c++ #include "third_party/jni_zero/jni_zero.h" + +// Must come after all headers that specialize FromJniType() / ToJniType(). #include "<path to BUILD.gn>/<generate_jni target name>/MyClass_jni.h" class MyClass { @@ -107,13 +111,21 @@ void NonStatic(JNIEnv* env); } -// Notice that unlike Java, function names are capitalized in C++. -// Static function names should follow this format and don't need to be declared. -void JNI_MyClass_Foo(JNIEnv* env) { ... } -void JNI_MyClass_Bar(JNIEnv* env, jint a, jint b) { ... } +namespace { // Can also declare each with `static` -// Member functions need to be declared. +void JNI_MyClass_Foo(JNIEnv* env) { + ... +} + +void JNI_MyClass_Bar(JNIEnv* env, jint a, jint b) { + ... +} + +} // namespace + void MyClass::NonStatic(JNIEnv* env) { ... } + +DEFINE_JNI(MyClass) ``` ### Calling Native -> Java
diff --git a/third_party/perfetto b/third_party/perfetto index 03b636c..bfd6932 160000 --- a/third_party/perfetto +++ b/third_party/perfetto
@@ -1 +1 @@ -Subproject commit 03b636c73098d523aea8254d37e194d8957b11af +Subproject commit bfd6932dfc3d9270ee05558daec56fbe359012e0
diff --git a/third_party/skia b/third_party/skia index a314118..e19670f 160000 --- a/third_party/skia +++ b/third_party/skia
@@ -1 +1 @@ -Subproject commit a314118792512895108df4034926e89e18d957fb +Subproject commit e19670f7040668370997825e2227ec2c054fce1e
diff --git a/third_party/spirv-tools/src b/third_party/spirv-tools/src index 3e36d0a..8c1e6ca 160000 --- a/third_party/spirv-tools/src +++ b/third_party/spirv-tools/src
@@ -1 +1 @@ -Subproject commit 3e36d0af6f2ad0bc7f870fdf4234b9e4477cd1d4 +Subproject commit 8c1e6ca9b896a5a82ea39973a2f677f515f1f45d
diff --git a/third_party/vulkan-deps b/third_party/vulkan-deps index a39d345..ef433db 160000 --- a/third_party/vulkan-deps +++ b/third_party/vulkan-deps
@@ -1 +1 @@ -Subproject commit a39d345d38f7499321e634436c35f80967ae0beb +Subproject commit ef433db61dc17278fb7452441edfa8c3ca0d986e
diff --git a/third_party/vulkan-loader/src b/third_party/vulkan-loader/src index 918e869d..0db9a0d 160000 --- a/third_party/vulkan-loader/src +++ b/third_party/vulkan-loader/src
@@ -1 +1 @@ -Subproject commit 918e869d4eb54a2fbe78546f4931f1ff9e9454bf +Subproject commit 0db9a0d55e33f8b63b733f37dc59eb441d51abf0
diff --git a/third_party/webrtc b/third_party/webrtc index f1785bb..e175a31 160000 --- a/third_party/webrtc +++ b/third_party/webrtc
@@ -1 +1 @@ -Subproject commit f1785bbb3d0159af1fbc4d5cb4cdffc1fdd0e670 +Subproject commit e175a31bf923aed9877f67f8530f6e08b280d5e7
diff --git a/tools/android/checkstyle/chromium-style-5.0.xml b/tools/android/checkstyle/chromium-style-5.0.xml index 80681f6..4d4f321 100644 --- a/tools/android/checkstyle/chromium-style-5.0.xml +++ b/tools/android/checkstyle/chromium-style-5.0.xml
@@ -47,6 +47,7 @@ <property name="tokens" value="INTERFACE_DEF, CLASS_DEF"/> <property name="scope" value="public"/> <property name="allowedAnnotations" value="NativeMethods"/> + <property name="allowMissingParamTags" value="true"/> <message key="javadoc.missing" value="Public classes and interfaces require JavaDoc comments."/> </module> <module name="JavadocMethod">
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index f9500f4..5988f50 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -3495,6 +3495,18 @@ <int value="3" label="Adult"/> </enum> +<enum name="DesktopToIOSPromoActionType"> + <int value="0" label="Accept"/> + <int value="1" label="Cancel"/> + <int value="2" label="Dismiss"/> +</enum> + +<enum name="DesktopToIOSPromoBubbleType"> + <int value="0" label="Reminder"/> + <int value="1" label="QRCode"/> + <int value="2" label="ReminderConfirmation"/> +</enum> + <enum name="DeviceAuthFinalResult"> <int value="0" label="Success with unknown method"/> <int value="1" label="Success with biometrics"/> @@ -9879,6 +9891,7 @@ <int value="-1520645293" label="InterestFeedNoticeCardAutoDismiss:disabled"/> <int value="-1520630395" label="DefaultPassthroughCommandDecoder:disabled"/> <int value="-1520542714" label="AccessibilityManifestV3GoogleTts:enabled"/> + <int value="-1520207616" label="GlicPrintMenuItem:enabled"/> <int value="-1519741393" label="AutofillEnableBuyNowPayLaterForExternallyLinkedKlarna:enabled"/> <int value="-1519536015" label="enable-hls-playback:disabled"/> @@ -10438,6 +10451,7 @@ <int value="-1332267458" label="RemoveNavigationHistory:enabled"/> <int value="-1331831950" label="site-isolation-for-password-sites:enabled"/> <int value="-1330409814" label="ContextMenuCopyImage:enabled"/> + <int value="-1330292576" label="GlicTrustFirstOnboarding:disabled"/> <int value="-1329990210" label="UserCloudSigninRestrictionPolicyFetcher:disabled"/> <int value="-1329973081" @@ -11558,6 +11572,7 @@ <int value="-943223021" label="FeatureNotificationGuideSkipCheckForLowEngagedUsers:disabled"/> <int value="-942935700" label="FastPairKeyboards:disabled"/> + <int value="-942248285" label="GlicTrustFirstOnboarding:enabled"/> <int value="-941752665" label="infobar-refresh:enabled"/> <int value="-941056354" label="CdmStorageDatabase:enabled"/> <int value="-940931658" label="UseDMSAAForTilesAndroidGL:disabled"/> @@ -12080,6 +12095,7 @@ <int value="-752707368" label="HistoryPagePromoCtaStringVariation:disabled"/> <int value="-752554170" label="ShowNewTabAnimations:disabled"/> <int value="-752321357" label="AutofillEnableGoogleIssuedCard:enabled"/> + <int value="-750742891" label="IdbSqliteBackingStore:enabled"/> <int value="-750175757" label="ClientLoFi:enabled"/> <int value="-749550261" label="SeamlessRefreshRateSwitching:enabled"/> <int value="-749306189" label="QsRevamp:enabled"/> @@ -15271,6 +15287,7 @@ <int value="363997248" label="UseXpsForPrinting:enabled"/> <int value="364245820" label="OnDeviceNotificationContentDetectionModel:disabled"/> + <int value="364359720" label="ReaderModeSupportNewFonts:enabled"/> <int value="364481315" label="CCTAuthTabDisableAllExternalIntents:enabled"/> <int value="364899966" label="AutofillUpstreamUseAlternateSecureDataType:disabled"/> @@ -15514,6 +15531,7 @@ <int value="445240121" label="CdmStorageDatabase:disabled"/> <int value="445851683" label="LauncherFuzzyMatchAcrossProviders:disabled"/> <int value="446316019" label="enable-threaded-compositing"/> + <int value="446423529" label="GlicPrintMenuItem:disabled"/> <int value="447286624" label="OmniboxDiscardTemporaryInputOnTabSwitch:enabled"/> <int value="448463569" label="NewShortcutMapping:disabled"/> @@ -17057,6 +17075,7 @@ <int value="996701528" label="SystemKeyboardLock:enabled"/> <int value="996987392" label="SearchNavigationPrefetch:disabled"/> <int value="997264173" label="MacLoopbackAudioForCast:disabled"/> + <int value="997319533" label="ReaderModeSupportNewFonts:disabled"/> <int value="998317588" label="SegmentationPlatformEphemeralCardRanker:disabled"/> <int value="998748600" label="SyncErrorInfoBarAndroid:disabled"/> @@ -18868,6 +18887,7 @@ <int value="1616938915" label="OmniboxUIExperimentWhiteBackgroundOnBlur:disabled"/> <int value="1617187093" label="enable-improved-a2hs"/> + <int value="1618337673" label="IdbSqliteBackingStore:disabled"/> <int value="1618633341" label="MashOopViz:enabled"/> <int value="1619842095" label="ColorProviderRedirection:enabled"/> <int value="1620369597" label="enable-unsafe-webgpu"/>
diff --git a/tools/metrics/histograms/metadata/actor/enums.xml b/tools/metrics/histograms/metadata/actor/enums.xml index efd23e90..c10ea56c 100644 --- a/tools/metrics/histograms/metadata/actor/enums.xml +++ b/tools/metrics/histograms/metadata/actor/enums.xml
@@ -28,7 +28,7 @@ <enum name="ActionResultCode"> <int value="0" label="Ok"/> - <int value="10" label="Error"/> + <int value="10" label="(Obsolete) Error. Removed in Dec 2025."/> <int value="11" label="UrlBlocked"/> <int value="12" label="NewTabCreationFailed"/> <int value="13" label="TabWentAway"/> @@ -58,8 +58,10 @@ <int value="37" label="ExecutionEngineExistingAction"/> <int value="38" label="ExternalProtocolNavigationBlocked"/> <int value="39" label="RendererCrashed"/> + <int value="40" label="NotImplemented"/> <int value="100" label="NavigateInvalidUrl"/> <int value="101" label="NavigateFailedToStart"/> + <int value="102" label="NavigateCommittedErrorPage"/> <int value="200" label="ClickSuppressed"/> <int value="300" label="DragAndReleaseFromOffscreen"/> <int value="301" label="DragAndReleaseToOffscreen"/> @@ -96,12 +98,18 @@ <int value="905" label="LoginPageChangedDuringSelection"/> <int value="906" label="LoginDeviceReauthRequired"/> <int value="907" label="LoginDeviceReauthFailed"/> + <int value="908" label="LoginFeatureDisabled"/> + <int value="909" label="LoginTooManyRequests"/> <int value="1000" label="MediaControlNoMedia"/> <int value="1100" label="FormFillingAutofillUnavailable"/> <int value="1101" label="FormFillingNoSuggestionsAvailable"/> <int value="1102" label="FormFillingDialogError"/> <int value="1103" label="FormFillingFieldNotFound"/> <int value="1104" label="FormFillingUnknownAutofillError"/> + <int value="1105" label="FormFillingNoLastTabObservation"/> + <int value="1106" label="FormFillingInvalidSuggestionId"/> + <int value="1200" label="ScriptToolNoResponse"/> + <int value="1300" label="ActorUiError"/> </enum> <!-- LINT.ThenChange(//chrome/common/actor.mojom:ActionResultCode) -->
diff --git a/tools/metrics/histograms/metadata/contextual_tasks/histograms.xml b/tools/metrics/histograms/metadata/contextual_tasks/histograms.xml index ac9e3c9..d50ac18e 100644 --- a/tools/metrics/histograms/metadata/contextual_tasks/histograms.xml +++ b/tools/metrics/histograms/metadata/contextual_tasks/histograms.xml
@@ -169,6 +169,29 @@ </summary> </histogram> +<histogram name="ContextualTasks.WebUI.UserAction{ActionType}" enum="Boolean" + expires_after="2026-03-22"> + <owner>sophiechang@chromium.org</owner> + <owner>chrome-contextual-tasks-eng@google.com</owner> + <summary> + Recorded every time the user interacted with the contextual tasks web UI + directly. {ActionType} Always recorded as true. + </summary> + <token key="ActionType"> + <variant name=".CloseSidePanel" summary="The user closed the side panel."/> + <variant name=".OpenHelp" summary="The user opened the help page."/> + <variant name=".OpenInNewTab" + summary="The user opened the task in a new tab."/> + <variant name=".OpenMyActivity" + summary="The user opened the My Activity page."/> + <variant name=".OpenNewThread" summary="The user opened a new thread."/> + <variant name=".OpenThreadHistory" + summary="The user opened the thread history."/> + <variant name=".TabFromSourcesMenuClicked" + summary="The user clicked on a tab from the sources menu."/> + </token> +</histogram> + </histograms> </histogram-configuration>
diff --git a/tools/metrics/histograms/metadata/ios/enums.xml b/tools/metrics/histograms/metadata/ios/enums.xml index 17721d6a..a5d9092 100644 --- a/tools/metrics/histograms/metadata/ios/enums.xml +++ b/tools/metrics/histograms/metadata/ios/enums.xml
@@ -560,6 +560,8 @@ <int value="2" label="Add account failure"/> </enum> +<!-- LINT.IfChange(IOSFilePickerDriveDisplayed) --> + <enum name="IOSFilePickerDriveDisplayed"> <int value="0" label="The Drive element was displayed"/> <int value="1" label="The tab was killed"/> @@ -567,8 +569,11 @@ <int value="3" label="The tab was OTR"/> <int value="4" label="The user was not signed in"/> <int value="5" label="The feature was disabled by an enterprise policy"/> + <int value="6" label="The Drive service is not supported"/> </enum> +<!-- LINT.ThenChange(//ios/chrome/browser/drive/model/drive_availability.mm:FilePickerDriveDisplayed) --> + <enum name="IOSFilePickerDriveFilter"> <int value="0" label="Select Archives"/> <int value="1" label="Select Audio"/>
diff --git a/tools/metrics/histograms/metadata/media/enums.xml b/tools/metrics/histograms/metadata/media/enums.xml index d12929e..4a2a8bb 100644 --- a/tools/metrics/histograms/metadata/media/enums.xml +++ b/tools/metrics/histograms/metadata/media/enums.xml
@@ -26,7 +26,14 @@ <enums> +<enum name="ActiveGpuDisplayInfo"> + <int value="0" label="Unknown"/> + <int value="1" label="Likely Built-in"/> + <int value="2" label="Likely External"/> +</enum> + <enum name="ActiveGpuInfo"> + <int value="0" label="None"/> <int value="1" label="Intel"/> <int value="2" label="NVIDIA"/> <int value="4" label="AMD"/> @@ -1263,6 +1270,14 @@ <int value="2" label="Two or more"/> </enum> +<enum name="GpuVendorId"> + <int value="-1" label="Unknown"/> + <int value="4098" label="AMD"/> + <int value="4318" label="NVIDIA"/> + <int value="5140" label="Microsoft"/> + <int value="32902" label="Intel"/> +</enum> + <enum name="HighlightedTabDiscardStatus"> <int value="0" label="NoTabsHighlighted"/> <int value="1" label="AllHighlightedTabsNonDiscarded"/>
diff --git a/tools/metrics/histograms/metadata/media/histograms.xml b/tools/metrics/histograms/metadata/media/histograms.xml index 17b83867..89ad53ef 100644 --- a/tools/metrics/histograms/metadata/media/histograms.xml +++ b/tools/metrics/histograms/metadata/media/histograms.xml
@@ -3794,6 +3794,18 @@ </histogram> <histogram + name="Media.EME.MediaFoundationService.HardwareContextReset.ActiveGpuDisplayInfo" + enum="ActiveGpuDisplayInfo" expires_after="2026-04-05"> + <owner>sangbaekpark@chromium.org</owner> + <owner>media-dev-uma@chromium.org</owner> + <summary> + Active GPU's display information whether likely built-in or external when a + HardwareContextReset event happened in the MediaFoundationService process. + Reported whenever such an event happens. + </summary> +</histogram> + +<histogram name="Media.EME.MediaFoundationService.HardwareContextReset.ActiveGpuInfo" enum="ActiveGpuInfo" expires_after="2026-04-05"> <owner>sangbaekpark@chromium.org</owner> @@ -3806,6 +3818,17 @@ </histogram> <histogram + name="Media.EME.MediaFoundationService.HardwareContextReset.ActiveGpuVendorId" + enum="GpuVendorId" expires_after="2026-04-05"> + <owner>sangbaekpark@chromium.org</owner> + <owner>media-dev-uma@chromium.org</owner> + <summary> + Active GPU vendor ID when a HardwareContextReset event happened in the + MediaFoundationService process. Reported whenever such an event happens. + </summary> +</histogram> + +<histogram name="Media.EME.MediaFoundationService.HardwareContextReset.DisplayCount" enum="GpuOrDisplayCount" expires_after="2026-04-05"> <owner>sangbaekpark@chromium.org</owner> @@ -3827,6 +3850,17 @@ </summary> </histogram> +<histogram + name="Media.EME.MediaFoundationService.HardwareContextReset.NonActiveGpuVendorId" + enum="GpuVendorId" expires_after="2026-04-05"> + <owner>sangbaekpark@chromium.org</owner> + <owner>media-dev-uma@chromium.org</owner> + <summary> + Non-active GPU vendor ID when a HardwareContextReset event happened in the + MediaFoundationService process. Reported whenever such an event happens. + </summary> +</histogram> + <histogram name="Media.EME.MediaFoundationService.IsKeySystemSupported" units="ms" expires_after="2026-05-24"> <owner>xhwang@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/uma/histograms.xml b/tools/metrics/histograms/metadata/uma/histograms.xml index 5253cbc..8d1a267 100644 --- a/tools/metrics/histograms/metadata/uma/histograms.xml +++ b/tools/metrics/histograms/metadata/uma/histograms.xml
@@ -797,9 +797,12 @@ <owner>asvitkine@chromium.org</owner> <owner>src/base/metrics/OWNERS</owner> <summary> - Compression ratio of the serialized protobuf that will be uploaded to the - UMA server. This serialized protobuf is compressed using gzip. See also - UMA.LogSize.OnSuccess. + Note: This is not a compression ratio. It is computed as 100 * compressed + size / original size. + + Compressed size fraction of the uncompressed size for a protobuf that will + be uploaded to the UMA server. This serialized protobuf is compressed using + gzip. See also UMA.LogSize.OnSuccess. </summary> </histogram>
diff --git a/tools/metrics/histograms/metadata/user_education/histograms.xml b/tools/metrics/histograms/metadata/user_education/histograms.xml index f17b5d4f..e9b09ea 100644 --- a/tools/metrics/histograms/metadata/user_education/histograms.xml +++ b/tools/metrics/histograms/metadata/user_education/histograms.xml
@@ -234,6 +234,47 @@ <token key="TutorialID" variants="TutorialID"/> </histogram> +<histogram + name="UserEducation.DesktopToIOSPromo.{PromoType}.BubbleView.Created" + enum="DesktopToIOSPromoBubbleType" expires_after="2026-06-04"> + <owner>hiramahmood@google.com</owner> + <owner>bling-pandamonium@google.com</owner> + <summary> + The type of Desktop-to-iOS Promo Bubble that was created (shown) to the + user. + </summary> + <token key="PromoType"> + <variant name="Address" summary="Address"/> + <variant name="EnhancedBrowsing" summary="Enhanced Browsing"/> + <variant name="Lens" summary="Lens"/> + <variant name="Password" summary="Password"/> + <variant name="Payment" summary="Payment"/> + </token> +</histogram> + +<histogram + name="UserEducation.DesktopToIOSPromo.{PromoType}.{BubbleType}.Action" + enum="DesktopToIOSPromoActionType" expires_after="2026-06-04"> + <owner>hiramahmood@google.com</owner> + <owner>bling-pandamonium@google.com</owner> + <summary> + The action taken by the user on the Desktop-to-iOS Promo Bubble. + </summary> + <token key="PromoType"> + <variant name="Address" summary="Address"/> + <variant name="EnhancedBrowsing" summary="Enhanced Browsing"/> + <variant name="Lens" summary="Lens"/> + <variant name="Password" summary="Password"/> + <variant name="Payment" summary="Payment"/> + </token> + <token key="BubbleType"> + <variant name="QRCode" summary="QR Code Bubble"/> + <variant name="Reminder" summary="Reminder Bubble"/> + <variant name="ReminderConfirmation" + summary="Reminder Confirmation Bubble"/> + </token> +</histogram> + <histogram name="UserEducation.MessageNotShown" enum="PromoFailure" expires_after="2026-05-10"> <owner>mickeyburks@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 6bbd573..5670240 100644 --- a/tools/perf/core/perfetto_binary_roller/binary_deps.json +++ b/tools/perf/core/perfetto_binary_roller/binary_deps.json
@@ -6,7 +6,7 @@ }, "win": { "hash": "0bc84fe254fcc6b56eecec0a42437790fc5cc37c", - "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/win/9b7f1abbdedcab5b477abcea515ad550f70b16e4/trace_processor_shell.exe" + "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/win/03b636c73098d523aea8254d37e194d8957b11af/trace_processor_shell.exe" }, "linux_arm": { "hash": "46d798c1864490cbb2ee053d6eda436184470e69", @@ -21,8 +21,8 @@ "full_remote_path": "perfetto-luci-artifacts/ebf44e57a3b734c5281bdff53d9945805486004e/mac-arm64/trace_processor_shell" }, "linux": { - "hash": "70fd11b597268454fd8db865127538befa841269", - "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux/9b7f1abbdedcab5b477abcea515ad550f70b16e4/trace_processor_shell" + "hash": "12fac62c88ea4550a4d8b6713f287084b0947e77", + "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux/1488a2e8df294078049f759faf4efe6450652d88/trace_processor_shell" } }, "power_profile.sql": {
diff --git a/ui/android/resources/resource_manager.h b/ui/android/resources/resource_manager.h index bff2565..f6bbbbf4 100644 --- a/ui/android/resources/resource_manager.h +++ b/ui/android/resources/resource_manager.h
@@ -6,6 +6,7 @@ #define UI_ANDROID_RESOURCES_RESOURCE_MANAGER_H_ #include "base/android/jni_android.h" +#include "base/memory/weak_ptr.h" #include "cc/resources/scoped_ui_resource.h" #include "third_party/skia/include/core/SkColor.h" #include "ui/android/resources/resource.h" @@ -51,6 +52,20 @@ SkColor tint_color, bool preserve_color_alpha) = 0; + // Return a handle to the resource specified by |res_id| that has a tint of + // |tint_color| applied to it, and tell the resource manager to keep the + // tinted resource in the cache until ReleaseStaticResource is called with the + // same |res_id|. This can be used for resources used by layers that aren't + // processed every frame (because they don't usually change) and are likely to + // have the same tint in future frames. Once you call this function again for + // the same resource but with a different tint color, the previous tint might + // get removed from the cache. + virtual Resource* GetAndRetainStaticResourceWithTint(int res_id, + SkColor tint_color) = 0; + + // Stop keeping a static resource in the cache. + virtual void ReleaseStaticResource(int res_id) = 0; + // Trigger asynchronous loading of the resource specified by |res_type| and // |res_id|, if it has not yet been loaded. virtual void PreloadResource(AndroidResourceType res_type, int res_id) = 0; @@ -65,6 +80,8 @@ // A notification that all updates have finished for the current frame. virtual void OnFrameUpdatesFinished() = 0; + virtual base::WeakPtr<ResourceManager> GetWeakPtr() = 0; + protected: virtual ~ResourceManager() {} };
diff --git a/ui/android/resources/resource_manager_impl.cc b/ui/android/resources/resource_manager_impl.cc index 07fcea7..594ebed 100644 --- a/ui/android/resources/resource_manager_impl.cc +++ b/ui/android/resources/resource_manager_impl.cc
@@ -121,6 +121,10 @@ } void ResourceManagerImpl::RemoveUnusedTints() { + for (auto& it : tinted_resources_to_keep_) { + used_tints_.insert(it.second); + } + // Iterate over the currently cached tints and remove ones that were not // used as defined in |used_tints|. for (auto it = tinted_resources_.cbegin(); it != tinted_resources_.cend();) { @@ -202,7 +206,19 @@ return (*resource_map)[res_id].get(); } +Resource* ResourceManagerImpl::GetAndRetainStaticResourceWithTint( + int res_id, + SkColor tint_color) { + tinted_resources_to_keep_[res_id] = tint_color; + return GetStaticResourceWithTint(res_id, tint_color); +} + +void ResourceManagerImpl::ReleaseStaticResource(int res_id) { + tinted_resources_to_keep_.erase(res_id); +} + void ResourceManagerImpl::ClearTintedResourceCache(JNIEnv* env) { + tinted_resources_to_keep_.clear(); tinted_resources_.clear(); } @@ -283,6 +299,10 @@ return true; } +base::WeakPtr<ResourceManager> ResourceManagerImpl::GetWeakPtr() { + return weak_ptr_factory_.GetWeakPtr(); +} + void ResourceManagerImpl::PreloadResourceFromJava(AndroidResourceType res_type, int res_id) { TRACE_EVENT2("ui", "ResourceManagerImpl::PreloadResourceFromJava",
diff --git a/ui/android/resources/resource_manager_impl.h b/ui/android/resources/resource_manager_impl.h index d37bc73..2d6a31a6 100644 --- a/ui/android/resources/resource_manager_impl.h +++ b/ui/android/resources/resource_manager_impl.h
@@ -13,6 +13,8 @@ #include "base/android/scoped_java_ref.h" #include "base/memory/raw_ptr.h" #include "base/trace_event/memory_dump_provider.h" +#include "third_party/abseil-cpp/absl/container/flat_hash_map.h" +#include "third_party/abseil-cpp/absl/container/flat_hash_set.h" #include "third_party/skia/include/core/SkColor.h" #include "ui/android/resources/resource_manager.h" #include "ui/android/ui_android_export.h" @@ -49,6 +51,10 @@ Resource* GetStaticResourceWithTint(int res_id, SkColor tint_color, bool preserve_color_alpha) override; + Resource* GetAndRetainStaticResourceWithTint(int res_id, + SkColor tint_color) override; + void ReleaseStaticResource(int res_id) override; + void PreloadResource(AndroidResourceType res_type, int res_id) override; void OnFrameUpdatesFinished() override; @@ -72,6 +78,8 @@ bool OnMemoryDump(const base::trace_event::MemoryDumpArgs& args, base::trace_event::ProcessMemoryDump* pmd) override; + base::WeakPtr<ResourceManager> GetWeakPtr() override; + private: friend class TestResourceManagerImpl; @@ -95,9 +103,13 @@ TintedResourceMap tinted_resources_; // The set of tints that are used for resources in the current frame. - std::unordered_set<SkColor> used_tints_; + absl::flat_hash_set<SkColor> used_tints_; + + absl::flat_hash_map<int, SkColor> tinted_resources_to_keep_; base::android::ScopedJavaGlobalRef<jobject> java_obj_; + + base::WeakPtrFactory<ResourceManagerImpl> weak_ptr_factory_{this}; }; } // namespace ui
diff --git a/ui/display/mac/ca_display_link_mac.h b/ui/display/mac/ca_display_link_mac.h index 4d1d782..f0a9a52 100644 --- a/ui/display/mac/ca_display_link_mac.h +++ b/ui/display/mac/ca_display_link_mac.h
@@ -25,7 +25,7 @@ std::unique_ptr<VSyncCallbackMac> RegisterCallback( VSyncCallbackMac::Callback callback) override; - double GetRefreshRate() const override; + base::TimeDelta GetRefreshInterval() const override; void GetRefreshIntervalRange(base::TimeDelta& min_interval, base::TimeDelta& max_interval, base::TimeDelta& granularity) const override;
diff --git a/ui/display/mac/ca_display_link_mac.mm b/ui/display/mac/ca_display_link_mac.mm index f961e69..2fd49f0 100644 --- a/ui/display/mac/ca_display_link_mac.mm +++ b/ui/display/mac/ca_display_link_mac.mm
@@ -97,8 +97,8 @@ } } -double CADisplayLinkMac::GetRefreshRate() const { - return display::GetNSScreenRefreshRate(display_id_); +base::TimeDelta CADisplayLinkMac::GetRefreshInterval() const { + return display::GetNSScreenRefreshInterval(display_id_); } void CADisplayLinkMac::GetRefreshIntervalRange(
diff --git a/ui/display/mac/cv_display_link_mac.h b/ui/display/mac/cv_display_link_mac.h index 8e1e1420..8a8c642 100644 --- a/ui/display/mac/cv_display_link_mac.h +++ b/ui/display/mac/cv_display_link_mac.h
@@ -39,7 +39,7 @@ std::unique_ptr<VSyncCallbackMac> RegisterCallback( VSyncCallbackMac::Callback callback) override; - double GetRefreshRate() const override; + base::TimeDelta GetRefreshInterval() const override; void GetRefreshIntervalRange(base::TimeDelta& min_interval, base::TimeDelta& max_interval, base::TimeDelta& granularity) const override;
diff --git a/ui/display/mac/cv_display_link_mac.mm b/ui/display/mac/cv_display_link_mac.mm index fe92d202..6ff7de6 100644 --- a/ui/display/mac/cv_display_link_mac.mm +++ b/ui/display/mac/cv_display_link_mac.mm
@@ -18,6 +18,7 @@ #include "base/synchronization/lock.h" #include "base/task/bind_post_task.h" #include "base/trace_event/trace_event.h" +#include "ui/display/mac/screen_utils_mac.h" namespace base::apple { @@ -245,19 +246,18 @@ consecutive_vsyncs_with_no_callbacks_ = 0; } -double CVDisplayLinkMac::GetRefreshRate() const { +base::TimeDelta CVDisplayLinkMac::GetRefreshInterval() const { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - double refresh_rate = 0; - CVTime cv_time = CVDisplayLinkGetNominalOutputVideoRefreshPeriod(display_link_.get()); if (!(cv_time.flags & kCVTimeIsIndefinite)) { - refresh_rate = (static_cast<double>(cv_time.timeScale) / - static_cast<double>(cv_time.timeValue)); + double refresh_interval = (static_cast<double>(cv_time.timeValue) / + static_cast<double>(cv_time.timeScale)); + return (base::Seconds(1) * refresh_interval); + } else { + return display::GetNSScreenRefreshInterval(display_id_); } - - return refresh_rate; } void CVDisplayLinkMac::GetRefreshIntervalRange( @@ -266,15 +266,9 @@ base::TimeDelta& granularity) const { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - double refresh_rate = GetRefreshRate(); - if (refresh_rate) { - min_interval = base::Seconds(1) / refresh_rate; - max_interval = min_interval; - granularity = min_interval; - } else { - min_interval = base::TimeDelta(); - max_interval = base::TimeDelta(); - } + // Force the max/min range because CVDisplayLink does not support + // preferredFrameRateRange. + min_interval = max_interval = granularity = GetRefreshInterval(); } base::TimeTicks CVDisplayLinkMac::GetCurrentTime() const {
diff --git a/ui/display/mac/display_link_mac.h b/ui/display/mac/display_link_mac.h index 62469e0..9dc6aa9 100644 --- a/ui/display/mac/display_link_mac.h +++ b/ui/display/mac/display_link_mac.h
@@ -78,8 +78,8 @@ virtual std::unique_ptr<VSyncCallbackMac> RegisterCallback( VSyncCallbackMac::Callback callback) = 0; - // Get the panel/monitor refresh rate - virtual double GetRefreshRate() const = 0; + // Get the panel/monitor refresh interval + virtual base::TimeDelta GetRefreshInterval() const = 0; virtual void GetRefreshIntervalRange(base::TimeDelta& min_interval, base::TimeDelta& max_interval, base::TimeDelta& granularity) const = 0;
diff --git a/ui/display/mac/screen_mac.mm b/ui/display/mac/screen_mac.mm index 890d86a..01eb13e9 100644 --- a/ui/display/mac/screen_mac.mm +++ b/ui/display/mac/screen_mac.mm
@@ -182,8 +182,7 @@ display.set_is_monochrome(CGDisplayUsesForceToGray()); // Query the display's refresh rate. - double refresh_rate = 1.0 / screen.minimumRefreshInterval; - display.set_display_frequency(refresh_rate); + display.set_display_frequency(screen.maximumFramesPerSecond); // CGDisplayRotation returns a double. Display::SetRotationAsDegree will // handle the unexpected situations were the angle is not a multiple of 90.
diff --git a/ui/display/mac/screen_utils_mac.h b/ui/display/mac/screen_utils_mac.h index 70dba859..21a7caa 100644 --- a/ui/display/mac/screen_utils_mac.h +++ b/ui/display/mac/screen_utils_mac.h
@@ -16,8 +16,8 @@ // about a screen. NSScreen* GetNSScreenFromDisplayID(CGDirectDisplayID display_id); -// Returns the highest refresh rate of the display. -double GetNSScreenRefreshRate(CGDirectDisplayID display_id); +// Returns the minimum refresh interval of the display. +base::TimeDelta GetNSScreenRefreshInterval(CGDirectDisplayID display_id); // Returns the range of intervals the display can support. // All screen refresh rates fall between the values in min_interval and
diff --git a/ui/display/mac/screen_utils_mac.mm b/ui/display/mac/screen_utils_mac.mm index c3d6414..870abf8 100644 --- a/ui/display/mac/screen_utils_mac.mm +++ b/ui/display/mac/screen_utils_mac.mm
@@ -18,13 +18,13 @@ return nullptr; } -double GetNSScreenRefreshRate(CGDirectDisplayID display_id) { +base::TimeDelta GetNSScreenRefreshInterval(CGDirectDisplayID display_id) { NSScreen* screen = GetNSScreenFromDisplayID(display_id); if (screen) { - return screen.maximumFramesPerSecond; + return base::Seconds(1) * screen.minimumRefreshInterval; } else { - return 60.0; + return base::Seconds(1) / 60.0; } }
diff --git a/ui/gfx/hdr_metadata.h b/ui/gfx/hdr_metadata.h index 802d4d3..46fed45a 100644 --- a/ui/gfx/hdr_metadata.h +++ b/ui/gfx/hdr_metadata.h
@@ -163,6 +163,13 @@ HDRMetadata& operator=(const HDRMetadata& rhs); ~HDRMetadata(); + // Return true if this structure holds no metadata. + bool IsEmpty() const { + return !smpte_st_2086.has_value() && !cta_861_3.has_value() && + !ndwl.has_value() && !extended_range.has_value() && + !agtm.has_value(); + } + bool IsValid() const { return (cta_861_3 && cta_861_3->IsValid()) || (smpte_st_2086 && smpte_st_2086->IsValid()) || extended_range;
diff --git a/ui/gl/dcomp_presenter_unittest.cc b/ui/gl/dcomp_presenter_unittest.cc index 43135702a..3ebf2727 100644 --- a/ui/gl/dcomp_presenter_unittest.cc +++ b/ui/gl/dcomp_presenter_unittest.cc
@@ -103,6 +103,26 @@ void OnCursorUpdate() override {} }; +class MockDCOMPSurfaceProxy : public gl::DCOMPSurfaceProxy { + public: + MockDCOMPSurfaceProxy() + : scoped_handle_( + gl::SwapChainPresenter::CreateDCompSurfaceHandleForTesting()) {} + MOCK_METHOD(gfx::Size&, GetSize, (), (const, override)); + MOCK_METHOD(void, + SetRect, + (const gfx::Rect& window_relative_rect), + (override)); + MOCK_METHOD(void, SetParentWindow, (HWND parent), (override)); + + HANDLE GetSurfaceHandle() override { return scoped_handle_.Get(); } + + private: + ~MockDCOMPSurfaceProxy() override = default; + + const base::win::ScopedHandle scoped_handle_; +}; + void RunPendingTasks(scoped_refptr<base::TaskRunner> task_runner) { base::WaitableEvent done(base::WaitableEvent::ResetPolicy::AUTOMATIC, base::WaitableEvent::InitialState::NOT_SIGNALED); @@ -1237,6 +1257,116 @@ DCompPresenterTest::GetValues(), &DCompPresenterTest::GetParamName); +class DCompPresenterMFLargeOnscreenSizeTest : public DCompPresenterTest { + protected: + void RunTest(const gfx::Size& monitor_size, + const gfx::Size& video_resource_size, + const gfx::Rect& onscreen_rect, + const gfx::Rect& expected_set_rect) { + SetDirectCompositionMonitorInfoForTesting(1, monitor_size); + + auto dcomp_surface_proxy = base::MakeRefCounted<MockDCOMPSurfaceProxy>(); + EXPECT_CALL(*dcomp_surface_proxy, SetParentWindow(testing::_)) + .Times(testing::AnyNumber()); + EXPECT_CALL(*dcomp_surface_proxy, GetSize()) + .WillRepeatedly(::testing::ReturnRefOfCopy(video_resource_size)); + + // We expect the onscreen size (set below) to be scaled down to enclose the + // monitor size while maintaining the onscreen aspect ratio. + EXPECT_CALL(*dcomp_surface_proxy, SetRect(testing::Eq(expected_set_rect))) + .Times(testing::AnyNumber()); + + { + auto params = CreateParamsFromImage( + DCLayerOverlayImage(video_resource_size, dcomp_surface_proxy)); + params.quad_rect = onscreen_rect; + params.layer_id = gfx::OverlayLayerId::MakeForTesting(0); + params.video_params.color_space = gfx::ColorSpace::CreateREC709(); + ScheduleOverlay(std::move(params)); + } + + ASSERT_EQ(PresentAndGetSwapResult(), gfx::SwapResult::SWAP_ACK); + } +}; + +// The video resolution is smaller than the monitor size so we're limited by +// the monitor size. +TEST_P(DCompPresenterMFLargeOnscreenSizeTest, ScaleDownToMonitorSize) { + const gfx::Size monitor_size = gfx::Size(20, 10); + const gfx::Size video_resource_size = gfx::Size(1, 1); + const gfx::Rect onscreen_rect = gfx::Rect(100, 100); + const gfx::Rect expected_set_rect = gfx::Rect(20, 20); + RunTest(monitor_size, video_resource_size, onscreen_rect, expected_set_rect); +} + +// The video resolution is larger than the monitor size so we're limited by +// the video resolution. +TEST_P(DCompPresenterMFLargeOnscreenSizeTest, ScaleDownToVideoSize) { + const gfx::Size monitor_size = gfx::Size(20, 10); + const gfx::Size video_resource_size = gfx::Size(50, 50); + const gfx::Rect onscreen_rect = gfx::Rect(100, 100); + const gfx::Rect expected_set_rect = gfx::Rect(50, 50); + RunTest(monitor_size, video_resource_size, onscreen_rect, expected_set_rect); +} + +// When the onscreen rect is smaller than the monitor or video size, the scale +// factor is not limited. +TEST_P(DCompPresenterMFLargeOnscreenSizeTest, + OnscreenRectIsSmallerThanMonitorOrVideoSize) { + const gfx::Size monitor_size = gfx::Size(20, 10); + const gfx::Size video_resource_size = gfx::Size(50, 50); + const gfx::Rect onscreen_rect = gfx::Rect(1, 1); + const gfx::Rect expected_set_rect = gfx::Rect(1, 1); + RunTest(monitor_size, video_resource_size, onscreen_rect, expected_set_rect); +} + +// When the monitor and video size are larger than each other in different +// dimensions, take the max of both to ensure that we'll at least either fill +// the screen fully or max out the video resolution. +TEST_P(DCompPresenterMFLargeOnscreenSizeTest, + ScaleDownToMaxOfMonitorAndVideoSize) { + // The max swap chain size will be 20x30. + { + const gfx::Size monitor_size = gfx::Size(20, 10); + const gfx::Size video_resource_size = gfx::Size(10, 30); + const gfx::Rect onscreen_rect = gfx::Rect(40, 60); + const gfx::Rect expected_set_rect = gfx::Rect(20, 30); + RunTest(monitor_size, video_resource_size, onscreen_rect, + expected_set_rect); + } + + // The max swap chain size will be 80x20 (30x20 expanded to meet the 4:1 + // aspect ratio). + { + const gfx::Size monitor_size = gfx::Size(30, 10); + const gfx::Size video_resource_size = gfx::Size(10, 20); + const gfx::Rect onscreen_rect = + gfx::Rect(gfx::ScaleToRoundedSize(gfx::Size(4, 1), 100)); + const gfx::Rect expected_set_rect = gfx::Rect(80, 20); + RunTest(monitor_size, video_resource_size, onscreen_rect, + expected_set_rect); + } +} + +// Even in extreme aspect ratio cases we will still limit the swap chain size. +// In these extreme cases, we are still wasteful with pixels, though not as +// wasteful as not being limited. +TEST_P(DCompPresenterMFLargeOnscreenSizeTest, ExtremeAspectRatioCase) { + // The max swap chain size will be 2500x50 (50x50 expanded to meet the 50:1 + // aspect ratio). + const gfx::Size monitor_size = gfx::Size(50, 1); + const gfx::Size video_resource_size = gfx::Size(1, 50); + const gfx::Rect onscreen_rect = + gfx::Rect(gfx::ScaleToRoundedSize(gfx::Size(50, 1), 100)); + const gfx::Rect expected_set_rect = gfx::Rect(2500, 50); + RunTest(monitor_size, video_resource_size, onscreen_rect, expected_set_rect); +} + +INSTANTIATE_TEST_SUITE_P(, + DCompPresenterMFLargeOnscreenSizeTest, + DCompPresenterMFLargeOnscreenSizeTest::GetValues(), + &DCompPresenterMFLargeOnscreenSizeTest::GetParamName); + template <class Param = std::monostate> class DCompPresenterPixelTestBase : public DCompPresenterTestBase<Param> { public: @@ -3590,26 +3720,6 @@ } } - class MockDCOMPSurfaceProxy : public gl::DCOMPSurfaceProxy { - public: - MockDCOMPSurfaceProxy() - : scoped_handle_( - gl::SwapChainPresenter::CreateDCompSurfaceHandleForTesting()) {} - MOCK_METHOD(gfx::Size&, GetSize, (), (const, override)); - MOCK_METHOD(void, - SetRect, - (const gfx::Rect& window_relative_rect), - (override)); - MOCK_METHOD(void, SetParentWindow, (HWND parent), (override)); - - HANDLE GetSurfaceHandle() override { return scoped_handle_.Get(); } - - private: - ~MockDCOMPSurfaceProxy() override = default; - - const base::win::ScopedHandle scoped_handle_; - }; - void ScheduleFullScreenOverlay(DCLayerOverlayParams overlay) { if (GetTestParam().use_letterbox_video_optimization && base::FeatureList::IsEnabled(
diff --git a/ui/gl/swap_chain_presenter.cc b/ui/gl/swap_chain_presenter.cc index c66f0f7..62785526 100644 --- a/ui/gl/swap_chain_presenter.cc +++ b/ui/gl/swap_chain_presenter.cc
@@ -17,8 +17,11 @@ #include "base/synchronization/waitable_event.h" #include "base/trace_event/trace_event.h" #include "ui/gfx/color_space_win.h" +#include "ui/gfx/geometry/axis_transform2d.h" #include "ui/gfx/geometry/rect_conversions.h" +#include "ui/gfx/geometry/size.h" #include "ui/gfx/geometry/size_conversions.h" +#include "ui/gfx/geometry/size_f.h" #include "ui/gl/dc_layer_overlay_image.h" #include "ui/gl/dc_layer_tree.h" #include "ui/gl/debug_utils.h" @@ -44,6 +47,14 @@ // monitor size in order for MF to handle fullscreen letterboxing of videos. BASE_FEATURE(kDisableVPBLTUpscale, base::FEATURE_DISABLED_BY_DEFAULT); +// Limit the video swap chain size that we request from Media Foundation, opting +// to do upscaling via DWM, rather than VPBLT. +// +// This is necessary in the case of very large onscreen size (particularly with +// scaled up videos that are clipped), where large MF swap chain sizes can +// negatively affect performance and memory usage. +BASE_FEATURE(kLimitMFSwapChainSize, base::FEATURE_ENABLED_BY_DEFAULT); + // This flag attempts to enable MPO for P010 SDR video content. The feature // should only be enabled when P010 MPO is detected as supported. BASE_FEATURE(kP010MPOForSDR, base::FEATURE_ENABLED_BY_DEFAULT); @@ -2033,6 +2044,60 @@ // in Media Foundation scaling the full video to the clipped region, // instead of allowing clipping to a portion of the video. + if (base::FeatureList::IsEnabled(kLimitMFSwapChainSize)) { + // We somewhat arbitrarily choose a combination of the monitor size and + // video natural size as the upper limit. + // - The monitor size upper limit ensures that if the video is a lower + // resolution than the screen and Media Foundation can do better scaling + // than DWM, full screen videos will continue to be upscaled nicely. + // - The video natural size upper limit ensures that if a video is a higher + // resolution than the screen size, we will not limit the max scale factor + // to less than 1x. + const gfx::SizeF monitor_size = gfx::SizeF(GetMonitorSize()); + // Note: we assume that the video has an unclipped UV rect, so the + // `content_rect` represents the resource size in pixels. + const gfx::SizeF video_natural_size = + gfx::SizeF(params.content_rect.size()); + const gfx::SizeF max_swap_chain_size = gfx::SizeF( + std::max(monitor_size.width(), video_natural_size.width()), + std::max(monitor_size.height(), video_natural_size.height())); + + // Since Chromium's MF renderer assumes that a MF video will be centered and + // scaled (maintaining aspect ratio) to fit its quad rect, we must expand + // one dimension of our chosen max size to match the onscreen aspect ratio. + // The resulting size is the smallest size that encloses + // `max_swap_chain_size` while maintaining the aspect ratio of + // `overlay_onscreen_rect`. + const double onscreen_to_max_size_scale = + std::max(max_swap_chain_size.width() / overlay_onscreen_rect.width(), + max_swap_chain_size.height() / overlay_onscreen_rect.height()); + const gfx::SizeF adjusted_max_swap_chain_size = gfx::ScaleSize( + overlay_onscreen_rect.size(), onscreen_to_max_size_scale); + + if (overlay_onscreen_rect.width() > adjusted_max_swap_chain_size.width() || + overlay_onscreen_rect.height() > + adjusted_max_swap_chain_size.height()) { + TRACE_EVENT("gpu", "PresentDCOMPSurface LimitMFSwapChainSize", + "overlay_onscreen_rect", overlay_onscreen_rect.ToString(), + "adjusted_max_swap_chain_size", + adjusted_max_swap_chain_size.ToString()); + mapped_rect.set_size(gfx::ToCeiledSize(adjusted_max_swap_chain_size)); + + if (!base::FeatureList::IsEnabled( + features::kEarlyFullScreenVideoOptimization)) { + *visual_transform = gfx::Transform( + gfx::AxisTransform2d(1.0f / onscreen_to_max_size_scale, + visual_transform->To2dTranslation())); + + // Adjust for the difference in the floating point "ideal" size and + // integer swap chain size that we request to Media Foundatation. + visual_transform->Scale( + adjusted_max_swap_chain_size.width() / + std::ceil(adjusted_max_swap_chain_size.width())); + } + } + } + pending_dcomp_surface_rect_in_window_ = mapped_rect; content_size_ = mapped_rect.size();
diff --git a/ui/views/examples/bubble_example.cc b/ui/views/examples/bubble_example.cc index e11ce52..dead16d 100644 --- a/ui/views/examples/bubble_example.cc +++ b/ui/views/examples/bubble_example.cc
@@ -93,7 +93,7 @@ protected: void Init() override { SetLayoutManager(std::make_unique<BoxLayout>( - BoxLayout::Orientation::kVertical, gfx::Insets(50))); + BoxLayout::Orientation::kVertical, gfx::Insets(30))); AddChildView(std::make_unique<Label>(GetArrowName(arrow()))); } }; @@ -106,8 +106,11 @@ BubbleExample::~BubbleExample() = default; void BubbleExample::CreateExampleView(View* container) { - container->SetLayoutManager(std::make_unique<BoxLayout>( - BoxLayout::Orientation::kHorizontal, gfx::Insets(), 10)); + auto* const box_layout = + container->SetLayoutManager(std::make_unique<BoxLayout>( + BoxLayout::Orientation::kHorizontal, gfx::Insets(), 10)); + box_layout->set_cross_axis_alignment(BoxLayout::CrossAxisAlignment::kCenter); + box_layout->set_main_axis_alignment(BoxLayout::MainAxisAlignment::kCenter); standard_shadow_ = container->AddChildView(std::make_unique<LabelButton>( base::BindRepeating(&BubbleExample::ShowBubble, base::Unretained(this),
diff --git a/ui/webui/resources/cr_components/composebox/contextual_entrypoint_and_carousel.ts b/ui/webui/resources/cr_components/composebox/contextual_entrypoint_and_carousel.ts index 700b55c4..838fbe7 100644 --- a/ui/webui/resources/cr_components/composebox/contextual_entrypoint_and_carousel.ts +++ b/ui/webui/resources/cr_components/composebox/contextual_entrypoint_and_carousel.ts
@@ -272,6 +272,8 @@ case ComposeboxMode.CREATE_IMAGE: this.onCreateImageClick_(); break; + default: + break; } }
diff --git a/ui/webui/resources/cr_components/history_embeddings/history_embeddings.ts b/ui/webui/resources/cr_components/history_embeddings/history_embeddings.ts index 5f91d149f..80e2e2a 100644 --- a/ui/webui/resources/cr_components/history_embeddings/history_embeddings.ts +++ b/ui/webui/resources/cr_components/history_embeddings/history_embeddings.ts
@@ -18,7 +18,7 @@ import {CrFeedbackOption} from '//resources/cr_elements/cr_feedback_buttons/cr_feedback_buttons.js'; import type {CrLazyRenderLitElement} from '//resources/cr_elements/cr_lazy_render/cr_lazy_render_lit.js'; import {I18nMixinLit} from '//resources/cr_elements/i18n_mixin_lit.js'; -import {assert, assertNotReached} from '//resources/js/assert.js'; +import {assert, assertNotReachedCase} from '//resources/js/assert.js'; import {EventTracker} from '//resources/js/event_tracker.js'; import {getFaviconForPageURL} from '//resources/js/icon.js'; import {loadTimeData} from '//resources/js/load_time_data.js'; @@ -272,7 +272,7 @@ case AnswerStatus.kExecutionFailure: return this.i18n('historyEmbeddingsAnswererErrorTryAgain'); default: - assertNotReached(); + assertNotReachedCase(this.searchResult_.answerStatus); } } @@ -361,6 +361,8 @@ case CrFeedbackOption.THUMBS_DOWN: this.browserProxy_.setUserFeedback(UserFeedback.kUserFeedbackNegative); return; + default: + assertNotReachedCase(e.detail.value); } }
diff --git a/ui/webui/resources/cr_components/searchbox/searchbox.ts b/ui/webui/resources/cr_components/searchbox/searchbox.ts index 7f4f4d0..671d6363 100644 --- a/ui/webui/resources/cr_components/searchbox/searchbox.ts +++ b/ui/webui/resources/cr_components/searchbox/searchbox.ts
@@ -20,7 +20,7 @@ import type {DragAndDropHost} from '//resources/cr_components/search/drag_drop_host.js'; import {I18nMixinLit} from '//resources/cr_elements/i18n_mixin_lit.js'; import {WebUiListenerMixinLit} from '//resources/cr_elements/web_ui_listener_mixin_lit.js'; -import {assert} from '//resources/js/assert.js'; +import {assert, assertNotReachedCase} from '//resources/js/assert.js'; import {loadTimeData} from '//resources/js/load_time_data.js'; import {MetricsReporterImpl} from '//resources/js/metrics_reporter/metrics_reporter.js'; import {hasKeyModifiers} from '//resources/js/util.js'; @@ -137,6 +137,8 @@ nextAnimationState: AnimationState.FADE_IN, }; break; + default: + assertNotReachedCase(state); } this.animation_ = this.input_.animate(