diff --git a/.gn b/.gn index 699e1e8..a7c8ed4 100644 --- a/.gn +++ b/.gn
@@ -66,7 +66,6 @@ "//chrome/test:browser_tests", "//chrome/test:browser_tests_runner", "//chrome/test:interactive_ui_tests", - "//chrome/test:test_support_ui", "//chrome/test:unit_tests", "//chrome/test:unit_tests__library", "//chrome/test:usage_time_limit_unittests", @@ -84,7 +83,6 @@ "//ppapi:*", # 3 errors "//remoting/host/file_transfer:*", # 43 errors "//remoting/host/installer/mac:*", # 1 error - "//remoting/host/it2me:*", # 18 errors "//remoting/host/mac:*", # 49 errors "//remoting/host/security_key:*", # 68 errors "//remoting/host/win:*", # 43 errors
diff --git a/.vpython3 b/.vpython3 index 39206c2..1f38037 100644 --- a/.vpython3 +++ b/.vpython3
@@ -28,7 +28,7 @@ # components/policy/test_support/policy_testserver.py wheel: < name: "infra/python/wheels/protobuf-py2_py3" - version: "version:3.15.8" + version: "version:3.6.1" > # TODO(https://crbug.com/898348): Add in necessary wheels as Python3 versions
diff --git a/DEPS b/DEPS index f2cc73c..2193df7 100644 --- a/DEPS +++ b/DEPS
@@ -209,7 +209,7 @@ # 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': 'c6260f974261ee9fb5dc9573669559d728a856e8', + 'skia_revision': '1f193df9b393d50da39570dab77a0bb5d28ec8ef', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. @@ -225,11 +225,11 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling SwiftShader # and whatever else without interference from each other. - 'swiftshader_revision': '2deb0df8fa34b2935bdae7a6e01560504bdad399', + 'swiftshader_revision': '3b9a1a795f1e46862973f145627ce71fb49a16d2', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling PDFium # and whatever else without interference from each other. - 'pdfium_revision': '230db1dfe1d55b0a669870b14ce1bf27b0173e9e', + 'pdfium_revision': 'dab1161c861cc239e48a17e1a5d729aa12785a53', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling BoringSSL # and whatever else without interference from each other. @@ -260,7 +260,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling freetype # and whatever else without interference from each other. - 'freetype_revision': '06e21ffedfac81edfa79137959141a9d78b6f858', + 'freetype_revision': 'ebf9e5ac719a5a1a374dbf2dd6b12e84de9466ed', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling freetype # and whatever else without interference from each other. @@ -328,7 +328,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. - 'dawn_revision': 'b2527e6d9c03a4560ee5aff27c61de3b2a87b63d', + 'dawn_revision': 'b58efd079cab22fe46db6a55e749b0179d9c5a07', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. @@ -573,7 +573,7 @@ }, 'src/ios/third_party/material_components_ios/src': { - 'url': Var('chromium_git') + '/external/github.com/material-components/material-components-ios.git' + '@' + '1bb324904901bc27566a0ea8c950533a4d932c7e', + 'url': Var('chromium_git') + '/external/github.com/material-components/material-components-ios.git' + '@' + 'bb30d816424f0131d94c8d2b27c3b59a2b6427bf', 'condition': 'checkout_ios', }, @@ -583,7 +583,7 @@ }, 'src/ios/third_party/material_internationalization_ios/src': { - 'url': Var('chromium_git') + '/external/github.com/material-foundation/material-internationalization-ios.git' + '@' + 'd8f32464ac97d5551c8db19de916170ae87cfa90', + 'url': Var('chromium_git') + '/external/github.com/material-foundation/material-internationalization-ios.git' + '@' + 'a18e7920fc12150d1f9cf4bec39ccc94a405ad81', 'condition': 'checkout_ios', }, @@ -598,7 +598,7 @@ }, 'src/ios/third_party/material_text_accessibility_ios/src': { - 'url': Var('chromium_git') + '/external/github.com/material-foundation/material-text-accessibility-ios.git' + '@' + '8f4a5acc074ba8d3bdb709896d6d1e116f9c51b5', + 'url': Var('chromium_git') + '/external/github.com/material-foundation/material-text-accessibility-ios.git' + '@' + '197375261e25ee5d473219d0f353a1f635f5393d', 'condition': 'checkout_ios', }, @@ -966,7 +966,7 @@ }, 'src/third_party/depot_tools': - Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'dd0076703b55ea14f15666c62759ea242906e4b7', + Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '51e37088411bd9626f8cccde403538668d4dcd00', 'src/third_party/devtools-frontend/src': Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'), @@ -1547,7 +1547,7 @@ 'src/third_party/usrsctp/usrsctplib': Var('chromium_git') + '/external/github.com/sctplab/usrsctp' + '@' + '22ba62ffe79c3881581ab430368bf3764d9533eb', - 'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@02a51202ebfe6eae1f8af87e97f69bb6486f42e5', + 'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@15fd0774bd4853524825cb5221a8bad4d7911a77', 'src/third_party/vulkan_memory_allocator': Var('chromium_git') + '/external/github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator.git' + '@' + '732a76d9d3c70d6aa487216495eeb28518349c3a', @@ -1571,7 +1571,7 @@ Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + 'a0b8774ce8cec1dc8f4308810bf05eb8867c62de', 'src/third_party/webgpu-cts/src': - Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + 'a03bb38c0e771a0b404753b8e65250e98719870f', + Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + '6ac8b328a4d1f08cd4069b48d2ddd9634548daf3', 'src/third_party/webrtc': Var('webrtc_git') + '/src.git' + '@' + 'cf0ec283d2a6ef55f3e6f6c19ec1f282e355a42b', @@ -1635,7 +1635,7 @@ Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'), 'src-internal': { - 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@3e2ef08e4c5aa8a73b56bb12c6bc9c34845f0ed4', + 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@82c040fb87d4bbe04ad6392066c94ef502c7c664', 'condition': 'checkout_src_internal', }, @@ -1665,7 +1665,7 @@ 'packages': [ { 'package': 'chromeos_internal/apps/media_app/app', - 'version': 'eu5KcWk2CMngdZ-5jWXPVukDEwnyb4g5Ez8T6uqIRzoC', + 'version': 'n3oT209iCIYXg1LYyyoHiSXFico1tJq1xwpMSsd4yh4C', }, ], 'condition': 'checkout_chromeos and checkout_src_internal',
diff --git a/ash/BUILD.gn b/ash/BUILD.gn index 36b8898..4da5383 100644 --- a/ash/BUILD.gn +++ b/ash/BUILD.gn
@@ -2630,6 +2630,7 @@ "//chrome/test:accessibility_live_site_tests", "//chrome/test:captured_sites_interactive_tests", "//chrome/test:test_support", + "//chrome/test:test_support_ui", "//chrome/test:test_support_unit", "//components/exo:*", "//components/exo/wayland:*",
diff --git a/ash/child_accounts/OWNERS b/ash/child_accounts/OWNERS index 3c504a4..6fa773cd 100644 --- a/ash/child_accounts/OWNERS +++ b/ash/child_accounts/OWNERS
@@ -1,3 +1,3 @@ agawronska@chromium.org llin@chromium.org -michaelpg@chromium.org \ No newline at end of file +michaelpg@chromium.org
diff --git a/ash/components/audio/OWNERS b/ash/components/audio/OWNERS index 4bebbefe..e71cb32 100644 --- a/ash/components/audio/OWNERS +++ b/ash/components/audio/OWNERS
@@ -1,2 +1,2 @@ jennyz@chromium.org -hychao@chromium.org \ No newline at end of file +hychao@chromium.org
diff --git a/ash/constants/ash_pref_names.cc b/ash/constants/ash_pref_names.cc index d428d42..87801d4 100644 --- a/ash/constants/ash_pref_names.cc +++ b/ash/constants/ash_pref_names.cc
@@ -15,6 +15,10 @@ const char kAssistPersonalInfoEnabled[] = "assistive_input.personal_info_enabled"; +// A boolean pref of whether assist predictive writing is enabled. +const char kAssistPredictiveWritingEnabled[] = + "assistive_input.predictive_writing_enabled"; + // A boolean pref of whether emoji suggestion is enabled. const char kEmojiSuggestionEnabled[] = "assistive_input.emoji_suggestion_enabled";
diff --git a/ash/constants/ash_pref_names.h b/ash/constants/ash_pref_names.h index 9a64dca..508920b 100644 --- a/ash/constants/ash_pref_names.h +++ b/ash/constants/ash_pref_names.h
@@ -15,6 +15,8 @@ COMPONENT_EXPORT(ASH_CONSTANTS) extern const char kAssistPersonalInfoEnabled[]; COMPONENT_EXPORT(ASH_CONSTANTS) +extern const char kAssistPredictiveWritingEnabled[]; +COMPONENT_EXPORT(ASH_CONSTANTS) extern const char kESimRefreshedEuiccs[]; COMPONENT_EXPORT(ASH_CONSTANTS) extern const char kESimProfiles[];
diff --git a/ash/content/common/OWNERS b/ash/content/common/OWNERS index 411167b..834505c7 100644 --- a/ash/content/common/OWNERS +++ b/ash/content/common/OWNERS
@@ -2,4 +2,4 @@ jimmyxgong@chromium.org zentaro@chromium.org gavinwill@chromium.org -joonbug@chromium.org \ No newline at end of file +joonbug@chromium.org
diff --git a/ash/content/shimless_rma/OWNERS b/ash/content/shimless_rma/OWNERS index ca0094a..1869fd6 100644 --- a/ash/content/shimless_rma/OWNERS +++ b/ash/content/shimless_rma/OWNERS
@@ -3,4 +3,4 @@ # Backup OWNERS zentaro@chromium.org -jimmyxgong@chromium.org \ No newline at end of file +jimmyxgong@chromium.org
diff --git a/ash/content/shortcut_customization_ui/OWNERS b/ash/content/shortcut_customization_ui/OWNERS index 168fc77..45cef29a 100644 --- a/ash/content/shortcut_customization_ui/OWNERS +++ b/ash/content/shortcut_customization_ui/OWNERS
@@ -1,3 +1,3 @@ # Primary OWNERS jimmyxgong@chromium.org -zentaro@chromium.org \ No newline at end of file +zentaro@chromium.org
diff --git a/ash/login/OWNERS b/ash/login/OWNERS index 88c95c1..8a99081 100644 --- a/ash/login/OWNERS +++ b/ash/login/OWNERS
@@ -1,4 +1,4 @@ file://ash/login/LOGIN_LOCK_OWNERS # For login-screen issues use component UI>Shell>StartScreen -# \ No newline at end of file +#
diff --git a/ash/public/cpp/child_accounts/OWNERS b/ash/public/cpp/child_accounts/OWNERS index 3c504a4..6fa773cd 100644 --- a/ash/public/cpp/child_accounts/OWNERS +++ b/ash/public/cpp/child_accounts/OWNERS
@@ -1,3 +1,3 @@ agawronska@chromium.org llin@chromium.org -michaelpg@chromium.org \ No newline at end of file +michaelpg@chromium.org
diff --git a/ash/shortcut_viewer/OWNERS b/ash/shortcut_viewer/OWNERS index c9c3bec..c933f89 100644 --- a/ash/shortcut_viewer/OWNERS +++ b/ash/shortcut_viewer/OWNERS
@@ -4,4 +4,4 @@ zentaro@chromium.org # For adding or removing languages. -per-file *.grd=claudiomagni@chromium.org \ No newline at end of file +per-file *.grd=claudiomagni@chromium.org
diff --git a/ash/system/holding_space/OWNERS b/ash/system/holding_space/OWNERS index d32dd69..03ad759 100644 --- a/ash/system/holding_space/OWNERS +++ b/ash/system/holding_space/OWNERS
@@ -1,2 +1,2 @@ file://ash/public/cpp/holding_space/OWNERS -amehfooz@chromium.org \ No newline at end of file +amehfooz@chromium.org
diff --git a/ash/system/message_center/OWNERS b/ash/system/message_center/OWNERS index f31077a5..577bbabd6 100644 --- a/ash/system/message_center/OWNERS +++ b/ash/system/message_center/OWNERS
@@ -1 +1 @@ -file://ui/message_center/OWNERS \ No newline at end of file +file://ui/message_center/OWNERS
diff --git a/base/BUILD.gn b/base/BUILD.gn index df24024..a3e92f6e 100644 --- a/base/BUILD.gn +++ b/base/BUILD.gn
@@ -3518,6 +3518,7 @@ "allocator/partition_allocator/address_space_randomization_unittest.cc", "allocator/partition_allocator/memory_reclaimer_unittest.cc", "allocator/partition_allocator/page_allocator_unittest.cc", + "allocator/partition_allocator/partition_address_space_unittest.cc", "allocator/partition_allocator/partition_alloc_unittest.cc", "allocator/partition_allocator/partition_lock_unittest.cc", "allocator/partition_allocator/starscan/object_bitmap_unittest.cc",
diff --git a/base/allocator/partition_allocator/page_allocator.cc b/base/allocator/partition_allocator/page_allocator.cc index 8b47bb4..3e84f5b5 100644 --- a/base/allocator/partition_allocator/page_allocator.cc +++ b/base/allocator/partition_allocator/page_allocator.cc
@@ -72,13 +72,18 @@ size_t base_length, size_t trim_length, uintptr_t alignment, + uintptr_t alignment_offset, PageAccessibilityConfiguration accessibility) { - size_t pre_slack = reinterpret_cast<uintptr_t>(base) & (alignment - 1); - if (pre_slack) { - pre_slack = alignment - pre_slack; - } + PA_DCHECK(base_length >= trim_length); + PA_DCHECK(bits::IsPowerOfTwo(alignment)); + PA_DCHECK(alignment_offset < alignment); + uintptr_t base_as_uintptr = reinterpret_cast<uintptr_t>(base); + uintptr_t new_base = + NextAlignedWithOffset(base_as_uintptr, alignment, alignment_offset); + PA_DCHECK(new_base >= base_as_uintptr); + size_t pre_slack = new_base - base_as_uintptr; size_t post_slack = base_length - pre_slack - trim_length; - PA_DCHECK(base_length >= trim_length || pre_slack || post_slack); + PA_DCHECK(base_length == trim_length || pre_slack || post_slack); PA_DCHECK(pre_slack < base_length); PA_DCHECK(post_slack < base_length); return TrimMappingInternal(base, base_length, trim_length, accessibility, @@ -87,6 +92,35 @@ } // namespace +// Align |address| up to the closest, non-smaller address, that gives +// |requested_offset| remainder modulo |alignment|. +// +// Examples for alignment=1024 and requested_offset=64: +// 64 -> 64 +// 65 -> 1088 +// 1024 -> 1088 +// 1088 -> 1088 +// 1089 -> 2112 +// 2048 -> 2112 +uintptr_t NextAlignedWithOffset(uintptr_t address, + uintptr_t alignment, + uintptr_t requested_offset) { + PA_DCHECK(bits::IsPowerOfTwo(alignment)); + PA_DCHECK(requested_offset < alignment); + + uintptr_t actual_offset = address & (alignment - 1); + uintptr_t new_address; + if (actual_offset <= requested_offset) + new_address = address + requested_offset - actual_offset; + else + new_address = address + alignment + requested_offset - actual_offset; + PA_DCHECK(new_address >= address); + PA_DCHECK(new_address - address < alignment); + PA_DCHECK(new_address % alignment == requested_offset); + + return new_address; +} + void* SystemAllocPages(void* hint, size_t length, PageAccessibilityConfiguration accessibility, @@ -106,22 +140,36 @@ size_t align, PageAccessibilityConfiguration accessibility, PageTag page_tag) { + return AllocPagesWithAlignOffset(address, length, align, 0, accessibility, + page_tag); +} + +void* AllocPagesWithAlignOffset(void* address, + size_t length, + size_t align, + size_t align_offset, + PageAccessibilityConfiguration accessibility, + PageTag page_tag) { PA_DCHECK(length >= PageAllocationGranularity()); PA_DCHECK(!(length & PageAllocationGranularityOffsetMask())); PA_DCHECK(align >= PageAllocationGranularity()); // Alignment must be power of 2 for masking math to work. PA_DCHECK(base::bits::IsPowerOfTwo(align)); + PA_DCHECK(align_offset < align); + PA_DCHECK(!(align_offset & PageAllocationGranularityOffsetMask())); PA_DCHECK(!(reinterpret_cast<uintptr_t>(address) & PageAllocationGranularityOffsetMask())); uintptr_t align_offset_mask = align - 1; uintptr_t align_base_mask = ~align_offset_mask; - PA_DCHECK(!(reinterpret_cast<uintptr_t>(address) & align_offset_mask)); + PA_DCHECK(address == nullptr || (reinterpret_cast<uintptr_t>(address) & + align_offset_mask) == align_offset); // If the client passed null as the address, choose a good one. if (address == nullptr) { address = GetRandomPageBase(); - address = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(address) & - align_base_mask); + address = reinterpret_cast<void*>( + (reinterpret_cast<uintptr_t>(address) & align_base_mask) + + align_offset); } // First try to force an exact-size, aligned allocation from our random base. @@ -139,7 +187,8 @@ AllocPagesIncludingReserved(address, length, accessibility, page_tag); if (ret != nullptr) { // If the alignment is to our liking, we're done. - if (!(reinterpret_cast<uintptr_t>(ret) & align_offset_mask)) + if ((reinterpret_cast<uintptr_t>(ret) & align_offset_mask) == + align_offset) return ret; // Free the memory and try again. FreePages(ret, length); @@ -151,15 +200,18 @@ #if defined(ARCH_CPU_32_BITS) // For small address spaces, try the first aligned address >= |ret|. Note - // |ret| may be null, in which case |address| becomes null. + // |ret| may be null, in which case |address| becomes null. If + // |align_offset| is non-zero, this calculation may get us not the first, + // but the next matching address. address = reinterpret_cast<void*>( - (reinterpret_cast<uintptr_t>(ret) + align_offset_mask) & - align_base_mask); + ((reinterpret_cast<uintptr_t>(ret) + align_offset_mask) & + align_base_mask) + + align_offset); #else // defined(ARCH_CPU_64_BITS) // Keep trying random addresses on systems that have a large address space. address = GetRandomPageBase(); - address = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(address) & - align_base_mask); + address = reinterpret_cast<void*>(NextAlignedWithOffset( + reinterpret_cast<uintptr_t>(address), align, align_offset)); #endif } @@ -175,8 +227,9 @@ page_tag); // The retries are for Windows, where a race can steal our mapping on // resize. - } while (ret != nullptr && (ret = TrimMapping(ret, try_length, length, align, - accessibility)) == nullptr); + } while (ret != nullptr && + (ret = TrimMapping(ret, try_length, length, align, align_offset, + accessibility)) == nullptr); return ret; }
diff --git a/base/allocator/partition_allocator/page_allocator.h b/base/allocator/partition_allocator/page_allocator.h index 68ed0f3..eec0034 100644 --- a/base/allocator/partition_allocator/page_allocator.h +++ b/base/allocator/partition_allocator/page_allocator.h
@@ -53,18 +53,24 @@ kLast = kV8 // Maximum tag value. }; +BASE_EXPORT uintptr_t NextAlignedWithOffset(uintptr_t ptr, + uintptr_t alignment, + uintptr_t requested_offset); + // Allocate one or more pages. // // The requested |address| is just a hint; the actual address returned may -// differ. The returned address will be aligned at least to |align| bytes. -// |length| is in bytes, and must be a multiple of -// |PageAllocationGranularity()|. |align| is in bytes, and must be a -// power-of-two multiple of |PageAllocationGranularity()|. +// differ. The returned address will be aligned to |align_offset| modulo |align| +// bytes. +// +// |length|, |align| and |align_offset| are in bytes, and must be a multiple of +// |PageAllocationGranularity()|. |length| and |align| must be non-zero. +// |align_offset| must be less than |align|. |align| must be a power of two. // // If |address| is null, then a suitable and randomized address will be chosen // automatically. // -// |page_accessibility| controls the permission of the allocated pages. +// |accessibility| controls the permission of the allocated pages. // PageInaccessible means uncommitted. // // |page_tag| is used on some platforms to identify the source of the @@ -74,8 +80,15 @@ BASE_EXPORT void* AllocPages(void* address, size_t length, size_t align, - PageAccessibilityConfiguration page_accessibility, - PageTag tag); + PageAccessibilityConfiguration accessibility, + PageTag page_tag); +BASE_EXPORT void* AllocPagesWithAlignOffset( + void* address, + size_t length, + size_t align, + size_t align_offset, + PageAccessibilityConfiguration page_accessibility, + PageTag page_tag); // Free one or more pages starting at |address| and continuing for |length| // bytes.
diff --git a/base/allocator/partition_allocator/page_allocator_unittest.cc b/base/allocator/partition_allocator/page_allocator_unittest.cc index 2f5e5a8..6df62d0 100644 --- a/base/allocator/partition_allocator/page_allocator_unittest.cc +++ b/base/allocator/partition_allocator/page_allocator_unittest.cc
@@ -7,6 +7,7 @@ #include <stdlib.h> #include <string.h> #include <algorithm> +#include <cstdint> #include <string> #include <vector> #include "base/cpu.h" @@ -87,6 +88,16 @@ 2 * PageAllocationGranularity() - 1)); } +TEST(PageAllocatorTest, NextAlignedWithOffset) { + EXPECT_EQ(1024u, NextAlignedWithOffset(1024, 1, 0)); + EXPECT_EQ(2024u, NextAlignedWithOffset(1024, 1024, 1000)); + EXPECT_EQ(2024u, NextAlignedWithOffset(2024, 1024, 1000)); + EXPECT_EQ(3048u, NextAlignedWithOffset(2025, 1024, 1000)); + EXPECT_EQ(2048u, NextAlignedWithOffset(1024, 2048, 0)); + EXPECT_EQ(2148u, NextAlignedWithOffset(1024, 2048, 100)); + EXPECT_EQ(2000u, NextAlignedWithOffset(1024, 2048, 2000)); +} + // Test that failed page allocations invoke base::ReleaseReservation(). // We detect this by making a reservation and ensuring that after failure, we // can make a new reservation. @@ -155,6 +166,24 @@ FreePages(buffer, PageAllocationGranularity()); } +TEST(PageAllocatorTest, AllocPagesAligned) { + size_t alignment = 8 * PageAllocationGranularity(); + size_t sizes[] = {PageAllocationGranularity(), + alignment - PageAllocationGranularity(), alignment, + alignment + PageAllocationGranularity(), alignment * 4}; + size_t offsets[] = {0, PageAllocationGranularity(), alignment / 2, + alignment - PageAllocationGranularity()}; + for (size_t size : sizes) { + for (size_t offset : offsets) { + void* buffer = AllocPagesWithAlignOffset( + nullptr, size, alignment, offset, PageReadWrite, PageTag::kChromium); + EXPECT_TRUE(buffer); + EXPECT_EQ(reinterpret_cast<uintptr_t>(buffer) % alignment, offset); + FreePages(buffer, size); + } + } +} + TEST(PageAllocatorTest, AllocAndFreePagesWithPageReadWriteTagged) { // This test checks that a page allocated with PageReadWriteTagged is // safe to use on all systems (even those which don't support MTE). @@ -458,21 +487,27 @@ TEST(PageAllocatorTest, MappedPagesAccounting) { size_t size = PageAllocationGranularity(); - size_t mapped_size_before = GetTotalMappedSize(); - // Ask for a large alignment to make sure that trimming doesn't change the // accounting. - void* data = AllocPages(nullptr, size, 128 * PageAllocationGranularity(), - PageInaccessible, PageTag::kChromium); - ASSERT_TRUE(data); + size_t alignment = 128 * PageAllocationGranularity(); + size_t offsets[] = {0, PageAllocationGranularity(), alignment / 2, + alignment - PageAllocationGranularity()}; - EXPECT_EQ(mapped_size_before + size, GetTotalMappedSize()); + size_t mapped_size_before = GetTotalMappedSize(); - DecommitSystemPages(data, size, PageKeepPermissionsIfPossible); - EXPECT_EQ(mapped_size_before + size, GetTotalMappedSize()); + for (size_t offset : offsets) { + void* data = AllocPagesWithAlignOffset( + nullptr, size, alignment, offset, PageInaccessible, PageTag::kChromium); + ASSERT_TRUE(data); - FreePages(data, size); - EXPECT_EQ(mapped_size_before, GetTotalMappedSize()); + EXPECT_EQ(mapped_size_before + size, GetTotalMappedSize()); + + DecommitSystemPages(data, size, PageKeepPermissionsIfPossible); + EXPECT_EQ(mapped_size_before + size, GetTotalMappedSize()); + + FreePages(data, size); + EXPECT_EQ(mapped_size_before, GetTotalMappedSize()); + } } } // namespace base
diff --git a/base/allocator/partition_allocator/partition_address_space.cc b/base/allocator/partition_allocator/partition_address_space.cc index e741a07e..9835f07 100644 --- a/base/allocator/partition_allocator/partition_address_space.cc +++ b/base/allocator/partition_allocator/partition_address_space.cc
@@ -4,6 +4,8 @@ #include "base/allocator/partition_allocator/partition_address_space.h" +#include <array> + #include "base/allocator/partition_allocator/address_pool_manager.h" #include "base/allocator/partition_allocator/page_allocator.h" #include "base/allocator/partition_allocator/page_allocator_internal.h" @@ -18,6 +20,8 @@ #if defined(PA_HAS_64_BITS_POINTERS) +constexpr std::array<size_t, 2> PartitionAddressSpace::kPoolSizes; + uintptr_t PartitionAddressSpace::reserved_base_address_ = 0; // Before PartitionAddressSpace::Init(), no allocation are allocated from a // reserved address space. Therefore, set *_pool_base_address_ initially to @@ -34,14 +38,19 @@ if (IsInitialized()) return; - reserved_base_address_ = reinterpret_cast<uintptr_t>(AllocPages( - nullptr, kDesiredAddressSpaceSize, kReservedAddressSpaceAlignment, - base::PageInaccessible, PageTag::kPartitionAlloc)); + GigaCageProperties properties = CalculateGigaCageProperties(kPoolSizes); + + reserved_base_address_ = + reinterpret_cast<uintptr_t>(AllocPagesWithAlignOffset( + nullptr, properties.size, properties.alignment, + properties.alignment_offset, base::PageInaccessible, + PageTag::kPartitionAlloc)); PA_CHECK(reserved_base_address_); uintptr_t current = reserved_base_address_; non_brp_pool_base_address_ = current; + PA_DCHECK(!(non_brp_pool_base_address_ & (kNonBRPPoolSize - 1))); non_brp_pool_ = internal::AddressPoolManager::GetInstance()->Add( current, kNonBRPPoolSize); PA_DCHECK(non_brp_pool_); @@ -52,6 +61,7 @@ PA_DCHECK(!IsInNonBRPPool(reinterpret_cast<void*>(current))); brp_pool_base_address_ = current; + PA_DCHECK(!(brp_pool_base_address_ & (kBRPPoolSize - 1))); brp_pool_ = internal::AddressPoolManager::GetInstance()->Add(current, kBRPPoolSize); PA_DCHECK(brp_pool_); @@ -72,12 +82,13 @@ SetSystemPagesAccess(actual_address, kSuperPageSize, PageInaccessible); #endif - PA_DCHECK(reserved_base_address_ + kDesiredAddressSpaceSize == current); + PA_DCHECK(reserved_base_address_ + properties.size == current); } void PartitionAddressSpace::UninitForTesting() { - FreePages(reinterpret_cast<void*>(reserved_base_address_), - kReservedAddressSpaceAlignment); + GigaCageProperties properties = CalculateGigaCageProperties(kPoolSizes); + + FreePages(reinterpret_cast<void*>(reserved_base_address_), properties.size); reserved_base_address_ = 0; non_brp_pool_base_address_ = kNonBRPPoolOffsetMask; brp_pool_base_address_ = kBRPPoolOffsetMask;
diff --git a/base/allocator/partition_allocator/partition_address_space.h b/base/allocator/partition_allocator/partition_address_space.h index f53ed1a1..59a2f456 100644 --- a/base/allocator/partition_allocator/partition_address_space.h +++ b/base/allocator/partition_allocator/partition_address_space.h
@@ -6,6 +6,7 @@ #define BASE_ALLOCATOR_PARTITION_ALLOCATOR_PARTITION_ADDRESS_SPACE_H_ #include <algorithm> +#include <array> #include "base/allocator/partition_allocator/address_pool_manager_types.h" #include "base/allocator/partition_allocator/partition_alloc_check.h" @@ -26,6 +27,47 @@ // The feature is not applicable to 32-bit address space. #if defined(PA_HAS_64_BITS_POINTERS) +struct GigaCageProperties { + size_t size; + size_t alignment; + size_t alignment_offset; +}; + +template <size_t N> +GigaCageProperties CalculateGigaCageProperties( + const std::array<size_t, N>& pool_sizes) { + size_t size_sum = 0; + size_t alignment = 0; + size_t alignment_offset; + // The goal is to find properties such that each pool's start address is + // aligned to its own size. To achieve that, the largest pool will serve + // as an anchor (the first one, if there are more) and it'll be used to + // determine the core alignment. The sizes of pools before the anchor will + // determine the offset within the core alignment at which the GigaCage will + // start. + // If this algorithm doesn't find the proper alignment, it means such an + // alignment doesn't exist. + for (size_t pool_size : pool_sizes) { + PA_CHECK(bits::IsPowerOfTwo(pool_size)); + if (pool_size > alignment) { + alignment = pool_size; + // This may underflow, leading to a very high value, so use modulo + // |alignment| to bring it down. + alignment_offset = (alignment - size_sum) & (alignment - 1); + } + size_sum += pool_size; + } + // Use PA_CHECK because we can't correctly proceed if any pool's start address + // isn't aligned to its own size. Exact initial value of |sample_address| + // doesn't matter as long as |address % alignment == alignment_offset|. + uintptr_t sample_address = alignment_offset + 7 * alignment; + for (size_t pool_size : pool_sizes) { + PA_CHECK(!(sample_address & (pool_size - 1))); + sample_address += pool_size; + } + return GigaCageProperties{size_sum, alignment, alignment_offset}; +} + // Reserves address space for PartitionAllocator. class BASE_EXPORT PartitionAddressSpace { public: @@ -101,37 +143,24 @@ static constexpr size_t kGigaBytes = 1024 * 1024 * 1024; - // Pool sizes are flexible, as long as each pool is aligned on its own size - // boundary and the size is a power of two. The entire region is aligned on - // the max pool size boundary, so the further pools only need to care about - // the shift from the beginning of the region (for clarity, the pool sizes are - // declared in the order the pools are allocated). + // Pool sizes have to be the power of two. Each pool will be aligned at its + // own size boundary. // - // For example, [8GiB,4GiB,4GiB], [8GiB,4GiB,2GiB,1GiB] would work, but - // [4GiB,8GiB] wouldn't (the 2nd pool is aligned on 4GiB but needs 8GiB), - // and [4GiB,4GiB,8GiB] would. + // In theory, pools can be allocated separately in the address space. However, + // due to the above restriction to have BRP pool be preceded by another pool, + // better to have them occupy contiguous addresses. Therefore, care has to be + // taken when choosing sizes, if more than 2 pools are needed. For example, + // with sizes [8GiB,4GiB,8GiB], it'd be impossible to align each pool at its + // own size boundary while keeping them next to each other. + // CalculateGigaCageProperties() has non-debug run-time checks to ensure that. static constexpr size_t kNonBRPPoolSize = 8 * kGigaBytes; static constexpr size_t kBRPPoolSize = 8 * kGigaBytes; - - static constexpr size_t kDesiredAddressSpaceSize = - kNonBRPPoolSize + kBRPPoolSize; - static constexpr size_t kReservedAddressSpaceAlignment = - std::max(kNonBRPPoolSize, kBRPPoolSize); + static constexpr std::array<size_t, 2> kPoolSizes = {kNonBRPPoolSize, + kBRPPoolSize}; static_assert(bits::IsPowerOfTwo(kNonBRPPoolSize) && bits::IsPowerOfTwo(kBRPPoolSize), "Each pool size should be a power of two."); - static_assert(bits::IsPowerOfTwo(kReservedAddressSpaceAlignment), - "kReservedAddressSpaceAlignment should be a power of two."); - static_assert(kReservedAddressSpaceAlignment >= kNonBRPPoolSize && - kReservedAddressSpaceAlignment >= kBRPPoolSize, - "kReservedAddressSpaceAlignment should be larger or equal to " - "each pool size."); - static_assert(kReservedAddressSpaceAlignment % kNonBRPPoolSize == 0 && - (kReservedAddressSpaceAlignment + kNonBRPPoolSize) % - kBRPPoolSize == - 0, - "Each pool should be aligned to its own size"); // Masks used to easy determine belonging to a pool. static constexpr uintptr_t kNonBRPPoolOffsetMask =
diff --git a/base/allocator/partition_allocator/partition_address_space_unittest.cc b/base/allocator/partition_allocator/partition_address_space_unittest.cc new file mode 100644 index 0000000..e98d1df --- /dev/null +++ b/base/allocator/partition_allocator/partition_address_space_unittest.cc
@@ -0,0 +1,89 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/allocator/partition_allocator/partition_address_space.h" + +#include <array> + +#include "base/allocator/partition_allocator/partition_alloc_config.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace base { +namespace internal { + +#if defined(PA_HAS_64_BITS_POINTERS) + +TEST(PartitionAllocAddressSpace, CalculateGigaCageProperties) { + GigaCageProperties props; + + props = CalculateGigaCageProperties(std::array<size_t, 1>{1}); + EXPECT_EQ(1u, props.size); + EXPECT_EQ(1u, props.alignment); + EXPECT_EQ(0u, props.alignment_offset); + + props = CalculateGigaCageProperties(std::array<size_t, 2>{2, 1}); + EXPECT_EQ(3u, props.size); + EXPECT_EQ(2u, props.alignment); + EXPECT_EQ(0u, props.alignment_offset); + + props = CalculateGigaCageProperties(std::array<size_t, 2>{1, 2}); + EXPECT_EQ(3u, props.size); + EXPECT_EQ(2u, props.alignment); + EXPECT_EQ(1u, props.alignment_offset); + + props = CalculateGigaCageProperties(std::array<size_t, 4>{8, 4, 2, 1}); + EXPECT_EQ(15u, props.size); + EXPECT_EQ(8u, props.alignment); + EXPECT_EQ(0u, props.alignment_offset); + + props = CalculateGigaCageProperties(std::array<size_t, 4>{1, 2, 4, 8}); + EXPECT_EQ(15u, props.size); + EXPECT_EQ(8u, props.alignment); + EXPECT_EQ(1u, props.alignment_offset); + + props = + CalculateGigaCageProperties(std::array<size_t, 7>{1, 2, 4, 2, 2, 4, 8}); + EXPECT_EQ(23u, props.size); + EXPECT_EQ(8u, props.alignment); + EXPECT_EQ(1u, props.alignment_offset); + + props = CalculateGigaCageProperties(std::array<size_t, 3>{8, 4, 4}); + EXPECT_EQ(16u, props.size); + EXPECT_EQ(8u, props.alignment); + EXPECT_EQ(0u, props.alignment_offset); + + props = CalculateGigaCageProperties(std::array<size_t, 3>{4, 4, 8}); + EXPECT_EQ(16u, props.size); + EXPECT_EQ(8u, props.alignment); + EXPECT_EQ(0u, props.alignment_offset); + + props = CalculateGigaCageProperties(std::array<size_t, 4>{8, 4, 4, 8}); + EXPECT_EQ(24u, props.size); + EXPECT_EQ(8u, props.alignment); + EXPECT_EQ(0u, props.alignment_offset); + + size_t GiB = 1024ull * 1024 * 1024; + props = CalculateGigaCageProperties( + std::array<size_t, 6>{GiB, GiB, GiB, GiB, GiB, GiB}); + EXPECT_EQ(6 * GiB, props.size); + EXPECT_EQ(GiB, props.alignment); + EXPECT_EQ(0u, props.alignment_offset); +} + +TEST(PartitionAllocAddressSpace, CalculateGigaCagePropertiesImpossible) { + EXPECT_DEATH_IF_SUPPORTED( + CalculateGigaCageProperties(std::array<size_t, 1>{0}), ""); + EXPECT_DEATH_IF_SUPPORTED( + CalculateGigaCageProperties(std::array<size_t, 1>{3}), ""); + EXPECT_DEATH_IF_SUPPORTED( + CalculateGigaCageProperties(std::array<size_t, 3>{8, 4, 8}), ""); + EXPECT_DEATH_IF_SUPPORTED( + CalculateGigaCageProperties(std::array<size_t, 7>{1, 2, 4, 1, 2, 4, 8}), + ""); +} + +#endif // defined(PA_HAS_64_BITS_POINTERS) + +} // namespace internal +} // namespace base
diff --git a/base/android/java/src/org/chromium/base/metrics/RecordUserAction.java b/base/android/java/src/org/chromium/base/metrics/RecordUserAction.java index e75f92bb..62e0c26 100644 --- a/base/android/java/src/org/chromium/base/metrics/RecordUserAction.java +++ b/base/android/java/src/org/chromium/base/metrics/RecordUserAction.java
@@ -16,7 +16,7 @@ * WARNINGS: JNI calls are relatively costly - avoid using in performance-critical code. * <p> * Action names must be documented in {@code actions.xml}. See {@link - * https://source.chromium.org/chromium/chromium/src/+/master:tools/metrics/actions/README.md} <p> + * https://source.chromium.org/chromium/chromium/src/+/main:tools/metrics/actions/README.md} <p> * We use a script ({@code extract_actions.py{}) to scan the source code and extract actions. A * string literal (not a variable) must be passed to {@link #record(String)}. */
diff --git a/base/android/java/src/org/chromium/base/metrics/UmaRecorder.java b/base/android/java/src/org/chromium/base/metrics/UmaRecorder.java index 7f488267..0d37d81 100644 --- a/base/android/java/src/org/chromium/base/metrics/UmaRecorder.java +++ b/base/android/java/src/org/chromium/base/metrics/UmaRecorder.java
@@ -50,7 +50,7 @@ /** * Records a user action. Action names must be documented in {@code actions.xml}. See {@link - * https://source.chromium.org/chromium/chromium/src/+/master:tools/metrics/actions/README.md} + * https://source.chromium.org/chromium/chromium/src/+/main:tools/metrics/actions/README.md} * * @param name Name of the user action. * @param elapsedRealtimeMillis Value of {@link android.os.SystemClock.elapsedRealtime()} when
diff --git a/base/debug/debugger_posix.cc b/base/debug/debugger_posix.cc index ed65181f..68f91d13 100644 --- a/base/debug/debugger_posix.cc +++ b/base/debug/debugger_posix.cc
@@ -141,7 +141,7 @@ << "Detected lldb without sourcing //tools/lldb/lldbinit.py. lldb may " "not be able to find debug symbols. Please see debug instructions for " "using //tools/lldb/lldbinit.py:\n" - "https://chromium.googlesource.com/chromium/src/+/master/docs/" + "https://chromium.googlesource.com/chromium/src/+/main/docs/" "lldbinit.md\n" "To continue anyway, type 'continue' in lldb. To always skip this " "check, define an environment variable CHROMIUM_LLDBINIT_SOURCED=1"; @@ -224,7 +224,7 @@ << "Detected gdb without sourcing //tools/gdb/gdbinit. gdb may not be " "able to find debug symbols, and pretty-printing of STL types may not " "work. Please see debug instructions for using //tools/gdb/gdbinit:\n" - "https://chromium.googlesource.com/chromium/src/+/master/docs/" + "https://chromium.googlesource.com/chromium/src/+/main/docs/" "gdbinit.md\n" "To continue anyway, type 'continue' in gdb. To always skip this " "check, define an environment variable CHROMIUM_GDBINIT_SOURCED=1";
diff --git a/base/logging.h b/base/logging.h index 04873761..31b9c94a 100644 --- a/base/logging.h +++ b/base/logging.h
@@ -166,7 +166,7 @@ // SetLogItems() // // Additional logging-related information can be found here: -// https://chromium.googlesource.com/chromium/src/+/master/docs/linux/debugging.md#Logging +// https://chromium.googlesource.com/chromium/src/+/main/docs/linux/debugging.md#Logging namespace logging {
diff --git a/base/memory/checked_ptr.md b/base/memory/checked_ptr.md index 71b6783..4b054a3 100644 --- a/base/memory/checked_ptr.md +++ b/base/memory/checked_ptr.md
@@ -260,7 +260,7 @@ One way to execute such an incorrect assignment is `reinterpret_cast` of a pointer to a `CheckedPtr`. For example, see https://crbug.com/1154799 where the `reintepret_cast` is/was used in the `Extract` method -[here](https://source.chromium.org/chromium/chromium/src/+/master:device/fido/cbor_extract.h;l=318;drc=16f9768803e17c90901adce97b3153cfd39fdde2)). +[here](https://source.chromium.org/chromium/chromium/src/+/main:device/fido/cbor_extract.h;l=318;drc=16f9768803e17c90901adce97b3153cfd39fdde2)). Simplified example: ```cpp @@ -353,4 +353,4 @@ TODO(glazunov): One example is accessing a class' CheckedPtr fields in its base class' constructor: -https://source.chromium.org/chromium/chromium/src/+/master:third_party/blink/renderer/platform/wtf/doubly_linked_list.h;drc=cce44dc1cb55c77f63f2ebec5e7015b8dc851c82;l=52 +https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/platform/wtf/doubly_linked_list.h;drc=cce44dc1cb55c77f63f2ebec5e7015b8dc851c82;l=52
diff --git a/base/ranges/README.md b/base/ranges/README.md index ee0e081..c9a72c4 100644 --- a/base/ranges/README.md +++ b/base/ranges/README.md
@@ -3,7 +3,7 @@ This directory aims to implement a C++14 version of the new `std::ranges` algorithms that were introduced in C++20. These implementations are added to the `::base::ranges` namespace, and callers can access them by including -[`base/ranges/algorithm.h`](https://source.chromium.org/chromium/chromium/src/+/master:base/ranges/algorithm.h). +[`base/ranges/algorithm.h`](https://source.chromium.org/chromium/chromium/src/+/main:base/ranges/algorithm.h). ## Similarities with C++20:
diff --git a/base/task/sequence_manager/sequence_manager_impl.cc b/base/task/sequence_manager/sequence_manager_impl.cc index 9d3ccbe0..ff51e5d 100644 --- a/base/task/sequence_manager/sequence_manager_impl.cc +++ b/base/task/sequence_manager/sequence_manager_impl.cc
@@ -1174,7 +1174,7 @@ // this. // // See - // https://chromium.googlesource.com/chromium/src/+/master/docs/debugging_with_crash_keys.md + // https://chromium.googlesource.com/chromium/src/+/main/docs/debugging_with_crash_keys.md // for instructions for symbolizing these crash keys. // // TODO(skyostil): Find a way to extract the destination function address
diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn index 4771251d..01c82b1 100644 --- a/build/config/compiler/BUILD.gn +++ b/build/config/compiler/BUILD.gn
@@ -452,7 +452,7 @@ # Linux-specific compiler flags setup. # ------------------------------------ - if ((is_posix || is_fuchsia) && use_lld) { + if ((is_posix || is_fuchsia) && !is_apple && use_lld) { if (current_cpu == "arm64") { # Reduce the page size from 65536 in order to reduce binary size slightly # by shrinking the alignment gap between segments. This also causes all @@ -698,9 +698,7 @@ ldflags += [ "-Wl,-mllvm,-import-instr-limit=$import_instr_limit" ] } - # Whole-program devirtualization increases android libchrome.so size - # by ~100kb on arm32 and reduces it by ~108kb on arm64 instead. - # Tracked by llvm bug: https://bugs.llvm.org/show_bug.cgi?id=48245 + # TODO(https://crbug.com/1211155): investigate why this isn't effective on arm32. if (!is_android || current_cpu == "arm64") { cflags += [ "-fwhole-program-vtables" ] if (!is_win) {
diff --git a/build/config/mac/mac_sdk.gni b/build/config/mac/mac_sdk.gni index 19aa066..7f4432d 100644 --- a/build/config/mac/mac_sdk.gni +++ b/build/config/mac/mac_sdk.gni
@@ -39,7 +39,7 @@ # The SDK version used when making official builds. This is a single exact # version, not a minimum. If this version isn't available official builds # will fail. - mac_sdk_official_version = "11.3" + mac_sdk_official_version = "11.1" # Production builds should use hermetic Xcode. If you want to do production # builds with system Xcode to test new SDKs, set this.
diff --git a/build/mac_toolchain.py b/build/mac_toolchain.py index 2dfdb43..43d336cf 100755 --- a/build/mac_toolchain.py +++ b/build/mac_toolchain.py
@@ -38,10 +38,10 @@ return plistlib.load(f) -# This contains binaries from Xcode 12.5 12E262, along with the macOS 11 SDK. +# This contains binaries from Xcode 12.4 12D4e, along with the macOS 11 SDK. # To build these packages, see comments in build/xcode_binaries.yaml MAC_BINARIES_LABEL = 'infra_internal/ios/xcode/xcode_binaries/mac-amd64' -MAC_BINARIES_TAG = 'pBipKbKSkYGXpuOBm4-8zuvfIGeFtpGbQ4IHM9YW0xMC' +MAC_BINARIES_TAG = 'Za4aUIwiTUjk8rnjRow4nXbth-j7ZoN5plyOSCLidcgC' # The toolchain will not be downloaded if the minimum OS version is not met. 19 # is the major version number for macOS 10.15. 12B5044c (Xcode 12.2rc) only runs
diff --git a/chrome/VERSION b/chrome/VERSION index 839e4665..ccdff92 100644 --- a/chrome/VERSION +++ b/chrome/VERSION
@@ -1,4 +1,4 @@ MAJOR=92 MINOR=0 -BUILD=4513 +BUILD=4515 PATCH=0
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn index baa0c8ab..c88fcbd 100644 --- a/chrome/android/BUILD.gn +++ b/chrome/android/BUILD.gn
@@ -47,7 +47,7 @@ # AndroidManifest and its upstream target's .AndroidManifest.expected file # are as expected. Upstream targets having a "org.chromium.chrome" package # name will cause the comparison to output many unnecessary differences. - # See https://source.chromium.org/chromium/chromium/src/+/master:chrome/android/java/README.md + # See https://source.chromium.org/chromium/chromium/src/+/main:chrome/android/java/README.md _default_package += "." + android_channel }
diff --git a/chrome/android/chrome_java_sources.gni b/chrome/android/chrome_java_sources.gni index 57c9cc3c..8ab1acc 100644 --- a/chrome/android/chrome_java_sources.gni +++ b/chrome/android/chrome_java_sources.gni
@@ -803,10 +803,12 @@ "java/src/org/chromium/chrome/browser/ntp/LogoView.java", "java/src/org/chromium/chrome/browser/ntp/NativePageRootFrameLayout.java", "java/src/org/chromium/chrome/browser/ntp/NewTabPage.java", + "java/src/org/chromium/chrome/browser/ntp/NewTabPageLaunchOrigin.java", "java/src/org/chromium/chrome/browser/ntp/NewTabPageLayout.java", "java/src/org/chromium/chrome/browser/ntp/NewTabPageManager.java", "java/src/org/chromium/chrome/browser/ntp/NewTabPageScrollView.java", "java/src/org/chromium/chrome/browser/ntp/NewTabPageUma.java", + "java/src/org/chromium/chrome/browser/ntp/NewTabPageUtils.java", "java/src/org/chromium/chrome/browser/ntp/RecentTabsExpandableListView.java", "java/src/org/chromium/chrome/browser/ntp/RecentTabsGroupView.java", "java/src/org/chromium/chrome/browser/ntp/RecentTabsManager.java",
diff --git a/chrome/android/expectations/lint-suppressions.xml b/chrome/android/expectations/lint-suppressions.xml index e1785792..2d68b46 100644 --- a/chrome/android/expectations/lint-suppressions.xml +++ b/chrome/android/expectations/lint-suppressions.xml
@@ -1,7 +1,7 @@ <?xml version="1.0" encoding="utf-8" ?> <!-- Please refer to the lint doc for how to use this file and what should go in it: -https://chromium.googlesource.com/chromium/src/+/master/build/android/docs/lint.md +https://chromium.googlesource.com/chromium/src/+/main/build/android/docs/lint.md --> <lint> <!-- Ignore all lint errors in clank code. -->
diff --git a/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/ExploreSurfaceCoordinator.java b/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/ExploreSurfaceCoordinator.java index 5ad4352..0fb2f23 100644 --- a/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/ExploreSurfaceCoordinator.java +++ b/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/ExploreSurfaceCoordinator.java
@@ -16,6 +16,7 @@ import org.chromium.chrome.browser.feed.FeedSurfaceLifecycleManager; import org.chromium.chrome.browser.feed.shared.FeedSurfaceDelegate; import org.chromium.chrome.browser.flags.ChromeFeatureList; +import org.chromium.chrome.browser.ntp.NewTabPageLaunchOrigin; import org.chromium.chrome.browser.ntp.ScrollableContainerDelegate; import org.chromium.chrome.browser.ntp.snippets.SectionHeaderView; import org.chromium.chrome.browser.profiles.Profile; @@ -50,10 +51,11 @@ /** * Creates the {@link FeedSurfaceCoordinator} for the specified mode. * @param isInNightMode Whether or not the feed surface is going to display in night mode. + * @param launchOrigin Where the feed was launched from. * @return The {@link FeedSurfaceCoordinator}. */ - FeedSurfaceCoordinator createFeedSurfaceCoordinator( - boolean isInNightMode, boolean isPlaceholderShown); + FeedSurfaceCoordinator createFeedSurfaceCoordinator(boolean isInNightMode, + boolean isPlaceholderShown, @NewTabPageLaunchOrigin int launchOrigin); } /** @@ -89,10 +91,11 @@ containerPropertyModel, parentView, ExploreSurfaceViewBinder::bind); mFeedSurfaceCreator = new FeedSurfaceCreator() { @Override - public FeedSurfaceCoordinator createFeedSurfaceCoordinator( - boolean isInNightMode, boolean isPlaceholderShown) { + public FeedSurfaceCoordinator createFeedSurfaceCoordinator(boolean isInNightMode, + boolean isPlaceholderShown, @NewTabPageLaunchOrigin int launchOrigin) { return internalCreateFeedSurfaceCoordinator(mHasHeader, isInNightMode, - isPlaceholderShown, bottomSheetController, scrollableContainerDelegate); + isPlaceholderShown, bottomSheetController, scrollableContainerDelegate, + launchOrigin); } }; } @@ -120,7 +123,8 @@ private FeedSurfaceCoordinator internalCreateFeedSurfaceCoordinator(boolean hasHeader, boolean isInNightMode, boolean isPlaceholderShown, BottomSheetController bottomSheetController, - ScrollableContainerDelegate scrollableContainerDelegate) { + ScrollableContainerDelegate scrollableContainerDelegate, + @NewTabPageLaunchOrigin int launchOrigin) { if (mExploreSurfaceNavigationDelegate == null) { mExploreSurfaceNavigationDelegate = new ExploreSurfaceNavigationDelegate(mParentTabSupplier); @@ -144,7 +148,7 @@ new FeedSurfaceCoordinator(mActivity, mSnackbarManager, mWindowAndroid, null, null, sectionHeaderView, isInNightMode, this, mExploreSurfaceNavigationDelegate, profile, isPlaceholderShown, bottomSheetController, mShareDelegateSupplier, - scrollableContainerDelegate, mTabModelSelector); + scrollableContainerDelegate, mTabModelSelector, launchOrigin); feedSurfaceCoordinator.getView().setId(R.id.start_surface_explore_view); return feedSurfaceCoordinator; // TODO(crbug.com/982018): Customize surface background for incognito and dark mode.
diff --git a/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/StartSurfaceMediator.java b/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/StartSurfaceMediator.java index 06ab0f7..f2a46132 100644 --- a/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/StartSurfaceMediator.java +++ b/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/StartSurfaceMediator.java
@@ -46,6 +46,7 @@ import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.lens.LensEntryPoint; import org.chromium.chrome.browser.lens.LensMetrics; +import org.chromium.chrome.browser.ntp.NewTabPageLaunchOrigin; import org.chromium.chrome.browser.omnibox.OmniboxStub; import org.chromium.chrome.browser.omnibox.UrlFocusChangeListener; import org.chromium.chrome.browser.preferences.ChromePreferenceKeys; @@ -130,6 +131,8 @@ private int mStartSurfaceState; @StartSurfaceState private int mPreviousStartSurfaceState; + @NewTabPageLaunchOrigin + private int mLaunchOrigin; @Nullable private TabModel mNormalTabModel; @Nullable @@ -180,6 +183,7 @@ mExcludeMVTiles = excludeMVTiles; mStartSurfaceSupplier = startSurfaceSupplier; mHadWarmStart = hadWarmStart; + mLaunchOrigin = NewTabPageLaunchOrigin.UNKNOWN; if (mPropertyModel != null) { assert mSurfaceMode == SurfaceMode.SINGLE_PANE; @@ -354,7 +358,8 @@ // two different things, audit the wording usage and see if we can rename this method to // setStartSurfaceState. @Override - public void setOverviewState(@StartSurfaceState int state) { + public void setOverviewState( + @StartSurfaceState int state, @NewTabPageLaunchOrigin int launchOrigin) { // TODO(crbug.com/1039691): Refactor into state and trigger to separate SHOWING and SHOWN // states. @@ -413,6 +418,7 @@ } notifyStateChange(); + setLaunchOrigin(launchOrigin); // Metrics collection if (mStartSurfaceState == StartSurfaceState.SHOWN_HOMEPAGE) { RecordUserAction.record("StartSurface.SinglePane.Home"); @@ -421,6 +427,23 @@ } } + @Override + public void setOverviewState(@StartSurfaceState int state) { + setOverviewState(state, mLaunchOrigin); + } + + private void setLaunchOrigin(@NewTabPageLaunchOrigin int launchOrigin) { + if (mLaunchOrigin == launchOrigin) return; + mLaunchOrigin = launchOrigin; + // If the FeedSurfaceCoordinator is already initialized, set the TabId. + if (mPropertyModel == null) return; + FeedSurfaceCoordinator feedSurfaceCoordinator = + mPropertyModel.get(FEED_SURFACE_COORDINATOR); + if (feedSurfaceCoordinator != null) { + feedSurfaceCoordinator.setTabIdFromLaunchOrigin(mLaunchOrigin); + } + } + // TODO(crbug.com/1115757): After crrev.com/c/2315823, Overview state and Startsurface state are // two different things, audit the wording usage and see if we can rename this method to // setStartSurfaceStateInternal. @@ -506,7 +529,7 @@ mIsIncognito = mTabModelSelector.isIncognitoSelected(); mPropertyModel.set(IS_INCOGNITO, mIsIncognito); - // if OvervieModeState is NOT_SHOWN, default to SHOWING_TABSWITCHER. This should only + // if OverviewModeState is NOT_SHOWN, default to SHOWING_TABSWITCHER. This should only // happen when entering Start through SwipeDown gesture on URL bar. if (mStartSurfaceState == StartSurfaceState.NOT_SHOWN) { mStartSurfaceState = StartSurfaceState.SHOWING_TABSWITCHER; @@ -526,7 +549,8 @@ && mFeedSurfaceCreator != null) { mPropertyModel.set(FEED_SURFACE_COORDINATOR, mFeedSurfaceCreator.createFeedSurfaceCoordinator( - ColorUtils.inNightMode(mContext), shouldShowFeedPlaceholder())); + ColorUtils.inNightMode(mContext), shouldShowFeedPlaceholder(), + mLaunchOrigin)); } mTabModelSelector.addObserver(mTabModelSelectorObserver); @@ -706,7 +730,8 @@ && !mActivityStateChecker.isFinishingOrDestroyed()) { mPropertyModel.set(FEED_SURFACE_COORDINATOR, mFeedSurfaceCreator.createFeedSurfaceCoordinator( - ColorUtils.inNightMode(mContext), shouldShowFeedPlaceholder())); + ColorUtils.inNightMode(mContext), shouldShowFeedPlaceholder(), + mLaunchOrigin)); } mPropertyModel.set(IS_EXPLORE_SURFACE_VISIBLE, isVisible);
diff --git a/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/ExploreSurfaceViewBinderTest.java b/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/ExploreSurfaceViewBinderTest.java index 3938042..52f2424 100644 --- a/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/ExploreSurfaceViewBinderTest.java +++ b/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/ExploreSurfaceViewBinderTest.java
@@ -35,6 +35,7 @@ import org.chromium.base.test.util.Restriction; import org.chromium.chrome.browser.feed.FeedSurfaceCoordinator; import org.chromium.chrome.browser.flags.ChromeSwitches; +import org.chromium.chrome.browser.ntp.NewTabPageLaunchOrigin; import org.chromium.chrome.browser.ntp.ScrollableContainerDelegate; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.chrome.test.ChromeTabbedActivityTestRule; @@ -85,7 +86,7 @@ mActivityTestRule.getActivity().getTabModelSelector()); mFeedSurfaceCoordinator = mExploreSurfaceCoordinator.getFeedSurfaceCreator().createFeedSurfaceCoordinator( - false, /* isPlaceholderShown= */ false); + false, /* isPlaceholderShown= */ false, NewTabPageLaunchOrigin.UNKNOWN); mFeedSurfaceView = mFeedSurfaceCoordinator.getView(); }); }
diff --git a/chrome/android/features/start_surface/internal/junit/src/org/chromium/chrome/features/start_surface/StartSurfaceMediatorUnitTest.java b/chrome/android/features/start_surface/internal/junit/src/org/chromium/chrome/features/start_surface/StartSurfaceMediatorUnitTest.java index 41e2bf2..23e5c9a6 100644 --- a/chrome/android/features/start_surface/internal/junit/src/org/chromium/chrome/features/start_surface/StartSurfaceMediatorUnitTest.java +++ b/chrome/android/features/start_surface/internal/junit/src/org/chromium/chrome/features/start_surface/StartSurfaceMediatorUnitTest.java
@@ -11,6 +11,7 @@ import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNull; import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doReturn; @@ -1009,7 +1010,7 @@ mediator.setOverviewState(StartSurfaceState.SHOWING_HOMEPAGE); mPropertyModel.set(IS_EXPLORE_SURFACE_VISIBLE, true); - when(mFeedSurfaceCreator.createFeedSurfaceCoordinator(anyBoolean(), anyBoolean())) + when(mFeedSurfaceCreator.createFeedSurfaceCoordinator(anyBoolean(), anyBoolean(), anyInt())) .thenReturn(mFeedSurfaceCoordinator); mediator.showOverview(false); mainTabGridController.verify(mMainTabGridController).showOverview(eq(false)); @@ -1024,7 +1025,7 @@ FeedSurfaceCoordinator feedSurfaceCoordinator = mock(FeedSurfaceCoordinator.class); assertNotEquals(mFeedSurfaceCoordinator, feedSurfaceCoordinator); - when(mFeedSurfaceCreator.createFeedSurfaceCoordinator(anyBoolean(), anyBoolean())) + when(mFeedSurfaceCreator.createFeedSurfaceCoordinator(anyBoolean(), anyBoolean(), anyInt())) .thenReturn(feedSurfaceCoordinator); mediator.setOverviewState(StartSurfaceState.SHOWING_PREVIOUS); mediator.showOverview(false); @@ -1131,7 +1132,7 @@ mediator.setOverviewState(StartSurfaceState.SHOWING_HOMEPAGE); mPropertyModel.set(IS_EXPLORE_SURFACE_VISIBLE, true); - when(mFeedSurfaceCreator.createFeedSurfaceCoordinator(anyBoolean(), anyBoolean())) + when(mFeedSurfaceCreator.createFeedSurfaceCoordinator(anyBoolean(), anyBoolean(), anyInt())) .thenReturn(mFeedSurfaceCoordinator); mediator.showOverview(false); assertThat(mediator.getStartSurfaceState(), equalTo(StartSurfaceState.SHOWN_HOMEPAGE));
diff --git a/chrome/android/features/start_surface/public/java/src/org/chromium/chrome/features/start_surface/StartSurface.java b/chrome/android/features/start_surface/public/java/src/org/chromium/chrome/features/start_surface/StartSurface.java index be146be..daba099 100644 --- a/chrome/android/features/start_surface/public/java/src/org/chromium/chrome/features/start_surface/StartSurface.java +++ b/chrome/android/features/start_surface/public/java/src/org/chromium/chrome/features/start_surface/StartSurface.java
@@ -9,6 +9,7 @@ import com.google.android.material.appbar.AppBarLayout; import org.chromium.base.supplier.Supplier; +import org.chromium.chrome.browser.ntp.NewTabPageLaunchOrigin; import org.chromium.chrome.browser.tasks.tab_management.TabSwitcher; /** Interface to communicate with the start surface. */ @@ -140,8 +141,18 @@ void showOverview(boolean animate); /** - * Sets the state {@link StartSurfaceState}. - * @param state the {@link StartSurfaceState} to show. + * Sets the state {@link StartSurfaceState} and {@link NewTabPageLaunchOrigin}. + * @param state The {@link StartSurfaceState} to show. + * @param launchOrigin The {@link NewTabPageLaunchOrigin} representing what launched the + * start surface. + */ + void setOverviewState( + @StartSurfaceState int state, @NewTabPageLaunchOrigin int launchOrigin); + + /** + * Sets the state {@link StartSurfaceState} without changing the existing {@link + * NewTabPageLaunchOrigin}. + * @param state The {@link StartSurfaceState} to show. */ void setOverviewState(@StartSurfaceState int state);
diff --git a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedSurfaceCoordinator.java b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedSurfaceCoordinator.java index 6e0bfef..554a072 100644 --- a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedSurfaceCoordinator.java +++ b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedSurfaceCoordinator.java
@@ -20,6 +20,7 @@ import android.widget.FrameLayout; import android.widget.ScrollView; +import androidx.annotation.IntDef; import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; import androidx.recyclerview.widget.RecyclerView; @@ -38,6 +39,7 @@ import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.native_page.ContextMenuManager; import org.chromium.chrome.browser.native_page.NativePageNavigationDelegate; +import org.chromium.chrome.browser.ntp.NewTabPageLaunchOrigin; import org.chromium.chrome.browser.ntp.NewTabPageLayout; import org.chromium.chrome.browser.ntp.ScrollListener; import org.chromium.chrome.browser.ntp.ScrollableContainerDelegate; @@ -139,6 +141,12 @@ private @Nullable HeaderIphScrollListener mHeaderIphScrollListener; + @IntDef({StreamTabId.FOR_YOU, StreamTabId.FOLLOWING}) + public @interface StreamTabId { + int FOR_YOU = 0; + int FOLLOWING = 1; + }; + /** * Provides the additional capabilities needed for the container view. */ @@ -229,6 +237,7 @@ * @param isPlaceholderShownInitially Whether the placeholder is shown initially. * @param bottomSheetController The bottom sheet controller. * @param shareDelegateSupplier The supplier for the share delegate used to share articles. + * @param launchOrigin The origin of what launched the feed. */ public FeedSurfaceCoordinator(Activity activity, SnackbarManager snackbarManager, WindowAndroid windowAndroid, @Nullable SnapScrollHelper snapScrollHelper, @@ -238,7 +247,7 @@ boolean isPlaceholderShownInitially, BottomSheetController bottomSheetController, Supplier<ShareDelegate> shareDelegateSupplier, @Nullable ScrollableContainerDelegate externalScrollableContainerDelegate, - TabModelSelector tabModelSelector) { + TabModelSelector tabModelSelector, @NewTabPageLaunchOrigin int launchOrigin) { FeedSurfaceTracker.getInstance().initServiceBridge(); mActivity = activity; mSnackbarManager = snackbarManager; @@ -284,8 +293,9 @@ } // Mediator should be created before any Stream changes. - mMediator = new FeedSurfaceMediator( - this, mActivity, snapScrollHelper, mPageNavigationDelegate, mSectionHeaderModel); + mMediator = + new FeedSurfaceMediator(this, mActivity, snapScrollHelper, mPageNavigationDelegate, + mSectionHeaderModel, getTabIdFromLaunchOrigin(launchOrigin)); // Creates streams, initiates content changes. mMediator.updateContent(); FeedSurfaceTracker.getInstance().trackSurface(this); @@ -400,6 +410,23 @@ mMediator.restoreSavedInstanceState(state); } + /** Sets the {@link StreamTabId} of the feed given a {@link NewTabPageLaunchOrigin}. */ + public void setTabIdFromLaunchOrigin(@NewTabPageLaunchOrigin int launchOrigin) { + mMediator.setTabId(getTabIdFromLaunchOrigin(launchOrigin)); + } + + /** + * Gets the appropriate {@link StreamTabId} for the given {@link NewTabPageLaunchOrigin}. + * + * <p>If coming from a Web Feed button, open the following tab, otherwise open the for you tab. + */ + @VisibleForTesting + @StreamTabId + int getTabIdFromLaunchOrigin(@NewTabPageLaunchOrigin int launchOrigin) { + return launchOrigin == NewTabPageLaunchOrigin.WEB_FEED ? StreamTabId.FOLLOWING + : StreamTabId.FOR_YOU; + } + private RecyclerView setUpView() { mContentManager = new NtpListContentManager(); Context context = new ContextThemeWrapper(
diff --git a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedSurfaceMediator.java b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedSurfaceMediator.java index 5435c36..45c8c50 100644 --- a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedSurfaceMediator.java +++ b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedSurfaceMediator.java
@@ -38,6 +38,7 @@ import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.native_page.ContextMenuManager; import org.chromium.chrome.browser.native_page.NativePageNavigationDelegate; +import org.chromium.chrome.browser.ntp.NewTabPageLaunchOrigin; import org.chromium.chrome.browser.ntp.NewTabPageLayout; import org.chromium.chrome.browser.ntp.ScrollListener; import org.chromium.chrome.browser.ntp.SnapScrollHelper; @@ -262,17 +263,19 @@ * @param pageNavigationDelegate The {@link NativePageNavigationDelegate} that handles page * navigation. * @param headerModel The {@link PropertyModel} that contains this mediator should work with. + * @param openingTabId The {@link FeedSurfaceCoordinator.StreamTabId} the feed should open to. */ FeedSurfaceMediator(FeedSurfaceCoordinator coordinator, Context context, @Nullable SnapScrollHelper snapScrollHelper, @Nullable NativePageNavigationDelegate pageNavigationDelegate, - PropertyModel headerModel) { + PropertyModel headerModel, @FeedSurfaceCoordinator.StreamTabId int openingTabId) { mCoordinator = coordinator; mContext = context; mSnapScrollHelper = snapScrollHelper; mSigninManager = IdentityServicesProvider.get().getSigninManager( Profile.getLastUsedRegularProfile()); mPageNavigationDelegate = pageNavigationDelegate; + mRestoreTabId = openingTabId; if (sTestPrefChangeRegistar != null) { mPrefChangeRegistrar = sTestPrefChangeRegistar; @@ -385,6 +388,17 @@ } /** + * Sets the current tab to {@code tabId}. + * + * <p>Called when the the mediator is already initialized in Start Surface, but the feed is + * being shown again with a different {@link NewTabPageLaunchOrigin}. + */ + void setTabId(@FeedSurfaceCoordinator.StreamTabId int tabId) { + if (mTabToStreamMap.size() <= tabId) tabId = 0; + mSectionHeaderModel.set(SectionHeaderListProperties.CURRENT_TAB_INDEX_KEY, tabId); + } + + /** * Initialize properties for UI components in the {@link NewTabPage}. * TODO(huayinz): Introduce a Model for these properties. */
diff --git a/chrome/android/java/res/layout/long_screenshots_area_selection_dialog.xml b/chrome/android/java/res/layout/long_screenshots_area_selection_dialog.xml index b1a03d3..bd8cae259 100644 --- a/chrome/android/java/res/layout/long_screenshots_area_selection_dialog.xml +++ b/chrome/android/java/res/layout/long_screenshots_area_selection_dialog.xml
@@ -31,14 +31,13 @@ style="@style/ToolbarButton" /> <TextView - android:id="@+id/qrcode_camera_error_text" + android:id="@+id/sharing_long_screenshot_dialog_title" android:layout_width="fill_parent" android:layout_height="wrap_content" android:gravity="center_horizontal" android:layout_gravity="center_horizontal" android:text="@string/sharing_long_screenshot" - android:textAppearance="@style/TextAppearance.TextLarge.Primary" /> - + android:textAppearance="@style/TextAppearance.TextSmall.Primary.Light" /> <org.chromium.ui.widget.ChromeImageButton android:id="@+id/done_button" android:contentDescription="@string/close" @@ -59,10 +58,22 @@ android:layout_height="1dp" android:layout_width="match_parent"/> + <TextView + android:id="@+id/sharing_long_screenshot_dialog_instructions" + android:background="@color/default_scrim_color" + android:layout_above="@id/divider" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:paddingBottom="6dp" + android:gravity="center_horizontal" + android:layout_gravity="center_horizontal" + android:text="@string/sharing_long_screenshot_instructions" + android:textAppearance="@style/TextAppearance.TextSmall.Primary.Light" /> + <FrameLayout android:id="@+id/bitmap_container" - android:background="@color/black_alpha_65" - android:layout_above="@id/divider" + android:background="@color/default_scrim_color" + android:layout_above="@id/sharing_long_screenshot_dialog_instructions" android:layout_alignParentTop="true" android:layout_width="match_parent" android:layout_height="0dp">
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 a3da89d5..24fcb9f 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
@@ -116,7 +116,9 @@ import org.chromium.chrome.browser.native_page.NativePageAssassin; import org.chromium.chrome.browser.navigation_predictor.NavigationPredictorBridge; import org.chromium.chrome.browser.night_mode.WebContentsDarkModeController; +import org.chromium.chrome.browser.ntp.NewTabPageLaunchOrigin; import org.chromium.chrome.browser.ntp.NewTabPageUma; +import org.chromium.chrome.browser.ntp.NewTabPageUtils; import org.chromium.chrome.browser.omnibox.OmniboxFocusReason; import org.chromium.chrome.browser.paint_preview.StartupPaintPreviewHelper; import org.chromium.chrome.browser.paint_preview.StartupPaintPreviewHelperSupplier; @@ -651,8 +653,9 @@ getTabModelSelector(), getBrowserControlsManager(), getSnackbarManager(), getShareDelegateSupplier(), getToolbarManager()::getOmniboxStub, getTabContentManager(), - getModalDialogManager(), /* chromeActivityNativeDelegate= */ this, - getLifecycleDispatcher(), getTabCreatorManagerSupplier().get(), + getModalDialogManager(), + /* chromeActivityNativeDelegate= */ this, getLifecycleDispatcher(), + getTabCreatorManagerSupplier().get(), getMenuOrKeyboardActionController(), getMultiWindowModeStateDispatcher()); } @@ -1778,7 +1781,10 @@ getWindow().getDecorView(), this, mOverviewModeBehaviorSupplier, mBookmarkBridgeSupplier, () - -> getTabCreator(/*incognito=*/false).launchNTP(), + -> getTabCreator(/*incognito=*/false) + .launchUrl(NewTabPageUtils.encodeNtpUrl( + NewTabPageLaunchOrigin.WEB_FEED), + TabLaunchType.FROM_CHROME_UI), getModalDialogManager(), getSnackbarManager(), new WebFeedBridge()); } @@ -1804,10 +1810,10 @@ if (StartSurfaceConfiguration.isStartSurfaceEnabled()) { overviewNTPCreator = new ChromeTabCreator.OverviewNTPCreator() { @Override - public boolean handleCreateNTPIfNeeded( - boolean isNTP, boolean incognito, Tab parentTab) { + public boolean handleCreateNTPIfNeeded(boolean isNTP, boolean incognito, + Tab parentTab, @NewTabPageLaunchOrigin int launchOrigin) { boolean shouldShowStart = - showStartSurfaceHomeForNTP(isNTP, incognito, parentTab); + showStartSurfaceHomeForNTP(isNTP, incognito, parentTab, launchOrigin); if (shouldShowStart) { mStartSurfaceParentTabSupplier.set(parentTab); } @@ -2237,10 +2243,15 @@ } } + private void showOverview(@StartSurfaceState int state) { + showOverview(state, NewTabPageLaunchOrigin.UNKNOWN); + } + // TODO(crbug.com/1115757): After crrev.com/c/2315823, Overview state and Startsurface state are // two different things, we actual can split this into two methods: showOverview() and // showStartSurface(state). Let's do some auditing and clean up before perform the actual split. - private void showOverview(@StartSurfaceState int state) { + private void showOverview( + @StartSurfaceState int state, @NewTabPageLaunchOrigin int launchOrigin) { assert (state == StartSurfaceState.SHOWING_TABSWITCHER || state == StartSurfaceState.SHOWING_HOMEPAGE || state == StartSurfaceState.SHOWING_PREVIOUS @@ -2256,7 +2267,7 @@ if (StartSurfaceConfiguration.shouldHideStartSurfaceWithAccessibilityOn()) { state = StartSurfaceState.SHOWING_TABSWITCHER; } - mStartSurfaceSupplier.get().getController().setOverviewState(state); + mStartSurfaceSupplier.get().getController().setOverviewState(state, launchOrigin); } if (mOverviewModeController == null) return; @@ -2294,7 +2305,8 @@ * surface, or open a new tab with the omnibox get focused, depending on the value of * {@link StartSurfaceConfiguration.OMNIBOX_FOCUSED_ON_NEW_TAB}. */ - private boolean showStartSurfaceHomeForNTP(boolean isNTP, boolean incognito, Tab parentTab) { + private boolean showStartSurfaceHomeForNTP(boolean isNTP, boolean incognito, Tab parentTab, + @NewTabPageLaunchOrigin int launchOrigin) { if (!isNTP || !ReturnToChromeExperimentsUtil.shouldShowStartSurfaceHomeAsNTP( incognito, isTablet())) { @@ -2304,14 +2316,14 @@ getTabModelSelector().selectModel(incognito); if (StartSurfaceConfiguration.OMNIBOX_FOCUSED_ON_NEW_TAB.getValue()) { Runnable emptyTabCloseCallback = isInOverviewMode() ? () -> { - showOverview(StartSurfaceState.SHOWING_PREVIOUS); + showOverview(StartSurfaceState.SHOWING_PREVIOUS, launchOrigin); } : null; ReturnToChromeExperimentsUtil.handleLoadUrlFromStartSurfaceAsNewTab(null, PageTransition.AUTO_TOPLEVEL, incognito, parentTab, getCurrentTabModel(), emptyTabCloseCallback); } else if (TabUiFeatureUtilities.supportInstantStart(isTablet()) || (getTabModelSelector().isTabStateInitialized() && isLayoutManagerCreated())) { - showOverview(StartSurfaceState.SHOWING_HOMEPAGE); + showOverview(StartSurfaceState.SHOWING_HOMEPAGE, launchOrigin); } return true; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/app/appmenu/AppMenuPropertiesDelegateImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/app/appmenu/AppMenuPropertiesDelegateImpl.java index da2ed94..3b3472f 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/app/appmenu/AppMenuPropertiesDelegateImpl.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/app/appmenu/AppMenuPropertiesDelegateImpl.java
@@ -300,10 +300,10 @@ UpdateMenuItemHelper.getInstance().registerObserver(mAppMenuInvalidator); } - boolean shouldShowMoveToOtherWindow = shouldShowMoveToOtherWindow(); - menu.findItem(R.id.new_window_menu_id) - .setVisible(shouldShowNewWindow(shouldShowMoveToOtherWindow)); - menu.findItem(R.id.move_to_other_window_menu_id).setVisible(shouldShowMoveToOtherWindow); + boolean showNewWindow = shouldShowNewWindow(); + boolean showMoveToOtherWindow = !showNewWindow && shouldShowMoveToOtherWindow(); + menu.findItem(R.id.new_window_menu_id).setVisible(showNewWindow); + menu.findItem(R.id.move_to_other_window_menu_id).setVisible(showMoveToOtherWindow); // Don't allow either "chrome://" pages or interstitial pages to be shared. menu.findItem(R.id.share_row_menu_id).setVisible(mShareUtils.shouldEnableShare(currentTab)); @@ -499,9 +499,9 @@ /** * @return Whether the "New window" menu item should be displayed. */ - protected boolean shouldShowNewWindow(boolean showMoveToOtherWindow) { - if (!isNewWindowMenuFeatureEnabled()) return false; - if (showMoveToOtherWindow || !isTabletSizeScreen()) return false; + protected boolean shouldShowNewWindow() { + if (!isNewWindowMenuFeatureEnabled() || !isTabletSizeScreen()) return false; + if (mMultiWindowModeStateDispatcher.isMultiInstanceRunning()) return false; return mMultiWindowModeStateDispatcher.canEnterMultiWindowMode() || mMultiWindowModeStateDispatcher.isInMultiWindowMode() || mMultiWindowModeStateDispatcher.isInMultiDisplayMode();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill/SaveAddressProfilePrompt.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill/SaveAddressProfilePrompt.java index 449b640a..543afcd 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/autofill/SaveAddressProfilePrompt.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill/SaveAddressProfilePrompt.java
@@ -39,6 +39,7 @@ private final View mDialogView; private final EditorDialog mEditorDialog; private final AddressEditor mAddressEditor; + private boolean mEditorClosingPending; /** * Save prompt to confirm saving an address profile imported from a form submission. @@ -66,6 +67,7 @@ mDialogModel = builder.build(); mEditorDialog = new EditorDialog(activity, /*deleteRunnable=*/null, browserProfile); + mEditorDialog.setShouldTriggerDoneCallbackBeforeCloseAnimation(true); mAddressEditor = new AddressEditor(AddressEditor.Purpose.AUTOFILL_SETTINGS, /*saveToDisk=*/false); mAddressEditor.setEditorDialog(mEditorDialog); @@ -159,11 +161,13 @@ */ @CalledByNative private void dismiss() { - if (mEditorDialog.isShowing()) mEditorDialog.dismiss(); + // Do not dismiss the editor if closing is pending to not abort the animation. + if (!mEditorClosingPending && mEditorDialog.isShowing()) mEditorDialog.dismiss(); mModalDialogManager.dismissDialog(mDialogModel, DialogDismissalCause.DISMISSED_BY_NATIVE); } private void onEdited(AutofillAddress autofillAddress) { + mEditorClosingPending = true; mController.onUserEdited(autofillAddress.getProfile()); mModalDialogManager.dismissDialog(mDialogModel, DialogDismissalCause.ACTION_ON_CONTENT); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill/prefeditor/EditorDialog.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill/prefeditor/EditorDialog.java index 3e78979a..e72c5bc 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/autofill/prefeditor/EditorDialog.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill/prefeditor/EditorDialog.java
@@ -91,6 +91,7 @@ private EditorModel mEditorModel; private Button mDoneButton; private boolean mFormWasValid; + private boolean mShouldTriggerDoneCallbackBeforeCloseAnimation; private ViewGroup mDataView; private View mFooter; @Nullable @@ -172,6 +173,15 @@ } /** + * @param shouldTrigger If true, done callback is triggered immediately after the user clicked + * on the done button. Otherwise, by default, it is triggered only after the dialog is + * dismissed with animation. + */ + public void setShouldTriggerDoneCallbackBeforeCloseAnimation(boolean shouldTrigger) { + mShouldTriggerDoneCallbackBeforeCloseAnimation = shouldTrigger; + } + + /** * Prepares the toolbar for use. * * Many of the things that would ideally be set as attributes don't work and need to be set @@ -281,6 +291,10 @@ if (view.getId() == R.id.editor_dialog_done_button) { if (validateForm()) { + if (mShouldTriggerDoneCallbackBeforeCloseAnimation && mEditorModel != null) { + mEditorModel.done(); + mEditorModel = null; + } mFormWasValid = true; animateOutDialog(); return;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dagger.md b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dagger.md index 1db2f573..ca19c96b 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dagger.md +++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dagger.md
@@ -116,10 +116,10 @@ Hopefully that should be enough to help you make changes to Custom Tabs code. If you need to do something more complicated, feel free to reach out to peconn@, either by email or by adding me on your code review. -[1]: https://source.chromium.org/chromium/chromium/src/+/master:chrome/android/java/src/org/chromium/chrome/browser/customtabs/dependency_injection/BaseCustomTabActivityModule.java -[2]: https://source.chromium.org/chromium/chromium/src/+/master:chrome/android/java/src/org/chromium/chrome/browser/dependency_injection/ChromeActivityCommonsModule.java -[3]: https://source.chromium.org/chromium/chromium/src/+/master:chrome/android/java/src/org/chromium/chrome/browser/dependency_injection/ChromeAppModule.java -[4]: https://source.chromium.org/chromium/chromium/src/+/master:chrome/android/java/src/org/chromium/chrome/browser/dependency_injection/ChromeAppComponent.java -[5]: https://source.chromium.org/chromium/chromium/src/+/master:chrome/android/java/src/org/chromium/chrome/browser/customtabs/dependency_injection/BaseCustomTabActivityComponent.java -[6]: https://source.chromium.org/chromium/chromium/src/+/master:chrome/android/javatests/src/org/chromium/chrome/browser/dependency_injection/ModuleOverridesRule.java -[7]: https://source.chromium.org/chromium/chromium/src/+/master:chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/RunningInChromeTest.java +[1]: https://source.chromium.org/chromium/chromium/src/+/main:chrome/android/java/src/org/chromium/chrome/browser/customtabs/dependency_injection/BaseCustomTabActivityModule.java +[2]: https://source.chromium.org/chromium/chromium/src/+/main:chrome/android/java/src/org/chromium/chrome/browser/dependency_injection/ChromeActivityCommonsModule.java +[3]: https://source.chromium.org/chromium/chromium/src/+/main:chrome/android/java/src/org/chromium/chrome/browser/dependency_injection/ChromeAppModule.java +[4]: https://source.chromium.org/chromium/chromium/src/+/main:chrome/android/java/src/org/chromium/chrome/browser/dependency_injection/ChromeAppComponent.java +[5]: https://source.chromium.org/chromium/chromium/src/+/main:chrome/android/java/src/org/chromium/chrome/browser/customtabs/dependency_injection/BaseCustomTabActivityComponent.java +[6]: https://source.chromium.org/chromium/chromium/src/+/main:chrome/android/javatests/src/org/chromium/chrome/browser/dependency_injection/ModuleOverridesRule.java +[7]: https://source.chromium.org/chromium/chromium/src/+/main:chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/RunningInChromeTest.java
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 af4f4f8..2f89ed0 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
@@ -31,12 +31,9 @@ import org.chromium.chrome.browser.ChromeTabbedActivity; import org.chromium.chrome.browser.ChromeTabbedActivity2; import org.chromium.chrome.browser.IntentHandler; -import org.chromium.chrome.browser.flags.CachedFeatureFlags; -import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.util.AndroidTaskUtils; import org.chromium.components.ukm.UkmRecorder; -import org.chromium.ui.base.DeviceFormFactor; import org.chromium.ui.display.DisplayAndroidManager; import java.lang.annotation.Retention; @@ -120,10 +117,7 @@ public boolean isOpenInOtherWindowSupported(Activity activity) { if (!isInMultiWindowMode(activity) && !isInMultiDisplayMode(activity)) return false; - // Supported only in multi-window mode and if activity supports side-by-side instances. - return (!CachedFeatureFlags.isEnabled(ChromeFeatureList.NEW_WINDOW_APP_MENU) - || !isTabletScreen(activity) || areMultipleChromeInstancesRunning(activity)) - && getOpenInOtherWindowActivity(activity) != null; + return getOpenInOtherWindowActivity(activity) != null; } /** @@ -132,7 +126,6 @@ * @return {@code True} if Chrome can get itself into multi-window mode. */ public boolean canEnterMultiWindowMode(Activity activity) { - if (areMultipleChromeInstancesRunning(activity)) return false; return isBuildAtLeastS() || customMultiWindowModeSupported(); } @@ -147,11 +140,6 @@ && Build.MANUFACTURER.toUpperCase(Locale.ENGLISH).equals("SAMSUNG"); } - @VisibleForTesting - boolean isTabletScreen(Context context) { - return DeviceFormFactor.isNonMultiDisplayContextOnTablet(context); - } - /** * Returns the activity to use when handling "open in other window" or "move to other window". * Returns null if the current activity doesn't support opening/moving tabs to another activity.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/native_page/NativePageFactory.java b/chrome/android/java/src/org/chromium/chrome/browser/native_page/NativePageFactory.java index cd421f5..63ec1673 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/native_page/NativePageFactory.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/native_page/NativePageFactory.java
@@ -86,7 +86,7 @@ mBottomSheetController = sheetController; } - protected NativePage buildNewTabPage(Tab tab) { + protected NativePage buildNewTabPage(Tab tab, String url) { NativePageHost nativePageHost = new TabShim(tab, mActivity); if (tab.isIncognito()) return new IncognitoNewTabPage(mActivity, nativePageHost); @@ -94,7 +94,7 @@ mActivity.getActivityTabProvider(), mActivity.getSnackbarManager(), mActivity.getLifecycleDispatcher(), mActivity.getTabModelSelector(), mActivity.isTablet(), mUma.get(), ColorUtils.inNightMode(mActivity), - nativePageHost, tab, mBottomSheetController, + nativePageHost, tab, url, mBottomSheetController, mActivity.getShareDelegateSupplier(), mActivity.getWindowAndroid()); } @@ -173,7 +173,7 @@ page = candidatePage; break; case NativePageType.NTP: - page = getBuilder().buildNewTabPage(tab); + page = getBuilder().buildNewTabPage(tab, url); break; case NativePageType.BOOKMARKS: page = getBuilder().buildBookmarksPage(tab);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/native_page/NativePageNavigationDelegateImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/native_page/NativePageNavigationDelegateImpl.java index 44ff287..22e277e2 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/native_page/NativePageNavigationDelegateImpl.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/native_page/NativePageNavigationDelegateImpl.java
@@ -44,7 +44,8 @@ @Override public boolean isOpenInNewWindowEnabled() { - return MultiWindowUtils.getInstance().isOpenInOtherWindowSupported(mActivity); + return MultiWindowUtils.getInstance().isOpenInOtherWindowSupported(mActivity) + || MultiWindowUtils.getInstance().canEnterMultiWindowMode(mActivity); } @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage.java index 843afe67..7500716b 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage.java
@@ -283,7 +283,7 @@ * @param browserControlsStateProvider {@link BrowserControlsStateProvider} to observe for * offset changes. * @param activityTabProvider Provides the current active tab. - * @param snackbarManager {@link SnackBarManager} object. + * @param snackbarManager {@link SnackbarManager} object. * @param lifecycleDispatcher Activity lifecycle dispatcher. * @param tabModelSelector {@link TabModelSelector} object. * @param isTablet {@code true} if running on a Tablet device. @@ -291,6 +291,7 @@ * @param isInNightMode {@code true} if the night mode setting is on. * @param nativePageHost The host that is showing this new tab page. * @param tab The {@link Tab} that contains this new tab page. + * @param url The URL that launched this new tab page. * @param bottomSheetController The controller for bottom sheets, used by the feed. * @param shareDelegateSupplier Supplies the Delegate used to open SharingHub. * @param windowAndroid @@ -299,7 +300,8 @@ Supplier<Tab> activityTabProvider, SnackbarManager snackbarManager, ActivityLifecycleDispatcher lifecycleDispatcher, TabModelSelector tabModelSelector, boolean isTablet, NewTabPageUma uma, boolean isInNightMode, - NativePageHost nativePageHost, Tab tab, BottomSheetController bottomSheetController, + NativePageHost nativePageHost, Tab tab, String url, + BottomSheetController bottomSheetController, ObservableSupplier<ShareDelegate> shareDelegateSupplier, WindowAndroid windowAndroid) { mConstructedTimeNs = System.nanoTime(); TraceEvent.begin(TAG); @@ -362,7 +364,7 @@ updateSearchProviderHasLogo(); initializeMainView(activity, windowAndroid, snackbarManager, uma, isInNightMode, - bottomSheetController, shareDelegateSupplier, tabModelSelector); + bottomSheetController, shareDelegateSupplier, tabModelSelector, url); mBrowserControlsStateProvider = browserControlsStateProvider; getView().addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() { @@ -416,7 +418,7 @@ SnackbarManager snackbarManager, NewTabPageUma uma, boolean isInNightMode, BottomSheetController bottomSheetController, ObservableSupplier<ShareDelegate> shareDelegateSupplier, - TabModelSelector tabModelSelector) { + TabModelSelector tabModelSelector, String url) { Profile profile = Profile.fromWebContents(mTab.getWebContents()); LayoutInflater inflater = LayoutInflater.from(activity); @@ -437,7 +439,7 @@ profile, /* isPlaceholderShownInitially= */ false, bottomSheetController, shareDelegateSupplier, /* externalScrollableContainerDelegate= */ null, - tabModelSelector); + tabModelSelector, NewTabPageUtils.decodeOriginFromNtpUrl(url)); // Record the timestamp at which the new tab page's construction started. uma.trackTimeToFirstDraw(mFeedSurfaceProvider.getView(), mConstructedTimeNs);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageLaunchOrigin.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageLaunchOrigin.java new file mode 100644 index 0000000..86340b13 --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageLaunchOrigin.java
@@ -0,0 +1,23 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.ntp; + +import androidx.annotation.IntDef; + +/** + * Indicates where a new tab was launched from. + */ +@IntDef({NewTabPageLaunchOrigin.UNKNOWN, NewTabPageLaunchOrigin.WEB_FEED}) +public @interface NewTabPageLaunchOrigin { + /** + * Unknown launch origin. Used as the default. + */ + int UNKNOWN = 0; + + /** + * Opened from the Web Feed go to feed option. Includes post-follow snackbar and dialog. + */ + int WEB_FEED = 1; +}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageUtils.java new file mode 100644 index 0000000..97aeabc --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPageUtils.java
@@ -0,0 +1,50 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.ntp; + +import android.net.Uri; + +import org.chromium.components.embedder_support.util.UrlConstants; +import org.chromium.components.embedder_support.util.UrlUtilities; + +/** + * Collection of util methods for help launching a NewTabPage. + */ +public class NewTabPageUtils { + private static final String ORIGIN_PARAMETER_KEY = "origin"; + private static final String WEB_FEED_PARAMETER = "web-feed"; + + /** + * @return The NTP url encoded with {@link NewTabPageLaunchOrigin} information. + */ + public static String encodeNtpUrl(@NewTabPageLaunchOrigin int launchOrigin) { + Uri.Builder uriBuilder = Uri.parse(UrlConstants.NTP_URL).buildUpon(); + switch (launchOrigin) { + case NewTabPageLaunchOrigin.WEB_FEED: + uriBuilder.appendQueryParameter(ORIGIN_PARAMETER_KEY, WEB_FEED_PARAMETER); + break; + case NewTabPageLaunchOrigin.UNKNOWN: + default: + break; + } + return uriBuilder.build().toString(); + } + + /** + * @return The {@link NewTabPageLaunchOrigin} decoded from the NTP url. + */ + @NewTabPageLaunchOrigin + public static int decodeOriginFromNtpUrl(String url) { + if (!UrlUtilities.isNTPUrl(url)) { + return NewTabPageLaunchOrigin.UNKNOWN; + } + Uri uri = Uri.parse(url); + String origin = uri.getQueryParameter(ORIGIN_PARAMETER_KEY); + if (origin != null && origin.equals(WEB_FEED_PARAMETER)) { + return NewTabPageLaunchOrigin.WEB_FEED; + } + return NewTabPageLaunchOrigin.UNKNOWN; + } +}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedRootUiCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedRootUiCoordinator.java index ee025118..59158c33 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedRootUiCoordinator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedRootUiCoordinator.java
@@ -52,6 +52,8 @@ import org.chromium.chrome.browser.merchant_viewer.MerchantTrustMetrics; import org.chromium.chrome.browser.merchant_viewer.MerchantTrustSignalsCoordinator; import org.chromium.chrome.browser.multiwindow.MultiWindowUtils; +import org.chromium.chrome.browser.ntp.NewTabPageLaunchOrigin; +import org.chromium.chrome.browser.ntp.NewTabPageUtils; import org.chromium.chrome.browser.offlinepages.indicator.OfflineIndicatorControllerV2; import org.chromium.chrome.browser.offlinepages.indicator.OfflineIndicatorInProductHelpController; import org.chromium.chrome.browser.omnibox.UrlFocusChangeListener; @@ -67,6 +69,7 @@ import org.chromium.chrome.browser.subscriptions.CommerceSubscriptionsServiceFactory; import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tab.TabAssociatedApp; +import org.chromium.chrome.browser.tab.TabLaunchType; import org.chromium.chrome.browser.tabmodel.TabModelSelector; import org.chromium.chrome.browser.tasks.tab_management.TabUiFeatureUtilities; import org.chromium.chrome.browser.toolbar.ToolbarButtonInProductHelpController; @@ -476,7 +479,10 @@ mAppMenuCoordinator.getAppMenuHandler(), mTabSupplier, mToolbarManager.getMenuButtonView(), () - -> mActivity.getTabCreator(/*incognito=*/false).launchNTP(), + -> mActivity.getTabCreator(/*incognito=*/false) + .launchUrl(NewTabPageUtils.encodeNtpUrl( + NewTabPageLaunchOrigin.WEB_FEED), + TabLaunchType.FROM_CHROME_UI), mActivity.getModalDialogManager(), mActivity.getSnackbarManager(), new WebFeedBridge()); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/ChromeTabCreator.java b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/ChromeTabCreator.java index afde54f..5b11436 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/ChromeTabCreator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/ChromeTabCreator.java
@@ -22,6 +22,8 @@ import org.chromium.chrome.browser.app.tab_activity_glue.ReparentingTask; import org.chromium.chrome.browser.compositor.CompositorViewHolder; import org.chromium.chrome.browser.init.StartupTabPreloader; +import org.chromium.chrome.browser.ntp.NewTabPageLaunchOrigin; +import org.chromium.chrome.browser.ntp.NewTabPageUtils; import org.chromium.chrome.browser.tab.RedirectHandlerTabHelper; import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tab.TabAssociatedApp; @@ -54,9 +56,11 @@ * @param isNTP Whether tab with NTP should be created. * @param isIncognito Whether tab is created in incognito. * @param parentTab The parent tab of the tab creation. + * @param launchOrigin The {@link NewTabPageLaunchOrigin} that launched the NTP. * @return Whether NTP creation was handled. */ - boolean handleCreateNTPIfNeeded(boolean isNTP, boolean isIncognito, Tab parentTab); + boolean handleCreateNTPIfNeeded(boolean isNTP, boolean isIncognito, Tab parentTab, + @NewTabPageLaunchOrigin int launchOrigin); /** * Called before the Tab's initialization. @@ -147,7 +151,8 @@ int position, Intent intent) { if (mOverviewNTPCreator != null && mOverviewNTPCreator.handleCreateNTPIfNeeded( - UrlUtilities.isNTPUrl(loadUrlParams.getUrl()), mIncognito, parent)) { + UrlUtilities.isNTPUrl(loadUrlParams.getUrl()), mIncognito, parent, + NewTabPageUtils.decodeOriginFromNtpUrl(loadUrlParams.getUrl()))) { return null; } try {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/display_cutout/WebappDisplayCutoutTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/display_cutout/WebappDisplayCutoutTest.java index 0c3d684..216e13f 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/display_cutout/WebappDisplayCutoutTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/display_cutout/WebappDisplayCutoutTest.java
@@ -14,6 +14,7 @@ import org.junit.runner.RunWith; import org.chromium.base.test.util.CommandLineFlags; +import org.chromium.base.test.util.DisabledTest; import org.chromium.base.test.util.MinAndroidSdkLevel; import org.chromium.chrome.browser.browserservices.intents.WebDisplayMode; import org.chromium.chrome.browser.flags.ChromeSwitches; @@ -51,6 +52,7 @@ @Test @LargeTest @WebappDisplayCutoutTestRule.TestConfiguration(displayMode = WebDisplayMode.FULLSCREEN) + @DisabledTest(message = "Flaky test - see: https://crbug.com/1211064") public void testViewportFitWebapp_Fullscreen() throws TimeoutException { mTestRule.setViewportFit(DisplayCutoutTestRule.VIEWPORT_FIT_COVER);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/README.md b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/README.md index 5f219d0..4c86854e 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/README.md +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/README.md
@@ -16,7 +16,7 @@ If you are reproducing an issue with the AR tests, run `export DOWNLOAD_VR_TEST_APKS=1 && gclient runhooks` in order to get the playback datasets that are necessary. This requires authentication, run -`gsutil.py config` [documentation](https://chromium.googlesource.com/chromiumos/docs/+/master/gsutil.md) +`gsutil.py config` [documentation](https://chromium.googlesource.com/chromiumos/docs/+/main/gsutil.md) to set this up if necessary. **NOTE** The message "Main Unable to find package info for org.chromium.chrome" @@ -186,10 +186,10 @@ [webxr_spec]: https://immersive-web.github.io/webxr-samples/explainer.html [shared_prefs_dir]: -https://chromium.googlesource.com/chromium/src/+/master/chrome/android/shared_preference_files/test -[html_dir]: https://chromium.googlesource.com/chromium/src/+/master/chrome/test/data/xr/e2e_test_files -[vr_test_apks]: https://chromium.googlesource.com/chromium/src/+/master/third_party/gvr-android-sdk/test-apks -[vr_test_libraries]: https://chromium.googlesource.com/chromium/src/+/master/third_party/gvr-android-sdk/test-libraries -[ar_test_apks]: https://chromium.googlesource.com/chromium/src/+/master/third_party/arcore-android-sdk/test-apks +https://chromium.googlesource.com/chromium/src/+/main/chrome/android/shared_preference_files/test +[html_dir]: https://chromium.googlesource.com/chromium/src/+/main/chrome/test/data/xr/e2e_test_files +[vr_test_apks]: https://chromium.googlesource.com/chromium/src/+/main/third_party/gvr-android-sdk/test-apks +[vr_test_libraries]: https://chromium.googlesource.com/chromium/src/+/main/third_party/gvr-android-sdk/test-libraries +[ar_test_apks]: https://chromium.googlesource.com/chromium/src/+/main/third_party/arcore-android-sdk/test-apks [adding_new_tests]: -https://chromium.googlesource.com/chromium/src/+/master/chrome/android/javatests/src/org/chromium/chrome/browser/vr/adding_new_tests.md +https://chromium.googlesource.com/chromium/src/+/main/chrome/android/javatests/src/org/chromium/chrome/browser/vr/adding_new_tests.md
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/adding_new_tests.md b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/adding_new_tests.md index 0a11207..6ecf1f1 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/adding_new_tests.md +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/adding_new_tests.md
@@ -162,8 +162,8 @@ bucket. -[xr_instrumentation_deep_dive]: https://chromium.googlesource.com/chromium/src/+/master/chrome/android/javatests/src/org/chromium/chrome/browser/vr/xr_instrumentation_deep_dive.md -[webxr_vr_transition_test]: https://chromium.googlesource.com/chromium/src/+/master/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrVrTransitionTest.java -[webxr_vr_transition_test_html]: https://chromium.googlesource.com/chromium/src/+/master/chrome/test/data/xr/e2e_test_files/html/test_non_immersive_stops_during_immersive.html -[vr_browser_transition_test]: https://chromium.googlesource.com/chromium/src/+/master/chrome/android/javatests/src/org/chromium/chrome/browser/vr/VrBrowserTransitionTest.java -[build_gn]: https://chromium.googlesource.com/chromium/src/+/master/chrome/android/BUILD.gn +[xr_instrumentation_deep_dive]: https://chromium.googlesource.com/chromium/src/+/main/chrome/android/javatests/src/org/chromium/chrome/browser/vr/xr_instrumentation_deep_dive.md +[webxr_vr_transition_test]: https://chromium.googlesource.com/chromium/src/+/main/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrVrTransitionTest.java +[webxr_vr_transition_test_html]: https://chromium.googlesource.com/chromium/src/+/main/chrome/test/data/xr/e2e_test_files/html/test_non_immersive_stops_during_immersive.html +[vr_browser_transition_test]: https://chromium.googlesource.com/chromium/src/+/main/chrome/android/javatests/src/org/chromium/chrome/browser/vr/VrBrowserTransitionTest.java +[build_gn]: https://chromium.googlesource.com/chromium/src/+/main/chrome/android/BUILD.gn
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/xr_instrumentation_deep_dive.md b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/xr_instrumentation_deep_dive.md index 5c3543a..73cee38 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/xr_instrumentation_deep_dive.md +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/xr_instrumentation_deep_dive.md
@@ -177,8 +177,8 @@ both easier and less prone to breaking than specifying a position in space. -[readme]: https://chromium.googlesource.com/chromium/src/+/master/chrome/android/javatests/src/org/chromium/chrome/browser/vr/README.md -[adding_new_tests]: https://chromium.googlesource.com/chromium/src/+/master/chrome/android/javatests/src/org/chromium/chrome/browser/vr/adding_new_tests.md +[readme]: https://chromium.googlesource.com/chromium/src/+/main/chrome/android/javatests/src/org/chromium/chrome/browser/vr/README.md +[adding_new_tests]: https://chromium.googlesource.com/chromium/src/+/main/chrome/android/javatests/src/org/chromium/chrome/browser/vr/adding_new_tests.md [junit4_wiki_parameterization]: https://github.com/junit-team/junit4/wiki/parameterized-tests -[parameter_set_source]: https://chromium.googlesource.com/chromium/src/+/master/base/test/android/javatests/src/org/chromium/base/test/params/ParameterSet.java +[parameter_set_source]: https://chromium.googlesource.com/chromium/src/+/main/base/test/android/javatests/src/org/chromium/base/test/params/ParameterSet.java [junit4_wiki_rules]: https://github.com/junit-team/junit4/wiki/rules
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/feed/FeedSurfaceCoordinatorTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/feed/FeedSurfaceCoordinatorTest.java index 38d80fa..255e26dd3 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/feed/FeedSurfaceCoordinatorTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/feed/FeedSurfaceCoordinatorTest.java
@@ -42,6 +42,7 @@ import org.chromium.chrome.browser.feed.webfeed.WebFeedBridge; import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.native_page.NativePageNavigationDelegate; +import org.chromium.chrome.browser.ntp.NewTabPageLaunchOrigin; import org.chromium.chrome.browser.ntp.SnapScrollHelper; import org.chromium.chrome.browser.ntp.cards.SignInPromo; import org.chromium.chrome.browser.ntp.snippets.SectionHeaderListProperties; @@ -162,7 +163,7 @@ @Mock private IdentityManager mIdentityManager; @Mock - private PrefChangeRegistrar mPrefChangeRegistar; + private PrefChangeRegistrar mPrefChangeRegistrar; @Mock private PrefService mPrefService; @Mock @@ -192,7 +193,7 @@ SignInPromo.setDisablePromoForTests(true); // Preferences to enable feed. - FeedSurfaceMediator.setPrefForTest(mPrefChangeRegistar, mPrefService); + FeedSurfaceMediator.setPrefForTest(mPrefChangeRegistrar, mPrefService); FeedFeatures.setFakePrefsForTest(mPrefService); when(mPrefService.getBoolean(Pref.ENABLE_SNIPPETS)).thenReturn(true); when(mPrefService.getBoolean(Pref.ARTICLES_LIST_VISIBLE)).thenReturn(true); @@ -217,7 +218,7 @@ mCoordinator = new FeedSurfaceCoordinator(mActivity, mSnackbarManager, mWindowAndroid, mSnapHelper, null, mSectionHeaderView, false, new TestSurfaceDelegate(), mPageNavigationDelegate, mProfileMock, false, mBottomSheetController, - mShareDelegateSupplier, null, mTabModelSelector); + mShareDelegateSupplier, null, mTabModelSelector, NewTabPageLaunchOrigin.UNKNOWN); mLayoutManager = new FakeLinearLayoutManager(mActivity); mRecyclerView.setLayoutManager(mLayoutManager); @@ -281,4 +282,16 @@ assertEquals(true, mCoordinator.isActive()); assertEquals(false, ((FeedStream) mCoordinator.getStream()).getBoundStatusForTest()); } + + @Test + public void testGetTabIdFromLaunchOrigin_webFeed() { + assertEquals(FeedSurfaceCoordinator.StreamTabId.FOLLOWING, + mCoordinator.getTabIdFromLaunchOrigin(NewTabPageLaunchOrigin.WEB_FEED)); + } + + @Test + public void testGetTabIdFromLaunchOrigin_unknown() { + assertEquals(FeedSurfaceCoordinator.StreamTabId.FOR_YOU, + mCoordinator.getTabIdFromLaunchOrigin(NewTabPageLaunchOrigin.UNKNOWN)); + } }
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/feed/FeedSurfaceMediatorTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/feed/FeedSurfaceMediatorTest.java index 16b6a68..6956f9c 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/feed/FeedSurfaceMediatorTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/feed/FeedSurfaceMediatorTest.java
@@ -4,19 +4,131 @@ package org.chromium.chrome.browser.feed; -import org.junit.Assert; +import static junit.framework.Assert.assertEquals; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.Mockito.when; + +import android.app.Activity; + +import androidx.recyclerview.widget.RecyclerView; + +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TestRule; import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; +import org.robolectric.Robolectric; import org.robolectric.annotation.Config; +import org.chromium.base.supplier.ObservableSupplierImpl; import org.chromium.base.test.BaseRobolectricTestRunner; +import org.chromium.base.test.util.JniMocker; +import org.chromium.chrome.browser.feed.shared.FeedFeatures; +import org.chromium.chrome.browser.feed.v2.FeedStream; +import org.chromium.chrome.browser.feed.webfeed.WebFeedBridge; +import org.chromium.chrome.browser.flags.ChromeFeatureList; +import org.chromium.chrome.browser.native_page.NativePageNavigationDelegate; +import org.chromium.chrome.browser.ntp.cards.SignInPromo; +import org.chromium.chrome.browser.ntp.snippets.SectionHeaderListProperties; +import org.chromium.chrome.browser.preferences.Pref; +import org.chromium.chrome.browser.preferences.PrefChangeRegistrar; +import org.chromium.chrome.browser.profiles.Profile; +import org.chromium.chrome.browser.search_engines.TemplateUrlServiceFactory; +import org.chromium.chrome.browser.signin.services.IdentityServicesProvider; +import org.chromium.chrome.browser.signin.services.SigninManager; +import org.chromium.chrome.test.util.browser.Features; +import org.chromium.components.prefs.PrefService; +import org.chromium.components.search_engines.TemplateUrlService; +import org.chromium.components.signin.identitymanager.IdentityManager; +import org.chromium.ui.modelutil.PropertyModel; /** * Tests for {@link FeedSurfaceMediator}. */ @RunWith(BaseRobolectricTestRunner.class) @Config(manifest = Config.NONE) +@Features.EnableFeatures({ChromeFeatureList.WEB_FEED}) public class FeedSurfaceMediatorTest { + @Rule + public final MockitoRule mMockitoRule = MockitoJUnit.rule(); + @Rule + public TestRule mFeaturesProcessorRule = new Features.JUnitProcessor(); + @Rule + public JniMocker mocker = new JniMocker(); + + // Mocked JNI. + @Mock + private FeedServiceBridge.Natives mFeedServiceBridgeJniMock; + @Mock + private WebFeedBridge.Natives mWebFeedBridgeJniMock; + + @Mock + private FeedSurfaceCoordinator mFeedSurfaceCoordinator; + @Mock + private IdentityServicesProvider mIdentityService; + @Mock + private NativePageNavigationDelegate mPageNavigationDelegate; + @Mock + private PrefChangeRegistrar mPrefChangeRegistrar; + @Mock + private PrefService mPrefService; + @Mock + private Profile mProfileMock; + @Mock + private SigninManager mSigninManager; + @Mock + private IdentityManager mIdentityManager; + @Mock + private TemplateUrlService mUrlService; + @Mock + private FeedStream mStream; + + private Activity mActivity; + private FeedSurfaceMediator mFeedSurfaceMediator; + + @Before + public void setUp() { + mActivity = Robolectric.buildActivity(Activity.class).get(); + mocker.mock(FeedServiceBridgeJni.TEST_HOOKS, mFeedServiceBridgeJniMock); + mocker.mock(WebFeedBridge.getTestHooksForTesting(), mWebFeedBridgeJniMock); + + when(mPrefService.getBoolean(Pref.ENABLE_SNIPPETS)).thenReturn(true); + when(mPrefService.getBoolean(Pref.ENABLE_WEB_FEED_UI)).thenReturn(true); + when(mWebFeedBridgeJniMock.isWebFeedSubscriber()).thenReturn(true); + when(mIdentityService.getSigninManager(any(Profile.class))).thenReturn(mSigninManager); + when(mSigninManager.getIdentityManager()).thenReturn(mIdentityManager); + when(mFeedSurfaceCoordinator.getRecyclerView()).thenReturn(new RecyclerView(mActivity)); + when(mFeedSurfaceCoordinator.getStream()).thenReturn(null, mStream); + when(mFeedSurfaceCoordinator.createFeedStream(anyBoolean())).thenReturn(mStream); + ObservableSupplierImpl<Boolean> hasUnreadContent = new ObservableSupplierImpl<>(); + hasUnreadContent.set(false); + when(mStream.hasUnreadContent()).thenReturn(hasUnreadContent); + + FeedSurfaceMediator.setPrefForTest(mPrefChangeRegistrar, mPrefService); + FeedFeatures.setFakePrefsForTest(mPrefService); + Profile.setLastUsedProfileForTesting(mProfileMock); + IdentityServicesProvider.setInstanceForTests(mIdentityService); + TemplateUrlServiceFactory.setInstanceForTesting(mUrlService); + SignInPromo.setDisablePromoForTests(true); + } + + @After + public void tearDown() { + if (mFeedSurfaceMediator != null) mFeedSurfaceMediator.destroy(); + FeedSurfaceMediator.setPrefForTest(null, null); + FeedFeatures.setFakePrefsForTest(null); + Profile.setLastUsedProfileForTesting(null); + IdentityServicesProvider.setInstanceForTests(null); + TemplateUrlServiceFactory.setInstanceForTesting(null); + SignInPromo.setDisablePromoForTests(false); + } + @Test public void testSerializeScrollState() { FeedSurfaceMediator.ScrollState state = new FeedSurfaceMediator.ScrollState(); @@ -28,15 +140,39 @@ FeedSurfaceMediator.ScrollState deserializedState = FeedSurfaceMediator.ScrollState.fromJson(state.toJson()); - Assert.assertEquals(2, deserializedState.position); - Assert.assertEquals(4, deserializedState.lastPosition); - Assert.assertEquals(50, deserializedState.offset); - Assert.assertEquals(5, deserializedState.tabId); - Assert.assertEquals(state.toJson(), deserializedState.toJson()); + assertEquals(2, deserializedState.position); + assertEquals(4, deserializedState.lastPosition); + assertEquals(50, deserializedState.offset); + assertEquals(5, deserializedState.tabId); + assertEquals(state.toJson(), deserializedState.toJson()); } @Test public void testScrollStateFromInvalidJson() { - Assert.assertEquals(null, FeedSurfaceMediator.ScrollState.fromJson("{{=xcg")); + assertEquals(null, FeedSurfaceMediator.ScrollState.fromJson("{{=xcg")); + } + + @Test + public void updateContent_openingTabIdFollowing() { + PropertyModel sectionHeaderModel = SectionHeaderListProperties.create(); + mFeedSurfaceMediator = new FeedSurfaceMediator(mFeedSurfaceCoordinator, mActivity, null, + mPageNavigationDelegate, sectionHeaderModel, + FeedSurfaceCoordinator.StreamTabId.FOLLOWING); + mFeedSurfaceMediator.updateContent(); + + assertEquals(FeedSurfaceCoordinator.StreamTabId.FOLLOWING, + sectionHeaderModel.get(SectionHeaderListProperties.CURRENT_TAB_INDEX_KEY)); + } + + @Test + public void updateContent_openingTabIdForYou() { + PropertyModel sectionHeaderModel = SectionHeaderListProperties.create(); + mFeedSurfaceMediator = new FeedSurfaceMediator(mFeedSurfaceCoordinator, mActivity, null, + mPageNavigationDelegate, sectionHeaderModel, + FeedSurfaceCoordinator.StreamTabId.FOR_YOU); + mFeedSurfaceMediator.updateContent(); + + assertEquals(FeedSurfaceCoordinator.StreamTabId.FOR_YOU, + sectionHeaderModel.get(SectionHeaderListProperties.CURRENT_TAB_INDEX_KEY)); } }
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 5e6a2b2..02e09cc 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
@@ -26,7 +26,6 @@ private boolean mIsMultipleInstanceRunning; private boolean mIsApi31; private boolean mCustomMultiWindowSupported; - private boolean mIsTabletScreen; @Before public void setUp() { @@ -57,11 +56,6 @@ } @Override - public boolean isTabletScreen(Context context) { - return mIsTabletScreen; - } - - @Override public Class<? extends Activity> getOpenInOtherWindowActivity(Activity current) { return Activity.class; } @@ -70,61 +64,35 @@ @Test public void testCanEnterMultiWindowMode() { - // Chrome can enter multi-window mode through menu when it is not already in it - // on the platform that supports it (Android S or certain vendor-customized platform). - // Cannot enter it if there are already multiple instances running in multiple windows. - boolean[][] flags = { - // multi-instances, multi-window, Android S, Vendor, result - {false, false, false, false, false}, - {false, false, false, true, true}, - {false, false, true, false, true}, - {false, false, true, true, true}, - {false, true, false, false, false}, - {false, true, false, true, true}, - {false, true, true, false, true}, - {false, true, true, true, true}, - {true, false, false, false, false}, - {true, false, false, true, false}, - {true, false, true, false, false}, - {true, false, true, true, false}, - {true, true, false, false, false}, - {true, true, false, true, false}, - {true, true, true, false, false}, - {true, true, true, true, false}, - }; + // Chrome can enter multi-window mode through menu on the platform that supports it + // (Android S or certain vendor-customized platform). + for (int i = 0; i < 32; ++i) { + mIsInMultiWindowMode = ((i >> 0) & 1) == 1; + mIsInMultiDisplayMode = ((i >> 1) & 1) == 1; + mIsMultipleInstanceRunning = ((i >> 2) & 1) == 1; + mIsApi31 = ((i >> 3) & 1) == 1; + mCustomMultiWindowSupported = ((i >> 4) & 1) == 1; - mIsTabletScreen = true; - for (int i = 0; i < flags.length; ++i) { - mIsMultipleInstanceRunning = flags[i][0]; - mIsInMultiWindowMode = flags[i][1]; - mIsApi31 = flags[i][2]; - mCustomMultiWindowSupported = flags[i][3]; - - boolean canEnter = flags[i][4]; - assertEquals("multi-instance: " + mIsMultipleInstanceRunning - + " multi-window: " + mIsInMultiWindowMode + " api-s: " + mIsApi31 - + " vendor: " + mCustomMultiWindowSupported, + boolean canEnter = mIsApi31 || mCustomMultiWindowSupported; + assertEquals(" api-s: " + mIsApi31 + " vendor: " + mCustomMultiWindowSupported, canEnter, mUtils.canEnterMultiWindowMode(null)); } } @Test - public void testIsOpenInOtherWindowSupported() { - for (int i = 0; i < 16; ++i) { - // Check all the combinations. + public void testIsOpenInOtherWindowEnabled() { + for (int i = 0; i < 32; ++i) { mIsInMultiWindowMode = ((i >> 0) & 1) == 1; mIsInMultiDisplayMode = ((i >> 1) & 1) == 1; mIsMultipleInstanceRunning = ((i >> 2) & 1) == 1; - mIsTabletScreen = ((i >> 3) & 1) == 1; + mIsApi31 = ((i >> 3) & 1) == 1; + mCustomMultiWindowSupported = ((i >> 4) & 1) == 1; - // 'OpenInOtherWindow' is supported as long as the platform supports it - // and we have another instance to move the window to. - // Multi-display device always can open in other window as well. - boolean openInOtherWindow = (mIsInMultiWindowMode || mIsInMultiDisplayMode) - && (!mIsTabletScreen || mIsMultipleInstanceRunning); + // 'openInOtherWindow' is supported if we are already in multi-window/display mode. + boolean openInOtherWindow = (mIsInMultiWindowMode || mIsInMultiDisplayMode); assertEquals("multi-window: " + mIsInMultiWindowMode - + " multi-display: " + mIsInMultiDisplayMode + " multi-instance: " - + mIsMultipleInstanceRunning + " tablet-screen: " + mIsTabletScreen, + + " multi-display: " + mIsInMultiDisplayMode + + " multi-instance: " + mIsMultipleInstanceRunning, openInOtherWindow, mUtils.isOpenInOtherWindowSupported(null)); } }
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/native_page/NativePageFactoryTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/native_page/NativePageFactoryTest.java index 1369f14..e28cfd8c 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/native_page/NativePageFactoryTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/native_page/NativePageFactoryTest.java
@@ -96,7 +96,7 @@ } @Override - public NativePage buildNewTabPage(Tab tab) { + public NativePage buildNewTabPage(Tab tab, String url) { return new MockNativePage(NativePageType.NTP); }
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 ed16558ba..e91a1ea 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
@@ -199,15 +199,6 @@ assertMenuItemsAreEqual(menu, expectedItems); } - private boolean canEnterMultiWindow() { - return !mIsMultiInstance && mIsMultiWindowApiSupported; - } - - private boolean isOpenInOtherWindow() { - if (!mIsMultiWindow && !mIsMultiInstance) return false; - return !mIsNewWindowMenuFeatureEnabled || !mIsTabletScreen || mIsMultiInstance; - } - private void setMultiWindowMenuFlags(int i) { mIsMultiTab = (i & 1) == 1; mIsMultiInstance = ((i >> 1) & 1) == 1; @@ -218,19 +209,19 @@ } private Menu initMocksForMultiWindowMenu(boolean isNewWindowFeatureEnabled) { - mIsNewWindowMenuFeatureEnabled = isNewWindowFeatureEnabled; doReturn(mIsMultiTab ? 2 : 1).when(mTabModelSelector).getTotalTabCount(); - doReturn(canEnterMultiWindow()) + doReturn(mIsMultiWindow).when(mMultiWindowModeStateDispatcher).isInMultiWindowMode(); + doReturn(mIsMultiWindowApiSupported) .when(mMultiWindowModeStateDispatcher) .canEnterMultiWindowMode(); - doReturn(isOpenInOtherWindow()) - .when(mMultiWindowModeStateDispatcher) - .isOpenInOtherWindowSupported(); doReturn(mIsMultiInstance).when(mMultiWindowModeStateDispatcher).isMultiInstanceRunning(); doReturn(mIsPartnerHomepageEnabled) .when(mTabbedAppMenuPropertiesDelegate) .isPartnerHomepageEnabled(); doReturn(mIsTabletScreen).when(mTabbedAppMenuPropertiesDelegate).isTabletSizeScreen(); + doReturn(isNewWindowFeatureEnabled) + .when(mTabbedAppMenuPropertiesDelegate) + .isNewWindowMenuFeatureEnabled(); Menu menu = createTestMenu(); mTabbedAppMenuPropertiesDelegate.prepareMenu(menu, null); return menu; @@ -276,7 +267,8 @@ } @Test - public void testPageMenuItems_newWindowMenuFeatureDisabled() { + public void testPageMenuItems_disabledFeature() { + // If the feature is disabled, show 'move to other window' as before. setUpMocksForPageMenu(); mIsMultiTab = true; mIsMultiWindow = true; @@ -284,6 +276,13 @@ Menu menu = initMocksForMultiWindowMenu(false); assertFalse(isMenuVisible(menu, R.id.new_window_menu_id)); assertTrue(isMenuVisible(menu, R.id.move_to_other_window_menu_id)); + + // Hide even 'move to other window' for single tab/enabled partner homepage. + mIsPartnerHomepageEnabled = true; + mIsMultiTab = false; + menu = initMocksForMultiWindowMenu(false); + assertFalse(isMenuVisible(menu, R.id.new_window_menu_id)); + assertFalse(isMenuVisible(menu, R.id.move_to_other_window_menu_id)); } @Test @@ -323,7 +322,7 @@ setUpMocksForPageMenu(); doReturn(1).when(mTabModelSelector).getTotalTabCount(); - doReturn(true).when(mMultiWindowModeStateDispatcher).isOpenInOtherWindowSupported(); + doReturn(true).when(mMultiWindowModeStateDispatcher).isInMultiWindowMode(); doReturn(true).when(mMultiWindowModeStateDispatcher).isMultiInstanceRunning(); Menu menu = createTestMenu(); mTabbedAppMenuPropertiesDelegate.prepareMenu(menu, null); @@ -339,7 +338,7 @@ setUpMocksForPageMenu(); doReturn(1).when(mTabModelSelector).getTotalTabCount(); - doReturn(true).when(mMultiWindowModeStateDispatcher).isOpenInOtherWindowSupported(); + doReturn(true).when(mMultiWindowModeStateDispatcher).isInMultiWindowMode(); doReturn(true).when(mTabbedAppMenuPropertiesDelegate).isPartnerHomepageEnabled(); Menu menu = createTestMenu(); mTabbedAppMenuPropertiesDelegate.prepareMenu(menu, null); @@ -347,6 +346,14 @@ // 'Move to other window' should be hidden when there is a single tab on the current // window but partner homepage is set, since that would close the current instance, // which apparently is not intended. + assertMenuContains(menu, R.id.new_window_menu_id); + assertMenuDoesNotContain(menu, R.id.move_to_other_window_menu_id); + + // Should be invisible when in multi-instance mode as well. + doReturn(true).when(mMultiWindowModeStateDispatcher).isMultiInstanceRunning(); + menu = createTestMenu(); + mTabbedAppMenuPropertiesDelegate.prepareMenu(menu, null); + assertMenuDoesNotContain(menu, R.id.new_window_menu_id); assertMenuDoesNotContain(menu, R.id.move_to_other_window_menu_id); } @@ -360,7 +367,8 @@ Menu menu = createTestMenu(); mTabbedAppMenuPropertiesDelegate.prepareMenu(menu, null); - // Multiple tabs in single-window mode with single instance shows 'New Window' only. + // Multiple tabs in single-window mode with single instance shows 'New Window' only + // if it's capable of entering multi-window mode. assertMenuContains(menu, R.id.new_window_menu_id); assertMenuDoesNotContain(menu, R.id.move_to_other_window_menu_id); } @@ -370,7 +378,7 @@ setUpMocksForPageMenu(); doReturn(2).when(mTabModelSelector).getTotalTabCount(); - doReturn(true).when(mMultiWindowModeStateDispatcher).isOpenInOtherWindowSupported(); + doReturn(true).when(mMultiWindowModeStateDispatcher).isInMultiWindowMode(); doReturn(true).when(mMultiWindowModeStateDispatcher).isMultiInstanceRunning(); Menu menu = createTestMenu(); mTabbedAppMenuPropertiesDelegate.prepareMenu(menu, null); @@ -390,6 +398,28 @@ } @Test + public void testPageMenuItems_multiwindow_singleinstance() { + setUpMocksForPageMenu(); + + doReturn(2).when(mTabModelSelector).getTotalTabCount(); + doReturn(true).when(mMultiWindowModeStateDispatcher).isInMultiWindowMode(); + Menu menu = createTestMenu(); + mTabbedAppMenuPropertiesDelegate.prepareMenu(menu, null); + + // In multi-window, single instance mode we show 'new window'. + assertMenuContains(menu, R.id.new_window_menu_id); + assertMenuDoesNotContain(menu, R.id.move_to_other_window_menu_id); + + doReturn(1).when(mTabModelSelector).getTotalTabCount(); + menu = createTestMenu(); + mTabbedAppMenuPropertiesDelegate.prepareMenu(menu, null); + + // Even with single tab, we show 'new window'. + assertMenuContains(menu, R.id.new_window_menu_id); + assertMenuDoesNotContain(menu, R.id.move_to_other_window_menu_id); + } + + @Test public void getFooterResourceId_incognito_doesNotReturnWebFeedMenuItem() { setUpMocksForWebFeedFooter(); when(mTab.isIncognito()).thenReturn(true); @@ -472,10 +502,17 @@ } private Menu createTestMenu() { + // mMultiWindowModeStateDispatcher.isOpenInOtherWindowSupported() is determined by + // isInMultiWindowMode() and isInMultiDisplayMode(). Set that condition here. + boolean openInOtherWindow = mMultiWindowModeStateDispatcher.isInMultiWindowMode() + || mMultiWindowModeStateDispatcher.isInMultiDisplayMode(); + doReturn(openInOtherWindow) + .when(mMultiWindowModeStateDispatcher) + .isOpenInOtherWindowSupported(); + PopupMenu tempMenu = new PopupMenu(ContextUtils.getApplicationContext(), mDecorView); tempMenu.inflate(mTabbedAppMenuPropertiesDelegate.getAppMenuLayoutId()); - Menu menu = tempMenu.getMenu(); - return menu; + return tempMenu.getMenu(); } private void assertMenuItemsAreEqual(Menu menu, Integer... expectedItems) {
diff --git a/chrome/android/webapk/README.md b/chrome/android/webapk/README.md index 700ad1d..a691632d 100644 --- a/chrome/android/webapk/README.md +++ b/chrome/android/webapk/README.md
@@ -41,7 +41,7 @@ On ChromeOS, build //chrome/android/webapk/shell_apk:webapk -Both can be customized via [shell_apk/manifest/bound_manifest_config.json](https://source.chromium.org/chromium/chromium/src/+/master:chrome/android/webapk/shell_apk/manifest/bound_manifest_config.json) +Both can be customized via [shell_apk/manifest/bound_manifest_config.json](https://source.chromium.org/chromium/chromium/src/+/main:chrome/android/webapk/shell_apk/manifest/bound_manifest_config.json) To make a locally built WebAPK launch Chrome in 'WebAPK mode': 1) Set the --skip-webapk-verification Chrome command line flag
diff --git a/chrome/app/chromeos_strings.grdp b/chrome/app/chromeos_strings.grdp index 8d508920..31bfbf38 100644 --- a/chrome/app/chromeos_strings.grdp +++ b/chrome/app/chromeos_strings.grdp
@@ -1983,7 +1983,13 @@ Unlock </message> <message name="IDS_SETTINGS_INTERNET_NETWORK_SIM_ENTER_PIN_TITLE" desc="Settings > Internet > Network details > Lock/unlock SIM card: Title for enter PIN dialog."> - Enter SIM PIN + Enter PIN + </message> + <message name="IDS_SETTINGS_INTERNET_NETWORK_SIM_ENTER_PIN_DESCRIPTION" desc="Settings > Internet > Network details > Lock/unlock SIM card: Description for enter PIN dialog."> + Anyone using this device will need to enter the PIN to connect to this mobile network + </message> + <message name="IDS_SETTINGS_INTERNET_NETWORK_SIM_ENTER_PIN_DESCRIPTION_TEXT_LABEL" desc="Settings > Internet > Network details > Lock/unlock SIM card: Label for the text input."> + Enter at least 4 numbers </message> <message name="IDS_SETTINGS_INTERNET_NETWORK_SIM_CHANGE_PIN_TITLE" desc="Settings > Internet > Network details > Lock/unlock SIM card: Title for change PIN dialog."> Change SIM PIN @@ -1992,7 +1998,7 @@ Connect to this network to change SIM lock setting </message> <message name="IDS_SETTINGS_INTERNET_NETWORK_SIM_LOCKED_TITLE" desc="Settings > Internet > Network details > Lock/unlock SIM card: Title for SIM locked dialog."> - SIM Card is locked + SIM card is locked </message> <message name="IDS_SETTINGS_INTERNET_NETWORK_SIM_LOCKED_PUK_SUBTITLE" desc="Settings > Internet > Network details > Lock/unlock SIM card: Title informing the user to enter a PIN provided by the carrier in order unlock network"> Enter the 8-digit PIN Unblocking Key provided by your carrier @@ -2007,7 +2013,7 @@ Enter PIN </message> <message name="IDS_SETTINGS_INTERNET_NETWORK_SIM_ENTER_OLD_PIN" desc="Settings > Internet > Network details > Lock/unlock SIM card: Label for entering an old (current) PIN."> - Enter old PIN + Enter current PIN </message> <message name="IDS_SETTINGS_INTERNET_NETWORK_SIM_ENTER_NEW_PIN" desc="Settings > Internet > Network details > Lock/unlock SIM card: Label for entering a new PIN."> Enter new PIN @@ -4444,12 +4450,6 @@ <message name="IDS_CROSTINI_TERMINAL_STATUS_START_CONTAINER" desc="Text shown in the crostini terminal when it is starting the Linux container"> Starting the Linux container </message> - <message name="IDS_CROSTINI_TERMINAL_STATUS_FETCH_SSH_KEYS" desc="Text shown in the crostini terminal when it is fetching the Linux container ssh keys"> - Fetching the Linux container ssh keys - </message> - <message name="IDS_CROSTINI_TERMINAL_STATUS_MOUNT_CONTAINER" desc="Text shown in the crostini terminal when it is mounting container sshfs (ssh filesystem)"> - Mounting the Linux container sshfs - </message> <message name="IDS_CROSTINI_TERMINAL_STATUS_CONNECT_CONTAINER" desc="Text shown in the crostini terminal when it is connecting to the container"> Connecting to the container </message>
diff --git a/chrome/app/chromeos_strings_grdp/IDS_CROSTINI_TERMINAL_STATUS_FETCH_SSH_KEYS.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_CROSTINI_TERMINAL_STATUS_FETCH_SSH_KEYS.png.sha1 deleted file mode 100644 index c2dd105..0000000 --- a/chrome/app/chromeos_strings_grdp/IDS_CROSTINI_TERMINAL_STATUS_FETCH_SSH_KEYS.png.sha1 +++ /dev/null
@@ -1 +0,0 @@ -d5dfef986211c69d831ac4515dd9defdc772cfc3 \ No newline at end of file
diff --git a/chrome/app/chromeos_strings_grdp/IDS_CROSTINI_TERMINAL_STATUS_MOUNT_CONTAINER.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_CROSTINI_TERMINAL_STATUS_MOUNT_CONTAINER.png.sha1 deleted file mode 100644 index c2dd105..0000000 --- a/chrome/app/chromeos_strings_grdp/IDS_CROSTINI_TERMINAL_STATUS_MOUNT_CONTAINER.png.sha1 +++ /dev/null
@@ -1 +0,0 @@ -d5dfef986211c69d831ac4515dd9defdc772cfc3 \ No newline at end of file
diff --git a/chrome/app/chromeos_strings_grdp/IDS_SETTINGS_INTERNET_NETWORK_SIM_ENTER_OLD_PIN.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_SETTINGS_INTERNET_NETWORK_SIM_ENTER_OLD_PIN.png.sha1 new file mode 100644 index 0000000..1ccee39 --- /dev/null +++ b/chrome/app/chromeos_strings_grdp/IDS_SETTINGS_INTERNET_NETWORK_SIM_ENTER_OLD_PIN.png.sha1
@@ -0,0 +1 @@ +902aedac79c387f6b87bfea4132137f4aa25ec5d \ No newline at end of file
diff --git a/chrome/app/chromeos_strings_grdp/IDS_SETTINGS_INTERNET_NETWORK_SIM_ENTER_PIN_DESCRIPTION.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_SETTINGS_INTERNET_NETWORK_SIM_ENTER_PIN_DESCRIPTION.png.sha1 new file mode 100644 index 0000000..5e205cd --- /dev/null +++ b/chrome/app/chromeos_strings_grdp/IDS_SETTINGS_INTERNET_NETWORK_SIM_ENTER_PIN_DESCRIPTION.png.sha1
@@ -0,0 +1 @@ +c74d1a798b24d96c7852487b32a22a399d24aecc \ No newline at end of file
diff --git a/chrome/app/chromeos_strings_grdp/IDS_SETTINGS_INTERNET_NETWORK_SIM_ENTER_PIN_DESCRIPTION_TEXT_LABEL.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_SETTINGS_INTERNET_NETWORK_SIM_ENTER_PIN_DESCRIPTION_TEXT_LABEL.png.sha1 new file mode 100644 index 0000000..5e205cd --- /dev/null +++ b/chrome/app/chromeos_strings_grdp/IDS_SETTINGS_INTERNET_NETWORK_SIM_ENTER_PIN_DESCRIPTION_TEXT_LABEL.png.sha1
@@ -0,0 +1 @@ +c74d1a798b24d96c7852487b32a22a399d24aecc \ No newline at end of file
diff --git a/chrome/app/chromeos_strings_grdp/IDS_SETTINGS_INTERNET_NETWORK_SIM_ENTER_PIN_TITLE.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_SETTINGS_INTERNET_NETWORK_SIM_ENTER_PIN_TITLE.png.sha1 new file mode 100644 index 0000000..5e205cd --- /dev/null +++ b/chrome/app/chromeos_strings_grdp/IDS_SETTINGS_INTERNET_NETWORK_SIM_ENTER_PIN_TITLE.png.sha1
@@ -0,0 +1 @@ +c74d1a798b24d96c7852487b32a22a399d24aecc \ No newline at end of file
diff --git a/chrome/app/chromeos_strings_grdp/IDS_SETTINGS_INTERNET_NETWORK_SIM_LOCKED_TITLE.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_SETTINGS_INTERNET_NETWORK_SIM_LOCKED_TITLE.png.sha1 new file mode 100644 index 0000000..9bbf73d --- /dev/null +++ b/chrome/app/chromeos_strings_grdp/IDS_SETTINGS_INTERNET_NETWORK_SIM_LOCKED_TITLE.png.sha1
@@ -0,0 +1 @@ +f1799a9f54b2c9f26aff555e4fb7f5f52edd19a4 \ No newline at end of file
diff --git a/chrome/app/settings_strings.grdp b/chrome/app/settings_strings.grdp index cc68e9d4..8703c865 100644 --- a/chrome/app/settings_strings.grdp +++ b/chrome/app/settings_strings.grdp
@@ -1240,7 +1240,7 @@ Privacy Sandbox is still in active development and is available in selected regions. For now, sites may try out Privacy Sandbox while continuing to use current web technologies like third-party cookies. <ph name="BEGIN_LINK"><a href="$1" target="_blank"></ph>Learn more<ph name="END_LINK"></a></ph> </message> <message name="IDS_SETTINGS_PRIVACY_SANDBOX_PAGE_EXPLANATION1_PHASE2" desc="Part 1 of the phase 2 explanation of the Privacy Sandbox, shown on the Privacy Sandbox Page. The 'Privacy Sandbox' link navigates the user to a page with more details."> - <ph name="BEGIN_LINK"><a href="$1" target="_blank"></ph>Privacy Sandbox<ph name="END_LINK"></a></ph> is an ongoing initiative to develop new technologies that will safeguard you from tracking mechanisms while preserving the open web. + With <ph name="BEGIN_LINK"><a href="$1" target="_blank"></ph>Privacy Sandbox<ph name="END_LINK"></a></ph>, Chrome is developing new technologies to safeguard you from cross-site tracking while preserving the open web. </message> <message name="IDS_SETTINGS_PRIVACY_SANDBOX_PAGE_EXPLANATION2_PHASE2" desc="Part 2 of the phase 2 explanation of the Privacy Sandbox, shown on the Privacy Sandbox Page. The 'Privacy Sandbox' link navigates the user to a page with more details."> Privacy Sandbox trials are still in active development and are available in selected regions. For now, sites may try out Privacy Sandbox while continuing to use current web technologies like third-party cookies.
diff --git a/chrome/app/settings_strings_grdp/IDS_SETTINGS_PRIVACY_SANDBOX_PAGE_EXPLANATION1_PHASE2.png.sha1 b/chrome/app/settings_strings_grdp/IDS_SETTINGS_PRIVACY_SANDBOX_PAGE_EXPLANATION1_PHASE2.png.sha1 index aa6d6f7..4b7b670 100644 --- a/chrome/app/settings_strings_grdp/IDS_SETTINGS_PRIVACY_SANDBOX_PAGE_EXPLANATION1_PHASE2.png.sha1 +++ b/chrome/app/settings_strings_grdp/IDS_SETTINGS_PRIVACY_SANDBOX_PAGE_EXPLANATION1_PHASE2.png.sha1
@@ -1 +1 @@ -26eb02bf641228865c1090d21689f8345b78730e \ No newline at end of file +cd9856072564bacb40136fb997d1b822d743c8b4 \ No newline at end of file
diff --git a/chrome/app/theme/PRESUBMIT.py b/chrome/app/theme/PRESUBMIT.py index 545b8e1..717d4d5 100644 --- a/chrome/app/theme/PRESUBMIT.py +++ b/chrome/app/theme/PRESUBMIT.py
@@ -6,7 +6,7 @@ See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts for more details about the presubmit API built into depot_tools, and see -https://chromium.googlesource.com/chromium/src/+/master/styleguide/web/web.md +https://chromium.googlesource.com/chromium/src/+/main/styleguide/web/web.md for the rules we're checking against here. """
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index 0605834..a49aeacf 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -3154,6 +3154,8 @@ "reputation/safety_tip_infobar.h", "reputation/safety_tip_infobar_delegate.cc", "reputation/safety_tip_infobar_delegate.h", + "reputation/safety_tip_message_delegate.cc", + "reputation/safety_tip_message_delegate.h", "safe_browsing/android/password_reuse_controller_android.cc", "safe_browsing/android/password_reuse_controller_android.h", "safe_browsing/android/safe_browsing_referring_app_bridge_android.cc",
diff --git a/chrome/browser/apps/app_service/web_apps_publisher_host.cc b/chrome/browser/apps/app_service/web_apps_publisher_host.cc index 8ce915e..78af198 100644 --- a/chrome/browser/apps/app_service/web_apps_publisher_host.cc +++ b/chrome/browser/apps/app_service/web_apps_publisher_host.cc
@@ -72,7 +72,7 @@ } service->GetRemote<crosapi::mojom::AppPublisher>()->RegisterAppController( - receiver_.BindNewPipeAndPassRemote()); + receiver_.BindNewPipeAndPassRemoteWithVersion()); remote_publisher_ = service->GetRemote<crosapi::mojom::AppPublisher>().get(); }
diff --git a/chrome/browser/ash/crostini/crostini_installer.cc b/chrome/browser/ash/crostini/crostini_installer.cc index 2b6c7bf..210dac6 100644 --- a/chrome/browser/ash/crostini/crostini_installer.cc +++ b/chrome/browser/ash/crostini/crostini_installer.cc
@@ -127,10 +127,6 @@ return SetupResult::kErrorConfiguringContainer; case InstallerError::kErrorOffline: return SetupResult::kErrorOffline; - case InstallerError::kErrorFetchingSshKeys: - return SetupResult::kErrorFetchingSshKeys; - case InstallerError::kErrorMountingContainer: - return SetupResult::kErrorMountingContainer; case InstallerError::kErrorSettingUpContainer: return SetupResult::kErrorSettingUpContainer; case InstallerError::kErrorInsufficientDiskSpace: @@ -165,10 +161,6 @@ return SetupResult::kUserCancelledStartContainer; case InstallerState::kConfigureContainer: return SetupResult::kUserCancelledConfiguringContainer; - case InstallerState::kFetchSshKeys: - return SetupResult::kUserCancelledFetchSshKeys; - case InstallerState::kMountContainer: - return SetupResult::kUserCancelledMountContainer; } NOTREACHED(); @@ -462,25 +454,6 @@ HandleError(InstallerError::kErrorStartingContainer); return; } - UpdateInstallingState(InstallerState::kFetchSshKeys); -} - -void CrostiniInstaller::OnSshKeysFetched(bool success) { - DCHECK_EQ(installing_state_, InstallerState::kFetchSshKeys); - - if (!success) { - HandleError(InstallerError::kErrorFetchingSshKeys); - return; - } - UpdateInstallingState(InstallerState::kMountContainer); -} - -void CrostiniInstaller::OnContainerMounted(bool success) { - DCHECK_EQ(installing_state_, InstallerState::kMountContainer); - - if (!success) { - HandleError(InstallerError::kErrorMountingContainer); - } } bool CrostiniInstaller::CanInstall() { @@ -540,18 +513,10 @@ break; case InstallerState::kConfigureContainer: state_start_mark = 0.79; - state_end_mark = 0.99; + state_end_mark = 1; // Ansible installation and playbook application. state_max_time = base::TimeDelta::FromSeconds(140 + 300); break; - case InstallerState::kFetchSshKeys: - state_start_mark = 0.99; - state_end_mark = 1; - break; - case InstallerState::kMountContainer: - state_start_mark = 1; - state_end_mark = 1; - break; default: NOTREACHED(); } @@ -652,7 +617,6 @@ return; } - DCHECK_EQ(installing_state_, InstallerState::kMountContainer); // Reset state to allow |Install()| again in case the user remove and // re-install crostini. UpdateState(State::IDLE);
diff --git a/chrome/browser/ash/crostini/crostini_installer.h b/chrome/browser/ash/crostini/crostini_installer.h index 7e6984c..aa79334a 100644 --- a/chrome/browser/ash/crostini/crostini_installer.h +++ b/chrome/browser/ash/crostini/crostini_installer.h
@@ -42,8 +42,8 @@ kErrorStartingTermina = 6, kErrorStartingContainer = 7, kErrorOffline = 8, - kErrorFetchingSshKeys = 9, - kErrorMountingContainer = 10, + // kErrorFetchingSshKeys = 9, + // kErrorMountingContainer = 10, kErrorSettingUpContainer = 11, kUserCancelledStart = 12, @@ -54,8 +54,8 @@ kUserCancelledCreateContainer = 17, kUserCancelledStartContainer = 18, kUserCancelledSetupContainer = 19, - kUserCancelledFetchSshKeys = 20, - kUserCancelledMountContainer = 21, + // kUserCancelledFetchSshKeys = 20, + // kUserCancelledMountContainer = 21, kErrorInsufficientDiskSpace = 22, @@ -102,8 +102,6 @@ void OnContainerCreated(crostini::CrostiniResult result) override; void OnContainerSetup(bool success) override; void OnContainerStarted(crostini::CrostiniResult result) override; - void OnSshKeysFetched(bool success) override; - void OnContainerMounted(bool success) override; // AnsibleManagementService::Observer: void OnAnsibleSoftwareConfigurationStarted() override;
diff --git a/chrome/browser/ash/crostini/crostini_installer_unittest.cc b/chrome/browser/ash/crostini/crostini_installer_unittest.cc index fb1a869..eed1601 100644 --- a/chrome/browser/ash/crostini/crostini_installer_unittest.cc +++ b/chrome/browser/ash/crostini/crostini_installer_unittest.cc
@@ -17,6 +17,7 @@ #include "chrome/browser/ash/crostini/crostini_test_helper.h" #include "chrome/browser/ash/crostini/crostini_types.mojom.h" #include "chrome/browser/component_updater/fake_cros_component_manager.h" +#include "chrome/browser/notifications/system_notification_helper.h" #include "chrome/test/base/browser_process_platform_part_test_api_chromeos.h" #include "chrome/test/base/scoped_testing_local_state.h" #include "chrome/test/base/testing_browser_process.h" @@ -129,6 +130,8 @@ g_browser_process->platform_part() ->InitializeSchedulerConfigurationManager(); + TestingBrowserProcess::GetGlobal()->SetSystemNotificationHelper( + std::make_unique<SystemNotificationHelper>()); } void TearDown() override {
diff --git a/chrome/browser/ash/crostini/crostini_low_disk_notification.cc b/chrome/browser/ash/crostini/crostini_low_disk_notification.cc index 03d4a31..a8d555b 100644 --- a/chrome/browser/ash/crostini/crostini_low_disk_notification.cc +++ b/chrome/browser/ash/crostini/crostini_low_disk_notification.cc
@@ -57,14 +57,22 @@ void CrostiniLowDiskNotification::OnLowDiskSpaceTriggered( const vm_tools::cicerone::LowDiskSpaceTriggeredSignal& signal) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); if (signal.vm_name() != kCrostiniDefaultVmName) { // TODO(crbug/1189009): Support VMs with different names return; } + ShowNotificationIfAppropriate(signal.free_bytes()); +} +void CrostiniLowDiskNotification::ShowNotificationIfAppropriate( + uint64_t free_bytes) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); bool show_low_disk_space_notification = true; + Severity severity = GetSeverity(free_bytes); + if (severity == Severity::NONE) { + return; + } if (!chromeos::CrosSettings::Get()->GetBoolean( chromeos::kDeviceShowLowDiskSpaceNotification, &show_low_disk_space_notification)) { @@ -80,10 +88,9 @@ << "suppressed on a managed device."; return; } - Severity severity = GetSeverity(signal.free_bytes()); base::Time now = base::Time::Now(); if (severity != last_notification_severity_ || - (severity == HIGH && + (severity == Severity::HIGH && now - last_notification_time_ > notification_interval_)) { SystemNotificationHelper::GetInstance()->Display( *CreateNotification(severity));
diff --git a/chrome/browser/ash/crostini/crostini_low_disk_notification.h b/chrome/browser/ash/crostini/crostini_low_disk_notification.h index cc08e69..4aa2aab 100644 --- a/chrome/browser/ash/crostini/crostini_low_disk_notification.h +++ b/chrome/browser/ash/crostini/crostini_low_disk_notification.h
@@ -35,17 +35,19 @@ // Unregisters from observing events. ~CrostiniLowDiskNotification() override; - // Called when the device is running low on disk space. This is responsible - // for deciding whether a notification should be shown or not and showing it - // if appropriate. This must be called from the thread that instantiated this - // object. + // chromeos::CiceroneClient::Observer override. void OnLowDiskSpaceTriggered( const vm_tools::cicerone::LowDiskSpaceTriggeredSignal& signal) override; + // This is responsible for deciding whether a notification should be shown or + // not and showing it if appropriate. This must be called from the thread that + // instantiated this object. + void ShowNotificationIfAppropriate(uint64_t free_bytes); + private: friend class CrostiniLowDiskNotificationTest; - enum Severity { NONE = -1, MEDIUM = 0, HIGH = 1 }; + enum class Severity { NONE = -1, MEDIUM = 0, HIGH = 1 }; // Creates a notification for the specified severity. If the severity does // not match a known value MEDIUM is used by default. @@ -61,7 +63,7 @@ void SetNotificationIntervalForTest(base::TimeDelta interval); base::Time last_notification_time_; - Severity last_notification_severity_ = NONE; + Severity last_notification_severity_ = Severity::NONE; base::TimeDelta notification_interval_; THREAD_CHECKER(thread_checker_);
diff --git a/chrome/browser/ash/crostini/crostini_low_disk_notification_unittest.cc b/chrome/browser/ash/crostini/crostini_low_disk_notification_unittest.cc index d399cf97..263d0a3 100644 --- a/chrome/browser/ash/crostini/crostini_low_disk_notification_unittest.cc +++ b/chrome/browser/ash/crostini/crostini_low_disk_notification_unittest.cc
@@ -173,4 +173,9 @@ EXPECT_EQ(0, notification_count_); } +TEST_F(CrostiniLowDiskNotificationTest, NoNotificationWhenEnoughFreeSpace) { + low_disk_notification_->ShowNotificationIfAppropriate(1024 * 1024 * 1024); + EXPECT_EQ(0, notification_count_); +} + } // namespace crostini
diff --git a/chrome/browser/ash/crostini/crostini_manager.cc b/chrome/browser/ash/crostini/crostini_manager.cc index 4a12211..22d4ba6 100644 --- a/chrome/browser/ash/crostini/crostini_manager.cc +++ b/chrome/browser/ash/crostini/crostini_manager.cc
@@ -175,12 +175,6 @@ case mojom::InstallerState::kStartContainer: name = "Crostini.RestarterTimeInState.StartContainer"; break; - case mojom::InstallerState::kFetchSshKeys: - name = "Crostini.RestarterTimeInState.FetchSshKeys"; - break; - case mojom::InstallerState::kMountContainer: - name = "Crostini.RestarterTimeInState.MountContainer"; - break; case mojom::InstallerState::kConfigureContainer: NOTREACHED(); return; @@ -301,12 +295,6 @@ case mojom::InstallerState::kStartContainer: result = CrostiniResult::START_CONTAINER_TIMED_OUT; break; - case mojom::InstallerState::kFetchSshKeys: - result = CrostiniResult::FETCH_SSH_KEYS_TIMED_OUT; - break; - case mojom::InstallerState::kMountContainer: - result = CrostiniResult::MOUNT_CONTAINER_TIMED_OUT; - break; case mojom::InstallerState::kConfigureContainer: case mojom::InstallerState::kStart: NOTREACHED(); @@ -424,36 +412,13 @@ // try mounting sshfs in that case. auto info = crostini_manager_->GetContainerInfo(container_id_); if (container_id_ == ContainerId::GetDefault() && info) { - StartStage(mojom::InstallerState::kFetchSshKeys); crostini_manager_->MountCrostiniFiles(container_id_, base::DoNothing()); // TODO(crbug/1142321): Metrics - FinishDefaultContainerRestart(result); - } else { - FinishRestart(result); - } - } - - private: - void FinishDefaultContainerRestart(CrostiniResult result) { - // TODO(crbug/1198006): For backwards compatibility quickly run through - // these stages which have since been removed, but some clients still - // expect to see. - for (auto& observer : observer_list_) { - observer.OnSshKeysFetched(true); - } - if (ReturnEarlyIfAborted()) { - return; - } - StartStage(mojom::InstallerState::kMountContainer); - for (auto& observer : observer_list_) { - observer.OnContainerMounted(result == CrostiniResult::SUCCESS); - } - if (ReturnEarlyIfAborted()) { - return; } FinishRestart(result); } + private: void ContinueRestart() { is_running_ = true; // Skip to the end immediately if testing. @@ -493,8 +458,6 @@ // StartContainer might need to do a UID remapping, which in the worst // case can take a very long time. {mojom::InstallerState::kStartContainer, base::TimeDelta::FromDays(5)}, - {mojom::InstallerState::kFetchSshKeys, base::TimeDelta::FromMinutes(5)}, - {mojom::InstallerState::kMountContainer, base::TimeDelta::FromMinutes(5)}, // ConfigureContainer is special, it's not part of the restarter flow, so // it doesn't have a timeout. {mojom::InstallerState::kConfigureContainer, @@ -2310,6 +2273,14 @@ break; } + // The UI can only resize the default VM, so only (maybe) show the + // notification for the default VM and only if there wasn't an error getting + // free space. + if (vm_name == ContainerId::GetDefault().vm_name && + response->free_bytes() != -1) { + low_disk_notifier_->ShowNotificationIfAppropriate(response->free_bytes()); + } + // If the vm is already marked "running" run the callback. if (response->status() == vm_tools::concierge::VM_STATUS_RUNNING) { running_vms_[vm_name] =
diff --git a/chrome/browser/ash/crostini/crostini_manager.h b/chrome/browser/ash/crostini/crostini_manager.h index 7a2f076..d4ecbb9 100644 --- a/chrome/browser/ash/crostini/crostini_manager.h +++ b/chrome/browser/ash/crostini/crostini_manager.h
@@ -194,8 +194,6 @@ virtual void OnContainerCreated(CrostiniResult result) {} virtual void OnContainerSetup(bool success) {} virtual void OnContainerStarted(CrostiniResult result) {} - virtual void OnSshKeysFetched(bool success) {} - virtual void OnContainerMounted(bool success) {} }; struct RestartOptions {
diff --git a/chrome/browser/ash/crostini/crostini_manager_unittest.cc b/chrome/browser/ash/crostini/crostini_manager_unittest.cc index 8df40756..a235d1be 100644 --- a/chrome/browser/ash/crostini/crostini_manager_unittest.cc +++ b/chrome/browser/ash/crostini/crostini_manager_unittest.cc
@@ -28,6 +28,7 @@ #include "chrome/browser/chromeos/policy/powerwash_requirements_checker.h" #include "chrome/browser/component_updater/fake_cros_component_manager.h" #include "chrome/browser/notifications/notification_display_service_tester.h" +#include "chrome/browser/notifications/system_notification_helper.h" #include "chrome/common/chrome_features.h" #include "chrome/test/base/browser_process_platform_part_test_api_chromeos.h" #include "chrome/test/base/scoped_testing_local_state.h" @@ -244,6 +245,8 @@ chromeos::CryptohomeMiscClient::InitializeFake(); chromeos::FakeCryptohomeMiscClient::Get()->set_requires_powerwash(false); policy::PowerwashRequirementsChecker::InitializeSynchronouslyForTesting(); + TestingBrowserProcess::GetGlobal()->SetSystemNotificationHelper( + std::make_unique<SystemNotificationHelper>()); } void TearDown() override { @@ -505,6 +508,21 @@ histogram_tester.ExpectTotalCount(kCrostiniCorruptionHistogram, 0); } +TEST_F(CrostiniManagerTest, StartTerminaVmLowDiskNotification) { + const base::FilePath& disk_path = base::FilePath(kVmName); + NotificationDisplayServiceTester notification_service(nullptr); + + EnsureTerminaInstalled(); + crostini_manager()->StartTerminaVm( + ContainerId::GetDefault().vm_name, disk_path, 0, + base::BindOnce(&ExpectSuccess, run_loop()->QuitClosure())); + run_loop()->Run(); + + EXPECT_GE(fake_concierge_client_->start_termina_vm_call_count(), 1); + auto notification = notification_service.GetNotification("crostini_low_disk"); + EXPECT_NE(absl::nullopt, notification); +} + TEST_F(CrostiniManagerTest, OnStartTremplinRecordsRunningVm) { const base::FilePath& disk_path = base::FilePath(kVmName); const std::string owner_id = CryptohomeIdForProfile(profile()); @@ -722,18 +740,6 @@ } } - void OnSshKeysFetched(bool success) override { - if (abort_on_ssh_keys_fetched_) { - Abort(); - } - } - - void OnContainerMounted(bool success) override { - if (abort_on_container_mounted_) { - Abort(); - } - } - protected: void ExpectCrostiniRestartResult(CrostiniResult result) { EXPECT_EQ(1, restart_crostini_callback_count_); @@ -767,8 +773,6 @@ bool abort_on_container_created_ = false; bool abort_on_container_started_ = false; bool abort_on_container_setup_ = false; - bool abort_on_ssh_keys_fetched_ = false; - bool abort_on_container_mounted_ = false; bool abort_then_stop_vm_ = false; int restart_crostini_callback_count_ = 0; @@ -1048,7 +1052,6 @@ TEST_F(CrostiniManagerRestartTest, AbortOnContainerCreated) { abort_on_container_created_ = true; - // Use termina/penguin names to allow fetch ssh keys. restart_id_ = crostini_manager()->RestartCrostini( ContainerId::GetDefault(), base::BindOnce(&CrostiniManagerRestartTest::RestartCrostiniCallback, @@ -1064,7 +1067,6 @@ TEST_F(CrostiniManagerRestartTest, TimeoutDuringCreateContainer) { fake_cicerone_client_->set_send_create_lxd_container_response_delay( base::TimeDelta::Max()); - // Use termina/penguin names to allow fetch ssh keys. restart_id_ = crostini_manager()->RestartCrostini( ContainerId::GetDefault(), base::BindOnce(&CrostiniManagerRestartTest::RestartCrostiniCallback, @@ -1079,7 +1081,6 @@ TEST_F(CrostiniManagerRestartTest, TimeoutWaitingForContainerCreated) { fake_cicerone_client_->set_send_notify_lxd_container_created_signal_delay( base::TimeDelta::Max()); - // Use termina/penguin names to allow fetch ssh keys. restart_id_ = crostini_manager()->RestartCrostini( ContainerId::GetDefault(), base::BindOnce(&CrostiniManagerRestartTest::RestartCrostiniCallback, @@ -1101,7 +1102,6 @@ signal.set_vm_name(ContainerId::GetDefault().vm_name); signal.set_owner_id(CryptohomeIdForProfile(profile())); - // Use termina/penguin names to allow fetch ssh keys. restart_id_ = crostini_manager()->RestartCrostini( ContainerId::GetDefault(), base::BindOnce(&CrostiniManagerRestartTest::RestartCrostiniCallback, @@ -1126,7 +1126,6 @@ abort_on_container_started_ = true; fake_cicerone_client_->set_lxd_container_created_signal_status( vm_tools::cicerone::LxdContainerCreatedSignal::UNKNOWN); - // Use termina/penguin names to allow fetch ssh keys. restart_id_ = crostini_manager()->RestartCrostini( ContainerId::GetDefault(), base::BindOnce(&ExpectCrostiniResult, run_loop()->QuitClosure(), @@ -1142,7 +1141,6 @@ TEST_F(CrostiniManagerRestartTest, AbortOnContainerStarted) { abort_on_container_started_ = true; - // Use termina/penguin names to allow fetch ssh keys. restart_id_ = crostini_manager()->RestartCrostini( ContainerId::GetDefault(), base::BindOnce(&CrostiniManagerRestartTest::RestartCrostiniCallback, @@ -1157,7 +1155,6 @@ TEST_F(CrostiniManagerRestartTest, AbortOnContainerSetup) { abort_on_container_setup_ = true; - // Use termina/penguin names to allow fetch ssh keys. restart_id_ = crostini_manager()->RestartCrostini( ContainerId::GetDefault(), base::BindOnce(&CrostiniManagerRestartTest::RestartCrostiniCallback, @@ -1173,7 +1170,6 @@ TEST_F(CrostiniManagerRestartTest, TimeoutDuringContainerSetup) { fake_cicerone_client_->set_send_set_up_lxd_container_user_response_delay( base::TimeDelta::Max()); - // Use termina/penguin names to allow fetch ssh keys. restart_id_ = crostini_manager()->RestartCrostini( ContainerId::GetDefault(), base::BindOnce(&CrostiniManagerRestartTest::RestartCrostiniCallback, @@ -1190,7 +1186,6 @@ TEST_F(CrostiniManagerRestartTest, TimeoutDuringStartContainer) { fake_cicerone_client_->set_send_start_lxd_container_response_delay( base::TimeDelta::Max()); - // Use termina/penguin names to allow fetch ssh keys. restart_id_ = crostini_manager()->RestartCrostini( ContainerId::GetDefault(), base::BindOnce(&CrostiniManagerRestartTest::RestartCrostiniCallback, @@ -1205,7 +1200,6 @@ TEST_F(CrostiniManagerRestartTest, TimeoutWaitingForContainerStarted) { fake_cicerone_client_->set_send_container_started_signal_delay( base::TimeDelta::Max()); - // Use termina/penguin names to allow fetch ssh keys. restart_id_ = crostini_manager()->RestartCrostini( ContainerId::GetDefault(), base::BindOnce(&CrostiniManagerRestartTest::RestartCrostiniCallback,
diff --git a/chrome/browser/ash/crostini/crostini_types.mojom b/chrome/browser/ash/crostini/crostini_types.mojom index f38ca940..3a9ff8a 100644 --- a/chrome/browser/ash/crostini/crostini_types.mojom +++ b/chrome/browser/ash/crostini/crostini_types.mojom
@@ -16,8 +16,8 @@ kCreateContainer = 5, // Creating the container inside the Termina VM. kSetupContainer = 6, // Setting up the container inside the Termina VM. kStartContainer = 7, // Starting the container inside the Termina VM. - kFetchSshKeys = 8, // Fetch ssh keys from concierge. - kMountContainer = 9, // Do sshfs mount of container. + //kFetchSshKeys = 8, // Fetch ssh keys from concierge. + //kMountContainer = 9, // Do sshfs mount of container. kConfigureContainer = 10, // Configuring the container inside the Termina VM. }; @@ -30,8 +30,8 @@ kErrorStartingLxd, kErrorStartingContainer, kErrorOffline, - kErrorFetchingSshKeys, - kErrorMountingContainer, + // kErrorFetchingSshKeys, + // kErrorMountingContainer, kErrorSettingUpContainer, kErrorInsufficientDiskSpace, kErrorConfiguringContainer,
diff --git a/chrome/browser/ash/guest_os/README.md b/chrome/browser/ash/guest_os/README.md index 0b460a3..5934489 100644 --- a/chrome/browser/ash/guest_os/README.md +++ b/chrome/browser/ash/guest_os/README.md
@@ -1,7 +1,7 @@ # Guest OS This directory contains code to interact with Chrome OS guest -[VMs and containers](https://chromium.googlesource.com/chromiumos/docs/+/master/containers_and_vms.md) +[VMs and containers](https://chromium.googlesource.com/chromiumos/docs/+/main/containers_and_vms.md) This directory includes code which is common to all VM types such as file sharing.
diff --git a/chrome/browser/attribution_reporting/android/DIR_METADATA b/chrome/browser/attribution_reporting/android/DIR_METADATA index 5777c4c..d263372e 100644 --- a/chrome/browser/attribution_reporting/android/DIR_METADATA +++ b/chrome/browser/attribution_reporting/android/DIR_METADATA
@@ -1,10 +1,10 @@ # Metadata information for this directory. # # For more information on DIR_METADATA files, see: -# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/README.md +# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/README.md # # For the schema of this file, see Metadata message: -# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/proto/dir_metadata.proto +# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/proto/dir_metadata.proto monorail { component: "Internals>ConversionMeasurement"
diff --git a/chrome/browser/autofill/android/save_address_profile_prompt_controller.cc b/chrome/browser/autofill/android/save_address_profile_prompt_controller.cc index 7caface..ed3e453 100644 --- a/chrome/browser/autofill/android/save_address_profile_prompt_controller.cc +++ b/chrome/browser/autofill/android/save_address_profile_prompt_controller.cc
@@ -6,6 +6,7 @@ #include <utility> +#include "base/strings/string_util.h" #include "chrome/android/chrome_jni_headers/SaveAddressProfilePromptController_jni.h" #include "chrome/browser/autofill/android/personal_data_manager_android.h" #include "chrome/browser/browser_process.h" @@ -104,27 +105,30 @@ std::pair<std::u16string, std::u16string> SaveAddressProfilePromptController::GetDiffFromOldToNewProfile() { DCHECK(original_profile_); - // TODO(crbug.com/1167061): Switch to using GetProfileDifferenceForUi. - base::flat_map<ServerFieldType, std::pair<std::u16string, std::u16string>> - differences = AutofillProfileComparator::GetProfileDifferenceMap( - original_profile_.value(), profile_, - autofill::ServerFieldTypeSet( - std::begin(kVisibleTypesForProfileDifferences), - std::end(kVisibleTypesForProfileDifferences)), - g_browser_process->GetApplicationLocale()); - std::vector<std::u16string> old_values; - std::vector<std::u16string> new_values; - for (auto type : kVisibleTypesForProfileDifferences) { - auto it = differences.find(type); - if (it == differences.end()) - continue; - if (!it->second.first.empty()) - old_values.push_back(it->second.first); - if (!it->second.second.empty()) - new_values.push_back(it->second.second); + std::vector<ProfileValueDifference> differences = + GetProfileDifferenceForUi(original_profile_.value(), profile_, + g_browser_process->GetApplicationLocale()); + + std::u16string old_diff; + std::u16string new_diff; + for (const auto& diff : differences) { + if (!diff.first_value.empty()) { + old_diff += diff.first_value + u"\n"; + // Add an extra newline to separate address and the following contacts. + if (diff.type == ADDRESS_HOME_ADDRESS) + old_diff += u"\n"; + } + if (!diff.second_value.empty()) { + new_diff += diff.second_value + u"\n"; + // Add an extra newline to separate address and the following contacts. + if (diff.type == ADDRESS_HOME_ADDRESS) + new_diff += u"\n"; + } } - return std::make_pair(base::JoinString(old_values, u"\n"), - base::JoinString(new_values, u"\n")); + // Make sure there will be no newlines in the end. + base::TrimString(old_diff, base::kWhitespaceASCIIAs16, &old_diff); + base::TrimString(new_diff, base::kWhitespaceASCIIAs16, &new_diff); + return std::make_pair(std::move(old_diff), std::move(new_diff)); } base::android::ScopedJavaLocalRef<jobject>
diff --git a/chrome/browser/autofill/android/save_address_profile_prompt_controller.h b/chrome/browser/autofill/android/save_address_profile_prompt_controller.h index 59ec431e..c440368 100644 --- a/chrome/browser/autofill/android/save_address_profile_prompt_controller.h +++ b/chrome/browser/autofill/android/save_address_profile_prompt_controller.h
@@ -46,10 +46,10 @@ std::u16string GetPhoneNumber(); // For update prompt: std::u16string GetSubtitle(); - // Returns two newline-separated lists of field values for all fields that - // will change when the `original_profile_` is updated to `profile_`. The old - // values, which will be replaced, are the first value, and the new values, - // which will be saved, are the second value. + // Returns two strings listing formatted profile data that will change when + // the `original_profile_` is updated to `profile_`. The old values, which + // will be replaced, are the first value, and the new values, which will be + // saved, are the second value. std::pair<std::u16string, std::u16string> GetDiffFromOldToNewProfile(); base::android::ScopedJavaLocalRef<jobject> GetJavaObject();
diff --git a/chrome/browser/autofill/android/save_address_profile_prompt_controller_unittest.cc b/chrome/browser/autofill/android/save_address_profile_prompt_controller_unittest.cc index 7ee6028..bcd6d0f 100644 --- a/chrome/browser/autofill/android/save_address_profile_prompt_controller_unittest.cc +++ b/chrome/browser/autofill/android/save_address_profile_prompt_controller_unittest.cc
@@ -90,13 +90,13 @@ } TEST_F(SaveAddressProfilePromptControllerTest, - ShouldShowViewOnDisplayPrompt_Save) { + ShouldShowViewOnDisplayPromptWhenSave) { EXPECT_CALL(*prompt_view_, Show(controller_.get(), profile_, false)); controller_->DisplayPrompt(); } TEST_F(SaveAddressProfilePromptControllerTest, - ShouldShowViewOnDisplayPrompt_Update) { + ShouldShowViewOnDisplayPromptWhenUpdate) { SetUpController(/*is_update=*/true); EXPECT_CALL(*prompt_view_, Show(controller_.get(), profile_, true)); controller_->DisplayPrompt(); @@ -168,7 +168,8 @@ controller_.reset(); } -TEST_F(SaveAddressProfilePromptControllerTest, ShouldReturnDataToDisplay_Save) { +TEST_F(SaveAddressProfilePromptControllerTest, + ShouldReturnDataToDisplayWhenSave) { EXPECT_EQ(u"Save address?", controller_->GetTitle()); EXPECT_EQ( u"John H. Doe\nUnderworld\n666 Erebus St.\nApt 8\nElysium, CA " @@ -181,7 +182,7 @@ } TEST_F(SaveAddressProfilePromptControllerTest, - ShouldReturnDataToDisplay_Update) { + ShouldReturnDataToDisplayWhenUpdate) { SetUpController(/*is_update=*/true); EXPECT_EQ(u"Update address?", controller_->GetTitle()); EXPECT_EQ(u"John Doe, 666 Erebus St.", controller_->GetSubtitle()); @@ -193,4 +194,25 @@ EXPECT_EQ(u"Cancel", controller_->GetNegativeButtonText()); } +TEST_F(SaveAddressProfilePromptControllerTest, + ShouldReturnDataToDisplayWhenUpdateWithAddressChanged) { + original_profile_ = test::GetFullProfile(); + original_profile_.SetInfo(ADDRESS_HOME_ZIP, u"", GetLocale()); + original_profile_.SetInfo(PHONE_HOME_WHOLE_NUMBER, u"", GetLocale()); + SetUpController(/*is_update=*/true); + + // Subtitle should contain the full name only. + EXPECT_EQ(u"John H. Doe", controller_->GetSubtitle()); + std::pair<std::u16string, std::u16string> differences = + controller_->GetDiffFromOldToNewProfile(); + // Differences should contain envelope style address. + EXPECT_EQ(u"Underworld\n666 Erebus St.\nApt 8\nElysium, CA \nUnited States", + differences.first); + // There should be an extra newline between address and contacts data. + EXPECT_EQ( + u"Underworld\n666 Erebus St.\nApt 8\nElysium, CA 91111\nUnited " + u"States\n\n16502111111", + differences.second); +} + } // namespace autofill
diff --git a/chrome/browser/chromeos/dbus/README.md b/chrome/browser/chromeos/dbus/README.md index d4072d73..8e79215 100644 --- a/chrome/browser/chromeos/dbus/README.md +++ b/chrome/browser/chromeos/dbus/README.md
@@ -4,4 +4,4 @@ Please see [Chrome OS D-Bus Usage in Chrome] for information about adding D-Bus services. -[Chrome OS D-Bus Usage in Chrome]: https://chromium.googlesource.com/chromiumos/docs/+/master/dbus_in_chrome.md +[Chrome OS D-Bus Usage in Chrome]: https://chromium.googlesource.com/chromiumos/docs/+/main/dbus_in_chrome.md
diff --git a/chrome/browser/chromeos/input_method/assistive_suggester.cc b/chrome/browser/chromeos/input_method/assistive_suggester.cc index 37a9fca..14662f7 100644 --- a/chrome/browser/chromeos/input_method/assistive_suggester.cc +++ b/chrome/browser/chromeos/input_method/assistive_suggester.cc
@@ -282,8 +282,9 @@ } bool AssistiveSuggester::IsMultiWordSuggestEnabled() { - // TODO(b/172617062): Add settings page preference for multi word suggestions. - return base::FeatureList::IsEnabled(chromeos::features::kAssistMultiWord); + return base::FeatureList::IsEnabled(chromeos::features::kAssistMultiWord) && + profile_->GetPrefs()->GetBoolean( + prefs::kAssistPredictiveWritingEnabled); } DisabledReason AssistiveSuggester::GetDisabledReasonForPersonalInfo() {
diff --git a/chrome/browser/chromeos/input_method/assistive_suggester_unittest.cc b/chrome/browser/chromeos/input_method/assistive_suggester_unittest.cc index 777bc700..84b2dcb 100644 --- a/chrome/browser/chromeos/input_method/assistive_suggester_unittest.cc +++ b/chrome/browser/chromeos/input_method/assistive_suggester_unittest.cc
@@ -124,24 +124,41 @@ } TEST_F(AssistiveSuggesterTest, - AssistMultiWordFeatureFlagTrue_AssitiveFeatureEnabledTrue) { + MultiWordEnabledWhenFeatureFlagEnabledAndPrefEnabled) { base::test::ScopedFeatureList feature_list; feature_list.InitWithFeatures( /*enabled_features=*/{chromeos::features::kAssistMultiWord}, /*disabled_features=*/{chromeos::features::kEmojiSuggestAddition, chromeos::features::kAssistPersonalInfo}); + profile_->GetPrefs()->SetBoolean(prefs::kAssistPredictiveWritingEnabled, + true); EXPECT_TRUE(assistive_suggester_->IsAssistiveFeatureEnabled()); } TEST_F(AssistiveSuggesterTest, - AssistMultiWordFeatureFlagFalse_AssitiveFeatureEnabledFalse) { + MultiWordDisabledWhenFeatureFlagEnabledAndPrefDisabled) { + base::test::ScopedFeatureList feature_list; + feature_list.InitWithFeatures( + /*enabled_features=*/{chromeos::features::kAssistMultiWord}, + /*disabled_features=*/{chromeos::features::kEmojiSuggestAddition, + chromeos::features::kAssistPersonalInfo}); + profile_->GetPrefs()->SetBoolean(prefs::kAssistPredictiveWritingEnabled, + false); + + EXPECT_FALSE(assistive_suggester_->IsAssistiveFeatureEnabled()); +} + +TEST_F(AssistiveSuggesterTest, + MultiWordDisabledWhenFeatureFlagDisabledAndPrefDisabled) { base::test::ScopedFeatureList feature_list; feature_list.InitWithFeatures( /*enabled_features=*/{}, /*disabled_features=*/{chromeos::features::kEmojiSuggestAddition, chromeos::features::kAssistPersonalInfo, chromeos::features::kAssistMultiWord}); + profile_->GetPrefs()->SetBoolean(prefs::kAssistPredictiveWritingEnabled, + false); EXPECT_FALSE(assistive_suggester_->IsAssistiveFeatureEnabled()); }
diff --git a/chrome/browser/chromeos/input_method/native_input_method_engine.cc b/chrome/browser/chromeos/input_method/native_input_method_engine.cc index 6554862..ea8a056 100644 --- a/chrome/browser/chromeos/input_method/native_input_method_engine.cc +++ b/chrome/browser/chromeos/input_method/native_input_method_engine.cc
@@ -271,9 +271,11 @@ remote_to_engine_.reset(); receiver_from_engine_.reset(); + // Pass an extra parameter to indicate that this connection is from + // NativeInputMethodEngine. remote_manager_->ConnectToImeEngine( new_engine_id, remote_to_engine_.BindNewPipeAndPassReceiver(), - receiver_from_engine_.BindNewPipeAndPassRemote(), {}, + receiver_from_engine_.BindNewPipeAndPassRemote(), /*extra=*/{0}, base::BindOnce(&ImeObserver::OnConnected, base::Unretained(this), base::Time::Now(), new_engine_id));
diff --git a/chrome/browser/chromeos/net/network_diagnostics/README.md b/chrome/browser/chromeos/net/network_diagnostics/README.md index 908a7d25..8d54f0ae 100644 --- a/chrome/browser/chromeos/net/network_diagnostics/README.md +++ b/chrome/browser/chromeos/net/network_diagnostics/README.md
@@ -195,9 +195,9 @@ and failed to establish a TLS connection to media hostnames. [Network Health and Configuration]: https://docs.google.com/document/d/10DSy-jZXaRo9I9aq1UqERy76t7HkgGvInWk57pHEkzg -[network_diagnostics.mojom]: https://source.chromium.org/chromium/chromium/src/+/master:chromeos/services/network_health/public/mojom/network_diagnostics.mojom?originalUrl=https:%2F%2Fcs.chromium.org%2F -[NetworkHealthService]: https://source.chromium.org/chromium/chromium/src/+/master:chrome/browser/chromeos/net/network_health/network_health_service.h?originalUrl=https:%2F%2Fcs.chromium.org%2F -[here]: https://source.chromium.org/chromium/chromium/src/+/master:chrome/browser/chromeos/net/network_diagnostics/ -[RoutineVerdict]: https://source.chromium.org/chromium/chromium/src/+/master:chromeos/services/network_health/public/mojom/network_diagnostics.mojom;l=12;drc=93304dcbcf58b0af39403af08928ea4e4ec28e6d?originalUrl=https:%2F%2Fcs.chromium.org%2F +[network_diagnostics.mojom]: https://source.chromium.org/chromium/chromium/src/+/main:chromeos/services/network_health/public/mojom/network_diagnostics.mojom?originalUrl=https:%2F%2Fcs.chromium.org%2F +[NetworkHealthService]: https://source.chromium.org/chromium/chromium/src/+/main:chrome/browser/chromeos/net/network_health/network_health_service.h?originalUrl=https:%2F%2Fcs.chromium.org%2F +[here]: https://source.chromium.org/chromium/chromium/src/+/main:chrome/browser/chromeos/net/network_diagnostics/ +[RoutineVerdict]: https://source.chromium.org/chromium/chromium/src/+/main:chromeos/services/network_health/public/mojom/network_diagnostics.mojom;l=12;drc=93304dcbcf58b0af39403af08928ea4e4ec28e6d?originalUrl=https:%2F%2Fcs.chromium.org%2F [Design Doc]: https://docs.google.com/document/d/1d5EoPBlsomWQ4HzqejFPG4v1d2cvPSndj7nmCjNZSSc [src/platform2/diagnostics/mojo/network_diagnostics.mojom]: http://cs/chromeos_public/src/platform2/diagnostics/cros_healthd/network_diagnostics/
diff --git a/chrome/browser/chromeos/net/network_health/README.md b/chrome/browser/chromeos/net/network_health/README.md index 55fedcf6..9670013 100644 --- a/chrome/browser/chromeos/net/network_health/README.md +++ b/chrome/browser/chromeos/net/network_health/README.md
@@ -46,10 +46,10 @@ [Design Doc]: https://docs.google.com/document/d/18ehcBF2iC1rZDo9AV79-qJ5KUfSGIUeqX0bLDRD3XHI/edit?usp=sharing&resourcekey=0-1mYPArwll_OTBaKgQ1qeDw [Network Health and Configuration]: https://docs.google.com/document/d/10DSy-jZXaRo9I9aq1UqERy76t7HkgGvInWk57pHEkzg -[Network Diagnostic Routines]: https://source.chromium.org/chromium/chromium/src/+/master:chrome/browser/chromeos/net/network_diagnostics/README.md -[Network Health telemetry]: https://source.chromium.org/chromium/chromium/src/+/master:chromeos/services/network_health/public/mojom/network_health.mojom +[Network Diagnostic Routines]: https://source.chromium.org/chromium/chromium/src/+/main:chrome/browser/chromeos/net/network_diagnostics/README.md +[Network Health telemetry]: https://source.chromium.org/chromium/chromium/src/+/main:chromeos/services/network_health/public/mojom/network_health.mojom [network_health.mojom]: https://source.chromium.org/chromiumos/chromiumos/codesearch/+/main:src/platform2/diagnostics/mojo/network_health.mojom -[NetworkHealthService]: https://source.chromium.org/chromium/chromium/src/+/master:chrome/browser/chromeos/net/network_health/network_health_service.h +[NetworkHealthService]: https://source.chromium.org/chromium/chromium/src/+/main:chrome/browser/chromeos/net/network_health/network_health_service.h [cros_healthd]: https://source.chromium.org/chromiumos/chromiumos/codesearch/+/main:src/platform2/diagnostics/cros_healthd/ [adding]: https://chromium-review.googlesource.com/c/chromiumos/platform2/+/2627331/8/diagnostics/mojo/cros_healthd.mojom#465
diff --git a/chrome/browser/chromeos/platform_keys/key_permissions/key_permissions_manager_impl.cc b/chrome/browser/chromeos/platform_keys/key_permissions/key_permissions_manager_impl.cc index 48e20dac..bd13a73 100644 --- a/chrome/browser/chromeos/platform_keys/key_permissions/key_permissions_manager_impl.cc +++ b/chrome/browser/chromeos/platform_keys/key_permissions/key_permissions_manager_impl.cc
@@ -154,11 +154,11 @@ case Mode::kMigratePermissionsFromPrefs: { // For more information about choosing |min| and |max| for the histogram, // please refer to: - // https://chromium.googlesource.com/chromium/src/tools/+/refs/heads/master/metrics/histograms/README.md#count-histograms_choosing-min-and-max + // https://chromium.googlesource.com/chromium/src/tools/+/refs/heads/main/metrics/histograms/README.md#count-histograms_choosing-min-and-max // // For more information about choosing the number of |buckets| for the // histogram, please refer to: - // https://chromium.googlesource.com/chromium/src/tools/+/refs/heads/master/metrics/histograms/README.md#count-histograms_choosing-number-of-buckets + // https://chromium.googlesource.com/chromium/src/tools/+/refs/heads/main/metrics/histograms/README.md#count-histograms_choosing-number-of-buckets base::UmaHistogramCustomTimes( kMigrationTimeHistogramName, /*sample=*/base::TimeTicks::Now() - update_start_time_,
diff --git a/chrome/browser/chromeos/policy/status_collector/app_info_generator.cc b/chrome/browser/chromeos/policy/status_collector/app_info_generator.cc index e293060..c5e9a722 100644 --- a/chrome/browser/chromeos/policy/status_collector/app_info_generator.cc +++ b/chrome/browser/chromeos/policy/status_collector/app_info_generator.cc
@@ -234,27 +234,29 @@ provider_->app_service_proxy.InstanceRegistry().ForEachInstance( [this, start_time](const apps::InstanceUpdate& update) { if (update.State() & apps::InstanceState::kStarted) { - OpenUsageInterval(update.AppId(), update.Window(), start_time); + OpenUsageInterval(update.AppId(), update.InstanceKey(), start_time); } }); provider_->app_service_proxy.InstanceRegistry().AddObserver(this); } -void AppInfoGenerator::OpenUsageInterval(const std::string& app_id, - aura::Window* window, - const base::Time start_time) { +void AppInfoGenerator::OpenUsageInterval( + const std::string& app_id, + const apps::Instance::InstanceKey& instance_key, + const base::Time start_time) { if (app_instances_by_id_.count(app_id) == 0) { app_instances_by_id_[app_id] = std::make_unique<AppInstances>(start_time); } - app_instances_by_id_[app_id]->running_instances.insert(window); + app_instances_by_id_[app_id]->running_instances.insert(instance_key); } -void AppInfoGenerator::CloseUsageInterval(const std::string& app_id, - aura::Window* window, - const base::Time end_time) { +void AppInfoGenerator::CloseUsageInterval( + const std::string& app_id, + const apps::Instance::InstanceKey& instance_key, + const base::Time end_time) { if (app_instances_by_id_.count(app_id)) { auto& app_instances = app_instances_by_id_[app_id]; - app_instances->running_instances.erase(window); + app_instances->running_instances.erase(instance_key); if (app_instances->running_instances.empty()) { base::Time start_time = app_instances->start_time; provider_->activity_storage.AddActivityPeriod(start_time, end_time, @@ -270,11 +272,11 @@ } apps::InstanceState state = update.State(); const std::string& app_id = update.AppId(); - aura::Window* window = update.Window(); + auto instance_key = update.InstanceKey(); if (state & apps::InstanceState::kStarted) { - OpenUsageInterval(app_id, window, update.LastUpdatedTime()); + OpenUsageInterval(app_id, instance_key, update.LastUpdatedTime()); } else if (state & apps::InstanceState::kDestroyed) { - CloseUsageInterval(app_id, window, update.LastUpdatedTime()); + CloseUsageInterval(app_id, instance_key, update.LastUpdatedTime()); } }
diff --git a/chrome/browser/chromeos/policy/status_collector/app_info_generator.h b/chrome/browser/chromeos/policy/status_collector/app_info_generator.h index ea139bf..c315a1b 100644 --- a/chrome/browser/chromeos/policy/status_collector/app_info_generator.h +++ b/chrome/browser/chromeos/policy/status_collector/app_info_generator.h
@@ -16,14 +16,11 @@ #include "chrome/browser/chromeos/policy/status_collector/affiliated_session_service.h" #include "chrome/browser/web_applications/web_app_provider.h" #include "components/prefs/pref_registry_simple.h" +#include "components/services/app_service/public/cpp/instance.h" #include "third_party/abseil-cpp/absl/types/optional.h" class Profile; -namespace aura { -class Window; -} // namespace aura - namespace enterprise_management { class AppInfo; } // namespace enterprise_management @@ -84,7 +81,8 @@ ~AppInstances(); const base::Time start_time; - std::unordered_set<aura::Window*> running_instances; + std::unordered_set<apps::Instance::InstanceKey, InstanceKeyHash> + running_instances; }; struct AppInfoProvider { explicit AppInfoProvider(Profile* profile); @@ -106,11 +104,11 @@ void SetIdleDurationsToOpen(); void OpenUsageInterval(const std::string& app_id, - aura::Window* window, + const apps::Instance::InstanceKey& instance_key, const base::Time start_time); void CloseUsageInterval(const std::string& app_id, - aura::Window* window, + const apps::Instance::InstanceKey& instance_key, const base::Time end_time); std::unique_ptr<AppInfoProvider> provider_;
diff --git a/chrome/browser/chromeos/preferences.cc b/chrome/browser/chromeos/preferences.cc index 3cc4e6b..5ef7a41 100644 --- a/chrome/browser/chromeos/preferences.cc +++ b/chrome/browser/chromeos/preferences.cc
@@ -305,6 +305,8 @@ chromeos::prefs::kAssistiveInputFeatureSettings); registry->RegisterBooleanPref(chromeos::prefs::kAssistPersonalInfoEnabled, true); + registry->RegisterBooleanPref( + chromeos::prefs::kAssistPredictiveWritingEnabled, true); registry->RegisterBooleanPref(chromeos::prefs::kEmojiSuggestionEnabled, true); registry->RegisterBooleanPref( chromeos::prefs::kEmojiSuggestionEnterpriseAllowed, true);
diff --git a/chrome/browser/chromeos/smb_client/smb_errors_unittest.cc b/chrome/browser/chromeos/smb_client/smb_errors_unittest.cc index 80b2ceab..356fad4 100644 --- a/chrome/browser/chromeos/smb_client/smb_errors_unittest.cc +++ b/chrome/browser/chromeos/smb_client/smb_errors_unittest.cc
@@ -14,10 +14,9 @@ class SmbErrorsTest : public ::testing::Test { public: SmbErrorsTest() = default; + SmbErrorsTest(const SmbErrorsTest&) = delete; + SmbErrorsTest& operator=(const SmbErrorsTest&) = delete; ~SmbErrorsTest() override = default; - - private: - DISALLOW_COPY_AND_ASSIGN(SmbErrorsTest); }; TEST_F(SmbErrorsTest, SmbErrorToFileError) {
diff --git a/chrome/browser/chromeos/smb_client/smb_file_system.h b/chrome/browser/chromeos/smb_client/smb_file_system.h index 90c33eb..b31f211 100644 --- a/chrome/browser/chromeos/smb_client/smb_file_system.h +++ b/chrome/browser/chromeos/smb_client/smb_file_system.h
@@ -13,7 +13,6 @@ #include "base/callback.h" #include "base/files/file.h" -#include "base/macros.h" #include "base/memory/weak_ptr.h" #include "base/observer_list.h" #include "base/timer/elapsed_timer.h" @@ -66,6 +65,8 @@ UnmountCallback unmount_callback, RequestCredentialsCallback request_creds_callback, RequestUpdatedSharePathCallback request_path_callback); + SmbFileSystem(const SmbFileSystem&) = delete; + SmbFileSystem& operator=(const SmbFileSystem&) = delete; ~SmbFileSystem() override; // ProvidedFileSystemInterface overrides. @@ -373,8 +374,6 @@ RequestUpdatedSharePathCallback request_path_callback_; std::unique_ptr<TempFileManager> temp_file_manager_; mutable SmbTaskQueue task_queue_; - - DISALLOW_COPY_AND_ASSIGN(SmbFileSystem); }; } // namespace smb_client
diff --git a/chrome/browser/chromeos/smb_client/smb_file_system_id_test.cc b/chrome/browser/chromeos/smb_client/smb_file_system_id_test.cc index d19c801..49d5b9b 100644 --- a/chrome/browser/chromeos/smb_client/smb_file_system_id_test.cc +++ b/chrome/browser/chromeos/smb_client/smb_file_system_id_test.cc
@@ -30,10 +30,9 @@ class SmbFileSystemIdTest : public testing::Test { public: SmbFileSystemIdTest() = default; + SmbFileSystemIdTest(const SmbFileSystemIdTest&) = delete; + SmbFileSystemIdTest& operator=(const SmbFileSystemIdTest&) = delete; ~SmbFileSystemIdTest() override = default; - - private: - DISALLOW_COPY_AND_ASSIGN(SmbFileSystemIdTest); }; TEST_F(SmbFileSystemIdTest, ShouldCreateFileSystemIdCorrectly) {
diff --git a/chrome/browser/chromeos/smb_client/smb_kerberos_credentials_updater.h b/chrome/browser/chromeos/smb_client/smb_kerberos_credentials_updater.h index 8bba766..4941c7ab 100644 --- a/chrome/browser/chromeos/smb_client/smb_kerberos_credentials_updater.h +++ b/chrome/browser/chromeos/smb_client/smb_kerberos_credentials_updater.h
@@ -9,7 +9,6 @@ #include <string> #include "base/callback.h" -#include "base/macros.h" #include "chrome/browser/ash/kerberos/kerberos_credentials_manager.h" namespace chromeos { @@ -27,7 +26,9 @@ SmbKerberosCredentialsUpdater( KerberosCredentialsManager* credentials_manager, ActiveAccountChangedCallback active_account_changed_callback); - + SmbKerberosCredentialsUpdater(const SmbKerberosCredentialsUpdater&) = delete; + SmbKerberosCredentialsUpdater& operator=( + const SmbKerberosCredentialsUpdater&) = delete; ~SmbKerberosCredentialsUpdater() override; // Checks if Kerberos is enabled by asking KerberosCredentialsManager. @@ -44,8 +45,6 @@ KerberosCredentialsManager* credentials_manager_; // Not owned. std::string active_account_name_; const ActiveAccountChangedCallback active_account_changed_callback_; - - DISALLOW_COPY_AND_ASSIGN(SmbKerberosCredentialsUpdater); }; } // namespace smb_client
diff --git a/chrome/browser/chromeos/smb_client/smb_provider.h b/chrome/browser/chromeos/smb_client/smb_provider.h index 0f87a22..fbdd703f 100644 --- a/chrome/browser/chromeos/smb_client/smb_provider.h +++ b/chrome/browser/chromeos/smb_client/smb_provider.h
@@ -38,7 +38,10 @@ UnmountCallback unmount_callback, SmbFileSystem::RequestCredentialsCallback request_creds_callback, SmbFileSystem::RequestUpdatedSharePathCallback request_path_callback); + SmbProvider(const SmbProvider&) = delete; + SmbProvider& operator=(const SmbProvider&) = delete; ~SmbProvider() override; + // ProviderInterface overrides. std::unique_ptr<ProvidedFileSystemInterface> CreateProvidedFileSystem( Profile* profile, @@ -59,8 +62,6 @@ UnmountCallback unmount_callback_; SmbFileSystem::RequestCredentialsCallback request_creds_callback_; SmbFileSystem::RequestUpdatedSharePathCallback request_path_callback_; - - DISALLOW_COPY_AND_ASSIGN(SmbProvider); }; } // namespace smb_client
diff --git a/chrome/browser/chromeos/smb_client/smb_service.h b/chrome/browser/chromeos/smb_client/smb_service.h index e6ae955d..274b318b 100644 --- a/chrome/browser/chromeos/smb_client/smb_service.h +++ b/chrome/browser/chromeos/smb_client/smb_service.h
@@ -13,7 +13,6 @@ #include "base/callback.h" #include "base/files/file.h" -#include "base/macros.h" #include "base/memory/weak_ptr.h" #include "base/time/time.h" #include "chrome/browser/ash/file_system_provider/provided_file_system_info.h" @@ -58,6 +57,8 @@ bool done)>; SmbService(Profile* profile, std::unique_ptr<base::TickClock> tick_clock); + SmbService(const SmbService&) = delete; + SmbService& operator=(const SmbService&) = delete; ~SmbService() override; // KeyedService override. @@ -320,8 +321,6 @@ base::OnceClosure setup_complete_callback_; SmbFsShare::MounterCreationCallback smbfs_mounter_creation_callback_; - - DISALLOW_COPY_AND_ASSIGN(SmbService); }; } // namespace smb_client
diff --git a/chrome/browser/chromeos/smb_client/smb_service_factory.h b/chrome/browser/chromeos/smb_client/smb_service_factory.h index d7374fa5..3a17e560 100644 --- a/chrome/browser/chromeos/smb_client/smb_service_factory.h +++ b/chrome/browser/chromeos/smb_client/smb_service_factory.h
@@ -5,7 +5,6 @@ #ifndef CHROME_BROWSER_CHROMEOS_SMB_CLIENT_SMB_SERVICE_FACTORY_H_ #define CHROME_BROWSER_CHROMEOS_SMB_CLIENT_SMB_SERVICE_FACTORY_H_ -#include "base/macros.h" #include "base/memory/singleton.h" #include "components/keyed_service/content/browser_context_keyed_service_factory.h" #include "content/public/browser/browser_context.h" @@ -31,6 +30,8 @@ friend struct base::DefaultSingletonTraits<SmbServiceFactory>; SmbServiceFactory(); + SmbServiceFactory(const SmbServiceFactory&) = delete; + SmbServiceFactory& operator=(const SmbServiceFactory&) = delete; ~SmbServiceFactory() override; // BrowserContextKeyedServiceFactory overrides: @@ -41,8 +42,6 @@ content::BrowserContext* context) const override; void RegisterProfilePrefs( user_prefs::PrefRegistrySyncable* registry) override; - - DISALLOW_COPY_AND_ASSIGN(SmbServiceFactory); }; } // namespace smb_client
diff --git a/chrome/browser/chromeos/smb_client/smb_service_helper_unittest.cc b/chrome/browser/chromeos/smb_client/smb_service_helper_unittest.cc index 11bbb152..c96432d 100644 --- a/chrome/browser/chromeos/smb_client/smb_service_helper_unittest.cc +++ b/chrome/browser/chromeos/smb_client/smb_service_helper_unittest.cc
@@ -14,6 +14,8 @@ class SmbServiceHelperTest : public ::testing::Test { public: SmbServiceHelperTest() = default; + SmbServiceHelperTest(const SmbServiceHelperTest&) = delete; + SmbServiceHelperTest& operator=(const SmbServiceHelperTest&) = delete; ~SmbServiceHelperTest() override = default; protected: @@ -41,9 +43,6 @@ return ::chromeos::smb_client::ParseUserName(down_level_logon_name, &user_name_, &realm_); } - - private: - DISALLOW_COPY_AND_ASSIGN(SmbServiceHelperTest); }; // a@b.c succeeds.
diff --git a/chrome/browser/chromeos/smb_client/smb_share_finder.h b/chrome/browser/chromeos/smb_client/smb_share_finder.h index a95d0e0..2028a51 100644 --- a/chrome/browser/chromeos/smb_client/smb_share_finder.h +++ b/chrome/browser/chromeos/smb_client/smb_share_finder.h
@@ -9,7 +9,6 @@ #include <vector> #include "base/callback.h" -#include "base/macros.h" #include "base/memory/weak_ptr.h" #include "chrome/browser/chromeos/smb_client/discovery/host_locator.h" #include "chrome/browser/chromeos/smb_client/discovery/network_scanner.h" @@ -31,6 +30,8 @@ base::OnceCallback<void(const std::vector<SmbUrl>& shares_gathered)>; explicit SmbShareFinder(SmbProviderClient* client); + SmbShareFinder(const SmbShareFinder&) = delete; + SmbShareFinder& operator=(const SmbShareFinder&) = delete; ~SmbShareFinder(); // Gathers the hosts in the network using |scanner_| and gets the shares for @@ -103,8 +104,6 @@ std::vector<GatherSharesInNetworkResponse> share_callbacks_; std::vector<SmbUrl> shares_; - - DISALLOW_COPY_AND_ASSIGN(SmbShareFinder); }; } // namespace smb_client
diff --git a/chrome/browser/chromeos/smb_client/smb_share_finder_unittest.cc b/chrome/browser/chromeos/smb_client/smb_share_finder_unittest.cc index aacb6d0..e9d65706a 100644 --- a/chrome/browser/chromeos/smb_client/smb_share_finder_unittest.cc +++ b/chrome/browser/chromeos/smb_client/smb_share_finder_unittest.cc
@@ -34,7 +34,8 @@ SmbShareFinderTest() { SetupShareFinderTest(true /* should_run_synchronously */); } - + SmbShareFinderTest(const SmbShareFinderTest&) = delete; + SmbShareFinderTest& operator=(const SmbShareFinderTest&) = delete; ~SmbShareFinderTest() override = default; protected: @@ -176,8 +177,6 @@ InMemoryHostLocator* host_locator_; std::unique_ptr<FakeSmbProviderClient> fake_client_; std::unique_ptr<SmbShareFinder> share_finder_; - - DISALLOW_COPY_AND_ASSIGN(SmbShareFinderTest); }; TEST_F(SmbShareFinderTest, NoSharesFoundWithNoHosts) {
diff --git a/chrome/browser/chromeos/smb_client/smb_task_queue.h b/chrome/browser/chromeos/smb_client/smb_task_queue.h index b34cc3b1..66461ef 100644 --- a/chrome/browser/chromeos/smb_client/smb_task_queue.h +++ b/chrome/browser/chromeos/smb_client/smb_task_queue.h
@@ -48,6 +48,11 @@ // } class SmbTaskQueue { public: + explicit SmbTaskQueue(size_t max_pending); + SmbTaskQueue(const SmbTaskQueue&) = delete; + SmbTaskQueue& operator=(const SmbTaskQueue&) = delete; + ~SmbTaskQueue(); + // Provides the caller with a new OperationId to associate new tasks with. OperationId GetNextOperationId(); @@ -67,9 +72,6 @@ // task was received. void TaskFinished(); - explicit SmbTaskQueue(size_t max_pending); - ~SmbTaskQueue(); - private: using TaskList = base::queue<SmbTask>; @@ -107,8 +109,6 @@ OperationId next_operation_id = 0; base::queue<OperationId> operations_; std::map<OperationId, TaskList> operation_map_; - - DISALLOW_COPY_AND_ASSIGN(SmbTaskQueue); }; } // namespace smb_client
diff --git a/chrome/browser/chromeos/smb_client/smb_task_queue_unittest.cc b/chrome/browser/chromeos/smb_client/smb_task_queue_unittest.cc index 1799913..596f3fb 100644 --- a/chrome/browser/chromeos/smb_client/smb_task_queue_unittest.cc +++ b/chrome/browser/chromeos/smb_client/smb_task_queue_unittest.cc
@@ -25,6 +25,8 @@ class SmbTaskQueueTest : public testing::Test { public: SmbTaskQueueTest() : task_queue_(kTaskQueueCapacity) {} + SmbTaskQueueTest(const SmbTaskQueueTest&) = delete; + SmbTaskQueueTest& operator=(const SmbTaskQueueTest&) = delete; ~SmbTaskQueueTest() override = default; protected: @@ -80,7 +82,6 @@ SmbTaskQueue task_queue_; std::map<uint32_t, base::OnceClosure> pending_; - DISALLOW_COPY_AND_ASSIGN(SmbTaskQueueTest); }; // SmbTaskQueue immediately runs a task when less than max_pending are running.
diff --git a/chrome/browser/chromeos/smb_client/smb_url_unittest.cc b/chrome/browser/chromeos/smb_client/smb_url_unittest.cc index c143ab9..57a79c8 100644 --- a/chrome/browser/chromeos/smb_client/smb_url_unittest.cc +++ b/chrome/browser/chromeos/smb_client/smb_url_unittest.cc
@@ -6,7 +6,6 @@ #include <string> -#include "base/macros.h" #include "chrome/browser/chromeos/smb_client/smb_constants.h" #include "testing/gtest/include/gtest/gtest.h" @@ -16,6 +15,8 @@ class SmbUrlTest : public testing::Test { public: SmbUrlTest() = default; + SmbUrlTest(const SmbUrlTest&) = delete; + SmbUrlTest& operator=(const SmbUrlTest&) = delete; ~SmbUrlTest() override = default; void ExpectInvalidUrl(const std::string& url) { @@ -40,9 +41,6 @@ EXPECT_TRUE(smb_url.IsValid()); EXPECT_EQ(expected_unc, smb_url.GetWindowsUNCString()); } - - private: - DISALLOW_COPY_AND_ASSIGN(SmbUrlTest); }; TEST_F(SmbUrlTest, EmptyUrlIsInvalid) {
diff --git a/chrome/browser/chromeos/smb_client/temp_file_manager.h b/chrome/browser/chromeos/smb_client/temp_file_manager.h index 7812a5f..e9fa994 100644 --- a/chrome/browser/chromeos/smb_client/temp_file_manager.h +++ b/chrome/browser/chromeos/smb_client/temp_file_manager.h
@@ -19,6 +19,8 @@ class TempFileManager { public: TempFileManager(); + TempFileManager(const TempFileManager&) = delete; + TempFileManager& operator=(const TempFileManager&) = delete; ~TempFileManager(); // Returns the path of the temporary directory. @@ -37,8 +39,6 @@ // Scoped class that handles deletion of the temporary directory. base::ScopedTempDir temp_dir_; - - DISALLOW_COPY_AND_ASSIGN(TempFileManager); }; } // namespace smb_client
diff --git a/chrome/browser/chromeos/smb_client/temp_file_manager_unittest.cc b/chrome/browser/chromeos/smb_client/temp_file_manager_unittest.cc index a385787..c71ed53 100644 --- a/chrome/browser/chromeos/smb_client/temp_file_manager_unittest.cc +++ b/chrome/browser/chromeos/smb_client/temp_file_manager_unittest.cc
@@ -26,10 +26,9 @@ class TempFileManagerTest : public testing::Test { public: TempFileManagerTest() = default; + TempFileManagerTest(const TempFileManagerTest&) = delete; + TempFileManagerTest& operator=(const TempFileManagerTest&) = delete; ~TempFileManagerTest() override = default; - - private: - DISALLOW_COPY_AND_ASSIGN(TempFileManagerTest); }; // Should properly create a path when the object is created.
diff --git a/chrome/browser/chromeos/system_token_cert_db_initializer.h b/chrome/browser/chromeos/system_token_cert_db_initializer.h index 61d432a9..4ab1016 100644 --- a/chrome/browser/chromeos/system_token_cert_db_initializer.h +++ b/chrome/browser/chromeos/system_token_cert_db_initializer.h
@@ -28,7 +28,7 @@ public: // It is stated in cryptohome implementation that 5 minutes is enough time to // wait for any TPM operations. For more information, please refer to: - // https://chromium.googlesource.com/chromiumos/platform2/+/master/cryptohome/cryptohome.cc + // https://chromium.googlesource.com/chromiumos/platform2/+/main/cryptohome/cryptohome.cc static constexpr base::TimeDelta kMaxCertDbRetrievalDelay = base::TimeDelta::FromMinutes(5);
diff --git a/chrome/browser/custom_handlers/protocol_handler_registry.cc b/chrome/browser/custom_handlers/protocol_handler_registry.cc index 70c38fd..041ab36b 100644 --- a/chrome/browser/custom_handlers/protocol_handler_registry.cc +++ b/chrome/browser/custom_handlers/protocol_handler_registry.cc
@@ -25,6 +25,7 @@ #include "components/user_prefs/user_prefs.h" #include "content/public/browser/child_process_security_policy.h" #include "third_party/abseil-cpp/absl/types/optional.h" +#include "third_party/blink/public/common/security/protocol_handler_security_level.h" using content::BrowserThread; using content::ChildProcessSecurityPolicy; @@ -117,6 +118,30 @@ ->StartCheckIsDefault(std::move(callback)); } +void ProtocolHandlerRegistry::Delegate::RegisterAppProtocolsWithOS( + const base::FilePath& app_profile_path, + const shell_integration::AppProtocolMap app_protocols, + base::OnceCallback<void(bool)> registration_complete_callback) { + shell_integration::AddAppProtocolClients( + app_protocols, app_profile_path, + std::move(registration_complete_callback)); +} + +void ProtocolHandlerRegistry::Delegate::DeregisterAppProtocolsWithOS( + const base::FilePath& app_profile_path, + const std::vector<std::string>& app_protocols) { + shell_integration::RemoveAppProtocolClients(app_protocols, app_profile_path); +} + +void ProtocolHandlerRegistry::Delegate::CheckAppIsDefaultClientWithOS( + const std::string& app_id, + const base::FilePath& app_profile_path, + const std::string& protocol, + base::OnceCallback<void(bool)> check_complete_callback) { + shell_integration::CheckAppIsProtocolClient( + app_id, protocol, app_profile_path, std::move(check_complete_callback)); +} + // ProtocolHandlerRegistry ----------------------------------------------------- ProtocolHandlerRegistry::ProtocolHandlerRegistry( @@ -168,6 +193,50 @@ NotifyChanged(); } +void ProtocolHandlerRegistry::RegisterAppProtocolHandlers( + const std::string& app_id, + const std::vector<apps::ProtocolHandlerInfo>& handler_infos) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + + std::vector<std::string> app_protocols; + + for (const auto& handler_info : handler_infos) { + ProtocolHandler handler = ProtocolHandler::CreateWebAppProtocolHandler( + handler_info.protocol, handler_info.url, app_id); + if (!handler.IsValid() || !RegisterProtocolHandler(handler, USER)) + continue; + + app_protocols.push_back(handler.protocol()); + + ProtocolHandler default_handler = GetHandlerFor(handler.protocol()); + if (default_handler.IsEmpty()) { + SetDefaultImpl(handler); + } + } + + UpdateAppProtocolsWithOS(app_protocols); + + Save(); + NotifyChanged(); +} + +void ProtocolHandlerRegistry::DeregisterAppProtocolHandlers( + const std::string& app_id, + const std::vector<apps::ProtocolHandlerInfo>& handler_infos) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + + std::vector<ProtocolHandler> handlers; + for (const auto& handler_info : handler_infos) { + ProtocolHandler handler = ProtocolHandler::CreateWebAppProtocolHandler( + handler_info.protocol, handler_info.url, app_id); + if (HandlerExists(handler, &protocol_handlers_)) { + handlers.push_back(handler); + } + } + + RemoveHandlers(handlers); +} + bool ProtocolHandlerRegistry::AttemptReplace(const ProtocolHandler& handler) { DCHECK_CURRENTLY_ON(BrowserThread::UI); ProtocolHandler old_default = GetHandlerFor(handler.protocol()); @@ -262,8 +331,15 @@ for (ProtocolHandlerMap::const_iterator p = default_handlers_.begin(); p != default_handlers_.end(); ++p) { const std::string& protocol = p->second.protocol(); - delegate_->CheckDefaultClientWithOS( - protocol, GetDefaultWebClientCallback(protocol)); + if (p->second.web_app_id()) { + std::string app_id = p->second.web_app_id().value(); + delegate_->CheckAppIsDefaultClientWithOS( + app_id, context_->GetPath(), protocol, + GetAppProtocolWorkerCallback({{protocol, app_id}})); + } else { + delegate_->CheckDefaultClientWithOS( + protocol, GetDefaultWebClientCallback(protocol)); + } } } } @@ -444,37 +520,82 @@ } void ProtocolHandlerRegistry::RemoveHandler(const ProtocolHandler& handler) { - if (IsIgnored(handler)) { - RemoveIgnoredHandler(handler); - return; + RemoveHandlers({handler}); +} + +void ProtocolHandlerRegistry::RemoveHandlers( + const std::vector<ProtocolHandler>& handlers) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + + std::vector<ProtocolHandler> erased_handlers; + std::vector<std::string> app_protocols_to_remove_from_os; + + for (const auto& handler : handlers) { + if (IsIgnored(handler)) { + RemoveIgnoredHandler(handler); + continue; + } + + ProtocolHandlerList& existing_handlers = + protocol_handlers_[handler.protocol()]; + bool erase_success = false; + if (HandlerExists(handler, existing_handlers) && + HandlerExists(handler, &user_protocol_handlers_)) { + EraseHandler(handler, &user_protocol_handlers_); + erase_success = true; + if (!HandlerExists(handler, &policy_protocol_handlers_)) + EraseHandler(handler, &protocol_handlers_); + } + + if (!erase_success) + continue; + else + erased_handlers.push_back(handler); } - DCHECK_CURRENTLY_ON(BrowserThread::UI); - ProtocolHandlerList& handlers = protocol_handlers_[handler.protocol()]; - bool erase_success = false; - if (HandlerExists(handler, handlers) && - HandlerExists(handler, &user_protocol_handlers_)) { - EraseHandler(handler, &user_protocol_handlers_); - erase_success = true; - if (!HandlerExists(handler, &policy_protocol_handlers_)) - EraseHandler(handler, &protocol_handlers_); - } - auto q = default_handlers_.find(handler.protocol()); - if (erase_success && q != default_handlers_.end() && q->second == handler) { - // Make the new top handler in the list the default. - if (!handlers.empty()) { - // NOTE We pass a copy because SetDefault() modifies handlers. - SetDefault(ProtocolHandler(handlers[0])); - } else { - default_handlers_.erase(q); + std::vector<ProtocolHandler> updated_default_handlers; + + // Choose new defaults for erased handlers that were default handlers. + for (const auto& erased_handler : erased_handlers) { + ProtocolHandlerList& existing_handlers = + protocol_handlers_[erased_handler.protocol()]; + ProtocolHandler default_handler = GetHandlerFor(erased_handler.protocol()); + if (default_handler == erased_handler || erased_handler.web_app_id()) { + // Removing the default handler for a protocol requires updating the + // default registration. If the default handler is a web app handler, its + // removal may require updating the the default registration as the + // protocol may no longer require disambiguation (i.e.: if a single app is + // left as a handler for a protocol, it should be registered with the OS + // instead). + if (!existing_handlers.empty()) { + updated_default_handlers.push_back(existing_handlers[0]); + } else { + default_handlers_.erase(erased_handler.protocol()); + } + } + + // TODO(1132105): Implement DeregisterExternalHandler so that websites can + // be unregistered with the OS. Alternatively, expand + // DeregisterAppProtocolsWithOS's scope to work with non-app protocols. + if (!IsHandledProtocol(erased_handler.protocol())) { + delegate_->DeregisterExternalHandler(erased_handler.protocol()); + } + + if (GetHandlerFor(erased_handler.protocol()).IsEmpty() && + erased_handler.web_app_id()) { + // Web app protocols are removed from the OS when the protocol no longer + // has a default handler. + app_protocols_to_remove_from_os.push_back(erased_handler.protocol()); } } - if (erase_success && !IsHandledProtocol(handler.protocol())) { - delegate_->DeregisterExternalHandler(handler.protocol()); - } + SetDefaults(updated_default_handlers); + if (!app_protocols_to_remove_from_os.empty()) + delegate_->DeregisterAppProtocolsWithOS(context_->GetPath(), + app_protocols_to_remove_from_os); + Save(); - if (erase_success) + if (!erased_handlers.empty()) NotifyChanged(); } @@ -593,18 +714,43 @@ } void ProtocolHandlerRegistry::SetDefault(const ProtocolHandler& handler) { + SetDefaults({handler}); +} + +void ProtocolHandlerRegistry::SetDefaults( + const std::vector<ProtocolHandler>& handlers) { DCHECK_CURRENTLY_ON(BrowserThread::UI); + for (const auto& handler : handlers) { + SetDefaultImpl(handler); + } + + if (is_loading_) + return; + + // Separate site handlers from web app handlers so that web app handlers can + // be registered to the OS in a batch operation. + std::vector<std::string> app_protocols; + for (const auto& handler : handlers) { + if (handler.web_app_id()) { + app_protocols.push_back(handler.protocol()); + } else { + delegate_->RegisterWithOSAsDefaultClient( + handler.protocol(), GetDefaultWebClientCallback(handler.protocol())); + } + } + + UpdateAppProtocolsWithOS(app_protocols); + + Save(); + NotifyChanged(); +} + +void ProtocolHandlerRegistry::SetDefaultImpl(const ProtocolHandler& handler) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); const std::string& protocol = handler.protocol(); - ProtocolHandlerMap::const_iterator p = default_handlers_.find(protocol); - // If we're not loading, and we are setting a default for a new protocol, - // register with the OS. - if (!is_loading_ && p == default_handlers_.end()) - delegate_->RegisterWithOSAsDefaultClient( - protocol, GetDefaultWebClientCallback(protocol)); default_handlers_.erase(protocol); default_handlers_.insert(std::make_pair(protocol, handler)); - PromoteHandler(handler); } @@ -767,6 +913,30 @@ list->erase(std::find(list->begin(), list->end(), handler)); } +void ProtocolHandlerRegistry::UpdateAppProtocolsWithOS( + const std::vector<std::string>& protocols) { + if (protocols.empty()) + return; + + shell_integration::AppProtocolMap app_protocols; + + for (const auto& protocol : protocols) { + ProtocolHandler default_handler = GetHandlerFor(protocol); + ProtocolHandlerList handlers = protocol_handlers_[protocol]; + // If other handlers exist for the protocol, the protocol will be + // registered for disambiguation (i.e.: the browser will be registered + // with the OS as the handler instead of the app). + if (handlers.size() == 1 && handlers[0] == default_handler) + app_protocols[protocol] = default_handler.web_app_id(); + else + app_protocols[protocol] = absl::nullopt; + } + + delegate_->RegisterAppProtocolsWithOS( + context_->GetPath(), app_protocols, + GetAppProtocolWorkerCallback(app_protocols)); +} + void ProtocolHandlerRegistry::OnSetAsDefaultProtocolClientFinished( const std::string& protocol, shell_integration::DefaultWebClientState state) { @@ -793,3 +963,21 @@ &ProtocolHandlerRegistry::OnSetAsDefaultProtocolClientFinished, weak_ptr_factory_.GetWeakPtr(), protocol); } + +void ProtocolHandlerRegistry::OnAppProtocolOperationFinished( + const shell_integration::AppProtocolMap& app_protocols, + bool registration_success) { + // Clear if the protocol could not be registered + if (ShouldRemoveHandlersNotInOS() && !registration_success) { + for (const auto& app_protocol_pair : app_protocols) + ClearDefault(app_protocol_pair.first); + } +} + +base::OnceCallback<void(bool)> +ProtocolHandlerRegistry::GetAppProtocolWorkerCallback( + const shell_integration::AppProtocolMap& app_protocols) { + return base::BindOnce( + &ProtocolHandlerRegistry::OnAppProtocolOperationFinished, + weak_ptr_factory_.GetWeakPtr(), app_protocols); +}
diff --git a/chrome/browser/custom_handlers/protocol_handler_registry.h b/chrome/browser/custom_handlers/protocol_handler_registry.h index ab449ca..ab76f62 100644 --- a/chrome/browser/custom_handlers/protocol_handler_registry.h +++ b/chrome/browser/custom_handlers/protocol_handler_registry.h
@@ -19,6 +19,7 @@ #include "chrome/browser/shell_integration.h" #include "chrome/common/custom_handlers/protocol_handler.h" #include "components/keyed_service/core/keyed_service.h" +#include "components/services/app_service/public/cpp/protocol_handler_info.h" #include "content/public/browser/browser_thread.h" namespace user_prefs { @@ -41,9 +42,9 @@ typedef std::vector<ProtocolHandler> ProtocolHandlerList; typedef std::map<std::string, ProtocolHandlerList> ProtocolHandlerMultiMap; - // |Delegate| provides an interface for interacting asynchronously - // with the underlying OS for the purposes of registering Chrome - // as the default handler for specific protocols. + // |Delegate| provides an interface for interacting asynchronously with the + // underlying OS for the purposes of registering Chrome and web apps as + // default handlers for specific protocols. class Delegate { public: virtual ~Delegate(); @@ -56,6 +57,18 @@ virtual void CheckDefaultClientWithOS( const std::string& protocol, shell_integration::DefaultWebClientWorkerCallback callback); + virtual void RegisterAppProtocolsWithOS( + const base::FilePath& app_profile_path, + const shell_integration::AppProtocolMap app_protocols, + base::OnceCallback<void(bool)> registration_complete_callback); + virtual void DeregisterAppProtocolsWithOS( + const base::FilePath& app_profile_path, + const std::vector<std::string>& app_protocols); + virtual void CheckAppIsDefaultClientWithOS( + const std::string& app_id, + const base::FilePath& app_profile_path, + const std::string& protocol, + base::OnceCallback<void(bool)> check_complete_callback); }; class Observer : public base::CheckedObserver { @@ -87,6 +100,18 @@ // given protocol handler again. void OnIgnoreRegisterProtocolHandler(const ProtocolHandler& handler); + // Registers each web app protocol handler as a non default handler if another + // handler exists for its scheme or as a default handler for uncontested + // schemes. + void RegisterAppProtocolHandlers( + const std::string& app_id, + const std::vector<apps::ProtocolHandlerInfo>& handler_infos); + + // Removes each web app protocol handler from the registry and OS. + void DeregisterAppProtocolHandlers( + const std::string& app_id, + const std::vector<apps::ProtocolHandlerInfo>& handler_infos); + // Removes all handlers that have the same origin and protocol as the given // one and installs the given handler. Returns true if any protocol handlers // were replaced. @@ -163,6 +188,9 @@ // Removes the given protocol handler from the registry. void RemoveHandler(const ProtocolHandler& handler); + // Removes multiple protocol handlers from the registry. + void RemoveHandlers(const std::vector<ProtocolHandler>& handlers); + // Remove the default handler for the given protocol. void RemoveDefaultHandler(const std::string& scheme); @@ -224,6 +252,13 @@ // Makes this ProtocolHandler the default handler for its protocol. void SetDefault(const ProtocolHandler& handler); + // Makes these ProtocolHandler the default handlers for their protocols and + // registers the handlers with the OS. + void SetDefaults(const std::vector<ProtocolHandler>& handlers); + + // Makes a handler the default for its protocol inside the registry. + void SetDefaultImpl(const ProtocolHandler& handler); + // Insert the given ProtocolHandler into the registry. void InsertHandler(const ProtocolHandler& handler); @@ -284,6 +319,13 @@ // Erases the handler that is guaranteed to exist from the list. void EraseHandler(const ProtocolHandler& handler, ProtocolHandlerList* list); + // Updates the OS registration for each protocol based on the registry state + // of corresponding app handlers. For each protocol, the resulting OS + // registration may be the associated app, the browser (for disambiguation), + // or no registration if the app handler is not present in the registry. + // |protocols| is expected to contain a list of unique protocols. + void UpdateAppProtocolsWithOS(const std::vector<std::string>& protocols); + // Called with the default state when the default protocol client worker is // done. void OnSetAsDefaultProtocolClientFinished( @@ -294,6 +336,16 @@ shell_integration::DefaultWebClientWorkerCallback GetDefaultWebClientCallback( const std::string& protocol); + // Called with success flag when an asynchronous app protocols operation is + // complete. + void OnAppProtocolOperationFinished( + const shell_integration::AppProtocolMap& app_protocols, + bool operation_success); + + // Gets the callback for AppProtocolWorkerCallback. + base::OnceCallback<void(bool)> GetAppProtocolWorkerCallback( + const shell_integration::AppProtocolMap& protocols); + // Map from protocols (strings) to protocol handlers. ProtocolHandlerMultiMap protocol_handlers_;
diff --git a/chrome/browser/custom_handlers/protocol_handler_registry_unittest.cc b/chrome/browser/custom_handlers/protocol_handler_registry_unittest.cc index a23c107f..88e88e1 100644 --- a/chrome/browser/custom_handlers/protocol_handler_registry_unittest.cc +++ b/chrome/browser/custom_handlers/protocol_handler_registry_unittest.cc
@@ -15,6 +15,7 @@ #include "base/scoped_observation.h" #include "base/strings/utf_string_conversions.h" #include "base/task/post_task.h" +#include "base/task/thread_pool/thread_pool_instance.h" #include "base/threading/thread_task_runner_handle.h" #include "build/build_config.h" #include "chrome/common/custom_handlers/protocol_handler.h" @@ -28,6 +29,7 @@ #include "content/public/test/test_renderer_host.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/public/common/security/protocol_handler_security_level.h" +#include "url/gurl.h" using content::BrowserThread; @@ -90,9 +92,43 @@ os_registered_protocols_.end(); } + void RegisterAppProtocolsWithOS( + const base::FilePath& app_profile_path, + const shell_integration::AppProtocolMap app_protocols, + base::OnceCallback<void(bool)> registration_complete_callback) override { + // Do as-if the registration has to run on another sequence and post back + // the result with a task to the current thread. + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::BindOnce(std::move(registration_complete_callback), + !force_os_failure_)); + + if (!force_os_failure_) { + for (const auto& protocol_pair : app_protocols) { + os_registered_app_protocols_[protocol_pair.first] = + protocol_pair.second; + } + } + } + + void DeregisterAppProtocolsWithOS( + const base::FilePath& app_profile_path, + const std::vector<std::string>& app_protocols) override { + for (const auto& protocol : app_protocols) { + os_registered_app_protocols_.erase(protocol); + } + } + + bool IsFakeAppHandlerRegisteredWithOS(const std::string& protocol, + absl::optional<std::string> app_id) { + auto handler_iter = os_registered_app_protocols_.find(protocol); + return handler_iter != os_registered_app_protocols_.end() && + handler_iter->second == app_id; + } + void Reset() { registered_protocols_.clear(); os_registered_protocols_.clear(); + os_registered_app_protocols_.clear(); force_os_failure_ = false; } @@ -103,6 +139,7 @@ private: std::set<std::string> registered_protocols_; std::set<std::string> os_registered_protocols_; + shell_integration::AppProtocolMap os_registered_app_protocols_; bool force_os_failure_; }; @@ -157,6 +194,21 @@ DISALLOW_COPY_AND_ASSIGN(QueryProtocolHandlerOnChange); }; +apps::ProtocolHandlerInfo GetProtocolHandlerInfo(const std::string& protocol, + const GURL& url) { + apps::ProtocolHandlerInfo handler_info; + handler_info.protocol = protocol; + handler_info.url = url; + return handler_info; +} + +ProtocolHandler GetProtocolHandler( + const apps::ProtocolHandlerInfo& handler_info, + const std::string& app_id) { + return ProtocolHandler::CreateWebAppProtocolHandler(handler_info.protocol, + handler_info.url, app_id); +} + } // namespace class ProtocolHandlerRegistryTest : public testing::Test { @@ -343,6 +395,7 @@ ProtocolHandler::CreateProtocolHandler(value.get()); EXPECT_EQ("news", recreated.protocol()); EXPECT_EQ(GURL("https://example.com"), recreated.url()); + EXPECT_EQ("app_id", recreated.web_app_id()); EXPECT_EQ(now, recreated.last_modified()); } @@ -1235,3 +1288,162 @@ "ext+foo", https_handler_url, blink::ProtocolHandlerSecurityLevel::kExtensionFeatures)); } + +TEST_F(ProtocolHandlerRegistryTest, TestRegisterWebAppHandlers) { + EXPECT_FALSE(delegate()->IsExternalHandlerRegistered("mailto")); + EXPECT_FALSE(delegate()->IsExternalHandlerRegistered("web+test")); + + apps::ProtocolHandlerInfo ph1_info = + GetProtocolHandlerInfo("mailto", GURL("https://test1.com/%s")); + ProtocolHandler ph1 = GetProtocolHandler(ph1_info, "app_id1"); + + apps::ProtocolHandlerInfo ph2_info = + GetProtocolHandlerInfo("web+test", GURL("https://test2.com/%s")); + ProtocolHandler ph2 = GetProtocolHandler(ph2_info, "app_id1"); + + registry()->RegisterAppProtocolHandlers("app_id1", {ph1_info, ph2_info}); + + // After registration, both handlers should be externally registered with the + // OS and registered as defaults in the ProtocolHandlerRegistsry. + EXPECT_TRUE(delegate()->IsExternalHandlerRegistered("mailto")); + EXPECT_TRUE(delegate()->IsExternalHandlerRegistered("web+test")); + + EXPECT_TRUE(registry()->IsRegistered(ph1)); + EXPECT_TRUE(registry()->IsDefault(ph1)); + EXPECT_TRUE(delegate()->IsFakeAppHandlerRegisteredWithOS(ph1.protocol(), + ph1.web_app_id())); + + EXPECT_TRUE(registry()->IsRegistered(ph2)); + EXPECT_TRUE(registry()->IsDefault(ph2)); + EXPECT_TRUE(delegate()->IsFakeAppHandlerRegisteredWithOS(ph2.protocol(), + ph2.web_app_id())); +} + +TEST_F(ProtocolHandlerRegistryTest, + TestDuplicateSchemeAppHandlersAreNonDefault) { + ProtocolHandler ph1 = ProtocolHandler::CreateProtocolHandler( + "mailto", GURL("https://test1.com/%s")); + registry()->OnAcceptRegisterProtocolHandler(ph1); + + EXPECT_TRUE(registry()->IsRegistered(ph1)); + EXPECT_TRUE(registry()->IsDefault(ph1)); + EXPECT_TRUE(delegate()->IsFakeRegisteredWithOS(ph1.protocol())); + + apps::ProtocolHandlerInfo ph2_info = + GetProtocolHandlerInfo("mailto", GURL("https://test2.com/%s")); + ProtocolHandler ph2 = GetProtocolHandler(ph2_info, "app_id1"); + + registry()->RegisterAppProtocolHandlers("app_id1", {ph2_info}); + + // Because ph2 was registered second and has the same scheme as ph1, it should + // be registered as non default with the ProtocolHandlerRegistry and not + // registered with the OS. + EXPECT_TRUE(registry()->IsRegistered(ph2)); + EXPECT_FALSE(registry()->IsDefault(ph2)); + EXPECT_FALSE(delegate()->IsFakeAppHandlerRegisteredWithOS(ph2.protocol(), + ph2.web_app_id())); +} + +TEST_F(ProtocolHandlerRegistryTest, + TestDuplicateSchemeAppHandlersAreRegisteredForDisambiguation) { + apps::ProtocolHandlerInfo ph1_info = + GetProtocolHandlerInfo("mailto", GURL("https://test1.com/%s")); + ProtocolHandler ph1 = GetProtocolHandler(ph1_info, "app_id1"); + + registry()->RegisterAppProtocolHandlers("app_id1", {ph1_info}); + EXPECT_TRUE( + delegate()->IsFakeAppHandlerRegisteredWithOS(ph1.protocol(), "app_id1")); + + apps::ProtocolHandlerInfo ph2_info = + GetProtocolHandlerInfo("mailto", GURL("https://test2.com/%s")); + ProtocolHandler ph2 = GetProtocolHandler(ph2_info, "app_id2"); + + registry()->RegisterAppProtocolHandlers("app_id2", {ph2_info}); + // The protocol should be registered for disambiguation with a null app_id. + EXPECT_TRUE(delegate()->IsFakeAppHandlerRegisteredWithOS(ph2.protocol(), + absl::nullopt)); +} + +TEST_F(ProtocolHandlerRegistryTest, TestRemoveWebAppHandlers) { + // Register a single handler for web+testing and multiple handlers for mailto. + apps::ProtocolHandlerInfo ph1_info = + GetProtocolHandlerInfo("mailto", GURL("https://test1.com/%s")); + ProtocolHandler ph1 = GetProtocolHandler(ph1_info, "app_id1"); + apps::ProtocolHandlerInfo ph2_info = + GetProtocolHandlerInfo("web+testing", GURL("https://test1.com/%s")); + ProtocolHandler ph2 = GetProtocolHandler(ph2_info, "app_id1"); + registry()->RegisterAppProtocolHandlers("app_id1", {ph1_info, ph2_info}); + + apps::ProtocolHandlerInfo ph3_info = + GetProtocolHandlerInfo("mailto", GURL("https://test2.com/%s")); + ProtocolHandler ph3 = GetProtocolHandler(ph3_info, "app_id2"); + registry()->RegisterAppProtocolHandlers("app_id2", {ph3_info}); + + EXPECT_TRUE( + delegate()->IsFakeAppHandlerRegisteredWithOS("mailto", absl::nullopt)); + EXPECT_TRUE( + delegate()->IsFakeAppHandlerRegisteredWithOS("web+testing", "app_id1")); + + // Deregister a single handler for both web+testing and mailto, leaving no + // registered web+testing and handlers and one registered mailto handler. + registry()->DeregisterAppProtocolHandlers("app_id1", {ph1_info, ph2_info}); + + EXPECT_FALSE(registry()->IsRegistered(ph1)); + EXPECT_FALSE(registry()->IsRegistered(ph2)); + EXPECT_TRUE(registry()->IsRegistered(ph3)); + EXPECT_TRUE(registry()->IsDefault(ph3)); + + // web+testing should be removed from the OS while mailto should remain + // registered with the OS since ph3 was promoted to default. + EXPECT_FALSE( + delegate()->IsFakeAppHandlerRegisteredWithOS("web+testing", "app_id1")); + EXPECT_FALSE(delegate()->IsExternalHandlerRegistered("web+testing")); + EXPECT_TRUE( + delegate()->IsFakeAppHandlerRegisteredWithOS("mailto", "app_id2")); + EXPECT_TRUE(delegate()->IsExternalHandlerRegistered("mailto")); +} + +TEST_F(ProtocolHandlerRegistryTest, + TestRemovingNonDefaultHandlerUpdatesDefault) { + // Register multiple handlers for mailto and ensure the protocol is registered + // for disambiguation. + apps::ProtocolHandlerInfo ph1_info = + GetProtocolHandlerInfo("mailto", GURL("https://test1.com/%s")); + ProtocolHandler ph1 = GetProtocolHandler(ph1_info, "app_id1"); + registry()->RegisterAppProtocolHandlers("app_id1", {ph1_info}); + + apps::ProtocolHandlerInfo ph2_info = + GetProtocolHandlerInfo("mailto", GURL("https://test2.com/%s")); + ProtocolHandler ph2 = GetProtocolHandler(ph2_info, "app_id2"); + registry()->RegisterAppProtocolHandlers("app_id2", {ph2_info}); + + ASSERT_TRUE( + delegate()->IsFakeAppHandlerRegisteredWithOS("mailto", absl::nullopt)); + + // Remove the non default handler (ph2) and test that the protocol is handled + // by ph1 and no longer registered for disambiguation. + registry()->DeregisterAppProtocolHandlers("app_id2", {ph2_info}); + + EXPECT_TRUE( + delegate()->IsFakeAppHandlerRegisteredWithOS("mailto", "app_id1")); +} + +TEST_F(ProtocolHandlerRegistryTest, TestRegisterHandlersWithOSFailure) { + delegate()->set_force_os_failure(true); + + apps::ProtocolHandlerInfo ph1_info = + GetProtocolHandlerInfo("mailto", GURL("https://test1.com/%s")); + ProtocolHandler ph1 = GetProtocolHandler(ph1_info, "app_id1"); + registry()->RegisterAppProtocolHandlers("app_id1", {ph1_info}); + base::RunLoop().RunUntilIdle(); + base::ThreadPoolInstance::Get()->FlushForTesting(); + + EXPECT_TRUE(delegate()->IsExternalHandlerRegistered(ph1.protocol())); + EXPECT_TRUE(registry()->IsRegistered(ph1)); + +#if defined(OS_WIN) || defined(OS_MAC) + // Default handlers that failed OS registration should no longer be default. + // TODO(crbug.com/1019239): Investigate Linux assumptions. + EXPECT_FALSE(registry()->IsDefault(ph1)); +#endif +}
diff --git a/chrome/browser/extensions/api/crash_report_private/DIR_METADATA b/chrome/browser/extensions/api/crash_report_private/DIR_METADATA index fe26aa57..c114595 100644 --- a/chrome/browser/extensions/api/crash_report_private/DIR_METADATA +++ b/chrome/browser/extensions/api/crash_report_private/DIR_METADATA
@@ -1,10 +1,10 @@ # Metadata information for this directory. # # For more information on DIR_METADATA files, see: -# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/README.md +# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/README.md # # For the schema of this file, see Metadata message: -# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/proto/dir_metadata.proto +# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/proto/dir_metadata.proto monorail { component: "Platform>Apps>SystemWebApps"
diff --git a/chrome/browser/extensions/api/desktop_capture/DIR_METADATA b/chrome/browser/extensions/api/desktop_capture/DIR_METADATA index 07a577b..2d5e0e1 100644 --- a/chrome/browser/extensions/api/desktop_capture/DIR_METADATA +++ b/chrome/browser/extensions/api/desktop_capture/DIR_METADATA
@@ -1,10 +1,10 @@ # Metadata information for this directory. # # For more information on DIR_METADATA files, see: -# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/README.md +# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/README.md # # For the schema of this file, see Metadata message: -# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/proto/dir_metadata.proto +# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/proto/dir_metadata.proto monorail { component: "Internals>Media>ScreenCapture"
diff --git a/chrome/browser/extensions/api/settings_private/prefs_util.cc b/chrome/browser/extensions/api/settings_private/prefs_util.cc index b5f8acc..23f4131a 100644 --- a/chrome/browser/extensions/api/settings_private/prefs_util.cc +++ b/chrome/browser/extensions/api/settings_private/prefs_util.cc
@@ -336,6 +336,8 @@ settings_api::PrefType::PREF_TYPE_BOOLEAN; (*s_allowlist)[chromeos::prefs::kAssistPersonalInfoEnabled] = settings_api::PrefType::PREF_TYPE_BOOLEAN; + (*s_allowlist)[chromeos::prefs::kAssistPredictiveWritingEnabled] = + settings_api::PrefType::PREF_TYPE_BOOLEAN; (*s_allowlist)[chromeos::prefs::kEmojiSuggestionEnabled] = settings_api::PrefType::PREF_TYPE_BOOLEAN; (*s_allowlist)[::prefs::kLanguageInputMethodSpecificSettings] =
diff --git a/chrome/browser/extensions/api/tab_capture/DIR_METADATA b/chrome/browser/extensions/api/tab_capture/DIR_METADATA index c46eabd..f689e00 100644 --- a/chrome/browser/extensions/api/tab_capture/DIR_METADATA +++ b/chrome/browser/extensions/api/tab_capture/DIR_METADATA
@@ -1,10 +1,10 @@ # Metadata information for this directory. # # For more information on DIR_METADATA files, see: -# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/README.md +# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/README.md # # For the schema of this file, see Metadata message: -# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/proto/dir_metadata.proto +# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/proto/dir_metadata.proto monorail { component: "Internals>Media>SurfaceCapture"
diff --git a/chrome/browser/extensions/api/terminal/crostini_startup_status.cc b/chrome/browser/extensions/api/terminal/crostini_startup_status.cc index 6cda9cec..3c28b91 100644 --- a/chrome/browser/extensions/api/terminal/crostini_startup_status.cc +++ b/chrome/browser/extensions/api/terminal/crostini_startup_status.cc
@@ -138,12 +138,6 @@ {InstallerState::kStartContainer, l10n_util::GetStringUTF8( IDS_CROSTINI_TERMINAL_STATUS_START_CONTAINER)}, - {InstallerState::kFetchSshKeys, - l10n_util::GetStringUTF8( - IDS_CROSTINI_TERMINAL_STATUS_FETCH_SSH_KEYS)}, - {InstallerState::kMountContainer, - l10n_util::GetStringUTF8( - IDS_CROSTINI_TERMINAL_STATUS_MOUNT_CONTAINER)}, }); const std::string& stage_string = (*kStartStrings)[stage]; PrintStage(kColor3Yellow, stage_string);
diff --git a/chrome/browser/extensions/api/webrtc_desktop_capture_private/DIR_METADATA b/chrome/browser/extensions/api/webrtc_desktop_capture_private/DIR_METADATA index 07a577b..2d5e0e1 100644 --- a/chrome/browser/extensions/api/webrtc_desktop_capture_private/DIR_METADATA +++ b/chrome/browser/extensions/api/webrtc_desktop_capture_private/DIR_METADATA
@@ -1,10 +1,10 @@ # Metadata information for this directory. # # For more information on DIR_METADATA files, see: -# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/README.md +# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/README.md # # For the schema of this file, see Metadata message: -# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/proto/dir_metadata.proto +# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/proto/dir_metadata.proto monorail { component: "Internals>Media>ScreenCapture"
diff --git a/chrome/browser/extensions/chrome_extensions_browser_interface_binders.cc b/chrome/browser/extensions/chrome_extensions_browser_interface_binders.cc index d8c50369..463b9832 100644 --- a/chrome/browser/extensions/chrome_extensions_browser_interface_binders.cc +++ b/chrome/browser/extensions/chrome_extensions_browser_interface_binders.cc
@@ -74,12 +74,12 @@ } #endif // BUILDFLAG(GOOGLE_CHROME_BRANDING) -void BindTtsStreamFactory( +void BindGoogleTtsStream( content::RenderFrameHost* render_frame_host, - mojo::PendingReceiver<chromeos::tts::mojom::TtsStreamFactory> receiver) { + mojo::PendingReceiver<chromeos::tts::mojom::GoogleTtsStream> receiver) { TtsEngineExtensionObserverChromeOS::GetInstance( Profile::FromBrowserContext(render_frame_host->GetBrowserContext())) - ->BindTtsStreamFactory(std::move(receiver)); + ->BindGoogleTtsStream(std::move(receiver)); } void BindRemoteAppsFactory( @@ -166,8 +166,8 @@ } if (extension->id() == extension_misc::kGoogleSpeechSynthesisExtensionId) { - binder_map->Add<chromeos::tts::mojom::TtsStreamFactory>( - base::BindRepeating(&BindTtsStreamFactory)); + binder_map->Add<chromeos::tts::mojom::GoogleTtsStream>( + base::BindRepeating(&BindGoogleTtsStream)); } if (chromeos::RemoteAppsImpl::IsAllowed(render_frame_host, extension)) {
diff --git a/chrome/browser/extensions/system_display/display_info_provider_lacros.cc b/chrome/browser/extensions/system_display/display_info_provider_lacros.cc index 04df8953..1577f7b 100644 --- a/chrome/browser/extensions/system_display/display_info_provider_lacros.cc +++ b/chrome/browser/extensions/system_display/display_info_provider_lacros.cc
@@ -30,7 +30,8 @@ static_cast<int>(crosapi::mojom::SystemDisplay:: kAddDisplayChangeObserverMinVersion)) { lacros_service->GetRemote<crosapi::mojom::SystemDisplay>() - ->AddDisplayChangeObserver(receiver_.BindNewPipeAndPassRemote()); + ->AddDisplayChangeObserver( + receiver_.BindNewPipeAndPassRemoteWithVersion()); } }
diff --git a/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/webfeed/WebFeedDialogCoordinator.java b/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/webfeed/WebFeedDialogCoordinator.java index d0fe906f..3beeb6f1 100644 --- a/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/webfeed/WebFeedDialogCoordinator.java +++ b/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/webfeed/WebFeedDialogCoordinator.java
@@ -73,7 +73,7 @@ secondaryButtonText = mContext.getString(R.string.close); buttonClickCallback = dismissalCause -> { if (dismissalCause.equals(DialogDismissalCause.POSITIVE_BUTTON_CLICKED)) { - feedLauncher.openFeed(); + feedLauncher.openFollowingFeed(); } }; } else {
diff --git a/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/webfeed/WebFeedSnackbarController.java b/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/webfeed/WebFeedSnackbarController.java index 581c202..b1b7d95 100644 --- a/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/webfeed/WebFeedSnackbarController.java +++ b/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/webfeed/WebFeedSnackbarController.java
@@ -26,7 +26,7 @@ */ @FunctionalInterface public interface FeedLauncher { - void openFeed(); + void openFollowingFeed(); } static final int SNACKBAR_DURATION_MS = (int) TimeUnit.SECONDS.toMillis(8); @@ -100,7 +100,7 @@ SnackbarController snackbarController = new SnackbarController() { @Override public void onAction(Object actionData) { - mFeedLauncher.openFeed(); + mFeedLauncher.openFollowingFeed(); } }; showSnackbar(
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json index 8847ea2..dc531da 100644 --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json
@@ -2,7 +2,7 @@ // automatically expire flags, as part of the review process, and to clean up // flags that have become obsolete or unused. For more details, see: // -// https://chromium.googlesource.com/chromium/src/+/master/docs/flag_ownership.md +// https://chromium.googlesource.com/chromium/src/+/main/docs/flag_ownership.md // // This file is a list of json objects; each object contains these keys: //
diff --git a/chrome/browser/flags/README.md b/chrome/browser/flags/README.md index 24dac65..75529e70 100644 --- a/chrome/browser/flags/README.md +++ b/chrome/browser/flags/README.md
@@ -6,13 +6,13 @@ Feature flags and switches are used to control application behavior. They are extensive described in the -[Configuration Documentation](https://chromium.googlesource.com/chromium/src/+/refs/heads/master/docs/configuration.md). +[Configuration Documentation](https://chromium.googlesource.com/chromium/src/+/refs/heads/main/docs/configuration.md). ## Feature Flags Feature flags are declared in C++ as a `base::Feature`. How to declare them is covered in -[Adding a new feature flag](https://chromium.googlesource.com/chromium/src/+/refs/heads/master/docs/how_to_add_your_feature_flag.md). +[Adding a new feature flag](https://chromium.googlesource.com/chromium/src/+/refs/heads/main/docs/how_to_add_your_feature_flag.md). To check the flag state in native code, call `FeatureList::IsEnabled(kMyFeature))`.
diff --git a/chrome/browser/lacros/automation_manager_lacros.cc b/chrome/browser/lacros/automation_manager_lacros.cc index c5bbbfb..0f56c76 100644 --- a/chrome/browser/lacros/automation_manager_lacros.cc +++ b/chrome/browser/lacros/automation_manager_lacros.cc
@@ -19,7 +19,7 @@ return; impl->GetRemote<crosapi::mojom::AutomationFactory>()->BindAutomation( - automation_client_receiver_.BindNewPipeAndPassRemote(), + automation_client_receiver_.BindNewPipeAndPassRemoteWithVersion(), automation_remote_.BindNewPipeAndPassReceiver()); extensions::AutomationEventRouter::GetInstance()->RegisterRemoteRouter(this);
diff --git a/chrome/browser/lacros/crosapi_pref_observer.cc b/chrome/browser/lacros/crosapi_pref_observer.cc index de6da46c..44f83b3 100644 --- a/chrome/browser/lacros/crosapi_pref_observer.cc +++ b/chrome/browser/lacros/crosapi_pref_observer.cc
@@ -16,7 +16,7 @@ return; } lacros_service->GetRemote<crosapi::mojom::Prefs>()->AddObserver( - path, receiver_.BindNewPipeAndPassRemote()); + path, receiver_.BindNewPipeAndPassRemoteWithVersion()); } CrosapiPrefObserver::~CrosapiPrefObserver() = default;
diff --git a/chrome/browser/lacros/metrics_reporting_observer.cc b/chrome/browser/lacros/metrics_reporting_observer.cc index e6aab99..9fe3f53 100644 --- a/chrome/browser/lacros/metrics_reporting_observer.cc +++ b/chrome/browser/lacros/metrics_reporting_observer.cc
@@ -33,7 +33,8 @@ // initial state above from lacros startup and the observer being added. lacros_service->BindMetricsReporting( metrics_reporting_remote_.BindNewPipeAndPassReceiver()); - metrics_reporting_remote_->AddObserver(receiver_.BindNewPipeAndPassRemote()); + metrics_reporting_remote_->AddObserver( + receiver_.BindNewPipeAndPassRemoteWithVersion()); } void MetricsReportingObserver::OnMetricsReportingChanged(bool enabled) {
diff --git a/chrome/browser/lacros/task_manager_lacros.cc b/chrome/browser/lacros/task_manager_lacros.cc index bbb6844..779f967c 100644 --- a/chrome/browser/lacros/task_manager_lacros.cc +++ b/chrome/browser/lacros/task_manager_lacros.cc
@@ -16,7 +16,8 @@ return; id_ = base::UnguessableToken::Create(); service->GetRemote<crosapi::mojom::TaskManager>() - ->RegisterTaskManagerProvider(receiver_.BindNewPipeAndPassRemote(), id_); + ->RegisterTaskManagerProvider( + receiver_.BindNewPipeAndPassRemoteWithVersion(), id_); task_manager_controller_ = std::make_unique<task_manager::TaskManagerControllerLacros>();
diff --git a/chrome/browser/media/media_engagement_autoplay_browsertest.cc b/chrome/browser/media/media_engagement_autoplay_browsertest.cc index 96c2f6ccf..12149380 100644 --- a/chrome/browser/media/media_engagement_autoplay_browsertest.cc +++ b/chrome/browser/media/media_engagement_autoplay_browsertest.cc
@@ -28,8 +28,18 @@ namespace { base::FilePath GetPythonPath() { - // Every environment should have vpython3. - return base::FilePath(FILE_PATH_LITERAL("vpython3")); +#if defined(OS_WIN) + // Windows bots do not have python installed and available on the PATH. + // Please see infra/doc/users/python.md + base::FilePath bot_path = + base::FilePath(FILE_PATH_LITERAL("c:/infra-system/bin/python.exe")); + + if (base::PathExists(bot_path)) + return bot_path; + return base::FilePath(FILE_PATH_LITERAL("python.exe")); +#else + return base::FilePath(FILE_PATH_LITERAL("python")); +#endif } const base::FilePath kTestDataPath = base::FilePath(
diff --git a/chrome/browser/media/webrtc/DIR_METADATA b/chrome/browser/media/webrtc/DIR_METADATA index 5ae03028..5d661d03 100644 --- a/chrome/browser/media/webrtc/DIR_METADATA +++ b/chrome/browser/media/webrtc/DIR_METADATA
@@ -1,10 +1,10 @@ # Metadata information for this directory. # # For more information on DIR_METADATA files, see: -# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/README.md +# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/README.md # # For the schema of this file, see Metadata message: -# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/proto/dir_metadata.proto +# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/proto/dir_metadata.proto monorail: { component: "UI>Browser>MediaCapture"
diff --git a/chrome/browser/metrics/process_memory_metrics_emitter.cc b/chrome/browser/metrics/process_memory_metrics_emitter.cc index 394627ac..565db2e 100644 --- a/chrome/browser/metrics/process_memory_metrics_emitter.cc +++ b/chrome/browser/metrics/process_memory_metrics_emitter.cc
@@ -173,6 +173,8 @@ EmitTo::kSizeInUkmAndUma, &Memory_Experimental::SetDiscardable}, {"discardable", "Discardable.FreelistSize", MetricSize::kSmall, "freelist_size", EmitTo::kSizeInUmaOnly, nullptr}, + {"discardable", "Discardable.FreelistSize.Dirty", MetricSize::kSmall, + "freelist_size_dirty", EmitTo::kSizeInUmaOnly, nullptr}, {"discardable", "Discardable.ResidentSize", MetricSize::kSmall, "resident_size", EmitTo::kSizeInUmaOnly, nullptr}, {"discardable", "Discardable.VirtualSize", MetricSize::kSmall,
diff --git a/chrome/browser/navigation_predictor/navigation_predictor.cc b/chrome/browser/navigation_predictor/navigation_predictor.cc index 283701a..519463c6 100644 --- a/chrome/browser/navigation_predictor/navigation_predictor.cc +++ b/chrome/browser/navigation_predictor/navigation_predictor.cc
@@ -154,16 +154,18 @@ tracked_anchor_id_to_index_[anchor_id] = tracked_anchor_id_to_index_.size(); } - NavigationPredictorKeyedService* service = - NavigationPredictorKeyedServiceFactory::GetForProfile( - Profile::FromBrowserContext( - render_frame_host()->GetBrowserContext())); - DCHECK(service); - service->OnPredictionUpdated( - web_contents, document_url, - NavigationPredictorKeyedService::PredictionSource:: - kAnchorElementsParsedFromWebPage, - new_predictions); + if (!new_predictions.empty()) { + NavigationPredictorKeyedService* service = + NavigationPredictorKeyedServiceFactory::GetForProfile( + Profile::FromBrowserContext( + render_frame_host()->GetBrowserContext())); + DCHECK(service); + service->OnPredictionUpdated( + web_contents, document_url, + NavigationPredictorKeyedService::PredictionSource:: + kAnchorElementsParsedFromWebPage, + new_predictions); + } } void NavigationPredictor::ReportAnchorElementClick(
diff --git a/chrome/browser/navigation_predictor/navigation_predictor_unittest.cc b/chrome/browser/navigation_predictor/navigation_predictor_unittest.cc index b3c2ac8..0403aeb 100644 --- a/chrome/browser/navigation_predictor/navigation_predictor_unittest.cc +++ b/chrome/browser/navigation_predictor/navigation_predictor_unittest.cc
@@ -164,6 +164,26 @@ EXPECT_EQ(0, data->MedianLinkLocation()); } +TEST_F(NavigationPredictorTest, ReportSameAnchorElementTwice) { + std::vector<blink::mojom::AnchorElementMetricsPtr> metrics; + metrics.push_back(CreateMetricsPtr()); + uint32_t anchor_id = metrics[0]->anchor_id; + predictor_service()->ReportNewAnchorElements(std::move(metrics)); + base::RunLoop().RunUntilIdle(); + metrics.clear(); + + // Report the same anchor again, it should be ignored. + metrics.push_back(CreateMetricsPtr()); + metrics[0]->anchor_id = anchor_id; + predictor_service()->ReportNewAnchorElements(std::move(metrics)); + base::RunLoop().RunUntilIdle(); + + PageAnchorsMetricsObserver::AnchorsData::CreateForWebContents(web_contents()); + PageAnchorsMetricsObserver::AnchorsData* data = + PageAnchorsMetricsObserver::AnchorsData::FromWebContents(web_contents()); + EXPECT_EQ(1u, data->number_of_anchors_); +} + // Basic test to check the ReportNewAnchorElements method can be // called with multiple anchors at once. TEST_F(NavigationPredictorTest, ReportNewAnchorElementsMultipleAnchors) {
diff --git a/chrome/browser/net/cert_verify_proc_browsertest.cc b/chrome/browser/net/cert_verify_proc_browsertest.cc index 037ed28..45799427 100644 --- a/chrome/browser/net/cert_verify_proc_browsertest.cc +++ b/chrome/browser/net/cert_verify_proc_browsertest.cc
@@ -146,7 +146,7 @@ // Technically there is no guarantee that if the cert verifier is running out // of process that the netlog mojo messages will be delivered before the cert // verification mojo result. See: - // https://chromium.googlesource.com/chromium/src/+/master/docs/mojo_ipc_conversion.md#Ordering-Considerations + // https://chromium.googlesource.com/chromium/src/+/main/docs/mojo_ipc_conversion.md#Ordering-Considerations // Hopefully this won't be flaky. base::RunLoop().RunUntilIdle(); content::FlushNetworkServiceInstanceForTesting();
diff --git a/chrome/browser/net/websocket_browsertest.cc b/chrome/browser/net/websocket_browsertest.cc index 1e4b993..72d2054 100644 --- a/chrome/browser/net/websocket_browsertest.cc +++ b/chrome/browser/net/websocket_browsertest.cc
@@ -14,6 +14,7 @@ #include "base/check_op.h" #include "base/macros.h" #include "base/notreached.h" +#include "base/path_service.h" #include "base/run_loop.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" @@ -34,6 +35,7 @@ #include "content/public/browser/render_process_host.h" #include "content/public/browser/storage_partition.h" #include "content/public/browser/web_contents.h" +#include "content/public/common/content_switches.h" #include "content/public/test/browser_test.h" #include "content/public/test/browser_test_utils.h" #include "mojo/public/cpp/bindings/pending_receiver.h" @@ -81,6 +83,15 @@ browser(), wss_server_.GetURL(path).ReplaceComponents(replacements)); } + void NavigateToPath(const std::string& relative) { + base::FilePath path; + EXPECT_TRUE(base::PathService::Get(base::DIR_SOURCE_ROOT, &path)); + path = + path.Append(net::GetWebSocketTestDataDirectory()).AppendASCII(relative); + GURL url(std::string("file://") + path.MaybeAsASCII()); + ui_test_utils::NavigateToURL(browser(), url); + } + // Prepare the title watcher. void SetUpOnMainThread() override { watcher_ = std::make_unique<content::TitleWatcher>( @@ -88,6 +99,10 @@ watcher_->AlsoWaitForTitle(u"FAIL"); } + void AlsoWaitForTitle(const std::u16string& title) { + watcher_->AlsoWaitForTitle(title); + } + void TearDownOnMainThread() override { watcher_.reset(); } std::string WaitAndGetTitle() { @@ -135,6 +150,16 @@ DISALLOW_COPY_AND_ASSIGN(WebSocketBrowserTest); }; +class WebSocketBrowserTestWithAllowFileAccessFromFiles + : public WebSocketBrowserTest { + private: + void SetUpCommandLine(base::CommandLine* command_line) override { + command_line->AppendSwitch(switches::kAllowFileAccessFromFiles); + + WebSocketBrowserTest::SetUpCommandLine(command_line); + } +}; + // Framework for tests using the connect_to.html page served by a separate HTTP // server. class WebSocketBrowserConnectToTest : public WebSocketBrowserTest { @@ -660,4 +685,29 @@ } } +IN_PROC_BROWSER_TEST_F(WebSocketBrowserTest, CheckFileOrigin) { + ASSERT_TRUE(ws_server_.Start()); + int port = ws_server_.host_port_pair().port(); + + AlsoWaitForTitle(u"NULL"); + AlsoWaitForTitle(u"FILE"); + + base::RunLoop run_loop; + NavigateToPath(base::StringPrintf("check-origin.html?port=%d", port)); + EXPECT_EQ("NULL", WaitAndGetTitle()); +} + +IN_PROC_BROWSER_TEST_F(WebSocketBrowserTestWithAllowFileAccessFromFiles, + CheckFileOrigin) { + ASSERT_TRUE(ws_server_.Start()); + int port = ws_server_.host_port_pair().port(); + + AlsoWaitForTitle(u"NULL"); + AlsoWaitForTitle(u"FILE"); + + base::RunLoop run_loop; + NavigateToPath(base::StringPrintf("check-origin.html?port=%d", port)); + EXPECT_EQ("FILE", WaitAndGetTitle()); +} + } // namespace
diff --git a/chrome/browser/notifications/notification_platform_bridge_lacros.cc b/chrome/browser/notifications/notification_platform_bridge_lacros.cc index 0cea519..cee679d 100644 --- a/chrome/browser/notifications/notification_platform_bridge_lacros.cc +++ b/chrome/browser/notifications/notification_platform_bridge_lacros.cc
@@ -116,7 +116,7 @@ mojo::PendingRemote<crosapi::mojom::NotificationDelegate> BindNotificationDelegate() { - return receiver_.BindNewPipeAndPassRemote(); + return receiver_.BindNewPipeAndPassRemoteWithVersion(); } // crosapi::mojom::NotificationDelegate:
diff --git a/chrome/browser/preferences/android/README.md b/chrome/browser/preferences/android/README.md index ac7edf6f..a9aa76e 100644 --- a/chrome/browser/preferences/android/README.md +++ b/chrome/browser/preferences/android/README.md
@@ -47,10 +47,10 @@ use PrefService and should instead create your own feature-specific JNI bridge to access the correct PrefService instance (see [`first_run_utils.cc`][6]). -[0]: https://source.chromium.org/chromium/chromium/src/+/master:chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/SharedPreferencesManager.java +[0]: https://source.chromium.org/chromium/chromium/src/+/main:chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/SharedPreferencesManager.java [1]: https://developer.android.com/reference/android/content/SharedPreferences -[2]: https://source.chromium.org/chromium/chromium/src/+/master:components/prefs/android/java/src/org/chromium/components/prefs/PrefService.java -[3]: https://chromium.googlesource.com/chromium/src/+/master/services/preferences/README.md -[4]: https://source.chromium.org/chromium/chromium/src/+/master:chrome/browser/preferences/BUILD.gn;drc=4ae1b7be67cd9b470ebcc90f2747a9f31f155b00;l=28 +[2]: https://source.chromium.org/chromium/chromium/src/+/main:components/prefs/android/java/src/org/chromium/components/prefs/PrefService.java +[3]: https://chromium.googlesource.com/chromium/src/+/main/services/preferences/README.md +[4]: https://source.chromium.org/chromium/chromium/src/+/main:chrome/browser/preferences/BUILD.gn;drc=4ae1b7be67cd9b470ebcc90f2747a9f31f155b00;l=28 [5]: https://www.chromium.org/developers/design-documents/preferences#TOC-Introduction -[6]: https://source.chromium.org/chromium/chromium/src/+/master:chrome/browser/first_run/android/first_run_utils.cc +[6]: https://source.chromium.org/chromium/chromium/src/+/main:chrome/browser/first_run/android/first_run_utils.cc
diff --git a/chrome/browser/prefetch/prefetch_proxy/prefetch_proxy_browsertest.cc b/chrome/browser/prefetch/prefetch_proxy/prefetch_proxy_browsertest.cc index ed2ef6bf..60dab6f1 100644 --- a/chrome/browser/prefetch/prefetch_proxy/prefetch_proxy_browsertest.cc +++ b/chrome/browser/prefetch/prefetch_proxy/prefetch_proxy_browsertest.cc
@@ -549,9 +549,6 @@ void InsertSpeculation(bool subresources, const std::vector<GURL>& prefetch_urls) { - // Make sure we are on a valid referring page. - ui_test_utils::NavigateToURL(browser(), - GetReferringPageServerURL("/search/q=blah")); std::string speculation_script = R"( var script = document.createElement('script'); @@ -4143,9 +4140,7 @@ void SetFeatures() override { scoped_feature_list_.InitWithFeaturesAndParameters( {{features::kIsolatePrerenders, - { - {"use_speculation_rules", "true"}, - }}, + {{"use_speculation_rules", "true"}, {"max_srp_prefetches", "3"}}}, {blink::features::kLightweightNoStatePrefetch, {}}, {blink::features::kSpeculationRulesPrefetchProxy, {}}}, {{features::kLazyImageLoading}}); @@ -4181,6 +4176,9 @@ tab_helper_observer.SetOnNSPFinishedClosure(nsp_run_loop.QuitClosure()); + // Make sure we are on a valid referring page. + ui_test_utils::NavigateToURL(browser(), + GetReferringPageServerURL("/search/q=blah")); InsertSpeculation(true, {eligible_link}); // This run loop will quit when all the prefetch responses have been @@ -4342,7 +4340,9 @@ tab_helper_observer.SetOnPrefetchSuccessfulClosure(run_loop.QuitClosure()); tab_helper_observer.SetExpectedSuccessfulURLs({prefetch_url}); - GURL doc_url("https://www.google.com/search?q=test"); + // Make sure we are on a valid referring page. + ui_test_utils::NavigateToURL(browser(), + GetReferringPageServerURL("/search/q=blah")); InsertSpeculation(false, {prefetch_url}); // This run loop will quit when the prefetch response has been successfully @@ -4362,3 +4362,45 @@ // The origin server should not have served this request. EXPECT_EQ(starting_origin_request_count, OriginServerRequestCount()); } + +IN_PROC_BROWSER_TEST_F(SpeculationPrefetchProxyTest, + DISABLE_ON_WIN_MAC_CHROMEOS(TwoSpeculations)) { + SetDataSaverEnabled(true); + WaitForUpdatedCustomProxyConfig(); + + PrefetchProxyTabHelper* tab_helper = + PrefetchProxyTabHelper::FromWebContents(GetWebContents()); + TestTabHelperObserver tab_helper_observer(tab_helper); + + GURL prefetch_url = GetOriginServerURL("/title2.html"); + + base::RunLoop run_loop; + tab_helper_observer.SetOnPrefetchSuccessfulClosure(run_loop.QuitClosure()); + tab_helper_observer.SetExpectedSuccessfulURLs({prefetch_url}); + + // Make sure we are on a valid referring page. + ui_test_utils::NavigateToURL(browser(), + GetReferringPageServerURL("/search/q=blah")); + InsertSpeculation(false, {prefetch_url}); + + // This run loop will quit when the prefetch response has been successfully + // done and processed. + run_loop.Run(); + + EXPECT_EQ(tab_helper->srp_metrics().prefetch_attempted_count_, 1U); + EXPECT_EQ(tab_helper->srp_metrics().prefetch_successful_count_, 1U); + + base::RunLoop run_loop_2; + GURL prefetch_url_2 = GetOriginServerURL("/title1.html"); + tab_helper_observer.SetOnPrefetchSuccessfulClosure(run_loop_2.QuitClosure()); + tab_helper_observer.SetExpectedSuccessfulURLs({prefetch_url_2}); + InsertSpeculation(false, {prefetch_url_2}); + + // This run loop will quit when the prefetch response has been successfully + // done and processed. + run_loop_2.Run(); + + // Verify that we de-dupe and only fetch one new URL. + EXPECT_EQ(tab_helper->srp_metrics().prefetch_attempted_count_, 2U); + EXPECT_EQ(tab_helper->srp_metrics().prefetch_successful_count_, 2U); +}
diff --git a/chrome/browser/prefetch/prefetch_proxy/prefetch_proxy_tab_helper.cc b/chrome/browser/prefetch/prefetch_proxy/prefetch_proxy_tab_helper.cc index d07389a..2710f19 100644 --- a/chrome/browser/prefetch/prefetch_proxy/prefetch_proxy_tab_helper.cc +++ b/chrome/browser/prefetch/prefetch_proxy/prefetch_proxy_tab_helper.cc
@@ -1244,11 +1244,21 @@ web_contents()->GetMainFrame()->GetPageUkmSourceId()); } + // Remove duplicate prefetches, but allow |allowed_to_prefetch_subresources| + // to be set for any upgraded prefetches. + std::vector<GURL> new_targets; + for (const auto& prefetch : prefetch_targets) { + if (page_->original_prediction_ordering_.find(prefetch) == + page_->original_prediction_ordering_.end()) { + new_targets.push_back(prefetch); + } + } + // It's very likely we'll prefetch something at this point, so inform PLM to // start tracking metrics. InformPLMOfLikelyPrefetching(web_contents()); - page_->srp_metrics_->predicted_urls_count_ += prefetch_targets.size(); + page_->srp_metrics_->predicted_urls_count_ += new_targets.size(); // It is possible, since it is not stipulated by the API contract, that the // navigation predictor will issue multiple predictions during a single page @@ -1261,8 +1271,8 @@ allowed_to_prefetch_subresources.begin(), allowed_to_prefetch_subresources.end()); - for (size_t i = 0; i < prefetch_targets.size(); ++i) { - GURL url = prefetch_targets[i]; + for (size_t i = 0; i < new_targets.size(); ++i) { + GURL url = new_targets[i]; size_t url_index = original_prediction_ordering_starting_size + i; page_->original_prediction_ordering_.emplace(url, url_index);
diff --git a/chrome/browser/prefetch/prefetch_proxy/prefetch_proxy_tab_helper_unittest.cc b/chrome/browser/prefetch/prefetch_proxy/prefetch_proxy_tab_helper_unittest.cc index 876c2069..fa54cf0 100644 --- a/chrome/browser/prefetch/prefetch_proxy/prefetch_proxy_tab_helper_unittest.cc +++ b/chrome/browser/prefetch/prefetch_proxy/prefetch_proxy_tab_helper_unittest.cc
@@ -1837,7 +1837,8 @@ RunNoRedirectTest(GURL("https://www.google.com/")); - EXPECT_EQ(predicted_urls_count(), 2U); + // The navigation prediction in |RunNoRedirectTest()| should be de-duped. + EXPECT_EQ(predicted_urls_count(), 1U); EXPECT_EQ(prefetch_eligible_count(), 0U); EXPECT_EQ(prefetch_attempted_count(), 0U); EXPECT_EQ(prefetch_successful_count(), 0U);
diff --git a/chrome/browser/prefs/README.md b/chrome/browser/prefs/README.md index ea620f0..33bfd4e 100644 --- a/chrome/browser/prefs/README.md +++ b/chrome/browser/prefs/README.md
@@ -61,11 +61,11 @@ 0. If the pref is also a policy, you will need to mark it deprecated as described in - [add_new_policy.md](https://chromium.googlesource.com/chromium/src/+/master/docs/enterprise/add_new_policy.md#deprecating-a-policy). + [add_new_policy.md](https://chromium.googlesource.com/chromium/src/+/main/docs/enterprise/add_new_policy.md#deprecating-a-policy). Deleting the pref logic (steps below) will need to wait a few milestones. 1. Move the pref name declaration to the anonymous namespace of - [chrome/browser/prefs/browser_prefs.cc](https://source.chromium.org/chromium/chromium/src/+/master:chrome/browser/prefs/browser_prefs.cc) + [chrome/browser/prefs/browser_prefs.cc](https://source.chromium.org/chromium/chromium/src/+/main:chrome/browser/prefs/browser_prefs.cc) 1. Move registration code into `RegisterProfilePrefsForMigration()` or `RegisterLocalStatePrefsForMigration()` as appropriate. 1. If the old registration code had the `SYNCABLE_PREF` flag, remove it now @@ -90,7 +90,7 @@ As per [deleting an old pref](#deleting-an-old-pref), if the old pref is also a policy, you will need to mark it deprecated for a few milestones first as described in -[add_new_policy.md](https://chromium.googlesource.com/chromium/src/+/master/docs/enterprise/add_new_policy.md#deprecating-a-policy). +[add_new_policy.md](https://chromium.googlesource.com/chromium/src/+/main/docs/enterprise/add_new_policy.md#deprecating-a-policy). Migration code will want to read the old pref using `base::PrefService::GetUserPrefValue()` (as opposed to
diff --git a/chrome/browser/privacy_sandbox/privacy_sandbox_settings.cc b/chrome/browser/privacy_sandbox/privacy_sandbox_settings.cc index 1f58e004..20e172f 100644 --- a/chrome/browser/privacy_sandbox/privacy_sandbox_settings.cc +++ b/chrome/browser/privacy_sandbox/privacy_sandbox_settings.cc
@@ -183,6 +183,17 @@ if (IsCookiesClearOnExitEnabled(host_content_settings_map_)) OnCookiesCleared(); + // Register observers for the Privacy Sandbox & FLoC preferences. + user_prefs_registrar_.Init(pref_service_); + user_prefs_registrar_.Add( + prefs::kPrivacySandboxApisEnabled, + base::BindRepeating(&PrivacySandboxSettings::OnPrivacySandboxPrefChanged, + base::Unretained(this))); + user_prefs_registrar_.Add( + prefs::kPrivacySandboxFlocEnabled, + base::BindRepeating(&PrivacySandboxSettings::OnPrivacySandboxPrefChanged, + base::Unretained(this))); + // On first entering the privacy sandbox experiment, users may have the // privacy sandbox disabled (or "reconciled") based on their current cookie // settings (e.g. blocking 3P cookies). Depending on the state of the sync @@ -290,10 +301,9 @@ } bool PrivacySandboxSettings::IsFlocIdResettable() const { - auto floc_id = federated_learning::FlocId::ReadFromPrefs(pref_service_); const bool floc_feature_enabled = base::FeatureList::IsEnabled( blink::features::kInterestCohortAPIOriginTrial); - return floc_feature_enabled && floc_id.IsValid() && IsFlocAllowed(); + return floc_feature_enabled && IsFlocAllowed(); } void PrivacySandboxSettings::ResetFlocId() const { @@ -401,6 +411,15 @@ SetFlocDataAccessibleFromNow(/*reset_calculate_timer=*/false); } +void PrivacySandboxSettings::OnPrivacySandboxPrefChanged() { + // Any change of the two observed prefs should be accompanied by a + // reset of the FLoC cohort. Technically this only needs to occur on the + // transition from FLoC being effectively disabled to effectively enabled, + // but performing it on every pref change achieves the same user visible + // behavior, and is much simpler. + ResetFlocId(); +} + void PrivacySandboxSettings::AddObserver(Observer* observer) { observers_.AddObserver(observer); }
diff --git a/chrome/browser/privacy_sandbox/privacy_sandbox_settings.h b/chrome/browser/privacy_sandbox/privacy_sandbox_settings.h index 63bbceae..85ebc20 100644 --- a/chrome/browser/privacy_sandbox/privacy_sandbox_settings.h +++ b/chrome/browser/privacy_sandbox/privacy_sandbox_settings.h
@@ -13,6 +13,7 @@ #include "components/content_settings/core/common/content_settings.h" #include "components/keyed_service/core/keyed_service.h" #include "components/policy/core/common/policy_service.h" +#include "components/prefs/pref_change_registrar.h" #include "components/signin/public/identity_manager/identity_manager.h" #include "components/sync/driver/sync_service.h" #include "components/sync/driver/sync_service_observer.h" @@ -105,8 +106,9 @@ std::u16string GetFlocStatusForDisplay() const; // Returns whether the user's current FLoC ID can be reset. This requires that - // the FLoC feature be enabled, FLoC be enabled in preferences, and the ID be - // valid. + // the FLoC feature be enabled and FLoC be enabled in preferences. It does not + // require that the current ID is valid, as resetting the ID also resets the + // compute timer, it should be available whenever FLoC is active. bool IsFlocIdResettable() const; // Sets the time when history is accessible for FLoC calculation to the @@ -171,6 +173,9 @@ // Clear-Site-Data header, as it's restricted to a specific site. void OnCookiesCleared(); + // Called when a preference relevant to the the Privacy Sandbox is changed. + void OnPrivacySandboxPrefChanged(); + void AddObserver(Observer* observer); void RemoveObserver(Observer* observer); @@ -295,6 +300,8 @@ signin::IdentityManager::Observer> identity_manager_observer_{this}; + PrefChangeRegistrar user_prefs_registrar_; + // A manual record of whether policy_service_ is being observerd. // Unfortunately PolicyService does not support scoped observers. bool policy_service_observed_ = false;
diff --git a/chrome/browser/privacy_sandbox/privacy_sandbox_settings_unittest.cc b/chrome/browser/privacy_sandbox/privacy_sandbox_settings_unittest.cc index 67eb94aa..9ff2f19 100644 --- a/chrome/browser/privacy_sandbox/privacy_sandbox_settings_unittest.cc +++ b/chrome/browser/privacy_sandbox/privacy_sandbox_settings_unittest.cc
@@ -53,6 +53,11 @@ MOCK_METHOD(base::Time, GetApproximateNextComputeTime, (), (const, override)); }; +class MockPrivacySandboxObserver : public PrivacySandboxSettings::Observer { + public: + MOCK_METHOD(void, OnFlocDataAccessibleSinceUpdated, (bool), (override)); +}; + // Define an additional content setting value to simulate an unmanaged default // content setting. const ContentSetting kNoSetting = static_cast<ContentSetting>(-1); @@ -1063,8 +1068,8 @@ } TEST_F(PrivacySandboxSettingsTest, IsFlocIdResettable) { - // Check that if the FLoC id is valid and FLoC is functional, then it is also - // resettable. + // Check that if FLoC is functional the FLoC ID is resettable, regardless of + // whether the FLoC ID is currently valid. feature_list()->InitWithFeatures( {blink::features::kInterestCohortAPIOriginTrial}, {}); federated_learning::FlocId floc_id(123456, base::Time(), base::Time::Now(), @@ -1097,7 +1102,7 @@ floc_id.InvalidateIdAndSaveToPrefs(profile()->GetTestingPrefService()); profile()->GetTestingPrefService()->SetBoolean( prefs::kPrivacySandboxFlocEnabled, true); - EXPECT_FALSE(privacy_sandbox_settings()->IsFlocIdResettable()); + EXPECT_TRUE(privacy_sandbox_settings()->IsFlocIdResettable()); } TEST_F(PrivacySandboxSettingsTest, IsFlocPrefEnabled) { @@ -1133,6 +1138,37 @@ prefs::kPrivacySandboxFlocEnabled)); } +TEST_F(PrivacySandboxSettingsTest, OnPrivacySandboxPrefChanged) { + // When either the main Privacy Sandbox pref, or the FLoC pref, are changed + // the FLoC ID should be reset. + MockPrivacySandboxObserver mock_privacy_sandbox_observer; + privacy_sandbox_settings()->AddObserver(&mock_privacy_sandbox_observer); + EXPECT_CALL(mock_privacy_sandbox_observer, + OnFlocDataAccessibleSinceUpdated(/*reset_compute_timer=*/true)); + + profile()->GetTestingPrefService()->SetBoolean( + prefs::kPrivacySandboxApisEnabled, false); + testing::Mock::VerifyAndClearExpectations(&mock_privacy_sandbox_observer); + + EXPECT_CALL(mock_privacy_sandbox_observer, + OnFlocDataAccessibleSinceUpdated(/*reset_compute_timer=*/true)); + profile()->GetTestingPrefService()->SetBoolean( + prefs::kPrivacySandboxFlocEnabled, false); + testing::Mock::VerifyAndClearExpectations(&mock_privacy_sandbox_observer); + + EXPECT_CALL(mock_privacy_sandbox_observer, + OnFlocDataAccessibleSinceUpdated(/*reset_compute_timer=*/true)); + profile()->GetTestingPrefService()->SetBoolean( + prefs::kPrivacySandboxFlocEnabled, true); + testing::Mock::VerifyAndClearExpectations(&mock_privacy_sandbox_observer); + + EXPECT_CALL(mock_privacy_sandbox_observer, + OnFlocDataAccessibleSinceUpdated(/*reset_compute_timer=*/true)); + profile()->GetTestingPrefService()->SetBoolean( + prefs::kPrivacySandboxApisEnabled, true); + testing::Mock::VerifyAndClearExpectations(&mock_privacy_sandbox_observer); +} + TEST_F(PrivacySandboxSettingsTest, ReconciliationOutcome) { // Check that reconciling preferences has the appropriate outcome based on // the current user cookie settings.
diff --git a/chrome/browser/reputation/reputation_web_contents_observer.cc b/chrome/browser/reputation/reputation_web_contents_observer.cc index 1cdb0ba..f4faa01 100644 --- a/chrome/browser/reputation/reputation_web_contents_observer.cc +++ b/chrome/browser/reputation/reputation_web_contents_observer.cc
@@ -28,6 +28,10 @@ #include "third_party/abseil-cpp/absl/types/optional.h" #include "url/gurl.h" +#if defined(OS_ANDROID) +#include "components/messages/android/messages_feature.h" +#endif + namespace { // Whether to show tips on server-side-flagged sites included in the component. @@ -415,12 +419,26 @@ lookalikes::features::kLookalikeDigitalAssetLinks) || !result.suggested_url.is_valid()) { RecordPostFlagCheckHistogram(result.safety_tip_status); - ShowSafetyTipDialog( - web_contents(), result.safety_tip_status, result.suggested_url, + + bool should_call_safety_tip_dialog = true; + base::OnceCallback<void(SafetyTipInteraction)> close_callback = base::BindOnce(OnSafetyTipClosed, result, base::Time::Now(), navigation_source_id, profile_, result.url, result.safety_tip_status, - std::move(safety_tip_close_callback_for_testing_))); + std::move(safety_tip_close_callback_for_testing_)); +#if defined(OS_ANDROID) + if (messages::IsSafetyTipMessagesUiEnabled()) { + should_call_safety_tip_dialog = false; + delegate_.DisplaySafetyTipPrompt(result.safety_tip_status, result.url, + web_contents(), + std::move(close_callback)); + } +#endif + + if (should_call_safety_tip_dialog) { + ShowSafetyTipDialog(web_contents(), result.safety_tip_status, + result.suggested_url, std::move(close_callback)); + } MaybeCallReputationCheckCallback(true); return; } @@ -456,12 +474,23 @@ RecordPostFlagCheckHistogram(result.safety_tip_status); - ShowSafetyTipDialog( - web_contents(), result.safety_tip_status, result.suggested_url, + bool should_call_safety_tip_dialog = true; + base::OnceCallback<void(SafetyTipInteraction)> close_callback = base::BindOnce(OnSafetyTipClosed, result, base::Time::Now(), navigation_source_id, profile_, result.url, result.safety_tip_status, - std::move(safety_tip_close_callback_for_testing_))); + std::move(safety_tip_close_callback_for_testing_)); +#if defined(OS_ANDROID) + if (messages::IsSafetyTipMessagesUiEnabled()) { + should_call_safety_tip_dialog = false; + delegate_.DisplaySafetyTipPrompt(result.safety_tip_status, result.url, + web_contents(), std::move(close_callback)); + } +#endif + if (should_call_safety_tip_dialog) { + ShowSafetyTipDialog(web_contents(), result.safety_tip_status, + result.suggested_url, std::move(close_callback)); + } MaybeCallReputationCheckCallback(/*heuristics_checked=*/true); }
diff --git a/chrome/browser/reputation/reputation_web_contents_observer.h b/chrome/browser/reputation/reputation_web_contents_observer.h index 3c658c2..c5adc3b 100644 --- a/chrome/browser/reputation/reputation_web_contents_observer.h +++ b/chrome/browser/reputation/reputation_web_contents_observer.h
@@ -6,6 +6,7 @@ #define CHROME_BROWSER_REPUTATION_REPUTATION_WEB_CONTENTS_OBSERVER_H_ #include "base/callback_forward.h" +#include "build/build_config.h" #include "chrome/browser/lookalikes/digital_asset_links_cross_validator.h" #include "chrome/browser/reputation/reputation_service.h" #include "chrome/browser/reputation/safety_tip_ui.h" @@ -20,6 +21,10 @@ #include "url/gurl.h" #include "url/origin.h" +#if defined(OS_ANDROID) +#include "chrome/browser/reputation/safety_tip_message_delegate.h" +#endif + class Profile; // Observes navigations and triggers a warning if a visited site is determined @@ -113,6 +118,10 @@ base::OnceClosure safety_tip_close_callback_for_testing_; +#if defined(OS_ANDROID) + SafetyTipMessageDelegate delegate_; +#endif + std::unique_ptr<DigitalAssetLinkCrossValidator> digital_asset_link_validator_; base::WeakPtrFactory<ReputationWebContentsObserver> weak_factory_{this};
diff --git a/chrome/browser/reputation/safety_tip_message_delegate.cc b/chrome/browser/reputation/safety_tip_message_delegate.cc new file mode 100644 index 0000000..561efe34 --- /dev/null +++ b/chrome/browser/reputation/safety_tip_message_delegate.cc
@@ -0,0 +1,92 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/reputation/safety_tip_message_delegate.h" + +#include "chrome/browser/android/android_theme_resources.h" +#include "chrome/browser/android/resource_mapper.h" +#include "chrome/browser/reputation/safety_tip_ui_helper.h" +#include "chrome/grit/generated_resources.h" +#include "components/messages/android/message_dispatcher_bridge.h" +#include "components/strings/grit/components_strings.h" +#include "ui/base/l10n/l10n_util.h" + +SafetyTipMessageDelegate::SafetyTipMessageDelegate() = default; + +SafetyTipMessageDelegate::~SafetyTipMessageDelegate() { + DismissInternal(); +} + +void SafetyTipMessageDelegate::DisplaySafetyTipPrompt( + security_state::SafetyTipStatus safety_tip_status, + const GURL& suggested_url, + content::WebContents* web_contents, + base::OnceCallback<void(SafetyTipInteraction)> close_callback) { + if (message_) + return; + web_contents_ = web_contents; + safety_tip_status_ = safety_tip_status; + suggested_url_ = suggested_url; + close_callback_ = std::move(close_callback); + message_ = std::make_unique<messages::MessageWrapper>( + base::BindOnce(&SafetyTipMessageDelegate::HandleLeaveSiteClick, + base::Unretained(this)), + base::BindOnce(&SafetyTipMessageDelegate::HandleDismissCallback, + base::Unretained(this))); + message_->SetTitle(GetSafetyTipTitle(safety_tip_status, suggested_url)); + + message_->SetDescription( + GetSafetyTipDescription(safety_tip_status, suggested_url)); + + message_->SetPrimaryButtonText( + l10n_util::GetStringUTF16(GetSafetyTipLeaveButtonId(safety_tip_status))); + message_->SetIconResourceId(ResourceMapper::MapToJavaDrawableId( + IDR_ANDROID_INFOBAR_SAFETYTIP_SHIELD)); + message_->DisableIconTint(); + message_->SetSecondaryIconResourceId( + ResourceMapper::MapToJavaDrawableId(IDR_ANDROID_AUTOFILL_SETTINGS)); + message_->SetSecondaryButtonMenuText( + l10n_util::GetStringUTF16(IDS_PAGE_INFO_SAFETY_TIP_MORE_INFO_LINK)); + + message_->SetSecondaryActionCallback(base::BindOnce( + &SafetyTipMessageDelegate::HandleLearnMoreClick, base::Unretained(this))); + + // 60s + message_->SetDuration(60000); + + messages::MessageDispatcherBridge::Get()->EnqueueMessage( + message_.get(), web_contents_, messages::MessageScopeType::NAVIGATION); +} + +void SafetyTipMessageDelegate::HandleLeaveSiteClick() { + action_taken_ = SafetyTipInteraction::kLeaveSite; + auto url = safety_tip_status_ == security_state::SafetyTipStatus::kLookalike + ? suggested_url_ + : GURL(); + LeaveSiteFromSafetyTip(web_contents_, url); +} + +void SafetyTipMessageDelegate::HandleLearnMoreClick() { + OpenHelpCenterFromSafetyTip(web_contents_); +} + +void SafetyTipMessageDelegate::HandleDismissCallback( + messages::DismissReason dismiss_reason) { + if (dismiss_reason == messages::DismissReason::GESTURE) { + action_taken_ = SafetyTipInteraction::kDismissWithClose; + } else if (dismiss_reason == messages::DismissReason::SCOPE_DESTROYED) { + action_taken_ = SafetyTipInteraction::kCloseTab; + } + std::move(close_callback_).Run(action_taken_); + action_taken_ = SafetyTipInteraction::kNoAction; + message_.reset(); + web_contents_ = nullptr; +} + +void SafetyTipMessageDelegate::DismissInternal() { + if (message_) { + messages::MessageDispatcherBridge::Get()->DismissMessage( + message_.get(), web_contents_, messages::DismissReason::UNKNOWN); + } +}
diff --git a/chrome/browser/reputation/safety_tip_message_delegate.h b/chrome/browser/reputation/safety_tip_message_delegate.h new file mode 100644 index 0000000..f80d2a8 --- /dev/null +++ b/chrome/browser/reputation/safety_tip_message_delegate.h
@@ -0,0 +1,54 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_REPUTATION_SAFETY_TIP_MESSAGE_DELEGATE_H_ +#define CHROME_BROWSER_REPUTATION_SAFETY_TIP_MESSAGE_DELEGATE_H_ + +#include <memory> + +#include "chrome/browser/reputation/safety_tip_ui.h" +#include "components/messages/android/message_enums.h" +#include "components/messages/android/message_wrapper.h" +#include "components/security_state/core/security_state.h" +#include "url/gurl.h" + +namespace content { +class WebContents; +} // namespace content + +// Message delegate to show a safety tip message on Android. +class SafetyTipMessageDelegate { + public: + SafetyTipMessageDelegate(); + ~SafetyTipMessageDelegate(); + + void DisplaySafetyTipPrompt( + security_state::SafetyTipStatus safety_tip_status, + const GURL& suggested_url, + content::WebContents* web_contents, + base::OnceCallback<void(SafetyTipInteraction)> close_callback); + + private: + friend class SafetyTipMessageDelegateTest; + + void HandleLeaveSiteClick(); + void HandleLearnMoreClick(); + + void HandleDismissCallback(messages::DismissReason dismiss_reason); + void DismissInternal(); + + std::unique_ptr<messages::MessageWrapper> message_; + content::WebContents* web_contents_ = nullptr; + + security_state::SafetyTipStatus safety_tip_status_; + + // The URL of the page the Safety Tip suggests you intended to go to, when + // applicable (for SafetyTipStatus::kLookalike). + GURL suggested_url_; + + SafetyTipInteraction action_taken_ = SafetyTipInteraction::kNoAction; + base::OnceCallback<void(SafetyTipInteraction)> close_callback_; +}; + +#endif // CHROME_BROWSER_REPUTATION_SAFETY_TIP_MESSAGE_DELEGATE_H_
diff --git a/chrome/browser/reputation/safety_tip_message_delegate_unittest.cc b/chrome/browser/reputation/safety_tip_message_delegate_unittest.cc new file mode 100644 index 0000000..599eb20 --- /dev/null +++ b/chrome/browser/reputation/safety_tip_message_delegate_unittest.cc
@@ -0,0 +1,205 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/reputation/safety_tip_message_delegate.h" + +#include "base/test/mock_callback.h" +#include "chrome/browser/android/android_theme_resources.h" +#include "chrome/browser/android/resource_mapper.h" +#include "chrome/browser/reputation/safety_tip_ui_helper.h" +#include "chrome/grit/generated_resources.h" +#include "chrome/test/base/chrome_render_view_host_test_harness.h" +#include "components/messages/android/mock_message_dispatcher_bridge.h" +#include "components/strings/grit/components_strings.h" +#include "content/public/browser/web_contents_delegate.h" +#include "ui/base/l10n/l10n_util.h" + +namespace { +constexpr char16_t kDefaultUrl[] = u"http://example.com"; +constexpr char16_t kSuggestUrl[] = u"http://google.com"; +} // namespace + +class TestNavigationDelegate : public content::WebContentsDelegate { + public: + ~TestNavigationDelegate() override {} + // content::WebContentsDelegate: + content::WebContents* OpenURLFromTab( + content::WebContents* source, + const content::OpenURLParams& params) override { + opened_++; + return source; + } + + int opened() const { return opened_; } + + private: + int opened_ = 0; +}; + +class SafetyTipMessageDelegateTest : public ChromeRenderViewHostTestHarness { + public: + SafetyTipMessageDelegateTest() = default; + + protected: + void SetUp() override; + void TearDown() override; + + void EnqueueMessage( + base::OnceCallback<void(SafetyTipInteraction)> close_callback, + bool enqueue_expected, + security_state::SafetyTipStatus safety_tip_status); + void DismissMessage(); + void TriggerPrimaryButtonClick(); + void TriggerSecondaryButtonClick(); + + messages::MessageWrapper* GetMessageWrapper() { + return delegate_.message_.get(); + } + + TestNavigationDelegate* GetTestNavigationDelegate() { + return &mock_web_contents_delegate_; + } + + private: + SafetyTipMessageDelegate delegate_; + messages::MockMessageDispatcherBridge message_dispatcher_bridge_; + TestNavigationDelegate mock_web_contents_delegate_; +}; + +void SafetyTipMessageDelegateTest::SetUp() { + ChromeRenderViewHostTestHarness::SetUp(); + messages::MessageDispatcherBridge::SetInstanceForTesting( + &message_dispatcher_bridge_); + NavigateAndCommit(GURL(kDefaultUrl)); +} + +void SafetyTipMessageDelegateTest::TearDown() { + messages::MessageDispatcherBridge::SetInstanceForTesting(nullptr); + ChromeRenderViewHostTestHarness::TearDown(); +} + +void SafetyTipMessageDelegateTest::EnqueueMessage( + base::OnceCallback<void(SafetyTipInteraction)> close_callback, + bool enqueue_expected, + security_state::SafetyTipStatus safety_tip_status) { + if (enqueue_expected) { + EXPECT_CALL(message_dispatcher_bridge_, EnqueueMessage); + } else { + EXPECT_CALL(message_dispatcher_bridge_, EnqueueMessage).Times(0); + } + delegate_.DisplaySafetyTipPrompt(safety_tip_status, GURL(kSuggestUrl), + web_contents(), std::move(close_callback)); +} + +void SafetyTipMessageDelegateTest::DismissMessage() { + EXPECT_CALL(message_dispatcher_bridge_, DismissMessage) + .WillOnce([](messages::MessageWrapper* message, + content::WebContents* web_contents, + messages::DismissReason dismiss_reason) { + message->HandleDismissCallback(base::android::AttachCurrentThread(), + static_cast<int>(dismiss_reason)); + }); + delegate_.DismissInternal(); + EXPECT_EQ(nullptr, GetMessageWrapper()); +} + +void SafetyTipMessageDelegateTest::TriggerPrimaryButtonClick() { + GetMessageWrapper()->HandleActionClick(base::android::AttachCurrentThread()); +} + +void SafetyTipMessageDelegateTest::TriggerSecondaryButtonClick() { + GetMessageWrapper()->HandleSecondaryActionClick( + base::android::AttachCurrentThread()); +} + +TEST_F(SafetyTipMessageDelegateTest, DismissOnNoAction) { + base::MockOnceCallback<void(SafetyTipInteraction)> mock_callback_receiver; + EnqueueMessage(mock_callback_receiver.Get(), true, + security_state::SafetyTipStatus::kBadReputation); + EXPECT_CALL(mock_callback_receiver, Run(SafetyTipInteraction::kNoAction)); + DismissMessage(); +} + +TEST_F(SafetyTipMessageDelegateTest, DoNotReplaceCurrentMessage) { + base::MockOnceCallback<void(SafetyTipInteraction)> mock_callback_receiver; + EnqueueMessage(mock_callback_receiver.Get(), true, + security_state::SafetyTipStatus::kBadReputation); + EXPECT_CALL(mock_callback_receiver, Run(SafetyTipInteraction::kNoAction)) + .Times(0); + EnqueueMessage(mock_callback_receiver.Get(), false, + security_state::SafetyTipStatus::kBadReputation); + EXPECT_CALL(mock_callback_receiver, Run(SafetyTipInteraction::kNoAction)) + .Times(1); + DismissMessage(); +} + +TEST_F(SafetyTipMessageDelegateTest, PrimaryActionCallback) { + base::MockOnceCallback<void(SafetyTipInteraction)> mock_callback_receiver; + EnqueueMessage(mock_callback_receiver.Get(), true, + security_state::SafetyTipStatus::kBadReputation); + + web_contents()->SetDelegate(GetTestNavigationDelegate()); + TriggerPrimaryButtonClick(); + EXPECT_EQ(GetTestNavigationDelegate()->opened(), 1); + + DismissMessage(); +} + +TEST_F(SafetyTipMessageDelegateTest, SecondaryActionCallback) { + base::MockOnceCallback<void(SafetyTipInteraction)> mock_callback_receiver; + EnqueueMessage(mock_callback_receiver.Get(), true, + security_state::SafetyTipStatus::kBadReputation); + + web_contents()->SetDelegate(GetTestNavigationDelegate()); + TriggerSecondaryButtonClick(); + EXPECT_EQ(GetTestNavigationDelegate()->opened(), 1); + + DismissMessage(); +} + +TEST_F(SafetyTipMessageDelegateTest, MessagePropertyValuesBadReputation) { + base::MockOnceCallback<void(SafetyTipInteraction)> mock_callback_receiver; + security_state::SafetyTipStatus status = + security_state::SafetyTipStatus::kBadReputation; + EnqueueMessage(mock_callback_receiver.Get(), true, status); + + EXPECT_EQ(GetSafetyTipTitle(status, GURL(kSuggestUrl)), + GetMessageWrapper()->GetTitle()); + EXPECT_EQ(GetSafetyTipDescription(status, GURL(kSuggestUrl)), + GetMessageWrapper()->GetDescription()); + + EXPECT_EQ(l10n_util::GetStringUTF16(GetSafetyTipLeaveButtonId(status)), + GetMessageWrapper()->GetPrimaryButtonText()); + EXPECT_EQ( + ResourceMapper::MapToJavaDrawableId(IDR_ANDROID_INFOBAR_SAFETYTIP_SHIELD), + GetMessageWrapper()->GetIconResourceId()); + EXPECT_EQ(ResourceMapper::MapToJavaDrawableId(IDR_ANDROID_AUTOFILL_SETTINGS), + GetMessageWrapper()->GetSecondaryIconResourceId()); + EXPECT_EQ(l10n_util::GetStringUTF16(IDS_PAGE_INFO_SAFETY_TIP_MORE_INFO_LINK), + GetMessageWrapper()->GetSecondaryButtonMenuText()); + DismissMessage(); +} + +TEST_F(SafetyTipMessageDelegateTest, MessagePropertyValuesLookAlike) { + base::MockOnceCallback<void(SafetyTipInteraction)> mock_callback_receiver; + security_state::SafetyTipStatus status = + security_state::SafetyTipStatus::kLookalike; + EnqueueMessage(mock_callback_receiver.Get(), true, status); + + EXPECT_EQ(GetSafetyTipTitle(status, GURL(kSuggestUrl)), + GetMessageWrapper()->GetTitle()); + EXPECT_EQ(GetSafetyTipDescription(status, GURL(kSuggestUrl)), + GetMessageWrapper()->GetDescription()); + + EXPECT_EQ(l10n_util::GetStringUTF16(GetSafetyTipLeaveButtonId(status)), + GetMessageWrapper()->GetPrimaryButtonText()); + EXPECT_EQ( + ResourceMapper::MapToJavaDrawableId(IDR_ANDROID_INFOBAR_SAFETYTIP_SHIELD), + GetMessageWrapper()->GetIconResourceId()); + EXPECT_EQ(ResourceMapper::MapToJavaDrawableId(IDR_ANDROID_AUTOFILL_SETTINGS), + GetMessageWrapper()->GetSecondaryIconResourceId()); + EXPECT_EQ(l10n_util::GetStringUTF16(IDS_PAGE_INFO_SAFETY_TIP_MORE_INFO_LINK), + GetMessageWrapper()->GetSecondaryButtonMenuText()); + DismissMessage(); +}
diff --git a/chrome/browser/reputation/safety_tip_ui_helper.cc b/chrome/browser/reputation/safety_tip_ui_helper.cc index 4240fe4..ba163fa9 100644 --- a/chrome/browser/reputation/safety_tip_ui_helper.cc +++ b/chrome/browser/reputation/safety_tip_ui_helper.cc
@@ -34,7 +34,8 @@ navigated_to = GURL(kSafetyTipLeaveSiteUrl); #if defined(OS_ANDROID) - if (TabAndroid::FromWebContents(web_contents)->IsCustomTab()) { + TabAndroid* tab = TabAndroid::FromWebContents(web_contents); + if (tab && tab->IsCustomTab()) { auto& controller = web_contents->GetController(); // For CCTs, just go back if we can... if (controller.CanGoBack()) {
diff --git a/chrome/browser/resources/chromeos/about_os_credits.html b/chrome/browser/resources/chromeos/about_os_credits.html index d47ac1db0..273562d 100644 --- a/chrome/browser/resources/chromeos/about_os_credits.html +++ b/chrome/browser/resources/chromeos/about_os_credits.html
@@ -17,7 +17,7 @@ <a href="https://dev.chromium.org/chromium-os/licensing-for-chromiumos-package-owners">Licensing for Chromium OS Package Owners</a></p> <p> If you need to change styles, fonts, layout, etc of <a href="chrome://os_credits">chrome://os_credits</a> page, -edit <a href="https://chromium.googlesource.com/chromiumos/chromite/+/master/licensing/about_credits.tmpl">chromite/licensing/about_credits.tmpl</a>. +edit <a href="https://chromium.googlesource.com/chromiumos/chromite/+/main/licensing/about_credits.tmpl">chromite/licensing/about_credits.tmpl</a>. The template is used to generate a device-dependent about_os_credits.html when a CrOS image is built.</p> </body>
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/BUILD.gn b/chrome/browser/resources/chromeos/accessibility/chromevox/BUILD.gn index 3edb7d6..f4920d32 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/BUILD.gn +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/BUILD.gn
@@ -4,7 +4,6 @@ import("//build/config/chromeos/ui_mode.gni") import("//build/config/features.gni") -import("//build/config/python.gni") import( "//chrome/browser/resources/chromeos/accessibility/common/run_jsbundler.gni") import("//chrome/common/features.gni") @@ -246,8 +245,7 @@ } } -# TODO(crbug.com/1112471): Get this to run under Python3. -python2_action("chromevox_phonetic_dictionaries_js") { +action("chromevox_phonetic_dictionaries_js") { script = "tools/phonetic_dictionaries.py" src_dir = [ "$root_out_dir/resources/chromeos/accessibility/_locales" ] output_file = "$chromevox_out_dir/phonetic_dictionaries.js" @@ -328,8 +326,7 @@ data += js2gtest_js_libraries } - # TODO(crbug.com/1112471): Get this to run under Python3. - python2_action("chromevox_test_messages_js") { + action("chromevox_test_messages_js") { script = "tools/generate_test_messages.py" sources = [ "$root_out_dir/resources/chromeos/accessibility/_locales/en/messages.json.gz" ] output_file = "$root_out_dir/test_data/chrome/browser/resources/chromeos/accessibility/chromevox/host/testing/test_messages.js"
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/tools/generate_test_messages.py b/chrome/browser/resources/chromeos/accessibility/chromevox/tools/generate_test_messages.py index 74db7850..841ed93e 100755 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/tools/generate_test_messages.py +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/tools/generate_test_messages.py
@@ -6,6 +6,7 @@ '''Generates test_messages.js from an extension message json file.''' import gzip +import io import optparse import sys @@ -42,10 +43,10 @@ def _OpenFile(filename): if filename.endswith('.gz'): return gzip.open(filename) - return open(filename) + return open(filename, 'rb') with _OpenFile(in_file_name) as in_file: - json = in_file.read().strip() - with open(options.output_file, 'w') as out_file: + json = in_file.read().decode('utf-8').strip() + with io.open(options.output_file, 'w', encoding='utf-8') as out_file: out_file.write(_JS_TEMPLATE % {'in_file': in_file_name, 'json': json})
diff --git a/chrome/browser/resources/chromeos/crostini_installer/app.js b/chrome/browser/resources/chromeos/crostini_installer/app.js index b98ae03b..8fa6200 100644 --- a/chrome/browser/resources/chromeos/crostini_installer/app.js +++ b/chrome/browser/resources/chromeos/crostini_installer/app.js
@@ -458,12 +458,6 @@ case InstallerState.kConfigureContainer: messageId = 'configureContainerMessage'; break; - case InstallerState.kFetchSshKeys: - messageId = 'fetchSshKeysMessage'; - break; - case InstallerState.kMountContainer: - messageId = 'mountContainerMessage'; - break; default: assertNotReached(); } @@ -503,12 +497,6 @@ case InstallerError.kErrorOffline: messageId = 'offlineError'; break; - case InstallerError.kErrorFetchingSshKeys: - messageId = 'fetchSshKeysError'; - break; - case InstallerError.kErrorMountingContainer: - messageId = 'mountContainerError'; - break; case InstallerError.kErrorSettingUpContainer: messageId = 'setupContainerError'; break;
diff --git a/chrome/browser/resources/chromeos/emoji_picker/emoji_button.html b/chrome/browser/resources/chromeos/emoji_picker/emoji_button.html index 0490afc..a9f9501 100644 --- a/chrome/browser/resources/chromeos/emoji_picker/emoji_button.html +++ b/chrome/browser/resources/chromeos/emoji_picker/emoji_button.html
@@ -24,8 +24,6 @@ #emoji-button:focus, #emoji-button:active { - --emoji-background: rgba(var(--cr-hairline-rgb), 0.1); - border-radius: 50%; outline-color: var(--cr-toggle-color); outline-width: 2px; }
diff --git a/chrome/browser/resources/chromeos/emoji_picker/emoji_picker.html b/chrome/browser/resources/chromeos/emoji_picker/emoji_picker.html index 0ff5a14..624fc16 100644 --- a/chrome/browser/resources/chromeos/emoji_picker/emoji_picker.html +++ b/chrome/browser/resources/chromeos/emoji_picker/emoji_picker.html
@@ -158,7 +158,7 @@ <div id="message" class="sr-only" aria-live="polite"></div> <emoji-search class="side-padding" - id$="search-container" + id="search-container" emoji-data="[[emojiData]]" search="{{search}}" on-scroll="onSearchScroll">
diff --git a/chrome/browser/resources/chromeos/emoji_picker/emoji_picker.js b/chrome/browser/resources/chromeos/emoji_picker/emoji_picker.js index b0c53bd..28f61dc 100644 --- a/chrome/browser/resources/chromeos/emoji_picker/emoji_picker.js +++ b/chrome/browser/resources/chromeos/emoji_picker/emoji_picker.js
@@ -242,7 +242,11 @@ ['history', 'emoji'], makeRecentlyUsed(this.recentEmojiStore.data.history)); } - this.apiProxy_.insertEmoji(emoji, isVariant); + const searchLength = this.$['search-container'] + .shadowRoot.querySelector('cr-search-field') + .getSearchInput() + .value.length; + this.apiProxy_.insertEmoji(emoji, isVariant, searchLength); } clearRecentEmoji() {
diff --git a/chrome/browser/resources/chromeos/emoji_picker/emoji_picker_api_proxy.js b/chrome/browser/resources/chromeos/emoji_picker/emoji_picker_api_proxy.js index f7e46a72..159bad82 100644 --- a/chrome/browser/resources/chromeos/emoji_picker/emoji_picker_api_proxy.js +++ b/chrome/browser/resources/chromeos/emoji_picker/emoji_picker_api_proxy.js
@@ -13,8 +13,9 @@ * * @param {string} emoji * @param {boolean} isVariant + * @param {number} searchLength */ - insertEmoji(emoji, isVariant) {} + insertEmoji(emoji, isVariant, searchLength) {} /** * @returns {Promise<{incognito:boolean}>} @@ -36,8 +37,8 @@ this.handler.showUI(); } /** @override */ - insertEmoji(emoji, isVariant) { - this.handler.insertEmoji(emoji, isVariant); + insertEmoji(emoji, isVariant, searchLength) { + this.handler.insertEmoji(emoji, isVariant, searchLength); } /** @override */
diff --git a/chrome/browser/resources/chromeos/zip_archiver/unpacker-test/README.txt b/chrome/browser/resources/chromeos/zip_archiver/unpacker-test/README.txt index 56f7468..ab674856 100644 --- a/chrome/browser/resources/chromeos/zip_archiver/unpacker-test/README.txt +++ b/chrome/browser/resources/chromeos/zip_archiver/unpacker-test/README.txt
@@ -5,5 +5,5 @@ part of browser_tests, files under this directory should be removed. If you want to run tests under this diretory, see: -https://chromium.googlesource.com/apps/unpacker/+/master/README.md +https://chromium.googlesource.com/apps/unpacker/+/main/README.md
diff --git a/chrome/browser/resources/chromeos/zip_archiver/unpacker-test/cpp/Makefile b/chrome/browser/resources/chromeos/zip_archiver/unpacker-test/cpp/Makefile index 46705da..cb64db4 100644 --- a/chrome/browser/resources/chromeos/zip_archiver/unpacker-test/cpp/Makefile +++ b/chrome/browser/resources/chromeos/zip_archiver/unpacker-test/cpp/Makefile
@@ -71,7 +71,7 @@ # manually. # -disable-setuid-sandbox is optional, but otherwise it is necessary to set up # the sandbox for development. See -# https://chromium.googlesource.com/chromium/src/+/master/docs/linux/suid_sandbox_development.md +# https://chromium.googlesource.com/chromium/src/+/main/docs/linux/suid_sandbox_development.md .PHONY: tests_run tests_run: check_for_chrome all $(TEST_PAGE) $(RUN_PY) -C $(CURDIR) -P $(TEST_PAGE_CONFIG) \
diff --git a/chrome/browser/resources/omnibox/omnibox_output.js b/chrome/browser/resources/omnibox/omnibox_output.js index 69cbaa9a..1e00f45 100644 --- a/chrome/browser/resources/omnibox/omnibox_output.js +++ b/chrome/browser/resources/omnibox/omnibox_output.js
@@ -1118,7 +1118,7 @@ ['duplicates'], OutputTextProperty), new Column( ['pi'], - 'https://source.chromium.org/chromium/chromium/src/+/master:components/omnibox/browser/omnibox_pedal_concepts.h;l=19;drc=c741e070dbfcc33b2369e7a5131be87c7b21bb99', + 'https://source.chromium.org/chromium/chromium/src/+/main:components/omnibox/browser/omnibox_pedal_concepts.h;l=19;drc=c741e070dbfcc33b2369e7a5131be87c7b21bb99', 'pedalId', false, 'Pedal ID\nThe ID of attached Pedal, or zero if none.', ['pedalId'], OutputTextProperty), new Column(
diff --git a/chrome/browser/resources/safe_browsing/README.md b/chrome/browser/resources/safe_browsing/README.md index 620ed95e..64307db3 100644 --- a/chrome/browser/resources/safe_browsing/README.md +++ b/chrome/browser/resources/safe_browsing/README.md
@@ -6,7 +6,7 @@ Chrome released and pushable to Chrome between releases (via `FileTypePolicies` class). http://crbug.com/596555 -Rendered version of this file: https://chromium.googlesource.com/chromium/src/+/master/chrome/browser/resources/safe_browsing/README.md +Rendered version of this file: https://chromium.googlesource.com/chromium/src/+/main/chrome/browser/resources/safe_browsing/README.md ## Procedure for adding/modifying file type(s)
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/fake_page_handler.js b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/fake_page_handler.js index 5426db3..8ad4852 100644 --- a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/fake_page_handler.js +++ b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/fake_page_handler.js
@@ -104,6 +104,7 @@ permissions: {}, hideMoreSettings: false, hidePinToShelf: false, + isPreferredApp: false, }; if (optConfig) {
diff --git a/chrome/browser/resources/settings/privacy_sandbox/app.html b/chrome/browser/resources/settings/privacy_sandbox/app.html index bac75f2..b6d6b00 100644 --- a/chrome/browser/resources/settings/privacy_sandbox/app.html +++ b/chrome/browser/resources/settings/privacy_sandbox/app.html
@@ -49,6 +49,10 @@ margin-top: var(--cr-section-vertical-margin); } + #flocExplanation { + margin-block-end: 8px; + } + #overscroll { padding-top: 64px; } @@ -131,7 +135,7 @@ $i18n{privacySandboxPageSettingExplanation1Phase2} </div> </div> - <div class="cr-row continuation"> + <div class="cr-row continuation box-last"> <div class="secondary"> <ul> <li> @@ -156,7 +160,7 @@ <settings-toggle-button pref="{{prefs.generated.floc_enabled}}" label="$i18n{privacySandboxPageFlocHeading}"> </settings-toggle-button> - <div class="cr-row continuation"> + <div id="flocExplanation" class="cr-row continuation"> <div class="secondary">$i18nRaw{privacySandboxPageFlocExplanation}</div> </div> <div class="cr-row continuation">
diff --git a/chrome/browser/resources/web_app_internals/web_app_internals.html b/chrome/browser/resources/web_app_internals/web_app_internals.html index c37a8e2..c6c473c 100644 --- a/chrome/browser/resources/web_app_internals/web_app_internals.html +++ b/chrome/browser/resources/web_app_internals/web_app_internals.html
@@ -34,22 +34,6 @@ <div class="section"> <p>Save JSON: <button id="saveButton">Save file</button></p> <p>Load JSON: <input type="file" id="loadButton"></p> - <p>BMO enabled: <b>[[isBmoEnabled_]]</b></p> - <template is="dom-if" if="[[!isBmoEnabled_]]"> - <p> - Web apps are using the extension system via bookmark apps, see - <a href="chrome://extensions-internals"> - chrome://extensions-internals - </a> - for bookmark app details. - </p> - <p> - Enable BMO via - <a href="chrome://flags/#enable-desktop-pwas-without-extensions"> - chrome://flags/#enable-desktop-pwas-without-extensions. - </a> - </p> - </template> </div> <div class="section">
diff --git a/chrome/browser/resources/web_app_internals/web_app_internals.js b/chrome/browser/resources/web_app_internals/web_app_internals.js index c459027..e3f1d20 100644 --- a/chrome/browser/resources/web_app_internals/web_app_internals.js +++ b/chrome/browser/resources/web_app_internals/web_app_internals.js
@@ -13,12 +13,6 @@ properties: { /** - * Whether Bookmark apps off Extensions is enabled. - * @private {!boolean} - */ - isBmoEnabled_: Boolean, - - /** * List of internal details about installed web apps. * @private {!Array<!mojom.webAppInternals.WebApp>} */ @@ -46,8 +40,6 @@ const remote = mojom.webAppInternals.WebAppInternalsPageHandler.getRemote(); - this.isBmoEnabled_ = (await remote.isBmoEnabled()).isBmoEnabled; - this.webAppList_ = (await remote.getWebApps()).webAppList; this.webAppList_.sort((a, b) => a.name.localeCompare(b.name));
diff --git a/chrome/browser/search/README.md b/chrome/browser/search/README.md index 567ce33..0f9932f 100644 --- a/chrome/browser/search/README.md +++ b/chrome/browser/search/README.md
@@ -31,7 +31,7 @@ [local-ntp]: #local-ntp [third-party-ntp]: #third_party-ntp -[engines]: https://chromium.googlesource.com/chromium/src/+/master/components/search_engines/prepopulated_engines.json +[engines]: https://chromium.googlesource.com/chromium/src/+/main/components/search_engines/prepopulated_engines.json Variants --------
diff --git a/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/long_screenshots/LongScreenshotsCoordinator.java b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/long_screenshots/LongScreenshotsCoordinator.java index 24d4d4fc..83b0888 100644 --- a/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/long_screenshots/LongScreenshotsCoordinator.java +++ b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/long_screenshots/LongScreenshotsCoordinator.java
@@ -8,6 +8,7 @@ import androidx.annotation.Nullable; +import org.chromium.chrome.R; import org.chromium.chrome.browser.paint_preview.PaintPreviewCompositorUtils; import org.chromium.chrome.browser.share.long_screenshots.bitmap_generation.EntryManager; import org.chromium.chrome.browser.share.screenshot.ScreenshotCoordinator; @@ -15,6 +16,7 @@ import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.modules.image_editor.ImageEditorModuleProvider; import org.chromium.components.browser_ui.bottomsheet.BottomSheetController; +import org.chromium.ui.widget.Toast; /** * Handles the long screenshot action in the Sharing Hub and launches the screenshot editor. @@ -84,7 +86,9 @@ mMediator.capture(() -> { mScreenshot = mMediator.getScreenshot(); if (mScreenshot == null) { - // TODO(crbug/1024586): Show error message + Toast.makeText(mActivity, R.string.sharing_long_screenshot_unknown_error, + Toast.LENGTH_LONG) + .show(); } else { super.handleScreenshot(); }
diff --git a/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/long_screenshots/LongScreenshotsMediator.java b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/long_screenshots/LongScreenshotsMediator.java index cd8ad92c..9bbd18c 100644 --- a/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/long_screenshots/LongScreenshotsMediator.java +++ b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/long_screenshots/LongScreenshotsMediator.java
@@ -29,6 +29,7 @@ import org.chromium.chrome.browser.share.screenshot.EditorScreenshotSource; import org.chromium.ui.modelutil.PropertyModel; import org.chromium.ui.modelutil.PropertyModelChangeProcessor; +import org.chromium.ui.widget.Toast; /** * LongScreenshotsMediator is responsible for retrieving the long screenshot Bitmaps via @@ -63,7 +64,10 @@ if (status == EntryStatus.BITMAP_GENERATED) { showAreaSelectionDialog(entry.getBitmap()); } else { - // TODO(tgupta/kmilka): Handle the error case correctly. + // TODO(crbug/1024586): Handle the error case properly: dismiss dialog? + Toast.makeText(mActivity, R.string.sharing_long_screenshot_unknown_error, + Toast.LENGTH_LONG) + .show(); } } }); @@ -123,20 +127,7 @@ } LongScreenshotsEntry newEntry = mEntryManager.getNextEntry(mCurrentEntry.getId()); - if (newEntry == null) { - return; - } else if (newEntry.getStatus() == EntryStatus.BOUNDS_BELOW_CAPTURE) { - // TODO(crbug/1153969): Disable the down button and show a toast - return; - } - - mPendingEntry = newEntry; - // Next entry is already generated/available. - if (mPendingEntry.getStatus() == EntryStatus.BITMAP_GENERATED) { - onResult(EntryStatus.BITMAP_GENERATED); - } else { - mPendingEntry.setListener(this); - } + processNewEntry(newEntry); } public void areaSelectionUp(View view) { @@ -147,10 +138,34 @@ } LongScreenshotsEntry newEntry = mEntryManager.getPreviousEntry(mCurrentEntry.getId()); + processNewEntry(newEntry); + } + + // Performs postprocessing or error handling on new entry availability. + private void processNewEntry(LongScreenshotsEntry newEntry) { if (newEntry == null) { return; - } else if (newEntry.getStatus() == EntryStatus.BOUNDS_ABOVE_CAPTURE) { - // TODO(crbug/1153969): Disable the down button and show a toast + } + if (newEntry.getStatus() == EntryStatus.BOUNDS_ABOVE_CAPTURE) { + // TODO(crbug/1153969): Disable the up button. + Toast.makeText( + mActivity, R.string.sharing_long_screenshot_reached_top, Toast.LENGTH_LONG) + .show(); + return; + } + + if (newEntry.getStatus() == EntryStatus.BOUNDS_BELOW_CAPTURE) { + // TODO(crbug/1153969): Disable the down button. + Toast.makeText(mActivity, R.string.sharing_long_screenshot_reached_bottom, + Toast.LENGTH_LONG) + .show(); + return; + } + + if (newEntry.getStatus() == EntryStatus.INSUFFICIENT_MEMORY) { + Toast.makeText(mActivity, R.string.sharing_long_screenshot_memory_pressure, + Toast.LENGTH_LONG) + .show(); return; }
diff --git a/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/long_screenshots/bitmap_generation/EntryManager.java b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/long_screenshots/bitmap_generation/EntryManager.java index 2f95700..24d0991 100644 --- a/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/long_screenshots/bitmap_generation/EntryManager.java +++ b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/long_screenshots/bitmap_generation/EntryManager.java
@@ -171,6 +171,7 @@ */ private void updateGeneratorStatus(@EntryStatus int status) { mGeneratorStatus = status; + if (status == EntryStatus.CAPTURE_COMPLETE) { for (LongScreenshotsEntry entry : mQueuedEntries) { entry.generateBitmap();
diff --git a/chrome/browser/shell_integration.cc b/chrome/browser/shell_integration.cc index aa6b876..025b423d 100644 --- a/chrome/browser/shell_integration.cc +++ b/chrome/browser/shell_integration.cc
@@ -18,6 +18,7 @@ #include "base/task/single_thread_task_runner_thread_mode.h" #include "base/task/task_traits.h" #include "base/threading/scoped_blocking_call.h" +#include "base/threading/sequenced_task_runner_handle.h" #include "build/build_config.h" #include "build/chromeos_buildflags.h" #include "chrome/browser/policy/policy_path_parser.h" @@ -89,6 +90,27 @@ } #if !defined(OS_WIN) +void AddAppProtocolClients(const AppProtocolMap& app_protocols, + const base::FilePath& profile_path, + AppProtocolWorkerCallback protocol_worker_callback) { + base::SequencedTaskRunnerHandle::Get()->PostTask( + FROM_HERE, + base::BindOnce(std::move(protocol_worker_callback), /*success=*/false)); +} + +void RemoveAppProtocolClients(const std::vector<std::string>& protocols, + const base::FilePath& profile_path) {} + +void CheckAppIsProtocolClient( + const std::string& app_id, + const std::string& protocol, + const base::FilePath& profile_path, + AppProtocolWorkerCallback protocol_worker_callback) { + base::SequencedTaskRunnerHandle::Get()->PostTask( + FROM_HERE, + base::BindOnce(std::move(protocol_worker_callback), /*success=*/false)); +} + bool IsElevationNeededForSettingDefaultProtocolClient() { return false; }
diff --git a/chrome/browser/shell_integration.h b/chrome/browser/shell_integration.h index d19b601..3413f93 100644 --- a/chrome/browser/shell_integration.h +++ b/chrome/browser/shell_integration.h
@@ -34,6 +34,34 @@ // all OSs. bool SetAsDefaultProtocolClient(const std::string& protocol); +// Maps protocols to handler app ids. A protocol with no app id (absl::nullopt) +// will be handled by the browser which is useful for app protocols requiring +// disambiguation. +using AppProtocolMap = std::map<std::string, absl::optional<std::string>>; + +// Called with the outcome of an asynchronous app protocol operation. +using AppProtocolWorkerCallback = base::OnceCallback<void(bool)>; + +// Registers the browser as the handler for all URL protocols in +// `app_protocols`. Protocols with a corresponding handler app id will be +// registered to launch that app. `protocol_worker_callback` will be run on the +// caller's sequence to report the results. +void AddAppProtocolClients(const AppProtocolMap& app_protocols, + const base::FilePath& profile_path, + AppProtocolWorkerCallback protocol_worker_callback); + +// Removes each protocol and its registered web app handler from the OS. +void RemoveAppProtocolClients(const std::vector<std::string>& protocols, + const base::FilePath& profile_path); + +// Determines if web app with `app_id` is the default client application for the +// given protocol. +void CheckAppIsProtocolClient( + const std::string& app_id, + const std::string& protocol, + const base::FilePath& profile_path, + AppProtocolWorkerCallback protocol_worker_callback); + // The different types of permissions required to set a default web client. enum DefaultWebClientSetPermission { // The browser distribution is not permitted to be made default.
diff --git a/chrome/browser/shell_integration_win.cc b/chrome/browser/shell_integration_win.cc index 66c6452..39e294a 100644 --- a/chrome/browser/shell_integration_win.cc +++ b/chrome/browser/shell_integration_win.cc
@@ -44,6 +44,7 @@ #include "base/win/windows_version.h" #include "chrome/browser/policy/policy_path_parser.h" #include "chrome/browser/shell_integration.h" +#include "chrome/browser/web_applications/components/web_app_handler_registration_utils_win.h" #include "chrome/browser/web_applications/components/web_app_helpers.h" #include "chrome/browser/web_applications/components/web_app_shortcut_win.h" #include "chrome/browser/win/settings_app_monitor.h" @@ -578,6 +579,98 @@ return true; } +void AddAppProtocolClients(const AppProtocolMap& app_protocols, + const base::FilePath& profile_path, + AppProtocolWorkerCallback protocol_worker_callback) { + auto set_app_as_protocol_client_task = base::BindOnce( + [](const AppProtocolMap& app_protocols, + const base::FilePath& profile_path) { + base::FilePath chrome_exe; + if (!base::PathService::Get(base::FILE_EXE, &chrome_exe)) + return false; + + std::vector<std::pair<std::wstring, std::wstring>> + protocol_association_pairs; + protocol_association_pairs.reserve(app_protocols.size()); + + for (const auto& protocol_pair : app_protocols) { + std::wstring protocol = base::UTF8ToWide(protocol_pair.first); + const absl::optional<std::string>& app_id = protocol_pair.second; + // A protocol with no app id (absl::nullopt) will be handled by the + // browser for disambiguation. + std::wstring handler_progid = + app_id.has_value() + ? web_app::GetProgIdForApp(profile_path, app_id.value()) + : ShellUtil::GetProgIdForBrowser(chrome_exe); + + protocol_association_pairs.emplace_back(protocol, handler_progid); + } + + ShellUtil::ProtocolAssociations protocol_associations( + std::move(protocol_association_pairs)); + return ShellUtil::AddAppProtocolAssociations(protocol_associations, + chrome_exe); + }, + app_protocols, profile_path); + + base::ThreadPool::PostTaskAndReplyWithResult( + FROM_HERE, {base::MayBlock()}, std::move(set_app_as_protocol_client_task), + std::move(protocol_worker_callback)); +} + +void RemoveAppProtocolClients(const std::vector<std::string>& protocols, + const base::FilePath& profile_path) { + auto delete_protocol_registration = base::BindOnce( + [](const std::vector<std::string>& protocols, + const base::FilePath& profile_path) { + // TODO(http://crbug.com/1019239): RemoveAppProtocolClients will remove + // all registrations across all profiles. profile_path will be used once + // multi-profile support is added. + base::FilePath chrome_exe; + if (!base::PathService::Get(base::FILE_EXE, &chrome_exe)) { + return; + } + + std::vector<std::wstring> wstring_protocols; + wstring_protocols.reserve(protocols.size()); + + for (const auto& protocol : protocols) { + wstring_protocols.push_back(base::UTF8ToWide(protocol)); + } + + ShellUtil::RemoveAppProtocolAssociations(wstring_protocols, chrome_exe, + /*elevate_if_not_admin=*/true); + }, + protocols, profile_path); + + base::ThreadPool::PostTask(FROM_HERE, {base::MayBlock()}, + std::move(delete_protocol_registration)); +} + +void CheckAppIsProtocolClient( + const std::string& app_id, + const std::string& protocol, + const base::FilePath& profile_path, + AppProtocolWorkerCallback protocol_worker_callback) { + auto check_app_is_protocol_client_task = base::BindOnce( + [](const std::string& app_id, const std::string& protocol, + const base::FilePath& profile_path) { + std::wstring prog_id = web_app::GetProgIdForApp(profile_path, app_id); + base::FilePath chrome_exe; + if (!base::PathService::Get(base::FILE_EXE, &chrome_exe)) { + return false; + } + return ShellUtil::DoesAppProtocolAssociationExist( + base::UTF8ToWide(protocol), prog_id, chrome_exe); + }, + app_id, protocol, profile_path); + + base::ThreadPool::PostTaskAndReplyWithResult( + FROM_HERE, {base::MayBlock()}, + std::move(check_app_is_protocol_client_task), + std::move(protocol_worker_callback)); +} + DefaultWebClientSetPermission GetDefaultWebClientSetPermission() { if (!install_static::SupportsSetAsDefaultBrowser()) return SET_DEFAULT_NOT_ALLOWED;
diff --git a/chrome/browser/speech/extension_api/tts_engine_extension_api_chromeos.cc b/chrome/browser/speech/extension_api/tts_engine_extension_api_chromeos.cc index ad9bff0..b75c125 100644 --- a/chrome/browser/speech/extension_api/tts_engine_extension_api_chromeos.cc +++ b/chrome/browser/speech/extension_api/tts_engine_extension_api_chromeos.cc
@@ -64,30 +64,26 @@ } TtsEngineExtensionObserverChromeOS::GetInstance(profile) - ->BindTtsStreamFactory(tts_stream_factory_.BindNewPipeAndPassReceiver()); + ->BindPlaybackTtsStream( + playback_tts_stream_.BindNewPipeAndPassReceiver(), + base::BindOnce( + [](extensions::EventRouter* event_router, + std::unique_ptr<base::ListValue> args, + const std::string& engine_id, Profile* profile, + TtsExtensionEngineChromeOS* owner, int32_t sample_rate, + int32_t buffer_size) { + // |owner| is always valid because TtsExtensionEngine is a + // singleton. + owner->UpdateAudioStreamOptions(sample_rate, buffer_size); + owner->Play(event_router, std::move(args), engine_id, profile); + }, + event_router, std::move(args), engine_id, profile, this)); - tts_stream_factory_->CreatePlaybackTtsStream(base::BindOnce( - [](mojo::Remote<chromeos::tts::mojom::PlaybackTtsStream>* - playback_tts_stream, - extensions::EventRouter* event_router, - std::unique_ptr<base::ListValue> args, const std::string& engine_id, - Profile* profile, TtsExtensionEngineChromeOS* owner, - mojo::PendingRemote<chromeos::tts::mojom::PlaybackTtsStream> stream, - int32_t sample_rate, int32_t buffer_size) { - playback_tts_stream->Bind(std::move(stream)); - playback_tts_stream->set_disconnect_handler(base::BindOnce( - [](mojo::Remote<chromeos::tts::mojom::PlaybackTtsStream>* stream) { - stream->reset(); - }, - playback_tts_stream)); - - // |owner| is always valid because TtsExtensionEngine is a - // singleton. - owner->UpdateAudioStreamOptions(sample_rate, buffer_size); - owner->Play(event_router, std::move(args), engine_id, profile); + playback_tts_stream_.set_disconnect_handler(base::BindOnce( + [](mojo::Remote<chromeos::tts::mojom::PlaybackTtsStream>* stream) { + stream->reset(); }, - &playback_tts_stream_, event_router, std::move(args), engine_id, profile, - this)); + &playback_tts_stream_)); } void TtsExtensionEngineChromeOS::Stop(content::TtsUtterance* utterance) {
diff --git a/chrome/browser/speech/extension_api/tts_engine_extension_api_chromeos.h b/chrome/browser/speech/extension_api/tts_engine_extension_api_chromeos.h index d98d5f8..3d0379802 100644 --- a/chrome/browser/speech/extension_api/tts_engine_extension_api_chromeos.h +++ b/chrome/browser/speech/extension_api/tts_engine_extension_api_chromeos.h
@@ -63,7 +63,6 @@ const std::string& engine_id, Profile* profile); - mojo::Remote<chromeos::tts::mojom::TtsStreamFactory> tts_stream_factory_; mojo::Remote<chromeos::tts::mojom::PlaybackTtsStream> playback_tts_stream_; mojo::ReceiverSet<chromeos::tts::mojom::TtsEventObserver> tts_event_observer_receiver_set_;
diff --git a/chrome/browser/speech/extension_api/tts_engine_extension_observer_chromeos.cc b/chrome/browser/speech/extension_api/tts_engine_extension_observer_chromeos.cc index 328a14b..c8c2a18 100644 --- a/chrome/browser/speech/extension_api/tts_engine_extension_observer_chromeos.cc +++ b/chrome/browser/speech/extension_api/tts_engine_extension_observer_chromeos.cc
@@ -147,30 +147,15 @@ TtsEngineExtensionObserverChromeOS::~TtsEngineExtensionObserverChromeOS() = default; -void TtsEngineExtensionObserverChromeOS::BindTtsStreamFactory( - mojo::PendingReceiver<chromeos::tts::mojom::TtsStreamFactory> receiver) { +void TtsEngineExtensionObserverChromeOS::BindGoogleTtsStream( + mojo::PendingReceiver<chromeos::tts::mojom::GoogleTtsStream> receiver) { // At this point, the component extension has loaded, and the js has requested // a TtsStreamFactory be bound. It's safe now to update the keep alive count // for important accessibility features. This path is also encountered if the // component extension background page forceably window.close(s) on error. UpdateGoogleSpeechSynthesisKeepAliveCountOnReload(profile_); - // Only launch a new TtsService if necessary. By assigning below, if - // |tts_service_| held a remote, it will be killed and a new one created, - // ensuring we only ever have one TtsService running. - if (!tts_service_) { - tts_service_ = - content::ServiceProcessHost::Launch<chromeos::tts::mojom::TtsService>( - content::ServiceProcessHost::Options() - .WithDisplayName("TtsService") - .Pass()); - - tts_service_.set_disconnect_handler(base::BindOnce( - [](mojo::Remote<chromeos::tts::mojom::TtsService>* tts_service) { - tts_service->reset(); - }, - &tts_service_)); - } + CreateTtsServiceIfNeeded(); // Always create a new audio stream for the tts stream. It is assumed once the // tts stream is reset by the service, the audio stream is appropriately @@ -178,8 +163,23 @@ mojo::PendingRemote<media::mojom::AudioStreamFactory> factory_remote; auto factory_receiver = factory_remote.InitWithNewPipeAndPassReceiver(); content::GetAudioService().BindStreamFactory(std::move(factory_receiver)); - tts_service_->BindTtsStreamFactory(std::move(receiver), - std::move(factory_remote)); + tts_service_->BindGoogleTtsStream(std::move(receiver), + std::move(factory_remote)); +} + +void TtsEngineExtensionObserverChromeOS::BindPlaybackTtsStream( + mojo::PendingReceiver<chromeos::tts::mojom::PlaybackTtsStream> receiver, + chromeos::tts::mojom::TtsService::BindPlaybackTtsStreamCallback callback) { + CreateTtsServiceIfNeeded(); + + // Always create a new audio stream for the tts stream. It is assumed once the + // tts stream is reset by the service, the audio stream is appropriately + // cleaned up by the audio service. + mojo::PendingRemote<media::mojom::AudioStreamFactory> factory_remote; + auto factory_receiver = factory_remote.InitWithNewPipeAndPassReceiver(); + content::GetAudioService().BindStreamFactory(std::move(factory_receiver)); + tts_service_->BindPlaybackTtsStream( + std::move(receiver), std::move(factory_remote), std::move(callback)); } void TtsEngineExtensionObserverChromeOS::Shutdown() { @@ -249,3 +249,23 @@ // increment. Decrements only occur when toggling off here. UpdateGoogleSpeechSynthesisKeepAliveCount(profile(), details.enabled); } + +void TtsEngineExtensionObserverChromeOS::CreateTtsServiceIfNeeded() { + // Only launch a new TtsService if necessary. By assigning below, if + // |tts_service_| held a remote, it will be killed and a new one created, + // ensuring we only ever have one TtsService running. + if (tts_service_) + return; + + tts_service_ = + content::ServiceProcessHost::Launch<chromeos::tts::mojom::TtsService>( + content::ServiceProcessHost::Options() + .WithDisplayName("TtsService") + .Pass()); + + tts_service_.set_disconnect_handler(base::BindOnce( + [](mojo::Remote<chromeos::tts::mojom::TtsService>* tts_service) { + tts_service->reset(); + }, + &tts_service_)); +}
diff --git a/chrome/browser/speech/extension_api/tts_engine_extension_observer_chromeos.h b/chrome/browser/speech/extension_api/tts_engine_extension_observer_chromeos.h index 66c2246b..7269370 100644 --- a/chrome/browser/speech/extension_api/tts_engine_extension_observer_chromeos.h +++ b/chrome/browser/speech/extension_api/tts_engine_extension_observer_chromeos.h
@@ -33,8 +33,11 @@ Profile* profile() { return profile_; } - void BindTtsStreamFactory( - mojo::PendingReceiver<chromeos::tts::mojom::TtsStreamFactory> receiver); + void BindGoogleTtsStream( + mojo::PendingReceiver<chromeos::tts::mojom::GoogleTtsStream> receiver); + void BindPlaybackTtsStream( + mojo::PendingReceiver<chromeos::tts::mojom::PlaybackTtsStream> receiver, + chromeos::tts::mojom::TtsService::BindPlaybackTtsStreamCallback callback); // Implementation of KeyedService. void Shutdown() override; @@ -62,6 +65,8 @@ void OnAccessibilityStatusChanged( const ash::AccessibilityStatusEventDetails& details); + void CreateTtsServiceIfNeeded(); + base::ScopedObservation<extensions::ExtensionRegistry, extensions::ExtensionRegistryObserver> extension_registry_observation_{this};
diff --git a/chrome/browser/sync/sessions/sync_sessions_router_tab_helper.h b/chrome/browser/sync/sessions/sync_sessions_router_tab_helper.h index 414098de..be95950 100644 --- a/chrome/browser/sync/sessions/sync_sessions_router_tab_helper.h +++ b/chrome/browser/sync/sessions/sync_sessions_router_tab_helper.h
@@ -25,7 +25,7 @@ // these events to sessions sync. // A TabHelper is a WebContentsObserver tied to the top level WebContents for a // browser tab. -// https://chromium.googlesource.com/chromium/src/+/master/docs/tab_helpers.md +// https://chromium.googlesource.com/chromium/src/+/main/docs/tab_helpers.md class SyncSessionsRouterTabHelper : public content::WebContentsUserData<SyncSessionsRouterTabHelper>, public content::WebContentsObserver,
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index c8f4158..53499cc 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -1604,6 +1604,7 @@ "//components/safety_check", "//components/search_provider_logos", "//components/services/app_service/public/cpp:app_update", + "//components/services/app_service/public/cpp:preferred_apps", "//components/services/app_service/public/mojom", "//components/ui_metrics", "//components/url_formatter",
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings.grd b/chrome/browser/ui/android/strings/android_chrome_strings.grd index c87a2b6..3f71c15 100644 --- a/chrome/browser/ui/android/strings/android_chrome_strings.grd +++ b/chrome/browser/ui/android/strings/android_chrome_strings.grd
@@ -4449,6 +4449,26 @@ Long Screenshot </message> + <message name="IDS_SHARING_LONG_SCREENSHOT_INSTRUCTIONS" desc="Text message instructing users how to extend a screenshot region in the long screenshot capture dialog."> + Drag to take a long screenshot + </message> + + <message name="IDS_SHARING_LONG_SCREENSHOT_REACHED_TOP" desc="Text shown in the toast notification when user reached the top of the available screenshot selection window, in the long screenshots feature."> + Can\u2019t go higher. Try starting from further up the page. + </message> + + <message name="IDS_SHARING_LONG_SCREENSHOT_REACHED_BOTTOM" desc="Text shown in the toast notification when user reached the bottom of the available screenshot selection window, in the long screenshots feature."> + Can\u2019t go lower. Try starting from further down the page. + </message> + + <message name="IDS_SHARING_LONG_SCREENSHOT_MEMORY_PRESSURE" desc="Text shown in the toast notification when additional screenshot data cannot be captured due to memory pressure, in the long screenshots feature."> + Can\u2019t extend screenshot. Try again when your phone isn\u2019t busy. + </message> + + <message name="IDS_SHARING_LONG_SCREENSHOT_UNKNOWN_ERROR" desc="Text shown in the toast notification when screenshot data cannot be captured due to a general or unknown error, in the long screenshots feature."> + Something went wrong. Try again. + </message> + <message name="IDS_SHARING_HIGHLIGHTS" desc="Label for Link-to-text button in the sharing hub."> Link to highlight </message>
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_SHARING_LONG_SCREENSHOT_INSTRUCTIONS.png.sha1 b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_SHARING_LONG_SCREENSHOT_INSTRUCTIONS.png.sha1 new file mode 100644 index 0000000..76a1b89e --- /dev/null +++ b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_SHARING_LONG_SCREENSHOT_INSTRUCTIONS.png.sha1
@@ -0,0 +1 @@ +836a37816b4e5402e899a4a28299ae5d11369f1d \ No newline at end of file
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_SHARING_LONG_SCREENSHOT_MEMORY_PRESSURE.png.sha1 b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_SHARING_LONG_SCREENSHOT_MEMORY_PRESSURE.png.sha1 new file mode 100644 index 0000000..6e08744 --- /dev/null +++ b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_SHARING_LONG_SCREENSHOT_MEMORY_PRESSURE.png.sha1
@@ -0,0 +1 @@ +93efd2c879d9bd12ef3f116a7ccbe2deeafe4e61 \ No newline at end of file
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_SHARING_LONG_SCREENSHOT_REACHED_BOTTOM.png.sha1 b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_SHARING_LONG_SCREENSHOT_REACHED_BOTTOM.png.sha1 new file mode 100644 index 0000000..a7edd4d --- /dev/null +++ b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_SHARING_LONG_SCREENSHOT_REACHED_BOTTOM.png.sha1
@@ -0,0 +1 @@ +3ac8a292e78db54a62c159f5465bf3f6198a6f5f \ No newline at end of file
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_SHARING_LONG_SCREENSHOT_REACHED_TOP.png.sha1 b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_SHARING_LONG_SCREENSHOT_REACHED_TOP.png.sha1 new file mode 100644 index 0000000..df56915 --- /dev/null +++ b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_SHARING_LONG_SCREENSHOT_REACHED_TOP.png.sha1
@@ -0,0 +1 @@ +1057495c68ccc8c916ff63d37780844362246466 \ No newline at end of file
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_SHARING_LONG_SCREENSHOT_UNKNOWN_ERROR.png.sha1 b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_SHARING_LONG_SCREENSHOT_UNKNOWN_ERROR.png.sha1 new file mode 100644 index 0000000..281ef368 --- /dev/null +++ b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_SHARING_LONG_SCREENSHOT_UNKNOWN_ERROR.png.sha1
@@ -0,0 +1 @@ +ccec60875cdc4b444646faa11ca443dcad1da408 \ No newline at end of file
diff --git a/chrome/browser/ui/autofill/save_update_address_profile_bubble_controller_impl.cc b/chrome/browser/ui/autofill/save_update_address_profile_bubble_controller_impl.cc index c332da15..17bc4f9b 100644 --- a/chrome/browser/ui/autofill/save_update_address_profile_bubble_controller_impl.cc +++ b/chrome/browser/ui/autofill/save_update_address_profile_bubble_controller_impl.cc
@@ -48,6 +48,19 @@ profile); return; } + // If the user closed the bubble of the previous import process using the + // "Close" button without making a decision to "Accept" or "Deny" the prompt, + // a fallback icon is shown, so the user can get back to the prompt. In this + // specific scenario the import process is considered in progress (since the + // backend didn't hear back via the callback yet), but hidden. When a second + // prompt arrives, we finish the previous import process as "Ignored", before + // showing the 2nd prompt. + if (address_profile_save_prompt_callback_) { + std::move(address_profile_save_prompt_callback_) + .Run(AutofillClient::SaveAddressProfileOfferUserDecision::kIgnored, + address_profile_); + } + address_profile_ = profile; original_profile_ = base::OptionalFromPtr(original_profile); address_profile_save_prompt_callback_ =
diff --git a/chrome/browser/ui/autofill/save_update_address_profile_bubble_controller_impl_unittest.cc b/chrome/browser/ui/autofill/save_update_address_profile_bubble_controller_impl_unittest.cc index ea04a97..c188a50 100644 --- a/chrome/browser/ui/autofill/save_update_address_profile_bubble_controller_impl_unittest.cc +++ b/chrome/browser/ui/autofill/save_update_address_profile_bubble_controller_impl_unittest.cc
@@ -138,7 +138,7 @@ // shown, the controller will ignore it, and inform the backend that the second // prompt has been auto declined. TEST_F(SaveUpdateAddressProfileBubbleControllerImplTest, - SecondPromptWillBeAutoDeclined) { + SecondPromptWillBeAutoDeclinedWhileFirstIsVisible) { AutofillProfile profile = test::GetFullProfile(); controller()->OfferSave( @@ -158,4 +158,28 @@ callback.Get()); } +// This is testing that when a second prompt comes while another prompt is in +// progress but not shown, the controller will inform the backend that the first +// process is ignored. +TEST_F(SaveUpdateAddressProfileBubbleControllerImplTest, + FirstHiddenPromptWillBeIgnoredWhenSecondPromptArrives) { + AutofillProfile profile = test::GetFullProfile(); + + base::MockCallback<AutofillClient::AddressProfileSavePromptCallback> callback; + controller()->OfferSave( + profile, /*original_profile=*/nullptr, + AutofillClient::SaveAddressProfilePromptOptions{.show_prompt = true}, + callback.Get()); + controller()->OnBubbleClosed(); + + // When second prompt comes, the first one will be ignored. + EXPECT_CALL(callback, + Run(AutofillClient::SaveAddressProfileOfferUserDecision::kIgnored, + testing::_)); + controller()->OfferSave( + profile, /*original_profile=*/nullptr, + AutofillClient::SaveAddressProfilePromptOptions{.show_prompt = true}, + /*address_profile_save_prompt_callback=*/base::DoNothing()); +} + } // namespace autofill
diff --git a/chrome/browser/ui/startup/startup_browser_creator.cc b/chrome/browser/ui/startup/startup_browser_creator.cc index b2390ee..fdf7a50 100644 --- a/chrome/browser/ui/startup/startup_browser_creator.cc +++ b/chrome/browser/ui/startup/startup_browser_creator.cc
@@ -63,8 +63,6 @@ #include "chrome/browser/ui/startup/startup_browser_creator_impl.h" #include "chrome/browser/ui/ui_features.h" #include "chrome/browser/ui/web_applications/web_app_ui_manager_impl.h" -#include "chrome/browser/web_applications/components/os_integration_manager.h" -#include "chrome/browser/web_applications/components/web_app_provider_base.h" #include "chrome/common/buildflags.h" #include "chrome/common/chrome_constants.h" #include "chrome/common/chrome_features.h" @@ -439,12 +437,19 @@ if (protocol_url.is_empty()) return false; - web_app::WebAppProviderBase* provider = - web_app::WebAppProviderBase::GetProviderBase(profile); - web_app::OsIntegrationManager& os_integration_manager = - provider->os_integration_manager(); + // Check the ProtocolHandlerRegistry for an entry that matches the appId + // and the protocol_url provided in the command line. We want to make sure + // that we only handle protocol handlers that we've registered for when + // installing a web app. This check also filters out file handler url + // activation and other unregistered protocol urls that will be handled + // by other startup code paths. + // TODO::(crbug/1105257) Adjust this once we no longer use + // the ProtocolHandlerRegistry to store protocol handler + // registration info for web apps. + ProtocolHandlerRegistry* handler_registry = + ProtocolHandlerRegistryFactory::GetForBrowserContext(profile); const std::vector<ProtocolHandler> handlers = - os_integration_manager.GetHandlersForProtocol(protocol_url.scheme()); + handler_registry->GetHandlersFor(protocol_url.scheme()); // Nothing to do if there are no handlers with a web_app_id. if (!base::Contains(handlers, true, [](const auto& handler) {
diff --git a/chrome/browser/ui/tab_helpers.h b/chrome/browser/ui/tab_helpers.h index b9bc0f1..507898b3 100644 --- a/chrome/browser/ui/tab_helpers.h +++ b/chrome/browser/ui/tab_helpers.h
@@ -39,7 +39,7 @@ // (or the equivalent on Android). The TabHelpers class allows specific classes // to attach the set of tab helpers that is used for tab contents. // -// https://chromium.googlesource.com/chromium/src/+/master/docs/tab_helpers.md +// https://chromium.googlesource.com/chromium/src/+/main/docs/tab_helpers.md // // TODO(avi): This list is rather large, and for most callers it's due to the // fact that they need tab helpers attached early to deal with arbitrary
diff --git a/chrome/browser/ui/tab_sharing/DIR_METADATA b/chrome/browser/ui/tab_sharing/DIR_METADATA index 7b35aa9b..62edae1 100644 --- a/chrome/browser/ui/tab_sharing/DIR_METADATA +++ b/chrome/browser/ui/tab_sharing/DIR_METADATA
@@ -1,10 +1,10 @@ # Metadata information for this directory. # # For more information on DIR_METADATA files, see: -# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/README.md +# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/README.md # # For the schema of this file, see Metadata message: -# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/proto/dir_metadata.proto +# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/proto/dir_metadata.proto monorail { component: "UI>Browser>MediaCapture"
diff --git a/chrome/browser/ui/views/desktop_capture/DIR_METADATA b/chrome/browser/ui/views/desktop_capture/DIR_METADATA index 7b35aa9b..62edae1 100644 --- a/chrome/browser/ui/views/desktop_capture/DIR_METADATA +++ b/chrome/browser/ui/views/desktop_capture/DIR_METADATA
@@ -1,10 +1,10 @@ # Metadata information for this directory. # # For more information on DIR_METADATA files, see: -# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/README.md +# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/README.md # # For the schema of this file, see Metadata message: -# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/proto/dir_metadata.proto +# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/proto/dir_metadata.proto monorail { component: "UI>Browser>MediaCapture"
diff --git a/chrome/browser/ui/views/tab_sharing/DIR_METADATA b/chrome/browser/ui/views/tab_sharing/DIR_METADATA index 7b35aa9b..62edae1 100644 --- a/chrome/browser/ui/views/tab_sharing/DIR_METADATA +++ b/chrome/browser/ui/views/tab_sharing/DIR_METADATA
@@ -1,10 +1,10 @@ # Metadata information for this directory. # # For more information on DIR_METADATA files, see: -# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/README.md +# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/README.md # # For the schema of this file, see Metadata message: -# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/proto/dir_metadata.proto +# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/proto/dir_metadata.proto monorail { component: "UI>Browser>MediaCapture"
diff --git a/chrome/browser/ui/web_applications/test/ssl_test_utils.cc b/chrome/browser/ui/web_applications/test/ssl_test_utils.cc index afe8f4ef..e027590 100644 --- a/chrome/browser/ui/web_applications/test/ssl_test_utils.cc +++ b/chrome/browser/ui/web_applications/test/ssl_test_utils.cc
@@ -4,11 +4,41 @@ #include "chrome/browser/ui/web_applications/test/ssl_test_utils.h" +#include "base/atomic_sequence_num.h" +#include "base/time/time.h" #include "chrome/browser/ssl/ssl_browsertest_util.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" #include "components/security_state/core/features.h" #include "components/security_state/core/security_state.h" +#include "crypto/rsa_private_key.h" +#include "net/cert/x509_certificate.h" +#include "net/cert/x509_util.h" +#include "net/ssl/ssl_info.h" + +namespace { + +// NSS requires that serial numbers be unique even for the same issuer; +// as all fake certificates will contain the same issuer name, it's +// necessary to ensure the serial number is unique, as otherwise +// NSS will fail to parse. +base::AtomicSequenceNumber g_serial_number; + +scoped_refptr<net::X509Certificate> CreateFakeCert() { + std::unique_ptr<crypto::RSAPrivateKey> unused_key; + std::string cert_der; + if (!net::x509_util::CreateKeyAndSelfSignedCert( + "CN=Error", static_cast<uint32_t>(g_serial_number.GetNext()), + base::Time::Now() - base::TimeDelta::FromMinutes(5), + base::Time::Now() + base::TimeDelta::FromMinutes(5), &unused_key, + &cert_der)) { + return nullptr; + } + return net::X509Certificate::CreateFromBytes(cert_der.data(), + cert_der.size()); +} + +} // namespace namespace web_app { @@ -28,4 +58,8 @@ ssl_test_util::AuthState::NONE); } +void CreateFakeSslInfoCertificate(net::SSLInfo* ssl_info) { + ssl_info->cert = ssl_info->unverified_cert = CreateFakeCert(); +} + } // namespace web_app
diff --git a/chrome/browser/ui/web_applications/test/ssl_test_utils.h b/chrome/browser/ui/web_applications/test/ssl_test_utils.h index fe335db..58cbdca 100644 --- a/chrome/browser/ui/web_applications/test/ssl_test_utils.h +++ b/chrome/browser/ui/web_applications/test/ssl_test_utils.h
@@ -7,6 +7,10 @@ class Browser; +namespace net { +class SSLInfo; +} + namespace web_app { // Checks that the active tab's authentication state indicates insecure content. @@ -15,6 +19,9 @@ // Checks that the active tab's authentication state indicates only secure // content is shown. void CheckMixedContentFailedToLoad(Browser* browser); + +void CreateFakeSslInfoCertificate(net::SSLInfo* ssl_info); + } // namespace web_app #endif // CHROME_BROWSER_UI_WEB_APPLICATIONS_TEST_SSL_TEST_UTILS_H_
diff --git a/chrome/browser/ui/webui/app_management/app_management.mojom b/chrome/browser/ui/webui/app_management/app_management.mojom index 5097e3c..a39fcf3 100644 --- a/chrome/browser/ui/webui/app_management/app_management.mojom +++ b/chrome/browser/ui/webui/app_management/app_management.mojom
@@ -24,6 +24,7 @@ apps.mojom.InstallSource install_source; bool hide_more_settings; bool hide_pin_to_shelf; + bool is_preferred_app; }; // Extension-based apps primarily use install-time permissions that cannot be
diff --git a/chrome/browser/ui/webui/app_management/app_management_page_handler.cc b/chrome/browser/ui/webui/app_management/app_management_page_handler.cc index 99f5ec36..f7f17d0 100644 --- a/chrome/browser/ui/webui/app_management/app_management_page_handler.cc +++ b/chrome/browser/ui/webui/app_management/app_management_page_handler.cc
@@ -17,6 +17,7 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/webui/app_management/app_management.mojom.h" #include "components/services/app_service/public/cpp/app_registry_cache.h" +#include "components/services/app_service/public/cpp/preferred_apps_list.h" #include "components/services/app_service/public/mojom/types.mojom.h" #include "extensions/browser/extension_registry.h" #include "extensions/common/constants.h" @@ -92,9 +93,14 @@ , shelf_delegate_(this, profile) #endif // BUILDFLAG(IS_CHROMEOS_ASH) -{ - Observe(&apps::AppServiceProxyFactory::GetForProfile(profile_) - ->AppRegistryCache()); + , + preferred_apps_list_(apps::AppServiceProxyFactory::GetForProfile(profile) + ->PreferredApps()) { + apps::AppRegistryCache::Observer::Observe( + &apps::AppServiceProxyFactory::GetForProfile(profile_) + ->AppRegistryCache()); + apps::PreferredAppsList::Observer::Observe( + &apps::AppServiceProxyFactory::GetForProfile(profile_)->PreferredApps()); } AppManagementPageHandler::~AppManagementPageHandler() {} @@ -211,7 +217,8 @@ ? OptionalBool::kTrue : OptionalBool::kFalse; #endif - + app->is_preferred_app = + preferred_apps_list_.IsPreferredAppForSupportedLinks(update.AppId()); app->hide_more_settings = ShouldHideMoreSettings(app->id); app->hide_pin_to_shelf = update.ShowInShelf() == apps::mojom::OptionalBool::kFalse || @@ -238,5 +245,30 @@ void AppManagementPageHandler::OnAppRegistryCacheWillBeDestroyed( apps::AppRegistryCache* cache) { - Observe(nullptr); + cache->RemoveObserver(this); +} + +void AppManagementPageHandler::OnPreferredAppChanged(const std::string& app_id, + bool is_preferred_app) { + app_management::mojom::AppPtr app; + + apps::AppServiceProxyFactory::GetForProfile(profile_) + ->AppRegistryCache() + .ForOneApp(app_id, [this, &app](const apps::AppUpdate& update) { + if (update.Readiness() == apps::mojom::Readiness::kReady) + app = CreateUIAppPtr(update); + }); + + // If an app with this id is not already installed, do nothing. + if (!app) + return; + + app->is_preferred_app = is_preferred_app; + + page_->OnAppChanged(std::move(app)); +} + +void AppManagementPageHandler::OnPreferredAppsListWillBeDestroyed( + apps::PreferredAppsList* list) { + list->RemoveObserver(this); }
diff --git a/chrome/browser/ui/webui/app_management/app_management_page_handler.h b/chrome/browser/ui/webui/app_management/app_management_page_handler.h index 4faeb2d3..291f752 100644 --- a/chrome/browser/ui/webui/app_management/app_management_page_handler.h +++ b/chrome/browser/ui/webui/app_management/app_management_page_handler.h
@@ -11,6 +11,7 @@ #include "chrome/browser/ui/webui/app_management/app_management.mojom-forward.h" #include "chrome/browser/ui/webui/app_management/app_management_shelf_delegate_chromeos.h" #include "components/services/app_service/public/cpp/app_registry_cache.h" +#include "components/services/app_service/public/cpp/preferred_apps_list.h" #include "mojo/public/cpp/bindings/pending_receiver.h" #include "mojo/public/cpp/bindings/pending_remote.h" #include "mojo/public/cpp/bindings/receiver.h" @@ -19,7 +20,8 @@ class Profile; class AppManagementPageHandler : public app_management::mojom::PageHandler, - public apps::AppRegistryCache::Observer { + public apps::AppRegistryCache::Observer, + public apps::PreferredAppsList::Observer { public: AppManagementPageHandler( mojo::PendingReceiver<app_management::mojom::PageHandler> receiver, @@ -49,6 +51,12 @@ void OnAppRegistryCacheWillBeDestroyed( apps::AppRegistryCache* cache) override; + // apps::PreferredAppsList::Observer overrides: + void OnPreferredAppChanged(const std::string& app_id, + bool is_preferred_app) override; + void OnPreferredAppsListWillBeDestroyed( + apps::PreferredAppsList* list) override; + mojo::Receiver<app_management::mojom::PageHandler> receiver_; mojo::Remote<app_management::mojom::Page> page_; @@ -59,6 +67,8 @@ AppManagementShelfDelegate shelf_delegate_; #endif // BUILDFLAG(IS_CHROMEOS_ASH) + apps::PreferredAppsList& preferred_apps_list_; + DISALLOW_COPY_AND_ASSIGN(AppManagementPageHandler); };
diff --git a/chrome/browser/ui/webui/chromeos/drive_internals_ui.cc b/chrome/browser/ui/webui/chromeos/drive_internals_ui.cc index 6ffebf9..3b51e519 100644 --- a/chrome/browser/ui/webui/chromeos/drive_internals_ui.cc +++ b/chrome/browser/ui/webui/chromeos/drive_internals_ui.cc
@@ -574,7 +574,7 @@ base::StrCat({"log-", severity})); last_sent_event_id_ = log[i].id; } - if (!list.empty()) { + if (!list.GetList().empty()) { MaybeCallJavascript("updateEventLog", std::move(list)); } } @@ -612,7 +612,7 @@ service_log_file_inode_ = response.first; last_sent_line_number_ = 0; } - if (!response.second.empty()) { + if (!response.second.GetList().empty()) { last_sent_line_number_ += response.second.GetList().size(); MaybeCallJavascript("updateServiceLog", std::move(response.second)); }
diff --git a/chrome/browser/ui/webui/chromeos/emoji/emoji_page_handler.cc b/chrome/browser/ui/webui/chromeos/emoji/emoji_page_handler.cc index cdf5347..0134ec8 100644 --- a/chrome/browser/ui/webui/chromeos/emoji/emoji_page_handler.cc +++ b/chrome/browser/ui/webui/chromeos/emoji/emoji_page_handler.cc
@@ -22,12 +22,14 @@ kMaxValue = kEmojiPickerVariant, }; -void LogInsertEmoji(bool is_variant) { +void LogInsertEmoji(bool is_variant, int16_t search_length) { EmojiVariantType insert_value = is_variant ? EmojiVariantType::kEmojiPickerVariant : EmojiVariantType::kEmojiPickerBase; base::UmaHistogramEnumeration("InputMethod.SystemEmojiPicker.TriggerType", insert_value); + base::UmaHistogramCounts100("InputMethod.SystemEmojiPicker.SearchLength", + search_length); } void LogInsertEmojiDelay(base::TimeDelta delay) { @@ -62,14 +64,15 @@ } void EmojiPageHandler::InsertEmoji(const std::string& emoji_to_insert, - bool is_variant) { + bool is_variant, + int16_t search_length) { // By hiding the emoji picker, we restore focus to the original text field so // we can insert the text. auto embedder = webui_controller_->embedder(); if (embedder) { embedder->CloseUI(); } - LogInsertEmoji(is_variant); + LogInsertEmoji(is_variant, search_length); LogInsertEmojiDelay(base::TimeTicks::Now() - shown_time_); // In theory, we are returning focus to the input field where the user // originally selected emoji. However, the input field may not exist anymore
diff --git a/chrome/browser/ui/webui/chromeos/emoji/emoji_page_handler.h b/chrome/browser/ui/webui/chromeos/emoji/emoji_page_handler.h index b412371a..d804618 100644 --- a/chrome/browser/ui/webui/chromeos/emoji/emoji_page_handler.h +++ b/chrome/browser/ui/webui/chromeos/emoji/emoji_page_handler.h
@@ -27,7 +27,8 @@ // emoji_picker::mojom::PageHandler: void ShowUI() override; void InsertEmoji(const std::string& emoji_to_insert, - bool is_variant) override; + bool is_variant, + int16_t search_length) override; void IsIncognitoTextField(IsIncognitoTextFieldCallback callback) override; private:
diff --git a/chrome/browser/ui/webui/chromeos/emoji/emoji_picker.mojom b/chrome/browser/ui/webui/chromeos/emoji/emoji_picker.mojom index f0870cc0..f96a410 100644 --- a/chrome/browser/ui/webui/chromeos/emoji/emoji_picker.mojom +++ b/chrome/browser/ui/webui/chromeos/emoji/emoji_picker.mojom
@@ -21,7 +21,8 @@ // Request backend to insert emoji (will close the picker). // emoji: The emoji to insert in string form e.g. "😂". // is_variant: If the emoji is a variant / base emoji, used for metrics. - InsertEmoji(string emoji, bool is_variant); + // search_length: Length of search string, used for metrics + InsertEmoji(string emoji, bool is_variant, int16 search_length); // Allows the emoji picker to identify if it was initialized in a incognito // text field (so it will disable storing preference etc.)
diff --git a/chrome/browser/ui/webui/chromeos/network_element_localized_strings_provider.cc b/chrome/browser/ui/webui/chromeos/network_element_localized_strings_provider.cc index f8f5642..67be7024 100644 --- a/chrome/browser/ui/webui/chromeos/network_element_localized_strings_provider.cc +++ b/chrome/browser/ui/webui/chromeos/network_element_localized_strings_provider.cc
@@ -319,6 +319,10 @@ {"networkSimEnterPin", IDS_SETTINGS_INTERNET_NETWORK_SIM_ENTER_PIN}, {"networkSimEnterPinTitle", IDS_SETTINGS_INTERNET_NETWORK_SIM_ENTER_PIN_TITLE}, + {"networkSimEnterPinDescription", + IDS_SETTINGS_INTERNET_NETWORK_SIM_ENTER_PIN_DESCRIPTION}, + {"networkSimEnterPinSubtext", + IDS_SETTINGS_INTERNET_NETWORK_SIM_ENTER_PIN_DESCRIPTION_TEXT_LABEL}, {"networkSimEnterPuk", IDS_SETTINGS_INTERNET_NETWORK_SIM_ENTER_PUK}, {"networkSimLockEnable", IDS_SETTINGS_INTERNET_NETWORK_SIM_LOCK_ENABLE}, {"networkSimLockEnableSublabel",
diff --git a/chrome/browser/ui/webui/internals/web_app/web_app_internals.mojom b/chrome/browser/ui/webui/internals/web_app/web_app_internals.mojom index 67f25f37..6da91f8 100644 --- a/chrome/browser/ui/webui/internals/web_app/web_app_internals.mojom +++ b/chrome/browser/ui/webui/internals/web_app/web_app_internals.mojom
@@ -66,9 +66,6 @@ // Provides access to browser side internal information about installed web apps // (also known as PWAs) for chrome://internals/web-app. interface WebAppInternalsPageHandler { - // Whether the BMO web app backend is enabled. - IsBmoEnabled() => (bool is_bmo_enabled); - // Returns details of all the installed web apps for the current profile. GetWebApps() => (array<WebApp> web_app_list);
diff --git a/chrome/browser/ui/webui/internals/web_app/web_app_internals_page_handler_impl.cc b/chrome/browser/ui/webui/internals/web_app/web_app_internals_page_handler_impl.cc index 1f4dbcaa..35f4b62 100644 --- a/chrome/browser/ui/webui/internals/web_app/web_app_internals_page_handler_impl.cc +++ b/chrome/browser/ui/webui/internals/web_app/web_app_internals_page_handler_impl.cc
@@ -44,11 +44,6 @@ source->AddResourcePath("web-app", IDR_WEB_APP_INTERNALS_HTML); } -void WebAppInternalsPageHandlerImpl::IsBmoEnabled( - IsBmoEnabledCallback callback) { - std::move(callback).Run(true); -} - void WebAppInternalsPageHandlerImpl::GetWebApps(GetWebAppsCallback callback) { auto* provider = web_app::WebAppProvider::Get(profile_); if (!provider) {
diff --git a/chrome/browser/ui/webui/internals/web_app/web_app_internals_page_handler_impl.h b/chrome/browser/ui/webui/internals/web_app/web_app_internals_page_handler_impl.h index b962b6f..2eb88bdd 100644 --- a/chrome/browser/ui/webui/internals/web_app/web_app_internals_page_handler_impl.h +++ b/chrome/browser/ui/webui/internals/web_app/web_app_internals_page_handler_impl.h
@@ -27,7 +27,6 @@ static void AddPageResources(content::WebUIDataSource* source); // mojom::web_app_internals::WebAppInternalsPageHandler: - void IsBmoEnabled(IsBmoEnabledCallback callback) override; void GetWebApps(GetWebAppsCallback callback) override; void GetPreinstalledWebAppDebugInfo( GetPreinstalledWebAppDebugInfoCallback callback) override;
diff --git a/chrome/browser/ui/webui/nearby_share/public/mojom/nearby_share_settings.mojom b/chrome/browser/ui/webui/nearby_share/public/mojom/nearby_share_settings.mojom index c04e698..ad69d44 100644 --- a/chrome/browser/ui/webui/nearby_share/public/mojom/nearby_share_settings.mojom +++ b/chrome/browser/ui/webui/nearby_share/public/mojom/nearby_share_settings.mojom
@@ -108,7 +108,7 @@ // Translated from the proto file (Contact.Identifier): -// https://source.chromium.org/chromium/chromium/src/+/master:chrome/browser/nearby_sharing/proto/rpc_resources.proto +// https://source.chromium.org/chromium/chromium/src/+/main:chrome/browser/nearby_sharing/proto/rpc_resources.proto // A single contact identifier. union ContactIdentifier { string obfuscated_gaia; @@ -117,7 +117,7 @@ }; // Translated from the proto file (ContactRecord): -// https://source.chromium.org/chromium/chromium/src/+/master:chrome/browser/nearby_sharing/proto/rpc_resources.proto +// https://source.chromium.org/chromium/chromium/src/+/main:chrome/browser/nearby_sharing/proto/rpc_resources.proto // A contact record from People backend. struct ContactRecord { // The stable id of this contact record.
diff --git a/chrome/browser/ui/webui/print_preview/print_preview_handler_chromeos.cc b/chrome/browser/ui/webui/print_preview/print_preview_handler_chromeos.cc index 55436f0..40c902f 100644 --- a/chrome/browser/ui/webui/print_preview/print_preview_handler_chromeos.cc +++ b/chrome/browser/ui/webui/print_preview/print_preview_handler_chromeos.cc
@@ -211,7 +211,7 @@ LOG(ERROR) << "Local printer not available"; return; } - local_printer_->AddObserver(receiver_.BindNewPipeAndPassRemote(), + local_printer_->AddObserver(receiver_.BindNewPipeAndPassRemoteWithVersion(), base::DoNothing()); #endif }
diff --git a/chrome/browser/vr/test/xr_browser_test_details.md b/chrome/browser/vr/test/xr_browser_test_details.md index eafd4d6..53a9f824 100644 --- a/chrome/browser/vr/test/xr_browser_test_details.md +++ b/chrome/browser/vr/test/xr_browser_test_details.md
@@ -14,5 +14,5 @@ start calling into the test via Mojo to get controller and headset data instead of attempting to use the real implementation. -[xr hook base]: https://chromium.googlesource.com/chromium/src/+/master/chrome/browser/vr/test/mock_xr_device_hook_base.h +[xr hook base]: https://chromium.googlesource.com/chromium/src/+/main/chrome/browser/vr/test/mock_xr_device_hook_base.h [xr service hook]: https://chromium.googlesource.com/chromium/src/+/HEAD/content/services/isolated_xr_device/xr_service_test_hook.cc
diff --git a/chrome/browser/vr/test/xr_browser_tests.md b/chrome/browser/vr/test/xr_browser_tests.md index a602982..758e178 100644 --- a/chrome/browser/vr/test/xr_browser_tests.md +++ b/chrome/browser/vr/test/xr_browser_tests.md
@@ -13,7 +13,7 @@ `//chrome/android/javatests/src/org/chromium/chrome/browser/vr/*.md`) for use in browser tests in order to test XR features on desktop platforms. -[vr android dir]: https://chromium.googlesource.com/chromium/src/+/master/chrome/android/javatests/src/org/chromium/chrome/browser/vr +[vr android dir]: https://chromium.googlesource.com/chromium/src/+/main/chrome/android/javatests/src/org/chromium/chrome/browser/vr This is pretty much a direct port, with the same JavaScript/HTML files being used for both and the Java/C++ code being functionally equivalent to each other, @@ -116,7 +116,7 @@ want the same functionality as `WEBXR_VR_ALL_RUNTIMES_BROWSER_TEST_F`, but also want the test run in Incognito mode in addition to regular Chrome. -[multi class macros]: https://chromium.googlesource.com/chromium/src/+/master/chrome/browser/vr/test/multi_class_browser_test.h +[multi class macros]: https://chromium.googlesource.com/chromium/src/+/main/chrome/browser/vr/test/multi_class_browser_test.h ## Test Class Names @@ -145,7 +145,7 @@ [`//chrome/browser/vr/test/xr_browser_test_details.md`][xr details], but below is a quick guide on how to use them. -[xr details]: https://chromium.googlesource.com/chromium/src/+/master/chrome/browser/vr/test/xr_browser_test_details.md +[xr details]: https://chromium.googlesource.com/chromium/src/+/main/chrome/browser/vr/test/xr_browser_test_details.md In order to let a test provide data to a runtime, it must create an instance of [`MockXRDeviceHookBase`][xr hook base] or some subclass of it. This should be @@ -153,7 +153,7 @@ as there are currently assumptions that prevent switching to or from the mock runtimes once they have been attempted to be started. -[xr hook base]: https://chromium.googlesource.com/chromium/src/+/master/chrome/browser/vr/test/mock_xr_device_hook_base.h +[xr hook base]: https://chromium.googlesource.com/chromium/src/+/main/chrome/browser/vr/test/mock_xr_device_hook_base.h Once created, the runtime being used will call the various functions inherited from [`VRTestHook`][vr test hook] whenever it would normally acquire or submit @@ -162,9 +162,9 @@ controller, and `OnFrameSubmitted()` will be called each time the runtime submits a finished frame to the headset. -[vr test hook]: https://chromium.googlesource.com/chromium/src/+/master/device/vr/test/test_hook.h +[vr test hook]: https://chromium.googlesource.com/chromium/src/+/main/device/vr/test/test_hook.h For real examples on how to use the input capabilities, look at the tests in [`//chrome/browser/vr/webxr_vr_input_browser_test.cc`][input test]. -[input test]: https://chromium.googlesource.com/chromium/src/+/master/chrome/browser/vr/webxr_vr_input_browser_test.cc +[input test]: https://chromium.googlesource.com/chromium/src/+/main/chrome/browser/vr/webxr_vr_input_browser_test.cc
diff --git a/chrome/browser/web_applications/BUILD.gn b/chrome/browser/web_applications/BUILD.gn index d5e2766..ec622491 100644 --- a/chrome/browser/web_applications/BUILD.gn +++ b/chrome/browser/web_applications/BUILD.gn
@@ -138,6 +138,39 @@ ] } +# The set of dependencies that //chrome/test:test_support{_ui} have on +# web_applications test support. Split out from the below target as the below +# target itself depends on //chrome/test:test_support{_ui}. +source_set("web_applications_test_support_minimal") { + testonly = true + + sources = [ + "system_web_apps/test/test_system_web_app_manager.cc", + "system_web_apps/test/test_system_web_app_manager.h", + "test/service_worker_registration_waiter.cc", + "test/service_worker_registration_waiter.h", + "test/test_web_app_provider.cc", + "test/test_web_app_provider.h", + "test/web_app_install_observer.cc", + "test/web_app_install_observer.h", + "test/web_app_install_test_utils.cc", + "test/web_app_install_test_utils.h", + ] + deps = [ + "//base", + "//base/test:test_support", + "//chrome/browser/profiles:profile", + "//chrome/browser/web_applications", + "//chrome/browser/web_applications/components", + "//chrome/common:chrome_features", + "//chrome/common:non_code_constants", + "//components/keyed_service/content", + "//components/webapps/browser", + "//content/public/browser", + "//url", + ] +} + # This test_support library doesn't use extensions. source_set("web_applications_test_support") { testonly = true @@ -147,8 +180,6 @@ "system_web_apps/test/system_web_app_browsertest_base.h", "system_web_apps/test/test_system_web_app_installation.cc", "system_web_apps/test/test_system_web_app_installation.h", - "system_web_apps/test/test_system_web_app_manager.cc", - "system_web_apps/test/test_system_web_app_manager.h", "system_web_apps/test/test_system_web_app_url_data_source.cc", "system_web_apps/test/test_system_web_app_url_data_source.h", "system_web_apps/test/test_system_web_app_web_ui_controller_factory.cc", @@ -159,8 +190,6 @@ "test/fake_url_handler_manager.h", "test/fake_web_app_origin_association_manager.cc", "test/fake_web_app_origin_association_manager.h", - "test/service_worker_registration_waiter.cc", - "test/service_worker_registration_waiter.h", "test/test_app_registrar.cc", "test/test_app_registrar.h", "test/test_app_registry_controller.cc", @@ -181,8 +210,6 @@ "test/test_os_integration_manager.h", "test/test_web_app_database_factory.cc", "test/test_web_app_database_factory.h", - "test/test_web_app_provider.cc", - "test/test_web_app_provider.h", "test/test_web_app_registry_controller.cc", "test/test_web_app_registry_controller.h", "test/test_web_app_ui_manager.cc", @@ -191,10 +218,6 @@ "test/test_web_app_url_loader.h", "test/web_app_icon_test_utils.cc", "test/web_app_icon_test_utils.h", - "test/web_app_install_observer.cc", - "test/web_app_install_observer.h", - "test/web_app_install_test_utils.cc", - "test/web_app_install_test_utils.h", "test/web_app_registration_waiter.cc", "test/web_app_registration_waiter.h", "test/web_app_test.h", @@ -204,6 +227,8 @@ "test/web_app_uninstall_waiter.h", ] + public_deps = [ ":web_applications_test_support_minimal" ] + deps = [ ":web_app_test_group", ":web_applications", @@ -213,6 +238,7 @@ "//chrome/browser/profiles:profile", "//chrome/browser/ui:ui", "//chrome/browser/web_applications/components", + "//chrome/test:test_support", "//chrome/test:test_support_ui", "//components/crx_file:crx_file", "//components/keyed_service/content:content",
diff --git a/chrome/browser/web_applications/components/BUILD.gn b/chrome/browser/web_applications/components/BUILD.gn index cd56b58..d701097 100644 --- a/chrome/browser/web_applications/components/BUILD.gn +++ b/chrome/browser/web_applications/components/BUILD.gn
@@ -121,7 +121,10 @@ } if (is_linux) { - sources += [ "web_app_run_on_os_login_linux.cc" ] + sources += [ + "web_app_protocol_handler_registration_linux.cc", + "web_app_run_on_os_login_linux.cc", + ] } if (is_chromeos_ash || is_chromeos_lacros) { @@ -133,6 +136,7 @@ "app_shim_registry_mac.cc", "app_shim_registry_mac.h", "web_app_file_handler_registration_mac.cc", + "web_app_protocol_handler_registration_mac.cc", "web_app_run_on_os_login_mac.mm", "web_app_shortcut_mac.h", "web_app_shortcut_mac.mm", @@ -247,6 +251,7 @@ if (is_mac) { sources += [ "app_shim_registry_mac_unittest.cc", + "web_app_protocol_handler_registration_mac_unittest.cc", "web_app_run_on_os_login_mac_unittest.mm", "web_app_shortcut_mac_unittest.mm", ] @@ -261,7 +266,10 @@ } if (is_linux) { - sources += [ "web_app_run_on_os_login_linux_unittest.cc" ] + sources += [ + "web_app_protocol_handler_registration_linux_unittest.cc", + "web_app_run_on_os_login_linux_unittest.cc", + ] } if (is_win || is_mac || (is_linux && !is_chromeos_lacros)) {
diff --git a/chrome/browser/web_applications/components/external_install_options.cc b/chrome/browser/web_applications/components/external_install_options.cc index 25e2e66..17d56a99 100644 --- a/chrome/browser/web_applications/components/external_install_options.cc +++ b/chrome/browser/web_applications/components/external_install_options.cc
@@ -54,6 +54,7 @@ options.is_disabled, options.override_previous_user_uninstall, options.only_for_new_users, + options.only_if_previously_preinstalled, options.user_type_allowlist, options.gate_on_feature, #if BUILDFLAG(IS_CHROMEOS_ASH) @@ -128,6 +129,8 @@ << "\n override_previous_user_uninstall: " << install_options.override_previous_user_uninstall << "\n only_for_new_users: " << install_options.only_for_new_users + << "\n only_if_previously_preinstalled: " + << install_options.only_if_previously_preinstalled << "\n user_type_allowlist: " << install_options.user_type_allowlist << "\n gate_on_feature: " << install_options.gate_on_feature #if BUILDFLAG(IS_CHROMEOS_ASH)
diff --git a/chrome/browser/web_applications/components/external_install_options.h b/chrome/browser/web_applications/components/external_install_options.h index e6f8538..6115dfd 100644 --- a/chrome/browser/web_applications/components/external_install_options.h +++ b/chrome/browser/web_applications/components/external_install_options.h
@@ -86,6 +86,12 @@ // the first time. bool only_for_new_users = false; + // Whether the app should be omitted for new preinstalls. This is the opposite + // of |only_for_new_users| option. It can be used for partial deprecation of + // a preinstalled app: do not preinstall the app for new users but leave + // existing users unaffected. + bool only_if_previously_preinstalled = false; + // Which user types this app should be installed for. // See apps::DetermineUserType() for relevant string constants. std::vector<std::string> user_type_allowlist;
diff --git a/chrome/browser/web_applications/components/os_integration_manager.cc b/chrome/browser/web_applications/components/os_integration_manager.cc index 05597ee9..1903fc0 100644 --- a/chrome/browser/web_applications/components/os_integration_manager.cc +++ b/chrome/browser/web_applications/components/os_integration_manager.cc
@@ -314,14 +314,6 @@ return protocol_handler_manager_->TranslateProtocolUrl(app_id, protocol_url); } -std::vector<ProtocolHandler> OsIntegrationManager::GetHandlersForProtocol( - const std::string& protocol) { - if (!protocol_handler_manager_) - return std::vector<ProtocolHandler>(); - - return protocol_handler_manager_->GetHandlersFor(protocol); -} - FileHandlerManager& OsIntegrationManager::file_handler_manager_for_testing() { DCHECK(file_handler_manager_); return *file_handler_manager_;
diff --git a/chrome/browser/web_applications/components/os_integration_manager.h b/chrome/browser/web_applications/components/os_integration_manager.h index 2d4e316..a85d61ba 100644 --- a/chrome/browser/web_applications/components/os_integration_manager.h +++ b/chrome/browser/web_applications/components/os_integration_manager.h
@@ -143,8 +143,6 @@ // Proxy calls for ProtocolHandlerManager. virtual absl::optional<GURL> TranslateProtocolUrl(const AppId& app_id, const GURL& protocol_url); - virtual std::vector<ProtocolHandler> GetHandlersForProtocol( - const std::string& protocol); // Getter for testing FileHandlerManager FileHandlerManager& file_handler_manager_for_testing();
diff --git a/chrome/browser/web_applications/components/protocol_handler_manager.cc b/chrome/browser/web_applications/components/protocol_handler_manager.cc index 7efcab7..139e5316 100644 --- a/chrome/browser/web_applications/components/protocol_handler_manager.cc +++ b/chrome/browser/web_applications/components/protocol_handler_manager.cc
@@ -93,7 +93,16 @@ } void ProtocolHandlerManager::UnregisterOsProtocolHandlers(const AppId& app_id) { - UnregisterProtocolHandlersWithOs(app_id, profile_); + const std::vector<apps::ProtocolHandlerInfo> handlers = + GetAppProtocolHandlerInfos(app_id); + UnregisterOsProtocolHandlers(app_id, handlers); +} + +void ProtocolHandlerManager::UnregisterOsProtocolHandlers( + const AppId& app_id, + const std::vector<apps::ProtocolHandlerInfo>& protocol_handlers) { + if (!protocol_handlers.empty()) + UnregisterProtocolHandlersWithOs(app_id, profile_, protocol_handlers); } } // namespace web_app
diff --git a/chrome/browser/web_applications/components/protocol_handler_manager.h b/chrome/browser/web_applications/components/protocol_handler_manager.h index 4c0ef77c..769b973 100644 --- a/chrome/browser/web_applications/components/protocol_handler_manager.h +++ b/chrome/browser/web_applications/components/protocol_handler_manager.h
@@ -56,9 +56,16 @@ const std::vector<apps::ProtocolHandlerInfo>& protocol_handlers, base::OnceCallback<void(bool)> callback); - // Unregisters OS specific protocol handlers for an app. + // Unregisters OS specific protocol handlers for OSs that need them, using the + // protocol handler information supplied in the app manifest. void UnregisterOsProtocolHandlers(const AppId& app_id); + // Unregisters OS specific protocol handlers for OSs that need them, using + // arbitrary protocol handler information. + void UnregisterOsProtocolHandlers( + const AppId& app_id, + const std::vector<apps::ProtocolHandlerInfo>& protocol_handlers); + AppRegistrar* app_registrar_; private:
diff --git a/chrome/browser/web_applications/components/web_app_handler_registration_utils_win.cc b/chrome/browser/web_applications/components/web_app_handler_registration_utils_win.cc index bf93607..0418bc42 100644 --- a/chrome/browser/web_applications/components/web_app_handler_registration_utils_win.cc +++ b/chrome/browser/web_applications/components/web_app_handler_registration_utils_win.cc
@@ -7,7 +7,6 @@ #include "base/command_line.h" #include "base/files/file_util.h" #include "base/metrics/histogram_macros.h" -#include "base/strings/strcat.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" @@ -87,37 +86,40 @@ return app_name_extension; } -bool UpdateAppRegistration(const web_app::AppId& app_id, +void UpdateAppRegistration(const web_app::AppId& app_id, const std::wstring& app_name, const base::FilePath& profile_path, const std::wstring& prog_id, - const std::wstring& app_name_extension) { + const std::wstring& app_name_extension, + base::OnceCallback<void(bool)> callback) { if (!base::DeleteFile(ShellUtil::GetApplicationPathForProgId(prog_id))) { web_app::RecordRegistration( web_app::RegistrationResult::kFailToDeleteExistingRegistration); - return false; + std::move(callback).Run(false); + return; } std::wstring user_visible_app_name(app_name); user_visible_app_name.append(app_name_extension); - base::FilePath web_app_path(web_app::GetOsIntegrationResourcesDirectoryForApp( - profile_path, app_id, GURL())); absl::optional<base::FilePath> app_launcher_path = - web_app::CreateAppLauncherFile(app_name, app_name_extension, - web_app_path); + web_app::CreateAppLauncherFile( + app_name, app_name_extension, + web_app::GetOsIntegrationResourcesDirectoryForApp(profile_path, + app_id, GURL())); if (!app_launcher_path) { - return false; + std::move(callback).Run(false); + return; } base::CommandLine app_launch_cmd = web_app::GetAppLauncherCommand( app_id, app_launcher_path.value(), profile_path); base::FilePath icon_path = web_app::internals::GetIconFilePath( - web_app_path, base::AsString16(app_name)); + app_launcher_path.value(), base::AsString16(app_name)); ShellUtil::AddApplicationClass(prog_id, app_launch_cmd, user_visible_app_name, app_name, icon_path); - return true; + std::move(callback).Run(true); } bool AppNameHasProfileExtension(const std::wstring& app_name, @@ -196,18 +198,14 @@ // can not be changed. std::wstring GetProgIdForApp(const base::FilePath& profile_path, const AppId& app_id) { - // On system-level Win7 installs of the browser we need a user specific - // part to differentiate HKLM entries from different Windows profiles. - std::wstring user_specific_part; - ShellUtil::GetUserSpecificRegistrySuffix(&user_specific_part); - - const uint32_t hash = base::PersistentHash( - base::StrCat({base::WideToUTF8(profile_path.BaseName().value()), app_id, - base::WideToUTF8(user_specific_part)})); - - return base::UTF16ToWide( - base::StrCat({base::AsStringPiece16(install_static::GetBaseAppId()), u".", - base::NumberToString16(hash)})); + std::wstring prog_id = install_static::GetBaseAppId(); + std::string app_specific_part( + base::WideToUTF8(profile_path.BaseName().value())); + app_specific_part.append(app_id); + uint32_t hash = base::PersistentHash(app_specific_part); + prog_id.push_back(L'.'); + prog_id.append(base::ASCIIToWide(base::NumberToString(hash))); + return prog_id; } absl::optional<base::FilePath> CreateAppLauncherFile( @@ -313,12 +311,12 @@ updated_extension = std::wstring(); } - base::ThreadPool::PostTaskAndReplyWithResult( + base::ThreadPool::PostTask( FROM_HERE, {base::MayBlock()}, base::BindOnce(&UpdateAppRegistration, app_id, updated_name, external_installation_profile_path, - external_installation_prog_id, updated_extension), - std::move(callback)); + external_installation_prog_id, updated_extension, + std::move(callback))); } // Record UMA metric for the result of file handler registration.
diff --git a/chrome/browser/web_applications/components/web_app_handler_registration_utils_win_unittest.cc b/chrome/browser/web_applications/components/web_app_handler_registration_utils_win_unittest.cc index 4dd4a702..23301aab 100644 --- a/chrome/browser/web_applications/components/web_app_handler_registration_utils_win_unittest.cc +++ b/chrome/browser/web_applications/components/web_app_handler_registration_utils_win_unittest.cc
@@ -9,7 +9,6 @@ #include "base/task/thread_pool/thread_pool_instance.h" #include "base/test/bind.h" #include "base/test/test_reg_util_win.h" -#include "base/win/registry.h" #include "base/win/windows_version.h" #include "chrome/browser/profiles/profile_attributes_entry.h" #include "chrome/browser/profiles/profile_attributes_storage.h" @@ -60,12 +59,9 @@ const std::wstring& app_name, const std::wstring& app_name_extension, const base::FilePath& profile_path) { - base::FilePath web_app_path( - web_app::GetOsIntegrationResourcesDirectoryForApp(profile_path, app_id, - GURL())); - - absl::optional<base::FilePath> launcher_path = - CreateAppLauncherFile(app_name, app_name_extension, web_app_path); + absl::optional<base::FilePath> launcher_path = CreateAppLauncherFile( + app_name, app_name_extension, + GetOsIntegrationResourcesDirectoryForApp(profile_path, app_id, GURL())); ASSERT_TRUE(launcher_path.has_value()); base::CommandLine launcher_command = @@ -74,16 +70,13 @@ std::wstring user_visible_app_name(app_name); user_visible_app_name.append(app_name_extension); - base::FilePath icon_path = - internals::GetIconFilePath(web_app_path, base::AsString16(app_name)); - - ASSERT_TRUE(ShellUtil::AddApplicationClass(prog_id, launcher_command, - user_visible_app_name, - std::wstring(), icon_path)); + ASSERT_TRUE(ShellUtil::AddApplicationClass( + prog_id, launcher_command, user_visible_app_name, std::wstring(), + base::FilePath())); } - // Tests that an app with |app_id| is registered with the expected name, - // icon and extension. + // Tests that an app with |app_id| is registered with the expected name / + // extension. void TestRegisteredApp(const AppId& app_id, const std::wstring& expected_app_name, const std::wstring& expected_app_name_extension, @@ -92,15 +85,9 @@ std::wstring expected_user_visible_app_name(app_name()); expected_user_visible_app_name.append(expected_app_name_extension); std::wstring app_progid = GetProgIdForApp(profile_path, app_id); - ShellUtil::ApplicationInfo registered_app = - ShellUtil::GetApplicationInfoForProgId(app_progid); - - EXPECT_EQ(expected_user_visible_app_name, registered_app.application_name); - - // Ensure that the OS registry contains the expected icon path. - EXPECT_EQ(registered_app.application_icon_path, - profile_path.Append(base::FilePath(FILE_PATH_LITERAL( - "Web Applications\\_crx_app_id\\app_name.ico")))); + ShellUtil::FileAssociationsAndAppName registered_app = + ShellUtil::GetFileAssociationsAndAppName(app_progid); + EXPECT_EQ(expected_user_visible_app_name, registered_app.app_name); // Ensure that the launcher file contains the expected app name. // On Windows 7 the extension is omitted.
diff --git a/chrome/browser/web_applications/components/web_app_install_utils.cc b/chrome/browser/web_applications/components/web_app_install_utils.cc index b04a516..d7190a7 100644 --- a/chrome/browser/web_applications/components/web_app_install_utils.cc +++ b/chrome/browser/web_applications/components/web_app_install_utils.cc
@@ -91,8 +91,8 @@ shortcut_info.name = shortcut.name; shortcut_info.url = shortcut.url; - std::array<IconPurpose, 2> purposes = {IconPurpose::ANY, - IconPurpose::MASKABLE}; + std::array<IconPurpose, 3> purposes = { + IconPurpose::ANY, IconPurpose::MASKABLE, IconPurpose::MONOCHROME}; for (IconPurpose purpose : purposes) { std::vector<WebApplicationShortcutsMenuItemInfo::Icon> shortcut_icons; for (const auto& icon : shortcut.icons) { @@ -316,9 +316,8 @@ if (base::FeatureList::IsEnabled( features::kDesktopPWAsAppIconShortcutsMenu)) { // Also add shortcut icon urls, so they can be downloaded. - // TODO (crbug.com/1114638): Support Monochrome icons. - std::array<IconPurpose, 2> purposes = {IconPurpose::ANY, - IconPurpose::MASKABLE}; + std::array<IconPurpose, 3> purposes = { + IconPurpose::ANY, IconPurpose::MASKABLE, IconPurpose::MONOCHROME}; for (const auto& shortcut : web_app_info.shortcuts_menu_item_infos) { for (IconPurpose purpose : purposes) { for (const auto& icon : @@ -340,8 +339,8 @@ for (auto& shortcut : web_app_info->shortcuts_menu_item_infos) { IconBitmaps shortcut_icon_bitmaps; - std::array<IconPurpose, 2> purposes = {IconPurpose::ANY, - IconPurpose::MASKABLE}; + std::array<IconPurpose, 3> purposes = { + IconPurpose::ANY, IconPurpose::MASKABLE, IconPurpose::MONOCHROME}; for (IconPurpose purpose : purposes) { std::map<SquareSizePx, SkBitmap> bitmaps; for (const auto& icon :
diff --git a/chrome/browser/web_applications/components/web_app_install_utils_unittest.cc b/chrome/browser/web_applications/components/web_app_install_utils_unittest.cc index 30ad2534..3e302e5 100644 --- a/chrome/browser/web_applications/components/web_app_install_utils_unittest.cc +++ b/chrome/browser/web_applications/components/web_app_install_utils_unittest.cc
@@ -315,8 +315,13 @@ icon.url = GURL("http://www.chromium.org/shortcuts/icon1.png"); icon.square_size_px = kIconSize; - shortcuts_menu_item_info.SetShortcutIconInfosForPurpose( - (i == 1) ? IconPurpose::MASKABLE : IconPurpose::ANY, {std::move(icon)}); + + ASSERT_LE(static_cast<int>(IconPurpose::kMinValue), i); + ASSERT_LE(i, static_cast<int>(IconPurpose::kMaxValue)); + auto purpose = static_cast<IconPurpose>(i); + + shortcuts_menu_item_info.SetShortcutIconInfosForPurpose(purpose, + {std::move(icon)}); web_app_info.shortcuts_menu_item_infos.push_back( std::move(shortcuts_menu_item_info)); } @@ -369,10 +374,10 @@ .GetShortcutIconInfosForPurpose(IconPurpose::ANY) .size()); EXPECT_EQ(1u, web_app_info.shortcuts_menu_item_infos[1] - .GetShortcutIconInfosForPurpose(IconPurpose::MASKABLE) + .GetShortcutIconInfosForPurpose(IconPurpose::MONOCHROME) .size()); EXPECT_EQ(1u, web_app_info.shortcuts_menu_item_infos[2] - .GetShortcutIconInfosForPurpose(IconPurpose::ANY) + .GetShortcutIconInfosForPurpose(IconPurpose::MASKABLE) .size()); // Test that |manifest.name| takes priority over |manifest.short_name|, and @@ -413,6 +418,8 @@ const GURL kIconUrl3("http://www.chromium.org/shortcuts/icon3.png"); icon.src = kIconUrl3; + icon.purpose = {Purpose::MASKABLE, Purpose::MONOCHROME}; + shortcut_item.icons.clear(); shortcut_item.icons.push_back(icon); @@ -439,12 +446,18 @@ IconPurpose::ANY)[0]; EXPECT_EQ(kIconUrl2, web_app_shortcut_icon.url); - EXPECT_EQ(1u, web_app_info.shortcuts_menu_item_infos[1] + EXPECT_EQ(0u, web_app_info.shortcuts_menu_item_infos[1] .GetShortcutIconInfosForPurpose(IconPurpose::ANY) .size()); + EXPECT_EQ(1u, web_app_info.shortcuts_menu_item_infos[1] + .GetShortcutIconInfosForPurpose(IconPurpose::MONOCHROME) + .size()); + EXPECT_EQ(1u, web_app_info.shortcuts_menu_item_infos[1] + .GetShortcutIconInfosForPurpose(IconPurpose::MASKABLE) + .size()); web_app_shortcut_icon = web_app_info.shortcuts_menu_item_infos[1].GetShortcutIconInfosForPurpose( - IconPurpose::ANY)[0]; + IconPurpose::MONOCHROME)[0]; EXPECT_EQ(kIconUrl3, web_app_shortcut_icon.url); // Check file handlers were updated
diff --git a/chrome/browser/web_applications/components/web_app_protocol_handler_registration.cc b/chrome/browser/web_applications/components/web_app_protocol_handler_registration.cc index c7cf5d8..58957bf 100644 --- a/chrome/browser/web_applications/components/web_app_protocol_handler_registration.cc +++ b/chrome/browser/web_applications/components/web_app_protocol_handler_registration.cc
@@ -10,7 +10,7 @@ namespace web_app { -#if !defined(OS_WIN) +#if !(defined(OS_WIN) || defined(OS_MAC) || defined(OS_LINUX)) // Registers a protocol handler for the web app with the OS. void RegisterProtocolHandlersWithOs( const AppId& app_id, @@ -19,14 +19,17 @@ std::vector<apps::ProtocolHandlerInfo> protocol_handlers, base::OnceCallback<void(bool)> callback) { base::SequencedTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::BindOnce(std::move(callback), /*success=*/true)); + FROM_HERE, base::BindOnce(std::move(callback), /*success=*/false)); } -// Unregisters protocol handlers for a web app with the OS. +// Unregisters a protocol handler for the web app with the OS. // // TODO(crbug.com/1174805): Add a callback as part of the protocol handling // unregistration flow. -void UnregisterProtocolHandlersWithOs(const AppId& app_id, Profile* profile) {} +void UnregisterProtocolHandlersWithOs( + const AppId& app_id, + Profile* profile, + std::vector<apps::ProtocolHandlerInfo> protocol_handlers) {} #endif } // namespace web_app
diff --git a/chrome/browser/web_applications/components/web_app_protocol_handler_registration.h b/chrome/browser/web_applications/components/web_app_protocol_handler_registration.h index 54feade..d8fdd2c 100644 --- a/chrome/browser/web_applications/components/web_app_protocol_handler_registration.h +++ b/chrome/browser/web_applications/components/web_app_protocol_handler_registration.h
@@ -26,7 +26,10 @@ std::vector<apps::ProtocolHandlerInfo> protocol_handlers, base::OnceCallback<void(bool)> callback); -void UnregisterProtocolHandlersWithOs(const AppId& app_id, Profile* profile); +void UnregisterProtocolHandlersWithOs( + const AppId& app_id, + Profile* profile, + std::vector<apps::ProtocolHandlerInfo> protocol_handlers); } // namespace web_app
diff --git a/chrome/browser/web_applications/components/web_app_protocol_handler_registration_linux.cc b/chrome/browser/web_applications/components/web_app_protocol_handler_registration_linux.cc new file mode 100644 index 0000000..eab5cee2 --- /dev/null +++ b/chrome/browser/web_applications/components/web_app_protocol_handler_registration_linux.cc
@@ -0,0 +1,33 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/web_applications/components/web_app_protocol_handler_registration.h" + +#include "chrome/browser/custom_handlers/protocol_handler_registry.h" +#include "chrome/browser/custom_handlers/protocol_handler_registry_factory.h" + +namespace web_app { + +void RegisterProtocolHandlersWithOs( + const AppId& app_id, + const std::string& app_name, + Profile* profile, + std::vector<apps::ProtocolHandlerInfo> protocol_handlers, + base::OnceCallback<void(bool)> callback) { + ProtocolHandlerRegistry* registry = + ProtocolHandlerRegistryFactory::GetForBrowserContext(profile); + registry->RegisterAppProtocolHandlers(app_id, protocol_handlers); + std::move(callback).Run(true); +} + +void UnregisterProtocolHandlersWithOs( + const AppId& app_id, + Profile* profile, + std::vector<apps::ProtocolHandlerInfo> protocol_handlers) { + ProtocolHandlerRegistry* registry = + ProtocolHandlerRegistryFactory::GetForBrowserContext(profile); + registry->DeregisterAppProtocolHandlers(app_id, protocol_handlers); +} + +} // namespace web_app
diff --git a/chrome/browser/web_applications/components/web_app_protocol_handler_registration_linux_unittest.cc b/chrome/browser/web_applications/components/web_app_protocol_handler_registration_linux_unittest.cc new file mode 100644 index 0000000..5b7c88f2 --- /dev/null +++ b/chrome/browser/web_applications/components/web_app_protocol_handler_registration_linux_unittest.cc
@@ -0,0 +1,143 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/web_applications/components/web_app_protocol_handler_registration.h" + +#include "base/run_loop.h" +#include "base/task/thread_pool/thread_pool_instance.h" +#include "chrome/browser/custom_handlers/protocol_handler_registry.h" +#include "chrome/browser/custom_handlers/protocol_handler_registry_factory.h" +#include "chrome/common/chrome_constants.h" +#include "chrome/test/base/testing_browser_process.h" +#include "chrome/test/base/testing_profile.h" +#include "chrome/test/base/testing_profile_manager.h" +#include "components/services/app_service/public/cpp/protocol_handler_info.h" +#include "content/public/test/browser_task_environment.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace { +const char kApp1Id[] = "app1_id"; +const char kApp1Name[] = "app1 name"; +const char kApp1Url[] = "https://app1.com/%s"; +const char kApp2Id[] = "app2_id"; +const char kApp2Name[] = "app2 name"; +const char kApp2Url[] = "https://app2.com/%s"; + +ProtocolHandler GetProtocolHandler( + const apps::ProtocolHandlerInfo& handler_info, + const std::string& app_id) { + return ProtocolHandler::CreateWebAppProtocolHandler(handler_info.protocol, + handler_info.url, app_id); +} + +std::unique_ptr<KeyedService> BuildProtocolHandlerRegistry( + content::BrowserContext* context) { + Profile* profile = Profile::FromBrowserContext(context); + return std::make_unique<ProtocolHandlerRegistry>( + profile, std::make_unique<ProtocolHandlerRegistry::Delegate>()); +} + +} // namespace + +namespace web_app { + +class WebAppProtocolHandlerRegistrationLinuxTest : public testing::Test { + protected: + WebAppProtocolHandlerRegistrationLinuxTest() = default; + + void SetUp() override { + testing_profile_manager_ = std::make_unique<TestingProfileManager>( + TestingBrowserProcess::GetGlobal()); + ASSERT_TRUE(testing_profile_manager_->SetUp()); + profile_ = + testing_profile_manager_->CreateTestingProfile(chrome::kInitialProfile); + + ProtocolHandlerRegistryFactory::GetInstance()->SetTestingFactory( + profile_, base::BindRepeating(&BuildProtocolHandlerRegistry)); + } + + void TearDown() override { + profile_ = nullptr; + testing_profile_manager_->DeleteAllTestingProfiles(); + } + + Profile* GetProfile() { return profile_; } + + ProtocolHandlerRegistry* protocol_handler_registry() { + return ProtocolHandlerRegistryFactory::GetForBrowserContext(GetProfile()); + } + + private: + content::BrowserTaskEnvironment task_environment_{ + content::BrowserTaskEnvironment::IO_MAINLOOP}; + std::unique_ptr<TestingProfileManager> testing_profile_manager_; + TestingProfile* profile_; +}; + +TEST_F(WebAppProtocolHandlerRegistrationLinuxTest, RegisterHandlers) { + apps::ProtocolHandlerInfo handler1_info; + handler1_info.protocol = "mailto"; + handler1_info.url = GURL(kApp1Url); + auto handler1 = GetProtocolHandler(handler1_info, kApp1Id); + + apps::ProtocolHandlerInfo handler2_info; + handler2_info.protocol = "web+test"; + handler2_info.url = GURL(kApp1Url); + auto handler2 = GetProtocolHandler(handler2_info, kApp1Id); + + RegisterProtocolHandlersWithOs(kApp1Id, kApp1Name, GetProfile(), + {handler1_info, handler2_info}, + base::DoNothing()); + + EXPECT_TRUE(protocol_handler_registry()->IsRegistered(handler1)); + EXPECT_TRUE(protocol_handler_registry()->IsDefault(handler1)); + + EXPECT_TRUE(protocol_handler_registry()->IsRegistered(handler2)); + EXPECT_TRUE(protocol_handler_registry()->IsDefault(handler2)); +} + +TEST_F(WebAppProtocolHandlerRegistrationLinuxTest, + RegisterMultipleHandlersWithSameScheme) { + apps::ProtocolHandlerInfo handler1_info; + handler1_info.protocol = "mailto"; + handler1_info.url = GURL(kApp1Url); + auto handler1 = GetProtocolHandler(handler1_info, kApp1Id); + + RegisterProtocolHandlersWithOs(kApp1Id, kApp1Name, GetProfile(), + {handler1_info}, base::DoNothing()); + + apps::ProtocolHandlerInfo handler2_info; + handler2_info.protocol = "mailto"; + handler2_info.url = GURL(kApp2Url); + auto handler2 = GetProtocolHandler(handler2_info, kApp2Id); + + RegisterProtocolHandlersWithOs(kApp2Id, kApp2Name, GetProfile(), + {handler2_info}, base::DoNothing()); + + EXPECT_TRUE(protocol_handler_registry()->IsRegistered(handler1)); + EXPECT_TRUE(protocol_handler_registry()->IsDefault(handler1)); + + EXPECT_TRUE(protocol_handler_registry()->IsRegistered(handler2)); + EXPECT_FALSE(protocol_handler_registry()->IsDefault(handler2)); +} + +TEST_F(WebAppProtocolHandlerRegistrationLinuxTest, UnregisterHandler) { + apps::ProtocolHandlerInfo handler_info; + handler_info.protocol = "mailto"; + handler_info.url = GURL(kApp1Url); + auto handler = GetProtocolHandler(handler_info, kApp1Id); + + RegisterProtocolHandlersWithOs(kApp1Id, kApp1Name, GetProfile(), + {handler_info}, base::DoNothing()); + + ASSERT_TRUE(protocol_handler_registry()->IsRegistered(handler)); + ASSERT_TRUE(protocol_handler_registry()->IsDefault(handler)); + + UnregisterProtocolHandlersWithOs(kApp1Id, GetProfile(), {handler_info}); + + EXPECT_FALSE(protocol_handler_registry()->IsRegistered(handler)); + EXPECT_FALSE(protocol_handler_registry()->IsDefault(handler)); +} + +} // namespace web_app
diff --git a/chrome/browser/web_applications/components/web_app_protocol_handler_registration_mac.cc b/chrome/browser/web_applications/components/web_app_protocol_handler_registration_mac.cc new file mode 100644 index 0000000..eab5cee2 --- /dev/null +++ b/chrome/browser/web_applications/components/web_app_protocol_handler_registration_mac.cc
@@ -0,0 +1,33 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/web_applications/components/web_app_protocol_handler_registration.h" + +#include "chrome/browser/custom_handlers/protocol_handler_registry.h" +#include "chrome/browser/custom_handlers/protocol_handler_registry_factory.h" + +namespace web_app { + +void RegisterProtocolHandlersWithOs( + const AppId& app_id, + const std::string& app_name, + Profile* profile, + std::vector<apps::ProtocolHandlerInfo> protocol_handlers, + base::OnceCallback<void(bool)> callback) { + ProtocolHandlerRegistry* registry = + ProtocolHandlerRegistryFactory::GetForBrowserContext(profile); + registry->RegisterAppProtocolHandlers(app_id, protocol_handlers); + std::move(callback).Run(true); +} + +void UnregisterProtocolHandlersWithOs( + const AppId& app_id, + Profile* profile, + std::vector<apps::ProtocolHandlerInfo> protocol_handlers) { + ProtocolHandlerRegistry* registry = + ProtocolHandlerRegistryFactory::GetForBrowserContext(profile); + registry->DeregisterAppProtocolHandlers(app_id, protocol_handlers); +} + +} // namespace web_app
diff --git a/chrome/browser/web_applications/components/web_app_protocol_handler_registration_mac_unittest.cc b/chrome/browser/web_applications/components/web_app_protocol_handler_registration_mac_unittest.cc new file mode 100644 index 0000000..a1e9e4c --- /dev/null +++ b/chrome/browser/web_applications/components/web_app_protocol_handler_registration_mac_unittest.cc
@@ -0,0 +1,143 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/web_applications/components/web_app_protocol_handler_registration.h" + +#include "base/run_loop.h" +#include "base/task/thread_pool/thread_pool_instance.h" +#include "chrome/browser/custom_handlers/protocol_handler_registry.h" +#include "chrome/browser/custom_handlers/protocol_handler_registry_factory.h" +#include "chrome/common/chrome_constants.h" +#include "chrome/test/base/testing_browser_process.h" +#include "chrome/test/base/testing_profile.h" +#include "chrome/test/base/testing_profile_manager.h" +#include "components/services/app_service/public/cpp/protocol_handler_info.h" +#include "content/public/test/browser_task_environment.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace { +const char kApp1Id[] = "app1_id"; +const char kApp1Name[] = "app1 name"; +const char kApp1Url[] = "https://app1.com/%s"; +const char kApp2Id[] = "app2_id"; +const char kApp2Name[] = "app2 name"; +const char kApp2Url[] = "https://app2.com/%s"; + +ProtocolHandler GetProtocolHandler( + const apps::ProtocolHandlerInfo& handler_info, + const std::string& app_id) { + return ProtocolHandler::CreateWebAppProtocolHandler(handler_info.protocol, + handler_info.url, app_id); +} + +std::unique_ptr<KeyedService> BuildProtocolHandlerRegistry( + content::BrowserContext* context) { + Profile* profile = Profile::FromBrowserContext(context); + return std::make_unique<ProtocolHandlerRegistry>( + profile, std::make_unique<ProtocolHandlerRegistry::Delegate>()); +} + +} // namespace + +namespace web_app { + +class WebAppProtocolHandlerRegistrationMacTest : public testing::Test { + protected: + WebAppProtocolHandlerRegistrationMacTest() = default; + + void SetUp() override { + testing_profile_manager_ = std::make_unique<TestingProfileManager>( + TestingBrowserProcess::GetGlobal()); + ASSERT_TRUE(testing_profile_manager_->SetUp()); + profile_ = + testing_profile_manager_->CreateTestingProfile(chrome::kInitialProfile); + + ProtocolHandlerRegistryFactory::GetInstance()->SetTestingFactory( + profile_, base::BindRepeating(&BuildProtocolHandlerRegistry)); + } + + void TearDown() override { + profile_ = nullptr; + testing_profile_manager_->DeleteAllTestingProfiles(); + } + + Profile* GetProfile() { return profile_; } + + ProtocolHandlerRegistry* protocol_handler_registry() { + return ProtocolHandlerRegistryFactory::GetForBrowserContext(GetProfile()); + } + + private: + content::BrowserTaskEnvironment task_environment_{ + content::BrowserTaskEnvironment::IO_MAINLOOP}; + std::unique_ptr<TestingProfileManager> testing_profile_manager_; + TestingProfile* profile_; +}; + +TEST_F(WebAppProtocolHandlerRegistrationMacTest, RegisterHandlers) { + apps::ProtocolHandlerInfo handler1_info; + handler1_info.protocol = "mailto"; + handler1_info.url = GURL(kApp1Url); + auto handler1 = GetProtocolHandler(handler1_info, kApp1Id); + + apps::ProtocolHandlerInfo handler2_info; + handler2_info.protocol = "web+test"; + handler2_info.url = GURL(kApp1Url); + auto handler2 = GetProtocolHandler(handler2_info, kApp1Id); + + RegisterProtocolHandlersWithOs(kApp1Id, kApp1Name, GetProfile(), + {handler1_info, handler2_info}, + base::DoNothing()); + + EXPECT_TRUE(protocol_handler_registry()->IsRegistered(handler1)); + EXPECT_TRUE(protocol_handler_registry()->IsDefault(handler1)); + + EXPECT_TRUE(protocol_handler_registry()->IsRegistered(handler2)); + EXPECT_TRUE(protocol_handler_registry()->IsDefault(handler2)); +} + +TEST_F(WebAppProtocolHandlerRegistrationMacTest, + RegisterMultipleHandlersWithSameScheme) { + apps::ProtocolHandlerInfo handler1_info; + handler1_info.protocol = "mailto"; + handler1_info.url = GURL(kApp1Url); + auto handler1 = GetProtocolHandler(handler1_info, kApp1Id); + + RegisterProtocolHandlersWithOs(kApp1Id, kApp1Name, GetProfile(), + {handler1_info}, base::DoNothing()); + + apps::ProtocolHandlerInfo handler2_info; + handler2_info.protocol = "mailto"; + handler2_info.url = GURL(kApp2Url); + auto handler2 = GetProtocolHandler(handler2_info, kApp2Id); + + RegisterProtocolHandlersWithOs(kApp2Id, kApp2Name, GetProfile(), + {handler2_info}, base::DoNothing()); + + EXPECT_TRUE(protocol_handler_registry()->IsRegistered(handler1)); + EXPECT_TRUE(protocol_handler_registry()->IsDefault(handler1)); + + EXPECT_TRUE(protocol_handler_registry()->IsRegistered(handler2)); + EXPECT_FALSE(protocol_handler_registry()->IsDefault(handler2)); +} + +TEST_F(WebAppProtocolHandlerRegistrationMacTest, UnregisterHandler) { + apps::ProtocolHandlerInfo handler_info; + handler_info.protocol = "mailto"; + handler_info.url = GURL(kApp1Url); + auto handler = GetProtocolHandler(handler_info, kApp1Id); + + RegisterProtocolHandlersWithOs(kApp1Id, kApp1Name, GetProfile(), + {handler_info}, base::DoNothing()); + + ASSERT_TRUE(protocol_handler_registry()->IsRegistered(handler)); + ASSERT_TRUE(protocol_handler_registry()->IsDefault(handler)); + + UnregisterProtocolHandlersWithOs(kApp1Id, GetProfile(), {handler_info}); + + EXPECT_FALSE(protocol_handler_registry()->IsRegistered(handler)); + EXPECT_FALSE(protocol_handler_registry()->IsDefault(handler)); +} + +} // namespace web_app
diff --git a/chrome/browser/web_applications/components/web_app_protocol_handler_registration_win.cc b/chrome/browser/web_applications/components/web_app_protocol_handler_registration_win.cc index b54defb..cc1d7de 100644 --- a/chrome/browser/web_applications/components/web_app_protocol_handler_registration_win.cc +++ b/chrome/browser/web_applications/components/web_app_protocol_handler_registration_win.cc
@@ -65,20 +65,25 @@ base::FilePath icon_path = web_app::internals::GetIconFilePath( web_app_path, base::AsString16(app_name)); - std::wstring prog_id = web_app::GetProgIdForApp(profile_path, app_id); - ShellUtil::AddApplicationClass(prog_id, app_specific_launcher_command, + ShellUtil::AddApplicationClass(web_app::GetProgIdForApp(profile_path, app_id), + app_specific_launcher_command, user_visible_app_name, user_visible_app_name, icon_path); - std::vector<std::wstring> wstring_protocols; - wstring_protocols.reserve(protocol_handlers.size()); + // Post to UI thread to access ProtocolHandlerRegistry. + // TODO(crbug.com/1174805): We should move this to ProtocolHandlerManager and + // use a callback instead. + content::GetUIThreadTaskRunner({})->PostTask( + FROM_HERE, + base::BindOnce( + [](Profile* profile, const web_app::AppId& app_id, + std::vector<apps::ProtocolHandlerInfo> protocol_handlers) { + ProtocolHandlerRegistry* registry = + ProtocolHandlerRegistryFactory::GetForBrowserContext(profile); - for (const auto& protocol_handler : protocol_handlers) { - wstring_protocols.push_back(base::UTF8ToWide(protocol_handler.protocol)); - } - - // Add protocol associations to the Windows registry. - ShellUtil::AddAppProtocolAssociations(wstring_protocols, prog_id); + registry->RegisterAppProtocolHandlers(app_id, protocol_handlers); + }, + profile, app_id, std::move(protocol_handlers))); } void UnregisterProtocolHandlersWithOsInBackground( @@ -97,13 +102,19 @@ // by default doesn't remove the web application directory. base::DeleteFile(app_specific_launcher_path); - // Remove application class registry key. + // Clean up application class registry key. ShellUtil::DeleteApplicationClass(prog_id); +} - // Remove protocol associations from the Windows registry. - ShellUtil::RemoveAppProtocolAssociations( - web_app::GetProgIdForApp(profile_path, app_id), - /*elevate_if_not_admin=*/true); +// TODO(crbug/1019239): Update CheckAndUpdateExternalInstallations +// to receive a callback that returns a bool. For now, return the call back +// below for test purposes (StartupBrowserWebAppProtocolHandlingTest). +void VerifyExternalInstallations(const base::FilePath& cur_profile_path, + const web_app::AppId& app_id, + base::OnceCallback<void(bool)> callback) { + web_app::CheckAndUpdateExternalInstallations(cur_profile_path, app_id, + base::DoNothing::Once<bool>()); + std::move(callback).Run(true); } } // namespace @@ -122,19 +133,25 @@ std::wstring app_name_extension = GetAppNameExtensionForNextInstall(app_id, profile->GetPath()); - // TODO(crbug/1019239): Update CheckAndUpdateExternalInstallations - // to receive a callback that returns a bool. base::ThreadPool::PostTaskAndReply( FROM_HERE, {base::MayBlock(), base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN}, base::BindOnce(&RegisterProtocolHandlersWithOSInBackground, app_id, base::UTF8ToWide(app_name), profile, profile->GetPath(), std::move(protocol_handlers), app_name_extension), - base::BindOnce(&CheckAndUpdateExternalInstallations, profile->GetPath(), - app_id, std::move(callback))); + base::BindOnce(&VerifyExternalInstallations, profile->GetPath(), app_id, + std::move(callback))); } -void UnregisterProtocolHandlersWithOs(const AppId& app_id, Profile* profile) { +void UnregisterProtocolHandlersWithOs( + const AppId& app_id, + Profile* profile, + std::vector<apps::ProtocolHandlerInfo> protocol_handlers) { + ProtocolHandlerRegistry* registry = + ProtocolHandlerRegistryFactory::GetForBrowserContext(profile); + + registry->DeregisterAppProtocolHandlers(app_id, protocol_handlers); + base::ThreadPool::PostTaskAndReply( FROM_HERE, {base::MayBlock(), base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN},
diff --git a/chrome/browser/web_applications/components/web_app_protocol_handler_registration_win_unittest.cc b/chrome/browser/web_applications/components/web_app_protocol_handler_registration_win_unittest.cc index df8750b..dc33a66 100644 --- a/chrome/browser/web_applications/components/web_app_protocol_handler_registration_win_unittest.cc +++ b/chrome/browser/web_applications/components/web_app_protocol_handler_registration_win_unittest.cc
@@ -4,25 +4,12 @@ #include "chrome/browser/web_applications/components/web_app_protocol_handler_registration.h" -#include <string> - -#include "base/files/file_util.h" -#include "base/files/scoped_temp_dir.h" #include "base/run_loop.h" -#include "base/strings/utf_string_conversions.h" #include "base/task/thread_pool/thread_pool_instance.h" #include "base/test/bind.h" -#include "base/test/test_reg_util_win.h" -#include "base/win/registry.h" -#include "base/win/windows_version.h" -#include "chrome/browser/profiles/profile.h" -#include "chrome/browser/profiles/profile_attributes_storage.h" -#include "chrome/browser/profiles/profile_manager.h" -#include "chrome/browser/web_applications/components/web_app_handler_registration_utils_win.h" +#include "chrome/browser/custom_handlers/protocol_handler_registry.h" +#include "chrome/browser/custom_handlers/protocol_handler_registry_factory.h" #include "chrome/common/chrome_constants.h" -#include "chrome/common/custom_handlers/protocol_handler.h" -#include "chrome/install_static/install_util.h" -#include "chrome/installer/util/shell_util.h" #include "chrome/test/base/testing_browser_process.h" #include "chrome/test/base/testing_profile.h" #include "chrome/test/base/testing_profile_manager.h" @@ -37,6 +24,21 @@ const char kApp2Id[] = "app2_id"; const char kApp2Name[] = "app2 name"; const char kApp2Url[] = "https://app2.com/%s"; + +ProtocolHandler GetProtocolHandler( + const apps::ProtocolHandlerInfo& handler_info, + const std::string& app_id) { + return ProtocolHandler::CreateWebAppProtocolHandler(handler_info.protocol, + handler_info.url, app_id); +} + +std::unique_ptr<KeyedService> BuildProtocolHandlerRegistry( + content::BrowserContext* context) { + Profile* profile = Profile::FromBrowserContext(context); + return std::make_unique<ProtocolHandlerRegistry>( + profile, std::make_unique<ProtocolHandlerRegistry::Delegate>()); +} + } // namespace namespace web_app { @@ -51,6 +53,9 @@ ASSERT_TRUE(testing_profile_manager_->SetUp()); profile_ = testing_profile_manager_->CreateTestingProfile(chrome::kInitialProfile); + + ProtocolHandlerRegistryFactory::GetInstance()->SetTestingFactory( + profile_, base::BindRepeating(&BuildProtocolHandlerRegistry)); } void TearDown() override { @@ -59,107 +64,9 @@ } Profile* GetProfile() { return profile_; } - ProfileManager* profile_manager() { - return testing_profile_manager_->profile_manager(); - } - TestingProfileManager* testing_profile_manager() { - return testing_profile_manager_.get(); - } - // Ensures that URLAssociations entries are created for a given protocol. - // "<root hkey>\Software\<prog_id>\Capabilities\URLAssociations\<protocol>". - bool ProgIdRegisteredForProtocol(const std::string& protocol, - const AppId& app_id, - Profile* profile) { - std::wstring prog_id = GetProgIdForApp(profile->GetPath(), app_id); - - std::wstring url_associations_key_name(install_static::GetRegistryPath()); - url_associations_key_name.append(ShellUtil::kRegAppProtocolHandlers); - url_associations_key_name.push_back(base::FilePath::kSeparators[0]); - url_associations_key_name.append(prog_id); - url_associations_key_name.append(L"\\Capabilities"); - url_associations_key_name.append(L"\\URLAssociations"); - - HKEY root = base::win::GetVersion() == base::win::Version::WIN7 - ? HKEY_LOCAL_MACHINE - : HKEY_CURRENT_USER; - - base::win::RegKey key; - std::wstring value; - bool association_exists = key.Open(root, url_associations_key_name.c_str(), - KEY_READ) == ERROR_SUCCESS; - - bool entry_matches = (key.ReadValue(base::UTF8ToWide(protocol).c_str(), - &value) == ERROR_SUCCESS) && - value == prog_id; - - return association_exists && entry_matches; - } - - void AddAndVerifyProtocolAssociations(const AppId& app_id, - const std::string& app_name, - const std::string& app_url, - Profile* profile, - const char* app_name_extension) { - std::string sanitized_app_name(app_name); - sanitized_app_name.append(app_name_extension); - base::FilePath expected_app_launcher_path = - GetLauncherPathForApp(profile, app_id, sanitized_app_name); - - apps::ProtocolHandlerInfo handler1_info; - handler1_info.protocol = "mailto"; - handler1_info.url = GURL(app_url); - - apps::ProtocolHandlerInfo handler2_info; - handler2_info.protocol = "web+test"; - handler2_info.url = GURL(app_url); - - base::RunLoop run_loop; - RegisterProtocolHandlersWithOs( - app_id, app_name, profile, {handler1_info, handler2_info}, - base::BindLambdaForTesting([&](bool success) { - EXPECT_TRUE(success); - run_loop.Quit(); - })); - run_loop.Run(); - - base::FilePath registered_app_path = ShellUtil::GetApplicationPathForProgId( - GetProgIdForApp(profile->GetPath(), app_id)); - - EXPECT_TRUE(base::PathExists(registered_app_path)); - EXPECT_EQ(registered_app_path, expected_app_launcher_path); - - // Both protocols should have been registered with the OS registry. - EXPECT_TRUE( - ProgIdRegisteredForProtocol(handler1_info.protocol, app_id, profile)); - EXPECT_TRUE( - ProgIdRegisteredForProtocol(handler2_info.protocol, app_id, profile)); - } - - // Gets the launcher file path for |sanitized_app_name|. If not - // on Win7, the name will have the ".exe" extension. - base::FilePath GetAppSpecificLauncherFilePath( - const std::string& sanitized_app_name) { - base::FilePath app_specific_launcher_filepath( - base::ASCIIToWide(sanitized_app_name)); - if (base::win::GetVersion() > base::win::Version::WIN7) { - app_specific_launcher_filepath = - app_specific_launcher_filepath.AddExtension(L"exe"); - } - return app_specific_launcher_filepath; - } - - // Returns the expected app launcher path inside the subdirectory for - // |app_id|. - base::FilePath GetLauncherPathForApp(Profile* profile, - const AppId app_id, - const std::string& sanitized_app_name) { - base::FilePath web_app_dir(GetOsIntegrationResourcesDirectoryForApp( - profile->GetPath(), app_id, GURL())); - base::FilePath app_specific_launcher_filepath = - GetAppSpecificLauncherFilePath(sanitized_app_name); - - return web_app_dir.Append(app_specific_launcher_filepath); + ProtocolHandlerRegistry* protocol_handler_registry() { + return ProtocolHandlerRegistryFactory::GetForBrowserContext(GetProfile()); } private: @@ -169,130 +76,94 @@ TestingProfile* profile_; }; -TEST_F(WebAppProtocolHandlerRegistrationWinTest, - AddAndVerifyProtocolAssociations) { - AddAndVerifyProtocolAssociations(kApp1Id, kApp1Name, kApp1Url, GetProfile(), - ""); +TEST_F(WebAppProtocolHandlerRegistrationWinTest, RegisterHandlers) { + apps::ProtocolHandlerInfo handler1_info; + handler1_info.protocol = "mailto"; + handler1_info.url = GURL(kApp1Url); + auto handler1 = GetProtocolHandler(handler1_info, kApp1Id); + + apps::ProtocolHandlerInfo handler2_info; + handler2_info.protocol = "web+test"; + handler2_info.url = GURL(kApp1Url); + auto handler2 = GetProtocolHandler(handler2_info, kApp1Id); + + base::RunLoop run_loop; + RegisterProtocolHandlersWithOs(kApp1Name, kApp1Id, GetProfile(), + {handler1_info, handler2_info}, + base::BindLambdaForTesting([&](bool success) { + EXPECT_TRUE(success); + run_loop.Quit(); + })); + run_loop.Run(); + + EXPECT_TRUE(protocol_handler_registry()->IsRegistered(handler1)); + EXPECT_TRUE(protocol_handler_registry()->IsDefault(handler1)); + + EXPECT_TRUE(protocol_handler_registry()->IsRegistered(handler2)); + EXPECT_TRUE(protocol_handler_registry()->IsDefault(handler2)); } TEST_F(WebAppProtocolHandlerRegistrationWinTest, RegisterMultipleHandlersWithSameScheme) { - AddAndVerifyProtocolAssociations(kApp1Id, kApp1Name, kApp1Url, GetProfile(), - ""); - AddAndVerifyProtocolAssociations(kApp2Id, kApp2Name, kApp2Url, GetProfile(), - ""); + apps::ProtocolHandlerInfo handler1_info; + handler1_info.protocol = "mailto"; + handler1_info.url = GURL(kApp1Url); + auto handler1 = GetProtocolHandler(handler1_info, kApp1Id); + + base::RunLoop handler1_run_loop; + RegisterProtocolHandlersWithOs(kApp1Name, kApp1Id, GetProfile(), + {handler1_info}, + base::BindLambdaForTesting([&](bool success) { + EXPECT_TRUE(success); + handler1_run_loop.Quit(); + })); + handler1_run_loop.Run(); + + apps::ProtocolHandlerInfo handler2_info; + handler2_info.protocol = "mailto"; + handler2_info.url = GURL(kApp2Url); + auto handler2 = GetProtocolHandler(handler2_info, kApp2Id); + + base::RunLoop handler2_run_loop; + RegisterProtocolHandlersWithOs(kApp2Name, kApp2Id, GetProfile(), + {handler2_info}, + base::BindLambdaForTesting([&](bool success) { + EXPECT_TRUE(success); + handler2_run_loop.Quit(); + })); + handler2_run_loop.Run(); + + EXPECT_TRUE(protocol_handler_registry()->IsRegistered(handler1)); + EXPECT_TRUE(protocol_handler_registry()->IsDefault(handler1)); + + EXPECT_TRUE(protocol_handler_registry()->IsRegistered(handler2)); + EXPECT_FALSE(protocol_handler_registry()->IsDefault(handler2)); } -// When an app is registered in one profile, and then is registered in a second -// profile, the disambiguation dialog for both app registrations should include -// the profile name, e.g., "app name (Default)" and "app name (Profile 2)". -TEST_F(WebAppProtocolHandlerRegistrationWinTest, - RegisterProtocolHandlersForWebAppIn2Profiles) { - AddAndVerifyProtocolAssociations(kApp1Id, kApp1Name, kApp1Url, GetProfile(), - ""); +TEST_F(WebAppProtocolHandlerRegistrationWinTest, UnregisterHandler) { + apps::ProtocolHandlerInfo handler_info; + handler_info.protocol = "mailto"; + handler_info.url = GURL(kApp1Url); + auto handler = GetProtocolHandler(handler_info, kApp1Id); - Profile* profile2 = - testing_profile_manager()->CreateTestingProfile("Profile 2"); - ProfileAttributesStorage& storage = - profile_manager()->GetProfileAttributesStorage(); - ASSERT_EQ(2u, storage.GetNumberOfProfiles()); + base::RunLoop run_loop; + RegisterProtocolHandlersWithOs(kApp1Name, kApp1Id, GetProfile(), + {handler_info}, + base::BindLambdaForTesting([&](bool success) { + EXPECT_TRUE(success); + run_loop.Quit(); + })); + run_loop.Run(); - AddAndVerifyProtocolAssociations(kApp1Id, kApp1Name, kApp1Url, profile2, - " (Profile 2)"); + ASSERT_TRUE(protocol_handler_registry()->IsRegistered(handler)); + ASSERT_TRUE(protocol_handler_registry()->IsDefault(handler)); - ShellUtil::ApplicationInfo app_info = ShellUtil::GetApplicationInfoForProgId( - GetProgIdForApp(GetProfile()->GetPath(), kApp1Id)); - - ASSERT_FALSE(app_info.application_name.empty()); - // Profile 1's app name should now include the profile in the name. - EXPECT_EQ(base::WideToUTF8(app_info.application_name), "app1 name (Default)"); - - // Profile 1's app_launcher should include the profile in its name. - base::FilePath profile1_app_specific_launcher_path = - GetAppSpecificLauncherFilePath("app1 name (Default)"); - base::FilePath profile1_launcher_path = - ShellUtil::GetApplicationPathForProgId( - GetProgIdForApp(GetProfile()->GetPath(), kApp1Id)); - EXPECT_EQ(profile1_launcher_path.BaseName(), - profile1_app_specific_launcher_path); - - // Verify that the app is still registered for "mailto" and "web+test" in - // profile 1. - EXPECT_TRUE(ProgIdRegisteredForProtocol("mailto", kApp1Id, GetProfile())); - EXPECT_TRUE(ProgIdRegisteredForProtocol("web+test", kApp1Id, GetProfile())); -} - -// When an app is registered in two profiles, and then unregistered in one of -// them, the remaining registration should no longer be profile-specific. It -// should not have the profile name in app_launcher executable name, or the -// registered app name. -TEST_F(WebAppProtocolHandlerRegistrationWinTest, - UnRegisterProtocolHandlersForWebAppIn2Profiles) { - AddAndVerifyProtocolAssociations(kApp1Id, kApp1Name, kApp1Url, GetProfile(), - ""); - base::FilePath app_specific_launcher_path = - ShellUtil::GetApplicationPathForProgId( - GetProgIdForApp(GetProfile()->GetPath(), kApp1Id)); - - Profile* profile2 = - testing_profile_manager()->CreateTestingProfile("Profile 2"); - ProfileAttributesStorage& storage = - profile_manager()->GetProfileAttributesStorage(); - ASSERT_EQ(2u, storage.GetNumberOfProfiles()); - AddAndVerifyProtocolAssociations(kApp1Id, kApp1Name, kApp1Url, profile2, - " (Profile 2)"); - - UnregisterProtocolHandlersWithOs(kApp1Id, GetProfile()); - base::ThreadPoolInstance::Get()->FlushForTesting(); - base::RunLoop().RunUntilIdle(); - base::ThreadPoolInstance::Get()->FlushForTesting(); - EXPECT_FALSE(base::PathExists(app_specific_launcher_path)); - - // Verify that "(Profile 2)" was removed from the web app launcher and - // protocol association registry entries. - ShellUtil::ApplicationInfo app_info = ShellUtil::GetApplicationInfoForProgId( - GetProgIdForApp(profile2->GetPath(), kApp1Id)); - ASSERT_FALSE(app_info.application_name.empty()); - - // Profile 2's app name should no longer include the profile in the name. - EXPECT_EQ(base::WideToUTF8(app_info.application_name), kApp1Name); - - // Profile 2's app_launcher should no longer include the profile in its name. - base::FilePath profile2_app_specific_launcher_path = - GetAppSpecificLauncherFilePath(kApp1Name); - base::FilePath profile2_launcher_path = - ShellUtil::GetApplicationPathForProgId( - GetProgIdForApp(profile2->GetPath(), kApp1Id)); - EXPECT_EQ(profile2_launcher_path.BaseName(), - profile2_app_specific_launcher_path); - - // Verify that the app is still registered for "mailto" and "web+test" in - // profile 2. - EXPECT_TRUE(ProgIdRegisteredForProtocol("mailto", kApp1Id, profile2)); - EXPECT_TRUE(ProgIdRegisteredForProtocol("web+test", kApp1Id, profile2)); -} - -// Register protocol handlers, and verify that unregistering removes the -// registry settings and the app-specific launcher. -TEST_F(WebAppProtocolHandlerRegistrationWinTest, - UnregisterProtocolHandlersForWebApp) { - AddAndVerifyProtocolAssociations(kApp1Id, kApp1Name, kApp1Url, GetProfile(), - ""); - base::FilePath app_specific_launcher_path = - ShellUtil::GetApplicationPathForProgId( - GetProgIdForApp(GetProfile()->GetPath(), kApp1Id)); - - UnregisterProtocolHandlersWithOs(kApp1Id, GetProfile()); + UnregisterProtocolHandlersWithOs(kApp1Id, GetProfile(), {handler_info}); base::ThreadPoolInstance::Get()->FlushForTesting(); base::RunLoop().RunUntilIdle(); - EXPECT_FALSE(base::PathExists(app_specific_launcher_path)); - EXPECT_FALSE(ProgIdRegisteredForProtocol("mailto", kApp1Id, GetProfile())); - EXPECT_FALSE(ProgIdRegisteredForProtocol("web+test", kApp1Id, GetProfile())); - - ShellUtil::ApplicationInfo app_info = ShellUtil::GetApplicationInfoForProgId( - GetProgIdForApp(GetProfile()->GetPath(), kApp1Id)); - EXPECT_TRUE(app_info.application_name.empty()); + EXPECT_FALSE(protocol_handler_registry()->IsRegistered(handler)); + EXPECT_FALSE(protocol_handler_registry()->IsDefault(handler)); } } // namespace web_app
diff --git a/chrome/browser/web_applications/components/web_application_info.cc b/chrome/browser/web_applications/components/web_application_info.cc index 63f6cfd6..d58c7a1 100644 --- a/chrome/browser/web_applications/components/web_application_info.cc +++ b/chrome/browser/web_applications/components/web_application_info.cc
@@ -161,9 +161,7 @@ IconPurpose purpose) const { switch (purpose) { case IconPurpose::MONOCHROME: - // TODO (crbug.com/1114638): Monochrome support. - NOTREACHED(); - FALLTHROUGH; + return monochrome; case IconPurpose::ANY: return any; case IconPurpose::MASKABLE: @@ -180,8 +178,7 @@ any = std::move(shortcut_icon_infos); return; case IconPurpose::MONOCHROME: - // TODO (crbug.com/1114638): Monochrome support. - NOTREACHED(); + monochrome = std::move(shortcut_icon_infos); return; case IconPurpose::MASKABLE: maskable = std::move(shortcut_icon_infos); @@ -257,11 +254,10 @@ bool operator==(const WebApplicationShortcutsMenuItemInfo& shortcut_info1, const WebApplicationShortcutsMenuItemInfo& shortcut_info2) { - // TODO (crbug.com/1114638): Add Monochrome support. return std::tie(shortcut_info1.name, shortcut_info1.url, shortcut_info1.any, - shortcut_info1.maskable) == + shortcut_info1.maskable, shortcut_info1.monochrome) == std::tie(shortcut_info2.name, shortcut_info2.url, shortcut_info2.any, - shortcut_info2.maskable); + shortcut_info2.maskable, shortcut_info2.monochrome); } std::ostream& operator<<(std::ostream& out, @@ -282,7 +278,11 @@ out << " square_size_px: " << icon.square_size_px << std::endl; } - // TODO (crbug.com/1114638): Add Monochrome support. + out << " monochrome:" << std::endl; + for (WebApplicationShortcutsMenuItemInfo::Icon icon : info.monochrome) { + out << " url: " << icon.url << std::endl; + out << " square_size_px: " << icon.square_size_px << std::endl; + } return out; }
diff --git a/chrome/browser/web_applications/components/web_application_info.h b/chrome/browser/web_applications/components/web_application_info.h index 1ef08f0..d5eb136 100644 --- a/chrome/browser/web_applications/components/web_application_info.h +++ b/chrome/browser/web_applications/components/web_application_info.h
@@ -153,6 +153,11 @@ // designed for masking. // See https://www.w3.org/TR/appmanifest/#dfn-maskable-purpose std::vector<Icon> maskable; + + // List of shortcut icon URLs with associated square size, + // designed for monochrome contexts. + // See https://www.w3.org/TR/appmanifest/#purpose-member + std::vector<Icon> monochrome; }; // Structure used when installing a web page as an app.
diff --git a/chrome/browser/web_applications/docs/installation_pipeline.md b/chrome/browser/web_applications/docs/installation_pipeline.md index ef11903..d17ff323 100644 --- a/chrome/browser/web_applications/docs/installation_pipeline.md +++ b/chrome/browser/web_applications/docs/installation_pipeline.md
@@ -102,7 +102,7 @@ * They need to be immediately saved to the database & be installed eventually. * Many are often queued up during a new profile sign-in, and it's not uncommon for the user to quit before the installation queue finishes. -Due to this, unlike other installs, a special [`WebApp::is_in_sync_install`](https://source.chromium.org/search?q=WebApp::is_in_sync_install) ([protobuf](https://source.chromium.org/chromium/chromium/src/+/master:chrome/browser/web_applications/proto/web_app.proto;l=110;bpv=1;bpt=1?q=web_app.proto%20is_in_sync_install&ss=chromium)) variable is saved in the database. WebApps with this set to true are treated as not fully installed, and are often left out of app listings. This variable is reset back to `false` when the app is finished installing. +Due to this, unlike other installs, a special [`WebApp::is_in_sync_install`](https://source.chromium.org/search?q=WebApp::is_in_sync_install) ([protobuf](https://source.chromium.org/chromium/chromium/src/+/main:chrome/browser/web_applications/proto/web_app.proto;l=110;bpv=1;bpt=1?q=web_app.proto%20is_in_sync_install&ss=chromium)) variable is saved in the database. WebApps with this set to true are treated as not fully installed, and are often left out of app listings. This variable is reset back to `false` when the app is finished installing. To handle the cases above, on startup when the database is loaded, any WebApp with `is_in_sync_install` of `true` will be re-installed inside of [`WebAppSyncBridge::MaybeInstallAppsInSyncInstall`](https://source.chromium.org/search?q=WebAppSyncBridge::MaybeInstallAppsInSyncInstall)
diff --git a/chrome/browser/web_applications/preinstalled_web_app_manager.cc b/chrome/browser/web_applications/preinstalled_web_app_manager.cc index 46bfe0d..296c6e8 100644 --- a/chrome/browser/web_applications/preinstalled_web_app_manager.cc +++ b/chrome/browser/web_applications/preinstalled_web_app_manager.cc
@@ -40,6 +40,8 @@ #include "chrome/browser/web_applications/extension_status_utils.h" #include "chrome/browser/web_applications/preinstalled_web_app_utils.h" #include "chrome/browser/web_applications/preinstalled_web_apps/preinstalled_web_apps.h" +#include "chrome/browser/web_applications/web_app.h" +#include "chrome/browser/web_applications/web_app_registrar.h" #include "chrome/common/chrome_features.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/pref_names.h" @@ -149,9 +151,12 @@ absl::optional<std::string> GetDisableReason( const ExternalInstallOptions& options, Profile* profile, + WebAppRegistrar* registrar, bool preinstalled_apps_enabled_in_prefs, bool is_new_user, const std::string& user_type) { + DCHECK(registrar); + if (!preinstalled_apps_enabled_in_prefs) { return options.install_url.spec() + " disabled by preinstalled_apps pref setting."; @@ -196,6 +201,25 @@ } } + // Remove if was not previously preinstalled. + if (options.only_if_previously_preinstalled) { + absl::optional<AppId> app_id = + ExternallyInstalledWebAppPrefs(profile->GetPrefs()) + .LookupAppId(options.install_url); + + bool was_previously_preinstalled = false; + if (app_id.has_value()) { + const WebApp* web_app = registrar->GetAppById(app_id.value()); + if (web_app && web_app->IsPreinstalledApp()) + was_previously_preinstalled = true; + } + + if (!was_previously_preinstalled) { + return options.install_url.spec() + + " disabled because was not previously preinstalled."; + } + } + // Remove if any apps to replace are blocked by admin policy. for (const AppId& app_id : options.uninstall_and_replace) { if (extensions::IsExtensionBlockedByPolicy(profile, app_id)) { @@ -317,7 +341,9 @@ PreinstalledWebAppManager::~PreinstalledWebAppManager() = default; void PreinstalledWebAppManager::SetSubsystems( + WebAppRegistrar* registrar, ExternallyManagedAppManager* externally_managed_app_manager) { + registrar_ = registrar; externally_managed_app_manager_ = externally_managed_app_manager; } @@ -450,9 +476,10 @@ size_t disabled_count = 0; base::EraseIf(parsed_configs.options_list, [&](const ExternalInstallOptions& options) { - absl::optional<std::string> disable_reason = GetDisableReason( - options, profile_, preinstalled_apps_enabled_in_prefs, - is_new_user, user_type); + absl::optional<std::string> disable_reason = + GetDisableReason(options, profile_, registrar_, + preinstalled_apps_enabled_in_prefs, + is_new_user, user_type); if (disable_reason) { VLOG(1) << *disable_reason; ++disabled_count;
diff --git a/chrome/browser/web_applications/preinstalled_web_app_manager.h b/chrome/browser/web_applications/preinstalled_web_app_manager.h index c79082c..86d8c19 100644 --- a/chrome/browser/web_applications/preinstalled_web_app_manager.h +++ b/chrome/browser/web_applications/preinstalled_web_app_manager.h
@@ -35,6 +35,7 @@ } // namespace class ExternallyManagedAppManager; +class WebAppRegistrar; // Installs web apps to be preinstalled on the device (AKA default apps) during // start up. Will keep the apps installed on the device in sync with the set of @@ -69,6 +70,7 @@ ~PreinstalledWebAppManager(); void SetSubsystems( + WebAppRegistrar* registrar, ExternallyManagedAppManager* externally_managed_app_manager); // Loads the preinstalled app configs and synchronizes them with the device's @@ -131,6 +133,7 @@ bool IsReinstallPastMilestoneNeededSinceLastSync( int force_reinstall_for_milestone); + WebAppRegistrar* registrar_ = nullptr; ExternallyManagedAppManager* externally_managed_app_manager_ = nullptr; Profile* const profile_;
diff --git a/chrome/browser/web_applications/preinstalled_web_app_manager_browsertest.cc b/chrome/browser/web_applications/preinstalled_web_app_manager_browsertest.cc index b25b38f..e0a965c 100644 --- a/chrome/browser/web_applications/preinstalled_web_app_manager_browsertest.cc +++ b/chrome/browser/web_applications/preinstalled_web_app_manager_browsertest.cc
@@ -5,12 +5,15 @@ #include "chrome/browser/web_applications/preinstalled_web_app_manager.h" #include "base/files/file_path.h" +#include "base/files/file_util.h" #include "base/json/json_reader.h" #include "base/path_service.h" +#include "base/strings/strcat.h" #include "base/strings/string_util.h" #include "base/test/bind.h" #include "build/chromeos_buildflags.h" #include "chrome/browser/extensions/extension_browsertest.h" +#include "chrome/browser/ui/web_applications/test/ssl_test_utils.h" #include "chrome/browser/ui/web_applications/test/web_app_browsertest_util.h" #include "chrome/browser/web_applications/components/preinstalled_app_install_features.h" #include "chrome/browser/web_applications/components/web_app_helpers.h" @@ -24,8 +27,10 @@ #include "components/prefs/pref_service.h" #include "content/public/test/browser_test.h" #include "content/public/test/test_launcher.h" +#include "content/public/test/url_loader_interceptor.h" #include "extensions/browser/extension_registry.h" #include "extensions/browser/test_extension_registry_observer.h" +#include "net/ssl/ssl_info.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -41,6 +46,32 @@ namespace web_app { +namespace { + +constexpr char kBaseDataDir[] = "chrome/test/data/banners"; + +// start_url in manifest.json matches navigation url for the simple +// manifest_test_page.html. +constexpr char kSimpleManifestStartUrl[] = + "https://example.org/manifest_test_page.html"; + +constexpr char kNoManifestTestPageStartUrl[] = + "https://example.org/no_manifest_test_page.html"; + +// Performs blocking IO operations. +base::FilePath GetDataFilePath(const base::FilePath& relative_path, + bool* path_exists) { + base::ScopedAllowBlockingForTesting allow_io; + + base::FilePath root_path; + CHECK(base::PathService::Get(base::DIR_SOURCE_ROOT, &root_path)); + base::FilePath path = root_path.Append(relative_path); + *path_exists = base::PathExists(path); + return path; +} + +} // namespace + class PreinstalledWebAppManagerBrowserTest : public extensions::ExtensionBrowserTest { public: @@ -52,6 +83,41 @@ ExtensionBrowserTest::SetUpOnMainThread(); } + void TearDownOnMainThread() override { + url_loader_interceptor_.reset(); + InProcessBrowserTest::TearDownOnMainThread(); + } + + void InitUrlLoaderInterceptor() { + // We use a URLLoaderInterceptor, rather than the EmbeddedTestServer, since + // a stable app_id across tests requires stable origin, whereas + // EmbeddedTestServer serves content on a random port. + url_loader_interceptor_ = + std::make_unique<content::URLLoaderInterceptor>(base::BindRepeating( + [](content::URLLoaderInterceptor::RequestParams* params) -> bool { + std::string relative_request = base::StrCat( + {kBaseDataDir, params->url_request.url.path_piece()}); + base::FilePath relative_path = + base::FilePath().AppendASCII(relative_request); + + bool path_exists = false; + base::FilePath path = + GetDataFilePath(relative_path, &path_exists); + if (!path_exists) + return /*intercepted=*/false; + + // Provide fake SSLInfo to avoid NOT_FROM_SECURE_ORIGIN error in + // InstallableManager::GetData(). + net::SSLInfo ssl_info; + CreateFakeSslInfoCertificate(&ssl_info); + + content::URLLoaderInterceptor::WriteResponse( + path, params->client.get(), /*headers=*/nullptr, ssl_info); + + return /*intercepted=*/true; + })); + } + GURL GetAppUrl() const { return embedded_test_server()->GetURL("/web_apps/basic.html"); } @@ -132,6 +198,7 @@ ~PreinstalledWebAppManagerBrowserTest() override = default; private: + std::unique_ptr<content::URLLoaderInterceptor> url_loader_interceptor_; ScopedOsHooksSuppress os_hooks_suppress_; }; @@ -348,6 +415,89 @@ EXPECT_EQ(SyncPreinstalledAppConfig(GetAppUrl(), app_config), absl::nullopt); } +const char kOnlyIfPreviouslyPreinstalled_PreviousConfig[] = R"({ + "app_url": "$1", + "launch_container": "window", + "user_type": ["unmanaged"] +})"; +const char kOnlyIfPreviouslyPreinstalled_NextConfig[] = R"({ + "app_url": "$1", + "launch_container": "window", + "user_type": ["unmanaged"], + "only_if_previously_preinstalled": true +})"; + +IN_PROC_BROWSER_TEST_F(PreinstalledWebAppManagerBrowserTest, + PRE_OnlyIfPreviouslyPreinstalled_AppPreserved) { + PreinstalledWebAppManager::BypassOfflineManifestRequirementForTesting(); + InitUrlLoaderInterceptor(); + + std::string prev_app_config = base::ReplaceStringPlaceholders( + kOnlyIfPreviouslyPreinstalled_PreviousConfig, {kSimpleManifestStartUrl}, + nullptr); + + // The user had the app installed. + EXPECT_EQ( + SyncPreinstalledAppConfig(GURL{kSimpleManifestStartUrl}, prev_app_config), + InstallResultCode::kSuccessNewInstall); + + AppId app_id = GenerateAppIdFromURL(GURL{kSimpleManifestStartUrl}); + EXPECT_TRUE(registrar().IsInstalled(app_id)); +} + +IN_PROC_BROWSER_TEST_F(PreinstalledWebAppManagerBrowserTest, + OnlyIfPreviouslyPreinstalled_AppPreserved) { + PreinstalledWebAppManager::BypassOfflineManifestRequirementForTesting(); + InitUrlLoaderInterceptor(); + + std::string next_app_config = + base::ReplaceStringPlaceholders(kOnlyIfPreviouslyPreinstalled_NextConfig, + {kSimpleManifestStartUrl}, nullptr); + + // The user still has the app. + EXPECT_EQ( + SyncPreinstalledAppConfig(GURL{kSimpleManifestStartUrl}, next_app_config), + InstallResultCode::kSuccessAlreadyInstalled); + + AppId app_id = GenerateAppIdFromURL(GURL{kSimpleManifestStartUrl}); + EXPECT_TRUE(registrar().IsInstalled(app_id)); +} + +IN_PROC_BROWSER_TEST_F(PreinstalledWebAppManagerBrowserTest, + PRE_OnlyIfPreviouslyPreinstalled_NoAppPreinstalled) { + PreinstalledWebAppManager::BypassOfflineManifestRequirementForTesting(); + InitUrlLoaderInterceptor(); + + std::string prev_app_config = base::ReplaceStringPlaceholders( + kOnlyIfPreviouslyPreinstalled_PreviousConfig, + {kNoManifestTestPageStartUrl}, nullptr); + + EXPECT_EQ(SyncPreinstalledAppConfig(GURL{kNoManifestTestPageStartUrl}, + prev_app_config), + InstallResultCode::kNotValidManifestForWebApp); + + AppId app_id = GenerateAppIdFromURL(GURL{kNoManifestTestPageStartUrl}); + EXPECT_FALSE(registrar().IsInstalled(app_id)); +} + +IN_PROC_BROWSER_TEST_F(PreinstalledWebAppManagerBrowserTest, + OnlyIfPreviouslyPreinstalled_NoAppPreinstalled) { + PreinstalledWebAppManager::BypassOfflineManifestRequirementForTesting(); + InitUrlLoaderInterceptor(); + + std::string next_app_config = + base::ReplaceStringPlaceholders(kOnlyIfPreviouslyPreinstalled_NextConfig, + {kNoManifestTestPageStartUrl}, nullptr); + + // The user has no the app. + EXPECT_EQ(SyncPreinstalledAppConfig(GURL{kNoManifestTestPageStartUrl}, + next_app_config), + absl::nullopt); + + AppId app_id = GenerateAppIdFromURL(GURL{kNoManifestTestPageStartUrl}); + EXPECT_FALSE(registrar().IsInstalled(app_id)); +} + // The offline manifest JSON config functionality is only available on Chrome // OS. #if BUILDFLAG(IS_CHROMEOS_ASH)
diff --git a/chrome/browser/web_applications/preinstalled_web_app_manager_unittest.cc b/chrome/browser/web_applications/preinstalled_web_app_manager_unittest.cc index 167eeaa..68dc51e 100644 --- a/chrome/browser/web_applications/preinstalled_web_app_manager_unittest.cc +++ b/chrome/browser/web_applications/preinstalled_web_app_manager_unittest.cc
@@ -25,6 +25,7 @@ #include "chrome/browser/web_applications/components/preinstalled_app_install_features.h" #include "chrome/browser/web_applications/components/web_app_constants.h" #include "chrome/browser/web_applications/preinstalled_web_apps/preinstalled_web_apps.h" +#include "chrome/browser/web_applications/web_app_provider.h" #include "chrome/common/chrome_features.h" #include "chrome/common/chrome_paths.h" #include "chrome/test/base/testing_profile.h" @@ -110,6 +111,12 @@ auto preinstalled_web_app_manager = std::make_unique<PreinstalledWebAppManager>(profile); + auto* provider = WebAppProvider::Get(profile); + DCHECK(provider); + preinstalled_web_app_manager->SetSubsystems( + provider->registrar().AsWebAppRegistrar(), + &provider->externally_managed_app_manager()); + std::vector<ExternalInstallOptions> result; base::RunLoop run_loop; preinstalled_web_app_manager->LoadForTesting(base::BindLambdaForTesting(
diff --git a/chrome/browser/web_applications/preinstalled_web_app_utils.cc b/chrome/browser/web_applications/preinstalled_web_app_utils.cc index 43cba9e..2f01933 100644 --- a/chrome/browser/web_applications/preinstalled_web_app_utils.cc +++ b/chrome/browser/web_applications/preinstalled_web_app_utils.cc
@@ -38,6 +38,11 @@ // the app for users that have already run Chrome before. constexpr char kOnlyForNewUsers[] = "only_for_new_users"; +// kOnlyIfPreviouslyPreinstalled is an optional boolean. If set and true we will +// not preinstall the app for new users. +constexpr char kOnlyIfPreviouslyPreinstalled[] = + "only_if_previously_preinstalled"; + // kUserType is an allowlist of user types to install this app for. This must be // populated otherwise the app won't ever be installed. // Example: "user_type": ["unmanaged", "managed", "child"] @@ -215,6 +220,16 @@ options.only_for_new_users = value->GetBool(); } + // only_if_previously_preinstalled + value = app_config.FindKey(kOnlyIfPreviouslyPreinstalled); + if (value) { + if (!value->is_bool()) { + return base::StrCat({file.AsUTF8Unsafe(), " had an invalid ", + kOnlyIfPreviouslyPreinstalled}); + } + options.only_if_previously_preinstalled = value->GetBool(); + } + // hide_from_user bool hide_from_user = false; value = app_config.FindKey(kHideFromUser);
diff --git a/chrome/browser/web_applications/proto/web_app.proto b/chrome/browser/web_applications/proto/web_app.proto index 8cfc3e1..8e2a43d 100644 --- a/chrome/browser/web_applications/proto/web_app.proto +++ b/chrome/browser/web_applications/proto/web_app.proto
@@ -67,12 +67,14 @@ required string url = 2; repeated sync_pb.WebAppIconInfo shortcut_icon_infos = 3; repeated sync_pb.WebAppIconInfo shortcut_icon_infos_maskable = 4; + repeated sync_pb.WebAppIconInfo shortcut_icon_infos_monochrome = 5; } // List of icon sizes downloaded to disk for a shortcuts menu item. message DownloadedShortcutsMenuIconSizesProto { repeated int32 icon_sizes = 1; repeated int32 icon_sizes_maskable = 2; + repeated int32 icon_sizes_monochrome = 3; } // Full WebApp object data. See detailed comments in
diff --git a/chrome/browser/web_applications/system_web_apps/system_web_app_manager.cc b/chrome/browser/web_applications/system_web_apps/system_web_app_manager.cc index 8885be3..b4e3cb0 100644 --- a/chrome/browser/web_applications/system_web_apps/system_web_app_manager.cc +++ b/chrome/browser/web_applications/system_web_apps/system_web_app_manager.cc
@@ -222,6 +222,7 @@ infos.at(SystemAppType::MEDIA).include_launch_directory = true; infos.at(SystemAppType::MEDIA).show_in_launcher = false; infos.at(SystemAppType::MEDIA).show_in_search = false; + infos.at(SystemAppType::MEDIA).capture_navigations = true; infos.at(SystemAppType::MEDIA).enabled_origin_trials = OriginTrialsMap({{GetOrigin("chrome://media-app"), {"FileHandling"}}}); }
diff --git a/chrome/browser/web_applications/test/web_app_test_utils.cc b/chrome/browser/web_applications/test/web_app_test_utils.cc index 486e3c4..b70a691 100644 --- a/chrome/browser/web_applications/test/web_app_test_utils.cc +++ b/chrome/browser/web_applications/test/web_app_test_utils.cc
@@ -144,24 +144,40 @@ WebApplicationShortcutsMenuItemInfo shortcut_info; shortcut_info.url = scope.Resolve("shortcut" + suffix_str); shortcut_info.name = base::UTF8ToUTF16("shortcut" + suffix_str); + std::vector<WebApplicationShortcutsMenuItemInfo::Icon> shortcut_icons_any; std::vector<WebApplicationShortcutsMenuItemInfo::Icon> shortcut_icons_maskable; + std::vector<WebApplicationShortcutsMenuItemInfo::Icon> + shortcut_icons_monochrome; + for (int j = random.next_uint(4) + 1; j >= 0; --j) { std::string icon_suffix_str = suffix_str + base::NumberToString(j); WebApplicationShortcutsMenuItemInfo::Icon shortcut_icon; shortcut_icon.url = scope.Resolve("/shortcuts/icon" + icon_suffix_str); // Within each shortcut_icons_*, square_size_px must be unique. shortcut_icon.square_size_px = (j * 10) + random.next_uint(10); - if (random.next_bool()) - shortcut_icons_any.push_back(std::move(shortcut_icon)); - else - shortcut_icons_maskable.push_back(std::move(shortcut_icon)); + int icon_purpose = random.next_uint(3); + switch (icon_purpose) { + case 0: + shortcut_icons_any.push_back(std::move(shortcut_icon)); + break; + case 1: + shortcut_icons_maskable.push_back(std::move(shortcut_icon)); + break; + case 2: + shortcut_icons_monochrome.push_back(std::move(shortcut_icon)); + break; + } } + shortcut_info.SetShortcutIconInfosForPurpose(IconPurpose::ANY, std::move(shortcut_icons_any)); shortcut_info.SetShortcutIconInfosForPurpose( IconPurpose::MASKABLE, std::move(shortcut_icons_maskable)); + shortcut_info.SetShortcutIconInfosForPurpose( + IconPurpose::MONOCHROME, std::move(shortcut_icons_monochrome)); + shortcuts_menu_item_infos.emplace_back(std::move(shortcut_info)); } return shortcuts_menu_item_infos; @@ -174,15 +190,20 @@ IconSizes result; std::vector<SquareSizePx> shortcuts_menu_icon_sizes_any; std::vector<SquareSizePx> shortcuts_menu_icon_sizes_maskable; + std::vector<SquareSizePx> shortcuts_menu_icon_sizes_monochrome; for (unsigned int j = 0; j < i; ++j) { shortcuts_menu_icon_sizes_any.emplace_back(random.next_uint(256) + 1); shortcuts_menu_icon_sizes_maskable.emplace_back(random.next_uint(256) + 1); + shortcuts_menu_icon_sizes_monochrome.emplace_back(random.next_uint(256) + + 1); } result.SetSizesForPurpose(IconPurpose::ANY, std::move(shortcuts_menu_icon_sizes_any)); result.SetSizesForPurpose(IconPurpose::MASKABLE, std::move(shortcuts_menu_icon_sizes_maskable)); + result.SetSizesForPurpose(IconPurpose::MONOCHROME, + std::move(shortcuts_menu_icon_sizes_monochrome)); results.emplace_back(std::move(result)); } return results;
diff --git a/chrome/browser/web_applications/web_app_database.cc b/chrome/browser/web_applications/web_app_database.cc index 538f48f3..30e7fd8 100644 --- a/chrome/browser/web_applications/web_app_database.cc +++ b/chrome/browser/web_applications/web_app_database.cc
@@ -305,9 +305,8 @@ } } - // TODO (crbug.com/1114638): Support Monochrome icons. - std::array<IconPurpose, 2> purposes = {IconPurpose::ANY, - IconPurpose::MASKABLE}; + std::array<IconPurpose, 3> purposes = { + IconPurpose::ANY, IconPurpose::MASKABLE, IconPurpose::MONOCHROME}; for (const WebApplicationShortcutsMenuItemInfo& shortcut_info : web_app.shortcuts_menu_item_infos()) { WebAppShortcutsMenuItemInfoProto* shortcut_info_proto = @@ -317,11 +316,22 @@ for (IconPurpose purpose : purposes) { for (const WebApplicationShortcutsMenuItemInfo::Icon& icon_info : shortcut_info.GetShortcutIconInfosForPurpose(purpose)) { - // TODO (crbug.com/1114638): Add Monochrome support. - sync_pb::WebAppIconInfo* shortcut_icon_info_proto = - (purpose == IconPurpose::ANY) - ? shortcut_info_proto->add_shortcut_icon_infos() - : shortcut_info_proto->add_shortcut_icon_infos_maskable(); + sync_pb::WebAppIconInfo* shortcut_icon_info_proto; + switch (purpose) { + case IconPurpose::ANY: + shortcut_icon_info_proto = + shortcut_info_proto->add_shortcut_icon_infos(); + break; + case IconPurpose::MASKABLE: + shortcut_icon_info_proto = + shortcut_info_proto->add_shortcut_icon_infos_maskable(); + break; + case IconPurpose::MONOCHROME: + shortcut_icon_info_proto = + shortcut_info_proto->add_shortcut_icon_infos_monochrome(); + break; + } + DCHECK(!icon_info.url.is_empty()); shortcut_icon_info_proto->set_url(icon_info.url.spec()); shortcut_icon_info_proto->set_size_in_px(icon_info.square_size_px); @@ -333,7 +343,6 @@ web_app.downloaded_shortcuts_menu_icons_sizes()) { DownloadedShortcutsMenuIconSizesProto* icon_sizes_proto = local_data->add_downloaded_shortcuts_menu_icons_sizes(); - // TODO (crbug.com/1114638): Add Monochrome support. for (const SquareSizePx& icon_size : icon_sizes.GetSizesForPurpose(IconPurpose::ANY)) { icon_sizes_proto->add_icon_sizes(icon_size); @@ -342,6 +351,10 @@ icon_sizes.GetSizesForPurpose(IconPurpose::MASKABLE)) { icon_sizes_proto->add_icon_sizes_maskable(icon_size); } + for (const SquareSizePx& icon_size : + icon_sizes.GetSizesForPurpose(IconPurpose::MONOCHROME)) { + icon_sizes_proto->add_icon_sizes_monochrome(icon_size); + } } for (const auto& additional_search_term : web_app.additional_search_terms()) { @@ -646,22 +659,34 @@ } std::vector<WebApplicationShortcutsMenuItemInfo> shortcuts_menu_item_infos; - // TODO (crbug.com/1114638): Support Monochrome icons. - std::array<IconPurpose, 2> purposes = {IconPurpose::ANY, - IconPurpose::MASKABLE}; + std::array<IconPurpose, 3> purposes = { + IconPurpose::ANY, IconPurpose::MASKABLE, IconPurpose::MONOCHROME}; for (const auto& shortcut_info_proto : local_data.shortcuts_menu_item_infos()) { WebApplicationShortcutsMenuItemInfo shortcut_info; shortcut_info.name = base::UTF8ToUTF16(shortcut_info_proto.name()); shortcut_info.url = GURL(shortcut_info_proto.url()); for (IconPurpose purpose : purposes) { - // TODO (crbug.com/1114638): Add Monochrome support. - const auto& shortcut_icon_infos = - (purpose == IconPurpose::ANY) - ? shortcut_info_proto.shortcut_icon_infos() - : shortcut_info_proto.shortcut_icon_infos_maskable(); + // This default init needed to infer the sophisticated protobuf type. + const auto* shortcut_icon_infos = + &shortcut_info_proto.shortcut_icon_infos(); + + switch (purpose) { + case IconPurpose::ANY: + shortcut_icon_infos = &shortcut_info_proto.shortcut_icon_infos(); + break; + case IconPurpose::MASKABLE: + shortcut_icon_infos = + &shortcut_info_proto.shortcut_icon_infos_maskable(); + break; + case IconPurpose::MONOCHROME: + shortcut_icon_infos = + &shortcut_info_proto.shortcut_icon_infos_monochrome(); + break; + } + std::vector<WebApplicationShortcutsMenuItemInfo::Icon> icon_infos; - for (const auto& icon_info_proto : shortcut_icon_infos) { + for (const auto& icon_info_proto : *shortcut_icon_infos) { WebApplicationShortcutsMenuItemInfo::Icon shortcut_icon_info; shortcut_icon_info.square_size_px = icon_info_proto.size_in_px(); shortcut_icon_info.url = GURL(icon_info_proto.url()); @@ -678,7 +703,6 @@ for (const auto& shortcuts_icon_sizes_proto : local_data.downloaded_shortcuts_menu_icons_sizes()) { IconSizes icon_sizes; - // TODO (crbug.com/1114638): Support Monochrome icons. icon_sizes.SetSizesForPurpose( IconPurpose::ANY, std::vector<SquareSizePx>( shortcuts_icon_sizes_proto.icon_sizes().begin(), @@ -688,6 +712,11 @@ std::vector<SquareSizePx>( shortcuts_icon_sizes_proto.icon_sizes_maskable().begin(), shortcuts_icon_sizes_proto.icon_sizes_maskable().end())); + icon_sizes.SetSizesForPurpose( + IconPurpose::MONOCHROME, + std::vector<SquareSizePx>( + shortcuts_icon_sizes_proto.icon_sizes_monochrome().begin(), + shortcuts_icon_sizes_proto.icon_sizes_monochrome().end())); shortcuts_menu_icons_sizes.push_back(std::move(icon_sizes)); }
diff --git a/chrome/browser/web_applications/web_app_icon_manager.cc b/chrome/browser/web_applications/web_app_icon_manager.cc index 1e4bf6a4..b132ceb 100644 --- a/chrome/browser/web_applications/web_app_icon_manager.cc +++ b/chrome/browser/web_applications/web_app_icon_manager.cc
@@ -172,9 +172,8 @@ FileUtilsWrapper* utils, const base::FilePath& app_manifest_resources_directory, const ShortcutsMenuIconBitmaps& shortcuts_menu_icon_bitmaps) { - // TODO(crbug.com/1114638): Write monochrome icons too. - std::array<IconPurpose, 2> purposes = {IconPurpose::ANY, - IconPurpose::MASKABLE}; + std::array<IconPurpose, 3> purposes = { + IconPurpose::ANY, IconPurpose::MASKABLE, IconPurpose::MONOCHROME}; for (IconPurpose purpose : purposes) { const base::FilePath shortcuts_menu_icons_dir = GetAppShortcutsMenuIconsDirectory(app_manifest_resources_directory, @@ -488,9 +487,8 @@ for (const auto& icon_sizes : shortcuts_menu_icons_sizes) { IconBitmaps result; - // TODO(crbug.com/1114638): Read monochrome icons too. - std::array<IconPurpose, 2> purposes = {IconPurpose::ANY, - IconPurpose::MASKABLE}; + std::array<IconPurpose, 3> purposes = { + IconPurpose::ANY, IconPurpose::MASKABLE, IconPurpose::MONOCHROME}; for (IconPurpose purpose : purposes) { std::map<SquareSizePx, SkBitmap> bitmaps;
diff --git a/chrome/browser/web_applications/web_app_icon_manager_unittest.cc b/chrome/browser/web_applications/web_app_icon_manager_unittest.cc index 632fd16..3a4bc05 100644 --- a/chrome/browser/web_applications/web_app_icon_manager_unittest.cc +++ b/chrome/browser/web_applications/web_app_icon_manager_unittest.cc
@@ -95,24 +95,31 @@ run_loop.Run(); } - void WriteShortcutsMenuIcons(const AppId& app_id, - const std::vector<int>& sizes_any, - const std::vector<SkColor>& colors_any, - const std::vector<int>& sizes_maskable, - const std::vector<SkColor>& colors_maskable) { - DCHECK_EQ(sizes_any.size(), sizes_maskable.size()); - DCHECK_EQ(sizes_any.size(), colors_any.size()); - DCHECK_EQ(sizes_maskable.size(), colors_maskable.size()); + void WriteGeneratedShortcutsMenuIcons( + const AppId& app_id, + const std::vector<GeneratedIconsInfo>& icons_info, + int num_menu_items) { ShortcutsMenuIconBitmaps shortcuts_menu_icons; - for (size_t i = 0; i < sizes_any.size(); i++) { - IconBitmaps shortcuts_menu_icon_map; - shortcuts_menu_icon_map.any.emplace( - sizes_any[i], CreateSquareIcon(sizes_any[i], colors_any[i])); - shortcuts_menu_icon_map.maskable.emplace( - sizes_maskable[i], - CreateSquareIcon(sizes_maskable[i], colors_maskable[i])); - shortcuts_menu_icons.push_back(std::move(shortcuts_menu_icon_map)); + + for (int i = 0; i < num_menu_items; ++i) { + IconBitmaps menu_item_icon_map; + + for (const GeneratedIconsInfo& info : icons_info) { + DCHECK_EQ(info.sizes_px.size(), info.colors.size()); + + std::map<SquareSizePx, SkBitmap> generated_bitmaps; + + for (size_t i = 0; i < info.sizes_px.size(); ++i) + AddGeneratedIcon(&generated_bitmaps, info.sizes_px[i], + info.colors[i]); + + menu_item_icon_map.SetBitmapsForPurpose(info.purpose, + std::move(generated_bitmaps)); + } + + shortcuts_menu_icons.push_back(std::move(menu_item_icon_map)); } + base::RunLoop run_loop; icon_manager_->WriteShortcutsMenuIconsData( app_id, std::move(shortcuts_menu_icons), @@ -136,45 +143,37 @@ return result; } + // Returns a list of downloaded sizes for the menu indexed by menu item + // number. std::vector<IconSizes> CreateDownloadedShortcutsMenuIconsSizes( - std::vector<SquareSizePx> sizes_px) { + const std::vector<SquareSizePx>& sizes_any, + const std::vector<SquareSizePx>& sizes_maskable, + const std::vector<SquareSizePx>& sizes_monochrome, + int num_menu_items) { std::vector<IconSizes> downloaded_shortcuts_menu_icons_sizes; - for (const auto& size : sizes_px) { + + for (int i = 0; i < num_menu_items; ++i) { IconSizes icon_sizes; - { - std::vector<SquareSizePx> shortcuts_menu_icon_sizes_any; - shortcuts_menu_icon_sizes_any.push_back(size); - icon_sizes.SetSizesForPurpose(IconPurpose::ANY, - std::move(shortcuts_menu_icon_sizes_any)); + + for (int p = static_cast<int>(IconPurpose::kMinValue); + p <= static_cast<int>(IconPurpose::kMaxValue); ++p) { + auto purpose = static_cast<IconPurpose>(p); + switch (purpose) { + case IconPurpose::ANY: + icon_sizes.SetSizesForPurpose(purpose, sizes_any); + break; + case IconPurpose::MASKABLE: + icon_sizes.SetSizesForPurpose(purpose, sizes_maskable); + break; + case IconPurpose::MONOCHROME: + icon_sizes.SetSizesForPurpose(purpose, sizes_monochrome); + break; + } } + downloaded_shortcuts_menu_icons_sizes.push_back(std::move(icon_sizes)); } - return downloaded_shortcuts_menu_icons_sizes; - } - std::vector<IconSizes> CreateDownloadedShortcutsMenuIconsSizes( - std::vector<SquareSizePx> sizes_any, - std::vector<SquareSizePx> sizes_maskable) { - DCHECK_EQ(sizes_any.size(), sizes_maskable.size()); - - std::vector<IconSizes> downloaded_shortcuts_menu_icons_sizes; - for (size_t index = 0; index < sizes_any.size(); ++index) { - IconSizes icon_sizes; - { - std::vector<SquareSizePx> shortcuts_menu_icon_sizes_any; - shortcuts_menu_icon_sizes_any.push_back(sizes_any[index]); - icon_sizes.SetSizesForPurpose(IconPurpose::ANY, - std::move(shortcuts_menu_icon_sizes_any)); - } - { - std::vector<SquareSizePx> shortcuts_menu_icon_sizes_maskable; - shortcuts_menu_icon_sizes_maskable.push_back(sizes_maskable[index]); - icon_sizes.SetSizesForPurpose( - IconPurpose::MASKABLE, - std::move(shortcuts_menu_icon_sizes_maskable)); - } - downloaded_shortcuts_menu_icons_sizes.push_back(std::move(icon_sizes)); - } return downloaded_shortcuts_menu_icons_sizes; } @@ -723,18 +722,21 @@ auto web_app = CreateWebApp(); const AppId app_id = web_app->app_id(); - const std::vector<SquareSizePx> sizes_px{icon_size::k96, icon_size::k256}; + const std::vector<SquareSizePx> sizes_px_any{icon_size::k96, icon_size::k256}; // Set shortcuts menu icons meta-info but don't write bitmaps to disk. web_app->SetDownloadedShortcutsMenuIconsSizes( - CreateDownloadedShortcutsMenuIconsSizes(sizes_px)); + CreateDownloadedShortcutsMenuIconsSizes(sizes_px_any, + /*sizes_maskable=*/{}, + /*sizes_monochrome=*/{}, + /*num_menu_items=*/10)); controller().RegisterApp(std::move(web_app)); // Request shortcuts menu icons which don't exist on disk. ShortcutsMenuIconBitmaps shortcuts_menu_icons_map = ReadAllShortcutsMenuIcons(app_id); - EXPECT_EQ(sizes_px.size(), shortcuts_menu_icons_map.size()); + EXPECT_EQ(10u, shortcuts_menu_icons_map.size()); for (const auto& icon_map : shortcuts_menu_icons_map) { EXPECT_TRUE(icon_map.empty()); } @@ -744,58 +746,86 @@ auto web_app = CreateWebApp(); const AppId app_id = web_app->app_id(); + const int num_menu_items = 3; + const std::vector<int> sizes_any = {icon_size::k64, icon_size::k128, icon_size::k256}; const std::vector<SkColor> colors_any = {SK_ColorRED, SK_ColorWHITE, SK_ColorBLUE}; + const std::vector<int> sizes_maskable = {icon_size::k64, icon_size::k96, icon_size::k128}; const std::vector<SkColor> colors_maskable = {SK_ColorCYAN, SK_ColorMAGENTA, SK_ColorYELLOW}; - WriteShortcutsMenuIcons(app_id, sizes_any, colors_any, sizes_maskable, - colors_maskable); + const std::vector<int> sizes_monochrome = {icon_size::k64, icon_size::k96, + icon_size::k128}; + const std::vector<SkColor> colors_monochrome = {SK_ColorGREEN, SK_ColorBLACK, + SK_ColorTRANSPARENT}; + + WriteGeneratedShortcutsMenuIcons( + app_id, + {{IconPurpose::ANY, sizes_any, colors_any}, + {IconPurpose::MASKABLE, sizes_maskable, colors_maskable}, + {IconPurpose::MONOCHROME, sizes_monochrome, colors_monochrome}}, + num_menu_items); web_app->SetDownloadedShortcutsMenuIconsSizes( - CreateDownloadedShortcutsMenuIconsSizes(sizes_any, sizes_maskable)); + CreateDownloadedShortcutsMenuIconsSizes( + sizes_any, sizes_maskable, sizes_monochrome, num_menu_items)); controller().RegisterApp(std::move(web_app)); ShortcutsMenuIconBitmaps shortcuts_menu_icons_map = ReadAllShortcutsMenuIcons(app_id); EXPECT_EQ(3u, shortcuts_menu_icons_map.size()); - EXPECT_EQ(sizes_any[0], shortcuts_menu_icons_map[0].any.begin()->first); - EXPECT_EQ(colors_any[0], - shortcuts_menu_icons_map[0].any.begin()->second.getColor(0, 0)); - EXPECT_EQ(sizes_maskable[0], - shortcuts_menu_icons_map[0].maskable.begin()->first); - EXPECT_EQ( - colors_maskable[0], - shortcuts_menu_icons_map[0].maskable.begin()->second.getColor(0, 0)); - EXPECT_EQ(sizes_any[1], shortcuts_menu_icons_map[1].any.begin()->first); - EXPECT_EQ(colors_any[1], - shortcuts_menu_icons_map[1].any.begin()->second.getColor(0, 0)); - EXPECT_EQ(sizes_maskable[1], - shortcuts_menu_icons_map[1].maskable.begin()->first); - EXPECT_EQ( - colors_maskable[1], - shortcuts_menu_icons_map[1].maskable.begin()->second.getColor(0, 0)); - EXPECT_EQ(sizes_any[2], shortcuts_menu_icons_map[2].any.begin()->first); - EXPECT_EQ(colors_any[2], - shortcuts_menu_icons_map[2].any.begin()->second.getColor(0, 0)); - EXPECT_EQ(sizes_maskable[2], - shortcuts_menu_icons_map[2].maskable.begin()->first); - EXPECT_EQ( - colors_maskable[2], - shortcuts_menu_icons_map[2].maskable.begin()->second.getColor(0, 0)); + + for (int i = 0; i < num_menu_items; ++i) { + for (int p = static_cast<int>(IconPurpose::kMinValue); + p <= static_cast<int>(IconPurpose::kMaxValue); ++p) { + auto purpose = static_cast<IconPurpose>(p); + SCOPED_TRACE(purpose); + + const std::vector<int>* expect_sizes; + const std::vector<SkColor>* expect_colors; + + switch (purpose) { + case IconPurpose::ANY: + expect_sizes = &sizes_any; + expect_colors = &colors_any; + break; + case IconPurpose::MASKABLE: + expect_sizes = &sizes_maskable; + expect_colors = &colors_maskable; + break; + case IconPurpose::MONOCHROME: + expect_sizes = &sizes_monochrome; + expect_colors = &colors_monochrome; + break; + } + + const std::map<SquareSizePx, SkBitmap>& icon_bitmaps = + shortcuts_menu_icons_map[i].GetBitmapsForPurpose(purpose); + + ASSERT_EQ(expect_sizes->size(), expect_colors->size()); + + for (unsigned s = 0; s < expect_sizes->size(); ++s) { + const SquareSizePx size_px = (*expect_sizes)[s]; + + const auto& size_and_bitmap = icon_bitmaps.find(size_px); + ASSERT_TRUE(size_and_bitmap != icon_bitmaps.end()); + + EXPECT_EQ((*expect_colors)[s], size_and_bitmap->second.getColor(0, 0)); + } + } + } } TEST_F(WebAppIconManagerTest, WriteShortcutsMenuIconsEmptyMap) { auto web_app = CreateWebApp(); const AppId app_id = web_app->app_id(); - web_app->SetDownloadedShortcutsMenuIconsSizes( - CreateDownloadedShortcutsMenuIconsSizes(std::vector<SquareSizePx>{})); + web_app->SetDownloadedShortcutsMenuIconsSizes(std::vector<IconSizes>{}); controller().RegisterApp(std::move(web_app));
diff --git a/chrome/browser/web_applications/web_app_installation_utils.cc b/chrome/browser/web_applications/web_app_installation_utils.cc index ed561e2..e7acd97 100644 --- a/chrome/browser/web_applications/web_app_installation_utils.cc +++ b/chrome/browser/web_applications/web_app_installation_utils.cc
@@ -49,12 +49,14 @@ shortcuts_menu_icons_sizes.reserve(shortcuts_menu_icon_bitmaps.size()); for (const auto& shortcut_icon_bitmaps : shortcuts_menu_icon_bitmaps) { IconSizes icon_sizes; - // TODO (crbug.com/1114638): Return monochrome icon sizes too. icon_sizes.SetSizesForPurpose(IconPurpose::ANY, GetSquareSizePxs(shortcut_icon_bitmaps.any)); icon_sizes.SetSizesForPurpose( IconPurpose::MASKABLE, GetSquareSizePxs(shortcut_icon_bitmaps.maskable)); + icon_sizes.SetSizesForPurpose( + IconPurpose::MONOCHROME, + GetSquareSizePxs(shortcut_icon_bitmaps.monochrome)); shortcuts_menu_icons_sizes.push_back(std::move(icon_sizes)); } return shortcuts_menu_icons_sizes;
diff --git a/chrome/browser/web_applications/web_app_provider.cc b/chrome/browser/web_applications/web_app_provider.cc index 07b03d1..8634be5 100644 --- a/chrome/browser/web_applications/web_app_provider.cc +++ b/chrome/browser/web_applications/web_app_provider.cc
@@ -265,7 +265,7 @@ registrar_.get(), os_integration_manager_.get(), ui_manager_.get(), install_finalizer_.get(), install_manager_.get()); preinstalled_web_app_manager_->SetSubsystems( - externally_managed_app_manager_.get()); + registrar_->AsWebAppRegistrar(), externally_managed_app_manager_.get()); system_web_app_manager_->SetSubsystems( externally_managed_app_manager_.get(), registrar_.get(), registry_controller_.get(), ui_manager_.get(),
diff --git a/chrome/browser/web_applications/web_app_unittest.cc b/chrome/browser/web_applications/web_app_unittest.cc index 05f7d3e..a1f05851 100644 --- a/chrome/browser/web_applications/web_app_unittest.cc +++ b/chrome/browser/web_applications/web_app_unittest.cc
@@ -251,22 +251,24 @@ url: https://example.com/scope1234/shortcut24741963851 icons: any: + maskable: + url: https://example.com/shortcuts/icon247419638512 + square_size_px: 28 + monochrome: url: https://example.com/shortcuts/icon247419638511 square_size_px: 11 url: https://example.com/shortcuts/icon247419638510 square_size_px: 1 - maskable: - url: https://example.com/shortcuts/icon247419638512 - square_size_px: 28 name: shortcut24741963850 url: https://example.com/scope1234/shortcut24741963850 icons: any: - url: https://example.com/shortcuts/icon247419638501 - square_size_px: 18 maskable: url: https://example.com/shortcuts/icon247419638500 square_size_px: 9 + monochrome: + url: https://example.com/shortcuts/icon247419638501 + square_size_px: 18 downloaded_shortcuts_menu_icons_sizes: index: 0: any: @@ -275,8 +277,8 @@ any: 58 maskable: 160 index: 2: - any: 232 77 - maskable: 113 154 + any: 113 90 + maskable: 77 109 file_handlers: action: https://example.com/open-13087720410 accept:
diff --git a/chrome/browser/window_placement/DEPS b/chrome/browser/window_placement/DEPS index abf767e..a8ce4911 100644 --- a/chrome/browser/window_placement/DEPS +++ b/chrome/browser/window_placement/DEPS
@@ -2,4 +2,7 @@ "window_placement_browsertest\.cc": [ "+ash/shell.h", ], + "window_placement_permission_context_browsertest\.cc": [ + "+ash/shell.h", + ], }
diff --git a/chrome/browser/window_placement/window_placement_permission_context_browsertest.cc b/chrome/browser/window_placement/window_placement_permission_context_browsertest.cc index bee737f..cf590f10 100644 --- a/chrome/browser/window_placement/window_placement_permission_context_browsertest.cc +++ b/chrome/browser/window_placement/window_placement_permission_context_browsertest.cc
@@ -3,6 +3,8 @@ // found in the LICENSE file. #include "base/command_line.h" +#include "build/build_config.h" +#include "build/chromeos_buildflags.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/test/base/in_process_browser_test.h" @@ -15,6 +17,13 @@ #include "net/dns/mock_host_resolver.h" #include "net/test/embedded_test_server/default_handlers.h" #include "net/test/embedded_test_server/embedded_test_server.h" +#include "ui/display/screen_base.h" +#include "ui/display/test/scoped_screen_override.h" + +#if BUILDFLAG(IS_CHROMEOS_ASH) +#include "ash/shell.h" +#include "ui/display/test/display_manager_test_api.h" +#endif // BUILDFLAG(IS_CHROMEOS_ASH) namespace { @@ -25,6 +34,19 @@ })(); )"; +#if !defined(OS_WIN) +// TODO(enne): Remove this in http://crbug.com/1205676 +constexpr char kDeprecatedIsMultiscreen[] = R"( + (async () => { + try { + return await window.isMultiScreen() + } catch (e) { + return 'error'; + } + })(); +)"; +#endif // !defined(OS_WIN) + // Tests of WindowPlacementPermissionContext behavior. class WindowPlacementPermissionContextTest : public InProcessBrowserTest { public: @@ -59,6 +81,40 @@ std::unique_ptr<net::EmbeddedTestServer> https_test_server_; }; +class MultiscreenWindowPlacementPermissionContextTest + : public WindowPlacementPermissionContextTest { + public: + void SetScreenInstance() override { +#if BUILDFLAG(IS_CHROMEOS_ASH) + // Use the default, see SetUpOnMainThread. + WindowPlacementPermissionContextTest::SetScreenInstance(); +#else + screen_override_.emplace(&screen_); + screen_.display_list().AddDisplay({1, gfx::Rect(100, 100, 801, 802)}, + display::DisplayList::Type::PRIMARY); + screen_.display_list().AddDisplay({2, gfx::Rect(901, 100, 802, 802)}, + display::DisplayList::Type::NOT_PRIMARY); + ASSERT_EQ(2, display::Screen::GetScreen()->GetNumDisplays()); +#endif // BUILDFLAG(IS_CHROMEOS_ASH) + } + + void SetUpOnMainThread() override { +#if BUILDFLAG(IS_CHROMEOS_ASH) + // This has to happen later than SetScreenInstance as the ash shell + // does not exist yet. + display::test::DisplayManagerTestApi(ash::Shell::Get()->display_manager()) + .UpdateDisplay("100+100-801x802,901+100-802x802"); + ASSERT_EQ(2, display::Screen::GetScreen()->GetNumDisplays()); +#endif + + WindowPlacementPermissionContextTest::SetUpOnMainThread(); + } + + private: + display::ScreenBase screen_; + absl::optional<display::test::ScopedScreenOverride> screen_override_; +}; + // Tests user activation after dimissing and denying the permission request. IN_PROC_BROWSER_TEST_F(WindowPlacementPermissionContextTest, DismissAndDeny) { const GURL url(https_test_server()->GetURL("a.test", "/empty.html")); @@ -185,4 +241,92 @@ EXPECT_TRUE(child->GetMainFrame()->HasTransientUserActivation()); } +// TODO(enne): Windows assumes that display::GetScreen() is a ScreenWin +// which is not true here. +#if !defined(OS_WIN) + +// Verify that window.screen.isExtended returns true in a same-origin +// iframe without the window placement permission policy allowed. +IN_PROC_BROWSER_TEST_F(MultiscreenWindowPlacementPermissionContextTest, + IsExtendedSameOriginAllow) { + const GURL url(https_test_server()->GetURL("a.test", "/iframe.html")); + EXPECT_TRUE(ui_test_utils::NavigateToURL(browser(), url)); + auto* tab = browser()->tab_strip_model()->GetActiveWebContents(); + + content::RenderFrameHost* child = ChildFrameAt(tab->GetMainFrame(), 0); + ASSERT_TRUE(child); + + EXPECT_EQ(true, EvalJs(tab, R"(window.screen.isExtended)", + content::EXECUTE_SCRIPT_NO_USER_GESTURE)); + EXPECT_EQ(true, EvalJs(child, R"(window.screen.isExtended)", + content::EXECUTE_SCRIPT_NO_USER_GESTURE)); + + // TODO(enne): Remove this in http://crbug.com/1205676 + EXPECT_EQ(true, EvalJs(tab, kDeprecatedIsMultiscreen, + content::EXECUTE_SCRIPT_NO_USER_GESTURE)); + EXPECT_EQ(true, EvalJs(child, kDeprecatedIsMultiscreen, + content::EXECUTE_SCRIPT_NO_USER_GESTURE)); +} + +// Verify that window.screen.isExtended returns false in a cross-origin +// iframe without the window placement permission policy allowed. +IN_PROC_BROWSER_TEST_F(MultiscreenWindowPlacementPermissionContextTest, + IsExtendedCrossOriginDeny) { + const GURL url(https_test_server()->GetURL("a.test", "/iframe.html")); + EXPECT_TRUE(ui_test_utils::NavigateToURL(browser(), url)); + auto* tab = browser()->tab_strip_model()->GetActiveWebContents(); + + GURL subframe_url(https_test_server()->GetURL("b.test", "/title1.html")); + content::NavigateIframeToURL(tab, /*iframe_id=*/"test", subframe_url); + + content::RenderFrameHost* child = ChildFrameAt(tab->GetMainFrame(), 0); + ASSERT_TRUE(child); + + EXPECT_EQ(true, EvalJs(tab, R"(window.screen.isExtended)", + content::EXECUTE_SCRIPT_NO_USER_GESTURE)); + EXPECT_EQ(false, EvalJs(child, R"(window.screen.isExtended)", + content::EXECUTE_SCRIPT_NO_USER_GESTURE)); + + // TODO(enne): Remove this in http://crbug.com/1205676 + EXPECT_EQ(true, EvalJs(tab, kDeprecatedIsMultiscreen, + content::EXECUTE_SCRIPT_NO_USER_GESTURE)); + EXPECT_EQ("error", EvalJs(child, kDeprecatedIsMultiscreen, + content::EXECUTE_SCRIPT_NO_USER_GESTURE)); +} + +// Verify that window.screen.isExtended returns true in a cross-origin +// iframe with the window placement permission policy allowed. +IN_PROC_BROWSER_TEST_F(MultiscreenWindowPlacementPermissionContextTest, + IsExtendedCrossOriginAllow) { + const GURL url(https_test_server()->GetURL("a.test", "/iframe.html")); + EXPECT_TRUE(ui_test_utils::NavigateToURL(browser(), url)); + auto* tab = browser()->tab_strip_model()->GetActiveWebContents(); + + // See https://w3c.github.io/webappsec-permissions-policy/ for more + // information on permissions policies and allowing cross-origin iframes + // to have particular permissions. + EXPECT_TRUE(ExecJs(tab, R"(const frame = document.getElementById('test'); + frame.setAttribute('allow', 'window-placement');)", + content::EXECUTE_SCRIPT_NO_USER_GESTURE)); + + GURL subframe_url(https_test_server()->GetURL("b.test", "/title1.html")); + content::NavigateIframeToURL(tab, /*iframe_id=*/"test", subframe_url); + + content::RenderFrameHost* child = ChildFrameAt(tab->GetMainFrame(), 0); + ASSERT_TRUE(child); + + EXPECT_EQ(true, EvalJs(tab, R"(window.screen.isExtended)", + content::EXECUTE_SCRIPT_NO_USER_GESTURE)); + EXPECT_EQ(true, EvalJs(child, R"(window.screen.isExtended)", + content::EXECUTE_SCRIPT_NO_USER_GESTURE)); + + // TODO(enne): Remove this in http://crbug.com/1205676 + EXPECT_EQ(true, EvalJs(tab, kDeprecatedIsMultiscreen, + content::EXECUTE_SCRIPT_NO_USER_GESTURE)); + EXPECT_EQ(true, EvalJs(child, kDeprecatedIsMultiscreen, + content::EXECUTE_SCRIPT_NO_USER_GESTURE)); +} + +#endif // !defined(OS_WIN) + } // namespace
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt index 228bb12..52f343f 100644 --- a/chrome/build/win32.pgo.txt +++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@ -chrome-win32-master-1621457572-e60d595e49521ac06da03b86bcaef384d8be53cc.profdata +chrome-win32-master-1621490381-39c4e0769179446f55075c328e8282300e674670.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt index a4d1a92d..2d375ef 100644 --- a/chrome/build/win64.pgo.txt +++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@ -chrome-win64-master-1621457572-764acf1b3fb28a91d1007d86e7f3479c23440a11.profdata +chrome-win64-master-1621490381-22c9fa38890acd744cac347e92c1a1769d8d278a.profdata
diff --git a/chrome/chrome_cleaner/docs/security.md b/chrome/chrome_cleaner/docs/security.md index d124d3b..24eddbc 100644 --- a/chrome/chrome_cleaner/docs/security.md +++ b/chrome/chrome_cleaner/docs/security.md
@@ -8,11 +8,11 @@ files that are found on users' machines for the presence of Unwanted Software (UwS) that could effect chrome. These files are untrusted inputs so, according to the [Rule of -2](https://chromium.googlesource.com/chromium/src/+/master/docs/security/rule-of-2.md) +2](https://chromium.googlesource.com/chromium/src/+/main/docs/security/rule-of-2.md) all code that parses them must run in a sandbox. Sandboxes are implemented using the [chromium sandbox -library.](https://chromium.googlesource.com/chromium/src/+/master/docs/design/sandbox.md) +library.](https://chromium.googlesource.com/chromium/src/+/main/docs/design/sandbox.md) *** note **TL;DR:** each sandbox runs in a separate process with severely reduced @@ -24,12 +24,12 @@ untrusted files: * [Engine - Sandbox](https://source.chromium.org/chromium/chromium/src/+/master:chrome/chrome_cleaner/engines/): + Sandbox](https://source.chromium.org/chromium/chromium/src/+/main:chrome/chrome_cleaner/engines/): The main scanning engine that detects UwS runs entirely in this sandbox. -* [Parser Sandbox](https://source.chromium.org/chromium/chromium/src/+/master:chrome/chrome_cleaner/parsers/): +* [Parser Sandbox](https://source.chromium.org/chromium/chromium/src/+/main:chrome/chrome_cleaner/parsers/): Parses various file formats such as JSON (mainly for Chrome extension settings) and Windows LNK files. * [Zip Archiver - Sandbox](https://source.chromium.org/chromium/chromium/src/+/master:chrome/chrome_cleaner/zip_archiver/): + Sandbox](https://source.chromium.org/chromium/chromium/src/+/main:chrome/chrome_cleaner/zip_archiver/): Compresses files into a .zip archive. Used when quarantining detected UwS files. @@ -41,7 +41,7 @@ * `broker` contains code that runs in the broker process. * This code has all the privileges of the user running the app. * Code can tell that it's running in the broker process because - [SandboxFactory::GetBrokerServices](https://source.chromium.org/chromium/chromium/src/+/master:sandbox/win/src/sandbox_factory.h) + [SandboxFactory::GetBrokerServices](https://source.chromium.org/chromium/chromium/src/+/main:sandbox/win/src/sandbox_factory.h) will return non-null. * `target` contains code that runs in the target process. * This process is considered untrusted because malicious files could gain @@ -51,29 +51,29 @@ by the broker process. * Cannot access the network to exfiltrate data. * Code can tell that it's running in the broker process because - [SandboxFactory::GetTargetServices](https://source.chromium.org/chromium/chromium/src/+/master:sandbox/win/src/sandbox_factory.h) + [SandboxFactory::GetTargetServices](https://source.chromium.org/chromium/chromium/src/+/main:sandbox/win/src/sandbox_factory.h) will return non-null. The target process communicates with the broker process using -[Mojo](https://chromium.googlesource.com/chromium/src/+/master/mojo/README.md). +[Mojo](https://chromium.googlesource.com/chromium/src/+/main/mojo/README.md). * Mojo interfaces are found in the - [mojom](https://source.chromium.org/chromium/chromium/src/+/master:chrome/chrome_cleaner/mojom) + [mojom](https://source.chromium.org/chromium/chromium/src/+/main:chrome/chrome_cleaner/mojom) directory. * A Mojo interface is a security boundary since it allows the untrusted target process to communicate with the broker process. This means: * The interface should follow the Chromium security [Mojo Style - Guide](https://chromium.googlesource.com/chromium/src/+/master/docs/security/mojo.md). + Guide](https://chromium.googlesource.com/chromium/src/+/main/docs/security/mojo.md). Note that the style guide calls the "broker" process the "browser" process. * All changes to the interface must be reviewed by an IPC security reviewer. This is enforced by the [OWNERS - file](https://source.chromium.org/chromium/chromium/src/+/master:chrome/chrome_cleaner/mojom/OWNERS). + file](https://source.chromium.org/chromium/chromium/src/+/main:chrome/chrome_cleaner/mojom/OWNERS). ### Spawning a sandbox (broker process) The main entry point to create a sandbox is `SpawnSandbox` in -[ipc/sandbox.cc](https://source.chromium.org/chromium/chromium/src/+/master:chrome/chrome_cleaner/ipc/sandbox.cc). +[ipc/sandbox.cc](https://source.chromium.org/chromium/chromium/src/+/main:chrome/chrome_cleaner/ipc/sandbox.cc). Call this with a `SandboxSetupHooks` subclass. * Override methods of `SandboxSetupHooks` to provide custom behaviour for each @@ -109,9 +109,9 @@ You will probably want to set up a Mojo IPC channel to your target process. To do this: 1. Subclass - [MojoSandboxSetupHooks](https://source.chromium.org/chromium/chromium/src/+/master:chrome/chrome_cleaner/ipc/mojo_sandbox_hooks.h) + [MojoSandboxSetupHooks](https://source.chromium.org/chromium/chromium/src/+/main:chrome/chrome_cleaner/ipc/mojo_sandbox_hooks.h) instead of `SandboxSetupHooks`. - * [ZipArchiverSandboxSetupHooks](https://source.chromium.org/chromium/chromium/src/+/master:chrome/chrome_cleaner/zip_archiver/broker/sandbox_setup.h) + * [ZipArchiverSandboxSetupHooks](https://source.chromium.org/chromium/chromium/src/+/main:chrome/chrome_cleaner/zip_archiver/broker/sandbox_setup.h) is a good example. 1. The hooks class should own a `mojo::Remote<SomeMojoInterface>`. This acts like a pointer-to-SomeMojoInterface. Methods called through this "pointer" @@ -119,7 +119,7 @@ SomeMojoInterface is implemented. * For the Zip Archiver, this is a `mojo::Remote<mojom::ZipArchiver>` defined in - [zip_archiver.mojom](https://source.chromium.org/chromium/chromium/src/+/master:chrome/chrome_cleaner/mojom/zip_archiver.mojom). + [zip_archiver.mojom](https://source.chromium.org/chromium/chromium/src/+/main:chrome/chrome_cleaner/mojom/zip_archiver.mojom). 1. Override `UpdateSandboxPolicy` to: 1. Call `MojoSandboxSetupHooks::SetupSandboxMessagePipe`, which returns a handle to the Mojo pipe. @@ -137,12 +137,12 @@ **Note:** All methods on a `mojo::Remote`, including the destructor, need to be called from the same sequence. For legacy reasons chrome_cleaner uses an object called -[MojoTaskRunner](https://source.chromium.org/chromium/chromium/src/+/master:chrome/chrome_cleaner/ipc/mojo_task_runner.h) +[MojoTaskRunner](https://source.chromium.org/chromium/chromium/src/+/main:chrome/chrome_cleaner/ipc/mojo_task_runner.h) for all remotes. The easy way to ensure that all methods are called on the same sequence would be to use -[SequenceBound](https://source.chromium.org/chromium/chromium/src/+/master:base/threading/sequence_bound.h) +[SequenceBound](https://source.chromium.org/chromium/chromium/src/+/main:base/threading/sequence_bound.h) but this code predates it, so instead there are lots of explicit calls to `PostTask` and `OnTaskRunnerDeleter`. *** @@ -159,10 +159,10 @@ 1. Checks the `--sandboxed-process-id` command-line switch to see which type of sandbox to start. 1. Instantiates an override of - [SandboxTargetHooks](https://source.chromium.org/chromium/chromium/src/+/master:chrome/chrome_cleaner/ipc/sandbox.h) + [SandboxTargetHooks](https://source.chromium.org/chromium/chromium/src/+/main:chrome/chrome_cleaner/ipc/sandbox.h) based on the sandbox type. 1. Calls `RunSandboxTarget` in - [ipc/sandbox.cc](https://source.chromium.org/chromium/chromium/src/+/master:chrome/chrome_cleaner/ipc/sandbox.cc), + [ipc/sandbox.cc](https://source.chromium.org/chromium/chromium/src/+/main:chrome/chrome_cleaner/ipc/sandbox.cc), which will: 1. Initialize the sandbox `TargetService`. 1. Call `hooks->TargetStartedWithHighPrivileges`. Override this to do any setup that needs privileges, @@ -185,16 +185,16 @@ To connect to a Mojo IPC channel in the target: 1. Subclass - [MojoSandboxTargetHooks](https://source.chromium.org/chromium/chromium/src/+/master:chrome/chrome_cleaner/ipc/mojo_sandbox_hooks.h) + [MojoSandboxTargetHooks](https://source.chromium.org/chromium/chromium/src/+/main:chrome/chrome_cleaner/ipc/mojo_sandbox_hooks.h) instead of `SandboxTargetHooks`. * This is paired with a `MojoSandboxSetupHooks` that creates a `mojo::Remote<SomeMojoInterface>`. - * [ZipArchiverSandboxTargetHooks](https://source.chromium.org/chromium/chromium/src/+/master:chrome/chrome_cleaner/zip_archiver/target/sandbox_setup.cc) + * [ZipArchiverSandboxTargetHooks](https://source.chromium.org/chromium/chromium/src/+/main:chrome/chrome_cleaner/zip_archiver/target/sandbox_setup.cc) is a good example. 1. Implement the methods of `SomeMojoInterface`. Traditionally this is done in a class called `SomeMojoInterfaceImpl`. * The implementation should own a `mojo::Receiver<SomeMojoInterface>`. * eg. `mojom::ZipArchiver` is implemented in - [ZipArchiverImpl](https://source.chromium.org/chromium/chromium/src/+/master:chrome/chrome_cleaner/zip_archiver/target/zip_archiver_impl.h), + [ZipArchiverImpl](https://source.chromium.org/chromium/chromium/src/+/main:chrome/chrome_cleaner/zip_archiver/target/zip_archiver_impl.h), and it owns a `mojo::Receiver<mojom::ZipArchier>`. * Note this is in the `target` subdir to enforce that the implementation is only used in the target process.
diff --git a/chrome/common/extensions/api/_features.md b/chrome/common/extensions/api/_features.md index f36852c1a..9f81ca0 100644 --- a/chrome/common/extensions/api/_features.md +++ b/chrome/common/extensions/api/_features.md
@@ -14,17 +14,17 @@ ## Files There are four different feature files used: -* [\_api\_features](https://chromium.googlesource.com/chromium/src/+/master/chrome/common/extensions/api/_api_features.json): +* [\_api\_features](https://chromium.googlesource.com/chromium/src/+/main/chrome/common/extensions/api/_api_features.json): Specifies the requirements for API availability. If an extension doesn't satisfy the requirements, the API will not be accessible in the extension's code. -* [\_permission\_features](https://chromium.googlesource.com/chromium/src/+/master/chrome/common/extensions/api/_permission_features.json): +* [\_permission\_features](https://chromium.googlesource.com/chromium/src/+/main/chrome/common/extensions/api/_permission_features.json): Specifies the requirements for permission availability. If an extension doesn't satisfy the requirements, the permission will not be granted and the extension will have an install warning. -* [\_manifest\_features](https://chromium.googlesource.com/chromium/src/+/master/chrome/common/extensions/api/_manifest_features.json): +* [\_manifest\_features](https://chromium.googlesource.com/chromium/src/+/main/chrome/common/extensions/api/_manifest_features.json): Specifies the requirements for manifest entry availability. If an extension doesn't satisfy the requirements, the extension will fail to load with an error. -* [\_behavior\_features](https://chromium.googlesource.com/chromium/src/+/master/extensions/common/api/_behavior_features.json): +* [\_behavior\_features](https://chromium.googlesource.com/chromium/src/+/main/extensions/common/api/_behavior_features.json): Specifies the requirements for miscellaneous extension behaviors. This should typically not be used. @@ -195,7 +195,7 @@ The `feature_flag` property specifies the name of a `base::Feature` flag that must be enabled for the feature to be available. This can be used to implement a remote kill switch for the feature. These feature flags should be defined at -[feature_flags.cc](https://source.chromium.org/chromium/chromium/src/+/master:extensions/common/features/feature_flags.cc). +[feature_flags.cc](https://source.chromium.org/chromium/chromium/src/+/main:extensions/common/features/feature_flags.cc). Accepted value is a single string for the feature flag.
diff --git a/chrome/installer/linux/common/chromium-browser/chromium-browser.appdata.xml b/chrome/installer/linux/common/chromium-browser/chromium-browser.appdata.xml index 3b564b1..e46c262 100644 --- a/chrome/installer/linux/common/chromium-browser/chromium-browser.appdata.xml +++ b/chrome/installer/linux/common/chromium-browser/chromium-browser.appdata.xml
@@ -32,5 +32,5 @@ <translation/> <developer_name>The Chromium Authors</developer_name> <url type="bugtracker">https://www.chromium.org/for-testers/bug-reporting-guidelines</url> - <url type="help">https://chromium.googlesource.com/chromium/src/+/master/docs/linux/debugging.md</url> + <url type="help">https://chromium.googlesource.com/chromium/src/+/main/docs/linux/debugging.md</url> </component>
diff --git a/chrome/installer/setup/setup_main.cc b/chrome/installer/setup/setup_main.cc index 9c285be..a39bd5f 100644 --- a/chrome/installer/setup/setup_main.cc +++ b/chrome/installer/setup/setup_main.cc
@@ -926,35 +926,15 @@ status = installer::IN_USE_UPDATED; } } else if (cmd_line.HasSwitch( - installer::switches::kRegisterWebAppURLProtocols)) { - const std::wstring switch_value = cmd_line.GetSwitchValueNative( - installer::switches::kRegisterWebAppURLProtocols); - std::vector<std::wstring> switch_parts = base::SplitString( - switch_value, L":", base::WhitespaceHandling::TRIM_WHITESPACE, + installer::switches::kDeregisterURLProtocol)) { + const std::wstring protocols_value = cmd_line.GetSwitchValueNative( + installer::switches::kDeregisterURLProtocol); + std::vector<std::wstring> protocols = base::SplitString( + protocols_value, L",", base::WhitespaceHandling::TRIM_WHITESPACE, base::SplitResult::SPLIT_WANT_NONEMPTY); - if (switch_parts.size() == 2) { - std::wstring prog_id = switch_parts[0]; - std::vector<std::wstring> protocols = base::SplitString( - switch_parts[1], L",", base::WhitespaceHandling::TRIM_WHITESPACE, - base::SplitResult::SPLIT_WANT_NONEMPTY); - - // ShellUtil::RegisterChromeForProtocol performs all registration - // done by ShellUtil::RegisterChromeBrowser, as well as registering - // with Windows as capable of handling the supplied protocols. - if (!protocols.empty() && !prog_id.empty() && - ShellUtil::RegisterApplicationForProtocols(protocols, prog_id, - chrome_exe, false)) { - status = installer::IN_USE_UPDATED; - } - } - } else if (cmd_line.HasSwitch( - installer::switches::kUnregisterWebAppProgId)) { - const std::wstring prog_id = cmd_line.GetSwitchValueNative( - installer::switches::kUnregisterWebAppProgId); - - if (!prog_id.empty() && - ShellUtil::RemoveAppProtocolAssociations(prog_id, false)) { + if (!protocols.empty() && ShellUtil::RemoveAppProtocolAssociations( + protocols, chrome_exe, false)) { status = installer::IN_USE_UPDATED; } } else {
diff --git a/chrome/installer/util/shell_util.cc b/chrome/installer/util/shell_util.cc index 072d79d..4b04e6b 100644 --- a/chrome/installer/util/shell_util.cc +++ b/chrome/installer/util/shell_util.cc
@@ -175,6 +175,40 @@ return true; } +// Details about a Windows application, to be entered into the registry for the +// purpose of file associations. +struct ApplicationInfo { + ApplicationInfo() : file_type_icon_index(0), application_icon_index(0) {} + + // The ProgId used by Windows for file associations with this application. + // Must not be empty or start with a '.'. + std::wstring prog_id; + // The friendly name, and the path of the icon that will be used for files of + // these types when associated with this application by default. (They are NOT + // the name/icon that will represent the application under the Open With + // menu.) + std::wstring file_type_name; + base::FilePath file_type_icon_path; + int file_type_icon_index; + // The command to execute when opening a file via this association. It should + // contain "%1" (to tell Windows to pass the filename as an argument). + // TODO(mgiuca): |command_line| should be a base::CommandLine. + std::wstring command_line; + // The AppUserModelId used by Windows 8 for this application. Distinct from + // |prog_id|. + std::wstring app_id; + + // User-visible details about this application. Any of these may be empty. + std::wstring application_name; + base::FilePath application_icon_path; + int application_icon_index; + std::wstring application_description; + std::wstring publisher_name; + + // The CLSID for the application's DelegateExecute handler. May be empty. + std::wstring delegate_clsid; +}; + // Returns the Windows browser client registration key for Chrome. For example: // "Software\Clients\StartMenuInternet\Chromium[.user]". Strictly speaking, we // should use the name of the executable (e.g., "chrome.exe"), but that ship has @@ -201,7 +235,7 @@ // needed for registering a web browser, not for general associations. std::vector<std::unique_ptr<RegistryEntry>> GetChromeDelegateExecuteEntries( const base::FilePath& chrome_exe, - const ShellUtil::ApplicationInfo& app_info) { + const ApplicationInfo& app_info) { std::vector<std::unique_ptr<RegistryEntry>> entries; std::wstring app_id_shell_key(ShellUtil::kRegClasses); @@ -263,7 +297,7 @@ // Gets the registry entries to register an application in the Windows registry. // |app_info| provides all of the information needed. -void GetProgIdEntries(const ShellUtil::ApplicationInfo& app_info, +void GetProgIdEntries(const ApplicationInfo& app_info, std::vector<std::unique_ptr<RegistryEntry>>* entries) { // Basic sanity checks. DCHECK(!app_info.prog_id.empty()); @@ -336,7 +370,7 @@ std::vector<std::unique_ptr<RegistryEntry>>* entries) { int chrome_icon_index = install_static::GetIconResourceIndex(); - ShellUtil::ApplicationInfo app_info; + ApplicationInfo app_info; app_info.prog_id = GetBrowserProgId(suffix); app_info.file_type_name = install_static::GetProgIdDescription(); // File types associated with Chrome are just given the Chrome icon. @@ -1613,11 +1647,9 @@ } // namespace -const wchar_t* ShellUtil::kRegAppProtocolHandlers = L"\\AppProtocolHandlers"; const wchar_t* ShellUtil::kRegDefaultIcon = L"\\DefaultIcon"; const wchar_t* ShellUtil::kRegShellPath = L"\\shell"; const wchar_t* ShellUtil::kRegShellOpen = L"\\shell\\open\\command"; -const wchar_t* ShellUtil::kRegSoftware = L"Software\\"; const wchar_t* ShellUtil::kRegStartMenuInternet = L"Software\\Clients\\StartMenuInternet"; const wchar_t* ShellUtil::kRegClasses = L"Software\\Classes"; @@ -1664,13 +1696,6 @@ ShellUtil::ShortcutProperties::~ShortcutProperties() {} -ShellUtil::ApplicationInfo::ApplicationInfo() = default; - -ShellUtil::ApplicationInfo::ApplicationInfo(ApplicationInfo&& other) noexcept = - default; - -ShellUtil::ApplicationInfo::~ApplicationInfo() = default; - ShellUtil::FileAssociationsAndAppName::FileAssociationsAndAppName() = default; ShellUtil::FileAssociationsAndAppName::FileAssociationsAndAppName( @@ -1906,21 +1931,6 @@ return icon_string; } -absl::optional<std::pair<base::FilePath, int>> ShellUtil::ParseIconLocation( - const std::wstring& argument) { - std::vector<std::wstring> icon_parts = - base::SplitString(argument, std::wstring(L","), base::TRIM_WHITESPACE, - base::SPLIT_WANT_NONEMPTY); - - if (icon_parts.size() < 2) - return absl::nullopt; - - int icon_index = 0; - base::StringToInt(icon_parts[1], &icon_index); - - return std::make_pair(base::FilePath(icon_parts[0]), icon_index); -} - std::wstring ShellUtil::GetChromeShellOpenCmd( const base::FilePath& chrome_exe) { return base::CommandLine(chrome_exe).GetCommandLineStringForShell(); @@ -2656,21 +2666,21 @@ // static bool ShellUtil::AddAppProtocolAssociations( - const std::vector<std::wstring>& protocols, - const std::wstring& prog_id) { - base::FilePath chrome_exe; - if (!base::PathService::Get(base::FILE_EXE, &chrome_exe)) { - NOTREACHED(); + const ProtocolAssociations& protocol_associations, + const base::FilePath& chrome_exe) { + std::wstring suffix; + if (!GetInstallationSpecificSuffix(chrome_exe, &suffix)) + return false; + + if (!RegisterChromeForProtocols(chrome_exe, suffix, protocol_associations, + true)) { return false; } - if (!RegisterApplicationForProtocols(protocols, prog_id, chrome_exe, true)) { - return false; - } - - for (const auto& protocol : protocols) { + for (const auto& protocol_association : protocol_associations.associations) { // This registry value tells Windows that this 'class' is a URL scheme. - // HKEY_CURRENT_USER\Software\Classes\<protocol>\URL Protocol + // <root hkey>\Software\Classes\<protocol>\URL Protocol + const std::wstring& protocol = protocol_association.first; std::wstring url_key(ShellUtil::kRegClasses); url_key.push_back(base::FilePath::kSeparators[0]); url_key.append(protocol); @@ -2721,118 +2731,60 @@ return true; } -// static -bool ShellUtil::RegisterApplicationForProtocols( - const std::vector<std::wstring>& protocols, - const std::wstring& prog_id, - const base::FilePath& chrome_exe, - bool elevate_if_not_admin) { - HKEY root = base::win::GetVersion() == base::win::Version::WIN7 - ? HKEY_LOCAL_MACHINE - : HKEY_CURRENT_USER; - - // Register directly if we can, otherwise elevate and use the installer. - if (root == HKEY_CURRENT_USER || IsUserAnAdmin()) { - std::vector<std::unique_ptr<RegistryEntry>> entries; - - ShellUtil::ApplicationInfo app_info = GetApplicationInfoForProgId(prog_id); - - // Build the Windows Default Programs capabilities key for the app. - // "<root_hkey>\Software\[CompanyPathName\]ProductPathName[install_suffix]\AppProtocolHandlers\|prog_id|\Capabilities". - std::wstring capabilities_path(install_static::GetRegistryPath()); - capabilities_path.append(ShellUtil::kRegAppProtocolHandlers); - capabilities_path.push_back(base::FilePath::kSeparators[0]); - capabilities_path.append(prog_id); - capabilities_path.append(L"\\Capabilities"); - - entries.push_back(std::make_unique<RegistryEntry>( - capabilities_path, ShellUtil::kRegApplicationName, - app_info.application_name)); - - // Use name as app description if description from |prog_id| registration is - // empty. The description is required for the app to show in various places - // of Windows 7. - std::wstring app_description = app_info.application_description.empty() - ? app_info.application_name - : app_info.application_description; - entries.push_back(std::make_unique<RegistryEntry>( - capabilities_path, ShellUtil::kRegApplicationDescription, - app_description)); - - // Create URLAssociations - const std::wstring url_associations( - std::wstring(capabilities_path).append(L"\\URLAssociations")); - - for (const auto& protocol : protocols) { - entries.push_back( - std::make_unique<RegistryEntry>(url_associations, protocol, prog_id)); - } - - // Add the |prog_id| value to <root hkey>\RegisteredApplications. - entries.push_back(std::make_unique<RegistryEntry>( - ShellUtil::kRegRegisteredApplications, prog_id, capabilities_path)); - - uint32_t look_for_in = root == HKEY_CURRENT_USER - ? RegistryEntry::LOOK_IN_HKCU - : RegistryEntry::LOOK_IN_HKLM; - - return AreEntriesAsDesired(entries, look_for_in) || - ShellUtil::AddRegistryEntries(root, entries); - } - - // Admin rights are required to modify system-level protocol associations. - if (!elevate_if_not_admin) - return false; - - // Elevate to do the whole job - std::wstring protocols_switch_value = base::JoinString(protocols, L","); - base::CommandLine::SwitchMap switches{ - {installer::switches::kRegisterWebAppURLProtocols, - prog_id + L":" + protocols_switch_value}}; - std::wstring suffix; - - return GetInstallationSpecificSuffix(chrome_exe, &suffix) && - ElevateAndRegisterChrome(chrome_exe, suffix, &switches); -} - -bool ShellUtil::RemoveAppProtocolAssociations(const std::wstring& prog_id, - bool elevate_if_not_admin) { - HKEY root = base::win::GetVersion() == base::win::Version::WIN7 - ? HKEY_LOCAL_MACHINE - : HKEY_CURRENT_USER; - - if (root == HKEY_CURRENT_USER || IsUserAnAdmin()) { - // Delete the |prog_id| value from <root hkey>\RegisteredApplications. - InstallUtil::DeleteRegistryValue(root, - ShellUtil::kRegRegisteredApplications, - WorkItem::kWow64Default, prog_id); - - // Delete the key - // <root_hkey>\Software\[CompanyPathName\]ProductPathName[install_suffix]\AppProtocolHandlers\|prog_id|. - std::wstring app_key_path(install_static::GetRegistryPath()); - app_key_path.append(ShellUtil::kRegAppProtocolHandlers); - app_key_path.push_back(base::FilePath::kSeparators[0]); - app_key_path.append(prog_id); - - return InstallUtil::DeleteRegistryKey(root, app_key_path, - WorkItem::kWow64Default); - } - - // Admin rights are required to modify system-level protocol associations. - if (!elevate_if_not_admin) - return false; - - base::FilePath chrome_exe; - if (!base::PathService::Get(base::FILE_EXE, &chrome_exe)) - return false; - +bool ShellUtil::DoesAppProtocolAssociationExist( + const std::wstring& protocol, + const std::wstring& app_progid, + const base::FilePath& chrome_exe) { std::wstring suffix; if (!GetInstallationSpecificSuffix(chrome_exe, &suffix)) return false; + bool user_level = InstallUtil::IsPerUserInstall(); + uint32_t look_for_in = user_level ? RegistryEntry::LOOK_IN_HKCU_THEN_HKLM + : RegistryEntry::LOOK_IN_HKLM; + + ProtocolAssociations protocol_associations({{protocol, app_progid}}); + + return IsChromeRegisteredForProtocolAssociations( + suffix, protocol_associations, look_for_in); +} + +bool ShellUtil::RemoveAppProtocolAssociations( + const std::vector<std::wstring>& protocols, + const base::FilePath& chrome_exe, + bool elevate_if_not_admin) { + std::wstring suffix; + if (!GetInstallationSpecificSuffix(chrome_exe, &suffix)) + return false; + + const bool user_level = InstallUtil::IsPerUserInstall(); + const HKEY root = DetermineRegistrationRoot(user_level); + + if (root == HKEY_CURRENT_USER || IsUserAnAdmin()) { + // We can do this operation directly. Delete associations for |protocols|. + std::wstring url_associations_path = + GetCapabilitiesKey(suffix).append(L"\\URLAssociations"); + + bool success = true; + for (const auto& protocol : protocols) { + if (!InstallUtil::DeleteRegistryValue( + root, url_associations_path, WorkItem::kWow64Default, protocol)) { + success = false; + } + } + + return success; + } + + if (!elevate_if_not_admin) { + // Admin rights are required to modify system-level protocol associations. + return false; + } + // Elevate to do the whole job. + std::wstring switch_value = base::JoinString(protocols, L","); base::CommandLine::SwitchMap switches{ - {installer::switches::kUnregisterWebAppProgId, prog_id}}; + {installer::switches::kDeregisterURLProtocol, switch_value}}; return ElevateAndRegisterChrome(chrome_exe, suffix, &switches); } @@ -2854,7 +2806,6 @@ app_info.prog_id = prog_id; app_info.file_type_name = application_description; - app_info.application_description = application_description; app_info.file_type_icon_path = icon_path; app_info.command_line = shell_open_command_line.GetCommandLineStringForShell(); @@ -2881,69 +2832,6 @@ } // static -ShellUtil::ApplicationInfo ShellUtil::GetApplicationInfoForProgId( - const std::wstring& prog_id) { - ApplicationInfo app_info; - app_info.prog_id = prog_id; - - std::wstring prog_id_path(kRegClasses); - prog_id_path.push_back(base::FilePath::kSeparators[0]); - prog_id_path.append(prog_id); - - RegKey class_key(HKEY_CURRENT_USER, prog_id_path.c_str(), KEY_QUERY_VALUE); - - class_key.ReadValue(L"", &app_info.file_type_name); - - // file_type_icon_* - std::wstring file_type_icon_path = prog_id_path + kRegDefaultIcon; - RegKey file_type_icon_key(HKEY_CURRENT_USER, file_type_icon_path.c_str(), - KEY_QUERY_VALUE); - - std::wstring file_type_icon_value; - file_type_icon_key.ReadValue(L"", &file_type_icon_value); - absl::optional<std::pair<base::FilePath, int>> file_type_icon_parts = - ShellUtil::ParseIconLocation(file_type_icon_value); - - if (file_type_icon_parts.has_value()) { - app_info.file_type_icon_path = file_type_icon_parts->first; - app_info.file_type_icon_index = file_type_icon_parts->second; - } - - // app_info.command_line - RegKey command_line_key(HKEY_CURRENT_USER, - (prog_id_path + kRegShellOpen).c_str(), - KEY_QUERY_VALUE); - command_line_key.ReadValue(L"", &app_info.command_line); - - std::wstring application_path = prog_id_path + kRegApplication; - RegKey application_key(HKEY_CURRENT_USER, application_path.c_str(), - KEY_QUERY_VALUE); - - // app_info.app_id - application_key.ReadValue(kRegAppUserModelId, &app_info.app_id); - - // User-visible details - application_key.ReadValue(kRegApplicationName, &app_info.application_name); - application_key.ReadValue(kRegApplicationDescription, - &app_info.application_description); - application_key.ReadValue(kRegApplicationCompany, &app_info.publisher_name); - - // application_icon_* - std::wstring application_icon_value; - application_key.ReadValue(ShellUtil::kRegApplicationIcon, - &application_icon_value); - absl::optional<std::pair<base::FilePath, int>> application_icon_parts = - ShellUtil::ParseIconLocation(application_icon_value); - - if (application_icon_parts.has_value()) { - app_info.application_icon_path = application_icon_parts.value().first; - app_info.application_icon_index = application_icon_parts.value().second; - } - - return app_info; -} - -// static ShellUtil::FileAssociationsAndAppName ShellUtil::GetFileAssociationsAndAppName( const std::wstring& prog_id) { FileAssociationsAndAppName file_associations_and_app_name;
diff --git a/chrome/installer/util/shell_util.h b/chrome/installer/util/shell_util.h index 20013fb..bca7750 100644 --- a/chrome/installer/util/shell_util.h +++ b/chrome/installer/util/shell_util.h
@@ -227,49 +227,9 @@ std::wstring app_name; }; - // Details about a Windows application, to be entered into the registry for - // the purpose of file associations. - struct ApplicationInfo { - ApplicationInfo(); - ApplicationInfo(ApplicationInfo&& other) noexcept; - ~ApplicationInfo(); - - // The ProgId used by Windows for file associations with this application. - // Must not be empty or start with a '.'. - std::wstring prog_id; - // The friendly name, and the path of the icon that will be used for files - // of these types when associated with this application by default. (They - // are NOT the name/icon that will represent the application under the Open - // With menu.) - std::wstring file_type_name; - base::FilePath file_type_icon_path; - int file_type_icon_index = 0; - // The command to execute when opening a file via this association. It - // should contain "%1" (to tell Windows to pass the filename as an - // argument). - // TODO(mgiuca): |command_line| should be a base::CommandLine. - std::wstring command_line; - // The AppUserModelId used by Windows 8 for this application. Distinct from - // |prog_id|. - std::wstring app_id; - - // User-visible details about this application. Any of these may be empty. - std::wstring application_name; - base::FilePath application_icon_path; - int application_icon_index = 0; - std::wstring application_description; - std::wstring publisher_name; - - // The CLSID for the application's DelegateExecute handler. May be empty. - std::wstring delegate_clsid; - }; - // Relative path of the URL Protocol registry entry (prefixed with '\'). static const wchar_t* kRegURLProtocol; - // Registry key under which web app protocol handler prog_ids are stored. - static const wchar_t* kRegAppProtocolHandlers; - // Relative path of DefaultIcon registry entry (prefixed with '\'). static const wchar_t* kRegDefaultIcon; @@ -280,9 +240,6 @@ // (i.e. \\shell\\open\\command). static const wchar_t* kRegShellOpen; - // Relative path of registry key under which applications need to register. - static const wchar_t* kRegSoftware; - // Relative path of registry key under which applications need to register // to control Windows Start menu links. static const wchar_t* kRegStartMenuInternet; @@ -407,13 +364,6 @@ static std::wstring FormatIconLocation(const base::FilePath& icon_path, int icon_index); - // Returns the pair <|icon_path|,|icon_index|> given a properly formatted icon - // location. The input should be formatted by FormatIconLocation above, - // or follow one of the formats specified in - // http://msdn.microsoft.com/library/windows/desktop/dd391573.aspx. - static absl::optional<std::pair<base::FilePath, int>> ParseIconLocation( - const std::wstring& argument); - // This method returns the command to open URLs/files using chrome. Typically // this command is written to the registry under shell\open\command key. // |chrome_exe|: the full path to chrome.exe @@ -755,7 +705,7 @@ // HKCU\SOFTWARE\classes\<prog_id> capable of handling file type / // protocol associations. // - // |prog_id| is the ProgId used by Windows to uniquely identify this + // |prog_id| is the ProgId used by Windows to uniquely identity this // application. Must not be empty or start with a '.'. // |shell_open_command_line| is the command to execute when opening the app // via association. @@ -776,55 +726,33 @@ // Removes all entries of an application at HKCU\SOFTWARE\classes\<prog_id>. static bool DeleteApplicationClass(const std::wstring& prog_id); - // Returns application details for HKCU\SOFTWARE\classes\|prog_id|. The - // returned instance's members will be empty if not found. - static ApplicationInfo GetApplicationInfoForProgId( - const std::wstring& prog_id); - // Returns the app name and file associations registered for a particular // application in the Windows registry. If there is no entry in the registry // for |prog_id|, nothing will be returned. static FileAssociationsAndAppName GetFileAssociationsAndAppName( const std::wstring& prog_id); - // For each protocol in |protocols|, the web app represented by |prog_id| is - // designated as the non-default handler for the corresponding protocol. For - // protocols uncontested by other handlers on the OS, the app will be - // promoted to default handler. + // For each association in |protocol_associations|, the web app is designated + // as the non-default handler for the corresponding protocol. For protocols + // uncontested by other handlers on the OS, the app will be promoted to + // default handler. static bool AddAppProtocolAssociations( - const std::vector<std::wstring>& protocols, - const std::wstring& prog_id); + const ProtocolAssociations& protocol_associations, + const base::FilePath& chrome_exe); - // Registers a set of protocols for a particular application in the Windows - // registry. - // - // This method requires write access to HKLM (prior to Win8). - // If write to HKLM is required, but fails, and: - // - |elevate_if_not_admin| is true: - // tries to launch setup.exe with admin privileges (by prompting the user - // with a UAC) to do these tasks. - // - |elevate_if_not_admin| is false: - // adds the ProgId entries to HKCU. These entries will not make the app show - // in Default Programs but they are still useful because the app can be - // registered to run when the user clicks on a protocol link. - // - // |protocols| is the set of protocols to register. Must not be empty. - // |prog_id| is the ProgId used by Windows for protocol associations with this - // application. Must not be empty or start with a '.'. - // |chrome_exe|: the full path to chrome.exe. - // |elevate_if_not_admin| if true will make this method try alternate methods - // as described above. - static bool RegisterApplicationForProtocols( + // Returns whether |app_progid| is registered to handle |protocol| within the + // browser's protocol associations. + static bool DoesAppProtocolAssociationExist(const std::wstring& protocol, + const std::wstring& app_progid, + const base::FilePath& chrome_exe); + + // For each protocol in |protocols|, the corresponding app handler registered + // within the browser's protocol associations is removed. + static bool RemoveAppProtocolAssociations( const std::vector<std::wstring>& protocols, - const std::wstring& prog_id, const base::FilePath& chrome_exe, bool elevate_if_not_admin); - // Removes all protocol associations for a particular web app from the Windows - // registry. - static bool RemoveAppProtocolAssociations(const std::wstring& prog_id, - bool elevate_if_not_admin); - // Returns the browser's ProgId for the current install. static std::wstring GetProgIdForBrowser(const base::FilePath& chrome_exe);
diff --git a/chrome/installer/util/shell_util_unittest.cc b/chrome/installer/util/shell_util_unittest.cc index fb293129..b840d0e 100644 --- a/chrome/installer/util/shell_util_unittest.cc +++ b/chrome/installer/util/shell_util_unittest.cc
@@ -42,7 +42,6 @@ const wchar_t kTestProgid[] = L"TestApp"; const wchar_t kTestOpenCommand[] = L"C:\\test.exe"; const wchar_t kTestApplicationName[] = L"Test Application"; -const wchar_t kTestApplicationDescription[] = L"Application Description"; const wchar_t kTestFileTypeName[] = L"Test File Type"; const wchar_t kTestIconPath[] = L"D:\\test.ico"; const wchar_t* kTestFileExtensions[] = { @@ -1098,6 +1097,14 @@ base::FilePath& chrome_exe() { return chrome_exe_; } + std::wstring url_associations_key_name() { + std::wstring browser_installation_key = + install_static::GetBaseAppName().append( + ShellUtil::GetCurrentInstallationSuffix(chrome_exe())); + return std::wstring(ShellUtil::kRegStartMenuInternet) + L"\\" + + browser_installation_key + L"\\Capabilities\\URLAssociations"; + } + private: registry_util::RegistryOverrideManager registry_overrides_; base::ScopedTempDir temp_dir_; @@ -1276,90 +1283,36 @@ EXPECT_EQ(file_associations_and_app_name.file_associations, FileExtensions()); } -TEST_F(ShellUtilRegistryTest, GetApplicationInfoForProgId) { - ShellUtil::ApplicationInfo empty_application_info( - ShellUtil::GetApplicationInfoForProgId(kTestProgid)); - EXPECT_TRUE(empty_application_info.application_name.empty()); - - // Add application class and test that GetApplicationInfoForProgId returns - // the registered application properties. - EXPECT_TRUE(ShellUtil::AddApplicationClass( - std::wstring(kTestProgid), OpenCommand(), kTestApplicationName, - kTestApplicationDescription, base::FilePath(kTestIconPath))); - - ShellUtil::ApplicationInfo app_info( - ShellUtil::GetApplicationInfoForProgId(kTestProgid)); - - EXPECT_EQ(kTestProgid, app_info.prog_id); - - EXPECT_EQ(app_info.application_description, app_info.file_type_name); - EXPECT_EQ(base::FilePath(kTestIconPath), app_info.file_type_icon_path); - EXPECT_EQ(0, app_info.file_type_icon_index); - - EXPECT_EQ(L"\"C:\\test.exe\" --single-argument %1", app_info.command_line); - - if (base::win::GetVersion() >= base::win::Version::WIN8) - EXPECT_EQ(L"", app_info.app_id); - - EXPECT_EQ(kTestApplicationName, app_info.application_name); - EXPECT_EQ(kTestApplicationDescription, app_info.application_description); - EXPECT_EQ(L"", app_info.publisher_name); - - EXPECT_EQ(base::FilePath(kTestIconPath), app_info.application_icon_path); - EXPECT_EQ(0, app_info.application_icon_index); -} - TEST_F(ShellUtilRegistryTest, AddAppProtocolAssociations) { - // Create test protocol associations. - const std::wstring app_progid = L"app_progid1"; - const std::vector<std::wstring> app_protocols = {L"web+test", L"mailto"}; + // Create protocol associations. + std::wstring app_progid1 = L"app_progid1"; + std::wstring app_progid2 = L"app_progid2"; - ASSERT_TRUE(ShellUtil::AddAppProtocolAssociations(app_protocols, app_progid)); + ShellUtil::ProtocolAssociations protocol_associations; + protocol_associations.associations[L"web+test"] = app_progid1; + protocol_associations.associations[L"mailto"] = app_progid2; - // Ensure that classes were created for each protocol. - // HKEY_CURRENT_USER\Software\Classes\<protocol>\URL Protocol + ASSERT_TRUE(ShellUtil::AddAppProtocolAssociations(protocol_associations, + chrome_exe())); + + // Ensure that the registry keys have been correctly set. base::win::RegKey key; std::wstring value; ASSERT_EQ(ERROR_SUCCESS, key.Open(HKEY_CURRENT_USER, L"Software\\Classes\\web+test", KEY_READ)); EXPECT_TRUE(key.HasValue(L"URL Protocol")); - ASSERT_EQ(ERROR_SUCCESS, key.Open(HKEY_CURRENT_USER, - L"Software\\Classes\\mailto", KEY_READ)); - EXPECT_TRUE(key.HasValue(L"URL Protocol")); - - // Ensure that URLAssociations entries were created for each protocol. - // "<root_hkey>\Software\[CompanyPathName\]ProductPathName[install_suffix]\AppProtocolHandlers\|prog_id|\Capabilities\URLAssociations\<protocol>". - std::wstring capabilities_path(install_static::GetRegistryPath()); - capabilities_path.append(ShellUtil::kRegAppProtocolHandlers); - capabilities_path.push_back(base::FilePath::kSeparators[0]); - capabilities_path.append(app_progid); - capabilities_path.append(L"\\Capabilities"); - - const std::wstring url_associations_key_name = - capabilities_path + L"\\URLAssociations"; HKEY root = base::win::GetVersion() == base::win::Version::WIN7 ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER; ASSERT_EQ(ERROR_SUCCESS, - key.Open(root, url_associations_key_name.c_str(), KEY_READ)); + key.Open(root, url_associations_key_name().c_str(), KEY_READ)); ASSERT_EQ(ERROR_SUCCESS, key.ReadValue(L"web+test", &value)); - EXPECT_EQ(app_progid, std::wstring(value)); + EXPECT_EQ(app_progid1, std::wstring(value)); ASSERT_EQ(ERROR_SUCCESS, key.ReadValue(L"mailto", &value)); - EXPECT_EQ(app_progid, std::wstring(value)); - - // Ensure that app was registered correctly under RegisteredApplications. - // <root hkey>\RegisteredApplications\<prog_id> - ASSERT_EQ( - ERROR_SUCCESS, - key.Open(root, - std::wstring(ShellUtil::kRegRegisteredApplications).c_str(), - KEY_READ)); - - ASSERT_EQ(ERROR_SUCCESS, key.ReadValue(app_progid.c_str(), &value)); - EXPECT_EQ(capabilities_path, std::wstring(value)); + EXPECT_EQ(app_progid2, std::wstring(value)); } TEST_F(ShellUtilRegistryTest, ToAndFromCommandLineArgument) { @@ -1371,6 +1324,9 @@ protocol_associations.associations[L"web+test"] = app_progid1; protocol_associations.associations[L"mailto"] = app_progid2; + ASSERT_TRUE(ShellUtil::AddAppProtocolAssociations(protocol_associations, + chrome_exe())); + // Ensure the above protocol_associations creates correct command line // arguments correctly. std::wstring command_line = protocol_associations.ToCommandLineArgument(); @@ -1386,39 +1342,45 @@ parsed_protocol_associations.value().associations[L"web+test"]); } -TEST_F(ShellUtilRegistryTest, RemoveAppProtocolAssociations) { - // Create test protocol associations. - const std::wstring app_progid = L"app_progid1"; - const std::vector<std::wstring> app_protocols = {L"web+test"}; +TEST_F(ShellUtilRegistryTest, DoesAppProtocolAssocationExist) { + std::wstring app_progid = L"app_progid"; + ShellUtil::ProtocolAssociations protocol_associations; + protocol_associations.associations[L"web+test"] = app_progid; - ASSERT_TRUE(ShellUtil::AddAppProtocolAssociations(app_protocols, app_progid)); + // Create protocol associations and ensure that + // DoesAppProtocolAssociationExist returns true. + ASSERT_TRUE(ShellUtil::AddAppProtocolAssociations(protocol_associations, + chrome_exe())); + EXPECT_TRUE(ShellUtil::DoesAppProtocolAssociationExist( + L"web+test", app_progid, chrome_exe())); + + // Delete protocol associations and ensure that + // DoesAppProtocolAssociationExist returns false. + ASSERT_TRUE(ShellUtil::RemoveAppProtocolAssociations({L"web+test"}, + chrome_exe(), false)); + EXPECT_FALSE(ShellUtil::DoesAppProtocolAssociationExist( + L"web+test", app_progid, chrome_exe())); +} + +TEST_F(ShellUtilRegistryTest, RemoveAppProtocolAssociations) { + std::wstring app_progid = L"app_progid"; + ShellUtil::ProtocolAssociations protocol_associations; + protocol_associations.associations[L"web+test"] = app_progid; + ASSERT_TRUE(ShellUtil::AddAppProtocolAssociations(protocol_associations, + chrome_exe())); // Delete associations and ensure that the protocol entry does not exist. - EXPECT_TRUE(ShellUtil::RemoveAppProtocolAssociations(app_progid, false)); - - // Ensure that the software registration key was removed. - // "<root_hkey>\Software\[CompanyPathName\]ProductPathName[install_suffix]\AppProtocolHandlers\|prog_id|". - std::wstring capabilities_path(install_static::GetRegistryPath()); - capabilities_path.append(ShellUtil::kRegAppProtocolHandlers); - capabilities_path.push_back(base::FilePath::kSeparators[0]); - capabilities_path.append(app_progid); + EXPECT_TRUE(ShellUtil::RemoveAppProtocolAssociations({L"web+test"}, + chrome_exe(), false)); HKEY root = base::win::GetVersion() == base::win::Version::WIN7 ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER; base::win::RegKey key; - - ASSERT_EQ(ERROR_FILE_NOT_FOUND, - key.Open(root, capabilities_path.c_str(), KEY_READ)); - - // Ensure that the RegisteredApplications entry was removed. - // <root hkey>\RegisteredApplications\<prog_id> - ASSERT_EQ( - ERROR_SUCCESS, - key.Open(root, - std::wstring(ShellUtil::kRegRegisteredApplications).c_str(), - KEY_READ)); - EXPECT_FALSE(key.HasValue(app_progid.c_str())); + std::wstring value; + ASSERT_EQ(ERROR_SUCCESS, + key.Open(root, url_associations_key_name().c_str(), KEY_READ)); + EXPECT_FALSE(key.HasValue(L"web+test")); // Protocol class entry should still exist after the deleted association is // removed so that other associations are not affected.
diff --git a/chrome/installer/util/util_constants.cc b/chrome/installer/util/util_constants.cc index 8bc66950..2422adb9 100644 --- a/chrome/installer/util/util_constants.cc +++ b/chrome/installer/util/util_constants.cc
@@ -38,6 +38,10 @@ // kUninstall, otherwise it is silently ignored. const char kDeleteProfile[] = "delete-profile"; +// Specifies a comma-separated list of protocols to remove from the browser's +// protocol associations list. +const char kDeregisterURLProtocol[] = "deregister-url-protocol"; + // Disable logging const char kDisableLogging[] = "disable-logging"; @@ -133,11 +137,6 @@ // in addition to the standard set of protocols. const char kRegisterURLProtocol[] = "register-url-protocol"; -// Specifies a comma-separated list of protocols to add as protocol associations -// for a web application, preceded by the prog_id of that web application. -// --register-web-app-url-protocols=<progid>:<protocol>,<protocol>,<protocol>..] -const char kRegisterWebAppURLProtocols[] = "register-web-app-url-protocols"; - // Removes Chrome registration from current machine. Requires admin rights. const char kRemoveChromeRegistration[] = "remove-chrome-registration"; @@ -177,10 +176,6 @@ // path given by --new-setup-exe. const char kUpdateSetupExe[] = "update-setup-exe"; -// Switch to pass the ProdId of a web application to be unregistered for -// protocol handling. -const char kUnregisterWebAppProgId[] = "unregister-web-app-prog-id"; - // Enable verbose logging (info level). const char kVerboseLogging[] = "verbose-logging";
diff --git a/chrome/installer/util/util_constants.h b/chrome/installer/util/util_constants.h index 1445a9e..60f85638 100644 --- a/chrome/installer/util/util_constants.h +++ b/chrome/installer/util/util_constants.h
@@ -159,6 +159,7 @@ extern const char kCriticalUpdateVersion[]; extern const char kDeleteOldVersions[]; extern const char kDeleteProfile[]; +extern const char kDeregisterURLProtocol[]; extern const char kDisableLogging[]; extern const char kDoNotLaunchChrome[]; extern const char kDoNotRegisterForUpdateLaunch[]; @@ -183,7 +184,6 @@ extern const char kRegisterChromeBrowserSuffix[]; extern const char kRegisterDevChrome[]; extern const char kRegisterURLProtocol[]; -extern const char kRegisterWebAppURLProtocols[]; extern const char kRemoveChromeRegistration[]; extern const char kRenameChromeExe[]; extern const char kRunAsAdmin[]; @@ -195,7 +195,6 @@ extern const char kUncompressedArchive[]; extern const char kUninstall[]; extern const char kUpdateSetupExe[]; -extern const char kUnregisterWebAppProgId[]; extern const char kVerboseLogging[]; } // namespace switches
diff --git a/chrome/renderer/extensions/chrome_extensions_dispatcher_delegate.cc b/chrome/renderer/extensions/chrome_extensions_dispatcher_delegate.cc index 4195d36..fa3aa17 100644 --- a/chrome/renderer/extensions/chrome_extensions_dispatcher_delegate.cc +++ b/chrome/renderer/extensions/chrome_extensions_dispatcher_delegate.cc
@@ -183,10 +183,10 @@ source_map->RegisterSource("chromeos.ime.service", IDR_IME_SERVICE_BINDINGS_JS); - source_map->RegisterSource("chromeos.tts.mojom.tts_stream_factory.mojom", - IDR_TTS_STREAM_FACTORY_MOJOM_JS); - source_map->RegisterSource("chromeos.tts.stream_factory", - IDR_TTS_STREAM_FACTORY_BINDINGS_JS); + source_map->RegisterSource("chromeos.tts.mojom.google_tts_stream.mojom", + IDR_GOOGLE_TTS_STREAM_MOJOM_JS); + source_map->RegisterSource("chromeos.tts.google_stream", + IDR_GOOGLE_TTS_STREAM_BINDINGS_JS); // Imprivata API. source_map->RegisterSource("chromeos.remote_apps.mojom-lite",
diff --git a/chrome/renderer/resources/extensions/chromeos_tts_stream_factory_bindings.js b/chrome/renderer/resources/extensions/chromeos_google_tts_stream_bindings.js similarity index 67% rename from chrome/renderer/resources/extensions/chromeos_tts_stream_factory_bindings.js rename to chrome/renderer/resources/extensions/chromeos_google_tts_stream_bindings.js index 20356b8..20c1ec6 100644 --- a/chrome/renderer/resources/extensions/chromeos_tts_stream_factory_bindings.js +++ b/chrome/renderer/resources/extensions/chromeos_google_tts_stream_bindings.js
@@ -9,11 +9,11 @@ } mojo.config.autoLoadMojomDeps = false; -loadScript('chromeos.tts.mojom.tts_stream_factory.mojom'); +loadScript('chromeos.tts.mojom.google_tts_stream.mojom'); (function() { - let ptr = new chromeos.tts.mojom.TtsStreamFactoryPtr; + let ptr = new chromeos.tts.mojom.GoogleTtsStreamPtr; Mojo.bindInterface( - chromeos.tts.mojom.TtsStreamFactory.name, mojo.makeRequest(ptr).handle); + chromeos.tts.mojom.GoogleTtsStream.name, mojo.makeRequest(ptr).handle); exports.$set('returnValue', ptr); })();
diff --git a/chrome/renderer/resources/renderer_resources.grd b/chrome/renderer/resources/renderer_resources.grd index c707ab48..98bd2f4 100644 --- a/chrome/renderer/resources/renderer_resources.grd +++ b/chrome/renderer/resources/renderer_resources.grd
@@ -74,8 +74,8 @@ <include name="IDR_REMOTE_APPS_MOJOM_LITE_JS" file="${mojom_root}\chromeos\components\remote_apps\mojom\remote_apps.mojom-lite.js" use_base_dir="false" type="BINDATA" /> <include name="IDR_MOJO_URL_MOJOM_LITE_JS" file="${mojom_root}\url\mojom\url.mojom-lite.js" use_base_dir="false" type="BINDATA" /> - <include name="IDR_TTS_STREAM_FACTORY_BINDINGS_JS" file="extensions\chromeos_tts_stream_factory_bindings.js" type="BINDATA" /> - <include name="IDR_TTS_STREAM_FACTORY_MOJOM_JS" file="${mojom_root}\chromeos\services\tts\public\mojom\tts_service.mojom.js" use_base_dir="false" type="BINDATA" /> + <include name="IDR_GOOGLE_TTS_STREAM_BINDINGS_JS" file="extensions\chromeos_google_tts_stream_bindings.js" type="BINDATA" /> + <include name="IDR_GOOGLE_TTS_STREAM_MOJOM_JS" file="${mojom_root}\chromeos\services\tts\public\mojom\tts_service.mojom.js" use_base_dir="false" type="BINDATA" /> </if> <!-- Media Router Mojo service and bindings. --> <include name="IDR_MEDIA_CONTROLLER_MOJOM_JS" file="${mojom_root}\components\media_router\common\mojom\media_controller.mojom.js" use_base_dir="false" type="BINDATA" />
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index a582e12..e2fe0a4 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -360,6 +360,7 @@ "base/test_browser_window.cc", "base/test_browser_window.h", ] + allow_circular_includes_from = [ ":test_support_ui" ] } if (is_linux || is_chromeos) { @@ -560,11 +561,9 @@ deps += [ "//build:chromeos_buildflags", - "//chrome/browser/web_applications:web_applications_test_support", + "//chrome/browser/web_applications:web_applications_test_support_minimal", "//components/webapps/browser", ] - allow_circular_includes_from = - [ "//chrome/browser/web_applications:web_applications_test_support" ] } if (enable_message_center) { @@ -4631,6 +4630,7 @@ "../browser/password_manager/android/update_password_infobar_delegate_android_unittest.cc", "../browser/permissions/permission_prompt_android_unittest.cc", "../browser/profiles/android/profile_resolver_unittest.cc", + "../browser/reputation/safety_tip_message_delegate_unittest.cc", "../browser/sharing/click_to_call/click_to_call_message_handler_android_unittest.cc", "../browser/sharing/sms/sms_fetch_request_handler_unittest.cc", "../browser/touch_to_fill/touch_to_fill_controller_unittest.cc", @@ -6630,6 +6630,8 @@ "../browser/ui/webui/signin/login_ui_test_utils.h", "../browser/web_applications/test/profile_test_helper.cc", "../browser/web_applications/test/profile_test_helper.h", + "base/devtools_listener.cc", + "base/devtools_listener.h", "base/in_process_browser_test.cc", "base/in_process_browser_test.h", "base/javascript_browser_test.cc", @@ -6664,20 +6666,80 @@ ] deps = [ "//build:chromeos_buildflags", + "//chrome/app:command_ids", + "//chrome/browser", + "//chrome/browser:browser_process", + "//chrome/browser/devtools", + "//chrome/browser/profiles:profile", + "//chrome/browser/ui", + "//chrome/browser/web_applications", + "//chrome/browser/web_applications:web_applications_test_support_minimal", + "//chrome/browser/web_applications/components", + "//chrome/common", + "//chrome/common:chrome_features", + "//chrome/common:constants", + "//chrome/common:non_code_constants", "//chrome/common/profiler", + "//chrome/renderer", + "//chrome/test/data:web_ui_test_bindings", + "//chrome/test/data:webui_test_resources_grit", + "//components/account_id", + "//components/autofill/content/browser", + "//components/autofill/core/browser", + "//components/autofill/core/browser:test_support", + "//components/autofill/core/common", + "//components/bookmarks/browser", + "//components/captive_portal/content", "//components/captive_portal/core:buildflags", + "//components/content_settings/core/browser", + "//components/embedder_support", + "//components/find_in_page", + "//components/google/core/common", + "//components/history/core/browser", + "//components/infobars/content", + "//components/infobars/core", + "//components/javascript_dialogs", + "//components/keyed_service/content", "//components/metrics:test_support", "//components/nacl/common:buildflags", + "//components/nacl/common:switches", + "//components/omnibox/browser", "//components/os_crypt:test_support", + "//components/password_manager/core/browser", + "//components/password_manager/core/browser:password_form", + "//components/password_manager/core/browser:test_support", + "//components/permissions", + "//components/prefs", + "//components/search_engines", + "//components/security_interstitials/content:security_interstitial_page", + "//components/signin/public/base", + "//components/signin/public/identity_manager", + "//components/storage_monitor:test_support", + "//components/sync/driver:test_support", + "//components/user_manager", + "//components/webapps/browser", "//content/public/browser", "//extensions/buildflags", + "//google_apis", + "//ppapi/shared_impl", + "//printing/buildflags", "//services/device/public/cpp:test_support", "//skia", "//testing/gtest", "//third_party/libaddressinput", "//ui/base:features", + "//ui/base:test_support", + "//ui/events:test_support", + "//ui/shell_dialogs", + "//ui/views", + "//ui/views:test_support", + "//ui/views/controls/webview", ] + if (use_aura) { + deps += [ "//ui/aura:test_support" ] + } + if (enable_plugins) { sources += [ "ppapi/ppapi_test.cc", @@ -6693,7 +6755,12 @@ if (is_chromeos_ash) { deps += [ + "//ash", + "//ash:test_support", + "//ash/constants", "//ash/public/cpp", + "//chrome/browser/chromeos", + "//chromeos/cryptohome", "//chromeos/services/device_sync", "//chromeos/services/device_sync:test_support", ]
diff --git a/chrome/test/base/web_ui_browser_test.cc b/chrome/test/base/web_ui_browser_test.cc index c646825..01b19b69 100644 --- a/chrome/test/base/web_ui_browser_test.cc +++ b/chrome/test/base/web_ui_browser_test.cc
@@ -15,6 +15,7 @@ #include "base/lazy_instance.h" #include "base/memory/ref_counted_memory.h" #include "base/path_service.h" +#include "base/strings/strcat.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "base/test/test_switches.h" @@ -32,6 +33,7 @@ #include "chrome/common/url_constants.h" #include "chrome/test/base/js_test_api.h" #include "chrome/test/base/test_chrome_web_ui_controller_factory.h" +#include "chrome/test/base/test_switches.h" #include "chrome/test/base/ui_test_utils.h" #include "content/public/browser/global_routing_id.h" #include "content/public/browser/url_data_source.h" @@ -137,6 +139,78 @@ content::WebUI* GetWebUI() override { return web_ui(); } }; +class WebUICoverageObserver : public content::DevToolsAgentHostObserver { + public: + explicit WebUICoverageObserver(base::FilePath devtools_code_coverage_dir) + : devtools_code_coverage_dir_(devtools_code_coverage_dir) { + content::DevToolsAgentHost::AddObserver(this); + } + + ~WebUICoverageObserver() override = default; + + bool CoverageEnabled() { return !devtools_code_coverage_dir_.empty(); } + + void CollectCoverage(const std::string& test_name) { + ASSERT_TRUE(CoverageEnabled()); + + content::DevToolsAgentHost::RemoveObserver(this); + content::RunAllTasksUntilIdle(); + + base::ScopedAllowBlockingForTesting allow_blocking; + base::FilePath store = devtools_code_coverage_dir_.AppendASCII( + "webui_javascript_code_coverage"); + coverage::DevToolsListener::SetupCoverageStore(store); + + for (auto& agent : devtools_agent_) { + auto* host = agent.first; + if (agent.second->HasCoverage(host)) + agent.second->GetCoverage(host, store, test_name); + agent.second->Detach(host); + } + + content::DevToolsAgentHost::DetachAllClients(); + } + + protected: + // content::DevToolsAgentHostObserver + bool ShouldForceDevToolsAgentHostCreation() override { + return CoverageEnabled(); + } + + void DevToolsAgentHostCreated(content::DevToolsAgentHost* host) override { + CHECK(devtools_agent_.find(host) == devtools_agent_.end()); + + uint32_t process_id = base::GetUniqueIdForProcess().GetUnsafeValue(); + devtools_agent_[host] = + std::make_unique<coverage::DevToolsListener>(host, process_id); + } + + void DevToolsAgentHostAttached(content::DevToolsAgentHost* host) override {} + + void DevToolsAgentHostNavigated(content::DevToolsAgentHost* host) override { + if (devtools_agent_.find(host) == devtools_agent_.end()) + return; + + devtools_agent_.find(host)->second->Navigated(host); + } + + void DevToolsAgentHostDetached(content::DevToolsAgentHost* host) override {} + + void DevToolsAgentHostCrashed(content::DevToolsAgentHost* host, + base::TerminationStatus status) override { + ASSERT_TRUE(devtools_agent_.find(host) == devtools_agent_.end()); + } + + private: + using DevToolsAgentMap = // agent hosts: have a unique devtools listener + std::map<content::DevToolsAgentHost*, + std::unique_ptr<coverage::DevToolsListener>>; + base::FilePath devtools_code_coverage_dir_; + DevToolsAgentMap devtools_agent_; + + DISALLOW_COPY_AND_ASSIGN(WebUICoverageObserver); +}; + } // namespace BaseWebUIBrowserTest::~BaseWebUIBrowserTest() = default; @@ -179,9 +253,15 @@ args.push_back(base::Value(test_fixture)); args.push_back(base::Value(test_name)); - if (is_async) - return RunJavascriptAsyncTest("RUN_TEST_F", std::move(args)); - return RunJavascriptTest("RUN_TEST_F", std::move(args)); + bool result = is_async ? RunJavascriptAsyncTest("RUN_TEST_F", std::move(args)) + : RunJavascriptTest("RUN_TEST_F", std::move(args)); + + if (coverage_handler_ && coverage_handler_->CoverageEnabled()) { + const std::string& full_test_name = base::StrCat({test_fixture, test_name}); + coverage_handler_->CollectCoverage(full_test_name); + } + + return result; } bool BaseWebUIBrowserTest::RunJavascriptTest(const std::string& test_name) { @@ -452,6 +532,13 @@ // Enables the MojoJSTest bindings which are used for WebUI tests. base::CommandLine::ForCurrentProcess()->AppendSwitchASCII( switches::kEnableBlinkFeatures, "MojoJSTest"); + + if (command_line->HasSwitch(switches::kDevtoolsCodeCoverage)) { + base::FilePath devtools_code_coverage_dir = + command_line->GetSwitchValuePath(switches::kDevtoolsCodeCoverage); + coverage_handler_ = + std::make_unique<WebUICoverageObserver>(devtools_code_coverage_dir); + } } void BaseWebUIBrowserTest::SetUpOnMainThread() {
diff --git a/chrome/test/base/web_ui_browser_test.h b/chrome/test/base/web_ui_browser_test.h index 94d1562..4d713d5 100644 --- a/chrome/test/base/web_ui_browser_test.h +++ b/chrome/test/base/web_ui_browser_test.h
@@ -12,22 +12,25 @@ #include "base/files/file_path.h" #include "chrome/browser/ui/webui/web_ui_test_handler.h" +#include "chrome/test/base/devtools_listener.h" #include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/javascript_browser_test.h" +#include "content/public/browser/devtools_agent_host_observer.h" namespace { class WebUITestMessageHandler; -} +class WebUICoverageObserver; +} // namespace namespace base { class Value; -} +} // namespace base namespace content { class RenderFrameHost; class ScopedWebUIControllerFactoryRegistration; class WebUI; -} +} // namespace content class TestChromeWebUIControllerFactory; @@ -184,6 +187,8 @@ std::unique_ptr<TestChromeWebUIControllerFactory> test_factory_; std::unique_ptr<content::ScopedWebUIControllerFactoryRegistration> factory_registration_; + + std::unique_ptr<WebUICoverageObserver> coverage_handler_; }; class WebUIBrowserTest : public BaseWebUIBrowserTest {
diff --git a/chrome/test/chromedriver/README.md b/chrome/test/chromedriver/README.md index c4cd27c..6c6448f0 100644 --- a/chrome/test/chromedriver/README.md +++ b/chrome/test/chromedriver/README.md
@@ -76,7 +76,7 @@ available in many languages, and many are available from the open source [Selenium WebDriver project](https://www.selenium.dev/). ChromeDriver uses the webserver from -[net/server](https://source.chromium.org/chromium/chromium/src/+/master:net/server/). +[net/server](https://source.chromium.org/chromium/chromium/src/+/main:net/server/). Additional information is available on the following pages: * [Threading](docs/threading.md): ChromeDriver threading model.
diff --git a/chrome/test/chromedriver/docs/event_listener.md b/chrome/test/chromedriver/docs/event_listener.md index 9dc9e59..66369f04 100644 --- a/chrome/test/chromedriver/docs/event_listener.md +++ b/chrome/test/chromedriver/docs/event_listener.md
@@ -11,26 +11,26 @@ `DevToolsClientImpl` object.) An event listener must be an object that implements the interface class -[`DevToolsEventListener`](https://source.chromium.org/chromium/chromium/src/+/master:chrome/test/chromedriver/chrome/devtools_event_listener.h?q=DevToolsEventListener). +[`DevToolsEventListener`](https://source.chromium.org/chromium/chromium/src/+/main:chrome/test/chromedriver/chrome/devtools_event_listener.h?q=DevToolsEventListener). Each listener is called in the following situations: * When the DevTools Client connects to Chrome. - ([`ConnectIfNecessary`](https://source.chromium.org/chromium/chromium/src/+/master:chrome/test/chromedriver/chrome/devtools_client_impl.cc?q=DevToolsClientImpl::ConnectIfNecessary) - -> [`EnsureListenersNotifiedOfConnect`](https://source.chromium.org/chromium/chromium/src/+/master:chrome/test/chromedriver/chrome/devtools_client_impl.cc?q=DevToolsClientImpl::EnsureListenersNotifiedOfConnect) - -> [`DevToolsEventListener::OnConnected`](https://source.chromium.org/chromium/chromium/src/+/master:chrome/test/chromedriver/chrome/devtools_event_listener.h?q=OnConnected)) + ([`ConnectIfNecessary`](https://source.chromium.org/chromium/chromium/src/+/main:chrome/test/chromedriver/chrome/devtools_client_impl.cc?q=DevToolsClientImpl::ConnectIfNecessary) + -> [`EnsureListenersNotifiedOfConnect`](https://source.chromium.org/chromium/chromium/src/+/main:chrome/test/chromedriver/chrome/devtools_client_impl.cc?q=DevToolsClientImpl::EnsureListenersNotifiedOfConnect) + -> [`DevToolsEventListener::OnConnected`](https://source.chromium.org/chromium/chromium/src/+/main:chrome/test/chromedriver/chrome/devtools_event_listener.h?q=OnConnected)) * When an event is received from Chrome. - ([`ProcessEvent`](https://source.chromium.org/chromium/chromium/src/+/master:chrome/test/chromedriver/chrome/devtools_client_impl.cc?q=DevToolsClientImpl::ProcessEvent) - -> [`EnsureListenersNotifiedOfEvent`](https://source.chromium.org/chromium/chromium/src/+/master:chrome/test/chromedriver/chrome/devtools_client_impl.cc?q=DevToolsClientImpl::EnsureListenersNotifiedOfEvent) - -> [`DevToolsEventListener::OnEvent`](https://source.chromium.org/chromium/chromium/src/+/master:chrome/test/chromedriver/chrome/devtools_event_listener.h?q=OnEvent)) + ([`ProcessEvent`](https://source.chromium.org/chromium/chromium/src/+/main:chrome/test/chromedriver/chrome/devtools_client_impl.cc?q=DevToolsClientImpl::ProcessEvent) + -> [`EnsureListenersNotifiedOfEvent`](https://source.chromium.org/chromium/chromium/src/+/main:chrome/test/chromedriver/chrome/devtools_client_impl.cc?q=DevToolsClientImpl::EnsureListenersNotifiedOfEvent) + -> [`DevToolsEventListener::OnEvent`](https://source.chromium.org/chromium/chromium/src/+/main:chrome/test/chromedriver/chrome/devtools_event_listener.h?q=OnEvent)) * When a command response is received from Chrome. - ([`ProcessCommandResponse`](https://source.chromium.org/chromium/chromium/src/+/master:chrome/test/chromedriver/chrome/devtools_client_impl.cc?q=DevToolsClientImpl::ProcessCommandResponse) - -> [`EnsureListenersNotifiedOfCommandResponse`](https://source.chromium.org/chromium/chromium/src/+/master:chrome/test/chromedriver/chrome/devtools_client_impl.cc?q=DevToolsClientImpl::EnsureListenersNotifiedOfCommandResponse) - -> [`DevToolsEventListener::OnCommandSuccess`](https://source.chromium.org/chromium/chromium/src/+/master:chrome/test/chromedriver/chrome/devtools_event_listener.h?q=OnCommandSuccess)) + ([`ProcessCommandResponse`](https://source.chromium.org/chromium/chromium/src/+/main:chrome/test/chromedriver/chrome/devtools_client_impl.cc?q=DevToolsClientImpl::ProcessCommandResponse) + -> [`EnsureListenersNotifiedOfCommandResponse`](https://source.chromium.org/chromium/chromium/src/+/main:chrome/test/chromedriver/chrome/devtools_client_impl.cc?q=DevToolsClientImpl::EnsureListenersNotifiedOfCommandResponse) + -> [`DevToolsEventListener::OnCommandSuccess`](https://source.chromium.org/chromium/chromium/src/+/main:chrome/test/chromedriver/chrome/devtools_event_listener.h?q=OnCommandSuccess)) The DevTools Client has three lists to keep track of listeners that still need to be notified of these three situations: -[`DevToolsClientImpl::unnotified_connect_listeners_`](https://source.chromium.org/chromium/chromium/src/+/master:chrome/test/chromedriver/chrome/devtools_client_impl.h?q=DevToolsClientImpl::unnotified_connect_listeners_), -[`DevToolsClientImpl::unnotified_event_listeners_`](https://source.chromium.org/chromium/chromium/src/+/master:chrome/test/chromedriver/chrome/devtools_client_impl.h?q=DevToolsClientImpl::unnotified_event_listeners_), and -[`DevToolsClientImpl::unnotified_cmd_response_listeners_`](https://source.chromium.org/chromium/chromium/src/+/master:chrome/test/chromedriver/chrome/devtools_client_impl.h?q=DevToolsClientImpl::unnotified_cmd_response_listeners_). +[`DevToolsClientImpl::unnotified_connect_listeners_`](https://source.chromium.org/chromium/chromium/src/+/main:chrome/test/chromedriver/chrome/devtools_client_impl.h?q=DevToolsClientImpl::unnotified_connect_listeners_), +[`DevToolsClientImpl::unnotified_event_listeners_`](https://source.chromium.org/chromium/chromium/src/+/main:chrome/test/chromedriver/chrome/devtools_client_impl.h?q=DevToolsClientImpl::unnotified_event_listeners_), and +[`DevToolsClientImpl::unnotified_cmd_response_listeners_`](https://source.chromium.org/chromium/chromium/src/+/main:chrome/test/chromedriver/chrome/devtools_client_impl.h?q=DevToolsClientImpl::unnotified_cmd_response_listeners_). These lists are necessary because while a listener processes one event, it can trigger the generation of additional events. @@ -39,15 +39,15 @@ ## Listener Registration Each instance of `DevToolsClientImpl` stores a list of listeners in field -[`DevToolsClientImpl::listeners_`](https://source.chromium.org/chromium/chromium/src/+/master:chrome/test/chromedriver/chrome/devtools_client_impl.h?q=DevToolsClientImpl::listeners_). +[`DevToolsClientImpl::listeners_`](https://source.chromium.org/chromium/chromium/src/+/main:chrome/test/chromedriver/chrome/devtools_client_impl.h?q=DevToolsClientImpl::listeners_). Listeners can be added by calling -[`DevToolsClientImpl::AddListener`](https://source.chromium.org/chromium/chromium/src/+/master:chrome/test/chromedriver/chrome/devtools_client_impl.cc?q=DevToolsClientImpl::AddListener). +[`DevToolsClientImpl::AddListener`](https://source.chromium.org/chromium/chromium/src/+/main:chrome/test/chromedriver/chrome/devtools_client_impl.cc?q=DevToolsClientImpl::AddListener). * For the browser-wide DevTools client, this is done by - [`CreateBrowserwideDevToolsClientAndConnect`](https://source.chromium.org/chromium/chromium/src/+/master:chrome/test/chromedriver/chrome_launcher.cc?q=CreateBrowserwideDevToolsClientAndConnect) + [`CreateBrowserwideDevToolsClientAndConnect`](https://source.chromium.org/chromium/chromium/src/+/main:chrome/test/chromedriver/chrome_launcher.cc?q=CreateBrowserwideDevToolsClientAndConnect) shortly after Chrome starts. * For other DevTools clients, this happens in - [`ChromeImpl::UpdateWebViews`](https://source.chromium.org/chromium/chromium/src/+/master:chrome/test/chromedriver/chrome/chrome_impl.cc?q=ChromeImpl::UpdateWebViews) and - [`WebViewImpl` constructor](https://source.chromium.org/chromium/chromium/src/+/master:chrome/test/chromedriver/chrome/web_view_impl.cc?q=WebViewImpl::WebViewImpl). + [`ChromeImpl::UpdateWebViews`](https://source.chromium.org/chromium/chromium/src/+/main:chrome/test/chromedriver/chrome/chrome_impl.cc?q=ChromeImpl::UpdateWebViews) and + [`WebViewImpl` constructor](https://source.chromium.org/chromium/chromium/src/+/main:chrome/test/chromedriver/chrome/web_view_impl.cc?q=WebViewImpl::WebViewImpl). Most listeners are added indirectly by `WebViewImpl` constructor. The constructor instantiates several listener objects, @@ -57,26 +57,26 @@ ## Details of Listeners ChromeDriver has the following event listeners: -* [`CastTracker`](https://source.chromium.org/chromium/chromium/src/+/master:chrome/test/chromedriver/chrome/cast_tracker.h?q=CastTracker) -* [`ConsoleLogger`](https://source.chromium.org/chromium/chromium/src/+/master:chrome/test/chromedriver/chrome/console_logger.h?q=ConsoleLogger) -* [`DevToolsEventsLogger`](https://source.chromium.org/chromium/chromium/src/+/master:chrome/test/chromedriver/devtools_events_logger.h?q=DevToolsEventsLogger) -* [`DomTracker`](https://source.chromium.org/chromium/chromium/src/+/master:chrome/test/chromedriver/chrome/dom_tracker.h?q=DomTracker) -* [`DownloadDirectoryOverrideManager`](https://source.chromium.org/chromium/chromium/src/+/master:chrome/test/chromedriver/chrome/download_directory_override_manager.h?q=DownloadDirectoryOverrideManager) -* [`FrameTracker`](https://source.chromium.org/chromium/chromium/src/+/master:chrome/test/chromedriver/chrome/frame_tracker.h?q=FrameTracker) -* [`GeolocationOverrideManager`](https://source.chromium.org/chromium/chromium/src/+/master:chrome/test/chromedriver/chrome/geolocation_override_manager.h?q=GeolocationOverrideManager) -* [`HeapSnapshotTaker`](https://source.chromium.org/chromium/chromium/src/+/master:chrome/test/chromedriver/chrome/heap_snapshot_taker.h?q=HeapSnapshotTaker) -* [`JavaScriptDialogManager`](https://source.chromium.org/chromium/chromium/src/+/master:chrome/test/chromedriver/chrome/javascript_dialog_manager.h?q=JavaScriptDialogManager) -* [`MobileEmulationOverrideManager`](https://source.chromium.org/chromium/chromium/src/+/master:chrome/test/chromedriver/chrome/mobile_emulation_override_manager.h?q=MobileEmulationOverrideManager) -* [`NavigationTracker`](https://source.chromium.org/chromium/chromium/src/+/master:chrome/test/chromedriver/chrome/navigation_tracker.h?q=NavigationTracker) -* [`NetworkConditionsOverrideManager`](https://source.chromium.org/chromium/chromium/src/+/master:chrome/test/chromedriver/chrome/network_conditions_override_manager.h?q=NetworkConditionsOverrideManager) -* [`PerformanceLogger`](https://source.chromium.org/chromium/chromium/src/+/master:chrome/test/chromedriver/performance_logger.h?q=PerformanceLogger) +* [`CastTracker`](https://source.chromium.org/chromium/chromium/src/+/main:chrome/test/chromedriver/chrome/cast_tracker.h?q=CastTracker) +* [`ConsoleLogger`](https://source.chromium.org/chromium/chromium/src/+/main:chrome/test/chromedriver/chrome/console_logger.h?q=ConsoleLogger) +* [`DevToolsEventsLogger`](https://source.chromium.org/chromium/chromium/src/+/main:chrome/test/chromedriver/devtools_events_logger.h?q=DevToolsEventsLogger) +* [`DomTracker`](https://source.chromium.org/chromium/chromium/src/+/main:chrome/test/chromedriver/chrome/dom_tracker.h?q=DomTracker) +* [`DownloadDirectoryOverrideManager`](https://source.chromium.org/chromium/chromium/src/+/main:chrome/test/chromedriver/chrome/download_directory_override_manager.h?q=DownloadDirectoryOverrideManager) +* [`FrameTracker`](https://source.chromium.org/chromium/chromium/src/+/main:chrome/test/chromedriver/chrome/frame_tracker.h?q=FrameTracker) +* [`GeolocationOverrideManager`](https://source.chromium.org/chromium/chromium/src/+/main:chrome/test/chromedriver/chrome/geolocation_override_manager.h?q=GeolocationOverrideManager) +* [`HeapSnapshotTaker`](https://source.chromium.org/chromium/chromium/src/+/main:chrome/test/chromedriver/chrome/heap_snapshot_taker.h?q=HeapSnapshotTaker) +* [`JavaScriptDialogManager`](https://source.chromium.org/chromium/chromium/src/+/main:chrome/test/chromedriver/chrome/javascript_dialog_manager.h?q=JavaScriptDialogManager) +* [`MobileEmulationOverrideManager`](https://source.chromium.org/chromium/chromium/src/+/main:chrome/test/chromedriver/chrome/mobile_emulation_override_manager.h?q=MobileEmulationOverrideManager) +* [`NavigationTracker`](https://source.chromium.org/chromium/chromium/src/+/main:chrome/test/chromedriver/chrome/navigation_tracker.h?q=NavigationTracker) +* [`NetworkConditionsOverrideManager`](https://source.chromium.org/chromium/chromium/src/+/main:chrome/test/chromedriver/chrome/network_conditions_override_manager.h?q=NetworkConditionsOverrideManager) +* [`PerformanceLogger`](https://source.chromium.org/chromium/chromium/src/+/main:chrome/test/chromedriver/performance_logger.h?q=PerformanceLogger) The listener description below is still incomplete. More will be added in the future. ### Navigation Tracker -The [`NavigationTracker`](https://source.chromium.org/chromium/chromium/src/+/master:chrome/test/chromedriver/chrome/navigation_tracker.h?q=NavigationTracker) +The [`NavigationTracker`](https://source.chromium.org/chromium/chromium/src/+/main:chrome/test/chromedriver/chrome/navigation_tracker.h?q=NavigationTracker) implements the [wait for navigation to complete](https://www.w3.org/TR/webdriver/#dfn-waiting-for-the-navigation-to-complete) algorithm defined by the WebDriver standard. It is used when the @@ -85,13 +85,13 @@ or [eager](https://www.w3.org/TR/webdriver/#dfn-eager-page-loading-strategy). (When the page loading strategy is [none](https://www.w3.org/TR/webdriver/#dfn-none-page-loading-strategy), -ChromeDriver uses [`NonBlockingNavigationTracker`](https://source.chromium.org/chromium/chromium/src/+/master:chrome/test/chromedriver/chrome/non_blocking_navigation_tracker.h?q=NonBlockingNavigationTracker), +ChromeDriver uses [`NonBlockingNavigationTracker`](https://source.chromium.org/chromium/chromium/src/+/main:chrome/test/chromedriver/chrome/non_blocking_navigation_tracker.h?q=NonBlockingNavigationTracker), which is not a DevTools event listener.) `NavigationTracker` keeps track of the loading state of the current browsing context (either a window/tab or a frame). The loading state is represented by -[`enum LoadingState`](https://source.chromium.org/chromium/chromium/src/+/master:chrome/test/chromedriver/chrome/page_load_strategy.h?q=LoadingState), +[`enum LoadingState`](https://source.chromium.org/chromium/chromium/src/+/main:chrome/test/chromedriver/chrome/page_load_strategy.h?q=LoadingState), and can be one of three values: `kUnknown`, `kLoading`, and `kNotLoading`. `NavigationTracker` moves the loading state between these values based on the events it receives from Chrome DevTools.
diff --git a/chrome/test/chromedriver/docs/run_javascript.md b/chrome/test/chromedriver/docs/run_javascript.md index 90efbf6..11834e33 100644 --- a/chrome/test/chromedriver/docs/run_javascript.md +++ b/chrome/test/chromedriver/docs/run_javascript.md
@@ -49,13 +49,13 @@ Selenium, to find elements on a page, to get the text displayed by a DOM element, etc. * Call one of the JavaScript function in the - [js](https://source.chromium.org/chromium/chromium/src/+/master:chrome/test/chromedriver/js/) + [js](https://source.chromium.org/chromium/chromium/src/+/main:chrome/test/chromedriver/js/) directory, e.g., to get the location of an element on the page. ## DevTools JavaScript API The Chrome DevTools provide [Runtime.evaluate -command](https://source.chromium.org/chromium/chromium/src/+/master:v8/include/js_protocol.pdl?q=command%5C%20evaluate$) +command](https://source.chromium.org/chromium/chromium/src/+/main:v8/include/js_protocol.pdl?q=command%5C%20evaluate$) for running JavaScript code. ChromeDriver uses this command to send all JavaScript code to Chrome. @@ -91,7 +91,7 @@ Runtime.evaluate returns a JSON object to the caller. This JSON object always has a property named `result`, whose value is another JSON object of -[type RemoteObject](https://source.chromium.org/chromium/chromium/src/+/master:v8/include/js_protocol.pdl?q=%22type%20RemoteObject%20%22). +[type RemoteObject](https://source.chromium.org/chromium/chromium/src/+/main:v8/include/js_protocol.pdl?q=%22type%20RemoteObject%20%22). The type of the result (e.g., string, number, object, etc) is given in the `type` property of the RemoteObject. @@ -191,7 +191,7 @@ ### Use `WebView::EvaluateScript` Method -The [`WebView::EvaluateScript`](https://source.chromium.org/chromium/chromium/src/+/master:chrome/test/chromedriver/chrome/web_view_impl.cc?q=WebViewImpl::EvaluateScript%5c%28) +The [`WebView::EvaluateScript`](https://source.chromium.org/chromium/chromium/src/+/main:chrome/test/chromedriver/chrome/web_view_impl.cc?q=WebViewImpl::EvaluateScript%5c%28) method is a thin wrapper around DevTools Runtime.evaluate command. The only additional service it provides is routing the script to the desired frame. The caller can provide a frame ID, @@ -203,10 +203,10 @@ ### Use `WebView::CallFunction` Method -The [`WebView::CallFunction`](https://source.chromium.org/chromium/chromium/src/+/master:chrome/test/chromedriver/chrome/web_view_impl.cc?q=WebViewImpl::CallFunction%5c%28) method -(and its variation [`WebView::CallFunctionWithTimeout`](https://source.chromium.org/chromium/chromium/src/+/master:chrome/test/chromedriver/chrome/web_view_impl.cc?q=WebViewImpl::CallFunctionWithTimeout%5c%28) method) +The [`WebView::CallFunction`](https://source.chromium.org/chromium/chromium/src/+/main:chrome/test/chromedriver/chrome/web_view_impl.cc?q=WebViewImpl::CallFunction%5c%28) method +(and its variation [`WebView::CallFunctionWithTimeout`](https://source.chromium.org/chromium/chromium/src/+/main:chrome/test/chromedriver/chrome/web_view_impl.cc?q=WebViewImpl::CallFunctionWithTimeout%5c%28) method) wraps the supplied JavaScript code inside -[callFunction](https://source.chromium.org/chromium/chromium/src/+/master:chrome/test/chromedriver/js/call_function.js?q=callFunction). +[callFunction](https://source.chromium.org/chromium/chromium/src/+/main:chrome/test/chromedriver/js/call_function.js?q=callFunction). It requires that the supplied JavaScript code must be a function. This method provides the following functionality: @@ -220,10 +220,10 @@ ### Use `WebView::CallUserSyncScript` Method -The [`WebView::CallUserSyncScript`](https://source.chromium.org/chromium/chromium/src/+/master:chrome/test/chromedriver/chrome/web_view_impl.cc?q=WebViewImpl::CallUserSyncScript%5c%28) +The [`WebView::CallUserSyncScript`](https://source.chromium.org/chromium/chromium/src/+/main:chrome/test/chromedriver/chrome/web_view_impl.cc?q=WebViewImpl::CallUserSyncScript%5c%28) method is used by the Execute Script command in the WebDriver API. It is responsible for wrapping the user-supplied script inside a -[function](https://source.chromium.org/chromium/chromium/src/+/master:chrome/test/chromedriver/js/execute_script.js), +[function](https://source.chromium.org/chromium/chromium/src/+/main:chrome/test/chromedriver/js/execute_script.js), before passing it to `WebView::CallFunctionWithTimeout`. This is necessary because the WebDriver standard requires that the user-supplied script is not a function, @@ -235,10 +235,10 @@ ### Use `WebView::CallUserAsyncFunction` Method -The [`WebView::CallUserAsyncFunction`](https://source.chromium.org/chromium/chromium/src/+/master:chrome/test/chromedriver/chrome/web_view_impl.cc?q=WebViewImpl::CallUserAsyncFunction%5c%28) +The [`WebView::CallUserAsyncFunction`](https://source.chromium.org/chromium/chromium/src/+/main:chrome/test/chromedriver/chrome/web_view_impl.cc?q=WebViewImpl::CallUserAsyncFunction%5c%28) method is used by the Execute Async Script command in the WebDriver API. It wraps the user-supplied script inside -[`executeAsyncScript`](https://source.chromium.org/chromium/chromium/src/+/master:chrome/test/chromedriver/js/execute_async_script.js) function, +[`executeAsyncScript`](https://source.chromium.org/chromium/chromium/src/+/main:chrome/test/chromedriver/js/execute_async_script.js) function, before passing it to `WebView::CallFunctionWithTimeout`. The [`executeAsyncScript`] function is responsible for waiting for the async script to finish, as required by the WebDriver standard.
diff --git a/chrome/test/chromedriver/docs/testing.md b/chrome/test/chromedriver/docs/testing.md index a819822..c81f95dc 100644 --- a/chrome/test/chromedriver/docs/testing.md +++ b/chrome/test/chromedriver/docs/testing.md
@@ -28,7 +28,7 @@ These tests are maintained by the ChromeDriver team, and are intended to verify that ChromeDriver works correctly with Chrome. They are written in Python script, in -[`test/run_py_tests.py`](https://source.chromium.org/chromium/chromium/src/+/master:chrome/test/chromedriver/test/run_py_tests.py). +[`test/run_py_tests.py`](https://source.chromium.org/chromium/chromium/src/+/main:chrome/test/chromedriver/test/run_py_tests.py). We run these tests on the CQ (commit queue) on all desktop platforms, and plan to run them on Android as well in the future. @@ -74,7 +74,7 @@ When running inside the CQ, the `--test-type=integration` option is passed to the `run_py_tests.py` command line. This has the following effects: * All tests listed in - [`_INTEGRATION_NEGATIVE_FILTER`](https://source.chromium.org/chromium/chromium/src/+/master:chrome/test/chromedriver/test/run_py_tests.py?q=_INTEGRATION_NEGATIVE_FILTER) + [`_INTEGRATION_NEGATIVE_FILTER`](https://source.chromium.org/chromium/chromium/src/+/main:chrome/test/chromedriver/test/run_py_tests.py?q=_INTEGRATION_NEGATIVE_FILTER) are skipped. Tests in this list should have comments indicating why they should be skipped in the CQ. * If there are a small number of test failures (no more than 10), @@ -95,7 +95,7 @@ option, where `package_name` can be one of the following values: * `chrome_stable`: normal in-box Chrome that is installed by the system. * `chrome_beta`: Beta build of Chrome. -* `chromium`: [Open source Chromium build](https://chromium.googlesource.com/chromium/src/+/master/docs/android_build_instructions.md). +* `chromium`: [Open source Chromium build](https://chromium.googlesource.com/chromium/src/+/main/docs/android_build_instructions.md). There is future plan to [run these tests in the Chromium Commit Queue](https://crbug.com/813466). @@ -111,7 +111,7 @@ We compile these tests, and store them in a special repository at https://chromium.googlesource.com/chromium/deps/webdriver/. We use a Python script -[`test/run_java_tests.py`](https://source.chromium.org/chromium/chromium/src/+/master:chrome/test/chromedriver/test/run_java_tests.py) +[`test/run_java_tests.py`](https://source.chromium.org/chromium/chromium/src/+/main:chrome/test/chromedriver/test/run_java_tests.py) to drive these tests. Before running these tests, you need to do a one-time setup with the following @@ -136,7 +136,7 @@ If there are any test cases that fail or are flaky, and you can't fix them quickly, please add the test names to one of the filters in -[`test_expectations`](https://source.chromium.org/chromium/chromium/src/+/master:chrome/test/chromedriver/test/test_expectations) +[`test_expectations`](https://source.chromium.org/chromium/chromium/src/+/main:chrome/test/chromedriver/test/test_expectations) file in the same directory as `run_java_tests.py`. ## Web Platform Tests (WPT) @@ -202,7 +202,7 @@ ## JavaScript Unit Tests All ChromeDriver JavaScript files in the -[js](https://source.chromium.org/chromium/chromium/src/+/master:chrome/test/chromedriver/js/) +[js](https://source.chromium.org/chromium/chromium/src/+/main:chrome/test/chromedriver/js/) directory have corresponding unit tests, stored in HTML files. These tests can be run in two ways:
diff --git a/chrome/test/chromedriver/docs/threading.md b/chrome/test/chromedriver/docs/threading.md index 3a48170..7db1fc9 100644 --- a/chrome/test/chromedriver/docs/threading.md +++ b/chrome/test/chromedriver/docs/threading.md
@@ -19,9 +19,9 @@ to post tasks between threads. Each thread in ChromeDriver is wrapped by a -[`base::Thread`](https://source.chromium.org/chromium/chromium/src/+/master:base/threading/thread.h?q=%22class%20BASE_EXPORT%20Thread%22) object. +[`base::Thread`](https://source.chromium.org/chromium/chromium/src/+/main:base/threading/thread.h?q=%22class%20BASE_EXPORT%20Thread%22) object. This object exposes a -[`base::TaskRunner`](https://source.chromium.org/chromium/chromium/src/+/master:base/task_runner.h?q=base::TaskRunner), +[`base::TaskRunner`](https://source.chromium.org/chromium/chromium/src/+/main:base/task_runner.h?q=base::TaskRunner), which provides the ability to post tasks to that thread.\ When thread A wants to call a function on thread B, it finds the `TaskRunner` object corresponding to thread B, and calls its `TaskRunner::PostTask` method.\ @@ -48,20 +48,20 @@ ### Process Initialization -The [`main`](https://source.chromium.org/chromium/chromium/src/+/master:chrome/test/chromedriver/server/chromedriver_server.cc?q=%22int%20main%22) +The [`main`](https://source.chromium.org/chromium/chromium/src/+/main:chrome/test/chromedriver/server/chromedriver_server.cc?q=%22int%20main%22) function runs on the command thread. After some initialization, it calls `RunServer`. -[`RunServer`](https://source.chromium.org/chromium/chromium/src/+/master:chrome/test/chromedriver/server/chromedriver_server.cc?q=RunServer) +[`RunServer`](https://source.chromium.org/chromium/chromium/src/+/main:chrome/test/chromedriver/server/chromedriver_server.cc?q=RunServer) also runs on the command thread. It does the following: * Creates the I/O thread. * Posts a task to run `StartServerOnIOThread` on the I/O thread. * Run an event loop, and waits for incoming tasks posted from other threads. The final part of initialization occurs in -[`StartServerOnIOThread`](https://source.chromium.org/chromium/chromium/src/+/master:chrome/test/chromedriver/server/chromedriver_server.cc?q=StartServerOnIOThread) +[`StartServerOnIOThread`](https://source.chromium.org/chromium/chromium/src/+/main:chrome/test/chromedriver/server/chromedriver_server.cc?q=StartServerOnIOThread) on the I/O thread. -It creates an [`HttpServer`](https://source.chromium.org/chromium/chromium/src/+/master:chrome/test/chromedriver/server/http_server.h?q=%22class%20HttpServer%22), +It creates an [`HttpServer`](https://source.chromium.org/chromium/chromium/src/+/main:chrome/test/chromedriver/server/http_server.h?q=%22class%20HttpServer%22), and then calls `HttpServer::Start` to start listening for incoming WebDriver requests. @@ -69,18 +69,18 @@ When a new request is received from a client, two things happen on the I/O thread. -* [`HttpServer::OnHttpRequest`](https://source.chromium.org/chromium/chromium/src/+/master:chrome/test/chromedriver/server/http_server.cc?q=HttpServer::OnHttpRequest) +* [`HttpServer::OnHttpRequest`](https://source.chromium.org/chromium/chromium/src/+/main:chrome/test/chromedriver/server/http_server.cc?q=HttpServer::OnHttpRequest) runs `HandleRequestOnIOThread`, which is stored in `HttpServer::handle_request_func_`. -* [`HandleRequestOnIOThread`](https://source.chromium.org/chromium/chromium/src/+/master:chrome/test/chromedriver/server/chromedriver_server.cc?q=%22void%20HandleRequestOnIOThread%22) +* [`HandleRequestOnIOThread`](https://source.chromium.org/chromium/chromium/src/+/main:chrome/test/chromedriver/server/chromedriver_server.cc?q=%22void%20HandleRequestOnIOThread%22) posts a task to run `HandleRequestOnCmdThread`. Then several activities happen on the command thread. -* [`HandleRequestOnCmdThread`](https://source.chromium.org/chromium/chromium/src/+/master:chrome/test/chromedriver/server/chromedriver_server.cc?q=%22void%20HandleRequestOnCmdThread%22) +* [`HandleRequestOnCmdThread`](https://source.chromium.org/chromium/chromium/src/+/main:chrome/test/chromedriver/server/chromedriver_server.cc?q=%22void%20HandleRequestOnCmdThread%22) verifies that the request comes from a trusted IP address. -* [`HttpHandler::Handle`](https://source.chromium.org/chromium/chromium/src/+/master:chrome/test/chromedriver/server/http_handler.cc?q=HttpHandler::Handle) +* [`HttpHandler::Handle`](https://source.chromium.org/chromium/chromium/src/+/main:chrome/test/chromedriver/server/http_handler.cc?q=HttpHandler::Handle) does some validation of the incoming request. -* [`HttpHandler::HandleCommand`](https://source.chromium.org/chromium/chromium/src/+/master:chrome/test/chromedriver/server/http_handler.cc?q=HttpHandler::HandleCommand) +* [`HttpHandler::HandleCommand`](https://source.chromium.org/chromium/chromium/src/+/main:chrome/test/chromedriver/server/http_handler.cc?q=HttpHandler::HandleCommand) matches the request against a list of commands implemented by ChromeDriver, and dispatches the request to the appropriate command handler. @@ -90,7 +90,7 @@ New session command (details below) does not target a specific session; instead it creates a new session thread for the session so that it can later be targeted by other commands. Regardless of which thread executes the command, when the command finishes, -[`HttpHandler::PrepareResponse`](https://source.chromium.org/chromium/chromium/src/+/master:chrome/test/chromedriver/server/http_handler.cc?q="void%20HttpHandler::PrepareResponse") +[`HttpHandler::PrepareResponse`](https://source.chromium.org/chromium/chromium/src/+/main:chrome/test/chromedriver/server/http_handler.cc?q="void%20HttpHandler::PrepareResponse") runs on command thread to prepare the response, and then the I/O thread sends the response back to the client. @@ -99,7 +99,7 @@ Before a client can do anything useful, it must first call the InitSession command to create a new session. This command is first dispatched to -[`ExecuteCreateSession`](https://source.chromium.org/chromium/chromium/src/+/master:chrome/test/chromedriver/commands.cc?q=ExecuteCreateSession), +[`ExecuteCreateSession`](https://source.chromium.org/chromium/chromium/src/+/main:chrome/test/chromedriver/commands.cc?q=ExecuteCreateSession), which runs on the command thread and does the following. * Generates a new session ID, which is defined by [W3C WebDriver Standard](https://www.w3.org/TR/webdriver/#dfn-session-id) @@ -108,7 +108,7 @@ to identify this session in all future requests. * Creates a new `Session` object to store session-specific data. * Creates and initializes a session thread. -* Invokes [`ExecuteInitSession`](https://source.chromium.org/chromium/chromium/src/+/master:chrome/test/chromedriver/session_commands.cc?q=ExecuteInitSession) +* Invokes [`ExecuteInitSession`](https://source.chromium.org/chromium/chromium/src/+/main:chrome/test/chromedriver/session_commands.cc?q=ExecuteInitSession) on the newly created session thread. Then the session thread is responsible for parsing the requested capabilities, @@ -117,5 +117,5 @@ ### Dispatching Command to a Session Most WebDriver protocol commands apply to a particular session. In such cases, -[`ExecuteSessionCommand`](https://source.chromium.org/chromium/chromium/src/+/master:chrome/test/chromedriver/commands.cc?q="ExecuteSessionCommand%28") +[`ExecuteSessionCommand`](https://source.chromium.org/chromium/chromium/src/+/main:chrome/test/chromedriver/commands.cc?q="ExecuteSessionCommand%28") is responsible for finding the target session thread and posting a task to it.
diff --git a/chrome/test/data/extensions/api_test/activity_log_private/PRESUBMIT.py b/chrome/test/data/extensions/api_test/activity_log_private/PRESUBMIT.py index d4ed0cea..0b74db1 100644 --- a/chrome/test/data/extensions/api_test/activity_log_private/PRESUBMIT.py +++ b/chrome/test/data/extensions/api_test/activity_log_private/PRESUBMIT.py
@@ -6,7 +6,7 @@ See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts for more details about the presubmit API built into depot_tools, and see -https://chromium.googlesource.com/chromium/src/+/master/styleguide/web/web.md +https://chromium.googlesource.com/chromium/src/+/main/styleguide/web/web.md for the rules we're checking against here. """
diff --git a/chrome/test/data/media/engagement/preload/BUILD.gn b/chrome/test/data/media/engagement/preload/BUILD.gn index f3f9634..597329be 100644 --- a/chrome/test/data/media/engagement/preload/BUILD.gn +++ b/chrome/test/data/media/engagement/preload/BUILD.gn
@@ -3,9 +3,11 @@ # found in the LICENSE file. import("//build/compiled_action.gni") +import("//build/config/python.gni") # Generates a proto file based on the real list. -action_foreach("generate_preload_list") { +# TODO(crbug.com/1112471): Get this to run cleanly under Python 3. +python2_action_foreach("generate_preload_list") { script = "//tools/media_engagement_preload/make_dafsa.py" sources = [ "test.json" ]
diff --git a/chrome/test/data/webui/cr_components/chromeos/network/sim_lock_dialogs_test.js b/chrome/test/data/webui/cr_components/chromeos/network/sim_lock_dialogs_test.js index f4c2c548..37c560fd 100644 --- a/chrome/test/data/webui/cr_components/chromeos/network/sim_lock_dialogs_test.js +++ b/chrome/test/data/webui/cr_components/chromeos/network/sim_lock_dialogs_test.js
@@ -96,7 +96,7 @@ await flushAsync(); assertEquals( simLockDialog.i18n('networkSimErrorInvalidPinPlural', 3), - unlockPinDialog.querySelector('.dialog-error').textContent.trim()); + unlockPinDialog.querySelector('.pinEntrySubtext').textContent.trim()); // Set SIM to PIN locked state with single retry left. simLockDialog.deviceState = { @@ -108,7 +108,7 @@ await flushAsync(); assertEquals( simLockDialog.i18n('networkSimErrorInvalidPin', 1), - unlockPinDialog.querySelector('.dialog-error').textContent.trim()); + unlockPinDialog.querySelector('.pinEntrySubtext').textContent.trim()); }); test(
diff --git a/chrome/test/data/webui/sandboxstatus_browsertest.js b/chrome/test/data/webui/sandboxstatus_browsertest.js index 1b7722ca..d5ce5c2 100644 --- a/chrome/test/data/webui/sandboxstatus_browsertest.js +++ b/chrome/test/data/webui/sandboxstatus_browsertest.js
@@ -25,7 +25,7 @@ // - If failures of this test are a problem on a bot under your care, // the proper way to address such failures is to install the SUID // sandbox. See: -// https://chromium.googlesource.com/chromium/src/+/master/docs/linux/suid_sandbox_development.md +// https://chromium.googlesource.com/chromium/src/+/main/docs/linux/suid_sandbox_development.md // - PLEASE DO NOT GLOBALLY DISABLE THIS TEST. GEN('#if defined(OS_LINUX) || defined(OS_CHROMEOS)'); GEN('# define MAYBE_testSUIDorNamespaceSandboxEnabled \\');
diff --git a/chrome/test/enterprise/e2e/.vpython b/chrome/test/enterprise/e2e/.vpython index 744b85c..3ad7696 100644 --- a/chrome/test/enterprise/e2e/.vpython +++ b/chrome/test/enterprise/e2e/.vpython
@@ -6,7 +6,7 @@ # running the test scripts. # # More information: -# https://chromium.googlesource.com/infra/infra/+/master/doc/users/vpython.md +# https://chromium.googlesource.com/infra/infra/+/main/doc/users/vpython.md python_version: "2.7" wheel: <
diff --git a/chrome/tools/build/README.md b/chrome/tools/build/README.md index 9d5c07da..396343e 100644 --- a/chrome/tools/build/README.md +++ b/chrome/tools/build/README.md
@@ -2,4 +2,4 @@ deployment. The main file in each platform-specific subdirectory is `FILES.cfg`. This file is interpreted by python's execfile, and the global FILES is extracted. For more details on how this file is used, see the [extraction -logic](https://source.chromium.org/chromium/chromium/tools/build/+/master:scripts/common/archive_utils.py). +logic](https://source.chromium.org/chromium/chromium/tools/build/+/main:scripts/common/archive_utils.py).
diff --git a/chrome/updater/docs/using_scoped_xpc_service_mock.md b/chrome/updater/docs/using_scoped_xpc_service_mock.md index f94f4d1d..1c1eb505 100644 --- a/chrome/updater/docs/using_scoped_xpc_service_mock.md +++ b/chrome/updater/docs/using_scoped_xpc_service_mock.md
@@ -16,7 +16,7 @@ [OCMock 3](https://ocmock.org/reference/) is an engine for creating mock objects for testing in Objective-C. A copy of version 3.1.5 is available in -[third_party/ocmock.](https://source.chromium.org/chromium/chromium/src/+/master:third_party/ocmock/) +[third_party/ocmock.](https://source.chromium.org/chromium/chromium/src/+/main:third_party/ocmock/) Note that this is several versions behind the current public release of OCMock, so some features described on OCMock's site are not present.
diff --git a/chromecast/bindings/public/mojom/OWNERS b/chromecast/bindings/public/mojom/OWNERS index 61b5e28..08850f4 100644 --- a/chromecast/bindings/public/mojom/OWNERS +++ b/chromecast/bindings/public/mojom/OWNERS
@@ -1,2 +1,2 @@ per-file *.mojom=set noparent -per-file *.mojom=file://ipc/SECURITY_OWNERS \ No newline at end of file +per-file *.mojom=file://ipc/SECURITY_OWNERS
diff --git a/chromecast/browser/android/apk/src/org/chromium/chromecast/shell/OWNERS b/chromecast/browser/android/apk/src/org/chromium/chromecast/shell/OWNERS index 89442abe..8f094e0 100644 --- a/chromecast/browser/android/apk/src/org/chromium/chromecast/shell/OWNERS +++ b/chromecast/browser/android/apk/src/org/chromium/chromecast/shell/OWNERS
@@ -1,2 +1,2 @@ per-file *.aidl=set noparent -per-file *.aidl=file://ipc/SECURITY_OWNERS \ No newline at end of file +per-file *.aidl=file://ipc/SECURITY_OWNERS
diff --git a/chromecast/resource_sizes/OWNERS b/chromecast/resource_sizes/OWNERS index 8cea670..39175d6 100644 --- a/chromecast/resource_sizes/OWNERS +++ b/chromecast/resource_sizes/OWNERS
@@ -1,2 +1,2 @@ juke@chromium.org -eliribble@chromium.org \ No newline at end of file +eliribble@chromium.org
diff --git a/chromeos/CHROMEOS_LKGM b/chromeos/CHROMEOS_LKGM index b8d3489..c8d20c1 100644 --- a/chromeos/CHROMEOS_LKGM +++ b/chromeos/CHROMEOS_LKGM
@@ -1 +1 @@ -13978.0.0 \ No newline at end of file +13980.0.0 \ No newline at end of file
diff --git a/chromeos/attestation/OWNERS b/chromeos/attestation/OWNERS index fbd86c8..d7df737 100644 --- a/chromeos/attestation/OWNERS +++ b/chromeos/attestation/OWNERS
@@ -1,3 +1,3 @@ dkrahn@chromium.org mnissler@chromium.org -bartfab@chromium.org \ No newline at end of file +bartfab@chromium.org
diff --git a/chromeos/components/OWNERS b/chromeos/components/OWNERS index 1594c6d..cebfe256 100644 --- a/chromeos/components/OWNERS +++ b/chromeos/components/OWNERS
@@ -5,4 +5,4 @@ # This is for the common case of adding or renaming files. If you're doing # structural changes, use usual OWNERS rules. -per-file BUILD.gn=* \ No newline at end of file +per-file BUILD.gn=*
diff --git a/chromeos/components/camera_app_ui/resources/strings/OWNERS b/chromeos/components/camera_app_ui/resources/strings/OWNERS index 379aa51b..a0d1e83 100644 --- a/chromeos/components/camera_app_ui/resources/strings/OWNERS +++ b/chromeos/components/camera_app_ui/resources/strings/OWNERS
@@ -1,2 +1,2 @@ # For adding or removing languages. -per-file *.grd=claudiomagni@chromium.org \ No newline at end of file +per-file *.grd=claudiomagni@chromium.org
diff --git a/chromeos/components/cdm_factory_daemon/OWNERS b/chromeos/components/cdm_factory_daemon/OWNERS index 057ad2e5..207a174 100644 --- a/chromeos/components/cdm_factory_daemon/OWNERS +++ b/chromeos/components/cdm_factory_daemon/OWNERS
@@ -1,2 +1,2 @@ jkardatzke@google.com -xhwang@chromium.org \ No newline at end of file +xhwang@chromium.org
diff --git a/chromeos/components/chromebox_for_meetings/OWNERS b/chromeos/components/chromebox_for_meetings/OWNERS index d915c5f4..9905ab4 100644 --- a/chromeos/components/chromebox_for_meetings/OWNERS +++ b/chromeos/components/chromebox_for_meetings/OWNERS
@@ -1,3 +1,3 @@ kdgwill@chromium.org pmoy@chromium.org -lasoren@chromium.org \ No newline at end of file +lasoren@chromium.org
diff --git a/chromeos/components/demo_mode_app_ui/OWNERS b/chromeos/components/demo_mode_app_ui/OWNERS index db69c0d0..2fc8ec3 100644 --- a/chromeos/components/demo_mode_app_ui/OWNERS +++ b/chromeos/components/demo_mode_app_ui/OWNERS
@@ -2,4 +2,4 @@ jacksontadie@google.com silinliu@google.com -# Internal Component: b/components/812312 \ No newline at end of file +# Internal Component: b/components/812312
diff --git a/chromeos/components/drivefs/OWNERS b/chromeos/components/drivefs/OWNERS index ab27dab..b9fd788 100644 --- a/chromeos/components/drivefs/OWNERS +++ b/chromeos/components/drivefs/OWNERS
@@ -3,4 +3,4 @@ slangley@chromium.org per-file *_mojom_traits*.*=set noparent -per-file *_mojom_traits*.*=file://ipc/SECURITY_OWNERS \ No newline at end of file +per-file *_mojom_traits*.*=file://ipc/SECURITY_OWNERS
diff --git a/chromeos/components/feature_usage/OWNERS b/chromeos/components/feature_usage/OWNERS index 4eef9ae6..896e981 100644 --- a/chromeos/components/feature_usage/OWNERS +++ b/chromeos/components/feature_usage/OWNERS
@@ -1,2 +1,2 @@ rsorokin@chromium.org -hsuregan@chromium.org \ No newline at end of file +hsuregan@chromium.org
diff --git a/chromeos/components/help_app_ui/OWNERS b/chromeos/components/help_app_ui/OWNERS index 97f2422..41728f9 100644 --- a/chromeos/components/help_app_ui/OWNERS +++ b/chromeos/components/help_app_ui/OWNERS
@@ -6,4 +6,4 @@ per-file *.mojom=set noparent per-file *.mojom=file://ipc/SECURITY_OWNERS -# Internal Component: b/components/690873 \ No newline at end of file +# Internal Component: b/components/690873
diff --git a/chromeos/components/media_app_ui/OWNERS b/chromeos/components/media_app_ui/OWNERS index 26575110..4757e11 100644 --- a/chromeos/components/media_app_ui/OWNERS +++ b/chromeos/components/media_app_ui/OWNERS
@@ -8,4 +8,4 @@ per-file *.mojom=set noparent per-file *.mojom=file://ipc/SECURITY_OWNERS -# Internal Component: b/components/562866 \ No newline at end of file +# Internal Component: b/components/562866
diff --git a/chromeos/components/multidevice/OWNERS b/chromeos/components/multidevice/OWNERS index 4bb0152..7460d5c 100644 --- a/chromeos/components/multidevice/OWNERS +++ b/chromeos/components/multidevice/OWNERS
@@ -2,4 +2,4 @@ jonmann@chromium.org khorimoto@chromium.org nohle@chromium.org -vecore@google.com \ No newline at end of file +vecore@google.com
diff --git a/chromeos/components/personalization_app/mojom/OWNERS b/chromeos/components/personalization_app/mojom/OWNERS index f8c31130..4ddafcf 100644 --- a/chromeos/components/personalization_app/mojom/OWNERS +++ b/chromeos/components/personalization_app/mojom/OWNERS
@@ -1,4 +1,4 @@ file://chromeos/assistant/OWNERS per-file *.mojom=set noparent -per-file *.mojom=file://ipc/SECURITY_OWNERS \ No newline at end of file +per-file *.mojom=file://ipc/SECURITY_OWNERS
diff --git a/chromeos/components/print_management/mojom/OWNERS b/chromeos/components/print_management/mojom/OWNERS index ec432081..ac36527f 100644 --- a/chromeos/components/print_management/mojom/OWNERS +++ b/chromeos/components/print_management/mojom/OWNERS
@@ -7,4 +7,4 @@ zentaro@chromium.org per-file *.mojom=set noparent -per-file *.mojom=file://ipc/SECURITY_OWNERS \ No newline at end of file +per-file *.mojom=file://ipc/SECURITY_OWNERS
diff --git a/chromeos/components/sensors/ash/sensor_hal_dispatcher.cc b/chromeos/components/sensors/ash/sensor_hal_dispatcher.cc index d3f809b..30919feb4 100644 --- a/chromeos/components/sensors/ash/sensor_hal_dispatcher.cc +++ b/chromeos/components/sensors/ash/sensor_hal_dispatcher.cc
@@ -74,6 +74,21 @@ base::Unretained(this))); } +base::UnguessableToken SensorHalDispatcher::GetTokenForTrustedClient() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + auto token = base::UnguessableToken::Create(); + client_token_set_.insert(token); + return token; +} + +bool SensorHalDispatcher::AuthenticateClient( + const base::UnguessableToken& token) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + return client_token_set_.find(token) != client_token_set_.end(); +} + SensorHalDispatcher::~SensorHalDispatcher() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); }
diff --git a/chromeos/components/sensors/ash/sensor_hal_dispatcher.h b/chromeos/components/sensors/ash/sensor_hal_dispatcher.h index 4f99d65..7dbdda13 100644 --- a/chromeos/components/sensors/ash/sensor_hal_dispatcher.h +++ b/chromeos/components/sensors/ash/sensor_hal_dispatcher.h
@@ -5,8 +5,11 @@ #ifndef CHROMEOS_COMPONENTS_SENSORS_ASH_SENSOR_HAL_DISPATCHER_H_ #define CHROMEOS_COMPONENTS_SENSORS_ASH_SENSOR_HAL_DISPATCHER_H_ +#include <set> + #include "base/component_export.h" #include "base/sequence_checker.h" +#include "base/unguessable_token.h" #include "chromeos/components/sensors/mojom/cros_sensor_service.mojom.h" #include "chromeos/components/sensors/mojom/sensor.mojom.h" #include "mojo/public/cpp/bindings/remote.h" @@ -37,6 +40,15 @@ // Register a sensor client's mojo remote to this dispatcher. void RegisterClient(mojo::PendingRemote<mojom::SensorHalClient> remote); + // Get a token for a trusted client, which will be used in + // |AuthenticateClient|. + base::UnguessableToken GetTokenForTrustedClient(); + + // Authenticate the client with |token|. If the caller get true in the + // callback, it can further register the client's mojo channel with + // |RegisterClient|. + bool AuthenticateClient(const base::UnguessableToken& token); + private: SensorHalDispatcher(); ~SensorHalDispatcher(); @@ -49,6 +61,8 @@ mojo::Remote<mojom::SensorHalServer> sensor_hal_server_; mojo::RemoteSet<mojom::SensorHalClient> sensor_hal_clients_; + std::set<base::UnguessableToken> client_token_set_; + SEQUENCE_CHECKER(sequence_checker_); };
diff --git a/chromeos/components/smbfs/OWNERS b/chromeos/components/smbfs/OWNERS index 657de5c..e16f7b10 100644 --- a/chromeos/components/smbfs/OWNERS +++ b/chromeos/components/smbfs/OWNERS
@@ -1,4 +1,4 @@ file://ui/file_manager/OWNERS per-file *_mojom_traits*.*=set noparent -per-file *_mojom_traits*.*=file://ipc/SECURITY_OWNERS \ No newline at end of file +per-file *_mojom_traits*.*=file://ipc/SECURITY_OWNERS
diff --git a/chromeos/cryptohome/OWNERS b/chromeos/cryptohome/OWNERS index 6edbd7b..e1627725 100644 --- a/chromeos/cryptohome/OWNERS +++ b/chromeos/cryptohome/OWNERS
@@ -1 +1 @@ -hashimoto@chromium.org \ No newline at end of file +hashimoto@chromium.org
diff --git a/chromeos/dbus/OWNERS b/chromeos/dbus/OWNERS index 3800cf0..b673b10a 100644 --- a/chromeos/dbus/OWNERS +++ b/chromeos/dbus/OWNERS
@@ -7,4 +7,4 @@ per-file *smb_provider*=zentaro@chromium.org per-file *wilco_dtc_supportd*=emaxx@chromium.org per-file *wilco_dtc_supportd*=pmarko@chromium.org -per-file *vm_plugin*=timloh@chromium.org \ No newline at end of file +per-file *vm_plugin*=timloh@chromium.org
diff --git a/chromeos/dbus/cdm_factory_daemon/OWNERS b/chromeos/dbus/cdm_factory_daemon/OWNERS index 057ad2e5..207a174 100644 --- a/chromeos/dbus/cdm_factory_daemon/OWNERS +++ b/chromeos/dbus/cdm_factory_daemon/OWNERS
@@ -1,2 +1,2 @@ jkardatzke@google.com -xhwang@chromium.org \ No newline at end of file +xhwang@chromium.org
diff --git a/chromeos/dbus/lorgnette_manager/OWNERS b/chromeos/dbus/lorgnette_manager/OWNERS index d88f079..1a7867b 100644 --- a/chromeos/dbus/lorgnette_manager/OWNERS +++ b/chromeos/dbus/lorgnette_manager/OWNERS
@@ -1 +1 @@ -file://chromeos/scanning/OWNERS \ No newline at end of file +file://chromeos/scanning/OWNERS
diff --git a/chromeos/dbus/pciguard/OWNERS b/chromeos/dbus/pciguard/OWNERS index 6e971c4..61ac656 100644 --- a/chromeos/dbus/pciguard/OWNERS +++ b/chromeos/dbus/pciguard/OWNERS
@@ -1,3 +1,3 @@ # Primary Owners jimmyxgong@chromium.org -zentaro@chromium.org \ No newline at end of file +zentaro@chromium.org
diff --git a/chromeos/dbus/typecd/OWNERS b/chromeos/dbus/typecd/OWNERS index 6e971c4..61ac656 100644 --- a/chromeos/dbus/typecd/OWNERS +++ b/chromeos/dbus/typecd/OWNERS
@@ -1,3 +1,3 @@ # Primary Owners jimmyxgong@chromium.org -zentaro@chromium.org \ No newline at end of file +zentaro@chromium.org
diff --git a/chromeos/disks/OWNERS b/chromeos/disks/OWNERS index 31b8eee..73220a8 100644 --- a/chromeos/disks/OWNERS +++ b/chromeos/disks/OWNERS
@@ -1 +1 @@ -file://ui/file_manager/OWNERS \ No newline at end of file +file://ui/file_manager/OWNERS
diff --git a/chromeos/geolocation/OWNERS b/chromeos/geolocation/OWNERS index 6faee649..2dcc458 100644 --- a/chromeos/geolocation/OWNERS +++ b/chromeos/geolocation/OWNERS
@@ -1 +1 @@ -alemate@chromium.org \ No newline at end of file +alemate@chromium.org
diff --git a/chromeos/hugepage_text/OWNERS b/chromeos/hugepage_text/OWNERS index bf7ba701..6f2d98e8 100644 --- a/chromeos/hugepage_text/OWNERS +++ b/chromeos/hugepage_text/OWNERS
@@ -2,4 +2,4 @@ cmtice@chromium.org gbiv@chromium.org manojgupta@chromium.org -tcwang@chromium.org \ No newline at end of file +tcwang@chromium.org
diff --git a/chromeos/lacros/system_idle_cache.cc b/chromeos/lacros/system_idle_cache.cc index 6058c47..213dbf31 100644 --- a/chromeos/lacros/system_idle_cache.cc +++ b/chromeos/lacros/system_idle_cache.cc
@@ -20,7 +20,7 @@ auto* lacros_service = chromeos::LacrosService::Get(); CHECK(lacros_service->IsAvailable<crosapi::mojom::IdleService>()); lacros_service->GetRemote<crosapi::mojom::IdleService>()->AddIdleInfoObserver( - receiver_.BindNewPipeAndPassRemote()); + receiver_.BindNewPipeAndPassRemoteWithVersion()); } base::TimeDelta SystemIdleCache::auto_lock_delay() const {
diff --git a/chromeos/language/OWNERS b/chromeos/language/OWNERS index 9aaf0f7e..a474a02 100644 --- a/chromeos/language/OWNERS +++ b/chromeos/language/OWNERS
@@ -1,3 +1,3 @@ claudiomagni@chromium.org dvallet@chromium.org -mlcui@google.com \ No newline at end of file +mlcui@google.com
diff --git a/chromeos/network/portal_detector/OWNERS b/chromeos/network/portal_detector/OWNERS index b528f0e..dccd40f 100644 --- a/chromeos/network/portal_detector/OWNERS +++ b/chromeos/network/portal_detector/OWNERS
@@ -1,3 +1,3 @@ achuith@chromium.org alemate@chromium.org -stevenjb@chromium.org \ No newline at end of file +stevenjb@chromium.org
diff --git a/chromeos/services/ime/decoder/system_engine.cc b/chromeos/services/ime/decoder/system_engine.cc index f0bad32c..c7cf42a 100644 --- a/chromeos/services/ime/decoder/system_engine.cc +++ b/chromeos/services/ime/decoder/system_engine.cc
@@ -114,6 +114,26 @@ mojo::PendingRemote<mojom::InputChannel> remote, const std::vector<uint8_t>& extra) { if (IsImeSupportedByDecoder(ime_spec)) { + // There can only be one client using the decoder at any time. There are two + // possible clients: NativeInputMethodEngine (for physical keyboard) and the + // XKB extension (for virtual keyboard). The XKB extension may try to + // connect the decoder even when it's not supposed to (due to race + // conditions), so we must prevent the extension from taking over the + // NativeInputMethodEngine connection. + // + // This is a hack to to determine whether a connection came from + // NativeInputMethodEngine or the extension. NativeInputMethodEngine will + // send some extra bytes, whereas the extension doesn't. Thus, we can + // prevent the extension from taking over the NativeInputMethodEngine's + // connection to the decoder. NativeInputMethodEngine will voluntarily give + // up its connection when tswitching to tablet mode, allowing the extension + // to connect again. + // TODO(b/184115850): Create a separate Mojo API for NativeInputMethodEngine + // so that we don't need to inspect `extra` to distinguish the client. + if (is_decoder_receiver_connected_ && extra.size() == 0) { + return false; + } + // Activates an IME engine via the shared library. Passing a // |ClientDelegate| for engine instance created by the shared library to // make safe calls on the client. @@ -123,9 +143,15 @@ base::BindRepeating(&SystemEngine::OnReply, base::Unretained(this))))) { decoder_channel_receiver_.Bind(std::move(receiver)); - // TODO(https://crbug.com/837156): Registry connection error handler. + is_decoder_receiver_connected_ = true; + decoder_channel_receiver_.set_disconnect_handler(base::BindOnce( + [](bool& is_decoder_receiver_connected) { + is_decoder_receiver_connected = false; + }, + std::ref(is_decoder_receiver_connected_))); return true; } + is_decoder_receiver_connected_ = false; return false; }
diff --git a/chromeos/services/ime/decoder/system_engine.h b/chromeos/services/ime/decoder/system_engine.h index 72e8429..1d4a4a82 100644 --- a/chromeos/services/ime/decoder/system_engine.h +++ b/chromeos/services/ime/decoder/system_engine.h
@@ -70,6 +70,9 @@ mojo::Receiver<mojom::InputChannel> decoder_channel_receiver_; + // Whether `decoder_channel_receiver_` is connected. + bool is_decoder_receiver_connected_ = false; + // Sequence ID for protobuf messages sent from the engine. uint64_t current_seq_id_ = 0;
diff --git a/chromeos/services/machine_learning/OWNERS b/chromeos/services/machine_learning/OWNERS index d7a074b3..e94d51f 100644 --- a/chromeos/services/machine_learning/OWNERS +++ b/chromeos/services/machine_learning/OWNERS
@@ -1,4 +1,4 @@ alanlxl@chromium.org amoylan@chromium.org honglinyu@chromium.org -martis@chromium.org \ No newline at end of file +martis@chromium.org
diff --git a/chromeos/services/tts/BUILD.gn b/chromeos/services/tts/BUILD.gn index e1fee21..02d1b3b 100644 --- a/chromeos/services/tts/BUILD.gn +++ b/chromeos/services/tts/BUILD.gn
@@ -12,6 +12,8 @@ "google_tts_stream.h", "playback_tts_stream.cc", "playback_tts_stream.h", + "tts_player.cc", + "tts_player.h", "tts_service.cc", "tts_service.h", ]
diff --git a/chromeos/services/tts/google_tts_stream.cc b/chromeos/services/tts/google_tts_stream.cc index ffa9dae..6366193 100644 --- a/chromeos/services/tts/google_tts_stream.cc +++ b/chromeos/services/tts/google_tts_stream.cc
@@ -14,6 +14,11 @@ namespace chromeos { namespace tts { +namespace { +constexpr int kDefaultSampleRate = 24000; +constexpr int kDefaultBufferSize = 512; +} // namespace + // Simple helper to bridge logging in the shared library to Chrome's logging. void HandleLibraryLogging(int severity, const char* message) { switch (severity) { @@ -41,8 +46,16 @@ GoogleTtsStream::GoogleTtsStream( TtsService* owner, - mojo::PendingReceiver<mojom::GoogleTtsStream> receiver) - : owner_(owner), stream_receiver_(this, std::move(receiver)) { + mojo::PendingReceiver<mojom::GoogleTtsStream> receiver, + mojo::PendingRemote<media::mojom::AudioStreamFactory> factory) + : owner_(owner), + stream_receiver_(this, std::move(receiver)), + tts_player_( + std::move(factory), + media::AudioParameters(media::AudioParameters::AUDIO_PCM_LOW_LATENCY, + media::CHANNEL_LAYOUT_MONO, + kDefaultSampleRate, + kDefaultBufferSize)) { bool loaded = libchrometts_.Load(kLibchromettsPath); if (!loaded) { LOG(ERROR) << "Unable to load libchrometts.so."; @@ -108,7 +121,7 @@ return; } - owner_->Play(std::move(callback)); + tts_player_.Play(std::move(callback)); is_buffering_ = true; base::ThreadTaskRunnerHandle::Get()->PostTask( @@ -118,27 +131,27 @@ } void GoogleTtsStream::Stop() { - owner_->Stop(); + tts_player_.Stop(); is_buffering_ = false; } void GoogleTtsStream::SetVolume(float volume) { - owner_->SetVolume(volume); + tts_player_.SetVolume(volume); } void GoogleTtsStream::Pause() { - owner_->Pause(); + tts_player_.Pause(); } void GoogleTtsStream::Resume() { - owner_->Resume(); + tts_player_.Resume(); } void GoogleTtsStream::ReadMoreFrames(bool is_first_buffer) { if (!is_buffering_) return; - TtsService::AudioBuffer buf; + TtsPlayer::AudioBuffer buf; buf.frames.resize(libchrometts_.GoogleTtsGetFramesInAudioBuffer()); size_t frames_in_buf = 0; const int status = @@ -150,12 +163,12 @@ buf.char_index = -1; buf.is_first_buffer = is_first_buffer; - owner_->AddAudioBuffer(std::move(buf)); + tts_player_.AddAudioBuffer(std::move(buf)); for (size_t timepoint_index = 0; timepoint_index < libchrometts_.GoogleTtsGetTimepointsCount(); timepoint_index++) { - owner_->AddExplicitTimepoint( + tts_player_.AddExplicitTimepoint( libchrometts_.GoogleTtsGetTimepointsCharIndexAtIndex(timepoint_index), base::TimeDelta::FromSecondsD( libchrometts_.GoogleTtsGetTimepointsTimeInSecsAtIndex(
diff --git a/chromeos/services/tts/google_tts_stream.h b/chromeos/services/tts/google_tts_stream.h index 7a68421..c6c88dba 100644 --- a/chromeos/services/tts/google_tts_stream.h +++ b/chromeos/services/tts/google_tts_stream.h
@@ -6,6 +6,7 @@ #define CHROMEOS_SERVICES_TTS_GOOGLE_TTS_STREAM_H_ #include "chromeos/services/tts/public/mojom/tts_service.mojom.h" +#include "chromeos/services/tts/tts_player.h" #include "library_loaders/libchrometts.h" #include "mojo/public/cpp/bindings/receiver.h" #include "mojo/public/cpp/bindings/remote.h" @@ -17,8 +18,10 @@ class GoogleTtsStream : public mojom::GoogleTtsStream { public: - GoogleTtsStream(TtsService* owner, - mojo::PendingReceiver<mojom::GoogleTtsStream> receiver); + GoogleTtsStream( + TtsService* owner, + mojo::PendingReceiver<mojom::GoogleTtsStream> receiver, + mojo::PendingRemote<media::mojom::AudioStreamFactory> factory); ~GoogleTtsStream() override; bool IsBound() const; @@ -52,6 +55,9 @@ // Whether buffering is in progress. bool is_buffering_ = false; + // Plays raw tts audio samples. + TtsPlayer tts_player_; + base::WeakPtrFactory<GoogleTtsStream> weak_factory_{this}; };
diff --git a/chromeos/services/tts/playback_tts_stream.cc b/chromeos/services/tts/playback_tts_stream.cc index cd9b49c0..f558ec9 100644 --- a/chromeos/services/tts/playback_tts_stream.cc +++ b/chromeos/services/tts/playback_tts_stream.cc
@@ -12,8 +12,11 @@ PlaybackTtsStream::PlaybackTtsStream( TtsService* owner, - mojo::PendingReceiver<mojom::PlaybackTtsStream> receiver) - : owner_(owner), stream_receiver_(this, std::move(receiver)) { + mojo::PendingReceiver<mojom::PlaybackTtsStream> receiver, + mojo::PendingRemote<media::mojom::AudioStreamFactory> factory, + const media::AudioParameters& params) + : stream_receiver_(this, std::move(receiver)), + tts_player_(std::move(factory), params) { stream_receiver_.set_disconnect_handler(base::BindOnce( [](TtsService* owner, mojo::Receiver<mojom::PlaybackTtsStream>* receiver) { @@ -32,41 +35,41 @@ } void PlaybackTtsStream::Play(PlayCallback callback) { - owner_->Play(std::move(callback)); + tts_player_.Play(std::move(callback)); // A small buffer to signal the start of the audio for this utterance. - TtsService::AudioBuffer buf; + TtsPlayer::AudioBuffer buf; buf.frames.resize(1, 0); buf.status = 1; buf.is_first_buffer = true; - owner_->AddAudioBuffer(std::move(buf)); + tts_player_.AddAudioBuffer(std::move(buf)); } void PlaybackTtsStream::SendAudioBuffer( const std::vector<float>& samples_buffer, int32_t char_index, bool is_done) { - TtsService::AudioBuffer buf; + TtsPlayer::AudioBuffer buf; buf.frames = samples_buffer; buf.status = is_done ? 0 : 1; buf.char_index = char_index; - owner_->AddAudioBuffer(std::move(buf)); + tts_player_.AddAudioBuffer(std::move(buf)); } void PlaybackTtsStream::Stop() { - owner_->Stop(); + tts_player_.Stop(); } void PlaybackTtsStream::SetVolume(float volume) { - owner_->SetVolume(volume); + tts_player_.SetVolume(volume); } void PlaybackTtsStream::Pause() { - owner_->Pause(); + tts_player_.Pause(); } void PlaybackTtsStream::Resume() { - owner_->Resume(); + tts_player_.Resume(); } } // namespace tts
diff --git a/chromeos/services/tts/playback_tts_stream.h b/chromeos/services/tts/playback_tts_stream.h index c58250e..701dc42a 100644 --- a/chromeos/services/tts/playback_tts_stream.h +++ b/chromeos/services/tts/playback_tts_stream.h
@@ -6,6 +6,7 @@ #define CHROMEOS_SERVICES_TTS_PLAYBACK_TTS_STREAM_H_ #include "chromeos/services/tts/public/mojom/tts_service.mojom.h" +#include "chromeos/services/tts/tts_player.h" #include "mojo/public/cpp/bindings/receiver.h" #include "mojo/public/cpp/bindings/remote.h" @@ -16,12 +17,19 @@ class PlaybackTtsStream : public mojom::PlaybackTtsStream { public: - PlaybackTtsStream(TtsService* owner, - mojo::PendingReceiver<mojom::PlaybackTtsStream> receiver); + PlaybackTtsStream( + TtsService* owner, + mojo::PendingReceiver<mojom::PlaybackTtsStream> receiver, + mojo::PendingRemote<media::mojom::AudioStreamFactory> factory, + const media::AudioParameters& params); ~PlaybackTtsStream() override; bool IsBound() const; + TtsPlayer* tts_player_for_testing() { return &tts_player_; } + + void FlushForTesting() { stream_receiver_.FlushForTesting(); } + private: // mojom::PlaybackTtsStream: void Play(PlayCallback callback) override; @@ -33,11 +41,11 @@ void Pause() override; void Resume() override; - // Owning service. - TtsService* owner_; - // Connection to tts in the component extension. mojo::Receiver<mojom::PlaybackTtsStream> stream_receiver_; + + // Plays raw tts audio samples. + TtsPlayer tts_player_; }; } // namespace tts
diff --git a/chromeos/services/tts/public/mojom/tts_service.mojom b/chromeos/services/tts/public/mojom/tts_service.mojom index d303e22..f43fc9e 100644 --- a/chromeos/services/tts/public/mojom/tts_service.mojom +++ b/chromeos/services/tts/public/mojom/tts_service.mojom
@@ -9,44 +9,17 @@ // The main interface to TTS engines on Chrome OS. TtsService lives in a // tts-sandboxed process. TtsEngineExtensionObserver, the other end of this // interface, in the browser process, brokers a connection between TtsService -// and the TTS engine extension through a TtsStreamFactory, but does not -// participate otherwise. -// -// Graph of audio data flow: -// -// <-component extension<----------------- -// / \ -// [Google|Playback]TtsStream TtsEventObserver -// | | -// ----------- ----------------- -// \ / -// ->TtsService-> -// <-> -// AudioOutputStream -// <-> -// AudioService +// and two possible engine types, [Google|Playback]TtsStream. interface TtsService { - // Binds a TtsStreamFactory implemented by this service. Returns an - // AudioOutputStream remote which is bound to AudioService in the browser and - // which pulls audio data for output. - BindTtsStreamFactory(pending_receiver<TtsStreamFactory> receiver, + // Binds a GoogleTtsStream received by this service. + // The remote lives in the Google tts component extension. + BindGoogleTtsStream(pending_receiver<GoogleTtsStream> receiver, pending_remote<media.mojom.AudioStreamFactory> stream_factory); -}; -// Interface to create various types of tts streams. -// -// The remote is in a component extension; the receiver is the tts service -// utility process. -interface TtsStreamFactory { - // Obtains the tts stream used by the Google tts component extension. - CreateGoogleTtsStream() => (pending_remote<GoogleTtsStream> stream); - - // Obtains the tts stream used by extensions that can perform audio generation - // and only require output services. - // See media/base/audio_parameters.h for further details on |sample_rate| and - // |buffer_size|. - CreatePlaybackTtsStream() => ( - pending_remote<PlaybackTtsStream> stream, + // Binds a PlaybackTtsStream received by this service. + // The remote lives in the Ash Chrome browser process. + BindPlaybackTtsStream(pending_receiver<PlaybackTtsStream> receiver, + pending_remote<media.mojom.AudioStreamFactory> stream_factory) => ( int32 sample_rate, int32 buffer_size); }; @@ -104,10 +77,10 @@ // Interface for a tts engine to control the TtsService's production of audio // for engines like Espeak, which send raw audio data. // -// The remote is in an extension; the receiver is the tts ervice utility -// process. The chrome.ttsEngine api uses this interface internally to produce -// audio output, but it is never directly exposed to the extension's public js -// bindings. +// The remote is in the Ash Chrome browser process; the receiver is the tts +// service utility process. The chrome.ttsEngine api uses this interface +// internally to produce audio output, but it is never directly exposed to the +// extension's public js bindings. // // Example usage: // Play() - starts playback of an utterance like 'hello world'
diff --git a/chromeos/services/tts/tts_player.cc b/chromeos/services/tts/tts_player.cc new file mode 100644 index 0000000..40e0066 --- /dev/null +++ b/chromeos/services/tts/tts_player.cc
@@ -0,0 +1,148 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chromeos/services/tts/tts_player.h" + +namespace chromeos { +namespace tts { + +TtsPlayer::TtsPlayer( + mojo::PendingRemote<media::mojom::AudioStreamFactory> factory, + const media::AudioParameters& params) + : output_device_(std::move(factory), params, this, std::string()), + task_runner_(base::ThreadTaskRunnerHandle::Get()) {} + +TtsPlayer::~TtsPlayer() = default; + +void TtsPlayer::Play( + base::OnceCallback<void(::mojo::PendingReceiver<mojom::TtsEventObserver>)> + callback) { + tts_event_observer_.reset(); + auto pending_receiver = tts_event_observer_.BindNewPipeAndPassReceiver(); + std::move(callback).Run(std::move(pending_receiver)); + + output_device_.Play(); +} + +void TtsPlayer::AddAudioBuffer(AudioBuffer buf) { + base::AutoLock al(state_lock_); + buffers_.emplace(std::move(buf)); +} + +void TtsPlayer::AddExplicitTimepoint(int char_index, base::TimeDelta delay) { + base::AutoLock al(state_lock_); + timepoints_.push({char_index, delay}); +} + +void TtsPlayer::Stop() { + base::AutoLock al(state_lock_); + StopLocked(); +} + +void TtsPlayer::SetVolume(float volume) { + output_device_.SetVolume(volume); +} + +void TtsPlayer::Pause() { + base::AutoLock al(state_lock_); + StopLocked(false /* clear_buffers */); +} + +void TtsPlayer::Resume() { + output_device_.Play(); +} + +int TtsPlayer::Render(base::TimeDelta delay, + base::TimeTicks delay_timestamp, + int prior_frames_skipped, + media::AudioBus* dest) { + size_t frames_in_buf = 0; + { + base::AutoLock al(state_lock_); + if (buffers_.empty()) + return 0; + + const AudioBuffer& buf = buffers_.front(); + + frames_in_buf = buf.frames.size(); + const float* frames = nullptr; + if (!buf.frames.empty()) + frames = &buf.frames[0]; + float* channel = dest->channel(0); + for (size_t i = 0; i < frames_in_buf; i++) + channel[i] = frames[i]; + + rendered_buffers_.push(std::move(buffers_.front())); + buffers_.pop(); + + if (!process_rendered_buffers_posted_) { + process_rendered_buffers_posted_ = true; + task_runner_->PostTask(FROM_HERE, + base::BindOnce(&TtsPlayer::ProcessRenderedBuffers, + weak_factory_.GetWeakPtr())); + } + } + + return frames_in_buf; +} + +void TtsPlayer::OnRenderError() {} + +void TtsPlayer::StopLocked(bool clear_buffers) { + output_device_.Pause(); + rendered_buffers_ = std::queue<AudioBuffer>(); + if (clear_buffers) { + buffers_ = std::queue<AudioBuffer>(); + timepoints_ = std::queue<Timepoint>(); + } +} + +void TtsPlayer::ProcessRenderedBuffers() { + base::AutoLock al(state_lock_); + process_rendered_buffers_posted_ = false; + for (; !rendered_buffers_.empty(); rendered_buffers_.pop()) { + const auto& buf = rendered_buffers_.front(); + int status = buf.status; + // Done, 0, or error, -1. + if (status <= 0) { + if (status == -1) + tts_event_observer_->OnError(); + else + tts_event_observer_->OnEnd(); + + StopLocked(); + return; + } + + if (buf.is_first_buffer) { + start_playback_time_ = base::Time::Now(); + tts_event_observer_->OnStart(); + } + + // Implicit timepoint. + if (buf.char_index != -1) + tts_event_observer_->OnTimepoint(buf.char_index); + } + + // Explicit timepoint(s). + base::TimeDelta start_to_now = base::Time::Now() - start_playback_time_; + while (!timepoints_.empty() && timepoints_.front().second <= start_to_now) { + tts_event_observer_->OnTimepoint(timepoints_.front().first); + timepoints_.pop(); + } +} + +TtsPlayer::AudioBuffer::AudioBuffer() = default; + +TtsPlayer::AudioBuffer::~AudioBuffer() = default; + +TtsPlayer::AudioBuffer::AudioBuffer(TtsPlayer::AudioBuffer&& other) { + frames.swap(other.frames); + status = other.status; + char_index = other.char_index; + is_first_buffer = other.is_first_buffer; +} + +} // namespace tts +} // namespace chromeos
diff --git a/chromeos/services/tts/tts_player.h b/chromeos/services/tts/tts_player.h new file mode 100644 index 0000000..2be71a3 --- /dev/null +++ b/chromeos/services/tts/tts_player.h
@@ -0,0 +1,102 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROMEOS_SERVICES_TTS_TTS_PLAYER_H_ +#define CHROMEOS_SERVICES_TTS_TTS_PLAYER_H_ + +#include "base/synchronization/lock.h" +#include "base/thread_annotations.h" +#include "chromeos/services/tts/public/mojom/tts_service.mojom.h" +#include "media/base/audio_renderer_sink.h" +#include "mojo/public/cpp/bindings/pending_receiver.h" +#include "mojo/public/cpp/bindings/receiver.h" +#include "mojo/public/cpp/bindings/remote.h" +#include "services/audio/public/cpp/output_device.h" + +namespace chromeos { +namespace tts { + +class TtsPlayer : public media::AudioRendererSink::RenderCallback { + public: + typedef std::pair<int, base::TimeDelta> Timepoint; + + // Helper group of state to pass from main thread to audio thread. + struct AudioBuffer { + AudioBuffer(); + ~AudioBuffer(); + AudioBuffer(const AudioBuffer& other) = delete; + AudioBuffer(AudioBuffer&& other); + + std::vector<float> frames; + int char_index = -1; + int status = 0; + bool is_first_buffer = false; + }; + + TtsPlayer(mojo::PendingRemote<media::mojom::AudioStreamFactory> factory, + const media::AudioParameters& params); + ~TtsPlayer() override; + + // Audio operations. + void Play( + base::OnceCallback<void(mojo::PendingReceiver<mojom::TtsEventObserver>)> + callback); + void AddAudioBuffer(AudioBuffer buf); + void AddExplicitTimepoint(int char_index, base::TimeDelta delay); + void Stop(); + void SetVolume(float volume); + void Pause(); + void Resume(); + + // media::AudioRendererSink::RenderCallback: + int Render(base::TimeDelta delay, + base::TimeTicks delay_timestamp, + int prior_frames_skipped, + media::AudioBus* dest) override; + void OnRenderError() override; + + private: + // Handles stopping tts. + void StopLocked(bool clear_buffers = true) + EXCLUSIVE_LOCKS_REQUIRED(state_lock_); + + // Do any processing (e.g. sending start/end events) on buffers that have just + // been rendered on the audio thread. + void ProcessRenderedBuffers(); + + // Protects access to state from main thread and audio thread. + base::Lock state_lock_; + + // Connection to send tts events. + mojo::Remote<mojom::TtsEventObserver> tts_event_observer_; + + // Outputs speech synthesis to audio. + audio::OutputDevice output_device_; + + // The queue of audio buffers to be played by the audio thread. + std::queue<AudioBuffer> buffers_ GUARDED_BY(state_lock_); + std::queue<AudioBuffer> rendered_buffers_; + + // An explicit list of increasing time delta sorted timepoints to be fired + // while rendering audio at the specified |delay| from start of audio + // playback. An AudioBuffer may contain an implicit timepoint for callers who + // specify a character index along with the audio buffer. + std::queue<Timepoint> timepoints_ GUARDED_BY(state_lock_); + + // The time at which playback of the current utterance started. + base::Time start_playback_time_; + + // Whether a task to process rendered audio buffers has been posted. + bool process_rendered_buffers_posted_ GUARDED_BY(state_lock_) = false; + + // Handles tasks posted from the audio thread, processed in the main thread. + scoped_refptr<base::SingleThreadTaskRunner> task_runner_; + + base::WeakPtrFactory<TtsPlayer> weak_factory_{this}; +}; + +} // namespace tts +} // namespace chromeos + +#endif // CHROMEOS_SERVICES_TTS_TTS_PLAYER_H_
diff --git a/chromeos/services/tts/tts_service.cc b/chromeos/services/tts/tts_service.cc index a7ca8451..1dbcd3c5 100644 --- a/chromeos/services/tts/tts_service.cc +++ b/chromeos/services/tts/tts_service.cc
@@ -7,23 +7,20 @@ #include <dlfcn.h> #include <sys/resource.h> -#include "base/files/file_util.h" -#include "chromeos/services/tts/constants.h" #include "media/base/audio_parameters.h" #include "media/base/audio_sample_types.h" -#include "services/audio/public/cpp/output_device.h" namespace chromeos { namespace tts { +// TODO: remove this once dynamic params are supported. namespace { constexpr int kDefaultSampleRate = 24000; constexpr int kDefaultBufferSize = 512; } // namespace TtsService::TtsService(mojo::PendingReceiver<mojom::TtsService> receiver) - : service_receiver_(this, std::move(receiver)), - task_runner_(base::ThreadTaskRunnerHandle::Get()) { + : service_receiver_(this, std::move(receiver)) { if (setpriority(PRIO_PROCESS, 0, -10 /* real time audio */) != 0) { PLOG(ERROR) << "Unable to request real time priority; performance will be " "impacted."; @@ -32,76 +29,26 @@ TtsService::~TtsService() = default; -void TtsService::BindTtsStreamFactory( - mojo::PendingReceiver<mojom::TtsStreamFactory> receiver, +void TtsService::BindGoogleTtsStream( + mojo::PendingReceiver<mojom::GoogleTtsStream> receiver, mojo::PendingRemote<media::mojom::AudioStreamFactory> factory) { - tts_stream_factory_receivers_.Add(this, std::move(receiver)); + google_tts_stream_ = std::make_unique<GoogleTtsStream>( + this, std::move(receiver), std::move(factory)); +} - // TODO(accessibility): make it possible to change this dynamically. Also, - // decouple TtsStreamFactory from AudioStreamFactory above into different - // calls. +void TtsService::BindPlaybackTtsStream( + mojo::PendingReceiver<mojom::PlaybackTtsStream> receiver, + mojo::PendingRemote<media::mojom::AudioStreamFactory> factory, + BindPlaybackTtsStreamCallback callback) { + // TODO(accessibility): make it possible to change this dynamically by passing + // params from extension manifest. media::AudioParameters params(media::AudioParameters::AUDIO_PCM_LOW_LATENCY, media::CHANNEL_LAYOUT_MONO, kDefaultSampleRate, kDefaultBufferSize); - output_device_ = std::make_unique<audio::OutputDevice>( - std::move(factory), params, this, std::string()); -} - -void TtsService::CreateGoogleTtsStream(CreateGoogleTtsStreamCallback callback) { - mojo::PendingRemote<mojom::GoogleTtsStream> remote; - auto receiver = remote.InitWithNewPipeAndPassReceiver(); - google_tts_stream_ = - std::make_unique<GoogleTtsStream>(this, std::move(receiver)); - std::move(callback).Run(std::move(remote)); -} - -void TtsService::CreatePlaybackTtsStream( - CreatePlaybackTtsStreamCallback callback) { - mojo::PendingRemote<mojom::PlaybackTtsStream> remote; - auto receiver = remote.InitWithNewPipeAndPassReceiver(); - playback_tts_stream_ = - std::make_unique<PlaybackTtsStream>(this, std::move(receiver)); - std::move(callback).Run(std::move(remote), kDefaultSampleRate, - kDefaultBufferSize); -} - -void TtsService::Play( - base::OnceCallback<void(::mojo::PendingReceiver<mojom::TtsEventObserver>)> - callback) { - tts_event_observer_.reset(); - auto pending_receiver = tts_event_observer_.BindNewPipeAndPassReceiver(); - std::move(callback).Run(std::move(pending_receiver)); - - output_device_->Play(); -} - -void TtsService::AddAudioBuffer(AudioBuffer buf) { - base::AutoLock al(state_lock_); - buffers_.emplace(std::move(buf)); -} - -void TtsService::AddExplicitTimepoint(int char_index, base::TimeDelta delay) { - base::AutoLock al(state_lock_); - timepoints_.push({char_index, delay}); -} - -void TtsService::Stop() { - base::AutoLock al(state_lock_); - StopLocked(); -} - -void TtsService::SetVolume(float volume) { - output_device_->SetVolume(volume); -} - -void TtsService::Pause() { - base::AutoLock al(state_lock_); - StopLocked(false /* clear_buffers */); -} - -void TtsService::Resume() { - output_device_->Play(); + playback_tts_stream_ = std::make_unique<PlaybackTtsStream>( + this, std::move(receiver), std::move(factory), params); + std::move(callback).Run(kDefaultSampleRate, kDefaultBufferSize); } void TtsService::MaybeExit() { @@ -113,96 +60,5 @@ } } -int TtsService::Render(base::TimeDelta delay, - base::TimeTicks delay_timestamp, - int prior_frames_skipped, - media::AudioBus* dest) { - size_t frames_in_buf = 0; - { - base::AutoLock al(state_lock_); - if (buffers_.empty()) - return 0; - - const AudioBuffer& buf = buffers_.front(); - - frames_in_buf = buf.frames.size(); - const float* frames = nullptr; - if (!buf.frames.empty()) - frames = &buf.frames[0]; - float* channel = dest->channel(0); - for (size_t i = 0; i < frames_in_buf; i++) - channel[i] = frames[i]; - - rendered_buffers_.push(std::move(buffers_.front())); - buffers_.pop(); - - if (!process_rendered_buffers_posted_) { - process_rendered_buffers_posted_ = true; - task_runner_->PostTask(FROM_HERE, - base::BindOnce(&TtsService::ProcessRenderedBuffers, - weak_factory_.GetWeakPtr())); - } - } - - return frames_in_buf; -} - -void TtsService::OnRenderError() {} - -void TtsService::StopLocked(bool clear_buffers) { - output_device_->Pause(); - rendered_buffers_ = std::queue<AudioBuffer>(); - if (clear_buffers) { - buffers_ = std::queue<AudioBuffer>(); - timepoints_ = std::queue<Timepoint>(); - } -} - -void TtsService::ProcessRenderedBuffers() { - base::AutoLock al(state_lock_); - process_rendered_buffers_posted_ = false; - for (; !rendered_buffers_.empty(); rendered_buffers_.pop()) { - const auto& buf = rendered_buffers_.front(); - int status = buf.status; - // Done, 0, or error, -1. - if (status <= 0) { - if (status == -1) - tts_event_observer_->OnError(); - else - tts_event_observer_->OnEnd(); - - StopLocked(); - return; - } - - if (buf.is_first_buffer) { - start_playback_time_ = base::Time::Now(); - tts_event_observer_->OnStart(); - } - - // Implicit timepoint. - if (buf.char_index != -1) - tts_event_observer_->OnTimepoint(buf.char_index); - } - - // Explicit timepoint(s). - base::TimeDelta start_to_now = base::Time::Now() - start_playback_time_; - while (!timepoints_.empty() && timepoints_.front().second <= start_to_now) { - tts_event_observer_->OnTimepoint(timepoints_.front().first); - timepoints_.pop(); - } -} - -TtsService::AudioBuffer::AudioBuffer() = default; - -TtsService::AudioBuffer::~AudioBuffer() = default; - -TtsService::AudioBuffer::AudioBuffer(TtsService::AudioBuffer&& other) { - frames.swap(other.frames); - status = other.status; - char_index = other.char_index; - is_first_buffer = other.is_first_buffer; -} - } // namespace tts } // namespace chromeos
diff --git a/chromeos/services/tts/tts_service.h b/chromeos/services/tts/tts_service.h index e5f0ef9..3cd1037 100644 --- a/chromeos/services/tts/tts_service.h +++ b/chromeos/services/tts/tts_service.h
@@ -5,65 +5,24 @@ #ifndef CHROMEOS_SERVICES_TTS_TTS_SERVICE_H_ #define CHROMEOS_SERVICES_TTS_TTS_SERVICE_H_ -#include "base/synchronization/lock.h" -#include "base/thread_annotations.h" #include "chromeos/services/tts/google_tts_stream.h" #include "chromeos/services/tts/playback_tts_stream.h" #include "chromeos/services/tts/public/mojom/tts_service.mojom.h" -#include "library_loaders/libchrometts.h" -#include "media/base/audio_renderer_sink.h" #include "mojo/public/cpp/bindings/receiver.h" #include "mojo/public/cpp/bindings/receiver_set.h" #include "mojo/public/cpp/bindings/remote.h" -namespace audio { -class OutputDevice; -} - namespace chromeos { namespace tts { -class TtsService : public mojom::TtsService, - public mojom::TtsStreamFactory, - public media::AudioRendererSink::RenderCallback { +class TtsService : public mojom::TtsService { public: - typedef std::pair<int, base::TimeDelta> Timepoint; - - // Helper group of state to pass from main thread to audio thread. - struct AudioBuffer { - AudioBuffer(); - ~AudioBuffer(); - AudioBuffer(const AudioBuffer& other) = delete; - AudioBuffer(AudioBuffer&& other); - - std::vector<float> frames; - int char_index = -1; - int status = 0; - bool is_first_buffer = false; - }; - explicit TtsService(mojo::PendingReceiver<mojom::TtsService> receiver); ~TtsService() override; - // Audio operations. - void Play( - base::OnceCallback<void(::mojo::PendingReceiver<mojom::TtsEventObserver>)> - callback); - void AddAudioBuffer(AudioBuffer buf); - void AddExplicitTimepoint(int char_index, base::TimeDelta delay); - void Stop(); - void SetVolume(float volume); - void Pause(); - void Resume(); - // Maybe exit this process. void MaybeExit(); - mojo::ReceiverSet<mojom::TtsStreamFactory>* - tts_stream_factory_receivers_for_testing() { - return &tts_stream_factory_receivers_; - } - void set_keep_process_alive_for_testing(bool value) { keep_process_alive_for_testing_ = value; } @@ -72,70 +31,29 @@ return &service_receiver_; } + PlaybackTtsStream* playback_tts_stream_for_testing() { + return playback_tts_stream_.get(); + } + // mojom::TtsService: - void BindTtsStreamFactory( - mojo::PendingReceiver<mojom::TtsStreamFactory> receiver, + void BindGoogleTtsStream( + mojo::PendingReceiver<mojom::GoogleTtsStream> receiver, mojo::PendingRemote<media::mojom::AudioStreamFactory> factory) override; - - // mojom::GoogleTtsStream: - void CreateGoogleTtsStream(CreateGoogleTtsStreamCallback callback) override; - void CreatePlaybackTtsStream( - CreatePlaybackTtsStreamCallback callback) override; - - // media::AudioRendererSink::RenderCallback: - int Render(base::TimeDelta delay, - base::TimeTicks delay_timestamp, - int prior_frames_skipped, - media::AudioBus* dest) override; - void OnRenderError() override; + void BindPlaybackTtsStream( + mojo::PendingReceiver<mojom::PlaybackTtsStream> receiver, + mojo::PendingRemote<media::mojom::AudioStreamFactory> factory, + BindPlaybackTtsStreamCallback callback) override; private: - // Handles stopping tts. - void StopLocked(bool clear_buffers = true) - EXCLUSIVE_LOCKS_REQUIRED(state_lock_); - - // Do any processing (e.g. sending start/end events) on buffers that have just - // been rendered on the audio thread. - void ProcessRenderedBuffers(); - // Connection to tts in the browser. mojo::Receiver<mojom::TtsService> service_receiver_; - // A list of active component extension tts stream factory connections. - mojo::ReceiverSet<mojom::TtsStreamFactory> tts_stream_factory_receivers_; - + // The Google text-to-speech engine. std::unique_ptr<GoogleTtsStream> google_tts_stream_; + // The active playback-based text-to-speech engine. std::unique_ptr<PlaybackTtsStream> playback_tts_stream_; - // Protects access to state from main thread and audio thread. - base::Lock state_lock_; - - // Connection to send tts events to component extension. - mojo::Remote<mojom::TtsEventObserver> tts_event_observer_; - - // Outputs speech synthesis to audio. - std::unique_ptr<audio::OutputDevice> output_device_; - - // The queue of audio buffers to be played by the audio thread. - std::queue<AudioBuffer> buffers_ GUARDED_BY(state_lock_); - std::queue<AudioBuffer> rendered_buffers_; - - // An explicit list of increasing time delta sorted timepoints to be fired - // while rendering audio at the specified |delay| from start of audio - // playback. An AudioBuffer may contain an implicit timepoint for callers who - // specify a character index along with the audio buffer. - std::queue<Timepoint> timepoints_ GUARDED_BY(state_lock_); - - // The time at which playback of the current utterance started. - base::Time start_playback_time_; - - // Whether a task to process rendered audio buffers has been posted. - bool process_rendered_buffers_posted_ GUARDED_BY(state_lock_) = false; - - // The main thread's task runner handle. - scoped_refptr<base::SingleThreadTaskRunner> task_runner_; - // Keeps this process alive for testing. bool keep_process_alive_for_testing_ = false;
diff --git a/chromeos/services/tts/tts_service_unittest.cc b/chromeos/services/tts/tts_service_unittest.cc index 77010e4..2b935f6b 100644 --- a/chromeos/services/tts/tts_service_unittest.cc +++ b/chromeos/services/tts/tts_service_unittest.cc
@@ -98,31 +98,21 @@ ~TtsServiceTest() override = default; protected: - void InitTtsStreamFactory( - mojo::Remote<mojom::TtsStreamFactory>* tts_stream_factory) { + void InitPlaybackTtsStream(mojo::Remote<mojom::PlaybackTtsStream>* stream) { // Audio stream factory is here to get a basic environment working only. // Unbind and rebind if needed. if (audio_stream_factory_.is_bound()) audio_stream_factory_.reset(); - remote_service_->BindTtsStreamFactory( - tts_stream_factory->BindNewPipeAndPassReceiver(), - audio_stream_factory_.BindNewPipeAndPassRemote()); - remote_service_.FlushForTesting(); - } + auto callback = + base::BindOnce([](int32_t sample_rate, int32_t buffer_size) { + // Do nothing. + }); - void InitPlaybackTtsStream( - mojo::Remote<mojom::PlaybackTtsStream>* playback_tts_stream) { - mojo::Remote<mojom::TtsStreamFactory> tts_stream_factory; - InitTtsStreamFactory(&tts_stream_factory); - tts_stream_factory->CreatePlaybackTtsStream(base::BindOnce( - [](mojo::Remote<mojom::PlaybackTtsStream>* playback_tts_stream, - PendingRemote<mojom::PlaybackTtsStream> stream, int32_t sample_rate, - int32_t buffer_size) { - playback_tts_stream->Bind(std::move(stream)); - }, - playback_tts_stream)); - tts_stream_factory.FlushForTesting(); + remote_service_->BindPlaybackTtsStream( + stream->BindNewPipeAndPassReceiver(), + audio_stream_factory_.BindNewPipeAndPassRemote(), std::move(callback)); + remote_service_.FlushForTesting(); } // testing::Test: @@ -135,99 +125,24 @@ mojo::Receiver<media::mojom::AudioStreamFactory> audio_stream_factory_; }; -TEST_F(TtsServiceTest, BindMultipleStreamFactories) { +TEST_F(TtsServiceTest, DisconnectPlaybackStream) { // Create the first tts stream factory and request a playback stream. - mojo::Remote<mojom::TtsStreamFactory> tts_stream_factory1; - InitTtsStreamFactory(&tts_stream_factory1); - - // Hang on to the pending remote obtained in the callback. Otherwise, it - // disconnects and the tts service tries to exit. - PendingRemote<mojom::PlaybackTtsStream> playback_remote; - tts_stream_factory1->CreatePlaybackTtsStream(base::BindOnce( - [](PendingRemote<mojom::PlaybackTtsStream>* outer_remote, - PendingRemote<mojom::PlaybackTtsStream> stream, int32_t sample_rate, - int32_t buffer_size) { *outer_remote = std::move(stream); }, - &playback_remote)); - tts_stream_factory1.FlushForTesting(); + mojo::Remote<mojom::PlaybackTtsStream> stream1; + InitPlaybackTtsStream(&stream1); // There's an active playback stream, so the tts service receiver should still // be bound. EXPECT_TRUE(service_.receiver_for_testing()->is_bound()); - auto* tts_stream_factory_receivers = - service_.tts_stream_factory_receivers_for_testing(); + // Simulate disconnecting the remote here (e.g. extension closes). + stream1.reset(); + service_.playback_tts_stream_for_testing()->FlushForTesting(); - // The receiver keeps the connection alive. - tts_stream_factory_receivers->FlushForTesting(); - EXPECT_TRUE(tts_stream_factory1.is_connected()); - - // Create the second tts stream factory and request a playback stream. - mojo::Remote<mojom::TtsStreamFactory> tts_stream_factory2; - InitTtsStreamFactory(&tts_stream_factory2); - tts_stream_factory2->CreatePlaybackTtsStream( - base::BindOnce([](PendingRemote<mojom::PlaybackTtsStream> stream, - int32_t sample_rate, int32_t buffer_size) { - // |stream| goes out of scope here and disconnects the playback stream, - // triggering tts service to exit. - })); - tts_stream_factory2.FlushForTesting(); - - // Simulate disconnecting the remotes here (e.g. extension closes). - tts_stream_factory1.reset(); - tts_stream_factory_receivers->FlushForTesting(); - EXPECT_EQ(1U, tts_stream_factory_receivers->size()); - tts_stream_factory2.reset(); - tts_stream_factory_receivers->FlushForTesting(); - EXPECT_TRUE(tts_stream_factory_receivers->empty()); - - // Finally, the tts service receiver should have been reset, indicating the + // The tts service receiver should have been reset, indicating the // process would have been exited in production. EXPECT_FALSE(service_.receiver_for_testing()->is_bound()); } -TEST_F(TtsServiceTest, BindMultipleStreamFactoriesCreateInterleaved) { - // Create two tts stream factories; then interleave their requests to create - // playback streams. - mojo::Remote<mojom::TtsStreamFactory> tts_stream_factory1; - InitTtsStreamFactory(&tts_stream_factory1); - EXPECT_TRUE(tts_stream_factory1.is_connected()); - mojo::Remote<mojom::TtsStreamFactory> tts_stream_factory2; - InitTtsStreamFactory(&tts_stream_factory2); - - // Note that "connectedness" simply means the remote has not been reset by the - // receiver and is bound to a PendingReceiver or Receiver. So, the second - // factory is "connected" even though it is only bound to a PendingReceiver - // (and not the concrete Receiver). - EXPECT_TRUE(tts_stream_factory1.is_connected()); - EXPECT_TRUE(tts_stream_factory2.is_connected()); - - // Simulate the first tts stream factory creating a playback stream. - tts_stream_factory1->CreatePlaybackTtsStream( - base::BindOnce([](PendingRemote<mojom::PlaybackTtsStream> stream, - int32_t sample_rate, int32_t buffer_size) {})); - tts_stream_factory1.FlushForTesting(); - - // The receiver keeps the connection alive. - EXPECT_TRUE(tts_stream_factory1.is_connected()); - EXPECT_TRUE(tts_stream_factory2.is_connected()); - - // Simulate the second tts stream factory creating a playback stream. - auto* tts_stream_factory_receivers = - service_.tts_stream_factory_receivers_for_testing(); - tts_stream_factory2->CreatePlaybackTtsStream( - base::BindOnce([](PendingRemote<mojom::PlaybackTtsStream> stream, - int32_t sample_rate, int32_t buffer_size) {})); - tts_stream_factory2.FlushForTesting(); - - // Simulate disconnecting the remotes here (e.g. extension closes). - tts_stream_factory1.reset(); - tts_stream_factory_receivers->FlushForTesting(); - EXPECT_EQ(1U, tts_stream_factory_receivers->size()); - tts_stream_factory2.reset(); - tts_stream_factory_receivers->FlushForTesting(); - EXPECT_TRUE(tts_stream_factory_receivers->empty()); -} - TEST_F(TtsServiceTest, BasicAudioBuffering) { mojo::Remote<mojom::PlaybackTtsStream> playback_tts_stream; InitPlaybackTtsStream(&playback_tts_stream); @@ -241,10 +156,12 @@ }, &observer)); playback_tts_stream.FlushForTesting(); + service_.playback_tts_stream_for_testing()->FlushForTesting(); auto bus = media::AudioBus::Create(1 /* channels */, 512 /* frames */); - service_.Render(base::TimeDelta::FromSeconds(0), base::TimeTicks::Now(), - 0 /* prior frames skipped */, bus.get()); + service_.playback_tts_stream_for_testing()->tts_player_for_testing()->Render( + base::TimeDelta::FromSeconds(0), base::TimeTicks::Now(), + 0 /* prior frames skipped */, bus.get()); observer.FlushForTesting(); // The playback stream pushes an empty buffer to trigger a start event. @@ -255,8 +172,9 @@ playback_tts_stream->SendAudioBuffer( std::vector<float>(), 100 /* char_index */, false /* last buffer */); playback_tts_stream.FlushForTesting(); - service_.Render(base::TimeDelta::FromSeconds(0), base::TimeTicks::Now(), - 0 /* prior frames skipped */, bus.get()); + service_.playback_tts_stream_for_testing()->tts_player_for_testing()->Render( + base::TimeDelta::FromSeconds(0), base::TimeTicks::Now(), + 0 /* prior frames skipped */, bus.get()); observer.FlushForTesting(); EXPECT_EQ(1, backing_observer.start_count); EXPECT_EQ(1U, backing_observer.char_indices.size()); @@ -268,8 +186,9 @@ playback_tts_stream->SendAudioBuffer( std::vector<float>(), 9999 /* char_index */, true /* last buffer */); playback_tts_stream.FlushForTesting(); - service_.Render(base::TimeDelta::FromSeconds(0), base::TimeTicks::Now(), - 0 /* prior frames skipped */, bus.get()); + service_.playback_tts_stream_for_testing()->tts_player_for_testing()->Render( + base::TimeDelta::FromSeconds(0), base::TimeTicks::Now(), + 0 /* prior frames skipped */, bus.get()); observer.FlushForTesting(); EXPECT_EQ(1, backing_observer.start_count); EXPECT_EQ(1U, backing_observer.char_indices.size()); @@ -291,8 +210,9 @@ playback_tts_stream.FlushForTesting(); auto bus = media::AudioBus::Create(1 /* channels */, 512 /* frames */); - service_.Render(base::TimeDelta::FromSeconds(0), base::TimeTicks::Now(), - 0 /* prior frames skipped */, bus.get()); + service_.playback_tts_stream_for_testing()->tts_player_for_testing()->Render( + base::TimeDelta::FromSeconds(0), base::TimeTicks::Now(), + 0 /* prior frames skipped */, bus.get()); observer.FlushForTesting(); // The playback stream pushes an empty buffer to trigger a start event. @@ -303,8 +223,9 @@ playback_tts_stream->SendAudioBuffer( std::vector<float>(), -1 /* char_index */, false /* last buffer */); playback_tts_stream.FlushForTesting(); - service_.Render(base::TimeDelta::FromSeconds(0), base::TimeTicks::Now(), - 0 /* prior frames skipped */, bus.get()); + service_.playback_tts_stream_for_testing()->tts_player_for_testing()->Render( + base::TimeDelta::FromSeconds(0), base::TimeTicks::Now(), + 0 /* prior frames skipped */, bus.get()); observer.FlushForTesting(); EXPECT_EQ(1, backing_observer.start_count); EXPECT_TRUE(backing_observer.char_indices.empty()); @@ -312,12 +233,19 @@ playback_tts_stream->SendAudioBuffer( std::vector<float>(), -1 /* char_index */, false /* last buffer */); - service_.AddExplicitTimepoint(100, base::TimeDelta::FromSeconds(0)); - service_.AddExplicitTimepoint(200, base::TimeDelta::FromSeconds(0)); - service_.AddExplicitTimepoint(300, base::TimeDelta::FromSeconds(0)); + service_.playback_tts_stream_for_testing() + ->tts_player_for_testing() + ->AddExplicitTimepoint(100, base::TimeDelta::FromSeconds(0)); + service_.playback_tts_stream_for_testing() + ->tts_player_for_testing() + ->AddExplicitTimepoint(200, base::TimeDelta::FromSeconds(0)); + service_.playback_tts_stream_for_testing() + ->tts_player_for_testing() + ->AddExplicitTimepoint(300, base::TimeDelta::FromSeconds(0)); playback_tts_stream.FlushForTesting(); - service_.Render(base::TimeDelta::FromSeconds(0), base::TimeTicks::Now(), - 0 /* prior frames skipped */, bus.get()); + service_.playback_tts_stream_for_testing()->tts_player_for_testing()->Render( + base::TimeDelta::FromSeconds(0), base::TimeTicks::Now(), + 0 /* prior frames skipped */, bus.get()); observer.FlushForTesting(); EXPECT_EQ(1, backing_observer.start_count); EXPECT_EQ(3U, backing_observer.char_indices.size()); @@ -329,8 +257,9 @@ playback_tts_stream->SendAudioBuffer( std::vector<float>(), 9999 /* char_index */, true /* last buffer */); playback_tts_stream.FlushForTesting(); - service_.Render(base::TimeDelta::FromSeconds(0), base::TimeTicks::Now(), - 0 /* prior frames skipped */, bus.get()); + service_.playback_tts_stream_for_testing()->tts_player_for_testing()->Render( + base::TimeDelta::FromSeconds(0), base::TimeTicks::Now(), + 0 /* prior frames skipped */, bus.get()); observer.FlushForTesting(); EXPECT_EQ(1, backing_observer.start_count); EXPECT_EQ(3U, backing_observer.char_indices.size());
diff --git a/chromeos/timezone/OWNERS b/chromeos/timezone/OWNERS index 6faee649..2dcc458 100644 --- a/chromeos/timezone/OWNERS +++ b/chromeos/timezone/OWNERS
@@ -1 +1 @@ -alemate@chromium.org \ No newline at end of file +alemate@chromium.org
diff --git a/components/arc/BUILD.gn b/components/arc/BUILD.gn index cb376e0d..c9db461 100644 --- a/components/arc/BUILD.gn +++ b/components/arc/BUILD.gn
@@ -22,8 +22,8 @@ "compat_mode/arc_resize_lock_pref_delegate.h", "compat_mode/arc_splash_screen_dialog_view.cc", "compat_mode/arc_splash_screen_dialog_view.h", - "compat_mode/resize_confirmation_dialog.cc", - "compat_mode/resize_confirmation_dialog.h", + "compat_mode/resize_confirmation_dialog_view.cc", + "compat_mode/resize_confirmation_dialog_view.h", "compat_mode/resize_toggle_menu.cc", "compat_mode/resize_toggle_menu.h", "compat_mode/resize_util.cc", @@ -428,7 +428,7 @@ "clipboard/arc_clipboard_bridge_unittest.cc", "compat_mode/arc_resize_lock_manager_unittest.cc", "compat_mode/arc_splash_screen_dialog_view_unittest.cc", - "compat_mode/resize_confirmation_dialog_unittest.cc", + "compat_mode/resize_confirmation_dialog_view_unittest.cc", "compat_mode/resize_toggle_menu_unittest.cc", "compat_mode/resize_util_unittest.cc", "crash_collector/arc_crash_collector_bridge_unittest.cc", @@ -523,6 +523,7 @@ "//ui/base/ime", "//ui/events", "//ui/events:dom_keycode_converter", + "//ui/events:test_support", "//ui/ozone", "//ui/views", "//ui/views:test_support",
diff --git a/components/arc/compat_mode/DEPS b/components/arc/compat_mode/DEPS index 53e4efa4..318ac66 100644 --- a/components/arc/compat_mode/DEPS +++ b/components/arc/compat_mode/DEPS
@@ -4,5 +4,6 @@ "+components/strings/grit/components_strings.h", "+ui/aura", "+ui/gfx", + "+ui/strings", "+ui/views", ]
diff --git a/components/arc/compat_mode/resize_confirmation_dialog.cc b/components/arc/compat_mode/resize_confirmation_dialog.cc deleted file mode 100644 index 09403ceb..0000000 --- a/components/arc/compat_mode/resize_confirmation_dialog.cc +++ /dev/null
@@ -1,112 +0,0 @@ -// Copyright 2021 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "components/arc/compat_mode/resize_confirmation_dialog.h" - -#include <memory> - -#include "base/bind.h" -#include "components/exo/wm_helper.h" -#include "components/strings/grit/components_strings.h" -#include "ui/base/l10n/l10n_util.h" -#include "ui/views/controls/button/checkbox.h" -#include "ui/views/layout/box_layout_view.h" -#include "ui/views/layout/layout_provider.h" -#include "ui/views/window/dialog_delegate.h" - -namespace arc { - -namespace { - -class ResizeConfirmationDialogDelegate : public views::DialogDelegate { - public: - ResizeConfirmationDialogDelegate(ResizeConfirmationCallback callback, - views::Checkbox* do_not_ask_checkbox) - : callback_(std::move(callback)), - do_not_ask_checkbox_(do_not_ask_checkbox) {} - ResizeConfirmationDialogDelegate(const ResizeConfirmationDialogDelegate&) = - delete; - ResizeConfirmationDialogDelegate& operator=( - const ResizeConfirmationDialogDelegate&) = delete; - ~ResizeConfirmationDialogDelegate() override = default; - - void RunCallback(bool accept) { - DCHECK(callback_); - std::move(callback_).Run(accept, do_not_ask_checkbox_->GetChecked()); - } - - private: - ResizeConfirmationCallback callback_; - const views::Checkbox* do_not_ask_checkbox_; -}; - -std::unique_ptr<views::DialogDelegate> MakeDialogDelegate( - ResizeConfirmationCallback callback, - int parent_width) { - // Setup contents. - views::LayoutProvider* provider = views::LayoutProvider::Get(); - auto contents = std::make_unique<views::BoxLayoutView>(); - contents->SetOrientation(views::BoxLayout::Orientation::kVertical); - contents->SetInsideBorderInsets( - provider->GetInsetsMetric(views::InsetsMetric::INSETS_DIALOG)); - contents->SetBetweenChildSpacing( - provider->GetDistanceMetric(views::DISTANCE_RELATED_CONTROL_VERTICAL)); - - auto* message_label = contents->AddChildView(std::make_unique<views::Label>( - l10n_util::GetStringUTF16(IDS_ASH_ARC_APP_COMPAT_RESIZE_CONFIRM_BODY), - views::style::CONTEXT_DIALOG_BODY_TEXT)); - message_label->SetHorizontalAlignment(gfx::ALIGN_LEFT); - message_label->SetMultiLine(true); - - auto* checkbox = contents->AddChildView( - std::make_unique<views::Checkbox>(l10n_util::GetStringUTF16( - IDS_ASH_ARC_APP_COMPAT_RESIZE_CONFIRM_DONT_ASK_ME))); - - // Setup delegate. - auto delegate = std::make_unique<ResizeConfirmationDialogDelegate>( - std::move(callback), checkbox); - delegate->SetContentsView(std::move(contents)); - delegate->SetShowCloseButton(false); - delegate->SetOwnedByWidget(true); - delegate->SetTitle( - l10n_util::GetStringUTF16(IDS_ASH_ARC_APP_COMPAT_RESIZE_CONFIRM_TITLE)); - delegate->SetButtonLabel( - ui::DIALOG_BUTTON_OK, - l10n_util::GetStringUTF16(IDS_ASH_ARC_APP_COMPAT_RESIZE_CONFIRM_ACCEPT)); - delegate->SetModalType(ui::MODAL_TYPE_WINDOW); - - int width = - provider->GetDistanceMetric(views::DISTANCE_MODAL_DIALOG_PREFERRED_WIDTH); - if (parent_width < width) - width = provider->GetDistanceMetric(views::DISTANCE_BUBBLE_PREFERRED_WIDTH); - - delegate->set_fixed_width(width); - - // Safe to set "Unretained" as |delegate| is owned by widget, so keeps - // alive within the life-time of the widget. - delegate->SetAcceptCallback( - base::BindOnce(&ResizeConfirmationDialogDelegate::RunCallback, - base::Unretained(delegate.get()), /*accept=*/true)); - delegate->SetCancelCallback( - base::BindOnce(&ResizeConfirmationDialogDelegate::RunCallback, - base::Unretained(delegate.get()), /*accept=*/false)); - - return delegate; -} - -} // namespace - -views::Widget* ShowResizeConfirmationDialog( - aura::Window* parent, - ResizeConfirmationCallback callback) { - // TOOD(b/183664767): Switch dialog to use exo's overlay. - auto* widget = views::DialogDelegate::CreateDialogWidget( - MakeDialogDelegate(std::move(callback), - parent ? parent->bounds().width() : 0), - exo::WMHelper::GetInstance()->GetRootWindowForNewWindows(), parent); - widget->Show(); - return widget; -} - -} // namespace arc
diff --git a/components/arc/compat_mode/resize_confirmation_dialog.h b/components/arc/compat_mode/resize_confirmation_dialog.h deleted file mode 100644 index 39e46c1..0000000 --- a/components/arc/compat_mode/resize_confirmation_dialog.h +++ /dev/null
@@ -1,34 +0,0 @@ -// Copyright 2021 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef COMPONENTS_ARC_COMPAT_MODE_RESIZE_CONFIRMATION_DIALOG_H_ -#define COMPONENTS_ARC_COMPAT_MODE_RESIZE_CONFIRMATION_DIALOG_H_ - -#include "base/callback_forward.h" - -namespace aura { -class Window; -} // namespace aura - -namespace views { -class Widget; -} // namespace views - -namespace arc { - -// Callback to notify user's confirmation for allowing to resize the app. -// If user accept it, the callback is invoked with 1st argument true. -// Otherwise, with false. -// If the user marked the "Don't ask me again", 2nd argument will be true. -using ResizeConfirmationCallback = base::OnceCallback<void(bool, bool)>; - -// Shows confirmation dialog for asking user if really want to perform resize -// operation for the resize-locked ARC app. -views::Widget* ShowResizeConfirmationDialog( - aura::Window* parent, - ResizeConfirmationCallback callback); - -} // namespace arc - -#endif // COMPONENTS_ARC_COMPAT_MODE_RESIZE_CONFIRMATION_DIALOG_H_
diff --git a/components/arc/compat_mode/resize_confirmation_dialog_unittest.cc b/components/arc/compat_mode/resize_confirmation_dialog_unittest.cc deleted file mode 100644 index a259dd2..0000000 --- a/components/arc/compat_mode/resize_confirmation_dialog_unittest.cc +++ /dev/null
@@ -1,29 +0,0 @@ -// Copyright 2021 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "components/arc/compat_mode/resize_confirmation_dialog.h" - -#include "base/callback_helpers.h" -#include "components/exo/test/exo_test_base_views.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "ui/views/layout/layout_provider.h" - -namespace arc { -namespace { - -using ResizeConfirmationDialogTest = exo::test::ExoTestBaseViews; - -// Test that ShowResizeConfirmationDialog does not crash -TEST_F(ResizeConfirmationDialogTest, ShowAndCloseDialog) { - // A LayoutProvider must exist in scope in order to set up views. - views::LayoutProvider layout_provider; - - auto* widget = ShowResizeConfirmationDialog(nullptr, base::DoNothing()); - RunPendingMessages(); - widget->Close(); - RunPendingMessages(); -} - -} // namespace -} // namespace arc
diff --git a/components/arc/compat_mode/resize_confirmation_dialog_view.cc b/components/arc/compat_mode/resize_confirmation_dialog_view.cc new file mode 100644 index 0000000..db17fe62 --- /dev/null +++ b/components/arc/compat_mode/resize_confirmation_dialog_view.cc
@@ -0,0 +1,166 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/arc/compat_mode/resize_confirmation_dialog_view.h" + +#include <memory> + +#include "base/bind.h" +#include "components/exo/shell_surface_base.h" +#include "components/exo/shell_surface_util.h" +#include "components/strings/grit/components_strings.h" +#include "ui/base/l10n/l10n_util.h" +#include "ui/strings/grit/ui_strings.h" +#include "ui/views/background.h" +#include "ui/views/bubble/bubble_border.h" +#include "ui/views/controls/button/checkbox.h" +#include "ui/views/controls/button/md_text_button.h" +#include "ui/views/layout/flex_layout_view.h" +#include "ui/views/layout/layout_provider.h" + +namespace arc { + +namespace { + +std::unique_ptr<views::View> MakeOverlayDialogContainerView( + std::unique_ptr<views::View> dialog_view) { + constexpr SkColor kScrimColor = SkColorSetA(gfx::kGoogleGrey900, 0x99); + + auto container = views::Builder<views::FlexLayoutView>() + .SetInteriorMargin(gfx::Insets(0, 32)) + .SetMainAxisAlignment(views::LayoutAlignment::kCenter) + .SetCrossAxisAlignment(views::LayoutAlignment::kCenter) + .SetBackground(views::CreateSolidBackground(kScrimColor)) + .Build(); + dialog_view->SetProperty( + views::kFlexBehaviorKey, + views::FlexSpecification(views::MinimumFlexSizeRule::kScaleToZero)); + + container->AddChildView(std::move(dialog_view)); + + return container; +} + +} // namespace + +ResizeConfirmationDialogView::ResizeConfirmationDialogView( + ResizeConfirmationCallback callback) + : callback_(std::move(callback)) { + views::LayoutProvider* provider = views::LayoutProvider::Get(); + SetOrientation(views::BoxLayout::Orientation::kVertical); + SetMainAxisAlignment(views::BoxLayout::MainAxisAlignment::kStart); + SetInsideBorderInsets(gfx::Insets(24, 24, 20, 24)); + SetBetweenChildSpacing( + provider->GetDistanceMetric(views::DISTANCE_RELATED_CONTROL_VERTICAL)); + + constexpr int kCornerRadius = 12; + auto border = std::make_unique<views::BubbleBorder>( + views::BubbleBorder::NONE, views::BubbleBorder::STANDARD_SHADOW, + GetNativeTheme()->GetSystemColor( + ui::NativeTheme::kColorId_DialogBackground)); + border->SetCornerRadius(kCornerRadius); + SetBackground(std::make_unique<views::BubbleBackground>(border.get())); + SetBorder(std::move(border)); + + AddChildView( + views::Builder<views::Label>() + .SetText(l10n_util::GetStringUTF16( + IDS_ASH_ARC_APP_COMPAT_RESIZE_CONFIRM_TITLE)) + .SetTextContext(views::style::CONTEXT_DIALOG_TITLE) + .SetMultiLine(true) + .SetHorizontalAlignment(gfx::ALIGN_LEFT) + .SetAllowCharacterBreak(true) + .SetFontList(views::style::GetFont( + views::style::TextContext::CONTEXT_DIALOG_TITLE, + views::style::TextStyle::STYLE_PRIMARY) + .DeriveWithWeight(gfx::Font::Weight::MEDIUM)) + .Build()); + + AddChildView(MakeContentsView()); + AddChildView(MakeButtonsView()); +} + +ResizeConfirmationDialogView::~ResizeConfirmationDialogView() = default; + +gfx::Size ResizeConfirmationDialogView::CalculatePreferredSize() const { + gfx::Size size = views::View::CalculatePreferredSize(); + + views::LayoutProvider* provider = views::LayoutProvider::Get(); + size.set_width(provider->GetDistanceMetric( + views::DistanceMetric::DISTANCE_MODAL_DIALOG_PREFERRED_WIDTH)); + return size; +} + +std::unique_ptr<views::View> ResizeConfirmationDialogView::MakeContentsView() { + return views::Builder<views::BoxLayoutView>() + .SetOrientation(views::BoxLayout::Orientation::kVertical) + .SetBetweenChildSpacing(19) + .SetProperty(views::kMarginsKey, gfx::Insets(0, 0, 23, 0)) + .AddChildren( + {views::Builder<views::Label>() + .SetText(l10n_util::GetStringUTF16( + IDS_ASH_ARC_APP_COMPAT_RESIZE_CONFIRM_BODY)) + .SetTextContext(views::style::CONTEXT_DIALOG_BODY_TEXT) + .SetHorizontalAlignment(gfx::ALIGN_LEFT) + .SetMultiLine(true), + views::Builder<views::Checkbox>() + .CopyAddressTo(&do_not_ask_checkbox_) + .SetText(l10n_util::GetStringUTF16( + IDS_ASH_ARC_APP_COMPAT_RESIZE_CONFIRM_DONT_ASK_ME))}) + .Build(); +} + +std::unique_ptr<views::View> ResizeConfirmationDialogView::MakeButtonsView() { + views::LayoutProvider* provider = views::LayoutProvider::Get(); + return views::Builder<views::BoxLayoutView>() + .SetOrientation(views::BoxLayout::Orientation::kHorizontal) + .SetMainAxisAlignment(views::BoxLayout::MainAxisAlignment::kEnd) + .SetBetweenChildSpacing(provider->GetDistanceMetric( + views::DistanceMetric::DISTANCE_RELATED_BUTTON_HORIZONTAL)) + .AddChildren({views::Builder<views::MdTextButton>() // Cancel button. + .CopyAddressTo(&cancel_button_) + .SetCallback(base::BindRepeating( + &ResizeConfirmationDialogView::OnButtonClicked, + base::Unretained(this), false)) + .SetText(l10n_util::GetStringUTF16(IDS_APP_CANCEL)) + .SetProminent(false) + .SetIsDefault(false), + views::Builder<views::MdTextButton>() // Accept button. + .CopyAddressTo(&accept_button_) + .SetCallback(base::BindRepeating( + &ResizeConfirmationDialogView::OnButtonClicked, + base::Unretained(this), true)) + .SetText(l10n_util::GetStringUTF16( + IDS_ASH_ARC_APP_COMPAT_RESIZE_CONFIRM_ACCEPT)) + .SetProminent(true) + .SetIsDefault(true)}) + .Build(); +} + +void ResizeConfirmationDialogView::OnButtonClicked(bool accept) { + DCHECK(callback_); + std::move(callback_).Run(accept, do_not_ask_checkbox_->GetChecked()); +} + +void ShowResizeConfirmationDialog(aura::Window* parent, + ResizeConfirmationCallback callback) { + auto* shell_surface_base = exo::GetShellSurfaceBaseForWindow(parent); + if (!shell_surface_base || shell_surface_base->HasOverlay()) + return; + + auto remove_overlay = base::BindOnce( + [](aura::Window* window) { + auto* shell_surface_base = exo::GetShellSurfaceBaseForWindow(window); + if (shell_surface_base && shell_surface_base->HasOverlay()) + shell_surface_base->RemoveOverlay(); + }, + base::Unretained(parent)); + exo::ShellSurfaceBase::OverlayParams params(MakeOverlayDialogContainerView( + std::make_unique<ResizeConfirmationDialogView>( + std::move(callback).Then(std::move(remove_overlay))))); + params.translucent = true; + shell_surface_base->AddOverlay(std::move(params)); +} + +} // namespace arc
diff --git a/components/arc/compat_mode/resize_confirmation_dialog_view.h b/components/arc/compat_mode/resize_confirmation_dialog_view.h new file mode 100644 index 0000000..d0b36a3 --- /dev/null +++ b/components/arc/compat_mode/resize_confirmation_dialog_view.h
@@ -0,0 +1,73 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_ARC_COMPAT_MODE_RESIZE_CONFIRMATION_DIALOG_VIEW_H_ +#define COMPONENTS_ARC_COMPAT_MODE_RESIZE_CONFIRMATION_DIALOG_VIEW_H_ + +#include "base/callback_forward.h" +#include "ui/views/layout/box_layout_view.h" + +namespace aura { +class Window; +} // namespace aura + +namespace views { +class MdTextButton; +class Checkbox; +} // namespace views + +namespace arc { + +// Callback to notify user's confirmation for allowing to resize the app. +// If user accept it, the callback is invoked with 1st argument true. +// Otherwise, with false. +// If the user marked the "Don't ask me again", 2nd argument will be true. +using ResizeConfirmationCallback = base::OnceCallback<void(bool, bool)>; + +class ResizeConfirmationDialogView : public views::BoxLayoutView { + public: + // TestApi is used only in tests to get internal views. + class TestApi { + public: + explicit TestApi(ResizeConfirmationDialogView* view) : view_(view) {} + + views::MdTextButton* accept_button() const { return view_->accept_button_; } + views::MdTextButton* cancel_button() const { return view_->cancel_button_; } + views::Checkbox* do_not_ask_checkbox() const { + return view_->do_not_ask_checkbox_; + } + + private: + ResizeConfirmationDialogView* const view_; + }; + + explicit ResizeConfirmationDialogView(ResizeConfirmationCallback callback); + ResizeConfirmationDialogView(const ResizeConfirmationDialogView&) = delete; + ResizeConfirmationDialogView& operator=(const ResizeConfirmationDialogView&) = + delete; + ~ResizeConfirmationDialogView() override; + + gfx::Size CalculatePreferredSize() const override; + + private: + std::unique_ptr<views::View> MakeContentsView(); + std::unique_ptr<views::View> MakeButtonsView(); + + void OnButtonClicked(bool accept); + + ResizeConfirmationCallback callback_; + + views::Checkbox* do_not_ask_checkbox_{nullptr}; + views::MdTextButton* accept_button_{nullptr}; + views::MdTextButton* cancel_button_{nullptr}; +}; + +// Shows confirmation dialog for asking user if really want to perform resize +// operation for the resize-locked ARC app. +void ShowResizeConfirmationDialog(aura::Window* parent, + ResizeConfirmationCallback callback); + +} // namespace arc + +#endif // COMPONENTS_ARC_COMPAT_MODE_RESIZE_CONFIRMATION_DIALOG_VIEW_H_
diff --git a/components/arc/compat_mode/resize_confirmation_dialog_view_unittest.cc b/components/arc/compat_mode/resize_confirmation_dialog_view_unittest.cc new file mode 100644 index 0000000..75a486c --- /dev/null +++ b/components/arc/compat_mode/resize_confirmation_dialog_view_unittest.cc
@@ -0,0 +1,109 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/arc/compat_mode/resize_confirmation_dialog_view.h" + +#include <memory> + +#include "base/bind.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "ui/events/base_event_utils.h" +#include "ui/events/test/event_generator.h" +#include "ui/views/controls/button/checkbox.h" +#include "ui/views/controls/button/md_text_button.h" +#include "ui/views/layout/layout_provider.h" +#include "ui/views/test/views_test_base.h" +#include "ui/views/widget/widget_utils.h" + +namespace arc { +namespace { + +class ResizeConfirmationDialogViewTest : public views::ViewsTestBase { + public: + // views::ViewsTestBase: + void SetUp() override { + views::ViewsTestBase::SetUp(); + widget_ = CreateTestWidget(); + widget_->SetBounds(gfx::Rect(800, 800)); + dialog_view_ = + widget_->SetContentsView(std::make_unique<ResizeConfirmationDialogView>( + base::BindOnce(&ResizeConfirmationDialogViewTest::OnClicked, + base::Unretained(this)))); + widget_->Show(); + } + + void TearDown() override { + widget_->Close(); + widget_.reset(); + views::ViewsTestBase::TearDown(); + } + + protected: + void ClickDialogButton(bool accept, bool with_checkbox) { + ResizeConfirmationDialogView::TestApi dialog_view_test(dialog_view_); + if (with_checkbox) + dialog_view_test.do_not_ask_checkbox()->SetChecked(true); + + auto* target_button = accept ? dialog_view_test.accept_button() + : dialog_view_test.cancel_button(); + + ui::test::EventGenerator event_generator(GetRootWindow(widget_.get())); + event_generator.MoveMouseTo( + target_button->GetBoundsInScreen().CenterPoint()); + event_generator.ClickLeftButton(); + } + + bool callback_called() { return callback_called_; } + bool callback_accepted() { return callback_accepted_; } + bool callback_do_not_ask_again() { return callback_do_not_ask_again_; } + + private: + void OnClicked(bool accepted, bool do_not_ask_again) { + callback_called_ = true; + callback_accepted_ = accepted; + callback_do_not_ask_again_ = do_not_ask_again; + } + + // For callback checks. + bool callback_called_{false}; + bool callback_accepted_{false}; + bool callback_do_not_ask_again_{false}; + + // A LayoutProvider must exist in scope in order to set up views. + views::LayoutProvider layout_provider; + + ResizeConfirmationDialogView* dialog_view_; + std::unique_ptr<views::Widget> widget_; +}; + +TEST_F(ResizeConfirmationDialogViewTest, ClickAcceptWithCheckbox) { + ClickDialogButton(/*accept=*/true, /*with_checkbox=*/true); + EXPECT_TRUE(callback_called()); + EXPECT_TRUE(callback_accepted()); + EXPECT_TRUE(callback_do_not_ask_again()); +} + +TEST_F(ResizeConfirmationDialogViewTest, ClickCancelWithCheckbox) { + ClickDialogButton(/*accept=*/false, /*with_checkbox=*/true); + EXPECT_TRUE(callback_called()); + EXPECT_FALSE(callback_accepted()); + EXPECT_TRUE(callback_do_not_ask_again()); +} + +TEST_F(ResizeConfirmationDialogViewTest, ClickAcceptWithoutCheckbox) { + ClickDialogButton(/*accept=*/true, /*with_checkbox=*/false); + EXPECT_TRUE(callback_called()); + EXPECT_TRUE(callback_accepted()); + EXPECT_FALSE(callback_do_not_ask_again()); +} + +TEST_F(ResizeConfirmationDialogViewTest, ClickCancelWithoutCheckbox) { + ClickDialogButton(/*accept=*/false, /*with_checkbox=*/false); + EXPECT_TRUE(callback_called()); + EXPECT_FALSE(callback_accepted()); + EXPECT_FALSE(callback_do_not_ask_again()); +} + +} // namespace +} // namespace arc
diff --git a/components/arc/compat_mode/resize_util.cc b/components/arc/compat_mode/resize_util.cc index 37f289a..ddfbf9e0 100644 --- a/components/arc/compat_mode/resize_util.cc +++ b/components/arc/compat_mode/resize_util.cc
@@ -9,7 +9,7 @@ #include "ash/public/cpp/window_properties.h" #include "base/callback_forward.h" #include "components/arc/compat_mode/arc_resize_lock_pref_delegate.h" -#include "components/arc/compat_mode/resize_confirmation_dialog.h" +#include "components/arc/compat_mode/resize_confirmation_dialog_view.h" #include "ui/aura/window.h" #include "ui/views/widget/widget.h"
diff --git a/components/arc/compat_mode/resize_util_unittest.cc b/components/arc/compat_mode/resize_util_unittest.cc index 6acc335..886d46a1 100644 --- a/components/arc/compat_mode/resize_util_unittest.cc +++ b/components/arc/compat_mode/resize_util_unittest.cc
@@ -16,7 +16,6 @@ #include "ui/aura/window.h" #include "ui/views/test/widget_test.h" #include "ui/views/widget/widget.h" -#include "ui/views/window/dialog_delegate.h" namespace arc { namespace { @@ -56,20 +55,6 @@ class ResizeUtilTest : public exo::test::ExoTestBaseViews { public: - void AcceptChildDialog(views::Widget* parent_widget) { - auto* dialog_widget = GetChildDialogWidget(parent_widget); - views::test::WidgetDestroyedWaiter waiter(dialog_widget); - DialogDelegateFor(dialog_widget)->AcceptDialog(); - waiter.Wait(); - } - - void CancelChildDialog(views::Widget* parent_widget) { - auto* dialog_widget = GetChildDialogWidget(parent_widget); - views::test::WidgetDestroyedWaiter waiter(dialog_widget); - DialogDelegateFor(dialog_widget)->CancelDialog(); - waiter.Wait(); - } - // Overridden from test::Test. void SetUp() override { exo::test::ExoTestBaseViews::SetUp(); @@ -82,18 +67,6 @@ views::Widget* widget() { return widget_.get(); } private: - views::DialogDelegate* DialogDelegateFor(views::Widget* widget) { - auto* delegate = widget->widget_delegate()->AsDialogDelegate(); - return delegate; - } - - views::Widget* GetChildDialogWidget(views::Widget* widget) { - std::set<views::Widget*> child_widgets; - views::Widget::GetAllOwnedWidgets(widget->GetNativeView(), &child_widgets); - DCHECK_EQ(1u, child_widgets.size()); - return *child_widgets.begin(); - } - TestArcResizeLockPrefDelegate pref_delegate_; std::unique_ptr<views::Widget> widget_; }; @@ -103,25 +76,11 @@ TEST_F(ResizeUtilTest, TestResizeToPhone) { widget()->Maximize(); - // Test the widget is resized if accepted the confirmation dialog. + // Test the widget is NOT resized immediately if the confirmation dialog is + // needed. pref_delegate()->SetResizeLockNeedsConfirmation(kTestAppId, true); ResizeToPhoneWithConfirmationIfNeeded(widget(), pref_delegate()); EXPECT_TRUE(widget()->IsMaximized()); - AcceptChildDialog(widget()); - EXPECT_FALSE(widget()->IsMaximized()); - EXPECT_LT(widget()->GetWindowBoundsInScreen().width(), - widget()->GetWindowBoundsInScreen().height()); - - widget()->Maximize(); - - // Test the widget is NOT resized if cancelled the confirmation dialog. - pref_delegate()->SetResizeLockNeedsConfirmation(kTestAppId, true); - ResizeToPhoneWithConfirmationIfNeeded(widget(), pref_delegate()); - EXPECT_TRUE(widget()->IsMaximized()); - CancelChildDialog(widget()); - EXPECT_TRUE(widget()->IsMaximized()); - - widget()->Maximize(); // Test the widget is resized without confirmation. pref_delegate()->SetResizeLockNeedsConfirmation(kTestAppId, false); @@ -137,25 +96,11 @@ TEST_F(ResizeUtilTest, TestResizeToTablet) { widget()->Maximize(); - // Test the widget is resized if accepted the confirmation dialog. + // Test the widget is NOT resized immediately if the confirmation dialog is + // needed. pref_delegate()->SetResizeLockNeedsConfirmation(kTestAppId, true); ResizeToTabletWithConfirmationIfNeeded(widget(), pref_delegate()); EXPECT_TRUE(widget()->IsMaximized()); - AcceptChildDialog(widget()); - EXPECT_FALSE(widget()->IsMaximized()); - EXPECT_GT(widget()->GetWindowBoundsInScreen().width(), - widget()->GetWindowBoundsInScreen().height()); - - widget()->Maximize(); - - // Test the widget is NOT resized if cancelled the confirmation dialog. - pref_delegate()->SetResizeLockNeedsConfirmation(kTestAppId, true); - ResizeToTabletWithConfirmationIfNeeded(widget(), pref_delegate()); - EXPECT_TRUE(widget()->IsMaximized()); - CancelChildDialog(widget()); - EXPECT_TRUE(widget()->IsMaximized()); - - widget()->Maximize(); // Test the widget is resized without confirmation. pref_delegate()->SetResizeLockNeedsConfirmation(kTestAppId, false); @@ -171,23 +116,11 @@ TEST_F(ResizeUtilTest, TestResizeToDesktop) { widget()->Restore(); - // Test the widget is resized if accepted the confirmation dialog. + // Test the widget is NOT resized immediately if the confirmation dialog is + // needed. pref_delegate()->SetResizeLockNeedsConfirmation(kTestAppId, true); ResizeToDesktopWithConfirmationIfNeeded(widget(), pref_delegate()); EXPECT_FALSE(widget()->IsMaximized()); - AcceptChildDialog(widget()); - EXPECT_TRUE(widget()->IsMaximized()); - - widget()->Restore(); - - // Test the widget is NOT resized if cancelled the confirmation dialog. - pref_delegate()->SetResizeLockNeedsConfirmation(kTestAppId, true); - ResizeToDesktopWithConfirmationIfNeeded(widget(), pref_delegate()); - EXPECT_FALSE(widget()->IsMaximized()); - CancelChildDialog(widget()); - EXPECT_FALSE(widget()->IsMaximized()); - - widget()->Restore(); // Test the widget is resized without confirmation. pref_delegate()->SetResizeLockNeedsConfirmation(kTestAppId, false);
diff --git a/components/autofill/core/browser/address_profile_save_manager_unittest.cc b/components/autofill/core/browser/address_profile_save_manager_unittest.cc index 21e5060..edeee49 100644 --- a/components/autofill/core/browser/address_profile_save_manager_unittest.cc +++ b/components/autofill/core/browser/address_profile_save_manager_unittest.cc
@@ -37,6 +37,10 @@ "Autofill.ProfileImport.NewProfileDecision"; constexpr char kProfileUpdateDecisionHistogram[] = "Autofill.ProfileImport.UpdateProfileDecision"; +constexpr char kNewProfileNumberOfEditsHistogram[] = + "Autofill.ProfileImport.NewProfileNumberOfEditedFields"; +constexpr char kProfileUpdateNumberOfEditsHistogram[] = + "Autofill.ProfileImport.UpdateProfileNumberOfEditedFields"; class MockPersonalDataManager : public TestPersonalDataManager { public: @@ -260,31 +264,45 @@ } else { DCHECK(!is_new_profile || !is_confirmable_merge); - const std::string changed_decision_histo = + const std::string affected_decision_histo = is_new_profile ? kNewProfileDecisionHistogram : kProfileUpdateDecisionHistogram; - const std::string unchanged_decision_histo = + const std::string unaffected_decision_histo = !is_new_profile ? kNewProfileDecisionHistogram : kProfileUpdateDecisionHistogram; - const std::string changed_edits_histo = is_new_profile - ? kNewProfileEditsHistogram - : kProfileUpdateEditsHistogram; - const std::string unchanged_edits_histo = + const std::string affected_edits_histo = is_new_profile + ? kNewProfileEditsHistogram + : kProfileUpdateEditsHistogram; + const std::string unaffected_edits_histo = !is_new_profile ? kNewProfileEditsHistogram : kProfileUpdateEditsHistogram; - histogram_tester.ExpectTotalCount(unchanged_decision_histo, 0); - histogram_tester.ExpectTotalCount(unchanged_edits_histo, 0); + const std::string affected_number_of_edits_histo = + is_new_profile ? kNewProfileNumberOfEditsHistogram + : kProfileUpdateNumberOfEditsHistogram; + const std::string unaffected_number_of_edits_histo = + !is_new_profile ? kNewProfileNumberOfEditsHistogram + : kProfileUpdateNumberOfEditsHistogram; - histogram_tester.ExpectUniqueSample(changed_decision_histo, + histogram_tester.ExpectTotalCount(unaffected_decision_histo, 0); + histogram_tester.ExpectTotalCount(unaffected_edits_histo, 0); + + histogram_tester.ExpectUniqueSample(affected_decision_histo, test_scenario.user_decision, 1); histogram_tester.ExpectTotalCount( - changed_edits_histo, + affected_edits_histo, test_scenario.expected_edited_types_for_metrics.size()); for (auto edited_type : test_scenario.expected_edited_types_for_metrics) { - histogram_tester.ExpectBucketCount(changed_edits_histo, edited_type, 1); + histogram_tester.ExpectBucketCount(affected_edits_histo, edited_type, 1); + } + + if (test_scenario.user_decision == UserDecision::kEditAccepted) { + histogram_tester.ExpectUniqueSample( + affected_number_of_edits_histo, + test_scenario.expected_edited_types_for_metrics.size(), 1); + histogram_tester.ExpectTotalCount(unaffected_number_of_edits_histo, 0); } }
diff --git a/components/autofill/core/browser/autofill_metrics.cc b/components/autofill/core/browser/autofill_metrics.cc index b7bbf2d..1b58ed5 100644 --- a/components/autofill/core/browser/autofill_metrics.cc +++ b/components/autofill/core/browser/autofill_metrics.cc
@@ -2689,6 +2689,18 @@ decision); } +void AutofillMetrics::LogNewProfileEditedType(ServerFieldType edited_type) { + base::UmaHistogramEnumeration("Autofill.ProfileImport.NewProfileEditedType", + ConvertEditedFieldTypeForMetrics(edited_type)); +} + +void AutofillMetrics::LogNewProfileNumberOfEditedFields( + int number_of_edited_fields) { + base::UmaHistogramExactLinear( + "Autofill.ProfileImport.NewProfileNumberOfEditedFields", + number_of_edited_fields, /*exclusive_max=*/15); +} + void AutofillMetrics::LogProfileUpdateImportDecision( AutofillClient::SaveAddressProfileOfferUserDecision decision) { base::UmaHistogramEnumeration("Autofill.ProfileImport.UpdateProfileDecision", @@ -2701,9 +2713,11 @@ ConvertEditedFieldTypeForMetrics(edited_type)); } -void AutofillMetrics::LogNewProfileEditedType(ServerFieldType edited_type) { - base::UmaHistogramEnumeration("Autofill.ProfileImport.NewProfileEditedType", - ConvertEditedFieldTypeForMetrics(edited_type)); +void AutofillMetrics::LogUpdateProfileNumberOfEditedFields( + int number_of_edited_fields) { + base::UmaHistogramExactLinear( + "Autofill.ProfileImport.UpdateProfileNumberOfEditedFields", + number_of_edited_fields, /*exclusive_max=*/15); } void AutofillMetrics::LogVerificationStatusOfNameTokensOnProfileUsage(
diff --git a/components/autofill/core/browser/autofill_metrics.h b/components/autofill/core/browser/autofill_metrics.h index 0640728c..6ef2f24 100644 --- a/components/autofill/core/browser/autofill_metrics.h +++ b/components/autofill/core/browser/autofill_metrics.h
@@ -1605,16 +1605,22 @@ static void LogNewProfileImportDecision( AutofillClient::SaveAddressProfileOfferUserDecision decision); + // Logs that a specific type was edited in a save prompt. + static void LogNewProfileEditedType(ServerFieldType edited_type); + + // Logs the number of edited fields for an accepted profile save. + static void LogNewProfileNumberOfEditedFields(int number_of_edited_fields); + // Logs the user decision for updating an exiting profile. static void LogProfileUpdateImportDecision( AutofillClient::SaveAddressProfileOfferUserDecision decision); - // Logs that a specific type was edited in an update prompts. - static void LogNewProfileEditedType(ServerFieldType edited_type); - - // Logs that a specific type was edited in an update prompts. + // Logs that a specific type was edited in an update prompt. static void LogProfileUpdateEditedType(ServerFieldType edited_type); + // Logs the number of edited fields for an accepted profile update. + static void LogUpdateProfileNumberOfEditedFields(int number_of_edited_fields); + // Logs when the virtual card metadata for one card have been updated. static void LogVirtualCardMetadataSynced(bool existing_card);
diff --git a/components/autofill/core/browser/autofill_profile_import_process.cc b/components/autofill/core/browser/autofill_profile_import_process.cc index 86cbf6c3..4a68842d7 100644 --- a/components/autofill/core/browser/autofill_profile_import_process.cc +++ b/components/autofill/core/browser/autofill_profile_import_process.cc
@@ -307,16 +307,24 @@ // If the profile was edited by the user, record a histogram of edited types. if (user_decision_ == UserDecision::kEditAccepted) { - for (const auto& difference : - AutofillProfileComparator::GetSettingsVisibleProfileDifference( - import_candidate_.value(), confirmed_import_candidate_.value(), - app_locale_)) { + const std::vector<ProfileValueDifference> edit_difference = + AutofillProfileComparator::GetSettingsVisibleProfileDifference( + import_candidate_.value(), confirmed_import_candidate_.value(), + app_locale_); + for (const auto& difference : edit_difference) { if (import_type_ == AutofillProfileImportType::kNewProfile) { AutofillMetrics::LogNewProfileEditedType(difference.type); } else { AutofillMetrics::LogProfileUpdateEditedType(difference.type); } } + if (import_type_ == AutofillProfileImportType::kNewProfile) { + AutofillMetrics::LogNewProfileNumberOfEditedFields( + edit_difference.size()); + } else { + AutofillMetrics::LogUpdateProfileNumberOfEditedFields( + edit_difference.size()); + } } }
diff --git a/components/autofill/core/browser/autofill_regex_constants.cc b/components/autofill/core/browser/autofill_regex_constants.cc index 12f66c4..c140328 100644 --- a/components/autofill/core/browser/autofill_regex_constants.cc +++ b/components/autofill/core/browser/autofill_regex_constants.cc
@@ -222,13 +222,13 @@ const char16_t kNameOnCardContextualRe[] = u"name"; const char16_t kCardNumberRe[] = u"(add)?(?:card|cc|acct).?(?:number|#|no|num|field|pan)" - u"|(?<!telefon|haus|person|fødsels)nummer" // de-DE, sv-SE, no - u"|カード番号" // ja-JP - u"|Номер.*карты" // ru - u"|no.*kartu" // id - u"|信用卡号|信用卡号码" // zh-CN - u"|信用卡卡號" // zh-TW - u"|카드" // ko-KR + u"|(?<!telefon|haus|person|fødsels|kunden)nummer" // de-DE, sv-SE, no + u"|カード番号" // ja-JP + u"|Номер.*карты" // ru + u"|no.*kartu" // id + u"|信用卡号|信用卡号码" // zh-CN + u"|信用卡卡號" // zh-TW + u"|카드" // ko-KR // es/pt/fr u"|(numero|número|numéro)(?!.*(document|fono|phone|réservation))";
diff --git a/components/autofill/core/browser/pattern_provider/resources/regex_patterns.json b/components/autofill/core/browser/pattern_provider/resources/regex_patterns.json index 139a72d..bcf66eb 100644 --- a/components/autofill/core/browser/pattern_provider/resources/regex_patterns.json +++ b/components/autofill/core/browser/pattern_provider/resources/regex_patterns.json
@@ -1573,7 +1573,7 @@ "de": [ { "pattern_identifier": "de_card_number_preserving", - "positive_pattern": "(?<!telefon|haus|person|fødsels)nummer", + "positive_pattern": "(?<!telefon|haus|person|fødsels|kunden)nummer", "positive_score": 1.0, "negative_pattern": null, "match_field_attributes": 3,
diff --git a/components/discardable_memory/common/discardable_shared_memory_heap.cc b/components/discardable_memory/common/discardable_shared_memory_heap.cc index 7bd44ad6..c6deffd 100644 --- a/components/discardable_memory/common/discardable_shared_memory_heap.cc +++ b/components/discardable_memory/common/discardable_shared_memory_heap.cc
@@ -366,6 +366,9 @@ total_dump->AddScalar("freelist_size", base::trace_event::MemoryAllocatorDump::kUnitsBytes, freelist_size); + total_dump->AddScalar("freelist_size_dirty", + base::trace_event::MemoryAllocatorDump::kUnitsBytes, + dirty_freed_memory_page_count_ * base::GetPageSize()); if (args.level_of_detail == base::trace_event::MemoryDumpLevelOfDetail::BACKGROUND) { // These metrics (size and virtual size) are also reported by each
diff --git a/components/discardable_memory/common/discardable_shared_memory_heap_unittest.cc b/components/discardable_memory/common/discardable_shared_memory_heap_unittest.cc index 2759134..31ac6cf7 100644 --- a/components/discardable_memory/common/discardable_shared_memory_heap_unittest.cc +++ b/components/discardable_memory/common/discardable_shared_memory_heap_unittest.cc
@@ -361,11 +361,14 @@ "discardable/child_0x%" PRIXPTR, reinterpret_cast<uintptr_t>(&heap))); ASSERT_NE(nullptr, dump); - base::trace_event::MemoryAllocatorDump::Entry freelist("freelist_size", - "bytes", 0); + base::trace_event::MemoryAllocatorDump::Entry freelist_size("freelist_size", + "bytes", 0); + base::trace_event::MemoryAllocatorDump::Entry freelist_size_dirty( + "freelist_size_dirty", "bytes", 0); base::trace_event::MemoryAllocatorDump::Entry virtual_size("virtual_size", "bytes", 0); - EXPECT_THAT(dump->entries(), Contains(Eq(ByRef(freelist)))); + EXPECT_THAT(dump->entries(), Contains(Eq(ByRef(freelist_size)))); + EXPECT_THAT(dump->entries(), Contains(Eq(ByRef(freelist_size_dirty)))); EXPECT_THAT(dump->entries(), Contains(Eq(ByRef(virtual_size)))); } @@ -382,11 +385,14 @@ "discardable/child_0x%" PRIXPTR, reinterpret_cast<uintptr_t>(&heap))); ASSERT_NE(nullptr, dump); - base::trace_event::MemoryAllocatorDump::Entry freelist("freelist_size", - "bytes", 0); + base::trace_event::MemoryAllocatorDump::Entry freelist_size("freelist_size", + "bytes", 0); + base::trace_event::MemoryAllocatorDump::Entry freelist_size_dirty( + "freelist_size_dirty", "bytes", 0); base::trace_event::MemoryAllocatorDump::Entry virtual_size( "virtual_size", "bytes", block_size); - EXPECT_THAT(dump->entries(), Contains(Eq(ByRef(freelist)))); + EXPECT_THAT(dump->entries(), Contains(Eq(ByRef(freelist_size)))); + EXPECT_THAT(dump->entries(), Contains(Eq(ByRef(freelist_size_dirty)))); EXPECT_THAT(dump->entries(), Contains(Eq(ByRef(virtual_size)))); }
diff --git a/components/feature_engagement/public/feature_configurations.cc b/components/feature_engagement/public/feature_configurations.cc index fdd8280..452e753 100644 --- a/components/feature_engagement/public/feature_configurations.cc +++ b/components/feature_engagement/public/feature_configurations.cc
@@ -128,6 +128,39 @@ Comparator(LESS_THAN, 1), 1, 360)); return config; } + if (kIPHAddToHomescreenMessageFeature.name == feature->name) { + // A config that allows the Add to homescreen message IPH to be shown: + // * Once per 15 days + // * Up to 2 times but only if unused in the last 15 days. + absl::optional<FeatureConfig> config = FeatureConfig(); + config->valid = true; + config->availability = Comparator(ANY, 0); + config->session_rate = Comparator(EQUAL, 0); + config->trigger = EventConfig("add_to_homescreen_message_iph_trigger", + Comparator(LESS_THAN, 2), 90, 90); + config->used = EventConfig("add_to_homescreen_dialog_shown", + Comparator(EQUAL, 0), 90, 90); + config->event_configs.insert(EventConfig( + "add_to_homescreen_message_iph_trigger", Comparator(EQUAL, 0), 15, 90)); + return config; + } + if (kIPHAddToHomescreenTextBubbleFeature.name == feature->name) { + // A config that allows the Add to homescreen text bubble IPH to be shown: + // * Once per 15 days + // * Up to 2 times but only if unused in the last 15 days. + absl::optional<FeatureConfig> config = FeatureConfig(); + config->valid = true; + config->availability = Comparator(ANY, 0); + config->session_rate = Comparator(EQUAL, 0); + config->trigger = EventConfig("add_to_homescreen_text_bubble_iph_trigger", + Comparator(LESS_THAN, 2), 90, 90); + config->used = EventConfig("add_to_homescreen_dialog_shown", + Comparator(EQUAL, 0), 90, 90); + config->event_configs.insert( + EventConfig("add_to_homescreen_text_bubble_iph_trigger", + Comparator(EQUAL, 0), 15, 90)); + return config; + } if (kIPHFeedHeaderMenuFeature.name == feature->name) { // A config that allows the feed header menu IPH to be shown only once when
diff --git a/components/messages/android/internal/java/res/layout/message_banner_view.xml b/components/messages/android/internal/java/res/layout/message_banner_view.xml index d688c59..fa33e81 100644 --- a/components/messages/android/internal/java/res/layout/message_banner_view.xml +++ b/components/messages/android/internal/java/res/layout/message_banner_view.xml
@@ -11,6 +11,7 @@ android:layout_width="match_parent" android:minHeight="@dimen/message_banner_height" android:layout_gravity="center_horizontal" + android:gravity="center_vertical" android:orientation="horizontal" android:layout_marginTop="@dimen/message_shadow_top_margin" android:layout_marginBottom="@dimen/message_shadow_bottom_margin" @@ -25,12 +26,11 @@ <ImageView android:id="@+id/message_icon" + app:tint="@color/default_icon_color_blue" android:paddingStart="@dimen/message_icon_padding" android:paddingEnd="@dimen/message_icon_padding" - app:tint="@color/default_icon_color_blue" - android:layout_weight="0" android:layout_width="wrap_content" - android:layout_height="match_parent" + android:layout_height="24dp" android:importantForAccessibility="no" /> <LinearLayout @@ -86,4 +86,4 @@ android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:visibility="gone" /> -</org.chromium.components.messages.MessageBannerView> \ No newline at end of file +</org.chromium.components.messages.MessageBannerView>
diff --git a/components/messages/android/internal/java/src/org/chromium/components/messages/SingleActionMessage.java b/components/messages/android/internal/java/src/org/chromium/components/messages/SingleActionMessage.java index 799abe8..8d4d189 100644 --- a/components/messages/android/internal/java/src/org/chromium/components/messages/SingleActionMessage.java +++ b/components/messages/android/internal/java/src/org/chromium/components/messages/SingleActionMessage.java
@@ -61,12 +61,12 @@ mMaxTranslationSupplier = maxTranslationSupplier; mAnimatorStartCallback = animatorStartCallback; - long dismissalDurationExtend = mModel.getAllSetProperties().contains( - MessageBannerProperties.DISMISSAL_DURATION_EXTEND) - ? mModel.get(MessageBannerProperties.DISMISSAL_DURATION_EXTEND) + long dismissalDuration = + mModel.getAllSetProperties().contains(MessageBannerProperties.DISMISSAL_DURATION) + ? mModel.get(MessageBannerProperties.DISMISSAL_DURATION) : 0; - mAutodismissDurationMs = () -> autodismissDurationProvider.get(dismissalDurationExtend); + mAutodismissDurationMs = () -> autodismissDurationProvider.get(dismissalDuration); mModel.set( MessageBannerProperties.PRIMARY_BUTTON_CLICK_LISTENER, this::handlePrimaryAction);
diff --git a/components/messages/android/internal/java/src/org/chromium/components/messages/SingleActionMessageTest.java b/components/messages/android/internal/java/src/org/chromium/components/messages/SingleActionMessageTest.java index b22628f00..e5881bd 100644 --- a/components/messages/android/internal/java/src/org/chromium/components/messages/SingleActionMessageTest.java +++ b/components/messages/android/internal/java/src/org/chromium/components/messages/SingleActionMessageTest.java
@@ -130,7 +130,7 @@ public void testAutoDismissDurationExtended() { MessageContainer container = new MessageContainer(sActivity, null); PropertyModel model = createBasicSingleActionMessageModel(); - model.set(MessageBannerProperties.DISMISSAL_DURATION_EXTEND, 1000); + model.set(MessageBannerProperties.DISMISSAL_DURATION, 1000); long duration = 42; SingleActionMessage message = new SingleActionMessage(container, model, mEmptyDismissCallback,
diff --git a/components/messages/android/java/src/org/chromium/components/messages/MessageBannerProperties.java b/components/messages/android/java/src/org/chromium/components/messages/MessageBannerProperties.java index f44a59e..4fc6017 100644 --- a/components/messages/android/java/src/org/chromium/components/messages/MessageBannerProperties.java +++ b/components/messages/android/java/src/org/chromium/components/messages/MessageBannerProperties.java
@@ -54,8 +54,7 @@ public static final WritableObjectPropertyKey<String> SECONDARY_ICON_CONTENT_DESCRIPTION = new WritableObjectPropertyKey<>(); // Unit: milliseconds. - public static final WritableLongPropertyKey DISMISSAL_DURATION_EXTEND = - new WritableLongPropertyKey(); + public static final WritableLongPropertyKey DISMISSAL_DURATION = new WritableLongPropertyKey(); /** * The callback invoked when the message is dismissed. DismissReason is passed through the * callback's parameter. @@ -77,7 +76,6 @@ public static final PropertyKey[] ALL_KEYS = new PropertyKey[] {PRIMARY_BUTTON_TEXT, PRIMARY_BUTTON_CLICK_LISTENER, TITLE, DESCRIPTION, ICON, ICON_RESOURCE_ID, ICON_TINT_COLOR, SECONDARY_ICON, SECONDARY_ICON_RESOURCE_ID, SECONDARY_BUTTON_MENU_TEXT, - SECONDARY_ICON_CONTENT_DESCRIPTION, DISMISSAL_DURATION_EXTEND, TRANSLATION_X, - TRANSLATION_Y, ALPHA, ON_TOUCH_RUNNABLE, ON_PRIMARY_ACTION, ON_SECONDARY_ACTION, - ON_DISMISSED}; + SECONDARY_ICON_CONTENT_DESCRIPTION, DISMISSAL_DURATION, TRANSLATION_X, TRANSLATION_Y, + ALPHA, ON_TOUCH_RUNNABLE, ON_PRIMARY_ACTION, ON_SECONDARY_ACTION, ON_DISMISSED}; }
diff --git a/components/messages/android/java/src/org/chromium/components/messages/MessageWrapper.java b/components/messages/android/java/src/org/chromium/components/messages/MessageWrapper.java index 37764d0..b130bc07 100644 --- a/components/messages/android/java/src/org/chromium/components/messages/MessageWrapper.java +++ b/components/messages/android/java/src/org/chromium/components/messages/MessageWrapper.java
@@ -98,6 +98,12 @@ } @CalledByNative + void disableIconTint() { + mMessageProperties.set( + MessageBannerProperties.ICON_TINT_COLOR, MessageBannerProperties.TINT_NONE); + } + + @CalledByNative @DrawableRes int getSecondaryIconResourceId() { return mMessageProperties.get(MessageBannerProperties.SECONDARY_ICON_RESOURCE_ID); @@ -109,8 +115,8 @@ } @CalledByNative - void setDurationExtension(long extension) { - mMessageProperties.set(MessageBannerProperties.DISMISSAL_DURATION_EXTEND, extension); + void setDuration(long customDuration) { + mMessageProperties.set(MessageBannerProperties.DISMISSAL_DURATION, customDuration); } @CalledByNative
diff --git a/components/messages/android/message_wrapper.cc b/components/messages/android/message_wrapper.cc index 562754c..5d55ca7 100644 --- a/components/messages/android/message_wrapper.cc +++ b/components/messages/android/message_wrapper.cc
@@ -105,6 +105,11 @@ resource_id); } +void MessageWrapper::DisableIconTint() { + JNIEnv* env = base::android::AttachCurrentThread(); + Java_MessageWrapper_disableIconTint(env, java_message_wrapper_); +} + int MessageWrapper::GetSecondaryIconResourceId() { JNIEnv* env = base::android::AttachCurrentThread(); return Java_MessageWrapper_getSecondaryIconResourceId(env, @@ -121,10 +126,9 @@ secondary_action_callback_ = std::move(callback); } -void MessageWrapper::SetDurationExtension(long extension) { +void MessageWrapper::SetDuration(long customDuration) { JNIEnv* env = base::android::AttachCurrentThread(); - Java_MessageWrapper_setDurationExtension(env, java_message_wrapper_, - extension); + Java_MessageWrapper_setDuration(env, java_message_wrapper_, customDuration); } void MessageWrapper::HandleActionClick(JNIEnv* env) {
diff --git a/components/messages/android/message_wrapper.h b/components/messages/android/message_wrapper.h index 2ba5c25..8e29bfc 100644 --- a/components/messages/android/message_wrapper.h +++ b/components/messages/android/message_wrapper.h
@@ -47,12 +47,15 @@ // translate from chromium resource_id to Android drawable resource_id. int GetIconResourceId(); void SetIconResourceId(int resource_id); + // The icon is tinted to default_icon_color_blue by default. + // Call this method to display icons of original colors. + void DisableIconTint(); int GetSecondaryIconResourceId(); void SetSecondaryIconResourceId(int resource_id); void SetSecondaryActionCallback(base::OnceClosure callback); - void SetDurationExtension(long extension); + void SetDuration(long customDuration); // Following methods forward calls from java to provided callbacks. void HandleActionClick(JNIEnv* env);
diff --git a/components/offline_pages/core/background/change_requests_state_task_unittest.cc b/components/offline_pages/core/background/change_requests_state_task_unittest.cc index 79e5bb0c..18ebab2 100644 --- a/components/offline_pages/core/background/change_requests_state_task_unittest.cc +++ b/components/offline_pages/core/background/change_requests_state_task_unittest.cc
@@ -18,6 +18,7 @@ namespace offline_pages { namespace { + const int64_t kRequestId1 = 42; const int64_t kRequestId2 = 43; const int64_t kRequestId3 = 44; @@ -25,15 +26,6 @@ const ClientId kClientId1("bookmark", "1234"); const ClientId kClientId2("async", "5678"); -// TODO(https://crbug.com/1042727): Fix test GURL scoping and remove this getter -// function. -GURL Url1() { - return GURL("http://example.com"); -} -GURL Url2() { - return GURL("http://another-example.com"); -} - class ChangeRequestsStateTaskTest : public RequestQueueTaskTestBase { public: ~ChangeRequestsStateTaskTest() override = default; @@ -52,13 +44,13 @@ void ChangeRequestsStateTaskTest::AddItemsToStore() { base::Time creation_time = OfflineTimeNow(); - SavePageRequest request_1(kRequestId1, Url1(), kClientId1, creation_time, - true); + SavePageRequest request_1(kRequestId1, GURL("http://example.com"), kClientId1, + creation_time, true); store_.AddRequest(request_1, RequestQueue::AddOptions(), base::BindOnce(&ChangeRequestsStateTaskTest::AddRequestDone, base::Unretained(this))); - SavePageRequest request_2(kRequestId2, Url2(), kClientId2, creation_time, - true); + SavePageRequest request_2(kRequestId2, GURL("http://another-example.com"), + kClientId2, creation_time, true); store_.AddRequest(request_2, RequestQueue::AddOptions(), base::BindOnce(&ChangeRequestsStateTaskTest::AddRequestDone, base::Unretained(this)));
diff --git a/components/offline_pages/core/background/cleanup_task_unittest.cc b/components/offline_pages/core/background/cleanup_task_unittest.cc index 5b5f70a..b2f1a90 100644 --- a/components/offline_pages/core/background/cleanup_task_unittest.cc +++ b/components/offline_pages/core/background/cleanup_task_unittest.cc
@@ -23,8 +23,8 @@ #include "testing/gtest/include/gtest/gtest.h" namespace offline_pages { - namespace { + // Data for request 1. const int64_t kRequestId1 = 17; const ClientId kClientId1("bookmark", "1234"); @@ -34,16 +34,6 @@ const ClientId kClientId2("bookmark", "5678"); const bool kUserRequested = true; -// TODO(https://crbug.com/1042727): Fix test GURL scoping and remove this getter -// function. -GURL Url1() { - return GURL("https://google.com"); -} - -GURL Url2() { - return GURL("http://nytimes.com"); -} - // Default request SavePageRequest EmptyRequest() { return SavePageRequest(0UL, GURL(""), ClientId("", ""), base::Time(), true); @@ -171,10 +161,10 @@ creation_time - base::TimeDelta::FromSeconds( policy()->GetRequestExpirationTimeInSeconds() + 10); // Request2 will be expired, request1 will be current. - SavePageRequest request1(kRequestId1, Url1(), kClientId1, creation_time, - kUserRequested); - SavePageRequest request2(kRequestId2, Url2(), kClientId2, expired_time, - kUserRequested); + SavePageRequest request1(kRequestId1, GURL("https://google.com"), kClientId1, + creation_time, kUserRequested); + SavePageRequest request2(kRequestId2, GURL("http://nytimes.com"), kClientId2, + expired_time, kUserRequested); QueueRequests(request1, request2); // Initiate cleanup. @@ -192,10 +182,10 @@ TEST_F(CleanupTaskTest, CleanupStartCountExceededRequest) { base::Time creation_time = OfflineTimeNow(); // Request2 will have an exceeded start count. - SavePageRequest request1(kRequestId1, Url1(), kClientId1, creation_time, - kUserRequested); - SavePageRequest request2(kRequestId2, Url2(), kClientId2, creation_time, - kUserRequested); + SavePageRequest request1(kRequestId1, GURL("https://google.com"), kClientId1, + creation_time, kUserRequested); + SavePageRequest request2(kRequestId2, GURL("http://nytimes.com"), kClientId2, + creation_time, kUserRequested); request2.set_started_attempt_count(policy()->GetMaxStartedTries()); QueueRequests(request1, request2); @@ -214,10 +204,10 @@ TEST_F(CleanupTaskTest, CleanupCompletionCountExceededRequest) { base::Time creation_time = OfflineTimeNow(); // Request2 will have an exceeded completion count. - SavePageRequest request1(kRequestId1, Url1(), kClientId1, creation_time, - kUserRequested); - SavePageRequest request2(kRequestId2, Url2(), kClientId2, creation_time, - kUserRequested); + SavePageRequest request1(kRequestId1, GURL("https://google.com"), kClientId1, + creation_time, kUserRequested); + SavePageRequest request2(kRequestId2, GURL("http://nytimes.com"), kClientId2, + creation_time, kUserRequested); request2.set_completed_attempt_count(policy()->GetMaxCompletedTries()); QueueRequests(request1, request2); @@ -237,12 +227,12 @@ base::Time creation_time = OfflineTimeNow(); // Both requests will have an exceeded completion count. // The first request will be marked as started. - SavePageRequest request1(kRequestId1, Url1(), kClientId1, creation_time, - kUserRequested); + SavePageRequest request1(kRequestId1, GURL("https://google.com"), kClientId1, + creation_time, kUserRequested); request1.set_completed_attempt_count(policy()->GetMaxCompletedTries()); request1.MarkAttemptStarted(creation_time); - SavePageRequest request2(kRequestId2, Url2(), kClientId2, creation_time, - kUserRequested); + SavePageRequest request2(kRequestId2, GURL("http://nytimes.com"), kClientId2, + creation_time, kUserRequested); request2.set_completed_attempt_count(policy()->GetMaxCompletedTries()); QueueRequests(request1, request2);
diff --git a/components/offline_pages/core/background/get_requests_task_unittest.cc b/components/offline_pages/core/background/get_requests_task_unittest.cc index e9f98f2b..162de234 100644 --- a/components/offline_pages/core/background/get_requests_task_unittest.cc +++ b/components/offline_pages/core/background/get_requests_task_unittest.cc
@@ -18,21 +18,13 @@ namespace offline_pages { namespace { + const int64_t kRequestId1 = 42; const int64_t kRequestId2 = 44; const ClientId kClientId1("download", "1234"); const ClientId kClientId2("download", "5678"); -// TODO(https://crbug.com/1042727): Fix test GURL scoping and remove this getter -// function. -GURL Url1() { - return GURL("http://example.com"); -} -GURL Url2() { - return GURL("http://otherexample.com"); -} - class GetRequestsTaskTest : public RequestQueueTaskTestBase { public: GetRequestsTaskTest() = default; @@ -63,13 +55,13 @@ void GetRequestsTaskTest::AddItemsToStore(RequestQueueStore* store) { base::Time creation_time = OfflineTimeNow(); - SavePageRequest request_1(kRequestId1, Url1(), kClientId1, creation_time, - true); + SavePageRequest request_1(kRequestId1, GURL("http://example.com"), kClientId1, + creation_time, true); store->AddRequest(request_1, RequestQueue::AddOptions(), base::BindOnce(&GetRequestsTaskTest::AddRequestDone)); creation_time = OfflineTimeNow(); - SavePageRequest request_2(kRequestId2, Url2(), kClientId2, creation_time, - true); + SavePageRequest request_2(kRequestId2, GURL("http://otherexample.com"), + kClientId2, creation_time, true); store->AddRequest(request_2, RequestQueue::AddOptions(), base::BindOnce(&GetRequestsTaskTest::AddRequestDone)); PumpLoop();
diff --git a/components/offline_pages/core/background/mark_attempt_aborted_task_unittest.cc b/components/offline_pages/core/background/mark_attempt_aborted_task_unittest.cc index 4c9c1cc..187c894 100644 --- a/components/offline_pages/core/background/mark_attempt_aborted_task_unittest.cc +++ b/components/offline_pages/core/background/mark_attempt_aborted_task_unittest.cc
@@ -21,17 +21,12 @@ namespace offline_pages { namespace { + const int64_t kRequestId1 = 42; const int64_t kRequestId2 = 44; const ClientId kClientId1("download", "1234"); -// TODO(https://crbug.com/1042727): Fix test GURL scoping and remove this getter -// function. -GURL Url1() { - return GURL("http://example.com"); -} - class MarkAttemptAbortedTaskTest : public RequestQueueTaskTestBase { public: MarkAttemptAbortedTaskTest() {} @@ -53,8 +48,8 @@ void MarkAttemptAbortedTaskTest::AddItemToStore(RequestQueueStore* store) { base::Time creation_time = OfflineTimeNow(); - SavePageRequest request_1(kRequestId1, Url1(), kClientId1, creation_time, - true); + SavePageRequest request_1(kRequestId1, GURL("http://example.com"), kClientId1, + creation_time, true); store->AddRequest(request_1, RequestQueue::AddOptions(), base::BindOnce(&MarkAttemptAbortedTaskTest::AddRequestDone, base::Unretained(this)));
diff --git a/components/offline_pages/core/background/mark_attempt_completed_task_unittest.cc b/components/offline_pages/core/background/mark_attempt_completed_task_unittest.cc index 2a4dba3..17930bb 100644 --- a/components/offline_pages/core/background/mark_attempt_completed_task_unittest.cc +++ b/components/offline_pages/core/background/mark_attempt_completed_task_unittest.cc
@@ -17,17 +17,12 @@ namespace offline_pages { namespace { + const int64_t kRequestId1 = 42; const int64_t kRequestId2 = 44; const ClientId kClientId1("download", "1234"); -// TODO(https://crbug.com/1042727): Fix test GURL scoping and remove this getter -// function. -GURL Url1() { - return GURL("http://example.com"); -} - class MarkAttemptCompletedTaskTest : public RequestQueueTaskTestBase { public: MarkAttemptCompletedTaskTest() {} @@ -48,8 +43,8 @@ void MarkAttemptCompletedTaskTest::AddStartedItemToStore() { base::Time creation_time = OfflineTimeNow(); - SavePageRequest request_1(kRequestId1, Url1(), kClientId1, creation_time, - true); + SavePageRequest request_1(kRequestId1, GURL("http://example.com"), kClientId1, + creation_time, true); request_1.MarkAttemptStarted(OfflineTimeNow()); store_.AddRequest( request_1, RequestQueue::AddOptions(),
diff --git a/components/offline_pages/core/background/mark_attempt_started_task_unittest.cc b/components/offline_pages/core/background/mark_attempt_started_task_unittest.cc index f48de0e..29ee9712 100644 --- a/components/offline_pages/core/background/mark_attempt_started_task_unittest.cc +++ b/components/offline_pages/core/background/mark_attempt_started_task_unittest.cc
@@ -18,16 +18,11 @@ namespace offline_pages { namespace { + const int64_t kRequestId1 = 42; const int64_t kRequestId2 = 44; const ClientId kClientId1("download", "1234"); -// TODO(https://crbug.com/1042727): Fix test GURL scoping and remove this getter -// function. -GURL Url1() { - return GURL("http://example.com"); -} - class MarkAttemptStartedTaskTest : public RequestQueueTaskTestBase { public: MarkAttemptStartedTaskTest() {} @@ -48,8 +43,8 @@ void MarkAttemptStartedTaskTest::AddItemToStore() { base::Time creation_time = OfflineTimeNow(); - SavePageRequest request_1(kRequestId1, Url1(), kClientId1, creation_time, - true); + SavePageRequest request_1(kRequestId1, GURL("http://example.com"), kClientId1, + creation_time, true); store_.AddRequest( request_1, RequestQueue::AddOptions(), base::BindOnce(&MarkAttemptStartedTaskTest::AddRequestDone));
diff --git a/components/offline_pages/core/background/pick_request_task_unittest.cc b/components/offline_pages/core/background/pick_request_task_unittest.cc index de1cf1b7..d6c26391 100644 --- a/components/offline_pages/core/background/pick_request_task_unittest.cc +++ b/components/offline_pages/core/background/pick_request_task_unittest.cc
@@ -44,16 +44,6 @@ const bool kPreferRetryCount = true; const int kBackgroundProcessingTimeBudgetSeconds = 170; -// TODO(https://crbug.com/1042727): Fix test GURL scoping and remove this getter -// function. -GURL Url1() { - return GURL("https://google.com"); -} - -GURL Url2() { - return GURL("http://nytimes.com"); -} - // Default request SavePageRequest EmptyRequest() { return SavePageRequest(0UL, GURL(""), ClientId("", ""), base::Time(), true); @@ -231,10 +221,10 @@ MakePickRequestTask(); base::Time creation_time = OfflineTimeNow(); - SavePageRequest request1(kRequestId1, Url1(), kClientId1, creation_time, - kUserRequested); - SavePageRequest request2(kRequestId2, Url2(), kClientId2, creation_time, - kUserRequested); + SavePageRequest request1(kRequestId1, GURL("https://google.com"), kClientId1, + creation_time, kUserRequested); + SavePageRequest request2(kRequestId2, GURL("http://nytimes.com"), kClientId2, + creation_time, kUserRequested); request2.set_completed_attempt_count(kAttemptCount); QueueRequests(request1, request2); @@ -253,10 +243,10 @@ base::Time creation_time1 = OfflineTimeNow() - base::TimeDelta::FromSeconds(10); base::Time creation_time2 = OfflineTimeNow(); - SavePageRequest request1(kRequestId1, Url1(), kClientId1, creation_time1, - kUserRequested); - SavePageRequest request2(kRequestId2, Url2(), kClientId2, creation_time2, - kUserRequested); + SavePageRequest request1(kRequestId1, GURL("https://google.com"), kClientId1, + creation_time1, kUserRequested); + SavePageRequest request2(kRequestId2, GURL("http://nytimes.com"), kClientId2, + creation_time2, kUserRequested); QueueRequests(request1, request2); @@ -278,10 +268,10 @@ base::Time creation_time1 = OfflineTimeNow() - base::TimeDelta::FromSeconds(10); base::Time creation_time2 = OfflineTimeNow(); - SavePageRequest request1(kRequestId1, Url1(), kClientId1, creation_time1, - kUserRequested); - SavePageRequest request2(kRequestId2, Url2(), kClientId2, creation_time2, - kUserRequested); + SavePageRequest request1(kRequestId1, GURL("https://google.com"), kClientId1, + creation_time1, kUserRequested); + SavePageRequest request2(kRequestId2, GURL("http://nytimes.com"), kClientId2, + creation_time2, kUserRequested); request2.set_completed_attempt_count(kAttemptCount); QueueRequests(request1, request2); @@ -302,10 +292,10 @@ MakePickRequestTask(); base::Time creation_time = OfflineTimeNow(); - SavePageRequest request1(kRequestId1, Url1(), kClientId1, creation_time, - kUserRequested); - SavePageRequest request2(kRequestId2, Url2(), kClientId2, creation_time, - kUserRequested); + SavePageRequest request1(kRequestId1, GURL("https://google.com"), kClientId1, + creation_time, kUserRequested); + SavePageRequest request2(kRequestId2, GURL("http://nytimes.com"), kClientId2, + creation_time, kUserRequested); request2.set_completed_attempt_count(kAttemptCount); QueueRequests(request1, request2); @@ -326,10 +316,10 @@ MakePickRequestTask(); base::Time creation_time = OfflineTimeNow(); - SavePageRequest request1(kRequestId1, Url1(), kClientId1, creation_time, - kUserRequested); - SavePageRequest request2(kRequestId2, Url2(), kClientId2, creation_time, - kUserRequested); + SavePageRequest request1(kRequestId1, GURL("https://google.com"), kClientId1, + creation_time, kUserRequested); + SavePageRequest request2(kRequestId2, GURL("http://nytimes.com"), kClientId2, + creation_time, kUserRequested); request2.set_completed_attempt_count(kAttemptCount); QueueRequests(request1, request2); @@ -352,10 +342,10 @@ base::Time creation_time1 = OfflineTimeNow() - base::TimeDelta::FromSeconds(10); base::Time creation_time2 = OfflineTimeNow(); - SavePageRequest request1(kRequestId1, Url1(), kClientId1, creation_time1, - kUserRequested); - SavePageRequest request2(kRequestId2, Url2(), kClientId2, creation_time2, - kUserRequested); + SavePageRequest request1(kRequestId1, GURL("https://google.com"), kClientId1, + creation_time1, kUserRequested); + SavePageRequest request2(kRequestId2, GURL("http://nytimes.com"), kClientId2, + creation_time2, kUserRequested); QueueRequests(request1, request2); @@ -372,10 +362,10 @@ base::Time expired_time = creation_time - base::TimeDelta::FromSeconds( policy_->GetRequestExpirationTimeInSeconds() + 60); - SavePageRequest request1(kRequestId1, Url1(), kClientId1, creation_time, - kUserRequested); - SavePageRequest request2(kRequestId2, Url2(), kClientId2, expired_time, - kUserRequested); + SavePageRequest request1(kRequestId1, GURL("https://google.com"), kClientId1, + creation_time, kUserRequested); + SavePageRequest request2(kRequestId2, GURL("http://nytimes.com"), kClientId2, + expired_time, kUserRequested); QueueRequests(request1, request2); @@ -394,10 +384,10 @@ base::Time creation_time1 = OfflineTimeNow() - base::TimeDelta::FromSeconds(1); base::Time creation_time2 = OfflineTimeNow(); - SavePageRequest request1(kRequestId1, Url1(), kClientId1, creation_time1, - kUserRequested); - SavePageRequest request2(kRequestId2, Url2(), kClientId2, creation_time2, - kUserRequested); + SavePageRequest request1(kRequestId1, GURL("https://google.com"), kClientId1, + creation_time1, kUserRequested); + SavePageRequest request2(kRequestId2, GURL("http://nytimes.com"), kClientId2, + creation_time2, kUserRequested); // With default policy settings, we should choose the earlier request. // However, we will make the earlier reqeust exceed the limit. @@ -420,10 +410,10 @@ base::Time creation_time1 = OfflineTimeNow() - base::TimeDelta::FromSeconds(1); base::Time creation_time2 = OfflineTimeNow(); - SavePageRequest request1(kRequestId1, Url1(), kClientId1, creation_time1, - kUserRequested); - SavePageRequest request2(kRequestId2, Url2(), kClientId2, creation_time2, - kUserRequested); + SavePageRequest request1(kRequestId1, GURL("https://google.com"), kClientId1, + creation_time1, kUserRequested); + SavePageRequest request2(kRequestId2, GURL("http://nytimes.com"), kClientId2, + creation_time2, kUserRequested); // With default policy settings, we should choose the earlier request. // However, we will make the earlier reqeust exceed the limit. @@ -451,10 +441,10 @@ MakePickRequestTask(); base::Time creation_time = OfflineTimeNow(); - SavePageRequest request1(kRequestId1, Url1(), kClientId1, creation_time, - kUserRequested); - SavePageRequest request2(kRequestId2, Url2(), kClientId2, creation_time, - kUserRequested); + SavePageRequest request1(kRequestId1, GURL("https://google.com"), kClientId1, + creation_time, kUserRequested); + SavePageRequest request2(kRequestId2, GURL("http://nytimes.com"), kClientId2, + creation_time, kUserRequested); request2.set_completed_attempt_count(kAttemptCount); // Add test requests on the Queue. @@ -480,10 +470,10 @@ MakePickRequestTask(); base::Time creation_time = OfflineTimeNow(); - SavePageRequest request1(kRequestId1, Url1(), kClientId1, creation_time, - kUserRequested); - SavePageRequest request2(kRequestId2, Url2(), kClientId2, creation_time, - kUserRequested); + SavePageRequest request1(kRequestId1, GURL("https://google.com"), kClientId1, + creation_time, kUserRequested); + SavePageRequest request2(kRequestId2, GURL("http://nytimes.com"), kClientId2, + creation_time, kUserRequested); // Since default policy prefer untried requests, make request1 the favorable // pick if no prioritized requests. But request2 is prioritized so it should // be picked. @@ -521,10 +511,10 @@ base::Time creation_time = OfflineTimeNow(); base::Time older_creation_time = creation_time - base::TimeDelta::FromMinutes(10); - SavePageRequest request1(kRequestId1, Url1(), kClientId1, older_creation_time, - kUserRequested); - SavePageRequest request2(kRequestId2, Url2(), kClientId2, creation_time, - kUserRequested); + SavePageRequest request1(kRequestId1, GURL("https://google.com"), kClientId1, + older_creation_time, kUserRequested); + SavePageRequest request2(kRequestId2, GURL("http://nytimes.com"), kClientId2, + creation_time, kUserRequested); request2.set_completed_attempt_count(kAttemptCount); // Add test requests on the Queue.
diff --git a/components/offline_pages/core/background/reconcile_task_unittest.cc b/components/offline_pages/core/background/reconcile_task_unittest.cc index b35be55..6817b28 100644 --- a/components/offline_pages/core/background/reconcile_task_unittest.cc +++ b/components/offline_pages/core/background/reconcile_task_unittest.cc
@@ -20,8 +20,8 @@ #include "testing/gtest/include/gtest/gtest.h" namespace offline_pages { - namespace { + // Data for request 1. const int64_t kRequestId1 = 17; const ClientId kClientId1("bookmark", "1234"); @@ -30,15 +30,6 @@ const ClientId kClientId2("bookmark", "5678"); const bool kUserRequested = true; -// TODO(https://crbug.com/1042727): Fix test GURL scoping and remove this getter -// function. -GURL Url1() { - return GURL("https://google.com"); -} -GURL Url2() { - return GURL("http://nytimes.com"); -} - class ReconcileTaskTest : public RequestQueueTaskTestBase { public: ReconcileTaskTest() {} @@ -118,11 +109,11 @@ TEST_F(ReconcileTaskTest, Reconcile) { base::Time creation_time = OfflineTimeNow(); // Request2 will be expired, request1 will be current. - SavePageRequest request1(kRequestId1, Url1(), kClientId1, creation_time, - kUserRequested); + SavePageRequest request1(kRequestId1, GURL("https://google.com"), kClientId1, + creation_time, kUserRequested); request1.set_request_state(SavePageRequest::RequestState::PAUSED); - SavePageRequest request2(kRequestId2, Url2(), kClientId2, creation_time, - kUserRequested); + SavePageRequest request2(kRequestId2, GURL("http://nytimes.com"), kClientId2, + creation_time, kUserRequested); request2.set_request_state(SavePageRequest::RequestState::OFFLINING); QueueRequests(request1, request2); @@ -153,11 +144,11 @@ TEST_F(ReconcileTaskTest, NothingToReconcile) { base::Time creation_time = OfflineTimeNow(); // Request2 will be expired, request1 will be current. - SavePageRequest request1(kRequestId1, Url1(), kClientId1, creation_time, - kUserRequested); + SavePageRequest request1(kRequestId1, GURL("https://google.com"), kClientId1, + creation_time, kUserRequested); request1.set_request_state(SavePageRequest::RequestState::PAUSED); - SavePageRequest request2(kRequestId2, Url2(), kClientId2, creation_time, - kUserRequested); + SavePageRequest request2(kRequestId2, GURL("http://nytimes.com"), kClientId2, + creation_time, kUserRequested); request2.set_request_state(SavePageRequest::RequestState::AVAILABLE); QueueRequests(request1, request2);
diff --git a/components/offline_pages/core/background/remove_requests_task_unittest.cc b/components/offline_pages/core/background/remove_requests_task_unittest.cc index a022f2d..46b481d 100644 --- a/components/offline_pages/core/background/remove_requests_task_unittest.cc +++ b/components/offline_pages/core/background/remove_requests_task_unittest.cc
@@ -25,15 +25,6 @@ const ClientId kClientId1("bookmark", "1234"); const ClientId kClientId2("async", "5678"); -// TODO(https://crbug.com/1042727): Fix test GURL scoping and remove this getter -// function. -GURL Url1() { - return GURL("http://example.com"); -} -GURL Url2() { - return GURL("http://another-example.com"); -} - class RemoveRequestsTaskTest : public RequestQueueTaskTestBase { public: RemoveRequestsTaskTest() {} @@ -60,12 +51,12 @@ void RemoveRequestsTaskTest::AddRequestsToStore() { base::Time creation_time = OfflineTimeNow(); - SavePageRequest request_1(kRequestId1, Url1(), kClientId1, creation_time, - true); + SavePageRequest request_1(kRequestId1, GURL("http://example.com"), kClientId1, + creation_time, true); store_.AddRequest(request_1, RequestQueue::AddOptions(), base::BindOnce(&RemoveRequestsTaskTest::AddRequestDone)); - SavePageRequest request_2(kRequestId2, Url2(), kClientId2, creation_time, - true); + SavePageRequest request_2(kRequestId2, GURL("http://another-example.com"), + kClientId2, creation_time, true); store_.AddRequest(request_2, RequestQueue::AddOptions(), base::BindOnce(&RemoveRequestsTaskTest::AddRequestDone)); PumpLoop();
diff --git a/components/offline_pages/core/background/request_coordinator_unittest.cc b/components/offline_pages/core/background/request_coordinator_unittest.cc index 3ab671ab..2a68f9a 100644 --- a/components/offline_pages/core/background/request_coordinator_unittest.cc +++ b/components/offline_pages/core/background/request_coordinator_unittest.cc
@@ -56,15 +56,6 @@ const int kAttemptCount = 1; const std::string kRequestOrigin("abc.xyz"); -// TODO(https://crbug.com/1042727): Fix test GURL scoping and remove this getter -// function. -GURL Url1() { - return GURL("http://universe.com/everything"); -} -GURL Url2() { - return GURL("http://universe.com/toinfinityandbeyond"); -} - class BoolCallbackResult { public: base::RepeatingCallback<void(bool)> Bind() { @@ -327,7 +318,7 @@ int64_t SavePageLater() { RequestCoordinator::SavePageLaterParams params; - params.url = Url1(); + params.url = GURL("http://universe.com/everything"); params.client_id = kClientId1; params.user_requested = kUserRequested; params.request_origin = kRequestOrigin; @@ -339,7 +330,7 @@ int64_t SavePageLaterWithAvailability( RequestCoordinator::RequestAvailability availability) { RequestCoordinator::SavePageLaterParams params; - params.url = Url1(); + params.url = GURL("http://universe.com/everything"); params.client_id = kClientId1; params.user_requested = kUserRequested; params.availability = availability; @@ -524,15 +515,17 @@ } SavePageRequest RequestCoordinatorTest::AddRequest1() { - offline_pages::SavePageRequest request1(kRequestId1, Url1(), kClientId1, - OfflineTimeNow(), kUserRequested); + offline_pages::SavePageRequest request1( + kRequestId1, GURL("http://universe.com/everything"), kClientId1, + OfflineTimeNow(), kUserRequested); queue()->AddRequest(request1, RequestQueue::AddOptions(), base::DoNothing()); return request1; } SavePageRequest RequestCoordinatorTest::AddRequest2() { - offline_pages::SavePageRequest request2(kRequestId2, Url2(), kClientId2, - OfflineTimeNow(), kUserRequested); + offline_pages::SavePageRequest request2( + kRequestId2, GURL("http://universe.com/toinfinityandbeyond"), kClientId2, + OfflineTimeNow(), kUserRequested); queue()->AddRequest(request2, RequestQueue::AddOptions(), base::DoNothing()); return request2; } @@ -645,10 +638,12 @@ processing_callback()); // Use default values for |user_requested| and |availability|. + const GURL kUrl1("http://universe.com/everything"); + const GURL kUrl2("http://universe.com/toinfinityandbeyond"); RequestCoordinator::SavePageLaterParams params; - params.url = Url1(); + params.url = kUrl1; params.client_id = kClientId1; - params.original_url = Url2(); + params.original_url = kUrl2; params.request_origin = kRequestOrigin; EXPECT_NE(0, coordinator()->SavePageLater( params, base::BindOnce( @@ -669,10 +664,10 @@ // Check the request queue is as expected. ASSERT_EQ(1UL, last_requests().size()); - EXPECT_EQ(Url1(), last_requests().at(0)->url()); + EXPECT_EQ(kUrl1, last_requests().at(0)->url()); EXPECT_EQ(kClientId1, last_requests().at(0)->client_id()); EXPECT_TRUE(last_requests().at(0)->user_requested()); - EXPECT_EQ(Url2(), last_requests().at(0)->original_url()); + EXPECT_EQ(kUrl2, last_requests().at(0)->original_url()); EXPECT_EQ(kRequestOrigin, last_requests().at(0)->request_origin()); // Expect that the scheduler got notified. @@ -720,7 +715,8 @@ EXPECT_TRUE(add_request_callback_called()); // Check the request queue is as expected. EXPECT_EQ(1UL, last_requests().size()); - EXPECT_EQ(Url1(), last_requests().at(0)->url()); + EXPECT_EQ(GURL("http://universe.com/everything"), + last_requests().at(0)->url()); EXPECT_EQ(kClientId1, last_requests().at(0)->client_id()); // Expect that the scheduler got notified. @@ -736,8 +732,9 @@ TEST_F(RequestCoordinatorTest, OfflinerDoneRequestSucceeded) { // Add a request to the queue, wait for callbacks to finish. - offline_pages::SavePageRequest request(kRequestId1, Url1(), kClientId1, - OfflineTimeNow(), kUserRequested); + offline_pages::SavePageRequest request( + kRequestId1, GURL("http://universe.com/everything"), kClientId1, + OfflineTimeNow(), kUserRequested); SetupForOfflinerDoneCallbackTest(&request); // Call the OfflinerDoneCallback to simulate the page being completed, wait @@ -767,8 +764,9 @@ TEST_F(RequestCoordinatorTest, OfflinerDoneRequestSucceededButLostNetwork) { // Add a request to the queue and set offliner done callback for it. - offline_pages::SavePageRequest request(kRequestId1, Url1(), kClientId1, - OfflineTimeNow(), kUserRequested); + offline_pages::SavePageRequest request( + kRequestId1, GURL("http://universe.com/everything"), kClientId1, + OfflineTimeNow(), kUserRequested); SetupForOfflinerDoneCallbackTest(&request); EnableOfflinerCallback(false); @@ -796,8 +794,9 @@ TEST_F(RequestCoordinatorTest, OfflinerDoneRequestFailed) { // Add a request to the queue, wait for callbacks to finish. - offline_pages::SavePageRequest request(kRequestId1, Url1(), kClientId1, - OfflineTimeNow(), kUserRequested); + offline_pages::SavePageRequest request( + kRequestId1, GURL("http://universe.com/everything"), kClientId1, + OfflineTimeNow(), kUserRequested); request.set_completed_attempt_count(kMaxCompletedTries - 1); SetupForOfflinerDoneCallbackTest(&request); // Stop processing before completing the second request on the queue. @@ -839,8 +838,9 @@ TEST_F(RequestCoordinatorTest, OfflinerDoneRequestFailedNoRetryFailure) { // Add a request to the queue, wait for callbacks to finish. - offline_pages::SavePageRequest request(kRequestId1, Url1(), kClientId1, - OfflineTimeNow(), kUserRequested); + offline_pages::SavePageRequest request( + kRequestId1, GURL("http://universe.com/everything"), kClientId1, + OfflineTimeNow(), kUserRequested); SetupForOfflinerDoneCallbackTest(&request); EnableOfflinerCallback(false); @@ -882,8 +882,9 @@ TEST_F(RequestCoordinatorTest, OfflinerDoneRequestFailedNoNextFailure) { // Add a request to the queue, wait for callbacks to finish. - offline_pages::SavePageRequest request(kRequestId1, Url1(), kClientId1, - OfflineTimeNow(), kUserRequested); + offline_pages::SavePageRequest request( + kRequestId1, GURL("http://universe.com/everything"), kClientId1, + OfflineTimeNow(), kUserRequested); SetupForOfflinerDoneCallbackTest(&request); EnableOfflinerCallback(false); @@ -914,8 +915,9 @@ TEST_F(RequestCoordinatorTest, OfflinerDoneForegroundCancel) { // Add a request to the queue, wait for callbacks to finish. - offline_pages::SavePageRequest request(kRequestId1, Url1(), kClientId1, - OfflineTimeNow(), kUserRequested); + offline_pages::SavePageRequest request( + kRequestId1, GURL("http://universe.com/everything"), kClientId1, + OfflineTimeNow(), kUserRequested); SetupForOfflinerDoneCallbackTest(&request); // Call the OfflinerDoneCallback to simulate the request failed, wait @@ -941,7 +943,7 @@ // defer_while_page_is_active. active_tab_info_->set_does_active_tab_match(true); RequestCoordinator::SavePageLaterParams params; - params.url = Url1(); + params.url = GURL("http://universe.com/everything"); // Auto-async uses defer_background_fetch_while_page_is_active. params.client_id = ClientId(kAutoAsyncNamespace, "1"); coordinator()->SavePageLater(params, base::DoNothing()); @@ -977,7 +979,7 @@ // false. The page should be offlined. active_tab_info_->set_does_active_tab_match(false); RequestCoordinator::SavePageLaterParams params; - params.url = Url1(); + params.url = GURL("http://universe.com/everything"); // Auto-async uses defer_background_fetch_while_page_is_active. params.client_id = ClientId(kAutoAsyncNamespace, "1"); coordinator()->SavePageLater(params, base::DoNothing()); @@ -1045,8 +1047,9 @@ // the second is not user requested. AddRequest1(); - offline_pages::SavePageRequest request2(kRequestId2, Url2(), kClientId2, - OfflineTimeNow(), !kUserRequested); + offline_pages::SavePageRequest request2( + kRequestId2, GURL("http://universe.com/toinfinityandbeyond"), kClientId2, + OfflineTimeNow(), !kUserRequested); queue()->AddRequest(request2, RequestQueue::AddOptions(), base::DoNothing()); PumpLoop(); @@ -1268,7 +1271,7 @@ // Add a new request, and remove current request while it is processing. RequestCoordinator::SavePageLaterParams request2; - request2.url = Url2(); + request2.url = GURL("http://universe.com/toinfinityandbeyond"); request2.client_id = kClientId2; request2.user_requested = true; coordinator()->SavePageLater(request2, base::DoNothing()); @@ -1344,8 +1347,9 @@ TEST_F(RequestCoordinatorTest, WatchdogTimeoutForScheduledProcessingNoLastSnapshot) { // Build a request to use with the pre-renderer, and put it on the queue. - offline_pages::SavePageRequest request(kRequestId1, Url1(), kClientId1, - OfflineTimeNow(), kUserRequested); + offline_pages::SavePageRequest request( + kRequestId1, GURL("http://universe.com/everything"), kClientId1, + OfflineTimeNow(), kUserRequested); // Set request to allow one more completed attempt. int max_tries = coordinator()->policy()->GetMaxCompletedTries(); request.set_completed_attempt_count(max_tries - 1); @@ -1417,8 +1421,9 @@ // Build two requests to use with the pre-renderer, and put it on the queue. AddRequest1(); // The second request will have a larger completed attempt count. - offline_pages::SavePageRequest request2(kRequestId1 + 1, Url1(), kClientId1, - OfflineTimeNow(), kUserRequested); + offline_pages::SavePageRequest request2( + kRequestId1 + 1, GURL("http://universe.com/everything"), kClientId1, + OfflineTimeNow(), kUserRequested); request2.set_completed_attempt_count(kAttemptCount); queue()->AddRequest(request2, RequestQueue::AddOptions(), base::DoNothing()); PumpLoop(); @@ -1701,8 +1706,9 @@ TEST_F(RequestCoordinatorTest, SnapshotOnLastTryForScheduledProcessing) { // Build a request to use with the pre-renderer, and put it on the queue. - offline_pages::SavePageRequest request(kRequestId1, Url1(), kClientId1, - OfflineTimeNow(), kUserRequested); + offline_pages::SavePageRequest request( + kRequestId1, GURL("http://universe.com/everything"), kClientId1, + OfflineTimeNow(), kUserRequested); // Set request to allow one more completed attempt. So that the next try would // be the last retry. int max_tries = coordinator()->policy()->GetMaxCompletedTries(); @@ -1867,7 +1873,7 @@ // Make a second request. RequestCoordinator::SavePageLaterParams params; - params.url = Url2(); + params.url = GURL("http://universe.com/toinfinityandbeyond"); params.client_id = kClientId2; params.user_requested = kUserRequested; EXPECT_NE(0, coordinator()->SavePageLater( @@ -1888,7 +1894,7 @@ EnableOfflinerCallback(false); RequestCoordinator::SavePageLaterParams params; - params.url = Url1(); + params.url = GURL("http://universe.com/everything"); params.client_id = kClientId1; params.add_options.disallow_duplicate_requests = true; std::vector<AddRequestResult> results;
diff --git a/components/offline_pages/core/background/request_queue_store_unittest.cc b/components/offline_pages/core/background/request_queue_store_unittest.cc index 71585b81..11a2714 100644 --- a/components/offline_pages/core/background/request_queue_store_unittest.cc +++ b/components/offline_pages/core/background/request_queue_store_unittest.cc
@@ -28,6 +28,7 @@ using UpdateStatus = RequestQueueStore::UpdateStatus; namespace { + const int64_t kRequestId = 42; const int64_t kRequestId2 = 44; const int64_t kRequestId3 = 47; @@ -42,17 +43,8 @@ RESULT_TRUE, }; -// TODO(https://crbug.com/1042727): Fix test GURL scoping and remove this getter -// function. -GURL Url1() { - return GURL("http://example.com"); -} -GURL Url2() { - return GURL("http://another-example.com"); -} - -SavePageRequest GetTestRequest() { - SavePageRequest request(kRequestId, Url1(), kClientId, +SavePageRequest GetTestRequest(const GURL& url, const GURL& original_url) { + SavePageRequest request(kRequestId, url, kClientId, base::Time::FromDeltaSinceWindowsEpoch( base::TimeDelta::FromSeconds(1000)), kUserRequested); @@ -64,13 +56,14 @@ base::TimeDelta::FromSeconds(400))); request.set_request_origin("http://www.origin.com"); // Note: pending_state is not stored. - request.set_original_url(Url2()); + request.set_original_url(original_url); request.set_auto_fetch_notification_state( SavePageRequest::AutoFetchNotificationState::kShown); return request; } -void BuildTestStoreWithSchemaFromM57(const base::FilePath& file) { +void BuildTestStoreWithSchemaFromM57(const base::FilePath& file, + const GURL& url) { sql::Database connection; ASSERT_TRUE( connection.Open(file.Append(FILE_PATH_LITERAL("RequestQueue.db")))); @@ -106,7 +99,7 @@ statement.BindInt64(4, 0); statement.BindInt64(5, 0); statement.BindInt64(6, 0); - statement.BindString(7, Url1().spec()); + statement.BindString(7, url.spec()); statement.BindString(8, kClientId.name_space); statement.BindString(9, kClientId.id); ASSERT_TRUE(statement.Run()); @@ -115,7 +108,9 @@ connection.DoesColumnExist(REQUEST_QUEUE_TABLE_NAME, "original_url")); } -void BuildTestStoreWithSchemaFromM58(const base::FilePath& file) { +void BuildTestStoreWithSchemaFromM58(const base::FilePath& file, + const GURL& url, + const GURL& original_url) { sql::Database connection; ASSERT_TRUE( connection.Open(file.Append(FILE_PATH_LITERAL("RequestQueue.db")))); @@ -152,17 +147,19 @@ statement.BindInt64(4, 0); statement.BindInt64(5, 0); statement.BindInt64(6, 0); - statement.BindString(7, Url1().spec()); + statement.BindString(7, url.spec()); statement.BindString(8, kClientId.name_space); statement.BindString(9, kClientId.id); - statement.BindString(10, Url2().spec()); + statement.BindString(10, original_url.spec()); ASSERT_TRUE(statement.Run()); ASSERT_TRUE(connection.DoesTableExist(REQUEST_QUEUE_TABLE_NAME)); ASSERT_FALSE( connection.DoesColumnExist(REQUEST_QUEUE_TABLE_NAME, "request_origin")); } -void BuildTestStoreWithSchemaFromM61(const base::FilePath& file) { +void BuildTestStoreWithSchemaFromM61(const base::FilePath& file, + const GURL& url, + const GURL& original_url) { sql::Database connection; ASSERT_TRUE( connection.Open(file.Append(FILE_PATH_LITERAL("RequestQueue.db")))); @@ -200,10 +197,10 @@ statement.BindInt64(4, 0); statement.BindInt64(5, 0); statement.BindInt64(6, 0); - statement.BindString(7, Url1().spec()); + statement.BindString(7, url.spec()); statement.BindString(8, kClientId.name_space); statement.BindString(9, kClientId.id); - statement.BindString(10, Url2().spec()); + statement.BindString(10, original_url.spec()); statement.BindString(11, kRequestOrigin); ASSERT_TRUE(statement.Run()); ASSERT_TRUE(connection.DoesTableExist(REQUEST_QUEUE_TABLE_NAME)); @@ -211,7 +208,9 @@ connection.DoesColumnExist(REQUEST_QUEUE_TABLE_NAME, "fail_state")); } -void BuildTestStoreWithSchemaFromM72(const base::FilePath& file) { +void BuildTestStoreWithSchemaFromM72(const base::FilePath& file, + const GURL& url, + const GURL& original_url) { sql::Database connection; ASSERT_TRUE( connection.Open(file.Append(FILE_PATH_LITERAL("RequestQueue.db")))); @@ -251,10 +250,10 @@ statement.BindInt64(4, 0); statement.BindInt64(5, 0); statement.BindInt64(6, 0); - statement.BindString(7, Url1().spec()); + statement.BindString(7, url.spec()); statement.BindString(8, kClientId.name_space); statement.BindString(9, kClientId.id); - statement.BindString(10, Url2().spec()); + statement.BindString(10, original_url.spec()); statement.BindString(11, kRequestOrigin); statement.BindInt64(12, 1); ASSERT_TRUE(statement.Run()); @@ -381,15 +380,21 @@ return std::make_unique<RequestQueueStore>( base::ThreadTaskRunnerHandle::Get(), temp_directory_.GetPath()); } - std::unique_ptr<RequestQueueStore> BuildStoreWithOldSchema(int version) { + std::unique_ptr<RequestQueueStore> BuildStoreWithOldSchema( + int version, + const GURL& url, + const GURL& original_url) { if (version == 57) { - BuildTestStoreWithSchemaFromM57(temp_directory_.GetPath()); + BuildTestStoreWithSchemaFromM57(temp_directory_.GetPath(), url); } else if (version == 58) { - BuildTestStoreWithSchemaFromM58(temp_directory_.GetPath()); + BuildTestStoreWithSchemaFromM58(temp_directory_.GetPath(), url, + original_url); } else if (version == 61) { - BuildTestStoreWithSchemaFromM61(temp_directory_.GetPath()); + BuildTestStoreWithSchemaFromM61(temp_directory_.GetPath(), url, + original_url); } else if (version == 72) { - BuildTestStoreWithSchemaFromM72(temp_directory_.GetPath()); + BuildTestStoreWithSchemaFromM72(temp_directory_.GetPath(), url, + original_url); } else { LOG(ERROR) << "Version " << version << " not implemented"; return nullptr; @@ -400,7 +405,7 @@ } // Performs checks on the database to verify it works after upgrading. - void PostUpgradeChecks(RequestQueueStore* store) { + void PostUpgradeChecks(RequestQueueStore* store, const GURL& url) { // First, remove all requests. { store->GetRequests(base::BindOnce( @@ -421,7 +426,7 @@ } // Verify a request can be added and retrieved. - SavePageRequest request(kRequestId, Url1(), kClientId, OfflineTimeNow(), + SavePageRequest request(kRequestId, url, kClientId, OfflineTimeNow(), kUserRequested); store->AddRequest(request, RequestQueue::AddOptions(), base::BindOnce(&RequestQueueStoreTestBase::AddRequestDone, @@ -443,7 +448,9 @@ // defined on the |RequestQuieueStoreBaseTest| class. That's by design. TEST_F(RequestQueueStoreTest, UpgradeFromVersion57Store) { - std::unique_ptr<RequestQueueStore> store = BuildStoreWithOldSchema(57); + const GURL kUrl1("http://example.com"); + std::unique_ptr<RequestQueueStore> store = + BuildStoreWithOldSchema(57, kUrl1, GURL()); this->InitializeStore(store.get()); store->GetRequests(base::BindOnce(&RequestQueueStoreTestBase::GetRequestsDone, @@ -452,14 +459,17 @@ ASSERT_EQ(LastResult::RESULT_TRUE, this->last_result()); ASSERT_EQ(1u, this->last_requests().size()); EXPECT_EQ(kRequestId, this->last_requests()[0]->request_id()); - EXPECT_EQ(Url1(), this->last_requests()[0]->url()); + EXPECT_EQ(kUrl1, this->last_requests()[0]->url()); EXPECT_EQ(GURL(), this->last_requests()[0]->original_url()); - PostUpgradeChecks(store.get()); + PostUpgradeChecks(store.get(), kUrl1); } TEST_F(RequestQueueStoreTest, UpgradeFromVersion58Store) { - std::unique_ptr<RequestQueueStore> store(BuildStoreWithOldSchema(58)); + const GURL kUrl1("http://example.com"); + const GURL kUrl2("http://another-example.com"); + std::unique_ptr<RequestQueueStore> store( + BuildStoreWithOldSchema(58, kUrl1, kUrl2)); this->InitializeStore(store.get()); store->GetRequests(base::BindOnce(&RequestQueueStoreTestBase::GetRequestsDone, @@ -468,15 +478,18 @@ ASSERT_EQ(LastResult::RESULT_TRUE, this->last_result()); ASSERT_EQ(1u, this->last_requests().size()); EXPECT_EQ(kRequestId, this->last_requests()[0]->request_id()); - EXPECT_EQ(Url1(), this->last_requests()[0]->url()); - EXPECT_EQ(Url2(), this->last_requests()[0]->original_url()); + EXPECT_EQ(kUrl1, this->last_requests()[0]->url()); + EXPECT_EQ(kUrl2, this->last_requests()[0]->original_url()); EXPECT_EQ("", this->last_requests()[0]->request_origin()); - PostUpgradeChecks(store.get()); + PostUpgradeChecks(store.get(), kUrl1); } TEST_F(RequestQueueStoreTest, UpgradeFromVersion61Store) { - std::unique_ptr<RequestQueueStore> store(BuildStoreWithOldSchema(61)); + const GURL kUrl1("http://example.com"); + const GURL kUrl2("http://another-example.com"); + std::unique_ptr<RequestQueueStore> store( + BuildStoreWithOldSchema(61, kUrl1, kUrl2)); this->InitializeStore(store.get()); store->GetRequests(base::BindOnce(&RequestQueueStoreTestBase::GetRequestsDone, @@ -485,16 +498,19 @@ ASSERT_EQ(LastResult::RESULT_TRUE, this->last_result()); ASSERT_EQ(1u, this->last_requests().size()); EXPECT_EQ(kRequestId, this->last_requests()[0]->request_id()); - EXPECT_EQ(Url1(), this->last_requests()[0]->url()); - EXPECT_EQ(Url2(), this->last_requests()[0]->original_url()); + EXPECT_EQ(kUrl1, this->last_requests()[0]->url()); + EXPECT_EQ(kUrl2, this->last_requests()[0]->original_url()); EXPECT_EQ(kRequestOrigin, this->last_requests()[0]->request_origin()); EXPECT_EQ(0, static_cast<int>(this->last_requests()[0]->fail_state())); - PostUpgradeChecks(store.get()); + PostUpgradeChecks(store.get(), kUrl1); } TEST_F(RequestQueueStoreTest, UpgradeFromVersion72Store) { - std::unique_ptr<RequestQueueStore> store(BuildStoreWithOldSchema(72)); + const GURL kUrl1("http://example.com"); + const GURL kUrl2("http://another-example.com"); + std::unique_ptr<RequestQueueStore> store( + BuildStoreWithOldSchema(72, kUrl1, kUrl2)); this->InitializeStore(store.get()); store->GetRequests(base::BindOnce(&RequestQueueStoreTestBase::GetRequestsDone, @@ -505,13 +521,13 @@ this->last_requests(); ASSERT_EQ(1u, requests.size()); EXPECT_EQ(kRequestId, requests[0]->request_id()); - EXPECT_EQ(Url1(), requests[0]->url()); - EXPECT_EQ(Url2(), requests[0]->original_url()); + EXPECT_EQ(kUrl1, requests[0]->url()); + EXPECT_EQ(kUrl2, requests[0]->original_url()); EXPECT_EQ(kRequestOrigin, requests[0]->request_origin()); EXPECT_EQ(1, static_cast<int>(requests[0]->fail_state())); EXPECT_EQ(0, static_cast<int>(requests[0]->auto_fetch_notification_state())); - PostUpgradeChecks(store.get()); + PostUpgradeChecks(store.get(), kUrl1); } TEST_F(RequestQueueStoreTest, GetRequestsEmpty) { @@ -531,13 +547,13 @@ this->InitializeStore(store.get()); base::Time creation_time = OfflineTimeNow(); - SavePageRequest request1(kRequestId, Url1(), kClientId, creation_time, - kUserRequested); + SavePageRequest request1(kRequestId, GURL("http://example.com"), kClientId, + creation_time, kUserRequested); store->AddRequest(request1, RequestQueue::AddOptions(), base::BindOnce(&RequestQueueStoreTestBase::AddRequestDone, base::Unretained(this))); - SavePageRequest request2(kRequestId2, Url2(), kClientId2, creation_time, - kUserRequested); + SavePageRequest request2(kRequestId2, GURL("http://another-example.com"), + kClientId2, creation_time, kUserRequested); store->AddRequest(request2, RequestQueue::AddOptions(), base::BindOnce(&RequestQueueStoreTestBase::AddRequestDone, base::Unretained(this))); @@ -592,9 +608,9 @@ this->InitializeStore(store.get()); base::Time creation_time = OfflineTimeNow(); - SavePageRequest request(kRequestId, Url1(), kClientId, creation_time, - kUserRequested); - request.set_original_url(Url2()); + SavePageRequest request(kRequestId, GURL("http://example.com"), kClientId, + creation_time, kUserRequested); + request.set_original_url(GURL("http://another-example.com")); store->AddRequest(request, RequestQueue::AddOptions(), base::BindOnce(&RequestQueueStoreTestBase::AddRequestDone, @@ -635,7 +651,8 @@ TEST_F(RequestQueueStoreTest, AddAndGetRequestsMatch) { std::unique_ptr<RequestQueueStore> store(this->BuildStore()); this->InitializeStore(store.get()); - const SavePageRequest request = GetTestRequest(); + const SavePageRequest request = GetTestRequest( + GURL("http://example.com"), GURL("http://another-example.com")); store->AddRequest(request, RequestQueue::AddOptions(), base::BindOnce(&RequestQueueStoreTestBase::AddRequestDone, base::Unretained(this))); @@ -650,11 +667,12 @@ } TEST_F(RequestQueueStoreTest, UpdateRequest) { + const GURL kUrl1("http://example.com"); std::unique_ptr<RequestQueueStore> store(this->BuildStore()); this->InitializeStore(store.get()); base::Time creation_time = OfflineTimeNow(); - SavePageRequest original_request(kRequestId, Url1(), kClientId, creation_time, + SavePageRequest original_request(kRequestId, kUrl1, kClientId, creation_time, kUserRequested); store->AddRequest(original_request, RequestQueue::AddOptions(), base::BindOnce(&RequestQueueStoreTestBase::AddRequestDone, @@ -665,12 +683,12 @@ base::Time new_creation_time = creation_time + base::TimeDelta::FromMinutes(1); // Try updating an existing request. - SavePageRequest updated_request(kRequestId, Url1(), kClientId, + SavePageRequest updated_request(kRequestId, kUrl1, kClientId, new_creation_time, kUserRequested); - updated_request.set_original_url(Url2()); + updated_request.set_original_url(GURL("http://another-example.com")); updated_request.set_request_origin(kRequestOrigin); // Try to update a non-existing request. - SavePageRequest updated_request2(kRequestId2, Url1(), kClientId, + SavePageRequest updated_request2(kRequestId2, kUrl1, kClientId, new_creation_time, kUserRequested); std::vector<SavePageRequest> requests_to_update{updated_request, updated_request2}; @@ -710,13 +728,13 @@ this->InitializeStore(store.get()); base::Time creation_time = OfflineTimeNow(); - SavePageRequest request1(kRequestId, Url1(), kClientId, creation_time, - kUserRequested); + SavePageRequest request1(kRequestId, GURL("http://example.com"), kClientId, + creation_time, kUserRequested); store->AddRequest(request1, RequestQueue::AddOptions(), base::BindOnce(&RequestQueueStoreTestBase::AddRequestDone, base::Unretained(this))); - SavePageRequest request2(kRequestId2, Url2(), kClientId2, creation_time, - kUserRequested); + SavePageRequest request2(kRequestId2, GURL("http://another-example.com"), + kClientId2, creation_time, kUserRequested); store->AddRequest(request2, RequestQueue::AddOptions(), base::BindOnce(&RequestQueueStoreTestBase::AddRequestDone, base::Unretained(this))); @@ -774,8 +792,8 @@ this->InitializeStore(store.get()); base::Time creation_time = OfflineTimeNow(); - SavePageRequest original_request(kRequestId, Url1(), kClientId, creation_time, - kUserRequested); + SavePageRequest original_request(kRequestId, GURL("http://example.com"), + kClientId, creation_time, kUserRequested); store->AddRequest(original_request, RequestQueue::AddOptions(), base::BindOnce(&RequestQueueStoreTestBase::AddRequestDone, base::Unretained(this))); @@ -804,8 +822,8 @@ this->InitializeStore(store.get()); base::Time creation_time = OfflineTimeNow(); - SavePageRequest original_request(kRequestId, Url1(), kClientId, creation_time, - kUserRequested); + SavePageRequest original_request(kRequestId, GURL("http://example.com"), + kClientId, creation_time, kUserRequested); store->AddRequest(original_request, RequestQueue::AddOptions(), base::BindOnce(&RequestQueueStoreTestBase::AddRequestDone, base::Unretained(this)));
diff --git a/components/offline_pages/core/background/request_queue_unittest.cc b/components/offline_pages/core/background/request_queue_unittest.cc index cf7359f..8391425 100644 --- a/components/offline_pages/core/background/request_queue_unittest.cc +++ b/components/offline_pages/core/background/request_queue_unittest.cc
@@ -28,6 +28,7 @@ using UpdateRequestResult = UpdateRequestResult; namespace { + // Data for request 1. const int64_t kRequestId = 42; const ClientId kClientId("bookmark", "1234"); @@ -38,15 +39,6 @@ const int64_t kRequestId3 = 99; const int kOneWeekInSeconds = 7 * 24 * 60 * 60; -// TODO(https://crbug.com/1042727): Fix test GURL scoping and remove this getter -// function. -GURL Url1() { - return GURL("http://example.com"); -} -GURL Url2() { - return GURL("http://test.com"); -} - // Default request SavePageRequest EmptyRequest() { return SavePageRequest(0UL, GURL(""), ClientId("", ""), base::Time(), true); @@ -215,8 +207,8 @@ TEST_F(RequestQueueTest, AddRequest) { base::Time creation_time = OfflineTimeNow(); - SavePageRequest request(kRequestId, Url1(), kClientId, creation_time, - kUserRequested); + SavePageRequest request(kRequestId, GURL("http://example.com"), kClientId, + creation_time, kUserRequested); queue()->AddRequest(request, RequestQueue::AddOptions(), base::BindOnce(&RequestQueueTest::AddRequestDone, base::Unretained(this))); @@ -234,8 +226,8 @@ TEST_F(RequestQueueTest, RemoveRequest) { base::Time creation_time = OfflineTimeNow(); - SavePageRequest request(kRequestId, Url1(), kClientId, creation_time, - kUserRequested); + SavePageRequest request(kRequestId, GURL("http://example.com"), kClientId, + creation_time, kUserRequested); queue()->AddRequest(request, RequestQueue::AddOptions(), base::BindOnce(&RequestQueueTest::AddRequestDone, base::Unretained(this))); @@ -263,16 +255,16 @@ TEST_F(RequestQueueTest, RemoveSeveralRequests) { base::Time creation_time = OfflineTimeNow(); - SavePageRequest request(kRequestId, Url1(), kClientId, creation_time, - kUserRequested); + SavePageRequest request(kRequestId, GURL("http://example.com"), kClientId, + creation_time, kUserRequested); queue()->AddRequest(request, RequestQueue::AddOptions(), base::BindOnce(&RequestQueueTest::AddRequestDone, base::Unretained(this))); PumpLoop(); ASSERT_EQ(kRequestId, last_added_request()->request_id()); - SavePageRequest request2(kRequestId2, Url2(), kClientId2, creation_time, - kUserRequested); + SavePageRequest request2(kRequestId2, GURL("http://test.com"), kClientId2, + creation_time, kUserRequested); queue()->AddRequest(request2, RequestQueue::AddOptions(), base::BindOnce(&RequestQueueTest::AddRequestDone, base::Unretained(this))); @@ -312,8 +304,8 @@ TEST_F(RequestQueueTest, PauseAndResume) { base::Time creation_time = OfflineTimeNow(); - SavePageRequest request(kRequestId, Url1(), kClientId, creation_time, - kUserRequested); + SavePageRequest request(kRequestId, GURL("http://example.com"), kClientId, + creation_time, kUserRequested); queue()->AddRequest(request, RequestQueue::AddOptions(), base::BindOnce(&RequestQueueTest::AddRequestDone, base::Unretained(this))); @@ -382,15 +374,15 @@ // listing multiple items and removing the right item. TEST_F(RequestQueueTest, MultipleRequestsAddGetRemove) { base::Time creation_time = OfflineTimeNow(); - SavePageRequest request1(kRequestId, Url1(), kClientId, creation_time, - kUserRequested); + SavePageRequest request1(kRequestId, GURL("http://example.com"), kClientId, + creation_time, kUserRequested); queue()->AddRequest(request1, RequestQueue::AddOptions(), base::BindOnce(&RequestQueueTest::AddRequestDone, base::Unretained(this))); PumpLoop(); ASSERT_EQ(request1.request_id(), last_added_request()->request_id()); - SavePageRequest request2(kRequestId2, Url2(), kClientId2, creation_time, - kUserRequested); + SavePageRequest request2(kRequestId2, GURL("http://test.com"), kClientId2, + creation_time, kUserRequested); queue()->AddRequest(request2, RequestQueue::AddOptions(), base::BindOnce(&RequestQueueTest::AddRequestDone, base::Unretained(this))); @@ -425,8 +417,8 @@ TEST_F(RequestQueueTest, MarkAttemptStarted) { // First add a request. Retry count will be set to 0. base::Time creation_time = OfflineTimeNow(); - SavePageRequest request(kRequestId, Url1(), kClientId, creation_time, - kUserRequested); + SavePageRequest request(kRequestId, GURL("http://example.com"), kClientId, + creation_time, kUserRequested); queue()->AddRequest(request, RequestQueue::AddOptions(), base::BindOnce(&RequestQueueTest::AddRequestDone, base::Unretained(this))); @@ -465,8 +457,8 @@ // First add a request. Retry count will be set to 0. base::Time creation_time = OfflineTimeNow(); // This request is never put into the queue. - SavePageRequest request1(kRequestId, Url1(), kClientId, creation_time, - kUserRequested); + SavePageRequest request1(kRequestId, GURL("http://example.com"), kClientId, + creation_time, kUserRequested); queue()->MarkAttemptStarted( kRequestId, base::BindOnce(&RequestQueueTest::UpdateRequestsDone, @@ -481,8 +473,8 @@ TEST_F(RequestQueueTest, MarkAttemptAborted) { base::Time creation_time = OfflineTimeNow(); - SavePageRequest request(kRequestId, Url1(), kClientId, creation_time, - kUserRequested); + SavePageRequest request(kRequestId, GURL("http://example.com"), kClientId, + creation_time, kUserRequested); queue()->AddRequest(request, RequestQueue::AddOptions(), base::BindOnce(&RequestQueueTest::AddRequestDone, base::Unretained(this))); @@ -514,8 +506,8 @@ // First add a request. Retry count will be set to 0. base::Time creation_time = OfflineTimeNow(); // This request is never put into the queue. - SavePageRequest request1(kRequestId, Url1(), kClientId, creation_time, - kUserRequested); + SavePageRequest request1(kRequestId, GURL("http://example.com"), kClientId, + creation_time, kUserRequested); queue()->MarkAttemptAborted( kRequestId, base::BindOnce(&RequestQueueTest::UpdateRequestsDone, @@ -530,8 +522,8 @@ TEST_F(RequestQueueTest, MarkAttemptCompleted) { base::Time creation_time = OfflineTimeNow(); - SavePageRequest request(kRequestId, Url1(), kClientId, creation_time, - kUserRequested); + SavePageRequest request(kRequestId, GURL("http://example.com"), kClientId, + creation_time, kUserRequested); queue()->AddRequest(request, RequestQueue::AddOptions(), base::BindOnce(&RequestQueueTest::AddRequestDone, base::Unretained(this))); @@ -565,8 +557,8 @@ base::Time creation_time = OfflineTimeNow() - base::TimeDelta::FromSeconds(2 * kOneWeekInSeconds); - SavePageRequest original_request(kRequestId, Url1(), kClientId, creation_time, - kUserRequested); + SavePageRequest original_request(kRequestId, GURL("http://example.com"), + kClientId, creation_time, kUserRequested); queue()->AddRequest(original_request, RequestQueue::AddOptions(), base::BindOnce(&RequestQueueTest::AddRequestDone, base::Unretained(this)));
diff --git a/components/offline_pages/core/background/save_page_request_unittest.cc b/components/offline_pages/core/background/save_page_request_unittest.cc index 6fef0daa..a7b6ab8 100644 --- a/components/offline_pages/core/background/save_page_request_unittest.cc +++ b/components/offline_pages/core/background/save_page_request_unittest.cc
@@ -10,20 +10,12 @@ namespace offline_pages { namespace { + const int64_t kRequestId = 42; const ClientId kClientId("bookmark", "1234"); const bool kUserRequested = true; const std::string kRequestOrigin = "abc.xyz"; -// TODO(https://crbug.com/1042727): Fix test GURL scoping and remove this getter -// function. -GURL Url1() { - return GURL("http://example.com"); -} -GURL Url2() { - return GURL("http://example.com/test"); -} - } // namespace class SavePageRequestTest : public testing::Test { @@ -34,12 +26,14 @@ SavePageRequestTest::~SavePageRequestTest() {} TEST_F(SavePageRequestTest, CreatePendingReqeust) { + const GURL kUrl1("http://example.com"); + const GURL kUrl2("http://example.com/test"); base::Time creation_time = OfflineTimeNow(); - SavePageRequest request(kRequestId, Url1(), kClientId, creation_time, + SavePageRequest request(kRequestId, kUrl1, kClientId, creation_time, kUserRequested); - request.set_original_url(Url2()); + request.set_original_url(kUrl2); EXPECT_EQ(kRequestId, request.request_id()); - EXPECT_EQ(Url1(), request.url()); + EXPECT_EQ(kUrl1, request.url()); EXPECT_EQ(kClientId, request.client_id()); EXPECT_EQ(creation_time, request.creation_time()); EXPECT_EQ(base::Time(), request.last_attempt_time()); @@ -47,13 +41,14 @@ EXPECT_EQ(SavePageRequest::RequestState::AVAILABLE, request.request_state()); EXPECT_EQ(0, request.started_attempt_count()); EXPECT_EQ(0, request.completed_attempt_count()); - EXPECT_EQ(Url2(), request.original_url()); + EXPECT_EQ(kUrl2, request.original_url()); EXPECT_EQ("", request.request_origin()); } TEST_F(SavePageRequestTest, StartAndCompleteRequest) { + const GURL kUrl1("http://example.com"); base::Time creation_time = OfflineTimeNow(); - SavePageRequest request(kRequestId, Url1(), kClientId, creation_time, + SavePageRequest request(kRequestId, kUrl1, kClientId, creation_time, kUserRequested); request.set_request_origin(kRequestOrigin); @@ -62,7 +57,7 @@ // Most things don't change about the request. EXPECT_EQ(kRequestId, request.request_id()); - EXPECT_EQ(Url1(), request.url()); + EXPECT_EQ(kUrl1, request.url()); EXPECT_EQ(kClientId, request.client_id()); EXPECT_EQ(creation_time, request.creation_time()); EXPECT_EQ(kRequestOrigin, request.request_origin()); @@ -76,7 +71,7 @@ // Again, most things don't change about the request. EXPECT_EQ(kRequestId, request.request_id()); - EXPECT_EQ(Url1(), request.url()); + EXPECT_EQ(kUrl1, request.url()); EXPECT_EQ(kClientId, request.client_id()); EXPECT_EQ(creation_time, request.creation_time()); @@ -86,8 +81,9 @@ } TEST_F(SavePageRequestTest, StartAndAbortRequest) { + const GURL kUrl1("http://example.com"); base::Time creation_time = OfflineTimeNow(); - SavePageRequest request(kRequestId, Url1(), kClientId, creation_time, + SavePageRequest request(kRequestId, kUrl1, kClientId, creation_time, kUserRequested); base::Time start_time = creation_time + base::TimeDelta::FromHours(3); @@ -95,7 +91,7 @@ // Most things don't change about the request. EXPECT_EQ(kRequestId, request.request_id()); - EXPECT_EQ(Url1(), request.url()); + EXPECT_EQ(kUrl1, request.url()); EXPECT_EQ(kClientId, request.client_id()); EXPECT_EQ(creation_time, request.creation_time()); EXPECT_EQ("", request.request_origin()); @@ -109,7 +105,7 @@ // Again, most things don't change about the request. EXPECT_EQ(kRequestId, request.request_id()); - EXPECT_EQ(Url1(), request.url()); + EXPECT_EQ(kUrl1, request.url()); EXPECT_EQ(kClientId, request.client_id()); EXPECT_EQ(creation_time, request.creation_time()); EXPECT_EQ("", request.request_origin());
diff --git a/components/offline_pages/core/downloads/offline_item_conversions_unittest.cc b/components/offline_pages/core/downloads/offline_item_conversions_unittest.cc index e2b71fe..42c6450e 100644 --- a/components/offline_pages/core/downloads/offline_item_conversions_unittest.cc +++ b/components/offline_pages/core/downloads/offline_item_conversions_unittest.cc
@@ -19,18 +19,6 @@ namespace offline_pages { -namespace { -// TODO(https://crbug.com/1042727): Fix test GURL scoping and remove this getter -// function. -GURL TestUrl() { - return GURL("http://www.example.com"); -} -GURL TestOriginalUrl() { - return GURL("http://www.exampleoriginalurl.com"); -} - -} // namespace - TEST(OfflineItemConversionsTest, OfflinePageItemConversion) { std::string name_space = "test_namespace"; std::string guid = "test_guid"; @@ -42,9 +30,11 @@ base::Time last_access_time = base::Time::Now(); std::string title = "test title"; - OfflinePageItem offline_page_item(TestUrl(), offline_id, client_id, file_path, + const GURL kTestUrl("http://www.example.com"); + const GURL kTestOriginalUrl("http://www.exampleoriginalurl.com"); + OfflinePageItem offline_page_item(kTestUrl, offline_id, client_id, file_path, file_size, creation_time); - offline_page_item.original_url_if_different = TestOriginalUrl(); + offline_page_item.original_url_if_different = kTestOriginalUrl; offline_page_item.title = base::UTF8ToUTF16(title); offline_page_item.last_access_time = last_access_time; offline_page_item.file_missing_time = base::Time::Now(); @@ -53,8 +43,8 @@ OfflineItemConversions::CreateOfflineItem(offline_page_item, true); EXPECT_EQ(ContentId(kOfflinePageNamespace, guid), offline_item.id); - EXPECT_EQ(TestUrl(), offline_item.page_url); - EXPECT_EQ(TestOriginalUrl(), offline_item.original_url); + EXPECT_EQ(kTestUrl, offline_item.page_url); + EXPECT_EQ(kTestOriginalUrl, offline_item.original_url); EXPECT_EQ(title, offline_item.title); EXPECT_EQ(file_path, offline_item.file_path); EXPECT_EQ(creation_time, offline_item.creation_time); @@ -93,9 +83,11 @@ int64_t request_id = 5; base::Time creation_time = base::Time::Now(); - SavePageRequest save_page_request(request_id, TestUrl(), client_id, + const GURL kTestUrl("http://www.example.com"); + const GURL kTestOriginalUrl("http://www.exampleoriginalurl.com"); + SavePageRequest save_page_request(request_id, kTestUrl, client_id, creation_time, false); - save_page_request.set_original_url(TestOriginalUrl()); + save_page_request.set_original_url(kTestOriginalUrl); save_page_request.set_request_state(SavePageRequest::RequestState::OFFLINING); save_page_request.set_fail_state(FailState::NETWORK_FAILED); save_page_request.set_pending_state(PendingState::PENDING_ANOTHER_DOWNLOAD); @@ -104,9 +96,9 @@ OfflineItemConversions::CreateOfflineItem(save_page_request); EXPECT_EQ(ContentId(kOfflinePageNamespace, guid), offline_item.id); - EXPECT_EQ(TestUrl(), offline_item.page_url); - EXPECT_EQ(TestOriginalUrl(), offline_item.original_url); - EXPECT_EQ(TestUrl().host(), offline_item.title); + EXPECT_EQ(kTestUrl, offline_item.page_url); + EXPECT_EQ(kTestOriginalUrl, offline_item.original_url); + EXPECT_EQ(kTestUrl.host(), offline_item.title); EXPECT_EQ(base::FilePath(), offline_item.file_path); EXPECT_EQ(creation_time, offline_item.creation_time); EXPECT_EQ(base::Time(), offline_item.completion_time);
diff --git a/components/offline_pages/core/model/add_page_task_unittest.cc b/components/offline_pages/core/model/add_page_task_unittest.cc index 9ece524..ffcc911 100644 --- a/components/offline_pages/core/model/add_page_task_unittest.cc +++ b/components/offline_pages/core/model/add_page_task_unittest.cc
@@ -38,15 +38,6 @@ const std::string kTestAttribution = "attribution"; const std::string kTestSnippet = "snippet"; -// TODO(https://crbug.com/1042727): Fix test GURL scoping and remove this getter -// function. -GURL TestUrl1() { - return GURL("http://example.com"); -} -GURL TestUrl2() { - return GURL("http://other.page.com"); -} - } // namespace class AddPageTaskTest : public ModelTaskTestBase { @@ -100,11 +91,12 @@ } TEST_F(AddPageTaskTest, AddPageWithAllFieldsSet) { - OfflinePageItem page(TestUrl1(), kTestOfflineId1, kTestClientId1, - kTestFilePath, kTestFileSize, base::Time::Now()); + OfflinePageItem page(GURL("http://example.com"), kTestOfflineId1, + kTestClientId1, kTestFilePath, kTestFileSize, + base::Time::Now()); page.request_origin = kTestOrigin; page.title = kTestTitle; - page.original_url_if_different = TestUrl2(); + page.original_url_if_different = GURL("http://other.page.com"); page.system_download_id = kTestDownloadId; page.file_missing_time = base::Time::Now(); page.digest = kTestDigest;
diff --git a/components/offline_pages/core/model/delete_page_task_unittest.cc b/components/offline_pages/core/model/delete_page_task_unittest.cc index 2bb7a1b..7c49bad2 100644 --- a/components/offline_pages/core/model/delete_page_task_unittest.cc +++ b/components/offline_pages/core/model/delete_page_task_unittest.cc
@@ -32,19 +32,6 @@ const char kTestNamespace[] = "default"; const ClientId kTestClientIdNoMatch(kTestNamespace, "20170905"); -// TODO(https://crbug.com/1042727): Fix test GURL scoping and remove this getter -// function. -GURL TestUrl1() { - return GURL("http://example.com"); -} -GURL TestUrl2() { - return GURL("http://other.page.com"); -} - -GURL OriginalUrl() { - return GURL("http://original.com"); -} - } // namespace class DeletePageTaskTest : public ModelTaskTestBase { @@ -105,10 +92,11 @@ // Delete a page and verify all the information in deleted_pages is accurate. TEST_F(DeletePageTaskTest, OfflinePageItemIsPopulated) { + const GURL kOriginalUrl("http://original.com"); generator()->SetNamespace(kTestNamespace); OfflinePageItem page1 = generator()->CreateItemWithTempFile(); - page1.url = TestUrl1(); - page1.original_url_if_different = OriginalUrl(); + page1.url = GURL("http://example.com"); + page1.original_url_if_different = kOriginalUrl; page1.request_origin = "test-origin"; page1.system_download_id = 1234; store_test_util()->InsertItem(page1); @@ -130,18 +118,19 @@ EXPECT_EQ(page1.request_origin, item.request_origin); EXPECT_EQ(page1.system_download_id, item.system_download_id); EXPECT_EQ(page1.offline_id, item.offline_id); - EXPECT_EQ(OriginalUrl(), item.original_url_if_different); - EXPECT_EQ(OriginalUrl(), item.GetOriginalUrl()); + EXPECT_EQ(kOriginalUrl, item.original_url_if_different); + EXPECT_EQ(kOriginalUrl, item.GetOriginalUrl()); } TEST_F(DeletePageTaskTest, DeletePageByUrlPredicate) { // Add 3 pages and try to delete 2 of them using url predicate. + const std::string kExample = "example.com"; generator()->SetNamespace(kTestNamespace); - generator()->SetUrl(TestUrl1()); + generator()->SetUrl(GURL("http://" + kExample)); OfflinePageItem page1 = generator()->CreateItemWithTempFile(); generator()->SetAccessCount(200); OfflinePageItem page2 = generator()->CreateItemWithTempFile(); - generator()->SetUrl(TestUrl2()); + generator()->SetUrl(GURL("http://other.page.com")); OfflinePageItem page3 = generator()->CreateItemWithTempFile(); store_test_util()->InsertItem(page1); @@ -153,10 +142,12 @@ EXPECT_TRUE(base::PathExists(page2.file_path)); EXPECT_TRUE(base::PathExists(page3.file_path)); - // Delete all pages with url contains example.com, which are with TestUrl1(). - UrlPredicate predicate = base::BindRepeating([](const GURL& url) -> bool { - return url.spec().find("example.com") != std::string::npos; - }); + // Delete all pages with url contains kExample. + UrlPredicate predicate = base::BindRepeating( + [](const std::string& to_find, const GURL& url) -> bool { + return url.spec().find(to_find) != std::string::npos; + }, + kExample); auto task = DeletePageTask::CreateTaskMatchingUrlPredicateForCachedPages( store(), delete_page_callback(), predicate); @@ -188,10 +179,10 @@ TEST_F(DeletePageTaskTest, DeletePageByUrlPredicateNotFound) { // Add 3 pages and try to delete 2 of them using url predicate. generator()->SetNamespace(kTestNamespace); - generator()->SetUrl(TestUrl1()); + generator()->SetUrl(GURL("http://example.com")); OfflinePageItem page1 = generator()->CreateItemWithTempFile(); OfflinePageItem page2 = generator()->CreateItemWithTempFile(); - generator()->SetUrl(TestUrl2()); + generator()->SetUrl(GURL("http://other.page.com")); OfflinePageItem page3 = generator()->CreateItemWithTempFile(); store_test_util()->InsertItem(page1); @@ -229,7 +220,7 @@ TEST_F(DeletePageTaskTest, DeletePageForPageLimit) { // Add 3 pages, the kTestNamespace has a limit of 1 for page per url. generator()->SetNamespace(kTestNamespace); - generator()->SetUrl(TestUrl1()); + generator()->SetUrl(GURL("http://example.com")); // Guarantees that page1 will be deleted by making it older. base::Time now = OfflineTimeNow(); generator()->SetLastAccessTime(now - base::TimeDelta::FromMinutes(5)); @@ -237,7 +228,7 @@ generator()->SetLastAccessTime(now); OfflinePageItem page2 = generator()->CreateItemWithTempFile(); OfflinePageItem page = generator()->CreateItem(); - generator()->SetUrl(TestUrl2()); + generator()->SetUrl(GURL("http://other.page.com")); OfflinePageItem page3 = generator()->CreateItemWithTempFile(); store_test_util()->InsertItem(page1); @@ -271,11 +262,11 @@ TEST_F(DeletePageTaskTest, DeletePageForPageLimit_UnlimitedNamespace) { // Add 3 pages, the kTestNamespace has a limit of 1 for page per url. generator()->SetNamespace(kDownloadNamespace); - generator()->SetUrl(TestUrl1()); + generator()->SetUrl(GURL("http://example.com")); OfflinePageItem page1 = generator()->CreateItemWithTempFile(); OfflinePageItem page2 = generator()->CreateItemWithTempFile(); OfflinePageItem page = generator()->CreateItem(); - generator()->SetUrl(TestUrl2()); + generator()->SetUrl(GURL("http://other.page.com")); OfflinePageItem page3 = generator()->CreateItemWithTempFile(); store_test_util()->InsertItem(page1);
diff --git a/components/offline_pages/core/model/mark_page_accessed_task_unittest.cc b/components/offline_pages/core/model/mark_page_accessed_task_unittest.cc index 2b4eac5..9d83c140 100644 --- a/components/offline_pages/core/model/mark_page_accessed_task_unittest.cc +++ b/components/offline_pages/core/model/mark_page_accessed_task_unittest.cc
@@ -16,18 +16,13 @@ namespace offline_pages { namespace { + const int64_t kTestOfflineId = 1234LL; const char kTestClientNamespace[] = "default"; const ClientId kTestClientId(kTestClientNamespace, "1234"); const base::FilePath kTestFilePath(FILE_PATH_LITERAL("/test/path/file")); const int64_t kTestFileSize = 876543LL; -// TODO(https://crbug.com/1042727): Fix test GURL scoping and remove this getter -// function. -GURL TestUrl() { - return GURL("http://example.com"); -} - } // namespace class MarkPageAccessedTaskTest : public ModelTaskTestBase { @@ -39,7 +34,8 @@ }; TEST_F(MarkPageAccessedTaskTest, MarkPageAccessed) { - OfflinePageItem page(TestUrl(), kTestOfflineId, kTestClientId, kTestFilePath, + const GURL kTestUrl("http://example.com"); + OfflinePageItem page(kTestUrl, kTestOfflineId, kTestClientId, kTestFilePath, kTestFileSize); store_test_util()->InsertItem(page); @@ -49,7 +45,7 @@ RunTask(std::move(task)); auto offline_page = store_test_util()->GetPageByOfflineId(kTestOfflineId); - EXPECT_EQ(TestUrl(), offline_page->url); + EXPECT_EQ(kTestUrl, offline_page->url); EXPECT_EQ(kTestClientId, offline_page->client_id); EXPECT_EQ(kTestFileSize, offline_page->file_size); EXPECT_EQ(1, offline_page->access_count); @@ -65,7 +61,8 @@ } TEST_F(MarkPageAccessedTaskTest, MarkPageAccessedTwice) { - OfflinePageItem page(TestUrl(), kTestOfflineId, kTestClientId, kTestFilePath, + const GURL kTestUrl("http://example.com"); + OfflinePageItem page(kTestUrl, kTestOfflineId, kTestClientId, kTestFilePath, kTestFileSize); store_test_util()->InsertItem(page); @@ -76,7 +73,7 @@ auto offline_page = store_test_util()->GetPageByOfflineId(kTestOfflineId); EXPECT_EQ(kTestOfflineId, offline_page->offline_id); - EXPECT_EQ(TestUrl(), offline_page->url); + EXPECT_EQ(kTestUrl, offline_page->url); EXPECT_EQ(kTestClientId, offline_page->client_id); EXPECT_EQ(kTestFileSize, offline_page->file_size); EXPECT_EQ(1, offline_page->access_count);
diff --git a/components/offline_pages/core/model/offline_page_model_taskified_unittest.cc b/components/offline_pages/core/model/offline_page_model_taskified_unittest.cc index 0b69852..0389907 100644 --- a/components/offline_pages/core/model/offline_page_model_taskified_unittest.cc +++ b/components/offline_pages/core/model/offline_page_model_taskified_unittest.cc
@@ -56,6 +56,7 @@ using ClearStorageResult = ClearStorageTask::ClearStorageResult; namespace { + const ClientId kTestClientId1(kDefaultNamespace, "1234"); const ClientId kTestClientId2(kDefaultNamespace, "5678"); const ClientId kTestUserRequestedClientId(kDownloadNamespace, "714"); @@ -68,27 +69,6 @@ const char kTestDigest[] = "test digest"; const int64_t kDownloadId = 42LL; -// TODO(https://crbug.com/1042727): Fix test GURL scoping and remove this getter -// function. -GURL TestUrl() { - return GURL("http://example.com"); -} -GURL TestUrl2() { - return GURL("http://other.page.com"); -} -GURL TestUrlWithFragment() { - return GURL("http://example.com#frag"); -} -GURL TestUrl2WithFragment() { - return GURL("http://other.page.com#frag"); -} -GURL OtherUrl() { - return GURL("http://foo"); -} -GURL FileUrl() { - return GURL("file:///foo"); -} - } // namespace class OfflinePageModelTaskifiedTest : public testing::Test, @@ -369,11 +349,12 @@ // Tests saving successfully a non-user-requested offline page. TEST_F(OfflinePageModelTaskifiedTest, SavePageSuccessful) { - auto archiver = - BuildArchiver(TestUrl(), ArchiverResult::SUCCESSFULLY_CREATED); + const GURL kTestUrl("http://example.com"); + auto archiver = BuildArchiver(kTestUrl, ArchiverResult::SUCCESSFULLY_CREATED); + const GURL kTestUrl2("http://other.page.com"); int64_t offline_id = SavePageWithExpectedResult( - TestUrl(), kTestClientId1, TestUrl2(), kEmptyRequestOrigin, + kTestUrl, kTestClientId1, kTestUrl2, kEmptyRequestOrigin, std::move(archiver), SavePageResult::SUCCESS); EXPECT_EQ(1UL, test_utils::GetFileCountInDirectory(temporary_dir_path())); @@ -381,7 +362,7 @@ auto saved_page_ptr = store_test_util()->GetPageByOfflineId(offline_id); ASSERT_TRUE(saved_page_ptr); - EXPECT_EQ(TestUrl(), saved_page_ptr->url); + EXPECT_EQ(kTestUrl, saved_page_ptr->url); EXPECT_EQ(kTestClientId1.id, saved_page_ptr->client_id.id); EXPECT_EQ(kTestClientId1.name_space, saved_page_ptr->client_id.name_space); EXPECT_EQ(last_path_created_by_archiver(), saved_page_ptr->file_path); @@ -389,7 +370,7 @@ EXPECT_EQ(0, saved_page_ptr->access_count); EXPECT_EQ(0, saved_page_ptr->flags); EXPECT_EQ(kTestTitle, saved_page_ptr->title); - EXPECT_EQ(TestUrl2(), saved_page_ptr->original_url_if_different); + EXPECT_EQ(kTestUrl2, saved_page_ptr->original_url_if_different); EXPECT_EQ("", saved_page_ptr->request_origin); EXPECT_EQ(kTestDigest, saved_page_ptr->digest); @@ -431,12 +412,12 @@ } TEST_F(OfflinePageModelTaskifiedTest, SavePageSuccessfulWithSameOriginalUrl) { - auto archiver = - BuildArchiver(TestUrl(), ArchiverResult::SUCCESSFULLY_CREATED); + const GURL kTestUrl("http://example.com"); + auto archiver = BuildArchiver(kTestUrl, ArchiverResult::SUCCESSFULLY_CREATED); // Pass the original URL same as the final URL. int64_t offline_id = SavePageWithExpectedResult( - TestUrl(), kTestClientId1, TestUrl(), kEmptyRequestOrigin, + kTestUrl, kTestClientId1, kTestUrl, kEmptyRequestOrigin, std::move(archiver), SavePageResult::SUCCESS); EXPECT_EQ(1UL, test_utils::GetFileCountInDirectory(temporary_dir_path())); @@ -444,7 +425,7 @@ auto saved_page_ptr = store_test_util()->GetPageByOfflineId(offline_id); ASSERT_TRUE(saved_page_ptr); - EXPECT_EQ(TestUrl(), saved_page_ptr->url); + EXPECT_EQ(kTestUrl, saved_page_ptr->url); // The original URL should be empty. EXPECT_TRUE(saved_page_ptr->original_url_if_different.is_empty()); @@ -463,11 +444,12 @@ } TEST_F(OfflinePageModelTaskifiedTest, SavePageSuccessfulWithRequestOrigin) { - auto archiver = - BuildArchiver(TestUrl(), ArchiverResult::SUCCESSFULLY_CREATED); + const GURL kTestUrl("http://example.com"); + auto archiver = BuildArchiver(kTestUrl, ArchiverResult::SUCCESSFULLY_CREATED); + const GURL kTestUrl2("http://other.page.com"); int64_t offline_id = SavePageWithExpectedResult( - TestUrl(), kTestClientId1, TestUrl2(), kTestRequestOrigin, + kTestUrl, kTestClientId1, kTestUrl2, kTestRequestOrigin, std::move(archiver), SavePageResult::SUCCESS); EXPECT_EQ(1UL, test_utils::GetFileCountInDirectory(temporary_dir_path())); @@ -475,7 +457,7 @@ auto saved_page_ptr = store_test_util()->GetPageByOfflineId(offline_id); ASSERT_TRUE(saved_page_ptr); - EXPECT_EQ(TestUrl(), saved_page_ptr->url); + EXPECT_EQ(kTestUrl, saved_page_ptr->url); EXPECT_EQ(kTestClientId1.id, saved_page_ptr->client_id.id); EXPECT_EQ(kTestClientId1.name_space, saved_page_ptr->client_id.name_space); EXPECT_EQ(last_path_created_by_archiver(), saved_page_ptr->file_path); @@ -483,7 +465,7 @@ EXPECT_EQ(0, saved_page_ptr->access_count); EXPECT_EQ(0, saved_page_ptr->flags); EXPECT_EQ(kTestTitle, saved_page_ptr->title); - EXPECT_EQ(TestUrl2(), saved_page_ptr->original_url_if_different); + EXPECT_EQ(kTestUrl2, saved_page_ptr->original_url_if_different); EXPECT_EQ(kTestRequestOrigin, saved_page_ptr->request_origin); histogram_tester()->ExpectUniqueSample( @@ -501,10 +483,11 @@ } TEST_F(OfflinePageModelTaskifiedTest, SavePageOfflineArchiverCancelled) { - auto archiver = BuildArchiver(TestUrl(), ArchiverResult::ERROR_CANCELED); - SavePageWithExpectedResult(TestUrl(), kTestClientId1, TestUrl2(), - kEmptyRequestOrigin, std::move(archiver), - SavePageResult::CANCELLED); + const GURL kTestUrl("http://example.com"); + auto archiver = BuildArchiver(kTestUrl, ArchiverResult::ERROR_CANCELED); + SavePageWithExpectedResult(kTestUrl, kTestClientId1, + GURL("http://other.page.com"), kEmptyRequestOrigin, + std::move(archiver), SavePageResult::CANCELLED); histogram_tester()->ExpectUniqueSample( model_utils::AddHistogramSuffix(kTestClientId1.name_space, @@ -521,10 +504,11 @@ } TEST_F(OfflinePageModelTaskifiedTest, SavePageOfflineArchiverDeviceFull) { - auto archiver = BuildArchiver(TestUrl(), ArchiverResult::ERROR_DEVICE_FULL); - SavePageWithExpectedResult(TestUrl(), kTestClientId1, TestUrl2(), - kEmptyRequestOrigin, std::move(archiver), - SavePageResult::DEVICE_FULL); + const GURL kTestUrl("http://example.com"); + auto archiver = BuildArchiver(kTestUrl, ArchiverResult::ERROR_DEVICE_FULL); + SavePageWithExpectedResult(kTestUrl, kTestClientId1, + GURL("http://other.page.com"), kEmptyRequestOrigin, + std::move(archiver), SavePageResult::DEVICE_FULL); histogram_tester()->ExpectUniqueSample( model_utils::AddHistogramSuffix(kTestClientId1.name_space, @@ -542,10 +526,12 @@ TEST_F(OfflinePageModelTaskifiedTest, SavePageOfflineArchiverContentUnavailable) { + const GURL kTestUrl("http://example.com"); auto archiver = - BuildArchiver(TestUrl(), ArchiverResult::ERROR_CONTENT_UNAVAILABLE); - SavePageWithExpectedResult(TestUrl(), kTestClientId1, TestUrl2(), - kEmptyRequestOrigin, std::move(archiver), + BuildArchiver(kTestUrl, ArchiverResult::ERROR_CONTENT_UNAVAILABLE); + SavePageWithExpectedResult(kTestUrl, kTestClientId1, + GURL("http://other.page.com"), kEmptyRequestOrigin, + std::move(archiver), SavePageResult::CONTENT_UNAVAILABLE); histogram_tester()->ExpectUniqueSample( @@ -563,10 +549,12 @@ } TEST_F(OfflinePageModelTaskifiedTest, SavePageOfflineCreationFailed) { + const GURL kTestUrl("http://example.com"); auto archiver = - BuildArchiver(TestUrl(), ArchiverResult::ERROR_ARCHIVE_CREATION_FAILED); - SavePageWithExpectedResult(TestUrl(), kTestClientId1, TestUrl2(), - kEmptyRequestOrigin, std::move(archiver), + BuildArchiver(kTestUrl, ArchiverResult::ERROR_ARCHIVE_CREATION_FAILED); + SavePageWithExpectedResult(kTestUrl, kTestClientId1, + GURL("http://other.page.com"), kEmptyRequestOrigin, + std::move(archiver), SavePageResult::ARCHIVE_CREATION_FAILED); histogram_tester()->ExpectUniqueSample( @@ -586,9 +574,9 @@ TEST_F(OfflinePageModelTaskifiedTest, SavePageOfflineArchiverReturnedWrongUrl) { auto archiver = BuildArchiver(GURL("http://other.random.url.com"), ArchiverResult::SUCCESSFULLY_CREATED); - SavePageWithExpectedResult(TestUrl(), kTestClientId1, TestUrl2(), - kEmptyRequestOrigin, std::move(archiver), - SavePageResult::INCORRECT_URL); + SavePageWithExpectedResult( + GURL("http://example.com"), kTestClientId1, GURL("http://other.page.com"), + kEmptyRequestOrigin, std::move(archiver), SavePageResult::INCORRECT_URL); histogram_tester()->ExpectUniqueSample( model_utils::AddHistogramSuffix(kTestClientId1.name_space, @@ -611,9 +599,10 @@ DISABLED_SavePageOfflineCreationStoreWriteFailure) {} TEST_F(OfflinePageModelTaskifiedTest, SavePageLocalFileFailed) { - SavePageWithExpectedResult( - FileUrl(), kTestClientId1, TestUrl2(), kEmptyRequestOrigin, - std::unique_ptr<OfflinePageTestArchiver>(), SavePageResult::SKIPPED); + SavePageWithExpectedResult(GURL("file:///foo"), kTestClientId1, + GURL("http://other.page.com"), kEmptyRequestOrigin, + std::unique_ptr<OfflinePageTestArchiver>(), + SavePageResult::SKIPPED); histogram_tester()->ExpectUniqueSample( model_utils::AddHistogramSuffix(kTestClientId1.name_space, @@ -650,16 +639,17 @@ // delayed_archiver_ptr will be valid until after first PumpLoop() call after // CompleteCreateArchive() is called. Keeping the raw pointer because the // ownership is transferring to the model. - auto archiver = - BuildArchiver(TestUrl(), ArchiverResult::SUCCESSFULLY_CREATED); + const GURL kTestUrl("http://example.com"); + auto archiver = BuildArchiver(kTestUrl, ArchiverResult::SUCCESSFULLY_CREATED); OfflinePageTestArchiver* delayed_archiver_ptr = archiver.get(); delayed_archiver_ptr->set_delayed(true); - SavePageWithCallback(TestUrl(), kTestClientId1, GURL(), kEmptyRequestOrigin, + SavePageWithCallback(kTestUrl, kTestClientId1, GURL(), kEmptyRequestOrigin, std::move(archiver), callback.Get()); // Request to save another page, with request origin. - archiver = BuildArchiver(TestUrl2(), ArchiverResult::SUCCESSFULLY_CREATED); - SavePageWithCallback(TestUrl2(), kTestClientId2, GURL(), kTestRequestOrigin, + const GURL kTestUrl2("http://other.page.com"); + archiver = BuildArchiver(kTestUrl2, ArchiverResult::SUCCESSFULLY_CREATED); + SavePageWithCallback(kTestUrl2, kTestClientId2, GURL(), kTestRequestOrigin, std::move(archiver), callback.Get()); EXPECT_EQ(1UL, test_utils::GetFileCountInDirectory(temporary_dir_path())); @@ -695,13 +685,13 @@ ASSERT_TRUE(saved_page_ptr1); ASSERT_TRUE(saved_page_ptr2); - EXPECT_EQ(TestUrl2(), saved_page_ptr1->url); + EXPECT_EQ(kTestUrl2, saved_page_ptr1->url); EXPECT_EQ(kTestClientId2, saved_page_ptr1->client_id); EXPECT_EQ(saved_file_path1, saved_page_ptr1->file_path); EXPECT_EQ(kTestFileSize, saved_page_ptr1->file_size); EXPECT_EQ(kTestRequestOrigin, saved_page_ptr1->request_origin); - EXPECT_EQ(TestUrl(), saved_page_ptr2->url); + EXPECT_EQ(GURL("http://example.com"), saved_page_ptr2->url); EXPECT_EQ(kTestClientId1, saved_page_ptr2->client_id); EXPECT_EQ(saved_file_path2, saved_page_ptr2->file_path); EXPECT_EQ(kTestFileSize, saved_page_ptr2->file_size); @@ -721,14 +711,14 @@ } TEST_F(OfflinePageModelTaskifiedTest, SavePageOnBackground) { - auto archiver = - BuildArchiver(TestUrl(), ArchiverResult::SUCCESSFULLY_CREATED); + const GURL kTestUrl("http://example.com"); + auto archiver = BuildArchiver(kTestUrl, ArchiverResult::SUCCESSFULLY_CREATED); OfflinePageTestArchiver* archiver_ptr = archiver.get(); OfflinePageModel::SavePageParams save_page_params; - save_page_params.url = TestUrl(); + save_page_params.url = kTestUrl; save_page_params.client_id = kTestClientId1; - save_page_params.original_url = TestUrl2(); + save_page_params.original_url = GURL("http://other.page.com"); save_page_params.is_background = true; save_page_params.use_page_problem_detectors = false; @@ -744,7 +734,7 @@ } TEST_F(OfflinePageModelTaskifiedTest, SavePageWithNullArchiver) { - SavePageWithExpectedResult(TestUrl(), kTestClientId1, GURL(), + SavePageWithExpectedResult(GURL("http://example.com"), kTestClientId1, GURL(), kEmptyRequestOrigin, nullptr, SavePageResult::CONTENT_UNAVAILABLE); histogram_tester()->ExpectUniqueSample( @@ -873,11 +863,12 @@ } TEST_F(OfflinePageModelTaskifiedTest, DeletePagesByUrlPredicate) { + const GURL kTestUrl("http://example.com"); page_generator()->SetArchiveDirectory(temporary_dir_path()); page_generator()->SetNamespace(kDefaultNamespace); - page_generator()->SetUrl(TestUrl()); + page_generator()->SetUrl(kTestUrl); OfflinePageItem page1 = page_generator()->CreateItemWithTempFile(); - page_generator()->SetUrl(TestUrl2()); + page_generator()->SetUrl(GURL("http://other.page.com")); OfflinePageItem page2 = page_generator()->CreateItemWithTempFile(); InsertPageIntoStore(page1); InsertPageIntoStore(page2); @@ -892,7 +883,7 @@ [](const GURL& expected_url, const GURL& url) -> bool { return url == expected_url; }, - TestUrl()); + kTestUrl); model()->DeleteCachedPagesByURLPredicate(predicate, callback.Get()); EXPECT_TRUE(task_queue()->HasRunningTask()); @@ -922,7 +913,7 @@ TEST_F(OfflinePageModelTaskifiedTest, GetPageByOfflineId) { page_generator()->SetNamespace(kDefaultNamespace); - page_generator()->SetUrl(TestUrl()); + page_generator()->SetUrl(GURL("http://example.com")); OfflinePageItem page = page_generator()->CreateItem(); InsertPageIntoStore(page); @@ -936,31 +927,33 @@ } TEST_F(OfflinePageModelTaskifiedTest, GetPagesWithCriteria_FinalUrl) { - page_generator()->SetUrl(TestUrl()); + const GURL kTestUrl("http://example.com"); + const GURL kTestUrl2("http://other.page.com"); + page_generator()->SetUrl(kTestUrl); OfflinePageItem page1 = page_generator()->CreateItem(); InsertPageIntoStore(page1); - page_generator()->SetUrl(TestUrl2()); + page_generator()->SetUrl(kTestUrl2); OfflinePageItem page2 = page_generator()->CreateItem(); InsertPageIntoStore(page2); - // Search by TestUrl(). + // Search by kTestUrl. base::MockCallback<MultipleOfflinePageItemCallback> callback; EXPECT_CALL(callback, Run(ElementsAre(page1))); PageCriteria criteria; - criteria.url = TestUrl(); + criteria.url = kTestUrl; model()->GetPagesWithCriteria(criteria, callback.Get()); EXPECT_TRUE(task_queue()->HasRunningTask()); PumpLoop(); - // Search by TestUrl2(). + // Search by kTestUrl2. EXPECT_CALL(callback, Run(ElementsAre(page2))); - criteria.url = TestUrl2(); + criteria.url = kTestUrl2; model()->GetPagesWithCriteria(criteria, callback.Get()); PumpLoop(); // Search by random url, which should return no pages. EXPECT_CALL(callback, Run(IsEmpty())); - criteria.url = OtherUrl(); + criteria.url = GURL("http://foo"); model()->GetPagesWithCriteria(criteria, callback.Get()); EXPECT_TRUE(task_queue()->HasRunningTask()); PumpLoop(); @@ -968,43 +961,48 @@ TEST_F(OfflinePageModelTaskifiedTest, GetPagesByUrl_FinalUrlWithFragmentStripped) { - page_generator()->SetUrl(TestUrl()); + const GURL kTestUrl("http://example.com"); + const GURL kTestUrlWithFragment("http://example.com#frag"); + const GURL kTestUrl2("http://other.page.com"); + const GURL kTestUrl2WithFragment("http://other.page.com#frag"); + page_generator()->SetUrl(kTestUrl); OfflinePageItem page1 = page_generator()->CreateItem(); InsertPageIntoStore(page1); - page_generator()->SetUrl(TestUrl2WithFragment()); + page_generator()->SetUrl(kTestUrl2WithFragment); OfflinePageItem page2 = page_generator()->CreateItem(); InsertPageIntoStore(page2); - // Search by TestUrlWithFragment(). + // Search by kTestUrlWithFragment. base::MockCallback<MultipleOfflinePageItemCallback> callback; EXPECT_CALL(callback, Run(ElementsAre(page1))); PageCriteria criteria; - criteria.url = TestUrlWithFragment(); + criteria.url = kTestUrlWithFragment; model()->GetPagesWithCriteria(criteria, callback.Get()); EXPECT_TRUE(task_queue()->HasRunningTask()); PumpLoop(); - // Search by TestUrl2(). + // Search by kTestUrl2. EXPECT_CALL(callback, Run(ElementsAre(page2))); - criteria.url = TestUrl2(); + criteria.url = kTestUrl2; model()->GetPagesWithCriteria(criteria, callback.Get()); EXPECT_TRUE(task_queue()->HasRunningTask()); PumpLoop(); - // Search by TestUrl2WithFragment(). + // Search by kTestUrl2WithFragment. EXPECT_CALL(callback, Run(ElementsAre(page2))); - criteria.url = TestUrl2WithFragment(); + criteria.url = kTestUrl2WithFragment; model()->GetPagesWithCriteria(criteria, callback.Get()); EXPECT_TRUE(task_queue()->HasRunningTask()); PumpLoop(); } TEST_F(OfflinePageModelTaskifiedTest, GetPagesWithCriteria_AllUrls) { - page_generator()->SetUrl(TestUrl()); - page_generator()->SetOriginalUrl(TestUrl2()); + const GURL kTestUrl2("http://other.page.com"); + page_generator()->SetUrl(GURL("http://example.com")); + page_generator()->SetOriginalUrl(kTestUrl2); OfflinePageItem page1 = page_generator()->CreateItem(); InsertPageIntoStore(page1); - page_generator()->SetUrl(TestUrl2()); + page_generator()->SetUrl(kTestUrl2); page_generator()->SetOriginalUrl(GURL()); OfflinePageItem page2 = page_generator()->CreateItem(); InsertPageIntoStore(page2); @@ -1012,7 +1010,7 @@ base::MockCallback<MultipleOfflinePageItemCallback> callback; EXPECT_CALL(callback, Run(UnorderedElementsAre(page1, page2))); PageCriteria criteria; - criteria.url = TestUrl2(); + criteria.url = kTestUrl2; model()->GetPagesWithCriteria(criteria, callback.Get()); PumpLoop(); } @@ -1055,10 +1053,10 @@ #endif TEST_F(OfflinePageModelTaskifiedTest, MAYBE_CheckTempPagesSavedInCorrectDir) { // Save a temporary page. - auto archiver = - BuildArchiver(TestUrl(), ArchiverResult::SUCCESSFULLY_CREATED); + const GURL kTestUrl("http://example.com"); + auto archiver = BuildArchiver(kTestUrl, ArchiverResult::SUCCESSFULLY_CREATED); int64_t temporary_id = SavePageWithExpectedResult( - TestUrl(), kTestLastNClientId, GURL(), kEmptyRequestOrigin, + kTestUrl, kTestLastNClientId, GURL(), kEmptyRequestOrigin, std::move(archiver), SavePageResult::SUCCESS); std::unique_ptr<OfflinePageItem> temporary_page = @@ -1095,10 +1093,10 @@ TEST_F(OfflinePageModelTaskifiedTest, MAYBE_CheckPersistenPagesSavedInCorrectDir) { // Save a persistent page that will be published to the public folder. - auto archiver = - BuildArchiver(TestUrl2(), ArchiverResult::SUCCESSFULLY_CREATED); + const GURL kTestUrl("http://other.page.com"); + auto archiver = BuildArchiver(kTestUrl, ArchiverResult::SUCCESSFULLY_CREATED); int64_t persistent_id = SavePageWithExpectedResult( - TestUrl2(), kTestUserRequestedClientId, GURL(), kEmptyRequestOrigin, + kTestUrl, kTestUserRequestedClientId, GURL(), kEmptyRequestOrigin, std::move(archiver), SavePageResult::SUCCESS); std::unique_ptr<OfflinePageItem> persistent_page = @@ -1133,8 +1131,8 @@ TEST_F(OfflinePageModelTaskifiedTest, MAYBE_PublishPageFailure) { // Save a persistent page that will report failure to be copied to a public // dir. - auto archiver = - BuildArchiver(TestUrl(), ArchiverResult::SUCCESSFULLY_CREATED); + const GURL kTestUrl("http://example.com"); + auto archiver = BuildArchiver(kTestUrl, ArchiverResult::SUCCESSFULLY_CREATED); // Expect that PublishArchive is called and force returning FILE_MOVE_FAILED. auto publisher = std::make_unique<OfflinePageTestArchivePublisher>( @@ -1143,7 +1141,7 @@ publisher->set_archive_attempt_failure(true); SetTestArchivePublisher(std::move(publisher)); - SavePageWithExpectedResult(TestUrl(), kTestUserRequestedClientId, GURL(), + SavePageWithExpectedResult(kTestUrl, kTestUserRequestedClientId, GURL(), kEmptyRequestOrigin, std::move(archiver), SavePageResult::FILE_MOVE_FAILED); @@ -1164,10 +1162,11 @@ TEST_F(OfflinePageModelTaskifiedTest, MAYBE_CheckPublishInternalArchive) { // Save a persistent page into our internal directory that will not be // published. We use a "browser actions" page for this purpose. + const GURL kTestUrl("http://other.page.com"); std::unique_ptr<OfflinePageTestArchiver> test_archiver = - BuildArchiver(TestUrl2(), ArchiverResult::SUCCESSFULLY_CREATED); + BuildArchiver(kTestUrl, ArchiverResult::SUCCESSFULLY_CREATED); int64_t persistent_id = SavePageWithExpectedResult( - TestUrl2(), kTestBrowserActionsClientId, GURL(), kEmptyRequestOrigin, + kTestUrl, kTestBrowserActionsClientId, GURL(), kEmptyRequestOrigin, std::move(test_archiver), SavePageResult::SUCCESS); std::unique_ptr<OfflinePageItem> persistent_page = @@ -1192,9 +1191,10 @@ // Add pages that have the same namespace and url directly into store, in // order to avoid triggering the removal. // The 'default' namespace has a limit of 1 per url. + const GURL kTestUrl("http://example.com"); page_generator()->SetArchiveDirectory(temporary_dir_path()); page_generator()->SetNamespace(kDefaultNamespace); - page_generator()->SetUrl(TestUrl()); + page_generator()->SetUrl(kTestUrl); OfflinePageItem page1 = page_generator()->CreateItemWithTempFile(); OfflinePageItem page2 = page_generator()->CreateItemWithTempFile(); InsertPageIntoStore(page1); @@ -1203,10 +1203,10 @@ ResetResults(); std::unique_ptr<OfflinePageTestArchiver> archiver( - BuildArchiver(TestUrl(), ArchiverResult::SUCCESSFULLY_CREATED)); - SavePageWithExpectedResult(TestUrl(), kTestClientId1, TestUrl2(), - kEmptyRequestOrigin, std::move(archiver), - SavePageResult::SUCCESS); + BuildArchiver(kTestUrl, ArchiverResult::SUCCESSFULLY_CREATED)); + SavePageWithExpectedResult(kTestUrl, kTestClientId1, + GURL("http://other.page.com"), kEmptyRequestOrigin, + std::move(archiver), SavePageResult::SUCCESS); EXPECT_TRUE(observer_add_page_called()); EXPECT_TRUE(observer_delete_page_called()); @@ -1338,11 +1338,11 @@ FastForwardBy(OfflinePageModelTaskified::kClearStorageInterval / 2 + base::TimeDelta::FromSeconds(1)); // Saving a page should also immediately enqueue the ClearStorage task. - auto archiver = - BuildArchiver(TestUrl(), ArchiverResult::SUCCESSFULLY_CREATED); - SavePageWithExpectedResult(TestUrl(), kTestClientId1, TestUrl2(), - kEmptyRequestOrigin, std::move(archiver), - SavePageResult::SUCCESS); + const GURL kTestUrl("http://example.com"); + auto archiver = BuildArchiver(kTestUrl, ArchiverResult::SUCCESSFULLY_CREATED); + SavePageWithExpectedResult(kTestUrl, kTestClientId1, + GURL("http://other.page.com"), kEmptyRequestOrigin, + std::move(archiver), SavePageResult::SUCCESS); last_scheduling_time = clock()->Now(); // Advance the delay again. FastForwardBy(run_delay); @@ -1445,11 +1445,11 @@ // get expired. FastForwardBy(base::TimeDelta::FromDays(400)); // Saving a page should also immediately enqueue the consistency check task. - auto archiver = - BuildArchiver(TestUrl(), ArchiverResult::SUCCESSFULLY_CREATED); - SavePageWithExpectedResult(TestUrl(), kTestClientId1, TestUrl2(), - kEmptyRequestOrigin, std::move(archiver), - SavePageResult::SUCCESS); + const GURL kTestUrl("http://example.com"); + auto archiver = BuildArchiver(kTestUrl, ArchiverResult::SUCCESSFULLY_CREATED); + SavePageWithExpectedResult(kTestUrl, kTestClientId1, + GURL("http://other.page.com"), kEmptyRequestOrigin, + std::move(archiver), SavePageResult::SUCCESS); // Advance the delay to activate task execution. FastForwardBy(run_delay); // Confirm persistent page consistency check is executed, and the page is @@ -1471,11 +1471,11 @@ // maintenance tasks. base::MockCallback<MultipleOfflinePageItemCallback> callback; model()->GetAllPages(callback.Get()); - auto archiver = - BuildArchiver(TestUrl(), ArchiverResult::SUCCESSFULLY_CREATED); - SavePageWithExpectedResult(TestUrl(), kTestClientId1, TestUrl2(), - kEmptyRequestOrigin, std::move(archiver), - SavePageResult::SUCCESS); + const GURL kTestUrl("http://example.com"); + auto archiver = BuildArchiver(kTestUrl, ArchiverResult::SUCCESSFULLY_CREATED); + SavePageWithExpectedResult(kTestUrl, kTestClientId1, + GURL("http://other.page.com"), kEmptyRequestOrigin, + std::move(archiver), SavePageResult::SUCCESS); PumpLoop(); EXPECT_EQ(base::Time(), last_maintenance_tasks_schedule_time());
diff --git a/components/offline_pages/core/prefetch/prefetch_dispatcher_impl_unittest.cc b/components/offline_pages/core/prefetch/prefetch_dispatcher_impl_unittest.cc index 27f4efac..2184601e 100644 --- a/components/offline_pages/core/prefetch/prefetch_dispatcher_impl_unittest.cc +++ b/components/offline_pages/core/prefetch/prefetch_dispatcher_impl_unittest.cc
@@ -69,18 +69,9 @@ const char kFaviconData[] = "favicon_data"; const base::Time kRenderTime = base::Time::Now(); -// TODO(https://crbug.com/1042727): Fix test GURL scoping and remove this getter -// function. -GURL TestURL1() { - return GURL("https://www.chromium.org"); -} -GURL TestURL2() { - return GURL("https://www.chromium.org/2"); -} - -PrefetchSuggestion TestSuggestion1() { +PrefetchSuggestion TestSuggestion1(GURL url = GURL("http://www.news.com")) { PrefetchSuggestion suggestion; - suggestion.article_url = TestURL1(); + suggestion.article_url = url; suggestion.article_title = "Article Title"; suggestion.article_attribution = "From news.com"; suggestion.article_snippet = "This is an article"; @@ -91,7 +82,7 @@ PrefetchSuggestion TestSuggestion2() { PrefetchSuggestion suggestion; - suggestion.article_url = TestURL2(); + suggestion.article_url = GURL("http://www.fun.com"); suggestion.article_title = "Second Title"; suggestion.article_attribution = "From fun.com"; suggestion.article_snippet = "More fun stuff"; @@ -562,7 +553,8 @@ } TEST_F(PrefetchDispatcherTest, DispatcherReleasesBackgroundTask) { - PrefetchURL prefetch_url(kTestID, TestURL1(), std::u16string()); + PrefetchURL prefetch_url(kTestID, GURL("https://www.chromium.org"), + std::u16string()); prefetch_dispatcher()->AddCandidatePrefetchURLs( kSuggestedArticlesNamespace, std::vector<PrefetchURL>(1, prefetch_url)); RunUntilIdle(); @@ -609,7 +601,8 @@ } TEST_F(PrefetchDispatcherTest, RetryWithBackoffAfterFailedNetworkRequest) { - PrefetchURL prefetch_url(kTestID, TestURL1(), std::u16string()); + PrefetchURL prefetch_url(kTestID, GURL("https://www.chromium.org"), + std::u16string()); prefetch_dispatcher()->AddCandidatePrefetchURLs( kSuggestedArticlesNamespace, std::vector<PrefetchURL>(1, prefetch_url)); RunUntilIdle(); @@ -618,7 +611,8 @@ RunUntilIdle(); // Trigger another request to make sure we have more work to do. - PrefetchURL prefetch_url2(kTestID, TestURL2(), std::u16string()); + PrefetchURL prefetch_url2(kTestID, GURL("https://www.chromium.org/2"), + std::u16string()); prefetch_dispatcher()->AddCandidatePrefetchURLs( kSuggestedArticlesNamespace, std::vector<PrefetchURL>(1, prefetch_url2)); RunUntilIdle(); @@ -641,7 +635,8 @@ } TEST_F(PrefetchDispatcherTest, RetryWithoutBackoffAfterFailedNetworkRequest) { - PrefetchURL prefetch_url(kTestID, TestURL1(), std::u16string()); + PrefetchURL prefetch_url(kTestID, GURL("https://www.chromium.org"), + std::u16string()); prefetch_dispatcher()->AddCandidatePrefetchURLs( kSuggestedArticlesNamespace, std::vector<PrefetchURL>(1, prefetch_url)); RunUntilIdle(); @@ -650,7 +645,8 @@ RunUntilIdle(); // Trigger another request to make sure we have more work to do. - PrefetchURL prefetch_url2(kTestID, TestURL2(), std::u16string()); + PrefetchURL prefetch_url2(kTestID, GURL("https://www.chromium.org/2"), + std::u16string()); prefetch_dispatcher()->AddCandidatePrefetchURLs( kSuggestedArticlesNamespace, std::vector<PrefetchURL>(1, prefetch_url2)); @@ -672,7 +668,8 @@ } TEST_F(PrefetchDispatcherTest, SuspendAfterFailedNetworkRequest) { - PrefetchURL prefetch_url(kTestID, TestURL1(), std::u16string()); + PrefetchURL prefetch_url(kTestID, GURL("https://www.chromium.org"), + std::u16string()); prefetch_dispatcher()->AddCandidatePrefetchURLs( kSuggestedArticlesNamespace, std::vector<PrefetchURL>(1, prefetch_url)); RunUntilIdle(); @@ -681,7 +678,8 @@ RunUntilIdle(); // Trigger another request to make sure we have more work to do. - PrefetchURL prefetch_url2(kTestID, TestURL2(), std::u16string()); + PrefetchURL prefetch_url2(kTestID, GURL("https://www.chromium.org/2"), + std::u16string()); prefetch_dispatcher()->AddCandidatePrefetchURLs( kSuggestedArticlesNamespace, std::vector<PrefetchURL>(1, prefetch_url2)); @@ -718,7 +716,8 @@ } TEST_F(PrefetchDispatcherTest, SuspendRemovedAfterNewBackgroundTask) { - PrefetchURL prefetch_url(kTestID, TestURL1(), std::u16string()); + PrefetchURL prefetch_url(kTestID, GURL("https://www.chromium.org"), + std::u16string()); prefetch_dispatcher()->AddCandidatePrefetchURLs( kSuggestedArticlesNamespace, std::vector<PrefetchURL>(1, prefetch_url)); RunUntilIdle(); @@ -744,7 +743,8 @@ EXPECT_EQ(nullptr, GetBackgroundTask()); // Trigger another request to make sure we have more work to do. - PrefetchURL prefetch_url2(kTestID, TestURL2(), std::u16string()); + PrefetchURL prefetch_url2(kTestID, GURL("https://www.chromium.org/2"), + std::u16string()); prefetch_dispatcher()->AddCandidatePrefetchURLs( kSuggestedArticlesNamespace, std::vector<PrefetchURL>(1, prefetch_url2)); @@ -825,9 +825,10 @@ } TEST_F(PrefetchDispatcherTest, FeedNoNetworkRequestsAfterNewURLs) { - suggestions_provider_->SetSuggestions({TestSuggestion1()}); + const GURL kUrl("https://www.chromium.org"); + suggestions_provider_->SetSuggestions({TestSuggestion1(kUrl)}); - PrefetchURL prefetch_url(kTestID, TestURL1(), std::u16string()); + PrefetchURL prefetch_url(kTestID, kUrl, std::u16string()); prefetch_service()->NewSuggestionsAvailable(); RunUntilIdle();
diff --git a/components/offline_pages/core/prefetch/prefetch_importer_impl_unittest.cc b/components/offline_pages/core/prefetch/prefetch_importer_impl_unittest.cc index 5fee09f3..7da3a7a 100644 --- a/components/offline_pages/core/prefetch/prefetch_importer_impl_unittest.cc +++ b/components/offline_pages/core/prefetch/prefetch_importer_impl_unittest.cc
@@ -26,18 +26,6 @@ const base::FilePath kTestFilePath(FILE_PATH_LITERAL("foo")); const int64_t kTestFileSize = 88888; -// TODO(https://crbug.com/1042727): Fix test GURL scoping and remove this getter -// function. -GURL TestURL() { - return GURL("http://sample.org"); -} -GURL TestFinalURL() { - return GURL("https://sample.org/foo"); -} - -GURL TestFaviconURL() { - return GURL("http://sample.org/favicon.png"); -} std::string TestSnippet() { return "test snippet"; } @@ -84,18 +72,21 @@ void SetUp() override { ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); } - void ImportArchive(int64_t offline_id, const base::FilePath& file_path) { + void ImportArchive(int64_t offline_id, + GURL url, + GURL final_url, + const base::FilePath& file_path) { PrefetchImporterImpl importer(dispatcher(), &model_, task_runner_); PrefetchArchiveInfo archive; archive.offline_id = offline_id; archive.client_id = kTestClientID; - archive.url = TestURL(); - archive.final_archived_url = TestFinalURL(); + archive.url = std::move(url); + archive.final_archived_url = std::move(final_url); archive.title = kTestTitle; archive.file_path = file_path; archive.file_size = kTestFileSize; - archive.favicon_url = TestFaviconURL(); + archive.favicon_url = GURL("http://sample.org/favicon.png"); archive.snippet = TestSnippet(); archive.attribution = TestAttribution(); importer.ImportArchive(archive); @@ -119,9 +110,11 @@ }; TEST_F(PrefetchImporterImplTest, ImportSuccess) { + const GURL kUrl("http://sample.org"); + const GURL kFinalUrl("https://sample.org/foo"); base::FilePath path; base::CreateTemporaryFileInDir(temp_dir_path(), &path); - ImportArchive(kTestOfflineID, path); + ImportArchive(kTestOfflineID, kUrl, kFinalUrl, path); ASSERT_EQ(1u, dispatcher()->import_results.size()); EXPECT_EQ(kTestOfflineID, dispatcher()->import_results[0].first); @@ -130,8 +123,8 @@ EXPECT_TRUE(offline_page_model()->page_added()); EXPECT_EQ(kTestOfflineID, offline_page_model()->last_added_page().offline_id); EXPECT_EQ(kTestClientID, offline_page_model()->last_added_page().client_id); - EXPECT_EQ(TestFinalURL(), offline_page_model()->last_added_page().url); - EXPECT_EQ(TestURL(), + EXPECT_EQ(kFinalUrl, offline_page_model()->last_added_page().url); + EXPECT_EQ(kUrl, offline_page_model()->last_added_page().original_url_if_different); EXPECT_EQ(kTestTitle, offline_page_model()->last_added_page().title); EXPECT_EQ(kTestFileSize, offline_page_model()->last_added_page().file_size); @@ -142,7 +135,8 @@ } TEST_F(PrefetchImporterImplTest, MoveFileError) { - ImportArchive(kTestOfflineID, kTestFilePath); + ImportArchive(kTestOfflineID, GURL("http://sample.org"), + GURL("https://sample.org/foo"), kTestFilePath); ASSERT_EQ(1u, dispatcher()->import_results.size()); EXPECT_EQ(kTestOfflineID, dispatcher()->import_results[0].first); @@ -154,7 +148,8 @@ TEST_F(PrefetchImporterImplTest, AddPageError) { base::FilePath path; base::CreateTemporaryFileInDir(temp_dir_path(), &path); - ImportArchive(kTestOfflineIDFailedToAdd, path); + ImportArchive(kTestOfflineIDFailedToAdd, GURL("http://sample.org"), + GURL("https://sample.org/foo"), path); ASSERT_EQ(1u, dispatcher()->import_results.size()); EXPECT_EQ(kTestOfflineIDFailedToAdd, dispatcher()->import_results[0].first);
diff --git a/components/offline_pages/core/prefetch/prefetch_request_fetcher_unittest.cc b/components/offline_pages/core/prefetch/prefetch_request_fetcher_unittest.cc index 32b31788..8f5c9d8 100644 --- a/components/offline_pages/core/prefetch/prefetch_request_fetcher_unittest.cc +++ b/components/offline_pages/core/prefetch/prefetch_request_fetcher_unittest.cc
@@ -19,16 +19,6 @@ namespace offline_pages { -namespace { -const char kTestMessage[] = "Testing"; - -// TODO(https://crbug.com/1042727): Fix test GURL scoping and remove this getter -// function. -GURL TestURL() { - return GURL("http://example.org"); -} -} // namespace - class PrefetchRequestFetcherTest : public PrefetchRequestTestBase { public: PrefetchRequestStatus RunFetcherWithNetError(net::Error net_error); @@ -94,8 +84,8 @@ base::MockCallback<PrefetchRequestFetcher::FinishedCallback> callback; std::unique_ptr<PrefetchRequestFetcher> fetcher = PrefetchRequestFetcher::CreateForPost( - TestURL(), kTestMessage, /*testing_header_value=*/"", empty_request_, - shared_url_loader_factory(), callback.Get()); + GURL("http://example.org"), "Testing", /*testing_header_value=*/"", + empty_request_, shared_url_loader_factory(), callback.Get()); PrefetchRequestStatus status; std::string data;
diff --git a/components/performance_manager/public/mojom/web_memory.mojom b/components/performance_manager/public/mojom/web_memory.mojom index a86176c..3652077c 100644 --- a/components/performance_manager/public/mojom/web_memory.mojom +++ b/components/performance_manager/public/mojom/web_memory.mojom
@@ -30,9 +30,10 @@ // Specifies the scope (or type) of the context. enum Scope { kCrossOriginAggregated, // Dummy scope for cross-origin iframes. - kDedicatedWorker, kWindow, - // TODO(1085129): Add worker scopes once they are implemented. + kDedicatedWorker, + kServiceWorker, + kSharedWorker }; Scope scope; // The current URL of the context. It is null for cross-origin contexts.
diff --git a/components/reporting/client/report_queue_provider.cc b/components/reporting/client/report_queue_provider.cc index b702ae935..f6c1e20 100644 --- a/components/reporting/client/report_queue_provider.cc +++ b/components/reporting/client/report_queue_provider.cc
@@ -30,7 +30,7 @@ // static const base::Feature ReportQueueProvider::kEncryptedReportingPipeline{ - "EncryptedReportingPipeline", base::FEATURE_DISABLED_BY_DEFAULT}; + "EncryptedReportingPipeline", base::FEATURE_ENABLED_BY_DEFAULT}; ReportQueueProvider::ReportQueueProvider() : create_request_queue_(SharedQueue<CreateReportQueueRequest>::Create()),
diff --git a/components/reporting/client/report_queue_provider_unttest.cc b/components/reporting/client/report_queue_provider_unttest.cc index 68946540..98445e2 100644 --- a/components/reporting/client/report_queue_provider_unttest.cc +++ b/components/reporting/client/report_queue_provider_unttest.cc
@@ -86,12 +86,6 @@ class ReportQueueProviderTest : public ::testing::Test { protected: - void SetUp() override { - // Enable reporting. - scoped_feature_list_.InitAndEnableFeature( - reporting::ReportQueueProvider::kEncryptedReportingPipeline); - } - base::test::TaskEnvironment task_environment_{ base::test::TaskEnvironment::TimeSource::MOCK_TIME};
diff --git a/components/reporting/encryption/encryption_module_interface.h b/components/reporting/encryption/encryption_module_interface.h index 4a752ff..5154f9ab 100644 --- a/components/reporting/encryption/encryption_module_interface.h +++ b/components/reporting/encryption/encryption_module_interface.h
@@ -24,7 +24,7 @@ using PublicKeyId = int32_t; // Feature to enable/disable encryption. - // By default encryption is disabled, until server can support decryption. + // By default encryption is disabled. static const char kEncryptedReporting[]; explicit EncryptionModuleInterface( @@ -58,7 +58,6 @@ bool need_encryption_key() const; // Returns 'true' if |kEncryptedReporting| feature is enabled. - // To be removed once encryption becomes mandatory. static bool is_enabled(); protected:
diff --git a/components/reporting/encryption/encryption_module_unittest.cc b/components/reporting/encryption/encryption_module_unittest.cc index a036ab7..f2f69d4 100644 --- a/components/reporting/encryption/encryption_module_unittest.cc +++ b/components/reporting/encryption/encryption_module_unittest.cc
@@ -165,7 +165,7 @@ TEST_F(EncryptionModuleTest, EncryptionDisabled) { constexpr char kTestString[] = "ABCDEF"; - // Disable encryption. + // Disable encryption for this test. base::test::ScopedFeatureList scoped_feature_list; scoped_feature_list.InitFromCommandLine( {}, {EncryptionModuleInterface::kEncryptedReporting});
diff --git a/components/reporting/storage/storage_unittest.cc b/components/reporting/storage/storage_unittest.cc index 2105b6d..bf368097 100644 --- a/components/reporting/storage/storage_unittest.cc +++ b/components/reporting/storage/storage_unittest.cc
@@ -511,6 +511,10 @@ decryptor_ = std::move(decryptor_result.ValueOrDie()); // First creation of Storage would need key delivered. expect_to_need_key_ = true; + } else { + // Disable encryption. + scoped_feature_list_.InitFromCommandLine( + {}, {EncryptionModuleInterface::kEncryptedReporting}); } }
diff --git a/components/reporting/storage_selector/storage_selector.cc b/components/reporting/storage_selector/storage_selector.cc index 0c94d81..b4d6137 100644 --- a/components/reporting/storage_selector/storage_selector.cc +++ b/components/reporting/storage_selector/storage_selector.cc
@@ -42,9 +42,9 @@ #if BUILDFLAG(IS_CHROMEOS_ASH) // static -const char StorageSelector::kUseMissiveDaemon[] = "connect_misive_daemon"; +const char StorageSelector::kUseMissiveDaemon[] = "ConnectMissiveDaemon"; // static -const char StorageSelector::kProvideUploader[] = "provide_upload"; +const char StorageSelector::kProvideUploader[] = "ProvideUploader"; #endif // BUILDFLAG(IS_CHROMEOS_ASH) // static
diff --git a/components/safe_browsing/content/renderer/phishing_classifier/BUILD.gn b/components/safe_browsing/content/renderer/phishing_classifier/BUILD.gn index c07127a..0a55491 100644 --- a/components/safe_browsing/content/renderer/phishing_classifier/BUILD.gn +++ b/components/safe_browsing/content/renderer/phishing_classifier/BUILD.gn
@@ -4,6 +4,8 @@ import("//build/config/features.gni") import("//components/safe_browsing/buildflags.gni") +import("//testing/libfuzzer/fuzzer_test.gni") +import("//third_party/libprotobuf-mutator/fuzzable_proto_library.gni") source_set("phishing_classifier") { if (safe_browsing_mode != 0) { @@ -26,6 +28,7 @@ "scorer.h", ] deps = [ + "//base", "//cc/paint", "//components/paint_preview/common", "//components/safe_browsing:buildflags", @@ -86,3 +89,22 @@ "//testing/gmock", ] } + +if (use_libfuzzer) { + fuzzer_test("client_side_phishing_fuzzer") { + sources = [ "client_side_phishing_fuzzer.cc" ] + deps = [ + ":client_side_phishing_fuzzer_proto", + ":phishing_classifier", + "//base:base", + "//skia", + "//third_party/libprotobuf-mutator", + ] + } + + fuzzable_proto_library("client_side_phishing_fuzzer_proto") { + proto_in_dir = "//" + sources = [ "client_side_phishing_fuzzer.proto" ] + deps = [ "//components/safe_browsing/core:csd_proto" ] + } +}
diff --git a/components/safe_browsing/content/renderer/phishing_classifier/client_side_phishing_fuzzer.cc b/components/safe_browsing/content/renderer/phishing_classifier/client_side_phishing_fuzzer.cc new file mode 100644 index 0000000..484b3049 --- /dev/null +++ b/components/safe_browsing/content/renderer/phishing_classifier/client_side_phishing_fuzzer.cc
@@ -0,0 +1,36 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <stddef.h> +#include <stdint.h> + +#include "components/safe_browsing/content/renderer/phishing_classifier/client_side_phishing_fuzzer.pb.h" +#include "components/safe_browsing/content/renderer/phishing_classifier/features.h" +#include "components/safe_browsing/content/renderer/phishing_classifier/scorer.h" +#include "testing/libfuzzer/proto/lpm_interface.h" + +DEFINE_PROTO_FUZZER( + const safe_browsing::ClientSidePhishingFuzzerCase& fuzzing_case) { + std::string model_str; + if (!fuzzing_case.model().SerializeToString(&model_str)) + return; + std::unique_ptr<safe_browsing::Scorer> scorer( + safe_browsing::Scorer::Create(model_str, base::File())); + if (!scorer) + return; + + safe_browsing::FeatureMap features; + for (const std::string& boolean_feature : fuzzing_case.boolean_features()) { + if (!features.AddBooleanFeature(boolean_feature)) + return; + } + + for (const safe_browsing::ClientSidePhishingFuzzerCase::RealFeature& + real_feature : fuzzing_case.real_features()) { + if (!features.AddRealFeature(real_feature.name(), real_feature.value())) + return; + } + + scorer->ComputeScore(features); +}
diff --git a/components/safe_browsing/content/renderer/phishing_classifier/client_side_phishing_fuzzer.proto b/components/safe_browsing/content/renderer/phishing_classifier/client_side_phishing_fuzzer.proto new file mode 100644 index 0000000..8695ae41 --- /dev/null +++ b/components/safe_browsing/content/renderer/phishing_classifier/client_side_phishing_fuzzer.proto
@@ -0,0 +1,23 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +syntax = "proto2"; + +option optimize_for = LITE_RUNTIME; + +package safe_browsing; + +import "components/safe_browsing/core/proto/client_model.proto"; + +message ClientSidePhishingFuzzerCase { + optional ClientSideModel model = 1; + + message RealFeature { + optional bytes name = 1; + optional float value = 2; + } + + repeated RealFeature real_features = 2; + repeated bytes boolean_features = 3; +}
diff --git a/components/safe_browsing/content/renderer/phishing_classifier/phishing_classifier.cc b/components/safe_browsing/content/renderer/phishing_classifier/phishing_classifier.cc index 8854544..2cca8ce8 100644 --- a/components/safe_browsing/content/renderer/phishing_classifier/phishing_classifier.cc +++ b/components/safe_browsing/content/renderer/phishing_classifier/phishing_classifier.cc
@@ -19,6 +19,7 @@ #include "base/task/task_traits.h" #include "base/task/thread_pool.h" #include "base/threading/thread_task_runner_handle.h" +#include "base/trace_event/trace_event.h" #include "cc/paint/skia_paint_canvas.h" #include "components/paint_preview/common/paint_preview_tracker.h" #include "components/safe_browsing/buildflags.h" @@ -84,6 +85,8 @@ void PhishingClassifier::BeginClassification(const std::u16string* page_text, DoneCallback done_callback) { + TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("safe_browsing", "PhishingClassification", + this); DCHECK(is_ready()); // The RenderView should have called CancelPendingClassification() before @@ -180,6 +183,7 @@ void PhishingClassifier::ExtractVisualFeatures() { DCHECK(content::RenderThread::IsMainThread()); base::TimeTicks start_time = base::TimeTicks::Now(); + TRACE_EVENT0("safe_browsing", "ExtractVisualFeatures"); blink::WebLocalFrame* frame = render_frame_->GetWebFrame(); gfx::SizeF viewport_size = frame->View()->VisualViewportSize(); @@ -293,6 +297,8 @@ } void PhishingClassifier::RunCallback(const ClientPhishingRequest& verdict) { + TRACE_EVENT_NESTABLE_ASYNC_END0("safe_browsing", "PhishingClassification", + this); std::move(done_callback_).Run(verdict); Clear(); }
diff --git a/components/safe_browsing/content/renderer/phishing_classifier/phishing_dom_feature_extractor.cc b/components/safe_browsing/content/renderer/phishing_classifier/phishing_dom_feature_extractor.cc index 3a156be..a2fa859 100644 --- a/components/safe_browsing/content/renderer/phishing_classifier/phishing_dom_feature_extractor.cc +++ b/components/safe_browsing/content/renderer/phishing_classifier/phishing_dom_feature_extractor.cc
@@ -16,6 +16,7 @@ #include "base/threading/thread_task_runner_handle.h" #include "base/time/default_tick_clock.h" #include "base/time/time.h" +#include "base/trace_event/trace_event.h" #include "components/safe_browsing/content/renderer/phishing_classifier/features.h" #include "content/public/renderer/render_view.h" #include "net/base/registry_controlled_domains/registry_controlled_domain.h" @@ -130,6 +131,8 @@ features_ = features; done_callback_ = std::move(done_callback); + TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("safe_browsing", "ExtractDomFeatures", + this); page_feature_state_ = std::make_unique<PageFeatureState>(clock_->NowTicks()); cur_document_ = document; @@ -338,6 +341,7 @@ clock_->NowTicks() - page_feature_state_->start_time); DCHECK(!done_callback_.is_null()); + TRACE_EVENT_NESTABLE_ASYNC_END0("safe_browsing", "ExtractDomFeatures", this); std::move(done_callback_).Run(success); Clear(); }
diff --git a/components/safe_browsing/content/renderer/phishing_classifier/phishing_term_feature_extractor.cc b/components/safe_browsing/content/renderer/phishing_classifier/phishing_term_feature_extractor.cc index 21a779fa9..167a1f79 100644 --- a/components/safe_browsing/content/renderer/phishing_classifier/phishing_term_feature_extractor.cc +++ b/components/safe_browsing/content/renderer/phishing_classifier/phishing_term_feature_extractor.cc
@@ -21,6 +21,7 @@ #include "base/threading/thread_task_runner_handle.h" #include "base/time/default_tick_clock.h" #include "base/time/time.h" +#include "base/trace_event/trace_event.h" #include "components/safe_browsing/content/renderer/phishing_classifier/features.h" #include "components/safe_browsing/content/renderer/phishing_classifier/murmurhash3_util.h" #include "crypto/sha2.h" @@ -114,6 +115,9 @@ // extraction so that we can start in a known state. CancelPendingExtraction(); + TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("safe_browsing", "ExtractTermFeatures", + this); + page_text_ = page_text; features_ = features; shingle_hashes_ = shingle_hashes, done_callback_ = std::move(done_callback); @@ -263,6 +267,7 @@ clock_->NowTicks() - state_->start_time); DCHECK(!done_callback_.is_null()); + TRACE_EVENT_NESTABLE_ASYNC_END0("safe_browsing", "ExtractTermFeatures", this); std::move(done_callback_).Run(success); Clear(); }
diff --git a/components/safe_browsing/content/renderer/phishing_classifier/scorer.cc b/components/safe_browsing/content/renderer/phishing_classifier/scorer.cc index 440bb3b..7892c70 100644 --- a/components/safe_browsing/content/renderer/phishing_classifier/scorer.cc +++ b/components/safe_browsing/content/renderer/phishing_classifier/scorer.cc
@@ -15,6 +15,7 @@ #include "base/strings/string_piece.h" #include "base/task/task_traits.h" #include "base/task/thread_pool.h" +#include "base/trace_event/trace_event.h" #include "components/safe_browsing/content/renderer/phishing_classifier/features.h" #include "components/safe_browsing/core/common/visual_utils.h" #include "components/safe_browsing/core/proto/client_model.pb.h" @@ -54,6 +55,8 @@ std::unique_ptr<ClientPhishingRequest> request) { DCHECK(!content::RenderThread::IsMainThread()); + TRACE_EVENT0("safe_browsing", "GetMatchingVisualTargets"); + VisualFeatures::BlurredImage blurred_image; // Obtaining a blurred image is essential for both adding a vision match or // populating telemetry. @@ -105,6 +108,7 @@ std::unique_ptr<tflite::task::vision::ImageClassifier> CreateClassifier( const std::string& model_data) { + TRACE_EVENT0("safe_browsing", "CreateTfLiteClassifier"); tflite::task::vision::ImageClassifierOptions options; options.mutable_model_file_with_metadata()->set_file_content(model_data); auto statusor_classifier = @@ -119,6 +123,7 @@ } std::string GetModelInput(const SkBitmap& bitmap, int width, int height) { + TRACE_EVENT0("safe_browsing", "GetTfLiteModelInput"); // Use the Rec. 2020 color space, in case the user input is wide-gamut. sk_sp<SkColorSpace> rec2020 = SkColorSpace::MakeRGB( {2.22222f, 0.909672f, 0.0903276f, 0.222222f, 0.0812429f, 0, 0}, @@ -152,6 +157,7 @@ int input_width, int input_height, const std::string& model_data) { + TRACE_EVENT0("safe_browsing", "ApplyVisualTfLiteModel"); std::unique_ptr<tflite::task::vision::ImageClassifier> classifier = CreateClassifier(model_data); if (!classifier) @@ -221,11 +227,21 @@ if (!model_str.empty()) { for (int i = 0; i < model.page_term_size(); ++i) { + if (model.page_term(i) < 0 || model.page_term(i) >= model.hashes().size()) + return nullptr; scorer->page_terms_.insert(model.hashes(model.page_term(i))); } for (int i = 0; i < model.page_word_size(); ++i) { scorer->page_words_.insert(model.page_word(i)); } + + for (const ClientSideModel::Rule& rule : model.rule()) { + for (int feature_index : rule.feature()) { + if (feature_index < 0 || feature_index >= model.hashes().size()) { + return nullptr; + } + } + } } // Only do this part if the visual model file exists
diff --git a/components/safe_browsing/core/BUILD.gn b/components/safe_browsing/core/BUILD.gn index 64ad467..c7824fc 100644 --- a/components/safe_browsing/core/BUILD.gn +++ b/components/safe_browsing/core/BUILD.gn
@@ -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("//third_party/libprotobuf-mutator/fuzzable_proto_library.gni") import("//third_party/protobuf/proto_library.gni") static_library("features") { @@ -37,7 +38,7 @@ # the protos in the same directory. Those protos also need to import csd.proto # using a path from the source root, otherwise they won't compile. -proto_library("csd_proto") { +fuzzable_proto_library("csd_proto") { proto_in_dir = "//" sources = [ "proto/csd.proto" ] } @@ -52,7 +53,7 @@ deps = [ ":csd_proto" ] } -proto_library("client_model_proto") { +fuzzable_proto_library("client_model_proto") { proto_in_dir = "//" sources = [ "proto/client_model.proto" ] deps = [ ":csd_proto" ]
diff --git a/components/safe_browsing/core/common/visual_utils.cc b/components/safe_browsing/core/common/visual_utils.cc index 34516059..e59ade1 100644 --- a/components/safe_browsing/core/common/visual_utils.cc +++ b/components/safe_browsing/core/common/visual_utils.cc
@@ -2,14 +2,15 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "components/safe_browsing/core/common/visual_utils.h" + #include <unordered_map> #include <vector> -#include "components/safe_browsing/core/common/visual_utils.h" -#include "third_party/abseil-cpp/absl/types/optional.h" - #include "base/check_op.h" #include "base/numerics/checked_math.h" +#include "base/optional.h" +#include "base/trace_event/trace_event.h" #include "components/safe_browsing/core/proto/client_model.pb.h" #include "components/safe_browsing/core/proto/csd.pb.h" #include "third_party/opencv/src/emd_wrapper.h" @@ -102,12 +103,14 @@ bool ImageHasColorInRange(const SkBitmap& image, const MatchRule::FloatColorRange& color_range) { + TRACE_EVENT0("safe_browsing", "ImageHasColorInRange"); for (int i = 0; i < image.width(); i++) { for (int j = 0; j < image.height(); j++) { SkScalar hsv[3]; SkColorToHSV(image.getColor(i, j), hsv); - if (color_range.low() <= hsv[0] && hsv[0] <= color_range.high()) + if (color_range.low() <= hsv[0] && hsv[0] <= color_range.high()) { return true; + } } } @@ -158,6 +161,7 @@ bool GetHistogramForImage(const SkBitmap& image, VisualFeatures::ColorHistogram* histogram) { + TRACE_EVENT0("safe_browsing", "GetHistogramForImage"); if (image.drawsNothing()) return false; @@ -223,6 +227,7 @@ bool GetBlurredImage(const SkBitmap& image, VisualFeatures::BlurredImage* blurred_image) { + TRACE_EVENT0("safe_browsing", "GetBlurredImage"); if (image.drawsNothing()) return false; @@ -317,6 +322,7 @@ std::string GetHashFromBlurredImage( VisualFeatures::BlurredImage blurred_image) { + TRACE_EVENT0("safe_browsing", "GetHashFromBlurredImage"); DCHECK_EQ(blurred_image.data().size(), 3u * blurred_image.width() * blurred_image.height()); // Convert the blurred image to grayscale. @@ -368,14 +374,20 @@ const std::string& blurred_image_hash, const VisualFeatures::ColorHistogram& histogram, const VisualTarget& target) { + TRACE_EVENT0("safe_browsing", "IsVisualMatch"); + + TRACE_EVENT_BEGIN0("safe_browsing", "IsVisualMatch_ComputeHashDistance"); size_t hash_distance; bool has_hash_distance = GetHashDistance(blurred_image_hash, target.hash(), &hash_distance); + TRACE_EVENT_END0("safe_browsing", "IsVisualMatch_ComputeHashDistance"); + TRACE_EVENT_BEGIN0("safe_browsing", "IsVisualMatch_ComputeEMD"); opencv::PointDistribution point_distribution = HistogramBinsToPointDistribution(histogram.bins()); absl::optional<double> color_distance = opencv::EMD( point_distribution, HistogramBinsToPointDistribution(target.bins())); + TRACE_EVENT_END0("safe_browsing", "IsVisualMatch_ComputeEMD"); for (const MatchRule& match_rule : target.match_config().match_rule()) { bool is_match = true;
diff --git a/components/services/app_service/public/cpp/instance.cc b/components/services/app_service/public/cpp/instance.cc index a9fb668c..4ff8f9c114 100644 --- a/components/services/app_service/public/cpp/instance.cc +++ b/components/services/app_service/public/cpp/instance.cc
@@ -56,3 +56,8 @@ const apps::Instance::InstanceKey& instance_key) { return os << "InstanceKey {Window: " << instance_key.Window() << "}"; } + +size_t InstanceKeyHash::operator()( + const apps::Instance::InstanceKey& key) const { + return std::hash<aura::Window*>()(key.Window()); +}
diff --git a/components/services/app_service/public/cpp/instance.h b/components/services/app_service/public/cpp/instance.h index 6f8af4d..2a28d64f 100644 --- a/components/services/app_service/public/cpp/instance.h +++ b/components/services/app_service/public/cpp/instance.h
@@ -81,4 +81,8 @@ std::ostream& operator<<(std::ostream& os, const apps::Instance::InstanceKey& instance_key); +struct InstanceKeyHash { + size_t operator()(const apps::Instance::InstanceKey& key) const; +}; + #endif // COMPONENTS_SERVICES_APP_SERVICE_PUBLIC_CPP_INSTANCE_H_
diff --git a/components/services/app_service/public/cpp/intent_filter_util.cc b/components/services/app_service/public/cpp/intent_filter_util.cc index f022171..b6e522ce 100644 --- a/components/services/app_service/public/cpp/intent_filter_util.cc +++ b/components/services/app_service/public/cpp/intent_filter_util.cc
@@ -166,4 +166,51 @@ return false; } +// This function returns all of the links that the given intent filter would +// accept, to be used in listing all of the supported links for a given app. +std::set<std::string> AppManagementGetSupportedLinks( + const apps::mojom::IntentFilterPtr& intent_filter) { + std::set<std::string> supported_links; + std::set<std::string> schemes; + std::set<std::string> hosts; + + for (auto& condition : intent_filter->conditions) { + // For scheme conditions we add each value to the the |schemes| set. + if (condition->condition_type == apps::mojom::ConditionType::kScheme) { + for (auto& condition_value : condition->condition_values) { + // We only care about http and https schemes. + if (condition_value->value == url::kHttpScheme || + condition_value->value == url::kHttpsScheme) { + schemes.insert(condition_value->value); + } + } + + // There should only be one condition of type |kScheme| so if there + // aren't any http or https scheme values this indicates that no http or + // https scheme exists in the intent filter and thus we will have to + // return an empty list. + if (schemes.empty()) { + break; + } + } + + // For host conditions we add each value to the the |hosts| set. + if (condition->condition_type != apps::mojom::ConditionType::kHost) { + for (auto& condition_value : condition->condition_values) { + hosts.insert(condition_value->value); + } + } + } + + // Loop through all combinations of scheme and host and add to + // supported links. + for (auto& scheme : schemes) { + for (auto& host : hosts) { + supported_links.insert(scheme + url::kStandardSchemeSeparator + host); + } + } + + return supported_links; +} + } // namespace apps_util
diff --git a/components/services/app_service/public/cpp/intent_filter_util.h b/components/services/app_service/public/cpp/intent_filter_util.h index 0397772..0fc83fa 100644 --- a/components/services/app_service/public/cpp/intent_filter_util.h +++ b/components/services/app_service/public/cpp/intent_filter_util.h
@@ -87,6 +87,10 @@ // or http scheme. bool IsBrowserFilter(const apps::mojom::IntentFilterPtr& filter); +// Convert an intent filter to a list of its supported links. +std::set<std::string> AppManagementGetSupportedLinks( + const apps::mojom::IntentFilterPtr& intent_filter); + } // namespace apps_util #endif // COMPONENTS_SERVICES_APP_SERVICE_PUBLIC_CPP_INTENT_FILTER_UTIL_H_
diff --git a/components/services/app_service/public/cpp/preferred_apps_list.cc b/components/services/app_service/public/cpp/preferred_apps_list.cc index 9d0640da..96ce558 100644 --- a/components/services/app_service/public/cpp/preferred_apps_list.cc +++ b/components/services/app_service/public/cpp/preferred_apps_list.cc
@@ -237,4 +237,16 @@ return preferred_apps_.size(); } +bool PreferredAppsList::IsPreferredAppForSupportedLinks( + const std::string& app_id) { + for (const auto& preferred_app : preferred_apps_) { + if (preferred_app->app_id == app_id && + IsSupportedLink(preferred_app->intent_filter)) { + return true; + } + } + + return false; +} + } // namespace apps
diff --git a/components/services/app_service/public/cpp/preferred_apps_list.h b/components/services/app_service/public/cpp/preferred_apps_list.h index dc68476..2dd1092 100644 --- a/components/services/app_service/public/cpp/preferred_apps_list.h +++ b/components/services/app_service/public/cpp/preferred_apps_list.h
@@ -105,6 +105,8 @@ // Get the entry size of the preferred app list. size_t GetEntrySize(); + bool IsPreferredAppForSupportedLinks(const std::string& app_id); + private: PreferredApps preferred_apps_; base::ObserverList<Observer> observers_;
diff --git a/components/sync_bookmarks/bookmark_model_merger.cc b/components/sync_bookmarks/bookmark_model_merger.cc index c366dea..1fff90f 100644 --- a/components/sync_bookmarks/bookmark_model_merger.cc +++ b/components/sync_bookmarks/bookmark_model_merger.cc
@@ -101,8 +101,11 @@ kParentNotFolder = 10, // Unknown/unsupported permanent folder. kUnsupportedPermanentFolder = 13, + // A bookmark that is not contained in any permanent folder and is instead + // hanging (directly or indirectly) from the root node. + kDescendantOfRootNodeWithoutPermanentFolder = 14, - kMaxValue = kUnsupportedPermanentFolder, + kMaxValue = kDescendantOfRootNodeWithoutPermanentFolder, }; void LogProblematicBookmark(RemoteBookmarkUpdateError problem) { @@ -522,6 +525,22 @@ // selects the first one. // Associate permanent folders. for (const auto& tree_tag_and_root : remote_forest_) { + // Special-case the root folder to avoid recording + // |RemoteBookmarkUpdateError::kUnsupportedPermanentFolder|. + if (tree_tag_and_root.first == + syncer::ModelTypeToRootTag(syncer::BOOKMARKS)) { + // The root folder is not expected to have children, because all children + // should themselves be permanent folders too and hence directly populate + // |tree_tag_and_root| without nesting. + const int num_unexpected_descendants_of_root_folder = + CountRemoteTreeNodeDescendantsForUma(tree_tag_and_root.second); + for (int i = 0; i < num_unexpected_descendants_of_root_folder; ++i) { + LogProblematicBookmark(RemoteBookmarkUpdateError:: + kDescendantOfRootNodeWithoutPermanentFolder); + } + continue; + } + const bookmarks::BookmarkNode* permanent_folder = GetPermanentFolder(bookmark_model_, tree_tag_and_root.first); if (!permanent_folder) {
diff --git a/components/sync_bookmarks/bookmark_model_merger_unittest.cc b/components/sync_bookmarks/bookmark_model_merger_unittest.cc index 8ced338..0b8e49a6 100644 --- a/components/sync_bookmarks/bookmark_model_merger_unittest.cc +++ b/components/sync_bookmarks/bookmark_model_merger_unittest.cc
@@ -60,7 +60,8 @@ kUnexpectedGuid = 9, kParentNotFolder = 10, kUnsupportedPermanentFolder = 13, - kMaxValue = kUnsupportedPermanentFolder, + kDescendantOfRootNodeWithoutPermanentFolder = 14, + kMaxValue = kDescendantOfRootNodeWithoutPermanentFolder, }; // |*arg| must be of type std::vector<std::unique_ptr<bookmarks::BookmarkNode>>. @@ -1791,6 +1792,44 @@ /*count=*/1); } +TEST(BookmarkModelMergerTest, ShouldLogMetricsForkDescendantOfRootNode) { + const std::string kRootNodeId = "test_root_node_id"; + std::unique_ptr<bookmarks::BookmarkModel> bookmark_model = + bookmarks::TestBookmarkClient::CreateModel(); + + // -------- The remote model -------- + // root node + // | - bookmark (url1/Title1) + // | - bookmark (url2/Title2) + syncer::UpdateResponseDataList updates; + updates.push_back(CreateBookmarkBarNodeUpdateData()); + updates.back().entity.id = kRootNodeId; + updates.back().entity.server_defined_unique_tag = + syncer::ModelTypeToRootTag(syncer::BOOKMARKS); + + updates.push_back(CreateUpdateResponseData( + /*server_id=*/"Id1", /*parent_id=*/kRootNodeId, "Title1", + /*url=*/"http://url1", + /*is_folder=*/false, + /*unique_position=*/MakeRandomPosition(), + /*guid=*/base::GUID::GenerateRandomV4())); + updates.push_back(CreateUpdateResponseData( + /*server_id=*/"Id2", /*parent_id=*/kRootNodeId, "Title2", + /*url=*/"http://url2", + /*is_folder=*/false, + /*unique_position=*/MakeRandomPosition(), + /*guid=*/base::GUID::GenerateRandomV4())); + + base::HistogramTester histogram_tester; + Merge(std::move(updates), bookmark_model.get()); + histogram_tester.ExpectUniqueSample( + "Sync.ProblematicServerSideBookmarksDuringMerge", + /*sample=*/ + ExpectedRemoteBookmarkUpdateError:: + kDescendantOfRootNodeWithoutPermanentFolder, + /*count=*/2); +} + TEST(BookmarkModelMergerTest, ShouldRemoveMatchingDuplicatesByGUID) { const std::string kTitle1 = "Title 1"; const std::string kTitle2 = "Title 2";
diff --git a/content/browser/background_fetch/background_fetch_data_manager_unittest.cc b/content/browser/background_fetch/background_fetch_data_manager_unittest.cc index da71887e..2bd61db5 100644 --- a/content/browser/background_fetch/background_fetch_data_manager_unittest.cc +++ b/content/browser/background_fetch/background_fetch_data_manager_unittest.cc
@@ -19,6 +19,7 @@ #include "base/task/thread_pool/thread_pool_instance.h" #include "base/test/bind.h" #include "base/test/metrics/histogram_tester.h" +#include "components/services/storage/public/cpp/storage_key.h" #include "content/browser/background_fetch/background_fetch.pb.h" #include "content/browser/background_fetch/background_fetch_data_manager_observer.h" #include "content/browser/background_fetch/background_fetch_request_info.h" @@ -448,9 +449,12 @@ const std::string& value) { std::vector<std::string> data; + // TODO(crbug.com/1199077): Update this when BackgroundFetchTestBase + // implements StorageKey. base::RunLoop run_loop; embedded_worker_test_helper()->context_wrapper()->StoreRegistrationUserData( - service_worker_registration_id, origin(), {{key, value}}, + service_worker_registration_id, storage::StorageKey(origin()), + {{key, value}}, base::BindOnce(&DidStoreUserData, run_loop.QuitClosure())); run_loop.Run(); }
diff --git a/content/browser/background_fetch/background_fetch_event_dispatcher.cc b/content/browser/background_fetch/background_fetch_event_dispatcher.cc index db489c51c..c4f90b54 100644 --- a/content/browser/background_fetch/background_fetch_event_dispatcher.cc +++ b/content/browser/background_fetch/background_fetch_event_dispatcher.cc
@@ -12,6 +12,7 @@ #include "base/callback_helpers.h" #include "base/metrics/histogram_functions.h" #include "base/strings/stringprintf.h" +#include "components/services/storage/public/cpp/storage_key.h" #include "content/browser/background_fetch/background_fetch_registration_id.h" #include "content/browser/background_fetch/background_fetch_registration_service_impl.h" #include "content/browser/devtools/devtools_background_services_context_impl.h" @@ -272,7 +273,7 @@ ServiceWorkerLoadedCallback loaded_callback) { service_worker_context_->FindReadyRegistrationForId( registration_id.service_worker_registration_id(), - registration_id.origin(), + storage::StorageKey(registration_id.origin()), base::BindOnce( &BackgroundFetchEventDispatcher::StartActiveWorkerForDispatch, event, std::move(finished_closure), std::move(loaded_callback)));
diff --git a/content/browser/background_fetch/background_fetch_registration_id.h b/content/browser/background_fetch/background_fetch_registration_id.h index 9e817e5..f532a8c 100644 --- a/content/browser/background_fetch/background_fetch_registration_id.h +++ b/content/browser/background_fetch/background_fetch_registration_id.h
@@ -74,6 +74,7 @@ private: int64_t service_worker_registration_id_; + // TODO(crbug.com/1199077): Implement StorageKey. url::Origin origin_; std::string developer_id_; std::string unique_id_;
diff --git a/content/browser/background_fetch/storage/create_metadata_task.cc b/content/browser/background_fetch/storage/create_metadata_task.cc index 38535f6..834f8d91 100644 --- a/content/browser/background_fetch/storage/create_metadata_task.cc +++ b/content/browser/background_fetch/storage/create_metadata_task.cc
@@ -14,6 +14,7 @@ #include "base/strings/string_number_conversions.h" #include "base/strings/utf_string_conversions.h" #include "base/trace_event/trace_event.h" +#include "components/services/storage/public/cpp/storage_key.h" #include "content/browser/background_fetch/background_fetch_data_manager.h" #include "content/browser/background_fetch/background_fetch_data_manager_observer.h" #include "content/browser/background_fetch/storage/database_helpers.h" @@ -50,14 +51,15 @@ ~CanCreateRegistrationTask() override = default; void Start() override { - service_worker_context()->GetRegistrationsForOrigin( - origin_, - base::BindOnce(&CanCreateRegistrationTask::DidGetRegistrationsForOrigin, - weak_factory_.GetWeakPtr())); + service_worker_context()->GetRegistrationsForStorageKey( + storage::StorageKey(origin_), + base::BindOnce( + &CanCreateRegistrationTask::DidGetRegistrationsForStorageKey, + weak_factory_.GetWeakPtr())); } private: - void DidGetRegistrationsForOrigin( + void DidGetRegistrationsForStorageKey( blink::ServiceWorkerStatusCode status, const std::vector<scoped_refptr<ServiceWorkerRegistration>>& registrations) { @@ -344,7 +346,7 @@ service_worker_context()->StoreRegistrationUserData( registration_id_.service_worker_registration_id(), - registration_id_.origin(), entries, + storage::StorageKey(registration_id_.origin()), entries, base::BindOnce(&CreateMetadataTask::DidStoreMetadata, weak_factory_.GetWeakPtr())); }
diff --git a/content/browser/background_fetch/storage/mark_request_complete_task.cc b/content/browser/background_fetch/storage/mark_request_complete_task.cc index 7ab3d17..be30f2c3 100644 --- a/content/browser/background_fetch/storage/mark_request_complete_task.cc +++ b/content/browser/background_fetch/storage/mark_request_complete_task.cc
@@ -8,6 +8,7 @@ #include "base/bind.h" #include "base/guid.h" #include "base/trace_event/trace_event.h" +#include "components/services/storage/public/cpp/storage_key.h" #include "content/browser/background_fetch/background_fetch_cross_origin_filter.h" #include "content/browser/background_fetch/background_fetch_data_manager.h" #include "content/browser/background_fetch/storage/database_helpers.h" @@ -216,7 +217,7 @@ service_worker_context()->StoreRegistrationUserData( registration_id_.service_worker_registration_id(), - registration_id_.origin(), + storage::StorageKey(registration_id_.origin()), {{CompletedRequestKey(completed_request_.unique_id(), completed_request_.request_index()), completed_request_.SerializeAsString()}}, @@ -293,7 +294,7 @@ service_worker_context()->StoreRegistrationUserData( registration_id_.service_worker_registration_id(), - registration_id_.origin(), + storage::StorageKey(registration_id_.origin()), {{RegistrationKey(registration_id_.unique_id()), metadata->SerializeAsString()}}, base::BindOnce(&MarkRequestCompleteTask::DidStoreMetadata,
diff --git a/content/browser/background_fetch/storage/start_next_pending_request_task.cc b/content/browser/background_fetch/storage/start_next_pending_request_task.cc index d9146c8..6676e31 100644 --- a/content/browser/background_fetch/storage/start_next_pending_request_task.cc +++ b/content/browser/background_fetch/storage/start_next_pending_request_task.cc
@@ -6,6 +6,7 @@ #include "base/bind.h" #include "base/guid.h" +#include "components/services/storage/public/cpp/storage_key.h" #include "content/browser/background_fetch/storage/database_helpers.h" #include "content/browser/service_worker/service_worker_context_wrapper.h" #include "content/common/fetch/fetch_api_request_proto.h" @@ -75,7 +76,7 @@ service_worker_context()->StoreRegistrationUserData( registration_id_.service_worker_registration_id(), - registration_id_.origin(), + storage::StorageKey(registration_id_.origin()), {{ActiveRequestKey(active_request_.unique_id(), active_request_.request_index()), active_request_.SerializeAsString()}},
diff --git a/content/browser/background_sync/background_sync_base_browsertest.cc b/content/browser/background_sync/background_sync_base_browsertest.cc index 82bba0c..76b4807 100644 --- a/content/browser/background_sync/background_sync_base_browsertest.cc +++ b/content/browser/background_sync/background_sync_base_browsertest.cc
@@ -10,6 +10,7 @@ #include "base/metrics/field_trial_param_associator.h" #include "base/strings/stringprintf.h" #include "base/task/post_task.h" +#include "components/services/storage/public/cpp/storage_key.h" #include "content/browser/background_sync/background_sync_manager.h" #include "content/browser/storage_partition_impl.h" #include "content/public/browser/browser_context.h" @@ -121,10 +122,11 @@ const GURL& url, base::OnceCallback<void(bool)> callback) { sw_context->FindReadyRegistrationForClientUrl( - url, base::BindOnce(&BackgroundSyncBaseBrowserTest:: - RegistrationPendingDidGetSWRegistration, - base::Unretained(this), sync_context, tag, - std::move(callback))); + url, storage::StorageKey(url::Origin::Create(url)), + base::BindOnce(&BackgroundSyncBaseBrowserTest:: + RegistrationPendingDidGetSWRegistration, + base::Unretained(this), sync_context, tag, + std::move(callback))); } void BackgroundSyncBaseBrowserTest::SetUp() {
diff --git a/content/browser/background_sync/background_sync_manager.cc b/content/browser/background_sync/background_sync_manager.cc index 3e829751..cfee53f 100644 --- a/content/browser/background_sync/background_sync_manager.cc +++ b/content/browser/background_sync/background_sync_manager.cc
@@ -19,6 +19,7 @@ #include "base/time/default_clock.h" #include "base/time/time.h" #include "build/build_config.h" +#include "components/services/storage/public/cpp/storage_key.h" #include "content/browser/background_sync/background_sync_metrics.h" #include "content/browser/background_sync/background_sync_network_observer.h" #include "content/browser/service_worker/embedded_worker_status.h" @@ -1314,7 +1315,8 @@ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); service_worker_context_->StoreRegistrationUserData( - sw_registration_id, origin, {{backend_key, data}}, std::move(callback)); + sw_registration_id, storage::StorageKey(origin), {{backend_key, data}}, + std::move(callback)); } void BackgroundSyncManager::GetDataFromBackend( @@ -1412,7 +1414,7 @@ void BackgroundSyncManager::HasMainFrameWindowClient(const url::Origin& origin, BoolCallback callback) { - service_worker_context_->HasMainFrameWindowClient(origin.GetURL(), + service_worker_context_->HasMainFrameWindowClient(storage::StorageKey(origin), std::move(callback)); } @@ -1948,9 +1950,12 @@ int64_t service_worker_registration_id = registration_info->service_worker_registration_id; + // If BackgroundSync becomes usable from a 3p context then + // BackgroundSyncRegistrations should be changed to use StorageKey. service_worker_context_->FindReadyRegistrationForId( service_worker_registration_id, - active_registrations_[service_worker_registration_id].origin, + storage::StorageKey( + active_registrations_[service_worker_registration_id].origin), base::BindOnce( &BackgroundSyncManager::FireReadyEventsDidFindRegistration, weak_ptr_factory_.GetWeakPtr(), std::move(registration_info),
diff --git a/content/browser/background_sync/background_sync_manager_unittest.cc b/content/browser/background_sync/background_sync_manager_unittest.cc index 0f840ec0..c2ab3c5 100644 --- a/content/browser/background_sync/background_sync_manager_unittest.cc +++ b/content/browser/background_sync/background_sync_manager_unittest.cc
@@ -185,12 +185,12 @@ // Hang onto the registrations as they need to be "live" when // calling BackgroundSyncManager::Register. helper_->context_wrapper()->FindReadyRegistrationForId( - sw_registration_id_1_, url::Origin::Create(GURL(kScope1)), + sw_registration_id_1_, key1, base::BindOnce(FindServiceWorkerRegistrationCallback, &sw_registration_1_)); helper_->context_wrapper()->FindReadyRegistrationForId( - sw_registration_id_2_, url::Origin::Create(GURL(kScope1)), + sw_registration_id_2_, key1, base::BindOnce(FindServiceWorkerRegistrationCallback, &sw_registration_2_)); base::RunLoop().RunUntilIdle();
diff --git a/content/browser/background_sync/background_sync_service_impl_test_harness.cc b/content/browser/background_sync/background_sync_service_impl_test_harness.cc index 828d86b..5a1267f 100644 --- a/content/browser/background_sync/background_sync_service_impl_test_harness.cc +++ b/content/browser/background_sync/background_sync_service_impl_test_harness.cc
@@ -185,7 +185,8 @@ ASSERT_TRUE(called); embedded_worker_helper_->context_wrapper()->FindReadyRegistrationForId( - sw_registration_id_, url::Origin::Create(GURL(kServiceWorkerScope)), + sw_registration_id_, + storage::StorageKey(url::Origin::Create(GURL(kServiceWorkerScope))), base::BindOnce(FindServiceWorkerRegistrationCallback, &sw_registration_)); base::RunLoop().RunUntilIdle(); EXPECT_TRUE(sw_registration_);
diff --git a/content/browser/content_index/content_index_database.cc b/content/browser/content_index/content_index_database.cc index b03bbc2..ed494c9 100644 --- a/content/browser/content_index/content_index_database.cc +++ b/content/browser/content_index/content_index_database.cc
@@ -11,6 +11,7 @@ #include "base/memory/ptr_util.h" #include "base/stl_util.h" #include "base/time/time.h" +#include "components/services/storage/public/cpp/storage_key.h" #include "content/browser/background_fetch/storage/image_helpers.h" #include "content/browser/content_index/content_index.pb.h" #include "content/browser/content_index/content_index_metrics.h" @@ -225,7 +226,7 @@ std::move(description), launch_url, entry_time); service_worker_context_->StoreRegistrationUserData( - service_worker_registration_id, origin, + service_worker_registration_id, storage::StorageKey(origin), {{std::move(entry_key), std::move(entry_value)}, {std::move(icon_key), std::move(icons_value)}}, base::BindOnce(&ContentIndexDatabase::DidAddEntry, @@ -656,7 +657,7 @@ return; service_worker_context_->FindReadyRegistrationForId( - service_worker_registration_id, origin, + service_worker_registration_id, storage::StorageKey(origin), base::BindOnce(&ContentIndexDatabase::StartActiveWorkerForDispatch, weak_ptr_factory_core_.GetWeakPtr(), description_id)); }
diff --git a/content/browser/cookie_store/cookie_store_manager.cc b/content/browser/cookie_store/cookie_store_manager.cc index 0ff2c90..9a0d6750 100644 --- a/content/browser/cookie_store/cookie_store_manager.cc +++ b/content/browser/cookie_store/cookie_store_manager.cc
@@ -9,6 +9,7 @@ #include "base/bind.h" #include "base/callback_helpers.h" +#include "components/services/storage/public/cpp/storage_key.h" #include "content/browser/cookie_store/cookie_change_subscriptions.pb.h" #include "content/browser/service_worker/embedded_worker_status.h" #include "content/browser/service_worker/service_worker_context_wrapper.h" @@ -417,9 +418,11 @@ DCHECK(!subscriptions_data.empty()) << "Failed to create cookie change subscriptions protobuf"; + // TODO(crbug.com/1199077): Update this when CookieStoreManager + // implements StorageKey. service_worker_context_->StoreRegistrationUserData( service_worker_registration_id, - url::Origin::Create(service_worker_origin), + storage::StorageKey(url::Origin::Create(service_worker_origin)), std::vector<std::pair<std::string, std::string>>( {{registration_user_data_key_, subscriptions_data}}), base::BindOnce(
diff --git a/content/browser/devtools/devtools_background_services_context_impl.cc b/content/browser/devtools/devtools_background_services_context_impl.cc index db9f9ea..cbda17e 100644 --- a/content/browser/devtools/devtools_background_services_context_impl.cc +++ b/content/browser/devtools/devtools_background_services_context_impl.cc
@@ -10,6 +10,7 @@ #include "base/metrics/histogram_macros.h" #include "base/strings/string_number_conversions.h" #include "base/time/time.h" +#include "components/services/storage/public/cpp/storage_key.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h" @@ -277,8 +278,10 @@ event.mutable_event_metadata()->insert(event_metadata.begin(), event_metadata.end()); + // TODO(crbug.com/1199077): Update this when + // DevToolsBackgroundServicesContextImpl implements StorageKey. service_worker_context_->StoreRegistrationUserData( - service_worker_registration_id, origin, + service_worker_registration_id, storage::StorageKey(origin), {{CreateEntryKey(event.background_service()), event.SerializeAsString()}}, base::BindOnce(&DidLogServiceEvent));
diff --git a/content/browser/devtools/protocol/service_worker_handler.cc b/content/browser/devtools/protocol/service_worker_handler.cc index fea9dba..4d90b9a 100644 --- a/content/browser/devtools/protocol/service_worker_handler.cc +++ b/content/browser/devtools/protocol/service_worker_handler.cc
@@ -12,6 +12,7 @@ #include "base/strings/string_number_conversions.h" #include "base/strings/utf_string_conversions.h" #include "base/task/post_task.h" +#include "components/services/storage/public/cpp/storage_key.h" #include "content/browser/background_sync/background_sync_context_impl.h" #include "content/browser/background_sync/background_sync_manager.h" #include "content/browser/devtools/service_worker_devtools_agent_host.h" @@ -161,7 +162,7 @@ const std::string& tag, bool last_chance) { context->FindReadyRegistrationForId( - registration_id, origin, + registration_id, storage::StorageKey(origin), base::BindOnce(&DidFindRegistrationForDispatchSyncEventOnCoreThread, sync_context, tag, last_chance)); } @@ -173,7 +174,7 @@ int64_t registration_id, const std::string& tag) { context->FindReadyRegistrationForId( - registration_id, origin, + registration_id, storage::StorageKey(origin), base::BindOnce( &DidFindRegistrationForDispatchPeriodicSyncEventOnCoreThread, sync_context, tag)); @@ -259,7 +260,10 @@ return CreateDomainNotEnabledErrorResponse(); if (!context_) return CreateContextErrorResponse(); - context_->StartActiveServiceWorker(GURL(scope_url), base::DoNothing()); + context_->StartActiveServiceWorker( + GURL(scope_url), + storage::StorageKey(url::Origin::Create(GURL(scope_url))), + base::DoNothing()); return Response::Success(); } @@ -268,7 +272,9 @@ return CreateDomainNotEnabledErrorResponse(); if (!context_) return CreateContextErrorResponse(); - context_->SkipWaitingWorker(GURL(scope_url)); + context_->SkipWaitingWorker( + GURL(scope_url), + storage::StorageKey(url::Origin::Create(GURL(scope_url)))); return Response::Success(); } @@ -306,7 +312,9 @@ return CreateDomainNotEnabledErrorResponse(); if (!context_) return CreateContextErrorResponse(); - context_->UpdateRegistration(GURL(scope_url)); + context_->UpdateRegistration( + GURL(scope_url), + storage::StorageKey(url::Origin::Create(GURL(scope_url)))); return Response::Success(); }
diff --git a/content/browser/metrics/OWNERS b/content/browser/metrics/OWNERS index 90304b7..9795904 100644 --- a/content/browser/metrics/OWNERS +++ b/content/browser/metrics/OWNERS
@@ -1 +1 @@ -file://base/metrics/OWNERS \ No newline at end of file +file://base/metrics/OWNERS
diff --git a/content/browser/notifications/notification_event_dispatcher_impl.cc b/content/browser/notifications/notification_event_dispatcher_impl.cc index 0f63398..438ea26 100644 --- a/content/browser/notifications/notification_event_dispatcher_impl.cc +++ b/content/browser/notifications/notification_event_dispatcher_impl.cc
@@ -9,6 +9,7 @@ #include "base/callback_helpers.h" #include "base/metrics/histogram_functions.h" #include "build/build_config.h" +#include "components/services/storage/public/cpp/storage_key.h" #include "content/browser/notifications/devtools_event_logging.h" #include "content/browser/notifications/platform_notification_context_impl.h" #include "content/browser/service_worker/service_worker_context_wrapper.h" @@ -181,12 +182,14 @@ return; } + // If Push Notification becomes usable from a 3p context then + // NotificationDatabaseData should be changed to use StorageKey. RunOrPostTaskOnThread( FROM_HERE, ServiceWorkerContext::GetCoreThreadId(), base::BindOnce(&ServiceWorkerContextWrapper::FindReadyRegistrationForId, service_worker_context, notification_database_data.service_worker_registration_id, - origin, + storage::StorageKey(origin), base::BindOnce(&DispatchNotificationEventOnRegistration, notification_database_data, std::move(notification_action_callback),
diff --git a/content/browser/notifications/notification_storage.cc b/content/browser/notifications/notification_storage.cc index f7caccdd4..c6e8118 100644 --- a/content/browser/notifications/notification_storage.cc +++ b/content/browser/notifications/notification_storage.cc
@@ -9,6 +9,7 @@ #include "base/bind.h" #include "base/metrics/histogram_macros.h" #include "base/time/time.h" +#include "components/services/storage/public/cpp/storage_key.h" #include "content/browser/notifications/notification_database_conversions.h" namespace content { @@ -56,8 +57,11 @@ return; } + // If Push Notification becomes usable from a 3p context then + // NotificationDatabaseData should be changed to use StorageKey. service_worker_context_->StoreRegistrationUserData( - data.service_worker_registration_id, url::Origin::Create(data.origin), + data.service_worker_registration_id, + storage::StorageKey(url::Origin::Create(data.origin)), {{CreateDataKey(data.notification_id), std::move(serialized_data)}}, base::BindOnce(&NotificationStorage::OnWriteComplete, weak_ptr_factory_.GetWeakPtr(), data, @@ -133,10 +137,11 @@ return; } - url::Origin origin = url::Origin::Create(data->origin); + storage::StorageKey key = + storage::StorageKey(url::Origin::Create(data->origin)); std::string notification_id = data->notification_id; service_worker_context_->StoreRegistrationUserData( - service_worker_registration_id, origin, + service_worker_registration_id, key, {{CreateDataKey(notification_id), std::move(serialized_data)}}, base::BindOnce(&NotificationStorage::OnInteractionUpdateComplete, weak_ptr_factory_.GetWeakPtr(), std::move(data),
diff --git a/content/browser/notifications/platform_notification_service_proxy.cc b/content/browser/notifications/platform_notification_service_proxy.cc index 79c9f41..baf72bb 100644 --- a/content/browser/notifications/platform_notification_service_proxy.cc +++ b/content/browser/notifications/platform_notification_service_proxy.cc
@@ -8,6 +8,7 @@ #include <utility> #include "base/check_op.h" +#include "components/services/storage/public/cpp/storage_key.h" #include "content/browser/notifications/devtools_event_logging.h" #include "content/browser/service_worker/service_worker_context_wrapper.h" #include "content/public/browser/browser_task_traits.h" @@ -101,7 +102,7 @@ base::BindOnce( &ServiceWorkerContextWrapper::FindReadyRegistrationForId, service_worker_context_, data.service_worker_registration_id, - url::Origin::Create(data.origin), + storage::StorageKey(url::Origin::Create(data.origin)), base::BindOnce( &PlatformNotificationServiceProxy::VerifyServiceWorkerScope, weak_ptr_factory_io_.GetWeakPtr(), data, std::move(callback))));
diff --git a/content/browser/payments/payment_app_database.cc b/content/browser/payments/payment_app_database.cc index 410aa20..bc9acd9 100644 --- a/content/browser/payments/payment_app_database.cc +++ b/content/browser/payments/payment_app_database.cc
@@ -12,6 +12,7 @@ #include "base/containers/contains.h" #include "base/strings/utf_string_conversions.h" #include "base/time/time.h" +#include "components/services/storage/public/cpp/storage_key.h" #include "content/browser/payments/payment_app.pb.h" #include "content/browser/payments/payment_app_context_impl.h" #include "content/browser/service_worker/service_worker_context_wrapper.h" @@ -172,8 +173,10 @@ DeletePaymentInstrumentCallback callback) { DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId()); + // TODO(crbug.com/1199077): Update this when PaymentManager + // implements StorageKey. service_worker_context_->FindReadyRegistrationForScope( - scope, + scope, storage::StorageKey(url::Origin::Create(scope)), base::BindOnce( &PaymentAppDatabase::DidFindRegistrationToDeletePaymentInstrument, weak_ptr_factory_.GetWeakPtr(), instrument_key, std::move(callback))); @@ -185,8 +188,10 @@ ReadPaymentInstrumentCallback callback) { DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId()); + // TODO(crbug.com/1199077): Update this when PaymentManager + // implements StorageKey. service_worker_context_->FindReadyRegistrationForScope( - scope, + scope, storage::StorageKey(url::Origin::Create(scope)), base::BindOnce( &PaymentAppDatabase::DidFindRegistrationToReadPaymentInstrument, weak_ptr_factory_.GetWeakPtr(), instrument_key, std::move(callback))); @@ -197,8 +202,10 @@ KeysOfPaymentInstrumentsCallback callback) { DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId()); + // TODO(crbug.com/1199077): Update this when PaymentManager + // implements StorageKey. service_worker_context_->FindReadyRegistrationForScope( - scope, + scope, storage::StorageKey(url::Origin::Create(scope)), base::BindOnce(&PaymentAppDatabase::DidFindRegistrationToGetKeys, weak_ptr_factory_.GetWeakPtr(), std::move(callback))); } @@ -209,8 +216,10 @@ HasPaymentInstrumentCallback callback) { DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId()); + // TODO(crbug.com/1199077): Update this when PaymentManager + // implements StorageKey. service_worker_context_->FindReadyRegistrationForScope( - scope, + scope, storage::StorageKey(url::Origin::Create(scope)), base::BindOnce( &PaymentAppDatabase::DidFindRegistrationToHasPaymentInstrument, weak_ptr_factory_.GetWeakPtr(), instrument_key, std::move(callback))); @@ -223,19 +232,21 @@ WritePaymentInstrumentCallback callback) { DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId()); + // TODO(crbug.com/1199077): Update this when PaymentManager + // implements StorageKey. if (instrument->icons.size() > 0) { std::vector<blink::Manifest::ImageResource> icons(instrument->icons); PaymentInstrumentIconFetcher::Start( scope, service_worker_context_->GetWindowClientFrameRoutingIds( - scope.GetOrigin()), + storage::StorageKey(url::Origin::Create(scope))), icons, base::BindOnce(&PaymentAppDatabase::DidFetchedPaymentInstrumentIcon, weak_ptr_factory_.GetWeakPtr(), scope, instrument_key, std::move(instrument), std::move(callback))); } else { service_worker_context_->FindReadyRegistrationForScope( - scope, + scope, storage::StorageKey(url::Origin::Create(scope)), base::BindOnce( &PaymentAppDatabase::DidFindRegistrationToWritePaymentInstrument, weak_ptr_factory_.GetWeakPtr(), instrument_key, @@ -256,8 +267,10 @@ return; } + // TODO(crbug.com/1199077): Update this when PaymentManager + // implements StorageKey. service_worker_context_->FindReadyRegistrationForScope( - scope, + scope, storage::StorageKey(url::Origin::Create(scope)), base::BindOnce( &PaymentAppDatabase::DidFindRegistrationToWritePaymentInstrument, weak_ptr_factory_.GetWeakPtr(), instrument_key, std::move(instrument), @@ -283,11 +296,14 @@ std::unique_ptr<PaymentAppInfoFetcher::PaymentAppInfo> app_info) { DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId()); + // TODO(crbug.com/1199077): Update this when PaymentManager + // implements StorageKey. service_worker_context_->FindReadyRegistrationForScope( - scope, base::BindOnce( - &PaymentAppDatabase::DidFindRegistrationToUpdatePaymentAppInfo, - weak_ptr_factory_.GetWeakPtr(), std::move(callback), - std::move(app_info))); + scope, storage::StorageKey(url::Origin::Create(scope)), + base::BindOnce( + &PaymentAppDatabase::DidFindRegistrationToUpdatePaymentAppInfo, + weak_ptr_factory_.GetWeakPtr(), std::move(callback), + std::move(app_info))); } void PaymentAppDatabase::DidFindRegistrationToUpdatePaymentAppInfo( @@ -348,8 +364,10 @@ bool success = payment_app_proto.SerializeToString(&serialized_payment_app); DCHECK(success); + // TODO(crbug.com/1199077): Update this when ServiceWorkerRegistration + // implements StorageKey. service_worker_context_->StoreRegistrationUserData( - registration->id(), registration->origin(), + registration->id(), storage::StorageKey(registration->origin()), {{CreatePaymentAppKey(registration->scope().spec()), serialized_payment_app}}, base::BindOnce(&PaymentAppDatabase::DidUpdatePaymentApp, @@ -378,8 +396,10 @@ ClearPaymentInstrumentsCallback callback) { DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId()); + // TODO(crbug.com/1199077): Update this when PaymentManager + // implements StorageKey. service_worker_context_->FindReadyRegistrationForScope( - scope, + scope, storage::StorageKey(url::Origin::Create(scope)), base::BindOnce( &PaymentAppDatabase::DidFindRegistrationToClearPaymentInstruments, weak_ptr_factory_.GetWeakPtr(), scope, std::move(callback))); @@ -389,8 +409,10 @@ const std::string& user_hint) { DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId()); + // TODO(crbug.com/1199077): Update this when PaymentManager + // implements StorageKey. service_worker_context_->FindReadyRegistrationForScope( - scope, + scope, storage::StorageKey(url::Origin::Create(scope)), base::BindOnce( &PaymentAppDatabase::DidFindRegistrationToSetPaymentAppUserHint, weak_ptr_factory_.GetWeakPtr(), user_hint)); @@ -402,8 +424,10 @@ EnableDelegationsCallback callback) { DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId()); + // TODO(crbug.com/1199077): Update this when PaymentManager + // implements StorageKey. service_worker_context_->FindReadyRegistrationForScope( - scope, + scope, storage::StorageKey(url::Origin::Create(scope)), base::BindOnce( &PaymentAppDatabase::DidFindRegistrationToEnablePaymentAppDelegations, weak_ptr_factory_.GetWeakPtr(), delegations, std::move(callback))); @@ -420,6 +444,8 @@ return; } + // TODO(crbug.com/1199077): Update this when ServiceWorkerRegistration + // implements StorageKey. service_worker_context_->GetRegistrationUserDataByKeyPrefix( registration->id(), CreatePaymentAppKey(registration->scope().spec()), base::BindOnce( @@ -473,7 +499,7 @@ DCHECK(success); service_worker_context_->StoreRegistrationUserData( - registration_id, url::Origin::Create(pattern), + registration_id, storage::StorageKey(url::Origin::Create(pattern)), {{CreatePaymentAppKey(pattern.spec()), serialized_payment_app}}, base::BindOnce(&PaymentAppDatabase::DidEnablePaymentAppDelegations, weak_ptr_factory_.GetWeakPtr(), std::move(callback))); @@ -497,6 +523,8 @@ if (status != blink::ServiceWorkerStatusCode::kOk) return; + // TODO(crbug.com/1199077): Update this when ServiceWorkerRegistration + // implements StorageKey. service_worker_context_->GetRegistrationUserDataByKeyPrefix( registration->id(), CreatePaymentAppKey(registration->scope().spec()), base::BindOnce(&PaymentAppDatabase::DidGetPaymentAppInfoToSetUserHint, @@ -526,7 +554,7 @@ DCHECK(success); service_worker_context_->StoreRegistrationUserData( - registration_id, url::Origin::Create(pattern), + registration_id, storage::StorageKey(url::Origin::Create(pattern)), {{CreatePaymentAppKey(pattern.spec()), serialized_payment_app}}, base::BindOnce(&PaymentAppDatabase::DidSetPaymentAppUserHint, weak_ptr_factory_.GetWeakPtr())); @@ -599,8 +627,10 @@ int64_t registration_id = registration->id(); url::Origin registration_origin = registration->origin(); std::string storage_key = CreatePaymentAppKey(registration->scope().spec()); + // TODO(crbug.com/1199077): Update this when ServiceWorkerRegistration + // implements StorageKey. service_worker_context_->StoreRegistrationUserData( - registration_id, registration_origin, + registration_id, storage::StorageKey(registration_origin), {{storage_key, serialized_payment_app}}, base::BindOnce(&PaymentAppDatabase::DidWritePaymentAppForSetPaymentApp, weak_ptr_factory_.GetWeakPtr(), instrument_key, method, @@ -639,8 +669,10 @@ success = key_info_proto.SerializeToString(&serialized_key_info); DCHECK(success); + // TODO(crbug.com/1199077): Update this when ServiceWorkerRegistration + // implements StorageKey. service_worker_context_->StoreRegistrationUserData( - registration->id(), registration->origin(), + registration->id(), storage::StorageKey(registration->origin()), {{CreatePaymentInstrumentKey(instrument_key), serialized_instrument}, {CreatePaymentInstrumentKeyInfoKey(instrument_key), serialized_key_info}}, @@ -920,8 +952,10 @@ success = key_info_proto.SerializeToString(&serialized_key_info); DCHECK(success); + // TODO(crbug.com/1199077): Update this when ServiceWorkerRegistration + // implements StorageKey. service_worker_context_->StoreRegistrationUserData( - registration->id(), registration->origin(), + registration->id(), storage::StorageKey(registration->origin()), {{CreatePaymentInstrumentKey(instrument_key), serialized_instrument}, {CreatePaymentInstrumentKeyInfoKey(instrument_key), serialized_key_info}},
diff --git a/content/browser/payments/payment_app_info_fetcher.cc b/content/browser/payments/payment_app_info_fetcher.cc index 7a2d7248..f6a9cf47 100644 --- a/content/browser/payments/payment_app_info_fetcher.cc +++ b/content/browser/payments/payment_app_info_fetcher.cc
@@ -11,6 +11,7 @@ #include "base/bind.h" #include "base/callback_helpers.h" #include "components/payments/content/icon/icon_size.h" +#include "components/services/storage/public/cpp/storage_key.h" #include "content/browser/renderer_host/render_frame_host_impl.h" #include "content/browser/service_worker/service_worker_context_wrapper.h" #include "content/browser/web_contents/web_contents_impl.h" @@ -38,7 +39,7 @@ std::unique_ptr<std::vector<GlobalFrameRoutingId>> frame_routing_ids = service_worker_context->GetWindowClientFrameRoutingIds( - context_url.GetOrigin()); + storage::StorageKey(url::Origin::Create(context_url))); RunOrPostTaskOnThread( FROM_HERE, BrowserThread::UI,
diff --git a/content/browser/payments/payment_app_installer.cc b/content/browser/payments/payment_app_installer.cc index 4706058..6a2c7020 100644 --- a/content/browser/payments/payment_app_installer.cc +++ b/content/browser/payments/payment_app_installer.cc
@@ -10,6 +10,7 @@ #include "base/memory/ref_counted.h" #include "base/metrics/histogram_functions.h" #include "base/task/post_task.h" +#include "components/services/storage/public/cpp/storage_key.h" #include "content/browser/payments/payment_app_context_impl.h" #include "content/browser/service_worker/service_worker_context_wrapper.h" #include "content/browser/storage_partition_impl.h" @@ -70,7 +71,7 @@ browser_context->GetDefaultStoragePartition() ->GetServiceWorkerContext())); service_worker_context_->FindReadyRegistrationForScope( - scope_, + scope_, storage::StorageKey(url::Origin::Create(scope_)), base::BindOnce(&SelfDeleteInstaller::OnFindReadyRegistrationForScope, this)); }
diff --git a/content/browser/prerender/OWNERS b/content/browser/prerender/OWNERS index cf065e6..ea93cf2 100644 --- a/content/browser/prerender/OWNERS +++ b/content/browser/prerender/OWNERS
@@ -1,6 +1,5 @@ falken@chromium.org kinuko@chromium.org +lingqi@chromium.org nhiroki@chromium.org toyoshim@chromium.org - -per-file *test.cc=lingqi@chromium.org
diff --git a/content/browser/prerender/prerender_host_registry.cc b/content/browser/prerender/prerender_host_registry.cc index e412512..8a338138 100644 --- a/content/browser/prerender/prerender_host_registry.cc +++ b/content/browser/prerender/prerender_host_registry.cc
@@ -40,6 +40,10 @@ blink::mojom::PrerenderAttributesPtr attributes, RenderFrameHostImpl& initiator_render_frame_host) { DCHECK(attributes); + TRACE_EVENT2( + "navigation", "PrerenderHostRegistry::CreateAndStartHost", "attributes", + attributes, "initiator_origin", + initiator_render_frame_host.GetLastCommittedOrigin().GetURL().spec()); // Ensure observers are notified that a trigger occurred. base::ScopedClosureRunner notify_trigger( @@ -57,15 +61,10 @@ } // Ignore prerendering requests for the same URL. - const GURL prerendering_url = attributes->url; - TRACE_EVENT2( - "navigation", "PrerenderHostRegistry::CreateAndStartHost", "attributes", - attributes, "initiator_origin", - initiator_render_frame_host.GetLastCommittedOrigin().GetURL().spec()); - - auto found = frame_tree_node_id_by_url_.find(prerendering_url); - if (found != frame_tree_node_id_by_url_.end()) - return found->second; + for (auto& iter : prerender_host_by_frame_tree_node_id_) { + if (iter.second->GetInitialUrl() == attributes->url) + return iter.first; + } auto prerender_host = std::make_unique<PrerenderHost>( std::move(attributes), initiator_render_frame_host); @@ -75,7 +74,6 @@ frame_tree_node_id)); prerender_host_by_frame_tree_node_id_[frame_tree_node_id] = std::move(prerender_host); - frame_tree_node_id_by_url_[prerendering_url] = frame_tree_node_id; prerender_host_by_frame_tree_node_id_[frame_tree_node_id] ->StartPrerendering(); @@ -137,17 +135,18 @@ if (site_instance->GetRelatedActiveContentsCount() != 1u) return RenderFrameHost::kNoFrameTreeNodeId; - auto id_iter = frame_tree_node_id_by_url_.find(navigation_url); - if (id_iter == frame_tree_node_id_by_url_.end()) - return RenderFrameHostImpl::kNoFrameTreeNodeId; - const int prerender_frame_tree_node_id = id_iter->second; - frame_tree_node_id_by_url_.erase(id_iter); - - auto host_iter = - prerender_host_by_frame_tree_node_id_.find(prerender_frame_tree_node_id); - DCHECK(host_iter != prerender_host_by_frame_tree_node_id_.end()); - std::unique_ptr<PrerenderHost> host = std::move(host_iter->second); - prerender_host_by_frame_tree_node_id_.erase(host_iter); + // Find an available host for the navigation URL. + std::unique_ptr<PrerenderHost> host; + for (auto iter = prerender_host_by_frame_tree_node_id_.begin(); + iter != prerender_host_by_frame_tree_node_id_.end(); ++iter) { + if (iter->second->GetInitialUrl() == navigation_url) { + host = std::move(iter->second); + prerender_host_by_frame_tree_node_id_.erase(iter); + break; + } + } + if (!host) + return RenderFrameHost::kNoFrameTreeNodeId; // If the host is not ready for activation yet, destroys it and returns // an invalid id. This is because it is likely that the prerendered page is @@ -156,6 +155,7 @@ return RenderFrameHost::kNoFrameTreeNodeId; // Reserve the host for activation. + const int prerender_frame_tree_node_id = host->frame_tree_node_id(); auto result = reserved_prerender_host_by_frame_tree_node_id_.emplace( prerender_frame_tree_node_id, std::move(host)); DCHECK(result.second); @@ -223,14 +223,11 @@ PrerenderHost* PrerenderHostRegistry::FindHostByUrlForTesting( const GURL& prerendering_url) { - auto id_iter = frame_tree_node_id_by_url_.find(prerendering_url); - if (id_iter == frame_tree_node_id_by_url_.end()) - return nullptr; - const int prerender_frame_tree_node_id = id_iter->second; - auto host_iter = - prerender_host_by_frame_tree_node_id_.find(prerender_frame_tree_node_id); - DCHECK(host_iter != prerender_host_by_frame_tree_node_id_.end()); - return host_iter->second.get(); + for (auto& iter : prerender_host_by_frame_tree_node_id_) { + if (iter.second->GetInitialUrl() == prerendering_url) + return iter.second.get(); + } + return nullptr; } std::unique_ptr<PrerenderHost> PrerenderHostRegistry::AbandonHostInternal( @@ -239,7 +236,6 @@ if (found == prerender_host_by_frame_tree_node_id_.end()) return nullptr; std::unique_ptr<PrerenderHost> prerender_host = std::move(found->second); - frame_tree_node_id_by_url_.erase(prerender_host->GetInitialUrl()); prerender_host_by_frame_tree_node_id_.erase(found); return prerender_host; }
diff --git a/content/browser/prerender/prerender_host_registry.h b/content/browser/prerender/prerender_host_registry.h index 785e498..04128db 100644 --- a/content/browser/prerender/prerender_host_registry.h +++ b/content/browser/prerender/prerender_host_registry.h
@@ -5,9 +5,9 @@ #ifndef CONTENT_BROWSER_PRERENDER_PRERENDER_HOST_REGISTRY_H_ #define CONTENT_BROWSER_PRERENDER_PRERENDER_HOST_REGISTRY_H_ -#include <map> #include <vector> +#include "base/containers/flat_map.h" #include "base/memory/weak_ptr.h" #include "base/observer_list_types.h" #include "base/types/pass_key.h" @@ -140,12 +140,11 @@ // Hosts that are not reserved for activation yet. // TODO(https://crbug.com/1132746): Expire prerendered contents if they are // not used for a while. - std::map<int, std::unique_ptr<PrerenderHost>> + base::flat_map<int, std::unique_ptr<PrerenderHost>> prerender_host_by_frame_tree_node_id_; - std::map<GURL, int> frame_tree_node_id_by_url_; // Hosts that are reserved for activation. - std::map<int, std::unique_ptr<PrerenderHost>> + base::flat_map<int, std::unique_ptr<PrerenderHost>> reserved_prerender_host_by_frame_tree_node_id_; // Hosts that are scheduled to be deleted asynchronously.
diff --git a/content/browser/push_messaging/push_messaging_manager.cc b/content/browser/push_messaging/push_messaging_manager.cc index 910e436a..8c62462 100644 --- a/content/browser/push_messaging/push_messaging_manager.cc +++ b/content/browser/push_messaging/push_messaging_manager.cc
@@ -18,6 +18,7 @@ #include "base/strings/string_number_conversions.h" #include "base/task/post_task.h" #include "base/time/time.h" +#include "components/services/storage/public/cpp/storage_key.h" #include "content/browser/permissions/permission_controller_impl.h" #include "content/browser/renderer_host/render_process_host_impl.h" #include "content/browser/service_worker/service_worker_context_core.h" @@ -569,7 +570,7 @@ data.options->application_server_key.end())); service_worker_context_->StoreRegistrationUserData( - registration_id, requesting_origin, + registration_id, storage::StorageKey(requesting_origin), {{kPushRegistrationIdServiceWorkerKey, push_subscription_id}, {kPushSenderIdServiceWorkerKey, application_server_key}}, base::BindOnce(&PushMessagingManager::DidPersistRegistrationOnSW,
diff --git a/content/browser/push_messaging/push_messaging_router.cc b/content/browser/push_messaging/push_messaging_router.cc index 43c4dd05..5ea11437 100644 --- a/content/browser/push_messaging/push_messaging_router.cc +++ b/content/browser/push_messaging/push_messaging_router.cc
@@ -9,6 +9,7 @@ #include "base/bind.h" #include "base/feature_list.h" #include "base/metrics/histogram_macros.h" +#include "components/services/storage/public/cpp/storage_key.h" #include "content/browser/devtools/devtools_background_services_context_impl.h" #include "content/browser/service_worker/service_worker_context_wrapper.h" #include "content/browser/service_worker/service_worker_registration.h" @@ -83,7 +84,7 @@ // Try to acquire the registration from storage. If it's already live we'll // receive it right away. If not, it will be revived from storage. service_worker_context->FindReadyRegistrationForId( - service_worker_registration_id, origin, + service_worker_registration_id, storage::StorageKey(origin), base::BindOnce(&DidFindServiceWorkerRegistration, event_type, std::move(devtools_context), std::move(callback))); }
diff --git a/content/browser/renderer_host/agent_scheduling_group_host.cc b/content/browser/renderer_host/agent_scheduling_group_host.cc index 68d34d9..5249e91 100644 --- a/content/browser/renderer_host/agent_scheduling_group_host.cc +++ b/content/browser/renderer_host/agent_scheduling_group_host.cc
@@ -343,11 +343,13 @@ int32_t view_routing_id, int32_t parent_routing_id, blink::mojom::FrameReplicationStatePtr replicated_state, - const base::UnguessableToken& devtools_frame_token) { + const base::UnguessableToken& devtools_frame_token, + mojom::RemoteMainFrameInterfacesPtr remote_main_frame_interfaces) { DCHECK_EQ(state_, LifecycleState::kBound); mojo_remote_.get()->CreateFrameProxy( token, routing_id, opener_frame_token, view_routing_id, parent_routing_id, - std::move(replicated_state), devtools_frame_token); + std::move(replicated_state), devtools_frame_token, + std::move(remote_main_frame_interfaces)); } void AgentSchedulingGroupHost::ReportNoBinderForInterface(
diff --git a/content/browser/renderer_host/agent_scheduling_group_host.h b/content/browser/renderer_host/agent_scheduling_group_host.h index ba5c49e..066e796 100644 --- a/content/browser/renderer_host/agent_scheduling_group_host.h +++ b/content/browser/renderer_host/agent_scheduling_group_host.h
@@ -99,7 +99,8 @@ int32_t view_routing_id, int32_t parent_routing_id, blink::mojom::FrameReplicationStatePtr replicated_state, - const base::UnguessableToken& devtools_frame_token); + const base::UnguessableToken& devtools_frame_token, + mojom::RemoteMainFrameInterfacesPtr remote_main_frame_interfaces); void ReportNoBinderForInterface(const std::string& error);
diff --git a/content/browser/renderer_host/input/OWNERS b/content/browser/renderer_host/input/OWNERS index 4b2a6ae8..d38a99e 100644 --- a/content/browser/renderer_host/input/OWNERS +++ b/content/browser/renderer_host/input/OWNERS
@@ -1,3 +1,3 @@ dtapuska@chromium.org flackr@chromium.org -bokan@chromium.org \ No newline at end of file +bokan@chromium.org
diff --git a/content/browser/renderer_host/render_frame_host_impl.cc b/content/browser/renderer_host/render_frame_host_impl.cc index 7f4dc27..59277c2e 100644 --- a/content/browser/renderer_host/render_frame_host_impl.cc +++ b/content/browser/renderer_host/render_frame_host_impl.cc
@@ -803,8 +803,11 @@ NavigationRequest* navigation_request, const mojom::DidCommitProvisionalLoadParams& params) { DCHECK(navigation_request); + + // This should be called only when a new document is created. Navigations in + // the same document and page activations do not create a new document. DCHECK(!navigation_request->IsSameDocument()); - DCHECK(!navigation_request->IsServedFromBackForwardCache()); + DCHECK(!navigation_request->IsPageActivation()); // Ignore for now cases where the NavigationRequest is in an unexpectedly // early state. Triggered by the following tests: @@ -3727,7 +3730,8 @@ GetMojomFrameInRenderer()->Unload( proxy->GetRoutingID(), is_loading, proxy->frame_tree_node()->current_replication_state().Clone(), - proxy->GetFrameToken()); + proxy->GetFrameToken(), + proxy->BindAndPassRemoteMainFrameInterfaces()); // Remember that a RenderFrameProxy was created as part of processing the // Unload message above. proxy->SetRenderFrameProxyCreated(true); @@ -3760,7 +3764,7 @@ GetMojomFrameInRenderer()->Unload( proxy->GetRoutingID(), /*is_loading=*/false, frame_tree_node()->current_replication_state().Clone(), - proxy->GetFrameToken()); + proxy->GetFrameToken(), proxy->BindAndPassRemoteMainFrameInterfaces()); } void RenderFrameHostImpl::DetachFromProxy() { @@ -9404,12 +9408,10 @@ isolation_info_ = navigation_request->isolation_info_for_subresources(); - // Navigations in the same document, or navigations that activate an existing - // bfcached or prerendered document, do not create a new document. + // Navigations in the same document and page activations do not create a new + // document. bool created_new_document = - !is_same_document_navigation && - !navigation_request->IsServedFromBackForwardCache() && - !navigation_request->IsPrerenderedPageActivation(); + !is_same_document_navigation && !navigation_request->IsPageActivation(); // TODO(crbug.com/936696): Remove this after we have RenderDocument. // IsWaitingToCommit can be false inside DidCommitNavigationInternal only in @@ -9503,9 +9505,10 @@ void RenderFrameHostImpl::DidCommitNewDocument( const mojom::DidCommitProvisionalLoadParams& params, NavigationRequest* navigation_request) { - // BackForwardCache navigations restore existing document, but never create - // new ones. - DCHECK(!navigation_request->IsServedFromBackForwardCache()); + // Navigations in the same document and page activations do not create a new + // document. + DCHECK(!navigation_request->IsSameDocument()); + DCHECK(!navigation_request->IsPageActivation()); ResetPermissionsPolicy(); // There are two type of navigations committing new documents:
diff --git a/content/browser/renderer_host/render_frame_proxy_host.cc b/content/browser/renderer_host/render_frame_proxy_host.cc index cd86b1a..9c5444e5 100644 --- a/content/browser/renderer_host/render_frame_proxy_host.cc +++ b/content/browser/renderer_host/render_frame_proxy_host.cc
@@ -60,6 +60,12 @@ return *s_callback; } +RenderFrameProxyHost::BindRemoteFrameCallback& GetBindRemoteFrameCallback() { + static base::NoDestructor<RenderFrameProxyHost::BindRemoteFrameCallback> + s_callback; + return *s_callback; +} + // The (process id, routing id) pair that identifies one RenderFrameProxy. typedef std::pair<int32_t, int32_t> RenderFrameProxyHostID; typedef std::unordered_map<RenderFrameProxyHostID, @@ -119,6 +125,12 @@ } // static +void RenderFrameProxyHost::SetBindRemoteFrameCallbackForTesting( + const BindRemoteFrameCallback& bind_callback) { + GetBindRemoteFrameCallback() = bind_callback; +} + +// static RenderFrameProxyHost* RenderFrameProxyHost::FromID(int process_id, int routing_id) { DCHECK_CURRENTLY_ON(BrowserThread::UI); @@ -300,7 +312,8 @@ .CreateFrameProxy(frame_token_, routing_id_, opener_frame_token, view_routing_id, parent_routing_id, frame_tree_node_->current_replication_state().Clone(), - frame_tree_node_->devtools_frame_token()); + frame_tree_node_->devtools_frame_token(), + BindAndPassRemoteMainFrameInterfaces()); SetRenderFrameProxyCreated(true); @@ -342,11 +355,6 @@ remote_frame_host_receiver_.Bind( mojo::PendingAssociatedReceiver<blink::mojom::RemoteFrameHost>( std::move(handle))); - } else if (interface_name == blink::mojom::RemoteMainFrameHost::Name_) { - remote_main_frame_host_receiver_.reset(); - remote_main_frame_host_receiver_.Bind( - mojo::PendingAssociatedReceiver<blink::mojom::RemoteMainFrameHost>( - std::move(handle))); } } @@ -374,6 +382,11 @@ void RenderFrameProxyHost::SetRenderFrameProxyCreated(bool created) { render_frame_proxy_created_ = created; + + // Reset the mojo channels when the associated renderer is gone. It allows + // reuse of the mojo channels when this RenderFrameProxyHost is reused. + if (!render_frame_proxy_created_) + InvalidateMojoConnection(); } const mojo::AssociatedRemote<blink::mojom::RemoteFrame>& @@ -385,8 +398,6 @@ const mojo::AssociatedRemote<blink::mojom::RemoteMainFrame>& RenderFrameProxyHost::GetAssociatedRemoteMainFrame() { - if (!remote_main_frame_) - GetRemoteAssociatedInterfaces()->GetInterface(&remote_main_frame_); return remote_main_frame_; } @@ -783,4 +794,33 @@ return GetRemoteAssociatedInterfaces(); } +mojo::PendingAssociatedReceiver<blink::mojom::RemoteMainFrame> +RenderFrameProxyHost::BindRemoteMainFrameReceiverForTesting() { + remote_main_frame_.reset(); + return remote_main_frame_.BindNewEndpointAndPassDedicatedReceiver(); +} + +mojom::RemoteMainFrameInterfacesPtr +RenderFrameProxyHost::BindAndPassRemoteMainFrameInterfaces() { + DCHECK(!remote_main_frame_.is_bound()); + DCHECK(!remote_main_frame_host_receiver_.is_bound()); + + auto params = mojom::RemoteMainFrameInterfaces::New(); + params->main_frame = remote_main_frame_.BindNewEndpointAndPassReceiver(); + remote_main_frame_host_receiver_.Bind( + params->main_frame_host.InitWithNewEndpointAndPassReceiver()); + + // This callback is only for testing which needs to intercept RemoteMainFrame + // interfaces. + if (!GetBindRemoteFrameCallback().is_null()) + GetBindRemoteFrameCallback().Run(this); + + return params; +} + +void RenderFrameProxyHost::InvalidateMojoConnection() { + remote_main_frame_.reset(); + remote_main_frame_host_receiver_.reset(); +} + } // namespace content
diff --git a/content/browser/renderer_host/render_frame_proxy_host.h b/content/browser/renderer_host/render_frame_proxy_host.h index b0445a40..88f7b04 100644 --- a/content/browser/renderer_host/render_frame_proxy_host.h +++ b/content/browser/renderer_host/render_frame_proxy_host.h
@@ -74,6 +74,8 @@ public: using CreatedCallback = base::RepeatingCallback<void(RenderFrameProxyHost*)>; using DeletedCallback = base::RepeatingCallback<void(RenderFrameProxyHost*)>; + using BindRemoteFrameCallback = + base::RepeatingCallback<void(RenderFrameProxyHost*)>; static RenderFrameProxyHost* FromID(int process_id, int routing_id); static RenderFrameProxyHost* FromFrameToken( @@ -88,6 +90,11 @@ static void SetDeletedCallbackForTesting( const DeletedCallback& deleted_callback); + // Sets a callback to be called whenever mojo connections to any + // RenderFrameProxyHost is bound and transferred. + static void SetBindRemoteFrameCallbackForTesting( + const BindRemoteFrameCallback& bind_callback); + RenderFrameProxyHost(SiteInstance* site_instance, scoped_refptr<RenderViewHostImpl> render_view_host, FrameTreeNode* frame_tree_node); @@ -222,8 +229,16 @@ blink::AssociatedInterfaceProvider* GetRemoteAssociatedInterfacesTesting(); bool IsInertForTesting(); + mojo::PendingAssociatedReceiver<blink::mojom::RemoteMainFrame> + BindRemoteMainFrameReceiverForTesting(); + const blink::RemoteFrameToken& GetFrameToken() const { return frame_token_; } + // Bind mojo endpoints of the RemoteMainFrame in blink and pass unbound + // corresponding endpoints. The corresponding endpoints should be transferred + // and bound in blink. + mojom::RemoteMainFrameInterfacesPtr BindAndPassRemoteMainFrameInterfaces(); + private: // These interceptor need access to frame_host_receiver_for_testing(). friend class RemoteFrameHostInterceptor; @@ -241,6 +256,10 @@ blink::AssociatedInterfaceProvider* GetRemoteAssociatedInterfaces(); + // Invalidate the mojo connections between this RenderFrameProxyHost and its + // associated instances in renderer. + void InvalidateMojoConnection(); + // Needed for tests to be able to swap the implementation and intercept calls. mojo::AssociatedReceiver<blink::mojom::RemoteFrameHost>& frame_host_receiver_for_testing() {
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc index 1512a77..6a84a65f 100644 --- a/content/browser/renderer_host/render_process_host_impl.cc +++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -23,6 +23,7 @@ #include "base/command_line.h" #include "base/containers/adapters.h" #include "base/containers/contains.h" +#include "base/containers/flat_map.h" #include "base/debug/alias.h" #include "base/debug/crash_logging.h" #include "base/debug/dump_without_crashing.h" @@ -280,6 +281,13 @@ #include "content/public/common/profiling_utils.h" #endif +// VLOG additional statements in Fuchsia release builds. +#if defined(OS_FUCHSIA) +#define MAYBEVLOG VLOG +#else +#define MAYBEVLOG DVLOG +#endif + namespace content { namespace { @@ -323,6 +331,31 @@ return *s_all_creation_observers; } +// Returns |host|'s PID if the process is valid and "no-process" otherwise. +std::string GetRendererPidAsString(RenderProcessHost* host) { + if (host->GetProcess().IsValid()) { + return base::NumberToString(host->GetProcess().Pid()); + } + + return "no-process"; +} + +std::ostream& operator<<(std::ostream& o, + const SiteInstanceProcessAssignment& assignment) { + switch (assignment) { + case SiteInstanceProcessAssignment::UNKNOWN: + return o << "No renderer process has been assigned to the SiteInstance " + "yet."; + case SiteInstanceProcessAssignment::REUSED_EXISTING_PROCESS: + return o << "Reused some pre-existing process."; + case SiteInstanceProcessAssignment::USED_SPARE_PROCESS: + return o << "Used an existing spare process."; + case SiteInstanceProcessAssignment::CREATED_NEW_PROCESS: + return o << "No renderer could be reused, so a new one was created for " + "the SiteInstance."; + } +} + // Map of site to process, to ensure we only have one RenderProcessHost per // site in process-per-site mode. Each map is specific to a BrowserContext. class SiteProcessMap : public base::SupportsUserData::Data { @@ -947,7 +980,65 @@ } } + // Returns a string containing formatted data from + // GetHostIdToSiteMapForDebugging(). + std::string GetDebugString() const { + HostIdToSiteMap rph_to_sites_map = GetHostIdToSiteMapForDebugging(); + std::string output; + + for (auto host_info : rph_to_sites_map) { + RenderProcessHost* host = GetAllHosts().Lookup(host_info.first); + DCHECK(host); + + bool is_locked_to_site = ChildProcessSecurityPolicyImpl::GetInstance() + ->GetProcessLock(host->GetID()) + .is_locked_to_site(); + output += base::StringPrintf("\tProcess Host ID %d (PID %s, %s):\n", + host_info.first, + GetRendererPidAsString(host).c_str(), + is_locked_to_site ? "locked" : "not locked"); + + for (auto site_string : host_info.second) { + output += base::StringPrintf("\t\t%s\n", site_string.c_str()); + } + } + + return output; + } + private: + using ProcessID = int; + using Count = int; + using HostIdToSiteMap = base::flat_map<ProcessID, std::vector<std::string>>; + + // Creates a new mapping of the ProcessID to sites and their count based on + // the current map_. + HostIdToSiteMap GetHostIdToSiteMapForDebugging() const { + HostIdToSiteMap rph_to_sites_map; + + // There may be process hosts without sites. To ensure all process hosts are + // represented, start by adding entries for all hosts. + rph_to_sites_map.reserve(GetAllHosts().size()); + for (auto iter(RenderProcessHost::AllHostsIterator()); !iter.IsAtEnd(); + iter.Advance()) { + rph_to_sites_map[iter.GetCurrentValue()->GetID()]; + } + + for (auto iter : map_) { + std::string site = iter.first.GetDebugString(); + std::map<ProcessID, Count>& counts_per_process = iter.second; + for (auto iter_process : counts_per_process) { + ProcessID id = iter_process.first; + Count count = iter_process.second; + + rph_to_sites_map[id].push_back( + base::StringPrintf("%s -- count: %d", site.c_str(), count)); + } + } + + return rph_to_sites_map; + } + void RenderProcessHostDestroyed(RenderProcessHost* host) override { #ifndef NDEBUG host->RemoveObserver(this); @@ -956,7 +1047,7 @@ } #ifndef NDEBUG - // Used in debug builds to ensure that RenderProcessHost don't persist in the + // Used in debug builds to ensure that RenderProcessHosts don't persist in the // map after they've been destroyed. bool HasProcess(RenderProcessHost* process) { for (auto iter : map_) { @@ -970,8 +1061,6 @@ } #endif - using ProcessID = int; - using Count = int; using CountPerProcessPerSiteMap = std::map<SiteInfo, std::map<ProcessID, Count>>; CountPerProcessPerSiteMap map_; @@ -983,8 +1072,12 @@ // StoragePartition. For now, track them only in the default one. StoragePartition* default_partition = browser_context->GetDefaultStoragePartition(); - if (dest_partition != default_partition) + if (dest_partition != default_partition) { + MAYBEVLOG(2) << __func__ + << ": Site process tracking will not be available for a " + "non-default partition."; return false; + } return true; } @@ -1010,6 +1103,18 @@ site_info.GetStoragePartitionConfig(browser_context))); } +std::string GetCurrentHostMapDebugString( + const SiteProcessCountTracker* tracker) { + std::string output = base::StringPrintf( + "There are now %zu RenderProcessHosts.", GetAllHosts().size()); + if (tracker) { + output += base::StringPrintf("\nThe mappings are:\n%s", + tracker->GetDebugString().c_str()); + } + + return output; +} + const void* const kUnmatchedServiceWorkerProcessTrackerKey = "UnmatchedServiceWorkerProcessTrackerKey"; @@ -1491,6 +1596,7 @@ max_count = base::ClampToRange(max_count, kMinRendererProcessCount, kMaxRendererProcessCount); + MAYBEVLOG(1) << __func__ << ": Calculated max " << max_count; } return max_count; #endif @@ -1498,7 +1604,9 @@ // static void RenderProcessHost::SetMaxRendererProcessCount(size_t count) { + MAYBEVLOG(1) << __func__ << ": Max override set to " << count; g_max_renderer_count_override = count; + if (GetAllHosts().size() > count) { SpareRenderProcessHostManager::GetInstance() .CleanupSpareRenderProcessHost(); @@ -2944,6 +3052,11 @@ SiteProcessCountTracker* tracker = SiteProcessCountTracker::GetInstance( browser_context, kCommittedSiteProcessCountTrackerKey); tracker->IncrementSiteProcessCount(site_info, render_process_host->GetID()); + + MAYBEVLOG(2) << __func__ << "(" << site_info + << "): Site added to process host " + << render_process_host->GetID() << "." << std::endl + << GetCurrentHostMapDebugString(tracker); } // static @@ -3892,6 +4005,13 @@ GetAllHosts().Remove(host_id); + // Log after updating the GetAllHosts() list but before deleting the host. + MAYBEVLOG(3) << __func__ << "(" << host_id << ")" << std::endl + << GetCurrentHostMapDebugString( + static_cast<SiteProcessCountTracker*>( + host->GetBrowserContext()->GetUserData( + kCommittedSiteProcessCountTrackerKey))); + // Look up the map of site to process for the given browser_context, // in case we need to remove this process from it. It will be registered // under any sites it rendered that use process-per-site mode. @@ -4146,8 +4266,14 @@ // a renderer process for a browser context that has no existing // renderers. This is OK in moderation, since the // GetMaxRendererProcessCount() is conservative. - if (GetAllHosts().size() >= GetMaxRendererProcessCount()) + if (GetAllHosts().size() >= GetMaxRendererProcessCount()) { + MAYBEVLOG(4) << __func__ + << ": GetAllHosts().size() >= GetMaxRendererProcessCount() (" + << GetAllHosts().size() + << " >= " << GetMaxRendererProcessCount() + << ") - will try to reuse an existing process"; return true; + } return GetContentClient()->browser()->ShouldTryToUseExistingProcessHost( browser_context, url); @@ -4171,6 +4297,10 @@ suitable_renderers.push_back(iter.GetCurrentValue()); } + MAYBEVLOG(4) << __func__ << ": Found " << suitable_renderers.size() + << " suitable process hosts out of " << GetAllHosts().size() + << "."; + // Now pick a random suitable renderer, if we have any. if (!suitable_renderers.empty()) { int suitable_count = static_cast<int>(suitable_renderers.size()); @@ -4405,6 +4535,15 @@ browser_context->GetStoragePartition(site_instance, false /* can_create */))); + MAYBEVLOG(2) << __func__ << "(" << site_info << ") selected process host " + << render_process_host->GetID() << " using assignment \"" + << site_instance->GetLastProcessAssignmentOutcome() << "\"" + << std::endl + << GetCurrentHostMapDebugString( + static_cast<SiteProcessCountTracker*>( + browser_context->GetUserData( + kCommittedSiteProcessCountTrackerKey))); + return render_process_host; }
diff --git a/content/browser/renderer_host/render_view_host_impl.cc b/content/browser/renderer_host/render_view_host_impl.cc index 33334db..542d785 100644 --- a/content/browser/renderer_host/render_view_host_impl.cc +++ b/content/browser/renderer_host/render_view_host_impl.cc
@@ -466,8 +466,9 @@ std::move(local_frame_params)); } else { params->main_frame = mojom::CreateMainFrameUnion::NewRemoteParams( - mojom::CreateRemoteMainFrameParams::New(main_rfph->GetFrameToken(), - proxy_route_id)); + mojom::CreateRemoteMainFrameParams::New( + main_rfph->GetFrameToken(), proxy_route_id, + main_rfph->BindAndPassRemoteMainFrameInterfaces())); } params->session_storage_namespace_id =
diff --git a/content/browser/resources/histograms/OWNERS b/content/browser/resources/histograms/OWNERS index a6565c5..b9e8da9 100644 --- a/content/browser/resources/histograms/OWNERS +++ b/content/browser/resources/histograms/OWNERS
@@ -1 +1 @@ -asvitkine@chromium.org \ No newline at end of file +asvitkine@chromium.org
diff --git a/content/browser/service_worker/service_worker_browsertest.cc b/content/browser/service_worker/service_worker_browsertest.cc index 380bb048..70ff1bd 100644 --- a/content/browser/service_worker/service_worker_browsertest.cc +++ b/content/browser/service_worker/service_worker_browsertest.cc
@@ -31,6 +31,7 @@ #include "base/test/scoped_feature_list.h" #include "base/time/time.h" #include "build/build_config.h" +#include "components/services/storage/public/cpp/storage_key.h" #include "components/services/storage/public/mojom/cache_storage_control.mojom.h" #include "content/browser/child_process_security_policy_impl.h" #include "content/browser/renderer_host/code_cache_host_impl.h" @@ -834,13 +835,15 @@ auto observer = base::MakeRefCounted<WorkerStateObserver>( wrapper(), ServiceWorkerVersion::ACTIVATED); observer->Init(); - wrapper()->UpdateRegistration(https_server.GetURL(kPageUrl)); + GURL url = https_server.GetURL(kPageUrl); + wrapper()->UpdateRegistration( + url, storage::StorageKey(url::Origin::Create(url))); observer->Wait(); // Wait until the page is appropriately served by the service worker. const std::u16string title = u"Title"; TitleWatcher title_watcher(shell()->web_contents(), title); - EXPECT_TRUE(NavigateToURL(shell(), https_server.GetURL(kPageUrl))); + EXPECT_TRUE(NavigateToURL(shell(), url)); EXPECT_EQ(title, title_watcher.WaitAndGetTitle()); // The page should be marked as secure. @@ -955,8 +958,9 @@ observer->Wait(); base::RunLoop run_loop; + GURL full_url = embedded_test_server()->GetURL(kWorkerUrl); wrapper()->StartActiveServiceWorker( - embedded_test_server()->GetURL(kWorkerUrl), + full_url, storage::StorageKey(url::Origin::Create(full_url)), base::BindLambdaForTesting([&](blink::ServiceWorkerStatusCode status) { EXPECT_EQ(status, blink::ServiceWorkerStatusCode::kErrorNotFound); run_loop.Quit(); @@ -1979,7 +1983,7 @@ blink::ServiceWorkerStatusCode* status, base::OnceClosure continuation) { wrapper()->FindReadyRegistrationForClientUrl( - document_url, + document_url, storage::StorageKey(url::Origin::Create(document_url)), base::BindOnce( &ServiceWorkerBlackBoxBrowserTest::DidFindRegistrationOnCoreThread, base::Unretained(this), status, std::move(continuation)));
diff --git a/content/browser/service_worker/service_worker_context_wrapper.cc b/content/browser/service_worker/service_worker_context_wrapper.cc index 6bc97de..be235f0 100644 --- a/content/browser/service_worker/service_worker_context_wrapper.cc +++ b/content/browser/service_worker/service_worker_context_wrapper.cc
@@ -580,13 +580,14 @@ ResultCallback callback) { RunOrPostTaskOnThread( FROM_HERE, BrowserThread::UI, - base::BindOnce(&ServiceWorkerContextWrapper::DeleteForOriginOnUIThread, - this, origin, std::move(callback), - base::ThreadTaskRunnerHandle::Get())); + base::BindOnce( + &ServiceWorkerContextWrapper::DeleteForStorageKeyOnUIThread, this, + storage::StorageKey(origin), std::move(callback), + base::ThreadTaskRunnerHandle::Get())); } -void ServiceWorkerContextWrapper::DeleteForOriginOnUIThread( - const url::Origin& origin, +void ServiceWorkerContextWrapper::DeleteForStorageKeyOnUIThread( + const storage::StorageKey& key, ResultCallback callback, scoped_refptr<base::TaskRunner> callback_runner) { DCHECK_CURRENTLY_ON(BrowserThread::UI); @@ -598,7 +599,7 @@ // TODO(crbug.com/1199077): Update this when ServiceWorkerContextWrapper // implements StorageKey. context()->DeleteForStorageKey( - storage::StorageKey(origin), + key, base::BindOnce( [](ResultCallback callback, scoped_refptr<base::TaskRunner> callback_runner, @@ -666,7 +667,8 @@ StatusCodeCallback failure_callback) { DCHECK_CURRENTLY_ON(BrowserThread::UI); FindRegistrationForScopeImpl( - scope, /*include_installing_version=*/true, + scope, storage::StorageKey(url::Origin::Create(scope)), + /*include_installing_version=*/true, base::BindOnce(&FoundRegistrationForStartWorker, std::move(info_callback), std::move(failure_callback))); } @@ -679,7 +681,9 @@ FROM_HERE, BrowserThread::UI, base::BindOnce(&ServiceWorkerContextWrapper:: StartServiceWorkerAndDispatchMessageOnUIThread, - this, scope, std::move(message), + this, scope, + storage::StorageKey(url::Origin::Create(scope)), + std::move(message), base::BindOnce( [](ResultCallback callback, scoped_refptr<base::TaskRunner> callback_runner, @@ -695,6 +699,7 @@ void ServiceWorkerContextWrapper:: StartServiceWorkerAndDispatchMessageOnUIThread( const GURL& scope, + const storage::StorageKey& key, blink::TransferableMessage message, ResultCallback result_callback) { DCHECK_CURRENTLY_ON(BrowserThread::UI); @@ -705,7 +710,8 @@ } FindRegistrationForScopeImpl( - net::SimplifyUrlForRequest(scope), false /* include_installing_version */, + net::SimplifyUrlForRequest(scope), key, + /*include_installing_version=*/false, base::BindOnce( &ServiceWorkerContextWrapper::DidFindRegistrationForMessageDispatch, this, std::move(message), scope, std::move(result_callback))); @@ -863,7 +869,7 @@ } void ServiceWorkerContextWrapper::HasMainFrameWindowClient( - const GURL& origin, + const storage::StorageKey& key, BoolCallback callback) const { DCHECK_CURRENTLY_ON(BrowserThread::UI); @@ -872,26 +878,21 @@ FROM_HERE, base::BindOnce(std::move(callback), false)); return; } - // TODO(crbug.com/1199077): Update this when ServiceWorkerContextWrapper - // implements StorageKey. - context_core_->HasMainFrameWindowClient( - storage::StorageKey(url::Origin::Create(origin)), std::move(callback)); + context_core_->HasMainFrameWindowClient(key, std::move(callback)); } std::unique_ptr<std::vector<GlobalFrameRoutingId>> ServiceWorkerContextWrapper::GetWindowClientFrameRoutingIds( - const GURL& origin) const { + const storage::StorageKey& key) const { DCHECK_CURRENTLY_ON(BrowserThread::UI); std::unique_ptr<std::vector<GlobalFrameRoutingId>> frame_routing_ids( new std::vector<GlobalFrameRoutingId>()); if (!context_core_) return frame_routing_ids; - // TODO(crbug.com/1199077): Update this when ServiceWorkerContextWrapper - // implements StorageKey. for (std::unique_ptr<ServiceWorkerContextCore::ContainerHostIterator> it = context_core_->GetWindowClientContainerHostIterator( - storage::StorageKey(url::Origin::Create(origin)), + key, /*include_reserved_clients=*/false); !it->IsAtEnd(); it->Advance()) { ServiceWorkerContainerHost* container_host = it->GetContainerHost(); @@ -905,6 +906,7 @@ void ServiceWorkerContextWrapper::FindReadyRegistrationForClientUrl( const GURL& client_url, + const storage::StorageKey& key, FindRegistrationCallback callback) { DCHECK_CURRENTLY_ON(BrowserThread::UI); if (!context_core_) { @@ -913,8 +915,7 @@ return; } context_core_->registry()->FindRegistrationForClientUrl( - net::SimplifyUrlForRequest(client_url), - storage::StorageKey(url::Origin::Create(client_url)), + net::SimplifyUrlForRequest(client_url), key, base::BindOnce( &ServiceWorkerContextWrapper::DidFindRegistrationForFindImpl, this, /*include_installing_version=*/false, std::move(callback))); @@ -922,6 +923,7 @@ void ServiceWorkerContextWrapper::FindReadyRegistrationForScope( const GURL& scope, + const storage::StorageKey& key, FindRegistrationCallback callback) { DCHECK_CURRENTLY_ON(BrowserThread::UI); if (!context_core_) { @@ -931,8 +933,7 @@ } const bool include_installing_version = false; context_core_->registry()->FindRegistrationForScope( - net::SimplifyUrlForRequest(scope), - storage::StorageKey(url::Origin::Create(scope)), + net::SimplifyUrlForRequest(scope), key, base::BindOnce( &ServiceWorkerContextWrapper::DidFindRegistrationForFindImpl, this, include_installing_version, std::move(callback))); @@ -940,16 +941,17 @@ void ServiceWorkerContextWrapper::FindRegistrationForScope( const GURL& scope, + const storage::StorageKey& key, FindRegistrationCallback callback) { DCHECK_CURRENTLY_ON(BrowserThread::UI); const bool include_installing_version = true; - FindRegistrationForScopeImpl(scope, include_installing_version, + FindRegistrationForScopeImpl(scope, key, include_installing_version, std::move(callback)); } void ServiceWorkerContextWrapper::FindReadyRegistrationForId( int64_t registration_id, - const url::Origin& origin, + const storage::StorageKey& key, FindRegistrationCallback callback) { DCHECK_CURRENTLY_ON(BrowserThread::UI); if (!context_core_) { @@ -958,7 +960,7 @@ return; } context_core_->registry()->FindRegistrationForId( - registration_id, storage::StorageKey(origin), + registration_id, key, base::BindOnce( &ServiceWorkerContextWrapper::DidFindRegistrationForFindImpl, this, /*include_installing_version=*/false, std::move(callback))); @@ -994,8 +996,8 @@ context_core_->registry()->GetAllRegistrationsInfos(std::move(callback)); } -void ServiceWorkerContextWrapper::GetRegistrationsForOrigin( - const url::Origin& origin, +void ServiceWorkerContextWrapper::GetRegistrationsForStorageKey( + const storage::StorageKey& key, GetRegistrationsCallback callback) { DCHECK_CURRENTLY_ON(BrowserThread::UI); if (!context_core_) { @@ -1006,8 +1008,8 @@ std::vector<scoped_refptr<ServiceWorkerRegistration>>())); return; } - context_core_->registry()->GetRegistrationsForStorageKey( - storage::StorageKey(origin), std::move(callback)); + context_core_->registry()->GetRegistrationsForStorageKey(key, + std::move(callback)); } void ServiceWorkerContextWrapper::GetRegistrationUserData( @@ -1120,14 +1122,14 @@ void ServiceWorkerContextWrapper::StoreRegistrationUserData( int64_t registration_id, - const url::Origin& origin, + const storage::StorageKey& key, const std::vector<std::pair<std::string, std::string>>& key_value_pairs, StatusCallback callback) { RunOrPostTaskOnThread( FROM_HERE, BrowserThread::UI, base::BindOnce( &ServiceWorkerContextWrapper::StoreRegistrationUserDataOnUIThread, - this, registration_id, origin, key_value_pairs, + this, registration_id, key, key_value_pairs, base::BindOnce( [](StatusCallback callback, scoped_refptr<base::TaskRunner> callback_runner, @@ -1140,7 +1142,7 @@ void ServiceWorkerContextWrapper::StoreRegistrationUserDataOnUIThread( int64_t registration_id, - const url::Origin& origin, + const storage::StorageKey& key, const std::vector<std::pair<std::string, std::string>>& key_value_pairs, StatusCallback callback) { DCHECK_CURRENTLY_ON(BrowserThread::UI); @@ -1149,8 +1151,7 @@ return; } context_core_->registry()->StoreUserData( - registration_id, storage::StorageKey(origin), key_value_pairs, - std::move(callback)); + registration_id, key, key_value_pairs, std::move(callback)); } void ServiceWorkerContextWrapper::ClearRegistrationUserData( @@ -1322,6 +1323,7 @@ void ServiceWorkerContextWrapper::StartActiveServiceWorker( const GURL& scope, + const storage::StorageKey& key, StatusCallback callback) { DCHECK_CURRENTLY_ON(BrowserThread::UI); if (!context_core_) { @@ -1331,19 +1333,19 @@ return; } context_core_->registry()->FindRegistrationForScope( - net::SimplifyUrlForRequest(scope), - storage::StorageKey(url::Origin::Create(scope)), + net::SimplifyUrlForRequest(scope), key, base::BindOnce(&DidFindRegistrationForStartActiveWorker, std::move(callback))); } -void ServiceWorkerContextWrapper::SkipWaitingWorker(const GURL& scope) { +void ServiceWorkerContextWrapper::SkipWaitingWorker( + const GURL& scope, + const storage::StorageKey& key) { DCHECK_CURRENTLY_ON(BrowserThread::UI); if (!context_core_) return; context_core_->registry()->FindRegistrationForScope( - net::SimplifyUrlForRequest(scope), - storage::StorageKey(url::Origin::Create(scope)), + net::SimplifyUrlForRequest(scope), key, base::BindOnce([](blink::ServiceWorkerStatusCode status, scoped_refptr<ServiceWorkerRegistration> registration) { if (status != blink::ServiceWorkerStatusCode::kOk || @@ -1355,13 +1357,14 @@ })); } -void ServiceWorkerContextWrapper::UpdateRegistration(const GURL& scope) { +void ServiceWorkerContextWrapper::UpdateRegistration( + const GURL& scope, + const storage::StorageKey& key) { DCHECK_CURRENTLY_ON(BrowserThread::UI); if (!context_core_) return; context_core_->registry()->FindRegistrationForScope( - net::SimplifyUrlForRequest(scope), - storage::StorageKey(url::Origin::Create(scope)), + net::SimplifyUrlForRequest(scope), key, base::BindOnce(&ServiceWorkerContextWrapper::DidFindRegistrationForUpdate, this)); } @@ -1400,6 +1403,7 @@ void ServiceWorkerContextWrapper::FindRegistrationForScopeImpl( const GURL& scope, + const storage::StorageKey& key, bool include_installing_version, FindRegistrationCallback callback) { DCHECK_CURRENTLY_ON(BrowserThread::UI); @@ -1409,8 +1413,7 @@ return; } context_core_->registry()->FindRegistrationForScope( - net::SimplifyUrlForRequest(scope), - storage::StorageKey(url::Origin::Create(scope)), + net::SimplifyUrlForRequest(scope), key, base::BindOnce( &ServiceWorkerContextWrapper::DidFindRegistrationForFindImpl, this, include_installing_version, std::move(callback)));
diff --git a/content/browser/service_worker/service_worker_context_wrapper.h b/content/browser/service_worker/service_worker_context_wrapper.h index 0f9b8fe..0ff51ed 100644 --- a/content/browser/service_worker/service_worker_context_wrapper.h +++ b/content/browser/service_worker/service_worker_context_wrapper.h
@@ -37,6 +37,7 @@ class QuotaManagerProxy; class ServiceWorkerStorageControlImpl; class SpecialStoragePolicy; +class StorageKey; } namespace url { @@ -192,63 +193,67 @@ std::vector<ServiceWorkerRegistrationInfo> GetAllLiveRegistrationInfo(); std::vector<ServiceWorkerVersionInfo> GetAllLiveVersionInfo(); - void HasMainFrameWindowClient(const GURL& origin, + void HasMainFrameWindowClient(const storage::StorageKey& key, BoolCallback callback) const; - // Returns all frame routing ids for the given |origin|. + // Returns all frame routing ids for the given `key`. std::unique_ptr<std::vector<GlobalFrameRoutingId>> - GetWindowClientFrameRoutingIds(const GURL& origin) const; + GetWindowClientFrameRoutingIds(const storage::StorageKey& key) const; - // Returns the registration whose scope longest matches |client_url|. It is + // Returns the registration whose scope longest matches `client_url` with the + // associated `key`. It is guaranteed that the returned registration has the + // activated worker. + // + // - If the registration is not found, returns ERROR_NOT_FOUND. + // - If the registration has neither the waiting version nor the active + // version, returns ERROR_NOT_FOUND. + // - If the registration does not have the active version but has the waiting + // version, activates the waiting version and runs `callback` when it is + // activated. + // + // There is no guarantee for whether the callback is called synchronously or + // asynchronously. + void FindReadyRegistrationForClientUrl(const GURL& client_url, + const storage::StorageKey& key, + FindRegistrationCallback callback); + + // Returns the registration for `scope` with the associated `key`. It is // guaranteed that the returned registration has the activated worker. // // - If the registration is not found, returns ERROR_NOT_FOUND. // - If the registration has neither the waiting version nor the active // version, returns ERROR_NOT_FOUND. // - If the registration does not have the active version but has the waiting - // version, activates the waiting version and runs |callback| when it is - // activated. - // - // There is no guarantee for whether the callback is called synchronously or - // asynchronously. - void FindReadyRegistrationForClientUrl(const GURL& client_url, - FindRegistrationCallback callback); - - // Returns the registration for |scope|. It is guaranteed that the returned - // registration has the activated worker. - // - // - If the registration is not found, returns ERROR_NOT_FOUND. - // - If the registration has neither the waiting version nor the active - // version, returns ERROR_NOT_FOUND. - // - If the registration does not have the active version but has the waiting - // version, activates the waiting version and runs |callback| when it is + // version, activates the waiting version and runs `callback` when it is // activated. // // There is no guarantee for whether the callback is called synchronously or // asynchronously. void FindReadyRegistrationForScope(const GURL& scope, + const storage::StorageKey& key, FindRegistrationCallback callback); // Similar to FindReadyRegistrationForScope, but in the case no waiting or // active worker is found (i.e., there is only an installing worker), - // |callback| is called without waiting for the worker to reach active. + // `callback` is called without waiting for the worker to reach active. void FindRegistrationForScope(const GURL& scope, + const storage::StorageKey& key, FindRegistrationCallback callback); - // Returns the registration for |registration_id|. It is guaranteed that the + // Returns the registration for `registration_id`. It is guaranteed that the // returned registration has the activated worker. // // - If the registration is not found, returns ERROR_NOT_FOUND. // - If the registration has neither the waiting version nor the active // version, returns ERROR_NOT_FOUND. // - If the registration does not have the active version but has the waiting - // version, activates the waiting version and runs |callback| when it is + // version, activates the waiting version and runs `callback` when it is // activated. // // There is no guarantee about whether the callback is called asynchronously // or synchronously. void FindReadyRegistrationForId(int64_t registration_id, - const url::Origin& origin, + const storage::StorageKey& key, FindRegistrationCallback callback); // Returns the registration for |registration_id|. It is guaranteed that the @@ -288,7 +293,7 @@ GetUserKeysAndDataCallback callback); void StoreRegistrationUserData( int64_t registration_id, - const url::Origin& origin, + const storage::StorageKey& key, const std::vector<std::pair<std::string, std::string>>& key_value_pairs, StatusCallback callback); void ClearRegistrationUserData(int64_t registration_id, @@ -308,19 +313,21 @@ const std::string& key_prefix, StatusCallback callback); - // Returns a list of ServiceWorkerRegistration for |origin|. The list includes + // Returns a list of ServiceWorkerRegistration for `key`. The list includes // stored registrations and installing (not stored yet) registrations. - void GetRegistrationsForOrigin(const url::Origin& origin, - GetRegistrationsCallback callback); + void GetRegistrationsForStorageKey(const storage::StorageKey& key, + GetRegistrationsCallback callback); // Fails with kErrorNotFound if there is no active registration for the given - // scope. It means that there is no registration at all or that the - // registration doesn't have an active version yet (which is the case for + // `scope` and `key`. It means that there is no registration at all or that + // the registration doesn't have an active version yet (which is the case for // installing service workers). - void StartActiveServiceWorker(const GURL& scope, StatusCallback callback); + void StartActiveServiceWorker(const GURL& scope, + const storage::StorageKey& key, + StatusCallback callback); - void SkipWaitingWorker(const GURL& scope); - void UpdateRegistration(const GURL& scope); + void SkipWaitingWorker(const GURL& scope, const storage::StorageKey& key); + void UpdateRegistration(const GURL& scope, const storage::StorageKey& key); void SetForceUpdateOnPageLoad(bool force_update_on_page_load); // Different from AddObserver/RemoveObserver(ServiceWorkerContextObserver*). @@ -379,9 +386,10 @@ URLLoaderFactoryGetter* loader_factory_getter, BrowserContext* browser_context); - // If |include_installing_version| is true, |callback| is called if there is + // If `include_installing_version` is true, `callback` is called if there is // an installing version with no waiting or active version. void FindRegistrationForScopeImpl(const GURL& scope, + const storage::StorageKey& key, bool include_installing_version, FindRegistrationCallback callback); @@ -440,10 +448,11 @@ // Temporary for https://crbug.com/1161153. void StartServiceWorkerAndDispatchMessageOnUIThread( const GURL& scope, + const storage::StorageKey& key, blink::TransferableMessage message, ResultCallback callback); - void DeleteForOriginOnUIThread( - const url::Origin& origin, + void DeleteForStorageKeyOnUIThread( + const storage::StorageKey& key, ResultCallback callback, scoped_refptr<base::TaskRunner> callback_runner); void GetRegistrationUserDataOnUIThread(int64_t registration_id, @@ -459,7 +468,7 @@ GetUserKeysAndDataCallback callback); void StoreRegistrationUserDataOnUIThread( int64_t registration_id, - const url::Origin& origin, + const storage::StorageKey& key, const std::vector<std::pair<std::string, std::string>>& key_value_pairs, StatusCallback callback); void ClearRegistrationUserDataOnUIThread(int64_t registration_id,
diff --git a/content/browser/service_worker/service_worker_internals_ui.cc b/content/browser/service_worker/service_worker_internals_ui.cc index 38d90aa..b7e5941 100644 --- a/content/browser/service_worker/service_worker_internals_ui.cc +++ b/content/browser/service_worker/service_worker_internals_ui.cc
@@ -678,7 +678,10 @@ base::OnceCallback<void(blink::ServiceWorkerStatusCode)> callback = base::BindOnce(OperationCompleteCallback, weak_ptr_factory_.GetWeakPtr(), callback_id); - context->StartActiveServiceWorker(GURL(scope_string), std::move(callback)); + context->StartActiveServiceWorker( + GURL(scope_string), + storage::StorageKey(url::Origin::Create(GURL(scope_string))), + std::move(callback)); } void ServiceWorkerInternalsHandler::StopWorkerWithId(
diff --git a/content/browser/site_per_process_browsertest.cc b/content/browser/site_per_process_browsertest.cc index 0f9d984..5f2a20b 100644 --- a/content/browser/site_per_process_browsertest.cc +++ b/content/browser/site_per_process_browsertest.cc
@@ -1040,11 +1040,9 @@ FakeRemoteMainFrame() = default; ~FakeRemoteMainFrame() override = default; - void Init(blink::AssociatedInterfaceProvider* provider) { - provider->OverrideBinderForTesting( - blink::mojom::RemoteMainFrame::Name_, - base::BindRepeating(&FakeRemoteMainFrame::BindFrameHostReceiver, - base::Unretained(this))); + void Init( + mojo::PendingAssociatedReceiver<blink::mojom::RemoteMainFrame> receiver) { + receiver_.Bind(std::move(receiver)); } // blink::mojom::RemoteMainFrame overrides: @@ -1052,12 +1050,6 @@ blink::mojom::TextAutosizerPageInfoPtr page_info) override {} private: - void BindFrameHostReceiver(mojo::ScopedInterfaceEndpointHandle handle) { - receiver_.Bind( - mojo::PendingAssociatedReceiver<blink::mojom::RemoteMainFrame>( - std::move(handle))); - } - mojo::AssociatedReceiver<blink::mojom::RemoteMainFrame> receiver_{this}; }; @@ -1067,14 +1059,14 @@ class UpdateTextAutosizerInfoProxyObserver { public: UpdateTextAutosizerInfoProxyObserver() { - RenderFrameProxyHost::SetCreatedCallbackForTesting( + RenderFrameProxyHost::SetBindRemoteFrameCallbackForTesting( base::BindRepeating(&UpdateTextAutosizerInfoProxyObserver:: - RenderFrameProxyHostCreatedCallback, + RemoteFrameInterfacesBoundCallback, base::Unretained(this))); } ~UpdateTextAutosizerInfoProxyObserver() { - RenderFrameProxyHost::SetCreatedCallbackForTesting( - RenderFrameProxyHost::CreatedCallback()); + RenderFrameProxyHost::SetBindRemoteFrameCallbackForTesting( + RenderFrameProxyHost::BindRemoteFrameCallback()); } const blink::mojom::TextAutosizerPageInfo& TextAutosizerPageInfo( @@ -1086,7 +1078,7 @@ class Remote : public FakeRemoteMainFrame { public: explicit Remote(RenderFrameProxyHost* proxy) { - Init(proxy->GetRemoteAssociatedInterfacesTesting()); + Init(proxy->BindRemoteMainFrameReceiverForTesting()); } void UpdateTextAutosizerPageInfo( blink::mojom::TextAutosizerPageInfoPtr page_info) override { @@ -1100,7 +1092,7 @@ blink::mojom::TextAutosizerPageInfo page_info_; }; - void RenderFrameProxyHostCreatedCallback(RenderFrameProxyHost* proxy_host) { + void RemoteFrameInterfacesBoundCallback(RenderFrameProxyHost* proxy_host) { remote_frames_[proxy_host] = std::make_unique<Remote>(proxy_host); } @@ -6217,13 +6209,23 @@ EXPECT_TRUE(ExecJs( root, "document.body.removeChild(document.querySelector('iframe'));")); + auto remote_main_frame_interfaces = mojom::RemoteMainFrameInterfaces::New(); + mojo::AssociatedRemote<blink::mojom::RemoteMainFrame> main_frame; + remote_main_frame_interfaces->main_frame = + main_frame.BindNewEndpointAndPassReceiver(); + + mojo::AssociatedRemote<blink::mojom::RemoteMainFrameHost> main_frame_host; + ignore_result(main_frame_host.BindNewEndpointAndPassReceiver()); + remote_main_frame_interfaces->main_frame_host = main_frame_host.Unbind(); + // Send the message to create a proxy for B's new child frame in A. This // used to crash, as parent_routing_id refers to a proxy that doesn't exist // anymore. agent_scheduling_group_a->CreateFrameProxy( blink::RemoteFrameToken(), new_routing_id, absl::nullopt, view_routing_id, parent_routing_id, blink::mojom::FrameReplicationState::New(), - base::UnguessableToken::Create()); + base::UnguessableToken::Create(), + std::move(remote_main_frame_interfaces)); // Ensure the subframe is detached in the browser process. observer.Wait();
diff --git a/content/browser/speculation_rules/speculation_host_impl.cc b/content/browser/speculation_rules/speculation_host_impl.cc index 0d9b1b2..5c210f4 100644 --- a/content/browser/speculation_rules/speculation_host_impl.cc +++ b/content/browser/speculation_rules/speculation_host_impl.cc
@@ -54,14 +54,9 @@ if (render_frame_host()->GetParent()) return; - // Only one update per document is allowed for now. - // TODO(ryansturm): Add support for updates. https://crbug.com/1190338 - if (received_update_) - return; - received_update_ = true; - // Let `delegate_` process the candidates that it is interested in. - delegate_->ProcessCandidates(candidates); + if (delegate_) + delegate_->ProcessCandidates(candidates); // TODO(crbug.com/1197133): process prerender candidates. }
diff --git a/content/browser/speculation_rules/speculation_host_impl.h b/content/browser/speculation_rules/speculation_host_impl.h index ae6e5b1b..2fa9fadf 100644 --- a/content/browser/speculation_rules/speculation_host_impl.h +++ b/content/browser/speculation_rules/speculation_host_impl.h
@@ -35,11 +35,6 @@ void UpdateSpeculationCandidates( std::vector<blink::mojom::SpeculationCandidatePtr> candidates) override; - // Track if an update has been received. The current implementation only - // processes one update per document. At present, updates after the first are - // ignored. - bool received_update_ = false; - std::unique_ptr<SpeculationHostDelegate> delegate_; };
diff --git a/content/browser/storage_partition_impl.cc b/content/browser/storage_partition_impl.cc index 73dbd97f0..4bb577a 100644 --- a/content/browser/storage_partition_impl.cc +++ b/content/browser/storage_partition_impl.cc
@@ -36,6 +36,7 @@ #include "components/leveldb_proto/public/proto_database_provider.h" #include "components/services/storage/public/cpp/constants.h" #include "components/services/storage/public/cpp/filesystem/filesystem_impl.h" +#include "components/services/storage/public/cpp/storage_key.h" #include "components/services/storage/public/mojom/filesystem/directory.mojom.h" #include "components/services/storage/public/mojom/indexed_db_control.mojom.h" #include "components/services/storage/public/mojom/storage_service.mojom.h" @@ -1023,7 +1024,7 @@ network::mojom::CookieAccessDetailsPtr details) { std::vector<GlobalFrameRoutingId> destinations = *service_worker_context->GetWindowClientFrameRoutingIds( - details->url.GetOrigin()); + storage::StorageKey(url::Origin::Create(details->url))); if (destinations.empty()) return; RunOrPostTaskOnThread(
diff --git a/content/browser/tracing/OWNERS b/content/browser/tracing/OWNERS index 2c2f79b..e94c6d8f 100644 --- a/content/browser/tracing/OWNERS +++ b/content/browser/tracing/OWNERS
@@ -1 +1 @@ -file://base/trace_event/OWNERS \ No newline at end of file +file://base/trace_event/OWNERS
diff --git a/content/browser/websockets/websocket_connector_impl.cc b/content/browser/websockets/websocket_connector_impl.cc index 5e8b4f43..020fe94 100644 --- a/content/browser/websockets/websocket_connector_impl.cc +++ b/content/browser/websockets/websocket_connector_impl.cc
@@ -4,17 +4,33 @@ #include "content/browser/websockets/websocket_connector_impl.h" +#include "base/containers/contains.h" #include "content/browser/renderer_host/render_frame_host_impl.h" #include "content/browser/renderer_host/render_process_host_impl.h" #include "content/public/browser/render_process_host.h" #include "content/public/browser/storage_partition.h" #include "content/public/common/content_client.h" +#include "content/public/common/content_switches.h" #include "services/network/public/cpp/features.h" #include "url/gurl.h" namespace content { namespace { + +url::Origin MaybeTreatLocalOriginAsOpaque(const url::Origin& origin) { + if (base::Contains(url::GetLocalSchemes(), origin.scheme()) && + !base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kAllowFileAccessFromFiles)) { + // For local origins we should use an opaque origin unless + // "--allow-file-access-from-files" is specified. This should have been + // done in content::RenderFrameHost. See https://crbug.com/1206736 for + // details. + return origin.DeriveNewOpaqueOrigin(); + } + return origin; +} + constexpr net::NetworkTrafficAnnotationTag kTrafficAnnotation = net::DefineNetworkTrafficAnnotation("websocket_stream", R"( semantics { @@ -47,7 +63,7 @@ const net::IsolationInfo& isolation_info) : process_id_(process_id), frame_id_(frame_id), - origin_(origin), + origin_(MaybeTreatLocalOriginAsOpaque(origin)), isolation_info_(isolation_info) {} WebSocketConnectorImpl::~WebSocketConnectorImpl() = default;
diff --git a/content/browser/worker_host/dedicated_worker_host.cc b/content/browser/worker_host/dedicated_worker_host.cc index e888f16..3086345 100644 --- a/content/browser/worker_host/dedicated_worker_host.cc +++ b/content/browser/worker_host/dedicated_worker_host.cc
@@ -9,6 +9,7 @@ #include "base/bind.h" #include "base/callback_helpers.h" +#include "components/services/storage/public/cpp/storage_key.h" #include "content/browser/appcache/appcache_navigation_handle.h" #include "content/browser/blob_storage/chrome_blob_storage_context.h" #include "content/browser/loader/content_security_notifier.h" @@ -707,8 +708,9 @@ if (!service_worker_context) return; - service_worker_context->GetRegistrationsForOrigin( - ancestor_render_frame_host->GetLastCommittedOrigin(), + service_worker_context->GetRegistrationsForStorageKey( + storage::StorageKey( + ancestor_render_frame_host->GetLastCommittedOrigin()), base::BindOnce(&DedicatedWorkerHost::ContinueOnMaybeCountWebFeature, weak_factory_.GetWeakPtr(), script_url, std::move(container_host)));
diff --git a/content/common/agent_scheduling_group.mojom b/content/common/agent_scheduling_group.mojom index 1e22330..f99eb01 100644 --- a/content/common/agent_scheduling_group.mojom +++ b/content/common/agent_scheduling_group.mojom
@@ -78,6 +78,7 @@ blink.mojom.FrameToken? opener_frame_token, int32 view_routing_id, int32 parent_routing_id, blink.mojom.FrameReplicationState replication_state, - mojo_base.mojom.UnguessableToken devtools_frame_token); + mojo_base.mojom.UnguessableToken devtools_frame_token, + RemoteMainFrameInterfaces remote_main_frame_interfaces); };
diff --git a/content/common/download/OWNERS b/content/common/download/OWNERS index 61b5e28..08850f4 100644 --- a/content/common/download/OWNERS +++ b/content/common/download/OWNERS
@@ -1,2 +1,2 @@ per-file *.mojom=set noparent -per-file *.mojom=file://ipc/SECURITY_OWNERS \ No newline at end of file +per-file *.mojom=file://ipc/SECURITY_OWNERS
diff --git a/content/common/frame.mojom b/content/common/frame.mojom index 5f6980c..642e02a6 100644 --- a/content/common/frame.mojom +++ b/content/common/frame.mojom
@@ -170,6 +170,9 @@ // The ID of the proxy object for the main frame in this view. Must not be // kRoutingIdNone. int32 routing_id = IPC.mojom.kRoutingIdNone; + + // The communication channels for the RemoteMainFrame in this view. + RemoteMainFrameInterfaces main_frame_interfaces; }; // Parameters used for creating a new frame widget. @@ -315,6 +318,12 @@ kSpeculativeMainFrameForNavigationCancelled, }; +// Struct for communication channels of the RemoteFrame in blink. +struct RemoteMainFrameInterfaces { + pending_associated_remote<blink.mojom.RemoteMainFrameHost> main_frame_host; + pending_associated_receiver<blink.mojom.RemoteMainFrame> main_frame; +}; + // Implemented by the frame provider, and must be associated with other content // mojoms bound to frames, widgets, views, and currently also with the legacy // IPC channel. @@ -355,10 +364,12 @@ // be posted back to the event loop to be invoked later. This is to ensure // that any postMessage() calls executed by JS during unload are dispatched, // since postMessage dispatch is always scheduled asynchronously. - Unload(int32 new_remote_frame_routing_id, - bool is_loading, - blink.mojom.FrameReplicationState new_remote_frame_replication_state, - blink.mojom.RemoteFrameToken new_remote_frame_token); + Unload( + int32 new_remote_frame_routing_id, + bool is_loading, + blink.mojom.FrameReplicationState new_remote_frame_replication_state, + blink.mojom.RemoteFrameToken new_remote_frame_token, + RemoteMainFrameInterfaces new_remote_main_frame_interfaces); // Delete the frame. This is only called for child frames that the browser // wants to detach, or for speculative main frames which are owned by the
diff --git a/content/public/browser/push_messaging_service.cc b/content/public/browser/push_messaging_service.cc index 8cb877dd..088204c 100644 --- a/content/public/browser/push_messaging_service.cc +++ b/content/public/browser/push_messaging_service.cc
@@ -6,6 +6,7 @@ #include "base/bind.h" #include "base/callback.h" +#include "components/services/storage/public/cpp/storage_key.h" #include "content/browser/push_messaging/push_messaging_manager.h" #include "content/browser/service_worker/service_worker_context_wrapper.h" #include "content/public/browser/browser_context.h" @@ -64,7 +65,8 @@ base::OnceClosure callback) { DCHECK_CURRENTLY_ON(BrowserThread::IO); service_worker_context->StoreRegistrationUserData( - service_worker_registration_id, url::Origin::Create(origin), + service_worker_registration_id, + storage::StorageKey(url::Origin::Create(origin)), {{kPushRegistrationIdServiceWorkerKey, subscription_id}}, base::BindOnce(&CallClosureFromIO, std::move(callback))); } @@ -79,7 +81,8 @@ DCHECK_CURRENTLY_ON(BrowserThread::IO); service_worker_context->StoreRegistrationUserData( - service_worker_registration_id, url::Origin::Create(origin), + service_worker_registration_id, + storage::StorageKey(url::Origin::Create(origin)), {{kPushRegistrationIdServiceWorkerKey, subscription_id}, {kPushSenderIdServiceWorkerKey, sender_id}}, base::BindOnce(&CallClosureFromIO, std::move(callback)));
diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc index f3db582..e6b4460 100644 --- a/content/public/common/content_features.cc +++ b/content/public/common/content_features.cc
@@ -1028,7 +1028,7 @@ "RetryGetVideoCaptureDeviceInfos", base::FEATURE_DISABLED_BY_DEFAULT}; const base::Feature kDesktopCaptureMacV2{"DesktopCaptureMacV2", - base::FEATURE_DISABLED_BY_DEFAULT}; + base::FEATURE_ENABLED_BY_DEFAULT}; const base::Feature kWindowCaptureMacV2{"WindowCaptureMacV2", base::FEATURE_ENABLED_BY_DEFAULT};
diff --git a/content/public/test/service_worker_host_interceptor.cc b/content/public/test/service_worker_host_interceptor.cc index 57abb9a..b9010847 100644 --- a/content/public/test/service_worker_host_interceptor.cc +++ b/content/public/test/service_worker_host_interceptor.cc
@@ -9,6 +9,7 @@ #include "base/callback.h" #include "base/location.h" #include "base/run_loop.h" +#include "components/services/storage/public/cpp/storage_key.h" #include "content/browser/service_worker/service_worker_context_wrapper.h" #include "content/browser/service_worker/service_worker_version.h" #include "content/public/browser/browser_context.h" @@ -70,7 +71,7 @@ BrowserThread::ID run_done_thread, base::OnceClosure done) { context->FindRegistrationForScope( - scope, + scope, storage::StorageKey(url::Origin::Create(scope)), base::BindOnce(&ServiceWorkerHostInterceptor:: OnFoundRegistrationOnServiceWorkerCoreThread, base::Unretained(this), run_done_thread, std::move(done)));
diff --git a/content/public/test/service_worker_test_helpers.cc b/content/public/test/service_worker_test_helpers.cc index 3aee035..8f37ab93 100644 --- a/content/public/test/service_worker_test_helpers.cc +++ b/content/public/test/service_worker_test_helpers.cc
@@ -10,6 +10,7 @@ #include "base/bind.h" #include "base/callback_helpers.h" #include "base/run_loop.h" +#include "components/services/storage/public/cpp/storage_key.h" #include "content/browser/service_worker/service_worker_context_core_observer.h" #include "content/browser/service_worker/service_worker_context_wrapper.h" #include "content/public/browser/browser_task_traits.h" @@ -131,7 +132,9 @@ std::move(callback))); return; } - context_wrapper->FindReadyRegistrationForScope(scope, std::move(callback)); + context_wrapper->FindReadyRegistrationForScope( + scope, storage::StorageKey(url::Origin::Create(scope)), + std::move(callback)); } } // namespace
diff --git a/content/renderer/agent_scheduling_group.cc b/content/renderer/agent_scheduling_group.cc index 59c98f4..dc537a3 100644 --- a/content/renderer/agent_scheduling_group.cc +++ b/content/renderer/agent_scheduling_group.cc
@@ -221,10 +221,12 @@ int32_t view_routing_id, int32_t parent_routing_id, blink::mojom::FrameReplicationStatePtr replicated_state, - const base::UnguessableToken& devtools_frame_token) { + const base::UnguessableToken& devtools_frame_token, + mojom::RemoteMainFrameInterfacesPtr remote_main_frame_interfaces) { RenderFrameProxy::CreateFrameProxy( *this, token, routing_id, opener_frame_token, view_routing_id, - parent_routing_id, std::move(replicated_state), devtools_frame_token); + parent_routing_id, std::move(replicated_state), devtools_frame_token, + std::move(remote_main_frame_interfaces)); } void AgentSchedulingGroup::BindAssociatedInterfaces(
diff --git a/content/renderer/agent_scheduling_group.h b/content/renderer/agent_scheduling_group.h index ecd3bb4a..cf259ff2d 100644 --- a/content/renderer/agent_scheduling_group.h +++ b/content/renderer/agent_scheduling_group.h
@@ -97,7 +97,9 @@ int32_t view_routing_id, int32_t parent_routing_id, blink::mojom::FrameReplicationStatePtr replicated_state, - const base::UnguessableToken& devtools_frame_token) override; + const base::UnguessableToken& devtools_frame_token, + mojom::RemoteMainFrameInterfacesPtr remote_main_frame_interfaces) + override; // mojom::RouteProvider void GetRoute(
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc index bc609e7..f5f15279 100644 --- a/content/renderer/render_frame_impl.cc +++ b/content/renderer/render_frame_impl.cc
@@ -2061,7 +2061,8 @@ int proxy_routing_id, bool is_loading, blink::mojom::FrameReplicationStatePtr replicated_frame_state, - const blink::RemoteFrameToken& proxy_frame_token) { + const blink::RemoteFrameToken& proxy_frame_token, + mojom::RemoteMainFrameInterfacesPtr remote_main_frame_interfaces) { TRACE_EVENT1("navigation,rail", "RenderFrameImpl::UnloadFrame", "id", routing_id_); DCHECK(!base::RunLoop::IsNestedOnCurrentThread()); @@ -2117,7 +2118,9 @@ // The RenderFrameProxy being swapped in here has now been attached to the // Page as its main frame and properly initialized by the WebFrame::Swap() // call, so we can call WebView's DidAttachRemoteMainFrame(). - render_view->GetWebView()->DidAttachRemoteMainFrame(); + render_view->GetWebView()->DidAttachRemoteMainFrame( + std::move(remote_main_frame_interfaces->main_frame_host), + std::move(remote_main_frame_interfaces->main_frame)); } if (!success) {
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h index d60ea42..0e7eb96 100644 --- a/content/renderer/render_frame_impl.h +++ b/content/renderer/render_frame_impl.h
@@ -793,7 +793,9 @@ void Unload(int proxy_routing_id, bool is_loading, blink::mojom::FrameReplicationStatePtr replicated_frame_state, - const blink::RemoteFrameToken& frame_token) override; + const blink::RemoteFrameToken& frame_token, + mojom::RemoteMainFrameInterfacesPtr remote_main_frame_interfaces) + override; void Delete(mojom::FrameDeleteIntention intent) override; void BlockRequests() override; void ResumeBlockedRequests() override;
diff --git a/content/renderer/render_frame_impl_browsertest.cc b/content/renderer/render_frame_impl_browsertest.cc index 9c9acc74..e3cde52 100644 --- a/content/renderer/render_frame_impl_browsertest.cc +++ b/content/renderer/render_frame_impl_browsertest.cc
@@ -130,10 +130,20 @@ frame_replication_state->name = "frame"; frame_replication_state->unique_name = "frame-uniqueName"; + auto remote_main_frame_interfaces = mojom::RemoteMainFrameInterfaces::New(); + mojo::AssociatedRemote<blink::mojom::RemoteMainFrame> main_frame; + remote_main_frame_interfaces->main_frame = + main_frame.BindNewEndpointAndPassDedicatedReceiver(); + + mojo::AssociatedRemote<blink::mojom::RemoteMainFrameHost> main_frame_host; + ignore_result(main_frame_host.BindNewEndpointAndPassDedicatedReceiver()); + remote_main_frame_interfaces->main_frame_host = main_frame_host.Unbind(); + RenderFrameImpl::FromWebFrame( view_->GetMainRenderFrame()->GetWebFrame()->FirstChild()) ->Unload(kFrameProxyRouteId, false, frame_replication_state->Clone(), - blink::RemoteFrameToken()); + blink::RemoteFrameToken(), + std::move(remote_main_frame_interfaces)); MockPolicyContainerHost mock_policy_container_host; RenderFrameImpl::CreateFrame( *agent_scheduling_group_, blink::LocalFrameToken(), kSubframeRouteId,
diff --git a/content/renderer/render_frame_proxy.cc b/content/renderer/render_frame_proxy.cc index 1e5a114b..cdd2691c 100644 --- a/content/renderer/render_frame_proxy.cc +++ b/content/renderer/render_frame_proxy.cc
@@ -89,7 +89,8 @@ int render_view_routing_id, int parent_routing_id, blink::mojom::FrameReplicationStatePtr replicated_state, - const base::UnguessableToken& devtools_frame_token) { + const base::UnguessableToken& devtools_frame_token, + mojom::RemoteMainFrameInterfacesPtr remote_main_frame_interfaces) { RenderFrameProxy* parent = nullptr; if (parent_routing_id != MSG_ROUTING_NONE) { parent = RenderFrameProxy::FromRoutingID(parent_routing_id); @@ -120,7 +121,9 @@ // The WebRemoteFrame created here was already attached to the Page as its // main frame, so we can call WebView's DidAttachRemoteMainFrame(). - web_view->DidAttachRemoteMainFrame(); + web_view->DidAttachRemoteMainFrame( + std::move(remote_main_frame_interfaces->main_frame_host), + std::move(remote_main_frame_interfaces->main_frame)); } else { // Create a frame under an existing parent. The parent is always expected // to be a RenderFrameProxy, because navigations initiated by local frames @@ -284,11 +287,8 @@ void RenderFrameProxy::OnAssociatedInterfaceRequest( const std::string& interface_name, mojo::ScopedInterfaceEndpointHandle handle) { - if (interface_name == blink::mojom::RemoteFrame::Name_) { + if (interface_name == blink::mojom::RemoteFrame::Name_) associated_interfaces_.TryBindInterface(interface_name, &handle); - } else if (interface_name == blink::mojom::RemoteMainFrame::Name_) { - associated_interfaces_.TryBindInterface(interface_name, &handle); - } } bool RenderFrameProxy::Send(IPC::Message* message) {
diff --git a/content/renderer/render_frame_proxy.h b/content/renderer/render_frame_proxy.h index 4027f535..7196f04 100644 --- a/content/renderer/render_frame_proxy.h +++ b/content/renderer/render_frame_proxy.h
@@ -9,6 +9,7 @@ #include "base/memory/ref_counted.h" #include "cc/paint/paint_canvas.h" #include "content/common/content_export.h" +#include "content/common/frame.mojom.h" #include "ipc/ipc_listener.h" #include "ipc/ipc_sender.h" #include "mojo/public/cpp/bindings/associated_receiver.h" @@ -93,7 +94,8 @@ int render_view_routing_id, int parent_routing_id, blink::mojom::FrameReplicationStatePtr replicated_state, - const base::UnguessableToken& devtools_frame_token); + const base::UnguessableToken& devtools_frame_token, + mojom::RemoteMainFrameInterfacesPtr remote_main_frame_interfaces); // Creates a RenderFrameProxy to be used with a portal owned by |parent|. // |routing_id| is the routing id of this new RenderFrameProxy.
diff --git a/content/renderer/render_view_browsertest.cc b/content/renderer/render_view_browsertest.cc index 6115849..24688c00 100644 --- a/content/renderer/render_view_browsertest.cc +++ b/content/renderer/render_view_browsertest.cc
@@ -275,6 +275,19 @@ return params; } +mojom::RemoteMainFrameInterfacesPtr CreateStubRemoteFrameInterfaces() { + auto interfaces = mojom::RemoteMainFrameInterfaces::New(); + + mojo::AssociatedRemote<blink::mojom::RemoteMainFrame> main_frame; + interfaces->main_frame = main_frame.BindNewEndpointAndPassDedicatedReceiver(); + + mojo::AssociatedRemote<blink::mojom::RemoteMainFrameHost> main_frame_host; + ignore_result(main_frame_host.BindNewEndpointAndPassDedicatedReceiver()); + interfaces->main_frame_host = main_frame_host.Unbind(); + + return interfaces; +} + } // namespace class RenderViewImplTest : public RenderViewTest { @@ -654,7 +667,7 @@ static_cast<mojom::Frame*>(child_frame_1) ->Unload(kProxyRoutingId, true, ReconstructReplicationStateForTesting(child_frame_1), - blink::RemoteFrameToken()); + blink::RemoteFrameToken(), CreateStubRemoteFrameInterfaces()); EXPECT_TRUE(root_web_frame->FirstChild()->IsWebRemoteFrame()); EXPECT_FALSE(root_web_frame->FirstChild() ->ToWebRemoteFrame() @@ -682,7 +695,7 @@ static_cast<mojom::Frame*>(child_frame_2) ->Unload(kProxyRoutingId + 1, true, ReconstructReplicationStateForTesting(child_frame_2), - blink::RemoteFrameToken()); + blink::RemoteFrameToken(), CreateStubRemoteFrameInterfaces()); EXPECT_TRUE(root_web_frame->FirstChild()->NextSibling()->IsWebRemoteFrame()); // Verify new child has the flag too. EXPECT_TRUE(root_web_frame->FirstChild() @@ -1052,7 +1065,7 @@ static_cast<mojom::Frame*>(child_frame) ->Unload(kProxyRoutingId + 1, true, ReconstructReplicationStateForTesting(child_frame), - blink::RemoteFrameToken()); + blink::RemoteFrameToken(), CreateStubRemoteFrameInterfaces()); EXPECT_TRUE(web_frame->FirstChild()->IsWebRemoteFrame()); RenderFrameProxy* child_proxy = RenderFrameProxy::FromWebFrame( web_frame->FirstChild()->ToWebRemoteFrame()); @@ -1094,7 +1107,7 @@ replication_state->origin = url::Origin::Create(GURL("http://foo.com")); static_cast<mojom::Frame*>(child_frame) ->Unload(kProxyRoutingId, true, replication_state->Clone(), - blink::RemoteFrameToken()); + blink::RemoteFrameToken(), CreateStubRemoteFrameInterfaces()); // The child frame should now be a WebRemoteFrame. EXPECT_TRUE(web_frame->FirstChild()->IsWebRemoteFrame()); @@ -1113,7 +1126,7 @@ web_frame->FirstChild()->NextSibling()->ToWebLocalFrame())); static_cast<mojom::Frame*>(child_frame2) ->Unload(kProxyRoutingId + 1, true, std::move(replication_state), - blink::RemoteFrameToken()); + blink::RemoteFrameToken(), CreateStubRemoteFrameInterfaces()); EXPECT_TRUE(web_frame->FirstChild()->NextSibling()->IsWebRemoteFrame()); EXPECT_TRUE( web_frame->FirstChild()->NextSibling()->GetSecurityOrigin().IsOpaque()); @@ -1139,9 +1152,9 @@ // Unload the main frame after which it should become a WebRemoteFrame. auto replication_state = ReconstructReplicationStateForTesting(frame()); // replication_state.origin = url::Origin(GURL("http://foo.com")); - static_cast<mojom::Frame*>(frame())->Unload(kProxyRoutingId, true, - replication_state->Clone(), - blink::RemoteFrameToken()); + static_cast<mojom::Frame*>(frame())->Unload( + kProxyRoutingId, true, replication_state->Clone(), + blink::RemoteFrameToken(), CreateStubRemoteFrameInterfaces()); EXPECT_TRUE(view()->GetWebView()->MainFrame()->IsWebRemoteFrame()); // Do the remote-to-local transition for the proxy, which is to create a @@ -1230,7 +1243,7 @@ auto replication_state = ReconstructReplicationStateForTesting(child_frame); static_cast<mojom::Frame*>(child_frame) ->Unload(kProxyRoutingId, true, replication_state.Clone(), - blink::RemoteFrameToken()); + blink::RemoteFrameToken(), CreateStubRemoteFrameInterfaces()); EXPECT_TRUE(web_frame->FirstChild()->IsWebRemoteFrame()); // Do the first step of a remote-to-local transition for the child proxy, @@ -1280,7 +1293,7 @@ static_cast<mojom::Frame*>(main_frame) ->Unload(kProxyRoutingId, true, ReconstructReplicationStateForTesting(main_frame), - blink::RemoteFrameToken()); + blink::RemoteFrameToken(), CreateStubRemoteFrameInterfaces()); EXPECT_TRUE(view()->GetWebView()->MainFrame()->IsWebRemoteFrame()); } @@ -3002,7 +3015,7 @@ // Unloads the main frame. static_cast<mojom::Frame*>(frame())->Unload( 1, false, blink::mojom::FrameReplicationState::New(), - blink::RemoteFrameToken()); + blink::RemoteFrameToken(), CreateStubRemoteFrameInterfaces()); was_callback_run = true; run_loop.Quit();
diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc index 5d85a561..be0a2a33 100644 --- a/content/renderer/render_view_impl.cc +++ b/content/renderer/render_view_impl.cc
@@ -151,8 +151,9 @@ agent_scheduling_group_, params->main_frame->get_remote_params()->token, params->main_frame->get_remote_params()->routing_id, params->opener_frame_token, GetRoutingID(), MSG_ROUTING_NONE, - std::move(params->replication_state), - params->devtools_main_frame_token); + std::move(params->replication_state), params->devtools_main_frame_token, + std::move( + params->main_frame->get_remote_params()->main_frame_interfaces)); } // TODO(davidben): Move this state from Blink into content.
diff --git a/content/shell/common/OWNERS b/content/shell/common/OWNERS index b6ba3c9..fb7b9cf 100644 --- a/content/shell/common/OWNERS +++ b/content/shell/common/OWNERS
@@ -5,4 +5,4 @@ per-file *_messages.cc=set noparent per-file *_messages.cc=file://ipc/SECURITY_OWNERS per-file *_param_traits*.*=set noparent -per-file *_param_traits*.*=file://ipc/SECURITY_OWNERS \ No newline at end of file +per-file *_param_traits*.*=file://ipc/SECURITY_OWNERS
diff --git a/content/test/test_render_view_host.cc b/content/test/test_render_view_host.cc index a38339db..88bd15d 100644 --- a/content/test/test_render_view_host.cc +++ b/content/test/test_render_view_host.cc
@@ -16,6 +16,7 @@ #include "content/browser/dom_storage/session_storage_namespace_impl.h" #include "content/browser/renderer_host/data_transfer_util.h" #include "content/browser/renderer_host/input/synthetic_gesture_target.h" +#include "content/browser/renderer_host/render_frame_proxy_host.h" #include "content/browser/renderer_host/render_widget_host_input_event_router.h" #include "content/browser/site_instance_impl.h" #include "content/browser/storage_partition_impl.h" @@ -277,8 +278,16 @@ // When the RenderViewHost has a main frame host attached, the RenderView // in the renderer creates the main frame along with it. We mimic that here by // creating the mojo connections and calling RenderFrameCreated(). - RenderFrameHostImpl* main_frame = RenderFrameHostImpl::FromID( - GetProcess()->GetID(), main_frame_routing_id_); + RenderFrameHostImpl* main_frame = nullptr; + RenderFrameProxyHost* proxy_host = nullptr; + if (main_frame_routing_id_ != MSG_ROUTING_NONE) { + main_frame = RenderFrameHostImpl::FromID(GetProcess()->GetID(), + main_frame_routing_id_); + } else { + proxy_host = + RenderFrameProxyHost::FromID(GetProcess()->GetID(), proxy_route_id); + } + DCHECK_EQ(!!main_frame, is_active()); if (main_frame) { // Pretend that we started a renderer process and created the renderer Frame @@ -298,7 +307,13 @@ // This also initializes the RenderWidgetHost attached to the frame. main_frame->RenderFrameCreated(); + } else { + // Pretend that mojo connections of the RemoteFrame is transferred to + // renderer process and bound in blink. + ignore_result(proxy_host->BindRemoteMainFrameReceiverForTesting()); + proxy_host->SetRenderFrameProxyCreated(true); } + opener_frame_token_ = opener_frame_token; DCHECK(IsRenderViewLive()); return true;
diff --git a/device/bluetooth/OWNERS b/device/bluetooth/OWNERS index 11ee500..7dc456f 100644 --- a/device/bluetooth/OWNERS +++ b/device/bluetooth/OWNERS
@@ -4,4 +4,4 @@ per-file BUILD.gn=* # For adding or removing languages. -per-file *.grd=claudiomagni@chromium.org \ No newline at end of file +per-file *.grd=claudiomagni@chromium.org
diff --git a/device/vr/openxr/OWNERS b/device/vr/openxr/OWNERS index f9743fb..49a9910 100644 --- a/device/vr/openxr/OWNERS +++ b/device/vr/openxr/OWNERS
@@ -1,3 +1,3 @@ alcooper@chromium.org bajones@chromium.org -rafael.cintron@microsoft.com \ No newline at end of file +rafael.cintron@microsoft.com
diff --git a/extensions/browser/api/networking_private/OWNERS b/extensions/browser/api/networking_private/OWNERS index 3bec69af..b321c2f 100644 --- a/extensions/browser/api/networking_private/OWNERS +++ b/extensions/browser/api/networking_private/OWNERS
@@ -1,2 +1,2 @@ stevenjb@chromium.org -tbarzic@chromium.org \ No newline at end of file +tbarzic@chromium.org
diff --git a/extensions/browser/event_router.cc b/extensions/browser/event_router.cc index f9b8f149..c8ac204 100644 --- a/extensions/browser/event_router.cc +++ b/extensions/browser/event_router.cc
@@ -78,6 +78,24 @@ "Tried to add an event listener for a service worker without a valid " "extension ID."; +// A message when mojom::EventRouter::RemoveListenerForMainThread() is called +// with an invalid param. +constexpr char kRemoveEventListenerWithInvalidParam[] = + "Tried to remove an event listener without a valid extension ID nor " + "listener URL"; + +// A message when mojom::EventRouter::RemoveListenerForServiceWorker() is called +// with an invalid worker scope URL. +constexpr char kRemoveEventListenerWithInvalidWorkerScopeURL[] = + "Tried to remove an event listener for a service worker without a valid " + "worker scope URL."; + +// A message when mojom::EventRouter::RemoveListenerForServiceWorker() is called +// with an invalid extension ID. +constexpr char kRemoveEventListenerWithInvalidExtensionID[] = + "Tried to remove an event listener for a service worker without a valid " + "extension ID."; + // Sends a notification about an event to the API activity monitor and the // ExtensionHost for |extension_id| on the UI thread. Can be called from any // thread. @@ -251,6 +269,48 @@ } } +void EventRouter::RemoveListenerForMainThread( + mojom::EventListenerParamPtr param, + const std::string& event_name) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + auto* process = RenderProcessHost::FromID(receivers_.current_context()); + if (!process) + return; + + if (param->is_extension_id() && + crx_file::id_util::IdIsValid(param->get_extension_id())) { + RemoveEventListener(event_name, process, param->get_extension_id()); + } else if (param->is_listener_url() && param->get_listener_url().is_valid()) { + RemoveEventListenerForURL(event_name, process, param->get_listener_url()); + } else { + mojo::ReportBadMessage(kRemoveEventListenerWithInvalidParam); + } +} + +void EventRouter::RemoveListenerForServiceWorker( + const std::string& extension_id, + const GURL& worker_scope_url, + const std::string& event_name, + int64_t service_worker_version_id, + int worker_thread_id) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + auto* process = RenderProcessHost::FromID(receivers_.current_context()); + if (!process) + return; + + if (crx_file::id_util::IdIsValid(extension_id)) { + if (!worker_scope_url.is_valid()) { + mojo::ReportBadMessage(kRemoveEventListenerWithInvalidWorkerScopeURL); + return; + } + RemoveServiceWorkerEventListener( + event_name, process, extension_id, worker_scope_url, + service_worker_version_id, worker_thread_id); + } else { + mojo::ReportBadMessage(kRemoveEventListenerWithInvalidExtensionID); + } +} + void EventRouter::AddEventListener(const std::string& event_name, RenderProcessHost* process, const std::string& extension_id) {
diff --git a/extensions/browser/event_router.h b/extensions/browser/event_router.h index 4a89090..b858b42c 100644 --- a/extensions/browser/event_router.h +++ b/extensions/browser/event_router.h
@@ -154,6 +154,15 @@ int64_t service_worker_version_id, int32_t worker_thread_id) override; + void RemoveListenerForMainThread(mojom::EventListenerParamPtr param, + const std::string& name) override; + + void RemoveListenerForServiceWorker(const std::string& extension_id, + const GURL& worker_scope_url, + const std::string& name, + int64_t service_worker_version_id, + int32_t worker_thread_id) override; + // Removes an extension as an event listener for |event_name|. // // Note that multiple extensions can share a process due to process
diff --git a/extensions/browser/extension_message_filter.cc b/extensions/browser/extension_message_filter.cc index 3b7bacee..6f7492f 100644 --- a/extensions/browser/extension_message_filter.cc +++ b/extensions/browser/extension_message_filter.cc
@@ -93,7 +93,6 @@ const IPC::Message& message, BrowserThread::ID* thread) { switch (message.type()) { - case ExtensionHostMsg_RemoveListener::ID: case ExtensionHostMsg_AddLazyListener::ID: case ExtensionHostMsg_RemoveLazyListener::ID: case ExtensionHostMsg_AddLazyServiceWorkerListener::ID: @@ -121,8 +120,6 @@ bool ExtensionMessageFilter::OnMessageReceived(const IPC::Message& message) { bool handled = true; IPC_BEGIN_MESSAGE_MAP(ExtensionMessageFilter, message) - IPC_MESSAGE_HANDLER(ExtensionHostMsg_RemoveListener, - OnExtensionRemoveListener) IPC_MESSAGE_HANDLER(ExtensionHostMsg_AddLazyListener, OnExtensionAddLazyListener) IPC_MESSAGE_HANDLER(ExtensionHostMsg_RemoveLazyListener, @@ -150,39 +147,6 @@ return handled; } -void ExtensionMessageFilter::OnExtensionRemoveListener( - const std::string& extension_id, - const GURL& listener_or_worker_scope_url, - const std::string& event_name, - int64_t service_worker_version_id, - int worker_thread_id) { - DCHECK_CURRENTLY_ON(BrowserThread::UI); - if (!browser_context_) - return; - - RenderProcessHost* process = RenderProcessHost::FromID(render_process_id_); - if (!process) - return; - - if (crx_file::id_util::IdIsValid(extension_id)) { - const bool is_service_worker_context = worker_thread_id != kMainThreadId; - if (is_service_worker_context) { - DCHECK(listener_or_worker_scope_url.is_valid()); - GetEventRouter()->RemoveServiceWorkerEventListener( - event_name, process, extension_id, listener_or_worker_scope_url, - service_worker_version_id, worker_thread_id); - } else { - GetEventRouter()->RemoveEventListener(event_name, process, extension_id); - } - } else if (listener_or_worker_scope_url.is_valid()) { - GetEventRouter()->RemoveEventListenerForURL(event_name, process, - listener_or_worker_scope_url); - } else { - NOTREACHED() << "Tried to remove an event listener without a valid " - << "extension ID nor listener URL"; - } -} - void ExtensionMessageFilter::OnExtensionAddLazyListener( const std::string& extension_id, const std::string& event_name) {
diff --git a/extensions/browser/extension_message_filter.h b/extensions/browser/extension_message_filter.h index 479bdc7..e2ba146 100644 --- a/extensions/browser/extension_message_filter.h +++ b/extensions/browser/extension_message_filter.h
@@ -64,11 +64,6 @@ bool OnMessageReceived(const IPC::Message& message) override; // Message handlers on the UI thread. - void OnExtensionRemoveListener(const std::string& extension_id, - const GURL& listener_url, - const std::string& event_name, - int64_t service_worker_version_id, - int worker_thread_id); void OnExtensionAddLazyListener(const std::string& extension_id, const std::string& event_name); void OnExtensionAddLazyServiceWorkerListener(
diff --git a/extensions/common/extension_messages.h b/extensions/common/extension_messages.h index b6b27e9..13ebc02 100644 --- a/extensions/common/extension_messages.h +++ b/extensions/common/extension_messages.h
@@ -461,15 +461,6 @@ // Messages sent from the renderer to the browser: -// Notify the browser that the given extension removed a listener from an -// event. -IPC_MESSAGE_CONTROL5(ExtensionHostMsg_RemoveListener, - std::string /* extension_id */, - GURL /* listener_or_worker_scope_url */, - std::string /* name */, - int64_t /* service_worker_version_id */, - int /* worker_thread_id */) - // Notify the browser that the given extension added a listener to an event from // a lazy background page. IPC_MESSAGE_CONTROL2(ExtensionHostMsg_AddLazyListener,
diff --git a/extensions/common/mojom/event_router.mojom b/extensions/common/mojom/event_router.mojom index 61a00e2f..3f21a09 100644 --- a/extensions/common/mojom/event_router.mojom +++ b/extensions/common/mojom/event_router.mojom
@@ -28,4 +28,19 @@ string event_name, int64 service_worker_version_id, int32 worker_thread_id); + + // Notifies the browser that the given |extension_id| or |listener_url| + // removed a listener to an event. If it has |extension_id| in |param|, the + // listener is removed for the extension. Otherwise, it has a |listener_url| + // in |param| and the listener is removed for the URL. + RemoveListenerForMainThread(EventListenerParam param, + string event_name); + + // Notifies the browser that the given extension removed a listener from an + // event in a service worker. + RemoveListenerForServiceWorker(string extension_id, + url.mojom.Url worker_scope_url, + string event_name, + int64 service_worker_version_id, + int32 worker_thread_id); };
diff --git a/extensions/renderer/ipc_message_sender.cc b/extensions/renderer/ipc_message_sender.cc index d658acc..f8077434 100644 --- a/extensions/renderer/ipc_message_sender.cc +++ b/extensions/renderer/ipc_message_sender.cc
@@ -77,9 +77,15 @@ DCHECK(!context->IsForServiceWorker()); DCHECK_EQ(kMainThreadId, content::WorkerThread::GetCurrentId()); - render_thread_->Send(new ExtensionHostMsg_RemoveListener( - context->GetExtensionID(), context->url(), event_name, - blink::mojom::kInvalidServiceWorkerVersionId, kMainThreadId)); + if (!context->GetExtensionID().empty()) { + GetEventRouter()->RemoveListenerForMainThread( + mojom::EventListenerParam::NewExtensionId(context->GetExtensionID()), + event_name); + } else { + GetEventRouter()->RemoveListenerForMainThread( + mojom::EventListenerParam::NewListenerUrl(context->url()), + event_name); + } } void SendAddUnfilteredLazyEventListenerIPC( @@ -274,10 +280,10 @@ DCHECK_NE(blink::mojom::kInvalidServiceWorkerVersionId, context->service_worker_version_id()); - dispatcher_->Send(new ExtensionHostMsg_RemoveListener( + dispatcher_->SendRemoveEventListener( context->GetExtensionID(), context->service_worker_scope(), event_name, context->service_worker_version_id(), - content::WorkerThread::GetCurrentId())); + content::WorkerThread::GetCurrentId()); } void SendAddUnfilteredLazyEventListenerIPC(
diff --git a/extensions/renderer/worker_thread_dispatcher.cc b/extensions/renderer/worker_thread_dispatcher.cc index a6821b6..0e9544a 100644 --- a/extensions/renderer/worker_thread_dispatcher.cc +++ b/extensions/renderer/worker_thread_dispatcher.cc
@@ -55,6 +55,19 @@ worker_thread_id); } +// Calls mojom::EventRouter::RemoveListenerForServiceWorker(). It should be +// called on the IO thread. +void RemoveEventListenerOnIO(const std::string& extension_id, + const GURL& scope, + const std::string& event_name, + int64_t service_worker_version_id, + int worker_thread_id) { + auto* dispatcher = WorkerThreadDispatcher::Get(); + dispatcher->GetEventRouterOnIO()->RemoveListenerForServiceWorker( + extension_id, scope, event_name, service_worker_version_id, + worker_thread_id); +} + } // namespace WorkerThreadDispatcher::WorkerThreadDispatcher() {} @@ -166,6 +179,18 @@ service_worker_version_id, worker_thread_id)); } +void WorkerThreadDispatcher::SendRemoveEventListener( + const std::string& extension_id, + const GURL& scope, + const std::string& event_name, + int64_t service_worker_version_id, + int worker_thread_id) { + io_task_runner_->PostTask( + FROM_HERE, + base::BindOnce(&RemoveEventListenerOnIO, extension_id, scope, event_name, + service_worker_version_id, worker_thread_id)); +} + void WorkerThreadDispatcher::OnMessageReceivedOnWorkerThread( int worker_thread_id, const IPC::Message& message) {
diff --git a/extensions/renderer/worker_thread_dispatcher.h b/extensions/renderer/worker_thread_dispatcher.h index 31e6b9e..90d2019 100644 --- a/extensions/renderer/worker_thread_dispatcher.h +++ b/extensions/renderer/worker_thread_dispatcher.h
@@ -101,6 +101,14 @@ int64_t service_worker_version_id, int worker_thread_id); + // Posts mojom::EventRouter::RemoveListenerForServiceWorker to the IO thread + // to call it with GetEventRouterOnIO(). + void SendRemoveEventListener(const std::string& extension_id, + const GURL& scope, + const std::string& event_name, + int64_t service_worker_version_id, + int worker_thread_id); + // NOTE: This must be called on the IO thread because it can call // SyncMessageFilter::GetRemoteAssociatedInterface() which must be called on // the IO thread.
diff --git a/extensions/strings/OWNERS b/extensions/strings/OWNERS index 379aa51b..a0d1e83 100644 --- a/extensions/strings/OWNERS +++ b/extensions/strings/OWNERS
@@ -1,2 +1,2 @@ # For adding or removing languages. -per-file *.grd=claudiomagni@chromium.org \ No newline at end of file +per-file *.grd=claudiomagni@chromium.org
diff --git a/google_apis/DIR_METADATA b/google_apis/DIR_METADATA index 3f72231..2322464 100644 --- a/google_apis/DIR_METADATA +++ b/google_apis/DIR_METADATA
@@ -1,10 +1,10 @@ # Metadata information for this directory. # # For more information on DIR_METADATA files, see: -# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/README.md +# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/README.md # # For the schema of this file, see Metadata message: -# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/proto/dir_metadata.proto +# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/proto/dir_metadata.proto monorail { component: "Services>SignIn"
diff --git a/google_apis/drive/DIR_METADATA b/google_apis/drive/DIR_METADATA index 658199f9..6f9a3839 100644 --- a/google_apis/drive/DIR_METADATA +++ b/google_apis/drive/DIR_METADATA
@@ -1,10 +1,10 @@ # Metadata information for this directory. # # For more information on DIR_METADATA files, see: -# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/README.md +# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/README.md # # For the schema of this file, see Metadata message: -# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/proto/dir_metadata.proto +# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/proto/dir_metadata.proto monorail { component: "Platform>Apps>FileManager"
diff --git a/google_apis/gcm/DIR_METADATA b/google_apis/gcm/DIR_METADATA index 6e64937..ca7bcee 100644 --- a/google_apis/gcm/DIR_METADATA +++ b/google_apis/gcm/DIR_METADATA
@@ -1,10 +1,10 @@ # Metadata information for this directory. # # For more information on DIR_METADATA files, see: -# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/README.md +# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/README.md # # For the schema of this file, see Metadata message: -# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/proto/dir_metadata.proto +# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/proto/dir_metadata.proto monorail { component: "Services>CloudMessaging"
diff --git a/google_apis/test/DIR_METADATA b/google_apis/test/DIR_METADATA index 1fd3fb96..eeda617 100644 --- a/google_apis/test/DIR_METADATA +++ b/google_apis/test/DIR_METADATA
@@ -1,10 +1,10 @@ # Metadata information for this directory. # # For more information on DIR_METADATA files, see: -# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/README.md +# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/README.md # # For the schema of this file, see Metadata message: -# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/proto/dir_metadata.proto +# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/proto/dir_metadata.proto monorail { component: "Internals>Services>Network"
diff --git a/infra/config/subprojects/webrtc/OWNERS b/infra/config/subprojects/webrtc/OWNERS new file mode 100644 index 0000000..35aab6c --- /dev/null +++ b/infra/config/subprojects/webrtc/OWNERS
@@ -0,0 +1,4 @@ +jansson@chromium.org +landrey@google.com +mbonadei@chromium.org +terelius@chromium.org
diff --git a/ios/chrome/browser/ui/authentication/signin/signin_utils.mm b/ios/chrome/browser/ui/authentication/signin/signin_utils.mm index c404c038..4e49313a 100644 --- a/ios/chrome/browser/ui/authentication/signin/signin_utils.mm +++ b/ios/chrome/browser/ui/authentication/signin/signin_utils.mm
@@ -90,6 +90,7 @@ if (auth_service->IsAuthenticated()) return false; + // Used for testing purposes only. if (signin::ForceStartupSigninPromo()) return true; @@ -106,14 +107,23 @@ } } + ios::ChromeIdentityService* identity_service = + ios::GetChromeBrowserProvider()->GetChromeIdentityService(); + // Don't show the promo if there are no identities. - NSArray* identities = - ios::GetChromeBrowserProvider() - ->GetChromeIdentityService() - ->GetAllIdentitiesSortedForDisplay(browser_state->GetPrefs()); + NSArray* identities = identity_service->GetAllIdentitiesSortedForDisplay( + browser_state->GetPrefs()); if (identities.count == 0) return false; + // Don't show the SSO promo if the default primary account is subject to + // minor mode restrictions. + absl::optional<bool> isSubjectToMinorModeRestrictions = + identity_service->IsSubjectToMinorModeRestrictions(identities[0]); + if (isSubjectToMinorModeRestrictions.has_value() && + isSubjectToMinorModeRestrictions.value()) + return false; + // The sign-in promo should be shown twice, even if no account has been added. NSInteger display_count = [defaults integerForKey:kSigninPromoViewDisplayCountKey];
diff --git a/ios/chrome/browser/ui/authentication/signin/signin_utils_unittest.mm b/ios/chrome/browser/ui/authentication/signin/signin_utils_unittest.mm index 603874a..e030a34 100644 --- a/ios/chrome/browser/ui/authentication/signin/signin_utils_unittest.mm +++ b/ios/chrome/browser/ui/authentication/signin/signin_utils_unittest.mm
@@ -42,8 +42,6 @@ base::BindRepeating( &AuthenticationServiceFake::CreateAuthenticationService)); chrome_browser_state_ = builder.Build(); - ios::FakeChromeIdentityService::GetInstanceFromChromeProvider() - ->AddIdentities(@[ @"foo", @"bar" ]); } void TearDown() override { @@ -72,6 +70,8 @@ // Should show the sign-in upgrade for the first time. TEST_F(SigninUtilsTest, TestWillDisplay) { + ios::FakeChromeIdentityService::GetInstanceFromChromeProvider() + ->AddIdentities(@[ @"foo", @"bar" ]); const base::Version version_1_0("1.0"); EXPECT_TRUE(signin::ShouldPresentUserSigninUpgrade( chrome_browser_state_.get(), version_1_0)); @@ -79,6 +79,8 @@ // Should not show the sign-in upgrade twice on the same version. TEST_F(SigninUtilsTest, TestWillNotDisplaySameVersion) { + ios::FakeChromeIdentityService::GetInstanceFromChromeProvider() + ->AddIdentities(@[ @"foo", @"bar" ]); const base::Version version_1_0("1.0"); signin::RecordVersionSeen(chrome_browser_state_->GetPrefs(), version_1_0); EXPECT_FALSE(signin::ShouldPresentUserSigninUpgrade( @@ -87,6 +89,8 @@ // Should not show the sign-in upgrade twice until two major version after. TEST_F(SigninUtilsTest, TestWillNotDisplayOneMinorVersion) { + ios::FakeChromeIdentityService::GetInstanceFromChromeProvider() + ->AddIdentities(@[ @"foo", @"bar" ]); const base::Version version_1_0("1.0"); const base::Version version_1_1("1.1"); signin::RecordVersionSeen(chrome_browser_state_->GetPrefs(), version_1_0); @@ -96,6 +100,8 @@ // Should not show the sign-in upgrade twice until two major version after. TEST_F(SigninUtilsTest, TestWillNotDisplayTwoMinorVersions) { + ios::FakeChromeIdentityService::GetInstanceFromChromeProvider() + ->AddIdentities(@[ @"foo", @"bar" ]); const base::Version version_1_0("1.0"); const base::Version version_1_2("1.2"); signin::RecordVersionSeen(chrome_browser_state_->GetPrefs(), version_1_0); @@ -105,6 +111,8 @@ // Should not show the sign-in upgrade twice until two major version after. TEST_F(SigninUtilsTest, TestWillNotDisplayOneMajorVersion) { + ios::FakeChromeIdentityService::GetInstanceFromChromeProvider() + ->AddIdentities(@[ @"foo", @"bar" ]); const base::Version version_1_0("1.0"); const base::Version version_2_0("2.0"); signin::RecordVersionSeen(chrome_browser_state_->GetPrefs(), version_1_0); @@ -114,6 +122,8 @@ // Should show the sign-in upgrade a second time, 2 version after. TEST_F(SigninUtilsTest, TestWillDisplayTwoMajorVersions) { + ios::FakeChromeIdentityService::GetInstanceFromChromeProvider() + ->AddIdentities(@[ @"foo", @"bar" ]); const base::Version version_1_0("1.0"); const base::Version version_3_0("3.0"); signin::RecordVersionSeen(chrome_browser_state_->GetPrefs(), version_1_0); @@ -126,6 +136,8 @@ // Move to version 5.0. // Expected: should not show the sign-in upgrade. TEST_F(SigninUtilsTest, TestWillShowTwoTimesOnly) { + ios::FakeChromeIdentityService::GetInstanceFromChromeProvider() + ->AddIdentities(@[ @"foo", @"bar" ]); const base::Version version_1_0("1.0"); const base::Version version_3_0("3.0"); const base::Version version_5_0("5.0"); @@ -218,6 +230,8 @@ // Should not show the sign-in upgrade if sign-in is disabled by policy. TEST_F(SigninUtilsTest, TestWillNotShowIfDisabledByPolicy) { + ios::FakeChromeIdentityService::GetInstanceFromChromeProvider() + ->AddIdentities(@[ @"foo", @"bar" ]); const base::Version version_1_0("1.0"); ios::FakeChromeIdentityService::GetInstanceFromChromeProvider() ->AddIdentities(@[ @"foo1" ]); @@ -229,6 +243,8 @@ // signin::IsSigninAllowed should respect the kSigninAllowed pref. TEST_F(SigninUtilsTest, TestSigninAllowedPref) { + ios::FakeChromeIdentityService::GetInstanceFromChromeProvider() + ->AddIdentities(@[ @"foo", @"bar" ]); // Sign-in is allowed by default. EXPECT_TRUE(signin::IsSigninAllowed(chrome_browser_state_.get()->GetPrefs())); @@ -238,4 +254,56 @@ signin::IsSigninAllowed(chrome_browser_state_.get()->GetPrefs())); } +// Show the sign-in upgrade on version 1.0. +// Move to version 3.0. +// Add an account subject to minor mode restrictions. +// Expected: should not show the sign-in upgrade. +TEST_F(SigninUtilsTest, TestWillNotShowForMinorModeAccount) { + const base::Version version_1_0("1.0"); + const base::Version version_3_0("3.0"); + signin::RecordVersionSeen(chrome_browser_state_->GetPrefs(), version_1_0); + + ios::FakeChromeIdentityService::GetInstanceFromChromeProvider() + ->AddMinorModeIdentities(@[ @"foo1" ]); + + EXPECT_FALSE(signin::ShouldPresentUserSigninUpgrade( + chrome_browser_state_.get(), version_3_0)); +} + +// Show the sign-in upgrade on version 1.0. +// Move to version 3.0. +// Add a minor account to list of existing accounts. +// Expected: should not show the sign-in upgrade. +TEST_F(SigninUtilsTest, TestWillShowIfMinorModeAccountNotDefault) { + ios::FakeChromeIdentityService* service = + ios::FakeChromeIdentityService::GetInstanceFromChromeProvider(); + service->AddIdentities(@[ @"foo", @"bar" ]); + + const base::Version version_1_0("1.0"); + const base::Version version_3_0("3.0"); + signin::RecordVersionSeen(chrome_browser_state_->GetPrefs(), version_1_0); + service->AddMinorModeIdentities(@[ @"foo1" ]); + + EXPECT_TRUE(signin::ShouldPresentUserSigninUpgrade( + chrome_browser_state_.get(), version_3_0)); +} + +// Show the sign-in upgrade on version 1.0. +// Move to version 3.0. +// Remove existing accounts and add a minor account. +// Expected: should not show the sign-in upgrade. +TEST_F(SigninUtilsTest, TestWillNotShowIfMinorModeAccountIsDefault) { + const base::Version version_1_0("1.0"); + const base::Version version_3_0("3.0"); + signin::RecordVersionSeen(chrome_browser_state_->GetPrefs(), version_1_0); + + ios::FakeChromeIdentityService* service = + ios::FakeChromeIdentityService::GetInstanceFromChromeProvider(); + service->AddMinorModeIdentities(@[ @"foo2" ]); + service->AddIdentities(@[ @"foo", @"bar" ]); + + EXPECT_FALSE(signin::ShouldPresentUserSigninUpgrade( + chrome_browser_state_.get(), version_3_0)); +} + } // namespace
diff --git a/ios/chrome/browser/ui/recent_tabs/BUILD.gn b/ios/chrome/browser/ui/recent_tabs/BUILD.gn index 7916701..495c72f 100644 --- a/ios/chrome/browser/ui/recent_tabs/BUILD.gn +++ b/ios/chrome/browser/ui/recent_tabs/BUILD.gn
@@ -105,6 +105,8 @@ "//ios/chrome/browser/web_state_list", "//ios/chrome/common/ui/colors", "//ios/chrome/common/ui/favicon", + "//ios/public/provider/chrome/browser", + "//ios/public/provider/chrome/browser/modals", "//ios/public/provider/chrome/browser/signin", "//ui/base", ]
diff --git a/ios/chrome/browser/ui/recent_tabs/recent_tabs_table_view_controller.mm b/ios/chrome/browser/ui/recent_tabs/recent_tabs_table_view_controller.mm index 8fb310b..4c4482c9 100644 --- a/ios/chrome/browser/ui/recent_tabs/recent_tabs_table_view_controller.mm +++ b/ios/chrome/browser/ui/recent_tabs/recent_tabs_table_view_controller.mm
@@ -67,6 +67,8 @@ #import "ios/chrome/common/ui/favicon/favicon_view.h" #include "ios/chrome/grit/ios_chromium_strings.h" #include "ios/chrome/grit/ios_strings.h" +#include "ios/public/provider/chrome/browser/chrome_browser_provider.h" +#import "ios/public/provider/chrome/browser/modals/modals_provider.h" #import "ios/public/provider/chrome/browser/signin/signin_presenter.h" #import "ios/web/public/web_state.h" #include "ui/base/l10n/l10n_util.h" @@ -798,6 +800,10 @@ - (void)dismissModals { [self.contextMenuCoordinator stop]; + + ios::GetChromeBrowserProvider() + ->GetModalsProvider() + ->DismissModalsForTableView(self.tableView); } #pragma mark - UITableViewDelegate
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/BUILD.gn b/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/BUILD.gn index a64e91b9..65be412 100644 --- a/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/BUILD.gn +++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/BUILD.gn
@@ -73,6 +73,8 @@ "//ios/chrome/browser/ui/util", "//ios/chrome/common/ui/colors", "//ios/chrome/common/ui/util", + "//ios/public/provider/chrome/browser", + "//ios/public/provider/chrome/browser/modals", "//ui/base", ] }
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/grid_consumer.h b/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/grid_consumer.h index 8cb8c34..ccc8ff4b 100644 --- a/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/grid_consumer.h +++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/grid_consumer.h
@@ -50,6 +50,9 @@ // of that item might be. - (void)moveItemWithID:(NSString*)itemID toIndex:(NSUInteger)toIndex; +// Dismisses any presented modal UI. +- (void)dismissModals; + @end #endif // IOS_CHROME_BROWSER_UI_TAB_SWITCHER_TAB_GRID_GRID_GRID_CONSUMER_H_
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/grid_context_menu_helper.mm b/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/grid_context_menu_helper.mm index 28cb3369..74eaa07 100644 --- a/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/grid_context_menu_helper.mm +++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/grid_context_menu_helper.mm
@@ -78,7 +78,8 @@ fromView:gridCell]; }]]; - if ([weakSelf.contextMenuDelegate + if (item.URL.SchemeIsHTTPOrHTTPS() && + [weakSelf.contextMenuDelegate respondsToSelector:@selector(addToReadingListURL:title:)]) { [menuElements addObject:[actionFactory actionToAddToReadingListWithBlock:^{
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/grid_view_controller.mm b/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/grid_view_controller.mm index cc26088..6b90688 100644 --- a/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/grid_view_controller.mm +++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/grid_view_controller.mm
@@ -32,6 +32,8 @@ #import "ios/chrome/browser/ui/util/rtl_geometry.h" #import "ios/chrome/browser/ui/util/uikit_ui_util.h" #import "ios/chrome/common/ui/util/constraints_ui_util.h" +#include "ios/public/provider/chrome/browser/chrome_browser_provider.h" +#import "ios/public/provider/chrome/browser/modals/modals_provider.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support." @@ -780,6 +782,12 @@ [self updateVisibleCellIdentifiers]; } +- (void)dismissModals { + ios::GetChromeBrowserProvider() + ->GetModalsProvider() + ->DismissModalsForCollectionView(self.collectionView); +} + #pragma mark - LayoutSwitcher - (void)willTransitionToLayout:(LayoutSwitcherState)nextState
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_coordinator.mm b/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_coordinator.mm index 724b743..476f6bd 100644 --- a/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_coordinator.mm +++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_coordinator.mm
@@ -227,8 +227,8 @@ } - (void)stopChildCoordinatorsWithCompletion:(ProceduralBlock)completion { - // Recent tabs context menu may be presented on top of the tab grid. - [self.baseViewController.remoteTabsViewController dismissModals]; + // A modal may be presented on top of the Recent Tabs or tab grid. + [self.baseViewController dismissModals]; [self.actionSheetCoordinator stop]; // History may be presented on top of the tab grid. if (self.historyCoordinator) {
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_mediator_unittest.mm b/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_mediator_unittest.mm index 3fd8955..df3eeac 100644 --- a/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_mediator_unittest.mm +++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_mediator_unittest.mm
@@ -219,6 +219,10 @@ [self.items insertObject:itemID atIndex:toIndex]; } +- (void)dismissModals { + // No-op. +} + @end // Fake WebStateList delegate that attaches the required tab helper.
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_view_controller.h b/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_view_controller.h index 27e36a0e..7d5806a 100644 --- a/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_view_controller.h +++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_view_controller.h
@@ -157,6 +157,9 @@ // has been closed. - (void)closeAllTabsConfirmationClosed; +// Dismisses any modal UI which may be presented. +- (void)dismissModals; + @end #endif // IOS_CHROME_BROWSER_UI_TAB_SWITCHER_TAB_GRID_TAB_GRID_VIEW_CONTROLLER_H_
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_view_controller.mm b/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_view_controller.mm index f79686b..70f21c8 100644 --- a/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_view_controller.mm +++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_view_controller.mm
@@ -498,6 +498,12 @@ [self configureButtonsForActiveAndCurrentPage]; } +- (void)dismissModals { + [self.regularTabsConsumer dismissModals]; + [self.incognitoTabsConsumer dismissModals]; + [self.remoteTabsViewController dismissModals]; +} + #pragma mark - Public Properties - (id<GridConsumer>)regularTabsConsumer {
diff --git a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.arm64.zip.sha1 b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.arm64.zip.sha1 index a074e1e4..6d4d745 100644 --- a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.arm64.zip.sha1 +++ b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.arm64.zip.sha1
@@ -1 +1 @@ -76a6ba7b57f509b7309d3553bada1633e264a2ed \ No newline at end of file +b6b18cfc7622fc77a8b179d96b828fafc622174d \ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.x64.zip.sha1 b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.x64.zip.sha1 index 3ce1945..177c48f6 100644 --- a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.x64.zip.sha1 +++ b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.x64.zip.sha1
@@ -1 +1 @@ -2ae2b9c0ee41b63e06512198de9cfcfecec47abb \ No newline at end of file +055f6a2204cfe77293a7310f2a7fc9ad2f8a81bb \ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.arm64.zip.sha1 b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.arm64.zip.sha1 index 7e824b6..3d8b640 100644 --- a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.arm64.zip.sha1 +++ b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.arm64.zip.sha1
@@ -1 +1 @@ -2d3d3afac9c36ab1ea74a2dabedefe2517e6a3e0 \ No newline at end of file +84dc689b736dd48ec87c222a44d1ff18ec88a1ce \ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.x64.zip.sha1 b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.x64.zip.sha1 index 9200aaa..ed83375 100644 --- a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.x64.zip.sha1 +++ b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.x64.zip.sha1
@@ -1 +1 @@ -a83650b6933c83698ba86f90e36fda9fa2a2cff8 \ No newline at end of file +886a658507f1542c0b44d22cae8eef0eabd40d5a \ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.arm64.zip.sha1 b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.arm64.zip.sha1 index 71350573..40e2911 100644 --- a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.arm64.zip.sha1 +++ b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.arm64.zip.sha1
@@ -1 +1 @@ -3c7364964e2f9bab5db61c2248c9f0848cc6fc86 \ No newline at end of file +5194c4e192ce16663ed0f8fda3c2d29d0eb3ec72 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.x64.zip.sha1 b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.x64.zip.sha1 index fce7344..58b60a0 100644 --- a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.x64.zip.sha1 +++ b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.x64.zip.sha1
@@ -1 +1 @@ -57d95e64264164118cdff2163be78b74314a06c6 \ No newline at end of file +99becdfe7c49b880debeca652c7af0c97c6b7f7c \ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.arm64.zip.sha1 b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.arm64.zip.sha1 index 9d183ae4..756c485 100644 --- a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.arm64.zip.sha1 +++ b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.arm64.zip.sha1
@@ -1 +1 @@ -312ed50cc60ecf41f82898cc71875ba4bd3e7395 \ No newline at end of file +e256a8a66bf023135b619f0f9af8d5e4a5b1c559 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.x64.zip.sha1 b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.x64.zip.sha1 index e3c0b5d..6a0c2545 100644 --- a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.x64.zip.sha1 +++ b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.x64.zip.sha1
@@ -1 +1 @@ -e089abe45d9c1144abb1791c60b8dffc6693f23d \ No newline at end of file +aaf9f9102c57ac248b24fbf74716eee76b4609bc \ No newline at end of file
diff --git a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.arm64.zip.sha1 b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.arm64.zip.sha1 index d4290af..aa72902d 100644 --- a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.arm64.zip.sha1 +++ b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.arm64.zip.sha1
@@ -1 +1 @@ -6d0705a10622db88f952f45bc9332323a1d4de9c \ No newline at end of file +78a0ca78f1538cf3af44cbd210c53c7b84931c38 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.x64.zip.sha1 b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.x64.zip.sha1 index 5870138..f5001bf 100644 --- a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.x64.zip.sha1 +++ b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.x64.zip.sha1
@@ -1 +1 @@ -6e4f519a7122867567609a445efc3b68c8990d87 \ No newline at end of file +e6c178106f27049a97420e14ecc7c3791601a159 \ No newline at end of file
diff --git a/ios/public/provider/chrome/browser/BUILD.gn b/ios/public/provider/chrome/browser/BUILD.gn index a77ab9c..842e077 100644 --- a/ios/public/provider/chrome/browser/BUILD.gn +++ b/ios/public/provider/chrome/browser/BUILD.gn
@@ -21,6 +21,7 @@ "//base", "//components/metrics", "//ios/public/provider/chrome/browser/mailto", + "//ios/public/provider/chrome/browser/modals", "//ios/public/provider/chrome/browser/signin", "//ios/web/public", "//ios/web/public/js_messaging",
diff --git a/ios/public/provider/chrome/browser/chrome_browser_provider.h b/ios/public/provider/chrome/browser/chrome_browser_provider.h index 9b7bf707..2688064 100644 --- a/ios/public/provider/chrome/browser/chrome_browser_provider.h +++ b/ios/public/provider/chrome/browser/chrome_browser_provider.h
@@ -19,6 +19,7 @@ class AppDistributionProvider; class BrandedImageProvider; class BrowserURLRewriterProvider; +class ModalsProvider; class DiscoverFeedProvider; class FullscreenProvider; class MailtoHandlerProvider; @@ -159,6 +160,8 @@ virtual TextZoomProvider* GetTextZoomProvider() const; + virtual ModalsProvider* GetModalsProvider() const; + // Adds and removes observers. void AddObserver(Observer* observer); void RemoveObserver(Observer* observer); @@ -170,6 +173,7 @@ private: base::ObserverList<Observer, true>::Unchecked observer_list_; std::unique_ptr<MailtoHandlerProvider> mailto_handler_provider_; + std::unique_ptr<ModalsProvider> modals_provider_; std::unique_ptr<TextZoomProvider> text_zoom_provider_; };
diff --git a/ios/public/provider/chrome/browser/chrome_browser_provider.mm b/ios/public/provider/chrome/browser/chrome_browser_provider.mm index 3273786..c508d35f 100644 --- a/ios/public/provider/chrome/browser/chrome_browser_provider.mm +++ b/ios/public/provider/chrome/browser/chrome_browser_provider.mm
@@ -8,6 +8,7 @@ #include "components/metrics/metrics_provider.h" #import "ios/public/provider/chrome/browser/mailto/mailto_handler_provider.h" +#import "ios/public/provider/chrome/browser/modals/modals_provider.h" #import "ios/public/provider/chrome/browser/signin/chrome_identity_service.h" #import "ios/public/provider/chrome/browser/text_zoom_provider.h" @@ -33,6 +34,7 @@ ChromeBrowserProvider::ChromeBrowserProvider() : mailto_handler_provider_(std::make_unique<MailtoHandlerProvider>()), + modals_provider_(std::make_unique<ModalsProvider>()), text_zoom_provider_(std::make_unique<TextZoomProvider>()) {} ChromeBrowserProvider::~ChromeBrowserProvider() { @@ -132,6 +134,10 @@ return text_zoom_provider_.get(); } +ModalsProvider* ChromeBrowserProvider::GetModalsProvider() const { + return modals_provider_.get(); +} + void ChromeBrowserProvider::HideModalViewStack() const {} void ChromeBrowserProvider::LogIfModalViewsArePresented() const {}
diff --git a/ios/public/provider/chrome/browser/modals/BUILD.gn b/ios/public/provider/chrome/browser/modals/BUILD.gn new file mode 100644 index 0000000..d879eb3 --- /dev/null +++ b/ios/public/provider/chrome/browser/modals/BUILD.gn
@@ -0,0 +1,11 @@ +# Copyright 2021 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +source_set("modals") { + configs += [ "//build/config/compiler:enable_arc" ] + sources = [ + "modals_provider.h", + "modals_provider.mm", + ] +}
diff --git a/ios/public/provider/chrome/browser/modals/modals_provider.h b/ios/public/provider/chrome/browser/modals/modals_provider.h new file mode 100644 index 0000000..6b9de941 --- /dev/null +++ b/ios/public/provider/chrome/browser/modals/modals_provider.h
@@ -0,0 +1,23 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_PUBLIC_PROVIDER_CHROME_BROWSER_MODALS_MODALS_PROVIDER_H_ +#define IOS_PUBLIC_PROVIDER_CHROME_BROWSER_MODALS_MODALS_PROVIDER_H_ + +#import <UIKit/UIKit.h> + +class ModalsProvider { + public: + ModalsProvider(); + virtual ~ModalsProvider(); + + // Dismisses any modals presented from a |collection_view| item. + virtual void DismissModalsForCollectionView( + UICollectionView* collection_view); + + // Dismisses any modals presented from a |table_view| cell. + virtual void DismissModalsForTableView(UITableView* table_view); +}; + +#endif // IOS_PUBLIC_PROVIDER_CHROME_BROWSER_MODALS_MODALS_PROVIDER_H_
diff --git a/ios/public/provider/chrome/browser/modals/modals_provider.mm b/ios/public/provider/chrome/browser/modals/modals_provider.mm new file mode 100644 index 0000000..08b8720 --- /dev/null +++ b/ios/public/provider/chrome/browser/modals/modals_provider.mm
@@ -0,0 +1,18 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/public/provider/chrome/browser/modals/modals_provider.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +ModalsProvider::ModalsProvider() = default; + +ModalsProvider::~ModalsProvider() = default; + +void ModalsProvider::DismissModalsForCollectionView( + UICollectionView* collection_view) {} + +void ModalsProvider::DismissModalsForTableView(UITableView* table_view) {} \ No newline at end of file
diff --git a/ios/public/provider/chrome/browser/signin/fake_chrome_identity_service.h b/ios/public/provider/chrome/browser/signin/fake_chrome_identity_service.h index 81660fb..855fe73 100644 --- a/ios/public/provider/chrome/browser/signin/fake_chrome_identity_service.h +++ b/ios/public/provider/chrome/browser/signin/fake_chrome_identity_service.h
@@ -76,6 +76,9 @@ // Sets up the mock methods for integration tests. void SetUpForIntegrationTests(); + // Adds the identities subject to minor mode restrictions given their name. + void AddMinorModeIdentities(NSArray* identitiesName); + // Adds the managed identities given their name. void AddManagedIdentities(NSArray* identitiesName);
diff --git a/ios/public/provider/chrome/browser/signin/fake_chrome_identity_service.mm b/ios/public/provider/chrome/browser/signin/fake_chrome_identity_service.mm index 7ccaba8..c2b1f0a 100644 --- a/ios/public/provider/chrome/browser/signin/fake_chrome_identity_service.mm +++ b/ios/public/provider/chrome/browser/signin/fake_chrome_identity_service.mm
@@ -302,7 +302,11 @@ absl::optional<bool> FakeChromeIdentityService::IsSubjectToMinorModeRestrictions( ChromeIdentity* identity) { - return absl::nullopt; + if (![identities_ containsObject:identity]) { + return absl::nullopt; + } + return absl::make_optional( + [identity.userEmail hasSuffix:kMinorModeIdentityEmailSuffix]); } void FakeChromeIdentityService::SetUpForIntegrationTests() {} @@ -318,6 +322,18 @@ } } +void FakeChromeIdentityService::AddMinorModeIdentities( + NSArray* identitiesNames) { + for (NSString* name in identitiesNames) { + NSString* email = [NSString + stringWithFormat:@"%@%@", name, kMinorModeIdentityEmailSuffix]; + NSString* gaiaID = [NSString stringWithFormat:kIdentityGaiaIDFormat, name]; + [identities_ addObject:[FakeChromeIdentity identityWithEmail:email + gaiaID:gaiaID + name:name]]; + } +} + void FakeChromeIdentityService::AddIdentities(NSArray* identitiesNames) { for (NSString* name in identitiesNames) { NSString* email = [NSString stringWithFormat:kIdentityEmailFormat, name];
diff --git a/ios/public/provider/chrome/browser/signin/fake_chrome_identity_service_constants.h b/ios/public/provider/chrome/browser/signin/fake_chrome_identity_service_constants.h index 6b1fff5..987b821 100644 --- a/ios/public/provider/chrome/browser/signin/fake_chrome_identity_service_constants.h +++ b/ios/public/provider/chrome/browser/signin/fake_chrome_identity_service_constants.h
@@ -12,6 +12,9 @@ // Email suffix used for managed accounts. extern NSString* const kManagedIdentityEmailSuffix; +// Email suffix used for accounts subject to minor mode restrictions. +extern NSString* const kMinorModeIdentityEmailSuffix; + } // namespace ios #endif // IOS_PUBLIC_PROVIDER_CHROME_BROWSER_SIGNIN_FAKE_CHROME_IDENTITY_SERVICE_CONSTANTS_H_
diff --git a/ios/public/provider/chrome/browser/signin/fake_chrome_identity_service_constants.mm b/ios/public/provider/chrome/browser/signin/fake_chrome_identity_service_constants.mm index dd44004..4252c84 100644 --- a/ios/public/provider/chrome/browser/signin/fake_chrome_identity_service_constants.mm +++ b/ios/public/provider/chrome/browser/signin/fake_chrome_identity_service_constants.mm
@@ -12,4 +12,6 @@ NSString* const kManagedIdentityEmailSuffix = @"@google.com"; +NSString* const kMinorModeIdentityEmailSuffix = @"@minor-mode"; + } // namespace ios
diff --git a/ios/third_party/material_components_ios/BUILD.gn b/ios/third_party/material_components_ios/BUILD.gn index 701ff13..990664e 100644 --- a/ios/third_party/material_components_ios/BUILD.gn +++ b/ios/third_party/material_components_ios/BUILD.gn
@@ -451,6 +451,7 @@ "src/components/Themes/src/MDCTonalColorScheme.h", "src/components/Themes/src/MDCTonalPalette.h", "src/components/Themes/src/MaterialThemes.h", + "src/components/Typography/src/FontLoader/MDCTypographyFontLoader.h", "src/components/Typography/src/MDCFontScaler.h", "src/components/Typography/src/MDCFontTextStyle.h", "src/components/Typography/src/MDCTypography.h", @@ -681,6 +682,7 @@ "src/components/TextFields/src/private", "src/components/Themes/src", "src/components/Typography/src", + "src/components/Typography/src/FontLoader", "src/components/Typography/src/private", "src/components/private/Application/src", "src/components/private/Color/src", @@ -1382,6 +1384,7 @@ "src/components/Themes/src/MDCTonalColorScheme.h", "src/components/Themes/src/MDCTonalPalette.h", "src/components/Themes/src/MaterialThemes.h", + "src/components/Typography/src/FontLoader/MDCTypographyFontLoader.h", "src/components/Typography/src/MDCFontScaler.h", "src/components/Typography/src/MDCFontScaler.m", "src/components/Typography/src/MDCFontTextStyle.h",
diff --git a/ios/web/test/web_int_test.mm b/ios/web/test/web_int_test.mm index 856b637a..5595d41 100644 --- a/ios/web/test/web_int_test.mm +++ b/ios/web/test/web_int_test.mm
@@ -6,7 +6,7 @@ #import "base/ios/block_types.h" #include "base/memory/ptr_util.h" -#include "base/scoped_observer.h" +#include "base/scoped_observation.h" #include "base/strings/sys_string_conversions.h" #import "base/test/ios/wait_util.h" #import "ios/web/common/uikit_ui_util.h" @@ -94,8 +94,9 @@ DCHECK(block); IntTestWebStateObserver observer(url); - ScopedObserver<WebState, WebStateObserver> scoped_observer(&observer); - scoped_observer.Add(web_state()); + base::ScopedObservation<WebState, WebStateObserver> scoped_observer( + &observer); + scoped_observer.Observe(web_state()); block();
diff --git a/ios/web/web_state/global_web_state_event_tracker.h b/ios/web/web_state/global_web_state_event_tracker.h index 9dd6b95..15d94c3 100644 --- a/ios/web/web_state/global_web_state_event_tracker.h +++ b/ios/web/web_state/global_web_state_event_tracker.h
@@ -10,7 +10,7 @@ #include "base/macros.h" #include "base/no_destructor.h" #include "base/observer_list.h" -#include "base/scoped_observer.h" +#include "base/scoped_multi_source_observation.h" #include "ios/web/public/deprecated/global_web_state_observer.h" #import "ios/web/public/web_state.h" #include "ios/web/public/web_state_observer.h" @@ -48,7 +48,8 @@ ~GlobalWebStateEventTracker() override; // ScopedObserver used to track registration with WebState. - ScopedObserver<WebState, WebStateObserver> scoped_observer_{this}; + base::ScopedMultiSourceObservation<WebState, WebStateObserver> + scoped_observations_{this}; // List of observers currently registered with the tracker. base::ObserverList<GlobalWebStateObserver, true>::Unchecked observer_list_;
diff --git a/ios/web/web_state/global_web_state_event_tracker.mm b/ios/web/web_state/global_web_state_event_tracker.mm index 78cce0e4..d9701fb1 100644 --- a/ios/web/web_state/global_web_state_event_tracker.mm +++ b/ios/web/web_state/global_web_state_event_tracker.mm
@@ -25,7 +25,7 @@ GlobalWebStateEventTracker::~GlobalWebStateEventTracker() = default; void GlobalWebStateEventTracker::OnWebStateCreated(WebState* web_state) { - scoped_observer_.Add(web_state); + scoped_observations_.AddObservation(web_state); } void GlobalWebStateEventTracker::AddObserver(GlobalWebStateObserver* observer) { @@ -62,7 +62,7 @@ void GlobalWebStateEventTracker::WebStateDestroyed(WebState* web_state) { for (auto& observer : observer_list_) observer.WebStateDestroyed(web_state); - scoped_observer_.Remove(web_state); + scoped_observations_.RemoveObservation(web_state); } } // namespace web
diff --git a/ios/web/web_state/ui/crw_web_controller_unittest.mm b/ios/web/web_state/ui/crw_web_controller_unittest.mm index e0bf361..cb7af00 100644 --- a/ios/web/web_state/ui/crw_web_controller_unittest.mm +++ b/ios/web/web_state/ui/crw_web_controller_unittest.mm
@@ -10,7 +10,7 @@ #include <utility> #include "base/mac/foundation_util.h" -#include "base/scoped_observer.h" +#include "base/scoped_observation.h" #include "base/strings/sys_string_conversions.h" #include "base/strings/utf_string_conversions.h" #import "base/test/ios/wait_util.h" @@ -1152,8 +1152,9 @@ }; TitleObserver observer; - ScopedObserver<WebState, WebStateObserver> scoped_observer(&observer); - scoped_observer.Add(web_state()); + base::ScopedObservation<WebState, WebStateObserver> scoped_observer( + &observer); + scoped_observer.Observe(web_state()); ASSERT_EQ(0, observer.title_change_count()); // Expect TitleWasSet callback after the page is loaded and due to WKWebView
diff --git a/ios/web/web_state/web_state_observer_bridge_unittest.mm b/ios/web/web_state/web_state_observer_bridge_unittest.mm index b3f089e..38d3a12 100644 --- a/ios/web/web_state/web_state_observer_bridge_unittest.mm +++ b/ios/web/web_state/web_state_observer_bridge_unittest.mm
@@ -5,7 +5,7 @@ #import "ios/web/public/web_state_observer_bridge.h" #include "base/memory/ptr_util.h" -#include "base/scoped_observer.h" +#include "base/scoped_observation.h" #import "ios/web/navigation/navigation_context_impl.h" #include "ios/web/public/favicon/favicon_url.h" #import "ios/web/public/test/fakes/crw_fake_web_state_observer.h" @@ -31,16 +31,16 @@ WebStateObserverBridgeTest() : observer_([[CRWFakeWebStateObserver alloc] init]), observer_bridge_(observer_), - scoped_observer_(&observer_bridge_), response_headers_(new net::HttpResponseHeaders( std::string(kRawResponseHeaders, sizeof(kRawResponseHeaders)))) { - scoped_observer_.Add(&fake_web_state_); + scoped_observation_.Observe(&fake_web_state_); } web::FakeWebState fake_web_state_; CRWFakeWebStateObserver* observer_; WebStateObserverBridge observer_bridge_; - ScopedObserver<WebState, WebStateObserver> scoped_observer_; + base::ScopedObservation<WebState, WebStateObserver> scoped_observation_{ + &observer_bridge_}; scoped_refptr<net::HttpResponseHeaders> response_headers_; };
diff --git a/ios/web/web_state/web_state_observer_inttest.mm b/ios/web/web_state/web_state_observer_inttest.mm index 3b2658a..24481844 100644 --- a/ios/web/web_state/web_state_observer_inttest.mm +++ b/ios/web/web_state/web_state_observer_inttest.mm
@@ -11,7 +11,7 @@ #include "base/ios/ios_util.h" #import "base/ios/ns_error_util.h" #include "base/path_service.h" -#include "base/scoped_observer.h" +#include "base/scoped_observation.h" #include "base/strings/sys_string_conversions.h" #include "base/strings/utf_string_conversions.h" #include "base/test/gmock_callback_support.h" @@ -777,13 +777,13 @@ // WebStatePolicyDecider. class WebStateObserverTest : public WebIntTest { public: - WebStateObserverTest() : scoped_observer_(&observer_) {} + WebStateObserverTest() {} void SetUp() override { WebIntTest::SetUp(); decider_ = std::make_unique<StrictMock<PolicyDeciderMock>>(web_state()); - scoped_observer_.Add(web_state()); + scoped_observation_.Observe(web_state()); test_server_ = std::make_unique<EmbeddedTestServer>(); test_server_->RegisterRequestHandler( @@ -799,7 +799,7 @@ } void TearDown() override { - scoped_observer_.RemoveAll(); + scoped_observation_.Reset(); WebIntTest::TearDown(); } @@ -809,7 +809,8 @@ std::unique_ptr<EmbeddedTestServer> test_server_; private: - ScopedObserver<WebState, WebStateObserver> scoped_observer_; + base::ScopedObservation<WebState, WebStateObserver> scoped_observation_{ + &observer_}; ::testing::InSequence callbacks_sequence_checker_; DISALLOW_COPY_AND_ASSIGN(WebStateObserverTest);
diff --git a/media/audio/fuchsia/OWNERS b/media/audio/fuchsia/OWNERS index 3ebcc42..e7034ea 100644 --- a/media/audio/fuchsia/OWNERS +++ b/media/audio/fuchsia/OWNERS
@@ -1 +1 @@ -file://build/fuchsia/OWNERS \ No newline at end of file +file://build/fuchsia/OWNERS
diff --git a/media/capture/BUILD.gn b/media/capture/BUILD.gn index cc13409..e96ba09d 100644 --- a/media/capture/BUILD.gn +++ b/media/capture/BUILD.gn
@@ -329,6 +329,7 @@ deps += [ "//ash/constants", "//build/config/linux/libdrm", + "//chromeos/components/sensors:sensors", "//chromeos/dbus/power", "//components/chromeos_camera:mojo_mjpeg_decode_accelerator", "//components/chromeos_camera/common",
diff --git a/media/capture/video/chromeos/DEPS b/media/capture/video/chromeos/DEPS index db76c2a..170ac6c6 100644 --- a/media/capture/video/chromeos/DEPS +++ b/media/capture/video/chromeos/DEPS
@@ -1,5 +1,6 @@ include_rules = [ "+ash/constants/ash_features.h", + "+chromeos/components/sensors", "+chromeos/dbus", "+components/chromeos_camera", "+third_party/libsync",
diff --git a/media/capture/video/chromeos/camera_hal_dispatcher_impl.cc b/media/capture/video/chromeos/camera_hal_dispatcher_impl.cc index e70ff952..bdba736 100644 --- a/media/capture/video/chromeos/camera_hal_dispatcher_impl.cc +++ b/media/capture/video/chromeos/camera_hal_dispatcher_impl.cc
@@ -23,7 +23,9 @@ #include "base/stl_util.h" #include "base/strings/string_number_conversions.h" #include "base/synchronization/waitable_event.h" +#include "base/threading/sequenced_task_runner_handle.h" #include "base/trace_event/trace_event.h" +#include "chromeos/components/sensors/sensor_util.h" #include "components/device_event_log/device_event_log.h" #include "media/base/bind_to_current_loop.h" #include "media/capture/video/chromeos/mojom/camera_common.mojom.h" @@ -196,6 +198,11 @@ LOG(ERROR) << "Failed to generate token for test client"; return false; } + if (!token_manager_.GenerateServerSensorClientToken()) { + LOG(ERROR) << "Failed to generate authentication token for server as a " + "sensor client"; + } + blocking_io_task_runner_->PostTask( FROM_HERE, base::BindOnce(&CameraHalDispatcherImpl::CreateSocket, @@ -267,6 +274,7 @@ CameraHalDispatcherImpl::CameraHalDispatcherImpl() : proxy_thread_("CameraProxyThread"), blocking_io_thread_("CameraBlockingIOThread"), + main_task_runner_(base::SequencedTaskRunnerHandle::Get()), camera_hal_server_callbacks_(this), active_client_observers_( new base::ObserverListThreadSafe<CameraActiveClientObserver>()), @@ -361,6 +369,20 @@ jea_factory_.Run(std::move(jea_receiver)); } +void CameraHalDispatcherImpl::RegisterSensorClientWithToken( + mojo::PendingRemote<chromeos::sensors::mojom::SensorHalClient> client, + const base::UnguessableToken& auth_token, + RegisterSensorClientWithTokenCallback callback) { + DCHECK(proxy_task_runner_->BelongsToCurrentThread()); + + main_task_runner_->PostTask( + FROM_HERE, + base::BindOnce( + &CameraHalDispatcherImpl::RegisterSensorClientWithTokenOnUIThread, + weak_factory_.GetWeakPtr(), std::move(client), auth_token, + BindToCurrentLoop(std::move(callback)))); +} + void CameraHalDispatcherImpl::CameraDeviceActivityChange( int32_t camera_id, bool opened, @@ -659,6 +681,26 @@ } } +void CameraHalDispatcherImpl::RegisterSensorClientWithTokenOnUIThread( + mojo::PendingRemote<chromeos::sensors::mojom::SensorHalClient> client, + const base::UnguessableToken& auth_token, + RegisterSensorClientWithTokenCallback callback) { + DCHECK(main_task_runner_->RunsTasksInCurrentSequence()); + + if (!token_manager_.AuthenticateServerSensorClient(auth_token)) { + std::move(callback).Run(-EPERM); + return; + } + + if (!chromeos::sensors::BindSensorHalClient(std::move(client))) { + LOG(ERROR) << "Failed to bind SensorHalClient to SensorHalDispatcher"; + std::move(callback).Run(-ENOSYS); + return; + } + + std::move(callback).Run(0); +} + void CameraHalDispatcherImpl::StopOnProxyThread() { DCHECK(proxy_task_runner_->BelongsToCurrentThread()); base::trace_event::TraceLog::GetInstance()->RemoveEnabledStateObserver(this);
diff --git a/media/capture/video/chromeos/camera_hal_dispatcher_impl.h b/media/capture/video/chromeos/camera_hal_dispatcher_impl.h index 57ecc711..e3422a8 100644 --- a/media/capture/video/chromeos/camera_hal_dispatcher_impl.h +++ b/media/capture/video/chromeos/camera_hal_dispatcher_impl.h
@@ -14,6 +14,7 @@ #include "base/files/scoped_file.h" #include "base/memory/scoped_refptr.h" #include "base/memory/singleton.h" +#include "base/memory/weak_ptr.h" #include "base/observer_list_threadsafe.h" #include "base/observer_list_types.h" #include "base/synchronization/lock.h" @@ -113,12 +114,18 @@ // /var/run/camera3.sock. CameraHalServer and CameraHalClients connect to the // unix domain socket to create the initial Mojo connections with the // CameraHalDisptcherImpl, and CameraHalDispatcherImpl then creates and -// dispaches the Mojo channels between CameraHalServer and CameraHalClients to +// dispatches the Mojo channels between CameraHalServer and CameraHalClients to // establish direct Mojo connections between the CameraHalServer and the // CameraHalClients. // // For general documentation about the CameraHalDispater Mojo interface see the // comments in mojo/cros_camera_service.mojom. +// +// On ChromeOS the video capture service must run in the browser process, +// because parts of the code depend on global objects that are only available in +// the Browser process. Therefore, CameraHalDispatcherImpl must run in the +// browser process as well. +// See https://crbug.com/891961. class CAPTURE_EXPORT CameraHalDispatcherImpl final : public cros::mojom::CameraHalDispatcher, public cros::mojom::CameraHalServerCallbacks, @@ -177,6 +184,10 @@ void GetJpegEncodeAccelerator( mojo::PendingReceiver<chromeos_camera::mojom::JpegEncodeAccelerator> jea_receiver) final; + void RegisterSensorClientWithToken( + mojo::PendingRemote<chromeos::sensors::mojom::SensorHalClient> client, + const base::UnguessableToken& auth_token, + RegisterSensorClientWithTokenCallback callback) final; // CameraHalServerCallbacks implementations. void CameraDeviceActivityChange(int32_t camera_id, @@ -229,6 +240,11 @@ void OnCameraHalServerConnectionError(); void OnCameraHalClientConnectionError(CameraClientObserver* client); + void RegisterSensorClientWithTokenOnUIThread( + mojo::PendingRemote<chromeos::sensors::mojom::SensorHalClient> client, + const base::UnguessableToken& auth_token, + RegisterSensorClientWithTokenCallback callback); + void StopOnProxyThread(); void OnTraceLogEnabledOnProxyThread(); @@ -241,6 +257,7 @@ base::Thread proxy_thread_; base::Thread blocking_io_thread_; + scoped_refptr<base::SequencedTaskRunner> main_task_runner_; scoped_refptr<base::SingleThreadTaskRunner> proxy_task_runner_; scoped_refptr<base::SingleThreadTaskRunner> blocking_io_task_runner_; @@ -275,6 +292,8 @@ scoped_refptr<base::ObserverListThreadSafe<CameraPrivacySwitchObserver>> privacy_switch_observers_; + base::WeakPtrFactory<CameraHalDispatcherImpl> weak_factory_{this}; + DISALLOW_COPY_AND_ASSIGN(CameraHalDispatcherImpl); };
diff --git a/media/capture/video/chromeos/mojom/BUILD.gn b/media/capture/video/chromeos/mojom/BUILD.gn index fd3bfa1b..4dfea8a 100644 --- a/media/capture/video/chromeos/mojom/BUILD.gn +++ b/media/capture/video/chromeos/mojom/BUILD.gn
@@ -16,6 +16,7 @@ ] deps = [ + "//chromeos/components/sensors/mojom", "//components/chromeos_camera/common", "//media/capture/mojom:image_capture", "//ui/gfx/geometry/mojom",
diff --git a/media/capture/video/chromeos/mojom/cros_camera_service.mojom b/media/capture/video/chromeos/mojom/cros_camera_service.mojom index ca5eeaa..45c00de 100644 --- a/media/capture/video/chromeos/mojom/cros_camera_service.mojom +++ b/media/capture/video/chromeos/mojom/cros_camera_service.mojom
@@ -2,10 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Next min version: 6 +// Next min version: 7 module cros.mojom; +import "chromeos/components/sensors/mojom/cros_sensor_service.mojom"; import "components/chromeos_camera/common/jpeg_encode_accelerator.mojom"; import "components/chromeos_camera/common/mjpeg_decode_accelerator.mojom"; import "media/capture/video/chromeos/mojom/camera_common.mojom"; @@ -49,7 +50,7 @@ // channel to the server and pass the established Mojo channel to the client in // order to set up a Mojo channel between the client and the server. // -// Next method ID: 6 +// Next method ID: 7 interface CameraHalDispatcher { // [Deprecated in version 4] // A CameraHalServer calls RegisterServer to register itself with the @@ -89,6 +90,13 @@ CameraClientType type, mojo_base.mojom.UnguessableToken auth_token) => (int32 result); + // A SensorHalClient calls RegisterSensorClient to register itself with + // SensorHalDispatcher through CameraHalDispatcher. |auth_token| is used to + // prove the caller has been granted permission to access SensorHalClient. + // CameraHalDispatcher will send back |result| as the errno. + [MinVersion=6] RegisterSensorClientWithToken@6( + pending_remote<chromeos.sensors.mojom.SensorHalClient> client, + mojo_base.mojom.UnguessableToken auth_token) => (int32 result); }; // The CrOS camera HAL v3 Mojo server.
diff --git a/media/capture/video/chromeos/token_manager.cc b/media/capture/video/chromeos/token_manager.cc index 2aec214..90e8f16 100644 --- a/media/capture/video/chromeos/token_manager.cc +++ b/media/capture/video/chromeos/token_manager.cc
@@ -13,6 +13,7 @@ #include "base/files/file_util.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" +#include "chromeos/components/sensors/ash/sensor_hal_dispatcher.h" namespace { @@ -66,6 +67,7 @@ namespace media { constexpr char TokenManager::kServerTokenPath[]; +constexpr char TokenManager::kServerSensorClientTokenPath[]; constexpr char TokenManager::kTestClientTokenPath[]; constexpr std::array<cros::mojom::CameraClientType, 3> TokenManager::kTrustedClientTypes; @@ -78,6 +80,16 @@ return WriteTokenToFile(base::FilePath(kServerTokenPath), server_token_); } +bool TokenManager::GenerateServerSensorClientToken() { + auto* sensor_hal_dispatcher = + chromeos::sensors::SensorHalDispatcher::GetInstance(); + if (!sensor_hal_dispatcher) + return false; + + return WriteTokenToFile(base::FilePath(kServerSensorClientTokenPath), + sensor_hal_dispatcher->GetTokenForTrustedClient()); +} + bool TokenManager::GenerateTestClientToken() { return WriteTokenToFile( base::FilePath(kTestClientTokenPath), @@ -122,6 +134,16 @@ return server_token_ == token; } +bool TokenManager::AuthenticateServerSensorClient( + const base::UnguessableToken& token) { + auto* sensor_hal_dispatcher = + chromeos::sensors::SensorHalDispatcher::GetInstance(); + if (!sensor_hal_dispatcher) + return false; + + return sensor_hal_dispatcher->AuthenticateClient(token); +} + absl::optional<cros::mojom::CameraClientType> TokenManager::AuthenticateClient( cros::mojom::CameraClientType type, const base::UnguessableToken& token) {
diff --git a/media/capture/video/chromeos/token_manager.h b/media/capture/video/chromeos/token_manager.h index 42f7a3e..0508aae 100644 --- a/media/capture/video/chromeos/token_manager.h +++ b/media/capture/video/chromeos/token_manager.h
@@ -20,6 +20,8 @@ class CAPTURE_EXPORT TokenManager { public: static constexpr char kServerTokenPath[] = "/run/camera_tokens/server/token"; + static constexpr char kServerSensorClientTokenPath[] = + "/run/camera_tokens/server/sensor_client_token"; static constexpr char kTestClientTokenPath[] = "/run/camera_tokens/testing/token"; static constexpr std::array<cros::mojom::CameraClientType, 3> @@ -31,6 +33,7 @@ ~TokenManager(); bool GenerateServerToken(); + bool GenerateServerSensorClientToken(); bool GenerateTestClientToken(); @@ -41,6 +44,7 @@ void UnregisterPluginVmToken(const base::UnguessableToken& token); bool AuthenticateServer(const base::UnguessableToken& token); + bool AuthenticateServerSensorClient(const base::UnguessableToken& token); // Authenticates client with the given |type| and |token|. When |type| is // cros::mojom::CameraClientType::UNKNOWN, it tries to figure out the actual
diff --git a/media/filters/fuchsia/OWNERS b/media/filters/fuchsia/OWNERS index 3ebcc42..e7034ea 100644 --- a/media/filters/fuchsia/OWNERS +++ b/media/filters/fuchsia/OWNERS
@@ -1 +1 @@ -file://build/fuchsia/OWNERS \ No newline at end of file +file://build/fuchsia/OWNERS
diff --git a/media/filters/fuchsia/fuchsia_video_decoder.cc b/media/filters/fuchsia/fuchsia_video_decoder.cc index e5397b82..fc109b9 100644 --- a/media/filters/fuchsia/fuchsia_video_decoder.cc +++ b/media/filters/fuchsia/fuchsia_video_decoder.cc
@@ -6,10 +6,8 @@ #include <fuchsia/media/cpp/fidl.h> #include <fuchsia/mediacodec/cpp/fidl.h> -#include <fuchsia/sysmem/cpp/fidl.h> #include <lib/sys/cpp/component_context.h> #include <vulkan/vulkan.h> -#include <zircon/rights.h> #include "base/bind.h" #include "base/bits.h" @@ -31,7 +29,6 @@ #include "gpu/ipc/common/gpu_memory_buffer_impl_native_pixmap.h" #include "media/base/bind_to_current_loop.h" #include "media/base/cdm_context.h" -#include "media/base/decryptor.h" #include "media/base/media_switches.h" #include "media/base/video_decoder.h" #include "media/base/video_decoder_config.h" @@ -40,9 +37,10 @@ #include "media/fuchsia/cdm/fuchsia_cdm_context.h" #include "media/fuchsia/cdm/fuchsia_decryptor.h" #include "media/fuchsia/cdm/fuchsia_stream_decryptor.h" +#include "media/fuchsia/common/decrypting_sysmem_buffer_stream.h" +#include "media/fuchsia/common/passthrough_sysmem_buffer_stream.h" #include "media/fuchsia/common/stream_processor_helper.h" #include "media/fuchsia/common/sysmem_client.h" -#include "media/fuchsia/common/vmo_buffer_writer_queue.h" #include "third_party/libyuv/include/libyuv/video_common.h" #include "ui/gfx/buffer_types.h" #include "ui/gfx/client_native_pixmap_factory.h" @@ -63,8 +61,10 @@ // on time. constexpr uint32_t kMaxUsedOutputBuffers = 5; -// Use 2 buffers for decoder input. Limiting total number of buffers to 2 allows -// to minimize required memory without significant effect on performance. +// Use 2 buffers for decoder input. Allocating more than one buffers ensures +// that when the decoder is done working on one packet it will have another one +// waiting in the queue. Limiting number of buffers to 2 allows to minimize +// required memory, without significant effect on performance. constexpr size_t kNumInputBuffers = 2; // Some codecs do not support splitting video frames across multiple input @@ -74,10 +74,6 @@ // codecs, not just H264). constexpr size_t kInputBufferSize = 1920 * 1080 * 3 / 2 / 2 + 128 * 1024; -// Input buffers are allocate once per decoder, the |buffer_lifetime_ordinal| is -// always the same. -constexpr uint64_t kInputBufferLifetimeOrdinal = 1; - // Helper used to hold mailboxes for the output textures. OutputMailbox may // outlive FuchsiaVideoDecoder if is referenced by a VideoFrame. class OutputMailbox { @@ -190,13 +186,17 @@ } // namespace class FuchsiaVideoDecoder : public VideoDecoder, - public FuchsiaSecureStreamDecryptor::Client { + public SysmemBufferStream::Sink, + public StreamProcessorHelper::Client { public: FuchsiaVideoDecoder( scoped_refptr<viz::RasterContextProvider> raster_context_provider, bool enable_sw_decoding); ~FuchsiaVideoDecoder() override; + FuchsiaVideoDecoder(const FuchsiaVideoDecoder&) = delete; + FuchsiaVideoDecoder& operator=(const FuchsiaVideoDecoder&) = delete; + // Decoder implementation. bool IsPlatformDecoder() const override; bool SupportsDecryption() const override; @@ -216,29 +216,33 @@ int GetMaxDecodeRequests() const override; private: - bool InitializeDecryptor(CdmContext* cdm_context); + StatusCode InitializeSysmemBufferStream(bool is_encrypted, + CdmContext* cdm_context, + bool* secure_mode); - // FuchsiaSecureStreamDecryptor::Client implementation. - size_t GetInputBufferSize() override; - void OnDecryptorOutputPacket(StreamProcessorHelper::IoPacket packet) override; - void OnDecryptorEndOfStreamPacket() override; - void OnDecryptorError() override; - void OnDecryptorNoKey() override; + // SysmemBufferStream::Sink implementation. + void OnSysmemBufferStreamBufferCollectionToken( + fuchsia::sysmem::BufferCollectionTokenPtr token) override; + void OnSysmemBufferStreamOutputPacket( + StreamProcessorHelper::IoPacket packet) override; + void OnSysmemBufferStreamEndOfStream() override; + void OnSysmemBufferStreamError() override; + void OnSysmemBufferStreamNoKey() override; - // Event handlers for |decoder_|. - void OnStreamFailed(uint64_t stream_lifetime_ordinal, - fuchsia::media::StreamError error); - void OnFreeInputPacket(fuchsia::media::PacketHeader free_input_packet); - void OnOutputConstraints( - fuchsia::media::StreamOutputConstraints output_constraints); - void OnOutputFormat(fuchsia::media::StreamOutputFormat output_format); - void OnOutputPacket(fuchsia::media::Packet output_packet, - bool error_detected_before, - bool error_detected_during); - void OnOutputEndOfStream(uint64_t stream_lifetime_ordinal, - bool error_detected_before); + // StreamProcessorHelper::Client implementation. + void OnStreamProcessorAllocateOutputBuffers( + const fuchsia::media::StreamBufferConstraints& stream_constraints) + override; + void OnStreamProcessorEndOfStream() override; + void OnStreamProcessorOutputFormat( + fuchsia::media::StreamOutputFormat format) override; + void OnStreamProcessorOutputPacket( + StreamProcessorHelper::IoPacket packet) override; + void OnStreamProcessorNoKey() override; + void OnStreamProcessorError() override; - void AllocateInputBuffers(); + // Calls next callback in the |decode_callbacks_| queue. + void CallNextDecodeCallback(); // Drops all pending input buffers and then calls all pending DecodeCB with // |status|. Returns true if the decoder still exists. @@ -247,32 +251,15 @@ // Called on errors to shutdown the decoder and notify the client. void OnError(); - // Callback for |input_buffer_collection_->GetSharedToken()|. - void SetInputBufferCollection( + // Callback for SysmemBufferCollection::CreateSharedToken(), used to send the + // sysmem buffer collection token to the GPU process. + void SetBufferCollectionTokenForGpu( fuchsia::sysmem::BufferCollectionTokenPtr token); - // Callback for |input_buffer_collection_->AcquireBuffers()|. - void OnInputBuffersAcquired( - std::vector<VmoBuffer> buffers, - const fuchsia::sysmem::SingleBufferSettings& buffer_settings); + // Called by OutputMailbox to signal that the output buffer can be reused. + void ReleaseOutputPacket(StreamProcessorHelper::IoPacket packet); - // Callbacks for |input_writer_|. - void SendInputPacket(const DecoderBuffer* buffer, - StreamProcessorHelper::IoPacket packet); - void ProcessEndOfStream(); - - // Called by OnOutputConstraints() to initialize input buffers. - void InitializeOutputBufferCollection( - fuchsia::media::StreamBufferConstraints constraints, - fuchsia::sysmem::BufferCollectionTokenPtr collection_token_for_codec, - fuchsia::sysmem::BufferCollectionTokenPtr collection_token_for_gpu); - - // Called by OutputMailbox to signal that the mailbox and buffer can be - // reused. - void OnReuseMailbox(uint32_t buffer_index, uint32_t packet_index); - - // Releases BufferCollections used for input or output buffers if any. - void ReleaseInputBuffers(); + // Releases BufferCollection used for output buffers if any. void ReleaseOutputBuffers(); const scoped_refptr<viz::RasterContextProvider> raster_context_provider_; @@ -286,50 +273,39 @@ // value is used only if the aspect ratio is not specified in the bitstream. float container_pixel_aspect_ratio_ = 1.0; - // Decryptor is allocated only for encrypted streams. - std::unique_ptr<FuchsiaSecureStreamDecryptor> decryptor_; + std::unique_ptr<SysmemBufferStream> sysmem_buffer_stream_; - VideoCodec current_codec_ = kUnknownVideoCodec; + size_t max_decoder_requests_ = kNumInputBuffers + 1; - // TODO(crbug.com/1131175): Use StreamProcessorHelper. - fuchsia::media::StreamProcessorPtr decoder_; + VideoDecoderConfig current_config_; - absl::optional<fuchsia::media::StreamBufferConstraints> - decoder_input_constraints_; + std::unique_ptr<StreamProcessorHelper> decoder_; SysmemAllocatorClient sysmem_allocator_; std::unique_ptr<gfx::ClientNativePixmapFactory> client_native_pixmap_factory_; - uint64_t stream_lifetime_ordinal_ = 1; - - // Set to true if we've sent an input packet with the current - // stream_lifetime_ordinal_. - bool active_stream_ = false; - // Callbacks for pending Decode() request. std::deque<DecodeCB> decode_callbacks_; - // Buffer queue for |decoder_|. Used only for clear streams, i.e. when there - // is no |decryptor_|. - VmoBufferWriterQueue input_writer_queue_; - // Input buffers for |decoder_|. std::unique_ptr<SysmemCollectionClient> input_buffer_collection_; - base::flat_map<size_t, InputDecoderPacket> in_flight_input_packets_; // Output buffers for |decoder_|. fuchsia::media::VideoUncompressedFormat output_format_; - uint64_t output_buffer_lifetime_ordinal_ = 1; - fuchsia::sysmem::BufferCollectionPtr output_buffer_collection_; + std::unique_ptr<SysmemCollectionClient> output_buffer_collection_; gfx::SysmemBufferCollectionId output_buffer_collection_id_; std::vector<OutputMailbox*> output_mailboxes_; size_t num_used_output_buffers_ = 0; base::WeakPtr<FuchsiaVideoDecoder> weak_this_; - base::WeakPtrFactory<FuchsiaVideoDecoder> weak_factory_; + base::WeakPtrFactory<FuchsiaVideoDecoder> weak_factory_{this}; - DISALLOW_COPY_AND_ASSIGN(FuchsiaVideoDecoder); + // WeakPtrFactory used to schedule CallNextDecodeCallbacks(). These pointers + // are discarded in DropInputQueue() in order to avoid calling + // Decode() callback when the decoder queue is discarded. + base::WeakPtrFactory<FuchsiaVideoDecoder> decode_callbacks_weak_factory_{ + this}; }; FuchsiaVideoDecoder::FuchsiaVideoDecoder( @@ -340,16 +316,17 @@ use_overlays_for_video_(base::CommandLine::ForCurrentProcess()->HasSwitch( switches::kUseOverlaysForVideo)), sysmem_allocator_("CrFuchsiaVideoDecoder"), - client_native_pixmap_factory_(ui::CreateClientNativePixmapFactoryOzone()), - weak_factory_(this) { + client_native_pixmap_factory_( + ui::CreateClientNativePixmapFactoryOzone()) { DCHECK(raster_context_provider_); weak_this_ = weak_factory_.GetWeakPtr(); } FuchsiaVideoDecoder::~FuchsiaVideoDecoder() { - // Call ReleaseInputBuffers() to make sure the corresponding fields are - // destroyed in the right order. - ReleaseInputBuffers(); + // Reset SysmemBufferStream to ensure it doesn't try to send new packets when + // the |decoder_| is destroyed. + sysmem_buffer_stream_.reset(); + decoder_.reset(); // Release mailboxes used for output frames. ReleaseOutputBuffers(); @@ -389,25 +366,25 @@ container_pixel_aspect_ratio_ = config.GetPixelAspectRatio(); // Keep decoder and decryptor if the configuration hasn't changed. - bool have_decryptor = decryptor_ != nullptr; - if (decoder_ && current_codec_ == config.codec() && - have_decryptor == config.is_encrypted()) { + if (decoder_ && current_config_.is_encrypted() == config.codec() && + current_config_.is_encrypted() == config.is_encrypted()) { std::move(done_callback).Run(OkStatus()); return; } - decryptor_.reset(); - decoder_.Unbind(); + sysmem_buffer_stream_.reset(); + decoder_.reset(); - // Initialize decryptor for encrypted streams. - if (config.is_encrypted() && !InitializeDecryptor(cdm_context)) { - std::move(done_callback) - .Run(StatusCode::kDecoderMissingCdmForEncryptedContent); + // Initialize the stream. + bool secure_mode = false; + StatusCode status = InitializeSysmemBufferStream(config.is_encrypted(), + cdm_context, &secure_mode); + if (status != StatusCode::kOk) { + std::move(done_callback).Run(StatusCode::kOk); return; } - // Reset IO buffers since we won't be able to re-use them. - ReleaseInputBuffers(); + // Reset output buffers since we won't be able to re-use them. ReleaseOutputBuffers(); fuchsia::mediacodec::CreateDecoder_Params decoder_params; @@ -435,18 +412,15 @@ return; } - if (base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kEnableProtectedVideoBuffers)) { - if (decryptor_) { - decoder_params.set_secure_input_mode( - fuchsia::mediacodec::SecureMemoryMode::ON); - } + if (secure_mode) { + decoder_params.set_secure_input_mode( + fuchsia::mediacodec::SecureMemoryMode::ON); + } - if (decryptor_ || base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kForceProtectedVideoOutputBuffers)) { - decoder_params.set_secure_output_mode( - fuchsia::mediacodec::SecureMemoryMode::ON); - } + if (secure_mode || base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kForceProtectedVideoOutputBuffers)) { + decoder_params.set_secure_output_mode( + fuchsia::mediacodec::SecureMemoryMode::ON); } decoder_params.set_promise_separate_access_units_on_input(true); @@ -455,32 +429,12 @@ auto decoder_factory = base::ComponentContextForProcess() ->svc() ->Connect<fuchsia::mediacodec::CodecFactory>(); + fuchsia::media::StreamProcessorPtr decoder; decoder_factory->CreateDecoder(std::move(decoder_params), - decoder_.NewRequest()); + decoder.NewRequest()); + decoder_ = std::make_unique<StreamProcessorHelper>(std::move(decoder), this); - decoder_.set_error_handler([this](zx_status_t status) { - ZX_LOG(ERROR, status) << "fuchsia.media.StreamProcessor disconnected."; - OnError(); - }); - - decoder_.events().OnStreamFailed = - fit::bind_member(this, &FuchsiaVideoDecoder::OnStreamFailed); - decoder_.events().OnFreeInputPacket = - fit::bind_member(this, &FuchsiaVideoDecoder::OnFreeInputPacket); - decoder_.events().OnOutputConstraints = - fit::bind_member(this, &FuchsiaVideoDecoder::OnOutputConstraints); - decoder_.events().OnOutputFormat = - fit::bind_member(this, &FuchsiaVideoDecoder::OnOutputFormat); - decoder_.events().OnOutputPacket = - fit::bind_member(this, &FuchsiaVideoDecoder::OnOutputPacket); - decoder_.events().OnOutputEndOfStream = - fit::bind_member(this, &FuchsiaVideoDecoder::OnOutputEndOfStream); - - decoder_->EnableOnStreamFailed(); - - AllocateInputBuffers(); - - current_codec_ = config.codec(); + current_config_ = config; std::move(done_callback).Run(OkStatus()); } @@ -498,11 +452,7 @@ decode_callbacks_.push_back(std::move(decode_cb)); - if (decryptor_) { - decryptor_->Decrypt(std::move(buffer)); - } else { - input_writer_queue_.EnqueueBuffer(buffer); - } + sysmem_buffer_stream_->EnqueueBuffer(std::move(buffer)); } void FuchsiaVideoDecoder::Reset(base::OnceClosure closure) { @@ -520,276 +470,113 @@ } int FuchsiaVideoDecoder::GetMaxDecodeRequests() const { - if (!decryptor_) { - // Add one extra request to be able to send a new InputBuffer immediately - // after OnFreeInputPacket(). - return input_writer_queue_.num_buffers() + 1; - } - - // For encrypted streams we need enough decode requests to fill the - // decryptor's queue and all decoder buffers. Add one extra same as above. - return decryptor_->GetMaxDecryptRequests() + kNumInputBuffers + 1; + return max_decoder_requests_; } -bool FuchsiaVideoDecoder::InitializeDecryptor(CdmContext* cdm_context) { - DCHECK(!decryptor_); +StatusCode FuchsiaVideoDecoder::InitializeSysmemBufferStream( + bool is_encrypted, + CdmContext* cdm_context, + bool* out_secure_mode) { + DCHECK(!sysmem_buffer_stream_); - // Caller makes sure |cdm_context| is available if the stream is encrypted. - if (!cdm_context) { - DLOG(ERROR) << "No cdm context for encrypted stream."; - return false; + *out_secure_mode = false; + + // By default queue as many decode requests as the input buffers available + // with one extra request to be able to send a new InputBuffer immediately. + max_decoder_requests_ = kNumInputBuffers + 1; + + if (is_encrypted) { + // Caller makes sure |cdm_context| is available if the stream is encrypted. + if (!cdm_context) { + DLOG(ERROR) << "No cdm context for encrypted stream."; + return StatusCode::kDecoderMissingCdmForEncryptedContent; + } + + // Use FuchsiaStreamDecryptor with FuchsiaCdm (it doesn't support + // media::Decryptor interface). Otherwise (e.g. for ClearKey CDM) use + // DecryptingSysmemBufferStream. + FuchsiaCdmContext* fuchsia_cdm = cdm_context->GetFuchsiaCdmContext(); + if (fuchsia_cdm) { + *out_secure_mode = base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kEnableProtectedVideoBuffers); + sysmem_buffer_stream_ = + fuchsia_cdm->CreateStreamDecryptor(*out_secure_mode); + + // For optimal performance allow more requests to fill the decryptor + // queue. + max_decoder_requests_ += FuchsiaStreamDecryptor::kInputBufferCount; + } else { + sysmem_buffer_stream_ = std::make_unique<DecryptingSysmemBufferStream>( + &sysmem_allocator_, cdm_context, Decryptor::kVideo); + } + } else { + sysmem_buffer_stream_ = + std::make_unique<PassthroughSysmemBufferStream>(&sysmem_allocator_); } - // If Cdm is not FuchsiaCdm then fail initialization to allow decoder - // selector to choose DecryptingDemuxerStream, which will handle the - // decryption and pass the clear stream to this decoder. - FuchsiaCdmContext* fuchsia_cdm = cdm_context->GetFuchsiaCdmContext(); - if (!fuchsia_cdm) { - DLOG(ERROR) << "FuchsiaVideoDecoder is compatible only with Fuchsia CDM."; - return false; - } + sysmem_buffer_stream_->Initialize(this, kInputBufferSize, kNumInputBuffers); - decryptor_ = fuchsia_cdm->CreateVideoDecryptor(this); - - return true; + return StatusCode::kOk; } -size_t FuchsiaVideoDecoder::GetInputBufferSize() { - return kInputBufferSize; +void FuchsiaVideoDecoder::OnSysmemBufferStreamBufferCollectionToken( + fuchsia::sysmem::BufferCollectionTokenPtr token) { + DCHECK(decoder_); + decoder_->SetInputBufferCollectionToken(std::move(token)); } -void FuchsiaVideoDecoder::OnDecryptorOutputPacket( +void FuchsiaVideoDecoder::OnSysmemBufferStreamOutputPacket( StreamProcessorHelper::IoPacket packet) { - SendInputPacket(nullptr, std::move(packet)); + packet.AddOnDestroyClosure( + base::BindOnce(&FuchsiaVideoDecoder::CallNextDecodeCallback, + decode_callbacks_weak_factory_.GetWeakPtr())); + decoder_->Process(std::move(packet)); } -void FuchsiaVideoDecoder::OnDecryptorEndOfStreamPacket() { - ProcessEndOfStream(); +void FuchsiaVideoDecoder::OnSysmemBufferStreamEndOfStream() { + decoder_->ProcessEos(); } -void FuchsiaVideoDecoder::OnDecryptorError() { +void FuchsiaVideoDecoder::OnSysmemBufferStreamError() { OnError(); } -void FuchsiaVideoDecoder::OnDecryptorNoKey() { +void FuchsiaVideoDecoder::OnSysmemBufferStreamNoKey() { waiting_cb_.Run(WaitingReason::kNoDecryptionKey); } -void FuchsiaVideoDecoder::OnStreamFailed(uint64_t stream_lifetime_ordinal, - fuchsia::media::StreamError error) { - if (stream_lifetime_ordinal_ != stream_lifetime_ordinal) { - return; - } - - OnError(); -} - -void FuchsiaVideoDecoder::AllocateInputBuffers() { - DCHECK(!input_buffer_collection_); - - input_buffer_collection_ = sysmem_allocator_.AllocateNewCollection(); - input_buffer_collection_->CreateSharedToken(base::BindOnce( - &FuchsiaVideoDecoder::SetInputBufferCollection, base::Unretained(this))); - if (decryptor_) { - input_buffer_collection_->CreateSharedToken(base::BindOnce( - &FuchsiaSecureStreamDecryptor::SetOutputBufferCollectionToken, - base::Unretained(decryptor_.get()))); - } - - // Create buffer constraints for the input buffer collection. - fuchsia::sysmem::BufferCollectionConstraints buffer_constraints; - if (decryptor_) { - buffer_constraints.usage.none = fuchsia::sysmem::noneUsage; - buffer_constraints.min_buffer_count = kNumInputBuffers; - buffer_constraints.has_buffer_memory_constraints = true; - buffer_constraints.buffer_memory_constraints.min_size_bytes = - kInputBufferSize; - buffer_constraints.buffer_memory_constraints.ram_domain_supported = true; - buffer_constraints.buffer_memory_constraints.cpu_domain_supported = true; - buffer_constraints.buffer_memory_constraints.inaccessible_domain_supported = - true; - } else { - buffer_constraints = VmoBuffer::GetRecommendedConstraints( - kNumInputBuffers, kInputBufferSize, /*writable=*/true); - } - - input_buffer_collection_->Initialize(std::move(buffer_constraints), - "CrVideoDecoderInput"); - - if (!decryptor_) { - input_buffer_collection_->AcquireBuffers(base::BindOnce( - &FuchsiaVideoDecoder::OnInputBuffersAcquired, base::Unretained(this))); - } -} - -void FuchsiaVideoDecoder::SetInputBufferCollection( - fuchsia::sysmem::BufferCollectionTokenPtr token) { - fuchsia::media::StreamBufferPartialSettings settings; - settings.set_buffer_lifetime_ordinal(kInputBufferLifetimeOrdinal); - settings.set_buffer_constraints_version_ordinal(0); - settings.set_sysmem_token(std::move(token)); - decoder_->SetInputBufferPartialSettings(std::move(settings)); -} - -void FuchsiaVideoDecoder::OnInputBuffersAcquired( - std::vector<VmoBuffer> buffers, - const fuchsia::sysmem::SingleBufferSettings& buffer_settings) { - if (buffers.empty()) { - OnError(); - return; - } - - input_writer_queue_.Start( - std::move(buffers), - base::BindRepeating(&FuchsiaVideoDecoder::SendInputPacket, - base::Unretained(this)), - base::BindRepeating(&FuchsiaVideoDecoder::ProcessEndOfStream, - base::Unretained(this))); -} - -void FuchsiaVideoDecoder::SendInputPacket( - const DecoderBuffer* buffer, - StreamProcessorHelper::IoPacket packet) { - fuchsia::media::Packet media_packet; - media_packet.mutable_header()->set_buffer_lifetime_ordinal( - kInputBufferLifetimeOrdinal); - media_packet.mutable_header()->set_packet_index(packet.buffer_index()); - media_packet.set_buffer_index(packet.buffer_index()); - media_packet.set_timestamp_ish(packet.timestamp().InNanoseconds()); - media_packet.set_stream_lifetime_ordinal(stream_lifetime_ordinal_); - media_packet.set_start_offset(packet.offset()); - media_packet.set_valid_length_bytes(packet.size()); - media_packet.set_known_end_access_unit(packet.unit_end()); - decoder_->QueueInputPacket(std::move(media_packet)); - - active_stream_ = true; - - DCHECK(in_flight_input_packets_.find(packet.buffer_index()) == - in_flight_input_packets_.end()); - const size_t buffer_index = packet.buffer_index(); - in_flight_input_packets_.insert_or_assign( - buffer_index, InputDecoderPacket{std::move(packet)}); -} - -void FuchsiaVideoDecoder::ProcessEndOfStream() { - active_stream_ = true; - decoder_->QueueInputEndOfStream(stream_lifetime_ordinal_); - decoder_->FlushEndOfStreamAndCloseStream(stream_lifetime_ordinal_); -} - -void FuchsiaVideoDecoder::OnFreeInputPacket( - fuchsia::media::PacketHeader free_input_packet) { - if (!free_input_packet.has_packet_index()) { - DLOG(ERROR) << "Received OnFreeInputPacket() with missing required fields."; - OnError(); - return; - } - - auto it = in_flight_input_packets_.find(free_input_packet.packet_index()); - if (it == in_flight_input_packets_.end()) { - DLOG(ERROR) << "Received OnFreeInputPacket() with invalid packet index."; - OnError(); - return; - } - - // Call DecodeCB if this was a last packet for a Decode() request. Ignore - // packets from a previous stream. - bool call_decode_callback = - it->second.packet.unit_end() && it->second.used_for_current_stream; - - { - // The packet should be destroyed only after it's removed from - // |in_flight_input_packets_|. Otherwise VmoBufferWriter may call - // SendInputPacket() while the packet is still in - // |in_flight_input_packets_|. - auto packet = std::move(it->second.packet); - in_flight_input_packets_.erase(it); - } - - if (call_decode_callback) { - DCHECK(!decode_callbacks_.empty()); - std::move(decode_callbacks_.front()).Run(DecodeStatus::OK); - decode_callbacks_.pop_front(); - } -} - -void FuchsiaVideoDecoder::OnOutputConstraints( - fuchsia::media::StreamOutputConstraints output_constraints) { - if (!output_constraints.has_stream_lifetime_ordinal()) { - DLOG(ERROR) - << "Received OnOutputConstraints() with missing required fields."; - OnError(); - return; - } - - if (output_constraints.stream_lifetime_ordinal() != - stream_lifetime_ordinal_) { - return; - } - - if (!output_constraints.has_buffer_constraints_action_required() || - !output_constraints.buffer_constraints_action_required()) { - return; - } - +void FuchsiaVideoDecoder::OnStreamProcessorAllocateOutputBuffers( + const fuchsia::media::StreamBufferConstraints& output_constraints) { ReleaseOutputBuffers(); - // mediacodec API expects odd buffer lifetime ordinal, which is incremented by - // 2 for each buffer generation. - output_buffer_lifetime_ordinal_ += 2; + output_buffer_collection_ = sysmem_allocator_.AllocateNewCollection(); - // Create a new sysmem buffer collection token for the output buffers. - fuchsia::sysmem::BufferCollectionTokenPtr collection_token; - sysmem_allocator_.raw()->AllocateSharedCollection( - collection_token.NewRequest()); - collection_token->SetName(100u, "ChromiumVideoDecoderOutput"); - collection_token->SetDebugClientInfo("chromium_video_decoder", 0u); + output_buffer_collection_->CreateSharedToken( + base::BindOnce(&StreamProcessorHelper::CompleteOutputBuffersAllocation, + base::Unretained(decoder_.get())), + "codec"); + output_buffer_collection_->CreateSharedToken( + base::BindOnce(&FuchsiaVideoDecoder::SetBufferCollectionTokenForGpu, + base::Unretained(this)), + "gpu"); - // Create sysmem tokens for the gpu process and the codec. - fuchsia::sysmem::BufferCollectionTokenPtr collection_token_for_codec; - collection_token->Duplicate(ZX_RIGHT_SAME_RIGHTS, - collection_token_for_codec.NewRequest()); - collection_token_for_codec->SetDebugClientInfo("codec", 0u); - fuchsia::sysmem::BufferCollectionTokenPtr collection_token_for_gpu; - collection_token->Duplicate(ZX_RIGHT_SAME_RIGHTS, - collection_token_for_gpu.NewRequest()); - collection_token_for_gpu->SetDebugClientInfo("chromium_gpu", 0u); - - // Convert the token to a BufferCollection connection. - sysmem_allocator_.raw()->BindSharedCollection( - std::move(collection_token), output_buffer_collection_.NewRequest()); - output_buffer_collection_.set_error_handler([this](zx_status_t status) { - ZX_LOG(ERROR, status) << "fuchsia.sysmem.BufferCollection disconnected."; - OnError(); - }); - - // BufferCollection needs to be synchronized before we can use it. - output_buffer_collection_->Sync( - [this, - buffer_constraints = std::move( - std::move(*output_constraints.mutable_buffer_constraints())), - collection_token_for_codec = std::move(collection_token_for_codec), - collection_token_for_gpu = - std::move(collection_token_for_gpu)]() mutable { - InitializeOutputBufferCollection(std::move(buffer_constraints), - std::move(collection_token_for_codec), - std::move(collection_token_for_gpu)); - }); + fuchsia::sysmem::BufferCollectionConstraints buffer_constraints; + buffer_constraints.usage.none = fuchsia::sysmem::noneUsage; + buffer_constraints.min_buffer_count_for_camping = kOutputBuffersForCamping; + buffer_constraints.min_buffer_count_for_shared_slack = + kMaxUsedOutputBuffers - kOutputBuffersForCamping; + output_buffer_collection_->Initialize(std::move(buffer_constraints), + "ChromiumVideoDecoderOutput"); } -void FuchsiaVideoDecoder::OnOutputFormat( +void FuchsiaVideoDecoder::OnStreamProcessorEndOfStream() { + // Decode() is not supposed to be called again after EOF. + DCHECK_EQ(decode_callbacks_.size(), 1U); + CallNextDecodeCallback(); +} + +void FuchsiaVideoDecoder::OnStreamProcessorOutputFormat( fuchsia::media::StreamOutputFormat output_format) { - if (!output_format.has_stream_lifetime_ordinal() || - !output_format.has_format_details()) { - DLOG(ERROR) << "Received OnOutputFormat() with missing required fields."; - OnError(); - return; - } - - if (output_format.stream_lifetime_ordinal() != stream_lifetime_ordinal_) { - return; - } - auto* format = output_format.mutable_format_details(); if (!format->has_domain() || !format->domain().is_video() || !format->domain().video().is_uncompressed()) { @@ -801,27 +588,8 @@ output_format_ = std::move(format->mutable_domain()->video().uncompressed()); } -void FuchsiaVideoDecoder::OnOutputPacket(fuchsia::media::Packet output_packet, - bool error_detected_before, - bool error_detected_during) { - if (!output_packet.has_header() || - !output_packet.header().has_buffer_lifetime_ordinal() || - !output_packet.header().has_packet_index() || - !output_packet.has_buffer_index()) { - DLOG(ERROR) << "Received OnOutputPacket() with missing required fields."; - OnError(); - return; - } - - if (output_packet.stream_lifetime_ordinal() != stream_lifetime_ordinal_) { - return; - } - - if (output_packet.header().buffer_lifetime_ordinal() != - output_buffer_lifetime_ordinal_) { - return; - } - +void FuchsiaVideoDecoder::OnStreamProcessorOutputPacket( + StreamProcessorHelper::IoPacket output_packet) { fuchsia::sysmem::PixelFormatType sysmem_pixel_format = output_format_.image_format.pixel_format.type; @@ -888,26 +656,24 @@ pixel_aspect_ratio = container_pixel_aspect_ratio_; } + auto timestamp = output_packet.timestamp(); + // SendInputPacket() sets timestamp for all packets sent to the decoder, so we // expect to receive timestamp for all decoded frames. Missing timestamp // indicates a bug in the decoder implementation. - if (!output_packet.has_timestamp_ish()) { + if (timestamp == kNoTimestamp) { LOG(ERROR) << "Received frame without timestamp."; OnError(); return; } - base::TimeDelta timestamp = - base::TimeDelta::FromNanoseconds(output_packet.timestamp_ish()); - num_used_output_buffers_++; auto frame = output_mailboxes_[buffer_index]->CreateFrame( pixel_format, coded_size, display_rect, GetNaturalSize(display_rect, pixel_aspect_ratio), timestamp, - base::BindOnce(&FuchsiaVideoDecoder::OnReuseMailbox, - base::Unretained(this), buffer_index, - output_packet.header().packet_index())); + base::BindOnce(&FuchsiaVideoDecoder::ReleaseOutputPacket, + base::Unretained(this), std::move(output_packet))); // Currently sysmem doesn't specify location of chroma samples relative to // luma (see fxb/13677). Assume they are cosited with luma. YCbCr info here @@ -934,41 +700,36 @@ output_cb_.Run(std::move(frame)); } -void FuchsiaVideoDecoder::OnOutputEndOfStream(uint64_t stream_lifetime_ordinal, - bool error_detected_before) { - if (stream_lifetime_ordinal != stream_lifetime_ordinal_) { - return; - } +void FuchsiaVideoDecoder::OnStreamProcessorNoKey() { + // Decoder is not expected to produce NoKey() error. + DLOG(ERROR) << "Video decoder failed with DECRYPTOR_NO_KEY expectedly"; + OnError(); +} - stream_lifetime_ordinal_ += 2; - active_stream_ = false; +void FuchsiaVideoDecoder::OnStreamProcessorError() { + OnError(); +} - // Decode() is not supposed to be called after EOF. - DCHECK_EQ(decode_callbacks_.size(), 1U); - auto flush_cb = std::move(decode_callbacks_.front()); +void FuchsiaVideoDecoder::CallNextDecodeCallback() { + DCHECK(!decode_callbacks_.empty()); + auto cb = std::move(decode_callbacks_.front()); decode_callbacks_.pop_front(); - std::move(flush_cb).Run(DecodeStatus::OK); + std::move(cb).Run(DecodeStatus::OK); } bool FuchsiaVideoDecoder::DropInputQueue(DecodeStatus status) { - input_writer_queue_.ResetQueue(); + // Invalidate callbacks for CallNextDecodeCallback(), so the callbacks are not + // called when the |decoder_| is dropped below. The callbacks are called + // explicitly later. + decode_callbacks_weak_factory_.InvalidateWeakPtrs(); - if (active_stream_) { - if (decoder_) { - decoder_->CloseCurrentStream(stream_lifetime_ordinal_, - /*release_input_buffers=*/false, - /*release_output_buffers=*/false); - } - stream_lifetime_ordinal_ += 2; - active_stream_ = false; + if (decoder_) { + decoder_->Reset(); } - if (decryptor_) - decryptor_->Reset(); - - for (auto& packet : in_flight_input_packets_) { - packet.second.used_for_current_stream = false; + if (sysmem_buffer_stream_) { + sysmem_buffer_stream_->Reset(); } auto weak_this = weak_this_; @@ -986,68 +747,35 @@ } void FuchsiaVideoDecoder::OnError() { - decoder_.Unbind(); - decryptor_.reset(); + sysmem_buffer_stream_.reset(); + decoder_.reset(); - ReleaseInputBuffers(); ReleaseOutputBuffers(); DropInputQueue(DecodeStatus::DECODE_ERROR); } -void FuchsiaVideoDecoder::InitializeOutputBufferCollection( - fuchsia::media::StreamBufferConstraints constraints, - fuchsia::sysmem::BufferCollectionTokenPtr collection_token_for_codec, - fuchsia::sysmem::BufferCollectionTokenPtr collection_token_for_gpu) { - fuchsia::sysmem::BufferCollectionConstraints buffer_constraints; - buffer_constraints.usage.none = fuchsia::sysmem::noneUsage; - buffer_constraints.min_buffer_count_for_camping = kOutputBuffersForCamping; - buffer_constraints.min_buffer_count_for_shared_slack = - kMaxUsedOutputBuffers - kOutputBuffersForCamping; - output_buffer_collection_->SetConstraints( - /*has_constraints=*/true, std::move(buffer_constraints)); - +void FuchsiaVideoDecoder::SetBufferCollectionTokenForGpu( + fuchsia::sysmem::BufferCollectionTokenPtr token) { // Register the new collection with the GPU process. DCHECK(!output_buffer_collection_id_); output_buffer_collection_id_ = gfx::SysmemBufferCollectionId::Create(); raster_context_provider_->SharedImageInterface() ->RegisterSysmemBufferCollection( - output_buffer_collection_id_, - collection_token_for_gpu.Unbind().TakeChannel(), + output_buffer_collection_id_, token.Unbind().TakeChannel(), gfx::BufferFormat::YUV_420_BIPLANAR, gfx::BufferUsage::GPU_READ, use_overlays_for_video_ /*register_with_image_pipe*/); - // Pass new output buffer settings to the codec. - fuchsia::media::StreamBufferPartialSettings settings; - settings.set_buffer_lifetime_ordinal(output_buffer_lifetime_ordinal_); - settings.set_buffer_constraints_version_ordinal( - constraints.buffer_constraints_version_ordinal()); - settings.set_sysmem_token(std::move(collection_token_for_codec)); - decoder_->SetOutputBufferPartialSettings(std::move(settings)); - decoder_->CompleteOutputBufferPartialSettings( - output_buffer_lifetime_ordinal_); - // Exact number of buffers sysmem will allocate is unknown here. // |output_mailboxes_| is resized when we start receiving output frames. DCHECK(output_mailboxes_.empty()); } -void FuchsiaVideoDecoder::ReleaseInputBuffers() { - input_writer_queue_.ResetBuffers(); - input_buffer_collection_.reset(); - - // |in_flight_input_packets_| must be destroyed after - // |input_writer_queue_.ResetBuffers()|. Otherwise |input_writer_queue_| may - // call SendInputPacket() in response to the packet destruction callbacks. - in_flight_input_packets_.clear(); -} - void FuchsiaVideoDecoder::ReleaseOutputBuffers() { // Release the buffer collection. num_used_output_buffers_ = 0; if (output_buffer_collection_) { - output_buffer_collection_->Close(); - output_buffer_collection_.Unbind(); + output_buffer_collection_.reset(); } // Release all output mailboxes. @@ -1065,17 +793,10 @@ } } -void FuchsiaVideoDecoder::OnReuseMailbox(uint32_t buffer_index, - uint32_t packet_index) { - DCHECK(decoder_); - +void FuchsiaVideoDecoder::ReleaseOutputPacket( + StreamProcessorHelper::IoPacket output_packet) { DCHECK_GT(num_used_output_buffers_, 0U); num_used_output_buffers_--; - - fuchsia::media::PacketHeader header; - header.set_buffer_lifetime_ordinal(output_buffer_lifetime_ordinal_); - header.set_packet_index(packet_index); - decoder_->RecycleOutputPacket(std::move(header)); } std::unique_ptr<VideoDecoder> CreateFuchsiaVideoDecoder(
diff --git a/media/fuchsia/audio/fuchsia_audio_renderer.cc b/media/fuchsia/audio/fuchsia_audio_renderer.cc index f47f525..cf974cc 100644 --- a/media/fuchsia/audio/fuchsia_audio_renderer.cc +++ b/media/fuchsia/audio/fuchsia_audio_renderer.cc
@@ -12,8 +12,10 @@ #include "base/sequenced_task_runner.h" #include "base/threading/sequenced_task_runner_handle.h" #include "base/threading/thread_task_runner_handle.h" +#include "media/base/cdm_context.h" #include "media/base/decoder_buffer.h" #include "media/base/renderer_client.h" +#include "media/fuchsia/cdm/fuchsia_cdm_context.h" #include "media/fuchsia/common/decrypting_sysmem_buffer_stream.h" #include "media/fuchsia/common/passthrough_sysmem_buffer_stream.h" @@ -126,11 +128,21 @@ stream->EnableBitstreamConverter(); } - // DecryptingSysmemBufferStream handles both encrypted and clear streams, so - // initialize it long as we have |cdm_context|. - if (cdm_context) { - sysmem_buffer_stream_ = std::make_unique<DecryptingSysmemBufferStream>( - &sysmem_allocator_, cdm_context, Decryptor::kAudio); + if (stream->audio_decoder_config().is_encrypted()) { + if (!cdm_context) { + DLOG(ERROR) << "No cdm context for encrypted stream."; + OnError(AUDIO_RENDERER_ERROR); + return; + } + + FuchsiaCdmContext* fuchsia_cdm = cdm_context->GetFuchsiaCdmContext(); + if (fuchsia_cdm) { + sysmem_buffer_stream_ = fuchsia_cdm->CreateStreamDecryptor(false); + } else { + sysmem_buffer_stream_ = std::make_unique<DecryptingSysmemBufferStream>( + &sysmem_allocator_, cdm_context, Decryptor::kAudio); + } + } else { sysmem_buffer_stream_ = std::make_unique<PassthroughSysmemBufferStream>(&sysmem_allocator_);
diff --git a/media/fuchsia/cdm/fuchsia_cdm.cc b/media/fuchsia/cdm/fuchsia_cdm.cc index 2af3260..a4692f43 100644 --- a/media/fuchsia/cdm/fuchsia_cdm.cc +++ b/media/fuchsia/cdm/fuchsia_cdm.cc
@@ -4,13 +4,11 @@ #include "media/fuchsia/cdm/fuchsia_cdm.h" -#include "base/command_line.h" #include "base/fuchsia/fuchsia_logging.h" #include "base/logging.h" #include "fuchsia/base/mem_buffer_util.h" #include "media/base/callback_registry.h" #include "media/base/cdm_promise.h" -#include "media/base/media_switches.h" #include "third_party/abseil-cpp/absl/types/optional.h" #define REJECT_PROMISE_AND_RETURN_IF_BAD_CDM(promise, cdm) \ @@ -24,10 +22,6 @@ namespace { -// Audio packets are normally smaller than 128kB (more than enough for 2 seconds -// at 320kb/s). -const size_t kAudioStreamBufferSize = 128 * 1024; - std::string GetInitDataTypeName(EmeInitDataType type) { switch (type) { case EmeInitDataType::WEBM: @@ -315,43 +309,28 @@ FuchsiaCdm::~FuchsiaCdm() = default; -std::unique_ptr<FuchsiaSecureStreamDecryptor> FuchsiaCdm::CreateVideoDecryptor( - FuchsiaSecureStreamDecryptor::Client* client) { +std::unique_ptr<FuchsiaStreamDecryptor> FuchsiaCdm::CreateStreamDecryptor( + bool secure_mode) { fuchsia::media::drm::DecryptorParams params; - - bool secure_mode = base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kEnableProtectedVideoBuffers); params.set_require_secure_mode(secure_mode); - params.mutable_input_details()->set_format_details_version_ordinal(0); + fuchsia::media::StreamProcessorPtr stream_processor; cdm_->CreateDecryptor(std::move(params), stream_processor.NewRequest()); - auto decryptor = std::make_unique<FuchsiaSecureStreamDecryptor>( - std::move(stream_processor), client); + auto decryptor = + std::make_unique<FuchsiaStreamDecryptor>(std::move(stream_processor)); // Save callback to use to notify the decryptor about a new key. auto new_key_cb = decryptor->GetOnNewKeyClosure(); { - base::AutoLock auto_lock(new_key_cb_for_video_lock_); - new_key_cb_for_video_ = new_key_cb; + base::AutoLock auto_lock(new_key_callbacks_lock_); + new_key_callbacks_.push_back(std::move(new_key_cb)); } return decryptor; } -std::unique_ptr<FuchsiaClearStreamDecryptor> -FuchsiaCdm::CreateAudioDecryptor() { - fuchsia::media::drm::DecryptorParams params; - params.set_require_secure_mode(false); - params.mutable_input_details()->set_format_details_version_ordinal(0); - fuchsia::media::StreamProcessorPtr stream_processor; - cdm_->CreateDecryptor(std::move(params), stream_processor.NewRequest()); - - return std::make_unique<FuchsiaClearStreamDecryptor>( - std::move(stream_processor), kAudioStreamBufferSize); -} - void FuchsiaCdm::SetServerCertificate( const std::vector<uint8_t>& certificate, std::unique_ptr<SimpleCdmPromise> promise) { @@ -616,9 +595,18 @@ void FuchsiaCdm::OnNewKey() { event_callbacks_.Notify(Event::kHasAdditionalUsableKey); { - base::AutoLock auto_lock(new_key_cb_for_video_lock_); - if (new_key_cb_for_video_) - new_key_cb_for_video_.Run(); + base::AutoLock auto_lock(new_key_callbacks_lock_); + + // Remove cancelled callbacks. + new_key_callbacks_.erase( + std::remove_if( + new_key_callbacks_.begin(), new_key_callbacks_.end(), + [](const base::RepeatingClosure& cb) { return cb.IsCancelled(); }), + new_key_callbacks_.end()); + + for (auto& cb : new_key_callbacks_) { + cb.Run(); + } } }
diff --git a/media/fuchsia/cdm/fuchsia_cdm.h b/media/fuchsia/cdm/fuchsia_cdm.h index 5044e50..5f72dac 100644 --- a/media/fuchsia/cdm/fuchsia_cdm.h +++ b/media/fuchsia/cdm/fuchsia_cdm.h
@@ -71,9 +71,8 @@ FuchsiaCdmContext* GetFuchsiaCdmContext() override; // FuchsiaCdmContext implementation: - std::unique_ptr<FuchsiaSecureStreamDecryptor> CreateVideoDecryptor( - FuchsiaSecureStreamDecryptor::Client* client) override; - std::unique_ptr<FuchsiaClearStreamDecryptor> CreateAudioDecryptor() override; + std::unique_ptr<FuchsiaStreamDecryptor> CreateStreamDecryptor( + bool secure_mode) override; private: class CdmSession; @@ -112,9 +111,9 @@ FuchsiaDecryptor decryptor_; - base::Lock new_key_cb_for_video_lock_; - base::RepeatingClosure new_key_cb_for_video_ - GUARDED_BY(new_key_cb_for_video_lock_); + base::Lock new_key_callbacks_lock_; + std::vector<base::RepeatingClosure> new_key_callbacks_ + GUARDED_BY(new_key_callbacks_lock_); CallbackRegistry<EventCB::RunType> event_callbacks_;
diff --git a/media/fuchsia/cdm/fuchsia_cdm_context.h b/media/fuchsia/cdm/fuchsia_cdm_context.h index 667b78d..cda2fc6 100644 --- a/media/fuchsia/cdm/fuchsia_cdm_context.h +++ b/media/fuchsia/cdm/fuchsia_cdm_context.h
@@ -15,10 +15,8 @@ FuchsiaCdmContext() = default; // Creates FuchsiaSecureStreamDecryptor instance for the CDM context. - virtual std::unique_ptr<FuchsiaSecureStreamDecryptor> CreateVideoDecryptor( - FuchsiaSecureStreamDecryptor::Client* client) = 0; - virtual std::unique_ptr<FuchsiaClearStreamDecryptor> - CreateAudioDecryptor() = 0; + virtual std::unique_ptr<FuchsiaStreamDecryptor> CreateStreamDecryptor( + bool secure_mode) = 0; protected: virtual ~FuchsiaCdmContext() = default;
diff --git a/media/fuchsia/cdm/fuchsia_decryptor.cc b/media/fuchsia/cdm/fuchsia_decryptor.cc index c046957..82ee7cad 100644 --- a/media/fuchsia/cdm/fuchsia_decryptor.cc +++ b/media/fuchsia/cdm/fuchsia_decryptor.cc
@@ -22,32 +22,16 @@ } FuchsiaDecryptor::~FuchsiaDecryptor() { - if (audio_decryptor_) { - audio_decryptor_task_runner_->DeleteSoon(FROM_HERE, - std::move(audio_decryptor_)); - } } void FuchsiaDecryptor::Decrypt(StreamType stream_type, scoped_refptr<DecoderBuffer> encrypted, DecryptCB decrypt_cb) { - if (stream_type != StreamType::kAudio) { - std::move(decrypt_cb).Run(Status::kError, nullptr); - return; - } - - if (!audio_decryptor_) { - audio_decryptor_task_runner_ = base::ThreadTaskRunnerHandle::Get(); - audio_decryptor_ = cdm_context_->CreateAudioDecryptor(); - } - - audio_decryptor_->Decrypt(std::move(encrypted), std::move(decrypt_cb)); + std::move(decrypt_cb).Run(Status::kError, nullptr); } void FuchsiaDecryptor::CancelDecrypt(StreamType stream_type) { - if (stream_type == StreamType::kAudio && audio_decryptor_) { - audio_decryptor_->CancelDecrypt(); - } + NOTREACHED(); } void FuchsiaDecryptor::InitializeAudioDecoder(const AudioDecoderConfig& config,
diff --git a/media/fuchsia/cdm/fuchsia_decryptor.h b/media/fuchsia/cdm/fuchsia_decryptor.h index ae502e7..006b079 100644 --- a/media/fuchsia/cdm/fuchsia_decryptor.h +++ b/media/fuchsia/cdm/fuchsia_decryptor.h
@@ -5,8 +5,6 @@ #ifndef MEDIA_FUCHSIA_CDM_FUCHSIA_DECRYPTOR_H_ #define MEDIA_FUCHSIA_CDM_FUCHSIA_DECRYPTOR_H_ -#include <memory> - #include "base/memory/ref_counted.h" #include "base/single_thread_task_runner.h" #include "base/synchronization/lock.h" @@ -17,7 +15,6 @@ namespace media { class FuchsiaCdmContext; -class FuchsiaClearStreamDecryptor; class FuchsiaDecryptor : public Decryptor { public: @@ -45,8 +42,6 @@ private: FuchsiaCdmContext* const cdm_context_; - std::unique_ptr<FuchsiaClearStreamDecryptor> audio_decryptor_; - // TaskRunner for the thread on which |audio_decryptor_| was created. scoped_refptr<base::SingleThreadTaskRunner> audio_decryptor_task_runner_;
diff --git a/media/fuchsia/cdm/fuchsia_stream_decryptor.cc b/media/fuchsia/cdm/fuchsia_stream_decryptor.cc index 82b2754..9b2e421 100644 --- a/media/fuchsia/cdm/fuchsia_stream_decryptor.cc +++ b/media/fuchsia/cdm/fuchsia_stream_decryptor.cc
@@ -19,11 +19,6 @@ namespace media { namespace { -// Minimum number of buffers in the input and output buffer collection. -// Decryptors provided by fuchsia.media.drm API normally decrypt a single -// buffer at a time. Second buffer is useful to allow reading/writing a -// packet while the decryptor is working on another one. -const size_t kMinBufferCount = 2; std::string GetEncryptionScheme(EncryptionScheme mode) { switch (mode) { @@ -95,63 +90,143 @@ } // namespace -FuchsiaStreamDecryptorBase::FuchsiaStreamDecryptorBase( - fuchsia::media::StreamProcessorPtr processor, - size_t min_buffer_size) +FuchsiaStreamDecryptor::FuchsiaStreamDecryptor( + fuchsia::media::StreamProcessorPtr processor) : processor_(std::move(processor), this), - min_buffer_size_(min_buffer_size), - allocator_("CrFuchsiaStreamDecryptorBase") { - AllocateInputBuffers(); -} + allocator_("CrFuchsiaStreamDecryptor") {} -FuchsiaStreamDecryptorBase::~FuchsiaStreamDecryptorBase() { +FuchsiaStreamDecryptor::~FuchsiaStreamDecryptor() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); } -int FuchsiaStreamDecryptorBase::GetMaxDecryptRequests() const { - return input_writer_queue_.num_buffers() + 1; -} - -void FuchsiaStreamDecryptorBase::DecryptInternal( - scoped_refptr<DecoderBuffer> encrypted) { +base::RepeatingClosure FuchsiaStreamDecryptor::GetOnNewKeyClosure() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - input_writer_queue_.EnqueueBuffer(std::move(encrypted)); + return BindToCurrentLoop(base::BindRepeating( + &FuchsiaStreamDecryptor::OnNewKey, weak_factory_.GetWeakPtr())); } -void FuchsiaStreamDecryptorBase::ResetStream() { +void FuchsiaStreamDecryptor::Initialize(Sink* sink, + size_t min_buffer_size, + size_t min_buffer_count) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + sink_ = sink; + + min_buffer_size_ = min_buffer_size; + min_buffer_count_ = min_buffer_count; + + input_buffer_collection_ = allocator_.AllocateNewCollection(); + input_buffer_collection_->CreateSharedToken( + base::BindOnce(&StreamProcessorHelper::SetInputBufferCollectionToken, + base::Unretained(&processor_))); + auto buffer_constraints = VmoBuffer::GetRecommendedConstraints( + kInputBufferCount, min_buffer_size_, /*writable=*/true); + input_buffer_collection_->Initialize(std::move(buffer_constraints), + "CrFuchsiaStreamDecryptor"); + input_buffer_collection_->AcquireBuffers(base::BindOnce( + &FuchsiaStreamDecryptor::OnInputBuffersAcquired, base::Unretained(this))); +} + +void FuchsiaStreamDecryptor::EnqueueBuffer( + scoped_refptr<DecoderBuffer> buffer) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + input_writer_queue_.EnqueueBuffer(std::move(buffer)); +} + +void FuchsiaStreamDecryptor::Reset() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); // Close current stream and drop all the cached decoder buffers. // Keep input and output buffers to avoid buffer re-allocation. processor_.Reset(); input_writer_queue_.ResetQueue(); + waiting_for_key_ = false; } -void FuchsiaStreamDecryptorBase::AllocateInputBuffers() { +void FuchsiaStreamDecryptor::OnStreamProcessorAllocateOutputBuffers( + const fuchsia::media::StreamBufferConstraints& stream_constraints) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - input_buffer_collection_ = allocator_.AllocateNewCollection(); - input_buffer_collection_->CreateSharedToken( - base::BindOnce(&StreamProcessorHelper::SetInputBufferCollectionToken, + output_buffer_collection_ = allocator_.AllocateNewCollection(); + output_buffer_collection_->CreateSharedToken( + base::BindOnce(&StreamProcessorHelper::CompleteOutputBuffersAllocation, base::Unretained(&processor_))); - input_buffer_collection_->Initialize( - VmoBuffer::GetRecommendedConstraints(kMinBufferCount, min_buffer_size_, - /*writable=*/true), - "CrStreamDecryptorInput"); - input_buffer_collection_->AcquireBuffers( - base::BindOnce(&FuchsiaStreamDecryptorBase::OnInputBuffersAcquired, - base::Unretained(this))); + output_buffer_collection_->CreateSharedToken( + base::BindOnce(&Sink::OnSysmemBufferStreamBufferCollectionToken, + base::Unretained(sink_))); + + fuchsia::sysmem::BufferCollectionConstraints buffer_constraints; + buffer_constraints.usage.none = fuchsia::sysmem::noneUsage; + buffer_constraints.min_buffer_count = min_buffer_count_; + buffer_constraints.has_buffer_memory_constraints = true; + buffer_constraints.buffer_memory_constraints.min_size_bytes = + min_buffer_size_; + buffer_constraints.buffer_memory_constraints.ram_domain_supported = true; + buffer_constraints.buffer_memory_constraints.cpu_domain_supported = true; + buffer_constraints.buffer_memory_constraints.inaccessible_domain_supported = + true; + + output_buffer_collection_->Initialize(std::move(buffer_constraints), + "CrFuchsiaStreamDecryptorOutput"); } -void FuchsiaStreamDecryptorBase::OnOutputFormat( +void FuchsiaStreamDecryptor::OnStreamProcessorEndOfStream() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + sink_->OnSysmemBufferStreamEndOfStream(); +} + +void FuchsiaStreamDecryptor::OnStreamProcessorOutputFormat( fuchsia::media::StreamOutputFormat format) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); } -void FuchsiaStreamDecryptorBase::OnInputBuffersAcquired( +void FuchsiaStreamDecryptor::OnStreamProcessorOutputPacket( + StreamProcessorHelper::IoPacket packet) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + sink_->OnSysmemBufferStreamOutputPacket(std::move(packet)); +} + +void FuchsiaStreamDecryptor::OnStreamProcessorNoKey() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK(!waiting_for_key_); + + // Reset stream position, but keep all pending buffers. They will be + // resubmitted later, when we have a new key. + input_writer_queue_.ResetPositionAndPause(); + + if (retry_on_no_key_event_) { + retry_on_no_key_event_ = false; + input_writer_queue_.Unpause(); + return; + } + + waiting_for_key_ = true; + sink_->OnSysmemBufferStreamNoKey(); +} + +void FuchsiaStreamDecryptor::OnStreamProcessorError() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + OnError(); +} + +void FuchsiaStreamDecryptor::OnError() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + Reset(); + + // No need to reset other fields since OnError() is called for non-recoverable + // errors. + + sink_->OnSysmemBufferStreamError(); +} + +void FuchsiaStreamDecryptor::OnInputBuffersAcquired( std::vector<VmoBuffer> buffers, - const fuchsia::sysmem::SingleBufferSettings& buffer_settings) { + const fuchsia::sysmem::SingleBufferSettings&) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (buffers.empty()) { @@ -161,13 +236,13 @@ input_writer_queue_.Start( std::move(buffers), - base::BindRepeating(&FuchsiaStreamDecryptorBase::SendInputPacket, + base::BindRepeating(&FuchsiaStreamDecryptor::SendInputPacket, base::Unretained(this)), - base::BindRepeating(&FuchsiaStreamDecryptorBase::ProcessEndOfStream, + base::BindRepeating(&FuchsiaStreamDecryptor::ProcessEndOfStream, base::Unretained(this))); } -void FuchsiaStreamDecryptorBase::SendInputPacket( +void FuchsiaStreamDecryptor::SendInputPacket( const DecoderBuffer* buffer, StreamProcessorHelper::IoPacket packet) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); @@ -191,265 +266,21 @@ processor_.Process(std::move(packet)); } -void FuchsiaStreamDecryptorBase::ProcessEndOfStream() { +void FuchsiaStreamDecryptor::ProcessEndOfStream() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); processor_.ProcessEos(); } -FuchsiaClearStreamDecryptor::FuchsiaClearStreamDecryptor( - fuchsia::media::StreamProcessorPtr processor, - size_t min_buffer_size) - : FuchsiaStreamDecryptorBase(std::move(processor), min_buffer_size) {} - -FuchsiaClearStreamDecryptor::~FuchsiaClearStreamDecryptor() = default; - -void FuchsiaClearStreamDecryptor::Decrypt( - scoped_refptr<DecoderBuffer> encrypted, - Decryptor::DecryptCB decrypt_cb) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - DCHECK(!decrypt_cb_); - - decrypt_cb_ = std::move(decrypt_cb); - current_status_ = Decryptor::kSuccess; - DecryptInternal(std::move(encrypted)); -} - -void FuchsiaClearStreamDecryptor::CancelDecrypt() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - - ResetStream(); - - // Fire |decrypt_cb_| immediately as required by Decryptor::CancelDecrypt. - if (decrypt_cb_) - std::move(decrypt_cb_).Run(Decryptor::kSuccess, nullptr); -} - -void FuchsiaClearStreamDecryptor::AllocateOutputBuffers( - const fuchsia::media::StreamBufferConstraints& stream_constraints) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - output_buffer_collection_ = allocator_.AllocateNewCollection(); - output_buffer_collection_->CreateSharedToken( - base::BindOnce(&StreamProcessorHelper::CompleteOutputBuffersAllocation, - base::Unretained(&processor_))); - output_buffer_collection_->Initialize( - VmoBuffer::GetRecommendedConstraints(kMinBufferCount, min_buffer_size_, - /*writable=*/false), - "CrFuchsiaStreamDecryptor"); - output_buffer_collection_->AcquireBuffers( - base::BindOnce(&FuchsiaClearStreamDecryptor::OnOutputBuffersAcquired, - base::Unretained(this))); -} - -void FuchsiaClearStreamDecryptor::OnProcessEos() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - - // Decryptor never pushes EOS frame. - NOTREACHED(); -} - -void FuchsiaClearStreamDecryptor::OnOutputPacket( - StreamProcessorHelper::IoPacket packet) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - DCHECK(decrypt_cb_); - - size_t buffer_index = packet.buffer_index(); - if (buffer_index >= output_buffers_.size()) { - DLOG(ERROR) << "Received output packet with invalid buffer index: " - << buffer_index; - OnError(); - return; - } - - // If that's not the last packet for the current Decrypt() request then just - // store the output and wait for the next packet. - if (!packet.unit_end()) { - size_t pos = output_data_.size(); - output_data_.resize(pos + packet.size()); - - size_t bytes_read = output_buffers_[buffer_index].Read( - packet.offset(), - base::make_span(output_data_.data() + pos, packet.size())); - - if (bytes_read != packet.size()) { - // If we've failed to read a partial packet then delay reporting the error - // until we've received the last packet to make sure we consume all output - // packets generated by the last Decrypt() call. - DLOG(ERROR) << "Failed to get decrypted result."; - current_status_ = Decryptor::kError; - output_data_.clear(); - } - - return; - } - - // We've received the last packet. Assemble DecoderBuffer and pass it to the - // DecryptCB. - auto clear_buffer = - base::MakeRefCounted<DecoderBuffer>(output_data_.size() + packet.size()); - clear_buffer->set_timestamp(packet.timestamp()); - - // Copy data received in the previous packets. - memcpy(clear_buffer->writable_data(), output_data_.data(), - output_data_.size()); - output_data_.clear(); - - // Copy data received in the last packet - size_t bytes_read = output_buffers_[buffer_index].Read( - packet.offset(), - base::make_span(clear_buffer->writable_data() + output_data_.size(), - packet.size())); - - if (bytes_read != packet.size()) { - DLOG(ERROR) << "Fail to get decrypted result."; - current_status_ = Decryptor::kError; - } - - std::move(decrypt_cb_) - .Run(current_status_, current_status_ == Decryptor::kSuccess - ? std::move(clear_buffer) - : nullptr); -} - -void FuchsiaClearStreamDecryptor::OnNoKey() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - - // Reset the queue. The client is expected to call Decrypt() with the same - // buffer again when it gets kNoKey. - input_writer_queue_.ResetQueue(); - - if (decrypt_cb_) - std::move(decrypt_cb_).Run(Decryptor::kNoKey, nullptr); -} - -void FuchsiaClearStreamDecryptor::OnError() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - - ResetStream(); - if (decrypt_cb_) - std::move(decrypt_cb_).Run(Decryptor::kError, nullptr); -} - -void FuchsiaClearStreamDecryptor::OnOutputBuffersAcquired( - std::vector<VmoBuffer> buffers, - const fuchsia::sysmem::SingleBufferSettings& buffer_settings) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - - if (buffers.empty()) { - LOG(ERROR) << "Fail to allocate output buffer."; - OnError(); - return; - } - - DCHECK(output_buffers_.empty()); - output_buffers_ = std::move(buffers); -} - -FuchsiaSecureStreamDecryptor::FuchsiaSecureStreamDecryptor( - fuchsia::media::StreamProcessorPtr processor, - Client* client) - : FuchsiaStreamDecryptorBase(std::move(processor), - client->GetInputBufferSize()), - client_(client) {} - -FuchsiaSecureStreamDecryptor::~FuchsiaSecureStreamDecryptor() = default; - -void FuchsiaSecureStreamDecryptor::SetOutputBufferCollectionToken( - fuchsia::sysmem::BufferCollectionTokenPtr token) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - DCHECK(!complete_buffer_allocation_callback_); - complete_buffer_allocation_callback_ = - base::BindOnce(&StreamProcessorHelper::CompleteOutputBuffersAllocation, - base::Unretained(&processor_), std::move(token)); - if (waiting_output_buffers_) { - std::move(complete_buffer_allocation_callback_).Run(); - waiting_output_buffers_ = false; - } -} - -void FuchsiaSecureStreamDecryptor::Decrypt( - scoped_refptr<DecoderBuffer> encrypted) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - - DecryptInternal(std::move(encrypted)); -} - -void FuchsiaSecureStreamDecryptor::Reset() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - - ResetStream(); - waiting_for_key_ = false; -} - -void FuchsiaSecureStreamDecryptor::AllocateOutputBuffers( - const fuchsia::media::StreamBufferConstraints& stream_constraints) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - - if (complete_buffer_allocation_callback_) { - std::move(complete_buffer_allocation_callback_).Run(); - } else { - waiting_output_buffers_ = true; - } -} - -void FuchsiaSecureStreamDecryptor::OnProcessEos() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - - client_->OnDecryptorEndOfStreamPacket(); -} - -void FuchsiaSecureStreamDecryptor::OnOutputPacket( - StreamProcessorHelper::IoPacket packet) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - - client_->OnDecryptorOutputPacket(std::move(packet)); -} - -base::RepeatingClosure FuchsiaSecureStreamDecryptor::GetOnNewKeyClosure() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - - return BindToCurrentLoop(base::BindRepeating( - &FuchsiaSecureStreamDecryptor::OnNewKey, weak_factory_.GetWeakPtr())); -} - -void FuchsiaSecureStreamDecryptor::OnError() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - - ResetStream(); - - // No need to reset other fields since OnError() is called for non-recoverable - // errors. - - client_->OnDecryptorError(); -} - -void FuchsiaSecureStreamDecryptor::OnNoKey() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - DCHECK(!waiting_for_key_); - - // Reset stream position, but keep all pending buffers. They will be - // resubmitted later, when we have a new key. - input_writer_queue_.ResetPositionAndPause(); - - if (retry_on_no_key_) { - retry_on_no_key_ = false; - input_writer_queue_.Unpause(); - return; - } - - waiting_for_key_ = true; - client_->OnDecryptorNoKey(); -} - -void FuchsiaSecureStreamDecryptor::OnNewKey() { +void FuchsiaStreamDecryptor::OnNewKey() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (!waiting_for_key_) { - retry_on_no_key_ = true; + retry_on_no_key_event_ = true; return; } - DCHECK(!retry_on_no_key_); + DCHECK(!retry_on_no_key_event_); waiting_for_key_ = false; input_writer_queue_.Unpause(); }
diff --git a/media/fuchsia/cdm/fuchsia_stream_decryptor.h b/media/fuchsia/cdm/fuchsia_stream_decryptor.h index 792c5e6..bba2d0c 100644 --- a/media/fuchsia/cdm/fuchsia_stream_decryptor.h +++ b/media/fuchsia/cdm/fuchsia_stream_decryptor.h
@@ -11,126 +11,31 @@ #include "base/sequence_checker.h" #include "media/base/decryptor.h" +#include "media/base/media_export.h" #include "media/fuchsia/common/stream_processor_helper.h" +#include "media/fuchsia/common/sysmem_buffer_stream.h" #include "media/fuchsia/common/sysmem_client.h" #include "media/fuchsia/common/vmo_buffer_writer_queue.h" namespace media { -// Base class for media stream decryptor implementations. -class FuchsiaStreamDecryptorBase : public StreamProcessorHelper::Client { +// Stream decryptor used to decrypt protected media streams on Fuchsia. Must be +// created an used on the same thread. +class MEDIA_EXPORT FuchsiaStreamDecryptor + : public SysmemBufferStream, + public StreamProcessorHelper::Client { public: - FuchsiaStreamDecryptorBase(fuchsia::media::StreamProcessorPtr processor, - size_t min_buffer_size); - ~FuchsiaStreamDecryptorBase() override; + // Number of buffers that the decryptor allocates for input buffer + // collection. Decryptors provided by fuchsia.media.drm API normally decrypt a + // single buffer at a time. Second buffer is useful to allow reading/writing a + // packet while the decryptor is working on another one. + static constexpr size_t kInputBufferCount = 2; - int GetMaxDecryptRequests() const; + explicit FuchsiaStreamDecryptor(fuchsia::media::StreamProcessorPtr processor); + ~FuchsiaStreamDecryptor() override; - protected: - // StreamProcessorHelper::Client overrides. - void OnOutputFormat(fuchsia::media::StreamOutputFormat format) final; - - void AllocateInputBuffers(); - void DecryptInternal(scoped_refptr<DecoderBuffer> encrypted); - void ResetStream(); - - StreamProcessorHelper processor_; - - const size_t min_buffer_size_; - - SysmemAllocatorClient allocator_; - - VmoBufferWriterQueue input_writer_queue_; - - // Key ID for which we received the last OnNewKey() event. - std::string last_new_key_id_; - - SEQUENCE_CHECKER(sequence_checker_); - - private: - void OnInputBuffersAcquired( - std::vector<VmoBuffer> buffers, - const fuchsia::sysmem::SingleBufferSettings& buffer_settings); - void SendInputPacket(const DecoderBuffer* buffer, - StreamProcessorHelper::IoPacket packet); - void ProcessEndOfStream(); - - std::unique_ptr<SysmemCollectionClient> input_buffer_collection_; - - DISALLOW_COPY_AND_ASSIGN(FuchsiaStreamDecryptorBase); -}; - -// Stream decryptor that copies output to clear DecodeBuffer's. Used for audio -// streams. -class FuchsiaClearStreamDecryptor : public FuchsiaStreamDecryptorBase { - public: - static std::unique_ptr<FuchsiaClearStreamDecryptor> Create( - fuchsia::media::drm::ContentDecryptionModule* cdm, - size_t min_buffer_size); - - FuchsiaClearStreamDecryptor(fuchsia::media::StreamProcessorPtr processor, - size_t min_buffer_size); - ~FuchsiaClearStreamDecryptor() override; - - // Decrypt() behavior should match media::Decryptor interface. - void Decrypt(scoped_refptr<DecoderBuffer> encrypted, - Decryptor::DecryptCB decrypt_cb); - void CancelDecrypt(); - - private: - // StreamProcessorHelper::Client overrides. - void AllocateOutputBuffers( - const fuchsia::media::StreamBufferConstraints& stream_constraints) final; - void OnProcessEos() final; - void OnOutputPacket(StreamProcessorHelper::IoPacket packet) final; - void OnNoKey() final; - void OnError() final; - - void OnOutputBuffersAcquired( - std::vector<VmoBuffer> buffers, - const fuchsia::sysmem::SingleBufferSettings& buffer_settings); - - Decryptor::DecryptCB decrypt_cb_; - - std::unique_ptr<SysmemCollectionClient> output_buffer_collection_; - std::vector<VmoBuffer> output_buffers_; - - // Used to re-assemble decrypted output that was split between multiple sysmem - // buffers. - Decryptor::Status current_status_ = Decryptor::kSuccess; - std::vector<uint8_t> output_data_; - - DISALLOW_COPY_AND_ASSIGN(FuchsiaClearStreamDecryptor); -}; - -// Stream decryptor that decrypts data to protected sysmem buffers. Used for -// video stream. -class FuchsiaSecureStreamDecryptor : public FuchsiaStreamDecryptorBase { - public: - class Client { - public: - virtual size_t GetInputBufferSize() = 0; - virtual void OnDecryptorOutputPacket( - StreamProcessorHelper::IoPacket packet) = 0; - virtual void OnDecryptorEndOfStreamPacket() = 0; - virtual void OnDecryptorError() = 0; - virtual void OnDecryptorNoKey() = 0; - - protected: - virtual ~Client() = default; - }; - - FuchsiaSecureStreamDecryptor(fuchsia::media::StreamProcessorPtr processor, - Client* client); - ~FuchsiaSecureStreamDecryptor() override; - - void SetOutputBufferCollectionToken( - fuchsia::sysmem::BufferCollectionTokenPtr token); - - // Enqueues the specified buffer to the input queue. Caller is allowed to - // queue as many buffers as it needs without waiting for results from the - // previous Decrypt() calls. - void Decrypt(scoped_refptr<DecoderBuffer> encrypted); + FuchsiaStreamDecryptor(const FuchsiaStreamDecryptor&) = delete; + FuchsiaStreamDecryptor& operator=(const FuchsiaStreamDecryptor&) = delete; // Returns closure that should be called when the key changes. This class // uses this notification to handle NO_KEY errors. Note that this class can @@ -141,42 +46,70 @@ // the key is updated. base::RepeatingClosure GetOnNewKeyClosure(); - // Drops all pending decryption requests. - void Reset(); + // SysmemBufferStream implementation. + void Initialize(Sink* sink, + size_t min_buffer_size, + size_t min_buffer_count) override; + void EnqueueBuffer(scoped_refptr<DecoderBuffer> buffer) override; + void Reset() override; private: // StreamProcessorHelper::Client overrides. - void AllocateOutputBuffers( + void OnStreamProcessorAllocateOutputBuffers( const fuchsia::media::StreamBufferConstraints& stream_constraints) final; - void OnProcessEos() final; - void OnOutputPacket(StreamProcessorHelper::IoPacket packet) final; - void OnNoKey() final; - void OnError() final; + void OnStreamProcessorEndOfStream() final; + void OnStreamProcessorOutputFormat( + fuchsia::media::StreamOutputFormat format) final; + void OnStreamProcessorOutputPacket( + StreamProcessorHelper::IoPacket packet) final; + void OnStreamProcessorNoKey() final; + void OnStreamProcessorError() final; + + void OnError(); + + void OnInputBuffersAcquired( + std::vector<VmoBuffer> buffers, + const fuchsia::sysmem::SingleBufferSettings& buffer_settings); + void SendInputPacket(const DecoderBuffer* buffer, + StreamProcessorHelper::IoPacket packet); + void ProcessEndOfStream(); // Callback returned by GetOnNewKeyClosure(). When waiting for a key this // method unpauses the stream to decrypt any pending buffers. void OnNewKey(); - Client* const client_; + StreamProcessorHelper processor_; - bool waiting_output_buffers_ = false; - base::OnceClosure complete_buffer_allocation_callback_; + SysmemAllocatorClient allocator_; + + Sink* sink_ = nullptr; + + size_t min_buffer_size_ = 0; + size_t min_buffer_count_ = 0; + + std::unique_ptr<SysmemCollectionClient> input_buffer_collection_; + VmoBufferWriterQueue input_writer_queue_; + + std::unique_ptr<SysmemCollectionClient> output_buffer_collection_; + + // Key ID for which we received the last OnNewKey() event. + std::string last_new_key_id_; // Set to true if some keys have been updated recently. New key notifications // are received from a LicenseSession, while DECRYPTOR_NO_KEY error is // received from StreamProcessor. These are separate FIDL connections that are // handled on different threads, so they are not synchronized. As result // OnNewKey() may be called before we get OnNoKey(). To handle this case - // correctly OnNewKey() sets |retry_on_no_key_| and then OnNoKey() tries to - // restart the stream immediately if this flag is set. - bool retry_on_no_key_ = false; + // correctly OnNewKey() sets |retry_on_no_key_event_| and then OnNoKey() tries + // to restart the stream immediately if this flag is set. + bool retry_on_no_key_event_ = false; // Set to true if the stream is paused while we are waiting for new keys. bool waiting_for_key_ = false; - base::WeakPtrFactory<FuchsiaSecureStreamDecryptor> weak_factory_{this}; + SEQUENCE_CHECKER(sequence_checker_); - DISALLOW_COPY_AND_ASSIGN(FuchsiaSecureStreamDecryptor); + base::WeakPtrFactory<FuchsiaStreamDecryptor> weak_factory_{this}; }; } // namespace media
diff --git a/media/fuchsia/common/stream_processor_helper.cc b/media/fuchsia/common/stream_processor_helper.cc index 51e9cec..0ca556a 100644 --- a/media/fuchsia/common/stream_processor_helper.cc +++ b/media/fuchsia/common/stream_processor_helper.cc
@@ -6,6 +6,7 @@ #include "base/bind.h" #include "base/fuchsia/fuchsia_logging.h" +#include "media/base/timestamp_constants.h" namespace media { @@ -27,36 +28,23 @@ offset_(offset), size_(size), timestamp_(timestamp), - unit_end_(unit_end), - destroy_cb_(std::move(destroy_cb)) {} + unit_end_(unit_end) { + destroy_callbacks_.push_front(std::move(destroy_cb)); +} -StreamProcessorHelper::IoPacket::~IoPacket() = default; +StreamProcessorHelper::IoPacket::~IoPacket() { + for (auto& cb : destroy_callbacks_) { + std::move(cb).Run(); + } +} StreamProcessorHelper::IoPacket::IoPacket(IoPacket&&) = default; StreamProcessorHelper::IoPacket& StreamProcessorHelper::IoPacket::operator=( IoPacket&&) = default; -// static -StreamProcessorHelper::IoPacket StreamProcessorHelper::IoPacket::CreateInput( - size_t index, - size_t size, - base::TimeDelta timestamp, - bool unit_end, - base::OnceClosure destroy_cb) { - return IoPacket(index, 0 /* offset */, size, timestamp, unit_end, - std::move(destroy_cb)); -} - -// static -StreamProcessorHelper::IoPacket StreamProcessorHelper::IoPacket::CreateOutput( - size_t index, - size_t offset, - size_t size, - base::TimeDelta timestamp, - bool unit_end, - base::OnceClosure destroy_cb) { - return IoPacket(index, offset, size, timestamp, unit_end, - std::move(destroy_cb)); +void StreamProcessorHelper::IoPacket::AddOnDestroyClosure( + base::OnceClosure closure) { + destroy_callbacks_.push_front(std::move(closure)); } StreamProcessorHelper::StreamProcessorHelper( @@ -160,7 +148,7 @@ // Always reset the stream since the current one has failed. Reset(); - client_->OnNoKey(); + client_->OnStreamProcessorNoKey(); return; } @@ -226,7 +214,7 @@ output_buffer_constraints_ = std::move(*output_constraints.mutable_buffer_constraints()); - client_->AllocateOutputBuffers(output_buffer_constraints_); + client_->OnStreamProcessorAllocateOutputBuffers(output_buffer_constraints_); } void StreamProcessorHelper::OnOutputFormat( @@ -244,7 +232,7 @@ return; } - client_->OnOutputFormat(std::move(output_format)); + client_->OnStreamProcessorOutputFormat(std::move(output_format)); } void StreamProcessorHelper::OnOutputPacket(fuchsia::media::Packet output_packet, @@ -276,12 +264,12 @@ auto buffer_index = output_packet.buffer_index(); auto packet_index = output_packet.header().packet_index(); - base::TimeDelta timestamp; - if (output_packet.has_timestamp_ish()) { - timestamp = base::TimeDelta::FromNanoseconds(output_packet.timestamp_ish()); - } + base::TimeDelta timestamp = + output_packet.has_timestamp_ish() + ? base::TimeDelta::FromNanoseconds(output_packet.timestamp_ish()) + : kNoTimestamp; - client_->OnOutputPacket(IoPacket::CreateOutput( + client_->OnStreamProcessorOutputPacket(IoPacket( buffer_index, output_packet.start_offset(), output_packet.valid_length_bytes(), timestamp, output_packet.known_end_access_unit(), @@ -301,12 +289,12 @@ stream_lifetime_ordinal_ += 2; active_stream_ = false; - client_->OnProcessEos(); + client_->OnStreamProcessorEndOfStream(); } void StreamProcessorHelper::OnError() { processor_.Unbind(); - client_->OnError(); + client_->OnStreamProcessorError(); } void StreamProcessorHelper::SetInputBufferCollectionToken(
diff --git a/media/fuchsia/common/stream_processor_helper.h b/media/fuchsia/common/stream_processor_helper.h index ad16a2d..c2e32de 100644 --- a/media/fuchsia/common/stream_processor_helper.h +++ b/media/fuchsia/common/stream_processor_helper.h
@@ -8,8 +8,9 @@ #include <fuchsia/media/cpp/fidl.h> #include <fuchsia/sysmem/cpp/fidl.h> +#include <forward_list> + #include "base/callback.h" -#include "base/callback_helpers.h" #include "base/containers/flat_map.h" #include "base/macros.h" #include "base/memory/weak_ptr.h" @@ -28,19 +29,6 @@ public: class MEDIA_EXPORT IoPacket { public: - static IoPacket CreateInput(size_t index, - size_t size, - base::TimeDelta timestamp, - bool unit_end, - base::OnceClosure destroy_cb); - - static IoPacket CreateOutput(size_t index, - size_t offset, - size_t size, - base::TimeDelta timestamp, - bool unit_end, - base::OnceClosure destroy_cb); - IoPacket(size_t index, size_t offset, size_t size, @@ -62,6 +50,9 @@ } const fuchsia::media::FormatDetails& format() const { return format_; } + // Adds a |closure| that will be called when the packet is destroyed. + void AddOnDestroyClosure(base::OnceClosure closure); + private: size_t index_; size_t offset_; @@ -69,7 +60,7 @@ base::TimeDelta timestamp_; bool unit_end_; fuchsia::media::FormatDetails format_; - base::ScopedClosureRunner destroy_cb_; + std::forward_list<base::OnceClosure> destroy_callbacks_; DISALLOW_COPY_AND_ASSIGN(IoPacket); }; @@ -78,26 +69,27 @@ public: // Allocate output buffers with the given constraints. Client should call // ProvideIOutputBufferCollectionToken to finish the buffer allocation flow. - virtual void AllocateOutputBuffers( + virtual void OnStreamProcessorAllocateOutputBuffers( const fuchsia::media::StreamBufferConstraints& stream_constraints) = 0; // Called when all the pushed packets are processed. - virtual void OnProcessEos() = 0; + virtual void OnStreamProcessorEndOfStream() = 0; // Called when output format is available. - virtual void OnOutputFormat(fuchsia::media::StreamOutputFormat format) = 0; + virtual void OnStreamProcessorOutputFormat( + fuchsia::media::StreamOutputFormat format) = 0; // Called when output packet is available. Deleting |packet| will notify // StreamProcessor the output buffer is available to be re-used. Client // should delete |packet| on the same thread as this function. - virtual void OnOutputPacket(IoPacket packet) = 0; + virtual void OnStreamProcessorOutputPacket(IoPacket packet) = 0; // Only available for decryption, which indicates currently the // StreamProcessor doesn't have the content key to process. - virtual void OnNoKey() = 0; + virtual void OnStreamProcessorNoKey() = 0; // Called when any fatal errors happens. - virtual void OnError() = 0; + virtual void OnStreamProcessorError() = 0; protected: virtual ~Client() = default;
diff --git a/media/fuchsia/common/sysmem_client.cc b/media/fuchsia/common/sysmem_client.cc index f2a198df..4c5d86db 100644 --- a/media/fuchsia/common/sysmem_client.cc +++ b/media/fuchsia/common/sysmem_client.cc
@@ -27,6 +27,8 @@ SysmemCollectionClient::~SysmemCollectionClient() { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + if (collection_) + collection_->Close(); } void SysmemCollectionClient::Initialize( @@ -60,13 +62,20 @@ fit::bind_member(this, &SysmemCollectionClient::OnSyncComplete)); } -void SysmemCollectionClient::CreateSharedToken(GetSharedTokenCB cb) { +void SysmemCollectionClient::CreateSharedToken( + GetSharedTokenCB cb, + base::StringPiece debug_client_name, + uint64_t debug_client_id) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); DCHECK(collection_token_); fuchsia::sysmem::BufferCollectionTokenPtr token; collection_token_->Duplicate(ZX_RIGHT_SAME_RIGHTS, token.NewRequest()); + if (!debug_client_name.empty()) { + token->SetDebugClientInfo(std::string(debug_client_name), debug_client_id); + } + sync_completion_closures_.push_back( base::BindOnce(std::move(cb), std::move(token))); }
diff --git a/media/fuchsia/common/sysmem_client.h b/media/fuchsia/common/sysmem_client.h index acedf70..c45fb264 100644 --- a/media/fuchsia/common/sysmem_client.h +++ b/media/fuchsia/common/sysmem_client.h
@@ -48,7 +48,10 @@ // Creates one shared token to be shared with other participants and returns // it asynchronously, when it's safe to pass it (i.e. after Sync()). Must be // called before Initialize(). - void CreateSharedToken(GetSharedTokenCB cb); + void CreateSharedToken( + GetSharedTokenCB cb, + base::StringPiece debug_client_name = base::StringPiece(), + uint64_t debug_client_id = 0); // Initializes the collection with the given name and constraints. void Initialize(fuchsia::sysmem::BufferCollectionConstraints constraints,
diff --git a/media/fuchsia/common/vmo_buffer_writer_queue.cc b/media/fuchsia/common/vmo_buffer_writer_queue.cc index fc81602..2367a8d 100644 --- a/media/fuchsia/common/vmo_buffer_writer_queue.cc +++ b/media/fuchsia/common/vmo_buffer_writer_queue.cc
@@ -108,9 +108,9 @@ bool buffer_end = current_buffer->bytes_left() == 0; - auto packet = StreamProcessorHelper::IoPacket::CreateInput( - buffer_index, bytes_filled, current_buffer->buffer->timestamp(), - buffer_end, + auto packet = StreamProcessorHelper::IoPacket( + buffer_index, /*offset=*/0, bytes_filled, + current_buffer->buffer->timestamp(), buffer_end, base::BindOnce(&VmoBufferWriterQueue::ReleaseBuffer, weak_factory_.GetWeakPtr(), buffer_index));
diff --git a/media/gpu/test/OWNERS b/media/gpu/test/OWNERS index f2b8fd7a..8efbdde4 100644 --- a/media/gpu/test/OWNERS +++ b/media/gpu/test/OWNERS
@@ -1,2 +1,2 @@ dstaessens@chromium.org -hiroh@chromium.org \ No newline at end of file +hiroh@chromium.org
diff --git a/media/gpu/vaapi/OWNERS b/media/gpu/vaapi/OWNERS index 93cfc79..54ca4a0 100644 --- a/media/gpu/vaapi/OWNERS +++ b/media/gpu/vaapi/OWNERS
@@ -7,4 +7,4 @@ # Legacy owners. dstaessens@chromium.org kcwu@chromium.org -posciak@chromium.org \ No newline at end of file +posciak@chromium.org
diff --git a/net/data/websocket/README b/net/data/websocket/README index 515601e..80ee67f0 100644 --- a/net/data/websocket/README +++ b/net/data/websocket/README
@@ -34,6 +34,10 @@ eg. connect_to.html?url=ws://localhost/echo Sets the title to "PASS" if connection succeeds and "FAIL" otherwise. +- check-origin.html : A page which checks the origin header of the WebSocket + opening handshake with check-origin_wsh.py. The page is expected to be + accessed via a file:// URL. + - multiple-connections.html : Verify that HTTP connection limits are not applied to WebSockets. Used by WebSocketBrowserTest.SSLConnectionLimit. @@ -72,3 +76,6 @@ - protocol-test_wsh.py : A WebSocket URL handler for testing outgoing opening handshake protocol. Used by kinds of PPAPI tests for WebSocket. + +- check-origin_wsh.py : A WebSocket URL handler to echo back the origin header + used in the opening handshake. \ No newline at end of file
diff --git a/net/data/websocket/check-origin.html b/net/data/websocket/check-origin.html new file mode 100644 index 0000000..17cb554 --- /dev/null +++ b/net/data/websocket/check-origin.html
@@ -0,0 +1,33 @@ +<!DOCTYPE html> +<html> +<head> +<title>test ws connection</title> +<script> + +const query = new URL(location.href).searchParams; + +async function test() { + try { + const port = query.get('port'); + const ws = new WebSocket(`ws://127.0.0.1:${port}/check-origin`); + const ev = await new Promise((resolve, reject) => { + ws.onmessage = resolve; + ws.onclose = reject; + }); + if (ev.data == 'file://') { + document.title = 'FILE'; + } else if (ev.data == 'null') { + document.title = 'NULL'; + } else { + document.title = 'FAIL'; + } + } catch (e) { + document.title = 'FAIL'; + } +} + +test(); + +</script> +</head> +</html>
diff --git a/net/data/websocket/check-origin_wsh.py b/net/data/websocket/check-origin_wsh.py new file mode 100644 index 0000000..3137b09 --- /dev/null +++ b/net/data/websocket/check-origin_wsh.py
@@ -0,0 +1,13 @@ +# Copyright 2021 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +from mod_pywebsocket import msgutil + + +def web_socket_do_extra_handshake(request): + pass # Always accept. + + +def web_socket_transfer_data(request): + msgutil.send_message(request, request.ws_origin)
diff --git a/ppapi/DIR_METADATA b/ppapi/DIR_METADATA index 070345d..eb4d302 100644 --- a/ppapi/DIR_METADATA +++ b/ppapi/DIR_METADATA
@@ -1,10 +1,10 @@ # Metadata information for this directory. # # For more information on DIR_METADATA files, see: -# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/README.md +# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/README.md # # For the schema of this file, see Metadata message: -# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/proto/dir_metadata.proto +# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/proto/dir_metadata.proto monorail { component: "Internals>Plugins>Pepper"
diff --git a/ppapi/nacl_irt/DIR_METADATA b/ppapi/nacl_irt/DIR_METADATA index c2353a59..02785b81e 100644 --- a/ppapi/nacl_irt/DIR_METADATA +++ b/ppapi/nacl_irt/DIR_METADATA
@@ -1,10 +1,10 @@ # Metadata information for this directory. # # For more information on DIR_METADATA files, see: -# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/README.md +# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/README.md # # For the schema of this file, see Metadata message: -# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/proto/dir_metadata.proto +# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/proto/dir_metadata.proto monorail { component: "Platform>NaCl"
diff --git a/remoting/host/OWNERS b/remoting/host/OWNERS index ef79bb2bb..a7e6c89 100644 --- a/remoting/host/OWNERS +++ b/remoting/host/OWNERS
@@ -5,4 +5,4 @@ per-file *_messages.cc=file://ipc/SECURITY_OWNERS per-file *_param_traits*.*=set noparent -per-file *_param_traits*.*=file://ipc/SECURITY_OWNERS \ No newline at end of file +per-file *_param_traits*.*=file://ipc/SECURITY_OWNERS
diff --git a/remoting/host/desktop_resizer_mac.cc b/remoting/host/desktop_resizer_mac.cc index 949d68b..0010d119 100644 --- a/remoting/host/desktop_resizer_mac.cc +++ b/remoting/host/desktop_resizer_mac.cc
@@ -23,7 +23,9 @@ class DesktopResizerMac : public DesktopResizer { public: - DesktopResizerMac(); + DesktopResizerMac() = default; + DesktopResizerMac(const DesktopResizerMac&) = delete; + DesktopResizerMac& operator=(const DesktopResizerMac&) = delete; // DesktopResizer interface ScreenResolution GetCurrentResolution() override; @@ -40,12 +42,8 @@ void GetSupportedModesAndResolutions( base::ScopedCFTypeRef<CFMutableArrayRef>* modes, std::list<ScreenResolution>* resolutions); - - DISALLOW_COPY_AND_ASSIGN(DesktopResizerMac); }; -DesktopResizerMac::DesktopResizerMac() {} - ScreenResolution DesktopResizerMac::GetCurrentResolution() { CGDirectDisplayID display; if (GetSoleDisplayId(&display)) {
diff --git a/remoting/host/desktop_resizer_win.cc b/remoting/host/desktop_resizer_win.cc index 26ab2ab..007fc3e 100644 --- a/remoting/host/desktop_resizer_win.cc +++ b/remoting/host/desktop_resizer_win.cc
@@ -10,7 +10,6 @@ #include "base/check.h" #include "base/logging.h" -#include "base/macros.h" #include "base/memory/ptr_util.h" namespace { @@ -36,6 +35,8 @@ class DesktopResizerWin : public DesktopResizer { public: DesktopResizerWin(); + DesktopResizerWin(const DesktopResizerWin&) = delete; + DesktopResizerWin& operator=(const DesktopResizerWin&) = delete; ~DesktopResizerWin() override; // DesktopResizer interface. @@ -64,8 +65,6 @@ std::map<ScreenResolution, DEVMODE> best_mode_for_resolution_; DEVMODE initial_mode_; - - DISALLOW_COPY_AND_ASSIGN(DesktopResizerWin); }; DesktopResizerWin::DesktopResizerWin() {
diff --git a/remoting/host/it2me/BUILD.gn b/remoting/host/it2me/BUILD.gn index 0a50599..b320b88 100644 --- a/remoting/host/it2me/BUILD.gn +++ b/remoting/host/it2me/BUILD.gn
@@ -61,17 +61,24 @@ deps = [ "//base:i18n", "//build:chromeos_buildflags", + "//components/policy:policy_code_generate", + "//extensions/browser/api/messaging:native_messaging", "//mojo/core/embedder", "//net", "//remoting/base", + "//remoting/base:authorization", + "//remoting/host:base", "//remoting/host:common", + "//remoting/host/native_messaging:native_messaging", "//remoting/protocol", "//remoting/resources", "//remoting/signaling", + "//services/network/public/cpp:cpp", ] if (is_linux && !is_chromeos_lacros) { deps += [ "//build/config/linux/gtk", + "//ui/base:base", # GTK pulls pangoft2, which requires HarfBuzz symbols. When linking # our own HarfBuzz avoid mixing symbols from system HarfBuzz and @@ -79,6 +86,15 @@ "//third_party:freetype_harfbuzz", ] } + if (is_chromeos_ash) { + deps += [ "//remoting/host/chromeos:chromeos" ] + } + if (is_mac) { + deps += [ "//ui/base:base" ] + } + if (is_win) { + deps += [ "//remoting/host/win:elevated_native_messaging_host" ] + } } if (is_chromeos_ash || is_chromeos_lacros) { @@ -105,6 +121,9 @@ deps = [ ":common", + "//extensions/browser/api/messaging:native_messaging", + "//remoting/base:base", + "//remoting/host:common", "//skia", ] @@ -254,6 +273,13 @@ } deps += [ ":remote_assistance_host_icons", + "//mojo/core/embedder:embedder", + "//net:net", + "//remoting/base:base", + "//remoting/base:breakpad", + "//remoting/host:base", + "//remoting/host:host_settings", + "//remoting/host:logging", "//remoting/host:remoting_infoplist_strings", "//remoting/host/mac:permission_checking", "//remoting/resources:copy_locales", @@ -264,7 +290,16 @@ } if (is_linux && !is_chromeos_lacros) { - deps += [ "//build/config/linux/gtk" ] + deps += [ + "//build/config/linux/gtk", + "//mojo/core/embedder:embedder", + "//net:net", + "//remoting/base:base", + "//remoting/base:breakpad", + "//remoting/host:base", + "//remoting/host:host_settings", + "//ui/events/platform/x11:x11", + ] } } }
diff --git a/remoting/resources/OWNERS b/remoting/resources/OWNERS index 379aa51b..a0d1e83 100644 --- a/remoting/resources/OWNERS +++ b/remoting/resources/OWNERS
@@ -1,2 +1,2 @@ # For adding or removing languages. -per-file *.grd=claudiomagni@chromium.org \ No newline at end of file +per-file *.grd=claudiomagni@chromium.org
diff --git a/testing/DIR_METADATA b/testing/DIR_METADATA index d53136c..cc209b0b 100644 --- a/testing/DIR_METADATA +++ b/testing/DIR_METADATA
@@ -1,10 +1,10 @@ # Metadata information for this directory. # # For more information on DIR_METADATA files, see: -# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/README.md +# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/README.md # # For the schema of this file, see Metadata message: -# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/proto/dir_metadata.proto +# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/proto/dir_metadata.proto # These aren't actually great contact points for this directory, but # changes in this directory are rare and most changes happen in better-owned
diff --git a/testing/android/DIR_METADATA b/testing/android/DIR_METADATA index be7428a..d503b44 100644 --- a/testing/android/DIR_METADATA +++ b/testing/android/DIR_METADATA
@@ -1,10 +1,10 @@ # Metadata information for this directory. # # For more information on DIR_METADATA files, see: -# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/README.md +# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/README.md # # For the schema of this file, see Metadata message: -# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/proto/dir_metadata.proto +# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/proto/dir_metadata.proto monorail { component: "Test>Android"
diff --git a/testing/android/docs/gtest_implementation.md b/testing/android/docs/gtest_implementation.md index b76a91f..40b78a5 100644 --- a/testing/android/docs/gtest_implementation.md +++ b/testing/android/docs/gtest_implementation.md
@@ -23,7 +23,7 @@ ``` This uses gn's native -[shared_library](https://chromium.googlesource.com/chromium/src/+/master/tools/gn/docs/reference.md#shared_library_Declare-a-shared-library-target) +[shared_library](https://chromium.googlesource.com/chromium/src/+/main/tools/gn/docs/reference.md#shared_library_Declare-a-shared-library-target) target type along with the [unittest_apk](https://codesearch.chromium.org/chromium/src/build/config/android/rules.gni?type=cs&q=file:%5Esrc%5C/build%5C/config%5C/android%5C/rules.gni$+template%5C(%5C"unittest_apk%5C"%5C)&sq=package:chromium) template to build an APK containing: @@ -111,7 +111,7 @@ ``` This uses gn's native -[executable](https://chromium.googlesource.com/chromium/src/+/master/tools/gn/docs/reference.md#executable_Declare-an-executable-target) +[executable](https://chromium.googlesource.com/chromium/src/+/main/tools/gn/docs/reference.md#executable_Declare-an-executable-target) target type, then copies the resulting executable and any requisite shared libraries to ```${root_out_dir}/${target_name}__dist``` (e.g. ```out/Debug/breakpad_unittests__dist```).
diff --git a/testing/android/docs/instrumentation.md b/testing/android/docs/instrumentation.md index e598b607..5a40e43 100644 --- a/testing/android/docs/instrumentation.md +++ b/testing/android/docs/instrumentation.md
@@ -74,7 +74,7 @@ #### Test Batching -The [`@Batch("group_name")`](https://chromium.googlesource.com/chromium/src/+/master/base/test/android/javatests/src/org/chromium/base/test/util/Batch.java) +The [`@Batch("group_name")`](https://chromium.googlesource.com/chromium/src/+/main/base/test/android/javatests/src/org/chromium/base/test/util/Batch.java) annotation is used to run all tests with the same batch group name in the same instrumentation invocation. In other words, the browser process is not restarted between these tests, and so any changes to global state, like @@ -100,18 +100,18 @@ - [`@LargeTest`](https://developer.android.com/reference/android/support/test/filters/LargeTest.html) (timeout: **2 minutes**) A few additional size annotations are provided in -[//base](https://chromium.googlesource.com/chromium/src/+/master/base): +[//base](https://chromium.googlesource.com/chromium/src/+/main/base): - - [`@EnormousTest`](https://chromium.googlesource.com/chromium/src/+/master/base/test/android/javatests/src/org/chromium/base/test/util/EnormousTest.java) + - [`@EnormousTest`](https://chromium.googlesource.com/chromium/src/+/main/base/test/android/javatests/src/org/chromium/base/test/util/EnormousTest.java) (timeout: **5 minutes**) Typically used for tests that require WiFi. - - [`@IntegrationTest`](https://chromium.googlesource.com/chromium/src/+/master/base/test/android/javatests/src/org/chromium/base/test/util/IntegrationTest.java) + - [`@IntegrationTest`](https://chromium.googlesource.com/chromium/src/+/main/base/test/android/javatests/src/org/chromium/base/test/util/IntegrationTest.java) (timeout: **10 minutes**) Used for tests that run against real services. - - [`@Manual`](https://chromium.googlesource.com/chromium/src/+/master/base/test/android/javatests/src/org/chromium/base/test/util/Manual.java) + - [`@Manual`](https://chromium.googlesource.com/chromium/src/+/main/base/test/android/javatests/src/org/chromium/base/test/util/Manual.java) (timeout: **10 hours**) Used for manual tests. Beware that the timeout durations for these annotations are subject to change, though they rarely do. These values are defined -[here](https://chromium.googlesource.com/chromium/src/+/master/build/android/pylib/local/device/local_device_instrumentation_test_run.py#20). +[here](https://chromium.googlesource.com/chromium/src/+/main/build/android/pylib/local/device/local_device_instrumentation_test_run.py#20). #### Annotations that disable tests @@ -120,7 +120,7 @@ ##### Unconditional disabling -[**@DisabledTest**](https://chromium.googlesource.com/chromium/src/+/master/base/test/android/javatests/src/org/chromium/base/test/util/DisabledTest.java) +[**@DisabledTest**](https://chromium.googlesource.com/chromium/src/+/main/base/test/android/javatests/src/org/chromium/base/test/util/DisabledTest.java) unconditionally disables a test. ```java @DisabledTest( @@ -129,7 +129,7 @@ ) ``` -[**@FlakyTest**](https://chromium.googlesource.com/chromium/src/+/master/base/test/android/javatests/src/org/chromium/base/test/util/FlakyTest.java) +[**@FlakyTest**](https://chromium.googlesource.com/chromium/src/+/main/base/test/android/javatests/src/org/chromium/base/test/util/FlakyTest.java) marks a test as flaky. This also unconditionally disables the test, though tests marked with **@FlakyTest** are explicitly run on some bots. ```java @@ -162,7 +162,7 @@ was not, is not, and will not be intended to run beyond those configurations. In both cases, conditional disabling manifests as a skipped test. -[**@DisableIf.Build**](https://chromium.googlesource.com/chromium/src/+/master/base/test/android/javatests/src/org/chromium/base/test/util/DisableIf.java#25) +[**@DisableIf.Build**](https://chromium.googlesource.com/chromium/src/+/main/base/test/android/javatests/src/org/chromium/base/test/util/DisableIf.java#25) allows for conditional test disabling based on values in [`android.os.Build`](https://developer.android.com/reference/android/os/Build.html): @@ -194,12 +194,12 @@ ) ``` -[**@DisableIf.Device**](https://chromium.googlesource.com/chromium/src/+/master/base/test/android/javatests/src/org/chromium/base/test/util/DisableIf.java#40) +[**@DisableIf.Device**](https://chromium.googlesource.com/chromium/src/+/main/base/test/android/javatests/src/org/chromium/base/test/util/DisableIf.java#40) allows for conditional test disabling based on whether a device is a phone, a tablet, or a "large tablet" as determined by -[org.chromium.ui.base.DeviceFormFactor](https://chromium.googlesource.com/chromium/src/+/master/ui/android/java/src/org/chromium/ui/base/DeviceFormFactor.java). +[org.chromium.ui.base.DeviceFormFactor](https://chromium.googlesource.com/chromium/src/+/main/ui/android/java/src/org/chromium/ui/base/DeviceFormFactor.java). This is available to tests in -[//ui](https://chromium.googlesource.com/chromium/src/+/master/ui/) +[//ui](https://chromium.googlesource.com/chromium/src/+/main/ui/) or code that uses //ui. ```java @@ -210,7 +210,7 @@ ) ``` -[**@Restriction**](https://chromium.googlesource.com/chromium/src/+/master/base/test/android/javatests/src/org/chromium/base/test/util/Restriction.java) +[**@Restriction**](https://chromium.googlesource.com/chromium/src/+/main/base/test/android/javatests/src/org/chromium/base/test/util/Restriction.java) currently allows for conditional test disabling based on device type, device performance, internet connectivity, whether Google Play Services is up to date, and whether the build was an official one. @@ -246,7 +246,7 @@ ) ``` -[**@MinAndroidSdkLevel**](https://chromium.googlesource.com/chromium/src/+/master/base/test/android/javatests/src/org/chromium/base/test/util/MinAndroidSdkLevel.java) +[**@MinAndroidSdkLevel**](https://chromium.googlesource.com/chromium/src/+/main/base/test/android/javatests/src/org/chromium/base/test/util/MinAndroidSdkLevel.java) is similar to **@Restriction** in purpose in that it's intended to permanently limit a test to only recent versions of Android. @@ -262,13 +262,13 @@ Several annotations affect how a test is run in interesting or nontrivial ways. -[**@CommandLineFlags.Add**](https://chromium.googlesource.com/chromium/src/+/master/base/test/android/javatests/src/org/chromium/base/test/util/CommandLineFlags.java#46) +[**@CommandLineFlags.Add**](https://chromium.googlesource.com/chromium/src/+/main/base/test/android/javatests/src/org/chromium/base/test/util/CommandLineFlags.java#46) and -[**@CommandLineFlags.Remove**](https://chromium.googlesource.com/chromium/src/+/master/base/test/android/javatests/src/org/chromium/base/test/util/CommandLineFlags.java#58) +[**@CommandLineFlags.Remove**](https://chromium.googlesource.com/chromium/src/+/main/base/test/android/javatests/src/org/chromium/base/test/util/CommandLineFlags.java#58) manipulate Chrome's command-line flags on a per-test basis (i.e., the flags handled by -[`org.chromium.base.CommandLine`](https://chromium.googlesource.com/chromium/src/+/master/base/android/java/src/org/chromium/base/CommandLine.java) and -[`base::CommandLine`](https://chromium.googlesource.com/chromium/src/+/master/base/command_line.h)). +[`org.chromium.base.CommandLine`](https://chromium.googlesource.com/chromium/src/+/main/base/android/java/src/org/chromium/base/CommandLine.java) and +[`base::CommandLine`](https://chromium.googlesource.com/chromium/src/+/main/base/command_line.h)). ```java @CommandLineFlags.Add( @@ -288,7 +288,7 @@ #### Feature annotations -[**@Feature**](https://chromium.googlesource.com/chromium/src/+/master/base/test/android/javatests/src/org/chromium/base/test/util/Feature.java) +[**@Feature**](https://chromium.googlesource.com/chromium/src/+/main/base/test/android/javatests/src/org/chromium/base/test/util/Feature.java) has been used inconsistently in Chromium to group tests across test cases according to the feature they're testing.
diff --git a/testing/android/docs/todo.md b/testing/android/docs/todo.md index fa59207b..2721e4c 100644 --- a/testing/android/docs/todo.md +++ b/testing/android/docs/todo.md
@@ -2,4 +2,4 @@ If you'd like more information about what you were looking for, try contacting one of the people listed in -[//testing/android OWNERS](https://chromium.googlesource.com/chromium/src/+/master/testing/android/OWNERS#2). +[//testing/android OWNERS](https://chromium.googlesource.com/chromium/src/+/main/testing/android/OWNERS#2).
diff --git a/testing/buildbot/DIR_METADATA b/testing/buildbot/DIR_METADATA index 3a18da1e..aea61c0b 100644 --- a/testing/buildbot/DIR_METADATA +++ b/testing/buildbot/DIR_METADATA
@@ -1,10 +1,10 @@ # Metadata information for this directory. # # For more information on DIR_METADATA files, see: -# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/README.md +# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/README.md # # For the schema of this file, see Metadata message: -# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/proto/dir_metadata.proto +# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/proto/dir_metadata.proto monorail { component: "Infra>Client>Chrome"
diff --git a/testing/buildbot/chromium.android.fyi.json b/testing/buildbot/chromium.android.fyi.json index 560685a..5f86336 100644 --- a/testing/buildbot/chromium.android.fyi.json +++ b/testing/buildbot/chromium.android.fyi.json
@@ -4689,7 +4689,7 @@ { "cipd_package": "chromium/testing/weblayer-x86", "location": "weblayer_instrumentation_test_M90", - "revision": "version:90.0.4430.218" + "revision": "version:90.0.4430.224" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -4768,7 +4768,7 @@ { "cipd_package": "chromium/testing/weblayer-x86", "location": "weblayer_instrumentation_test_M91", - "revision": "version:91.0.4472.62" + "revision": "version:91.0.4472.72" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -4926,7 +4926,7 @@ { "cipd_package": "chromium/testing/weblayer-x86", "location": "weblayer_instrumentation_test_M90", - "revision": "version:90.0.4430.218" + "revision": "version:90.0.4430.224" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -5005,7 +5005,7 @@ { "cipd_package": "chromium/testing/weblayer-x86", "location": "weblayer_instrumentation_test_M91", - "revision": "version:91.0.4472.62" + "revision": "version:91.0.4472.72" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
diff --git a/testing/buildbot/chromium.android.json b/testing/buildbot/chromium.android.json index dd05fd1..8c41088 100644 --- a/testing/buildbot/chromium.android.json +++ b/testing/buildbot/chromium.android.json
@@ -53852,7 +53852,7 @@ { "cipd_package": "chromium/testing/weblayer-x86", "location": "weblayer_instrumentation_test_M90", - "revision": "version:90.0.4430.218" + "revision": "version:90.0.4430.224" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -53932,7 +53932,7 @@ { "cipd_package": "chromium/testing/weblayer-x86", "location": "weblayer_instrumentation_test_M91", - "revision": "version:91.0.4472.62" + "revision": "version:91.0.4472.72" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -54092,7 +54092,7 @@ { "cipd_package": "chromium/testing/weblayer-x86", "location": "weblayer_instrumentation_test_M90", - "revision": "version:90.0.4430.218" + "revision": "version:90.0.4430.224" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -54172,7 +54172,7 @@ { "cipd_package": "chromium/testing/weblayer-x86", "location": "weblayer_instrumentation_test_M91", - "revision": "version:91.0.4472.62" + "revision": "version:91.0.4472.72" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -54397,7 +54397,7 @@ { "cipd_package": "chromium/testing/weblayer-x86", "location": "weblayer_instrumentation_test_M90", - "revision": "version:90.0.4430.218" + "revision": "version:90.0.4430.224" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -54476,7 +54476,7 @@ { "cipd_package": "chromium/testing/weblayer-x86", "location": "weblayer_instrumentation_test_M91", - "revision": "version:91.0.4472.62" + "revision": "version:91.0.4472.72" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -54634,7 +54634,7 @@ { "cipd_package": "chromium/testing/weblayer-x86", "location": "weblayer_instrumentation_test_M90", - "revision": "version:90.0.4430.218" + "revision": "version:90.0.4430.224" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -54713,7 +54713,7 @@ { "cipd_package": "chromium/testing/weblayer-x86", "location": "weblayer_instrumentation_test_M91", - "revision": "version:91.0.4472.62" + "revision": "version:91.0.4472.72" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -54938,7 +54938,7 @@ { "cipd_package": "chromium/testing/weblayer-x86", "location": "weblayer_instrumentation_test_M90", - "revision": "version:90.0.4430.218" + "revision": "version:90.0.4430.224" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -55017,7 +55017,7 @@ { "cipd_package": "chromium/testing/weblayer-x86", "location": "weblayer_instrumentation_test_M91", - "revision": "version:91.0.4472.62" + "revision": "version:91.0.4472.72" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -55175,7 +55175,7 @@ { "cipd_package": "chromium/testing/weblayer-x86", "location": "weblayer_instrumentation_test_M90", - "revision": "version:90.0.4430.218" + "revision": "version:90.0.4430.224" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -55254,7 +55254,7 @@ { "cipd_package": "chromium/testing/weblayer-x86", "location": "weblayer_instrumentation_test_M91", - "revision": "version:91.0.4472.62" + "revision": "version:91.0.4472.72" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
diff --git a/testing/buildbot/filters/PRESUBMIT.py b/testing/buildbot/filters/PRESUBMIT.py index dae77206..25a7cac 100644 --- a/testing/buildbot/filters/PRESUBMIT.py +++ b/testing/buildbot/filters/PRESUBMIT.py
@@ -15,7 +15,7 @@ """This ensures all modified filter files are free of common syntax errors. See the following for the correct syntax of these files: - https://chromium.googlesource.com/chromium/src/+/master/testing/buildbot/filters/README.md#file-syntax + https://chromium.googlesource.com/chromium/src/+/main/testing/buildbot/filters/README.md#file-syntax As well as: https://bit.ly/chromium-test-list-format """
diff --git a/testing/buildbot/filters/ozone-linux.wayland_views_unittests.filter b/testing/buildbot/filters/ozone-linux.wayland_views_unittests.filter index 54f61f0..809a776 100644 --- a/testing/buildbot/filters/ozone-linux.wayland_views_unittests.filter +++ b/testing/buildbot/filters/ozone-linux.wayland_views_unittests.filter
@@ -6,30 +6,3 @@ # Tests behaviour that is specific for X11. -DesktopWidgetTest.GetWindowPlacement - -# crbug.com/1186996: tests below require XKB. --EditableComboboxTest.TypingInTextfieldUnhighlightsMenuItem --EditableComboboxTest.EscClosesMenuWithoutSelectingHighlightedMenuItem --ExtensionsMenuViewBrowserTest.InvokeUi_UninstallDialog_Cancel --SubresourceRedirectLoginRobotsBrowserTest.TestRobotsRulesFetchTimeout --TextfieldTest.ContextMenuDisplayTest --TextfieldTest.ControlAndSelectTest --TextfieldTest.CursorMovement --TextfieldTest.CursorViewHeight --TextfieldTest.CutCopyPasteWithEditCommand --TextfieldTest.InsertionDeletionTest --TextfieldTest.KeyTest --TextfieldTest.KeyTestControlModifier --TextfieldTest.OnKeyPressBinding --TextfieldTest.OverflowInRTLTest --TextfieldTest.OverflowTest --TextfieldTest.OvertypeMode --TextfieldTest.RedoWithCtrlY --TextfieldTest.SwitchFocusInKeyDown --TextfieldTest.TextCursorDisplayInRTLTest --TextfieldTest.TextCursorDisplayTest --TextfieldTest.TextCursorPositionInLTRTest --TextfieldTest.TextCursorPositionInRTLTest --TextfieldTest.TextInputType_InsertionTest --TextfieldTest.TextfieldBoundsChangeTest --TextfieldTest.UndoRedoTest
diff --git a/testing/buildbot/generate_buildbot_json.py b/testing/buildbot/generate_buildbot_json.py index 644fcb5..90072db 100755 --- a/testing/buildbot/generate_buildbot_json.py +++ b/testing/buildbot/generate_buildbot_json.py
@@ -1041,7 +1041,7 @@ assert isinstance(test, dict) # This assumes the recipe logic which prefers 'test' to 'isolate_name' - # https://source.chromium.org/chromium/chromium/tools/build/+/master:scripts/slave/recipe_modules/chromium_tests/generators.py;l=89;drc=14c062ba0eb418d3c4623dde41a753241b9df06b + # https://source.chromium.org/chromium/chromium/tools/build/+/main:scripts/slave/recipe_modules/chromium_tests/generators.py;l=89;drc=14c062ba0eb418d3c4623dde41a753241b9df06b # TODO(crbug.com/1035124): clean this up. isolate_name = test.get('test') or test.get('isolate_name') or key gn_entry = self.gn_isolate_map.get(isolate_name)
diff --git a/testing/buildbot/scripts/upload_test_result_artifacts.py b/testing/buildbot/scripts/upload_test_result_artifacts.py index 92324fd9..8697994 100755 --- a/testing/buildbot/scripts/upload_test_result_artifacts.py +++ b/testing/buildbot/scripts/upload_test_result_artifacts.py
@@ -6,7 +6,7 @@ This script takes a list of json test results files, the format of which is described in -https://chromium.googlesource.com/chromium/src/+/master/docs/testing/json_test_results_format.md. +https://chromium.googlesource.com/chromium/src/+/main/docs/testing/json_test_results_format.md. For each file, it looks for test artifacts embedded in each test. It detects this by looking for the top level "artifact_type_info" key.
diff --git a/testing/buildbot/variants.pyl b/testing/buildbot/variants.pyl index 21cc864..fe6b24c 100644 --- a/testing/buildbot/variants.pyl +++ b/testing/buildbot/variants.pyl
@@ -352,7 +352,7 @@ { 'cipd_package': 'chromium/testing/weblayer-x86', 'location': 'weblayer_instrumentation_test_M91', - 'revision': 'version:91.0.4472.62', + 'revision': 'version:91.0.4472.72', } ], }, @@ -376,7 +376,7 @@ { 'cipd_package': 'chromium/testing/weblayer-x86', 'location': 'weblayer_instrumentation_test_M90', - 'revision': 'version:90.0.4430.218', + 'revision': 'version:90.0.4430.224', } ], }, @@ -424,7 +424,7 @@ { 'cipd_package': 'chromium/testing/weblayer-x86', 'location': 'weblayer_instrumentation_test_M91', - 'revision': 'version:91.0.4472.62', + 'revision': 'version:91.0.4472.72', } ], }, @@ -448,7 +448,7 @@ { 'cipd_package': 'chromium/testing/weblayer-x86', 'location': 'weblayer_instrumentation_test_M90', - 'revision': 'version:90.0.4430.218', + 'revision': 'version:90.0.4430.224', } ], }, @@ -496,7 +496,7 @@ { 'cipd_package': 'chromium/testing/weblayer-x86', 'location': 'weblayer_instrumentation_test_M91', - 'revision': 'version:91.0.4472.62', + 'revision': 'version:91.0.4472.72', } ], }, @@ -520,7 +520,7 @@ { 'cipd_package': 'chromium/testing/weblayer-x86', 'location': 'weblayer_instrumentation_test_M90', - 'revision': 'version:90.0.4430.218', + 'revision': 'version:90.0.4430.224', } ], },
diff --git a/testing/chromoting/DIR_METADATA b/testing/chromoting/DIR_METADATA index 8d2b486..0ffd3c7 100644 --- a/testing/chromoting/DIR_METADATA +++ b/testing/chromoting/DIR_METADATA
@@ -1,10 +1,10 @@ # Metadata information for this directory. # # For more information on DIR_METADATA files, see: -# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/README.md +# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/README.md # # For the schema of this file, see Metadata message: -# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/proto/dir_metadata.proto +# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/proto/dir_metadata.proto monorail { component: "Services>Chromoting"
diff --git a/testing/clusterfuzz/DIR_METADATA b/testing/clusterfuzz/DIR_METADATA index ee0a9c1..be80138 100644 --- a/testing/clusterfuzz/DIR_METADATA +++ b/testing/clusterfuzz/DIR_METADATA
@@ -1,10 +1,10 @@ # Metadata information for this directory. # # For more information on DIR_METADATA files, see: -# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/README.md +# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/README.md # # For the schema of this file, see Metadata message: -# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/proto/dir_metadata.proto +# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/proto/dir_metadata.proto monorail { component: "Tools>Stability>Clusterfuzz"
diff --git a/testing/generate_location_tags.py b/testing/generate_location_tags.py index 2860d9db..19b275db 100755 --- a/testing/generate_location_tags.py +++ b/testing/generate_location_tags.py
@@ -7,7 +7,7 @@ # pylint: disable=line-too-long # # For more on the tags, see -# https://source.chromium.org/chromium/infra/infra/+/master:go/src/go.chromium.org/luci/resultdb/sink/proto/v1/location_tag.proto +# https://source.chromium.org/chromium/infra/infra/+/main:go/src/go.chromium.org/luci/resultdb/sink/proto/v1/location_tag.proto # # pylint: enable=line-too-long
diff --git a/testing/libfuzzer/unittest_main.cc b/testing/libfuzzer/unittest_main.cc index 87c70694..01a7af3 100644 --- a/testing/libfuzzer/unittest_main.cc +++ b/testing/libfuzzer/unittest_main.cc
@@ -42,7 +42,7 @@ "Alternatively, try building this target with " "use_libfuzzer=true for a better test driver. For details see:\n" "\n" - "https://chromium.googlesource.com/chromium/src/+/master/" + "https://chromium.googlesource.com/chromium/src/+/main/" "testing/libfuzzer/getting_started.md" << std::endl; exit(1);
diff --git a/testing/merge_scripts/code_coverage/merge_results.py b/testing/merge_scripts/code_coverage/merge_results.py index fcb8723..073207a0 100755 --- a/testing/merge_scripts/code_coverage/merge_results.py +++ b/testing/merge_scripts/code_coverage/merge_results.py
@@ -23,7 +23,7 @@ def _MergeAPIArgumentParser(*args, **kwargs): """Parameters passed to this merge script, as per: - https://chromium.googlesource.com/chromium/tools/build/+/master/scripts/slave/recipe_modules/swarming/resources/merge_api.py + https://chromium.googlesource.com/chromium/tools/build/+/main/scripts/slave/recipe_modules/swarming/resources/merge_api.py """ parser = argparse.ArgumentParser(*args, **kwargs) parser.add_argument('--build-properties', help=argparse.SUPPRESS)
diff --git a/testing/scripts/DIR_METADATA b/testing/scripts/DIR_METADATA index 3a18da1e..aea61c0b 100644 --- a/testing/scripts/DIR_METADATA +++ b/testing/scripts/DIR_METADATA
@@ -1,10 +1,10 @@ # Metadata information for this directory. # # For more information on DIR_METADATA files, see: -# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/README.md +# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/README.md # # For the schema of this file, see Metadata message: -# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/proto/dir_metadata.proto +# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/proto/dir_metadata.proto monorail { component: "Infra>Client>Chrome"
diff --git a/testing/scripts/run_performance_tests.py b/testing/scripts/run_performance_tests.py index a098937..d2d2e36 100755 --- a/testing/scripts/run_performance_tests.py +++ b/testing/scripts/run_performance_tests.py
@@ -40,7 +40,7 @@ is the perf specific results (with unenforced format, could be histogram or graph json), and test_results.json, which is a JSON test results format file -https://chromium.googlesource.com/chromium/src/+/master/docs/testing/json_test_results_format.md +https://chromium.googlesource.com/chromium/src/+/main/docs/testing/json_test_results_format.md TESTING: To test changes to this script, please run @@ -246,7 +246,7 @@ def write_simple_test_results(return_code, output_filepath, benchmark_name): # TODO(crbug.com/1115658): Fix to output - # https://chromium.googlesource.com/chromium/src/+/master/docs/testing/json_test_results_format.md + # https://chromium.googlesource.com/chromium/src/+/main/docs/testing/json_test_results_format.md # for each test rather than this summary. # Append the shard index to the end of the name so that the merge script # doesn't blow up trying to merge unmergeable results.
diff --git a/testing/scripts/wpt_common.py b/testing/scripts/wpt_common.py index ae36261..6631b89 100644 --- a/testing/scripts/wpt_common.py +++ b/testing/scripts/wpt_common.py
@@ -72,7 +72,7 @@ os.path.join(layout_test_results, 'full_results.json'), os.path.join(layout_test_results, 'full_results_jsonp.js'), # NOTE: Despite the name, this is actually a JSONP file. - # https://source.chromium.org/chromium/chromium/src/+/master:third_party/blink/tools/blinkpy/web_tests/controllers/manager.py;l=636;drc=3b93609b2498af0e9dc298f64e2b4f6204af68fa + # https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/tools/blinkpy/web_tests/controllers/manager.py;l=636;drc=3b93609b2498af0e9dc298f64e2b4f6204af68fa os.path.join(layout_test_results, 'failing_results.json'), ) @@ -109,7 +109,7 @@ self.fs.copyfile(self.wpt_output, full_results_json) # JSONP paddings need to be the same as - # https://source.chromium.org/chromium/chromium/src/+/master:third_party/blink/tools/blinkpy/web_tests/controllers/manager.py;l=629;drc=3b93609b2498af0e9dc298f64e2b4f6204af68fa + # https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/tools/blinkpy/web_tests/controllers/manager.py;l=629;drc=3b93609b2498af0e9dc298f64e2b4f6204af68fa # Write to full_results.jsonp with self.fs.open_text_file_for_writing(full_results_jsonp) as f: f.write('ADD_FULL_RESULTS(')
diff --git a/testing/test_env.py b/testing/test_env.py index a333222a..32d2020 100755 --- a/testing/test_env.py +++ b/testing/test_env.py
@@ -185,7 +185,7 @@ """Run command and stream its stdout/stderr to the console & |stdoutfile|. Also forward_signals to obey - https://chromium.googlesource.com/infra/luci/luci-py/+/master/appengine/swarming/doc/Bot.md#graceful-termination_aka-the-sigterm-and-sigkill-dance + https://chromium.googlesource.com/infra/luci/luci-py/+/main/appengine/swarming/doc/Bot.md#graceful-termination_aka-the-sigterm-and-sigkill-dance Returns: integer returncode of the subprocess. @@ -212,7 +212,7 @@ """Run command and stream its stdout/stderr both to stdout. Also forward_signals to obey - https://chromium.googlesource.com/infra/luci/luci-py/+/master/appengine/swarming/doc/Bot.md#graceful-termination_aka-the-sigterm-and-sigkill-dance + https://chromium.googlesource.com/infra/luci/luci-py/+/main/appengine/swarming/doc/Bot.md#graceful-termination_aka-the-sigterm-and-sigkill-dance Returns: integer returncode of the subprocess. @@ -228,7 +228,7 @@ """Run command and stream its stdout/stderr both to |file_handle|. Also forward_signals to obey - https://chromium.googlesource.com/infra/luci/luci-py/+/master/appengine/swarming/doc/Bot.md#graceful-termination_aka-the-sigterm-and-sigkill-dance + https://chromium.googlesource.com/infra/luci/luci-py/+/main/appengine/swarming/doc/Bot.md#graceful-termination_aka-the-sigterm-and-sigkill-dance Returns: integer returncode of the subprocess. @@ -268,7 +268,7 @@ """Forwards unix's SIGTERM or win's CTRL_BREAK_EVENT to the given processes. This plays nicely with swarming's timeout handling. See also - https://chromium.googlesource.com/infra/luci/luci-py/+/master/appengine/swarming/doc/Bot.md#graceful-termination_aka-the-sigterm-and-sigkill-dance + https://chromium.googlesource.com/infra/luci/luci-py/+/main/appengine/swarming/doc/Bot.md#graceful-termination_aka-the-sigterm-and-sigkill-dance Args: procs: A list of subprocess.Popen objects representing child processes.
diff --git a/testing/variations/DIR_METADATA b/testing/variations/DIR_METADATA index 98a668c..b5d17e5 100644 --- a/testing/variations/DIR_METADATA +++ b/testing/variations/DIR_METADATA
@@ -1,10 +1,10 @@ # Metadata information for this directory. # # For more information on DIR_METADATA files, see: -# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/README.md +# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/README.md # # For the schema of this file, see Metadata message: -# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/proto/dir_metadata.proto +# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/proto/dir_metadata.proto monorail { component: "Internals>Metrics>Variations"
diff --git a/third_party/android_deps/buildSrc/src/main/groovy/BuildConfigGenerator.groovy b/third_party/android_deps/buildSrc/src/main/groovy/BuildConfigGenerator.groovy index 4ad840a8..54e336a 100644 --- a/third_party/android_deps/buildSrc/src/main/groovy/BuildConfigGenerator.groovy +++ b/third_party/android_deps/buildSrc/src/main/groovy/BuildConfigGenerator.groovy
@@ -819,7 +819,7 @@ static String makeOwners() { // Make it easier to upgrade existing dependencies without full third_party review. - return "file://third_party/android_deps/OWNERS" + return "file://third_party/android_deps/OWNERS\n" } static String makeReadme(ChromiumDepGraph.DependencyDescription dependency) {
diff --git a/third_party/android_deps/libs/android_arch_core_common/OWNERS b/third_party/android_deps/libs/android_arch_core_common/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/android_arch_core_common/OWNERS +++ b/third_party/android_deps/libs/android_arch_core_common/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/android_arch_core_runtime/OWNERS b/third_party/android_deps/libs/android_arch_core_runtime/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/android_arch_core_runtime/OWNERS +++ b/third_party/android_deps/libs/android_arch_core_runtime/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/android_arch_lifecycle_common/OWNERS b/third_party/android_deps/libs/android_arch_lifecycle_common/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/android_arch_lifecycle_common/OWNERS +++ b/third_party/android_deps/libs/android_arch_lifecycle_common/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/android_arch_lifecycle_common_java8/OWNERS b/third_party/android_deps/libs/android_arch_lifecycle_common_java8/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/android_arch_lifecycle_common_java8/OWNERS +++ b/third_party/android_deps/libs/android_arch_lifecycle_common_java8/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/android_arch_lifecycle_livedata/OWNERS b/third_party/android_deps/libs/android_arch_lifecycle_livedata/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/android_arch_lifecycle_livedata/OWNERS +++ b/third_party/android_deps/libs/android_arch_lifecycle_livedata/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/android_arch_lifecycle_livedata_core/OWNERS b/third_party/android_deps/libs/android_arch_lifecycle_livedata_core/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/android_arch_lifecycle_livedata_core/OWNERS +++ b/third_party/android_deps/libs/android_arch_lifecycle_livedata_core/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/android_arch_lifecycle_runtime/OWNERS b/third_party/android_deps/libs/android_arch_lifecycle_runtime/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/android_arch_lifecycle_runtime/OWNERS +++ b/third_party/android_deps/libs/android_arch_lifecycle_runtime/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/android_arch_lifecycle_viewmodel/OWNERS b/third_party/android_deps/libs/android_arch_lifecycle_viewmodel/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/android_arch_lifecycle_viewmodel/OWNERS +++ b/third_party/android_deps/libs/android_arch_lifecycle_viewmodel/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/backport_util_concurrent_backport_util_concurrent/OWNERS b/third_party/android_deps/libs/backport_util_concurrent_backport_util_concurrent/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/backport_util_concurrent_backport_util_concurrent/OWNERS +++ b/third_party/android_deps/libs/backport_util_concurrent_backport_util_concurrent/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/classworlds_classworlds/OWNERS b/third_party/android_deps/libs/classworlds_classworlds/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/classworlds_classworlds/OWNERS +++ b/third_party/android_deps/libs/classworlds_classworlds/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/com_android_support_animated_vector_drawable/OWNERS b/third_party/android_deps/libs/com_android_support_animated_vector_drawable/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/com_android_support_animated_vector_drawable/OWNERS +++ b/third_party/android_deps/libs/com_android_support_animated_vector_drawable/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/com_android_support_appcompat_v7/OWNERS b/third_party/android_deps/libs/com_android_support_appcompat_v7/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/com_android_support_appcompat_v7/OWNERS +++ b/third_party/android_deps/libs/com_android_support_appcompat_v7/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/com_android_support_asynclayoutinflater/OWNERS b/third_party/android_deps/libs/com_android_support_asynclayoutinflater/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/com_android_support_asynclayoutinflater/OWNERS +++ b/third_party/android_deps/libs/com_android_support_asynclayoutinflater/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/com_android_support_cardview_v7/OWNERS b/third_party/android_deps/libs/com_android_support_cardview_v7/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/com_android_support_cardview_v7/OWNERS +++ b/third_party/android_deps/libs/com_android_support_cardview_v7/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/com_android_support_collections/OWNERS b/third_party/android_deps/libs/com_android_support_collections/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/com_android_support_collections/OWNERS +++ b/third_party/android_deps/libs/com_android_support_collections/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/com_android_support_coordinatorlayout/OWNERS b/third_party/android_deps/libs/com_android_support_coordinatorlayout/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/com_android_support_coordinatorlayout/OWNERS +++ b/third_party/android_deps/libs/com_android_support_coordinatorlayout/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/com_android_support_cursoradapter/OWNERS b/third_party/android_deps/libs/com_android_support_cursoradapter/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/com_android_support_cursoradapter/OWNERS +++ b/third_party/android_deps/libs/com_android_support_cursoradapter/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/com_android_support_customview/OWNERS b/third_party/android_deps/libs/com_android_support_customview/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/com_android_support_customview/OWNERS +++ b/third_party/android_deps/libs/com_android_support_customview/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/com_android_support_design/OWNERS b/third_party/android_deps/libs/com_android_support_design/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/com_android_support_design/OWNERS +++ b/third_party/android_deps/libs/com_android_support_design/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/com_android_support_documentfile/OWNERS b/third_party/android_deps/libs/com_android_support_documentfile/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/com_android_support_documentfile/OWNERS +++ b/third_party/android_deps/libs/com_android_support_documentfile/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/com_android_support_drawerlayout/OWNERS b/third_party/android_deps/libs/com_android_support_drawerlayout/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/com_android_support_drawerlayout/OWNERS +++ b/third_party/android_deps/libs/com_android_support_drawerlayout/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/com_android_support_interpolator/OWNERS b/third_party/android_deps/libs/com_android_support_interpolator/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/com_android_support_interpolator/OWNERS +++ b/third_party/android_deps/libs/com_android_support_interpolator/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/com_android_support_loader/OWNERS b/third_party/android_deps/libs/com_android_support_loader/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/com_android_support_loader/OWNERS +++ b/third_party/android_deps/libs/com_android_support_loader/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/com_android_support_localbroadcastmanager/OWNERS b/third_party/android_deps/libs/com_android_support_localbroadcastmanager/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/com_android_support_localbroadcastmanager/OWNERS +++ b/third_party/android_deps/libs/com_android_support_localbroadcastmanager/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/com_android_support_multidex/OWNERS b/third_party/android_deps/libs/com_android_support_multidex/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/com_android_support_multidex/OWNERS +++ b/third_party/android_deps/libs/com_android_support_multidex/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/com_android_support_print/OWNERS b/third_party/android_deps/libs/com_android_support_print/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/com_android_support_print/OWNERS +++ b/third_party/android_deps/libs/com_android_support_print/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/com_android_support_recyclerview_v7/OWNERS b/third_party/android_deps/libs/com_android_support_recyclerview_v7/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/com_android_support_recyclerview_v7/OWNERS +++ b/third_party/android_deps/libs/com_android_support_recyclerview_v7/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/com_android_support_slidingpanelayout/OWNERS b/third_party/android_deps/libs/com_android_support_slidingpanelayout/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/com_android_support_slidingpanelayout/OWNERS +++ b/third_party/android_deps/libs/com_android_support_slidingpanelayout/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/com_android_support_support_annotations/OWNERS b/third_party/android_deps/libs/com_android_support_support_annotations/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/com_android_support_support_annotations/OWNERS +++ b/third_party/android_deps/libs/com_android_support_support_annotations/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/com_android_support_support_compat/OWNERS b/third_party/android_deps/libs/com_android_support_support_compat/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/com_android_support_support_compat/OWNERS +++ b/third_party/android_deps/libs/com_android_support_support_compat/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/com_android_support_support_core_ui/OWNERS b/third_party/android_deps/libs/com_android_support_support_core_ui/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/com_android_support_support_core_ui/OWNERS +++ b/third_party/android_deps/libs/com_android_support_support_core_ui/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/com_android_support_support_core_utils/OWNERS b/third_party/android_deps/libs/com_android_support_support_core_utils/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/com_android_support_support_core_utils/OWNERS +++ b/third_party/android_deps/libs/com_android_support_support_core_utils/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/com_android_support_support_fragment/OWNERS b/third_party/android_deps/libs/com_android_support_support_fragment/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/com_android_support_support_fragment/OWNERS +++ b/third_party/android_deps/libs/com_android_support_support_fragment/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/com_android_support_support_media_compat/OWNERS b/third_party/android_deps/libs/com_android_support_support_media_compat/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/com_android_support_support_media_compat/OWNERS +++ b/third_party/android_deps/libs/com_android_support_support_media_compat/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/com_android_support_support_v4/OWNERS b/third_party/android_deps/libs/com_android_support_support_v4/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/com_android_support_support_v4/OWNERS +++ b/third_party/android_deps/libs/com_android_support_support_v4/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/com_android_support_support_vector_drawable/OWNERS b/third_party/android_deps/libs/com_android_support_support_vector_drawable/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/com_android_support_support_vector_drawable/OWNERS +++ b/third_party/android_deps/libs/com_android_support_support_vector_drawable/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/com_android_support_swiperefreshlayout/OWNERS b/third_party/android_deps/libs/com_android_support_swiperefreshlayout/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/com_android_support_swiperefreshlayout/OWNERS +++ b/third_party/android_deps/libs/com_android_support_swiperefreshlayout/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/com_android_support_transition/OWNERS b/third_party/android_deps/libs/com_android_support_transition/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/com_android_support_transition/OWNERS +++ b/third_party/android_deps/libs/com_android_support_transition/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/com_android_support_versionedparcelable/OWNERS b/third_party/android_deps/libs/com_android_support_versionedparcelable/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/com_android_support_versionedparcelable/OWNERS +++ b/third_party/android_deps/libs/com_android_support_versionedparcelable/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/com_android_support_viewpager/OWNERS b/third_party/android_deps/libs/com_android_support_viewpager/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/com_android_support_viewpager/OWNERS +++ b/third_party/android_deps/libs/com_android_support_viewpager/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/com_android_tools_common/OWNERS b/third_party/android_deps/libs/com_android_tools_common/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/com_android_tools_common/OWNERS +++ b/third_party/android_deps/libs/com_android_tools_common/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/com_android_tools_desugar_jdk_libs/OWNERS b/third_party/android_deps/libs/com_android_tools_desugar_jdk_libs/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/com_android_tools_desugar_jdk_libs/OWNERS +++ b/third_party/android_deps/libs/com_android_tools_desugar_jdk_libs/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/com_android_tools_desugar_jdk_libs_configuration/OWNERS b/third_party/android_deps/libs/com_android_tools_desugar_jdk_libs_configuration/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/com_android_tools_desugar_jdk_libs_configuration/OWNERS +++ b/third_party/android_deps/libs/com_android_tools_desugar_jdk_libs_configuration/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/com_android_tools_layoutlib_layoutlib_api/OWNERS b/third_party/android_deps/libs/com_android_tools_layoutlib_layoutlib_api/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/com_android_tools_layoutlib_layoutlib_api/OWNERS +++ b/third_party/android_deps/libs/com_android_tools_layoutlib_layoutlib_api/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/com_android_tools_sdk_common/OWNERS b/third_party/android_deps/libs/com_android_tools_sdk_common/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/com_android_tools_sdk_common/OWNERS +++ b/third_party/android_deps/libs/com_android_tools_sdk_common/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/com_github_ben_manes_caffeine_caffeine/OWNERS b/third_party/android_deps/libs/com_github_ben_manes_caffeine_caffeine/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/com_github_ben_manes_caffeine_caffeine/OWNERS +++ b/third_party/android_deps/libs/com_github_ben_manes_caffeine_caffeine/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/com_github_kevinstern_software_and_algorithms/OWNERS b/third_party/android_deps/libs/com_github_kevinstern_software_and_algorithms/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/com_github_kevinstern_software_and_algorithms/OWNERS +++ b/third_party/android_deps/libs/com_github_kevinstern_software_and_algorithms/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/com_google_android_datatransport_transport_api/OWNERS b/third_party/android_deps/libs/com_google_android_datatransport_transport_api/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/com_google_android_datatransport_transport_api/OWNERS +++ b/third_party/android_deps/libs/com_google_android_datatransport_transport_api/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/com_google_android_gms_play_services_auth/OWNERS b/third_party/android_deps/libs/com_google_android_gms_play_services_auth/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/com_google_android_gms_play_services_auth/OWNERS +++ b/third_party/android_deps/libs/com_google_android_gms_play_services_auth/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/com_google_android_gms_play_services_auth_api_phone/OWNERS b/third_party/android_deps/libs/com_google_android_gms_play_services_auth_api_phone/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/com_google_android_gms_play_services_auth_api_phone/OWNERS +++ b/third_party/android_deps/libs/com_google_android_gms_play_services_auth_api_phone/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/com_google_android_gms_play_services_auth_base/OWNERS b/third_party/android_deps/libs/com_google_android_gms_play_services_auth_base/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/com_google_android_gms_play_services_auth_base/OWNERS +++ b/third_party/android_deps/libs/com_google_android_gms_play_services_auth_base/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/com_google_android_gms_play_services_base/OWNERS b/third_party/android_deps/libs/com_google_android_gms_play_services_base/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/com_google_android_gms_play_services_base/OWNERS +++ b/third_party/android_deps/libs/com_google_android_gms_play_services_base/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/com_google_android_gms_play_services_basement/OWNERS b/third_party/android_deps/libs/com_google_android_gms_play_services_basement/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/com_google_android_gms_play_services_basement/OWNERS +++ b/third_party/android_deps/libs/com_google_android_gms_play_services_basement/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/com_google_android_gms_play_services_cast/OWNERS b/third_party/android_deps/libs/com_google_android_gms_play_services_cast/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/com_google_android_gms_play_services_cast/OWNERS +++ b/third_party/android_deps/libs/com_google_android_gms_play_services_cast/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/com_google_android_gms_play_services_cast_framework/OWNERS b/third_party/android_deps/libs/com_google_android_gms_play_services_cast_framework/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/com_google_android_gms_play_services_cast_framework/OWNERS +++ b/third_party/android_deps/libs/com_google_android_gms_play_services_cast_framework/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/com_google_android_gms_play_services_clearcut/OWNERS b/third_party/android_deps/libs/com_google_android_gms_play_services_clearcut/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/com_google_android_gms_play_services_clearcut/OWNERS +++ b/third_party/android_deps/libs/com_google_android_gms_play_services_clearcut/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/com_google_android_gms_play_services_cloud_messaging/OWNERS b/third_party/android_deps/libs/com_google_android_gms_play_services_cloud_messaging/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/com_google_android_gms_play_services_cloud_messaging/OWNERS +++ b/third_party/android_deps/libs/com_google_android_gms_play_services_cloud_messaging/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/com_google_android_gms_play_services_fido/OWNERS b/third_party/android_deps/libs/com_google_android_gms_play_services_fido/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/com_google_android_gms_play_services_fido/OWNERS +++ b/third_party/android_deps/libs/com_google_android_gms_play_services_fido/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/com_google_android_gms_play_services_flags/OWNERS b/third_party/android_deps/libs/com_google_android_gms_play_services_flags/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/com_google_android_gms_play_services_flags/OWNERS +++ b/third_party/android_deps/libs/com_google_android_gms_play_services_flags/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/com_google_android_gms_play_services_gcm/OWNERS b/third_party/android_deps/libs/com_google_android_gms_play_services_gcm/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/com_google_android_gms_play_services_gcm/OWNERS +++ b/third_party/android_deps/libs/com_google_android_gms_play_services_gcm/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/com_google_android_gms_play_services_iid/OWNERS b/third_party/android_deps/libs/com_google_android_gms_play_services_iid/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/com_google_android_gms_play_services_iid/OWNERS +++ b/third_party/android_deps/libs/com_google_android_gms_play_services_iid/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/com_google_android_gms_play_services_instantapps/OWNERS b/third_party/android_deps/libs/com_google_android_gms_play_services_instantapps/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/com_google_android_gms_play_services_instantapps/OWNERS +++ b/third_party/android_deps/libs/com_google_android_gms_play_services_instantapps/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/com_google_android_gms_play_services_location/OWNERS b/third_party/android_deps/libs/com_google_android_gms_play_services_location/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/com_google_android_gms_play_services_location/OWNERS +++ b/third_party/android_deps/libs/com_google_android_gms_play_services_location/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/com_google_android_gms_play_services_phenotype/OWNERS b/third_party/android_deps/libs/com_google_android_gms_play_services_phenotype/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/com_google_android_gms_play_services_phenotype/OWNERS +++ b/third_party/android_deps/libs/com_google_android_gms_play_services_phenotype/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/com_google_android_gms_play_services_places_placereport/OWNERS b/third_party/android_deps/libs/com_google_android_gms_play_services_places_placereport/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/com_google_android_gms_play_services_places_placereport/OWNERS +++ b/third_party/android_deps/libs/com_google_android_gms_play_services_places_placereport/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/com_google_android_gms_play_services_stats/OWNERS b/third_party/android_deps/libs/com_google_android_gms_play_services_stats/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/com_google_android_gms_play_services_stats/OWNERS +++ b/third_party/android_deps/libs/com_google_android_gms_play_services_stats/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/com_google_android_gms_play_services_tasks/OWNERS b/third_party/android_deps/libs/com_google_android_gms_play_services_tasks/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/com_google_android_gms_play_services_tasks/OWNERS +++ b/third_party/android_deps/libs/com_google_android_gms_play_services_tasks/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/com_google_android_gms_play_services_vision/OWNERS b/third_party/android_deps/libs/com_google_android_gms_play_services_vision/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/com_google_android_gms_play_services_vision/OWNERS +++ b/third_party/android_deps/libs/com_google_android_gms_play_services_vision/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/com_google_android_gms_play_services_vision_common/OWNERS b/third_party/android_deps/libs/com_google_android_gms_play_services_vision_common/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/com_google_android_gms_play_services_vision_common/OWNERS +++ b/third_party/android_deps/libs/com_google_android_gms_play_services_vision_common/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/com_google_android_material_material/OWNERS b/third_party/android_deps/libs/com_google_android_material_material/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/com_google_android_material_material/OWNERS +++ b/third_party/android_deps/libs/com_google_android_material_material/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/com_google_auto_auto_common/OWNERS b/third_party/android_deps/libs/com_google_auto_auto_common/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/com_google_auto_auto_common/OWNERS +++ b/third_party/android_deps/libs/com_google_auto_auto_common/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/com_google_auto_service_auto_service/OWNERS b/third_party/android_deps/libs/com_google_auto_service_auto_service/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/com_google_auto_service_auto_service/OWNERS +++ b/third_party/android_deps/libs/com_google_auto_service_auto_service/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/com_google_auto_service_auto_service_annotations/OWNERS b/third_party/android_deps/libs/com_google_auto_service_auto_service_annotations/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/com_google_auto_service_auto_service_annotations/OWNERS +++ b/third_party/android_deps/libs/com_google_auto_service_auto_service_annotations/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/com_google_auto_value_auto_value_annotations/OWNERS b/third_party/android_deps/libs/com_google_auto_value_auto_value_annotations/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/com_google_auto_value_auto_value_annotations/OWNERS +++ b/third_party/android_deps/libs/com_google_auto_value_auto_value_annotations/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/com_google_code_findbugs_jformatstring/OWNERS b/third_party/android_deps/libs/com_google_code_findbugs_jformatstring/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/com_google_code_findbugs_jformatstring/OWNERS +++ b/third_party/android_deps/libs/com_google_code_findbugs_jformatstring/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/com_google_code_findbugs_jsr305/OWNERS b/third_party/android_deps/libs/com_google_code_findbugs_jsr305/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/com_google_code_findbugs_jsr305/OWNERS +++ b/third_party/android_deps/libs/com_google_code_findbugs_jsr305/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/com_google_code_gson_gson/OWNERS b/third_party/android_deps/libs/com_google_code_gson_gson/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/com_google_code_gson_gson/OWNERS +++ b/third_party/android_deps/libs/com_google_code_gson_gson/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/com_google_dagger_dagger/OWNERS b/third_party/android_deps/libs/com_google_dagger_dagger/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/com_google_dagger_dagger/OWNERS +++ b/third_party/android_deps/libs/com_google_dagger_dagger/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/com_google_dagger_dagger_compiler/OWNERS b/third_party/android_deps/libs/com_google_dagger_dagger_compiler/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/com_google_dagger_dagger_compiler/OWNERS +++ b/third_party/android_deps/libs/com_google_dagger_dagger_compiler/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/com_google_dagger_dagger_producers/OWNERS b/third_party/android_deps/libs/com_google_dagger_dagger_producers/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/com_google_dagger_dagger_producers/OWNERS +++ b/third_party/android_deps/libs/com_google_dagger_dagger_producers/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/com_google_dagger_dagger_spi/OWNERS b/third_party/android_deps/libs/com_google_dagger_dagger_spi/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/com_google_dagger_dagger_spi/OWNERS +++ b/third_party/android_deps/libs/com_google_dagger_dagger_spi/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/com_google_errorprone_error_prone_annotation/OWNERS b/third_party/android_deps/libs/com_google_errorprone_error_prone_annotation/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/com_google_errorprone_error_prone_annotation/OWNERS +++ b/third_party/android_deps/libs/com_google_errorprone_error_prone_annotation/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/com_google_errorprone_error_prone_annotations/OWNERS b/third_party/android_deps/libs/com_google_errorprone_error_prone_annotations/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/com_google_errorprone_error_prone_annotations/OWNERS +++ b/third_party/android_deps/libs/com_google_errorprone_error_prone_annotations/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/com_google_errorprone_error_prone_check_api/OWNERS b/third_party/android_deps/libs/com_google_errorprone_error_prone_check_api/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/com_google_errorprone_error_prone_check_api/OWNERS +++ b/third_party/android_deps/libs/com_google_errorprone_error_prone_check_api/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/com_google_errorprone_error_prone_core/OWNERS b/third_party/android_deps/libs/com_google_errorprone_error_prone_core/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/com_google_errorprone_error_prone_core/OWNERS +++ b/third_party/android_deps/libs/com_google_errorprone_error_prone_core/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/com_google_errorprone_error_prone_type_annotations/OWNERS b/third_party/android_deps/libs/com_google_errorprone_error_prone_type_annotations/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/com_google_errorprone_error_prone_type_annotations/OWNERS +++ b/third_party/android_deps/libs/com_google_errorprone_error_prone_type_annotations/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/com_google_errorprone_javac/OWNERS b/third_party/android_deps/libs/com_google_errorprone_javac/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/com_google_errorprone_javac/OWNERS +++ b/third_party/android_deps/libs/com_google_errorprone_javac/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/com_google_errorprone_javac_shaded/OWNERS b/third_party/android_deps/libs/com_google_errorprone_javac_shaded/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/com_google_errorprone_javac_shaded/OWNERS +++ b/third_party/android_deps/libs/com_google_errorprone_javac_shaded/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/com_google_firebase_firebase_annotations/OWNERS b/third_party/android_deps/libs/com_google_firebase_firebase_annotations/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/com_google_firebase_firebase_annotations/OWNERS +++ b/third_party/android_deps/libs/com_google_firebase_firebase_annotations/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/com_google_firebase_firebase_common/OWNERS b/third_party/android_deps/libs/com_google_firebase_firebase_common/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/com_google_firebase_firebase_common/OWNERS +++ b/third_party/android_deps/libs/com_google_firebase_firebase_common/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/com_google_firebase_firebase_components/OWNERS b/third_party/android_deps/libs/com_google_firebase_firebase_components/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/com_google_firebase_firebase_components/OWNERS +++ b/third_party/android_deps/libs/com_google_firebase_firebase_components/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/com_google_firebase_firebase_encoders/OWNERS b/third_party/android_deps/libs/com_google_firebase_firebase_encoders/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/com_google_firebase_firebase_encoders/OWNERS +++ b/third_party/android_deps/libs/com_google_firebase_firebase_encoders/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/com_google_firebase_firebase_encoders_json/OWNERS b/third_party/android_deps/libs/com_google_firebase_firebase_encoders_json/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/com_google_firebase_firebase_encoders_json/OWNERS +++ b/third_party/android_deps/libs/com_google_firebase_firebase_encoders_json/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/com_google_firebase_firebase_iid/OWNERS b/third_party/android_deps/libs/com_google_firebase_firebase_iid/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/com_google_firebase_firebase_iid/OWNERS +++ b/third_party/android_deps/libs/com_google_firebase_firebase_iid/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/com_google_firebase_firebase_iid_interop/OWNERS b/third_party/android_deps/libs/com_google_firebase_firebase_iid_interop/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/com_google_firebase_firebase_iid_interop/OWNERS +++ b/third_party/android_deps/libs/com_google_firebase_firebase_iid_interop/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/com_google_firebase_firebase_installations/OWNERS b/third_party/android_deps/libs/com_google_firebase_firebase_installations/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/com_google_firebase_firebase_installations/OWNERS +++ b/third_party/android_deps/libs/com_google_firebase_firebase_installations/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/com_google_firebase_firebase_installations_interop/OWNERS b/third_party/android_deps/libs/com_google_firebase_firebase_installations_interop/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/com_google_firebase_firebase_installations_interop/OWNERS +++ b/third_party/android_deps/libs/com_google_firebase_firebase_installations_interop/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/com_google_firebase_firebase_measurement_connector/OWNERS b/third_party/android_deps/libs/com_google_firebase_firebase_measurement_connector/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/com_google_firebase_firebase_measurement_connector/OWNERS +++ b/third_party/android_deps/libs/com_google_firebase_firebase_measurement_connector/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/com_google_firebase_firebase_messaging/OWNERS b/third_party/android_deps/libs/com_google_firebase_firebase_messaging/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/com_google_firebase_firebase_messaging/OWNERS +++ b/third_party/android_deps/libs/com_google_firebase_firebase_messaging/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/com_google_googlejavaformat_google_java_format/OWNERS b/third_party/android_deps/libs/com_google_googlejavaformat_google_java_format/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/com_google_googlejavaformat_google_java_format/OWNERS +++ b/third_party/android_deps/libs/com_google_googlejavaformat_google_java_format/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/com_google_guava_failureaccess/OWNERS b/third_party/android_deps/libs/com_google_guava_failureaccess/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/com_google_guava_failureaccess/OWNERS +++ b/third_party/android_deps/libs/com_google_guava_failureaccess/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/com_google_guava_guava/OWNERS b/third_party/android_deps/libs/com_google_guava_guava/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/com_google_guava_guava/OWNERS +++ b/third_party/android_deps/libs/com_google_guava_guava/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/com_google_guava_guava_android/OWNERS b/third_party/android_deps/libs/com_google_guava_guava_android/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/com_google_guava_guava_android/OWNERS +++ b/third_party/android_deps/libs/com_google_guava_guava_android/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/com_google_guava_listenablefuture/OWNERS b/third_party/android_deps/libs/com_google_guava_listenablefuture/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/com_google_guava_listenablefuture/OWNERS +++ b/third_party/android_deps/libs/com_google_guava_listenablefuture/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/com_google_j2objc_j2objc_annotations/OWNERS b/third_party/android_deps/libs/com_google_j2objc_j2objc_annotations/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/com_google_j2objc_j2objc_annotations/OWNERS +++ b/third_party/android_deps/libs/com_google_j2objc_j2objc_annotations/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/com_google_protobuf_protobuf_java/OWNERS b/third_party/android_deps/libs/com_google_protobuf_protobuf_java/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/com_google_protobuf_protobuf_java/OWNERS +++ b/third_party/android_deps/libs/com_google_protobuf_protobuf_java/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/com_google_protobuf_protobuf_javalite/OWNERS b/third_party/android_deps/libs/com_google_protobuf_protobuf_javalite/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/com_google_protobuf_protobuf_javalite/OWNERS +++ b/third_party/android_deps/libs/com_google_protobuf_protobuf_javalite/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/com_googlecode_java_diff_utils_diffutils/OWNERS b/third_party/android_deps/libs/com_googlecode_java_diff_utils_diffutils/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/com_googlecode_java_diff_utils_diffutils/OWNERS +++ b/third_party/android_deps/libs/com_googlecode_java_diff_utils_diffutils/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/com_squareup_javapoet/OWNERS b/third_party/android_deps/libs/com_squareup_javapoet/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/com_squareup_javapoet/OWNERS +++ b/third_party/android_deps/libs/com_squareup_javapoet/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/com_squareup_javawriter/OWNERS b/third_party/android_deps/libs/com_squareup_javawriter/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/com_squareup_javawriter/OWNERS +++ b/third_party/android_deps/libs/com_squareup_javawriter/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/javax_annotation_javax_annotation_api/OWNERS b/third_party/android_deps/libs/javax_annotation_javax_annotation_api/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/javax_annotation_javax_annotation_api/OWNERS +++ b/third_party/android_deps/libs/javax_annotation_javax_annotation_api/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/javax_annotation_jsr250_api/OWNERS b/third_party/android_deps/libs/javax_annotation_jsr250_api/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/javax_annotation_jsr250_api/OWNERS +++ b/third_party/android_deps/libs/javax_annotation_jsr250_api/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/javax_inject_javax_inject/OWNERS b/third_party/android_deps/libs/javax_inject_javax_inject/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/javax_inject_javax_inject/OWNERS +++ b/third_party/android_deps/libs/javax_inject_javax_inject/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/nekohtml_nekohtml/OWNERS b/third_party/android_deps/libs/nekohtml_nekohtml/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/nekohtml_nekohtml/OWNERS +++ b/third_party/android_deps/libs/nekohtml_nekohtml/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/nekohtml_xercesminimal/OWNERS b/third_party/android_deps/libs/nekohtml_xercesminimal/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/nekohtml_xercesminimal/OWNERS +++ b/third_party/android_deps/libs/nekohtml_xercesminimal/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/net_ltgt_gradle_incap_incap/OWNERS b/third_party/android_deps/libs/net_ltgt_gradle_incap_incap/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/net_ltgt_gradle_incap_incap/OWNERS +++ b/third_party/android_deps/libs/net_ltgt_gradle_incap_incap/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/net_sf_kxml_kxml2/OWNERS b/third_party/android_deps/libs/net_sf_kxml_kxml2/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/net_sf_kxml_kxml2/OWNERS +++ b/third_party/android_deps/libs/net_sf_kxml_kxml2/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/org_apache_ant_ant/OWNERS b/third_party/android_deps/libs/org_apache_ant_ant/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/org_apache_ant_ant/OWNERS +++ b/third_party/android_deps/libs/org_apache_ant_ant/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/org_apache_ant_ant_launcher/OWNERS b/third_party/android_deps/libs/org_apache_ant_ant_launcher/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/org_apache_ant_ant_launcher/OWNERS +++ b/third_party/android_deps/libs/org_apache_ant_ant_launcher/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/org_apache_maven_maven_ant_tasks/OWNERS b/third_party/android_deps/libs/org_apache_maven_maven_ant_tasks/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/org_apache_maven_maven_ant_tasks/OWNERS +++ b/third_party/android_deps/libs/org_apache_maven_maven_ant_tasks/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/org_apache_maven_maven_artifact/OWNERS b/third_party/android_deps/libs/org_apache_maven_maven_artifact/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/org_apache_maven_maven_artifact/OWNERS +++ b/third_party/android_deps/libs/org_apache_maven_maven_artifact/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/org_apache_maven_maven_artifact_manager/OWNERS b/third_party/android_deps/libs/org_apache_maven_maven_artifact_manager/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/org_apache_maven_maven_artifact_manager/OWNERS +++ b/third_party/android_deps/libs/org_apache_maven_maven_artifact_manager/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/org_apache_maven_maven_error_diagnostics/OWNERS b/third_party/android_deps/libs/org_apache_maven_maven_error_diagnostics/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/org_apache_maven_maven_error_diagnostics/OWNERS +++ b/third_party/android_deps/libs/org_apache_maven_maven_error_diagnostics/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/org_apache_maven_maven_model/OWNERS b/third_party/android_deps/libs/org_apache_maven_maven_model/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/org_apache_maven_maven_model/OWNERS +++ b/third_party/android_deps/libs/org_apache_maven_maven_model/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/org_apache_maven_maven_plugin_registry/OWNERS b/third_party/android_deps/libs/org_apache_maven_maven_plugin_registry/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/org_apache_maven_maven_plugin_registry/OWNERS +++ b/third_party/android_deps/libs/org_apache_maven_maven_plugin_registry/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/org_apache_maven_maven_profile/OWNERS b/third_party/android_deps/libs/org_apache_maven_maven_profile/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/org_apache_maven_maven_profile/OWNERS +++ b/third_party/android_deps/libs/org_apache_maven_maven_profile/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/org_apache_maven_maven_project/OWNERS b/third_party/android_deps/libs/org_apache_maven_maven_project/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/org_apache_maven_maven_project/OWNERS +++ b/third_party/android_deps/libs/org_apache_maven_maven_project/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/org_apache_maven_maven_repository_metadata/OWNERS b/third_party/android_deps/libs/org_apache_maven_maven_repository_metadata/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/org_apache_maven_maven_repository_metadata/OWNERS +++ b/third_party/android_deps/libs/org_apache_maven_maven_repository_metadata/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/org_apache_maven_maven_settings/OWNERS b/third_party/android_deps/libs/org_apache_maven_maven_settings/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/org_apache_maven_maven_settings/OWNERS +++ b/third_party/android_deps/libs/org_apache_maven_maven_settings/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/org_apache_maven_wagon_wagon_file/OWNERS b/third_party/android_deps/libs/org_apache_maven_wagon_wagon_file/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/org_apache_maven_wagon_wagon_file/OWNERS +++ b/third_party/android_deps/libs/org_apache_maven_wagon_wagon_file/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/org_apache_maven_wagon_wagon_http_lightweight/OWNERS b/third_party/android_deps/libs/org_apache_maven_wagon_wagon_http_lightweight/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/org_apache_maven_wagon_wagon_http_lightweight/OWNERS +++ b/third_party/android_deps/libs/org_apache_maven_wagon_wagon_http_lightweight/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/org_apache_maven_wagon_wagon_http_shared/OWNERS b/third_party/android_deps/libs/org_apache_maven_wagon_wagon_http_shared/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/org_apache_maven_wagon_wagon_http_shared/OWNERS +++ b/third_party/android_deps/libs/org_apache_maven_wagon_wagon_http_shared/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/org_apache_maven_wagon_wagon_provider_api/OWNERS b/third_party/android_deps/libs/org_apache_maven_wagon_wagon_provider_api/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/org_apache_maven_wagon_wagon_provider_api/OWNERS +++ b/third_party/android_deps/libs/org_apache_maven_wagon_wagon_provider_api/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/org_ccil_cowan_tagsoup_tagsoup/OWNERS b/third_party/android_deps/libs/org_ccil_cowan_tagsoup_tagsoup/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/org_ccil_cowan_tagsoup_tagsoup/OWNERS +++ b/third_party/android_deps/libs/org_ccil_cowan_tagsoup_tagsoup/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/org_checkerframework_checker_compat_qual/OWNERS b/third_party/android_deps/libs/org_checkerframework_checker_compat_qual/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/org_checkerframework_checker_compat_qual/OWNERS +++ b/third_party/android_deps/libs/org_checkerframework_checker_compat_qual/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/org_checkerframework_checker_qual/OWNERS b/third_party/android_deps/libs/org_checkerframework_checker_qual/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/org_checkerframework_checker_qual/OWNERS +++ b/third_party/android_deps/libs/org_checkerframework_checker_qual/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/org_checkerframework_dataflow_shaded/OWNERS b/third_party/android_deps/libs/org_checkerframework_dataflow_shaded/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/org_checkerframework_dataflow_shaded/OWNERS +++ b/third_party/android_deps/libs/org_checkerframework_dataflow_shaded/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/org_codehaus_mojo_animal_sniffer_annotations/OWNERS b/third_party/android_deps/libs/org_codehaus_mojo_animal_sniffer_annotations/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/org_codehaus_mojo_animal_sniffer_annotations/OWNERS +++ b/third_party/android_deps/libs/org_codehaus_mojo_animal_sniffer_annotations/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/org_codehaus_plexus_plexus_container_default/OWNERS b/third_party/android_deps/libs/org_codehaus_plexus_plexus_container_default/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/org_codehaus_plexus_plexus_container_default/OWNERS +++ b/third_party/android_deps/libs/org_codehaus_plexus_plexus_container_default/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/org_codehaus_plexus_plexus_interpolation/OWNERS b/third_party/android_deps/libs/org_codehaus_plexus_plexus_interpolation/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/org_codehaus_plexus_plexus_interpolation/OWNERS +++ b/third_party/android_deps/libs/org_codehaus_plexus_plexus_interpolation/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/org_codehaus_plexus_plexus_utils/OWNERS b/third_party/android_deps/libs/org_codehaus_plexus_plexus_utils/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/org_codehaus_plexus_plexus_utils/OWNERS +++ b/third_party/android_deps/libs/org_codehaus_plexus_plexus_utils/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/org_jetbrains_annotations/OWNERS b/third_party/android_deps/libs/org_jetbrains_annotations/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/org_jetbrains_annotations/OWNERS +++ b/third_party/android_deps/libs/org_jetbrains_annotations/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/org_jetbrains_kotlin_kotlin_stdlib/OWNERS b/third_party/android_deps/libs/org_jetbrains_kotlin_kotlin_stdlib/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/org_jetbrains_kotlin_kotlin_stdlib/OWNERS +++ b/third_party/android_deps/libs/org_jetbrains_kotlin_kotlin_stdlib/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/org_jetbrains_kotlin_kotlin_stdlib_common/OWNERS b/third_party/android_deps/libs/org_jetbrains_kotlin_kotlin_stdlib_common/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/org_jetbrains_kotlin_kotlin_stdlib_common/OWNERS +++ b/third_party/android_deps/libs/org_jetbrains_kotlin_kotlin_stdlib_common/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/org_jetbrains_kotlinx_kotlinx_metadata_jvm/OWNERS b/third_party/android_deps/libs/org_jetbrains_kotlinx_kotlinx_metadata_jvm/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/org_jetbrains_kotlinx_kotlinx_metadata_jvm/OWNERS +++ b/third_party/android_deps/libs/org_jetbrains_kotlinx_kotlinx_metadata_jvm/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/org_ow2_asm_asm/OWNERS b/third_party/android_deps/libs/org_ow2_asm_asm/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/org_ow2_asm_asm/OWNERS +++ b/third_party/android_deps/libs/org_ow2_asm_asm/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/org_ow2_asm_asm_analysis/OWNERS b/third_party/android_deps/libs/org_ow2_asm_asm_analysis/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/org_ow2_asm_asm_analysis/OWNERS +++ b/third_party/android_deps/libs/org_ow2_asm_asm_analysis/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/org_ow2_asm_asm_commons/OWNERS b/third_party/android_deps/libs/org_ow2_asm_asm_commons/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/org_ow2_asm_asm_commons/OWNERS +++ b/third_party/android_deps/libs/org_ow2_asm_asm_commons/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/org_ow2_asm_asm_tree/OWNERS b/third_party/android_deps/libs/org_ow2_asm_asm_tree/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/org_ow2_asm_asm_tree/OWNERS +++ b/third_party/android_deps/libs/org_ow2_asm_asm_tree/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/org_ow2_asm_asm_util/OWNERS b/third_party/android_deps/libs/org_ow2_asm_asm_util/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/org_ow2_asm_asm_util/OWNERS +++ b/third_party/android_deps/libs/org_ow2_asm_asm_util/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/org_pcollections_pcollections/OWNERS b/third_party/android_deps/libs/org_pcollections_pcollections/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/org_pcollections_pcollections/OWNERS +++ b/third_party/android_deps/libs/org_pcollections_pcollections/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/org_robolectric_annotations/OWNERS b/third_party/android_deps/libs/org_robolectric_annotations/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/org_robolectric_annotations/OWNERS +++ b/third_party/android_deps/libs/org_robolectric_annotations/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/org_robolectric_junit/OWNERS b/third_party/android_deps/libs/org_robolectric_junit/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/org_robolectric_junit/OWNERS +++ b/third_party/android_deps/libs/org_robolectric_junit/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/org_robolectric_pluginapi/OWNERS b/third_party/android_deps/libs/org_robolectric_pluginapi/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/org_robolectric_pluginapi/OWNERS +++ b/third_party/android_deps/libs/org_robolectric_pluginapi/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/org_robolectric_plugins_maven_dependency_resolver/OWNERS b/third_party/android_deps/libs/org_robolectric_plugins_maven_dependency_resolver/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/org_robolectric_plugins_maven_dependency_resolver/OWNERS +++ b/third_party/android_deps/libs/org_robolectric_plugins_maven_dependency_resolver/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/org_robolectric_resources/OWNERS b/third_party/android_deps/libs/org_robolectric_resources/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/org_robolectric_resources/OWNERS +++ b/third_party/android_deps/libs/org_robolectric_resources/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/org_robolectric_robolectric/OWNERS b/third_party/android_deps/libs/org_robolectric_robolectric/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/org_robolectric_robolectric/OWNERS +++ b/third_party/android_deps/libs/org_robolectric_robolectric/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/org_robolectric_sandbox/OWNERS b/third_party/android_deps/libs/org_robolectric_sandbox/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/org_robolectric_sandbox/OWNERS +++ b/third_party/android_deps/libs/org_robolectric_sandbox/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/org_robolectric_shadowapi/OWNERS b/third_party/android_deps/libs/org_robolectric_shadowapi/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/org_robolectric_shadowapi/OWNERS +++ b/third_party/android_deps/libs/org_robolectric_shadowapi/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/org_robolectric_shadows_framework/OWNERS b/third_party/android_deps/libs/org_robolectric_shadows_framework/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/org_robolectric_shadows_framework/OWNERS +++ b/third_party/android_deps/libs/org_robolectric_shadows_framework/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/org_robolectric_shadows_playservices/OWNERS b/third_party/android_deps/libs/org_robolectric_shadows_playservices/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/org_robolectric_shadows_playservices/OWNERS +++ b/third_party/android_deps/libs/org_robolectric_shadows_playservices/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/org_robolectric_utils/OWNERS b/third_party/android_deps/libs/org_robolectric_utils/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/org_robolectric_utils/OWNERS +++ b/third_party/android_deps/libs/org_robolectric_utils/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/org_robolectric_utils_reflector/OWNERS b/third_party/android_deps/libs/org_robolectric_utils_reflector/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/org_robolectric_utils_reflector/OWNERS +++ b/third_party/android_deps/libs/org_robolectric_utils_reflector/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/org_threeten_threeten_extra/OWNERS b/third_party/android_deps/libs/org_threeten_threeten_extra/OWNERS index 7b571d97..aea47a05 100644 --- a/third_party/android_deps/libs/org_threeten_threeten_extra/OWNERS +++ b/third_party/android_deps/libs/org_threeten_threeten_extra/OWNERS
@@ -1 +1 @@ -file://third_party/android_deps/OWNERS \ No newline at end of file +file://third_party/android_deps/OWNERS
diff --git a/third_party/blink/common/use_counter/OWNERS b/third_party/blink/common/use_counter/OWNERS index 585fa06..d5fefd8 100644 --- a/third_party/blink/common/use_counter/OWNERS +++ b/third_party/blink/common/use_counter/OWNERS
@@ -1,2 +1,2 @@ per-file *_mojom_traits*.*=set noparent -per-file *_mojom_traits*.*=file://ipc/SECURITY_OWNERS \ No newline at end of file +per-file *_mojom_traits*.*=file://ipc/SECURITY_OWNERS
diff --git a/third_party/blink/common/web_preferences/OWNERS b/third_party/blink/common/web_preferences/OWNERS index 585fa06..d5fefd8 100644 --- a/third_party/blink/common/web_preferences/OWNERS +++ b/third_party/blink/common/web_preferences/OWNERS
@@ -1,2 +1,2 @@ per-file *_mojom_traits*.*=set noparent -per-file *_mojom_traits*.*=file://ipc/SECURITY_OWNERS \ No newline at end of file +per-file *_mojom_traits*.*=file://ipc/SECURITY_OWNERS
diff --git a/third_party/blink/public/common/web_preferences/OWNERS b/third_party/blink/public/common/web_preferences/OWNERS index 585fa06..d5fefd8 100644 --- a/third_party/blink/public/common/web_preferences/OWNERS +++ b/third_party/blink/public/common/web_preferences/OWNERS
@@ -1,2 +1,2 @@ per-file *_mojom_traits*.*=set noparent -per-file *_mojom_traits*.*=file://ipc/SECURITY_OWNERS \ No newline at end of file +per-file *_mojom_traits*.*=file://ipc/SECURITY_OWNERS
diff --git a/third_party/blink/public/mojom/OWNERS b/third_party/blink/public/mojom/OWNERS index d970307..1feb514 100644 --- a/third_party/blink/public/mojom/OWNERS +++ b/third_party/blink/public/mojom/OWNERS
@@ -1,4 +1,4 @@ per-file *.mojom=set noparent per-file *.mojom=file://ipc/SECURITY_OWNERS per-file *_mojom_traits*.*=set noparent -per-file *_mojom_traits*.*=file://ipc/SECURITY_OWNERS \ No newline at end of file +per-file *_mojom_traits*.*=file://ipc/SECURITY_OWNERS
diff --git a/third_party/blink/public/mojom/insecure_input/OWNERS b/third_party/blink/public/mojom/insecure_input/OWNERS index 61b5e28..08850f4 100644 --- a/third_party/blink/public/mojom/insecure_input/OWNERS +++ b/third_party/blink/public/mojom/insecure_input/OWNERS
@@ -1,2 +1,2 @@ per-file *.mojom=set noparent -per-file *.mojom=file://ipc/SECURITY_OWNERS \ No newline at end of file +per-file *.mojom=file://ipc/SECURITY_OWNERS
diff --git a/third_party/blink/public/mojom/webpreferences/OWNERS b/third_party/blink/public/mojom/webpreferences/OWNERS index 61b5e28..08850f4 100644 --- a/third_party/blink/public/mojom/webpreferences/OWNERS +++ b/third_party/blink/public/mojom/webpreferences/OWNERS
@@ -1,2 +1,2 @@ per-file *.mojom=set noparent -per-file *.mojom=file://ipc/SECURITY_OWNERS \ No newline at end of file +per-file *.mojom=file://ipc/SECURITY_OWNERS
diff --git a/third_party/blink/public/strings/OWNERS b/third_party/blink/public/strings/OWNERS index aeedeaf..0e6f77b 100644 --- a/third_party/blink/public/strings/OWNERS +++ b/third_party/blink/public/strings/OWNERS
@@ -1,4 +1,4 @@ # For adding or removing languages. per-file *.grd=claudiomagni@chromium.org # Translation artifacts: -per-file *.xtb=file://tools/translation/TRANSLATION_OWNERS \ No newline at end of file +per-file *.xtb=file://tools/translation/TRANSLATION_OWNERS
diff --git a/third_party/blink/public/web/web_view.h b/third_party/blink/public/web/web_view.h index 7ea8039..7acd3f2 100644 --- a/third_party/blink/public/web/web_view.h +++ b/third_party/blink/public/web/web_view.h
@@ -36,6 +36,7 @@ #include "third_party/blink/public/common/page/drag_operation.h" #include "third_party/blink/public/common/renderer_preferences/renderer_preferences.h" #include "third_party/blink/public/common/web_preferences/web_preferences.h" +#include "third_party/blink/public/mojom/frame/frame.mojom-shared.h" #include "third_party/blink/public/mojom/input/focus_type.mojom-shared.h" #include "third_party/blink/public/mojom/page/page.mojom-shared.h" #include "third_party/blink/public/mojom/page/page_visibility_state.mojom-shared.h" @@ -139,7 +140,12 @@ virtual void DidDetachLocalMainFrame() = 0; // Called to inform WebViewImpl that a remote main frame has been attached. - virtual void DidAttachRemoteMainFrame() = 0; + // Associated channels should be passed and bound. + virtual void DidAttachRemoteMainFrame( + CrossVariantMojoAssociatedRemote<mojom::RemoteMainFrameHostInterfaceBase> + main_frame_host, + CrossVariantMojoAssociatedReceiver<mojom::RemoteMainFrameInterfaceBase> + main_frame) = 0; // Called to inform WebViewImpl that a remote main frame has been detached. virtual void DidDetachRemoteMainFrame() = 0;
diff --git a/third_party/blink/renderer/core/DEPS b/third_party/blink/renderer/core/DEPS index 4015396..b51c546 100644 --- a/third_party/blink/renderer/core/DEPS +++ b/third_party/blink/renderer/core/DEPS
@@ -64,6 +64,7 @@ "+cc/trees/paint_holding_commit_trigger.h", "+cc/trees/ukm_manager.h", "+components/performance_manager/public/mojom/coordination_unit.mojom-blink.h", + "+components/performance_manager/public/mojom/web_memory.mojom-blink.h", "+gpu/config/gpu_feature_info.h", "-inspector/v8", "+inspector/v8/public",
diff --git a/third_party/blink/renderer/core/exported/web_view_impl.cc b/third_party/blink/renderer/core/exported/web_view_impl.cc index 3583015..efb3316 100644 --- a/third_party/blink/renderer/core/exported/web_view_impl.cc +++ b/third_party/blink/renderer/core/exported/web_view_impl.cc
@@ -1958,18 +1958,19 @@ } } -void WebViewImpl::DidAttachRemoteMainFrame() { +void WebViewImpl::DidAttachRemoteMainFrame( + CrossVariantMojoAssociatedRemote< + mojom::blink::RemoteMainFrameHostInterfaceBase> main_frame_host, + CrossVariantMojoAssociatedReceiver< + mojom::blink::RemoteMainFrameInterfaceBase> main_frame) { + DCHECK(main_frame_host); + DCHECK(main_frame); DCHECK(!MainFrameImpl()); RemoteFrame* remote_frame = DynamicTo<RemoteFrame>(GetPage()->MainFrame()); - remote_frame->WasAttachedAsRemoteMainFrame(); + remote_frame->WasAttachedAsRemoteMainFrame(std::move(main_frame)); - remote_frame->GetRemoteAssociatedInterfaces()->GetInterface( - remote_main_frame_host_remote_.BindNewEndpointAndPassReceiver( - GetPage() - ->GetPageScheduler() - ->GetAgentGroupScheduler() - .DefaultTaskRunner())); + remote_main_frame_host_remote_.Bind(std::move(main_frame_host)); auto& viewport = GetPage()->GetVisualViewport(); viewport.Reset();
diff --git a/third_party/blink/renderer/core/exported/web_view_impl.h b/third_party/blink/renderer/core/exported/web_view_impl.h index 1e80d82d..c2e704e 100644 --- a/third_party/blink/renderer/core/exported/web_view_impl.h +++ b/third_party/blink/renderer/core/exported/web_view_impl.h
@@ -137,7 +137,11 @@ // WebView methods: void DidAttachLocalMainFrame() override; void DidDetachLocalMainFrame() override; - void DidAttachRemoteMainFrame() override; + void DidAttachRemoteMainFrame( + CrossVariantMojoAssociatedRemote< + mojom::blink::RemoteMainFrameHostInterfaceBase>, + CrossVariantMojoAssociatedReceiver< + mojom::blink::RemoteMainFrameInterfaceBase>) override; void DidDetachRemoteMainFrame() override; void SetNoStatePrefetchClient(WebNoStatePrefetchClient*) override; WebSettings* GetSettings() override;
diff --git a/third_party/blink/renderer/core/frame/remote_frame.cc b/third_party/blink/renderer/core/frame/remote_frame.cc index 56ec1f0..83560e3 100644 --- a/third_party/blink/renderer/core/frame/remote_frame.cc +++ b/third_party/blink/renderer/core/frame/remote_frame.cc
@@ -509,11 +509,6 @@ return *remote_frame_host_remote_.get(); } -AssociatedInterfaceProvider* RemoteFrame::GetRemoteAssociatedInterfaces() { - DCHECK(Client()); - return Client()->GetRemoteAssociatedInterfaces(); -} - RemoteFrameClient* RemoteFrame::Client() const { return static_cast<RemoteFrameClient*>(Frame::Client()); } @@ -882,9 +877,9 @@ TextAutosizer::UpdatePageInfoInAllFrames(root_frame); } -void RemoteFrame::WasAttachedAsRemoteMainFrame() { - interface_registry_->AddAssociatedInterface(WTF::BindRepeating( - &RemoteFrame::BindToMainFrameReceiver, WrapWeakPersistent(this))); +void RemoteFrame::WasAttachedAsRemoteMainFrame( + mojo::PendingAssociatedReceiver<mojom::blink::RemoteMainFrame> main_frame) { + main_frame_receiver_.Bind(std::move(main_frame), task_runner_); } const viz::LocalSurfaceId& RemoteFrame::GetLocalSurfaceId() const { @@ -1134,11 +1129,4 @@ frame->receiver_.Bind(std::move(receiver), frame->task_runner_); } -void RemoteFrame::BindToMainFrameReceiver( - RemoteFrame* frame, - mojo::PendingAssociatedReceiver<mojom::blink::RemoteMainFrame> receiver) { - DCHECK(frame); - frame->main_frame_receiver_.Bind(std::move(receiver), frame->task_runner_); -} - } // namespace blink
diff --git a/third_party/blink/renderer/core/frame/remote_frame.h b/third_party/blink/renderer/core/frame/remote_frame.h index d30000e..0125d2d1 100644 --- a/third_party/blink/renderer/core/frame/remote_frame.h +++ b/third_party/blink/renderer/core/frame/remote_frame.h
@@ -102,8 +102,6 @@ mojom::blink::RemoteFrameHost& GetRemoteFrameHostRemote(); - AssociatedInterfaceProvider* GetRemoteAssociatedInterfaces(); - RemoteFrameView* View() const override; RemoteFrameClient* Client() const; @@ -220,7 +218,9 @@ mojom::blink::TextAutosizerPageInfoPtr page_info) override; // Indicate that this frame was attached as a MainFrame. - void WasAttachedAsRemoteMainFrame(); + void WasAttachedAsRemoteMainFrame( + mojo::PendingAssociatedReceiver<mojom::blink::RemoteMainFrame> + main_frame); RemoteFrameToken GetRemoteFrameToken() const { return GetFrameToken().GetAs<RemoteFrameToken>(); @@ -252,9 +252,6 @@ static void BindToReceiver( RemoteFrame* frame, mojo::PendingAssociatedReceiver<mojom::blink::RemoteFrame> receiver); - static void BindToMainFrameReceiver( - RemoteFrame* frame, - mojo::PendingAssociatedReceiver<mojom::blink::RemoteMainFrame> receiver); Member<RemoteFrameView> view_; RemoteSecurityContext security_context_;
diff --git a/third_party/blink/renderer/core/frame/screen.cc b/third_party/blink/renderer/core/frame/screen.cc index cae8755..f46aba9 100644 --- a/third_party/blink/renderer/core/frame/screen.cc +++ b/third_party/blink/renderer/core/frame/screen.cc
@@ -166,6 +166,13 @@ if (!DomWindow()) return false; LocalFrame* frame = DomWindow()->GetFrame(); + + auto* context = GetExecutionContext(); + if (!context->IsFeatureEnabled( + mojom::blink::PermissionsPolicyFeature::kWindowPlacement)) { + return false; + } + return GetScreenInfo(*frame).is_extended; }
diff --git a/third_party/blink/renderer/core/frame/web_frame_test.cc b/third_party/blink/renderer/core/frame/web_frame_test.cc index 10ffb30..eb22710 100644 --- a/third_party/blink/renderer/core/frame/web_frame_test.cc +++ b/third_party/blink/renderer/core/frame/web_frame_test.cc
@@ -9060,7 +9060,14 @@ WebRemoteFrame* remote_frame = frame_test_helpers::CreateRemote(); MainFrame()->Swap(remote_frame); - WebView()->DidAttachRemoteMainFrame(); + + mojo::AssociatedRemote<mojom::blink::RemoteMainFrameHost> main_frame_host; + ignore_result(main_frame_host.BindNewEndpointAndPassDedicatedReceiver()); + WebView()->DidAttachRemoteMainFrame( + main_frame_host.Unbind(), + mojo::AssociatedRemote<mojom::blink::RemoteMainFrame>() + .BindNewEndpointAndPassDedicatedReceiver()); + EXPECT_EQ(1.0, WebView()->PageScaleFactor()); } @@ -9792,11 +9799,7 @@ class RemoteWindowCloseTest : public WebFrameTest { public: - RemoteWindowCloseTest() { - remote_main_frame_host_.Init( - remote_frame_client_.GetRemoteAssociatedInterfaces()); - } - + RemoteWindowCloseTest() = default; ~RemoteWindowCloseTest() override = default; frame_test_helpers::TestWebRemoteFrameClient* remote_frame_client() { @@ -9805,6 +9808,10 @@ bool Closed() const { return remote_main_frame_host_.remote_window_closed(); } + TestRemoteMainFrameHostForWindowClose* remote_main_frame_host() { + return &remote_main_frame_host_; + } + private: TestRemoteMainFrameHostForWindowClose remote_main_frame_host_; frame_test_helpers::TestWebRemoteFrameClient remote_frame_client_; @@ -9817,7 +9824,10 @@ // Create a remote window that will be closed later in the test. frame_test_helpers::WebViewHelper popup; popup.InitializeRemote(remote_frame_client(), nullptr, nullptr); - popup.GetWebView()->DidAttachRemoteMainFrame(); + popup.GetWebView()->DidAttachRemoteMainFrame( + remote_main_frame_host()->BindNewAssociatedRemote(), + mojo::AssociatedRemote<mojom::blink::RemoteMainFrame>() + .BindNewEndpointAndPassDedicatedReceiver()); LocalFrame* local_frame = main_web_view.LocalMainFrame()->GetFrame(); RemoteFrame* remote_frame = popup.RemoteMainFrame()->GetFrame();
diff --git a/third_party/blink/renderer/core/html/forms/OWNERS b/third_party/blink/renderer/core/html/forms/OWNERS index 77cd0dd..62721b9 100644 --- a/third_party/blink/renderer/core/html/forms/OWNERS +++ b/third_party/blink/renderer/core/html/forms/OWNERS
@@ -1,4 +1,4 @@ keishi@chromium.org tkent@chromium.org masonf@chromium.org -jarhar@chromium.org \ No newline at end of file +jarhar@chromium.org
diff --git a/third_party/blink/renderer/core/html/media/autoplay_uma_helper.cc b/third_party/blink/renderer/core/html/media/autoplay_uma_helper.cc index 394387e..9f4e7f14 100644 --- a/third_party/blink/renderer/core/html/media/autoplay_uma_helper.cc +++ b/third_party/blink/renderer/core/html/media/autoplay_uma_helper.cc
@@ -63,8 +63,6 @@ AutoplaySource source) { if (IsA<HTMLVideoElement>(element)) { base::UmaHistogramEnumeration("Media.Video.Autoplay", source); - if (element->muted()) - base::UmaHistogramEnumeration("Media.Video.Autoplay.Muted", source); return; } base::UmaHistogramEnumeration("Media.Audio.Autoplay", source);
diff --git a/third_party/blink/renderer/core/paint/box_painter_base.cc b/third_party/blink/renderer/core/paint/box_painter_base.cc index 9acb533..fd60be2 100644 --- a/third_party/blink/renderer/core/paint/box_painter_base.cc +++ b/third_party/blink/renderer/core/paint/box_painter_base.cc
@@ -397,23 +397,14 @@ namespace { -// Given the |size| that the whole image should draw at, and the input phase +// Given the size that the whole image should draw at, and the input phase // requested by the content, and the space between repeated tiles, return a -// rectangle with |size| and a location that respects the phase but is no more -// than one size + space in magnitude. In practice, this means that if there is -// no repeating the returned rect would contain the destination_offset -// location. The destination_offset passed here must exactly match the location -// of the subset in a following call to ComputeSubsetForBackground. -FloatRect ComputePhaseForBackground(const FloatPoint& destination_offset, - const FloatSize& size, - const FloatPoint& phase, - const FloatSize& spacing) { - const FloatSize step_per_tile(size + spacing); - return FloatRect( - FloatPoint( - destination_offset.X() + fmodf(-phase.X(), step_per_tile.Width()), - destination_offset.Y() + fmodf(-phase.Y(), step_per_tile.Height())), - size); +// phase that is no more than one size + space in magnitude. +PhysicalOffset ComputePhaseForBackground( + const BackgroundImageGeometry& geometry) { + const PhysicalSize step_per_tile = geometry.TileSize() + geometry.SpaceSize(); + return {IntMod(-geometry.Phase().left, step_per_tile.width), + IntMod(-geometry.Phase().top, step_per_tile.height)}; } // Compute the image subset, in intrinsic image coordinates, that gets mapped @@ -425,19 +416,18 @@ // It is used to undo the offset added in ComputePhaseForBackground. The size // of requested subset should be the unsnapped size so that the computed // scale and location in the source image can be correctly determined. -FloatRect ComputeSubsetForBackground(const FloatRect& phase_and_size, - const FloatRect& subset, +FloatRect ComputeSubsetForBackground(const PhysicalRect& phase_and_size, + const PhysicalRect& subset, const FloatSize& intrinsic_size) { // TODO(schenney): Re-enable this after determining why it fails for // CAP, and maybe other cases. // DCHECK(phase_and_size.Contains(subset)); - + const PhysicalOffset offset_in_tile = subset.offset - phase_and_size.offset; const FloatSize scale(phase_and_size.Width() / intrinsic_size.Width(), phase_and_size.Height() / intrinsic_size.Height()); - return FloatRect((subset.X() - phase_and_size.X()) / scale.Width(), - (subset.Y() - phase_and_size.Y()) / scale.Height(), - subset.Width() / scale.Width(), - subset.Height() / scale.Height()); + return FloatRect( + offset_in_tile.left / scale.Width(), offset_in_tile.top / scale.Height(), + subset.Width() / scale.Width(), subset.Height() / scale.Height()); } FloatRect SnapSourceRectIfNearIntegral(const FloatRect src_rect) { @@ -469,15 +459,11 @@ // sprite computation. void DrawTiledBackground(GraphicsContext& context, Image* image, - const FloatSize& unsnapped_subset_size, - const FloatRect& snapped_paint_rect, - const FloatPoint& phase, - const FloatSize& tile_size, + const BackgroundImageGeometry& geometry, SkBlendMode op, - const FloatSize& repeat_spacing, bool has_filter_property, RespectImageOrientationEnum respect_orientation) { - DCHECK(!tile_size.IsEmpty()); + DCHECK(!geometry.TileSize().IsEmpty()); // Use the intrinsic size of the image if it has one, otherwise force the // generated image to be the tile size. @@ -497,22 +483,24 @@ // scale that would be calculated in the |else| part. // We should probably support subpixel size here. intrinsic_tile_size.IsEmpty()) { - intrinsic_tile_size = tile_size; + intrinsic_tile_size = FloatSize(geometry.TileSize()); } else { - scale = FloatSize(tile_size.Width() / intrinsic_tile_size.Width(), - tile_size.Height() / intrinsic_tile_size.Height()); + scale = + FloatSize(geometry.TileSize().width / intrinsic_tile_size.Width(), + geometry.TileSize().height / intrinsic_tile_size.Height()); } - const FloatRect one_tile_rect = ComputePhaseForBackground( - snapped_paint_rect.Location(), tile_size, phase, repeat_spacing); + const PhysicalOffset dest_phase = + geometry.SnappedDestRect().offset + ComputePhaseForBackground(geometry); // Check and see if a single draw of the image can cover the entire area we // are supposed to tile. The dest_rect_for_subset must use the same // location that was used in ComputePhaseForBackground and the unsnapped // destination rect in order to correctly evaluate the subset size and // location in the presence of border snapping and zoom. - FloatRect dest_rect_for_subset(snapped_paint_rect.Location(), - unsnapped_subset_size); + const PhysicalRect dest_rect_for_subset(geometry.SnappedDestRect().offset, + geometry.UnsnappedDestRect().size); + const PhysicalRect one_tile_rect(dest_phase, geometry.TileSize()); if (one_tile_rect.Contains(dest_rect_for_subset)) { FloatRect visible_src_rect = ComputeSubsetForBackground( one_tile_rect, dest_rect_for_subset, intrinsic_tile_size); @@ -527,9 +515,9 @@ intrinsic_tile_size, visible_src_rect); } - context.DrawImage(image, Image::kSyncDecode, snapped_paint_rect, - &visible_src_rect, has_filter_property, op, - respect_orientation); + context.DrawImage(image, Image::kSyncDecode, + FloatRect(geometry.SnappedDestRect()), &visible_src_rect, + has_filter_property, op, respect_orientation); return; } @@ -545,18 +533,23 @@ // // So detect when we do not want to repeat and set the scale to round the // values in that dimension. - if (fabs(tile_size.Width() - snapped_paint_rect.Width()) <= 0.5) { - scale.SetWidth(snapped_paint_rect.Width() / intrinsic_tile_size.Width()); + const PhysicalSize tile_dest_diff = + geometry.TileSize() - geometry.SnappedDestRect().size; + if (tile_dest_diff.width.Abs() <= 0.5f) { + scale.SetWidth(geometry.SnappedDestRect().Width() / + intrinsic_tile_size.Width()); } - if (fabs(tile_size.Height() - snapped_paint_rect.Height()) <= 0.5) { - scale.SetHeight(snapped_paint_rect.Height() / intrinsic_tile_size.Height()); + if (tile_dest_diff.height.Abs() <= 0.5f) { + scale.SetHeight(geometry.SnappedDestRect().Height() / + intrinsic_tile_size.Height()); } // This call takes the unscaled image, applies the given scale, and paints // it into the snapped_dest_rect using phase from one_tile_rect and the // given repeat spacing. Note the phase is already scaled. - context.DrawImageTiled(image, snapped_paint_rect, tile_rect, scale, - one_tile_rect.Location(), repeat_spacing, op, + context.DrawImageTiled(image, FloatRect(geometry.SnappedDestRect()), + tile_rect, scale, FloatPoint(dest_phase), + FloatSize(geometry.SpaceSize()), op, respect_orientation); } @@ -645,7 +638,7 @@ // tile. The border for painting images may not be the same as the color due // to optimizations for the image painting destination that avoid painting // under the border. - FloatRect image_tile; + PhysicalRect image_tile; FloatRoundedRect image_border; if (info.should_paint_image) { // Avoid image shaders when printing (poorly supported in PDF). @@ -666,23 +659,17 @@ // Phase calculation uses the actual painted location, given by the // border-snapped destination rect. - image_tile = ComputePhaseForBackground( - FloatPoint(geometry.SnappedDestRect().offset), - FloatSize(geometry.TileSize()), FloatPoint(geometry.Phase()), - FloatSize(geometry.SpaceSize())); + image_tile = PhysicalRect(geometry.SnappedDestRect().offset + + ComputePhaseForBackground(geometry), + geometry.TileSize()); - // Force the image tile to LayoutUnit precision, which is the precision - // it was calculated in. This avoids bleeding due to values very close to - // integers. - // The test images/sprite-no-bleed.html fails on two of the sub-cases - // due to this rounding still not being enough to make the Contains check - // pass. The best way to fix this would be to remove the paint rect offset - // from the tile computation, because we effectively add it in - // ComputePhaseForBackground then remove it in ComputeSubsetForBackground. - image_tile = - FloatRect(PhysicalRect::FastAndLossyFromFloatRect(image_tile)); + // Use FastAndLossyFromFloatRect when converting the image border rect. + // At this point it should have been derived from a snapped rectangle, so + // the conversion from float should be as precise as it can be. + // We cannot optimize if the tile is misaligned. - if (!image_tile.Contains(image_border.Rect())) + if (!image_tile.Contains( + PhysicalRect::FastAndLossyFromFloatRect(image_border.Rect()))) return false; } } @@ -719,7 +706,7 @@ bool has_intrinsic_size = image->HasIntrinsicSize(); const FloatSize intrinsic_tile_size = !has_intrinsic_size - ? image_tile.Size() + ? FloatSize(image_tile.size) : FloatSize(image->Size(info.respect_image_orientation)); // Subset computation needs the same location as was used with @@ -727,10 +714,10 @@ // size to correctly calculate sprite subsets in the presence of zoom. But if // this is a generated image sized according to the tile size (which is a // snapped value), use the snapped dest rect instead. - FloatRect dest_rect_for_subset( - FloatPoint(geometry.SnappedDestRect().offset), - !has_intrinsic_size ? FloatSize(geometry.SnappedDestRect().size) - : FloatSize(geometry.UnsnappedDestRect().size)); + const PhysicalRect dest_rect_for_subset( + geometry.SnappedDestRect().offset, + !has_intrinsic_size ? geometry.SnappedDestRect().size + : geometry.UnsnappedDestRect().size); // Content providers almost always choose source pixels at integer locations, // so snap to integers. This is particuarly important for sprite maps. // Calculation up to this point, in LayoutUnits, can lead to small variations @@ -898,10 +885,7 @@ inspector_paint_image_event::Data, node, *info.image, FloatRect(image->Rect()), FloatRect(scrolled_paint_rect)); DrawTiledBackground( - context, image, FloatSize(geometry.UnsnappedDestRect().size), - FloatRect(geometry.SnappedDestRect()), FloatPoint(geometry.Phase()), - FloatSize(geometry.TileSize()), composite_op, - FloatSize(geometry.SpaceSize()), + context, image, geometry, composite_op, node && node->ComputedStyleRef().HasFilterInducingProperty(), info.respect_image_orientation); if (node && info.image && info.image->IsImageResource()) {
diff --git a/third_party/blink/renderer/core/streams/miscellaneous_operations.cc b/third_party/blink/renderer/core/streams/miscellaneous_operations.cc index 31ae03191..3e65fc3 100644 --- a/third_party/blink/renderer/core/streams/miscellaneous_operations.cc +++ b/third_party/blink/renderer/core/streams/miscellaneous_operations.cc
@@ -405,6 +405,20 @@ return MakeGarbageCollected<TrivialStreamAlgorithm>(); } +CORE_EXPORT ScriptValue CreateTrivialQueuingStrategy(v8::Isolate* isolate, + size_t high_water_mark) { + v8::Local<v8::Name> high_water_mark_string = + V8AtomicString(isolate, "highWaterMark"); + v8::Local<v8::Value> high_water_mark_value = + v8::Number::New(isolate, high_water_mark); + + auto strategy = + v8::Object::New(isolate, v8::Null(isolate), &high_water_mark_string, + &high_water_mark_value, 1); + + return ScriptValue(isolate, strategy); +} + CORE_EXPORT v8::MaybeLocal<v8::Value> CallOrNoop1( ScriptState* script_state, v8::Local<v8::Object> object,
diff --git a/third_party/blink/renderer/core/streams/miscellaneous_operations.h b/third_party/blink/renderer/core/streams/miscellaneous_operations.h index 70dacef..692b138f 100644 --- a/third_party/blink/renderer/core/streams/miscellaneous_operations.h +++ b/third_party/blink/renderer/core/streams/miscellaneous_operations.h
@@ -84,6 +84,13 @@ // undefined. CORE_EXPORT StreamAlgorithm* CreateTrivialStreamAlgorithm(); +// Returns a strategy object that has no size() function and the supplied +// highWaterMark. It has a null prototype so that it won't be affected by +// changes to the global Object prototype. It behaves the same as a +// CountQueuingStrategy but is faster and safer to use from C++. +CORE_EXPORT ScriptValue CreateTrivialQueuingStrategy(v8::Isolate*, + size_t high_water_mark); + // Used in place of InvokeOrNoop in spec. Always takes 1 argument. // https://streams.spec.whatwg.org/#invoke-or-noop CORE_EXPORT v8::MaybeLocal<v8::Value> CallOrNoop1(ScriptState*,
diff --git a/third_party/blink/renderer/core/streams/readable_stream.cc b/third_party/blink/renderer/core/streams/readable_stream.cc index 6236b1a..127ac6e5 100644 --- a/third_party/blink/renderer/core/streams/readable_stream.cc +++ b/third_party/blink/renderer/core/streams/readable_stream.cc
@@ -1116,19 +1116,7 @@ std::unique_ptr<ReadableStreamTransferringOptimizer> optimizer) { auto* isolate = script_state->GetIsolate(); - // It's safer to use a workalike rather than a real CountQueuingStrategy - // object. We use the default "size" function as it is implemented in C++ and - // so much faster than calling into JavaScript. Since the create object has a - // null prototype, there is no danger of us finding some other "size" function - // via the prototype chain. - v8::Local<v8::Name> high_water_mark_string = - V8AtomicString(isolate, "highWaterMark"); - v8::Local<v8::Value> high_water_mark_value = - v8::Number::New(isolate, high_water_mark); - - auto strategy_object = - v8::Object::New(isolate, v8::Null(isolate), &high_water_mark_string, - &high_water_mark_value, 1); + auto strategy = CreateTrivialQueuingStrategy(isolate, high_water_mark); ExceptionState exception_state(isolate, ExceptionState::kConstructionContext, "ReadableStream"); @@ -1140,8 +1128,7 @@ auto* stream = MakeGarbageCollected<ReadableStream>(); stream->InitInternal(script_state, ScriptValue(isolate, underlying_source_v8), - ScriptValue(isolate, strategy_object), true, - exception_state); + strategy, true, exception_state); if (exception_state.HadException()) { exception_state.ClearException();
diff --git a/third_party/blink/renderer/core/streams/writable_stream.cc b/third_party/blink/renderer/core/streams/writable_stream.cc index 3f7dcbd..e47f01b 100644 --- a/third_party/blink/renderer/core/streams/writable_stream.cc +++ b/third_party/blink/renderer/core/streams/writable_stream.cc
@@ -210,33 +210,41 @@ UnderlyingSinkBase* underlying_sink, size_t high_water_mark, std::unique_ptr<WritableStreamTransferringOptimizer> optimizer) { - // TODO(crbug.com/902633): This method of constructing a WritableStream - // introduces unnecessary trips through V8. Implement algorithms based on an - // UnderlyingSinkBase. - auto* init = QueuingStrategyInit::Create(); - init->setHighWaterMark(static_cast<double>(high_water_mark)); - auto* strategy = CountQueuingStrategy::Create(script_state, init); - ScriptValue strategy_value = ScriptValue::From(script_state, strategy); - if (strategy_value.IsEmpty()) - return nullptr; - - auto underlying_sink_value = ScriptValue::From(script_state, underlying_sink); - v8::Isolate* isolate = script_state->GetIsolate(); ExceptionState exception_state(isolate, ExceptionState::kConstructionContext, "WritableStream"); v8::MicrotasksScope microtasks_scope( isolate, v8::MicrotasksScope::kDoNotRunMicrotasks); auto* stream = MakeGarbageCollected<WritableStream>(); - stream->InitInternal(script_state, underlying_sink_value, strategy_value, - exception_state); + stream->InitWithCountQueueingStrategy(script_state, underlying_sink, + high_water_mark, std::move(optimizer), + exception_state); if (exception_state.HadException()) return nullptr; - stream->transferring_optimizer_ = std::move(optimizer); return stream; } +void WritableStream::InitWithCountQueueingStrategy( + ScriptState* script_state, + UnderlyingSinkBase* underlying_sink, + size_t high_water_mark, + std::unique_ptr<WritableStreamTransferringOptimizer> optimizer, + ExceptionState& exception_state) { + ScriptValue strategy_value = + CreateTrivialQueuingStrategy(script_state->GetIsolate(), high_water_mark); + + auto underlying_sink_value = ScriptValue::From(script_state, underlying_sink); + + // TODO(crbug.com/902633): This method of constructing a WritableStream + // introduces unnecessary trips through V8. Implement algorithms based on an + // UnderlyingSinkBase. + InitInternal(script_state, underlying_sink_value, strategy_value, + exception_state); + + transferring_optimizer_ = std::move(optimizer); +} + void WritableStream::Serialize(ScriptState* script_state, MessagePort* port, ExceptionState& exception_state) {
diff --git a/third_party/blink/renderer/core/streams/writable_stream.h b/third_party/blink/renderer/core/streams/writable_stream.h index 6ed34e0..0022a25 100644 --- a/third_party/blink/renderer/core/streams/writable_stream.h +++ b/third_party/blink/renderer/core/streams/writable_stream.h
@@ -78,6 +78,15 @@ WritableStream(); ~WritableStream() override; + // This should only be used with freshly-constructed streams. It expects to be + // called in a valid microtask scope. + void InitWithCountQueueingStrategy( + ScriptState*, + UnderlyingSinkBase*, + size_t high_water_mark, + std::unique_ptr<WritableStreamTransferringOptimizer>, + ExceptionState&); + // IDL defined functions // https://streams.spec.whatwg.org/#ws-locked @@ -229,6 +238,7 @@ protected: // Used when creating a stream from JavaScript. Called from Create(). // https://streams.spec.whatwg.org/#ws-constructor + // TODO(ricea): Port external callers to InitWithCountQueuingStrategy(). void InitInternal(ScriptState*, ScriptValue raw_underlying_sink, ScriptValue raw_strategy,
diff --git a/third_party/blink/renderer/core/svg/graphics/svg_image.cc b/third_party/blink/renderer/core/svg/graphics/svg_image.cc index f0d16f7..e222cfc 100644 --- a/third_party/blink/renderer/core/svg/graphics/svg_image.cc +++ b/third_party/blink/renderer/core/svg/graphics/svg_image.cc
@@ -481,7 +481,7 @@ const FloatRect bounds(FloatPoint(), draw_info.ContainerSize()); flags.setShader(PaintShader::MakePaintRecord( - std::move(record), bounds, SkTileMode::kRepeat, SkTileMode::kRepeat, + std::move(record), bounds, SkTileMode::kClamp, SkTileMode::kClamp, &local_matrix)); // Animation is normally refreshed in Draw() impls, which we don't reach when
diff --git a/third_party/blink/renderer/core/testing/fake_remote_main_frame_host.cc b/third_party/blink/renderer/core/testing/fake_remote_main_frame_host.cc index b34e920..3533143a 100644 --- a/third_party/blink/renderer/core/testing/fake_remote_main_frame_host.cc +++ b/third_party/blink/renderer/core/testing/fake_remote_main_frame_host.cc
@@ -8,13 +8,10 @@ namespace blink { -void FakeRemoteMainFrameHost::Init( - blink::AssociatedInterfaceProvider* provider) { - provider->OverrideBinderForTesting( - mojom::blink::RemoteMainFrameHost::Name_, - base::BindRepeating( - &FakeRemoteMainFrameHost::BindRemoteMainFrameHostReceiver, - base::Unretained(this))); +mojo::PendingAssociatedRemote<mojom::blink::RemoteMainFrameHost> +FakeRemoteMainFrameHost::BindNewAssociatedRemote() { + receiver_.reset(); + return receiver_.BindNewEndpointAndPassDedicatedRemote(); } void FakeRemoteMainFrameHost::FocusPage() {} @@ -27,11 +24,4 @@ void FakeRemoteMainFrameHost::RouteCloseEvent() {} -void FakeRemoteMainFrameHost::BindRemoteMainFrameHostReceiver( - mojo::ScopedInterfaceEndpointHandle handle) { - receiver_.Bind( - mojo::PendingAssociatedReceiver<mojom::blink::RemoteMainFrameHost>( - std::move(handle))); -} - } // namespace blink
diff --git a/third_party/blink/renderer/core/testing/fake_remote_main_frame_host.h b/third_party/blink/renderer/core/testing/fake_remote_main_frame_host.h index 2d11f7e9..75ca67b9 100644 --- a/third_party/blink/renderer/core/testing/fake_remote_main_frame_host.h +++ b/third_party/blink/renderer/core/testing/fake_remote_main_frame_host.h
@@ -6,21 +6,21 @@ #define THIRD_PARTY_BLINK_RENDERER_CORE_TESTING_FAKE_REMOTE_MAIN_FRAME_HOST_H_ #include "mojo/public/cpp/bindings/associated_receiver_set.h" -#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h" #include "third_party/blink/public/mojom/frame/frame.mojom-blink.h" #include "third_party/blink/renderer/platform/weborigin/kurl.h" namespace blink { -// This class implements a RemoteMainFrameHost that can be attached to the -// AssociatedInterfaceProvider so that it will be called when the renderer -// normally sends a request to the browser process. But for a unittest -// setup it can be intercepted by this class. +// This class implements a RemoteMainFrameHost that will be called when the +// renderer normally sends a request to the browser process. But for a unittest +// setup it can be intercepted by this class with passing a corresponding +// fake remote. class FakeRemoteMainFrameHost : public mojom::blink::RemoteMainFrameHost { public: FakeRemoteMainFrameHost() = default; - void Init(blink::AssociatedInterfaceProvider* provider); + mojo::PendingAssociatedRemote<mojom::blink::RemoteMainFrameHost> + BindNewAssociatedRemote(); // blink::mojom::RemoteMainFrameHost overrides: void FocusPage() override; @@ -31,9 +31,6 @@ void RouteCloseEvent() override; private: - void BindRemoteMainFrameHostReceiver( - mojo::ScopedInterfaceEndpointHandle handle); - mojo::AssociatedReceiver<mojom::blink::RemoteMainFrameHost> receiver_{this}; };
diff --git a/third_party/blink/renderer/core/timing/build.gni b/third_party/blink/renderer/core/timing/build.gni index 5d43f873..c12d93b 100644 --- a/third_party/blink/renderer/core/timing/build.gni +++ b/third_party/blink/renderer/core/timing/build.gni
@@ -15,6 +15,8 @@ "layout_shift.h", "layout_shift_attribution.cc", "layout_shift_attribution.h", + "measure_memory/local_web_memory_measurer.cc", + "measure_memory/local_web_memory_measurer.h", "measure_memory/measure_memory_controller.cc", "measure_memory/measure_memory_controller.h", "memory_info.cc",
diff --git a/third_party/blink/renderer/core/timing/measure_memory/local_web_memory_measurer.cc b/third_party/blink/renderer/core/timing/measure_memory/local_web_memory_measurer.cc new file mode 100644 index 0000000..e474b58 --- /dev/null +++ b/third_party/blink/renderer/core/timing/measure_memory/local_web_memory_measurer.cc
@@ -0,0 +1,89 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/blink/renderer/core/timing/measure_memory/local_web_memory_measurer.h" + +#include <memory> +#include <utility> + +#include "base/check.h" +#include "third_party/blink/renderer/core/timing/measure_memory/measure_memory_controller.h" +#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" +#include "third_party/blink/renderer/platform/wtf/vector.h" + +namespace blink { + +using performance_manager::mojom::blink::WebMemoryAttribution; +using performance_manager::mojom::blink::WebMemoryAttributionPtr; +using performance_manager::mojom::blink::WebMemoryBreakdownEntry; +using performance_manager::mojom::blink::WebMemoryBreakdownEntryPtr; +using performance_manager::mojom::blink::WebMemoryMeasurement; +using performance_manager::mojom::blink::WebMemoryMeasurementPtr; +using performance_manager::mojom::blink::WebMemoryUsage; + +namespace { +v8::MeasureMemoryExecution ToV8MeasureMemoryExecution( + WebMemoryMeasurement::Mode mode) { + switch (mode) { + case WebMemoryMeasurement::Mode::kDefault: + return v8::MeasureMemoryExecution::kDefault; + case WebMemoryMeasurement::Mode::kEager: + return v8::MeasureMemoryExecution::kEager; + } + NOTREACHED(); +} +} // anonymous namespace + +// static +void LocalWebMemoryMeasurer::StartMeasurement( + v8::Isolate* isolate, + WebMemoryMeasurement::Mode mode, + MeasureMemoryController* controller, + WebMemoryAttribution::Scope attribution_scope, + WTF::String attribution_url) { + // We cannot use std::make_unique here because the constructor is private. + auto delegate = + std::unique_ptr<LocalWebMemoryMeasurer>(new LocalWebMemoryMeasurer( + controller, attribution_scope, attribution_url)); + isolate->MeasureMemory(std::move(delegate), ToV8MeasureMemoryExecution(mode)); +} + +LocalWebMemoryMeasurer::LocalWebMemoryMeasurer( + MeasureMemoryController* controller, + WebMemoryAttribution::Scope attribution_scope, + WTF::String attribution_url) + : controller_(controller), + attribution_scope_(attribution_scope), + attribution_url_(attribution_url) {} + +LocalWebMemoryMeasurer::~LocalWebMemoryMeasurer() = default; + +bool LocalWebMemoryMeasurer::ShouldMeasure(v8::Local<v8::Context> context) { + return true; +} + +void LocalWebMemoryMeasurer::MeasurementComplete( + const std::vector<std::pair<v8::Local<v8::Context>, size_t>>& context_sizes, + size_t unattributed_size) { + DCHECK_LE(context_sizes.size(), 1u); + // The isolate has only one context, so all memory of the isolate can be + // attributed to that context. + size_t bytes = unattributed_size; + for (const auto& context_size : context_sizes) { + bytes += context_size.second; + } + WebMemoryAttributionPtr attribution = WebMemoryAttribution::New(); + attribution->scope = attribution_scope_; + attribution->url = attribution_url_; + WebMemoryBreakdownEntryPtr breakdown = WebMemoryBreakdownEntry::New(); + breakdown->attribution.emplace_back(std::move(attribution)); + breakdown->memory = WebMemoryUsage::New(bytes); + WebMemoryMeasurementPtr measurement = WebMemoryMeasurement::New(); + measurement->breakdown.push_back(std::move(breakdown)); + measurement->blink_memory = WebMemoryUsage::New(0); + measurement->shared_memory = WebMemoryUsage::New(0); + controller_->MeasurementComplete(std::move(measurement)); +} + +} // namespace blink
diff --git a/third_party/blink/renderer/core/timing/measure_memory/local_web_memory_measurer.h b/third_party/blink/renderer/core/timing/measure_memory/local_web_memory_measurer.h new file mode 100644 index 0000000..68377c6 --- /dev/null +++ b/third_party/blink/renderer/core/timing/measure_memory/local_web_memory_measurer.h
@@ -0,0 +1,63 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_TIMING_MEASURE_MEMORY_LOCAL_WEB_MEMORY_MEASURER_H_ +#define THIRD_PARTY_BLINK_RENDERER_CORE_TIMING_MEASURE_MEMORY_LOCAL_WEB_MEMORY_MEASURER_H_ + +#include "components/performance_manager/public/mojom/web_memory.mojom-blink.h" + +#include "third_party/blink/renderer/platform/heap/persistent.h" +#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" +#include "v8/include/v8.h" + +namespace blink { + +class MeasureMemoryController; + +// Performs a memory measurement of a V8 isolate containing +// a single context. It is a much simplified version of +// performance_manager::v8_memory::WebMemoryMeasurer and does +// not require aggregation of multiple nodes. +// +// This is used in service and shared workers. +class LocalWebMemoryMeasurer : public v8::MeasureMemoryDelegate { + public: + using WebMemoryAttribution = + performance_manager::mojom::blink::WebMemoryAttribution; + using WebMemoryMeasurement = + performance_manager::mojom::blink::WebMemoryMeasurement; + + ~LocalWebMemoryMeasurer() override; + + // Measures the memory usage the given isolate using the given + // measurement mode. When the measurement is done, it constructs + // a new WebMemoryMeasurement containing a single breakdown entry + // with the attribution set to the given scope and URL. + // The measurement result is passed to + // MeasureMemoryController::MeasurementComplete. + static void StartMeasurement(v8::Isolate*, + WebMemoryMeasurement::Mode, + MeasureMemoryController*, + WebMemoryAttribution::Scope, + WTF::String attribution_url); + + // v8::MeasureMemoryDelegate overrides. + bool ShouldMeasure(v8::Local<v8::Context> context) override; + void MeasurementComplete( + const std::vector<std::pair<v8::Local<v8::Context>, size_t>>& + context_sizes, + size_t unattributed_size) override; + + private: + LocalWebMemoryMeasurer(MeasureMemoryController*, + WebMemoryAttribution::Scope, + WTF::String attribution_url); + Persistent<MeasureMemoryController> controller_; + WebMemoryAttribution::Scope attribution_scope_; + WTF::String attribution_url_; +}; + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_CORE_TIMING_MEASURE_MEMORY_LOCAL_WEB_MEMORY_MEASURER_H_
diff --git a/third_party/blink/renderer/core/timing/measure_memory/measure_memory_controller.cc b/third_party/blink/renderer/core/timing/measure_memory/measure_memory_controller.cc index 877c73ff..5d2837d 100644 --- a/third_party/blink/renderer/core/timing/measure_memory/measure_memory_controller.cc +++ b/third_party/blink/renderer/core/timing/measure_memory/measure_memory_controller.cc
@@ -20,6 +20,8 @@ #include "third_party/blink/renderer/core/frame/local_dom_window.h" #include "third_party/blink/renderer/core/frame/local_frame.h" #include "third_party/blink/renderer/core/frame/settings.h" +#include "third_party/blink/renderer/core/timing/measure_memory/local_web_memory_measurer.h" +#include "third_party/blink/renderer/core/workers/worker_global_scope.h" #include "third_party/blink/renderer/platform/bindings/exception_state.h" #include "third_party/blink/renderer/platform/bindings/script_state.h" #include "third_party/blink/renderer/platform/heap/heap.h" @@ -49,6 +51,8 @@ constexpr const char* kMemoryTypeShared = "Shared"; constexpr const char* kScopeCrossOriginAggregated = "cross-origin-aggregated"; constexpr const char* kScopeDedicatedWorker = "DedicatedWorker"; +constexpr const char* kScopeServiceWorker = "ServiceWorkerGlobalScope"; +constexpr const char* kScopeSharedWorker = "SharedWorkerGlobalScope"; constexpr const char* kScopeWindow = "Window"; } // anonymous namespace @@ -82,41 +86,58 @@ kNotAvailableDueToResourceCoordinator, }; -ApiStatus CheckMeasureMemoryAvailability(LocalDOMWindow* window) { +ApiStatus CheckMeasureMemoryAvailability() { if (!base::FeatureList::IsEnabled( features::kWebMeasureMemoryViaPerformanceManager)) { return ApiStatus::kNotAvailableDueToFlag; } - if (!window) { - return ApiStatus::kNotAvailableDueToDetachedContext; - } - LocalFrame* local_frame = window->GetFrame(); - if (!local_frame) { - return ApiStatus::kNotAvailableDueToDetachedContext; - } - - DCHECK(window->CrossOriginIsolatedCapability() || - local_frame->GetSettings()->GetWebSecurityEnabled()); - - // We need DocumentResourceCoordinator to query PerformanceManager. - if (!window->document()) { - return ApiStatus::kNotAvailableDueToDetachedContext; - } - - if (!window->document()->GetResourceCoordinator()) { + if (!RuntimeEnabledFeatures::PerformanceManagerInstrumentationEnabled()) { return ApiStatus::kNotAvailableDueToResourceCoordinator; } - return ApiStatus::kAvailable; } +bool IsAttached(ExecutionContext* execution_context) { + auto* window = To<LocalDOMWindow>(execution_context); + return window && window->GetFrame() && window->document(); +} + +void StartMemoryMeasurement(LocalDOMWindow* window, + MeasureMemoryController* controller, + WebMemoryMeasurement::Mode mode) { + Document* document = window->document(); + document->GetResourceCoordinator()->OnWebMemoryMeasurementRequested( + mode, WTF::Bind(&MeasureMemoryController::MeasurementComplete, + WrapPersistent(controller))); +} + +void StartMemoryMeasurement(WorkerGlobalScope* worker, + MeasureMemoryController* controller, + WebMemoryMeasurement::Mode mode) { + DCHECK(worker->IsSharedWorkerGlobalScope() || + worker->IsServiceWorkerGlobalScope()); + WebMemoryAttribution::Scope attribution_scope = + worker->IsServiceWorkerGlobalScope() + ? WebMemoryAttribution::Scope::kServiceWorker + : WebMemoryAttribution::Scope::kSharedWorker; + LocalWebMemoryMeasurer::StartMeasurement(worker->GetIsolate(), mode, + controller, attribution_scope, + worker->Url().GetString()); +} + } // anonymous namespace ScriptPromise MeasureMemoryController::StartMeasurement( ScriptState* script_state, ExceptionState& exception_state) { - switch (auto status = CheckMeasureMemoryAvailability( - LocalDOMWindow::From(script_state))) { + ExecutionContext* execution_context = ExecutionContext::From(script_state); + DCHECK(execution_context->CrossOriginIsolatedCapability()); + ApiStatus status = CheckMeasureMemoryAvailability(); + if (status == ApiStatus::kAvailable && execution_context->IsWindow() && + !IsAttached(execution_context)) { + status = ApiStatus::kNotAvailableDueToDetachedContext; + } + switch (status) { case ApiStatus::kAvailable: break; case ApiStatus::kNotAvailableDueToFlag: @@ -152,11 +173,14 @@ auto* impl = MakeGarbageCollected<MeasureMemoryController>( base::PassKey<MeasureMemoryController>(), isolate, context, promise_resolver); - Document* document = LocalDOMWindow::From(script_state)->document(); - document->GetResourceCoordinator()->OnWebMemoryMeasurementRequested( - measurement_mode, WTF::Bind(&MeasureMemoryController::MeasurementComplete, - WrapPersistent(impl))); + if (execution_context->IsWindow()) { + StartMemoryMeasurement(To<LocalDOMWindow>(execution_context), impl, + measurement_mode); + } else { + StartMemoryMeasurement(To<WorkerGlobalScope>(execution_context), impl, + measurement_mode); + } return ScriptPromise(script_state, promise_resolver->GetPromise()); } @@ -186,6 +210,10 @@ return kScopeWindow; case Scope::kCrossOriginAggregated: return kScopeCrossOriginAggregated; + case Scope::kServiceWorker: + return kScopeServiceWorker; + case Scope::kSharedWorker: + return kScopeSharedWorker; } }
diff --git a/third_party/blink/renderer/core/timing/measure_memory/measure_memory_controller.h b/third_party/blink/renderer/core/timing/measure_memory/measure_memory_controller.h index e280ba2..5da5bb8 100644 --- a/third_party/blink/renderer/core/timing/measure_memory/measure_memory_controller.h +++ b/third_party/blink/renderer/core/timing/measure_memory/measure_memory_controller.h
@@ -42,11 +42,10 @@ void Trace(Visitor* visitor) const; - private: - // Invoked when the memory of the main V8 isolate is measured. void MeasurementComplete( performance_manager::mojom::blink::WebMemoryMeasurementPtr); + private: v8::Isolate* isolate_; ScopedPersistent<v8::Context> context_; TraceWrapperV8Reference<v8::Promise::Resolver> promise_resolver_;
diff --git a/third_party/blink/renderer/core/timing/performance.idl b/third_party/blink/renderer/core/timing/performance.idl index 80a71a5c..7088dff9 100644 --- a/third_party/blink/renderer/core/timing/performance.idl +++ b/third_party/blink/renderer/core/timing/performance.idl
@@ -67,7 +67,9 @@ // https://groups.google.com/a/chromium.org/d/msg/blink-dev/g5YRCGpC9vs/b4OJz71NmPwJ [Exposed=Window, Measure, CallWith=ScriptState] readonly attribute MemoryInfo memory; - [MeasureAs=MeasureMemory, Exposed=Window, CallWith=ScriptState, RuntimeEnabled=MeasureMemory, RaisesException, CrossOriginIsolated] Promise<MemoryMeasurement> measureUserAgentSpecificMemory(); + // The API is not exposed to DedicatedWorker because the memory usage of + // a dedicated worker is included in the result of the API call in Window. + [MeasureAs=MeasureMemory, Exposed=(Window,ServiceWorker,SharedWorker), CallWith=ScriptState, RuntimeEnabled=MeasureMemory, RaisesException, CrossOriginIsolated] Promise<MemoryMeasurement> measureUserAgentSpecificMemory(); // JS Self-Profiling API // https://github.com/WICG/js-self-profiling/
diff --git a/third_party/blink/renderer/modules/payments/OWNERS b/third_party/blink/renderer/modules/payments/OWNERS index 06b9d2b..88a70bc 100644 --- a/third_party/blink/renderer/modules/payments/OWNERS +++ b/third_party/blink/renderer/modules/payments/OWNERS
@@ -8,4 +8,4 @@ per-file *_type_converter*.*=file://ipc/SECURITY_OWNERS # Emeritus -mathp@chromium.org \ No newline at end of file +mathp@chromium.org
diff --git a/third_party/blink/renderer/modules/screen_enumeration/global_screen_enumeration.cc b/third_party/blink/renderer/modules/screen_enumeration/global_screen_enumeration.cc index a644cff..bf0a211 100644 --- a/third_party/blink/renderer/modules/screen_enumeration/global_screen_enumeration.cc +++ b/third_party/blink/renderer/modules/screen_enumeration/global_screen_enumeration.cc
@@ -6,6 +6,7 @@ #include "mojo/public/cpp/bindings/remote.h" #include "third_party/blink/public/common/browser_interface_broker_proxy.h" +#include "third_party/blink/public/mojom/permissions_policy/permissions_policy.mojom-blink.h" #include "third_party/blink/public/mojom/screen_enumeration/screen_enumeration.mojom-blink.h" #include "third_party/blink/renderer/bindings/core/v8/script_promise.h" #include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h" @@ -108,11 +109,19 @@ return ScriptPromise(); } + auto* context = ExecutionContext::From(script_state); + if (!context->IsFeatureEnabled( + mojom::blink::PermissionsPolicyFeature::kWindowPlacement)) { + exception_state.ThrowDOMException( + DOMExceptionCode::kInvalidStateError, + "Screen information is unavailable or access is not allowed."); + return ScriptPromise(); + } + // TODO(msw): Cache the backend connection. mojo::Remote<mojom::blink::ScreenEnumeration> backend; - ExecutionContext::From(script_state) - ->GetBrowserInterfaceBroker() - .GetInterface(backend.BindNewPipeAndPassReceiver()); + context->GetBrowserInterfaceBroker().GetInterface( + backend.BindNewPipeAndPassReceiver()); auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state); auto* raw_backend = backend.get();
diff --git a/third_party/blink/renderer/modules/webtransport/bidirectional_stream.cc b/third_party/blink/renderer/modules/webtransport/bidirectional_stream.cc index 4cdbfd96..54c9d4e 100644 --- a/third_party/blink/renderer/modules/webtransport/bidirectional_stream.cc +++ b/third_party/blink/renderer/modules/webtransport/bidirectional_stream.cc
@@ -8,6 +8,7 @@ #include "base/check.h" #include "third_party/blink/renderer/modules/webtransport/web_transport.h" +#include "third_party/blink/renderer/platform/bindings/exception_state.h" #include "third_party/blink/renderer/platform/heap/heap.h" #include "third_party/blink/renderer/platform/heap/persistent.h" #include "third_party/blink/renderer/platform/heap/visitor.h" @@ -32,8 +33,11 @@ web_transport_(web_transport), stream_id_(stream_id) {} -void BidirectionalStream::Init() { - outgoing_stream_->Init(); +void BidirectionalStream::Init(ExceptionState& exception_state) { + outgoing_stream_->Init(exception_state); + if (exception_state.HadException()) + return; + incoming_stream_->Init(); }
diff --git a/third_party/blink/renderer/modules/webtransport/bidirectional_stream.h b/third_party/blink/renderer/modules/webtransport/bidirectional_stream.h index 8cc2cf06..4a49fae 100644 --- a/third_party/blink/renderer/modules/webtransport/bidirectional_stream.h +++ b/third_party/blink/renderer/modules/webtransport/bidirectional_stream.h
@@ -34,7 +34,7 @@ mojo::ScopedDataPipeProducerHandle, mojo::ScopedDataPipeConsumerHandle); - void Init(); + void Init(ExceptionState&); // Implementation of bidirectional_stream.idl. As noted in the IDL file, these // properties are implemented on OutgoingStream and IncomingStream in the
diff --git a/third_party/blink/renderer/modules/webtransport/outgoing_stream.cc b/third_party/blink/renderer/modules/webtransport/outgoing_stream.cc index 243e1ee..d8b0d6e8 100644 --- a/third_party/blink/renderer/modules/webtransport/outgoing_stream.cc +++ b/third_party/blink/renderer/modules/webtransport/outgoing_stream.cc
@@ -17,6 +17,7 @@ #include "third_party/blink/renderer/core/execution_context/execution_context.h" #include "third_party/blink/renderer/core/streams/underlying_sink_base.h" #include "third_party/blink/renderer/core/streams/writable_stream.h" +#include "third_party/blink/renderer/core/streams/writable_stream_transferring_optimizer.h" #include "third_party/blink/renderer/modules/webtransport/web_transport_stream.h" #include "third_party/blink/renderer/platform/bindings/exception_code.h" #include "third_party/blink/renderer/platform/bindings/exception_state.h" @@ -129,9 +130,15 @@ OutgoingStream::~OutgoingStream() = default; -void OutgoingStream::Init() { +void OutgoingStream::Init(ExceptionState& exception_state) { DVLOG(1) << "OutgoingStream::Init() this=" << this; + auto* stream = MakeGarbageCollected<WritableStream>(); + InitWithExistingWritableStream(stream, exception_state); +} +void OutgoingStream::InitWithExistingWritableStream( + WritableStream* stream, + ExceptionState& exception_state) { write_watcher_.Watch(data_pipe_.get(), MOJO_HANDLE_SIGNAL_WRITABLE, MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED, WTF::BindRepeating(&OutgoingStream::OnHandleReady, @@ -146,8 +153,10 @@ writing_aborted_resolver_ = MakeGarbageCollected<ScriptPromiseResolver>(script_state_); writing_aborted_ = writing_aborted_resolver_->Promise(); - writable_ = WritableStream::CreateWithCountQueueingStrategy( - script_state_, MakeGarbageCollected<UnderlyingSink>(this), 1); + writable_ = stream; + stream->InitWithCountQueueingStrategy( + script_state_, MakeGarbageCollected<UnderlyingSink>(this), 1, + /*optimizer=*/nullptr, exception_state); } void OutgoingStream::AbortWriting(StreamAbortInfo* stream_abort_info) {
diff --git a/third_party/blink/renderer/modules/webtransport/outgoing_stream.h b/third_party/blink/renderer/modules/webtransport/outgoing_stream.h index bcdc87e..ec71cd30 100644 --- a/third_party/blink/renderer/modules/webtransport/outgoing_stream.h +++ b/third_party/blink/renderer/modules/webtransport/outgoing_stream.h
@@ -24,6 +24,7 @@ namespace blink { +class ExceptionState; class ScriptState; class StreamAbortInfo; class WritableStream; @@ -61,8 +62,11 @@ OutgoingStream(ScriptState*, Client*, mojo::ScopedDataPipeProducerHandle); ~OutgoingStream(); - // Init() must be called before the stream is used. - void Init(); + // Init() or InitWithExistingWritableStream() must be called before the stream + // is used. + void Init(ExceptionState&); + + void InitWithExistingWritableStream(WritableStream*, ExceptionState&); // Implementation of OutgoingStream IDL, used by client classes to implement // it. https://wicg.github.io/web-transport/#outgoing-stream
diff --git a/third_party/blink/renderer/modules/webtransport/outgoing_stream_test.cc b/third_party/blink/renderer/modules/webtransport/outgoing_stream_test.cc index 23d824f..758be34 100644 --- a/third_party/blink/renderer/modules/webtransport/outgoing_stream_test.cc +++ b/third_party/blink/renderer/modules/webtransport/outgoing_stream_test.cc
@@ -71,7 +71,11 @@ mock_client_ = MakeGarbageCollected<StrictMock<MockClient>>(); auto* outgoing_stream = MakeGarbageCollected<OutgoingStream>( script_state, mock_client_, std::move(data_pipe_producer)); - outgoing_stream->Init(); + ExceptionState exception_state(scope.GetIsolate(), + ExceptionState::kConstructionContext, + "OutgoingStream"); + outgoing_stream->Init(exception_state); + CHECK(!exception_state.HadException()); return outgoing_stream; }
diff --git a/third_party/blink/renderer/modules/webtransport/send_stream.cc b/third_party/blink/renderer/modules/webtransport/send_stream.cc index af4824e6..b1f02f65d 100644 --- a/third_party/blink/renderer/modules/webtransport/send_stream.cc +++ b/third_party/blink/renderer/modules/webtransport/send_stream.cc
@@ -50,7 +50,7 @@ void SendStream::Trace(Visitor* visitor) const { visitor->Trace(outgoing_stream_); visitor->Trace(web_transport_); - ScriptWrappable::Trace(visitor); + WritableStream::Trace(visitor); WebTransportStream::Trace(visitor); OutgoingStream::Client::Trace(visitor); }
diff --git a/third_party/blink/renderer/modules/webtransport/send_stream.h b/third_party/blink/renderer/modules/webtransport/send_stream.h index 840d90e..a051013 100644 --- a/third_party/blink/renderer/modules/webtransport/send_stream.h +++ b/third_party/blink/renderer/modules/webtransport/send_stream.h
@@ -8,6 +8,7 @@ #include <stdint.h> #include "mojo/public/cpp/system/data_pipe.h" +#include "third_party/blink/renderer/core/streams/writable_stream.h" #include "third_party/blink/renderer/modules/modules_export.h" #include "third_party/blink/renderer/modules/webtransport/outgoing_stream.h" #include "third_party/blink/renderer/modules/webtransport/web_transport_stream.h" @@ -17,10 +18,11 @@ namespace blink { +class ExceptionState; class WebTransport; class ScriptState; -class MODULES_EXPORT SendStream final : public ScriptWrappable, +class MODULES_EXPORT SendStream final : public WritableStream, public WebTransportStream, public OutgoingStream::Client { DEFINE_WRAPPERTYPEINFO(); @@ -34,11 +36,13 @@ mojo::ScopedDataPipeProducerHandle); ~SendStream() override; - void Init() { outgoing_stream_->Init(); } + void Init(ExceptionState& exception_state) { + outgoing_stream_->InitWithExistingWritableStream(this, exception_state); + } - // Implementation of send_stream.idl. As noted in the IDL file, these - // properties are implemented on OutgoingStream in the standard. - WritableStream* writable() const { return outgoing_stream_->Writable(); } + // Methods for backwards compatibility. + // TODO(ricea): Remove them when they have been removed from the IDL file. + SendStream* writable() { return this; } ScriptPromise writingAborted() const { return outgoing_stream_->WritingAborted();
diff --git a/third_party/blink/renderer/modules/webtransport/send_stream.idl b/third_party/blink/renderer/modules/webtransport/send_stream.idl index fc58013..274cec5 100644 --- a/third_party/blink/renderer/modules/webtransport/send_stream.idl +++ b/third_party/blink/renderer/modules/webtransport/send_stream.idl
@@ -6,11 +6,10 @@ [ Exposed=(Window,Worker), RuntimeEnabled=WebTransport ] -interface SendStream { - // OutgoingStream interface. In the standard this is a mixin, but we can't use - // a mixin in the implementation because BidirectionalStream would end up - // inheriting from two mixins, causing diamond inheritance. - readonly attribute WritableStream writable; +interface SendStream : WritableStream { + // These attributes and method are for backwards compatibility. + // TODO(ricea): Remove them once the origin trial is over. + readonly attribute SendStream writable; readonly attribute Promise<StreamAbortInfo> writingAborted; void abortWriting(optional StreamAbortInfo abortInfo = {}); };
diff --git a/third_party/blink/renderer/modules/webtransport/web_transport.cc b/third_party/blink/renderer/modules/webtransport/web_transport.cc index 6b00defe..6c83f91 100644 --- a/third_party/blink/renderer/modules/webtransport/web_transport.cc +++ b/third_party/blink/renderer/modules/webtransport/web_transport.cc
@@ -44,6 +44,7 @@ #include "third_party/blink/renderer/platform/wtf/functional.h" #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" #include "third_party/blink/renderer/platform/wtf/vector.h" +#include "v8/include/v8.h" namespace blink { @@ -347,7 +348,19 @@ auto* bidirectional_stream = MakeGarbageCollected<BidirectionalStream>( script_state_, web_transport_, stream_id, std::move(outgoing_producer), std::move(incoming_consumer)); - bidirectional_stream->Init(); + + auto* isolate = script_state_->GetIsolate(); + ExceptionState exception_state( + isolate, ExceptionState::kConstructionContext, "BidirectionalStream"); + v8::MicrotasksScope microtasks_scope( + isolate, v8::MicrotasksScope::kDoNotRunMicrotasks); + bidirectional_stream->Init(exception_state); + if (exception_state.HadException()) { + // Just throw away the stream. + exception_state.ClearException(); + return; + } + // 0xfffffffe and 0xffffffff are reserved values in stream_map_. CHECK_LT(stream_id, 0xfffffffe); web_transport_->stream_map_.insert(stream_id, bidirectional_stream); @@ -858,7 +871,18 @@ auto* send_stream = MakeGarbageCollected<SendStream>( script_state_, this, stream_id, std::move(producer)); - send_stream->Init(); + + auto* isolate = script_state_->GetIsolate(); + ExceptionState exception_state(isolate, ExceptionState::kConstructionContext, + "SendStream"); + v8::MicrotasksScope microtasks_scope( + isolate, v8::MicrotasksScope::kDoNotRunMicrotasks); + send_stream->Init(exception_state); + if (exception_state.HadException()) { + resolver->Reject(exception_state.GetException()); + exception_state.ClearException(); + return; + } // 0xfffffffe and 0xffffffff are reserved values in stream_map_. CHECK_LT(stream_id, 0xfffffffe); @@ -885,9 +909,10 @@ return; ScriptState::Scope scope(script_state_); + auto* isolate = script_state_->GetIsolate(); if (!succeeded) { resolver->Reject(V8ThrowDOMException::CreateOrEmpty( - script_state_->GetIsolate(), DOMExceptionCode::kNetworkError, + isolate, DOMExceptionCode::kNetworkError, "Failed to create bidirectional stream.")); return; } @@ -895,7 +920,17 @@ auto* bidirectional_stream = MakeGarbageCollected<BidirectionalStream>( script_state_, this, stream_id, std::move(outgoing_producer), std::move(incoming_consumer)); - bidirectional_stream->Init(); + + ExceptionState exception_state(isolate, ExceptionState::kConstructionContext, + "BidirectionalStream"); + v8::MicrotasksScope microtasks_scope( + isolate, v8::MicrotasksScope::kDoNotRunMicrotasks); + bidirectional_stream->Init(exception_state); + if (exception_state.HadException()) { + resolver->Reject(exception_state.GetException()); + exception_state.ClearException(); + return; + } // 0xfffffffe and 0xffffffff are reserved values in stream_map_. CHECK_LT(stream_id, 0xfffffffe);
diff --git a/third_party/blink/renderer/modules/webtransport/web_transport_test.cc b/third_party/blink/renderer/modules/webtransport/web_transport_test.cc index 1d51198..67d25b9 100644 --- a/third_party/blink/renderer/modules/webtransport/web_transport_test.cc +++ b/third_party/blink/renderer/modules/webtransport/web_transport_test.cc
@@ -981,8 +981,17 @@ auto* script_state = scope.GetScriptState(); - ScriptPromise close_promise = - send_stream->writable()->close(script_state, ASSERT_NO_EXCEPTION); + ScriptPromise close_promise; + + { + // The close() method also creates v8 handles referencing the + // SendStream via the base class. + v8::HandleScope handle_scope(scope.GetIsolate()); + + close_promise = + send_stream->writable()->close(script_state, ASSERT_NO_EXCEPTION); + } + ScriptPromiseTester tester(script_state, close_promise); tester.WaitUntilSettled(); EXPECT_TRUE(tester.IsFulfilled());
diff --git a/third_party/blink/renderer/platform/fonts/OWNERS b/third_party/blink/renderer/platform/fonts/OWNERS index c0787f4..7a3866f 100644 --- a/third_party/blink/renderer/platform/fonts/OWNERS +++ b/third_party/blink/renderer/platform/fonts/OWNERS
@@ -1,2 +1,2 @@ per-file font_matching_metrics.cc=file://third_party/blink/public/common/privacy_budget/OWNERS -per-file font_matching_metrics.h=file://third_party/blink/public/common/privacy_budget/OWNERS \ No newline at end of file +per-file font_matching_metrics.h=file://third_party/blink/public/common/privacy_budget/OWNERS
diff --git a/third_party/blink/renderer/platform/graphics/image.cc b/third_party/blink/renderer/platform/graphics/image.cc index 7da5b5d7..80f0a2d1 100644 --- a/third_party/blink/renderer/platform/graphics/image.cc +++ b/third_party/blink/renderer/platform/graphics/image.cc
@@ -327,8 +327,8 @@ if (!image) return false; - flags.setShader(PaintShader::MakeImage(image, SkTileMode::kRepeat, - SkTileMode::kRepeat, &local_matrix)); + flags.setShader(PaintShader::MakeImage(image, SkTileMode::kClamp, + SkTileMode::kClamp, &local_matrix)); if (!flags.HasShader()) return false;
diff --git a/third_party/blink/renderer/platform/graphics/image.h b/third_party/blink/renderer/platform/graphics/image.h index 7ce8f41..04116a9 100644 --- a/third_party/blink/renderer/platform/graphics/image.h +++ b/third_party/blink/renderer/platform/graphics/image.h
@@ -239,6 +239,9 @@ ImageClampingMode, ImageDecodingMode) = 0; + // Apply this Image as a shader to the passed PaintFlags. This is currently + // only used by GraphicsContext::DrawImageRRect() and to match the semantics + // of that function the shader should use a clamping tile mode if possible. virtual bool ApplyShader(cc::PaintFlags&, const SkMatrix& local_matrix); // Use ContextProvider() for immediate use only, use
diff --git a/third_party/blink/renderer/platform/instrumentation/resource_coordinator/OWNERS b/third_party/blink/renderer/platform/instrumentation/resource_coordinator/OWNERS index ee9a18a..dcd54320 100644 --- a/third_party/blink/renderer/platform/instrumentation/resource_coordinator/OWNERS +++ b/third_party/blink/renderer/platform/instrumentation/resource_coordinator/OWNERS
@@ -1 +1 @@ -file://services/resource_coordinator/OWNERS \ No newline at end of file +file://services/resource_coordinator/OWNERS
diff --git a/third_party/blink/renderer/platform/peerconnection/rtc_video_encoder.cc b/third_party/blink/renderer/platform/peerconnection/rtc_video_encoder.cc index c3a4895..5b81f01 100644 --- a/third_party/blink/renderer/platform/peerconnection/rtc_video_encoder.cc +++ b/third_party/blink/renderer/platform/peerconnection/rtc_video_encoder.cc
@@ -1133,7 +1133,7 @@ // Do a strided copy and scale (if necessary) the input frame to match // the input requirements for the encoder. // TODO(sheu): Support zero-copy from WebRTC. http://crbug.com/269312 - // TODO(magjed): Downscale with kFilterBox in an image pyramid instead. + // TODO(magjed): Downscale with an image pyramid instead. rtc::scoped_refptr<webrtc::I420BufferInterface> i420_buffer = next_frame->video_frame_buffer()->ToI420(); if (libyuv::I420Scale(i420_buffer->DataY(), i420_buffer->StrideY(), @@ -1148,7 +1148,7 @@ frame->stride(media::VideoFrame::kVPlane), frame->visible_rect().width(), frame->visible_rect().height(), - libyuv::kFilterBox)) { + libyuv::kFilterBilinear)) { LogAndNotifyError(FROM_HERE, "Failed to copy buffer", media::VideoEncodeAccelerator::kPlatformFailureError); async_encode_event_.SetAndReset(WEBRTC_VIDEO_CODEC_ERROR);
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5 index 2951941..0b0aa04 100644 --- a/third_party/blink/renderer/platform/runtime_enabled_features.json5 +++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -1199,6 +1199,10 @@ status: "stable" }, { + name: "LayoutNGTextCombine", + depends_on: ["LayoutNG"], + }, + { name: "LayoutNGTextControl", depends_on: ["EditingNG"], status: "stable",
diff --git a/third_party/blink/renderer/platform/webrtc/convert_to_webrtc_video_frame_buffer.cc b/third_party/blink/renderer/platform/webrtc/convert_to_webrtc_video_frame_buffer.cc index 2117ca38..6873b13 100644 --- a/third_party/blink/renderer/platform/webrtc/convert_to_webrtc_video_frame_buffer.cc +++ b/third_party/blink/renderer/platform/webrtc/convert_to_webrtc_video_frame_buffer.cc
@@ -334,7 +334,7 @@ dst_frame->data(media::VideoFrame::kUVPlane), nv12_planes[media::VideoFrame::kUVPlane].stride, dst_frame->coded_size().width(), - dst_frame->coded_size().height(), libyuv::kFilterBox); + dst_frame->coded_size().height(), libyuv::kFilterBilinear); return dst_frame; }
diff --git a/third_party/blink/renderer/platform/webrtc/legacy_webrtc_video_frame_adapter.cc b/third_party/blink/renderer/platform/webrtc/legacy_webrtc_video_frame_adapter.cc index 459ff84..97621b7 100644 --- a/third_party/blink/renderer/platform/webrtc/legacy_webrtc_video_frame_adapter.cc +++ b/third_party/blink/renderer/platform/webrtc/legacy_webrtc_video_frame_adapter.cc
@@ -321,7 +321,7 @@ dst_frame->data(media::VideoFrame::kUVPlane), nv12_planes[media::VideoFrame::kUVPlane].stride, dst_frame->coded_size().width(), - dst_frame->coded_size().height(), libyuv::kFilterBox); + dst_frame->coded_size().height(), libyuv::kFilterBilinear); return dst_frame; }
diff --git a/third_party/blink/web_tests/NeverFixTests b/third_party/blink/web_tests/NeverFixTests index fc052a4d..04367f2 100644 --- a/third_party/blink/web_tests/NeverFixTests +++ b/third_party/blink/web_tests/NeverFixTests
@@ -1720,6 +1720,8 @@ crbug.com/1150938 virtual/force-eager/external/wpt/measure-memory/window-open.mix.https.window.html [ Skip ] crbug.com/1085129 virtual/force-eager/external/wpt/measure-memory/main-frame-and-worker.https.window.html [ Skip ] crbug.com/1085129 virtual/force-eager/external/wpt/measure-memory/idlharness.window.html [ Skip ] +crbug.com/1207146 virtual/force-eager/external/wpt/measure-memory/service-worker.https.any.serviceworker.html [ Skip ] +crbug.com/1207146 virtual/force-eager/external/wpt/measure-memory/shared-worker.https.any.sharedworker.html [ Skip ] # Legacy SameSite cookie tests do not apply when non-legacy behavior is in effect. crbug.com/961439 external/wpt/cookies/samesite/fetch.https.html?legacy-samesite [ Skip ]
diff --git a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/background-image-with-border-radius-fidelity.html b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/background-image-with-border-radius-fidelity.html new file mode 100644 index 0000000..b0b494f5 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/background-image-with-border-radius-fidelity.html
@@ -0,0 +1,14 @@ +<!DOCTYPE html> +<title>Consistent image fidelity of background-image with border-radius</title> +<link rel="help" href="https://crbug.com/1069434"> +<link rel="match" href="reference/background-image-with-border-radius-fidelity-ref.html"> +<style> + #target { + background-image: url("support/aqua-yellow-32x32.png"); + background-size: 100% 100%; + border-radius: 8px; + width: 256px; + height: 256px; + } +</style> +<div id="target"></div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/reference/background-image-with-border-radius-fidelity-ref.html b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/reference/background-image-with-border-radius-fidelity-ref.html new file mode 100644 index 0000000..0d8f30d --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/reference/background-image-with-border-radius-fidelity-ref.html
@@ -0,0 +1,12 @@ +<!DOCTYPE html> +<title>Consistent image fidelity of background-image with border-radius (reference)</title> +<style> + #target { + background-image: url("../support/aqua-yellow-32x32.png"); + background-size: 100% 100%; + border-radius: 8px; + width: 256px; + height: 256px; + } +</style> +<div id="target" style="background-clip: padding-box"></div>
diff --git a/third_party/blink/web_tests/external/wpt/measure-memory/detached.https.window.js b/third_party/blink/web_tests/external/wpt/measure-memory/detached.https.window.js index 430cb2d..1fcedef 100644 --- a/third_party/blink/web_tests/external/wpt/measure-memory/detached.https.window.js +++ b/third_party/blink/web_tests/external/wpt/measure-memory/detached.https.window.js
@@ -1,11 +1,13 @@ // META: script=/common/get-host-info.sub.js +// META: script=./resources/checker.js // META: script=./resources/common.js // META: timeout=long 'use strict'; -assert_true(self.crossOriginIsolated); promise_test(async testCase => { + assert_true(self.crossOriginIsolated); + const {iframes, windows} = await build([ { id: 'cross-site-1',
diff --git a/third_party/blink/web_tests/external/wpt/measure-memory/iframe.cross-origin.https.window.js b/third_party/blink/web_tests/external/wpt/measure-memory/iframe.cross-origin.https.window.js index d977c3a8..de256ad 100644 --- a/third_party/blink/web_tests/external/wpt/measure-memory/iframe.cross-origin.https.window.js +++ b/third_party/blink/web_tests/external/wpt/measure-memory/iframe.cross-origin.https.window.js
@@ -1,11 +1,12 @@ // META: script=/common/get-host-info.sub.js +// META: script=./resources/checker.js // META: script=./resources/common.js // META: timeout=long 'use strict'; -assert_true(self.crossOriginIsolated); - promise_test(async testCase => { + assert_true(self.crossOriginIsolated); + const {iframes, windows} = await build([ { id: 'cross-origin-1',
diff --git a/third_party/blink/web_tests/external/wpt/measure-memory/iframe.cross-site.https.window.js b/third_party/blink/web_tests/external/wpt/measure-memory/iframe.cross-site.https.window.js index 919bc3e2..a4c50a5687 100644 --- a/third_party/blink/web_tests/external/wpt/measure-memory/iframe.cross-site.https.window.js +++ b/third_party/blink/web_tests/external/wpt/measure-memory/iframe.cross-site.https.window.js
@@ -1,11 +1,12 @@ // META: script=/common/get-host-info.sub.js +// META: script=./resources/checker.js // META: script=./resources/common.js // META: timeout=long 'use strict'; -assert_true(self.crossOriginIsolated); - promise_test(async testCase => { + assert_true(self.crossOriginIsolated); + const {iframes, windows} = await build([ { id: 'cross-site-1',
diff --git a/third_party/blink/web_tests/external/wpt/measure-memory/iframe.same-origin.https.window.js b/third_party/blink/web_tests/external/wpt/measure-memory/iframe.same-origin.https.window.js index 10fad71a7..5d710bd1 100644 --- a/third_party/blink/web_tests/external/wpt/measure-memory/iframe.same-origin.https.window.js +++ b/third_party/blink/web_tests/external/wpt/measure-memory/iframe.same-origin.https.window.js
@@ -1,11 +1,12 @@ // META: script=/common/get-host-info.sub.js +// META: script=./resources/checker.js // META: script=./resources/common.js // META: timeout=long 'use strict'; -assert_true(self.crossOriginIsolated); - promise_test(async testCase => { + assert_true(self.crossOriginIsolated); + const {iframes, windows} = await build([ { id: 'same-origin-1',
diff --git a/third_party/blink/web_tests/external/wpt/measure-memory/main-frame-and-worker.https.window.js b/third_party/blink/web_tests/external/wpt/measure-memory/main-frame-and-worker.https.window.js index 43c27904..a9f1ad0 100644 --- a/third_party/blink/web_tests/external/wpt/measure-memory/main-frame-and-worker.https.window.js +++ b/third_party/blink/web_tests/external/wpt/measure-memory/main-frame-and-worker.https.window.js
@@ -1,11 +1,12 @@ // META: script=/common/get-host-info.sub.js +// META: script=./resources/checker.js // META: script=./resources/common.js // META: timeout=long 'use strict'; -assert_true(self.crossOriginIsolated); - promise_test(async testCase => { + assert_true(self.crossOriginIsolated); + const BYTES_PER_WORKER = 10 * 1024 * 1024; const worker_url = await createWorker(BYTES_PER_WORKER); const result = await performance.measureUserAgentSpecificMemory();
diff --git a/third_party/blink/web_tests/external/wpt/measure-memory/main-frame.https.window.js b/third_party/blink/web_tests/external/wpt/measure-memory/main-frame.https.window.js index 7500170..1119ca4 100644 --- a/third_party/blink/web_tests/external/wpt/measure-memory/main-frame.https.window.js +++ b/third_party/blink/web_tests/external/wpt/measure-memory/main-frame.https.window.js
@@ -1,10 +1,12 @@ // META: script=/common/get-host-info.sub.js +// META: script=./resources/checker.js // META: script=./resources/common.js // META: timeout=long 'use strict'; -assert_true(self.crossOriginIsolated); promise_test(async testCase => { + assert_true(self.crossOriginIsolated); + const result = await performance.measureUserAgentSpecificMemory(); checkMeasureMemory(result, [ {
diff --git a/third_party/blink/web_tests/external/wpt/measure-memory/randomized-breakdown.https.window.js b/third_party/blink/web_tests/external/wpt/measure-memory/randomized-breakdown.https.window.js index 2ad8535..09937d5 100644 --- a/third_party/blink/web_tests/external/wpt/measure-memory/randomized-breakdown.https.window.js +++ b/third_party/blink/web_tests/external/wpt/measure-memory/randomized-breakdown.https.window.js
@@ -1,4 +1,5 @@ // META: script=/common/get-host-info.sub.js +// META: script=./resources/checker.js // META: script=./resources/common.js // META: timeout=long 'use strict'; @@ -7,8 +8,9 @@ return result.breakdown.findIndex(isEmptyBreakdownEntry); } -assert_true(self.crossOriginIsolated); promise_test(async testCase => { + assert_true(self.crossOriginIsolated); + const initial = await performance.measureUserAgentSpecificMemory(); let observed_different_order = false; for (let i = 0; i < 100; ++i) {
diff --git a/third_party/blink/web_tests/external/wpt/measure-memory/redirect.client.https.window.js b/third_party/blink/web_tests/external/wpt/measure-memory/redirect.client.https.window.js index 9cad328..a78a7ddf 100644 --- a/third_party/blink/web_tests/external/wpt/measure-memory/redirect.client.https.window.js +++ b/third_party/blink/web_tests/external/wpt/measure-memory/redirect.client.https.window.js
@@ -1,11 +1,12 @@ // META: script=/common/get-host-info.sub.js +// META: script=./resources/checker.js // META: script=./resources/common.js // META: timeout=long 'use strict'; -assert_true(self.crossOriginIsolated); - promise_test(async testCase => { + assert_true(self.crossOriginIsolated); + const {iframes, windows} = await build([ { id: 'cross-origin-1',
diff --git a/third_party/blink/web_tests/external/wpt/measure-memory/redirect.server.https.window.js b/third_party/blink/web_tests/external/wpt/measure-memory/redirect.server.https.window.js index 2c32de2d..98273ed 100644 --- a/third_party/blink/web_tests/external/wpt/measure-memory/redirect.server.https.window.js +++ b/third_party/blink/web_tests/external/wpt/measure-memory/redirect.server.https.window.js
@@ -1,11 +1,12 @@ // META: script=/common/get-host-info.sub.js +// META: script=./resources/checker.js // META: script=./resources/common.js // META: timeout=long 'use strict'; -assert_true(self.crossOriginIsolated); - promise_test(async testCase => { + assert_true(self.crossOriginIsolated); + const {iframes, windows} = await build([ { id: 'cross-origin-1',
diff --git a/third_party/blink/web_tests/external/wpt/measure-memory/resources/checker.js b/third_party/blink/web_tests/external/wpt/measure-memory/resources/checker.js new file mode 100644 index 0000000..25487b7b --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/measure-memory/resources/checker.js
@@ -0,0 +1,58 @@ +function checkContainer(actual, expected) { + if (!actual) return true; + if (!expected) return false; + return actual.id == expected.id && actual.src == expected.src; +} + +function checkAttribution(attribution, expected) { + assert_own_property(attribution, 'url'); + assert_own_property(attribution, 'scope'); + let found = false; + for (const e of expected) { + if (attribution.url === e.url && + attribution.scope === e.scope && + checkContainer(attribution.container, e.container)) { + found = true; + e.found = true; + } + } + assert_true(found, JSON.stringify(attribution) + + ' is not found in ' + JSON.stringify(expected) + '.'); +} + +function checkBreakdown(breakdown, expected) { + assert_own_property(breakdown, 'bytes'); + assert_greater_than_equal(breakdown.bytes, 0); + assert_own_property(breakdown, 'types'); + for (const memoryType of breakdown.types) { + assert_equals(typeof memoryType, 'string'); + } + assert_own_property(breakdown, 'attribution'); + for (const attribution of breakdown.attribution) { + checkAttribution(attribution, expected); + } +} + +function isEmptyBreakdownEntry(entry) { + return entry.bytes === 0 && entry.attribution.length === 0 && + entry.types.length === 0; +} + +function checkMeasureMemory(result, expected) { + assert_own_property(result, 'bytes'); + assert_own_property(result, 'breakdown'); + let bytes = 0; + for (let breakdown of result.breakdown) { + checkBreakdown(breakdown, expected); + bytes += breakdown.bytes; + } + assert_equals(bytes, result.bytes); + for (const e of expected) { + if (e.required) { + assert_true(e.found, + JSON.stringify(e) + ' did not appear in the result.'); + } + } + assert_true(result.breakdown.some(isEmptyBreakdownEntry), + 'The result must include an empty breakdown entry.'); +} \ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/measure-memory/resources/common.js b/third_party/blink/web_tests/external/wpt/measure-memory/resources/common.js index 41f7c94..4332c6e 100644 --- a/third_party/blink/web_tests/external/wpt/measure-memory/resources/common.js +++ b/third_party/blink/web_tests/external/wpt/measure-memory/resources/common.js
@@ -4,65 +4,6 @@ 'cross-site': get_host_info().HTTPS_NOTSAMESITE_ORIGIN, } -function checkContainer(actual, expected) { - if (!actual) return true; - if (!expected) return false; - return actual.id == expected.id && actual.src == expected.src; -} - -function checkAttribuiton(attribution, expected) { - assert_own_property(attribution, 'url'); - assert_own_property(attribution, 'scope'); - let found = false; - for (const e of expected) { - if (attribution.url === e.url && - attribution.scope === e.scope && - checkContainer(attribution.container, e.container)) { - found = true; - e.found = true; - } - } - assert_true(found, JSON.stringify(attribution) + - ' is not found in ' + JSON.stringify(expected) + '.'); -} - -function checkBreakdown(breakdown, expected) { - assert_own_property(breakdown, 'bytes'); - assert_greater_than_equal(breakdown.bytes, 0); - assert_own_property(breakdown, 'types'); - for (const memoryType of breakdown.types) { - assert_equals(typeof memoryType, 'string'); - } - assert_own_property(breakdown, 'attribution'); - for (const attribution of breakdown.attribution) { - checkAttribuiton(attribution, expected); - } -} - -function isEmptyBreakdownEntry(entry) { - return entry.bytes === 0 && entry.attribution.length === 0 && - entry.types.length === 0; -} - -function checkMeasureMemory(result, expected) { - assert_own_property(result, 'bytes'); - assert_own_property(result, 'breakdown'); - let bytes = 0; - for (let breakdown of result.breakdown) { - checkBreakdown(breakdown, expected); - bytes += breakdown.bytes; - } - assert_equals(bytes, result.bytes); - for (const e of expected) { - if (e.required) { - assert_true(e.found, - JSON.stringify(e) + ' did not appear in the result.'); - } - } - assert_true(result.breakdown.some(isEmptyBreakdownEntry), - 'The result must include an empty breakdown entry.'); -} - function url(params) { let origin = null; for (const key of Object.keys(ORIGINS)) {
diff --git a/third_party/blink/web_tests/external/wpt/measure-memory/service-worker.https.any.js b/third_party/blink/web_tests/external/wpt/measure-memory/service-worker.https.any.js new file mode 100644 index 0000000..c025111 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/measure-memory/service-worker.https.any.js
@@ -0,0 +1,18 @@ +// META: script=./resources/checker.js +// META: timeout=long +// META: global=serviceworker +'use strict'; + +promise_test(async testCase => { + assert_true(self.crossOriginIsolated); + + const result = await performance.measureUserAgentSpecificMemory(); + + checkMeasureMemory(result, [ + { + url: self.location.href, + scope: 'ServiceWorkerGlobalScope', + container: null, + }, + ]); +}, 'Well-formed result of performance.measureUserAgentSpecificMemory.');
diff --git a/third_party/blink/web_tests/external/wpt/measure-memory/service-worker.https.any.js.headers b/third_party/blink/web_tests/external/wpt/measure-memory/service-worker.https.any.js.headers new file mode 100644 index 0000000..4fff9d9 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/measure-memory/service-worker.https.any.js.headers
@@ -0,0 +1,2 @@ +Cross-Origin-Opener-Policy: same-origin +Cross-Origin-Embedder-Policy: require-corp \ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/measure-memory/shared-worker.https.any.js b/third_party/blink/web_tests/external/wpt/measure-memory/shared-worker.https.any.js new file mode 100644 index 0000000..4e359ad --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/measure-memory/shared-worker.https.any.js
@@ -0,0 +1,18 @@ +// META: script=./resources/checker.js +// META: global=sharedworker +'use strict'; + +promise_test(async testCase => { + assert_true(self.crossOriginIsolated); + + const result = await performance.measureUserAgentSpecificMemory(); + + checkMeasureMemory(result, [ + { + url: self.location.href, + scope: 'SharedWorkerGlobalScope', + container: null, + }, + ]); +}, 'Well-formed result of performance.measureUserAgentSpecificMemory.'); +
diff --git a/third_party/blink/web_tests/external/wpt/measure-memory/shared-worker.https.any.js.headers b/third_party/blink/web_tests/external/wpt/measure-memory/shared-worker.https.any.js.headers new file mode 100644 index 0000000..4fff9d9 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/measure-memory/shared-worker.https.any.js.headers
@@ -0,0 +1,2 @@ +Cross-Origin-Opener-Policy: same-origin +Cross-Origin-Embedder-Policy: require-corp \ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/measure-memory/window-open.cross-origin.https.window.js b/third_party/blink/web_tests/external/wpt/measure-memory/window-open.cross-origin.https.window.js index 9a05430..5305b1c 100644 --- a/third_party/blink/web_tests/external/wpt/measure-memory/window-open.cross-origin.https.window.js +++ b/third_party/blink/web_tests/external/wpt/measure-memory/window-open.cross-origin.https.window.js
@@ -1,11 +1,12 @@ // META: script=/common/get-host-info.sub.js +// META: script=./resources/checker.js // META: script=./resources/common.js // META: timeout=long 'use strict'; -assert_true(self.crossOriginIsolated); - promise_test(async testCase => { + assert_true(self.crossOriginIsolated); + const {iframes, windows} = await build([ { id: 'cross-origin-1',
diff --git a/third_party/blink/web_tests/external/wpt/measure-memory/window-open.cross-site.https.window.js b/third_party/blink/web_tests/external/wpt/measure-memory/window-open.cross-site.https.window.js index a5fc1d31..3a9481f 100644 --- a/third_party/blink/web_tests/external/wpt/measure-memory/window-open.cross-site.https.window.js +++ b/third_party/blink/web_tests/external/wpt/measure-memory/window-open.cross-site.https.window.js
@@ -1,11 +1,12 @@ // META: script=/common/get-host-info.sub.js +// META: script=./resources/checker.js // META: script=./resources/common.js // META: timeout=long 'use strict'; -assert_true(self.crossOriginIsolated); - promise_test(async testCase => { + assert_true(self.crossOriginIsolated); + const {iframes, windows} = await build([ { id: 'cross-site-1',
diff --git a/third_party/blink/web_tests/external/wpt/measure-memory/window-open.mix.https.window.js b/third_party/blink/web_tests/external/wpt/measure-memory/window-open.mix.https.window.js index 91d13a500..2b4c9e5 100644 --- a/third_party/blink/web_tests/external/wpt/measure-memory/window-open.mix.https.window.js +++ b/third_party/blink/web_tests/external/wpt/measure-memory/window-open.mix.https.window.js
@@ -1,11 +1,12 @@ // META: script=/common/get-host-info.sub.js +// META: script=./resources/checker.js // META: script=./resources/common.js // META: timeout=long 'use strict'; -assert_true(self.crossOriginIsolated); - promise_test(async testCase => { + assert_true(self.crossOriginIsolated); + const {iframes, windows} = await build([ { id: 'same-origin-1',
diff --git a/third_party/blink/web_tests/external/wpt/measure-memory/window-open.same-origin.https.window.js b/third_party/blink/web_tests/external/wpt/measure-memory/window-open.same-origin.https.window.js index ee4a59e..f0ff6f2 100644 --- a/third_party/blink/web_tests/external/wpt/measure-memory/window-open.same-origin.https.window.js +++ b/third_party/blink/web_tests/external/wpt/measure-memory/window-open.same-origin.https.window.js
@@ -1,11 +1,12 @@ // META: script=/common/get-host-info.sub.js +// META: script=./resources/checker.js // META: script=./resources/common.js // META: timeout=long 'use strict'; -assert_true(self.crossOriginIsolated); - promise_test(async testCase => { + assert_true(self.crossOriginIsolated); + const {iframes, windows} = await build([ { id: 'same-origin-1',
diff --git a/third_party/blink/web_tests/fast/xpath/OWNERS b/third_party/blink/web_tests/fast/xpath/OWNERS index 55fa2fc1..300e435 100644 --- a/third_party/blink/web_tests/fast/xpath/OWNERS +++ b/third_party/blink/web_tests/fast/xpath/OWNERS
@@ -1,4 +1,4 @@ # There's no real owners here. If you're familiar with the code please send # a CL to add yourself here. dcheng@chromium.org -palmer@chromium.org \ No newline at end of file +palmer@chromium.org
diff --git a/third_party/blink/web_tests/fast/xsl/OWNERS b/third_party/blink/web_tests/fast/xsl/OWNERS index 55fa2fc1..300e435 100644 --- a/third_party/blink/web_tests/fast/xsl/OWNERS +++ b/third_party/blink/web_tests/fast/xsl/OWNERS
@@ -1,4 +1,4 @@ # There's no real owners here. If you're familiar with the code please send # a CL to add yourself here. dcheng@chromium.org -palmer@chromium.org \ No newline at end of file +palmer@chromium.org
diff --git a/third_party/blink/web_tests/http/tests/devtools/OWNERS b/third_party/blink/web_tests/http/tests/devtools/OWNERS index 827ae416..00bcf63 100644 --- a/third_party/blink/web_tests/http/tests/devtools/OWNERS +++ b/third_party/blink/web_tests/http/tests/devtools/OWNERS
@@ -1,4 +1,4 @@ # Audits owners. per-file audits*=cjamcl@google.com -per-file audits*=paulirish@chromium.org \ No newline at end of file +per-file audits*=paulirish@chromium.org
diff --git a/third_party/blink/web_tests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt b/third_party/blink/web_tests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt index 534f606..6690f88 100644 --- a/third_party/blink/web_tests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt +++ b/third_party/blink/web_tests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
@@ -1377,7 +1377,7 @@ getter statusCode getter violatedDirective method constructor -interface SendStream +interface SendStream : WritableStream attribute @@toStringTag getter writable getter writingAborted
diff --git a/third_party/blink/web_tests/http/tests/xsl/OWNERS b/third_party/blink/web_tests/http/tests/xsl/OWNERS index 55fa2fc1..300e435 100644 --- a/third_party/blink/web_tests/http/tests/xsl/OWNERS +++ b/third_party/blink/web_tests/http/tests/xsl/OWNERS
@@ -1,4 +1,4 @@ # There's no real owners here. If you're familiar with the code please send # a CL to add yourself here. dcheng@chromium.org -palmer@chromium.org \ No newline at end of file +palmer@chromium.org
diff --git a/third_party/blink/web_tests/third_party/Amstelvar/OWNERS b/third_party/blink/web_tests/third_party/Amstelvar/OWNERS index 52de412..8e337df 100644 --- a/third_party/blink/web_tests/third_party/Amstelvar/OWNERS +++ b/third_party/blink/web_tests/third_party/Amstelvar/OWNERS
@@ -1,2 +1,2 @@ alexrudenko@chromium.org -mathias@chromium.org \ No newline at end of file +mathias@chromium.org
diff --git a/third_party/blink/web_tests/webaudio/OWNERS b/third_party/blink/web_tests/webaudio/OWNERS index 5eae04b..a837fc9b 100644 --- a/third_party/blink/web_tests/webaudio/OWNERS +++ b/third_party/blink/web_tests/webaudio/OWNERS
@@ -1,2 +1,2 @@ hongchan@chromium.org -rtoy@chromium.org \ No newline at end of file +rtoy@chromium.org
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt index 75a99b0..573ca1a 100644 --- a/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt +++ b/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt
@@ -1392,7 +1392,7 @@ [Worker] getter statusCode [Worker] getter violatedDirective [Worker] method constructor -[Worker] interface SendStream +[Worker] interface SendStream : WritableStream [Worker] attribute @@toStringTag [Worker] getter writable [Worker] getter writingAborted
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt index 594479dc..7ce87d15 100644 --- a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt +++ b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
@@ -8221,7 +8221,7 @@ method setBaseAndExtent method setPosition method toString -interface SendStream +interface SendStream : WritableStream attribute @@toStringTag getter writable getter writingAborted
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-shared-worker-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-shared-worker-expected.txt index dd179638..eafa2f51 100644 --- a/third_party/blink/web_tests/webexposed/global-interface-listing-shared-worker-expected.txt +++ b/third_party/blink/web_tests/webexposed/global-interface-listing-shared-worker-expected.txt
@@ -1266,7 +1266,7 @@ [Worker] getter statusCode [Worker] getter violatedDirective [Worker] method constructor -[Worker] interface SendStream +[Worker] interface SendStream : WritableStream [Worker] attribute @@toStringTag [Worker] getter writable [Worker] getter writingAborted
diff --git a/third_party/blink/web_tests/wpt_internal/prerender/clients-matchall.https.html b/third_party/blink/web_tests/wpt_internal/prerender/clients-matchall.https.html index c045884..695b621 100644 --- a/third_party/blink/web_tests/wpt_internal/prerender/clients-matchall.https.html +++ b/third_party/blink/web_tests/wpt_internal/prerender/clients-matchall.https.html
@@ -3,32 +3,17 @@ <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> <script src="resources/utils.js"></script> +<script src="/service-workers/service-worker/resources/test-helpers.sub.js"></script> <body> <script> -async function unregisterServiceWorker(scope) { - const registration = await navigator.serviceWorker.getRegistration(scope); - if (!registration) - return; - return registration.unregister(); -} - -function getNewestWorker(registration) { - if (registration.installing) - return registration.installing; - if (registration.waiting) - return registration.waiting; - if (registration.active) - return registration.active; -} - promise_test(async t => { const workerUrl = 'resources/clients-matchall-service-worker.js'; const pageUrl = 'resources/prerendered-page.html'; // Start a service worker. - await unregisterServiceWorker(workerUrl); - const registration = await navigator.serviceWorker.register(workerUrl); + const registration = + await service_worker_unregister_and_register(t, workerUrl, workerUrl); t.add_cleanup(_ => registration.unregister()); // Observe the message from a prerendered page. @@ -49,7 +34,7 @@ // Clients#matchAll(). const message = await new Promise(resolve => { navigator.serviceWorker.onmessage = resolve; - getNewestWorker(registration).postMessage('invoke clients.matchAll()'); + get_newest_worker(registration).postMessage('invoke clients.matchAll()'); }); assert_array_equals(
diff --git a/third_party/blink/web_tests/wpt_internal/presentation/OWNERS b/third_party/blink/web_tests/wpt_internal/presentation/OWNERS index 1cbae82..00b27fe 100644 --- a/third_party/blink/web_tests/wpt_internal/presentation/OWNERS +++ b/third_party/blink/web_tests/wpt_internal/presentation/OWNERS
@@ -1 +1 @@ -file://third_party/blink/renderer/modules/presentation/OWNERS \ No newline at end of file +file://third_party/blink/renderer/modules/presentation/OWNERS
diff --git a/third_party/blink/web_tests/wpt_internal/sanitizer-api/OWNERS b/third_party/blink/web_tests/wpt_internal/sanitizer-api/OWNERS index 9f2ef48..fc6bc863 100644 --- a/third_party/blink/web_tests/wpt_internal/sanitizer-api/OWNERS +++ b/third_party/blink/web_tests/wpt_internal/sanitizer-api/OWNERS
@@ -1 +1 @@ -file://third_party/blink/renderer/modules/sanitizer_api/OWNERS \ No newline at end of file +file://third_party/blink/renderer/modules/sanitizer_api/OWNERS
diff --git a/third_party/freetype/README.chromium b/third_party/freetype/README.chromium index d3aa929..be0dfa0 100644 --- a/third_party/freetype/README.chromium +++ b/third_party/freetype/README.chromium
@@ -1,7 +1,7 @@ Name: FreeType URL: http://www.freetype.org/ -Version: VER-2-10-4-251 -Revision: 06e21ffedfac81edfa79137959141a9d78b6f858 +Version: VER-2-10-4-252-gebf9e5ac7 +Revision: ebf9e5ac719a5a1a374dbf2dd6b12e84de9466ed CPEPrefix: cpe:/a:freetype:freetype:2.10.4 License: Custom license "inspired by the BSD, Artistic, and IJG (Independent JPEG Group) licenses"
diff --git a/third_party/webgpu-cts/ts_sources.txt b/third_party/webgpu-cts/ts_sources.txt index 68f3baa..0be1475 100644 --- a/third_party/webgpu-cts/ts_sources.txt +++ b/third_party/webgpu-cts/ts_sources.txt
@@ -54,9 +54,9 @@ src/unittests/params_builder_toplevel.spec.ts src/unittests/preprocessor.spec.ts src/unittests/query_compare.spec.ts +src/unittests/query_string.spec.ts src/unittests/test_group.spec.ts src/unittests/test_query.spec.ts -src/unittests/url_query.spec.ts src/webgpu/constants.ts src/webgpu/capability_info.ts src/webgpu/util/buffer.ts
diff --git a/tools/media_engagement_preload/PRESUBMIT.py b/tools/media_engagement_preload/PRESUBMIT.py index 97e25f9..df19c77f 100644 --- a/tools/media_engagement_preload/PRESUBMIT.py +++ b/tools/media_engagement_preload/PRESUBMIT.py
@@ -5,10 +5,6 @@ """Chromium presubmit script for src/tools/media_engagement_preload.""" -# This line is 'magic' in that git-cl looks for it to decide whether to -# use Python3 instead of Python2 when running the code in this file. -USE_PYTHON3 = True - def _RunMakeDafsaTests(input_api, output_api): """Runs unittest for make_dafsa if any related file has been modified.""" @@ -16,14 +12,16 @@ 'tools/media_engagement_preload/make_dafsa_unittest.py') if not any(f in input_api.LocalPaths() for f in files): return [] - - return input_api.RunTests( - input_api.canned_checks.RunUnitTestsInDirectory( - input_api, - output_api, - input_api.PresubmitLocalPath(), - files_to_check=['.*test\.py$'], - run_on_python2=False)) + test_path = input_api.os_path.join(input_api.PresubmitLocalPath(), + 'make_dafsa_unittest.py') + cmd_name = 'make_dafsa_unittest' + cmd = [input_api.python_executable, test_path] + test_cmd = input_api.Command( + name=cmd_name, + cmd=cmd, + kwargs={}, + message=output_api.PresubmitPromptWarning) + return input_api.RunTests([test_cmd]) def CheckChangeOnUpload(input_api, output_api):
diff --git a/tools/media_engagement_preload/make_dafsa.py b/tools/media_engagement_preload/make_dafsa.py index db78c67..72cbf7d 100755 --- a/tools/media_engagement_preload/make_dafsa.py +++ b/tools/media_engagement_preload/make_dafsa.py
@@ -1,4 +1,4 @@ -#!/usr/bin/env python3 +#!/usr/bin/env python # Copyright 2017 The Chromium Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. @@ -9,7 +9,7 @@ import json import sys import os -import urllib.parse +import urlparse SOURCE_ROOT = os.path.join(os.path.dirname( os.path.abspath(__file__)), os.pardir, os.pardir) @@ -440,7 +440,7 @@ def to_proto(data): """Generates protobuf from a list of encoded bytes.""" message = media_engagement_preload_pb2.PreloadedData() - message.dafsa = array.array('B', data).tobytes() + message.dafsa = array.array('B', data).tostring() return message.SerializeToString() @@ -458,7 +458,7 @@ netlocs = {} for entry in json.loads(infile): # Parse the origin and reject any with an invalid protocol. - parsed = urllib.parse.urlparse(entry) + parsed = urlparse.urlparse(entry) if parsed.scheme != 'http' and parsed.scheme != 'https': raise InputError('Invalid protocol: %s' % entry) @@ -471,7 +471,7 @@ # Join the numerical values to the netlocs. output = [] - for location, value in netlocs.items(): + for location, value in netlocs.iteritems(): output.append(location + str(value)) return output except ValueError:
diff --git a/tools/media_engagement_preload/make_dafsa_unittest.py b/tools/media_engagement_preload/make_dafsa_unittest.py index 3575af58..cdf7965 100755 --- a/tools/media_engagement_preload/make_dafsa_unittest.py +++ b/tools/media_engagement_preload/make_dafsa_unittest.py
@@ -1,4 +1,4 @@ -#!/usr/bin/env python3 +#!/usr/bin/env python # Copyright 2017 The Chromium Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. @@ -6,7 +6,6 @@ import sys import unittest - import make_dafsa @@ -679,14 +678,14 @@ def testExample1(self): """Tests Example 1 from make_dafsa.py.""" infile = '["https://www.example.com:8081", "http://www.example.org"]' - outfile = b'\n\x1c\x81www.example\xae\x02\x84org\x81com:8081\x80' + outfile = "\n\x1c\x81www.example\xae\x02\x89com:8081\x80org\x81" self.assertEqual(make_dafsa.words_to_proto(make_dafsa.parse_json(infile)), outfile) def testExample2(self): """Tests Example 2 from make_dafsa.py.""" infile = '["https://www.example.org", "http://www.google.com"]' - outfile = b'\n\x1e\x81www\xae\x02\x8bgoogle.com\x81example.org\x80' + outfile = "\n\x1e\x81www\xae\x02\x8bgoogle.com\x81example.org\x80" self.assertEqual(make_dafsa.words_to_proto(make_dafsa.parse_json(infile)), outfile)
diff --git a/tools/media_engagement_preload/media_engagement_preload_pb2.py b/tools/media_engagement_preload/media_engagement_preload_pb2.py index bdb9bdc..0cde5091 100644 --- a/tools/media_engagement_preload/media_engagement_preload_pb2.py +++ b/tools/media_engagement_preload/media_engagement_preload_pb2.py
@@ -1,26 +1,23 @@ -# -*- coding: utf-8 -*- +# Copyright 2017 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + # Generated by the protocol buffer compiler. DO NOT EDIT! # source: media_engagement_preload.proto from google.protobuf import descriptor as _descriptor from google.protobuf import message as _message from google.protobuf import reflection as _reflection -from google.protobuf import symbol_database as _symbol_database +from google.protobuf import descriptor_pb2 # @@protoc_insertion_point(imports) -_sym_db = _symbol_database.Default() - DESCRIPTOR = _descriptor.FileDescriptor( name='media_engagement_preload.proto', package='chrome_browser_media', - syntax='proto2', - serialized_options=b'H\003', - create_key=_descriptor._internal_create_key, - serialized_pb=b'\n\x1emedia_engagement_preload.proto\x12\x14\x63hrome_browser_media\"\x1e\n\rPreloadedData\x12\r\n\x05\x64\x61\x66sa\x18\x01 \x01(\x0c\x42\x02H\x03' -) + serialized_pb='\n\x1emedia_engagement_preload.proto\x12\x14\x63hrome_browser_media\"\x1e\n\rPreloadedData\x12\r\n\x05\x64\x61\x66sa\x18\x01 \x01(\x0c\x42\x02H\x03') @@ -31,41 +28,36 @@ filename=None, file=DESCRIPTOR, containing_type=None, - create_key=_descriptor._internal_create_key, fields=[ _descriptor.FieldDescriptor( name='dafsa', full_name='chrome_browser_media.PreloadedData.dafsa', index=0, number=1, type=12, cpp_type=9, label=1, - has_default_value=False, default_value=b"", + has_default_value=False, default_value="", message_type=None, enum_type=None, containing_type=None, is_extension=False, extension_scope=None, - serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key), + options=None), ], extensions=[ ], nested_types=[], enum_types=[ ], - serialized_options=None, + options=None, is_extendable=False, - syntax='proto2', extension_ranges=[], - oneofs=[ - ], serialized_start=56, serialized_end=86, ) DESCRIPTOR.message_types_by_name['PreloadedData'] = _PRELOADEDDATA -_sym_db.RegisterFileDescriptor(DESCRIPTOR) -PreloadedData = _reflection.GeneratedProtocolMessageType('PreloadedData', (_message.Message,), { - 'DESCRIPTOR' : _PRELOADEDDATA, - '__module__' : 'media_engagement_preload_pb2' +class PreloadedData(_message.Message): + __metaclass__ = _reflection.GeneratedProtocolMessageType + DESCRIPTOR = _PRELOADEDDATA + # @@protoc_insertion_point(class_scope:chrome_browser_media.PreloadedData) - }) -_sym_db.RegisterMessage(PreloadedData) -DESCRIPTOR._options = None +DESCRIPTOR.has_options = True +DESCRIPTOR._options = _descriptor._ParseOptions(descriptor_pb2.FileOptions(), 'H\003') # @@protoc_insertion_point(module_scope)
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index 67d9ea7..bb040f47 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -15826,8 +15826,8 @@ <int value="5" label="CreateContainer"/> <int value="6" label="SetupContainer"/> <int value="7" label="StartContainer"/> - <int value="8" label="FetchSshKeys"/> - <int value="9" label="MountContainer"/> + <int value="8" label="FetchSshKeys (Obsolete crbug/1198006)"/> + <int value="9" label="MountContainer (Obsolete crbug/1198006)"/> <int value="10" label="ConfigureContainer"/> </enum> @@ -67597,6 +67597,8 @@ label="Permanent node update received without a server-defined unique tag"/> <int value="13" label="Unsupported permanent folder server tag"/> + <int value="14" + label="Node is descendant of root node, without permanent folder"/> </enum> <enum name="RemoteCommandExecutionStatus">
diff --git a/tools/metrics/histograms/histograms_xml/autofill/histograms.xml b/tools/metrics/histograms/histograms_xml/autofill/histograms.xml index 7ceccd6..38da58f 100644 --- a/tools/metrics/histograms/histograms_xml/autofill/histograms.xml +++ b/tools/metrics/histograms/histograms_xml/autofill/histograms.xml
@@ -1505,6 +1505,16 @@ </summary> </histogram> +<histogram name="Autofill.ProfileImport.NewProfileNumberOfEditedFields" + units="fields" expires_after="M96"> + <owner>koerber@google.com</owner> + <owner>src/components/autofill/OWNERS</owner> + <summary> + Logs the number of fields that have been edited by the user in the process + of succesfully importing a new profile after an observed form submission. + </summary> +</histogram> + <histogram name="Autofill.ProfileImport.ProfileImportType" enum="AutofillProfileImportType" expires_after="M96"> <owner>koerber@google.com</owner> @@ -1540,6 +1550,17 @@ </summary> </histogram> +<histogram name="Autofill.ProfileImport.UpdateProfileNumberOfEditedFields" + units="fields" expires_after="M96"> + <owner>koerber@google.com</owner> + <owner>src/components/autofill/OWNERS</owner> + <summary> + Logs the number of fields that have been edited by the user in the process + of succesfully updating an existing profile after an observed form + submission. + </summary> +</histogram> + <histogram name="Autofill.ProfileSuggestionsMadeWithFormatter" enum="BooleanCreated" expires_after="2020-09-30"> <owner>battre@chromium.org</owner>
diff --git a/tools/metrics/histograms/histograms_xml/histogram_suffixes_list.xml b/tools/metrics/histograms/histograms_xml/histogram_suffixes_list.xml index 83f6522..be844c5 100644 --- a/tools/metrics/histograms/histograms_xml/histogram_suffixes_list.xml +++ b/tools/metrics/histograms/histograms_xml/histogram_suffixes_list.xml
@@ -9055,6 +9055,8 @@ <suffix name="TextClassifier.SuggestSelection" label=""/> <suffix name="TextSuggester.LoadModelResult" label=""/> <suffix name="TextSuggester.Suggest" label=""/> + <suffix name="WebPlatformHandwritingModel.GetPrediction" label=""/> + <suffix name="WebPlatformHandwritingModel.LoadModelResult" label=""/> <affected-histogram name="MachineLearningService.CpuTimeMicrosec"/> <affected-histogram name="MachineLearningService.ElapsedTimeMicrosec"> <obsolete>
diff --git a/tools/metrics/histograms/histograms_xml/input/histograms.xml b/tools/metrics/histograms/histograms_xml/input/histograms.xml index db05e3d..f47ca678 100644 --- a/tools/metrics/histograms/histograms_xml/input/histograms.xml +++ b/tools/metrics/histograms/histograms_xml/input/histograms.xml
@@ -645,6 +645,15 @@ </summary> </histogram> +<histogram name="InputMethod.SystemEmojiPicker.SearchLength" units="characters" + expires_after="M95"> + <owner>jopalmer@chromium.org</owner> + <owner>essential-inputs-team@google.com</owner> + <summary> + Length of search string in emoji picker when emoji was inserted. + </summary> +</histogram> + <histogram name="InputMethod.SystemEmojiPicker.TriggerType" enum="VirtualKeyboardEmojiTriggerType" expires_after="M95"> <owner>jopalmer@chromium.org</owner> @@ -762,6 +771,15 @@ <summary>How long the virtual keyboard was visible.</summary> </histogram> +<histogram name="InputMethod.VirtualKeyboard.Emoji.Delay" units="ms" + expires_after="M95"> + <owner>jopalmer@chromium.org</owner> + <owner>essential-inputs-team@google.com</owner> + <summary> + Time between when emoji shown in VK and when the emoji is inserted. + </summary> +</histogram> + <histogram name="InputMethod.VirtualKeyboard.Emoji.TriggerType" enum="VirtualKeyboardEmojiTriggerType" expires_after="M95"> <owner>shend@chromium.org</owner>
diff --git a/tools/metrics/histograms/histograms_xml/media/histograms.xml b/tools/metrics/histograms/histograms_xml/media/histograms.xml index 627fbdf..d63d423b 100644 --- a/tools/metrics/histograms/histograms_xml/media/histograms.xml +++ b/tools/metrics/histograms/histograms_xml/media/histograms.xml
@@ -4013,6 +4013,9 @@ <histogram name="Media.Video.Autoplay.Muted" enum="AutoplaySource" expires_after="2021-06-01"> + <obsolete> + Removed in May 2021. + </obsolete> <owner>dalecurtis@chromium.org</owner> <owner>media-dev@chromium.org</owner> <summary>Records the autoplay source of muted videos.</summary>
diff --git a/tools/metrics/histograms/histograms_xml/others/histograms.xml b/tools/metrics/histograms/histograms_xml/others/histograms.xml index 703dcd5..594f18e 100644 --- a/tools/metrics/histograms/histograms_xml/others/histograms.xml +++ b/tools/metrics/histograms/histograms_xml/others/histograms.xml
@@ -9356,6 +9356,32 @@ </summary> </histogram> +<histogram + name="MachineLearningService.WebPlatformHandwritingModel.GetPrediction.Event" + enum="Boolean" expires_after="2021-09-19"> + <owner>amoylan@chromium.org</owner> + <owner>alanlxl@chromium.org</owner> + <owner>charleszhao@chromium.org</owner> + <summary> + The result of Web platform handwriting recognition, which can be either OK + or Error. + </summary> +</histogram> + +<histogram + name="MachineLearningService.WebPlatformHandwritingModel.LoadModelResult.Event" + enum="MachineLearningServiceLoadHandwritingModelResultEvent" + expires_after="2021-10-31"> + <owner>amoylan@chromium.org</owner> + <owner>alanlxl@chromium.org</owner> + <owner>charleszhao@chromium.org</owner> + <summary> + The result of load web platform handwriting model, which can be OK or some + specific error. The error code could be logged in machine learning service + in chrome or in chromeos when handwriting model is not loaded successfully. + </summary> +</histogram> + <histogram name="MachineLearningService.WorkerProcessAcceptMojoConnectionTime" units="microseconds" expires_after="2021-10-24"> <owner>alanlxl@chromium.org</owner>
diff --git a/tools/metrics/histograms/histograms_xml/quota/histograms.xml b/tools/metrics/histograms/histograms_xml/quota/histograms.xml index 9c7eafc..31ca99e 100644 --- a/tools/metrics/histograms/histograms_xml/quota/histograms.xml +++ b/tools/metrics/histograms/histograms_xml/quota/histograms.xml
@@ -21,7 +21,7 @@ <histograms> -<histogram name="Quota.AgeOfDataInDays" units="days" expires_after="2021-05-18"> +<histogram name="Quota.AgeOfDataInDays" units="days" expires_after="2022-05-18"> <owner>jarrydg@chromium.org</owner> <owner>chrome-owp-storage@google.com</owner> <summary> @@ -146,8 +146,9 @@ </histogram> <histogram name="Quota.NumberOfEvictedOriginsPerRound" units="units" - expires_after="2021-05-18"> + expires_after="2022-05-18"> <owner>jarrydg@chromium.org</owner> + <owner>chrome-owp-storage@google.com</owner> <summary>Number of evicted origins per round.</summary> </histogram>
diff --git a/tools/perf/core/perfetto_binary_roller/binary_deps.json b/tools/perf/core/perfetto_binary_roller/binary_deps.json index 378573350..58deec66 100644 --- a/tools/perf/core/perfetto_binary_roller/binary_deps.json +++ b/tools/perf/core/perfetto_binary_roller/binary_deps.json
@@ -2,7 +2,7 @@ "trace_processor_shell": { "win": { "hash": "1a68e36202f77491d3c0993d3abd36004f3a0eac", - "remote_path": "perfetto_binaries/trace_processor_shell/win/3baa021c258ba7670ab363a7ef73b3fd24fee97a/trace_processor_shell.exe" + "remote_path": "perfetto_binaries/trace_processor_shell/win/565fc165d0f867c9de129ead9b1766f42d2a1205/trace_processor_shell.exe" }, "mac": { "hash": "d60c6038003ec1b551e16068d49f4d55ee20656f",
diff --git a/ui/accessibility/extensions/chromevoxclassic/BUILD.gn b/ui/accessibility/extensions/chromevoxclassic/BUILD.gn index 8975eae..88f9d1e 100644 --- a/ui/accessibility/extensions/chromevoxclassic/BUILD.gn +++ b/ui/accessibility/extensions/chromevoxclassic/BUILD.gn
@@ -505,6 +505,8 @@ "//chrome/browser/extensions/browsertest_util.h", "//chrome/browser/ui/webui/web_ui_test_handler.cc", "//chrome/browser/ui/webui/web_ui_test_handler.h", + "//chrome/test/base/devtools_listener.cc", + "//chrome/test/base/devtools_listener.h", "//chrome/test/base/extension_js_browser_test.cc", "//chrome/test/base/extension_js_browser_test.h", "//chrome/test/base/extension_load_waiter_one_shot.cc",
diff --git a/ui/events/ozone/layout/BUILD.gn b/ui/events/ozone/layout/BUILD.gn index 987498b..c7a5230b 100644 --- a/ui/events/ozone/layout/BUILD.gn +++ b/ui/events/ozone/layout/BUILD.gn
@@ -75,3 +75,17 @@ "//ui/events:dom_keycode_converter", ] } + +source_set("test_support") { + testonly = true + + sources = [ + "keyboard_layout_engine_test_utils.cc", + "keyboard_layout_engine_test_utils.h", ] + + deps = [ + ":layout", + "//base", + "//ui/base:features", + ] +}
diff --git a/ui/events/ozone/layout/keyboard_layout_engine.h b/ui/events/ozone/layout/keyboard_layout_engine.h index 986a2621a..295e33c 100644 --- a/ui/events/ozone/layout/keyboard_layout_engine.h +++ b/ui/events/ozone/layout/keyboard_layout_engine.h
@@ -7,6 +7,7 @@ #include <string> +#include "base/callback.h" #include "base/component_export.h" #include "ui/events/keycodes/dom/dom_key.h" #include "ui/events/keycodes/keyboard_codes.h" @@ -70,6 +71,11 @@ int event_flags, DomKey* dom_key, KeyboardCode* key_code) const = 0; + + // Tests may need to wait for the keyboard layout to be fully initialised. + // The implementation should run |closure| when it is ready to handle calls to + // Lookup(). + virtual void SetInitCallbackForTest(base::OnceClosure closure) = 0; }; } // namespace ui
diff --git a/ui/events/ozone/layout/keyboard_layout_engine_test_utils.cc b/ui/events/ozone/layout/keyboard_layout_engine_test_utils.cc new file mode 100644 index 0000000..09c73ba --- /dev/null +++ b/ui/events/ozone/layout/keyboard_layout_engine_test_utils.cc
@@ -0,0 +1,31 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ui/events/ozone/layout/keyboard_layout_engine_test_utils.h" + +#include "base/callback.h" +#include "base/run_loop.h" +#include "ui/base/ui_base_features.h" +#include "ui/events/ozone/layout/keyboard_layout_engine.h" +#include "ui/events/ozone/layout/keyboard_layout_engine_manager.h" + +namespace ui { + +// TODO(crbug.com/1209477): Wayland bots use Weston with Headless backend that +// sets up XkbKeyboardLayoutEngine differently. When that is fixed, remove the +// workaround function below. +void WaitUntilLayoutEngineIsReadyForTest() { + if (!features::IsUsingOzonePlatform()) + return; + // The platform may set the keyboard layout asynchronously. We need the + // layout when handling key events, so wait until it is ready. + // + // See crbug.com/1186996 + base::RunLoop loop; + ui::KeyboardLayoutEngineManager::GetKeyboardLayoutEngine() + ->SetInitCallbackForTest(loop.QuitClosure()); + loop.Run(); +} + +} // namespace ui
diff --git a/ui/events/ozone/layout/keyboard_layout_engine_test_utils.h b/ui/events/ozone/layout/keyboard_layout_engine_test_utils.h new file mode 100644 index 0000000..6a7245e --- /dev/null +++ b/ui/events/ozone/layout/keyboard_layout_engine_test_utils.h
@@ -0,0 +1,16 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef UI_EVENTS_OZONE_LAYOUT_KEYBOARD_LAYOUT_ENGINE_TEST_UTILS_H_ +#define UI_EVENTS_OZONE_LAYOUT_KEYBOARD_LAYOUT_ENGINE_TEST_UTILS_H_ + +namespace ui { + +// Helper for tests that require the layout to be ready when handling key +// events. +void WaitUntilLayoutEngineIsReadyForTest(); + +} // namespace ui + +#endif // UI_EVENTS_OZONE_LAYOUT_KEYBOARD_LAYOUT_ENGINE_TEST_UTILS_H_
diff --git a/ui/events/ozone/layout/no/no_keyboard_layout_engine.cc b/ui/events/ozone/layout/no/no_keyboard_layout_engine.cc index c3adea4..d2d999a 100644 --- a/ui/events/ozone/layout/no/no_keyboard_layout_engine.cc +++ b/ui/events/ozone/layout/no/no_keyboard_layout_engine.cc
@@ -35,4 +35,8 @@ return false; } +void NoKeyboardLayoutEngine::SetInitCallbackForTest(base::OnceClosure closure) { + std::move(closure).Run(); +} + } // namespace ui
diff --git a/ui/events/ozone/layout/no/no_keyboard_layout_engine.h b/ui/events/ozone/layout/no/no_keyboard_layout_engine.h index 3b7ad27..d049099 100644 --- a/ui/events/ozone/layout/no/no_keyboard_layout_engine.h +++ b/ui/events/ozone/layout/no/no_keyboard_layout_engine.h
@@ -27,6 +27,7 @@ int flags, DomKey* dom_key, KeyboardCode* key_code) const override; + void SetInitCallbackForTest(base::OnceClosure closure) override; }; } // namespace ui
diff --git a/ui/events/ozone/layout/stub/stub_keyboard_layout_engine.cc b/ui/events/ozone/layout/stub/stub_keyboard_layout_engine.cc index 069f83c..bcde64fd 100644 --- a/ui/events/ozone/layout/stub/stub_keyboard_layout_engine.cc +++ b/ui/events/ozone/layout/stub/stub_keyboard_layout_engine.cc
@@ -48,4 +48,9 @@ return DomCodeToUsLayoutDomKey(dom_code, flags, out_dom_key, out_key_code); } +void StubKeyboardLayoutEngine::SetInitCallbackForTest( + base::OnceClosure closure) { + std::move(closure).Run(); +} + } // namespace ui
diff --git a/ui/events/ozone/layout/stub/stub_keyboard_layout_engine.h b/ui/events/ozone/layout/stub/stub_keyboard_layout_engine.h index 4db623b1d..3cfe7dd 100644 --- a/ui/events/ozone/layout/stub/stub_keyboard_layout_engine.h +++ b/ui/events/ozone/layout/stub/stub_keyboard_layout_engine.h
@@ -27,6 +27,7 @@ int flags, DomKey* dom_key, KeyboardCode* key_code) const override; + void SetInitCallbackForTest(base::OnceClosure closure) override; }; } // namespace ui
diff --git a/ui/events/ozone/layout/xkb/xkb_keyboard_layout_engine.cc b/ui/events/ozone/layout/xkb/xkb_keyboard_layout_engine.cc index 9059eca..2e2d6791 100644 --- a/ui/events/ozone/layout/xkb/xkb_keyboard_layout_engine.cc +++ b/ui/events/ozone/layout/xkb/xkb_keyboard_layout_engine.cc
@@ -808,6 +808,16 @@ return true; } +void XkbKeyboardLayoutEngine::SetInitCallbackForTest( + base::OnceClosure closure) { + if (xkb_state_) { + std::move(closure).Run(); + return; + } + + keymap_init_closure_for_test_ = std::move(closure); +} + bool XkbKeyboardLayoutEngine::SetCurrentLayoutFromBuffer( const char* keymap_string, size_t size) { @@ -885,6 +895,9 @@ #endif shift_mod_mask_ = EventFlagsToXkbFlags(ui::EF_SHIFT_DOWN); altgr_mod_mask_ = EventFlagsToXkbFlags(ui::EF_ALTGR_DOWN); + + if (keymap_init_closure_for_test_) + std::move(keymap_init_closure_for_test_).Run(); } xkb_mod_mask_t XkbKeyboardLayoutEngine::EventFlagsToXkbFlags(
diff --git a/ui/events/ozone/layout/xkb/xkb_keyboard_layout_engine.h b/ui/events/ozone/layout/xkb/xkb_keyboard_layout_engine.h index fd9948d..05d62643 100644 --- a/ui/events/ozone/layout/xkb/xkb_keyboard_layout_engine.h +++ b/ui/events/ozone/layout/xkb/xkb_keyboard_layout_engine.h
@@ -49,6 +49,8 @@ DomKey* dom_key, KeyboardCode* key_code) const override; + void SetInitCallbackForTest(base::OnceClosure closure) override; + int UpdateModifiers(uint32_t depressed, uint32_t latched, uint32_t locked, @@ -142,6 +144,8 @@ xkb_layout_index_t layout_index_ = 0; + base::OnceClosure keymap_init_closure_for_test_; + // Support weak pointers for attach & detach callbacks. base::WeakPtrFactory<XkbKeyboardLayoutEngine> weak_ptr_factory_; };
diff --git a/ui/file_manager/BUILD.gn b/ui/file_manager/BUILD.gn index 469ef97a..bd47236 100644 --- a/ui/file_manager/BUILD.gn +++ b/ui/file_manager/BUILD.gn
@@ -266,7 +266,7 @@ # Files app Elements: "file_manager/foreground/elements/icons.m.js", - "file_manager/foreground/elements/files_format_dialog.m.js", + "file_manager/foreground/elements/files_format_dialog.js", "file_manager/foreground/elements/files_icon_button.m.js", "file_manager/foreground/elements/files_message.m.js", "file_manager/foreground/elements/files_metadata_box.m.js", @@ -379,6 +379,7 @@ "//ui/file_manager/file_manager/externs/background:modulize", "//ui/file_manager/file_manager/foreground/elements:elements", "//ui/file_manager/file_manager/foreground/elements:modulize", + "//ui/file_manager/file_manager/foreground/elements:web_components", "//ui/file_manager/file_manager/foreground/js:modulize", "//ui/file_manager/file_manager/foreground/js/metadata:modulize", "//ui/file_manager/file_manager/foreground/js/ui:modulize",
diff --git a/ui/file_manager/file_manager/foreground/elements/BUILD.gn b/ui/file_manager/file_manager/foreground/elements/BUILD.gn index d2ee096..c43eef6 100644 --- a/ui/file_manager/file_manager/foreground/elements/BUILD.gn +++ b/ui/file_manager/file_manager/foreground/elements/BUILD.gn
@@ -4,6 +4,7 @@ import("//third_party/closure_compiler/compile_js.gni") import("//third_party/closure_compiler/js_unit_tests.gni") +import("//tools/polymer/html_to_js.gni") import("//tools/polymer/polymer.gni") import("//ui/file_manager/base/gn/js_test_gen_html.gni") import("//ui/webui/resources/tools/js_modulizer.gni") @@ -13,7 +14,6 @@ group("elements") { visibility += [ "//ui/file_manager/*" ] public_deps = [ - "//ui/file_manager/file_manager/foreground/elements:files_format_dialog_module", "//ui/file_manager/file_manager/foreground/elements:files_icon_button_module", "//ui/file_manager/file_manager/foreground/elements:files_metadata_box_module", "//ui/file_manager/file_manager/foreground/elements:files_metadata_entry_module", @@ -32,40 +32,19 @@ testonly = true visibility += [ "//ui/file_manager:closure_compile" ] deps = [ - ":closure_compile_internal", ":closure_compile_jsmodules", ":js_test_gen_html_modules_type_check_auto", ] } -js_type_check("closure_compile_internal") { - uses_legacy_modules = true - deps = [ - ":files_format_dialog", - ":files_icon_button", - ":files_message", - ":files_metadata_box", - ":files_metadata_entry", - ":files_password_dialog", - ":files_quick_view", - ":files_ripple", - ":files_safe_media", - ":files_safe_media_webview_content", - ":files_spinner", - ":files_toast", - ":files_toggle_ripple", - ":files_tooltip", - ":xf_button", - ":xf_circular_progress", - ":xf_display_panel", - ":xf_panel_item", - ] -} - js_type_check("closure_compile_jsmodules") { is_polymer3 = true + closure_flags = default_closure_args + [ + "js_module_root=gen/ui/file_manager/", + "js_module_root=../../ui/file_manager/", + ] deps = [ - ":files_format_dialog.m", + ":files_format_dialog", ":files_icon_button.m", ":files_message.m", ":files_metadata_box.m", @@ -85,33 +64,12 @@ ] } +html_to_js("web_components") { + js_files = [ "files_format_dialog.js" ] +} + js_library("files_format_dialog") { - deps = [ - "//ui/file_manager/file_manager/common/js:util", - "//ui/webui/resources/cr_elements/cr_button:cr_button", - "//ui/webui/resources/cr_elements/cr_dialog:cr_dialog", - "//ui/webui/resources/cr_elements/cr_input:cr_input", - "//ui/webui/resources/js:i18n_behavior", - ] -} - -polymer_modulizer("files_format_dialog") { - js_file = "files_format_dialog.js" - html_file = "files_format_dialog.html" - html_type = "dom-module" - preserve_url_scheme = true - - auto_imports = [ - "ui/file_manager/file_manager/common/js/util.html|util", - "ui/file_manager/file_manager/common/js/files_app_entry_types.html|EntryList,VolumeEntry", - "ui/file_manager/file_manager/common/js/volume_manager_types.html|VolumeManagerCommon", - "ui/file_manager/file_manager/externs/volume_info.html|VolumeInfo", - ] -} - -js_library("files_format_dialog.m") { visibility += [ "//ui/file_manager/audio_player/*" ] - sources = [ "$root_gen_dir/ui/file_manager/file_manager/foreground/elements/files_format_dialog.m.js" ] deps = [ "//third_party/polymer/v3_0/components-chromium/iron-icon:iron-icon", "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", @@ -124,7 +82,6 @@ "//ui/webui/resources/cr_elements/cr_input:cr_input.m", "//ui/webui/resources/js:i18n_behavior.m", ] - extra_deps = [ ":files_format_dialog_module" ] } js_library("files_icon_button") {
diff --git a/ui/file_manager/file_manager/foreground/elements/files_format_dialog.html b/ui/file_manager/file_manager/foreground/elements/files_format_dialog.html index 44b5924..e197393 100644 --- a/ui/file_manager/file_manager/foreground/elements/files_format_dialog.html +++ b/ui/file_manager/file_manager/foreground/elements/files_format_dialog.html
@@ -2,101 +2,78 @@ -- Use of this source code is governed by a BSD-style license that can be -- found in the LICENSE file. --> +<style include="cr-shared-style md-select"> + .md-select { + width: 100%; + } -<link rel="import" href="chrome://resources/html/polymer.html"> + [slot='body'] > div { + margin-bottom: var(--cr-form-field-bottom-spacing); + } -<link rel="import" href="chrome://resources/cr_elements/cr_button/cr_button.html"> -<link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html"> -<link rel="import" href="chrome://resources/cr_elements/cr_input/cr_input.html"> -<link rel="import" href="chrome://resources/cr_elements/icons.html"> -<link rel="import" href="chrome://resources/cr_elements/md_select_css.html"> -<link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html"> -<link rel="import" href="chrome://resources/cr_elements/shared_style_css.html"> -<link rel="import" href="chrome://resources/html/i18n_behavior.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html"> + [slot='body'] > #disk-format { + margin-bottom: 0; + padding-bottom: 2px; + } -<!-- <link rel="import" href="../../common/js/util.html"> --> -<!-- <link rel="import" href="../../common/js/files_app_entry_types.html"> --> -<!-- <link rel="import" href="../../common/js/volume_manager_types.html"> --> -<!-- <link rel="import" href="../../externs/volume_info.html"> --> + [slot='button-container'] { + padding-top: 32px; + } -<dom-module id="files-format-dialog"> - <template> - <style include="cr-shared-style md-select"> - .md-select { - width: 100%; - } + #warning-icon { + --iron-icon-fill-color: var(--google-red-600); + } - [slot='body'] > div { - margin-bottom: var(--cr-form-field-bottom-spacing); - } + #warning-message { + color: var(--google-red-600); + display: inline-block; + margin-inline-start: 8px; + } - [slot='body'] > #disk-format { - margin-bottom: 0; - padding-bottom: 2px; - } + cr-dialog::part(dialog) { + border-radius: 12px; + } + cr-dialog::part(wrapper) { + /* subtract the internal padding in <cr-dialog> */ + padding: calc(24px - 20px); + } +</style> - [slot='button-container'] { - padding-top: 32px; - } - - #warning-icon { - --iron-icon-fill-color: var(--google-red-600); - } - - #warning-message { - color: var(--google-red-600); - display: inline-block; - margin-inline-start: 8px; - } - - cr-dialog::part(dialog) { - border-radius: 12px; - } - cr-dialog::part(wrapper) { - /* subtract the internal padding in <cr-dialog> */ - padding: calc(24px - 20px); - } - </style> - - <cr-dialog id="dialog" close-text="[[i18n('CLOSE_LABEL')]]" - single-partition-format$="[[getSinglePartitionFormat()]]"> - <div slot="title"> - [[i18n('FORMAT_DIALOG_TITLE', title)]] +<cr-dialog id="dialog" close-text="[[i18n('CLOSE_LABEL')]]" + single-partition-format$="[[getSinglePartitionFormat()]]"> + <div slot="title"> + [[i18n('FORMAT_DIALOG_TITLE', title)]] + </div> + <div slot="body"> + <div>[[getDialogMessage_(isErase_)]]</div> + <div id="warning-container" hidden="[[!space_used_]]" role="alert"> + <iron-icon id="warning-icon" icon="cr:warning"></iron-icon> + <div id="warning-message"> + [[i18n('FORMAT_DIALOG_DELETE_WARNING', space_used_)]] </div> - <div slot="body"> - <div>[[getDialogMessage_(isErase_)]]</div> - <div id="warning-container" hidden="[[!space_used_]]" role="alert"> - <iron-icon id="warning-icon" icon="cr:warning"></iron-icon> - <div id="warning-message"> - [[i18n('FORMAT_DIALOG_DELETE_WARNING', space_used_)]] - </div> - </div> - <cr-input label="[[i18n('FORMAT_DIALOG_DRIVE_NAME_LABEL')]]" - id="label" value="{{label_}}" auto-validate="true"> - </cr-input> - <div id="disk-format"> - <label id="format-type-label" class="cr-form-field-label"> - [[i18n('FORMAT_DIALOG_FORMAT_LABEL')]] - </label> - <select class="md-select" aria-labelledby="format-type-label" - value="{{formatType_::change}}"> - <option value="vfat">FAT32</option> - <option value="exfat">exFAT</option> - <option value="ntfs">NTFS</option> - </select> - </div> - </div> - <div slot="button-container"> - <cr-button class="cancel-button" on-click="cancel_" id="cancel"> - [[i18n('CANCEL_LABEL')]] - </cr-button> - <cr-button class="action-button" on-click="format_" - id="format-button"> - [[getConfirmLabel_(isErase_)]] - </cr-button> - </div> - </cr-dialog> - </template> - <script src="files_format_dialog.js"></script> -</dom-module> + </div> + <cr-input label="[[i18n('FORMAT_DIALOG_DRIVE_NAME_LABEL')]]" + id="label" value="{{label_}}" auto-validate="true"> + </cr-input> + <div id="disk-format"> + <label id="format-type-label" class="cr-form-field-label"> + [[i18n('FORMAT_DIALOG_FORMAT_LABEL')]] + </label> + <select class="md-select" aria-labelledby="format-type-label" + value="{{formatType_::change}}"> + <option value="vfat">FAT32</option> + <option value="exfat">exFAT</option> + <option value="ntfs">NTFS</option> + </select> + </div> + </div> + <div slot="button-container"> + <cr-button class="cancel-button" on-click="cancel_" id="cancel"> + [[i18n('CANCEL_LABEL')]] + </cr-button> + <cr-button class="action-button" on-click="format_" + id="format-button"> + [[getConfirmLabel_(isErase_)]] + </cr-button> + </div> +</cr-dialog>
diff --git a/ui/file_manager/file_manager/foreground/elements/files_format_dialog.js b/ui/file_manager/file_manager/foreground/elements/files_format_dialog.js index efd7efa..659308c 100644 --- a/ui/file_manager/file_manager/foreground/elements/files_format_dialog.js +++ b/ui/file_manager/file_manager/foreground/elements/files_format_dialog.js
@@ -2,7 +2,26 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import 'chrome://resources/cr_elements/cr_button/cr_button.m.js'; +import 'chrome://resources/cr_elements/cr_dialog/cr_dialog.m.js'; +import 'chrome://resources/cr_elements/cr_input/cr_input.m.js'; +import 'chrome://resources/cr_elements/icons.m.js'; +import 'chrome://resources/cr_elements/md_select_css.m.js'; +import 'chrome://resources/cr_elements/shared_vars_css.m.js'; +import 'chrome://resources/cr_elements/shared_style_css.m.js'; +import 'chrome://resources/polymer/v3_0/iron-icon/iron-icon.js'; + +import {I18nBehavior} from 'chrome://resources/js/i18n_behavior.m.js'; +import {html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; + +import {EntryList, VolumeEntry} from '../../common/js/files_app_entry_types.m.js'; +import {util} from '../../common/js/util.m.js'; +import {VolumeManagerCommon} from '../../common/js/volume_manager_types.m.js'; +import {VolumeInfo} from '../../externs/volume_info.m.js'; + Polymer({ + _template: html`{__html_template__}`, + is: 'files-format-dialog', behaviors: [I18nBehavior],
diff --git a/ui/file_manager/file_manager/foreground/elements/files_quick_view.css b/ui/file_manager/file_manager/foreground/elements/files_quick_view.css index a05c8cb..cf369ba 100644 --- a/ui/file_manager/file_manager/foreground/elements/files_quick_view.css +++ b/ui/file_manager/file_manager/foreground/elements/files_quick_view.css
@@ -84,8 +84,8 @@ } :host-context(html[dir='rtl']) #contentPanel[metadata-box-active] { - margin-inline-end: auto; - margin-inline-start: 320px; + margin-inline-end: 320px; + margin-inline-start: auto; } #innerContentPanel {
diff --git a/ui/file_manager/file_manager/foreground/js/BUILD.gn b/ui/file_manager/file_manager/foreground/js/BUILD.gn index 1473c7d3..01b6756 100644 --- a/ui/file_manager/file_manager/foreground/js/BUILD.gn +++ b/ui/file_manager/file_manager/foreground/js/BUILD.gn
@@ -20,9 +20,7 @@ visibility += [ "//ui/file_manager:closure_compile" ] deps = [ ":closure_compile_jsmodules", - ":closure_compile_module", ":js_test_gen_html_modules_type_check_auto", - ":test_support_type_check", ] } @@ -30,6 +28,7 @@ is_polymer3 = true closure_flags = default_closure_args + [ "js_module_root=gen/ui/file_manager/", + "js_module_root=../../ui/file_manager/", "browser_resolver_prefix_replacements=\"chrome-extension://hhaomjibdihmijegdhdafkllkbggdgoj/=./file_manager/\"", "browser_resolver_prefix_replacements=\"chrome-extension://pmfjbimdmchhbnneeidfognadeopoehp/=./image_loader/\"", ] @@ -99,110 +98,6 @@ ] } -js_type_check("closure_compile_module") { - uses_legacy_modules = true - deps = [ - ":actions_controller", - ":actions_model", - ":android_app_list_model", - ":app_state_controller", - ":closure_compile_externs", - ":column_visibility_controller", - ":constants", - ":crossover_search_utils", - ":crostini_controller", - ":dialog_action_controller", - ":dialog_type", - ":directory_contents", - ":directory_model", - ":directory_tree_naming_controller", - ":drive_dialog_controller", - ":drop_effect_and_label", - ":elements_importer", - ":empty_folder_controller", - ":file_list_model", - ":file_manager", - ":file_manager_commands", - ":file_selection", - ":file_tasks", - ":file_transfer_controller", - ":file_type_filters_controller", - ":file_watcher", - ":folder_shortcuts_data_model", - ":gear_menu_controller", - ":import_controller", - ":last_modified_controller", - ":launch_param", - ":list_thumbnail_loader", - ":main", - ":main_window_component", - ":metadata_box_controller", - ":metadata_update_controller", - ":metrics_start", - ":naming_controller", - ":navigation_list_model", - ":navigation_uma", - ":path_component", - ":providers_model", - ":quick_view_controller", - ":quick_view_model", - ":quick_view_uma", - ":scan_controller", - ":search_controller", - ":selection_menu_controller", - ":sort_menu_controller", - ":spinner_controller", - ":task_controller", - ":task_history", - ":thumbnail_loader", - ":toolbar_controller", - ":webui_command_extender", - ] -} - -js_library("closure_compile_externs") { - sources = [] - externs_list = [ - "$externs_path/command_line_private.js", - "$externs_path/metrics_private.js", - "//ui/file_manager/file_manager/externs/background/crostini.js", - "//ui/file_manager/file_manager/externs/background/drive_sync_handler.js", - "//ui/file_manager/file_manager/externs/background/background_base.js", - "//ui/file_manager/file_manager/externs/background/file_browser_background_full.js", - "//ui/file_manager/file_manager/externs/background/file_operation_manager.js", - "//ui/file_manager/file_manager/externs/background/media_import_handler.js", - "//ui/file_manager/file_manager/externs/background/task_queue.js", - "//ui/file_manager/file_manager/externs/background/duplicate_finder.js", - "//ui/file_manager/file_manager/externs/background/media_scanner.js", - "//ui/file_manager/file_manager/externs/background/progress_center.js", - "//ui/file_manager/file_manager/externs/background_window.js", - "//ui/file_manager/file_manager/externs/chrome_echo_private.js", - "//ui/file_manager/file_manager/externs/command_handler_deps.js", - "//ui/file_manager/file_manager/externs/css_rule.js", - "//ui/file_manager/file_manager/externs/directory_change_event.js", - "//ui/file_manager/file_manager/externs/drive_dialog_controller.js", - "//ui/file_manager/file_manager/externs/entries_changed_event.js", - "//ui/file_manager/file_manager/externs/gallery_foreground.js", - "//ui/file_manager/file_manager/externs/menu_item_update_event.js", - "//ui/file_manager/file_manager/externs/paper_elements.js", - "//ui/file_manager/file_manager/externs/platform.js", - "//ui/file_manager/file_manager/externs/search_item.js", - ] -} - -js_type_check("test_support_type_check") { - uses_legacy_modules = true - testonly = true - deps = [ - ":fake_android_app_list_model", - ":mock_actions_model", - ":mock_directory_model", - ":mock_folder_shortcut_data_model", - ":mock_navigation_list_model", - ":mock_thumbnail_loader", - ] -} - js_library("actions_controller") { deps = [ ":actions_model", @@ -734,7 +629,7 @@ js_library("deferred_elements.m") { visibility += [ "//ui/file_manager:*" ] deps = [ - "//ui/file_manager/file_manager/foreground/elements:files_format_dialog.m", + "//ui/file_manager/file_manager/foreground/elements:files_format_dialog", "//ui/file_manager/file_manager/foreground/elements:files_message.m", "//ui/file_manager/file_manager/foreground/elements:files_password_dialog.m", "//ui/file_manager/file_manager/foreground/elements:files_ripple.m", @@ -990,7 +885,7 @@ "//ui/file_manager/file_manager/externs:files_app_entry_interfaces.m", "//ui/file_manager/file_manager/externs:volume_info.m", "//ui/file_manager/file_manager/externs:volume_manager.m", - "//ui/file_manager/file_manager/foreground/elements:files_format_dialog.m", + "//ui/file_manager/file_manager/foreground/elements:files_format_dialog", "//ui/webui/resources/js:assert.m", "//ui/webui/resources/js/cr/ui:command.m", "//ui/webui/resources/js/cr/ui:context_menu_handler.m",
diff --git a/ui/file_manager/file_manager/foreground/js/deferred_elements.m.js b/ui/file_manager/file_manager/foreground/js/deferred_elements.m.js index 2e4ac4d..53aa556 100644 --- a/ui/file_manager/file_manager/foreground/js/deferred_elements.m.js +++ b/ui/file_manager/file_manager/foreground/js/deferred_elements.m.js
@@ -7,7 +7,7 @@ */ import 'chrome://resources/cr_elements/cr_toggle/cr_toggle.m.js'; -import '../elements/files_format_dialog.m.js'; +import '../elements/files_format_dialog.js'; import '../elements/files_message.m.js'; import '../elements/files_password_dialog.m.js'; import '../elements/files_ripple.m.js';
diff --git a/ui/file_manager/file_manager/foreground/js/ui/BUILD.gn b/ui/file_manager/file_manager/foreground/js/ui/BUILD.gn index acf7527..e5dff30b 100644 --- a/ui/file_manager/file_manager/foreground/js/ui/BUILD.gn +++ b/ui/file_manager/file_manager/foreground/js/ui/BUILD.gn
@@ -15,7 +15,6 @@ visibility += [ "//ui/file_manager:closure_compile" ] deps = [ ":closure_compile_jsmodules", - ":closure_compile_module", ":js_test_gen_html_modules_type_check_auto", ] } @@ -72,74 +71,6 @@ ] } -js_type_check("closure_compile_module") { - uses_legacy_modules = true - deps = [ - ":action_model_ui", - ":actions_submenu", - ":banners", - ":breadcrumb", - ":closure_compile_externs", - ":combobutton", - ":commandbutton", - ":default_task_dialog", - ":dialog_footer", - ":directory_tree", - ":drag_selector", - ":empty_folder", - ":file_grid", - ":file_list_selection_model", - ":file_manager_dialog_base", - ":file_manager_ui", - ":file_metadata_formatter", - ":file_table", - ":file_table_list", - ":file_tap_handler", - ":files_alert_dialog", - ":files_confirm_dialog", - ":files_menu", - ":gear_menu", - ":import_crostini_image_dialog", - ":install_linux_package_dialog", - ":list_container", - ":location_line", - ":multi_menu", - ":multi_menu_button", - ":progress_center_panel", - ":providers_menu", - ":search_box", - "table:table", - "table:table_column", - "table:table_column_model", - "table:table_header", - "table:table_list", - "table:table_splitter", - ] -} - -js_library("closure_compile_externs") { - sources = [] - externs_list = [ - "$externs_path/metrics_private.js", - "//ui/file_manager/file_manager/externs/background/crostini.js", - "//ui/file_manager/file_manager/externs/background/drive_sync_handler.js", - "//ui/file_manager/file_manager/externs/background/background_base.js", - "//ui/file_manager/file_manager/externs/background/file_operation_manager.js", - "//ui/file_manager/file_manager/externs/background/import_history.js", - "//ui/file_manager/file_manager/externs/background_window.js", - "//ui/file_manager/file_manager/externs/chrome_echo_private.js", - "//ui/file_manager/file_manager/externs/css_rule.js", - "//ui/file_manager/file_manager/externs/drag_target.js", - "//ui/file_manager/file_manager/externs/drive_dialog_controller.js", - "//ui/file_manager/file_manager/externs/entries_changed_event.js", - "//ui/file_manager/file_manager/externs/gallery_foreground.js", - "//ui/file_manager/file_manager/externs/menu_item_update_event.js", - "//ui/file_manager/file_manager/externs/paper_elements.js", - "//ui/file_manager/file_manager/externs/platform.js", - "//ui/file_manager/file_manager/externs/search_item.js", - ] -} - js_library("a11y_announce") { }
diff --git a/ui/file_manager/file_manager_resources.grd b/ui/file_manager/file_manager_resources.grd index 1ba088f..f0613f7 100644 --- a/ui/file_manager/file_manager_resources.grd +++ b/ui/file_manager/file_manager_resources.grd
@@ -25,8 +25,6 @@ <!-- Polymer elements --> <include name="IDR_FILE_MANAGER_ELEMENTS_ELEMENTS_BUNDLE_HTML" file="file_manager/foreground/elements/elements_bundle.html" type="BINDATA"/> - <include name="IDR_FILE_MANAGER_ELEMENTS_FILES_FORMAT_DIALOG_HTML" file="file_manager/foreground/elements/files_format_dialog.html" type="BINDATA" /> - <include name="IDR_FILE_MANAGER_ELEMENTS_FILES_FORMAT_DIALOG_JS" file="file_manager/foreground/elements/files_format_dialog.js" type="BINDATA" /> <include name="IDR_FILE_MANAGER_ELEMENTS_FILES_ICON_BUTTON_HTML" file="file_manager/foreground/elements/files_icon_button.html" type="BINDATA" /> <include name="IDR_FILE_MANAGER_ELEMENTS_FILES_ICON_BUTTON_JS" file="file_manager/foreground/elements/files_icon_button.js" type="BINDATA" /> <include name="IDR_FILE_MANAGER_ELEMENTS_FILES_MESSAGE_HTML" file="file_manager/foreground/elements/files_message.html" type="BINDATA" />
diff --git a/ui/ozone/platform/wayland/BUILD.gn b/ui/ozone/platform/wayland/BUILD.gn index 05e9087..85268ff 100644 --- a/ui/ozone/platform/wayland/BUILD.gn +++ b/ui/ozone/platform/wayland/BUILD.gn
@@ -180,6 +180,7 @@ "//mojo/public/cpp/bindings", "//mojo/public/cpp/system", "//skia", + "//third_party/libsync", "//third_party/wayland:wayland_util", "//third_party/wayland-protocols:cursor_shapes_protocol", "//third_party/wayland-protocols:extended_drag",
diff --git a/ui/ozone/platform/wayland/gpu/gbm_surfaceless_wayland.cc b/ui/ozone/platform/wayland/gpu/gbm_surfaceless_wayland.cc index bd857b2..aba3311 100644 --- a/ui/ozone/platform/wayland/gpu/gbm_surfaceless_wayland.cc +++ b/ui/ozone/platform/wayland/gpu/gbm_surfaceless_wayland.cc
@@ -4,6 +4,7 @@ #include "ui/ozone/platform/wayland/gpu/gbm_surfaceless_wayland.h" +#include <sync/sync.h> #include <memory> #include "base/bind.h" @@ -276,7 +277,6 @@ void GbmSurfacelessWayland::OnSubmission(BufferId buffer_id, const gfx::SwapResult& swap_result, gfx::GpuFenceHandle release_fence) { - DCHECK(release_fence.is_null()); // submitted_frames_ may temporarily have more than one buffer in it if // buffers are released out of order by the Wayland server. DCHECK(!submitted_frames_.empty() || background_buffer_id_ == buffer_id); @@ -294,6 +294,19 @@ submitted_frame->swap_result = swap_result; } submitted_frame->pending_presentation_buffers.insert(buffer_id); + + // Accumulate release fences into a single fence. + if (!release_fence.is_null()) { + if (submitted_frame->merged_release_fence_fd.is_valid()) { + submitted_frame->merged_release_fence_fd.reset( + sync_merge("", submitted_frame->merged_release_fence_fd.get(), + release_fence.owned_fd.get())); + } else { + submitted_frame->merged_release_fence_fd = + std::move(release_fence.owned_fd); + } + DCHECK(submitted_frame->merged_release_fence_fd.is_valid()); + } break; } } @@ -309,8 +322,13 @@ submitted_frames_.erase(submitted_frames_.begin()); submitted_frame->overlays.clear(); + gfx::GpuFenceHandle release_fence; + if (submitted_frame->merged_release_fence_fd.is_valid()) + release_fence.owned_fd = + std::move(submitted_frame->merged_release_fence_fd); std::move(submitted_frame->completion_callback) - .Run(gfx::SwapCompletionResult(submitted_frame->swap_result)); + .Run(gfx::SwapCompletionResult(submitted_frame->swap_result, + std::move(release_fence))); pending_presentation_frames_.push_back(std::move(submitted_frame)); }
diff --git a/ui/ozone/platform/wayland/gpu/gbm_surfaceless_wayland.h b/ui/ozone/platform/wayland/gpu/gbm_surfaceless_wayland.h index 5b65de1..781c761 100644 --- a/ui/ozone/platform/wayland/gpu/gbm_surfaceless_wayland.h +++ b/ui/ozone/platform/wayland/gpu/gbm_surfaceless_wayland.h
@@ -100,6 +100,9 @@ std::vector<gl::GLSurfaceOverlay> overlays; SwapCompletionCallback completion_callback; PresentationCallback presentation_callback; + // Merged release fence fd. This is taken as the union of all release + // fences for a particular OnSubmission. + base::ScopedFD merged_release_fence_fd; bool schedule_planes_succeeded = false; // Maps |buffer_id| to an OverlayPlane, used for committing overlays and
diff --git a/ui/views/BUILD.gn b/ui/views/BUILD.gn index 00a2bde3a..bc83b44f 100644 --- a/ui/views/BUILD.gn +++ b/ui/views/BUILD.gn
@@ -1392,7 +1392,10 @@ } if (use_ozone) { - deps += [ "//ui/ozone" ] + deps += [ + "//ui/ozone", + "//ui/events/ozone/layout:test_support", + ] } if (is_linux || is_chromeos) {
diff --git a/ui/views/controls/editable_combobox/editable_combobox_unittest.cc b/ui/views/controls/editable_combobox/editable_combobox_unittest.cc index 716c3c6..26ed4ab 100644 --- a/ui/views/controls/editable_combobox/editable_combobox_unittest.cc +++ b/ui/views/controls/editable_combobox/editable_combobox_unittest.cc
@@ -38,6 +38,10 @@ #include "ui/views/widget/widget.h" #include "ui/views/widget/widget_utils.h" +#if defined(USE_OZONE) +#include "ui/events/ozone/layout/keyboard_layout_engine_test_utils.h" +#endif + namespace views { namespace { @@ -69,6 +73,7 @@ public: EditableComboboxTest() { views::test::DisableMenuClosureAnimations(); } + void SetUp() override; void TearDown() override; // Initializes the combobox with the given number of items. @@ -130,6 +135,17 @@ DISALLOW_COPY_AND_ASSIGN(EditableComboboxTest); }; +void EditableComboboxTest::SetUp() { + ViewsTestBase::SetUp(); + +#if defined(USE_OZONE) + // TODO(crbug.com/1209477): Wayland bots use Weston with Headless backend that + // sets up XkbKeyboardLayoutEngine differently. When that is fixed, remove the + // workaround below. + ui::WaitUntilLayoutEngineIsReadyForTest(); +#endif +} + void EditableComboboxTest::TearDown() { if (IsMenuOpen()) { combobox_->GetMenuRunnerForTest()->Cancel();
diff --git a/ui/views/controls/textfield/textfield_unittest.cc b/ui/views/controls/textfield/textfield_unittest.cc index 182a40fa..788e8538 100644 --- a/ui/views/controls/textfield/textfield_unittest.cc +++ b/ui/views/controls/textfield/textfield_unittest.cc
@@ -77,6 +77,10 @@ #include "ui/base/cocoa/text_services_context_menu.h" #endif +#if defined(USE_OZONE) +#include "ui/events/ozone/layout/keyboard_layout_engine_test_utils.h" +#endif + namespace views { namespace test { @@ -396,6 +400,13 @@ ui::Clipboard::SetClipboardForCurrentThread( std::make_unique<ui::TestClipboard>()); ViewsTestBase::SetUp(); + +#if defined(USE_OZONE) + // TODO(crbug.com/1209477): Wayland bots use Weston with Headless backend that + // sets up XkbKeyboardLayoutEngine differently. When that is fixed, remove the + // workaround below. + ui::WaitUntilLayoutEngineIsReadyForTest(); +#endif } void TextfieldTest::TearDown() {
diff --git a/ui/webui/resources/cr_components/chromeos/network/network_password_input.html b/ui/webui/resources/cr_components/chromeos/network/network_password_input.html index 61f1bb1..92bca29c 100644 --- a/ui/webui/resources/cr_components/chromeos/network/network_password_input.html +++ b/ui/webui/resources/cr_components/chromeos/network/network_password_input.html
@@ -13,6 +13,15 @@ <dom-module id="network-password-input"> <template> <style include="network-shared"> + :host { + display: block; + } + + :host([allow-error-message]) #input { + --cr-input-error-display: block; + margin-bottom: 0; + } + #container { align-items: center; display: flex; @@ -38,20 +47,22 @@ type="[[getInputType_(showPassword)]]" on-mousedown="onMousedown_" on-touchstart="onMousedown_" - on-keydown="onKeydown_"> + on-keydown="onKeydown_" + invalid="[[invalid]]" + error-message="[[errorMessage]]"> + <template is="dom-if" if="[[!showPolicyIndicator_]]" restamp> + <cr-icon-button id="icon" slot="suffix" + class$="[[getIconClass_(showPassword)]]" + aria-describedby="passwordVisibilityTooltip" + on-click="onShowPasswordTap_" + on-touchend="onShowPasswordTap_"> + </cr-icon-button> + <paper-tooltip id="passwordVisibilityTooltip" for="icon" position="left" + fit-to-visible-bounds role="tooltip"> + [[getShowPasswordTitle_(showPassword)]] + </paper-tooltip> + </template> </cr-input> - <template is="dom-if" if="[[!showPolicyIndicator_]]" restamp> - <cr-icon-button id="icon" slot="suffix" - class$="[[getIconClass_(showPassword)]]" - aria-describedby="passwordVisibilityTooltip" - on-click="onShowPasswordTap_" - on-touchend="onShowPasswordTap_"> - </cr-icon-button> - <paper-tooltip id="passwordVisibilityTooltip" for="icon" position="left" - fit-to-visible-bounds role="tooltip"> - [[getShowPasswordTitle_(showPassword)]] - </paper-tooltip> - </template> <template is="dom-if" if="[[showPolicyIndicator_]]" restamp> <cr-policy-network-indicator-mojo property="[[property]]" tooltip-position="left">
diff --git a/ui/webui/resources/cr_components/chromeos/network/network_password_input.js b/ui/webui/resources/cr_components/chromeos/network/network_password_input.js index a0e28e58..71f0c96 100644 --- a/ui/webui/resources/cr_components/chromeos/network/network_password_input.js +++ b/ui/webui/resources/cr_components/chromeos/network/network_password_input.js
@@ -36,6 +36,28 @@ value: false, }, + invalid: { + type: Boolean, + value: false, + }, + + /** + * Whether an errorMessage can be shown beneath the input. + */ + allowErrorMessage: { + type: Boolean, + value: false, + }, + + /** + * Error message shown beneath input (only shown if allowErrorMessage is + * true). + */ + errorMessage: { + type: String, + value: '', + }, + showPolicyIndicator_: { type: Boolean, value: false,
diff --git a/ui/webui/resources/cr_components/chromeos/network/sim_lock_dialogs.html b/ui/webui/resources/cr_components/chromeos/network/sim_lock_dialogs.html index c2550e18..af6a318d 100644 --- a/ui/webui/resources/cr_components/chromeos/network/sim_lock_dialogs.html +++ b/ui/webui/resources/cr_components/chromeos/network/sim_lock_dialogs.html
@@ -20,6 +20,28 @@ font-weight: 500; margin-bottom: 10px; } + + #enter-pin-description { + margin-bottom: 16px; + } + + .pinEntrySubtext { + font-size: var(--cr-form-field-label-font-size); + font-weight: 400; + margin-top: -10px; + } + + :host([has-error-text_]) .pinEntrySubtext { + color: red; + } + + #changePinOld { + margin-top: 24px; + } + + #unlockPin { + margin-top: 24px; + } </style> <!-- Enter PIN dialog --> <cr-dialog id="enterPinDialog" @@ -27,14 +49,18 @@ close-text="[[i18n('close')]]"> <div slot="title">[[i18n('networkSimEnterPinTitle')]]</div> <div slot="body"> + <div id="enter-pin-description" aria-hidden="true"> + [[i18n('networkSimEnterPinDescription')]] + </div> <network-password-input id="enterPin" value="{{pin_}}" - label="[[i18n('networkSimEnterPin')]]" on-enter="sendEnterPin_" - disabled="[[inProgress_]]"> + disabled="[[inProgress_]]" + invalid="[[hasErrorText_]]" + aria-labeledby="pinEntrySubtext"> </network-password-input> - <div class="dialog-error" aria-live="assertive"> - [[getErrorMsg_(error_, deviceState)]] + <div class="pinEntrySubtext" aria-live="assertive"> + [[getPinEntrySubtext_(error_, deviceState)]] </div> </div> <div slot="button-container"> @@ -42,6 +68,7 @@ [[i18n('cancel')]] </cr-button> <cr-button class="action-button" + aria-describedby="enter-pin-description" on-click="sendEnterPin_" disabled="[[!enterPinEnabled_]]"> [[i18n('networkSimEnter')]] @@ -58,22 +85,26 @@ <network-password-input id="changePinOld" value="{{pin_}}" label="[[i18n('networkSimEnterOldPin')]]" - disabled="[[inProgress_]]"> + disabled="[[inProgress_]]" + invalid="[[isOldPinInvalid_(error_, deviceState)]]" + error-message="[[getOldPinErrorMessage_(error_, deviceState)]]" + allow-error-message> </network-password-input> <network-password-input id="changePinNew1" value="{{pin_new1_}}" label="[[i18n('networkSimEnterNewPin')]]" - disabled="[[inProgress_]]"> + disabled="[[inProgress_]]" + allow-error-message> </network-password-input> <network-password-input id="changePinNew2" value="{{pin_new2_}}" label="[[i18n('networkSimReEnterNewPin')]]" on-enter="sendChangePin_" - disabled="[[inProgress_]]"> + disabled="[[inProgress_]]" + invalid="[[isSecondNewPinInvalid_(error_, deviceState)]]" + error-message="[[getSecondNewPinErrorMessage_(error_, deviceState)]]" + allow-error-message> </network-password-input> - <div class="dialog-error" aria-live="assertive"> - [[getErrorMsg_(error_, deviceState)]] - </div> </div> <div slot="button-container"> <cr-button class="cancel-button" on-click="onCancel_"> @@ -95,12 +126,11 @@ <div slot="body"> <network-password-input id="unlockPin" value="{{pin_}}" - label="[[i18n('networkSimEnterPin')]]" on-enter="sendUnlockPin_" disabled="[[inProgress_]]"> </network-password-input> - <div class="dialog-error" aria-live="assertive"> - [[getErrorMsg_(error_, deviceState)]] + <div class="pinEntrySubtext" aria-live="assertive"> + [[getPinEntrySubtext_(error_, deviceState)]] </div> </div> <div slot="button-container">
diff --git a/ui/webui/resources/cr_components/chromeos/network/sim_lock_dialogs.js b/ui/webui/resources/cr_components/chromeos/network/sim_lock_dialogs.js index c6a33a48..e69e569a 100644 --- a/ui/webui/resources/cr_components/chromeos/network/sim_lock_dialogs.js +++ b/ui/webui/resources/cr_components/chromeos/network/sim_lock_dialogs.js
@@ -73,6 +73,13 @@ observer: 'updateSubmitButtonEnabled_', }, + /** @private */ + hasErrorText_: { + type: Boolean, + computed: 'computeHasErrorText_(error_, deviceState)', + reflectToAttribute: true, + }, + /** * Error, if defined, that error_ should be set as the next time deviceState * updates. @@ -476,7 +483,11 @@ if (this.$.enterPinDialog.open) { this.$.enterPin.focus(); } else if (this.$.changePinDialog.open) { - this.$.changePinOld.focus(); + if (this.isSecondNewPinInvalid_()) { + this.$.changePinNew2.focus(); + } else { + this.$.changePinOld.focus(); + } } else if (this.$.unlockPinDialog.open) { this.$.unlockPin.focus(); } else if (this.$.unlockPukDialog.open) { @@ -526,7 +537,10 @@ return true; }, - /** @private */ + /** + * @return {string} + * @private + */ getErrorMsg_() { if (this.error_ === ErrorType.NONE) { return ''; @@ -561,5 +575,66 @@ return this.i18n(errorStringId, retriesLeft); }, + /** + * @return {boolean} + * @private + */ + computeHasErrorText_() { + return !!this.getErrorMsg_(); + }, + + /** + * @return {string} + * @private + */ + getPinEntrySubtext_() { + const errorMessage = this.getErrorMsg_(); + if (errorMessage) { + return errorMessage; + } + + return this.i18n('networkSimEnterPinSubtext'); + }, + + /** + * @return {boolean} + * @private + */ + isOldPinInvalid_() { + return this.error_ === ErrorType.INCORRECT_PIN || + this.error_ === ErrorType.INVALID_PIN; + }, + + /** + * @return {string} + * @private + */ + getOldPinErrorMessage_() { + if (this.isOldPinInvalid_()) { + return this.getErrorMsg_(); + } + + return ''; + }, + + /** + * @return {boolean} + * @private + */ + isSecondNewPinInvalid_() { + return this.error_ === ErrorType.MISMATCHED_PIN; + }, + + /** + * @return {string} + * @private + */ + getSecondNewPinErrorMessage_() { + if (this.isSecondNewPinInvalid_()) { + return this.getErrorMsg_(); + } + + return ''; + }, }); })(); \ No newline at end of file
diff --git a/ui/webui/resources/cr_elements/cr_input/cr_input.html b/ui/webui/resources/cr_elements/cr_input/cr_input.html index a20592e1..3beffd1 100644 --- a/ui/webui/resources/cr_elements/cr_input/cr_input.html +++ b/ui/webui/resources/cr_elements/cr_input/cr_input.html
@@ -152,7 +152,7 @@ </div> <slot name="suffix"></slot> </div> - <div id="error">[[displayErrorMessage_]]</div> + <div id="error" aria-live="assertive">[[displayErrorMessage_]]</div> </template> <script src="cr_input.js"></script> </dom-module>