diff --git a/AUTHORS b/AUTHORS index 1f2536f..638c9492 100644 --- a/AUTHORS +++ b/AUTHORS
@@ -493,6 +493,7 @@ Jinsong Fan <fanjinsong@sogou-inc.com> Jinsong Fan <jinsong.van@gmail.com> Jinwoo Song <jinwoo7.song@samsung.com> +Jinyoung Hur <hur.ims@navercorp.com> Jinyoung Hur <hurims@gmail.com> Jitendra Kumar Sahoo <jitendra.ks@samsung.com> Joachim Bauch <jbauch@webrtc.org>
diff --git a/DEPS b/DEPS index 19b4dbb..4f2ac01 100644 --- a/DEPS +++ b/DEPS
@@ -199,11 +199,11 @@ # 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': '20f1b3462878a98125aa03d4aa74b955fcf4acf3', + 'skia_revision': 'b64da3907f7638c87967d60cd250a6b02c914251', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. - 'v8_revision': 'ee505470971ec0c0a00a0c3a0be51f6877475aff', + 'v8_revision': '804d2150372f0e8a19996e7152d984898e8cb85d', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling swarming_client # and whatever else without interference from each other. @@ -219,7 +219,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling PDFium # and whatever else without interference from each other. - 'pdfium_revision': 'ba1c65b08f2da6532811077fd51ffcfde6b92874', + 'pdfium_revision': '0a1e0410572e3c9f378c426e9301f878798b3ab0', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling BoringSSL # and whatever else without interference from each other. @@ -250,7 +250,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': 'f6be92767d1d002f5e90a4673ee4e6d4f1e1744f', + 'freetype_revision': '84b3616c94f48726c596ead4150218d4431b3412', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling freetype # and whatever else without interference from each other. @@ -274,7 +274,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling devtools-frontend # and whatever else without interference from each other. - 'devtools_frontend_revision': '9eeb00431109dd98382aa95f88961edb51ee7300', + 'devtools_frontend_revision': '0096403e47fb3159757415c943e63826b228a192', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libprotobuf-mutator # and whatever else without interference from each other. @@ -326,7 +326,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': 'b31cd871ad1000a56302409b62d76e079f8a0b46', + 'dawn_revision': '155241b665f8305d54145ca460e0b8cebe888336', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. @@ -565,7 +565,7 @@ }, 'src/ios/third_party/material_components_ios/src': { - 'url': Var('chromium_git') + '/external/github.com/material-components/material-components-ios.git' + '@' + 'f03c0a36e0fcc5ded1f7ce51b0a0589224689d01', + 'url': Var('chromium_git') + '/external/github.com/material-components/material-components-ios.git' + '@' + 'e946f7e093404de560e8f63a76921e1bf7e2b1f6', 'condition': 'checkout_ios', }, @@ -1615,7 +1615,7 @@ Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'), 'src-internal': { - 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@e35dcb0515eb3f0260d36cc3534bd49cbc33f116', + 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@7bbf434aef522ac6e4a1cc0002aa61d698399549', 'condition': 'checkout_src_internal', },
diff --git a/ash/login/ui/login_password_view.cc b/ash/login/ui/login_password_view.cc index 8dce8d65..ee4dc321d 100644 --- a/ash/login/ui/login_password_view.cc +++ b/ash/login/ui/login_password_view.cc
@@ -253,7 +253,6 @@ if (on_blur_closure_) on_blur_closure_.Run(); views::Textfield::OnBlur(); - SetPlaceholderText(prepared_placeholder_text_); } // views::Textfield: @@ -261,7 +260,6 @@ if (on_focus_closure_) on_focus_closure_.Run(); views::Textfield::OnFocus(); - SetPlaceholderText(base::string16()); } void AboutToRequestFocusFromTabTraversal(bool reverse) override { @@ -272,10 +270,6 @@ SelectAll(/*reversed=*/false); } - void set_prepared_placeholder_text(const base::string16& text) { - prepared_placeholder_text_ = text; - } - void UpdateFontListAndCursor() { SetCursorEnabled(GetText().empty()); // We do not want the cursor to be too big, therefore the hidden font is @@ -321,9 +315,6 @@ base::RepeatingClosure on_focus_closure_; base::RepeatingClosure on_blur_closure_; base::RepeatingClosure on_tab_focus_closure_; - - // Placeholder text to set when focus gets lost. - base::string16 prepared_placeholder_text_; }; class LoginPasswordView::EasyUnlockIcon : public views::Button { @@ -737,7 +728,7 @@ void LoginPasswordView::SetPlaceholderText( const base::string16& placeholder_text) { - textfield_->set_prepared_placeholder_text(placeholder_text); + textfield_->SetPlaceholderText(placeholder_text); } void LoginPasswordView::SetReadOnly(bool read_only) {
diff --git a/base/BUILD.gn b/base/BUILD.gn index 7f2bf59..7be3ca124 100644 --- a/base/BUILD.gn +++ b/base/BUILD.gn
@@ -3517,6 +3517,7 @@ "callback_unittest.nc", "containers/buffer_iterator_unittest.nc", "containers/checked_iterators_unittest.nc", + "containers/contains_unittest.nc", "containers/span_unittest.nc", "debug/crash_logging_unittest.nc", "memory/checked_ptr_unittest.nc",
diff --git a/base/allocator/partition_allocator/oom.h b/base/allocator/partition_allocator/oom.h index 916ef12..6b9d042 100644 --- a/base/allocator/partition_allocator/oom.h +++ b/base/allocator/partition_allocator/oom.h
@@ -16,7 +16,7 @@ namespace { // The crash is generated in a NOINLINE function so that we can classify the // crash as an OOM solely by analyzing the stack trace. -NOINLINE void OnNoMemory(size_t size) { +[[noreturn]] NOINLINE void OnNoMemory(size_t size) { base::internal::RunPartitionAllocOomCallback(); base::internal::OnNoMemoryInternal(size); IMMEDIATE_CRASH();
diff --git a/base/allocator/partition_allocator/partition_oom.cc b/base/allocator/partition_allocator/partition_oom.cc index 9636728..9befc3f 100644 --- a/base/allocator/partition_allocator/partition_oom.cc +++ b/base/allocator/partition_allocator/partition_oom.cc
@@ -20,7 +20,13 @@ NOINLINE void PartitionOutOfMemoryWithLotsOfUncommitedPages(size_t size) { OOM_CRASH(size); } -#endif + +[[noreturn]] NOINLINE void PartitionOutOfMemoryWithLargeVirtualSize( + size_t virtual_size) { + OOM_CRASH(virtual_size); +} + +#endif // !defined(ARCH_CPU_64_BITS) } // namespace internal } // namespace base
diff --git a/base/allocator/partition_allocator/partition_oom.h b/base/allocator/partition_allocator/partition_oom.h index 466fe10..7cf1ec5 100644 --- a/base/allocator/partition_allocator/partition_oom.h +++ b/base/allocator/partition_allocator/partition_oom.h
@@ -23,10 +23,14 @@ // g_oom_handling_function is invoked when PartitionAlloc hits OutOfMemory. extern OomFunction g_oom_handling_function; -BASE_EXPORT NOINLINE void PartitionExcessiveAllocationSize(size_t size); +[[noreturn]] BASE_EXPORT NOINLINE void PartitionExcessiveAllocationSize( + size_t size); #if !defined(ARCH_CPU_64_BITS) -NOINLINE void PartitionOutOfMemoryWithLotsOfUncommitedPages(size_t size); +[[noreturn]] NOINLINE void PartitionOutOfMemoryWithLotsOfUncommitedPages( + size_t size); +[[noreturn]] NOINLINE void PartitionOutOfMemoryWithLargeVirtualSize( + size_t virtual_size); #endif } // namespace internal
diff --git a/base/allocator/partition_allocator/partition_root.cc b/base/allocator/partition_allocator/partition_root.cc index cc0b8cc..e7abd126 100644 --- a/base/allocator/partition_allocator/partition_root.cc +++ b/base/allocator/partition_allocator/partition_root.cc
@@ -310,17 +310,38 @@ } // namespace internal template <bool thread_safe> -NOINLINE void PartitionRoot<thread_safe>::OutOfMemory(size_t size) { +[[noreturn]] NOINLINE void PartitionRoot<thread_safe>::OutOfMemory( + size_t size) { #if !defined(ARCH_CPU_64_BITS) + size_t virtual_address_space_size = + total_size_of_super_pages.load(std::memory_order_relaxed) + + total_size_of_direct_mapped_pages.load(std::memory_order_relaxed); + size_t uncommitted_size = + virtual_address_space_size - + total_size_of_committed_pages.load(std::memory_order_relaxed); + // Check whether this OOM is due to a lot of super pages that are allocated // but not committed, probably due to http://crbug.com/421387. - // - if (total_size_of_super_pages.load(std::memory_order_relaxed) + - total_size_of_direct_mapped_pages.load(std::memory_order_relaxed) - - total_size_of_committed_pages.load(std::memory_order_relaxed) > - kReasonableSizeOfUnusedPages) { + if (uncommitted_size > kReasonableSizeOfUnusedPages) { internal::PartitionOutOfMemoryWithLotsOfUncommitedPages(size); } + + constexpr size_t kReasonableVirtualSize = +#if defined(OS_WIN) + // 1GiB on Windows, as the entire address space is typically 2GiB. + 1024 * 1024 * 1024; +#else + // 1.5GiB elsewhere, since address space is typically 3GiB. + (1024 + 512) * 1024 * 1024; +#endif + if (virtual_address_space_size > kReasonableVirtualSize) { + internal::PartitionOutOfMemoryWithLargeVirtualSize( + virtual_address_space_size); + } + + // Make the virtual size visible to crash reports all the time. + base::debug::Alias(&virtual_address_space_size); + #endif if (internal::g_oom_handling_function) (*internal::g_oom_handling_function)(size);
diff --git a/base/allocator/partition_allocator/partition_root.h b/base/allocator/partition_allocator/partition_root.h index 98bd28b..342941eb 100644 --- a/base/allocator/partition_allocator/partition_root.h +++ b/base/allocator/partition_allocator/partition_root.h
@@ -246,7 +246,7 @@ PageAccessibilityDisposition accessibility_disposition) EXCLUSIVE_LOCKS_REQUIRED(lock_); - NOINLINE void OutOfMemory(size_t size); + [[noreturn]] NOINLINE void OutOfMemory(size_t size); // Returns a pointer aligned on |alignment|, or nullptr. //
diff --git a/base/allocator/partition_allocator/partition_stats.h b/base/allocator/partition_allocator/partition_stats.h index 961b360..657a988 100644 --- a/base/allocator/partition_allocator/partition_stats.h +++ b/base/allocator/partition_allocator/partition_stats.h
@@ -28,6 +28,8 @@ uint64_t cache_fill_hits; uint64_t cache_fill_misses; // Object too large. + uint64_t batch_fill_count; // Number of central allocator requests. + // Memory cost: uint64_t bucket_total_memory; uint64_t metadata_overhead;
diff --git a/base/allocator/partition_allocator/thread_cache.cc b/base/allocator/partition_allocator/thread_cache.cc index 317373f..9621da0 100644 --- a/base/allocator/partition_allocator/thread_cache.cc +++ b/base/allocator/partition_allocator/thread_cache.cc
@@ -301,6 +301,8 @@ // clearing which would greatly increase calls to the central allocator. (3) // tries to keep memory usage low. So clearing half of the bucket, and filling // a quarter of it are sensible defaults. + INCREMENT_COUNTER(stats_.batch_fill_count); + Bucket& bucket = buckets_[bucket_index]; int count = bucket.limit / kBatchFillRatio; @@ -388,6 +390,8 @@ stats_.cache_fill_hits = 0; stats_.cache_fill_misses = 0; + stats_.batch_fill_count = 0; + stats_.bucket_total_memory = 0; stats_.metadata_overhead = 0; @@ -407,9 +411,11 @@ stats->cache_fill_hits += stats_.cache_fill_hits; stats->cache_fill_misses += stats_.cache_fill_misses; - for (size_t i = 0; i < kBucketCount; i++) { + stats->batch_fill_count += stats_.batch_fill_count; + + for (const Bucket& bucket : buckets_) { stats->bucket_total_memory += - buckets_[i].count * static_cast<size_t>(buckets_[i].slot_size); + bucket.count * static_cast<size_t>(bucket.slot_size); } stats->metadata_overhead += sizeof(*this); }
diff --git a/base/allocator/partition_allocator/thread_cache.h b/base/allocator/partition_allocator/thread_cache.h index 216a87d..225550f 100644 --- a/base/allocator/partition_allocator/thread_cache.h +++ b/base/allocator/partition_allocator/thread_cache.h
@@ -257,6 +257,8 @@ friend class ThreadCacheRegistry; friend class ThreadCacheTest; + FRIEND_TEST_ALL_PREFIXES(ThreadCacheTest, Simple); + FRIEND_TEST_ALL_PREFIXES(ThreadCacheTest, MultipleObjectsCachedPerBucket); FRIEND_TEST_ALL_PREFIXES(ThreadCacheTest, LargeAllocationsAreNotCached); FRIEND_TEST_ALL_PREFIXES(ThreadCacheTest, MultipleThreadCaches); FRIEND_TEST_ALL_PREFIXES(ThreadCacheTest, RecordStats);
diff --git a/base/allocator/partition_allocator/thread_cache_unittest.cc b/base/allocator/partition_allocator/thread_cache_unittest.cc index c05ef20..627ed4ad 100644 --- a/base/allocator/partition_allocator/thread_cache_unittest.cc +++ b/base/allocator/partition_allocator/thread_cache_unittest.cc
@@ -121,12 +121,13 @@ }; TEST_F(ThreadCacheTest, Simple) { - void* ptr = g_root->Alloc(kSmallSize, ""); - ASSERT_TRUE(ptr); - // There is a cache. auto* tcache = g_root->thread_cache_for_testing(); EXPECT_TRUE(tcache); + DeltaCounter batch_fill_counter{tcache->stats_.batch_fill_count}; + + void* ptr = g_root->Alloc(kSmallSize, ""); + ASSERT_TRUE(ptr); uint16_t index = PartitionRoot<ThreadSafe>::SizeToBucketIndex(kSmallSize); EXPECT_EQ(kFillCountForSmallBucket - 1, @@ -141,6 +142,8 @@ // Allocated from the thread cache. EXPECT_EQ(kFillCountForSmallBucket - 1, tcache->bucket_count_for_testing(index)); + + EXPECT_EQ(1u, batch_fill_counter.Delta()); } TEST_F(ThreadCacheTest, InexactSizeMatch) { @@ -167,11 +170,15 @@ } TEST_F(ThreadCacheTest, MultipleObjectsCachedPerBucket) { + auto* tcache = g_root->thread_cache_for_testing(); + DeltaCounter batch_fill_counter{tcache->stats_.batch_fill_count}; size_t bucket_index = FillThreadCacheAndReturnIndex(kMediumSize, kFillCountForMediumBucket + 2); - auto* tcache = g_root->thread_cache_for_testing(); EXPECT_EQ(2 * kFillCountForMediumBucket, tcache->bucket_count_for_testing(bucket_index)); + // 2 batches, since there were more than |kFillCountForMediumBucket| + // allocations. + EXPECT_EQ(2u, batch_fill_counter.Delta()); } TEST_F(ThreadCacheTest, ObjectsCachedCountIsLimited) {
diff --git a/base/android/java/src/org/chromium/base/metrics/RecordHistogram.java b/base/android/java/src/org/chromium/base/metrics/RecordHistogram.java index 66d3690..ed60e3e 100644 --- a/base/android/java/src/org/chromium/base/metrics/RecordHistogram.java +++ b/base/android/java/src/org/chromium/base/metrics/RecordHistogram.java
@@ -238,7 +238,7 @@ * @param sample sample to be recorded, expected to fall in range {@code [0, max)} * @param max the smallest value counted in the overflow bucket, shouldn't be larger than 100 */ - private static void recordExactLinearHistogram(String name, int sample, int max) { + public static void recordExactLinearHistogram(String name, int sample, int max) { // Range [0, 1) is counted in the underflow bucket. The first "real" bucket starts at 1. final int min = 1; // One extra is added for the overflow bucket.
diff --git a/base/containers/contains.h b/base/containers/contains.h index 63120f8..ec0a890 100644 --- a/base/containers/contains.h +++ b/base/containers/contains.h
@@ -8,7 +8,6 @@ #include <type_traits> #include <utility> -#include "base/functional/identity.h" #include "base/ranges/algorithm.h" #include "base/ranges/ranges.h" #include "base/template_util.h" @@ -17,6 +16,14 @@ namespace internal { +// Small helper to detect whether a given type has a nested `key_type` typedef. +// Used below to catch misuses of the API for associative containers. +template <typename T, typename SFINAE = void> +struct HasKeyType : std::false_type {}; + +template <typename T> +struct HasKeyType<T, void_t<typename T::key_type>> : std::true_type {}; + // Probe whether a `contains` member function exists and return the result of // `container.contains(value)` if this is a valid expression. This is the // highest priority option. @@ -51,14 +58,18 @@ } // Generic fallback option, using a linear search over `container` to find -// `value`. Has the lowest priority. -template <typename Container, typename Value, typename Proj = identity> +// `value`. Has the lowest priority. This will not compile for associative +// containers, as this likely is a performance bug. +template <typename Container, typename Value> constexpr bool ContainsImpl(const Container& container, const Value& value, - priority_tag<0>, - Proj proj = {}) { - return ranges::find(container, value, std::move(proj)) != - ranges::end(container); + priority_tag<0>) { + static_assert( + !HasKeyType<Container>::value, + "Error: About to perform linear search on an associative container. " + "Either use a more generic comparator (e.g. std::less<>) or, if a linear " + "search is desired, provide an explicit projection parameter."); + return ranges::find(container, value) != ranges::end(container); } } // namespace internal @@ -78,8 +89,8 @@ constexpr bool Contains(const Container& container, const Value& value, Proj proj) { - return internal::ContainsImpl(container, value, internal::priority_tag<0>(), - std::move(proj)); + return ranges::find(container, value, std::move(proj)) != + ranges::end(container); } } // namespace base
diff --git a/base/containers/contains_unittest.cc b/base/containers/contains_unittest.cc index f3b9164b..66d2519 100644 --- a/base/containers/contains_unittest.cc +++ b/base/containers/contains_unittest.cc
@@ -8,6 +8,8 @@ #include <string> #include "base/containers/flat_set.h" +#include "base/functional/identity.h" +#include "base/strings/string_piece.h" #include "base/strings/string_util.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -33,6 +35,14 @@ EXPECT_FALSE(Contains(allowed_chars, 0, &ToLowerASCII<char>)); } +TEST(ContainsTest, GenericSetContainsWithProjection) { + constexpr StringPiece kFoo = "foo"; + std::set<std::string> set = {"foo", "bar", "baz"}; + + // Opt into a linear search by explicitly providing a projection: + EXPECT_TRUE(Contains(set, kFoo, identity{})); +} + TEST(ContainsTest, ContainsWithFindAndNpos) { std::string str = "abcd";
diff --git a/base/containers/contains_unittest.nc b/base/containers/contains_unittest.nc new file mode 100644 index 0000000..8931ad6 --- /dev/null +++ b/base/containers/contains_unittest.nc
@@ -0,0 +1,33 @@ +// Copyright 2020 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. + +// This is a "No Compile Test" suite. +// https://dev.chromium.org/developers/testing/no-compile-tests + +#include "base/containers/contains.h" + +#include <set> + +#include "base/strings/string_piece.h" + +namespace base { + +// The following code would perform a linear search through the set which is +// likely unexpected and not intended. This is because the expression +// `set.find(kFoo)` is ill-formed, since there is no implimit conversion from +// StringPiece to `std::string`. This means Contains would fall back to the +// general purpose `base::ranges::find(set, kFoo)` linear search. +// To fix this clients can either use a more generic comparator like std::less<> +// (in this case `set.find()` accepts any type that is comparable to a +// std::string), or pass an explicit projection parameter to Contains, at which +// point it will always perform a linear search. +#if defined(NCTEST_CONTAINS_UNEXPECTED_LINEAR_SEARCH) // [r"Error: About to perform linear search on an associative container."] +void WontCompile() { + constexpr StringPiece kFoo = "foo"; + std::set<std::string> set = {"foo", "bar", "baz"}; + Contains(set, kFoo); +} +#endif + +} // namespace base
diff --git a/base/memory/discardable_shared_memory.cc b/base/memory/discardable_shared_memory.cc index c885b30..453f29ea 100644 --- a/base/memory/discardable_shared_memory.cc +++ b/base/memory/discardable_shared_memory.cc
@@ -8,6 +8,7 @@ #include <algorithm> +#include "base/allocator/partition_allocator/page_allocator.h" #include "base/atomicops.h" #include "base/bits.h" #include "base/feature_list.h" @@ -460,6 +461,35 @@ return true; } +void DiscardableSharedMemory::ReleaseMemoryIfPossible(size_t offset, + size_t length) { +#if defined(OS_POSIX) && !defined(OS_NACL) +// Linux and Android provide MADV_REMOVE which is preferred as it has a +// behavior that can be verified in tests. Other POSIX flavors (MacOSX, BSDs), +// provide MADV_FREE which has the same result but memory is purged lazily. +#if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID) +#define MADV_PURGE_ARGUMENT MADV_REMOVE +#elif defined(OS_APPLE) +// MADV_FREE_REUSABLE is similar to MADV_FREE, but also marks the pages with the +// reusable bit, which allows both Activity Monitor and memory-infra to +// correctly track the pages. +#define MADV_PURGE_ARGUMENT MADV_FREE_REUSABLE +#else // defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID) +#define MADV_PURGE_ARGUMENT MADV_FREE +#endif // defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID) + // Advise the kernel to remove resources associated with purged pages. + // Subsequent accesses of memory pages will succeed, but might result in + // zero-fill-on-demand pages. + if (madvise(static_cast<char*>(shared_memory_mapping_.memory()) + offset, + length, MADV_PURGE_ARGUMENT)) { + DPLOG(ERROR) << "madvise() failed"; + } +#else // defined(OS_POSIX) && !defined(OS_NACL) + DiscardSystemPages( + static_cast<char*>(shared_memory_mapping_.memory()) + offset, length); +#endif // defined(OS_POSIX) && !defined(OS_NACL) +} + bool DiscardableSharedMemory::IsMemoryResident() const { DCHECK(shared_memory_mapping_.IsValid());
diff --git a/base/memory/discardable_shared_memory.h b/base/memory/discardable_shared_memory.h index 1c92c8c..c5c805a 100644 --- a/base/memory/discardable_shared_memory.h +++ b/base/memory/discardable_shared_memory.h
@@ -116,6 +116,13 @@ // different process. Returns NULL time if purged. Time last_known_usage() const { return last_known_usage_; } + // Releases any allocated pages in the specified range, if supported by the + // platform. Address space in the specified range continues to be reserved. + // The memory is not guaranteed to be released immediately. + // |offset| and |length| are both in bytes. |offset| and |length| must both be + // page aligned. + void ReleaseMemoryIfPossible(size_t offset, size_t length); + // This returns true and sets |last_known_usage_| to 0 if // DiscardableSharedMemory object was successfully purged. Purging can fail // for two reasons; object might be locked or our last known usage timestamp
diff --git a/base/trace_event/malloc_dump_provider.cc b/base/trace_event/malloc_dump_provider.cc index 00fca84..a867123f 100644 --- a/base/trace_event/malloc_dump_provider.cc +++ b/base/trace_event/malloc_dump_provider.cc
@@ -227,6 +227,8 @@ dump->AddScalar("cache_fill_hits", "scalar", stats.cache_fill_hits); dump->AddScalar("cache_fill_misses", "scalar", stats.cache_fill_misses); + dump->AddScalar("batch_fill_count", "scalar", stats.batch_fill_count); + dump->AddScalar("size", "bytes", stats.bucket_total_memory); dump->AddScalar("metadata_overhead", "bytes", stats.metadata_overhead); }
diff --git a/base/trace_event/process_memory_dump.cc b/base/trace_event/process_memory_dump.cc index 27338159..2009f95 100644 --- a/base/trace_event/process_memory_dump.cc +++ b/base/trace_event/process_memory_dump.cc
@@ -81,8 +81,9 @@ } // static -size_t ProcessMemoryDump::CountResidentBytes(void* start_address, - size_t mapped_size) { +base::Optional<size_t> ProcessMemoryDump::CountResidentBytes( + void* start_address, + size_t mapped_size) { const size_t page_size = GetSystemPageSize(); const uintptr_t start_pointer = reinterpret_cast<uintptr_t>(start_address); DCHECK_EQ(0u, start_pointer % page_size); @@ -160,8 +161,8 @@ DCHECK(!failure); if (failure) { - total_resident_pages = 0; LOG(ERROR) << "CountResidentBytes failed. The resident size is invalid"; + return base::nullopt; } return total_resident_pages; }
diff --git a/base/trace_event/process_memory_dump.h b/base/trace_event/process_memory_dump.h index c897387..e26442a 100644 --- a/base/trace_event/process_memory_dump.h +++ b/base/trace_event/process_memory_dump.h
@@ -76,7 +76,8 @@ // |start_address| and |mapped_size|. |mapped_size| is specified in bytes. The // value returned is valid only if the given range is currently mmapped by the // process. The |start_address| must be page-aligned. - static size_t CountResidentBytes(void* start_address, size_t mapped_size); + static base::Optional<size_t> CountResidentBytes(void* start_address, + size_t mapped_size); // The same as above, but the given mapped range should belong to the // shared_memory's mapped region.
diff --git a/base/trace_event/process_memory_dump_unittest.cc b/base/trace_event/process_memory_dump_unittest.cc index 64c98ef..903f9c9 100644 --- a/base/trace_event/process_memory_dump_unittest.cc +++ b/base/trace_event/process_memory_dump_unittest.cc
@@ -486,17 +486,20 @@ const size_t size1 = 5 * page_size; void* memory1 = Map(size1); memset(memory1, 0, size1); - size_t res1 = ProcessMemoryDump::CountResidentBytes(memory1, size1); - ASSERT_EQ(res1, size1); + base::Optional<size_t> res1 = + ProcessMemoryDump::CountResidentBytes(memory1, size1); + ASSERT_TRUE(res1.has_value()); + ASSERT_EQ(res1.value(), size1); Unmap(memory1, size1); // Allocate a large memory segment (> 8Mib). const size_t kVeryLargeMemorySize = 15 * 1024 * 1024; void* memory2 = Map(kVeryLargeMemorySize); memset(memory2, 0, kVeryLargeMemorySize); - size_t res2 = + base::Optional<size_t> res2 = ProcessMemoryDump::CountResidentBytes(memory2, kVeryLargeMemorySize); - ASSERT_EQ(res2, kVeryLargeMemorySize); + ASSERT_TRUE(res2.has_value()); + ASSERT_EQ(res2.value(), kVeryLargeMemorySize); Unmap(memory2, kVeryLargeMemorySize); }
diff --git a/build/android/gradle/generate_gradle.py b/build/android/gradle/generate_gradle.py index eb960259..80d0b0a 100755 --- a/build/android/gradle/generate_gradle.py +++ b/build/android/gradle/generate_gradle.py
@@ -578,13 +578,6 @@ _TemplatePath(target_type.split('_')[0]), variables) -def _IsTestDir(path): - return ('javatests/' in path or - 'junit/' in path or - 'test/' in path or - 'testing/' in path) - - # Example: //chrome/android:monochrome def _GetNative(relative_func, target_names): """Returns an object containing native c++ sources list and its included path @@ -638,8 +631,11 @@ res_dirs = sorted(generator.processed_res_dirs) def Relativize(paths): return _RebasePath(paths, os.path.join(gradle_output_dir, _MODULE_ALL)) - main_java_dirs = [d for d in java_dirs if not _IsTestDir(d)] - test_java_dirs = [d for d in java_dirs if _IsTestDir(d)] + + # As after clank modularization, the java and javatests code will live side by + # side in the same module, we will list both of them in the main target here. + main_java_dirs = [d for d in java_dirs if 'junit/' not in d] + junit_test_java_dirs = [d for d in java_dirs if 'junit/' in d] variables['main'] = { 'android_manifest': Relativize(_DEFAULT_ANDROID_MANIFEST_PATH), 'java_dirs': Relativize(main_java_dirs), @@ -648,7 +644,7 @@ 'res_dirs': Relativize(res_dirs), } variables['android_test'] = [{ - 'java_dirs': Relativize(test_java_dirs), + 'java_dirs': Relativize(junit_test_java_dirs), 'java_excludes': ['**/*.java'], }] if native_targets:
diff --git a/build/config/BUILDCONFIG.gn b/build/config/BUILDCONFIG.gn index 093a94b3..d8eb6546 100644 --- a/build/config/BUILDCONFIG.gn +++ b/build/config/BUILDCONFIG.gn
@@ -274,8 +274,8 @@ # - is_mac is set only for desktop Mac. It is not set on iOS. # - is_posix is true for mac and any Unix-like system (basically everything # except Fuchsia and Windows). -# - is_linux is true for desktop Linux and ChromeOS, but not Android (which is -# generally too different despite being based on the Linux kernel). +# - is_linux is true for desktop Linux, but not for ChromeOS nor Android (which +# is generally too different despite being based on the Linux kernel). # # Do not add more is_* variants here for random lesser-used Unix systems like # aix or one of the BSDs. If you need to check these, just check the
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1 index 3f020ec..77f3645c 100644 --- a/build/fuchsia/linux.sdk.sha1 +++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@ -0.20201216.3.1 +0.20201217.1.1
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1 index 3f020ec..77f3645c 100644 --- a/build/fuchsia/mac.sdk.sha1 +++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@ -0.20201216.3.1 +0.20201217.1.1
diff --git a/cc/metrics/compositor_frame_reporter.cc b/cc/metrics/compositor_frame_reporter.cc index c529919c..9392f0a 100644 --- a/cc/metrics/compositor_frame_reporter.cc +++ b/cc/metrics/compositor_frame_reporter.cc
@@ -75,6 +75,102 @@ } } +// Returns the name of the event dispatch breakdown of EventLatency histograms +// between `start_stage` and `end_stage`. +constexpr const char* GetEventLatencyDispatchBreakdownName( + EventMetrics::DispatchStage start_stage, + EventMetrics::DispatchStage end_stage) { + switch (start_stage) { + case EventMetrics::DispatchStage::kGenerated: + DCHECK_EQ(end_stage, + EventMetrics::DispatchStage::kArrivedInRendererCompositor); + return "GenerationToRendererCompositor"; + case EventMetrics::DispatchStage::kArrivedInRendererCompositor: + switch (end_stage) { + case EventMetrics::DispatchStage::kRendererCompositorStarted: + return "RendererCompositorQueueingDelay"; + case EventMetrics::DispatchStage::kRendererMainStarted: + return "RendererCompositorToMain"; + default: + NOTREACHED(); + return nullptr; + } + case EventMetrics::DispatchStage::kRendererCompositorStarted: + DCHECK_EQ(end_stage, + EventMetrics::DispatchStage::kRendererCompositorFinished); + return "RendererCompositorProcessing"; + case EventMetrics::DispatchStage::kRendererCompositorFinished: + DCHECK_EQ(end_stage, EventMetrics::DispatchStage::kRendererMainStarted); + return "RendererCompositorToMain"; + case EventMetrics::DispatchStage::kRendererMainStarted: + DCHECK_EQ(end_stage, EventMetrics::DispatchStage::kRendererMainFinished); + return "RendererMainProcessing"; + case EventMetrics::DispatchStage::kRendererMainFinished: + NOTREACHED(); + return nullptr; + } +} + +// Returns the name of EventLatency breakdown between `dispatch_stage` and +// `compositor_stage`. +constexpr const char* GetEventLatencyDispatchToCompositorBreakdownName( + EventMetrics::DispatchStage dispatch_stage, + CompositorFrameReporter::StageType compositor_stage) { + switch (dispatch_stage) { + case EventMetrics::DispatchStage::kRendererCompositorFinished: + switch (compositor_stage) { + case CompositorFrameReporter::StageType:: + kBeginImplFrameToSendBeginMainFrame: + return "RendererCompositorFinishedToBeginImplFrame"; + case CompositorFrameReporter::StageType::kSendBeginMainFrameToCommit: + return "RendererCompositorFinishedToSendBeginMainFrame"; + case CompositorFrameReporter::StageType::kCommit: + return "RendererCompositorFinishedToCommit"; + case CompositorFrameReporter::StageType::kEndCommitToActivation: + return "RendererCompositorFinishedToEndCommit"; + case CompositorFrameReporter::StageType::kActivation: + return "RendererCompositorFinishedToActivation"; + case CompositorFrameReporter::StageType:: + kEndActivateToSubmitCompositorFrame: + return "RendererCompositorFinishedToEndActivate"; + case CompositorFrameReporter::StageType:: + kSubmitCompositorFrameToPresentationCompositorFrame: + return "RendererCompositorFinishedToSubmitCompositorFrame"; + default: + NOTREACHED(); + return nullptr; + } + break; + case EventMetrics::DispatchStage::kRendererMainFinished: + switch (compositor_stage) { + case CompositorFrameReporter::StageType:: + kBeginImplFrameToSendBeginMainFrame: + return "RendererMainFinishedToBeginImplFrame"; + case CompositorFrameReporter::StageType::kSendBeginMainFrameToCommit: + return "RendererMainFinishedToSendBeginMainFrame"; + case CompositorFrameReporter::StageType::kCommit: + return "RendererMainFinishedToCommit"; + case CompositorFrameReporter::StageType::kEndCommitToActivation: + return "RendererMainFinishedToEndCommit"; + case CompositorFrameReporter::StageType::kActivation: + return "RendererMainFinishedToActivation"; + case CompositorFrameReporter::StageType:: + kEndActivateToSubmitCompositorFrame: + return "RendererMainFinishedToEndActivate"; + case CompositorFrameReporter::StageType:: + kSubmitCompositorFrameToPresentationCompositorFrame: + return "RendererMainFinishedToSubmitCompositorFrame"; + default: + NOTREACHED(); + return nullptr; + } + break; + default: + NOTREACHED(); + return nullptr; + } +} + // Names for CompositorFrameReporter::StageType, which should be updated in case // of changes to the enum. constexpr const char* GetStageName(int stage_type_index, @@ -905,6 +1001,11 @@ } void CompositorFrameReporter::ReportEventLatencyTraceEvents() const { + // TODO(mohsen): This function is becoming large and there is concerns about + // having this in the compositor critical path. crbug.com/1072740 is + // considering doing the reporting off-thread, but as a short-term solution, + // we should investigate whether we can skip this function entirely if tracing + // is off and whether that has any positive impact or not. for (const auto& event_metrics : events_metrics_) { const base::TimeTicks generated_timestamp = event_metrics->GetDispatchStageTimestamp( @@ -915,30 +1016,68 @@ "cc,input", "EventLatency", trace_id, generated_timestamp, "event", event_metrics->GetTypeName()); - // Find the first stage that happens after the event's arrival in the - // browser. - auto stage_it = - std::find_if(stage_history_.begin(), stage_history_.end(), - [generated_timestamp](const StageData& stage) { - return stage.start_time > generated_timestamp; - }); + // Event dispatch stages. + EventMetrics::DispatchStage dispatch_stage = + EventMetrics::DispatchStage::kGenerated; + base::TimeTicks dispatch_timestamp = + event_metrics->GetDispatchStageTimestamp(dispatch_stage); + while (dispatch_stage != EventMetrics::DispatchStage::kMaxValue) { + DCHECK(!dispatch_timestamp.is_null()); + + // Find the end dispatch stage. + auto end_stage = static_cast<EventMetrics::DispatchStage>( + static_cast<int>(dispatch_stage) + 1); + base::TimeTicks end_timestamp = + event_metrics->GetDispatchStageTimestamp(end_stage); + while (end_timestamp.is_null() && + end_stage != EventMetrics::DispatchStage::kMaxValue) { + end_stage = static_cast<EventMetrics::DispatchStage>( + static_cast<int>(end_stage) + 1); + end_timestamp = event_metrics->GetDispatchStageTimestamp(end_stage); + } + if (end_timestamp.is_null()) + break; + + const char* breakdown_name = + GetEventLatencyDispatchBreakdownName(dispatch_stage, end_stage); + TRACE_EVENT_NESTABLE_ASYNC_BEGIN_WITH_TIMESTAMP0( + "cc,input", breakdown_name, trace_id, dispatch_timestamp); + TRACE_EVENT_NESTABLE_ASYNC_END_WITH_TIMESTAMP0("cc,input", breakdown_name, + trace_id, end_timestamp); + + dispatch_stage = end_stage; + dispatch_timestamp = end_timestamp; + } + + // Find the first compositor stage that happens after the final dispatch + // stage. + auto stage_it = std::find_if(stage_history_.begin(), stage_history_.end(), + [dispatch_timestamp](const StageData& stage) { + return stage.start_time > dispatch_timestamp; + }); // TODO(crbug.com/1079116): Ideally, at least the start time of // SubmitCompositorFrameToPresentationCompositorFrame stage should be - // greater than the event time stamp, but apparently, this is not always the - // case (see crbug.com/1093698). For now, skip to the next event in such - // cases. Hopefully, the work to reduce discrepancies between the new - // EventLatency and the old Event.Latency metrics would fix this issue. If - // not, we need to reconsider investigating this issue. + // greater than the final event dispatch timestamp, but apparently, this is + // not always the case (see crbug.com/1093698). For now, skip to the next + // event in such cases. Hopefully, the work to reduce discrepancies between + // the new EventLatency and the old Event.Latency metrics would fix this + // issue. If not, we need to reconsider investigating this issue. if (stage_it == stage_history_.end()) continue; + DCHECK(dispatch_stage == + EventMetrics::DispatchStage::kRendererCompositorFinished || + dispatch_stage == + EventMetrics::DispatchStage::kRendererMainFinished); + const char* d2c_breakdown_name = + GetEventLatencyDispatchToCompositorBreakdownName(dispatch_stage, + stage_it->stage_type); TRACE_EVENT_NESTABLE_ASYNC_BEGIN_WITH_TIMESTAMP0( - "cc,input", "BrowserToRendererCompositor", trace_id, - generated_timestamp); + "cc,input", d2c_breakdown_name, trace_id, dispatch_timestamp); TRACE_EVENT_NESTABLE_ASYNC_END_WITH_TIMESTAMP0( - "cc,input", "BrowserToRendererCompositor", trace_id, - stage_it->start_time); + "cc,input", d2c_breakdown_name, trace_id, stage_it->start_time); + // Compositor stages. for (; stage_it != stage_history_.end(); ++stage_it) { const int stage_type_index = static_cast<int>(stage_it->stage_type); CHECK_LT(stage_type_index, static_cast<int>(StageType::kStageTypeCount));
diff --git a/chrome/android/chrome_java_sources.gni b/chrome/android/chrome_java_sources.gni index 659ded91..e5d0729 100644 --- a/chrome/android/chrome_java_sources.gni +++ b/chrome/android/chrome_java_sources.gni
@@ -1248,7 +1248,6 @@ "java/src/org/chromium/chrome/browser/signin/SigninActivityLauncherImpl.java", "java/src/org/chromium/chrome/browser/signin/SigninFragment.java", "java/src/org/chromium/chrome/browser/signin/SigninFragmentBase.java", - "java/src/org/chromium/chrome/browser/signin/SigninHelper.java", "java/src/org/chromium/chrome/browser/signin/SigninHelperProvider.java", "java/src/org/chromium/chrome/browser/signin/SigninManagerImpl.java", "java/src/org/chromium/chrome/browser/signin/SigninPromoController.java",
diff --git a/chrome/android/features/autofill_assistant/BUILD.gn b/chrome/android/features/autofill_assistant/BUILD.gn index 87bd5f7..d77e7b18 100644 --- a/chrome/android/features/autofill_assistant/BUILD.gn +++ b/chrome/android/features/autofill_assistant/BUILD.gn
@@ -96,7 +96,6 @@ "java/src/org/chromium/chrome/browser/autofill_assistant/AssistantInfoPopup.java", "java/src/org/chromium/chrome/browser/autofill_assistant/AssistantKeyboardCoordinator.java", "java/src/org/chromium/chrome/browser/autofill_assistant/AssistantModel.java", - "java/src/org/chromium/chrome/browser/autofill_assistant/AssistantOnboardingCoordinator.java", "java/src/org/chromium/chrome/browser/autofill_assistant/AssistantPeekHeightCoordinator.java", "java/src/org/chromium/chrome/browser/autofill_assistant/AssistantRootViewContainer.java", "java/src/org/chromium/chrome/browser/autofill_assistant/AssistantSnackbar.java", @@ -110,6 +109,8 @@ "java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantModuleEntryImpl.java", "java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantServiceInjector.java", "java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiController.java", + "java/src/org/chromium/chrome/browser/autofill_assistant/BaseOnboardingCoordinator.java", + "java/src/org/chromium/chrome/browser/autofill_assistant/BottomSheetOnboardingCoordinator.java", "java/src/org/chromium/chrome/browser/autofill_assistant/BottomSheetUtils.java", "java/src/org/chromium/chrome/browser/autofill_assistant/FeedbackContext.java", "java/src/org/chromium/chrome/browser/autofill_assistant/LayoutUtils.java", @@ -199,11 +200,11 @@ "java/src/org/chromium/chrome/browser/autofill_assistant/AssistantDialogButton.java", "java/src/org/chromium/chrome/browser/autofill_assistant/AssistantInfoPopup.java", "java/src/org/chromium/chrome/browser/autofill_assistant/AssistantModel.java", - "java/src/org/chromium/chrome/browser/autofill_assistant/AssistantOnboardingCoordinator.java", "java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantClient.java", "java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantDirectActionImpl.java", "java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantLiteService.java", "java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiController.java", + "java/src/org/chromium/chrome/browser/autofill_assistant/BaseOnboardingCoordinator.java", "java/src/org/chromium/chrome/browser/autofill_assistant/carousel/AssistantChip.java", "java/src/org/chromium/chrome/browser/autofill_assistant/details/AssistantDetails.java", "java/src/org/chromium/chrome/browser/autofill_assistant/details/AssistantDetailsModel.java", @@ -270,7 +271,6 @@ testonly = true sources = [ - "javatests/src/org/chromium/chrome/browser/autofill_assistant/AssistantOnboardingCoordinatorTest.java", "javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantAccessibilityIntegrationTest.java", "javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantActionsCarouselUiTest.java", "javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantAutostartTest.java", @@ -299,6 +299,7 @@ "javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantTriggerScriptIntegrationTest.java", "javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiTest.java", "javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiTestUtil.java", + "javatests/src/org/chromium/chrome/browser/autofill_assistant/BottomSheetOnboardingCoordinatorTest.java", "javatests/src/org/chromium/chrome/browser/autofill_assistant/TestingAutofillAssistantModuleEntryProvider.java", ]
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantRootViewContainer.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantRootViewContainer.java index 56f53b3..b54fcb8 100644 --- a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantRootViewContainer.java +++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantRootViewContainer.java
@@ -27,6 +27,7 @@ private final BrowserControlsStateProvider mBrowserControlsStateProvider; private Rect mVisibleViewportRect = new Rect(); private float mTalkbackSheetSizeFraction; + private boolean mTalkbackResizingDisabled; public AssistantRootViewContainer(Context context, @Nullable AttributeSet attrs) { super(context, attrs); @@ -53,6 +54,10 @@ invalidate(); } + public void disableTalkbackViewResizing() { + mTalkbackResizingDisabled = true; + } + void destroy() { mBrowserControlsStateProvider.removeObserver(this); } @@ -67,7 +72,7 @@ int targetHeight; int mode; - if (ChromeAccessibilityUtil.get().isAccessibilityEnabled()) { + if (ChromeAccessibilityUtil.get().isAccessibilityEnabled() && !mTalkbackResizingDisabled) { // TODO(b/143944870): Make this more stable with landscape mode. targetHeight = (int) (availableHeight * mTalkbackSheetSizeFraction); mode = MeasureSpec.EXACTLY;
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantActionHandlerImpl.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantActionHandlerImpl.java index ba97e59..aab251f 100644 --- a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantActionHandlerImpl.java +++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantActionHandlerImpl.java
@@ -82,8 +82,8 @@ public void performOnboarding( String experimentIds, Bundle arguments, Callback<Boolean> callback) { Map<String, String> parameters = toArgumentMap(arguments); - AssistantOnboardingCoordinator coordinator = - new AssistantOnboardingCoordinator(experimentIds, parameters, mContext, + BottomSheetOnboardingCoordinator coordinator = + new BottomSheetOnboardingCoordinator(experimentIds, parameters, mContext, mBottomSheetController, mBrowserControls, mCompositorViewHolder, mScrim); coordinator.show(accepted -> { coordinator.hide(); @@ -101,13 +101,13 @@ } Map<String, String> argumentMap = toArgumentMap(arguments); - Callback<AssistantOnboardingCoordinator> afterOnboarding = (onboardingCoordinator) -> { + Callback<BottomSheetOnboardingCoordinator> afterOnboarding = (onboardingCoordinator) -> { callback.onResult(client.performDirectAction( name, experimentIds, argumentMap, onboardingCoordinator)); }; if (!AutofillAssistantPreferencesUtil.isAutofillOnboardingAccepted()) { - AssistantOnboardingCoordinator coordinator = new AssistantOnboardingCoordinator( + BottomSheetOnboardingCoordinator coordinator = new BottomSheetOnboardingCoordinator( experimentIds, argumentMap, mContext, mBottomSheetController, mBrowserControls, mCompositorViewHolder, mScrim); coordinator.show(accepted -> {
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantClient.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantClient.java index 79798b25..0482f84 100644 --- a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantClient.java +++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantClient.java
@@ -109,7 +109,7 @@ */ boolean start(String initialUrl, Map<String, String> parameters, String experimentIds, @Nullable String callerAccount, @Nullable String userName, boolean isChromeCustomTab, - @Nullable AssistantOnboardingCoordinator onboardingCoordinator) { + @Nullable BaseOnboardingCoordinator onboardingCoordinator) { if (mNativeClientAndroid == 0) return false; checkNativeClientIsAliveOrThrow(); @@ -213,7 +213,7 @@ */ public boolean performDirectAction(String actionId, String experimentIds, Map<String, String> arguments, - @Nullable AssistantOnboardingCoordinator onboardingCoordinator) { + @Nullable BaseOnboardingCoordinator onboardingCoordinator) { if (mNativeClientAndroid == 0) return false; // Note that only fetchWebsiteActions can start AA, so only it needs @@ -405,8 +405,8 @@ boolean start(long nativeClientAndroid, AutofillAssistantClient caller, String initialUrl, String experimentIds, String callerAccount, String[] parameterNames, String[] parameterValues, boolean isChromeCustomTab, - @Nullable AssistantOnboardingCoordinator onboardingCoordinator, - boolean onboardingShown, long nativeService); + @Nullable BaseOnboardingCoordinator onboardingCoordinator, boolean onboardingShown, + long nativeService); void startTriggerScript(long nativeClientAndroid, AutofillAssistantClient caller, AssistantTriggerScriptBridge delegate, String initialUrl, String experimentIds, String[] parameterNames, String[] parameterValues, long nativeServiceRequestSender); @@ -426,7 +426,6 @@ boolean performDirectAction(long nativeClientAndroid, AutofillAssistantClient caller, String actionId, String experimentId, String[] argumentNames, - String[] argumentValues, - @Nullable AssistantOnboardingCoordinator onboardingCoordinator); + String[] argumentValues, @Nullable BaseOnboardingCoordinator onboardingCoordinator); } }
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantModuleEntryImpl.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantModuleEntryImpl.java index c780a69..aa7a070 100644 --- a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantModuleEntryImpl.java +++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantModuleEntryImpl.java
@@ -167,9 +167,11 @@ return; } - AssistantOnboardingCoordinator onboardingCoordinator = new AssistantOnboardingCoordinator( - experimentIds, parameters, context, bottomSheetController, browserControls, - compositorViewHolder, bottomSheetController.getScrimCoordinator()); + BottomSheetOnboardingCoordinator onboardingCoordinator = + new BottomSheetOnboardingCoordinator(experimentIds, parameters, context, + bottomSheetController, browserControls, compositorViewHolder, + bottomSheetController.getScrimCoordinator()); + onboardingCoordinator.show(accepted -> { if (parameters.containsKey(PARAMETER_TRIGGER_SCRIPT_USED) || parameters.containsKey(PARAMETER_STARTED_WITH_TRIGGER_SCRIPT)) {
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiController.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiController.java index eb97928..7aeca2b 100644 --- a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiController.java +++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiController.java
@@ -104,7 +104,7 @@ @CalledByNative private static AutofillAssistantUiController create(ChromeActivity activity, boolean allowTabSwitching, long nativeUiController, - @Nullable AssistantOnboardingCoordinator onboardingCoordinator) { + @Nullable BaseOnboardingCoordinator onboardingCoordinator) { BottomSheetController sheetController = BottomSheetControllerProvider.from(activity.getWindowAndroid()); assert activity != null; @@ -124,8 +124,7 @@ private AutofillAssistantUiController(ChromeActivity activity, BottomSheetController controller, TabObscuringHandler tabObscuringHandler, boolean allowTabSwitching, - long nativeUiController, - @Nullable AssistantOnboardingCoordinator onboardingCoordinator) { + long nativeUiController, @Nullable BaseOnboardingCoordinator onboardingCoordinator) { mNativeUiController = nativeUiController; mActivity = activity; mCoordinator = new AssistantCoordinator(activity, controller, tabObscuringHandler,
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantOnboardingCoordinator.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/BaseOnboardingCoordinator.java similarity index 67% rename from chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantOnboardingCoordinator.java rename to chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/BaseOnboardingCoordinator.java index e169d87b..df3168d 100644 --- a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantOnboardingCoordinator.java +++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/BaseOnboardingCoordinator.java
@@ -23,17 +23,7 @@ import org.chromium.chrome.browser.autofill_assistant.metrics.DropOutReason; import org.chromium.chrome.browser.autofill_assistant.metrics.OnBoarding; import org.chromium.chrome.browser.autofill_assistant.overlay.AssistantOverlayCoordinator; -import org.chromium.chrome.browser.autofill_assistant.overlay.AssistantOverlayModel; -import org.chromium.chrome.browser.autofill_assistant.overlay.AssistantOverlayState; -import org.chromium.chrome.browser.browser_controls.BrowserControlsStateProvider; -import org.chromium.chrome.browser.compositor.CompositorViewHolder; import org.chromium.chrome.browser.customtabs.CustomTabActivity; -import org.chromium.components.browser_ui.bottomsheet.BottomSheetContent; -import org.chromium.components.browser_ui.bottomsheet.BottomSheetController; -import org.chromium.components.browser_ui.bottomsheet.BottomSheetController.SheetState; -import org.chromium.components.browser_ui.bottomsheet.BottomSheetObserver; -import org.chromium.components.browser_ui.bottomsheet.EmptyBottomSheetObserver; -import org.chromium.components.browser_ui.widget.scrim.ScrimCoordinator; import org.chromium.components.embedder_support.util.UrlUtilitiesJni; import org.chromium.content_public.browser.NavigationHandle; import org.chromium.content_public.browser.WebContents; @@ -46,11 +36,12 @@ import java.util.Map; /** - * Coordinator responsible for showing the onboarding screen when the user is using the Autofill - * Assistant for the first time. + * Base Coordinator class responsible for showing the onboarding screen when the user is using the + * Autofill Assistant for the first time. */ @JNINamespace("autofill_assistant") -class AssistantOnboardingCoordinator { +// TODO(b/174445633): Add a public interface for |show()|, |hide()| and |getOboardingShown()| +abstract class BaseOnboardingCoordinator { private static final String INTENT_IDENTFIER = "INTENT"; private static final String FETCH_TIMEOUT_IDENTIFIER = "ONBOARDING_FETCH_TIMEOUT_MS"; private static final String BUY_MOVIE_TICKETS_INTENT = "BUY_MOVIE_TICKET"; @@ -67,40 +58,24 @@ private final String mExperimentIds; private final Map<String, String> mParameters; - private final Context mContext; - private final BottomSheetController mController; - private final BrowserControlsStateProvider mBrowserControls; - private final CompositorViewHolder mCompositorViewHolder; - private final ScrimCoordinator mScrimCoordinator; - - @Nullable - private AssistantOverlayCoordinator mOverlayCoordinator; + private final Map<String, String> mStringMap = new HashMap<>(); @Nullable private WebContentsObserver mWebContentsObserver; - private BottomSheetObserver mBottomSheetObserver; - - @Nullable - private AssistantBottomSheetContent mContent; - private boolean mAnimate = true; - - @Nullable - private ScrollView mView; - private final Map<String, String> mStringMap = new HashMap<>(); - private boolean mOnboardingShown; - AssistantOnboardingCoordinator(String experimentIds, Map<String, String> parameters, - Context context, BottomSheetController controller, - BrowserControlsStateProvider browserControls, CompositorViewHolder compositorViewHolder, - ScrimCoordinator scrim) { + final Context mContext; + boolean mAnimate = true; + @Nullable + ScrollView mView; + + BaseOnboardingCoordinator( + String experimentIds, Map<String, String> parameters, Context context) { mExperimentIds = experimentIds; mParameters = parameters; mContext = context; - mController = controller; - mBrowserControls = browserControls; - mCompositorViewHolder = compositorViewHolder; - mScrimCoordinator = scrim; + mView = (ScrollView) LayoutUtils.createInflater(mContext).inflate( + R.layout.autofill_assistant_onboarding, /* root= */ null); } /** @@ -113,6 +88,62 @@ * navigation to that URL is allowed, other navigations will hide Autofill Assistant. */ void show(Callback<Boolean> callback, WebContents webContents, String targetUrl) { + addWebContentObserver(callback, webContents, targetUrl); + show(callback); + } + + /** + * Shows onboarding and provides the result to the given callback. + * + * <p>The {@code callback} will be called with true or false when the user accepts or cancels + * the onboarding (respectively). + * + * <p>Note that the onboarding screen will be hidden after the callback returns. Call, from the + * callback, {@link #hide} to hide it earlier or {@link #transferControls} to take ownership of + * it and possibly keep it past the end of the callback. + */ + void show(Callback<Boolean> callback) { + AutofillAssistantMetrics.recordOnBoarding(OnBoarding.OB_SHOWN); + mOnboardingShown = true; + + initViewImpl(callback); + setupSharedView(callback); + + int fetchTimeoutMs = 300; + if (mParameters.containsKey(FETCH_TIMEOUT_IDENTIFIER)) { + fetchTimeoutMs = Integer.parseInt(mParameters.get(FETCH_TIMEOUT_IDENTIFIER)); + } + if (!mParameters.containsKey(INTENT_IDENTFIER) || fetchTimeoutMs == 0) { + updateAndShowView(); + } else { + BaseOnboardingCoordinatorJni.get().fetchOnboardingDefinition(this, + mParameters.get(INTENT_IDENTFIER), LocaleUtils.getDefaultLocaleString(), + fetchTimeoutMs); + } + } + + /** + * Returns {@code true} if the onboarding has been shown at the beginning when this + * autofill assistant flow got triggered. + */ + boolean getOnboardingShown() { + return mOnboardingShown; + } + + abstract void hide(); + // TODO(b/175598484): Move transferControls to bottom sheet subclass + abstract AssistantOverlayCoordinator transferControls(); + + /** Destroy web contents observer. */ + void destroy() { + if (mWebContentsObserver != null) { + mWebContentsObserver.destroy(); + mWebContentsObserver = null; + } + } + + private void addWebContentObserver( + Callback<Boolean> callback, WebContents webContents, String targetUrl) { mWebContentsObserver = new WebContentsObserver(webContents) { @Override public void didStartNavigation(NavigationHandle navigationHandle) { @@ -128,141 +159,14 @@ } }; webContents.addObserver(mWebContentsObserver); - - show(callback); } /** - * Shows onboarding and provides the result to the given callback. - * - * <p>The {@code callback} will be called with true or false when the user accepts or cancels - * the onboarding (respectively). - * - * <p>Note that the bottom sheet will be hidden after the callback returns. Call, from the - * callback, {@link #hide} to hide it earlier or {@link #transferControls} to take ownership of - * it and possibly keep it past the end of the callback. + * Setup the shared |mView| */ - void show(Callback<Boolean> callback) { - AutofillAssistantMetrics.recordOnBoarding(OnBoarding.OB_SHOWN); - mOnboardingShown = true; - - // If there's a tab, cover it with an overlay. - AssistantOverlayModel overlayModel = new AssistantOverlayModel(); - mOverlayCoordinator = new AssistantOverlayCoordinator( - mContext, mBrowserControls, mCompositorViewHolder, mScrimCoordinator, overlayModel); - overlayModel.set(AssistantOverlayModel.STATE, AssistantOverlayState.FULL); - - mBottomSheetObserver = new EmptyBottomSheetObserver() { - @Override - public void onSheetStateChanged(int newState) { - if (mOverlayCoordinator == null) { - return; - } - - if (newState == SheetState.HIDDEN) { - mOverlayCoordinator.suppress(); - } - if (newState == SheetState.PEEK || newState == SheetState.HALF - || newState == SheetState.FULL) { - mOverlayCoordinator.restore(); - } - } - }; - mController.addObserver(mBottomSheetObserver); - - AssistantBottomBarDelegate delegate = new AssistantBottomBarDelegate() { - @Override - public boolean onBackButtonPressed() { - onUserAction( - /* accept= */ false, callback, OnBoarding.OB_NO_ANSWER, - DropOutReason.ONBOARDING_BACK_BUTTON_CLICKED); - return true; - } - - @Override - public void onBottomSheetClosedWithSwipe() {} - }; - BottomSheetContent currentSheetContent = mController.getCurrentSheetContent(); - if (currentSheetContent instanceof AssistantBottomSheetContent) { - mContent = (AssistantBottomSheetContent) currentSheetContent; - mContent.setDelegate(() -> delegate); - } else { - mContent = new AssistantBottomSheetContent(mContext, () -> delegate); - } - initContent(callback); - } - - /** - * Transfers ownership of the controls to the caller, returns the overlay coordinator, if one - * was created. - * - * <p>This call is only useful when called from inside a callback provided to {@link #show}, as - * before that there are no controls and after that the coordinator automatically hides them. - * This call allows callbacks to reuse the controls setup for onboarding and provide a smooth - * transition. - */ - @Nullable - AssistantOverlayCoordinator transferControls() { - assert isInProgress(); - - AssistantOverlayCoordinator coordinator = mOverlayCoordinator; - mOverlayCoordinator = null; - mContent = null; - return coordinator; - } - - /** Hides the UI, if one is shown. */ - void hide() { - mController.removeObserver(mBottomSheetObserver); - - if (mOverlayCoordinator != null) { - mOverlayCoordinator.destroy(); - mOverlayCoordinator = null; - } - - if (mContent != null) { - mController.hideContent(mContent, /* animate= */ mAnimate); - mContent = null; - } - - if (mWebContentsObserver != null) { - mWebContentsObserver.destroy(); - mWebContentsObserver = null; - } - } - - /** - * Returns {@code true} between the time {@link #show} is called and the time - * the callback has returned. - */ - boolean isInProgress() { - return mContent != null; - } - - /** Don't animate the bottom sheet expansion. */ - @VisibleForTesting - void disableAnimationForTesting() { - mAnimate = false; - } - - /** - * Returns {@code true} if the onboarding has been shown at the beginning when this - * autofill assistant flow got triggered. - */ - boolean getOnboardingShown() { - return mOnboardingShown; - } - - /** - * Set the content of the bottom sheet to be the Autofill Assistant onboarding. - */ - private void initContent(Callback<Boolean> callback) { - mView = (ScrollView) LayoutUtils.createInflater(mContext).inflate( - R.layout.autofill_assistant_onboarding, /* root= */ null); - + private void setupSharedView(Callback<Boolean> callback) { // Set focusable for accessibility. mView.setFocusable(true); - mView.findViewById(R.id.button_init_ok) .setOnClickListener(unusedView -> onUserAction( @@ -273,22 +177,10 @@ -> onUserAction( /* accept= */ false, callback, OnBoarding.OB_CANCELLED, DropOutReason.DECLINED)); - - int fetchTimeoutMs = 300; - if (mParameters.containsKey(FETCH_TIMEOUT_IDENTIFIER)) { - fetchTimeoutMs = Integer.parseInt(mParameters.get(FETCH_TIMEOUT_IDENTIFIER)); - } - if (!mParameters.containsKey(INTENT_IDENTFIER) || fetchTimeoutMs == 0) { - updateAndShowView(); - } else { - AssistantOnboardingCoordinatorJni.get().fetchOnboardingDefinition(this, - mParameters.get(INTENT_IDENTFIER), LocaleUtils.getDefaultLocaleString(), - fetchTimeoutMs); - } } - private void onUserAction(boolean accept, Callback<Boolean> callback, - @OnBoarding int onboardingAnswer, @DropOutReason int dropoutReason) { + void onUserAction(boolean accept, Callback<Boolean> callback, @OnBoarding int onboardingAnswer, + @DropOutReason int dropoutReason) { AutofillAssistantPreferencesUtil.setInitialPreferences(accept); AutofillAssistantMetrics.recordOnBoarding(onboardingAnswer); if (!accept) { @@ -299,6 +191,44 @@ hide(); } + @CalledByNative + @VisibleForTesting + public void addEntryToStringMap(String key, String value) { + mStringMap.put(key, value); + } + + @CalledByNative + @VisibleForTesting + public void updateAndShowView() { + updateView(); + showViewImpl(); + } + + private void updateView() { + assert mView != null; + + String termsAndConditionsKey = "terms_and_conditions"; + String termsAndConditionsUrlKey = "terms_and_conditions_url"; + updateTermsAndConditions(mView, mStringMap.get(termsAndConditionsKey), + mStringMap.get(termsAndConditionsUrlKey)); + + if (mStringMap.isEmpty()) { + updateViewBasedOnIntent(mView); + } else { + String onboardingTitleKey = "onboarding_title"; + if (mStringMap.containsKey(onboardingTitleKey)) { + ((TextView) mView.findViewById(R.id.onboarding_try_assistant)) + .setText(mStringMap.get(onboardingTitleKey)); + } + + String onboardingTextKey = "onboarding_text"; + if (mStringMap.containsKey(onboardingTextKey)) { + ((TextView) mView.findViewById(R.id.onboarding_subtitle)) + .setText(mStringMap.get(onboardingTextKey)); + } + } + } + private void updateTermsAndConditions(ScrollView initView, @Nullable String termsAndConditionsString, @Nullable String termsAndConditionsUrl) { TextView termsTextView = initView.findViewById(R.id.google_terms_message); @@ -374,46 +304,18 @@ } } - @CalledByNative + /** Don't animate the user interface. */ @VisibleForTesting - public void addEntryToStringMap(String key, String value) { - mStringMap.put(key, value); + void disableAnimationForTesting() { + mAnimate = false; } - @CalledByNative - @VisibleForTesting - public void updateAndShowView() { - assert mView != null; - - String termsAndConditionsKey = "terms_and_conditions"; - String termsAndConditionsUrlKey = "terms_and_conditions_url"; - updateTermsAndConditions(mView, mStringMap.get(termsAndConditionsKey), - mStringMap.get(termsAndConditionsUrlKey)); - - if (mStringMap.isEmpty()) { - updateViewBasedOnIntent(mView); - } else { - String onboardingTitleKey = "onboarding_title"; - if (mStringMap.containsKey(onboardingTitleKey)) { - ((TextView) mView.findViewById(R.id.onboarding_try_assistant)) - .setText(mStringMap.get(onboardingTitleKey)); - } - - String onboardingTextKey = "onboarding_text"; - if (mStringMap.containsKey(onboardingTextKey)) { - ((TextView) mView.findViewById(R.id.onboarding_subtitle)) - .setText(mStringMap.get(onboardingTextKey)); - } - } - - mContent.setContent(mView, mView); - BottomSheetUtils.showContentAndMaybeExpand( - mController, mContent, /* shouldExpand = */ true, mAnimate); - } + abstract void initViewImpl(Callback<Boolean> callback); + abstract void showViewImpl(); @NativeMethods interface Natives { - void fetchOnboardingDefinition(AssistantOnboardingCoordinator coordinator, String intent, - String locale, int timeoutMs); + void fetchOnboardingDefinition( + BaseOnboardingCoordinator coordinator, String intent, String locale, int timeoutMs); } -} +} \ No newline at end of file
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/BottomSheetOnboardingCoordinator.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/BottomSheetOnboardingCoordinator.java new file mode 100644 index 0000000..93e0cc4e --- /dev/null +++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/BottomSheetOnboardingCoordinator.java
@@ -0,0 +1,152 @@ +// Copyright 2020 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.autofill_assistant; + +import android.content.Context; + +import androidx.annotation.Nullable; +import androidx.annotation.VisibleForTesting; + +import org.chromium.base.Callback; +import org.chromium.chrome.browser.autofill_assistant.metrics.DropOutReason; +import org.chromium.chrome.browser.autofill_assistant.metrics.OnBoarding; +import org.chromium.chrome.browser.autofill_assistant.overlay.AssistantOverlayCoordinator; +import org.chromium.chrome.browser.autofill_assistant.overlay.AssistantOverlayModel; +import org.chromium.chrome.browser.autofill_assistant.overlay.AssistantOverlayState; +import org.chromium.chrome.browser.browser_controls.BrowserControlsStateProvider; +import org.chromium.chrome.browser.compositor.CompositorViewHolder; +import org.chromium.components.browser_ui.bottomsheet.BottomSheetContent; +import org.chromium.components.browser_ui.bottomsheet.BottomSheetController; +import org.chromium.components.browser_ui.bottomsheet.BottomSheetController.SheetState; +import org.chromium.components.browser_ui.bottomsheet.BottomSheetObserver; +import org.chromium.components.browser_ui.bottomsheet.EmptyBottomSheetObserver; +import org.chromium.components.browser_ui.widget.scrim.ScrimCoordinator; + +import java.util.Map; + +/** + * Coordinator responsible for showing the bottom sheet onboarding screen when the user is using the + * Autofill Assistant for the first time. + */ +class BottomSheetOnboardingCoordinator extends BaseOnboardingCoordinator { + @Nullable + private AssistantBottomSheetContent mContent; + private BottomSheetObserver mBottomSheetObserver; + private final BottomSheetController mController; + private final BrowserControlsStateProvider mBrowserControls; + private final CompositorViewHolder mCompositorViewHolder; + private final ScrimCoordinator mScrimCoordinator; + + @Nullable + AssistantOverlayCoordinator mOverlayCoordinator; + + BottomSheetOnboardingCoordinator(String experimentIds, Map<String, String> parameters, + Context context, BottomSheetController controller, + BrowserControlsStateProvider browserControls, CompositorViewHolder compositorViewHolder, + ScrimCoordinator scrim) { + super(experimentIds, parameters, context); + this.mController = controller; + this.mBrowserControls = browserControls; + this.mCompositorViewHolder = compositorViewHolder; + this.mScrimCoordinator = scrim; + } + + @Override + void initViewImpl(Callback<Boolean> callback) { + // If there's a tab, cover it with an overlay. + AssistantOverlayModel overlayModel = new AssistantOverlayModel(); + mOverlayCoordinator = new AssistantOverlayCoordinator( + mContext, mBrowserControls, mCompositorViewHolder, mScrimCoordinator, overlayModel); + overlayModel.set(AssistantOverlayModel.STATE, AssistantOverlayState.FULL); + + mBottomSheetObserver = new EmptyBottomSheetObserver() { + @Override + public void onSheetStateChanged(int newState) { + if (mOverlayCoordinator == null) { + return; + } + + if (newState == SheetState.HIDDEN) { + mOverlayCoordinator.suppress(); + } + if (newState == SheetState.PEEK || newState == SheetState.HALF + || newState == SheetState.FULL) { + mOverlayCoordinator.restore(); + } + } + }; + mController.addObserver(mBottomSheetObserver); + + AssistantBottomBarDelegate delegate = new AssistantBottomBarDelegate() { + @Override + public boolean onBackButtonPressed() { + onUserAction( + /* accept= */ false, callback, OnBoarding.OB_NO_ANSWER, + DropOutReason.ONBOARDING_BACK_BUTTON_CLICKED); + return true; + } + + @Override + public void onBottomSheetClosedWithSwipe() {} + }; + BottomSheetContent currentSheetContent = mController.getCurrentSheetContent(); + if (currentSheetContent instanceof AssistantBottomSheetContent) { + mContent = (AssistantBottomSheetContent) currentSheetContent; + mContent.setDelegate(() -> delegate); + } else { + mContent = new AssistantBottomSheetContent(mContext, () -> delegate); + } + } + + @Override + void showViewImpl() { + mContent.setContent(mView, mView); + BottomSheetUtils.showContentAndMaybeExpand( + mController, mContent, /* shouldExpand = */ true, mAnimate); + } + + /** + * Transfers ownership of the controls to the caller, returns the overlay coordinator, if one + * was created. + * + * <p>This call is only useful when called from inside a callback provided to {@link #show}, as + * before that there are no controls and after that the coordinator automatically hides them. + * This call allows callbacks to reuse the controls setup for onboarding and provide a smooth + * transition. + */ + @Nullable + @Override + AssistantOverlayCoordinator transferControls() { + assert isInProgress(); + mContent = null; + AssistantOverlayCoordinator coordinator = mOverlayCoordinator; + mOverlayCoordinator = null; + return coordinator; + } + + /** Hides the UI, if one is shown. */ + @Override + void hide() { + mController.removeObserver(mBottomSheetObserver); + if (mContent != null) { + mController.hideContent(mContent, /* animate= */ mAnimate); + mContent = null; + } + if (mOverlayCoordinator != null) { + mOverlayCoordinator.destroy(); + mOverlayCoordinator = null; + } + destroy(); + } + + /** + * Returns {@code true} between the time {@link #show} is called and the time + * the callback has returned. + */ + @VisibleForTesting + boolean isInProgress() { + return mContent != null; + } +} \ No newline at end of file
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/trigger_scripts/AssistantTriggerScript.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/trigger_scripts/AssistantTriggerScript.java index e58f94e..54e8011 100644 --- a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/trigger_scripts/AssistantTriggerScript.java +++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/trigger_scripts/AssistantTriggerScript.java
@@ -142,6 +142,7 @@ AssistantRootViewContainer rootViewContainer = (AssistantRootViewContainer) LayoutUtils.createInflater(mContext).inflate( R.layout.autofill_assistant_bottom_sheet_content, /* root= */ null); + rootViewContainer.disableTalkbackViewResizing(); ScrollView scrollableContent = rootViewContainer.findViewById(R.id.scrollable_content); rootViewContainer.addView(mHeaderCoordinator.getView(), 0); rootViewContainer.addView(mChipsContainer,
diff --git a/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AssistantOnboardingCoordinatorTest.java b/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/BottomSheetOnboardingCoordinatorTest.java similarity index 90% rename from chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AssistantOnboardingCoordinatorTest.java rename to chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/BottomSheetOnboardingCoordinatorTest.java index edae79f..c2efc0c 100644 --- a/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AssistantOnboardingCoordinatorTest.java +++ b/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/BottomSheetOnboardingCoordinatorTest.java
@@ -54,7 +54,6 @@ import org.chromium.chrome.browser.customtabs.CustomTabActivity; import org.chromium.chrome.browser.customtabs.CustomTabActivityTestRule; import org.chromium.chrome.browser.flags.ChromeSwitches; -import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.components.browser_ui.bottomsheet.BottomSheetController; import org.chromium.components.browser_ui.widget.scrim.ScrimCoordinator; @@ -66,11 +65,11 @@ import java.util.List; /** - * Tests {@link AssistantOnboardingCoordinator} + * Tests {@link BottomSheetOnboardingCoordinator} */ @RunWith(ChromeJUnit4ClassRunner.class) @CommandLineFlags.Add(ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE) -public class AssistantOnboardingCoordinatorTest { +public class BottomSheetOnboardingCoordinatorTest { @Rule public CustomTabActivityTestRule mCustomTabActivityTestRule = new CustomTabActivityTestRule(); @@ -82,7 +81,6 @@ private ChromeActivity mActivity; private BottomSheetController mBottomSheetController; - private Tab mTab; private ScrimCoordinator mScrimCoordinator; @Before @@ -91,15 +89,14 @@ mActivity = mCustomTabActivityTestRule.getActivity(); mBottomSheetController = TestThreadUtils.runOnUiThreadBlocking( () -> AutofillAssistantUiTestUtil.getBottomSheetController(mActivity)); - mTab = mActivity.getTabModelSelector().getCurrentTab(); mScrimCoordinator = mCustomTabActivityTestRule.getActivity() .getRootUiCoordinatorForTesting() .getScrimCoordinator(); } - private AssistantOnboardingCoordinator createCoordinator(Tab tab) { - AssistantOnboardingCoordinator coordinator = - new AssistantOnboardingCoordinator("", new HashMap<String, String>(), mActivity, + private BottomSheetOnboardingCoordinator createCoordinator() { + BottomSheetOnboardingCoordinator coordinator = + new BottomSheetOnboardingCoordinator("", new HashMap<String, String>(), mActivity, mBottomSheetController, mActivity.getBrowserControlsManager(), mActivity.getCompositorViewHolder(), mScrimCoordinator); coordinator.disableAnimationForTesting(); @@ -121,7 +118,7 @@ private void testOnboarding(@IdRes int buttonToClick, boolean expectAccept) throws Exception { AutofillAssistantPreferencesUtil.setInitialPreferences(!expectAccept); - AssistantOnboardingCoordinator coordinator = createCoordinator(mTab); + BottomSheetOnboardingCoordinator coordinator = createCoordinator(); showOnboardingAndWait(coordinator, mCallback); assertTrue(TestThreadUtils.runOnUiThreadBlocking(coordinator::isInProgress)); @@ -136,7 +133,7 @@ @Test @MediumTest public void testOnboardingWithNoTabs() { - AssistantOnboardingCoordinator coordinator = createCoordinator(/* tab= */ null); + BottomSheetOnboardingCoordinator coordinator = createCoordinator(); showOnboardingAndWait(coordinator, mCallback); onView(withId(R.id.button_init_ok)).perform(click()); @@ -147,7 +144,7 @@ @Test @MediumTest public void testTransferControls() throws Exception { - AssistantOnboardingCoordinator coordinator = createCoordinator(mTab); + BottomSheetOnboardingCoordinator coordinator = createCoordinator(); List<AssistantOverlayCoordinator> capturedOverlays = Collections.synchronizedList(new ArrayList<>()); @@ -173,7 +170,7 @@ @Test @MediumTest public void testShownFlag() { - AssistantOnboardingCoordinator coordinator = createCoordinator(/* tab= */ null); + BottomSheetOnboardingCoordinator coordinator = createCoordinator(); assertFalse(coordinator.getOnboardingShown()); showOnboardingAndWait(coordinator, mCallback); @@ -187,8 +184,8 @@ HashMap<String, String> parameters = new HashMap(); parameters.put("INTENT", "RENT_CAR"); - AssistantOnboardingCoordinator coordinator = - new AssistantOnboardingCoordinator("", parameters, mActivity, + BottomSheetOnboardingCoordinator coordinator = + new BottomSheetOnboardingCoordinator("", parameters, mActivity, mBottomSheetController, mActivity.getBrowserControlsManager(), mActivity.getCompositorViewHolder(), mScrimCoordinator); coordinator.disableAnimationForTesting(); @@ -211,8 +208,8 @@ HashMap<String, String> parameters = new HashMap(); parameters.put("INTENT", "BUY_MOVIE_TICKET"); - AssistantOnboardingCoordinator coordinator = - new AssistantOnboardingCoordinator("4363482", parameters, mActivity, + BottomSheetOnboardingCoordinator coordinator = + new BottomSheetOnboardingCoordinator("4363482", parameters, mActivity, mBottomSheetController, mActivity.getBrowserControlsManager(), mActivity.getCompositorViewHolder(), mScrimCoordinator); coordinator.disableAnimationForTesting(); @@ -234,8 +231,8 @@ AutofillAssistantPreferencesUtil.setInitialPreferences(true); HashMap<String, String> parameters = new HashMap(); - AssistantOnboardingCoordinator coordinator = - new AssistantOnboardingCoordinator("", parameters, mActivity, + BottomSheetOnboardingCoordinator coordinator = + new BottomSheetOnboardingCoordinator("", parameters, mActivity, mBottomSheetController, mActivity.getBrowserControlsManager(), mActivity.getCompositorViewHolder(), mScrimCoordinator); coordinator.disableAnimationForTesting(); @@ -257,8 +254,8 @@ HashMap<String, String> parameters = new HashMap<>(); parameters.put("ONBOARDING_FETCH_TIMEOUT_MS", "0"); - AssistantOnboardingCoordinator coordinator = - new AssistantOnboardingCoordinator("", parameters, mActivity, + BottomSheetOnboardingCoordinator coordinator = + new BottomSheetOnboardingCoordinator("", parameters, mActivity, mBottomSheetController, mActivity.getBrowserControlsManager(), mActivity.getCompositorViewHolder(), mScrimCoordinator); @@ -309,8 +306,8 @@ HashMap<String, String> parameters = new HashMap<>(); parameters.put("ONBOARDING_FETCH_TIMEOUT_MS", "0"); - AssistantOnboardingCoordinator coordinator = - new AssistantOnboardingCoordinator("", parameters, mActivity, + BottomSheetOnboardingCoordinator coordinator = + new BottomSheetOnboardingCoordinator("", parameters, mActivity, mBottomSheetController, mActivity.getBrowserControlsManager(), mActivity.getCompositorViewHolder(), mScrimCoordinator); @@ -335,8 +332,8 @@ HashMap<String, String> parameters = new HashMap<>(); parameters.put("ONBOARDING_FETCH_TIMEOUT_MS", "0"); - AssistantOnboardingCoordinator coordinator = - new AssistantOnboardingCoordinator("", parameters, mActivity, + BottomSheetOnboardingCoordinator coordinator = + new BottomSheetOnboardingCoordinator("", parameters, mActivity, mBottomSheetController, mActivity.getBrowserControlsManager(), mActivity.getCompositorViewHolder(), mScrimCoordinator); @@ -373,7 +370,7 @@ /** Trigger onboarding and wait until it is fully displayed. */ private void showOnboardingAndWait( - AssistantOnboardingCoordinator coordinator, Callback<Boolean> callback) { + BottomSheetOnboardingCoordinator coordinator, Callback<Boolean> callback) { TestThreadUtils.runOnUiThreadBlocking(() -> coordinator.show(callback)); waitUntilViewMatchesCondition(withId(R.id.button_init_ok), isCompletelyDisplayed()); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillUiUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillUiUtils.java index 3bcf3608..60966b2 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillUiUtils.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill/AutofillUiUtils.java
@@ -4,6 +4,7 @@ package org.chromium.chrome.browser.autofill; +import android.app.Activity; import android.content.ComponentCallbacks; import android.content.Context; import android.content.res.Configuration; @@ -26,6 +27,8 @@ import org.chromium.base.ApiCompatibilityUtils; import org.chromium.base.ContextUtils; import org.chromium.chrome.R; +import org.chromium.chrome.browser.feedback.HelpAndFeedbackLauncherImpl; +import org.chromium.chrome.browser.profiles.Profile; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -61,6 +64,16 @@ int NOT_ENOUGH_INFO = 6; int NONE = 7; } + + /** + * Launches the Autofill help page on top of the current @{link android.app.Activity} and + * current @{link Profile}. + */ + public static void launchAutofillHelpPage(Activity activity, Profile profile) { + HelpAndFeedbackLauncherImpl.getInstance().show( + activity, activity.getString(R.string.help_context_autofill), profile, null); + } + /** * Show Tooltip UI. *
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 bfed528..0cc03b2 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
@@ -9,7 +9,6 @@ import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.app.Activity; -import android.content.Context; import android.content.DialogInterface; import android.graphics.Color; import android.graphics.drawable.ColorDrawable; @@ -42,8 +41,8 @@ import org.chromium.base.ApiCompatibilityUtils; import org.chromium.chrome.R; +import org.chromium.chrome.browser.autofill.AutofillUiUtils; import org.chromium.chrome.browser.autofill.settings.CreditCardNumberFormattingTextWatcher; -import org.chromium.chrome.browser.feedback.HelpAndFeedbackLauncherImpl; import org.chromium.chrome.browser.profiles.Profile; import org.chromium.components.browser_ui.settings.SettingsUtils; import org.chromium.components.browser_ui.widget.AlwaysDismissedDialog; @@ -76,7 +75,7 @@ private static EditorObserverForTest sObserverForTest; - private final Context mContext; + private final Activity mActivity; private final Handler mHandler; private final TextView.OnEditorActionListener mEditorActionListener; private final int mHalfRowMargin; @@ -115,7 +114,7 @@ super(activity, R.style.Theme_Chromium_Fullscreen); // Sets transparent background for animating content view. getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); - mContext = activity; + mActivity = activity; mHandler = new Handler(); mIsDismissed = false; mEditorActionListener = new TextView.OnEditorActionListener() { @@ -172,12 +171,6 @@ getWindow().setAttributes(attributes); } - /** Launches the Autofill help page on top of the current Context and current Profile. */ - public static void launchAutofillHelpPage(Context context, Profile profile) { - HelpAndFeedbackLauncherImpl.getInstance().show((Activity) context, - context.getString(R.string.help_context_autofill), profile, null); - } - /** * Prepares the toolbar for use. * @@ -202,7 +195,7 @@ mDeleteRunnable.run(); animateOutDialog(); } else if (item.getItemId() == R.id.help_menu_id) { - launchAutofillHelpPage(mContext, mProfile); + AutofillUiUtils.launchAutofillHelpPage(mActivity, mProfile); } return true; } @@ -406,7 +399,7 @@ addFieldViewToEditor(mDataView, fieldModel); } else { // Create a LinearLayout to put it and the next view side by side. - LinearLayout rowLayout = new LinearLayout(mContext); + LinearLayout rowLayout = new LinearLayout(mActivity); mDataView.addView(rowLayout); View firstView = addFieldViewToEditor(rowLayout, fieldModel); @@ -448,9 +441,9 @@ View childView = null; if (fieldModel.getInputTypeHint() == EditorFieldModel.INPUT_TYPE_HINT_ICONS) { - childView = new EditorIconsField(mContext, parent, fieldModel).getLayout(); + childView = new EditorIconsField(mActivity, parent, fieldModel).getLayout(); } else if (fieldModel.getInputTypeHint() == EditorFieldModel.INPUT_TYPE_HINT_LABEL) { - childView = new EditorLabelField(mContext, parent, fieldModel).getLayout(); + childView = new EditorLabelField(mActivity, parent, fieldModel).getLayout(); } else if (fieldModel.getInputTypeHint() == EditorFieldModel.INPUT_TYPE_HINT_DROPDOWN) { Runnable prepareEditorRunnable = new Runnable() { @Override @@ -465,7 +458,7 @@ } }; EditorDropdownField dropdownView = - new EditorDropdownField(mContext, parent, fieldModel, prepareEditorRunnable); + new EditorDropdownField(mActivity, parent, fieldModel, prepareEditorRunnable); mFieldViews.add(dropdownView); mDropdownFields.add(dropdownView.getDropdown()); @@ -475,7 +468,7 @@ checkbox.setId(R.id.payments_edit_checkbox); checkbox.setText(fieldModel.getLabel()); checkbox.setChecked(fieldModel.isChecked()); - checkbox.setMinimumHeight(mContext.getResources().getDimensionPixelSize( + checkbox.setMinimumHeight(mActivity.getResources().getDimensionPixelSize( R.dimen.editor_dialog_checkbox_min_height)); checkbox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override @@ -499,7 +492,7 @@ } EditorTextField inputLayout = new EditorTextField( - mContext, fieldModel, mEditorActionListener, filter, formatter); + mActivity, fieldModel, mEditorActionListener, filter, formatter); mFieldViews.add(inputLayout); EditText input = inputLayout.getEditText(); @@ -527,15 +520,15 @@ */ public void show(EditorModel editorModel) { // If an asynchronous task calls show, while the activity is already finishing, return. - if (((Activity) mContext).isFinishing()) return; + if (mActivity.isFinishing()) return; setOnShowListener(this); setOnDismissListener(this); mEditorModel = editorModel; - mLayout = LayoutInflater.from(mContext).inflate(R.layout.payment_request_editor, null); + mLayout = LayoutInflater.from(mActivity).inflate(R.layout.payment_request_editor, null); setContentView(mLayout); - mFooter = LayoutInflater.from(mContext).inflate( + mFooter = LayoutInflater.from(mActivity).inflate( R.layout.editable_option_editor_footer, null, false); prepareToolbar();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill/settings/AutofillEditorBase.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill/settings/AutofillEditorBase.java index 3a39dc4..2986be5d 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/autofill/settings/AutofillEditorBase.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill/settings/AutofillEditorBase.java
@@ -27,7 +27,7 @@ import androidx.fragment.app.Fragment; import org.chromium.chrome.R; -import org.chromium.chrome.browser.autofill.prefeditor.EditorDialog; +import org.chromium.chrome.browser.autofill.AutofillUiUtils; import org.chromium.chrome.browser.profiles.Profile; import org.chromium.components.browser_ui.settings.SettingsUtils; import org.chromium.components.browser_ui.widget.FadingEdgeScrollView; @@ -93,8 +93,10 @@ deleteEntry(); getActivity().finish(); return true; - } else if (item.getItemId() == R.id.help_menu_id) { - EditorDialog.launchAutofillHelpPage(getActivity(), Profile.getLastUsedRegularProfile()); + } + if (item.getItemId() == R.id.help_menu_id) { + AutofillUiUtils.launchAutofillHelpPage( + getActivity(), Profile.getLastUsedRegularProfile()); return true; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill/settings/AutofillPaymentMethodsFragment.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill/settings/AutofillPaymentMethodsFragment.java index 0e938171..84f2b351 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/autofill/settings/AutofillPaymentMethodsFragment.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill/settings/AutofillPaymentMethodsFragment.java
@@ -10,6 +10,9 @@ import android.hardware.biometrics.BiometricManager; import android.os.Build; import android.os.Bundle; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; import androidx.appcompat.content.res.AppCompatResources; import androidx.core.hardware.fingerprint.FingerprintManagerCompat; @@ -19,10 +22,12 @@ import org.chromium.base.ApiCompatibilityUtils; import org.chromium.chrome.R; +import org.chromium.chrome.browser.autofill.AutofillUiUtils; import org.chromium.chrome.browser.autofill.PersonalDataManager; import org.chromium.chrome.browser.autofill.PersonalDataManager.CreditCard; import org.chromium.chrome.browser.payments.AndroidPaymentAppFactory; import org.chromium.chrome.browser.payments.ServiceWorkerPaymentAppBridge; +import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.settings.ChromeManagedPreferenceDelegate; import org.chromium.components.browser_ui.settings.ChromeSwitchPreference; @@ -37,7 +42,7 @@ @Override public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { getActivity().setTitle(R.string.autofill_payment_methods); - + setHasOptionsMenu(true); PreferenceScreen screen = getPreferenceManager().createPreferenceScreen(getStyledContext()); // Suppresses unwanted animations while Preferences are removed from and re-added to the // screen. @@ -47,6 +52,24 @@ } @Override + public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { + menu.clear(); + MenuItem help = + menu.add(Menu.NONE, R.id.menu_id_targeted_help, Menu.NONE, R.string.menu_help); + help.setIcon(R.drawable.ic_help_and_feedback); + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + if (item.getItemId() == R.id.menu_id_targeted_help) { + AutofillUiUtils.launchAutofillHelpPage( + getActivity(), Profile.getLastUsedRegularProfile()); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override public void onResume() { super.onResume(); // Always rebuild our list of credit cards. Although we could detect if credit cards are
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill/settings/AutofillProfilesFragment.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill/settings/AutofillProfilesFragment.java index 3a13b0a..e3ac6c7 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/autofill/settings/AutofillProfilesFragment.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill/settings/AutofillProfilesFragment.java
@@ -8,6 +8,9 @@ import android.graphics.PorterDuff; import android.graphics.drawable.Drawable; import android.os.Bundle; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; import androidx.annotation.VisibleForTesting; import androidx.preference.Preference; @@ -17,6 +20,7 @@ import org.chromium.base.ApiCompatibilityUtils; import org.chromium.base.StrictModeContext; import org.chromium.chrome.R; +import org.chromium.chrome.browser.autofill.AutofillUiUtils; import org.chromium.chrome.browser.autofill.PersonalDataManager; import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile; import org.chromium.chrome.browser.autofill.prefeditor.EditorDialog; @@ -41,7 +45,7 @@ @Override public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { getActivity().setTitle(R.string.autofill_addresses_settings_title); - + setHasOptionsMenu(true); PreferenceScreen screen = getPreferenceManager().createPreferenceScreen(getStyledContext()); // Suppresses unwanted animations while Preferences are removed from and re-added to the // screen. @@ -51,6 +55,24 @@ } @Override + public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { + menu.clear(); + MenuItem help = + menu.add(Menu.NONE, R.id.menu_id_targeted_help, Menu.NONE, R.string.menu_help); + help.setIcon(R.drawable.ic_help_and_feedback); + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + if (item.getItemId() == R.id.menu_id_targeted_help) { + AutofillUiUtils.launchAutofillHelpPage( + getActivity(), Profile.getLastUsedRegularProfile()); + return true; + } + return super.onOptionsItemSelected(item); + } + + @Override public void onResume() { super.onResume(); // Always rebuild our list of profiles. Although we could detect if profiles are added or
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ChromeContextMenuPopulator.java b/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ChromeContextMenuPopulator.java index 15e9fc8a..2db3148 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ChromeContextMenuPopulator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ChromeContextMenuPopulator.java
@@ -91,6 +91,7 @@ private final LensQueryResult mLensQueryResultWithShoppingItent = (new LensQueryResult.Builder()).withIsShoppyIntent(true).build(); private boolean mEnableLensWithSearchByImageText; + private boolean mIsLensIntentInProgress; private @Nullable UkmRecorder.Bridge mUkmRecorderBridge; private ContextMenuNativeDelegate mNativeDelegate; private static final String LENS_SEARCH_MENU_ITEM_KEY = "searchWithGoogleLensMenuItem"; @@ -774,6 +775,11 @@ TrackerFactory.getTrackerForProfile(Profile.getLastUsedRegularProfile()); if (tracker.isInitialized()) tracker.dismissed(FeatureConstants.EPHEMERAL_TAB_FEATURE); } + + if (!mIsLensIntentInProgress) { + // TODO(crbug/1158604): Remove leftover Lens dependencies. + LensUtils.terminateLensConnectionsIfNecessary(mItemDelegate.isIncognito()); + } } private WindowAndroid getWindow() { @@ -834,6 +840,7 @@ */ protected void searchWithGoogleLens( boolean requiresConfirmation, @Nullable LensQueryResult lensQueryResult) { + mIsLensIntentInProgress = true; mNativeDelegate.retrieveImageForShare(ContextMenuImageFormat.PNG, (Uri imageUri) -> { ShareHelper.shareImageWithGoogleLens(getWindow(), imageUri, mItemDelegate.isIncognito(), mParams.getSrcUrl(), mParams.getTitleText(), mParams.getPageUrl(),
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ContextMenuHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ContextMenuHelper.java index 6e8d394..f3ecd364 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ContextMenuHelper.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ContextMenuHelper.java
@@ -224,6 +224,8 @@ Log.i(TAG, "Created mCurrentContextMenu: " + mCurrentContextMenu); Log.i(TAG, "Activity was " + mWindow.getActivity().get() + " when the menu was created."); + // TODO(crbug/1158604): Remove leftover Lens dependencies. + LensUtils.startLensConnectionIfNecessary(mIsIncognito); if (mChipDelegate != null) { menuCoordinator.displayMenuWithChip(mWindow, mWebContents, mCurrentContextMenuParams, items, mCallback, mOnMenuShown, mOnMenuClosed, mChipDelegate);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/downloads/OfflinePageDownloadBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/downloads/OfflinePageDownloadBridge.java index ba6c035..0fa34357 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/downloads/OfflinePageDownloadBridge.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/downloads/OfflinePageDownloadBridge.java
@@ -158,7 +158,9 @@ intent.setPackage(context.getPackageName()); intent.putExtra(Browser.EXTRA_APPLICATION_ID, context.getPackageName()); intent.putExtra(CustomTabIntentDataProvider.EXTRA_UI_TYPE, CustomTabsUiType.OFFLINE_PAGE); - intent.putExtra(IntentHandler.EXTRA_OPEN_NEW_INCOGNITO_TAB, isIncognito); + // TODO(crbug.com/1148275): Pass isIncognito boolean here after finding a way not to + // reload the downloaded page for Incognito CCT. + intent.putExtra(IntentHandler.EXTRA_OPEN_NEW_INCOGNITO_TAB, false); IntentHandler.addTrustedIntentExtras(intent); if (!(context instanceof Activity)) intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/share/LensUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/share/LensUtils.java index 538ffe98..2f7a945 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/share/LensUtils.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/share/LensUtils.java
@@ -16,6 +16,8 @@ import org.chromium.chrome.browser.IntentHandler; import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.gsa.GSAState; +import org.chromium.chrome.browser.lens.LensController; +import org.chromium.chrome.browser.lens.LensIntentParams; import org.chromium.chrome.browser.lens.LensQueryResult; import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.signin.services.IdentityServicesProvider; @@ -28,6 +30,7 @@ /** * This class provides utilities for intenting into Google Lens. */ +// TODO(crbug/1157496): Consolidate param-checks into a single function. public class LensUtils { private static final String LENS_CONTRACT_URI = "googleapp://lens"; private static final String LENS_DIRECT_INTENT_CONTRACT_URI = "google://lens"; @@ -47,6 +50,8 @@ "minAgsaVersionNameForShopping"; private static final String MIN_AGSA_VERSION_DIRECT_INTENT_FEATURE_PARAM_NAME = "minAgsaVersionForDirectIntent"; + private static final String MIN_AGSA_VERSION_DIRECT_INTENT_SDK_FEATURE_PARAM_NAME = + "minAgsaVersionForDirectIntentSdk"; private static final String USE_SEARCH_BY_IMAGE_TEXT_FEATURE_PARAM_NAME = "useSearchByImageText"; private static final String LENS_SHOPPING_ALLOWLIST_ENTRIES_FEATURE_PARAM_NAME = @@ -58,12 +63,15 @@ private static final String SEND_ALT_PARAM_NAME = "sendAlt"; private static final String SEND_PAGE_PARAM_NAME = "sendPage"; private static final String USE_DIRECT_INTENT_FEATURE_PARAM_NAME = "useDirectIntent"; + private static final String USE_DIRECT_INTENT_SDK_INTEGRATION_PARAM_NAME = + "useDirectIntentSdkIntegration"; private static final String DISABLE_ON_INCOGNITO_PARAM_NAME = "disableOnIncognito"; private static final String ORDER_SHARE_IMAGE_BEFORE_LENS_PARAM_NAME = "orderShareImageBeforeLens"; private static final String MIN_AGSA_VERSION_NAME_FOR_LENS_POSTCAPTURE = "10.65"; private static final String MIN_AGSA_VERSION_NAME_FOR_LENS_CHROME_SHOPPING_INTENT = "11.16"; private static final String MIN_AGSA_VERSION_NAME_FOR_LENS_DIRECT_INTENT = "11.34"; + private static final String MIN_AGSA_VERSION_NAME_FOR_LENS_DIRECT_INTENT_SDK = "11.39.7"; private static final int LENS_INTENT_TYPE_LENS_CHROME_SHOPPING = 18; private static final String LENS_SHOPPING_FEATURE_FLAG_VARIANT_NAME = "lensShopVariation"; private static final String LENS_DEFAULT_SHOPPING_URL_PATTERNS = @@ -221,6 +229,32 @@ } /** + * Gets the minimum AGSA version required to support the direct intent SDK + * integration on this device. Takes the value from a server provided value if a + * field trial is active but otherwise will take the value from a client side + * default (unless the lens feature is not enabled at all, in which case return + * an empty string). + * + * @return The minimum version name string or an empty string if not available. + */ + public static String getMinimumAgsaVersionForDirectIntentSdkSupport() { + // Shopping feature AGSA version takes priority over Search with Google Lens + if (ChromeFeatureList.isEnabled(ChromeFeatureList.CONTEXT_MENU_SEARCH_WITH_GOOGLE_LENS)) { + final String serverProvidedMinAgsaVersion = + ChromeFeatureList.getFieldTrialParamByFeature( + ChromeFeatureList.CONTEXT_MENU_SEARCH_WITH_GOOGLE_LENS, + MIN_AGSA_VERSION_DIRECT_INTENT_SDK_FEATURE_PARAM_NAME); + if (TextUtils.isEmpty(serverProvidedMinAgsaVersion)) { + // Falls into this block if the user enabled the feature using chrome://flags + // and the param was not set by the server. + return MIN_AGSA_VERSION_NAME_FOR_LENS_DIRECT_INTENT_SDK; + } + return serverProvidedMinAgsaVersion; + } + return ""; + } + + /** * Checks whether the device is below Android O. We restrict to these versions * to limit to OS"s where image processing vulnerabilities can be retroactively * fixed if they are discovered in the future. @@ -342,6 +376,59 @@ return intent; } + /** + * Start an early Lens AGSA connection if feature parameter is enabled and client is not + * incognito. Eligibity checks happen in LensController. + * + * @param isIncognito Whether the client is incognito + */ + public static void startLensConnectionIfNecessary(boolean isIncognito) { + // TODO(crbug/1157543): Pass isIncognito through to LensController. + if (!isIncognito) { + LensController.getInstance().startLensConnection(); + } + } + + /** + * Terminate an early Lens AGSA connection if feature parameter is enabled and client is not + * incognito. Eligibity checks happen in LensController. + * + * @param isIncognito Whether the client is incognito + */ + public static void terminateLensConnectionsIfNecessary(boolean isIncognito) { + // TODO(crbug/1157543): Pass isIncognito through to LensController. + if (!isIncognito) { + LensController.getInstance().terminateLensConnections(); + } + } + + /** + * Build a LensIntentParams object from the provided parameters in order to intent into Lens. + * + * @param imageUri The content provider URI generated by chrome (or + * empty URI) if only resolving the activity. + * @param isIncognito Whether the current tab is in incognito mode. + * @param srcUrl The 'src' attribute of the image. + * @param titleOrAltText The 'title' or, if empty, the 'alt' attribute of the + * image. + * @param pageUrl The url of the top level frame of the page. + * @param requiresConfirmation Whether the request requires an confirmation dialog. + * @return The intent parameters to intent to Google Lens. + */ + public static LensIntentParams buildLensIntentParams(final Uri imageUri, + final boolean isIncognito, final String srcUrl, final String titleOrAltText, + final String pageUrl, final boolean requiresConfirmation) { + LensIntentParams.Builder intentParamsBuilder = new LensIntentParams.Builder(); + return intentParamsBuilder.withImageUri(imageUri) + .withIsIncognito(isIncognito) + .withRequiresConfirmation(requiresConfirmation) + .withIntentType(getLensShoppingIntentType()) + .withImageTitleOrAltText(titleOrAltText) + .withSrcUrl(srcUrl) + .withPageUrl(pageUrl) + .build(); + } + public static boolean isGoogleLensFeatureEnabled(boolean isIncognito) { return ChromeFeatureList.isEnabled(ChromeFeatureList.CONTEXT_MENU_SEARCH_WITH_GOOGLE_LENS) && !(isIncognito @@ -380,6 +467,24 @@ } /** + * Enables the starting of LenActivity directly, rather than going through the Lens + * session running in AGSA. Also checks if the required AGSA version for direct intent + * is below or equal to the provided version. + */ + public static boolean useDirectIntentSdkIntegration(final Context context) { + // TODO(https://crbug.com/1146591): Refactor GSA state checks to avoid multiple version + // grabs. + String agsaVersionName = sFakeInstalledAgsaVersion != null + ? sFakeInstalledAgsaVersion + : getLensActivityVersionNameIfAvailable(context); + return ChromeFeatureList.getFieldTrialParamByFeatureAsBoolean( + ChromeFeatureList.CONTEXT_MENU_SEARCH_WITH_GOOGLE_LENS, + USE_DIRECT_INTENT_SDK_INTEGRATION_PARAM_NAME, false) + && !GSAState.getInstance(context).isAgsaVersionBelowMinimum( + agsaVersionName, getMinimumAgsaVersionForDirectIntentSdkSupport()); + } + + /** * Whether to display the lens menu item with the search by image text */ public static boolean useLensWithSearchByImageText() {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/share/ShareHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/share/ShareHelper.java index 8f20213..5aa434a 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/share/ShareHelper.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/share/ShareHelper.java
@@ -27,6 +27,8 @@ import org.chromium.base.StrictModeContext; import org.chromium.base.metrics.RecordHistogram; import org.chromium.chrome.R; +import org.chromium.chrome.browser.lens.LensController; +import org.chromium.chrome.browser.lens.LensIntentParams; import org.chromium.chrome.browser.lens.LensQueryResult; import org.chromium.chrome.browser.preferences.ChromePreferenceKeys; import org.chromium.chrome.browser.preferences.SharedPreferencesManager; @@ -134,19 +136,27 @@ public static void shareImageWithGoogleLens(final WindowAndroid window, Uri imageUri, boolean isIncognito, GURL srcUrl, String titleOrAltText, GURL pageUrl, LensQueryResult lensQueryResult, boolean requiresConfirmation) { - Intent shareIntent = - LensUtils.getShareWithGoogleLensIntent(ContextUtils.getApplicationContext(), - imageUri, isIncognito, SystemClock.elapsedRealtimeNanos(), srcUrl, - titleOrAltText, pageUrl, lensQueryResult, requiresConfirmation); - try { - // Pass an empty callback to ensure the triggered activity can identify the source - // of the intent (startActivityForResult allows app identification). - fireIntent(window, shareIntent, (w, resultCode, data) -> {}); - } catch (ActivityNotFoundException e) { - // The initial version check should guarantee that the activity is available. However, - // the exception may be thrown in test environments after mocking out the version check. - if (Boolean.TRUE.equals(sIgnoreActivityNotFoundException)) return; - throw e; + if (LensUtils.useDirectIntentSdkIntegration(ContextUtils.getApplicationContext())) { + LensIntentParams intentParams = LensUtils.buildLensIntentParams(imageUri, isIncognito, + srcUrl.getValidSpecOrEmpty(), titleOrAltText, pageUrl.getValidSpecOrEmpty(), + requiresConfirmation); + LensController.getInstance().startLens(window, intentParams); + } else { + Intent shareIntent = + LensUtils.getShareWithGoogleLensIntent(ContextUtils.getApplicationContext(), + imageUri, isIncognito, SystemClock.elapsedRealtimeNanos(), srcUrl, + titleOrAltText, pageUrl, lensQueryResult, requiresConfirmation); + try { + // Pass an empty callback to ensure the triggered activity can identify the source + // of the intent (startActivityForResult allows app identification). + fireIntent(window, shareIntent, (w, resultCode, data) -> {}); + } catch (ActivityNotFoundException e) { + // The initial version check should guarantee that the activity is available. + // However, the exception may be thrown in test environments after mocking out the + // version check. + if (Boolean.TRUE.equals(sIgnoreActivityNotFoundException)) return; + throw e; + } } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninHelperProvider.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninHelperProvider.java index 86e7be8..27143f6 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninHelperProvider.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninHelperProvider.java
@@ -8,6 +8,7 @@ import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.signin.services.IdentityServicesProvider; +import org.chromium.chrome.browser.signin.services.SigninHelper; import org.chromium.chrome.browser.signin.services.SigninPreferencesManager; import org.chromium.chrome.browser.sync.SyncController;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerBottomSheetCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerBottomSheetCoordinator.java index 1733431..730eedfe 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerBottomSheetCoordinator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerBottomSheetCoordinator.java
@@ -14,6 +14,7 @@ import org.chromium.chrome.browser.incognito.interstitial.IncognitoInterstitialCoordinator; import org.chromium.chrome.browser.incognito.interstitial.IncognitoInterstitialDelegate; import org.chromium.chrome.browser.signin.services.SigninMetricsUtils; +import org.chromium.chrome.browser.signin.services.SigninPreferencesManager; import org.chromium.chrome.browser.signin.ui.account_picker.AccountPickerDelegate; import org.chromium.chrome.browser.tabmodel.TabCreator; import org.chromium.chrome.browser.tabmodel.TabModel; @@ -81,7 +82,10 @@ BottomSheetController bottomSheetController, AccountPickerDelegate accountPickerDelegate, IncognitoInterstitialDelegate incognitoInterstitialDelegate) { + SigninPreferencesManager.getInstance().incrementAccountPickerBottomSheetShownCount(); SigninMetricsUtils.logAccountConsistencyPromoAction(AccountConsistencyPromoAction.SHOWN); + SigninMetricsUtils.logAccountConsistencyPromoShownCount( + "Signin.AccountConsistencyPromoAction.Shown.Count"); mAccountPickerBottomSheetMediator = new AccountPickerBottomSheetMediator( activity, accountPickerDelegate, this::dismissBottomSheet);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerBottomSheetMediator.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerBottomSheetMediator.java index fe85bdb7..7eb5e0e 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerBottomSheetMediator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerBottomSheetMediator.java
@@ -222,6 +222,8 @@ private void signIn() { mModel.set(AccountPickerBottomSheetProperties.VIEW_STATE, ViewState.SIGNIN_IN_PROGRESS); + SigninMetricsUtils.logAccountConsistencyPromoShownCount( + "Signin.AccountConsistencyPromoAction.SignedIn.Count"); if (TextUtils.equals(mSelectedAccountName, mAddedAccountName)) { SigninMetricsUtils.logAccountConsistencyPromoAction( AccountConsistencyPromoAction.SIGNED_IN_WITH_ADDED_ACCOUNT);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/sync/settings/ManageSyncSettings.java b/chrome/android/java/src/org/chromium/chrome/browser/sync/settings/ManageSyncSettings.java index c4d64df..4a25aca 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/sync/settings/ManageSyncSettings.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/sync/settings/ManageSyncSettings.java
@@ -205,9 +205,11 @@ mTurnOffSync.setOnPreferenceClickListener( SyncSettingsUtils.toOnClickListener(this, this::onTurnOffSyncClicked)); + Profile profile = Profile.getLastUsedRegularProfile(); if (ChromeFeatureList.isEnabled(ChromeFeatureList.MOBILE_IDENTITY_CONSISTENCY) && !mIsFromSigninScreen) { - mTurnOffSync.setVisible(true); + // Child profiles should not be able to sign out. + mTurnOffSync.setVisible(!profile.isChild()); findPreference(PREF_ADVANCED_CATEGORY).setVisible(true); /** @@ -239,7 +241,6 @@ type.setOnPreferenceChangeListener(this); } - Profile profile = Profile.getLastUsedRegularProfile(); if (profile.isChild()) { mGoogleActivityControls.setSummary( R.string.sign_in_google_activity_controls_summary_child_account); @@ -392,7 +393,9 @@ PersonalDataManager.setPaymentsIntegrationEnabled(mSyncEverything.isChecked() || (mSyncPaymentsIntegration.isChecked() && mSyncAutofill.isChecked())); - if (ChromeFeatureList.isEnabled(ChromeFeatureList.MOBILE_IDENTITY_CONSISTENCY)) { + // For child profiles sync should always be on. + if (ChromeFeatureList.isEnabled(ChromeFeatureList.MOBILE_IDENTITY_CONSISTENCY) + && !Profile.getLastUsedRegularProfile().isChild()) { boolean atLeastOneDataTypeEnabled = mSyncEverything.isChecked() || selectedModelTypes.size() > 0; if (mProfileSyncService.isSyncRequested() && !atLeastOneDataTypeEnabled) {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/externalnav/UrlOverridingTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/externalnav/UrlOverridingTest.java index a4c33d4..8d04f49e 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/externalnav/UrlOverridingTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/externalnav/UrlOverridingTest.java
@@ -36,6 +36,7 @@ import org.chromium.base.test.util.CommandLineFlags; import org.chromium.base.test.util.Criteria; import org.chromium.base.test.util.CriteriaHelper; +import org.chromium.base.test.util.DisabledTest; import org.chromium.base.test.util.ScalableTimeout; import org.chromium.chrome.browser.ChromeTabbedActivity; import org.chromium.chrome.browser.document.ChromeLauncherActivity; @@ -451,6 +452,7 @@ @Test @SmallTest + @DisabledTest(message = "https://crbug.com/1159767") public void testRedirectionFromIntentWarm() throws Exception { Context context = ContextUtils.getApplicationContext(); // TODO(crbug.com/1153686): This test times out on M tablets.
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/share/LensUtilsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/share/LensUtilsTest.java index 3c0ffd68..a95ae50b 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/share/LensUtilsTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/share/LensUtilsTest.java
@@ -29,6 +29,7 @@ import org.chromium.chrome.browser.IntentHandler; import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.flags.ChromeSwitches; +import org.chromium.chrome.browser.lens.LensIntentParams; import org.chromium.chrome.browser.lens.LensQueryResult; import org.chromium.chrome.test.ChromeBrowserTestRule; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; @@ -914,6 +915,36 @@ assertTrue(isInShoppingAllowlistOnUiThread(googleShoppingItemUrl)); } + /** + * Test {@link LensUtils#buildLensIntentParams()} method for building intent parameters for + * startng Lens. + */ + @Test + @SmallTest + public void buildLensIntentParamsTest() { + final String contentUrl = "content://image-url"; + final boolean isIncognito = false; + final String srcUrl = "https://www.google.com"; + final String titleOrAltText = "Image Title"; + final String pageUrl = "https://www.google.com"; + final boolean requiresConfirmation = false; + LensIntentParams lensIntentParams = LensUtils.buildLensIntentParams(Uri.parse(contentUrl), + isIncognito, srcUrl, titleOrAltText, pageUrl, requiresConfirmation); + + Assert.assertEquals("Lens intent parameters has incorrect image URI.", contentUrl, + lensIntentParams.getImageUri().toString()); + Assert.assertEquals("Lens intent parameters has incorrect incognito value.", isIncognito, + lensIntentParams.getIsIncognito()); + Assert.assertEquals("Lens intent parameters has incorrect src URL.", srcUrl, + lensIntentParams.getSrcUrl()); + Assert.assertEquals("Lens intent parameters has incorrect title or alt text.", + titleOrAltText, lensIntentParams.getImageTitleOrAltText()); + Assert.assertEquals("Lens intent parameters has incorrect page URL.", pageUrl, + lensIntentParams.getPageUrl()); + Assert.assertEquals("Lens intent parameters has incorrect requires confirmation value.", + requiresConfirmation, lensIntentParams.getRequiresConfirmation()); + } + private boolean isInShoppingAllowlistOnUiThread(GURL imageUri) { return TestThreadUtils.runOnUiThreadBlockingNoException( () -> LensUtils.isInShoppingAllowlist(imageUri));
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/AccountPickerBottomSheetTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/AccountPickerBottomSheetTest.java index 888c675..bd69bf9 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/AccountPickerBottomSheetTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/AccountPickerBottomSheetTest.java
@@ -33,6 +33,7 @@ import androidx.test.filters.MediumTest; import org.hamcrest.Matcher; +import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.ClassRule; @@ -54,6 +55,8 @@ import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.flags.ChromeSwitches; import org.chromium.chrome.browser.incognito.interstitial.IncognitoInterstitialDelegate; +import org.chromium.chrome.browser.preferences.ChromePreferenceKeys; +import org.chromium.chrome.browser.preferences.SharedPreferencesManager; import org.chromium.chrome.browser.signin.account_picker.AccountPickerBottomSheetCoordinator; import org.chromium.chrome.browser.signin.ui.account_picker.AccountPickerDelegate; import org.chromium.chrome.browser.tabmodel.TabCreator; @@ -98,6 +101,8 @@ /* accountName= */ "test.account2@gmail.com", /* avatar= */ null, /* fullName= */ null, /* givenName= */ null); + private final int mShowCount = 1; + // Disable animations to reduce flakiness. @ClassRule public static final DisableAnimationsTestRule sNoAnimationsRule = @@ -144,6 +149,14 @@ when(mAccountPickerDelegateMock.isIncognitoModeEnabled()).thenReturn(true); mAccountManagerTestRule.addAccount(PROFILE_DATA1); mAccountManagerTestRule.addAccount(PROFILE_DATA2); + SharedPreferencesManager.getInstance().removeKey( + ChromePreferenceKeys.ACCOUNT_PICKER_BOTTOM_SHEET_SHOWN_COUNT); + } + + @After + public void tearDown() { + SharedPreferencesManager.getInstance().removeKey( + ChromePreferenceKeys.ACCOUNT_PICKER_BOTTOM_SHEET_SHOWN_COUNT); } @Test @@ -151,9 +164,25 @@ public void testCollapsedSheetWithAccount() { MetricsUtils.HistogramDelta accountConsistencyHistogram = new HistogramDelta( "Signin.AccountConsistencyPromoAction", AccountConsistencyPromoAction.SHOWN); + MetricsUtils.HistogramDelta shownCountHistogram = + new HistogramDelta("Signin.AccountConsistencyPromoAction.Shown.Count", mShowCount); buildAndShowCollapsedBottomSheet(); checkCollapsedAccountList(PROFILE_DATA1); Assert.assertEquals(1, accountConsistencyHistogram.getDelta()); + Assert.assertEquals(1, shownCountHistogram.getDelta()); + } + + @Test + @MediumTest + public void testPromoShownHistogramMaxCount() { + final int max = 100; + SharedPreferencesManager.getInstance().writeInt( + ChromePreferenceKeys.ACCOUNT_PICKER_BOTTOM_SHEET_SHOWN_COUNT, max + 5); + MetricsUtils.HistogramDelta shownCountHistogram = + new HistogramDelta("Signin.AccountConsistencyPromoAction.Shown.Count", max); + buildAndShowCollapsedBottomSheet(); + checkCollapsedAccountList(PROFILE_DATA1); + Assert.assertEquals(1, shownCountHistogram.getDelta()); } @Test @@ -352,9 +381,12 @@ MetricsUtils.HistogramDelta accountConsistencyHistogram = new HistogramDelta("Signin.AccountConsistencyPromoAction", AccountConsistencyPromoAction.SIGNED_IN_WITH_DEFAULT_ACCOUNT); + MetricsUtils.HistogramDelta signedInCountHistogram = new HistogramDelta( + "Signin.AccountConsistencyPromoAction.SignedIn.Count", mShowCount); buildAndShowCollapsedBottomSheet(); clickContinueButtonAndCheckSignInInProgressSheet(); Assert.assertEquals(1, accountConsistencyHistogram.getDelta()); + Assert.assertEquals(1, signedInCountHistogram.getDelta()); } @Test @@ -363,12 +395,15 @@ MetricsUtils.HistogramDelta accountConsistencyHistogram = new HistogramDelta("Signin.AccountConsistencyPromoAction", AccountConsistencyPromoAction.SIGNED_IN_WITH_NON_DEFAULT_ACCOUNT); + MetricsUtils.HistogramDelta signedInCountHistogram = new HistogramDelta( + "Signin.AccountConsistencyPromoAction.SignedIn.Count", mShowCount); buildAndShowExpandedBottomSheet(); onView(withText(PROFILE_DATA2.getAccountEmail())).perform(click()); CriteriaHelper.pollUiThread(mCoordinator.getBottomSheetViewForTesting().findViewById( R.id.account_picker_selected_account)::isShown); clickContinueButtonAndCheckSignInInProgressSheet(); Assert.assertEquals(1, accountConsistencyHistogram.getDelta()); + Assert.assertEquals(1, signedInCountHistogram.getDelta()); } @Test @@ -383,6 +418,8 @@ MetricsUtils.HistogramDelta signedInWithNonDefaultAccountHistogram = new HistogramDelta("Signin.AccountConsistencyPromoAction", AccountConsistencyPromoAction.SIGNED_IN_WITH_NON_DEFAULT_ACCOUNT); + MetricsUtils.HistogramDelta signedInCountHistogram = new HistogramDelta( + "Signin.AccountConsistencyPromoAction.SignedIn.Count", mShowCount); buildAndShowExpandedBottomSheet(); onVisibleView(withText(R.string.signin_add_account_to_device)).perform(click()); verify(mAccountPickerDelegateMock).addAccount(callbackArgumentCaptor.capture()); @@ -396,6 +433,7 @@ Assert.assertEquals(1, addAccountHistogram.getDelta()); Assert.assertEquals(1, signedInWithAddedAccountHistogram.getDelta()); Assert.assertEquals(0, signedInWithNonDefaultAccountHistogram.getDelta()); + Assert.assertEquals(1, signedInCountHistogram.getDelta()); } @Test
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SigninHelperTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SigninHelperTest.java index be7b8a5..de307bc5b 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SigninHelperTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SigninHelperTest.java
@@ -14,6 +14,7 @@ import org.junit.runner.RunWith; import org.chromium.base.test.util.Batch; +import org.chromium.chrome.browser.signin.services.SigninHelper; import org.chromium.chrome.browser.signin.services.SigninPreferencesManager; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.chrome.test.util.browser.signin.AccountManagerTestRule;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/sync/SyncTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/sync/SyncTest.java index 54d4930..65e13b14 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/sync/SyncTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/sync/SyncTest.java
@@ -23,9 +23,9 @@ import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.flags.ChromeSwitches; import org.chromium.chrome.browser.profiles.Profile; -import org.chromium.chrome.browser.signin.SigninHelper; import org.chromium.chrome.browser.signin.SigninHelperProvider; import org.chromium.chrome.browser.signin.services.IdentityServicesProvider; +import org.chromium.chrome.browser.signin.services.SigninHelper; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.chrome.test.util.browser.Features; import org.chromium.chrome.test.util.browser.signin.MockChangeEventChecker;
diff --git a/chrome/android/profiles/newest.txt b/chrome/android/profiles/newest.txt index 115fc5cc..0a573a32 100644 --- a/chrome/android/profiles/newest.txt +++ b/chrome/android/profiles/newest.txt
@@ -1 +1 @@ -chromeos-chrome-amd64-89.0.4351.0_rc-r1-merged.afdo.bz2 +chromeos-chrome-amd64-89.0.4357.3_rc-r1-merged.afdo.bz2
diff --git a/chrome/app/settings_strings.grdp b/chrome/app/settings_strings.grdp index a000d7d..c795c1d 100644 --- a/chrome/app/settings_strings.grdp +++ b/chrome/app/settings_strings.grdp
@@ -559,20 +559,23 @@ <message name="IDS_SETTINGS_PASSWORD_DELETED_PASSWORD_FROM_ACCOUNT_AND_DEVICE" desc="Label for an undo tooltip following deletion of a password from the account and the device."> Password deleted from this device and your Google Account </message> - <!-- TODO(crbug.com/1139263): Make it translateable and add translation screenshots once final mocks are available. --> - <message translateable="false" name="IDS_SETTINGS_PASSWORD_MOVE_PASSWORDS_TO_ACCOUNT" desc="Message displayed in the moving multiple passwords to the user Google Account banner."> - Move them to your Google Account, and make it across-device accessible + <message name="IDS_SETTINGS_PASSWORD_MOVE_PASSWORDS_TO_ACCOUNT" desc="Message displayed in the moving multiple passwords to the user Google Account banner."> + To use them on all your devices, move them to your Google Account </message> - <!-- TODO(crbug.com/1139263): Make it translateable and add translation screenshots once final mocks are available. --> - <message translateable="false" name="IDS_SETTINGS_PASSWORD_MOVE_PASSWORDS_TO_ACCOUNT_COUNT" desc="Message shown in the footer of the moving multiple password to the Google Account dialog. It reflects how many passwords are selected and will be movec."> + <message name="IDS_SETTINGS_PASSWORD_MOVE_PASSWORDS_TO_ACCOUNT_COUNT" desc="Label shown in the link that open moving multiple password dialog."> {COUNT, plural, - =1 {You are moving {COUNT} password from your device to your Google Account} - other {You are moving {COUNT} passwords from your device to your Google Account}} + =1 {{COUNT} password is accessible on this device} + other {{COUNT} passwords are accessible on this device}} </message> - <!-- TODO(crbug.com/1139263): Make it translateable and add translation screenshots once final mocks are available. --> - <message translateable="false" name="IDS_SETTINGS_PASSWORD_MOVE_PASSWORDS_TO_ACCOUNT_DIALOG_TITLE" desc="Title for the dialog that asks the user to select which passwords to move to their Google Account."> + <message name="IDS_SETTINGS_PASSWORD_MOVE_PASSWORDS_TO_ACCOUNT_DIALOG_FOOTER" desc="Footer for the dialog that asks the user to select which passwords to move to their Google Account."> + Passwords will be moved from your device to your Google Account + </message> + <message name="IDS_SETTINGS_PASSWORD_MOVE_PASSWORDS_TO_ACCOUNT_DIALOG_TITLE" desc="Title for the dialog that asks the user to select which passwords to move to their Google Account."> Choose which passwords to move </message> + <message name="IDS_SETTINGS_PASSWORD_MOVE_PASSWORDS_TO_ACCOUNT_SNACKBAR" desc="Text in the snackbar that appears after the user successfuly moved local passwords to their Google Account."> + Passwords moved to your Google Account + </message> <message name="IDS_SETTINGS_PASSWORD_MOVE_TO_ACCOUNT_DIALOG_TITLE" desc="Title for the dialog that confirms whether the user wishes to move a password to their Google Account."> Move to Google Account? </message> @@ -585,9 +588,8 @@ <message name="IDS_SETTINGS_PASSWORD_MOVE_TO_ACCOUNT_DIALOG_CANCEL_BUTTON_TEXT" desc="Text for the button that cancels the action of moving a password to the user Google Account."> No thanks </message> - <!-- TODO(crbug.com/1139263): Make it translateable and add translation screenshots once final mocks are available. --> - <message translateable="false" name="IDS_SETTINGS_PASSWORD_OPEN_MOVE_MULTIPLE_PASSWORDS_TO_ACCOUNT_DIALOG_BUTTON_TEXT" desc="Text for the button that opens the dialog that moves multiple passwords to the user Google Account."> - Move Passwords ... + <message name="IDS_SETTINGS_PASSWORD_OPEN_MOVE_MULTIPLE_PASSWORDS_TO_ACCOUNT_DIALOG_BUTTON_TEXT" desc="Text for the button that opens the dialog that moves multiple passwords to the user Google Account."> + Move passwords </message> <message name="IDS_SETTINGS_PASSWORD_REMOVE_DIALOG_TITLE" desc="Title for the dialog that asks the user which versions of a password to remove (device, Google Account or both)."> Delete password?
diff --git a/chrome/app/settings_strings_grdp/IDS_SETTINGS_PASSWORD_MOVE_PASSWORDS_TO_ACCOUNT.png.sha1 b/chrome/app/settings_strings_grdp/IDS_SETTINGS_PASSWORD_MOVE_PASSWORDS_TO_ACCOUNT.png.sha1 new file mode 100644 index 0000000..80acf6a --- /dev/null +++ b/chrome/app/settings_strings_grdp/IDS_SETTINGS_PASSWORD_MOVE_PASSWORDS_TO_ACCOUNT.png.sha1
@@ -0,0 +1 @@ +eca1d45d15c5cfa5cf94eba96f1ca96f763d1887 \ No newline at end of file
diff --git a/chrome/app/settings_strings_grdp/IDS_SETTINGS_PASSWORD_MOVE_PASSWORDS_TO_ACCOUNT_COUNT.png.sha1 b/chrome/app/settings_strings_grdp/IDS_SETTINGS_PASSWORD_MOVE_PASSWORDS_TO_ACCOUNT_COUNT.png.sha1 new file mode 100644 index 0000000..80acf6a --- /dev/null +++ b/chrome/app/settings_strings_grdp/IDS_SETTINGS_PASSWORD_MOVE_PASSWORDS_TO_ACCOUNT_COUNT.png.sha1
@@ -0,0 +1 @@ +eca1d45d15c5cfa5cf94eba96f1ca96f763d1887 \ No newline at end of file
diff --git a/chrome/app/settings_strings_grdp/IDS_SETTINGS_PASSWORD_MOVE_PASSWORDS_TO_ACCOUNT_DIALOG_FOOTER.png.sha1 b/chrome/app/settings_strings_grdp/IDS_SETTINGS_PASSWORD_MOVE_PASSWORDS_TO_ACCOUNT_DIALOG_FOOTER.png.sha1 new file mode 100644 index 0000000..bfe31349 --- /dev/null +++ b/chrome/app/settings_strings_grdp/IDS_SETTINGS_PASSWORD_MOVE_PASSWORDS_TO_ACCOUNT_DIALOG_FOOTER.png.sha1
@@ -0,0 +1 @@ +886f6d4fe2fb704a0ed8e39365da209ad44fee15 \ No newline at end of file
diff --git a/chrome/app/settings_strings_grdp/IDS_SETTINGS_PASSWORD_MOVE_PASSWORDS_TO_ACCOUNT_DIALOG_TITLE.png.sha1 b/chrome/app/settings_strings_grdp/IDS_SETTINGS_PASSWORD_MOVE_PASSWORDS_TO_ACCOUNT_DIALOG_TITLE.png.sha1 new file mode 100644 index 0000000..bfe31349 --- /dev/null +++ b/chrome/app/settings_strings_grdp/IDS_SETTINGS_PASSWORD_MOVE_PASSWORDS_TO_ACCOUNT_DIALOG_TITLE.png.sha1
@@ -0,0 +1 @@ +886f6d4fe2fb704a0ed8e39365da209ad44fee15 \ No newline at end of file
diff --git a/chrome/app/settings_strings_grdp/IDS_SETTINGS_PASSWORD_MOVE_PASSWORDS_TO_ACCOUNT_SNACKBAR.png.sha1 b/chrome/app/settings_strings_grdp/IDS_SETTINGS_PASSWORD_MOVE_PASSWORDS_TO_ACCOUNT_SNACKBAR.png.sha1 new file mode 100644 index 0000000..1adae42 --- /dev/null +++ b/chrome/app/settings_strings_grdp/IDS_SETTINGS_PASSWORD_MOVE_PASSWORDS_TO_ACCOUNT_SNACKBAR.png.sha1
@@ -0,0 +1 @@ +96e9e6adaa4dec2f34b5fac9b45a9f3edf7f9b84 \ No newline at end of file
diff --git a/chrome/app/settings_strings_grdp/IDS_SETTINGS_PASSWORD_OPEN_MOVE_MULTIPLE_PASSWORDS_TO_ACCOUNT_DIALOG_BUTTON_TEXT.png.sha1 b/chrome/app/settings_strings_grdp/IDS_SETTINGS_PASSWORD_OPEN_MOVE_MULTIPLE_PASSWORDS_TO_ACCOUNT_DIALOG_BUTTON_TEXT.png.sha1 new file mode 100644 index 0000000..80acf6a --- /dev/null +++ b/chrome/app/settings_strings_grdp/IDS_SETTINGS_PASSWORD_OPEN_MOVE_MULTIPLE_PASSWORDS_TO_ACCOUNT_DIALOG_BUTTON_TEXT.png.sha1
@@ -0,0 +1 @@ +eca1d45d15c5cfa5cf94eba96f1ca96f763d1887 \ No newline at end of file
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index 54b7a87..71c195d 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -1286,6 +1286,7 @@ const FeatureEntry::FeatureVariation kOmniboxOnFocusSuggestionsContextualWebVariations[] = { {"GOC Only", {}, 0, "t3317583"}, + {"pSuggest Only", {}, 0, "t3318055"}, {"GOC, pSuggest Fallback", {}, 0, "t3317692"}, {"GOC, pSuggest Backfill", {}, 0, "t3317694"}, {"GOC, Default Hidden", {}, 0, "t3317834"},
diff --git a/chrome/browser/android/autofill_assistant/onboarding_coordinator_bridge.cc b/chrome/browser/android/autofill_assistant/onboarding_coordinator_bridge.cc index 1d05228..cb7dc74 100644 --- a/chrome/browser/android/autofill_assistant/onboarding_coordinator_bridge.cc +++ b/chrome/browser/android/autofill_assistant/onboarding_coordinator_bridge.cc
@@ -6,7 +6,7 @@ #include "base/android/jni_string.h" #include "base/containers/flat_map.h" -#include "chrome/android/features/autofill_assistant/jni_headers/AssistantOnboardingCoordinator_jni.h" +#include "chrome/android/features/autofill_assistant/jni_headers/BaseOnboardingCoordinator_jni.h" #include "chrome/browser/android/autofill_assistant/onboarding_fetcher_factory.h" #include "chrome/browser/profiles/profile_manager.h" #include "components/autofill_assistant/browser/autofill_assistant_onboarding_fetcher.h" @@ -21,27 +21,27 @@ for (const auto& it : string_map) { DCHECK(!it.first.empty()); DCHECK(!it.second.empty()); - Java_AssistantOnboardingCoordinator_addEntryToStringMap( + Java_BaseOnboardingCoordinator_addEntryToStringMap( env, jonboarding_coordinator, base::android::ConvertUTF8ToJavaString(env, it.first), base::android::ConvertUTF8ToJavaString(env, it.second)); } - Java_AssistantOnboardingCoordinator_updateAndShowView( - env, jonboarding_coordinator); + Java_BaseOnboardingCoordinator_updateAndShowView(env, + jonboarding_coordinator); } } // namespace // static -void JNI_AssistantOnboardingCoordinator_FetchOnboardingDefinition( +void JNI_BaseOnboardingCoordinator_FetchOnboardingDefinition( JNIEnv* env, const base::android::JavaParamRef<jobject>& jonboarding_coordinator, const base::android::JavaParamRef<jstring>& jintent, const base::android::JavaParamRef<jstring>& jlocale, jint timeout_ms) { if (!jonboarding_coordinator || !jintent || !jlocale || !timeout_ms) { - Java_AssistantOnboardingCoordinator_updateAndShowView( - env, jonboarding_coordinator); + Java_BaseOnboardingCoordinator_updateAndShowView(env, + jonboarding_coordinator); return; }
diff --git a/chrome/browser/android/autofill_assistant/onboarding_coordinator_bridge.h b/chrome/browser/android/autofill_assistant/onboarding_coordinator_bridge.h index 1ecd3a5d..370ddab3 100644 --- a/chrome/browser/android/autofill_assistant/onboarding_coordinator_bridge.h +++ b/chrome/browser/android/autofill_assistant/onboarding_coordinator_bridge.h
@@ -10,7 +10,7 @@ namespace autofill_assistant { -static void JNI_AssistantOnboardingCoordinator_FetchOnboardingDefinition( +static void JNI_BaseOnboardingCoordinator_FetchOnboardingDefinition( JNIEnv* env, const base::android::JavaParamRef<jobject>& jonboarding_coordinator, const base::android::JavaParamRef<jstring>& jintent,
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc index aded546..d9e747d3 100644 --- a/chrome/browser/chrome_content_browser_client.cc +++ b/chrome/browser/chrome_content_browser_client.cc
@@ -4411,7 +4411,6 @@ chrome_navigation_ui_data->prerender_mode() != prerender::mojom::PrerenderMode::kNoPrerender) { result.push_back(std::make_unique<prerender::PrerenderURLLoaderThrottle>( - chrome_navigation_ui_data->prerender_mode(), chrome_navigation_ui_data->prerender_histogram_prefix(), GetPrerenderCanceler(wc_getter))); }
diff --git a/chrome/browser/chromeos/dbus/plugin_vm_service_provider.cc b/chrome/browser/chromeos/dbus/plugin_vm_service_provider.cc index 3788a8e1..66af625 100644 --- a/chrome/browser/chromeos/dbus/plugin_vm_service_provider.cc +++ b/chrome/browser/chromeos/dbus/plugin_vm_service_provider.cc
@@ -13,8 +13,8 @@ #include "chrome/browser/chromeos/plugin_vm/plugin_vm_pref_names.h" #include "chrome/browser/chromeos/plugin_vm/plugin_vm_util.h" #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h" -#include "chrome/browser/chromeos/profiles/profile_helper.h" #include "chrome/browser/profiles/profile.h" +#include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/ui/chrome_pages.h" #include "chrome/browser/ui/settings_window_manager_chromeos.h" #include "chrome/browser/ui/webui/settings/chromeos/app_management/app_management_uma.h" @@ -22,7 +22,6 @@ #include "chrome/common/webui_url_constants.h" #include "chromeos/dbus/plugin_vm_service/plugin_vm_service.pb.h" #include "components/prefs/pref_service.h" -#include "components/user_manager/user_manager.h" #include "dbus/message.h" #include "third_party/cros_system_api/dbus/service_constants.h" @@ -33,14 +32,6 @@ constexpr char kShowSettingsPageDetails[] = "pluginVm/details"; constexpr char kShowSettingsPageSharedPaths[] = "pluginVm/sharedPaths"; -namespace { -Profile* GetPrimaryProfile() { - const user_manager::User* primary_user = - user_manager::UserManager::Get()->GetPrimaryUser(); - return chromeos::ProfileHelper::Get()->GetProfileByUser(primary_user); -} -} // namespace - namespace chromeos { PluginVmServiceProvider::PluginVmServiceProvider() {} @@ -118,7 +109,7 @@ return; } - Profile* primary_profile = GetPrimaryProfile(); + Profile* primary_profile = ProfileManager::GetPrimaryUserProfile(); if (request.subpage_path() == kShowSettingsPageDetails) { chrome::ShowAppManagementPage( primary_profile, plugin_vm::kPluginVmShelfAppId, @@ -145,8 +136,8 @@ std::unique_ptr<dbus::Response> response = dbus::Response::FromMethodCall(method_call); plugin_vm_service::GetAppLicenseUserIdResponse payload; - payload.set_user_id( - plugin_vm::GetPluginVmUserIdForProfile(GetPrimaryProfile())); + payload.set_user_id(plugin_vm::GetPluginVmUserIdForProfile( + ProfileManager::GetPrimaryUserProfile())); dbus::MessageWriter writer(response.get()); writer.AppendProtoAsArrayOfBytes(payload); std::move(response_sender).Run(std::move(response)); @@ -159,7 +150,7 @@ dbus::Response::FromMethodCall(method_call); plugin_vm_service::GetPermissionsResponse payload; payload.set_data_collection_enabled( - GetPrimaryProfile()->GetPrefs()->GetBoolean( + ProfileManager::GetPrimaryUserProfile()->GetPrefs()->GetBoolean( plugin_vm::prefs::kPluginVmDataCollectionAllowed)); dbus::MessageWriter writer(response.get()); writer.AppendProtoAsArrayOfBytes(payload);
diff --git a/chrome/browser/chromeos/exo/chrome_data_exchange_delegate.cc b/chrome/browser/chromeos/exo/chrome_data_exchange_delegate.cc index de929dc50..01094a28 100644 --- a/chrome/browser/chromeos/exo/chrome_data_exchange_delegate.cc +++ b/chrome/browser/chromeos/exo/chrome_data_exchange_delegate.cc
@@ -27,9 +27,8 @@ #include "chrome/browser/chromeos/guest_os/guest_os_share_path.h" #include "chrome/browser/chromeos/plugin_vm/plugin_vm_files.h" #include "chrome/browser/chromeos/plugin_vm/plugin_vm_util.h" -#include "chrome/browser/chromeos/profiles/profile_helper.h" #include "chrome/browser/profiles/profile.h" -#include "components/user_manager/user_manager.h" +#include "chrome/browser/profiles/profile_manager.h" #include "content/public/common/drop_data.h" #include "storage/browser/file_system/external_mount_points.h" #include "storage/browser/file_system/file_system_context.h" @@ -50,17 +49,6 @@ constexpr char kUriListSeparator[] = "\r\n"; constexpr char kVmFileScheme[] = "vmfile"; -// We are using our own GetPrimaryProfile() rather than -// ProfileManager::GetPrimaryUserProfile() to help unittest. -Profile* GetPrimaryProfile() { - if (!user_manager::UserManager::IsInitialized()) - return nullptr; - const auto* primary_user = user_manager::UserManager::Get()->GetPrimaryUser(); - if (!primary_user) - return nullptr; - return chromeos::ProfileHelper::Get()->GetProfileByUser(primary_user); -} - // We implement our own URLToPath() and PathToURL() rather than use // net::FileUrlToFilePath() or net::FilePathToFileURL() since //net code does // not support Windows network paths such as //ChromeOS/MyFiles on OS_CHROMEOS. @@ -114,7 +102,7 @@ } storage::FileSystemContext* GetFileSystemContext() { - Profile* primary_profile = GetPrimaryProfile(); + Profile* primary_profile = ProfileManager::GetPrimaryUserProfile(); if (!primary_profile) return nullptr; @@ -175,7 +163,7 @@ void ShareAndSend(aura::Window* target, std::vector<FileInfo> files, exo::DataExchangeDelegate::SendDataCallback callback) { - Profile* primary_profile = GetPrimaryProfile(); + Profile* primary_profile = ProfileManager::GetPrimaryUserProfile(); aura::Window* toplevel = target->GetToplevelWindow(); bool is_crostini = crostini::IsCrostiniWindow(toplevel); bool is_plugin_vm = plugin_vm::IsPluginVmAppWindow(toplevel); @@ -279,7 +267,7 @@ std::vector<ui::FileInfo> ChromeDataExchangeDelegate::GetFilenames( aura::Window* source, const std::vector<uint8_t>& data) const { - Profile* primary_profile = GetPrimaryProfile(); + Profile* primary_profile = ProfileManager::GetPrimaryUserProfile(); aura::Window* toplevel = source->GetToplevelWindow(); bool is_crostini = crostini::IsCrostiniWindow(toplevel); bool is_plugin_vm = plugin_vm::IsPluginVmAppWindow(toplevel);
diff --git a/chrome/browser/chromeos/file_manager/file_manager_jstest.cc b/chrome/browser/chromeos/file_manager/file_manager_jstest.cc index 6c98838..9aa4513f 100644 --- a/chrome/browser/chromeos/file_manager/file_manager_jstest.cc +++ b/chrome/browser/chromeos/file_manager/file_manager_jstest.cc
@@ -58,7 +58,7 @@ } IN_PROC_BROWSER_TEST_F(FileManagerJsTest, DuplicateFinderTest) { - RunTestURL("background/js/duplicate_finder_unittest_gen.html"); + RunTestURL("background/js/duplicate_finder_unittest.m_gen.html"); } IN_PROC_BROWSER_TEST_F(FileManagerJsTest, ExifParser) { @@ -181,11 +181,11 @@ } IN_PROC_BROWSER_TEST_F(FileManagerJsTest, MediaImportHandlerTest) { - RunTestURL("background/js/media_import_handler_unittest_gen.html"); + RunTestURL("background/js/media_import_handler_unittest.m_gen.html"); } IN_PROC_BROWSER_TEST_F(FileManagerJsTest, MediaScannerTest) { - RunTestURL("background/js/media_scanner_unittest_gen.html"); + RunTestURL("background/js/media_scanner_unittest.m_gen.html"); } IN_PROC_BROWSER_TEST_F(FileManagerJsTest, MetadataCacheItem) {
diff --git a/chrome/browser/chromeos/file_manager/path_util.cc b/chrome/browser/chromeos/file_manager/path_util.cc index 0db32ad..2acb330d 100644 --- a/chrome/browser/chromeos/file_manager/path_util.cc +++ b/chrome/browser/chromeos/file_manager/path_util.cc
@@ -32,6 +32,7 @@ #include "chrome/browser/download/download_dir_util.h" #include "chrome/browser/download/download_prefs.h" #include "chrome/browser/profiles/profile.h" +#include "chrome/browser/profiles/profile_manager.h" #include "chromeos/constants/chromeos_features.h" #include "chromeos/disks/disk.h" #include "chromeos/disks/disk_mount_manager.h" @@ -83,15 +84,6 @@ constexpr char kArcDriveContentUrlPrefix[] = "content://org.chromium.arc.volumeprovider/MyDrive/"; -Profile* GetPrimaryProfile() { - if (!user_manager::UserManager::IsInitialized()) - return nullptr; - const auto* primary_user = user_manager::UserManager::Get()->GetPrimaryUser(); - if (!primary_user) - return nullptr; - return chromeos::ProfileHelper::Get()->GetProfileByUser(primary_user); -} - // Helper function for |ConvertToContentUrls|. void OnSingleContentUrlResolved(const base::RepeatingClosure& barrier_closure, std::vector<GURL>* out_urls, @@ -561,7 +553,7 @@ // Obtain the primary profile. This information is required because currently // only the file systems for the primary profile is exposed to ARC. - Profile* primary_profile = GetPrimaryProfile(); + Profile* primary_profile = ProfileManager::GetPrimaryUserProfile(); if (!primary_profile) return false; @@ -734,8 +726,8 @@ void ConvertToContentUrls( const std::vector<storage::FileSystemURL>& file_system_urls, ConvertToContentUrlsCallback callback) { - ConvertToContentUrls(GetPrimaryProfile(), file_system_urls, - std::move(callback)); + ConvertToContentUrls(ProfileManager::GetPrimaryUserProfile(), + file_system_urls, std::move(callback)); } bool ReplacePrefix(std::string* s,
diff --git a/chrome/browser/devtools/protocol/page_handler.cc b/chrome/browser/devtools/protocol/page_handler.cc index ed48b48..fa22258b 100644 --- a/chrome/browser/devtools/protocol/page_handler.cc +++ b/chrome/browser/devtools/protocol/page_handler.cc
@@ -4,7 +4,7 @@ #include "chrome/browser/devtools/protocol/page_handler.h" -#include "chrome/browser/subresource_filter/chrome_subresource_filter_client.h" +#include "components/subresource_filter/content/browser/devtools_interaction_tracker.h" #include "components/webapps/installable/installable_manager.h" #include "ui/gfx/image/image.h" @@ -22,10 +22,15 @@ void PageHandler::ToggleAdBlocking(bool enabled) { if (!web_contents()) return; - if (auto* client = - ChromeSubresourceFilterClient::FromWebContents(web_contents())) { - client->ToggleForceActivationInCurrentWebContents(enabled); - } + + // Create the DevtoolsInteractionTracker lazily (note that this call is a + // no-op if the object was already created). + subresource_filter::DevtoolsInteractionTracker::CreateForWebContents( + web_contents()); + + subresource_filter::DevtoolsInteractionTracker::FromWebContents( + web_contents()) + ->ToggleForceActivation(enabled); } protocol::Response PageHandler::Enable() {
diff --git a/chrome/browser/extensions/BUILD.gn b/chrome/browser/extensions/BUILD.gn index e0840b80..271e545 100644 --- a/chrome/browser/extensions/BUILD.gn +++ b/chrome/browser/extensions/BUILD.gn
@@ -835,6 +835,7 @@ "//components/policy:generated", "//components/policy/core/browser", "//components/pref_registry", + "//components/privacy_sandbox:privacy_sandbox_prefs", "//components/proxy_config", "//components/rappor", "//components/resources",
diff --git a/chrome/browser/extensions/api/passwords_private/password_check_delegate_unittest.cc b/chrome/browser/extensions/api/passwords_private/password_check_delegate_unittest.cc index cca2138..907a998b 100644 --- a/chrome/browser/extensions/api/passwords_private/password_check_delegate_unittest.cc +++ b/chrome/browser/extensions/api/passwords_private/password_check_delegate_unittest.cc
@@ -80,6 +80,7 @@ using password_manager::CompromiseType; using password_manager::InsecureCredentialTypeFlags; using password_manager::IsLeaked; +using password_manager::IsMuted; using password_manager::LeakCheckCredential; using password_manager::PasswordForm; using password_manager::SavedPasswordsPresenter; @@ -143,8 +144,7 @@ CompromiseType compromise_type = CompromiseType::kLeaked) { return CompromisedCredentials( std::string(signon_realm), base::ASCIIToUTF16(username), - base::Time::Now() - time_since_creation, compromise_type, - /*is_muted=*/false); + base::Time::Now() - time_since_creation, compromise_type, IsMuted(false)); } PasswordForm MakeSavedPassword(base::StringPiece signon_realm, @@ -812,11 +812,10 @@ IsLeaked(true)); RunUntilIdle(); - EXPECT_THAT( - store().compromised_credentials(), - ElementsAre(CompromisedCredentials( - kExampleCom, base::ASCIIToUTF16(kUsername1), base::Time::Now(), - CompromiseType::kLeaked, /*is_muted=*/false))); + EXPECT_THAT(store().compromised_credentials(), + ElementsAre(CompromisedCredentials( + kExampleCom, base::ASCIIToUTF16(kUsername1), + base::Time::Now(), CompromiseType::kLeaked, IsMuted(false)))); } // Test that a found leak creates a compromised credential in the password @@ -848,16 +847,16 @@ UnorderedElementsAre( CompromisedCredentials(kExampleCom, base::ASCIIToUTF16(kUsername1), base::Time::Now(), CompromiseType::kLeaked, - /*is_muted=*/false), + IsMuted(false)), CompromisedCredentials(kExampleOrg, base::ASCIIToUTF16(kUsername1), base::Time::Now(), CompromiseType::kLeaked, - /*is_muted=*/false), + IsMuted(false)), CompromisedCredentials( kExampleCom, base::ASCIIToUTF16(kUsername2Upper), - base::Time::Now(), CompromiseType::kLeaked, /*is_muted=*/false), + base::Time::Now(), CompromiseType::kLeaked, IsMuted(false)), CompromisedCredentials( kExampleOrg, base::ASCIIToUTF16(kUsername2Email), - base::Time::Now(), CompromiseType::kLeaked, /*is_muted=*/false))); + base::Time::Now(), CompromiseType::kLeaked, IsMuted(false)))); } // Verifies that the case where the user has no saved passwords is reported
diff --git a/chrome/browser/extensions/api/settings_private/prefs_util.cc b/chrome/browser/extensions/api/settings_private/prefs_util.cc index 1f888dd0..cb636a01 100644 --- a/chrome/browser/extensions/api/settings_private/prefs_util.cc +++ b/chrome/browser/extensions/api/settings_private/prefs_util.cc
@@ -20,6 +20,7 @@ #include "chrome/browser/prefs/session_startup_pref.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/safe_browsing/generated_safe_browsing_pref.h" +#include "chrome/common/chrome_features.h" #include "chrome/common/pref_names.h" #include "components/autofill/core/common/autofill_prefs.h" #include "components/bookmarks/common/bookmark_pref_names.h" @@ -35,6 +36,7 @@ #include "components/password_manager/core/common/password_manager_pref_names.h" #include "components/payments/core/payment_prefs.h" #include "components/prefs/pref_service.h" +#include "components/privacy_sandbox/privacy_sandbox_prefs.h" #include "components/proxy_config/proxy_config_pref_names.h" #include "components/safe_browsing/core/common/safe_browsing_prefs.h" #include "components/search_engines/default_search_manager.h" @@ -266,6 +268,11 @@ (*s_allowlist)[::prefs::kDnsOverHttpsTemplates] = settings_api::PrefType::PREF_TYPE_STRING; + // Privacy sandbox + if (base::FeatureList::IsEnabled(features::kPrivacySandboxSettings)) + (*s_allowlist)[::prefs::kPrivacySandboxApisEnabled] = + settings_api::PrefType::PREF_TYPE_BOOLEAN; + // Security page (*s_allowlist)[::kGeneratedPasswordLeakDetectionPref] = settings_api::PrefType::PREF_TYPE_BOOLEAN;
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json index a9bc87e..a278de6 100644 --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json
@@ -847,7 +847,7 @@ { "name": "desktop-version-default", "owners": [ "gambard", "bling-flags@google.com" ], - "expiry_milestone": 89 + "expiry_milestone": 92 }, { "name": "destroy-profile-on-browser-close",
diff --git a/chrome/browser/metrics/process_memory_metrics_emitter.cc b/chrome/browser/metrics/process_memory_metrics_emitter.cc index 138b10b..ae42485 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.ResidentSize", MetricSize::kSmall, + "resident_size", EmitTo::kSizeInUmaOnly, nullptr}, {"discardable", "Discardable.VirtualSize", MetricSize::kSmall, "virtual_size", EmitTo::kSizeInUmaOnly, nullptr}, {"extensions/functions", "ExtensionFunctions", MetricSize::kLarge,
diff --git a/chrome/browser/nearby_sharing/nearby_notification_manager.cc b/chrome/browser/nearby_sharing/nearby_notification_manager.cc index 20e1412..54ecaee 100644 --- a/chrome/browser/nearby_sharing/nearby_notification_manager.cc +++ b/chrome/browser/nearby_sharing/nearby_notification_manager.cc
@@ -120,7 +120,7 @@ case TextAttachment::Type::kUrl: return IDS_NEARBY_TEXT_ATTACHMENTS_LINKS; default: - return IDS_NEARBY_UNKNOWN_ATTACHMENTS; + return IDS_NEARBY_TEXT_ATTACHMENTS_UNKNOWN; } }
diff --git a/chrome/browser/password_check/android/password_check_manager_unittest.cc b/chrome/browser/password_check/android/password_check_manager_unittest.cc index 70751fc..d7aa9e8 100644 --- a/chrome/browser/password_check/android/password_check_manager_unittest.cc +++ b/chrome/browser/password_check/android/password_check_manager_unittest.cc
@@ -170,7 +170,8 @@ CompromiseType compromise_type = CompromiseType::kLeaked) { return CompromisedCredentials( std::string(signon_realm), base::ASCIIToUTF16(username), - base::Time::Now() - time_since_creation, compromise_type, false); + base::Time::Now() - time_since_creation, compromise_type, + password_manager::IsMuted(false)); } // Creates matcher for a given compromised credential
diff --git a/chrome/browser/password_manager/multi_profile_credentials_filter_unittest.cc b/chrome/browser/password_manager/multi_profile_credentials_filter_unittest.cc index bd40032..5dfe84d 100644 --- a/chrome/browser/password_manager/multi_profile_credentials_filter_unittest.cc +++ b/chrome/browser/password_manager/multi_profile_credentials_filter_unittest.cc
@@ -35,10 +35,13 @@ class TestDiceWebSigninInterceptorDelegate : public DiceWebSigninInterceptor::Delegate { public: - void ShowSigninInterceptionBubble( + std::unique_ptr<ScopedDiceWebSigninInterceptionBubbleHandle> + ShowSigninInterceptionBubble( content::WebContents* web_contents, const BubbleParameters& bubble_parameters, - base::OnceCallback<void(SigninInterceptionResult)> callback) override {} + base::OnceCallback<void(SigninInterceptionResult)> callback) override { + return nullptr; + } void ShowProfileCustomizationBubble(Browser* browser) override {} };
diff --git a/chrome/browser/performance_manager/chrome_browser_main_extra_parts_performance_manager.cc b/chrome/browser/performance_manager/chrome_browser_main_extra_parts_performance_manager.cc index db72792d..769c765b 100644 --- a/chrome/browser/performance_manager/chrome_browser_main_extra_parts_performance_manager.cc +++ b/chrome/browser/performance_manager/chrome_browser_main_extra_parts_performance_manager.cc
@@ -48,7 +48,9 @@ #endif // BUILDFLAG(IS_CHROMEOS_ASH) #if !defined(OS_ANDROID) +#include "chrome/browser/performance_manager/mechanisms/page_freezer.h" #include "chrome/browser/performance_manager/policies/page_discarding_helper.h" +#include "chrome/browser/performance_manager/policies/page_freezing_policy.h" #include "chrome/browser/performance_manager/policies/urgent_page_discarding_policy.h" #include "chrome/browser/tab_contents/form_interaction_tab_helper.h" #endif // !defined(OS_ANDROID) @@ -148,6 +150,12 @@ graph->PassToGraph(std::make_unique< performance_manager::policies::HighPMFDiscardPolicy>()); } + + // The freezing policy isn't enabled on Android yet as it doesn't play well + // with the freezing logic already in place in renderers. This logic should be + // moved to PerformanceManager, this is tracked in https://crbug.com/1156803. + graph->PassToGraph( + std::make_unique<performance_manager::policies::PageFreezingPolicy>()); #endif // !defined(OS_ANDROID) graph->PassToGraph(
diff --git a/chrome/browser/performance_manager/policies/page_freezing_policy.cc b/chrome/browser/performance_manager/policies/page_freezing_policy.cc index 61806df2..a624a3a4 100644 --- a/chrome/browser/performance_manager/policies/page_freezing_policy.cc +++ b/chrome/browser/performance_manager/policies/page_freezing_policy.cc
@@ -46,9 +46,6 @@ if (page_node->IsAudible()) OnIsAudibleChanged(page_node); - - if (page_node->IsVisible()) - OnIsVisibleChanged(page_node); } void PageFreezingPolicy::OnBeforePageNodeRemoved(const PageNode* page_node) { @@ -59,13 +56,6 @@ page_node_being_removed_ = nullptr; } -void PageFreezingPolicy::OnIsVisibleChanged(const PageNode* page_node) { - UpdateNegativeFreezingVote(page_node, CannotFreezeReason::kVisible, - page_node->IsVisible() - ? NegativeVoteAction::kEmit - : NegativeVoteAction::kRemove); -} - void PageFreezingPolicy::OnIsAudibleChanged(const PageNode* page_node) { UpdateNegativeFreezingVote(page_node, CannotFreezeReason::kAudible, page_node->IsAudible() @@ -185,8 +175,6 @@ switch (reason) { case CannotFreezeReason::kAudible: return "Page is audible"; - case CannotFreezeReason::kVisible: - return "Page is visible"; case CannotFreezeReason::kHoldingIndexedDBLock: return "Page is holding an IndexedDB lock"; case CannotFreezeReason::kHoldingWebLock: @@ -232,7 +220,7 @@ ->GetRegisteredObjectAs<freezing::FreezingVoteAggregator>() ->GetVotingChannel()); } else { - DCHECK(!iter->second->IsValid()); + DCHECK(!iter->second->HasVoteForContext(page_node)); } // Submit the negative freezing vote. iter->second->SubmitVote(page_node,
diff --git a/chrome/browser/performance_manager/policies/page_freezing_policy.h b/chrome/browser/performance_manager/policies/page_freezing_policy.h index 82ff985c..216c9407 100644 --- a/chrome/browser/performance_manager/policies/page_freezing_policy.h +++ b/chrome/browser/performance_manager/policies/page_freezing_policy.h
@@ -22,7 +22,6 @@ // freezing vote is positive. // // Tabs in one of the following states won't be frozen: -// - Visible; // - Audible; // - Capturing video; // - Capturing audio; @@ -33,6 +32,9 @@ // - Connected to a USB device; // - Holding at least one IndexedDB lock; // - Holding at least one WebLock. +// +// Note that visible tabs can't be frozen and tabs that becomes visible are +// automatically unfrozen, there's no need to track this feature here. class PageFreezingPolicy : public GraphOwned, public PageNode::ObserverDefaultImpl, public PageLiveStateObserver { @@ -52,7 +54,6 @@ protected: // List of states that prevent a tab from being frozen. enum class CannotFreezeReason { - kVisible, kAudible, kHoldingIndexedDBLock, kHoldingWebLock, @@ -90,7 +91,6 @@ // PageNodeObserver implementation: void OnPageNodeAdded(const PageNode* page_node) override; void OnBeforePageNodeRemoved(const PageNode* page_node) override; - void OnIsVisibleChanged(const PageNode* page_node) override; void OnIsAudibleChanged(const PageNode* page_node) override; void OnPageIsHoldingWebLockChanged(const PageNode* page_node) override; void OnPageIsHoldingIndexedDBLockChanged(const PageNode* page_node) override;
diff --git a/chrome/browser/performance_manager/policies/page_freezing_policy_unittest.cc b/chrome/browser/performance_manager/policies/page_freezing_policy_unittest.cc index 911314fc..a24ae2b 100644 --- a/chrome/browser/performance_manager/policies/page_freezing_policy_unittest.cc +++ b/chrome/browser/performance_manager/policies/page_freezing_policy_unittest.cc
@@ -93,15 +93,6 @@ PageFreezingPolicy* policy_; }; -TEST_F(PageFreezingPolicyTest, VisiblePageGetsCannotFreezeVote) { - page_node()->SetIsVisible(true); - EXPECT_EQ(page_node()->freezing_vote()->value(), - freezing::FreezingVoteValue::kCannotFreeze); - EXPECT_EQ(page_node()->freezing_vote()->reason(), - PageFreezingPolicyAccess::CannotFreezeReasonToString( - PageFreezingPolicyAccess::CannotFreezeReason::kVisible)); -} - TEST_F(PageFreezingPolicyTest, AudiblePageGetsCannotFreezeVote) { page_node()->SetIsAudible(true); EXPECT_EQ(page_node()->freezing_vote()->value(),
diff --git a/chrome/browser/picture_in_picture/picture_in_picture_window_controller_browsertest.cc b/chrome/browser/picture_in_picture/picture_in_picture_window_controller_browsertest.cc index f11e4e6b..b9216e04 100644 --- a/chrome/browser/picture_in_picture/picture_in_picture_window_controller_browsertest.cc +++ b/chrome/browser/picture_in_picture/picture_in_picture_window_controller_browsertest.cc
@@ -4,9 +4,11 @@ #include "content/public/browser/picture_in_picture_window_controller.h" +#include "base/barrier_closure.h" #include "base/bind.h" #include "base/files/file_util.h" #include "base/path_service.h" +#include "base/scoped_observation.h" #include "base/strings/utf_string_conversions.h" #include "base/test/scoped_feature_list.h" #include "build/build_config.h" @@ -52,6 +54,7 @@ #include "ui/events/base_event_utils.h" #include "ui/gfx/codec/png_codec.h" #include "ui/views/controls/button/image_button.h" +#include "ui/views/view_observer.h" #include "ui/views/widget/widget_observer.h" #if BUILDFLAG(IS_CHROMEOS_ASH) @@ -95,6 +98,47 @@ const base::FilePath::CharType kPictureInPictureWindowSizePage[] = FILE_PATH_LITERAL("media/picture-in-picture/window-size.html"); +// Determines whether |control| is visible taking into account OverlayWindow's +// custom control hiding that includes setting the size to 0x0. +bool IsOverlayWindowControlVisible(views::View* control) { + return control->IsDrawn() && !control->size().IsEmpty(); +} + +// An observer used to notify about control visibility changes. +class ControlVisibilityObserver : views::ViewObserver { + public: + explicit ControlVisibilityObserver(views::View* observed_view, + bool expected_visible, + base::OnceClosure callback) + : expected_visible_(expected_visible), + visibility_change_callback_(std::move(callback)) { + observation_.Observe(observed_view); + + MaybeNotifyOfVisibilityChange(observed_view); + } + + // views::ViewObserver overrides. + void OnViewVisibilityChanged(views::View* observed_view, + views::View* starting_view) override { + MaybeNotifyOfVisibilityChange(observed_view); + } + void OnViewBoundsChanged(views::View* observed_view) override { + MaybeNotifyOfVisibilityChange(observed_view); + } + + private: + void MaybeNotifyOfVisibilityChange(views::View* observed_view) { + if (visibility_change_callback_ && + IsOverlayWindowControlVisible(observed_view) == expected_visible_) { + std::move(visibility_change_callback_).Run(); + } + } + + base::ScopedObservation<views::View, views::ViewObserver> observation_{this}; + bool expected_visible_; + base::OnceClosure visibility_change_callback_; +}; + } // namespace class PictureInPictureWindowControllerBrowserTest @@ -164,6 +208,24 @@ EXPECT_FALSE(in_picture_in_picture); } + // Makes sure all |controls| have the expected visibility state, waiting if + // necessary. + void AssertControlsVisible(std::vector<views::View*> controls, + bool expected_visible) { + base::RunLoop run_loop; + const auto barrier = + base::BarrierClosure(controls.size(), run_loop.QuitClosure()); + std::vector<std::unique_ptr<ControlVisibilityObserver>> observers; + for (views::View* control : controls) { + observers.push_back(std::make_unique<ControlVisibilityObserver>( + control, expected_visible, barrier)); + } + run_loop.Run(); + + for (views::View* control : controls) + ASSERT_EQ(IsOverlayWindowControlVisible(control), expected_visible); + } + class WidgetBoundsChangeWaiter final : public views::WidgetObserver { public: explicit WidgetBoundsChangeWaiter(views::Widget* widget) @@ -189,7 +251,8 @@ base::RunLoop run_loop_; }; - void MoveMouseOver(OverlayWindowViews* window) { + void MoveMouseOverOverlayWindow() { + auto* const window = GetOverlayWindow(); gfx::Point p(window->GetBounds().x(), window->GetBounds().y()); ui::MouseEvent moved_over(ui::ET_MOUSE_MOVED, p, p, ui::EventTimeForNow(), ui::EF_NONE, ui::EF_NONE); @@ -400,7 +463,7 @@ EXPECT_TRUE(content::ExecuteScript(active_web_contents, "video.play();")); Wait(base::TimeDelta::FromSeconds(3)); - MoveMouseOver(GetOverlayWindow()); + MoveMouseOverOverlayWindow(); TakeOverlayWindowScreenshot(GetOverlayWindow()); base::FilePath expected_pause_image_path = @@ -428,7 +491,7 @@ EXPECT_TRUE(content::ExecuteScript(active_web_contents, "video.pause();")); Wait(base::TimeDelta::FromSeconds(3)); - MoveMouseOver(GetOverlayWindow()); + MoveMouseOverOverlayWindow(); TakeOverlayWindowScreenshot(GetOverlayWindow()); ASSERT_TRUE(ReadImageFile(expected_play_image_path, &expected_image)); EXPECT_TRUE(CompareImages(GetResultBitmap(), expected_image)); @@ -831,18 +894,11 @@ EXPECT_TRUE(window_controller()->GetWindowForTesting()->IsVisible()); EXPECT_TRUE(GetOverlayWindow()->video_layer_for_testing()->visible()); - EXPECT_FALSE(GetOverlayWindow() - ->previous_track_controls_view_for_testing() - ->layer() - ->visible()); - EXPECT_FALSE(GetOverlayWindow() - ->play_pause_controls_view_for_testing() - ->layer() - ->visible()); - EXPECT_FALSE(GetOverlayWindow() - ->next_track_controls_view_for_testing() - ->layer() - ->visible()); + AssertControlsVisible( + {GetOverlayWindow()->previous_track_controls_view_for_testing(), + GetOverlayWindow()->play_pause_controls_view_for_testing(), + GetOverlayWindow()->next_track_controls_view_for_testing()}, + false); } // Tests that we can enter Picture-in-Picture when a video is not preloaded, @@ -1717,26 +1773,26 @@ ASSERT_NE(nullptr, GetOverlayWindow()); // Play/Pause button is displayed if video is not a mediastream. - MoveMouseOver(GetOverlayWindow()); - EXPECT_TRUE( - GetOverlayWindow()->play_pause_controls_view_for_testing()->IsDrawn()); + MoveMouseOverOverlayWindow(); + AssertControlsVisible( + {GetOverlayWindow()->play_pause_controls_view_for_testing()}, true); // Play/Pause button is hidden if video is a mediastream. bool result = false; ASSERT_TRUE(content::ExecuteScriptAndExtractBool( active_web_contents, "changeVideoSrcToMediaStream();", &result)); EXPECT_TRUE(result); - MoveMouseOver(GetOverlayWindow()); - EXPECT_FALSE( - GetOverlayWindow()->play_pause_controls_view_for_testing()->IsDrawn()); + MoveMouseOverOverlayWindow(); + AssertControlsVisible( + {GetOverlayWindow()->play_pause_controls_view_for_testing()}, false); // Play/Pause button is not hidden anymore when video is not a mediastream. ASSERT_TRUE(content::ExecuteScriptAndExtractBool( active_web_contents, "changeVideoSrc();", &result)); EXPECT_TRUE(result); - MoveMouseOver(GetOverlayWindow()); - EXPECT_TRUE( - GetOverlayWindow()->play_pause_controls_view_for_testing()->IsDrawn()); + MoveMouseOverOverlayWindow(); + AssertControlsVisible( + {GetOverlayWindow()->play_pause_controls_view_for_testing()}, true); } // Check that page visibility API events are fired when tab is hidden, shown, @@ -1871,11 +1927,9 @@ // Skip Ad button is not displayed initially when mouse is hovering over the // window. - MoveMouseOver(GetOverlayWindow()); - EXPECT_FALSE(GetOverlayWindow() - ->skip_ad_controls_view_for_testing() - ->layer() - ->visible()); + MoveMouseOverOverlayWindow(); + AssertControlsVisible( + {GetOverlayWindow()->skip_ad_controls_view_for_testing()}, false); content::WebContents* active_web_contents = browser()->tab_strip_model()->GetActiveWebContents(); @@ -1884,33 +1938,28 @@ // hovering over the window and media session action handler has been set. ASSERT_TRUE(content::ExecuteScript( active_web_contents, "setMediaSessionActionHandler('skipad');")); - base::RunLoop().RunUntilIdle(); - MoveMouseOver(GetOverlayWindow()); - EXPECT_FALSE(GetOverlayWindow() - ->skip_ad_controls_view_for_testing() - ->layer() - ->visible()); + MoveMouseOverOverlayWindow(); + // Wait for the controls to show if necessary, then verify the Skip Ad button + // is not among those shown. + AssertControlsVisible( + {GetOverlayWindow()->back_to_tab_controls_for_testing()}, true); + EXPECT_FALSE(IsOverlayWindowControlVisible( + GetOverlayWindow()->skip_ad_controls_view_for_testing())); // Play video and check that Skip Ad button is now displayed when // video plays and mouse is hovering over the window. ASSERT_TRUE(content::ExecuteScript(active_web_contents, "video.play();")); - base::RunLoop().RunUntilIdle(); - MoveMouseOver(GetOverlayWindow()); - EXPECT_TRUE(GetOverlayWindow() - ->skip_ad_controls_view_for_testing() - ->layer() - ->visible()); + MoveMouseOverOverlayWindow(); + AssertControlsVisible( + {GetOverlayWindow()->skip_ad_controls_view_for_testing()}, true); // Unset action handler and check that Skip Ad button is not displayed when // video plays and mouse is hovering over the window. ASSERT_TRUE(content::ExecuteScript( active_web_contents, "unsetMediaSessionActionHandler('skipad');")); - base::RunLoop().RunUntilIdle(); - MoveMouseOver(GetOverlayWindow()); - EXPECT_FALSE(GetOverlayWindow() - ->skip_ad_controls_view_for_testing() - ->layer() - ->visible()); + MoveMouseOverOverlayWindow(); + AssertControlsVisible( + {GetOverlayWindow()->skip_ad_controls_view_for_testing()}, false); } // Tests that the Play/Plause button is displayed in the Picture-in-Picture @@ -1932,10 +1981,13 @@ ASSERT_TRUE(content::ExecuteScriptAndExtractBool( active_web_contents, "changeVideoSrcToMediaStream();", &result)); EXPECT_TRUE(result); - base::RunLoop().RunUntilIdle(); - MoveMouseOver(GetOverlayWindow()); - EXPECT_FALSE( - GetOverlayWindow()->play_pause_controls_view_for_testing()->IsDrawn()); + MoveMouseOverOverlayWindow(); + // Wait for the controls to show if necessary, then verify the Play/Pause + // button is not among those shown. + AssertControlsVisible( + {GetOverlayWindow()->back_to_tab_controls_for_testing()}, true); + EXPECT_FALSE(IsOverlayWindowControlVisible( + GetOverlayWindow()->play_pause_controls_view_for_testing())); // Play second video (non-muted) so that Media Session becomes active. ASSERT_TRUE( @@ -1945,28 +1997,29 @@ // is still hidden when mouse is hovering over the window. ASSERT_TRUE(content::ExecuteScript(active_web_contents, "setMediaSessionActionHandler('play');")); - base::RunLoop().RunUntilIdle(); - MoveMouseOver(GetOverlayWindow()); - EXPECT_FALSE( - GetOverlayWindow()->play_pause_controls_view_for_testing()->IsDrawn()); + MoveMouseOverOverlayWindow(); + // Wait for the controls to show if necessary, then verify the Play/Pause + // button is not among those shown. + AssertControlsVisible( + {GetOverlayWindow()->back_to_tab_controls_for_testing()}, true); + EXPECT_FALSE(IsOverlayWindowControlVisible( + GetOverlayWindow()->play_pause_controls_view_for_testing())); // Set Media Session action "pause" handler and check that Play/Pause button // is now displayed when mouse is hovering over the window. ASSERT_TRUE(content::ExecuteScript(active_web_contents, "setMediaSessionActionHandler('pause');")); - base::RunLoop().RunUntilIdle(); - MoveMouseOver(GetOverlayWindow()); - EXPECT_TRUE( - GetOverlayWindow()->play_pause_controls_view_for_testing()->IsDrawn()); + MoveMouseOverOverlayWindow(); + AssertControlsVisible( + {GetOverlayWindow()->play_pause_controls_view_for_testing()}, true); // Unset Media Session action "pause" handler and check that Play/Pause button // is hidden when mouse is hovering over the window. ASSERT_TRUE(content::ExecuteScript( active_web_contents, "unsetMediaSessionActionHandler('pause');")); - base::RunLoop().RunUntilIdle(); - MoveMouseOver(GetOverlayWindow()); - EXPECT_FALSE( - GetOverlayWindow()->play_pause_controls_view_for_testing()->IsDrawn()); + MoveMouseOverOverlayWindow(); + AssertControlsVisible( + {GetOverlayWindow()->play_pause_controls_view_for_testing()}, false); ASSERT_TRUE( content::ExecuteScript(active_web_contents, "exitPictureInPicture();")); @@ -1974,16 +2027,14 @@ // Reset Media Session action "pause" handler and check that Play/Pause button // is now displayed when mouse is hovering over the window when it enters // Picture-in-Picture again. - base::RunLoop().RunUntilIdle(); ASSERT_TRUE(content::ExecuteScript(active_web_contents, "setMediaSessionActionHandler('pause');")); ASSERT_TRUE(content::ExecuteScriptAndExtractBool( active_web_contents, "enterPictureInPicture();", &result)); EXPECT_TRUE(result); - base::RunLoop().RunUntilIdle(); - MoveMouseOver(GetOverlayWindow()); - EXPECT_TRUE( - GetOverlayWindow()->play_pause_controls_view_for_testing()->IsDrawn()); + MoveMouseOverOverlayWindow(); + AssertControlsVisible( + {GetOverlayWindow()->play_pause_controls_view_for_testing()}, true); } // Tests that a Next Track button is displayed in the Picture-in-Picture window @@ -1996,97 +2047,53 @@ // Next Track button is not displayed initially when mouse is hovering over // the window. - MoveMouseOver(GetOverlayWindow()); - EXPECT_FALSE( - GetOverlayWindow()->next_track_controls_view_for_testing()->IsDrawn()); + MoveMouseOverOverlayWindow(); + AssertControlsVisible( + {GetOverlayWindow()->next_track_controls_view_for_testing()}, false); content::WebContents* active_web_contents = browser()->tab_strip_model()->GetActiveWebContents(); - // Next Track button is not displayed if video is not playing even if mouse is - // hovering over the window and media session action handler has been set. + // Next Track button is not displayed if video is not playing even if mouse + // is hovering over the window and media session action handler has been set. ASSERT_TRUE(content::ExecuteScript( active_web_contents, "setMediaSessionActionHandler('nexttrack');")); - base::RunLoop().RunUntilIdle(); - MoveMouseOver(GetOverlayWindow()); - EXPECT_FALSE( - GetOverlayWindow()->next_track_controls_view_for_testing()->IsDrawn()); + MoveMouseOverOverlayWindow(); + // Wait for the controls to show if necessary, then verify the Next Track + // button is not among those shown. + AssertControlsVisible( + {GetOverlayWindow()->back_to_tab_controls_for_testing()}, true); + EXPECT_FALSE(IsOverlayWindowControlVisible( + GetOverlayWindow()->next_track_controls_view_for_testing())); - // Play video and check that Next Track button is now displayed when - // video plays and mouse is hovering over the window. + // Play video and check that Next Track button is now displayed when video + // plays and mouse is hovering over the window. ASSERT_TRUE(content::ExecuteScript(active_web_contents, "video.play();")); - base::RunLoop().RunUntilIdle(); - MoveMouseOver(GetOverlayWindow()); - EXPECT_TRUE( - GetOverlayWindow()->next_track_controls_view_for_testing()->IsDrawn()); + MoveMouseOverOverlayWindow(); + AssertControlsVisible( + {GetOverlayWindow()->next_track_controls_view_for_testing()}, true); - gfx::Rect next_track_bounds = GetOverlayWindow() - ->next_track_controls_view_for_testing() - ->GetBoundsInScreen(); - - // Unset action handler and check that Next Track button is not displayed when - // video plays and mouse is hovering over the window. + // Unset action handler and check that Next Track button is not displayed + // when video plays and mouse is hovering over the window. ASSERT_TRUE(content::ExecuteScript( active_web_contents, "unsetMediaSessionActionHandler('nexttrack');")); - base::RunLoop().RunUntilIdle(); - MoveMouseOver(GetOverlayWindow()); - EXPECT_FALSE( - GetOverlayWindow()->next_track_controls_view_for_testing()->IsDrawn()); - - // Next Track button is still at the same previous location. - EXPECT_EQ(next_track_bounds, GetOverlayWindow() - ->next_track_controls_view_for_testing() - ->GetBoundsInScreen()); -} - -// Tests that Next Track button bounds are updated right away when -// Picture-in-Picture window controls are hidden. -IN_PROC_BROWSER_TEST_F(MediaSessionPictureInPictureWindowControllerBrowserTest, - NextTrackButtonBounds) { - LoadTabAndEnterPictureInPicture( - browser(), base::FilePath(kPictureInPictureWindowSizePage)); - ASSERT_NE(GetOverlayWindow(), nullptr); - - content::WebContents* active_web_contents = - browser()->tab_strip_model()->GetActiveWebContents(); - - gfx::Rect next_track_bounds = GetOverlayWindow() - ->next_track_controls_view_for_testing() - ->GetBoundsInScreen(); - - ASSERT_TRUE(content::ExecuteScript( - active_web_contents, "setMediaSessionActionHandler('nexttrack');")); - ASSERT_TRUE(content::ExecuteScript(active_web_contents, "video.play();")); - base::RunLoop().RunUntilIdle(); - - EXPECT_NE(next_track_bounds, GetOverlayWindow() - ->next_track_controls_view_for_testing() - ->GetBoundsInScreen()); + MoveMouseOverOverlayWindow(); + AssertControlsVisible( + {GetOverlayWindow()->next_track_controls_view_for_testing()}, false); } // Tests that a Previous Track button is displayed in the Picture-in-Picture // window when Media Session Action "previoustrack" is handled by the website. -// TODO(crbug.com/985303): Flaky on Linux. -// TODO(crbug.com/1052397): Revisit once build flag switch of lacros-chrome is -// complete. -#if defined(OS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS) -#define MAYBE_PreviousTrackButtonVisibility \ - DISABLED_PreviousTrackButtonVisibility -#else -#define MAYBE_PreviousTrackButtonVisibility PreviousTrackButtonVisibility -#endif IN_PROC_BROWSER_TEST_F(MediaSessionPictureInPictureWindowControllerBrowserTest, - MAYBE_PreviousTrackButtonVisibility) { + PreviousTrackButtonVisibility) { LoadTabAndEnterPictureInPicture( browser(), base::FilePath(kPictureInPictureWindowSizePage)); - ASSERT_NE(GetOverlayWindow(), nullptr); // Previous Track button is not displayed initially when mouse is hovering // over the window. - MoveMouseOver(GetOverlayWindow()); - EXPECT_FALSE(GetOverlayWindow() - ->previous_track_controls_view_for_testing() - ->IsDrawn()); + MoveMouseOverOverlayWindow(); + AssertControlsVisible( + {GetOverlayWindow()->previous_track_controls_view_for_testing()}, false); content::WebContents* active_web_contents = browser()->tab_strip_model()->GetActiveWebContents(); @@ -2096,67 +2103,28 @@ // set. ASSERT_TRUE(content::ExecuteScript( active_web_contents, "setMediaSessionActionHandler('previoustrack');")); - base::RunLoop().RunUntilIdle(); - MoveMouseOver(GetOverlayWindow()); - EXPECT_FALSE(GetOverlayWindow() - ->previous_track_controls_view_for_testing() - ->IsDrawn()); + MoveMouseOverOverlayWindow(); + // Wait for the controls to show if necessary, then verify the Previous Track + // button is not among those shown. + AssertControlsVisible( + {GetOverlayWindow()->back_to_tab_controls_for_testing()}, true); + EXPECT_FALSE(IsOverlayWindowControlVisible( + GetOverlayWindow()->previous_track_controls_view_for_testing())); // Play video and check that Previous Track button is now displayed when // video plays and mouse is hovering over the window. ASSERT_TRUE(content::ExecuteScript(active_web_contents, "video.play();")); - base::RunLoop().RunUntilIdle(); - MoveMouseOver(GetOverlayWindow()); - EXPECT_TRUE(GetOverlayWindow() - ->previous_track_controls_view_for_testing() - ->IsDrawn()); - - gfx::Rect previous_track_bounds = - GetOverlayWindow() - ->previous_track_controls_view_for_testing() - ->GetBoundsInScreen(); + MoveMouseOverOverlayWindow(); + AssertControlsVisible( + {GetOverlayWindow()->previous_track_controls_view_for_testing()}, true); // Unset action handler and check that Previous Track button is not displayed // when video plays and mouse is hovering over the window. ASSERT_TRUE(content::ExecuteScript( active_web_contents, "unsetMediaSessionActionHandler('previoustrack');")); - base::RunLoop().RunUntilIdle(); - MoveMouseOver(GetOverlayWindow()); - EXPECT_FALSE(GetOverlayWindow() - ->previous_track_controls_view_for_testing() - ->IsDrawn()); - // Previous Track button is still at the same previous location. - EXPECT_EQ(previous_track_bounds, - GetOverlayWindow() - ->previous_track_controls_view_for_testing() - ->GetBoundsInScreen()); -} - -// Tests that Previous Track button bounds are updated right away when -// Picture-in-Picture window controls are hidden. -IN_PROC_BROWSER_TEST_F(MediaSessionPictureInPictureWindowControllerBrowserTest, - PreviousTrackButtonBounds) { - LoadTabAndEnterPictureInPicture( - browser(), base::FilePath(kPictureInPictureWindowSizePage)); - ASSERT_NE(GetOverlayWindow(), nullptr); - - content::WebContents* active_web_contents = - browser()->tab_strip_model()->GetActiveWebContents(); - - gfx::Rect previous_track_bounds = - GetOverlayWindow() - ->previous_track_controls_view_for_testing() - ->GetBoundsInScreen(); - - ASSERT_TRUE(content::ExecuteScript( - active_web_contents, "setMediaSessionActionHandler('previoustrack');")); - ASSERT_TRUE(content::ExecuteScript(active_web_contents, "video.play();")); - base::RunLoop().RunUntilIdle(); - - EXPECT_NE(previous_track_bounds, - GetOverlayWindow() - ->previous_track_controls_view_for_testing() - ->GetBoundsInScreen()); + MoveMouseOverOverlayWindow(); + AssertControlsVisible( + {GetOverlayWindow()->previous_track_controls_view_for_testing()}, false); } // Tests that clicking the Skip Ad button in the Picture-in-Picture window
diff --git a/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceKeys.java b/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceKeys.java index f2d6f3e..bda1631a 100644 --- a/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceKeys.java +++ b/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceKeys.java
@@ -49,6 +49,9 @@ */ public static final String ACCESSIBILITY_TAB_SWITCHER = "accessibility_tab_switcher"; + public static final String ACCOUNT_PICKER_BOTTOM_SHEET_SHOWN_COUNT = + "Chrome.AccountPickerBottomSheet.ShownCount"; + /** The language code to override application language with. */ public static final String APPLICATION_OVERRIDE_LANGUAGE = "Chrome.Language.ApplicationOverrideLanguage"; @@ -813,6 +816,7 @@ static List<String> getKeysInUse() { // clang-format off return Arrays.asList( + ACCOUNT_PICKER_BOTTOM_SHEET_SHOWN_COUNT, ASSISTANT_LAST_VERSION, ASSISTANT_VOICE_SEARCH_ENABLED, ASSISTANT_VOICE_SEARCH_SUPPORTED,
diff --git a/chrome/browser/profiles/profile_manager.cc b/chrome/browser/profiles/profile_manager.cc index 7885a77..1cdcb56 100644 --- a/chrome/browser/profiles/profile_manager.cc +++ b/chrome/browser/profiles/profile_manager.cc
@@ -442,26 +442,24 @@ // static Profile* ProfileManager::GetPrimaryUserProfile() { +#if BUILDFLAG(IS_CHROMEOS_ASH) + if (IsLoggedIn()) { + user_manager::UserManager* manager = user_manager::UserManager::Get(); + const user_manager::User* user = manager->GetPrimaryUser(); + if (!user) // Can be null in unit tests. + return nullptr; + + // Note: The ProfileHelper will take care of guest profiles. + return chromeos::ProfileHelper::Get()->GetProfileByUserUnsafe(user); + } +#endif + ProfileManager* profile_manager = g_browser_process->profile_manager(); if (!profile_manager) // Can be null in unit tests. return nullptr; -#if BUILDFLAG(IS_CHROMEOS_ASH) - if (!IsLoggedIn()) { - return profile_manager->GetActiveUserOrOffTheRecordProfileFromPath( - profile_manager->user_data_dir()); - } - user_manager::UserManager* manager = user_manager::UserManager::Get(); - const user_manager::User* user = manager->GetPrimaryUser(); - if (!user) // Can be null in unit tests. - return nullptr; - - // Note: The ProfileHelper will take care of guest profiles. - return chromeos::ProfileHelper::Get()->GetProfileByUserUnsafe(user); -#else return profile_manager->GetActiveUserOrOffTheRecordProfileFromPath( profile_manager->user_data_dir()); -#endif } // static
diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu_browsertest.cc b/chrome/browser/renderer_context_menu/render_view_context_menu_browsertest.cc index d497a08..db4d41c 100644 --- a/chrome/browser/renderer_context_menu/render_view_context_menu_browsertest.cc +++ b/chrome/browser/renderer_context_menu/render_view_context_menu_browsertest.cc
@@ -1169,7 +1169,7 @@ // Functionality is not present on ChromeOS. #if !BUILDFLAG(IS_CHROMEOS_ASH) -IN_PROC_BROWSER_TEST_F(ContextMenuBrowserTest, OpenLinkInProfileEntryPresent) { +IN_PROC_BROWSER_TEST_F(ContextMenuBrowserTest, DISABLED_OpenLinkInProfileEntryPresent) { { std::unique_ptr<TestRenderViewContextMenu> menu( CreateContextMenuMediaTypeNone(GURL("http://www.google.com/"),
diff --git a/chrome/browser/resources/discards/discards_tab.js b/chrome/browser/resources/discards/discards_tab.js index 0f53157b..61b45fc 100644 --- a/chrome/browser/resources/discards/discards_tab.js +++ b/chrome/browser/resources/discards/discards_tab.js
@@ -220,6 +220,8 @@ return pageLifecycleStateFromVisibilityAndFocus(); case LifecycleUnitState.THROTTLED: return pageLifecycleStateFromVisibilityAndFocus() + ' (throttled)'; + case LifecycleUnitState.FROZEN: + return 'frozen'; case LifecycleUnitState.DISCARDED: return 'discarded (' + this.discardReasonToString_(reason) + ')' + ((reason === LifecycleUnitDiscardReason.URGENT) ? ' at ' +
diff --git a/chrome/browser/resources/settings/autofill_page/password_move_multiple_passwords_to_account_dialog.html b/chrome/browser/resources/settings/autofill_page/password_move_multiple_passwords_to_account_dialog.html index b8bcc9d..6061042 100644 --- a/chrome/browser/resources/settings/autofill_page/password_move_multiple_passwords_to_account_dialog.html +++ b/chrome/browser/resources/settings/autofill_page/password_move_multiple_passwords_to_account_dialog.html
@@ -21,8 +21,7 @@ <div slot="body"> <dom-repeat id="devicePasswordList" items="[[passwordsToMove]]" - class="cr-separators list-with-header" - on-rendered-item-count-changed="updateMovingPasswordsCountLabel_"> + class="cr-separators list-with-header"> <template> <password-list-item entry="[[item]]" tabindex$="[[tabIndex]]" focus-row-index="[[index]]" @@ -30,8 +29,7 @@ last-focused="{{lastFocused_}}" list-blurred="{{listBlurred_}}" should-hide-more-actions-button> <cr-checkbox slot="checkbox" id="checkbox" checked="true" - data-id$="[[item.deviceId_]]" - on-checked-changed="updateMovingPasswordsCountLabel_"> + data-id$="[[item.deviceId_]]"> </cr-checkbox> </password-list-item> </template> @@ -52,8 +50,9 @@ <div class="cr-row two-line "> <settings-avatar-icon></settings-avatar-icon> <div class="flex cr-padded-text"> - <div id="movingPasswordsCountLabel">[[movingPasswordsCountLabel_]]</div> - <div class="secondary">$i18n{passwordMovePasswordsToAccount}</div> + <div id="movingPasswordsCountLabel"> + $i18n{passwordMovePasswordsToAccountDialogFooter}</div> + <div class="secondary">[[accountEmail]]</div> </div> </div> </div>
diff --git a/chrome/browser/resources/settings/autofill_page/password_move_multiple_passwords_to_account_dialog.js b/chrome/browser/resources/settings/autofill_page/password_move_multiple_passwords_to_account_dialog.js index 2116ff5b..e8b3148 100644 --- a/chrome/browser/resources/settings/autofill_page/password_move_multiple_passwords_to_account_dialog.js +++ b/chrome/browser/resources/settings/autofill_page/password_move_multiple_passwords_to_account_dialog.js
@@ -11,7 +11,6 @@ import './password_list_item.js'; import {I18nBehavior} from 'chrome://resources/js/i18n_behavior.m.js'; -import {PluralStringProxyImpl} from 'chrome://resources/js/plural_string_proxy.js'; import {html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {MultiStorePasswordUiEntry} from './multi_store_password_ui_entry.js'; @@ -31,11 +30,7 @@ type: Array, value: () => [], }, - /** @private */ - movingPasswordsCountLabel_: { - type: String, - value: '', - }, + accountEmail: String, }, /** @override */ @@ -67,16 +62,4 @@ onCancelButtonClick_() { this.$.dialog.close(); }, - - updateMovingPasswordsCountLabel_() { - const checkboxes = this.$.dialog.querySelectorAll('cr-checkbox'); - const selectedPasswordsCount = - Array.from(checkboxes).filter(box => box.checked).length; - - PluralStringProxyImpl.getInstance() - .getPluralString('movePasswordsToAccount', selectedPasswordsCount) - .then(label => { - this.movingPasswordsCountLabel_ = label; - }); - }, });
diff --git a/chrome/browser/resources/settings/autofill_page/passwords_device_section.html b/chrome/browser/resources/settings/autofill_page/passwords_device_section.html index a3cc37b..9d28bc78 100644 --- a/chrome/browser/resources/settings/autofill_page/passwords_device_section.html +++ b/chrome/browser/resources/settings/autofill_page/passwords_device_section.html
@@ -98,6 +98,7 @@ <template is="dom-if" if="[[showMoveMultiplePasswordsDialog_]]" restamp> <password-move-multiple-passwords-to-account-dialog passwords-to-move="[[allDevicePasswords_]]" + account-email="[[accountEmail_]]" on-close="onMoveMultiplePasswordsDialogClose_"> </password-move-multiple-passwords-to-account-dialog> </template>
diff --git a/chrome/browser/resources/settings/autofill_page/passwords_device_section.js b/chrome/browser/resources/settings/autofill_page/passwords_device_section.js index ae4df301f..4b18c21 100644 --- a/chrome/browser/resources/settings/autofill_page/passwords_device_section.js +++ b/chrome/browser/resources/settings/autofill_page/passwords_device_section.js
@@ -22,6 +22,7 @@ import 'chrome://resources/polymer/v3_0/iron-list/iron-list.js'; import {I18nBehavior} from 'chrome://resources/js/i18n_behavior.m.js'; +import {PluralStringProxyImpl} from 'chrome://resources/js/plural_string_proxy.js'; import {getDeepActiveElement} from 'chrome://resources/js/util.m.js'; import {WebUIListenerBehavior} from 'chrome://resources/js/web_ui_listener_behavior.m.js'; import {IronA11yKeysBehavior} from 'chrome://resources/polymer/v3_0/iron-a11y-keys-behavior/iron-a11y-keys-behavior.js'; @@ -119,6 +120,7 @@ type: Array, value: () => [], computed: 'computeAllDevicePasswords_(savedPasswords.splices)', + observer: 'onAllDevicePasswordsChanged_', }, /** @private {!MultiStorePasswordUiEntry} */ @@ -178,7 +180,6 @@ devicePasswordsLabel_: { type: String, value: '', - computed: 'computeDevicePasswordsLabel_(allDevicePasswords_)', }, /** @private */ @@ -269,13 +270,11 @@ /** * @private - * @return {string} */ - computeDevicePasswordsLabel_() { - return this.allDevicePasswords_.length === 1 ? - this.i18n('devicePasswordsLinkLabelSingular') : - this.i18n( - 'devicePasswordsLinkLabelPlural', this.allDevicePasswords_.length); + async onAllDevicePasswordsChanged_() { + this.devicePasswordsLabel_ = + await PluralStringProxyImpl.getInstance().getPluralString( + 'movePasswordsToAccount', this.allDevicePasswords_.length); }, /**
diff --git a/chrome/browser/resources/settings/privacy_sandbox/BUILD.gn b/chrome/browser/resources/settings/privacy_sandbox/BUILD.gn index aefd267..c9bc394 100644 --- a/chrome/browser/resources/settings/privacy_sandbox/BUILD.gn +++ b/chrome/browser/resources/settings/privacy_sandbox/BUILD.gn
@@ -24,6 +24,7 @@ js_library("app") { deps = [ + "..:settings", "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", ] }
diff --git a/chrome/browser/resources/settings/privacy_sandbox/app.html b/chrome/browser/resources/settings/privacy_sandbox/app.html index f6653a9..18daad3 100644 --- a/chrome/browser/resources/settings/privacy_sandbox/app.html +++ b/chrome/browser/resources/settings/privacy_sandbox/app.html
@@ -43,6 +43,7 @@ } </style> +<settings-prefs prefs="{{prefs}}"></settings-prefs> <div id="page-container"> <h1 id="page-heading">$i18n{privacySandboxPageHeading}</h1> <picture> @@ -78,6 +79,7 @@ </div> <div class="card"> <settings-toggle-button id="toggleButton" + pref="{{prefs.privacy_sandbox.apis_enabled}}" class="hr" label="$i18n{privacySandboxPageHeading}"> </settings-toggle-button> <div class="cr-row continuation"> @@ -87,8 +89,8 @@ <div class="secondary">$i18n{privacySandboxPageHeading}</div> </div> <div class="cr-row continuation"> - <cr-button class="cr-button" id="button" aria-disabled="false" - role="button" tabindex="0" on-click="onButtonClick_"> + <cr-button class="cr-button" id="learnMoreButton" role="button" + tabindex="0" on-click="onLearnMoreButtonClick_"> $i18n{passwordViewDetails} </cr-button> </div>
diff --git a/chrome/browser/resources/settings/privacy_sandbox/app.js b/chrome/browser/resources/settings/privacy_sandbox/app.js index 80490c0..2c38edc 100644 --- a/chrome/browser/resources/settings/privacy_sandbox/app.js +++ b/chrome/browser/resources/settings/privacy_sandbox/app.js
@@ -7,13 +7,26 @@ import {html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +// Those resources are loaded through settings.js as the privacy sandbox page +// lives outside regular settings, hence can't access those resources directly +// with |optimize_webui="true"|. +import{loadTimeData, OpenWindowProxyImpl} from '../settings.js'; + Polymer({ is: 'privacy-sandbox-app', _template: html`{__html_template__}`, + properties: { + /** + * Preferences state. + */ + prefs: Object, + }, + /** @private */ - onButtonClick_: function() { - // TODO(crbug/1152336): Implement button click. + onLearnMoreButtonClick_: function() { + OpenWindowProxyImpl.getInstance().openURL( + loadTimeData.getString('privacySandboxURL')); }, });
diff --git a/chrome/browser/resources/settings/settings.js b/chrome/browser/resources/settings/settings.js index e542cb1..29f3218 100644 --- a/chrome/browser/resources/settings/settings.js +++ b/chrome/browser/resources/settings/settings.js
@@ -15,6 +15,7 @@ // </if> export {ExtensionControlBrowserProxyImpl} from './extension_control_browser_proxy.m.js'; export {HatsBrowserProxy, HatsBrowserProxyImpl} from './hats_browser_proxy.js'; +export {loadTimeData} from './i18n_setup.js'; export {LifetimeBrowserProxy, LifetimeBrowserProxyImpl} from './lifetime_browser_proxy.m.js'; export {MetricsBrowserProxy, MetricsBrowserProxyImpl, PrivacyElementInteractions, SafeBrowsingInteractions, SafetyCheckInteractions} from './metrics_browser_proxy.js'; export {OnStartupBrowserProxy, OnStartupBrowserProxyImpl} from './on_startup_page/on_startup_browser_proxy.js';
diff --git a/chrome/browser/safe_browsing/chrome_password_protection_service.cc b/chrome/browser/safe_browsing/chrome_password_protection_service.cc index 967501a..c6034a9 100644 --- a/chrome/browser/safe_browsing/chrome_password_protection_service.cc +++ b/chrome/browser/safe_browsing/chrome_password_protection_service.cc
@@ -1725,7 +1725,8 @@ password_store->AddCompromisedCredentials( password_manager::CompromisedCredentials( credential.signon_realm, credential.username, base::Time::Now(), - password_manager::CompromiseType::kPhished, false)); + password_manager::CompromiseType::kPhished, + password_manager::IsMuted(false))); } }
diff --git a/chrome/browser/signin/dice_web_signin_interceptor.cc b/chrome/browser/signin/dice_web_signin_interceptor.cc index 415bd7e..3837243 100644 --- a/chrome/browser/signin/dice_web_signin_interceptor.cc +++ b/chrome/browser/signin/dice_web_signin_interceptor.cc
@@ -90,6 +90,9 @@ } // namespace +ScopedDiceWebSigninInterceptionBubbleHandle:: + ~ScopedDiceWebSigninInterceptionBubbleHandle() = default; + bool SigninInterceptionHeuristicOutcomeIsSuccess( SigninInterceptionHeuristicOutcome outcome) { return outcome == SigninInterceptionHeuristicOutcome::kInterceptEnterprise || @@ -237,7 +240,7 @@ SigninInterceptionType::kProfileSwitch, *account_info, GetPrimaryAccountInfo(identity_manager_), entry->GetProfileThemeColors().profile_highlight_color}; - delegate_->ShowSigninInterceptionBubble( + interception_bubble_handle_ = delegate_->ShowSigninInterceptionBubble( web_contents, bubble_parameters, base::BindOnce(&DiceWebSigninInterceptor::OnProfileSwitchChoice, base::Unretained(this), entry->GetPath())); @@ -267,14 +270,17 @@ void DiceWebSigninInterceptor::CreateBrowserAfterSigninInterception( CoreAccountId account_id, content::WebContents* intercepted_contents, + std::unique_ptr<ScopedDiceWebSigninInterceptionBubbleHandle> bubble_handle, bool show_customization_bubble) { DCHECK(!session_startup_helper_); + DCHECK(bubble_handle); + interception_bubble_handle_ = std::move(bubble_handle); session_startup_helper_ = std::make_unique<DiceInterceptedSessionStartupHelper>( profile_, account_id, intercepted_contents); session_startup_helper_->Startup( - base::Bind(&DiceWebSigninInterceptor::OnNewBrowserCreated, - base::Unretained(this), show_customization_bubble)); + base::BindOnce(&DiceWebSigninInterceptor::OnNewBrowserCreated, + base::Unretained(this), show_customization_bubble)); } void DiceWebSigninInterceptor::Shutdown() { @@ -295,6 +301,7 @@ was_interception_ui_displayed_ = false; account_info_fetch_start_time_ = base::TimeTicks(); profile_creation_start_time_ = base::TimeTicks(); + interception_bubble_handle_.reset(); } const ProfileAttributesEntry* @@ -395,7 +402,7 @@ Delegate::BubbleParameters bubble_parameters{ *interception_type, info, GetPrimaryAccountInfo(identity_manager_), GetAutogeneratedThemeColors(profile_color).frame_color}; - delegate_->ShowSigninInterceptionBubble( + interception_bubble_handle_ = delegate_->ShowSigninInterceptionBubble( web_contents(), bubble_parameters, base::BindOnce(&DiceWebSigninInterceptor::OnProfileCreationChoice, base::Unretained(this), info, profile_color)); @@ -423,6 +430,7 @@ return; } + DCHECK(interception_bubble_handle_); profile_creation_start_time_ = base::TimeTicks::Now(); base::string16 profile_name; profile_name = profiles::GetDefaultNameForNewSignedInProfile(account_info); @@ -445,8 +453,9 @@ return; } - profile_creation_start_time_ = base::TimeTicks::Now(); + DCHECK(interception_bubble_handle_); DCHECK(!dice_signed_in_profile_creator_); + profile_creation_start_time_ = base::TimeTicks::Now(); // Unretained is fine because the profile creator is owned by this. dice_signed_in_profile_creator_ = std::make_unique<DiceSignedInProfileCreator>( @@ -490,13 +499,16 @@ // Work is done in this profile, the flow continues in the // DiceWebSigninInterceptor that is attached to the new profile. DiceWebSigninInterceptorFactory::GetForProfile(new_profile) - ->CreateBrowserAfterSigninInterception(account_id_, web_contents(), - show_customization_bubble); + ->CreateBrowserAfterSigninInterception( + account_id_, web_contents(), std::move(interception_bubble_handle_), + show_customization_bubble); Reset(); } void DiceWebSigninInterceptor::OnNewBrowserCreated( bool show_customization_bubble) { + DCHECK(interception_bubble_handle_); + interception_bubble_handle_.reset(); // Close the bubble now. session_startup_helper_.reset(); if (show_customization_bubble) { Browser* browser = chrome::FindBrowserWithProfile(profile_);
diff --git a/chrome/browser/signin/dice_web_signin_interceptor.h b/chrome/browser/signin/dice_web_signin_interceptor.h index 2f9f9ca..098c608 100644 --- a/chrome/browser/signin/dice_web_signin_interceptor.h +++ b/chrome/browser/signin/dice_web_signin_interceptor.h
@@ -98,6 +98,14 @@ kMaxValue = kNotDisplayed, }; +// The ScopedDiceWebSigninInterceptionBubbleHandle closes the signin intercept +// bubble when it is destroyed, if the bubble is still opened. Note that this +// handle does not prevent the bubble from being closed for other reasons. +class ScopedDiceWebSigninInterceptionBubbleHandle { + public: + virtual ~ScopedDiceWebSigninInterceptionBubbleHandle() = 0; +}; + // Returns whether the heuristic outcome is a success (the signin should be // intercepted). bool SigninInterceptionHeuristicOutcomeIsSuccess( @@ -111,11 +119,16 @@ // enterprise or multi-user case: // * MaybeInterceptWebSignin() is called when the new signin happens. // * Wait until the account info is downloaded. -// * Interception UI is shown by the delegate. +// * Interception UI is shown by the delegate. Keep a handle on the bubble. // * If the user approved, a new profile is created and the token is moved from // this profile to the new profile, using DiceSignedInProfileCreator. // * At this point, the flow ends in this profile, and continues in the new -// profile using DiceInterceptedSessionStartupHelper. +// profile using DiceInterceptedSessionStartupHelper to add the account. +// * When the account is available on the web in the new profile: +// - A new browser window is created for the new profile, +// - The tab is moved to the new profile, +// - The interception bubble is closed by deleting the handle, +// - The profile customization bubble is shown. class DiceWebSigninInterceptor : public KeyedService, public content::WebContentsObserver, public signin::IdentityManager::Observer { @@ -139,7 +152,15 @@ // whether the user should continue in a new profile. // The callback is never called if the delegate is deleted before it // completes. - virtual void ShowSigninInterceptionBubble( + // May return a nullptr handle if the bubble cannot be shown. + // Warning: the handle closes the bubble when it is destroyed ; it is the + // responsibility of the caller to keep the handle alive until the bubble + // should be closed. + // The callback must not be called synchronously if this function returns a + // valid handle (because the caller needs to be able to close the bubble + // from the callback). + virtual std::unique_ptr<ScopedDiceWebSigninInterceptionBubbleHandle> + ShowSigninInterceptionBubble( content::WebContents* web_contents, const BubbleParameters& bubble_parameters, base::OnceCallback<void(SigninInterceptionResult)> callback) = 0; @@ -183,6 +204,8 @@ void CreateBrowserAfterSigninInterception( CoreAccountId account_id, content::WebContents* intercepted_contents, + std::unique_ptr<ScopedDiceWebSigninInterceptionBubbleHandle> + bubble_handle, bool show_customization_bubble); // Returns the outcome of the interception heuristic. @@ -286,6 +309,9 @@ // is cancelled if the account info cannot be fetched quickly. base::CancelableOnceCallback<void()> on_account_info_update_timeout_; std::unique_ptr<DiceSignedInProfileCreator> dice_signed_in_profile_creator_; + // Used to retain the interception UI bubble until profile creation completes. + std::unique_ptr<ScopedDiceWebSigninInterceptionBubbleHandle> + interception_bubble_handle_; // Used for metrics: bool was_interception_ui_displayed_ = false; base::TimeTicks account_info_fetch_start_time_;
diff --git a/chrome/browser/signin/dice_web_signin_interceptor_browsertest.cc b/chrome/browser/signin/dice_web_signin_interceptor_browsertest.cc index 091d95d..e4265c8cd 100644 --- a/chrome/browser/signin/dice_web_signin_interceptor_browsertest.cc +++ b/chrome/browser/signin/dice_web_signin_interceptor_browsertest.cc
@@ -6,11 +6,13 @@ #include <map> +#include "base/memory/weak_ptr.h" #include "base/run_loop.h" #include "base/scoped_observer.h" #include "base/strings/utf_string_conversions.h" #include "base/test/bind.h" #include "base/test/metrics/histogram_tester.h" +#include "base/threading/thread_task_runner_handle.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/profiles/profile_attributes_entry.h" #include "chrome/browser/profiles/profile_attributes_storage.h" @@ -41,18 +43,33 @@ #include "url/gurl.h" namespace { +class FakeDiceWebSigninInterceptorDelegate; + +class FakeBubbleHandle : public ScopedDiceWebSigninInterceptionBubbleHandle, + public base::SupportsWeakPtr<FakeBubbleHandle> { + public: + ~FakeBubbleHandle() override = default; +}; // Dummy interception delegate that automatically accepts multi user // interception. class FakeDiceWebSigninInterceptorDelegate : public DiceWebSigninInterceptor::Delegate { public: - void ShowSigninInterceptionBubble( + std::unique_ptr<ScopedDiceWebSigninInterceptionBubbleHandle> + ShowSigninInterceptionBubble( content::WebContents* web_contents, const BubbleParameters& bubble_parameters, base::OnceCallback<void(SigninInterceptionResult)> callback) override { EXPECT_EQ(bubble_parameters.interception_type, expected_interception_type_); - std::move(callback).Run(SigninInterceptionResult::kAccepted); + auto bubble_handle = std::make_unique<FakeBubbleHandle>(); + weak_bubble_handle_ = bubble_handle->AsWeakPtr(); + // The callback must not be called synchronously (see the documentation for + // ShowSigninInterceptionBubble). + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::BindOnce(std::move(callback), + SigninInterceptionResult::kAccepted)); + return bubble_handle; } void ShowProfileCustomizationBubble(Browser* browser) override { EXPECT_FALSE(customized_browser_) @@ -66,10 +83,17 @@ expected_interception_type_ = type; } + bool intercept_bubble_shown() const { return weak_bubble_handle_.get(); } + + bool intercept_bubble_destroyed() const { + return weak_bubble_handle_.WasInvalidated(); + } + private: Browser* customized_browser_ = nullptr; DiceWebSigninInterceptor::SigninInterceptionType expected_interception_type_ = DiceWebSigninInterceptor::SigninInterceptionType::kMultiUser; + base::WeakPtr<FakeBubbleHandle> weak_bubble_handle_; }; // Waits until a new profile is created. @@ -252,6 +276,9 @@ Profile* new_profile = InterceptAndWaitProfileCreation(web_contents, account_info.account_id); ASSERT_TRUE(new_profile); + FakeDiceWebSigninInterceptorDelegate* source_interceptor_delegate = + GetInterceptorDelegate(profile()); + EXPECT_TRUE(source_interceptor_delegate->intercept_bubble_shown()); signin::IdentityManager* new_identity_manager = IdentityManagerFactory::GetForProfile(new_profile); EXPECT_TRUE(new_identity_manager->HasAccountWithRefreshToken( @@ -285,10 +312,16 @@ CheckHistograms(histogram_tester, SigninInterceptionHeuristicOutcome::kInterceptMultiUser); + // Interception bubble is destroyed in the source profile, and was not shown + // in the new profile. + FakeDiceWebSigninInterceptorDelegate* new_interceptor_delegate = + GetInterceptorDelegate(new_profile); + EXPECT_TRUE(source_interceptor_delegate->intercept_bubble_destroyed()); + EXPECT_FALSE(new_interceptor_delegate->intercept_bubble_shown()); + EXPECT_FALSE(new_interceptor_delegate->intercept_bubble_destroyed()); // Profile customization UI was shown exactly once in the new profile. - EXPECT_EQ(GetInterceptorDelegate(new_profile)->customized_browser(), - added_browser); - EXPECT_EQ(GetInterceptorDelegate(profile())->customized_browser(), nullptr); + EXPECT_EQ(new_interceptor_delegate->customized_browser(), added_browser); + EXPECT_EQ(source_interceptor_delegate->customized_browser(), nullptr); } // Tests the complete profile switch flow when the profile is not loaded. @@ -319,11 +352,14 @@ int original_tab_count = browser()->tab_strip_model()->count(); // Do the signin interception. - GetInterceptorDelegate(profile())->set_expected_interception_type( + FakeDiceWebSigninInterceptorDelegate* source_interceptor_delegate = + GetInterceptorDelegate(profile()); + source_interceptor_delegate->set_expected_interception_type( DiceWebSigninInterceptor::SigninInterceptionType::kProfileSwitch); Profile* new_profile = InterceptAndWaitProfileCreation(web_contents, account_info.account_id); ASSERT_TRUE(new_profile); + EXPECT_TRUE(source_interceptor_delegate->intercept_bubble_shown()); signin::IdentityManager* new_identity_manager = IdentityManagerFactory::GetForProfile(new_profile); EXPECT_TRUE(new_identity_manager->HasAccountWithRefreshToken( @@ -348,9 +384,11 @@ CheckHistograms(histogram_tester, SigninInterceptionHeuristicOutcome::kInterceptProfileSwitch); + // Interception bubble was closed. + EXPECT_TRUE(source_interceptor_delegate->intercept_bubble_destroyed()); // Profile customization was not shown. EXPECT_EQ(GetInterceptorDelegate(new_profile)->customized_browser(), nullptr); - EXPECT_EQ(GetInterceptorDelegate(profile())->customized_browser(), nullptr); + EXPECT_EQ(source_interceptor_delegate->customized_browser(), nullptr); } // Tests the complete profile switch flow when the profile is already loaded.
diff --git a/chrome/browser/signin/dice_web_signin_interceptor_unittest.cc b/chrome/browser/signin/dice_web_signin_interceptor_unittest.cc index 0ae69ac..a12a04a5 100644 --- a/chrome/browser/signin/dice_web_signin_interceptor_unittest.cc +++ b/chrome/browser/signin/dice_web_signin_interceptor_unittest.cc
@@ -37,7 +37,7 @@ class MockDiceWebSigninInterceptorDelegate : public DiceWebSigninInterceptor::Delegate { public: - MOCK_METHOD(void, + MOCK_METHOD(std::unique_ptr<ScopedDiceWebSigninInterceptionBubbleHandle>, ShowSigninInterceptionBubble, (content::WebContents * web_contents, const BubbleParameters& bubble_parameters, @@ -456,6 +456,7 @@ [&delegate_callback]( base::OnceCallback<void(SigninInterceptionResult)> callback) { delegate_callback = std::move(callback); + return nullptr; }))); MaybeIntercept(account_info.account_id); testing::Mock::VerifyAndClearExpectations(mock_delegate()); @@ -504,8 +505,10 @@ .WillOnce(testing::WithArg<2>(testing::Invoke( [](base::OnceCallback<void(SigninInterceptionResult)> callback) { std::move(callback).Run(SigninInterceptionResult::kDeclined); + return nullptr; }))); MaybeIntercept(account_info.account_id); + EXPECT_EQ(interceptor()->is_interception_in_progress(), false); histogram_tester.ExpectUniqueSample( "Signin.Intercept.HeuristicOutcome", SigninInterceptionHeuristicOutcome::kInterceptEnterprise, i + 1);
diff --git a/chrome/browser/signin/process_dice_header_delegate_impl_unittest.cc b/chrome/browser/signin/process_dice_header_delegate_impl_unittest.cc index b3bfd42..03284e0 100644 --- a/chrome/browser/signin/process_dice_header_delegate_impl_unittest.cc +++ b/chrome/browser/signin/process_dice_header_delegate_impl_unittest.cc
@@ -40,11 +40,13 @@ : public DiceWebSigninInterceptor::Delegate { public: ~TestDiceWebSigninInterceptorDelegate() override = default; - void ShowSigninInterceptionBubble( + std::unique_ptr<ScopedDiceWebSigninInterceptionBubbleHandle> + ShowSigninInterceptionBubble( content::WebContents* web_contents, const BubbleParameters& bubble_parameters, base::OnceCallback<void(SigninInterceptionResult)> callback) override { std::move(callback).Run(SigninInterceptionResult::kDeclined); + return nullptr; } void ShowProfileCustomizationBubble(Browser* browser) override {} };
diff --git a/chrome/browser/signin/services/android/BUILD.gn b/chrome/browser/signin/services/android/BUILD.gn index f2359be..426e654b 100644 --- a/chrome/browser/signin/services/android/BUILD.gn +++ b/chrome/browser/signin/services/android/BUILD.gn
@@ -20,6 +20,7 @@ "java/src/org/chromium/chrome/browser/signin/services/IdentityServicesProvider.java", "java/src/org/chromium/chrome/browser/signin/services/ProfileDataCache.java", "java/src/org/chromium/chrome/browser/signin/services/ProfileDownloader.java", + "java/src/org/chromium/chrome/browser/signin/services/SigninHelper.java", "java/src/org/chromium/chrome/browser/signin/services/SigninManager.java", "java/src/org/chromium/chrome/browser/signin/services/SigninMetricsUtils.java", "java/src/org/chromium/chrome/browser/signin/services/SigninPreferencesManager.java", @@ -28,6 +29,7 @@ ] deps = [ ":java_resources", + "$google_play_services_package:google_play_services_auth_base_java", "//base:base_java", "//base:jni_java", "//chrome/browser/preferences:java",
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninHelper.java b/chrome/browser/signin/services/android/java/src/org/chromium/chrome/browser/signin/services/SigninHelper.java similarity index 94% rename from chrome/android/java/src/org/chromium/chrome/browser/signin/SigninHelper.java rename to chrome/browser/signin/services/android/java/src/org/chromium/chrome/browser/signin/services/SigninHelper.java index 5150c35..7c137827 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninHelper.java +++ b/chrome/browser/signin/services/android/java/src/org/chromium/chrome/browser/signin/services/SigninHelper.java
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package org.chromium.chrome.browser.signin; +package org.chromium.chrome.browser.signin.services; import android.accounts.Account; import android.content.Context; @@ -19,9 +19,6 @@ import org.chromium.base.Log; import org.chromium.base.TraceEvent; import org.chromium.base.task.AsyncTask; -import org.chromium.chrome.browser.signin.services.SigninManager; -import org.chromium.chrome.browser.signin.services.SigninManager.SignInCallback; -import org.chromium.chrome.browser.signin.services.SigninPreferencesManager; import org.chromium.components.signin.AccountManagerFacadeProvider; import org.chromium.components.signin.AccountTrackerService; import org.chromium.components.signin.AccountUtils; @@ -56,11 +53,10 @@ public static final class SystemAccountChangeEventChecker implements SigninHelper.AccountChangeEventChecker { @Override - public List<String> getAccountChangeEvents( - Context context, int index, String accountName) { + public List<String> getAccountChangeEvents(Context context, int index, String accountName) { try { - List<AccountChangeEvent> list = GoogleAuthUtil.getAccountChangeEvents( - context, index, accountName); + List<AccountChangeEvent> list = + GoogleAuthUtil.getAccountChangeEvents(context, index, accountName); List<String> result = new ArrayList<>(list.size()); for (AccountChangeEvent e : list) { if (e.getChangeType() == GoogleAuthUtil.CHANGE_TYPE_ACCOUNT_RENAMED_TO) { @@ -89,7 +85,7 @@ * Please use SigninHelperProvider to get SigninHelper instance instead of creating it * manually. */ - SigninHelper(SigninManager signinManager, AccountTrackerService accountTrackerService, + public SigninHelper(SigninManager signinManager, AccountTrackerService accountTrackerService, SigninPreferencesManager signinPreferencesManager) { mSigninManager = signinManager; mAccountTrackerService = accountTrackerService; @@ -192,7 +188,7 @@ final Account account = AccountUtils.createAccountFromName(newName); mSigninManager.signinAndEnableSync( - SigninAccessPoint.ACCOUNT_RENAMED, account, new SignInCallback() { + SigninAccessPoint.ACCOUNT_RENAMED, account, new SigninManager.SignInCallback() { @Override public void onSignInComplete() { validateAccountsInternal(true);
diff --git a/chrome/browser/signin/services/android/java/src/org/chromium/chrome/browser/signin/services/SigninMetricsUtils.java b/chrome/browser/signin/services/android/java/src/org/chromium/chrome/browser/signin/services/SigninMetricsUtils.java index cbd355a7..f470b24 100644 --- a/chrome/browser/signin/services/android/java/src/org/chromium/chrome/browser/signin/services/SigninMetricsUtils.java +++ b/chrome/browser/signin/services/android/java/src/org/chromium/chrome/browser/signin/services/SigninMetricsUtils.java
@@ -33,6 +33,15 @@ promoAction, AccountConsistencyPromoAction.MAX); } + /** + * Logs AccountPickerBottomSheet shown count histograms. + */ + public static void logAccountConsistencyPromoShownCount(String histogram) { + RecordHistogram.recordExactLinearHistogram(histogram, + SigninPreferencesManager.getInstance().getAccountPickerBottomSheetShownCount(), + 100); + } + @VisibleForTesting @NativeMethods public interface Natives {
diff --git a/chrome/browser/signin/services/android/java/src/org/chromium/chrome/browser/signin/services/SigninPreferencesManager.java b/chrome/browser/signin/services/android/java/src/org/chromium/chrome/browser/signin/services/SigninPreferencesManager.java index d8b7dea..171e0e09 100644 --- a/chrome/browser/signin/services/android/java/src/org/chromium/chrome/browser/signin/services/SigninPreferencesManager.java +++ b/chrome/browser/signin/services/android/java/src/org/chromium/chrome/browser/signin/services/SigninPreferencesManager.java
@@ -188,4 +188,18 @@ public String getLegacySyncAccountEmail() { return mManager.readString(ChromePreferenceKeys.SIGNIN_LEGACY_SYNC_ACCOUNT_EMAIL, null); } + + /** + * Increments the shown count for the account picker bottom sheet. + */ + public void incrementAccountPickerBottomSheetShownCount() { + mManager.incrementInt(ChromePreferenceKeys.ACCOUNT_PICKER_BOTTOM_SHEET_SHOWN_COUNT); + } + + /** + * Returns the number of times account picker bottom sheet has already been shown. + */ + public int getAccountPickerBottomSheetShownCount() { + return mManager.readInt(ChromePreferenceKeys.ACCOUNT_PICKER_BOTTOM_SHEET_SHOWN_COUNT); + } }
diff --git a/chrome/browser/subresource_filter/chrome_subresource_filter_client.cc b/chrome/browser/subresource_filter/chrome_subresource_filter_client.cc index 58e8eb0..2879967 100644 --- a/chrome/browser/subresource_filter/chrome_subresource_filter_client.cc +++ b/chrome/browser/subresource_filter/chrome_subresource_filter_client.cc
@@ -107,11 +107,6 @@ subresource_filter::mojom::ActivationLevel effective_activation_level = initial_activation_level; - if (activated_via_devtools_) { - effective_activation_level = - subresource_filter::mojom::ActivationLevel::kEnabled; - *decision = subresource_filter::ActivationDecision::FORCED_ACTIVATION; - } if (profile_context_->ads_intervention_manager()->ShouldActivate( navigation_handle)) { @@ -161,14 +156,6 @@ : nullptr; } -void ChromeSubresourceFilterClient::ToggleForceActivationInCurrentWebContents( - bool force_activation) { - if (!activated_via_devtools_ && force_activation) - subresource_filter::ContentSubresourceFilterThrottleManager::LogAction( - subresource_filter::SubresourceFilterAction::kForcedActivationEnabled); - activated_via_devtools_ = force_activation; -} - void ChromeSubresourceFilterClient::ShowUI(const GURL& url) { #if defined(OS_ANDROID) InfoBarService* infobar_service =
diff --git a/chrome/browser/subresource_filter/chrome_subresource_filter_client.h b/chrome/browser/subresource_filter/chrome_subresource_filter_client.h index b893848..0ef6322 100644 --- a/chrome/browser/subresource_filter/chrome_subresource_filter_client.h +++ b/chrome/browser/subresource_filter/chrome_subresource_filter_client.h
@@ -58,11 +58,6 @@ GetSafeBrowsingDatabaseManager() override; void OnReloadRequested() override; - // Should be called by devtools in response to a protocol command to enable ad - // blocking in this WebContents. Should only persist while devtools is - // attached. - void ToggleForceActivationInCurrentWebContents(bool force_activation); - private: void ShowUI(const GURL& url); @@ -78,11 +73,6 @@ std::unique_ptr<subresource_filter::ProfileInteractionManager> profile_interaction_manager_; - // Corresponds to a devtools command which triggers filtering on all page - // loads. We must be careful to ensure this boolean does not persist after the - // devtools window is closed, which should be handled by the devtools system. - bool activated_via_devtools_ = false; - DISALLOW_COPY_AND_ASSIGN(ChromeSubresourceFilterClient); };
diff --git a/chrome/browser/subresource_filter/subresource_filter_unittest.cc b/chrome/browser/subresource_filter/subresource_filter_unittest.cc index cf0ab237..bb0dc310 100644 --- a/chrome/browser/subresource_filter/subresource_filter_unittest.cc +++ b/chrome/browser/subresource_filter/subresource_filter_unittest.cc
@@ -182,58 +182,6 @@ EXPECT_TRUE(GetSettingsManager()->GetSiteActivationFromMetadata(url)); } -TEST_F(SubresourceFilterTest, ToggleForceActivation) { - base::HistogramTester histogram_tester; - const GURL url("https://example.test/"); - - // Navigate initially, should be no activation. - SimulateNavigateAndCommit(url, main_rfh()); - EXPECT_TRUE(CreateAndNavigateDisallowedSubframe(main_rfh())); - EXPECT_FALSE(GetSettingsManager()->GetSiteActivationFromMetadata(url)); - - // Simulate opening devtools and forcing activation. - GetClient()->ToggleForceActivationInCurrentWebContents(true); - histogram_tester.ExpectBucketCount( - kSubresourceFilterActionsHistogram, - subresource_filter::SubresourceFilterAction::kForcedActivationEnabled, 1); - - SimulateNavigateAndCommit(url, main_rfh()); - EXPECT_FALSE(CreateAndNavigateDisallowedSubframe(main_rfh())); - - histogram_tester.ExpectBucketCount( - kSubresourceFilterActionsHistogram, - subresource_filter::SubresourceFilterAction::kUIShown, 1); - - EXPECT_TRUE(GetSettingsManager()->GetSiteActivationFromMetadata(url)); - histogram_tester.ExpectBucketCount( - "SubresourceFilter.PageLoad.ActivationDecision", - subresource_filter::ActivationDecision::FORCED_ACTIVATION, 1); - - // Simulate closing devtools. - GetClient()->ToggleForceActivationInCurrentWebContents(false); - - SimulateNavigateAndCommit(url, main_rfh()); - EXPECT_TRUE(CreateAndNavigateDisallowedSubframe(main_rfh())); - histogram_tester.ExpectBucketCount( - kSubresourceFilterActionsHistogram, - subresource_filter::SubresourceFilterAction::kForcedActivationEnabled, 1); -} - -TEST_F(SubresourceFilterTest, ToggleOffForceActivation_AfterCommit) { - base::HistogramTester histogram_tester; - GetClient()->ToggleForceActivationInCurrentWebContents(true); - const GURL url("https://example.test/"); - SimulateNavigateAndCommit(url, main_rfh()); - GetClient()->ToggleForceActivationInCurrentWebContents(false); - - // Resource should be disallowed, since navigation commit had activation. - EXPECT_FALSE(CreateAndNavigateDisallowedSubframe(main_rfh())); - - histogram_tester.ExpectBucketCount( - kSubresourceFilterActionsHistogram, - subresource_filter::SubresourceFilterAction::kUIShown, 1); -} - enum class AdBlockOnAbusiveSitesTest { kEnabled, kDisabled }; TEST_F(SubresourceFilterTest, NotifySafeBrowsing) {
diff --git a/chrome/browser/ui/passwords/manage_passwords_test.cc b/chrome/browser/ui/passwords/manage_passwords_test.cc index e2b439a..2dcd2053 100644 --- a/chrome/browser/ui/passwords/manage_passwords_test.cc +++ b/chrome/browser/ui/passwords/manage_passwords_test.cc
@@ -155,7 +155,8 @@ // This is an unrelated compromised credential that should still be fixed. password_manager::CompromisedCredentials compromised( "https://somesite.com/", ASCIIToUTF16(kTestUsername), base::Time(), - password_manager::CompromiseType::kLeaked, false); + password_manager::CompromiseType::kLeaked, + password_manager::IsMuted(false)); password_store->AddCompromisedCredentials(compromised); SetupPendingPassword(); GetController()->SavePassword(password_form_.username_value, @@ -174,10 +175,12 @@ // This is an unrelated compromised credential that should still be fixed. password_manager::CompromisedCredentials some_compromised( "https://somesite.com/", ASCIIToUTF16(kTestUsername), base::Time(), - password_manager::CompromiseType::kLeaked, false); + password_manager::CompromiseType::kLeaked, + password_manager::IsMuted(false)); password_manager::CompromisedCredentials current_compromised( password_form_.signon_realm, password_form_.username_value, base::Time(), - password_manager::CompromiseType::kLeaked, false); + password_manager::CompromiseType::kLeaked, + password_manager::IsMuted(false)); password_store->AddCompromisedCredentials(some_compromised); password_store->AddCompromisedCredentials(current_compromised); SetupPendingPassword(); @@ -236,7 +239,8 @@ password_manager::CompromisedCredentials compromised( password_form_.signon_realm, password_form_.username_value, base::Time(), - password_manager::CompromiseType::kLeaked, false); + password_manager::CompromiseType::kLeaked, + password_manager::IsMuted(false)); fetcher_.set_compromised({compromised}); fetcher_.NotifyFetchCompleted();
diff --git a/chrome/browser/ui/passwords/manage_passwords_ui_controller_unittest.cc b/chrome/browser/ui/passwords/manage_passwords_ui_controller_unittest.cc index 417b9930..1f5e337 100644 --- a/chrome/browser/ui/passwords/manage_passwords_ui_controller_unittest.cc +++ b/chrome/browser/ui/passwords/manage_passwords_ui_controller_unittest.cc
@@ -212,9 +212,10 @@ } CompromisedCredentials CreateCompromised(const PasswordForm& form) { - return CompromisedCredentials( - form.signon_realm, form.username_value, base::Time(), - password_manager::CompromiseType::kLeaked, false); + return CompromisedCredentials(form.signon_realm, form.username_value, + base::Time(), + password_manager::CompromiseType::kLeaked, + password_manager::IsMuted(false)); } } // namespace
diff --git a/chrome/browser/ui/signin/dice_web_signin_interceptor_delegate.cc b/chrome/browser/ui/signin/dice_web_signin_interceptor_delegate.cc index 5064d892..2a30ffc 100644 --- a/chrome/browser/ui/signin/dice_web_signin_interceptor_delegate.cc +++ b/chrome/browser/ui/signin/dice_web_signin_interceptor_delegate.cc
@@ -13,15 +13,16 @@ DiceWebSigninInterceptorDelegate::~DiceWebSigninInterceptorDelegate() = default; -void DiceWebSigninInterceptorDelegate::ShowSigninInterceptionBubble( +std::unique_ptr<ScopedDiceWebSigninInterceptionBubbleHandle> +DiceWebSigninInterceptorDelegate::ShowSigninInterceptionBubble( content::WebContents* web_contents, const BubbleParameters& bubble_parameters, base::OnceCallback<void(SigninInterceptionResult)> callback) { if (!web_contents) { std::move(callback).Run(SigninInterceptionResult::kNotDisplayed); - return; + return nullptr; } - ShowSigninInterceptionBubbleInternal( + return ShowSigninInterceptionBubbleInternal( chrome::FindBrowserWithWebContents(web_contents), bubble_parameters, std::move(callback)); }
diff --git a/chrome/browser/ui/signin/dice_web_signin_interceptor_delegate.h b/chrome/browser/ui/signin/dice_web_signin_interceptor_delegate.h index 3d020e0..b796032 100644 --- a/chrome/browser/ui/signin/dice_web_signin_interceptor_delegate.h +++ b/chrome/browser/ui/signin/dice_web_signin_interceptor_delegate.h
@@ -22,7 +22,8 @@ ~DiceWebSigninInterceptorDelegate() override; // DiceWebSigninInterceptor::Delegate - void ShowSigninInterceptionBubble( + std::unique_ptr<ScopedDiceWebSigninInterceptionBubbleHandle> + ShowSigninInterceptionBubble( content::WebContents* web_contents, const BubbleParameters& bubble_parameters, base::OnceCallback<void(SigninInterceptionResult)> callback) override; @@ -30,7 +31,8 @@ private: // Implemented in dice_web_signin_interception_bubble_view.cc - void ShowSigninInterceptionBubbleInternal( + std::unique_ptr<ScopedDiceWebSigninInterceptionBubbleHandle> + ShowSigninInterceptionBubbleInternal( Browser* browser, const BubbleParameters& bubble_parameters, base::OnceCallback<void(SigninInterceptionResult)> callback);
diff --git a/chrome/browser/ui/thumbnails/thumbnail_image.cc b/chrome/browser/ui/thumbnails/thumbnail_image.cc index bfaa104e..3a8e8433 100644 --- a/chrome/browser/ui/thumbnails/thumbnail_image.cc +++ b/chrome/browser/ui/thumbnails/thumbnail_image.cc
@@ -4,10 +4,8 @@ #include "chrome/browser/ui/thumbnails/thumbnail_image.h" -#include <algorithm> #include <utility> -#include "base/memory/ptr_util.h" #include "base/metrics/histogram_macros.h" #include "base/task/post_task.h" #include "base/task/task_traits.h" @@ -17,12 +15,15 @@ #include "ui/gfx/codec/jpeg_codec.h" #include "ui/gfx/skia_util.h" -ThumbnailImage::Subscription::Subscription( - scoped_refptr<ThumbnailImage> thumbnail) - : thumbnail_(std::move(thumbnail)) {} +void ThumbnailImage::Observer::OnThumbnailImageAvailable( + gfx::ImageSkia thumbnail_image) {} -ThumbnailImage::Subscription::~Subscription() { - thumbnail_->HandleSubscriptionDestroyed(this); +void ThumbnailImage::Observer::OnCompressedThumbnailDataAvailable( + CompressedThumbnailData thumbnail_data) {} + +base::Optional<gfx::Size> ThumbnailImage::Observer::GetThumbnailSizeHint() + const { + return base::nullopt; } ThumbnailImage::Delegate::~Delegate() { @@ -45,17 +46,29 @@ delegate_->thumbnail_ = nullptr; } -std::unique_ptr<ThumbnailImage::Subscription> ThumbnailImage::Subscribe() { - // Use explicit new since Subscription constructor is private. - auto subscription = - base::WrapUnique(new Subscription(base::WrapRefCounted(this))); - subscribers_.insert(subscribers_.end(), subscription.get()); +void ThumbnailImage::AddObserver(Observer* observer) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK(observer); + if (!observers_.HasObserver(observer)) { + const bool is_first_observer = !observers_.might_have_observers(); + observers_.AddObserver(observer); + if (is_first_observer && delegate_) + delegate_->ThumbnailImageBeingObservedChanged(true); + } +} - // Notify |delegate_| if this is the first subscriber. - if (subscribers_.size() == 1) - delegate_->ThumbnailImageBeingObservedChanged(true); +void ThumbnailImage::RemoveObserver(Observer* observer) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK(observer); + if (observers_.HasObserver(observer)) { + observers_.RemoveObserver(observer); + if (delegate_ && !observers_.might_have_observers()) + delegate_->ThumbnailImageBeingObservedChanged(false); + } +} - return subscription; +bool ThumbnailImage::HasObserver(const Observer* observer) const { + return observers_.HasObserver(observer); } void ThumbnailImage::AssignSkBitmap(SkBitmap bitmap) { @@ -126,22 +139,18 @@ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (async_operation_finished_callback_) async_operation_finished_callback_.Run(); - - for (Subscription* subscription : subscribers_) { - auto size_hint = subscription->size_hint_; - if (subscription->uncompressed_image_callback_) - subscription->uncompressed_image_callback_.Run( - size_hint ? CropPreviewImage(image, *size_hint) : image); + for (auto& observer : observers_) { + auto size_hint = observer.GetThumbnailSizeHint(); + observer.OnThumbnailImageAvailable( + size_hint ? CropPreviewImage(image, *size_hint) : image); } } void ThumbnailImage::NotifyCompressedDataObservers( CompressedThumbnailData data) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - for (Subscription* subscription : subscribers_) { - if (subscription->compressed_image_callback_) - subscription->compressed_image_callback_.Run(data); - } + for (auto& observer : observers_) + observer.OnCompressedThumbnailDataAvailable(data); } // static @@ -199,17 +208,3 @@ source_image.bitmap()->extractSubset(&cropped, gfx::RectToSkIRect(clip_rect)); return gfx::ImageSkia::CreateFrom1xBitmap(cropped); } - -void ThumbnailImage::HandleSubscriptionDestroyed(Subscription* subscription) { - // The order of |subscribers_| does not matter. We can simply swap - // |subscription| in |subscribers_| with the last element, then pop it - // off the back. - auto it = std::find(subscribers_.begin(), subscribers_.end(), subscription); - DCHECK(it != subscribers_.end()); - std::swap(*it, *(subscribers_.end() - 1)); - subscribers_.pop_back(); - - // If that was the last subscriber, tell |delegate_|. - if (subscribers_.empty()) - delegate_->ThumbnailImageBeingObservedChanged(false); -}
diff --git a/chrome/browser/ui/thumbnails/thumbnail_image.h b/chrome/browser/ui/thumbnails/thumbnail_image.h index fce916a..9b67c4f 100644 --- a/chrome/browser/ui/thumbnails/thumbnail_image.h +++ b/chrome/browser/ui/thumbnails/thumbnail_image.h
@@ -5,12 +5,10 @@ #ifndef CHROME_BROWSER_UI_THUMBNAILS_THUMBNAIL_IMAGE_H_ #define CHROME_BROWSER_UI_THUMBNAILS_THUMBNAIL_IMAGE_H_ -#include <memory> #include <utility> #include <vector> #include "base/callback.h" -#include "base/containers/flat_set.h" #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" #include "base/observer_list.h" @@ -31,27 +29,16 @@ using CompressedThumbnailData = scoped_refptr<base::RefCountedData<std::vector<uint8_t>>>; - class Subscription { + // Observes uncompressed and/or compressed versions of the thumbnail image as + // they are available. + class Observer : public base::CheckedObserver { public: - Subscription() = delete; - ~Subscription(); + // Receives uncompressed thumbnail image data. Default is no-op. + virtual void OnThumbnailImageAvailable(gfx::ImageSkia thumbnail_image); - using UncompressedImageCallback = - base::RepeatingCallback<void(gfx::ImageSkia)>; - using CompressedImageCallback = - base::RepeatingCallback<void(CompressedThumbnailData)>; - - // Set callbacks to receive image data. Subscribers are not allowed - // to unsubscribe (by destroying |this|) from the callback. If - // necessary, post a task to destroy it soon after. - - void SetUncompressedImageCallback(UncompressedImageCallback callback) { - uncompressed_image_callback_ = std::move(callback); - } - - void SetCompressedImageCallback(CompressedImageCallback callback) { - compressed_image_callback_ = std::move(callback); - } + // Receives compressed thumbnail image data. Default is no-op. + virtual void OnCompressedThumbnailDataAvailable( + CompressedThumbnailData thumbnail_data); // Provides a desired aspect ratio and minimum size that the observer will // accept. If not specified, or if available thumbnail data is smaller in @@ -67,20 +54,7 @@ // image passed to OnThumbnailImageAvailable fits the needs of the observer // for display purposes, without the observer having to further crop the // image. The default is unspecified. - void SetSizeHint(const base::Optional<gfx::Size>& size_hint) { - size_hint_ = size_hint; - } - - private: - friend class ThumbnailImage; - - explicit Subscription(scoped_refptr<ThumbnailImage> thumbnail); - - scoped_refptr<ThumbnailImage> thumbnail_; - base::Optional<gfx::Size> size_hint_; - - UncompressedImageCallback uncompressed_image_callback_; - CompressedImageCallback compressed_image_callback_; + virtual base::Optional<gfx::Size> GetThumbnailSizeHint() const; }; // Represents the endpoint @@ -103,14 +77,9 @@ bool has_data() const { return data_.get(); } - // Subscribe to thumbnail updates. See |Subscription| to set a - // callback and conigure additional options. - // - // Even if a callback is not set, the subscription influences - // thumbnail capture. It should be destroyed when updates are not - // needed. It is designed to be stored in base::Optional, created and - // destroyed as needed. - std::unique_ptr<Subscription> Subscribe(); + void AddObserver(Observer* observer); + void RemoveObserver(Observer* observer); + bool HasObserver(const Observer* observer) const; // Sets the SkBitmap data and notifies observers with the resulting image. void AssignSkBitmap(SkBitmap bitmap); @@ -161,18 +130,11 @@ static gfx::ImageSkia CropPreviewImage(const gfx::ImageSkia& source_image, const gfx::Size& minimum_size); - void HandleSubscriptionDestroyed(Subscription* subscription); - Delegate* delegate_; CompressedThumbnailData data_; - // Subscriptions are inserted on |Subscribe()| calls and removed when - // they are destroyed via callback. The order of subscriber - // notification doesn't matter, so don't maintain any ordering. Since - // the number of subscribers for a given thumbnail is expected to be - // small, doing a linear search to remove a subscriber is fine. - std::vector<Subscription*> subscribers_; + base::ObserverList<Observer> observers_; // Called when an asynchronous operation (such as encoding image data upon // assignment or decoding image data for observers) finishes or fails.
diff --git a/chrome/browser/ui/thumbnails/thumbnail_image_unittest.cc b/chrome/browser/ui/thumbnails/thumbnail_image_unittest.cc index 8533b63..93b7ed7c 100644 --- a/chrome/browser/ui/thumbnails/thumbnail_image_unittest.cc +++ b/chrome/browser/ui/thumbnails/thumbnail_image_unittest.cc
@@ -9,7 +9,6 @@ #include "base/bind.h" #include "base/macros.h" -#include "base/memory/weak_ptr.h" #include "base/run_loop.h" #include "base/scoped_observer.h" #include "base/test/task_environment.h" @@ -21,47 +20,81 @@ constexpr int kTestBitmapWidth = 200; constexpr int kTestBitmapHeight = 123; -template <typename... T> -base::RepeatingCallback<void(T...)> IgnoreArgs( - base::RepeatingCallback<void()> cb) { - auto helper = [](T...) {}; - return base::BindRepeating(helper).Then(std::move(cb)); -} - -class CallbackWaiter { +// Waits for thumbnail images (or compressed data) and can report how many +// images it has received. +class TestThumbnailImageObserver : public ThumbnailImage::Observer { public: - CallbackWaiter() { - callback_ = base::BindRepeating(&CallbackWaiter::HandleCallback, - weak_ptr_factory_.GetWeakPtr()); + // Wait for the uncompressed thumbnail image. + void WaitForImage() { + if (new_image_count_ > last_image_count_) { + last_image_count_ = new_image_count_; + return; + } + + // Need a fresh loop since we may have quit out of the last one. + run_loop_ = std::make_unique<base::RunLoop>(); + waiting_for_image_ = true; + run_loop_->Run(); } - base::RepeatingClosure callback() { return callback_; } - - bool called() const { return called_; } - - void Reset() { called_ = false; } - - void Wait() { - if (called_) + // Wait for compressed thumbnail data. + void WaitForCompressedData() { + if (new_compressed_count_ > last_compressed_count_) { + last_compressed_count_ = new_compressed_count_; return; + } - base::RunLoop run_loop; - quit_closure_ = run_loop.QuitClosure(); - run_loop.Run(); + // Need a fresh loop since we may have quit out of the last one. + run_loop_ = std::make_unique<base::RunLoop>(); + waiting_for_data_ = true; + run_loop_->Run(); + } + + int new_image_count() const { return new_image_count_; } + gfx::ImageSkia thumbnail_image() const { return thumbnail_image_; } + int new_compressed_count() const { return new_compressed_count_; } + ThumbnailImage::CompressedThumbnailData compressed_data() const { + return compressed_data_; + } + + ScopedObserver<ThumbnailImage, ThumbnailImage::Observer>* scoped_observer() { + return &scoped_observer_; } private: - void HandleCallback() { - if (quit_closure_) - std::move(quit_closure_).Run(); - called_ = true; + // ThumbnailImage::Observer: + void OnThumbnailImageAvailable(gfx::ImageSkia thumbnail_image) override { + ++new_image_count_; + thumbnail_image_ = thumbnail_image; + if (waiting_for_image_) { + last_image_count_ = new_image_count_; + run_loop_->Quit(); + waiting_for_image_ = false; + } } - base::RepeatingClosure callback_; - base::OnceClosure quit_closure_; - bool called_ = false; + void OnCompressedThumbnailDataAvailable( + ThumbnailImage::CompressedThumbnailData thumbnail_data) override { + ++new_compressed_count_; + compressed_data_ = thumbnail_data; + if (waiting_for_data_) { + last_compressed_count_ = new_compressed_count_; + run_loop_->Quit(); + waiting_for_data_ = false; + } + } - base::WeakPtrFactory<CallbackWaiter> weak_ptr_factory_{this}; + ScopedObserver<ThumbnailImage, ThumbnailImage::Observer> scoped_observer_{ + this}; + int new_image_count_ = 0; + int last_image_count_ = 0; + gfx::ImageSkia thumbnail_image_; + int new_compressed_count_ = 0; + int last_compressed_count_ = 0; + ThumbnailImage::CompressedThumbnailData compressed_data_; + bool waiting_for_image_ = false; + bool waiting_for_data_ = false; + std::unique_ptr<base::RunLoop> run_loop_; }; } // anonymous namespace @@ -95,192 +128,155 @@ DISALLOW_COPY_AND_ASSIGN(ThumbnailImageTest); }; -using Subscription = ThumbnailImage::Subscription; - -TEST_F(ThumbnailImageTest, AddRemoveSubscriber) { +TEST_F(ThumbnailImageTest, Add_Remove_Observer) { auto image = base::MakeRefCounted<ThumbnailImage>(this); EXPECT_FALSE(is_being_observed()); - - std::unique_ptr<Subscription> subscription = image->Subscribe(); + TestThumbnailImageObserver observer; + image->AddObserver(&observer); + EXPECT_TRUE(image->HasObserver(&observer)); EXPECT_TRUE(is_being_observed()); - - subscription.reset(); + image->RemoveObserver(&observer); + EXPECT_FALSE(image->HasObserver(&observer)); EXPECT_FALSE(is_being_observed()); } -TEST_F(ThumbnailImageTest, AddRemoveMultipleObservers) { +TEST_F(ThumbnailImageTest, Add_Remove_MultipleObservers) { auto image = base::MakeRefCounted<ThumbnailImage>(this); EXPECT_FALSE(is_being_observed()); - - std::unique_ptr<Subscription> subscription1 = image->Subscribe(); + TestThumbnailImageObserver observer; + TestThumbnailImageObserver observer2; + image->AddObserver(&observer); + EXPECT_TRUE(image->HasObserver(&observer)); EXPECT_TRUE(is_being_observed()); - - std::unique_ptr<Subscription> subscription2 = image->Subscribe(); + image->AddObserver(&observer2); + EXPECT_TRUE(image->HasObserver(&observer2)); EXPECT_TRUE(is_being_observed()); - - subscription1.reset(); + image->RemoveObserver(&observer); + EXPECT_FALSE(image->HasObserver(&observer)); + EXPECT_TRUE(image->HasObserver(&observer2)); EXPECT_TRUE(is_being_observed()); - - subscription2.reset(); + image->RemoveObserver(&observer2); + EXPECT_FALSE(image->HasObserver(&observer2)); EXPECT_FALSE(is_being_observed()); } -TEST_F(ThumbnailImageTest, AssignSkBitmapNotifiesObservers) { +TEST_F(ThumbnailImageTest, AssignSkBitmap_NotifiesObservers) { auto image = base::MakeRefCounted<ThumbnailImage>(this); - - std::unique_ptr<Subscription> subscription1 = image->Subscribe(); - std::unique_ptr<Subscription> subscription2 = image->Subscribe(); - - CallbackWaiter waiter1; - subscription1->SetUncompressedImageCallback( - IgnoreArgs<gfx::ImageSkia>(waiter1.callback())); - - CallbackWaiter waiter2; - subscription2->SetUncompressedImageCallback( - IgnoreArgs<gfx::ImageSkia>(waiter2.callback())); + TestThumbnailImageObserver observer; + TestThumbnailImageObserver observer2; + observer.scoped_observer()->Add(image.get()); + observer2.scoped_observer()->Add(image.get()); SkBitmap bitmap = CreateBitmap(kTestBitmapWidth, kTestBitmapHeight); image->AssignSkBitmap(bitmap); - - waiter1.Wait(); - waiter2.Wait(); - EXPECT_TRUE(waiter1.called()); - EXPECT_TRUE(waiter2.called()); + observer.WaitForImage(); + observer2.WaitForImage(); + EXPECT_EQ(1, observer.new_image_count()); + EXPECT_EQ(1, observer2.new_image_count()); + EXPECT_FALSE(observer.thumbnail_image().isNull()); + EXPECT_FALSE(observer2.thumbnail_image().isNull()); + EXPECT_EQ(gfx::Size(kTestBitmapWidth, kTestBitmapHeight), + observer.thumbnail_image().size()); } TEST_F(ThumbnailImageTest, AssignSkBitmap_NotifiesObserversAgain) { auto image = base::MakeRefCounted<ThumbnailImage>(this); - - std::unique_ptr<Subscription> subscription1 = image->Subscribe(); - std::unique_ptr<Subscription> subscription2 = image->Subscribe(); - - CallbackWaiter waiter1; - subscription1->SetUncompressedImageCallback( - IgnoreArgs<gfx::ImageSkia>(waiter1.callback())); - - CallbackWaiter waiter2; - subscription2->SetUncompressedImageCallback( - IgnoreArgs<gfx::ImageSkia>(waiter2.callback())); + TestThumbnailImageObserver observer; + TestThumbnailImageObserver observer2; + observer.scoped_observer()->Add(image.get()); + observer2.scoped_observer()->Add(image.get()); SkBitmap bitmap = CreateBitmap(kTestBitmapWidth, kTestBitmapHeight); image->AssignSkBitmap(bitmap); - - waiter1.Wait(); - waiter2.Wait(); - EXPECT_TRUE(waiter1.called()); - EXPECT_TRUE(waiter2.called()); - - waiter1.Reset(); - waiter2.Reset(); - + observer.WaitForImage(); + observer2.WaitForImage(); image->AssignSkBitmap(bitmap); - - waiter1.Wait(); - waiter2.Wait(); - EXPECT_TRUE(waiter1.called()); - EXPECT_TRUE(waiter2.called()); + observer.WaitForImage(); + observer2.WaitForImage(); + EXPECT_EQ(2, observer.new_image_count()); + EXPECT_EQ(2, observer2.new_image_count()); + EXPECT_FALSE(observer.thumbnail_image().isNull()); + EXPECT_FALSE(observer2.thumbnail_image().isNull()); + EXPECT_EQ(gfx::Size(kTestBitmapWidth, kTestBitmapHeight), + observer.thumbnail_image().size()); } TEST_F(ThumbnailImageTest, AssignSkBitmap_NotifiesCompressedObservers) { auto image = base::MakeRefCounted<ThumbnailImage>(this); - - std::unique_ptr<Subscription> subscription1 = image->Subscribe(); - std::unique_ptr<Subscription> subscription2 = image->Subscribe(); - - CallbackWaiter waiter1; - subscription1->SetCompressedImageCallback( - IgnoreArgs<ThumbnailImage::CompressedThumbnailData>(waiter1.callback())); - - CallbackWaiter waiter2; - subscription2->SetCompressedImageCallback( - IgnoreArgs<ThumbnailImage::CompressedThumbnailData>(waiter2.callback())); + TestThumbnailImageObserver observer; + TestThumbnailImageObserver observer2; + observer.scoped_observer()->Add(image.get()); + observer2.scoped_observer()->Add(image.get()); SkBitmap bitmap = CreateBitmap(kTestBitmapWidth, kTestBitmapHeight); - image->AssignSkBitmap(bitmap); + auto compressed = Compress(bitmap); - waiter1.Wait(); - waiter2.Wait(); - EXPECT_TRUE(waiter1.called()); - EXPECT_TRUE(waiter2.called()); + image->AssignSkBitmap(bitmap); + observer.WaitForCompressedData(); + observer2.WaitForCompressedData(); + EXPECT_EQ(1, observer.new_compressed_count()); + EXPECT_EQ(1, observer2.new_compressed_count()); + EXPECT_TRUE(observer.compressed_data()); + EXPECT_TRUE(observer2.compressed_data()); + EXPECT_EQ(compressed, observer.compressed_data()->data); + EXPECT_EQ(compressed, observer2.compressed_data()->data); } TEST_F(ThumbnailImageTest, AssignSkBitmap_NotifiesCompressedObserversAgain) { auto image = base::MakeRefCounted<ThumbnailImage>(this); - - std::unique_ptr<Subscription> subscription1 = image->Subscribe(); - std::unique_ptr<Subscription> subscription2 = image->Subscribe(); - - CallbackWaiter waiter1; - subscription1->SetCompressedImageCallback( - IgnoreArgs<ThumbnailImage::CompressedThumbnailData>(waiter1.callback())); - - CallbackWaiter waiter2; - subscription2->SetCompressedImageCallback( - IgnoreArgs<ThumbnailImage::CompressedThumbnailData>(waiter2.callback())); + TestThumbnailImageObserver observer; + TestThumbnailImageObserver observer2; + observer.scoped_observer()->Add(image.get()); + observer2.scoped_observer()->Add(image.get()); SkBitmap bitmap = CreateBitmap(kTestBitmapWidth, kTestBitmapHeight); - image->AssignSkBitmap(bitmap); - - waiter1.Wait(); - waiter2.Wait(); - EXPECT_TRUE(waiter1.called()); - EXPECT_TRUE(waiter2.called()); - - waiter1.Reset(); - waiter2.Reset(); + auto compressed = Compress(bitmap); image->AssignSkBitmap(bitmap); - - waiter1.Wait(); - waiter2.Wait(); - EXPECT_TRUE(waiter1.called()); - EXPECT_TRUE(waiter2.called()); + observer.WaitForCompressedData(); + observer2.WaitForCompressedData(); + image->AssignSkBitmap(bitmap); + observer.WaitForCompressedData(); + observer2.WaitForCompressedData(); + EXPECT_EQ(2, observer.new_compressed_count()); + EXPECT_EQ(2, observer2.new_compressed_count()); + EXPECT_TRUE(observer.compressed_data()); + EXPECT_TRUE(observer2.compressed_data()); + EXPECT_EQ(compressed, observer.compressed_data()->data); + EXPECT_EQ(compressed, observer2.compressed_data()->data); } TEST_F(ThumbnailImageTest, RequestThumbnailImage) { auto image = base::MakeRefCounted<ThumbnailImage>(this); - - std::unique_ptr<Subscription> subscription1 = image->Subscribe(); - - CallbackWaiter waiter1; - subscription1->SetUncompressedImageCallback( - IgnoreArgs<gfx::ImageSkia>(waiter1.callback())); + TestThumbnailImageObserver observer; + observer.scoped_observer()->Add(image.get()); SkBitmap bitmap = CreateBitmap(kTestBitmapWidth, kTestBitmapHeight); image->AssignSkBitmap(bitmap); - waiter1.Wait(); - EXPECT_TRUE(waiter1.called()); - waiter1.Reset(); + observer.WaitForImage(); - std::unique_ptr<Subscription> subscription2 = image->Subscribe(); - - CallbackWaiter waiter2; - subscription2->SetUncompressedImageCallback( - IgnoreArgs<gfx::ImageSkia>(waiter2.callback())); - + TestThumbnailImageObserver observer2; + observer2.scoped_observer()->Add(image.get()); image->RequestThumbnailImage(); - waiter1.Wait(); - waiter2.Wait(); - EXPECT_TRUE(waiter1.called()); - EXPECT_TRUE(waiter2.called()); + observer.WaitForImage(); + observer2.WaitForImage(); + EXPECT_EQ(2, observer.new_image_count()); + EXPECT_EQ(1, observer2.new_image_count()); + EXPECT_FALSE(observer2.thumbnail_image().isNull()); + EXPECT_EQ(gfx::Size(kTestBitmapWidth, kTestBitmapHeight), + observer2.thumbnail_image().size()); } TEST_F(ThumbnailImageTest, RequestCompressedThumbnailData) { auto image = base::MakeRefCounted<ThumbnailImage>(this); + TestThumbnailImageObserver observer; + observer.scoped_observer()->Add(image.get()); - std::unique_ptr<Subscription> subscription = image->Subscribe(); - - CallbackWaiter waiter; - subscription->SetCompressedImageCallback( - IgnoreArgs<ThumbnailImage::CompressedThumbnailData>(waiter.callback())); - - SkBitmap bitmap = CreateBitmap(kTestBitmapWidth, kTestBitmapHeight); + SkBitmap bitmap = CreateBitmap(kTestBitmapHeight, kTestBitmapHeight); image->AssignSkBitmap(bitmap); - waiter.Wait(); - EXPECT_TRUE(waiter.called()); - waiter.Reset(); + observer.WaitForImage(); + const int count_before_request = observer.new_compressed_count(); image->RequestCompressedThumbnailData(); - waiter.Wait(); - EXPECT_TRUE(waiter.called()); + EXPECT_EQ(count_before_request + 1, observer.new_compressed_count()); }
diff --git a/chrome/browser/ui/thumbnails/thumbnail_tab_helper_browsertest.cc b/chrome/browser/ui/thumbnails/thumbnail_tab_helper_browsertest.cc index 6ecc30d0..3e1ce62 100644 --- a/chrome/browser/ui/thumbnails/thumbnail_tab_helper_browsertest.cc +++ b/chrome/browser/ui/thumbnails/thumbnail_tab_helper_browsertest.cc
@@ -29,30 +29,37 @@ namespace { -class ThumbnailWaiter { +class ThumbnailWaiter : public ThumbnailImage::Observer { public: ThumbnailWaiter() = default; - ~ThumbnailWaiter() = default; + ~ThumbnailWaiter() override = default; base::Optional<gfx::ImageSkia> WaitForThumbnail(ThumbnailImage* thumbnail) { - std::unique_ptr<ThumbnailImage::Subscription> subscription = - thumbnail->Subscribe(); - subscription->SetUncompressedImageCallback(base::BindRepeating( - &ThumbnailWaiter::ThumbnailImageCallback, base::Unretained(this))); - thumbnail->RequestThumbnailImage(); + DCHECK(!thumbnail_); + thumbnail_ = thumbnail; + scoped_observer_.Add(thumbnail); + thumbnail_->RequestThumbnailImage(); run_loop_.Run(); return image_; } protected: - void ThumbnailImageCallback(gfx::ImageSkia thumbnail_image) { - image_ = std::move(thumbnail_image); - run_loop_.Quit(); + // ThumbnailImage::Observer: + void OnThumbnailImageAvailable(gfx::ImageSkia thumbnail_image) override { + if (thumbnail_) { + scoped_observer_.Remove(thumbnail_); + thumbnail_ = nullptr; + image_ = thumbnail_image; + run_loop_.Quit(); + } } private: base::RunLoop run_loop_; + ThumbnailImage* thumbnail_ = nullptr; base::Optional<gfx::ImageSkia> image_; + ScopedObserver<ThumbnailImage, ThumbnailImage::Observer> scoped_observer_{ + this}; }; } // anonymous namespace
diff --git a/chrome/browser/ui/views/overlay/overlay_window_views.cc b/chrome/browser/ui/views/overlay/overlay_window_views.cc index 45629d2..6779068 100644 --- a/chrome/browser/ui/views/overlay/overlay_window_views.cc +++ b/chrome/browser/ui/views/overlay/overlay_window_views.cc
@@ -480,7 +480,6 @@ resize_handle_view_ = AddChildView(&view_holder_, std::move(resize_handle_view)); #endif - UpdateControlsVisibility(false); } void OverlayWindowViews::OnRootViewReady() { @@ -496,6 +495,9 @@ for (std::unique_ptr<views::View>& child : view_holder_) contents_view->AddChildView(std::move(child)); view_holder_.clear(); + + // Don't show the controls until the mouse hovers over the window. + UpdateControlsVisibility(false); } void OverlayWindowViews::UpdateLayerBoundsWithLetterboxing( @@ -626,7 +628,7 @@ visible_controls_views[0]->SetPosition( gfx::Point(mid_window_x - kSecondaryControlSize.width() / 2, secondary_control_y)); - return; + break; } case 2: { /* | ----- [ ] [ ] ----- | */ @@ -638,7 +640,7 @@ visible_controls_views[1]->SetSize(kSecondaryControlSize); visible_controls_views[1]->SetPosition( gfx::Point(mid_window_x + kControlMargin / 2, secondary_control_y)); - return; + break; } case 3: { /* | --- [ ] [ ] [ ] --- | */ @@ -669,7 +671,7 @@ mid_window_x + kSecondaryControlSize.width() / 2 + kControlMargin, secondary_control_y)); } - return; + break; } case 4: { /* | - [ ] [ ] [ ] [ ] - | */ @@ -692,10 +694,15 @@ visible_controls_views[3]->SetPosition(gfx::Point( mid_window_x + kControlMargin * 3 / 2 + kSecondaryControlSize.width(), secondary_control_y)); - return; + break; } + default: + NOTREACHED(); } - DCHECK(false); + + // This will actually update the visibility of a control that was just added + // or removed, see SetPlayPauseButtonVisibility(), etc. + UpdateControlsVisibility(AreControlsVisible()); } gfx::Rect OverlayWindowViews::CalculateControlsBounds(int x, @@ -779,7 +786,11 @@ } void OverlayWindowViews::SetSkipAdButtonVisibility(bool is_visible) { + if (show_skip_ad_button_ == is_visible) + return; + show_skip_ad_button_ = is_visible; + UpdateControlsBounds(); } void OverlayWindowViews::SetNextTrackButtonVisibility(bool is_visible) { @@ -1032,6 +1043,11 @@ return controls_scrim_view_->layer()->visible(); } +bool OverlayWindowViews::IsLayoutPendingForTesting() const { + return update_controls_bounds_timer_ && + update_controls_bounds_timer_->IsRunning(); +} + ui::Layer* OverlayWindowViews::GetControlsScrimLayer() { return controls_scrim_view_->layer(); } @@ -1108,8 +1124,8 @@ return skip_ad_controls_view_; } -gfx::Point OverlayWindowViews::back_to_tab_image_position_for_testing() const { - return back_to_tab_controls_view_->origin(); +views::View* OverlayWindowViews::back_to_tab_controls_for_testing() const { + return back_to_tab_controls_view_; } gfx::Point OverlayWindowViews::close_image_position_for_testing() const {
diff --git a/chrome/browser/ui/views/overlay/overlay_window_views.h b/chrome/browser/ui/views/overlay/overlay_window_views.h index 96fe145..de1b130 100644 --- a/chrome/browser/ui/views/overlay/overlay_window_views.h +++ b/chrome/browser/ui/views/overlay/overlay_window_views.h
@@ -84,11 +84,15 @@ // visible. bool AreControlsVisible() const; + // Determines whether a layout of the window controls has been scheduled but + // is not done yet. + bool IsLayoutPendingForTesting() const; + views::PlaybackImageButton* play_pause_controls_view_for_testing() const; views::TrackImageButton* next_track_controls_view_for_testing() const; views::TrackImageButton* previous_track_controls_view_for_testing() const; views::SkipAdLabelButton* skip_ad_controls_view_for_testing() const; - gfx::Point back_to_tab_image_position_for_testing() const; + views::View* back_to_tab_controls_for_testing() const; gfx::Point close_image_position_for_testing() const; gfx::Point resize_handle_position_for_testing() const; OverlayWindowViews::PlaybackState playback_state_for_testing() const;
diff --git a/chrome/browser/ui/views/overlay/overlay_window_views_unittest.cc b/chrome/browser/ui/views/overlay/overlay_window_views_unittest.cc index 0b5d15b4..1ceb903 100644 --- a/chrome/browser/ui/views/overlay/overlay_window_views_unittest.cc +++ b/chrome/browser/ui/views/overlay/overlay_window_views_unittest.cc
@@ -6,6 +6,7 @@ #include <utility> #include "chrome/browser/ui/views/overlay/overlay_window_views.h" +#include "chrome/browser/ui/views/overlay/track_image_button.h" #include "chrome/test/base/testing_profile.h" #include "chrome/test/views/chrome_views_test_base.h" #include "content/public/browser/picture_in_picture_window_controller.h" @@ -276,3 +277,40 @@ overlay_window().OnNativeWidgetMove(); EXPECT_EQ(gfx::Size(500, 500), overlay_window().GetMaximumSize()); } + +// Tests that Next Track button bounds are updated right away when window +// controls are hidden. +TEST_F(OverlayWindowViewsTest, NextTrackButtonAddedWhenControlsHidden) { + ASSERT_FALSE(overlay_window().AreControlsVisible()); + ASSERT_TRUE(overlay_window() + .next_track_controls_view_for_testing() + ->size() + .IsEmpty()); + + const auto origin_before_layout = + overlay_window().next_track_controls_view_for_testing()->origin(); + + overlay_window().SetNextTrackButtonVisibility(true); + EXPECT_NE(overlay_window().next_track_controls_view_for_testing()->origin(), + origin_before_layout); + EXPECT_FALSE(overlay_window().IsLayoutPendingForTesting()); +} + +// Tests that Previous Track button bounds are updated right away when window +// controls are hidden. +TEST_F(OverlayWindowViewsTest, PreviousTrackButtonAddedWhenControlsHidden) { + ASSERT_FALSE(overlay_window().AreControlsVisible()); + ASSERT_TRUE(overlay_window() + .previous_track_controls_view_for_testing() + ->size() + .IsEmpty()); + + const auto origin_before_layout = + overlay_window().previous_track_controls_view_for_testing()->origin(); + + overlay_window().SetPreviousTrackButtonVisibility(true); + EXPECT_NE( + overlay_window().previous_track_controls_view_for_testing()->origin(), + origin_before_layout); + EXPECT_FALSE(overlay_window().IsLayoutPendingForTesting()); +}
diff --git a/chrome/browser/ui/views/profiles/dice_web_signin_interception_bubble_view.cc b/chrome/browser/ui/views/profiles/dice_web_signin_interception_bubble_view.cc index d44416be..5ab072d 100644 --- a/chrome/browser/ui/views/profiles/dice_web_signin_interception_bubble_view.cc +++ b/chrome/browser/ui/views/profiles/dice_web_signin_interception_bubble_view.cc
@@ -10,11 +10,11 @@ #include "base/callback_helpers.h" #include "base/check.h" #include "base/feature_list.h" +#include "base/memory/ptr_util.h" #include "base/metrics/histogram_functions.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/signin/identity_manager_factory.h" #include "chrome/browser/ui/browser.h" -#include "chrome/browser/ui/browser_list.h" #include "chrome/browser/ui/signin/dice_web_signin_interceptor_delegate.h" #include "chrome/browser/ui/ui_features.h" #include "chrome/browser/ui/views/frame/browser_view.h" @@ -37,40 +37,55 @@ } // namespace -DiceWebSigninInterceptionBubbleView::ScopedBrowserListObserver:: - ScopedBrowserListObserver(BrowserListObserver* owner) - : owner_(owner) { - DCHECK(owner_); - BrowserList::AddObserver(owner_); -} - -DiceWebSigninInterceptionBubbleView::ScopedBrowserListObserver:: - ~ScopedBrowserListObserver() { - BrowserList::RemoveObserver(owner_); -} - DiceWebSigninInterceptionBubbleView::~DiceWebSigninInterceptionBubbleView() { // Cancel if the bubble is destroyed without user interaction. if (callback_) { RecordInterceptionResult(bubble_parameters_, profile_, SigninInterceptionResult::kIgnored); + // The callback may synchronously delete a handle, which would attempt to + // close this bubble while it is being destroyed. Invalidate the handles now + // to prevent this. + weak_factory_.InvalidateWeakPtrs(); std::move(callback_).Run(SigninInterceptionResult::kIgnored); } } // static -void DiceWebSigninInterceptionBubbleView::CreateBubble( +std::unique_ptr<ScopedDiceWebSigninInterceptionBubbleHandle> +DiceWebSigninInterceptionBubbleView::CreateBubble( Profile* profile, views::View* anchor_view, const DiceWebSigninInterceptor::Delegate::BubbleParameters& bubble_parameters, base::OnceCallback<void(SigninInterceptionResult)> callback) { + auto interception_bubble = + base::WrapUnique(new DiceWebSigninInterceptionBubbleView( + profile, anchor_view, bubble_parameters, std::move(callback))); + std::unique_ptr<ScopedDiceWebSigninInterceptionBubbleHandle> handle = + interception_bubble->GetHandle(); // The widget is owned by the views system. views::Widget* widget = views::BubbleDialogDelegateView::CreateBubble( - new DiceWebSigninInterceptionBubbleView( - profile, anchor_view, bubble_parameters, std::move(callback))); + std::move(interception_bubble)); // TODO(droger): Delay showing the bubble until the web view is loaded. widget->Show(); + return handle; +} + +DiceWebSigninInterceptionBubbleView::ScopedHandle::~ScopedHandle() { + if (!bubble_) + return; // The bubble was already closed, do nothing. + views::Widget* widget = bubble_->GetWidget(); + if (!widget) + return; + widget->CloseWithReason( + bubble_->HasAccepted() ? views::Widget::ClosedReason::kAcceptButtonClicked + : views::Widget::ClosedReason::kUnspecified); +} + +DiceWebSigninInterceptionBubbleView::ScopedHandle::ScopedHandle( + base::WeakPtr<DiceWebSigninInterceptionBubbleView> bubble) + : bubble_(std::move(bubble)) { + DCHECK(bubble_); } // static @@ -116,6 +131,10 @@ } } +bool DiceWebSigninInterceptionBubbleView::HasAccepted() const { + return has_accepted_; +} + DiceWebSigninInterceptionBubbleView::DiceWebSigninInterceptionBubbleView( Profile* profile, views::View* anchor_view, @@ -128,6 +147,7 @@ bubble_parameters_(bubble_parameters), callback_(std::move(callback)) { DCHECK(profile_); + DCHECK(callback_); set_close_on_deactivate(false); // Create the web view in the native bubble. @@ -154,36 +174,30 @@ SetLayoutManager(std::make_unique<views::FillLayout>()); } +std::unique_ptr<ScopedDiceWebSigninInterceptionBubbleHandle> +DiceWebSigninInterceptionBubbleView::GetHandle() const { + return std::make_unique<ScopedHandle>(weak_factory_.GetWeakPtr()); +} + void DiceWebSigninInterceptionBubbleView::OnWebUIUserChoice(bool accept) { + has_accepted_ = accept; SigninInterceptionResult result = accept ? SigninInterceptionResult::kAccepted : SigninInterceptionResult::kDeclined; RecordInterceptionResult(bubble_parameters_, profile_, result); std::move(callback_).Run(result); - - // Only close the dialog when the user declined. If the user accepted the - // dialog displays a spinner until the new browser is created. - if (accept) { - browser_list_observer_ = std::make_unique<ScopedBrowserListObserver>(this); - } else { + if (!accept) { + // Only close the dialog when the user declined. If the user accepted the + // dialog displays a spinner until the handle is released. GetWidget()->CloseWithReason( views::Widget::ClosedReason::kCancelButtonClicked); } } -void DiceWebSigninInterceptionBubbleView::OnBrowserAdded(Browser* browser) { - // This function is only called when the user already accepted. - // Close the bubble when any new browser is created, not necessarily the one - // related to the signin interception ; this is a good-enough approximation. - DCHECK(browser_list_observer_); - browser_list_observer_.reset(); - GetWidget()->CloseWithReason( - views::Widget::ClosedReason::kAcceptButtonClicked); -} - // DiceWebSigninInterceptorDelegate -------------------------------------------- -void DiceWebSigninInterceptorDelegate::ShowSigninInterceptionBubbleInternal( +std::unique_ptr<ScopedDiceWebSigninInterceptionBubbleHandle> +DiceWebSigninInterceptorDelegate::ShowSigninInterceptionBubbleInternal( Browser* browser, const DiceWebSigninInterceptor::Delegate::BubbleParameters& bubble_parameters, @@ -194,6 +208,6 @@ ->toolbar_button_provider() ->GetAvatarToolbarButton(); DCHECK(anchor_view); - DiceWebSigninInterceptionBubbleView::CreateBubble( + return DiceWebSigninInterceptionBubbleView::CreateBubble( browser->profile(), anchor_view, bubble_parameters, std::move(callback)); }
diff --git a/chrome/browser/ui/views/profiles/dice_web_signin_interception_bubble_view.h b/chrome/browser/ui/views/profiles/dice_web_signin_interception_bubble_view.h index bd8ef75e..43f22b8 100644 --- a/chrome/browser/ui/views/profiles/dice_web_signin_interception_bubble_view.h +++ b/chrome/browser/ui/views/profiles/dice_web_signin_interception_bubble_view.h
@@ -8,9 +8,10 @@ #include "ui/views/bubble/bubble_dialog_delegate_view.h" #include "base/callback.h" +#include "base/compiler_specific.h" #include "base/gtest_prod_util.h" +#include "base/memory/weak_ptr.h" #include "chrome/browser/signin/dice_web_signin_interceptor.h" -#include "chrome/browser/ui/browser_list_observer.h" namespace views { class View; @@ -21,8 +22,7 @@ // Bubble shown as part of Dice web signin interception. This bubble is // implemented as a WebUI page rendered inside a native bubble. class DiceWebSigninInterceptionBubbleView - : public views::BubbleDialogDelegateView, - public BrowserListObserver { + : public views::BubbleDialogDelegateView { public: ~DiceWebSigninInterceptionBubbleView() override; @@ -31,12 +31,16 @@ DiceWebSigninInterceptionBubbleView& operator=( const DiceWebSigninInterceptionBubbleView& other) = delete; - static void CreateBubble( - Profile* profile, - views::View* anchor_view, - const DiceWebSigninInterceptor::Delegate::BubbleParameters& - bubble_parameters, - base::OnceCallback<void(SigninInterceptionResult)> callback); + // Warning: the bubble is closed when the handle is destroyed ; it is the + // responsibility of the caller to keep the handle alive until the bubble + // should be closed. + static std::unique_ptr<ScopedDiceWebSigninInterceptionBubbleHandle> + CreateBubble(Profile* profile, + views::View* anchor_view, + const DiceWebSigninInterceptor::Delegate::BubbleParameters& + bubble_parameters, + base::OnceCallback<void(SigninInterceptionResult)> callback) + WARN_UNUSED_RESULT; // Record metrics about the result of the signin interception. static void RecordInterceptionResult( @@ -45,6 +49,9 @@ Profile* profile, SigninInterceptionResult result); + // Returns true if the user has accepted the interception. + bool HasAccepted() const; + private: FRIEND_TEST_ALL_PREFIXES(DiceWebSigninInterceptionBubbleBrowserTest, BubbleClosed); @@ -53,19 +60,19 @@ FRIEND_TEST_ALL_PREFIXES(DiceWebSigninInterceptionBubbleBrowserTest, BubbleAccepted); - // base::ScopedObservation does not work for BrowserList because its - // AddObserver/RemoveObserver methods are static. - class ScopedBrowserListObserver { + // Closes the bubble when `ScopedHandle` is destroyed. Does nothing if the + // bubble has been already closed. + class ScopedHandle : public ScopedDiceWebSigninInterceptionBubbleHandle { public: - explicit ScopedBrowserListObserver(BrowserListObserver* owner); - ~ScopedBrowserListObserver(); + explicit ScopedHandle( + base::WeakPtr<DiceWebSigninInterceptionBubbleView> bubble); + ~ScopedHandle() override; - ScopedBrowserListObserver(const ScopedBrowserListObserver&) = delete; - ScopedBrowserListObserver& operator=(const ScopedBrowserListObserver&) = - delete; + ScopedHandle& operator=(const ScopedHandle&) = delete; + ScopedHandle(const ScopedHandle&) = delete; private: - BrowserListObserver* owner_; + base::WeakPtr<DiceWebSigninInterceptionBubbleView> bubble_; }; DiceWebSigninInterceptionBubbleView( @@ -75,20 +82,23 @@ bubble_parameters, base::OnceCallback<void(SigninInterceptionResult)> callback); + // Gets a handle on the bubble. Warning: the bubble is closed when the handle + // is destroyed ; it is the responsibility of the caller to keep the handle + // alive until the bubble should be closed. + std::unique_ptr<ScopedDiceWebSigninInterceptionBubbleHandle> GetHandle() + const; + // This bubble has no native buttons. The user accepts or cancels through this // method, which is called by the inner web UI. void OnWebUIUserChoice(bool accept); - // BrowserListObserver: - void OnBrowserAdded(Browser* browser) override; - Profile* profile_; + bool has_accepted_ = false; DiceWebSigninInterceptor::Delegate::BubbleParameters bubble_parameters_; base::OnceCallback<void(SigninInterceptionResult)> callback_; - // Once the user accepted, a spinner is shown until the new browser is - // created, and then the bubble is closed. - std::unique_ptr<ScopedBrowserListObserver> browser_list_observer_; + // Last member in the class: pointers are invalidated before other fields. + base::WeakPtrFactory<DiceWebSigninInterceptionBubbleView> weak_factory_{this}; }; #endif // CHROME_BROWSER_UI_VIEWS_PROFILES_DICE_WEB_SIGNIN_INTERCEPTION_BUBBLE_VIEW_H_
diff --git a/chrome/browser/ui/views/profiles/dice_web_signin_interception_bubble_view_browsertest.cc b/chrome/browser/ui/views/profiles/dice_web_signin_interception_bubble_view_browsertest.cc index eda6462..365f523 100644 --- a/chrome/browser/ui/views/profiles/dice_web_signin_interception_bubble_view_browsertest.cc +++ b/chrome/browser/ui/views/profiles/dice_web_signin_interception_bubble_view_browsertest.cc
@@ -6,6 +6,7 @@ #include <string> +#include "base/callback_helpers.h" #include "base/optional.h" #include "base/test/metrics/histogram_tester.h" #include "chrome/browser/ui/browser.h" @@ -25,9 +26,9 @@ // DialogBrowserTest: void ShowUi(const std::string& name) override { - DiceWebSigninInterceptionBubbleView::CreateBubble( + bubble_handle_ = DiceWebSigninInterceptionBubbleView::CreateBubble( browser()->profile(), GetAvatarButton(), GetTestBubbleParameters(), - base::OnceCallback<void(SigninInterceptionResult)>()); + base::DoNothing()); } // Returns the avatar button, which is the anchor view for the interception @@ -59,6 +60,7 @@ } base::Optional<SigninInterceptionResult> callback_result_; + std::unique_ptr<ScopedDiceWebSigninInterceptionBubbleHandle> bubble_handle_; }; IN_PROC_BROWSER_TEST_F(DiceWebSigninInterceptionBubbleBrowserTest, @@ -141,16 +143,21 @@ widget->Show(); EXPECT_FALSE(callback_result_.has_value()); + // Take a handle on the bubble, to close it later. + bubble_handle_ = bubble->GetHandle(); + views::test::WidgetClosingObserver closing_observer(widget); + EXPECT_FALSE(bubble->HasAccepted()); // Simulate clicking Accept in the WebUI. bubble->OnWebUIUserChoice(/*accept=*/true); ASSERT_TRUE(callback_result_.has_value()); EXPECT_EQ(callback_result_, SigninInterceptionResult::kAccepted); + EXPECT_TRUE(bubble->HasAccepted()); // Widget was not closed yet. ASSERT_FALSE(closing_observer.widget_closed()); - // Simulate a new browser being created by the interception. - CreateGuestBrowser(); + // Simulate completion of the interception process. + bubble_handle_.reset(); // Widget will close now. closing_observer.Wait();
diff --git a/chrome/browser/ui/views/profiles/profile_menu_view_base.cc b/chrome/browser/ui/views/profiles/profile_menu_view_base.cc index 4d9a74d..d8a7bec 100644 --- a/chrome/browser/ui/views/profiles/profile_menu_view_base.cc +++ b/chrome/browser/ui/views/profiles/profile_menu_view_base.cc
@@ -36,6 +36,7 @@ #include "ui/gfx/image/image_skia_operations.h" #include "ui/gfx/vector_icon_types.h" #include "ui/native_theme/themed_vector_icon.h" +#include "ui/strings/grit/ui_strings.h" #include "ui/views/accessibility/view_accessibility.h" #include "ui/views/controls/button/label_button.h" #include "ui/views/controls/button/md_text_button.h" @@ -547,6 +548,23 @@ return gfx::ImageSkia(); } +const base::string16 ProfileMenuViewBase::GetAccessibleMenuName( + const base::string16& title, + const base::string16& subtitle) { + if (title.empty()) { + if (subtitle.empty()) + return GetAccessibleWindowTitle(); + + return subtitle; + } else { + if (subtitle.empty()) + return title; + + return l10n_util::GetStringFUTF16(IDS_CONCAT_TWO_STRINGS_WITH_COMMA, title, + subtitle); + } +} + void ProfileMenuViewBase::SetProfileIdentityInfo( const base::string16& profile_name, SkColor profile_background_color, @@ -574,10 +592,7 @@ // Use the profile identity info to label the entire menu, for accessibility // users to get the user account as context information when they open it. - const base::string16& accessible_menu_name = - title.empty() ? (subtitle.empty() ? GetAccessibleWindowTitle() : subtitle) - : title; - GetViewAccessibility().OverrideName(accessible_menu_name); + GetViewAccessibility().OverrideName(GetAccessibleMenuName(title, subtitle)); if (!new_design) { if (!profile_name.empty()) {
diff --git a/chrome/browser/ui/views/profiles/profile_menu_view_base.h b/chrome/browser/ui/views/profiles/profile_menu_view_base.h index 774b4f5..bed6a00 100644 --- a/chrome/browser/ui/views/profiles/profile_menu_view_base.h +++ b/chrome/browser/ui/views/profiles/profile_menu_view_base.h
@@ -190,6 +190,9 @@ void UpdateSyncInfoContainerBackground(); + const base::string16 GetAccessibleMenuName(const base::string16& title, + const base::string16& subtitle); + Browser* const browser_; views::Button* const anchor_button_;
diff --git a/chrome/browser/ui/views/tabs/tab_hover_card_bubble_view.cc b/chrome/browser/ui/views/tabs/tab_hover_card_bubble_view.cc index 5df0a2a1..8757384 100644 --- a/chrome/browser/ui/views/tabs/tab_hover_card_bubble_view.cc +++ b/chrome/browser/ui/views/tabs/tab_hover_card_bubble_view.cc
@@ -396,11 +396,12 @@ // Maintains a set of thumbnails to watch, ensuring the capture count on the // associated WebContents stays nonzero until a valid thumbnail has been // captured. -class TabHoverCardBubbleView::ThumbnailObserver { +class TabHoverCardBubbleView::ThumbnailObserver + : public ThumbnailImage::Observer { public: explicit ThumbnailObserver(TabHoverCardBubbleView* hover_card) : hover_card_(hover_card) {} - ~ThumbnailObserver() = default; + ~ThumbnailObserver() override = default; // Begin watching the specified thumbnail image for updates. Ideally, should // trigger the associated WebContents to load (if not loaded already) and @@ -410,17 +411,13 @@ if (current_image_ == thumbnail_image) return; - subscription_.reset(); + scoped_observation_.Reset(); current_image_ = std::move(thumbnail_image); - if (!current_image_) - return; - subscription_ = current_image_->Subscribe(); - subscription_->SetSizeHint(TabStyle::GetPreviewImageSize()); - subscription_->SetUncompressedImageCallback(base::BindRepeating( - &ThumbnailObserver::ThumbnailImageCallback, base::Unretained(this))); - - current_image_->RequestThumbnailImage(); + if (current_image_) { + scoped_observation_.Observe(current_image_.get()); + current_image_->RequestThumbnailImage(); + } } // Returns the current (most recent) thumbnail being watched. @@ -428,13 +425,18 @@ return current_image_; } - void ThumbnailImageCallback(gfx::ImageSkia preview_image) { + base::Optional<gfx::Size> GetThumbnailSizeHint() const override { + return TabStyle::GetPreviewImageSize(); + } + + void OnThumbnailImageAvailable(gfx::ImageSkia preview_image) override { hover_card_->OnThumbnailImageAvailable(std::move(preview_image)); } scoped_refptr<ThumbnailImage> current_image_; - std::unique_ptr<ThumbnailImage::Subscription> subscription_; TabHoverCardBubbleView* const hover_card_; + base::ScopedObservation<ThumbnailImage, ThumbnailImage::Observer> + scoped_observation_{this}; }; TabHoverCardBubbleView::TabHoverCardBubbleView(Tab* tab)
diff --git a/chrome/browser/ui/webui/settings/safety_check_handler_unittest.cc b/chrome/browser/ui/webui/settings/safety_check_handler_unittest.cc index 007e40d..6e291145 100644 --- a/chrome/browser/ui/webui/settings/safety_check_handler_unittest.cc +++ b/chrome/browser/ui/webui/settings/safety_check_handler_unittest.cc
@@ -167,7 +167,8 @@ "test.com", base::ASCIIToUTF16("test" + base::NumberToString(test_credential_counter_++)), - base::Time(), password_manager::CompromiseType::kLeaked, false)); + base::Time(), password_manager::CompromiseType::kLeaked, + password_manager::IsMuted(false))); base::RunLoop().RunUntilIdle(); }
diff --git a/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc b/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc index 186b8f67..d65f2e37e 100644 --- a/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc +++ b/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc
@@ -978,6 +978,8 @@ IDS_SETTINGS_PASSWORD_DELETED_PASSWORD_FROM_ACCOUNT_AND_DEVICE}, {"passwordMovePasswordsToAccount", IDS_SETTINGS_PASSWORD_MOVE_PASSWORDS_TO_ACCOUNT}, + {"passwordMovePasswordsToAccountDialogFooter", + IDS_SETTINGS_PASSWORD_MOVE_PASSWORDS_TO_ACCOUNT_DIALOG_FOOTER}, {"passwordMovePasswordsToAccountDialogTitle", IDS_SETTINGS_PASSWORD_MOVE_PASSWORDS_TO_ACCOUNT_DIALOG_TITLE}, {"passwordMoveToAccountDialogTitle", @@ -1450,6 +1452,8 @@ {"privacySandboxPageHeading", IDS_SETTINGS_PRIVACY_SANDBOX_PAGE_HEADING}, }; AddLocalizedStringsBulk(html_source, kLocalizedStrings); + + html_source->AddString("privacySandboxURL", chrome::kPrivacySandboxURL); } void AddSafetyCheckStrings(content::WebUIDataSource* html_source) {
diff --git a/chrome/browser/ui/webui/tab_strip/thumbnail_tracker.cc b/chrome/browser/ui/webui/tab_strip/thumbnail_tracker.cc index aa733a93..161644f9 100644 --- a/chrome/browser/ui/webui/tab_strip/thumbnail_tracker.cc +++ b/chrome/browser/ui/webui/tab_strip/thumbnail_tracker.cc
@@ -15,17 +15,14 @@ // Handles requests for a given tab's thumbnail and watches for thumbnail // updates for the lifetime of the tab. -class ThumbnailTracker::ContentsData : public content::WebContentsObserver { +class ThumbnailTracker::ContentsData : public content::WebContentsObserver, + public ThumbnailImage::Observer { public: ContentsData(ThumbnailTracker* parent, content::WebContents* contents) : content::WebContentsObserver(contents), parent_(parent) { thumbnail_ = parent_->thumbnail_getter_.Run(contents); - if (!thumbnail_) - return; - - subscription_ = thumbnail_->Subscribe(); - subscription_->SetCompressedImageCallback(base::BindRepeating( - &ContentsData::ThumbnailImageCallback, base::Unretained(this))); + if (thumbnail_) + observer_.Add(thumbnail_.get()); } void RequestThumbnail() { @@ -38,7 +35,7 @@ // We must un-observe each ThumbnailImage when the WebContents it came from // closes. if (thumbnail_) { - subscription_.reset(); + observer_.Remove(thumbnail_.get()); thumbnail_.reset(); } @@ -46,14 +43,16 @@ parent_->ContentsClosed(web_contents()); } - private: - void ThumbnailImageCallback(CompressedThumbnailData image) { - parent_->ThumbnailUpdated(web_contents(), image); + // ThumbnailImage::Observer: + void OnCompressedThumbnailDataAvailable( + CompressedThumbnailData thumbnail_image) override { + parent_->ThumbnailUpdated(web_contents(), thumbnail_image); } + private: ThumbnailTracker* parent_; scoped_refptr<ThumbnailImage> thumbnail_; - std::unique_ptr<ThumbnailImage::Subscription> subscription_; + ScopedObserver<ThumbnailImage, ThumbnailImage::Observer> observer_{this}; DISALLOW_COPY_AND_ASSIGN(ContentsData); };
diff --git a/chrome/browser/ui/webui/test_data_source.cc b/chrome/browser/ui/webui/test_data_source.cc index 50a7f5c..4c8a72b 100644 --- a/chrome/browser/ui/webui/test_data_source.cc +++ b/chrome/browser/ui/webui/test_data_source.cc
@@ -42,6 +42,8 @@ custom_paths_ = { {"/chai.js", "third_party/chaijs/chai.js"}, {"/mocha.js", "third_party/mocha/mocha.js"}, + {"/test_loader.html", "ui/webui/resources/html/test_loader.html"}, + {"/test_loader.js", "ui/webui/resources/js/test_loader.js"}, }; } @@ -63,14 +65,16 @@ } std::string TestDataSource::GetMimeType(const std::string& path) { - if (base::EndsWith(path, ".html", base::CompareCase::INSENSITIVE_ASCII) || + std::string clean_path = GetURLForPath(path).path(); + if (base::EndsWith(clean_path, ".html", + base::CompareCase::INSENSITIVE_ASCII) || base::StartsWith(GetURLForPath(path).query(), kModuleQuery, base::CompareCase::INSENSITIVE_ASCII)) { // Direct request for HTML, or autogenerated HTML response for module query. return "text/html"; } // The test data source currently only serves HTML and JS. - CHECK(base::EndsWith(path, ".js", base::CompareCase::INSENSITIVE_ASCII)) + CHECK(base::EndsWith(clean_path, ".js", base::CompareCase::INSENSITIVE_ASCII)) << "Tried to read file with unexpected type from test data source: " << path; return "application/javascript";
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt index 9e305f7..faa1be0 100644 --- a/chrome/build/linux.pgo.txt +++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@ -chrome-linux-master-1608163120-124e90d18fac2bedecb2b27b978f1959d49c27fb.profdata +chrome-linux-master-1608206305-4389a6a6a359fb8abf452a6f4bc1a98be145b6cd.profdata
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt index b0dc505..9d1d645 100644 --- a/chrome/build/mac.pgo.txt +++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@ -chrome-mac-master-1608163120-6c9e93d828b8e2586093ed8c8e6e7f26f6a53c36.profdata +chrome-mac-master-1608206305-43a406c5421ed694ad09e180106f1be95f3f52fa.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt index 7e2a3213..732900f 100644 --- a/chrome/build/win32.pgo.txt +++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@ -chrome-win32-master-1608141458-c308516ff1ef658b0966cc17b391babeaf39cbb5.profdata +chrome-win32-master-1608163120-4986bcffa849ffffd428f29082c0e0792a369cda.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt index 95a4794..7f9fd1e 100644 --- a/chrome/build/win64.pgo.txt +++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@ -chrome-win64-master-1608152110-c6b8168a74d771ecb9159dac1f934f7c3a6ae962.profdata +chrome-win64-master-1608173994-6a2e9c3f805f7667eca640b2b557f764d57c9690.profdata
diff --git a/chrome/common/url_constants.cc b/chrome/common/url_constants.cc index e85f2f0..e5d4c11 100644 --- a/chrome/common/url_constants.cc +++ b/chrome/common/url_constants.cc
@@ -238,6 +238,9 @@ "https://support.google.com/chrome/?p=settings_privacy"; #endif +const char kPrivacySandboxURL[] = + "https://www.chromium.org/Home/chromium-privacy/privacy-sandbox"; + const char kRemoveNonCWSExtensionURL[] = "https://support.google.com/chrome/?p=ui_remove_non_cws_extensions";
diff --git a/chrome/common/url_constants.h b/chrome/common/url_constants.h index 462c10d..6ad80524 100644 --- a/chrome/common/url_constants.h +++ b/chrome/common/url_constants.h
@@ -207,6 +207,9 @@ // "Learn more" URL for the Privacy section under Options. extern const char kPrivacyLearnMoreURL[]; +// "Learn more" URL for the privacy sandbox. +extern const char kPrivacySandboxURL[]; + // The URL for the Learn More link of the non-CWS bubble. extern const char kRemoveNonCWSExtensionURL[];
diff --git a/chrome/renderer/chrome_content_renderer_client.cc b/chrome/renderer/chrome_content_renderer_client.cc index b8379e7..8425272f 100644 --- a/chrome/renderer/chrome_content_renderer_client.cc +++ b/chrome/renderer/chrome_content_renderer_client.cc
@@ -540,7 +540,6 @@ // Avoid any race conditions from having the browser tell subframes that // they're prerendering. new prerender::PrerenderHelper(render_frame, - prerender_helper->prerender_mode(), prerender_helper->histogram_prefix()); } }
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index 86b3d861..5462da8 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -6541,6 +6541,7 @@ "//third_party/pywebsocket3/src/mod_pywebsocket/", "//third_party/tlslite/", "//tools/metrics/histograms/enums.xml", + "//ui/webui/resources/html/test_loader.html", "//ui/webui/resources/js/", "$root_out_dir/test_case.html", "$root_out_dir/test_case.html.mock-http-headers",
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/signin/MockChangeEventChecker.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/signin/MockChangeEventChecker.java index 097c446..9ead390 100644 --- a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/signin/MockChangeEventChecker.java +++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/signin/MockChangeEventChecker.java
@@ -6,7 +6,7 @@ import android.content.Context; -import org.chromium.chrome.browser.signin.SigninHelper; +import org.chromium.chrome.browser.signin.services.SigninHelper; import java.util.ArrayList; import java.util.HashMap;
diff --git a/chrome/test/data/webui/BUILD.gn b/chrome/test/data/webui/BUILD.gn index 837e4cd..96e909ed 100644 --- a/chrome/test/data/webui/BUILD.gn +++ b/chrome/test/data/webui/BUILD.gn
@@ -99,6 +99,7 @@ "sandboxstatus_browsertest.js", "settings/a11y/v3_a11y_browsertest.js", "settings/cr_settings_v3_browsertest.js", + "settings/privacy_sandbox_browsertest.js", "settings/settings_idle_load_v3_browsertest.js", "tab_search/tab_search_browsertest.js", "text_defaults_browsertest.js",
diff --git a/chrome/test/data/webui/cr_components/cr_components_v3_browsertest.js b/chrome/test/data/webui/cr_components/cr_components_v3_browsertest.js index ec3f7c8b..85d54278 100644 --- a/chrome/test/data/webui/cr_components/cr_components_v3_browsertest.js +++ b/chrome/test/data/webui/cr_components/cr_components_v3_browsertest.js
@@ -35,15 +35,7 @@ class extends CrComponentsV3BrowserTest { /** @override */ get browsePreload() { - return 'chrome://test?module=cr_components/managed_footnote_test.m.js'; - } - - /** @override */ - get extraLibraries() { - return [ - '//third_party/mocha/mocha.js', - '//chrome/test/data/webui/mocha_adapter.js', - ]; + return 'chrome://test/test_loader.html?module=cr_components/managed_footnote_test.m.js'; } };
diff --git a/chrome/test/data/webui/cr_elements/cr_elements_v3_browsertest.js b/chrome/test/data/webui/cr_elements/cr_elements_v3_browsertest.js index 8cd05ea..d201dbb 100644 --- a/chrome/test/data/webui/cr_elements/cr_elements_v3_browsertest.js +++ b/chrome/test/data/webui/cr_elements/cr_elements_v3_browsertest.js
@@ -20,10 +20,7 @@ /** @override */ get extraLibraries() { - return [ - '//third_party/mocha/mocha.js', - '//chrome/test/data/webui/mocha_adapter.js', - ]; + return []; } /** @override */ @@ -36,7 +33,7 @@ var CrElementsButtonV3Test = class extends CrElementsV3BrowserTest { /** @override */ get browsePreload() { - return 'chrome://test?module=cr_elements/cr_button_tests.m.js'; + return 'chrome://test/test_loader.html?module=cr_elements/cr_button_tests.m.js'; } }; @@ -49,7 +46,7 @@ class extends CrElementsV3BrowserTest { /** @override */ get browsePreload() { - return 'chrome://test?module=cr_elements/cr_container_shadow_behavior_test.m.js'; + return 'chrome://test/test_loader.html?module=cr_elements/cr_container_shadow_behavior_test.m.js'; } }; @@ -62,7 +59,7 @@ var CrElementsDialogV3Test = class extends CrElementsV3BrowserTest { /** @override */ get browsePreload() { - return 'chrome://test?module=cr_elements/cr_dialog_test.m.js'; + return 'chrome://test/test_loader.html?module=cr_elements/cr_dialog_test.m.js'; } }; @@ -74,7 +71,7 @@ var CrElementsDrawerV3Test = class extends CrElementsV3BrowserTest { /** @override */ get browsePreload() { - return 'chrome://test?module=cr_elements/cr_drawer_tests.m.js'; + return 'chrome://test/test_loader.html?module=cr_elements/cr_drawer_tests.m.js'; } }; @@ -93,7 +90,7 @@ var CrElementsExpandButtonV3Test = class extends CrElementsV3BrowserTest { /** @override */ get browsePreload() { - return 'chrome://test?module=cr_elements/cr_expand_button_tests.m.js'; + return 'chrome://test/test_loader.html?module=cr_elements/cr_expand_button_tests.m.js'; } }; @@ -106,7 +103,7 @@ class extends CrElementsV3BrowserTest { /** @override */ get browsePreload() { - return 'chrome://test?module=cr_elements/find_shortcut_behavior_test.m.js'; + return 'chrome://test/test_loader.html?module=cr_elements/find_shortcut_behavior_test.m.js'; } }; @@ -119,7 +116,7 @@ class extends CrElementsV3BrowserTest { /** @override */ get browsePreload() { - return 'chrome://test?module=cr_elements/cr_fingerprint_progress_arc_tests.m.js'; + return 'chrome://test/test_loader.html?module=cr_elements/cr_fingerprint_progress_arc_tests.m.js'; } /** @override */ @@ -144,7 +141,7 @@ var CrElementsIconButtonV3Test = class extends CrElementsV3BrowserTest { /** @override */ get browsePreload() { - return 'chrome://test?module=cr_elements/cr_icon_button_tests.m.js'; + return 'chrome://test/test_loader.html?module=cr_elements/cr_icon_button_tests.m.js'; } }; @@ -156,7 +153,7 @@ var CrElementsLazyRenderV3Test = class extends CrElementsV3BrowserTest { /** @override */ get browsePreload() { - return 'chrome://test?module=cr_elements/cr_lazy_render_tests.m.js'; + return 'chrome://test/test_loader.html?module=cr_elements/cr_lazy_render_tests.m.js'; } }; @@ -168,7 +165,7 @@ var CrElementsLinkRowV3Test = class extends CrElementsV3BrowserTest { /** @override */ get browsePreload() { - return 'chrome://test?module=cr_elements/cr_link_row_tests.m.js'; + return 'chrome://test/test_loader.html?module=cr_elements/cr_link_row_tests.m.js'; } }; @@ -180,7 +177,7 @@ var CrElementsRadioButtonV3Test = class extends CrElementsV3BrowserTest { /** @override */ get browsePreload() { - return 'chrome://test?module=cr_elements/cr_radio_button_test.m.js'; + return 'chrome://test/test_loader.html?module=cr_elements/cr_radio_button_test.m.js'; } }; @@ -192,7 +189,7 @@ var CrElementsRadioGroupV3Test = class extends CrElementsV3BrowserTest { /** @override */ get browsePreload() { - return 'chrome://test?module=cr_elements/cr_radio_group_test.m.js'; + return 'chrome://test/test_loader.html?module=cr_elements/cr_radio_group_test.m.js'; } }; @@ -204,7 +201,7 @@ var CrElementsScrollableBehaviorV3Test = class extends CrElementsV3BrowserTest { /** @override */ get browsePreload() { - return 'chrome://test?module=cr_elements/cr_scrollable_behavior_tests.m.js'; + return 'chrome://test/test_loader.html?module=cr_elements/cr_scrollable_behavior_tests.m.js'; } }; @@ -216,7 +213,7 @@ var CrElementsSearchFieldV3Test = class extends CrElementsV3BrowserTest { /** @override */ get browsePreload() { - return 'chrome://test?module=cr_elements/cr_search_field_tests.m.js'; + return 'chrome://test/test_loader.html?module=cr_elements/cr_search_field_tests.m.js'; } }; @@ -229,7 +226,7 @@ var CrElementsSearchableDropDownV3Test = class extends CrElementsV3BrowserTest { /** @override */ get browsePreload() { - return 'chrome://test?module=cr_elements/cr_searchable_drop_down_tests.m.js'; + return 'chrome://test/test_loader.html?module=cr_elements/cr_searchable_drop_down_tests.m.js'; } }; @@ -242,7 +239,7 @@ var CrElementsSliderV3Test = class extends CrElementsV3BrowserTest { /** @override */ get browsePreload() { - return 'chrome://test?module=cr_elements/cr_slider_test.m.js'; + return 'chrome://test/test_loader.html?module=cr_elements/cr_slider_test.m.js'; } }; @@ -254,7 +251,7 @@ var CrElementsSplitterV3Test = class extends CrElementsV3BrowserTest { /** @override */ get browsePreload() { - return 'chrome://test?module=cr_elements/cr_splitter_test.js'; + return 'chrome://test/test_loader.html?module=cr_elements/cr_splitter_test.js'; } }; @@ -266,7 +263,7 @@ var CrElementsToastV3Test = class extends CrElementsV3BrowserTest { /** @override */ get browsePreload() { - return 'chrome://test?module=cr_elements/cr_toast_test.m.js'; + return 'chrome://test/test_loader.html?module=cr_elements/cr_toast_test.m.js'; } }; @@ -278,7 +275,7 @@ var CrElementsToastManagerV3Test = class extends CrElementsV3BrowserTest { /** @override */ get browsePreload() { - return 'chrome://test?module=cr_elements/cr_toast_manager_test.m.js'; + return 'chrome://test/test_loader.html?module=cr_elements/cr_toast_manager_test.m.js'; } }; @@ -290,7 +287,7 @@ var CrElementsViewManagerV3Test = class extends CrElementsV3BrowserTest { /** @override */ get browsePreload() { - return 'chrome://test?module=cr_elements/cr_view_manager_test.m.js'; + return 'chrome://test/test_loader.html?module=cr_elements/cr_view_manager_test.m.js'; } }; @@ -302,7 +299,7 @@ var CrElementsPolicyIndicatorV3Test = class extends CrElementsV3BrowserTest { /** @override */ get browsePreload() { - return 'chrome://test?module=cr_elements/cr_policy_indicator_tests.m.js'; + return 'chrome://test/test_loader.html?module=cr_elements/cr_policy_indicator_tests.m.js'; } }; @@ -329,7 +326,7 @@ class extends CrElementsV3BrowserTest { /** @override */ get browsePreload() { - return 'chrome://test?module=cr_elements/cr_policy_indicator_behavior_tests.m.js'; + return 'chrome://test/test_loader.html?module=cr_elements/cr_policy_indicator_behavior_tests.m.js'; } }; @@ -341,7 +338,7 @@ var CrElementsLottieV3Test = class extends CrElementsV3BrowserTest { /** @override */ get browsePreload() { - return 'chrome://test?module=cr_elements/cr_lottie_tests.m.js'; + return 'chrome://test/test_loader.html?module=cr_elements/cr_lottie_tests.m.js'; } /** @override */
diff --git a/chrome/test/data/webui/cr_elements/cr_elements_v3_focus_test.js b/chrome/test/data/webui/cr_elements/cr_elements_v3_focus_test.js index 3c3378b..1c1bb89 100644 --- a/chrome/test/data/webui/cr_elements/cr_elements_v3_focus_test.js +++ b/chrome/test/data/webui/cr_elements/cr_elements_v3_focus_test.js
@@ -18,10 +18,7 @@ /** @override */ get extraLibraries() { - return [ - '//third_party/mocha/mocha.js', - '//chrome/test/data/webui/mocha_adapter.js', - ]; + return []; } /** @override */ @@ -36,6 +33,16 @@ get browsePreload() { return 'chrome://test?module=cr_elements/cr_action_menu_test.m.js'; } + + /** @override */ + get extraLibraries() { + return [ + // TODO(dpapad): Figure out why this test fails if test_loader.html is + // used instead. + '//third_party/mocha/mocha.js', + '//chrome/test/data/webui/mocha_adapter.js', + ]; + } }; TEST_F('CrElementsActionMenuV3Test', 'All', function() { @@ -46,7 +53,7 @@ var CrElementsCheckboxV3Test = class extends CrElementsV3FocusTest { /** @override */ get browsePreload() { - return 'chrome://test?module=cr_elements/cr_checkbox_test.m.js'; + return 'chrome://test/test_loader.html?module=cr_elements/cr_checkbox_test.m.js'; } }; @@ -58,7 +65,7 @@ var CrElementsExpandButtonV3FocusTest = class extends CrElementsV3FocusTest { /** @override */ get browsePreload() { - return 'chrome://test?module=cr_elements/cr_expand_button_focus_tests.m.js'; + return 'chrome://test/test_loader.html?module=cr_elements/cr_expand_button_focus_tests.m.js'; } }; @@ -70,7 +77,7 @@ var CrElementsIconButtonV3FocusTest = class extends CrElementsV3FocusTest { /** @override */ get browsePreload() { - return 'chrome://test?module=cr_elements/cr_icon_button_focus_tests.m.js'; + return 'chrome://test/test_loader.html?module=cr_elements/cr_icon_button_focus_tests.m.js'; } }; @@ -82,7 +89,7 @@ var CrElementsInputV3Test = class extends CrElementsV3FocusTest { /** @override */ get browsePreload() { - return 'chrome://test?module=cr_elements/cr_input_test.m.js'; + return 'chrome://test/test_loader.html?module=cr_elements/cr_input_test.m.js'; } }; @@ -101,7 +108,7 @@ class extends CrElementsV3FocusTest { /** @override */ get browsePreload() { - return 'chrome://test?module=cr_elements/cr_profile_avatar_selector_tests.m.js'; + return 'chrome://test/test_loader.html?module=cr_elements/cr_profile_avatar_selector_tests.m.js'; } }; @@ -113,7 +120,7 @@ var CrElementsTabsV3Test = class extends CrElementsV3FocusTest { /** @override */ get browsePreload() { - return 'chrome://test?module=cr_elements/cr_tabs_test.m.js'; + return 'chrome://test/test_loader.html?module=cr_elements/cr_tabs_test.m.js'; } }; @@ -125,7 +132,7 @@ var CrElementsToggleV3Test = class extends CrElementsV3FocusTest { /** @override */ get browsePreload() { - return 'chrome://test?module=cr_elements/cr_toggle_test.m.js'; + return 'chrome://test/test_loader.html?module=cr_elements/cr_toggle_test.m.js'; } }; @@ -137,7 +144,7 @@ var CrElementsToolbarSearchFieldV3Test = class extends CrElementsV3FocusTest { /** @override */ get browsePreload() { - return 'chrome://test?module=cr_elements/cr_toolbar_search_field_tests.m.js'; + return 'chrome://test/test_loader.html?module=cr_elements/cr_toolbar_search_field_tests.m.js'; } }; @@ -150,7 +157,7 @@ var IronListFocusV3Test = class extends CrElementsV3FocusTest { /** @override */ get browsePreload() { - return 'chrome://test?module=cr_elements/iron_list_focus_test.m.js'; + return 'chrome://test/test_loader.html?module=cr_elements/iron_list_focus_test.m.js'; } }; @@ -163,7 +170,7 @@ var CrElementsGridFocusTest = class extends CrElementsV3FocusTest { /** @override */ get browsePreload() { - return 'chrome://test?module=cr_elements/cr_grid_focus_test.js'; + return 'chrome://test/test_loader.html?module=cr_elements/cr_grid_focus_test.js'; } }; @@ -176,7 +183,7 @@ var CrElementsMenuSelectorFocusTest = class extends CrElementsV3FocusTest { /** @override */ get browsePreload() { - return 'chrome://test?module=cr_elements/cr_menu_selector_focus_test.js'; + return 'chrome://test/test_loader.html?module=cr_elements/cr_menu_selector_focus_test.js'; } }; @@ -189,7 +196,7 @@ var CrElementsToolbarFocusV3Test = class extends CrElementsV3FocusTest { /** @override */ get browsePreload() { - return 'chrome://test?module=cr_elements/cr_toolbar_focus_tests.m.js'; + return 'chrome://test/test_loader.html?module=cr_elements/cr_toolbar_focus_tests.m.js'; } };
diff --git a/chrome/test/data/webui/cr_focus_row_behavior_v3_interactive_test.js b/chrome/test/data/webui/cr_focus_row_behavior_v3_interactive_test.js index 3d57ac22..01422f2 100644 --- a/chrome/test/data/webui/cr_focus_row_behavior_v3_interactive_test.js +++ b/chrome/test/data/webui/cr_focus_row_behavior_v3_interactive_test.js
@@ -15,7 +15,7 @@ var CrFocusRowBehaviorV3Test = class extends PolymerInteractiveUITest { /** @override */ get browsePreload() { - return 'chrome://test?module=cr_focus_row_behavior_test.m.js'; + return 'chrome://test/test_loader.html?module=cr_focus_row_behavior_test.m.js'; } /** @override */ @@ -25,10 +25,7 @@ /** @override */ get extraLibraries() { - return [ - '//third_party/mocha/mocha.js', - '//chrome/test/data/webui/mocha_adapter.js', - ]; + return []; } };
diff --git a/chrome/test/data/webui/js/webui_resource_module_async_browsertest.js b/chrome/test/data/webui/js/webui_resource_module_async_browsertest.js index f377f3d..10d493d 100644 --- a/chrome/test/data/webui/js/webui_resource_module_async_browsertest.js +++ b/chrome/test/data/webui/js/webui_resource_module_async_browsertest.js
@@ -24,20 +24,12 @@ get webuiHost() { return 'dummyurl'; } - - /** @override */ - get extraLibraries() { - return [ - '//third_party/mocha/mocha.js', - '//chrome/test/data/webui/mocha_adapter.js', - ]; - } }; var CrModuleTest = class extends WebUIResourceModuleAsyncTest { /** @override */ get browsePreload() { - return 'chrome://test?module=js/cr_test.js'; + return 'chrome://test/test_loader.html?module=js/cr_test.js'; } }; @@ -56,7 +48,7 @@ var PromiseResolverModuleTest = class extends WebUIResourceModuleAsyncTest { /** @override */ get browsePreload() { - return 'chrome://test?module=js/promise_resolver_test.js'; + return 'chrome://test/test_loader.html?module=js/promise_resolver_test.js'; } }; @@ -67,7 +59,7 @@ var ParseHtmlSubsetModuleTest = class extends WebUIResourceModuleAsyncTest { /** @override */ get browsePreload() { - return 'chrome://test?module=js/parse_html_subset_test.js'; + return 'chrome://test/test_loader.html?module=js/parse_html_subset_test.js'; } }; @@ -79,7 +71,7 @@ class extends WebUIResourceModuleAsyncTest { /** @override */ get browsePreload() { - return 'chrome://test?module=js/parse_html_subset_trusted_types_test.js'; + return 'chrome://test/test_loader.html?module=js/parse_html_subset_trusted_types_test.js'; } }; @@ -90,7 +82,7 @@ var UtilModuleTest = class extends WebUIResourceModuleAsyncTest { /** @override */ get browsePreload() { - return 'chrome://test?module=js/util_test.js'; + return 'chrome://test/test_loader.html?module=js/util_test.js'; } }; @@ -101,7 +93,7 @@ var LoadTimeDataModuleTest = class extends WebUIResourceModuleAsyncTest { /** @override */ get browsePreload() { - return 'chrome://test?module=js/load_time_data_test.js'; + return 'chrome://test/test_loader.html?module=js/load_time_data_test.js'; } }; @@ -112,7 +104,7 @@ var I18nBehaviorModuleTest = class extends WebUIResourceModuleAsyncTest { /** @override */ get browsePreload() { - return 'chrome://test?module=js/i18n_behavior_test.js'; + return 'chrome://test/test_loader.html?module=js/i18n_behavior_test.js'; } }; @@ -123,7 +115,7 @@ var ColorUtilsModuleTest = class extends WebUIResourceModuleAsyncTest { /** @override */ get browsePreload() { - return 'chrome://test?module=js/color_utils_test.js'; + return 'chrome://test/test_loader.html?module=js/color_utils_test.js'; } };
diff --git a/chrome/test/data/webui/resources/webui_resources_v3_browsertest.js b/chrome/test/data/webui/resources/webui_resources_v3_browsertest.js index a85d860..e3c010a 100644 --- a/chrome/test/data/webui/resources/webui_resources_v3_browsertest.js +++ b/chrome/test/data/webui/resources/webui_resources_v3_browsertest.js
@@ -23,10 +23,7 @@ /** @override */ get extraLibraries() { - return [ - '//third_party/mocha/mocha.js', - '//chrome/test/data/webui/mocha_adapter.js', - ]; + return []; } }; @@ -35,7 +32,7 @@ class extends WebUIResourcesV3BrowserTest { /** @override */ get browsePreload() { - return 'chrome://test?module=resources/list_property_update_behavior_tests.m.js'; + return 'chrome://test/test_loader.html?module=resources/list_property_update_behavior_tests.m.js'; } };
diff --git a/chrome/test/data/webui/settings/BUILD.gn b/chrome/test/data/webui/settings/BUILD.gn index ce5ea14..d22dbd8f 100644 --- a/chrome/test/data/webui/settings/BUILD.gn +++ b/chrome/test/data/webui/settings/BUILD.gn
@@ -132,6 +132,7 @@ #":prefs_test_cases", #":prefs_tests", ":privacy_page_test", + ":privacy_sandbox_test", #":protocol_handlers_tests", ":recent_site_permissions_test", @@ -336,6 +337,16 @@ externs_list = [ "$externs_path/mocha-2.5.js" ] } +js_library("privacy_sandbox_test") { + deps = [ + ":test_open_window_proxy", + "..:chai_assert", + "//chrome/browser/resources/settings:settings", + "//chrome/browser/resources/settings/privacy_sandbox:app", + ] + externs_list = [ "$externs_path/mocha-2.5.js" ] +} + js_library("recent_site_permissions_test") { deps = [ ":test_site_settings_prefs_browser_proxy",
diff --git a/chrome/test/data/webui/settings/passwords_device_section_test.js b/chrome/test/data/webui/settings/passwords_device_section_test.js index 976a870c..e5ae5e48 100644 --- a/chrome/test/data/webui/settings/passwords_device_section_test.js +++ b/chrome/test/data/webui/settings/passwords_device_section_test.js
@@ -4,7 +4,6 @@ /** @fileoverview Runs the Polymer tests for the PasswordsDeviceSection page. */ -import {PluralStringProxyImpl} from 'chrome://resources/js/plural_string_proxy.js'; import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {MultiStorePasswordUiEntry, PasswordManagerImpl, Router, routes, SyncBrowserProxyImpl} from 'chrome://settings/settings.js'; import {createMultiStorePasswordEntry, createPasswordEntry, PasswordDeviceSectionElementFactory} from 'chrome://test/settings/passwords_and_autofill_fake_data.js'; @@ -366,36 +365,4 @@ assertTrue(firstPasswordItem.$.moreActionsButton.hidden); }); - // Testing moving multiple password dialog footer reflects how many passwords - // are going to be moved. - test('moveMultiplePasswordsDialogFooter', async function() { - const deviceEntry1 = createMultiStorePasswordEntry( - {url: 'goo.gl', username: 'bart1', deviceId: 41}); - const deviceEntry2 = createMultiStorePasswordEntry( - {url: 'goo.gl', username: 'bart2', deviceId: 54}); - const moveMultipleDialog = elementFactory.createMoveMultiplePasswordsDialog( - [deviceEntry1, deviceEntry2]); - flush(); - - let expectedCountLabel = - await PluralStringProxyImpl.getInstance().getPluralString( - 'movePasswordsToAccount', 2); - let countLabel = - moveMultipleDialog.$$('#movingPasswordsCountLabel').textContent.trim(); - expectEquals(expectedCountLabel, countLabel); - - // Uncheck the first entry - const firstPasswordItem = moveMultipleDialog.$$('password-list-item'); - firstPasswordItem.querySelector('cr-checkbox').click(); - - // The footer should have been updated that only one item is selected now. - expectedCountLabel = - await PluralStringProxyImpl.getInstance().getPluralString( - 'movePasswordsToAccount', 1); - countLabel = - moveMultipleDialog.$$('#movingPasswordsCountLabel').textContent.trim(); - expectEquals(expectedCountLabel, countLabel); - }); - - });
diff --git a/chrome/test/data/webui/settings/privacy_sandbox_browsertest.js b/chrome/test/data/webui/settings/privacy_sandbox_browsertest.js new file mode 100644 index 0000000..981da47 --- /dev/null +++ b/chrome/test/data/webui/settings/privacy_sandbox_browsertest.js
@@ -0,0 +1,33 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** @fileoverview Tests for the privacy sandbox UI. */ + +// Polymer BrowserTest fixture. +GEN_INCLUDE(['//chrome/test/data/webui/polymer_browser_test_base.js']); + +GEN('#include "chrome/common/chrome_features.h"'); +GEN('#include "content/public/test/browser_test.h"'); + +// eslint-disable-next-line no-var +var PrivacySandboxTest = class extends PolymerTest { + /** @override */ + get browsePreload() { + return 'chrome://settings/test_loader.html?module=settings/privacy_sandbox_test.js'; + } + + /** @override */ + get extraLibraries() { + return []; + } + + /** @override */ + get featureList() { + return {enabled: ['features::kPrivacySandboxSettings']}; + } +}; + +TEST_F('PrivacySandboxTest', 'All', function() { + mocha.run(); +});
diff --git a/chrome/test/data/webui/settings/privacy_sandbox_test.js b/chrome/test/data/webui/settings/privacy_sandbox_test.js new file mode 100644 index 0000000..6ac16ee --- /dev/null +++ b/chrome/test/data/webui/settings/privacy_sandbox_test.js
@@ -0,0 +1,39 @@ +// Copyright 2020 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 'chrome://settings/privacy_sandbox/app.js'; + +import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {loadTimeData, OpenWindowProxyImpl} from 'chrome://settings/settings.js'; + +import {assertEquals} from '../chai_assert.js'; + +import {TestOpenWindowProxy} from './test_open_window_proxy.js'; + +suite('PrivacySandbox', function() { + /** @type {PrivacySandboxAppElement} */ + let page; + + /** @type {?TestOpenWindowProxy} */ + let openWindowProxy = null; + + setup(async function() { + openWindowProxy = new TestOpenWindowProxy(); + OpenWindowProxyImpl.instance_ = openWindowProxy; + + document.body.innerHTML = ''; + page = /** @type {!PrivacySandboxAppElement} */ + (document.createElement('privacy-sandbox-app')); + document.body.appendChild(page); + }); + + test('learnMoreTest', async function() { + // User clicks the "Learn more" button. + page.$$('#learnMoreButton').click(); + // Ensure the browser proxy call is done. + assertEquals( + loadTimeData.getString('privacySandboxURL'), + await openWindowProxy.whenCalled('openURL')); + }); +});
diff --git a/chromecast/media/cma/backend/proxy/BUILD.gn b/chromecast/media/cma/backend/proxy/BUILD.gn index 9f60d7d..f7903e0 100644 --- a/chromecast/media/cma/backend/proxy/BUILD.gn +++ b/chromecast/media/cma/backend/proxy/BUILD.gn
@@ -58,7 +58,8 @@ "//third_party/protobuf:protobuf_full", ] - if (chromecast_branding == "public") { + if (!enable_chromium_runtime_cast_renderer || + chromecast_branding == "public") { sources += [ "audio_channel_broker_simple.cc" ] } }
diff --git a/chromeos/components/camera_app_ui/camera_app_helper.mojom b/chromeos/components/camera_app_ui/camera_app_helper.mojom index b659e2e3..4ad3525 100644 --- a/chromeos/components/camera_app_ui/camera_app_helper.mojom +++ b/chromeos/components/camera_app_ui/camera_app_helper.mojom
@@ -52,20 +52,20 @@ REGULAR = 3, // None of the above. }; -// Interface for monitoring window state. +// Interface for monitoring window states. interface WindowStateMonitor { - // Updates when the window state is changed. - OnWindowStateChanged(WindowStateType state); + // Updates when any of the window states are changed. + OnWindowStateChanged(array<WindowStateType> states); }; // Interface for window controlling. interface WindowStateController { // Adds |monitor| for window state changes. AddMonitor(pending_remote<WindowStateMonitor> monitor) - => (WindowStateType state); + => (array<WindowStateType> states); - // Gets current |state| of the window. - GetWindowState() => (WindowStateType state); + // Gets current |states| of the window. + GetWindowState() => (array<WindowStateType> states); // Minimize the window. Minimize() => ();
diff --git a/chromeos/components/camera_app_ui/camera_app_window_state_controller.cc b/chromeos/components/camera_app_ui/camera_app_window_state_controller.cc index d19174a..4fe29e4 100644 --- a/chromeos/components/camera_app_ui/camera_app_window_state_controller.cc +++ b/chromeos/components/camera_app_ui/camera_app_window_state_controller.cc
@@ -8,9 +8,27 @@ namespace chromeos { +namespace { + +bool IsRestored(views::Widget* widget) { + if (ash::TabletMode::Get()->InTabletMode()) { + return !widget->IsMinimized(); + } + return !widget->IsMinimized() && !widget->IsMaximized() && + !widget->IsFullscreen(); +} + +std::vector<CameraAppWindowStateController::WindowStateType> ToVector( + const base::flat_set<CameraAppWindowStateController::WindowStateType>& s) { + return std::vector<CameraAppWindowStateController::WindowStateType>(s.begin(), + s.end()); +} + +} // namespace + CameraAppWindowStateController::CameraAppWindowStateController( views::Widget* widget) - : widget_(widget), window_state_(GetCurrentWindowState()) { + : widget_(widget), window_states_(GetCurrentWindowStates()) { widget_->AddObserver(this); } @@ -30,16 +48,16 @@ auto remote = mojo::Remote<chromeos_camera::mojom::WindowStateMonitor>( std::move(monitor)); monitors_.push_back(std::move(remote)); - std::move(callback).Run(window_state_); + std::move(callback).Run(ToVector(window_states_)); } void CameraAppWindowStateController::GetWindowState( GetWindowStateCallback callback) { - std::move(callback).Run(window_state_); + std::move(callback).Run(ToVector(window_states_)); } void CameraAppWindowStateController::Minimize(MinimizeCallback callback) { - if (GetCurrentWindowState() == WindowStateType::MINIMIZED) { + if (widget_->IsMinimized()) { std::move(callback).Run(); return; } @@ -48,15 +66,7 @@ } void CameraAppWindowStateController::Restore(RestoreCallback callback) { - auto current_state = GetCurrentWindowState(); - - // In tablet mode, it won't do anything when calling restore() for windows - // which are already maximized. Therefore, for maximized windows, trigger the - // callback immediately. - if (current_state == WindowStateType::REGULAR || - (ash::TabletMode::Get()->InTabletMode() && - (current_state == WindowStateType::MAXIMIZED || - current_state == WindowStateType::FULLSCREEN))) { + if (IsRestored(widget_)) { std::move(callback).Run(); return; } @@ -65,7 +75,7 @@ } void CameraAppWindowStateController::Maximize(MaximizeCallback callback) { - if (GetCurrentWindowState() == WindowStateType::MAXIMIZED) { + if (widget_->IsMaximized()) { std::move(callback).Run(); return; } @@ -74,7 +84,7 @@ } void CameraAppWindowStateController::Fullscreen(FullscreenCallback callback) { - if (GetCurrentWindowState() == WindowStateType::FULLSCREEN) { + if (widget_->IsFullscreen()) { std::move(callback).Run(); return; } @@ -113,47 +123,51 @@ } void CameraAppWindowStateController::OnWindowStateChanged() { - auto prev_state = window_state_; - window_state_ = GetCurrentWindowState(); + auto trigger_callbacks = [](std::queue<base::OnceClosure>* callbacks) { + while (!callbacks->empty()) { + std::move(callbacks->front()).Run(); + callbacks->pop(); + } + }; - std::queue<base::OnceClosure>* callbacks; - switch (window_state_) { - case WindowStateType::MINIMIZED: - callbacks = &minimize_callbacks_; - break; - case WindowStateType::REGULAR: - callbacks = &restore_callbacks_; - break; - case WindowStateType::MAXIMIZED: - callbacks = &maximize_callbacks_; - break; - case WindowStateType::FULLSCREEN: - callbacks = &fullscreen_callbacks_; - break; + if (widget_->IsMinimized()) { + trigger_callbacks(&minimize_callbacks_); } - while (!callbacks->empty()) { - std::move(callbacks->front()).Run(); - callbacks->pop(); + if (IsRestored(widget_)) { + trigger_callbacks(&restore_callbacks_); + } + if (widget_->IsMaximized()) { + trigger_callbacks(&maximize_callbacks_); + } + if (widget_->IsFullscreen()) { + trigger_callbacks(&fullscreen_callbacks_); } - if (prev_state != window_state_) { + auto prev_states = window_states_; + window_states_ = GetCurrentWindowStates(); + if (prev_states != window_states_) { for (const auto& monitor : monitors_) { - monitor->OnWindowStateChanged(window_state_); + monitor->OnWindowStateChanged(ToVector(window_states_)); } } } -CameraAppWindowStateController::WindowStateType -CameraAppWindowStateController::GetCurrentWindowState() { +base::flat_set<CameraAppWindowStateController::WindowStateType> +CameraAppWindowStateController::GetCurrentWindowStates() { + base::flat_set<CameraAppWindowStateController::WindowStateType> states; if (widget_->IsMinimized()) { - return WindowStateType::MINIMIZED; - } else if (widget_->IsMaximized()) { - return WindowStateType::MAXIMIZED; - } else if (widget_->IsFullscreen()) { - return WindowStateType::FULLSCREEN; - } else { - return WindowStateType::REGULAR; + states.insert(WindowStateType::MINIMIZED); } + if (widget_->IsMaximized()) { + states.insert(WindowStateType::MAXIMIZED); + } + if (widget_->IsFullscreen()) { + states.insert(WindowStateType::FULLSCREEN); + } + if (IsRestored(widget_)) { + states.insert(WindowStateType::REGULAR); + } + return states; } } // namespace chromeos
diff --git a/chromeos/components/camera_app_ui/camera_app_window_state_controller.h b/chromeos/components/camera_app_ui/camera_app_window_state_controller.h index 82c90eb..5d1d7da 100644 --- a/chromeos/components/camera_app_ui/camera_app_window_state_controller.h +++ b/chromeos/components/camera_app_ui/camera_app_window_state_controller.h
@@ -8,6 +8,7 @@ #include <queue> #include <vector> +#include "base/containers/flat_set.h" #include "chromeos/components/camera_app_ui/camera_app_helper.mojom.h" #include "mojo/public/cpp/bindings/pending_receiver.h" #include "mojo/public/cpp/bindings/pending_remote.h" @@ -55,10 +56,10 @@ private: void OnWindowStateChanged(); - WindowStateType GetCurrentWindowState(); + base::flat_set<WindowStateType> GetCurrentWindowStates(); views::Widget* widget_; - WindowStateType window_state_; + base::flat_set<WindowStateType> window_states_; mojo::ReceiverSet<chromeos_camera::mojom::WindowStateController> receivers_; std::vector<mojo::Remote<WindowStateMonitor>> monitors_; std::queue<base::OnceClosure> minimize_callbacks_;
diff --git a/chromeos/components/camera_app_ui/resources/camera_app_resources.grd b/chromeos/components/camera_app_ui/resources/camera_app_resources.grd index 8acb824..7e74c5a 100644 --- a/chromeos/components/camera_app_ui/resources/camera_app_resources.grd +++ b/chromeos/components/camera_app_ui/resources/camera_app_resources.grd
@@ -163,6 +163,7 @@ <include name="IDR_CAMERA_BARCODE_CHEVRON_DOWN_SVG" file="images/barcode_chevron_down.svg" type="BINDATA" /> <include name="IDR_CAMERA_BARCODE_CHEVRON_UP_SVG" file="images/barcode_chevron_up.svg" type="BINDATA" /> <include name="IDR_CAMERA_BARCODE_COPY_SVG" file="images/barcode_copy.svg" type="BINDATA" /> + <include name="IDR_CAMERA_BARCODE_SCAN_BOX_BORDER_MASK_SVG" file="images/barcode_scan_box_border_mask.svg" type="BINDATA" /> <include name="IDR_CAMERA_BARCODE_TOGGLE_OFF_SVG" file="images/barcode_toggle_off.svg" type="BINDATA" /> <include name="IDR_CAMERA_BARCODE_TOGGLE_ON_SVG" file="images/barcode_toggle_on.svg" type="BINDATA" /> <include name="IDR_CAMERA_BARCODE_URL_SVG" file="images/barcode_url.svg" type="BINDATA" />
diff --git a/chromeos/components/camera_app_ui/resources/css/main.css b/chromeos/components/camera_app_ui/resources/css/main.css index eeda5ca3..924262b 100644 --- a/chromeos/components/camera_app_ui/resources/css/main.css +++ b/chromeos/components/camera_app_ui/resources/css/main.css
@@ -206,6 +206,7 @@ rgba(0, 0, 0, 0) 0, rgba(0, 0, 0, 1) var(--fade-padding) calc(100% - var(--fade-padding)), rgba(0, 0, 0, 0) 100%); + display: block; left: calc(var(--left-line) * 2); overflow: auto; padding: 5px 0; @@ -1508,6 +1509,52 @@ visibility: visible; } +/* The container of scan box for layout and positioning. */ +.barcode-scan-box { + --border-distance: 8px; + --border-width: 4px; + --inner-border-radius: 16px; + /* Use padding-top instead of height to make a responsive square, since the + * percentage in padding-top is relative to the width of the containing + * block. */ + padding-top: calc(100% / 3); + visibility: hidden; + width: calc(100% / 3); + z-index: 30; +} + +body.photo.scan-barcode .barcode-scan-box { + visibility: visible; +} + +/* The inner scan box with a translucent overlay. */ +.barcode-scan-box::before { + --offset: calc(var(--border-width) + var(--border-distance)); + border-radius: var(--inner-border-radius); + bottom: var(--offset); + box-shadow: 0 0 0 9999px rgba(0, 0, 0, 0.6); + content: ''; + left: var(--offset); + position: absolute; + right: var(--offset); + top: var(--offset); + z-index: -1; /* This need to be lower than the corner borders */ +} + +/* The corner borders of the scan box. */ +.barcode-scan-box::after { + -webkit-mask: url(/images/barcode_scan_box_border_mask.svg); + border: var(--border-width) solid white; + border-radius: calc(var(--inner-border-radius) + var(--border-distance)); + box-sizing: border-box; + content: ''; + height: 100%; + left: 0; + position: absolute; + top: 0; + width: 100%; +} + /* TODO(b/172879638): Tune the position and layout after we finalized the * responsive window design. */ .barcode-chip-container { @@ -1651,6 +1698,7 @@ position: absolute; visibility: hidden; width: 256px; + z-index: 50; } .snackbar.animate {
diff --git a/chromeos/components/camera_app_ui/resources/images/barcode_scan_box_border_mask.svg b/chromeos/components/camera_app_ui/resources/images/barcode_scan_box_border_mask.svg new file mode 100644 index 0000000..7b4a56bc9 --- /dev/null +++ b/chromeos/components/camera_app_ui/resources/images/barcode_scan_box_border_mask.svg
@@ -0,0 +1,6 @@ +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"> + <rect x="0" y="0" width="25" height="25" fill="#000000"/> + <rect x="75" y="0" width="25" height="25" fill="#000000"/> + <rect x="0" y="75" width="25" height="25" fill="#000000"/> + <rect x="75" y="75" width="25" height="25" fill="#000000"/> +</svg>
diff --git a/chromeos/components/camera_app_ui/resources/images/images.gni b/chromeos/components/camera_app_ui/resources/images/images.gni index 4b03b27..d0f394d 100644 --- a/chromeos/components/camera_app_ui/resources/images/images.gni +++ b/chromeos/components/camera_app_ui/resources/images/images.gni
@@ -6,6 +6,7 @@ "barcode_chevron_down.svg", "barcode_chevron_up.svg", "barcode_copy.svg", + "barcode_scan_box_border_mask.svg", "barcode_toggle_off.svg", "barcode_toggle_on.svg", "barcode_url.svg",
diff --git a/chromeos/components/camera_app_ui/resources/js/window_controller/mojo_window_controller.js b/chromeos/components/camera_app_ui/resources/js/window_controller/mojo_window_controller.js index 94d728d..6b5656ea 100644 --- a/chromeos/components/camera_app_ui/resources/js/window_controller/mojo_window_controller.js +++ b/chromeos/components/camera_app_ui/resources/js/window_controller/mojo_window_controller.js
@@ -23,10 +23,10 @@ this.windowStateController_ = null; /** - * Current window state. - * @type {?chromeosCamera.mojom.WindowStateType} + * Current window states. + * @type {!Array<!chromeosCamera.mojom.WindowStateType>} */ - this.windowState_ = null; + this.windowStates_ = []; } /** @override */ @@ -35,12 +35,12 @@ const windowMonitorCallbackRouter = new chromeosCamera.mojom.WindowStateMonitorCallbackRouter(); - windowMonitorCallbackRouter.onWindowStateChanged.addListener((state) => { - this.windowState_ = state; + windowMonitorCallbackRouter.onWindowStateChanged.addListener((states) => { + this.windowStates_ = states; }); - const {state} = await this.windowStateController_.addMonitor( + const {states} = await this.windowStateController_.addMonitor( windowMonitorCallbackRouter.$.bindNewPipeAndPassRemote()); - this.windowState_ = state; + this.windowStates_ = states; } /** @override */ @@ -85,14 +85,16 @@ /** @override */ isMinimized() { - return this.windowState_ === chromeosCamera.mojom.WindowStateType.MINIMIZED; + return this.windowStates_.includes( + chromeosCamera.mojom.WindowStateType.MINIMIZED); } /** @override */ isFullscreenOrMaximized() { - return this.windowState_ === - chromeosCamera.mojom.WindowStateType.FULLSCREEN || - this.windowState_ === chromeosCamera.mojom.WindowStateType.MAXIMIZED; + return this.windowStates_.includes( + chromeosCamera.mojom.WindowStateType.FULLSCREEN) || + this.windowStates_.includes( + chromeosCamera.mojom.WindowStateType.MAXIMIZED); } /** @override */
diff --git a/chromeos/components/camera_app_ui/resources/views/main.html b/chromeos/components/camera_app_ui/resources/views/main.html index b48e657..5ad81bb 100644 --- a/chromeos/components/camera_app_ui/resources/views/main.html +++ b/chromeos/components/camera_app_ui/resources/views/main.html
@@ -75,6 +75,7 @@ data="/images/camera_focus_aim.svg" tabindex="-1" hidden></object> </div> + <div class="barcode-scan-box centered-overlay"></div> <div class="snackbar"></div> <div id="camera-mode" class="centered-overlay"></div> </div>
diff --git a/components/autofill/core/browser/autofill_regex_constants.cc b/components/autofill/core/browser/autofill_regex_constants.cc index fe3fb99f..342d20f 100644 --- a/components/autofill/core/browser/autofill_regex_constants.cc +++ b/components/autofill/core/browser/autofill_regex_constants.cc
@@ -18,7 +18,10 @@ "province|region|other" "|provincia" // es "|bairro|suburb"; // pt-BR, pt-PT -const char kAddressNameIgnoredRe[] = "address.*nickname|address.*label"; +const char kAddressNameIgnoredRe[] = + "address.*nickname|address.*label" + "|adres ([İi]sim|başlığı|adı)" // tr + "|identificação do endereço"; // pt-BR, pt-PT const char kCompanyRe[] = "company|business|organization|organisation" "|(?<!con)firma|firmenname" // de-DE @@ -52,29 +55,29 @@ const char kAddressLine1Re[] = "^address$|address[_-]?line(one)?|address1|addr1|street" "|(?:shipping|billing)address$" - "|strasse|straße|hausnummer|housenumber" // de-DE - "|house.?name" // en-GB - "|direccion|dirección" // es - "|adresse" // fr-FR - "|indirizzo" // it-IT - "|^住所$|住所1" // ja-JP - "|morada|((?<!do |de )endereço)" // pt-BR, pt-PT - "|Адрес" // ru - "|地址" // zh-CN - "|(\\b|_)adres(?! (başlığı(nız)?|tarifi))(\\b|_)" // tr - "|^주소.?$|주소.?1"; // ko-KR + "|strasse|straße|hausnummer|housenumber" // de-DE + "|house.?name" // en-GB + "|direccion|dirección" // es + "|adresse" // fr-FR + "|indirizzo" // it-IT + "|^住所$|住所1" // ja-JP + "|morada|((?<!do |de )endereço)" // pt-BR, pt-PT + "|Адрес" // ru + "|地址" // zh-CN + "|(\\b|_)adres(?! tarifi)(\\b|_)" // tr + "|^주소.?$|주소.?1"; // ko-KR const char kAddressLine1LabelRe[] = "(^\\W*address)" "|(address\\W*$)" "|(?:shipping|billing|mailing|pick.?up|drop.?off|delivery|sender|postal|" "recipient|home|work|office|school|business|mail)[\\s\\-]+address" "|address\\s+(of|for|to|from)" - "|adresse" // fr-FR - "|indirizzo" // it-IT - "|住所" // ja-JP - "|地址" // zh-CN - "|(\\b|_)adres(?! (başlığı(nız)?|tarifi))(\\b|_)" // tr - "|주소"; // ko-KR + "|adresse" // fr-FR + "|indirizzo" // it-IT + "|住所" // ja-JP + "|地址" // zh-CN + "|(\\b|_)adres(?! tarifi)(\\b|_)" // tr + "|주소"; // ko-KR const char kAddressLine2Re[] = "address[_-]?line(2|two)|address2|addr2|street|suite|unit" "|adresszusatz|ergänzende.?angaben" // de-DE @@ -307,7 +310,6 @@ ///////////////////////////////////////////////////////////////////////////// const char kNameIgnoredRe[] = "user.?name|user.?id|nickname|maiden name|title|prefix|suffix" - "|adres başlığınız" // tr "|vollständiger.?name" // de-DE "|用户名" // zh-CN "|(?:사용자.?)?아이디|사용자.?ID"; // ko-KR
diff --git a/components/autofill/core/browser/form_parsing/address_field_unittest.cc b/components/autofill/core/browser/form_parsing/address_field_unittest.cc index 07fada1..c4cc35f 100644 --- a/components/autofill/core/browser/form_parsing/address_field_unittest.cc +++ b/components/autofill/core/browser/form_parsing/address_field_unittest.cc
@@ -282,4 +282,10 @@ ClassifyAndVerify(/*parsed=*/true, LanguageCode("tr")); } +// Tests that address name is not misclassified as address. +TEST_F(AddressFieldTest, NotParseAddressName) { + AddTextFormFieldData("address", "Adres Başlığı", UNKNOWN_TYPE); + ClassifyAndVerify(/*parsed=*/false, LanguageCode("tr")); +} + } // namespace autofill
diff --git a/components/autofill/core/browser/form_parsing/name_field.cc b/components/autofill/core/browser/form_parsing/name_field.cc index f0c76f94..32ef678 100644 --- a/components/autofill/core/browser/form_parsing/name_field.cc +++ b/components/autofill/core/browser/form_parsing/name_field.cc
@@ -133,9 +133,15 @@ const std::vector<MatchingPattern>& name_ignored_patterns = PatternProvider::GetInstance().GetMatchPatterns("NAME_IGNORED", page_language); + const std::vector<MatchingPattern>& address_name_ignored_patterns = + PatternProvider::GetInstance().GetMatchPatterns("ADDRESS_NAME_IGNORED", + page_language); bool should_ignore = ParseField(scanner, UTF8ToUTF16(kNameIgnoredRe), name_ignored_patterns, - nullptr, {log_manager, "kNameIgnoredRe"}); + nullptr, {log_manager, "kNameIgnoredRe"}) || + ParseField(scanner, UTF8ToUTF16(kAddressNameIgnoredRe), + address_name_ignored_patterns, nullptr, + {log_manager, "kAddressNameIgnoredRe"}); scanner->Rewind(); if (should_ignore) return nullptr; @@ -186,6 +192,9 @@ const std::vector<MatchingPattern>& name_ignored_patterns = PatternProvider::GetInstance().GetMatchPatterns("NAME_IGNORED", page_language); + const std::vector<MatchingPattern>& address_name_ignored_patterns = + PatternProvider::GetInstance().GetMatchPatterns("ADDRESS_NAME_IGNORED", + page_language); const std::vector<MatchingPattern>& first_name_patterns = PatternProvider::GetInstance().GetMatchPatterns("FIRST_NAME", page_language); @@ -217,7 +226,10 @@ if (ParseFieldSpecifics(scanner, UTF8ToUTF16(kNameIgnoredRe), MATCH_DEFAULT | MATCH_SELECT | MATCH_SEARCH, name_ignored_patterns, nullptr, - {log_manager, "kNameIgnoredRe"})) { + {log_manager, "kNameIgnoredRe"}) || + ParseFieldSpecifics(scanner, UTF8ToUTF16(kAddressNameIgnoredRe), + MATCH_DEFAULT, address_name_ignored_patterns, + nullptr, {log_manager, "kAddressNameIgnoredRe"})) { continue; } @@ -333,6 +345,9 @@ const std::vector<MatchingPattern>& name_ignored_patterns = PatternProvider::GetInstance().GetMatchPatterns("NAME_IGNORED", page_language); + const std::vector<MatchingPattern>& address_name_ignored_patterns = + PatternProvider::GetInstance().GetMatchPatterns("ADDRESS_NAME_IGNORED", + page_language); const std::vector<MatchingPattern>& first_name_patterns = PatternProvider::GetInstance().GetMatchPatterns("FIRST_NAME", page_language); @@ -366,7 +381,10 @@ if (ParseFieldSpecifics(scanner, UTF8ToUTF16(kNameIgnoredRe), MATCH_DEFAULT | MATCH_SELECT | MATCH_SEARCH, name_ignored_patterns, nullptr, - {log_manager, "kNameIgnoredRe"})) { + {log_manager, "kNameIgnoredRe"}) || + ParseFieldSpecifics(scanner, UTF8ToUTF16(kAddressNameIgnoredRe), + MATCH_DEFAULT, address_name_ignored_patterns, + nullptr, {log_manager, "kAddressNameIgnoredRe"})) { continue; }
diff --git a/components/autofill/core/browser/form_parsing/name_field_unittest.cc b/components/autofill/core/browser/form_parsing/name_field_unittest.cc index eebe67a..3559c65 100644 --- a/components/autofill/core/browser/form_parsing/name_field_unittest.cc +++ b/components/autofill/core/browser/form_parsing/name_field_unittest.cc
@@ -547,4 +547,19 @@ } } +// Tests that address name is not misclassified as name. +TEST_F(NameFieldTest, NotAddressName) { + FormFieldData field; + field.form_control_type = "text"; + + field.label = base::UTF8ToUTF16("Identificação do Endereço"); + field.name = base::UTF8ToUTF16("name"); + field.unique_renderer_id = MakeFieldRendererId(); + list_.push_back(std::make_unique<AutofillField>(field)); + + AutofillScanner scanner(list_); + field_ = Parse(&scanner); + ASSERT_EQ(nullptr, field_.get()); +} + } // namespace autofill
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 848cb2e..eee8f473 100644 --- a/components/autofill/core/browser/pattern_provider/resources/regex_patterns.json +++ b/components/autofill/core/browser/pattern_provider/resources/regex_patterns.json
@@ -219,6 +219,26 @@ "match_field_attributes": 3, "match_field_input_types": 1 } + ], + "tr": [ + { + "pattern_identifier": "tr_address_name_ignored_preserving", + "positive_pattern": "adres ([İi]sim|başlığı|adı)", + "positive_score": 1.1, + "negative_pattern": null, + "match_field_attributes": 3, + "match_field_input_types": 1 + } + ], + "pt": [ + { + "pattern_identifier": "pt_address_name_ignored_preserving", + "positive_pattern": "identificação do endereço", + "positive_score": 1.1, + "negative_pattern": null, + "match_field_attributes": 3, + "match_field_input_types": 1 + } ] }, "COMPANY": { @@ -449,7 +469,7 @@ "tr": [ { "pattern_identifier": "tr_address_line_1_preserving", - "positive_pattern": "(\\b|_)adres(?! (başlığı(nız)?|tarifi))(\\b|_)", + "positive_pattern": "(\\b|_)adres(?! tarifi)(\\b|_)", "positive_score": 1.1, "negative_pattern": null, "match_field_attributes": 3, @@ -457,7 +477,7 @@ }, { "pattern_identifier": "tr_address_line_1_label_preserving", - "positive_pattern": "(\\b|_)adres(?! (başlığı(nız)?|tarifi))(\\b|_)", + "positive_pattern": "(\\b|_)adres(?! tarifi)(\\b|_)", "positive_score": 1.1, "negative_pattern": null, "match_field_attributes": 1, @@ -2028,16 +2048,6 @@ "positive_score": 0.9, "negative_pattern": null, "match_field_attributes": 3, - "match_field_input_types": 137 - } - ], - "tr": [ - { - "pattern_identifier": "tr_name_ignored_preserving", - "positive_pattern": "adres başlığınız", - "positive_score": 0.9, - "negative_pattern": null, - "match_field_attributes": 3, "match_field_input_types": 137 } ],
diff --git a/components/autofill_assistant/browser/controller.cc b/components/autofill_assistant/browser/controller.cc index ada7439..84511c13 100644 --- a/components/autofill_assistant/browser/controller.cc +++ b/components/autofill_assistant/browser/controller.cc
@@ -925,7 +925,9 @@ observer.OnClientSettingsChanged(settings_); } } - + if (response_proto.has_script_store_config()) { + GetService()->SetScriptStoreConfig(response_proto.script_store_config()); + } std::vector<std::unique_ptr<Script>> scripts; for (const auto& script_proto : response_proto.scripts()) { ProtocolUtils::AddScript(script_proto, &scripts);
diff --git a/components/autofill_assistant/browser/controller_unittest.cc b/components/autofill_assistant/browser/controller_unittest.cc index 4c0b419..96405022 100644 --- a/components/autofill_assistant/browser/controller_unittest.cc +++ b/components/autofill_assistant/browser/controller_unittest.cc
@@ -1167,6 +1167,26 @@ EXPECT_EQ(ACTION_APPLIED, processed_actions_capture[1].status()); } +TEST_F(ControllerTest, SetScriptStoreConfig) { + // A single script, and its corresponding bundle info. + SupportsScriptResponseProto script_response; + AddRunnableScript(&script_response, "script"); + script_response.mutable_script_store_config()->set_bundle_path("bundle/path"); + script_response.mutable_script_store_config()->set_bundle_version(12); + SetupScripts(script_response); + + ScriptStoreConfig script_store_config; + std::vector<ProcessedActionProto> processed_actions_capture; + EXPECT_CALL(*mock_service_, SetScriptStoreConfig(_)) + .WillOnce(SaveArg<0>(&script_store_config)); + + Start("http://a.example.com/path"); + controller_->GetUserActions(); + + EXPECT_THAT(script_store_config.bundle_path(), Eq("bundle/path")); + EXPECT_THAT(script_store_config.bundle_version(), Eq(12)); +} + TEST_F(ControllerTest, InitialDataUrlDoesNotChange) { const std::string deeplink_url("http://initialurl.com/path"); Start(deeplink_url);
diff --git a/components/autofill_assistant/browser/protocol_utils.cc b/components/autofill_assistant/browser/protocol_utils.cc index 40702397..5ace64c 100644 --- a/components/autofill_assistant/browser/protocol_utils.cc +++ b/components/autofill_assistant/browser/protocol_utils.cc
@@ -123,10 +123,15 @@ const std::string& global_payload, const std::string& script_payload, const ClientContextProto& client_context, - const std::map<std::string, std::string>& script_parameters) { + const std::map<std::string, std::string>& script_parameters, + const base::Optional<ScriptStoreConfig>& script_store_config) { ScriptActionRequestProto request_proto; InitialScriptActionsRequestProto* initial_request_proto = request_proto.mutable_initial_request(); + if (script_store_config.has_value()) { + *initial_request_proto->mutable_script_store_config() = + *script_store_config; + } InitialScriptActionsRequestProto::QueryProto* query = initial_request_proto->mutable_query(); query->add_script_path(script_path);
diff --git a/components/autofill_assistant/browser/protocol_utils.h b/components/autofill_assistant/browser/protocol_utils.h index 7642f1f..231ae8c 100644 --- a/components/autofill_assistant/browser/protocol_utils.h +++ b/components/autofill_assistant/browser/protocol_utils.h
@@ -45,7 +45,8 @@ const std::string& global_payload, const std::string& script_payload, const ClientContextProto& client_context, - const std::map<std::string, std::string>& script_parameters); + const std::map<std::string, std::string>& script_parameters, + const base::Optional<ScriptStoreConfig>& script_store_config); // Create request to get next sequence of actions for a script. static std::string CreateNextScriptActionsRequest(
diff --git a/components/autofill_assistant/browser/protocol_utils_unittest.cc b/components/autofill_assistant/browser/protocol_utils_unittest.cc index f6aecd2..c736407 100644 --- a/components/autofill_assistant/browser/protocol_utils_unittest.cc +++ b/components/autofill_assistant/browser/protocol_utils_unittest.cc
@@ -126,10 +126,14 @@ std::map<std::string, std::string> parameters = {{"key_a", "value_a"}, {"key_b", "value_b"}}; ScriptActionRequestProto request; + ScriptStoreConfig config; + config.set_bundle_path("bundle/path"); + config.set_bundle_version(12); EXPECT_TRUE( request.ParseFromString(ProtocolUtils::CreateInitialScriptActionsRequest( "script_path", GURL("http://example.com/"), "global_payload", - "script_payload", client_context_proto_, parameters))); + "script_payload", client_context_proto_, parameters, + base::Optional<ScriptStoreConfig>(config)))); const InitialScriptActionsRequestProto& initial = request.initial_request(); EXPECT_THAT(initial.query().script_path(), ElementsAre("script_path")); @@ -139,6 +143,8 @@ AssertClientContext(request.client_context()); EXPECT_EQ("global_payload", request.global_payload()); EXPECT_EQ("script_payload", request.script_payload()); + EXPECT_EQ("bundle/path", initial.script_store_config().bundle_path()); + EXPECT_EQ(12, initial.script_store_config().bundle_version()); } TEST_F(ProtocolUtilsTest, CreateNextScriptActionsRequest) {
diff --git a/components/autofill_assistant/browser/service.proto b/components/autofill_assistant/browser/service.proto index c77ec61cd..ef836189 100644 --- a/components/autofill_assistant/browser/service.proto +++ b/components/autofill_assistant/browser/service.proto
@@ -123,6 +123,11 @@ optional ScriptTimeoutError script_timeout_error = 2; optional ClientSettingsProto client_settings = 3; + + // The ScriptStoreConfig to use with the initial GetActions request. + optional ScriptStoreConfig script_store_config = 6; + + reserved 4, 5; } // Overlay image to be drawn on top of full overlays. @@ -375,6 +380,13 @@ } } +// Message specifying how to retrieve the scripts. If bundle_path is set, it +// will read that bundle with the associated version. +message ScriptStoreConfig { + optional string bundle_path = 2; + optional int64 bundle_version = 3; +} + // Initial request to get a script's actions. message InitialScriptActionsRequestProto { message QueryProto { @@ -388,6 +400,9 @@ optional QueryProto query = 3; repeated ScriptParameterProto script_parameters = 2; + + // Specify a bundle and version to run. + optional ScriptStoreConfig script_store_config = 6; } message RoundtripTimingStats {
diff --git a/components/autofill_assistant/browser/service/lite_service.cc b/components/autofill_assistant/browser/service/lite_service.cc index f072214..6238c94 100644 --- a/components/autofill_assistant/browser/service/lite_service.cc +++ b/components/autofill_assistant/browser/service/lite_service.cc
@@ -3,7 +3,6 @@ // found in the LICENSE file. #include "components/autofill_assistant/browser/service/lite_service.h" -#include "components/autofill_assistant/browser/service/lite_service_util.h" #include <algorithm> #include <string> @@ -13,6 +12,7 @@ #include "base/logging.h" #include "base/strings/string_number_conversions.h" #include "components/autofill_assistant/browser/protocol_utils.h" +#include "components/autofill_assistant/browser/service/lite_service_util.h" #include "net/http/http_status_code.h" namespace autofill_assistant { @@ -78,7 +78,7 @@ ProtocolUtils::CreateInitialScriptActionsRequest( trigger_script_path_, GURL(), /* global_payload = */ std::string(), /* script_payload = */ std::string(), EmptyClientContext().AsProto(), - /* script_parameters = */ {}), + /* script_parameters = */ {}, /* bundle_info */ base::nullopt), base::BindOnce(&LiteService::OnGetActions, weak_ptr_factory_.GetWeakPtr(), std::move(callback))); }
diff --git a/components/autofill_assistant/browser/service/mock_service.h b/components/autofill_assistant/browser/service/mock_service.h index 05d1a388..42be97ce 100644 --- a/components/autofill_assistant/browser/service/mock_service.h +++ b/components/autofill_assistant/browser/service/mock_service.h
@@ -70,6 +70,9 @@ ResponseCallback& callback)); MOCK_CONST_METHOD0(IsLiteService, bool()); + + MOCK_METHOD1(SetScriptStoreConfig, + void(const ScriptStoreConfig& script_store_config)); }; } // namespace autofill_assistant
diff --git a/components/autofill_assistant/browser/service/service.h b/components/autofill_assistant/browser/service/service.h index ca413cf..6b1f577 100644 --- a/components/autofill_assistant/browser/service/service.h +++ b/components/autofill_assistant/browser/service/service.h
@@ -51,6 +51,9 @@ const RoundtripTimingStats& timing_stats, ResponseCallback callback) = 0; + virtual void SetScriptStoreConfig( + const ScriptStoreConfig& script_store_config) {} + protected: Service() = default; };
diff --git a/components/autofill_assistant/browser/service/service_impl.cc b/components/autofill_assistant/browser/service/service_impl.cc index 1aa89ea..93069455 100644 --- a/components/autofill_assistant/browser/service/service_impl.cc +++ b/components/autofill_assistant/browser/service/service_impl.cc
@@ -61,6 +61,11 @@ ServiceImpl::~ServiceImpl() {} +void ServiceImpl::SetScriptStoreConfig( + const ScriptStoreConfig& script_store_config) { + script_store_config_ = script_store_config; +} + void ServiceImpl::GetScriptsForUrl(const GURL& url, const TriggerContext& trigger_context, ResponseCallback callback) { @@ -89,7 +94,8 @@ script_action_server_url_, ProtocolUtils::CreateInitialScriptActionsRequest( script_path, url, global_payload, script_payload, - client_context_->AsProto(), trigger_context.GetParameters()), + client_context_->AsProto(), trigger_context.GetParameters(), + script_store_config_), std::move(callback)); }
diff --git a/components/autofill_assistant/browser/service/service_impl.h b/components/autofill_assistant/browser/service/service_impl.h index 64b53f2..a690b270 100644 --- a/components/autofill_assistant/browser/service/service_impl.h +++ b/components/autofill_assistant/browser/service/service_impl.h
@@ -75,6 +75,9 @@ const RoundtripTimingStats& timing_stats, ResponseCallback callback) override; + void SetScriptStoreConfig( + const ScriptStoreConfig& script_store_config) override; + private: // The request sender responsible for communicating with a remote endpoint. std::unique_ptr<ServiceRequestSender> request_sender_; @@ -86,6 +89,10 @@ // The client context to send to the backend. std::unique_ptr<ClientContext> client_context_; + // The script store config used for GetActions request. This is set by the + // controller, obtained from the GetScriptsForUrl's response. + base::Optional<ScriptStoreConfig> script_store_config_; + base::WeakPtrFactory<ServiceImpl> weak_ptr_factory_{this}; };
diff --git a/components/autofill_assistant/browser/service/service_impl_unittest.cc b/components/autofill_assistant/browser/service/service_impl_unittest.cc index c95f4637..fa3a81d 100644 --- a/components/autofill_assistant/browser/service/service_impl_unittest.cc +++ b/components/autofill_assistant/browser/service/service_impl_unittest.cc
@@ -4,12 +4,11 @@ #include "components/autofill_assistant/browser/service/service_impl.h" +#include "base/test/gmock_callback_support.h" +#include "base/test/mock_callback.h" #include "components/autofill_assistant/browser/mock_client_context.h" #include "components/autofill_assistant/browser/service/mock_service_request_sender.h" #include "components/autofill_assistant/browser/service/service.h" - -#include "base/test/gmock_callback_support.h" -#include "base/test/mock_callback.h" #include "net/http/http_status_code.h" #include "testing/gmock/include/gmock/gmock.h" @@ -17,8 +16,10 @@ using ::base::test::RunOnceCallback; using ::testing::_; +using ::testing::DoAll; using ::testing::NiceMock; using ::testing::Return; +using ::testing::SaveArg; namespace { @@ -80,6 +81,41 @@ std::string("fake_script_payload"), mock_response_callback_.Get()); } +TEST_F(ServiceImplTest, GetActionsForwardsScriptStoreConfig) { + EXPECT_CALL(*mock_client_context_, Update).Times(1); + + ScriptActionRequestProto expected_get_actions; + ScriptStoreConfig* config = expected_get_actions.mutable_initial_request() + ->mutable_script_store_config(); + config->set_bundle_path("bundle/path"); + config->set_bundle_version(12); + + std::string get_actions_request; + EXPECT_CALL(*mock_request_sender_, + OnSendRequest(GURL(kActionServerUrl), _, _)) + .WillOnce(SaveArg<1>(&get_actions_request)); + + ScriptStoreConfig set_config; + set_config.set_bundle_path("bundle/path"); + set_config.set_bundle_version(12); + service_->SetScriptStoreConfig(set_config); + + TriggerContextImpl trigger_context; + service_->GetActions( + std::string("fake_script_path"), GURL("https://www.example.com"), + trigger_context, std::string("fake_global_payload"), + std::string("fake_script_payload"), mock_response_callback_.Get()); + + ScriptActionRequestProto get_actions_request_proto; + EXPECT_TRUE(get_actions_request_proto.ParseFromString(get_actions_request)); + EXPECT_EQ("bundle/path", get_actions_request_proto.initial_request() + .script_store_config() + .bundle_path()); + EXPECT_EQ(12, get_actions_request_proto.initial_request() + .script_store_config() + .bundle_version()); +} + TEST_F(ServiceImplTest, GetNextActions) { EXPECT_CALL(*mock_client_context_, Update).Times(1); EXPECT_CALL(*mock_request_sender_,
diff --git a/components/autofill_assistant/browser/trigger_scripts/trigger_script_coordinator.cc b/components/autofill_assistant/browser/trigger_scripts/trigger_script_coordinator.cc index 9f29583a..21ee879 100644 --- a/components/autofill_assistant/browser/trigger_scripts/trigger_script_coordinator.cc +++ b/components/autofill_assistant/browser/trigger_scripts/trigger_script_coordinator.cc
@@ -75,12 +75,6 @@ const GURL& deeplink_url, std::unique_ptr<TriggerContext> trigger_context) { deeplink_url_ = deeplink_url; - if (!url_utils::IsInDomainOrSubDomain(GetCurrentURL(), deeplink_url_)) { - LOG(ERROR) << "Trigger script requested for domain other than the deeplink"; - Stop(Metrics::LiteScriptFinishedState::LITE_SCRIPT_PROMPT_FAILED_NAVIGATE); - return; - } - trigger_context_ = std::make_unique<TriggerContextImpl>( ExtractDebugScriptParameters(*trigger_context), trigger_context->experiment_ids());
diff --git a/components/autofill_assistant/browser/trigger_scripts/trigger_script_coordinator_unittest.cc b/components/autofill_assistant/browser/trigger_scripts/trigger_script_coordinator_unittest.cc index 8552f31f..67f8d39 100644 --- a/components/autofill_assistant/browser/trigger_scripts/trigger_script_coordinator_unittest.cc +++ b/components/autofill_assistant/browser/trigger_scripts/trigger_script_coordinator_unittest.cc
@@ -42,7 +42,6 @@ }; const char kFakeDeepLink[] = "https://example.com/q?data=test"; -const char kFakeSubdomainDeepLink[] = "https://b.example.com"; const char kFakeServerUrl[] = "https://www.fake.backend.com/trigger_script_server"; @@ -143,39 +142,6 @@ NiceMock<MockDynamicTriggerConditions>* mock_dynamic_trigger_conditions_; }; -TEST_F(TriggerScriptCoordinatorTest, StartSucceedsForCorrectDomain) { - SimulateNavigateToUrl(GURL(kFakeDeepLink)); - EXPECT_CALL(*mock_request_sender_, OnSendRequest).Times(1); - coordinator_->Start(GURL(kFakeDeepLink), - std::make_unique<TriggerContextImpl>()); -} - -TEST_F(TriggerScriptCoordinatorTest, StartSucceedsWhileNoCommittedURL) { - content::WebContentsTester::For(web_contents())->SetLastCommittedURL(GURL()); - EXPECT_CALL(*mock_request_sender_, OnSendRequest).Times(1); - coordinator_->Start(GURL(kFakeDeepLink), - std::make_unique<TriggerContextImpl>()); -} - -TEST_F(TriggerScriptCoordinatorTest, StartSucceedsForSubDomain) { - SimulateNavigateToUrl(GURL(kFakeSubdomainDeepLink)); - EXPECT_CALL(*mock_request_sender_, OnSendRequest).Times(1); - coordinator_->Start(GURL(kFakeDeepLink), - std::make_unique<TriggerContextImpl>()); -} - -TEST_F(TriggerScriptCoordinatorTest, StartFailsForDifferentDomain) { - SimulateNavigateToUrl(GURL("https://different.com/example")); - EXPECT_CALL(*mock_request_sender_, OnSendRequest).Times(0); - EXPECT_CALL(mock_observer_, - OnTriggerScriptFinished(Metrics::LiteScriptFinishedState:: - LITE_SCRIPT_PROMPT_FAILED_NAVIGATE)); - coordinator_->Start(GURL(kFakeDeepLink), - std::make_unique<TriggerContextImpl>()); - AssertRecordedFinishedState( - Metrics::LiteScriptFinishedState::LITE_SCRIPT_PROMPT_FAILED_NAVIGATE); -} - TEST_F(TriggerScriptCoordinatorTest, StartSendsOnlyApprovedFields) { std::map<std::string, std::string> input_script_params{ {"keyA", "valueA"}, @@ -568,18 +534,21 @@ OnUpdate(mock_web_controller_, _)) .Times(0); SimulateWebContentsVisibilityChanged(content::Visibility::HIDDEN); + // Note: in reality, it should be impossible to navigate on hidden tabs. SimulateNavigateToUrl(GURL("https://example.different.com")); + SimulateNavigateToUrl(GURL("https://also-not-supported.com")); - // However, when the tab becomes visible again, resuming the trigger script - // will fail if the last committed URL is still on a non-supported domain. - EXPECT_CALL( - mock_observer_, - OnTriggerScriptFinished( - Metrics::LiteScriptFinishedState::LITE_SCRIPT_PROMPT_FAILED_NAVIGATE)) + EXPECT_CALL(*mock_request_sender_, OnSendRequest(GURL(kFakeServerUrl), _, _)) + .WillOnce(RunOnceCallback<2>(net::HTTP_OK, /* response = */ "")); + // However, when the tab becomes visible again, the trigger script is + // restarted and thus fails if the tab is still on an unsupported domain. + EXPECT_CALL(mock_observer_, OnTriggerScriptFinished( + Metrics::LiteScriptFinishedState:: + LITE_SCRIPT_NO_TRIGGER_SCRIPT_AVAILABLE)) .Times(1); SimulateWebContentsVisibilityChanged(content::Visibility::VISIBLE); - AssertRecordedFinishedState( - Metrics::LiteScriptFinishedState::LITE_SCRIPT_PROMPT_FAILED_NAVIGATE); + AssertRecordedFinishedState(Metrics::LiteScriptFinishedState:: + LITE_SCRIPT_NO_TRIGGER_SCRIPT_AVAILABLE); } TEST_F(TriggerScriptCoordinatorTest, BottomSheetClosedWithSwipe) {
diff --git a/components/discardable_memory/client/client_discardable_shared_memory_manager.cc b/components/discardable_memory/client/client_discardable_shared_memory_manager.cc index 332af99..24b1b24 100644 --- a/components/discardable_memory/client/client_discardable_shared_memory_manager.cc +++ b/components/discardable_memory/client/client_discardable_shared_memory_manager.cc
@@ -112,10 +112,8 @@ DCHECK(!is_locked()); return; } - if (is_locked()) - manager_->UnlockSpan(span_.get()); - manager_->ReleaseMemory(this, std::move(span_)); + manager_->UnlockAndReleaseMemory(this, std::move(span_)); } bool ClientDiscardableSharedMemoryManager::DiscardableMemoryImpl::Lock() { @@ -537,9 +535,15 @@ return span->shared_memory()->Unlock(offset, length); } -void ClientDiscardableSharedMemoryManager::ReleaseMemory( +void ClientDiscardableSharedMemoryManager::UnlockAndReleaseMemory( DiscardableMemoryImpl* memory, std::unique_ptr<DiscardableSharedMemoryHeap::Span> span) { + memory->manager_->lock_.AssertAcquired(); + // lock_.AssertAcquired(); + if (memory->is_locked()) { + UnlockSpan(span.get()); + } + DCHECK(span); auto removed = allocated_memory_.erase(memory); DCHECK_EQ(removed, 1u);
diff --git a/components/discardable_memory/client/client_discardable_shared_memory_manager.h b/components/discardable_memory/client/client_discardable_shared_memory_manager.h index 36d96fe..f929349 100644 --- a/components/discardable_memory/client/client_discardable_shared_memory_manager.h +++ b/components/discardable_memory/client/client_discardable_shared_memory_manager.h
@@ -114,6 +114,7 @@ bool is_purge_scheduled_ GUARDED_BY(lock_) = false; private: + friend class TestClientDiscardableSharedMemoryManager; class DiscardableMemoryImpl : public base::DiscardableMemory { public: DiscardableMemoryImpl( @@ -174,8 +175,9 @@ // Releases all unlocked memory that was last locked at least |min_age| ago. void PurgeUnlockedMemory(base::TimeDelta min_age); void ReleaseFreeMemoryImpl(); - void ReleaseMemory(DiscardableMemoryImpl* memory, - std::unique_ptr<DiscardableSharedMemoryHeap::Span> span) + void UnlockAndReleaseMemory( + DiscardableMemoryImpl* memory, + std::unique_ptr<DiscardableSharedMemoryHeap::Span> span) EXCLUSIVE_LOCKS_REQUIRED(lock_); void ReleaseSpan(std::unique_ptr<DiscardableSharedMemoryHeap::Span> span) EXCLUSIVE_LOCKS_REQUIRED(lock_);
diff --git a/components/discardable_memory/common/discardable_shared_memory_heap.cc b/components/discardable_memory/common/discardable_shared_memory_heap.cc index 2ae86cb..ceda5c0f 100644 --- a/components/discardable_memory/common/discardable_shared_memory_heap.cc +++ b/components/discardable_memory/common/discardable_shared_memory_heap.cc
@@ -10,15 +10,21 @@ #include <utility> #include "base/bits.h" +#include "base/feature_list.h" #include "base/format_macros.h" #include "base/memory/aligned_memory.h" #include "base/memory/discardable_shared_memory.h" #include "base/memory/ptr_util.h" +#include "base/metrics/histogram_macros.h" #include "base/stl_util.h" #include "base/strings/stringprintf.h" #include "base/trace_event/memory_dump_manager.h" namespace discardable_memory { + +const base::Feature kReleaseDiscardableFreeListPages{ + "ReleaseDiscardableFreeListPages", base::FEATURE_DISABLED_BY_DEFAULT}; + namespace { bool IsInFreeList(DiscardableSharedMemoryHeap::Span* span) { @@ -142,6 +148,25 @@ // First add length of |span| to |num_free_blocks_|. num_free_blocks_ += span->length_; + if (base::FeatureList::IsEnabled(kReleaseDiscardableFreeListPages)) { + SCOPED_UMA_HISTOGRAM_SHORT_TIMER("Memory.Discardable.FreeListReleaseTime"); + // Release as much memory as possible before putting it into the freelists + // in order to reduce their size. Getting this memory back is still much + // cheaper than an IPC, while also saving us space in the freelists. + // + // The "+ 1" in the offset is for the SharedState that's at the start of + // the DiscardableSharedMemory. See DiscardableSharedMemory for details on + // what this is used for. We don't want to remove it, so we offset by an + // extra page. + size_t offset = (1 + span->start_) * base::GetPageSize() - + reinterpret_cast<size_t>(span->shared_memory()->memory()); + // Since we always offset by at least one page because of the SharedState, + // our offset should never be 0. + DCHECK_GT(offset, 0u); + span->shared_memory()->ReleaseMemoryIfPossible( + offset, span->length_ * base::GetPageSize()); + } + // Merge with previous span if possible. auto prev_it = spans_.find(span->start_ - 1); if (prev_it != spans_.end() && IsInFreeList(prev_it->second)) { @@ -250,6 +275,29 @@ return num_free_blocks_ * block_size_; } +base::Optional<size_t> DiscardableSharedMemoryHeap::GetResidentSize() const { + size_t resident_size = 0; + // Each member of |free_spans_| is a LinkedList of Spans. We need to iterate + // over each of these. + for (const base::LinkedList<Span>& span_list : free_spans_) { + for (base::LinkNode<Span>* curr = span_list.head(); curr != span_list.end(); + curr = curr->next()) { + Span* free_span = curr->value(); + // A given span over a piece of Shared Memory (which we will call + // |shared_memory|) has Span::start_ initialized to a value equivalent + // to reinterpret_cast<shared_memory->memory()) / block_size_. + void* mem = reinterpret_cast<void*>(free_span->start() * block_size_); + base::Optional<size_t> resident_in_span = + base::trace_event::ProcessMemoryDump::CountResidentBytes( + mem, free_span->length() * base::GetPageSize()); + if (!resident_in_span) + return base::nullopt; + resident_size += resident_in_span.value(); + } + } + return resident_size; +} + bool DiscardableSharedMemoryHeap::OnMemoryDump( const base::trace_event::MemoryDumpArgs& args, base::trace_event::ProcessMemoryDump* pmd) { @@ -275,6 +323,12 @@ total_dump->AddScalar("virtual_size", base::trace_event::MemoryAllocatorDump::kUnitsBytes, total_size); + auto resident_size = GetResidentSize(); + if (resident_size) { + total_dump->AddScalar("resident_size", + base::trace_event::MemoryAllocatorDump::kUnitsBytes, + resident_size.value()); + } } else { // This iterates over all the memory allocated by the heap, and calls // |OnMemoryDump| for each. It does not contain any information about the @@ -292,6 +346,7 @@ std::unique_ptr<DiscardableSharedMemoryHeap::Span> span) { DCHECK(!IsInFreeList(span.get())); size_t index = std::min(span->length_, base::size(free_spans_)) - 1; + free_spans_[index].Append(span.release()); }
diff --git a/components/discardable_memory/common/discardable_shared_memory_heap.h b/components/discardable_memory/common/discardable_shared_memory_heap.h index efa9e05..d4de3fe8 100644 --- a/components/discardable_memory/common/discardable_shared_memory_heap.h +++ b/components/discardable_memory/common/discardable_shared_memory_heap.h
@@ -150,6 +150,8 @@ void ReleaseMemory(const base::DiscardableSharedMemory* shared_memory, size_t size); + base::Optional<size_t> GetResidentSize() const; + // Dumps memory statistics about a memory segment for chrome://tracing. void OnMemoryDump(const base::DiscardableSharedMemory* shared_memory, size_t size,
diff --git a/components/neterror/resources/BUILD.gn b/components/neterror/resources/BUILD.gn index 34307cd..267d5b99 100644 --- a/components/neterror/resources/BUILD.gn +++ b/components/neterror/resources/BUILD.gn
@@ -11,6 +11,9 @@ "//components/security_interstitials/core/common/resources:interstitial_mobile_nav", "//ui/webui/resources/js:load_time_data", ] + if (is_ios) { + deps += [ ":error_page_controller_ios" ] + } } js_library("neterror") { @@ -22,3 +25,8 @@ js_library("offline") { } + +if (is_ios) { + js_library("error_page_controller_ios") { + } +}
diff --git a/components/neterror/resources/error_page_controller_ios.js b/components/neterror/resources/error_page_controller_ios.js new file mode 100644 index 0000000..209c9fb --- /dev/null +++ b/components/neterror/resources/error_page_controller_ios.js
@@ -0,0 +1,50 @@ +// Copyright (c) 2020 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. + +window.errorPageController = { + // Execute a button click to download page later. + downloadButtonClick: function() {}, + + // Execute a click on the reload button. + reloadButtonClick: function() {}, + + // Execute a "Details" button click. + detailsButtonClick: function() {}, + + // Execute a "Diagnose Errors" button click. + diagnoseErrorsButtonClick: function() {}, + + // ??? + launchOfflineItem: function() {}, + savePageForLater: function() {}, + cancelSavePage: function() {}, + listVisibilityChange: function() {}, + + // Track easter egg plays and high scores. + trackEasterEgg: function() { + __gCrWeb.message.invokeOnHost( + {'command': 'errorPageController.trackEasterEgg'}); + }, + + updateEasterEggHighScore: function(highScore) { + __gCrWeb.message.invokeOnHost({ + 'command': 'errorPageController.updateEasterEggHighScore', + 'highScore': highScore.toString() + }); + }, + + resetEasterEggHighScore: function() { + __gCrWeb.message.invokeOnHost( + {'command': 'errorPageController.resetEasterEggHighScore'}); + } +}; + +// Create a __gCrWeb binding of initializeEasterEggHighScore so it can be +// called using JS messaging. +__gCrWeb.errorPageController = {}; +__gCrWeb['errorPageController'] = __gCrWeb.errorPageController; +__gCrWeb.errorPageController['initializeEasterEggHighScore'] = function( + highscore) { + initializeEasterEggHighScore(highscore); +};
diff --git a/components/neterror/resources/neterror.html b/components/neterror/resources/neterror.html index d3cbee72..0fea0137 100644 --- a/components/neterror/resources/neterror.html +++ b/components/neterror/resources/neterror.html
@@ -13,6 +13,9 @@ <script src="neterror.js"></script> <script src="../../../components/security_interstitials/core/common/resources/interstitial_mobile_nav.js"></script> <script src="offline.js"></script> + <if expr="is_ios"> + <script src="error_page_controller_ios.js"></script> + </if> </head> <body id="t" style="font-family: $i18n{fontfamily}; font-size: $i18n{fontsize}"> <div id="main-frame-error" class="interstitial-wrapper">
diff --git a/components/no_state_prefetch/common/prerender_url_loader_throttle.cc b/components/no_state_prefetch/common/prerender_url_loader_throttle.cc index 96aaf92..e5538c6 100644 --- a/components/no_state_prefetch/common/prerender_url_loader_throttle.cc +++ b/components/no_state_prefetch/common/prerender_url_loader_throttle.cc
@@ -38,14 +38,10 @@ } // namespace PrerenderURLLoaderThrottle::PrerenderURLLoaderThrottle( - prerender::mojom::PrerenderMode mode, const std::string& histogram_prefix, mojo::PendingRemote<prerender::mojom::PrerenderCanceler> canceler) : histogram_prefix_(histogram_prefix), canceler_(std::move(canceler)) { DCHECK(canceler_); - // TODO(https://crbug.com/755921): Remove the `mode` param. This is now kept - // just for validation check until mojom::PrerenderMode is completely removed. - DCHECK_EQ(mode, mojom::PrerenderMode::kPrefetchOnly); } PrerenderURLLoaderThrottle::~PrerenderURLLoaderThrottle() {
diff --git a/components/no_state_prefetch/common/prerender_url_loader_throttle.h b/components/no_state_prefetch/common/prerender_url_loader_throttle.h index 5ecca87..d6199da2 100644 --- a/components/no_state_prefetch/common/prerender_url_loader_throttle.h +++ b/components/no_state_prefetch/common/prerender_url_loader_throttle.h
@@ -11,7 +11,6 @@ #include "base/sequenced_task_runner.h" #include "base/timer/timer.h" #include "components/no_state_prefetch/common/prerender_canceler.mojom.h" -#include "components/no_state_prefetch/common/prerender_types.mojom.h" #include "net/base/request_priority.h" #include "third_party/blink/public/common/loader/url_loader_throttle.h" #include "third_party/blink/public/mojom/loader/resource_load_info.mojom-shared.h" @@ -23,7 +22,6 @@ public base::SupportsWeakPtr<PrerenderURLLoaderThrottle> { public: PrerenderURLLoaderThrottle( - prerender::mojom::PrerenderMode mode, const std::string& histogram_prefix, mojo::PendingRemote<prerender::mojom::PrerenderCanceler> canceler); ~PrerenderURLLoaderThrottle() override;
diff --git a/components/no_state_prefetch/renderer/prerender_helper.cc b/components/no_state_prefetch/renderer/prerender_helper.cc index de57da94..09330e1 100644 --- a/components/no_state_prefetch/renderer/prerender_helper.cc +++ b/components/no_state_prefetch/renderer/prerender_helper.cc
@@ -6,7 +6,7 @@ #include "base/metrics/field_trial.h" #include "base/metrics/histogram_macros.h" -#include "components/no_state_prefetch//common/prerender_url_loader_throttle.h" +#include "components/no_state_prefetch/common/prerender_url_loader_throttle.h" #include "content/public/renderer/document_state.h" #include "content/public/renderer/render_frame.h" #include "content/public/renderer/render_thread.h" @@ -18,14 +18,11 @@ namespace prerender { PrerenderHelper::PrerenderHelper(content::RenderFrame* render_frame, - prerender::mojom::PrerenderMode prerender_mode, const std::string& histogram_prefix) : content::RenderFrameObserver(render_frame), content::RenderFrameObserverTracker<PrerenderHelper>(render_frame), - prerender_mode_(prerender_mode), histogram_prefix_(histogram_prefix), start_time_(base::TimeTicks::Now()) { - DCHECK_NE(prerender_mode_, prerender::mojom::PrerenderMode::kNoPrerender); } PrerenderHelper::~PrerenderHelper() = default; @@ -42,13 +39,12 @@ if (!prerender_helper) return nullptr; - mojo::PendingRemote<prerender::mojom::PrerenderCanceler> canceler; + mojo::PendingRemote<mojom::PrerenderCanceler> canceler; render_frame->GetBrowserInterfaceBroker()->GetInterface( canceler.InitWithNewPipeAndPassReceiver()); auto throttle = std::make_unique<PrerenderURLLoaderThrottle>( - prerender_helper->prerender_mode(), prerender_helper->histogram_prefix(), - std::move(canceler)); + prerender_helper->histogram_prefix(), std::move(canceler)); prerender_helper->AddThrottle(*throttle); return throttle; } @@ -56,25 +52,19 @@ // static. bool PrerenderHelper::IsPrerendering(const content::RenderFrame* render_frame) { return PrerenderHelper::GetPrerenderMode(render_frame) != - prerender::mojom::PrerenderMode::kNoPrerender; + mojom::PrerenderMode::kNoPrerender; } // static. -prerender::mojom::PrerenderMode PrerenderHelper::GetPrerenderMode( +mojom::PrerenderMode PrerenderHelper::GetPrerenderMode( const content::RenderFrame* render_frame) { PrerenderHelper* helper = PrerenderHelper::Get(render_frame); if (!helper) - return prerender::mojom::PrerenderMode::kNoPrerender; - - DCHECK_NE(helper->prerender_mode_, - prerender::mojom::PrerenderMode::kNoPrerender); - return helper->prerender_mode_; + return mojom::PrerenderMode::kNoPrerender; + return mojom::PrerenderMode::kPrefetchOnly; } void PrerenderHelper::DidFinishDocumentLoad() { - if (prerender_mode_ != prerender::mojom::PrerenderMode::kPrefetchOnly) - return; - parsed_time_ = base::TimeTicks::Now(); prefetch_finished_ = true; if (prefetch_count_ == 0) @@ -90,11 +80,9 @@ // sending the "prefetch finished" signal until they are destroyed. This is // important since that signal tells the browser that it can tear down this // renderer which could interrupt subresource prefetching. - if (prerender_mode_ == prerender::mojom::PrerenderMode::kPrefetchOnly) { - prefetch_count_++; - throttle.set_destruction_closure(base::BindOnce( - &PrerenderHelper::OnThrottleDestroyed, weak_factory_.GetWeakPtr())); - } + prefetch_count_++; + throttle.set_destruction_closure(base::BindOnce( + &PrerenderHelper::OnThrottleDestroyed, weak_factory_.GetWeakPtr())); } void PrerenderHelper::OnThrottleDestroyed() { @@ -111,7 +99,7 @@ UMA_HISTOGRAM_MEDIUM_TIMES("Prerender.NoStatePrefetchRendererParseTime", parsed_time_ - start_time_); - mojo::Remote<prerender::mojom::PrerenderCanceler> canceler; + mojo::Remote<mojom::PrerenderCanceler> canceler; render_frame()->GetBrowserInterfaceBroker()->GetInterface( canceler.BindNewPipeAndPassReceiver()); canceler->CancelPrerenderForNoStatePrefetch();
diff --git a/components/no_state_prefetch/renderer/prerender_helper.h b/components/no_state_prefetch/renderer/prerender_helper.h index 1aba2aa6..e8e138f 100644 --- a/components/no_state_prefetch/renderer/prerender_helper.h +++ b/components/no_state_prefetch/renderer/prerender_helper.h
@@ -27,7 +27,6 @@ public content::RenderFrameObserverTracker<PrerenderHelper> { public: PrerenderHelper(content::RenderFrame* render_frame, - prerender::mojom::PrerenderMode prerender_mode, const std::string& histogram_prefix); ~PrerenderHelper() override; @@ -40,12 +39,9 @@ // Returns true if |render_frame| is currently prerendering. static bool IsPrerendering(const content::RenderFrame* render_frame); - static prerender::mojom::PrerenderMode GetPrerenderMode( + static mojom::PrerenderMode GetPrerenderMode( const content::RenderFrame* render_frame); - prerender::mojom::PrerenderMode prerender_mode() const { - return prerender_mode_; - } std::string histogram_prefix() const { return histogram_prefix_; } private: @@ -57,7 +53,6 @@ void OnThrottleDestroyed(); void SendPrefetchFinished(); - const prerender::mojom::PrerenderMode prerender_mode_; std::string histogram_prefix_; int prefetch_count_ = 0;
diff --git a/components/no_state_prefetch/renderer/prerender_render_frame_observer.cc b/components/no_state_prefetch/renderer/prerender_render_frame_observer.cc index 7888156..6391f92 100644 --- a/components/no_state_prefetch/renderer/prerender_render_frame_observer.cc +++ b/components/no_state_prefetch/renderer/prerender_render_frame_observer.cc
@@ -41,9 +41,8 @@ if (!prerender_helper) { // The PrerenderHelper will destroy itself either after recording // histograms or on destruction of the RenderView. - prerender_helper = new prerender::PrerenderHelper( - render_frame(), /*prerender_mode=*/mojom::PrerenderMode::kPrefetchOnly, - histogram_prefix); + prerender_helper = + new prerender::PrerenderHelper(render_frame(), histogram_prefix); } prerender::PrerenderObserverList::SetIsPrerenderingForFrame(
diff --git a/components/password_manager/core/browser/browser_save_password_progress_logger.cc b/components/password_manager/core/browser/browser_save_password_progress_logger.cc index 5f1fa0d..5af2b691 100644 --- a/components/password_manager/core/browser/browser_save_password_progress_logger.cc +++ b/components/password_manager/core/browser/browser_save_password_progress_logger.cc
@@ -4,6 +4,7 @@ #include "components/password_manager/core/browser/browser_save_password_progress_logger.h" +#include <sstream> #include <string> #include <utility> #include <vector> @@ -18,6 +19,7 @@ #include "components/autofill/core/browser/logging/log_manager.h" #include "components/autofill/core/browser/proto/server.pb.h" #include "components/autofill/core/common/signatures.h" +#include "components/password_manager/core/browser/generation/password_requirements_spec_printer.h" #include "components/password_manager/core/browser/password_form.h" #include "components/password_manager/core/browser/password_form_metrics_recorder.h" #include "components/password_manager/core/browser/password_manager.h" @@ -265,6 +267,12 @@ if (field->generated_password_changed()) field_info += ", generated password changed"; + if (field->password_requirements()) { + std::ostringstream s; + s << *field->password_requirements(); + base::StrAppend(&field_info, {", PASSWORD_REQUIREMENTS: ", s.str()}); + } + result += field_info + "\n"; }
diff --git a/components/password_manager/core/browser/form_fetcher_impl_unittest.cc b/components/password_manager/core/browser/form_fetcher_impl_unittest.cc index 1c23bb42..ac6067e 100644 --- a/components/password_manager/core/browser/form_fetcher_impl_unittest.cc +++ b/components/password_manager/core/browser/form_fetcher_impl_unittest.cc
@@ -421,7 +421,7 @@ const std::vector<CompromisedCredentials> credentials = { CompromisedCredentials( form_digest_.signon_realm, base::ASCIIToUTF16("username_value"), - base::Time::FromTimeT(1), CompromiseType::kLeaked, false)}; + base::Time::FromTimeT(1), CompromiseType::kLeaked, IsMuted(false))}; static_cast<CompromisedCredentialsConsumer*>(form_fetcher_.get()) ->OnGetCompromisedCredentials(credentials); EXPECT_THAT(form_fetcher_->GetCompromisedCredentials(), @@ -491,7 +491,7 @@ TEST_P(FormFetcherImplTest, FetchCompromised) { CompromisedCredentials credentials( form_digest_.signon_realm, base::ASCIIToUTF16("username_value"), - base::Time::FromTimeT(1), CompromiseType::kLeaked, false); + base::Time::FromTimeT(1), CompromiseType::kLeaked, IsMuted(false)); std::vector<CompromisedCredentials> list = {credentials}; EXPECT_CALL(*mock_store_, GetMatchingCompromisedCredentialsImpl(form_digest_.signon_realm)) @@ -813,7 +813,7 @@ const std::vector<CompromisedCredentials> credentials = { CompromisedCredentials( form_digest_.signon_realm, base::ASCIIToUTF16("username_value"), - base::Time::FromTimeT(1), CompromiseType::kLeaked, false)}; + base::Time::FromTimeT(1), CompromiseType::kLeaked, IsMuted(false))}; static_cast<CompromisedCredentialsConsumer*>(form_fetcher_.get()) ->OnGetCompromisedCredentials(credentials);
diff --git a/components/password_manager/core/browser/insecure_credentials_table.cc b/components/password_manager/core/browser/insecure_credentials_table.cc index 83ad7c9..04c6481 100644 --- a/components/password_manager/core/browser/insecure_credentials_table.cc +++ b/components/password_manager/core/browser/insecure_credentials_table.cc
@@ -28,7 +28,7 @@ bool is_muted = !!s->ColumnInt64(4); results.emplace_back(std::move(signon_realm), std::move(username), - create_time, insecurity_type, is_muted); + create_time, insecurity_type, IsMuted(is_muted)); } return results; } @@ -41,7 +41,7 @@ base::string16 username, base::Time create_time, CompromiseType insecurity_type, - bool is_muted) + IsMuted is_muted) : signon_realm(std::move(signon_realm)), username(std::move(username)), create_time(create_time), @@ -107,7 +107,7 @@ s.BindInt(0, static_cast<int>(compromised_credentials.compromise_type)); s.BindInt64(1, compromised_credentials.create_time.ToDeltaSinceWindowsEpoch() .InMicroseconds()); - s.BindBool(2, compromised_credentials.is_muted); + s.BindBool(2, compromised_credentials.is_muted.value()); s.BindString(3, compromised_credentials.signon_realm); s.BindString16(4, compromised_credentials.username);
diff --git a/components/password_manager/core/browser/insecure_credentials_table.h b/components/password_manager/core/browser/insecure_credentials_table.h index 792fcb9..99cd489c 100644 --- a/components/password_manager/core/browser/insecure_credentials_table.h +++ b/components/password_manager/core/browser/insecure_credentials_table.h
@@ -19,6 +19,7 @@ namespace password_manager { using BulkCheckDone = base::StrongAlias<class BulkCheckDoneTag, bool>; +using IsMuted = base::StrongAlias<class IsMutedTag, bool>; // These values are persisted to logs. Entries should not be renumbered and // numeric values should never be reused. @@ -51,7 +52,7 @@ base::string16 username, base::Time create_time, CompromiseType compromise_type, - bool is_muted); + IsMuted is_muted); CompromisedCredentials(const CompromisedCredentials& rhs); CompromisedCredentials(CompromisedCredentials&& rhs); CompromisedCredentials& operator=(const CompromisedCredentials& rhs); @@ -67,7 +68,7 @@ // The type of the credentials that was compromised. CompromiseType compromise_type = CompromiseType::kLeaked; // Whether the problem was explicitly muted by the user. - bool is_muted = false; + IsMuted is_muted{false}; // The store in which those credentials are stored. PasswordForm::Store in_store = PasswordForm::Store::kNotSet; };
diff --git a/components/password_manager/core/browser/insecure_credentials_table_unittest.cc b/components/password_manager/core/browser/insecure_credentials_table_unittest.cc index b4c2ddec..332a580 100644 --- a/components/password_manager/core/browser/insecure_credentials_table_unittest.cc +++ b/components/password_manager/core/browser/insecure_credentials_table_unittest.cc
@@ -78,7 +78,7 @@ std::unique_ptr<LoginDatabase> login_db_; CompromisedCredentials test_data_{kTestDomain, base::ASCIIToUTF16(kUsername), base::Time::FromTimeT(1), - CompromiseType::kLeaked, false}; + CompromiseType::kLeaked, IsMuted(false)}; PasswordForm test_form_ = TestForm(); };
diff --git a/components/password_manager/core/browser/leak_detection_delegate_helper.cc b/components/password_manager/core/browser/leak_detection_delegate_helper.cc index 0b891d9..5215a29 100644 --- a/components/password_manager/core/browser/leak_detection_delegate_helper.cc +++ b/components/password_manager/core/browser/leak_detection_delegate_helper.cc
@@ -59,7 +59,7 @@ form->IsUsingAccountStore() ? *account_store_ : *profile_store_; store.AddCompromisedCredentials(CompromisedCredentials( form->signon_realm, form->username_value, base::Time::Now(), - CompromiseType::kLeaked, false)); + CompromiseType::kLeaked, IsMuted(false))); } }
diff --git a/components/password_manager/core/browser/leak_detection_delegate_helper_unittest.cc b/components/password_manager/core/browser/leak_detection_delegate_helper_unittest.cc index f6c5392f..ad504a5 100644 --- a/components/password_manager/core/browser/leak_detection_delegate_helper_unittest.cc +++ b/components/password_manager/core/browser/leak_detection_delegate_helper_unittest.cc
@@ -202,11 +202,11 @@ EXPECT_CALL(*store_, AddCompromisedCredentialsImpl(CompromisedCredentials( GetSignonRealm(GURL(kLeakedOrigin)), ASCIIToUTF16(kLeakedUsername), base::Time::Now(), - CompromiseType::kLeaked, false))); + CompromiseType::kLeaked, IsMuted(false)))); EXPECT_CALL(*store_, AddCompromisedCredentialsImpl(CompromisedCredentials( GetSignonRealm(GURL(kOtherOrigin)), ASCIIToUTF16(kLeakedUsername), base::Time::Now(), - CompromiseType::kLeaked, false))); + CompromiseType::kLeaked, IsMuted(false)))); InitiateGetCredentialLeakType(); } @@ -217,10 +217,11 @@ SetOnShowLeakDetectionNotificationExpectation(IsSaved(false), IsReused(true), CompromisedSitesCount(1)); - EXPECT_CALL(*store_, AddCompromisedCredentialsImpl(CompromisedCredentials( - GetSignonRealm(GURL(kOtherOrigin)), - ASCIIToUTF16(kLeakedUsernameNonCanonicalized), - base::Time::Now(), CompromiseType::kLeaked, false))); + EXPECT_CALL(*store_, + AddCompromisedCredentialsImpl(CompromisedCredentials( + GetSignonRealm(GURL(kOtherOrigin)), + ASCIIToUTF16(kLeakedUsernameNonCanonicalized), + base::Time::Now(), CompromiseType::kLeaked, IsMuted(false)))); InitiateGetCredentialLeakType(); }
diff --git a/components/password_manager/core/browser/leak_detection_delegate_unittest.cc b/components/password_manager/core/browser/leak_detection_delegate_unittest.cc index 820e7be..1ac5475 100644 --- a/components/password_manager/core/browser/leak_detection_delegate_unittest.cc +++ b/components/password_manager/core/browser/leak_detection_delegate_unittest.cc
@@ -347,7 +347,7 @@ const CompromisedCredentials compromised_credentials( GetSignonRealm(form.url), form.username_value, base::Time::Now(), - CompromiseType::kLeaked, false); + CompromiseType::kLeaked, IsMuted(false)); EXPECT_CALL(*store(), AddCompromisedCredentialsImpl(compromised_credentials)); WaitForPasswordStore(); }
diff --git a/components/password_manager/core/browser/multi_store_form_fetcher_unittest.cc b/components/password_manager/core/browser/multi_store_form_fetcher_unittest.cc index 856f686..a28d924 100644 --- a/components/password_manager/core/browser/multi_store_form_fetcher_unittest.cc +++ b/components/password_manager/core/browser/multi_store_form_fetcher_unittest.cc
@@ -443,13 +443,13 @@ Fetch(); CompromisedCredentials profile_store_compromised_credentials( form_digest_.signon_realm, base::ASCIIToUTF16("profile_username"), - base::Time::FromTimeT(1), CompromiseType::kLeaked, false); + base::Time::FromTimeT(1), CompromiseType::kLeaked, IsMuted(false)); profile_store_compromised_credentials.in_store = PasswordForm::Store::kProfileStore; CompromisedCredentials account_store_compromised_credentials( form_digest_.signon_realm, base::ASCIIToUTF16("account_username"), - base::Time::FromTimeT(1), CompromiseType::kLeaked, false); + base::Time::FromTimeT(1), CompromiseType::kLeaked, IsMuted(false)); account_store_compromised_credentials.in_store = PasswordForm::Store::kAccountStore;
diff --git a/components/password_manager/core/browser/password_store_unittest.cc b/components/password_manager/core/browser/password_store_unittest.cc index c5dca5b..6da2d33 100644 --- a/components/password_manager/core/browser/password_store_unittest.cc +++ b/components/password_manager/core/browser/password_store_unittest.cc
@@ -365,7 +365,7 @@ TEST_F(PasswordStoreTest, CompromisedCredentialsObserverOnRemoveLogin) { CompromisedCredentials compromised_credentials( kTestWebRealm1, base::ASCIIToUTF16("username_value_1"), - base::Time::FromTimeT(1), CompromiseType::kLeaked, false); + base::Time::FromTimeT(1), CompromiseType::kLeaked, IsMuted(false)); scoped_refptr<PasswordStoreImpl> store = CreatePasswordStore(); store->Init(nullptr); @@ -405,7 +405,7 @@ TEST_F(PasswordStoreTest, CompromisedCredentialsObserverOnLoginUpdated) { CompromisedCredentials compromised_credentials( kTestWebRealm1, base::ASCIIToUTF16("username_value_1"), - base::Time::FromTimeT(1), CompromiseType::kLeaked, false); + base::Time::FromTimeT(1), CompromiseType::kLeaked, IsMuted(false)); scoped_refptr<PasswordStoreImpl> store = CreatePasswordStore(); store->Init(nullptr); @@ -444,7 +444,7 @@ TEST_F(PasswordStoreTest, CompromisedCredentialsObserverOnLoginAdded) { CompromisedCredentials compromised_credentials( kTestWebRealm1, base::ASCIIToUTF16("username_value_1"), - base::Time::FromTimeT(1), CompromiseType::kLeaked, false); + base::Time::FromTimeT(1), CompromiseType::kLeaked, IsMuted(false)); scoped_refptr<PasswordStoreImpl> store = CreatePasswordStore(); store->Init(nullptr); @@ -495,7 +495,7 @@ 1}; CompromisedCredentials compromised_credentials( kTestWebRealm1, base::ASCIIToUTF16("username_value_1"), - base::Time::FromTimeT(1), CompromiseType::kLeaked, false); + base::Time::FromTimeT(1), CompromiseType::kLeaked, IsMuted(false)); scoped_refptr<PasswordStoreImpl> store = CreatePasswordStore(); store->Init(nullptr); @@ -533,7 +533,7 @@ CompromisedCredentials compromised_credentials( kTestWebRealm1, base::ASCIIToUTF16("username_value_1"), - base::Time::FromTimeT(1), CompromiseType::kLeaked, false); + base::Time::FromTimeT(1), CompromiseType::kLeaked, IsMuted(false)); scoped_refptr<PasswordStoreImpl> store = CreatePasswordStore(); store->Init(nullptr); @@ -566,7 +566,7 @@ CompromisedCredentials compromised_credentials( kTestWebRealm1, base::ASCIIToUTF16("username_value_1"), - base::Time::FromTimeT(1), CompromiseType::kLeaked, false); + base::Time::FromTimeT(1), CompromiseType::kLeaked, IsMuted(false)); constexpr PasswordFormData kTestCredentials = {PasswordForm::Scheme::kHtml, kTestWebRealm1, kTestWebRealm1, @@ -1504,10 +1504,10 @@ store->AddLogin(*FillPasswordFormWithData(data)); CompromisedCredentials compromised_credentials( "https://example.com/", base::ASCIIToUTF16("username"), - base::Time::FromTimeT(1), CompromiseType::kLeaked, false); + base::Time::FromTimeT(1), CompromiseType::kLeaked, IsMuted(false)); CompromisedCredentials compromised_credentials2( "https://2.example.com/", base::ASCIIToUTF16("username2"), - base::Time::FromTimeT(2), CompromiseType::kLeaked, false); + base::Time::FromTimeT(2), CompromiseType::kLeaked, IsMuted(false)); store->AddCompromisedCredentials(compromised_credentials); store->AddCompromisedCredentials(compromised_credentials2); @@ -1546,10 +1546,10 @@ CompromisedCredentials credentials1( kTestWebRealm1, base::ASCIIToUTF16("username_value"), - base::Time::FromTimeT(1), CompromiseType::kLeaked, false); + base::Time::FromTimeT(1), CompromiseType::kLeaked, IsMuted(false)); CompromisedCredentials credentials2( kTestWebRealm2, base::ASCIIToUTF16("username_value"), - base::Time::FromTimeT(2), CompromiseType::kLeaked, false); + base::Time::FromTimeT(2), CompromiseType::kLeaked, IsMuted(false)); for (const auto& credentials : {credentials1, credentials2}) store->AddCompromisedCredentials(credentials); @@ -1580,13 +1580,13 @@ CompromisedCredentials credentials1( kTestWebRealm1, base::ASCIIToUTF16("username_value"), - base::Time::FromTimeT(1), CompromiseType::kLeaked, false); + base::Time::FromTimeT(1), CompromiseType::kLeaked, IsMuted(false)); CompromisedCredentials credentials2( kTestAndroidRealm1, base::ASCIIToUTF16("username_value_1"), - base::Time::FromTimeT(2), CompromiseType::kPhished, false); + base::Time::FromTimeT(2), CompromiseType::kPhished, IsMuted(false)); CompromisedCredentials credentials3( kTestWebRealm2, base::ASCIIToUTF16("username_value_2"), - base::Time::FromTimeT(3), CompromiseType::kLeaked, false); + base::Time::FromTimeT(3), CompromiseType::kLeaked, IsMuted(false)); for (const auto& credentials : {credentials1, credentials2, credentials3}) store->AddCompromisedCredentials(credentials); @@ -1610,13 +1610,13 @@ TEST_F(PasswordStoreTest, RemoveCompromisedCredentialsCreatedBetween) { CompromisedCredentials compromised_credentials1( "https://example1.com/", base::ASCIIToUTF16("username1"), - base::Time::FromTimeT(100), CompromiseType::kLeaked, false); + base::Time::FromTimeT(100), CompromiseType::kLeaked, IsMuted(false)); CompromisedCredentials compromised_credentials2( "https://2.example.com/", base::ASCIIToUTF16("username2"), - base::Time::FromTimeT(200), CompromiseType::kLeaked, false); + base::Time::FromTimeT(200), CompromiseType::kLeaked, IsMuted(false)); CompromisedCredentials compromised_credentials3( "https://example3.com/", base::ASCIIToUTF16("username3"), - base::Time::FromTimeT(300), CompromiseType::kLeaked, false); + base::Time::FromTimeT(300), CompromiseType::kLeaked, IsMuted(false)); scoped_refptr<PasswordStoreImpl> store = CreatePasswordStore(); store->Init(nullptr); @@ -1671,7 +1671,7 @@ CompromisedCredentials compromised_credentials( kTestWebRealm1, base::ASCIIToUTF16("username1"), - base::Time::FromTimeT(100), CompromiseType::kLeaked, false); + base::Time::FromTimeT(100), CompromiseType::kLeaked, IsMuted(false)); constexpr PasswordFormData kTestCredential = {PasswordForm::Scheme::kHtml, kTestWebRealm1, kTestWebOrigin1, @@ -1707,7 +1707,7 @@ CompromisedCredentials compromised_credentials( kTestWebRealm1, base::ASCIIToUTF16("username1"), - base::Time::FromTimeT(100), CompromiseType::kLeaked, false); + base::Time::FromTimeT(100), CompromiseType::kLeaked, IsMuted(false)); constexpr PasswordFormData kTestCredential = {PasswordForm::Scheme::kHtml, kTestWebRealm1, kTestWebOrigin1,
diff --git a/components/password_manager/core/browser/ui/insecure_credentials_manager.cc b/components/password_manager/core/browser/ui/insecure_credentials_manager.cc index 2ec0103e..f3fcba9c 100644 --- a/components/password_manager/core/browser/ui/insecure_credentials_manager.cc +++ b/components/password_manager/core/browser/ui/insecure_credentials_manager.cc
@@ -267,7 +267,7 @@ GetStoreFor(saved_password) .AddCompromisedCredentials(CompromisedCredentials( saved_password.signon_realm, saved_password.username_value, - base::Time::Now(), CompromiseType::kLeaked, false)); + base::Time::Now(), CompromiseType::kLeaked, IsMuted(false))); } } }
diff --git a/components/password_manager/core/browser/ui/insecure_credentials_manager_unittest.cc b/components/password_manager/core/browser/ui/insecure_credentials_manager_unittest.cc index 63ff837..cbb21389 100644 --- a/components/password_manager/core/browser/ui/insecure_credentials_manager_unittest.cc +++ b/components/password_manager/core/browser/ui/insecure_credentials_manager_unittest.cc
@@ -63,7 +63,7 @@ CompromiseType type = CompromiseType::kLeaked) { return CompromisedCredentials(std::move(signon_realm), base::ASCIIToUTF16(username), base::Time(), - type, false); + type, IsMuted(false)); } PasswordForm MakeSavedPassword(base::StringPiece signon_realm,
diff --git a/components/password_manager/core/browser/ui/post_save_compromised_helper_unittest.cc b/components/password_manager/core/browser/ui/post_save_compromised_helper_unittest.cc index 48103ac..6f5d177 100644 --- a/components/password_manager/core/browser/ui/post_save_compromised_helper_unittest.cc +++ b/components/password_manager/core/browser/ui/post_save_compromised_helper_unittest.cc
@@ -31,7 +31,7 @@ PasswordForm::Store store = PasswordForm::Store::kProfileStore) { CompromisedCredentials compromised(kSignonRealm, base::ASCIIToUTF16(username), base::Time(), CompromiseType::kLeaked, - false); + IsMuted(false)); compromised.in_store = store; return compromised; }
diff --git a/components/performance_manager/BUILD.gn b/components/performance_manager/BUILD.gn index 5f3e977..3727500 100644 --- a/components/performance_manager/BUILD.gn +++ b/components/performance_manager/BUILD.gn
@@ -46,6 +46,7 @@ "execution_context_priority/root_vote_observer.cc", "execution_context_priority/root_vote_observer.h", "features.cc", + "freezing/freezing.cc", "freezing/freezing_vote_aggregator.cc", "freezing/freezing_vote_aggregator.h", "graph/frame_node.cc", @@ -295,6 +296,7 @@ if (!is_android) { sources += [ "decorators/site_data_recorder_unittest.cc", + "freezing/freezing_unittest.cc", "persistence/site_data/exponential_moving_average_unittest.cc", "persistence/site_data/leveldb_site_data_store_unittest.cc", "persistence/site_data/non_recording_site_data_cache_unittest.cc",
diff --git a/components/performance_manager/embedder/graph_features_helper.h b/components/performance_manager/embedder/graph_features_helper.h index 679aab3..e20ca222 100644 --- a/components/performance_manager/embedder/graph_features_helper.h +++ b/components/performance_manager/embedder/graph_features_helper.h
@@ -28,6 +28,7 @@ bool execution_context_registry : 1; bool frame_node_impl_describer : 1; bool frame_visibility_decorator : 1; + bool freezing_vote_decorator : 1; bool page_live_state_decorator : 1; bool page_load_tracker_decorator : 1; bool page_node_impl_describer : 1; @@ -64,6 +65,11 @@ return *this; } + constexpr GraphFeaturesHelper& EnableFreezingVoteDecorator() { + flags_.freezing_vote_decorator = true; + return *this; + } + constexpr GraphFeaturesHelper& EnablePageLiveStateDecorator() { flags_.page_live_state_decorator = true; return *this; @@ -120,6 +126,7 @@ EnableExecutionContextRegistry(); EnableFrameNodeImplDescriber(); EnableFrameVisibilityDecorator(); + EnableFreezingVoteDecorator(); EnablePageLiveStateDecorator(); EnablePageLoadTrackerDecorator(); EnablePageNodeImplDescriber();
diff --git a/components/performance_manager/freezing/freezing.cc b/components/performance_manager/freezing/freezing.cc new file mode 100644 index 0000000..90bb84f7 --- /dev/null +++ b/components/performance_manager/freezing/freezing.cc
@@ -0,0 +1,141 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/performance_manager/public/freezing/freezing.h" + +#include <memory> + +#include "base/bind.h" +#include "base/sequence_checker.h" +#include "base/sequenced_task_runner.h" +#include "base/task/post_task.h" +#include "components/performance_manager/freezing/freezing_vote_aggregator.h" +#include "components/performance_manager/performance_manager_impl.h" +#include "components/performance_manager/public/graph/page_node.h" +#include "components/performance_manager/public/performance_manager.h" +#include "content/public/browser/web_contents.h" + +namespace performance_manager { + +namespace freezing { + +namespace { + +// The counterpart of a FreezingVoteToken that lives on the PM sequence. +class FreezingVoteTokenPMImpl : public PageNode::ObserverDefaultImpl { + public: + FreezingVoteTokenPMImpl(content::WebContents* content, + FreezingVoteValue vote_value, + const char* vote_reason); + ~FreezingVoteTokenPMImpl() override; + FreezingVoteTokenPMImpl(const FreezingVoteTokenPMImpl& other) = delete; + FreezingVoteTokenPMImpl& operator=(const FreezingVoteTokenPMImpl&) = delete; + + // PageNodeObserver: + void OnBeforePageNodeRemoved(const PageNode* page_node) override; + + private: + const PageNode* page_node_ = nullptr; + Graph* graph_ = nullptr; + + // Voting channel wrapper. This objects should only be used on the PM + // sequence. + std::unique_ptr<FreezingVotingChannelWrapper> voter_; + + SEQUENCE_CHECKER(sequence_checker_); +}; + +// Concrete implementation of a FreezingVoteToken. +class FreezingVoteTokenImpl : public FreezingVoteToken { + public: + FreezingVoteTokenImpl(content::WebContents* content, + FreezingVoteValue vote_value, + const char* vote_reason); + ~FreezingVoteTokenImpl() override; + FreezingVoteTokenImpl(const FreezingVoteTokenImpl& other) = delete; + FreezingVoteTokenImpl& operator=(const FreezingVoteTokenImpl&) = delete; + + private: + // Voting channel wrapper. This objects should only be used on the PM + // sequence. + std::unique_ptr<FreezingVoteTokenPMImpl, base::OnTaskRunnerDeleter> pm_impl_; +}; + +} // namespace + +FreezingVoteToken::FreezingVoteToken() = default; +FreezingVoteToken::~FreezingVoteToken() = default; + +FreezingVoteTokenPMImpl::FreezingVoteTokenPMImpl(content::WebContents* content, + FreezingVoteValue vote_value, + const char* vote_reason) { + DETACH_FROM_SEQUENCE(sequence_checker_); + // Register the vote on the PM sequence. + PerformanceManager::CallOnGraph( + FROM_HERE, + base::BindOnce( + [](base::WeakPtr<PageNode> page_node, FreezingVoteValue vote_value, + const char* vote_reason, FreezingVoteTokenPMImpl* voter_pm_impl, + Graph* graph) { + voter_pm_impl->voter_ = + std::make_unique<FreezingVotingChannelWrapper>(); + voter_pm_impl->graph_ = graph; + graph->AddPageNodeObserver(voter_pm_impl); + voter_pm_impl->voter_->SetVotingChannel( + graph->GetRegisteredObjectAs<FreezingVoteAggregator>() + ->GetVotingChannel()); + if (page_node) { + voter_pm_impl->voter_->SubmitVote(page_node.get(), + {vote_value, vote_reason}); + voter_pm_impl->page_node_ = page_node.get(); + } + }, + PerformanceManager::GetPageNodeForWebContents(content), vote_value, + // It's safe to use Unretained because |vote_reason| is a static + // string. + base::Unretained(vote_reason), + // It's safe to use Unretained because |this| can only be deleted + // from a task running on the PM sequence after this callback. + base::Unretained(this))); +} + +FreezingVoteTokenPMImpl::~FreezingVoteTokenPMImpl() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + if (graph_) + graph_->RemovePageNodeObserver(this); +} + +void FreezingVoteTokenPMImpl::OnBeforePageNodeRemoved( + const PageNode* page_node) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + if (page_node == page_node_) { + // Invalidate the vote if its associated page node is destroyed. This can + // happen if a freezing vote token is released after the destruction of the + // WebContents it's associated with. + voter_->InvalidateVote(page_node); + page_node_ = nullptr; + graph_->RemovePageNodeObserver(this); + graph_ = nullptr; + } +} + +FreezingVoteTokenImpl::FreezingVoteTokenImpl(content::WebContents* content, + FreezingVoteValue vote_value, + const char* vote_reason) + : pm_impl_(new FreezingVoteTokenPMImpl(content, vote_value, vote_reason), + base::OnTaskRunnerDeleter(PerformanceManager::GetTaskRunner())) { +} + +FreezingVoteTokenImpl::~FreezingVoteTokenImpl() = default; + +std::unique_ptr<FreezingVoteToken> EmitFreezingVoteForWebContents( + content::WebContents* content, + FreezingVoteValue vote_value, + const char* vote_reason) { + return std::make_unique<FreezingVoteTokenImpl>(content, vote_value, + vote_reason); +} + +} // namespace freezing +} // namespace performance_manager \ No newline at end of file
diff --git a/components/performance_manager/freezing/freezing_unittest.cc b/components/performance_manager/freezing/freezing_unittest.cc new file mode 100644 index 0000000..4d4e8fd8 --- /dev/null +++ b/components/performance_manager/freezing/freezing_unittest.cc
@@ -0,0 +1,103 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/performance_manager/public/freezing/freezing.h" + +#include "components/performance_manager/public/graph/page_node.h" +#include "components/performance_manager/public/performance_manager.h" +#include "components/performance_manager/test_support/performance_manager_test_harness.h" +#include "components/performance_manager/test_support/test_harness_helper.h" +#include "content/public/test/test_renderer_host.h" +#include "content/public/test/web_contents_tester.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace performance_manager { +namespace freezing { + +namespace { + +constexpr char kCanFreeze[] = "Can freeze"; +constexpr char kCannotFreeze[] = "Cannot freeze"; + +// Check that the freezing vote attached to the page node associated with +// |content| has the expected value. +void ExpectFreezingVote(content::WebContents* content, + base::Optional<FreezingVote> expected_vote) { + base::RunLoop run_loop; + auto quit_closure = run_loop.QuitClosure(); + PerformanceManager::CallOnGraph( + FROM_HERE, + base::BindOnce( + [](base::WeakPtr<PageNode> page_node, base::OnceClosure quit_closure, + base::Optional<FreezingVote> expected_vote) { + EXPECT_TRUE(page_node); + auto vote = page_node->GetFreezingVote(); + EXPECT_EQ(expected_vote, vote); + std::move(quit_closure).Run(); + }, + PerformanceManager::GetPageNodeForWebContents(content), + std::move(quit_closure), expected_vote)); + run_loop.Run(); +} + +} // namespace + +class FreezingTest : public PerformanceManagerTestHarness { + public: + FreezingTest() = default; + ~FreezingTest() override = default; + FreezingTest(const FreezingTest& other) = delete; + FreezingTest& operator=(const FreezingTest&) = delete; + + void SetUp() override { + GetGraphFeaturesHelper().EnableFreezingVoteDecorator(); + PerformanceManagerTestHarness::SetUp(); + SetContents(CreateTestWebContents()); + } +}; + +TEST_F(FreezingTest, FreezingToken) { + content::WebContentsTester* web_contents_tester = + content::WebContentsTester::For(web_contents()); + EXPECT_TRUE(web_contents_tester); + web_contents_tester->NavigateAndCommit(GURL("https:/foo.com")); + + { + // Emit a positive freezing vote, this should make the page node freezable. + auto token = EmitFreezingVoteForWebContents( + web_contents(), FreezingVoteValue::kCanFreeze, kCanFreeze); + ExpectFreezingVote(web_contents(), + FreezingVote(FreezingVoteValue::kCanFreeze, kCanFreeze)); + } + // Once the freezing vote token is destroyed the vote should be invalidated. + ExpectFreezingVote(web_contents(), base::nullopt); + + // Same test but for a negative freezing vote. + { + auto token = EmitFreezingVoteForWebContents( + web_contents(), FreezingVoteValue::kCannotFreeze, kCannotFreeze); + ExpectFreezingVote( + web_contents(), + FreezingVote(FreezingVoteValue::kCannotFreeze, kCannotFreeze)); + } + ExpectFreezingVote(web_contents(), base::nullopt); +} + +TEST_F(FreezingTest, WebContentsDestroyedBeforeToken) { + content::WebContentsTester* web_contents_tester = + content::WebContentsTester::For(web_contents()); + EXPECT_TRUE(web_contents_tester); + web_contents_tester->NavigateAndCommit(GURL("https:/foo.com")); + + // Emit a positive freezing vote, this should make the page node freezable. + auto token = EmitFreezingVoteForWebContents( + web_contents(), FreezingVoteValue::kCanFreeze, kCanFreeze); + ExpectFreezingVote(web_contents(), + FreezingVote(FreezingVoteValue::kCanFreeze, kCanFreeze)); + DeleteContents(); + base::RunLoop().RunUntilIdle(); +} + +} // namespace freezing +} // namespace performance_manager \ No newline at end of file
diff --git a/components/performance_manager/graph_features_helper.cc b/components/performance_manager/graph_features_helper.cc index d0dd4f32..7a56dd22 100644 --- a/components/performance_manager/graph_features_helper.cc +++ b/components/performance_manager/graph_features_helper.cc
@@ -8,6 +8,7 @@ #include "build/build_config.h" #include "components/performance_manager/decorators/frame_visibility_decorator.h" +#include "components/performance_manager/decorators/freezing_vote_decorator.h" #include "components/performance_manager/decorators/page_load_tracker_decorator.h" #include "components/performance_manager/execution_context/execution_context_registry_impl.h" #include "components/performance_manager/execution_context_priority/execution_context_priority_decorator.h" @@ -42,6 +43,8 @@ Install<FrameNodeImplDescriber>(graph); if (flags_.frame_visibility_decorator) Install<FrameVisibilityDecorator>(graph); + if (flags_.freezing_vote_decorator) + Install<FreezingVoteDecorator>(graph); if (flags_.page_live_state_decorator) Install<PageLiveStateDecorator>(graph); if (flags_.page_load_tracker_decorator)
diff --git a/components/performance_manager/graph_features_helper_unittest.cc b/components/performance_manager/graph_features_helper_unittest.cc index 5c5e5a3..cf0d6b1 100644 --- a/components/performance_manager/graph_features_helper_unittest.cc +++ b/components/performance_manager/graph_features_helper_unittest.cc
@@ -50,7 +50,7 @@ execution_context::ExecutionContextRegistry::GetFromGraph(&graph)); EXPECT_FALSE(v8_memory::V8ContextTracker::GetFromGraph(&graph)); - size_t graph_owned_count = 10; + size_t graph_owned_count = 11; #if !defined(OS_ANDROID) // The SiteDataRecorder is not available on Android. graph_owned_count++; @@ -60,7 +60,7 @@ features.EnableDefault(); features.ConfigureGraph(&graph); EXPECT_EQ(graph_owned_count, graph.GraphOwnedCountForTesting()); - EXPECT_EQ(2u, graph.GraphRegisteredCountForTesting()); + EXPECT_EQ(3u, graph.GraphRegisteredCountForTesting()); EXPECT_EQ(8u, graph.NodeDataDescriberCountForTesting()); // Ensure the GraphRegistered objects can be queried directly. EXPECT_TRUE(
diff --git a/components/performance_manager/public/freezing/freezing.h b/components/performance_manager/public/freezing/freezing.h index ff6980bf..10eaadefa 100644 --- a/components/performance_manager/public/freezing/freezing.h +++ b/components/performance_manager/public/freezing/freezing.h
@@ -10,6 +10,10 @@ #include "components/performance_manager/public/voting/voting.h" +namespace content { +class WebContents; +} + namespace performance_manager { class PageNode; @@ -30,6 +34,28 @@ voting::VoteConsumerDefaultImpl<FreezingVote>; using FreezingVotingChannelWrapper = voting::VotingChannelWrapper<FreezingVote>; +// A freezing vote token, instances of this are meant to be retrieved by calling +// |EmitFreezingVoteForWebContents|. +class FreezingVoteToken { + public: + FreezingVoteToken(const FreezingVoteToken& other) = delete; + FreezingVoteToken& operator=(const FreezingVoteToken&) = delete; + virtual ~FreezingVoteToken() = 0; + + protected: + FreezingVoteToken(); +}; + +// Allows emiting a freezing vote for a WebContents. The vote's lifetime will +// follow the lifetime of this object, as soon as it's released the vote will be +// invalidated. +// +// NOTE: |vote_reason| *must* be a static string. +std::unique_ptr<FreezingVoteToken> EmitFreezingVoteForWebContents( + content::WebContents* content, + FreezingVoteValue vote_value, + const char* vote_reason); + } // namespace freezing } // namespace performance_manager
diff --git a/components/performance_manager/public/voting/voting.h b/components/performance_manager/public/voting/voting.h index 7e47e5c..071ba2af 100644 --- a/components/performance_manager/public/voting/voting.h +++ b/components/performance_manager/public/voting/voting.h
@@ -486,6 +486,9 @@ // Returns true if the underlying VotingChannel is valid. bool IsValid() const; + // Checks whether or not there's a vote associated with |context|. + bool HasVoteForContext(const ContextType* context); + VoterId<VoteImpl> voter_id() const { return voting_channel_.voter_id(); } private: @@ -1034,6 +1037,12 @@ return voting_channel_.IsValid(); } +template <class VoteImpl> +bool VotingChannelWrapper<VoteImpl>::HasVoteForContext( + const ContextType* context) { + return base::Contains(vote_receipts_, context); +} + } // namespace voting } // namespace performance_manager
diff --git a/components/policy/resources/policy_templates.json b/components/policy/resources/policy_templates.json index 82eb9dbe..7e7aed6 100644 --- a/components/policy/resources/policy_templates.json +++ b/components/policy/resources/policy_templates.json
@@ -23420,7 +23420,7 @@ If this policy is enabled or not set the <ph name="PRODUCT_NAME">User-Agent Client Hints</ph> feature is enabled. If the policy is disabled the feature is unavailable. - This enterprise policy is for short-term adaptation and will be removed in Chrome 88.''', + This enterprise policy is for short-term adaptation purposes and will be available at least until Chrome 91.''', }, { 'name': 'SuggestedContentEnabled',
diff --git a/components/signin/internal/identity_manager/primary_account_manager.cc b/components/signin/internal/identity_manager/primary_account_manager.cc index 98d52b4..50a8037 100644 --- a/components/signin/internal/identity_manager/primary_account_manager.cc +++ b/components/signin/internal/identity_manager/primary_account_manager.cc
@@ -25,6 +25,8 @@ #include "components/signin/public/base/signin_pref_names.h" #include "components/signin/public/base/signin_switches.h" +using signin::PrimaryAccountChangeEvent; + PrimaryAccountManager::PrimaryAccountManager( SigninClient* client, ProfileOAuth2TokenService* token_service, @@ -155,11 +157,16 @@ } bool account_changed = account_info != primary_account_info(); + PrimaryAccountChangeEvent::State previous_state( + primary_account_info(), signin::ConsentLevel::kNotRequired); SetPrimaryAccountInternal(account_info, /*consented_to_sync=*/false); if (account_changed) { + PrimaryAccountChangeEvent::State current_state( + account_info, signin::ConsentLevel::kNotRequired); + PrimaryAccountChangeEvent event_details(previous_state, current_state); for (Observer& observer : observers_) - observer.UnconsentedPrimaryAccountChanged(primary_account_info()); + observer.UnconsentedPrimaryAccountChanged(event_details); } } @@ -243,12 +250,21 @@ } bool account_changed = info != primary_account_info(); + PrimaryAccountChangeEvent::State previous_state( + primary_account_info(), signin::ConsentLevel::kNotRequired); + PrimaryAccountChangeEvent::State current_state(info, + signin::ConsentLevel::kSync); + PrimaryAccountChangeEvent event_details(previous_state, current_state); + SetAuthenticatedAccountInfo(info); for (Observer& observer : observers_) { + // TODO(https://crbug.com/1158855): Remove call to + // UnconsentedPrimaryAccountChanged() after IdentityManager::Observer + // migration has been completed. if (account_changed) - observer.UnconsentedPrimaryAccountChanged(info); - observer.GoogleSigninSucceeded(info); + observer.UnconsentedPrimaryAccountChanged(event_details); + observer.GoogleSigninSucceeded(event_details); } } @@ -335,9 +351,10 @@ } const CoreAccountInfo account_info = primary_account_info(); + const bool has_sync_consent = HasPrimaryAccount(signin::ConsentLevel::kSync); client_->GetPrefs()->ClearPref(prefs::kGoogleServicesHostedDomain); // Revoke the sync consent. - if (HasPrimaryAccount(signin::ConsentLevel::kSync)) + if (has_sync_consent) SetPrimaryAccountInternal(account_info, /*consented_to_sync=*/false); DCHECK(!HasPrimaryAccount(signin::ConsentLevel::kSync)); @@ -357,8 +374,15 @@ break; } + PrimaryAccountChangeEvent::State previous_state; + previous_state.primary_account = account_info; + previous_state.consent_level = has_sync_consent + ? signin::ConsentLevel::kSync + : signin::ConsentLevel::kNotRequired; + PrimaryAccountChangeEvent event_details(previous_state, + PrimaryAccountChangeEvent::State()); for (Observer& observer : observers_) - observer.GoogleSignedOut(account_info); + observer.GoogleSignedOut(event_details); } void PrimaryAccountManager::OnRefreshTokensLoaded() {
diff --git a/components/signin/internal/identity_manager/primary_account_manager.h b/components/signin/internal/identity_manager/primary_account_manager.h index 2d4d490..b05fb4c 100644 --- a/components/signin/internal/identity_manager/primary_account_manager.h +++ b/components/signin/internal/identity_manager/primary_account_manager.h
@@ -30,6 +30,7 @@ #include "components/signin/public/base/signin_client.h" #include "components/signin/public/identity_manager/account_info.h" #include "components/signin/public/identity_manager/consent_level.h" +#include "components/signin/public/identity_manager/primary_account_change_event.h" class AccountTrackerService; class PrefRegistrySimple; @@ -48,15 +49,17 @@ public: // Called whenever a user signs into Google services such as sync. // Not called during a reauth. - virtual void GoogleSigninSucceeded(const CoreAccountInfo& info) {} + virtual void GoogleSigninSucceeded( + const signin::PrimaryAccountChangeEvent& event_details) {} // Called whenever the unconsented primary account changes. This includes // the changes for the consented primary account as well. - virtual void UnconsentedPrimaryAccountChanged(const CoreAccountInfo& info) { - } + virtual void UnconsentedPrimaryAccountChanged( + const signin::PrimaryAccountChangeEvent& event_details) {} // Called whenever the currently signed-in user has been signed out. - virtual void GoogleSignedOut(const CoreAccountInfo& info) {} + virtual void GoogleSignedOut( + const signin::PrimaryAccountChangeEvent& event_details) {} }; // Used to remove accounts from the token service and the account tracker.
diff --git a/components/signin/internal/identity_manager/primary_account_manager_unittest.cc b/components/signin/internal/identity_manager/primary_account_manager_unittest.cc index e9b42c7..dd98841 100644 --- a/components/signin/internal/identity_manager/primary_account_manager_unittest.cc +++ b/components/signin/internal/identity_manager/primary_account_manager_unittest.cc
@@ -121,11 +121,13 @@ EXPECT_EQ(1, num_successful_signins_); } - void GoogleSigninSucceeded(const CoreAccountInfo& account_info) override { + void GoogleSigninSucceeded( + const signin::PrimaryAccountChangeEvent& account_info) override { num_successful_signins_++; } - void UnconsentedPrimaryAccountChanged(const CoreAccountInfo& info) override { + void UnconsentedPrimaryAccountChanged( + const signin::PrimaryAccountChangeEvent& info) override { num_unconsented_account_changed_++; } @@ -477,4 +479,4 @@ EXPECT_FALSE(manager_->HasPrimaryAccount(ConsentLevel::kSync)); EXPECT_FALSE(manager_->HasPrimaryAccount(ConsentLevel::kNotRequired)); } -#endif // !BUILDFLAG(IS_CHROMEOS_ASH) \ No newline at end of file +#endif // !BUILDFLAG(IS_CHROMEOS_ASH)
diff --git a/components/signin/public/identity_manager/BUILD.gn b/components/signin/public/identity_manager/BUILD.gn index 9a65599..5ba621b1 100644 --- a/components/signin/public/identity_manager/BUILD.gn +++ b/components/signin/public/identity_manager/BUILD.gn
@@ -34,6 +34,8 @@ "load_credentials_state.h", "primary_account_access_token_fetcher.cc", "primary_account_access_token_fetcher.h", + "primary_account_change_event.cc", + "primary_account_change_event.h", "primary_account_mutator.h", "scope_set.h", "set_accounts_in_cookie_result.h", @@ -100,6 +102,7 @@ "identity_test_environment_unittest.cc", "identity_utils_unittest.cc", "primary_account_access_token_fetcher_unittest.cc", + "primary_account_change_event_unittest.cc", "primary_account_mutator_unittest.cc", ]
diff --git a/components/signin/public/identity_manager/identity_manager.cc b/components/signin/public/identity_manager/identity_manager.cc index 37dc9de..53c6ee0 100644 --- a/components/signin/public/identity_manager/identity_manager.cc +++ b/components/signin/public/identity_manager/identity_manager.cc
@@ -480,9 +480,12 @@ } void IdentityManager::GoogleSigninSucceeded( - const CoreAccountInfo& account_info) { + const PrimaryAccountChangeEvent& event_details) { + const CoreAccountInfo& account_info = + event_details.GetCurrentState().primary_account; for (auto& observer : observer_list_) { observer.OnPrimaryAccountSet(account_info); + observer.OnPrimaryAccountChanged(event_details); } #if defined(OS_ANDROID) if (java_identity_manager_) { @@ -495,12 +498,19 @@ } void IdentityManager::UnconsentedPrimaryAccountChanged( - const CoreAccountInfo& account_info) { - for (auto& observer : observer_list_) + const PrimaryAccountChangeEvent& event_details) { + const CoreAccountInfo& account_info = + event_details.GetCurrentState().primary_account; + for (auto& observer : observer_list_) { observer.OnUnconsentedPrimaryAccountChanged(account_info); + observer.OnPrimaryAccountChanged(event_details); + } } -void IdentityManager::GoogleSignedOut(const CoreAccountInfo& account_info) { +void IdentityManager::GoogleSignedOut( + const PrimaryAccountChangeEvent& event_details) { + const CoreAccountInfo& account_info = + event_details.GetPreviousState().primary_account; DCHECK(!HasPrimaryAccount()); DCHECK(!account_info.IsEmpty()); for (auto& observer : observer_list_) { @@ -509,6 +519,7 @@ for (auto& observer : observer_list_) { observer.OnPrimaryAccountCleared(account_info); + observer.OnPrimaryAccountChanged(event_details); } #if defined(OS_ANDROID)
diff --git a/components/signin/public/identity_manager/identity_manager.h b/components/signin/public/identity_manager/identity_manager.h index 307693b..ece5290 100644 --- a/components/signin/public/identity_manager/identity_manager.h +++ b/components/signin/public/identity_manager/identity_manager.h
@@ -75,14 +75,21 @@ Observer(const Observer&) = delete; Observer& operator=(const Observer&) = delete; + // Called when there is a change in the primary account or in the consent + // level for the primary account. + virtual void OnPrimaryAccountChanged( + const PrimaryAccountChangeEvent& event_details) {} + // Called when an account becomes the user's primary account. // This method is not called during a reauth. + // DEPRECATED: Use OnPrimaryAccountChanged() instead. virtual void OnPrimaryAccountSet( const CoreAccountInfo& primary_account_info) {} // Called when the user moves from having a primary account to no longer // having a primary account (note that the user may still have an // *unconsented* primary account after this event; see./README.md). + // DEPRECATED: Use OnPrimaryAccountChanged() instead. virtual void OnPrimaryAccountCleared( const CoreAccountInfo& previous_primary_account_info) {} @@ -106,6 +113,7 @@ // the identity manager does not have clear guarantees that that account // cannot change in one atomic operation (without getting cleared in the // mean-time). + // DEPRECATED: Use OnPrimaryAccountChanged() instead. virtual void OnUnconsentedPrimaryAccountChanged( const CoreAccountInfo& unconsented_primary_account_info) {} @@ -627,10 +635,11 @@ const CoreAccountId& account_id) const; // PrimaryAccountManager::Observer: - void GoogleSigninSucceeded(const CoreAccountInfo& account_info) override; + void GoogleSigninSucceeded( + const PrimaryAccountChangeEvent& event_details) override; void UnconsentedPrimaryAccountChanged( - const CoreAccountInfo& account_info) override; - void GoogleSignedOut(const CoreAccountInfo& account_info) override; + const PrimaryAccountChangeEvent& event_details) override; + void GoogleSignedOut(const PrimaryAccountChangeEvent& event_details) override; // ProfileOAuth2TokenServiceObserver: void OnRefreshTokenAvailable(const CoreAccountId& account_id) override;
diff --git a/components/signin/public/identity_manager/primary_account_change_event.cc b/components/signin/public/identity_manager/primary_account_change_event.cc new file mode 100644 index 0000000..890ef755 --- /dev/null +++ b/components/signin/public/identity_manager/primary_account_change_event.cc
@@ -0,0 +1,80 @@ +// Copyright 2020 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/signin/public/identity_manager/primary_account_change_event.h" + +namespace signin { + +PrimaryAccountChangeEvent::State::State() = default; + +PrimaryAccountChangeEvent::State::State(const State& other) = default; + +PrimaryAccountChangeEvent::State::State(CoreAccountInfo account_info, + ConsentLevel consent_level) + : primary_account(account_info), consent_level(consent_level) {} + +PrimaryAccountChangeEvent::State::~State() = default; + +PrimaryAccountChangeEvent::State& PrimaryAccountChangeEvent::State::operator=( + const State& other) = default; + +PrimaryAccountChangeEvent::PrimaryAccountChangeEvent() = default; + +PrimaryAccountChangeEvent::PrimaryAccountChangeEvent(State previous_state, + State current_state) + : previous_state_(previous_state), current_state_(current_state) {} + +PrimaryAccountChangeEvent::~PrimaryAccountChangeEvent() = default; + +PrimaryAccountChangeEvent::Type PrimaryAccountChangeEvent::GetEventTypeFor( + ConsentLevel consent_level) const { + if (previous_state_ == current_state_) + return Type::kNone; + + if (previous_state_.consent_level == ConsentLevel::kSync) { + // Cannot change the Sync account without signing out first. + DCHECK(previous_state_.primary_account == current_state_.primary_account || + current_state_.primary_account.IsEmpty()); + } + if (previous_state_.primary_account == current_state_.primary_account) { + // Cannot change the consent level for the empty account. + DCHECK(!previous_state_.primary_account.IsEmpty()); + } + + switch (consent_level) { + case ConsentLevel::kNotRequired: + if (previous_state_.primary_account != current_state_.primary_account) { + return current_state_.primary_account.IsEmpty() ? Type::kCleared + : Type::kSet; + } + return Type::kNone; + case ConsentLevel::kSync: + if (previous_state_.consent_level != current_state_.consent_level) { + return current_state_.consent_level == ConsentLevel::kSync + ? Type::kSet + : Type::kCleared; + } + // Cannot change the Sync account without signing out first. + DCHECK_EQ(current_state_.consent_level, ConsentLevel::kNotRequired); + return Type::kNone; + } +} + +const PrimaryAccountChangeEvent::State& +PrimaryAccountChangeEvent::GetCurrentState() const { + return current_state_; +} + +const PrimaryAccountChangeEvent::State& +PrimaryAccountChangeEvent::GetPreviousState() const { + return previous_state_; +} + +bool operator==(const PrimaryAccountChangeEvent::State& lhs, + const PrimaryAccountChangeEvent::State& rhs) { + return lhs.primary_account == rhs.primary_account && + lhs.consent_level == rhs.consent_level; +} + +} // namespace signin \ No newline at end of file
diff --git a/components/signin/public/identity_manager/primary_account_change_event.h b/components/signin/public/identity_manager/primary_account_change_event.h new file mode 100644 index 0000000..8ca54ae --- /dev/null +++ b/components/signin/public/identity_manager/primary_account_change_event.h
@@ -0,0 +1,60 @@ +// Copyright 2020 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_SIGNIN_PUBLIC_IDENTITY_MANAGER_PRIMARY_ACCOUNT_CHANGE_EVENT_H_ +#define COMPONENTS_SIGNIN_PUBLIC_IDENTITY_MANAGER_PRIMARY_ACCOUNT_CHANGE_EVENT_H_ + +#include "components/signin/public/identity_manager/account_info.h" +#include "components/signin/public/identity_manager/consent_level.h" + +namespace signin { + +class PrimaryAccountChangeEvent { + public: + // Used to denote the type of the change event. + enum class Type { + // No change. + kNone = 0, + // Primary account set or changed. + kSet, + // Primary account cleared. + kCleared + }; + + struct State { + State(); + State(const State& other); + State(CoreAccountInfo account_info, ConsentLevel consent_level); + ~State(); + + State& operator=(const State& other); + + CoreAccountInfo primary_account; + ConsentLevel consent_level = ConsentLevel::kNotRequired; + }; + + PrimaryAccountChangeEvent(); + PrimaryAccountChangeEvent(State previous_state, State current_state); + ~PrimaryAccountChangeEvent(); + + // Returns primary account change event type for the corresponding + // consent_level. There can be 3 different event types. + // kNone - No change in primary account for the given consent_level. + // kSet - A new primary account is set or changed for the given consent_level. + // kCleared - The primary account set for the consent level is cleared. + Type GetEventTypeFor(ConsentLevel consent_level) const; + + const State& GetPreviousState() const; + const State& GetCurrentState() const; + + private: + State previous_state_, current_state_; +}; + +bool operator==(const PrimaryAccountChangeEvent::State& lhs, + const PrimaryAccountChangeEvent::State& rhs); + +} // namespace signin + +#endif // COMPONENTS_SIGNIN_PUBLIC_IDENTITY_MANAGER_PRIMARY_ACCOUNT_CHANGE_EVENT_H_
diff --git a/components/signin/public/identity_manager/primary_account_change_event_unittest.cc b/components/signin/public/identity_manager/primary_account_change_event_unittest.cc new file mode 100644 index 0000000..33866c8 --- /dev/null +++ b/components/signin/public/identity_manager/primary_account_change_event_unittest.cc
@@ -0,0 +1,98 @@ +// Copyright 2020 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/signin/public/identity_manager/primary_account_change_event.h" +#include "components/signin/public/identity_manager/consent_level.h" +#include "google_apis/gaia/core_account_id.h" +#include "testing/gtest/include/gtest/gtest.h" + +using signin::ConsentLevel; +using signin::PrimaryAccountChangeEvent; +using Type = signin::PrimaryAccountChangeEvent::Type; +using State = signin::PrimaryAccountChangeEvent::State; + +class PrimaryAccountChangeEventTest : public testing::Test { + public: + PrimaryAccountChangeEventTest() { + CoreAccountInfo account_info1 = GetCoreAccountInfoFrom("account1@test.com"); + CoreAccountInfo account_info2 = GetCoreAccountInfoFrom("account2@test.com"); + + empty_not_required_ = State(CoreAccountInfo(), ConsentLevel::kNotRequired); + account1_not_required_ = State(account_info1, ConsentLevel::kNotRequired); + account2_not_required_ = State(account_info2, ConsentLevel::kNotRequired); + account1_sync_ = State(account_info1, ConsentLevel::kSync); + account2_sync_ = State(account_info2, ConsentLevel::kSync); + } + + State empty_not_required_; + State account1_not_required_; + State account2_not_required_; + State account1_sync_; + State account2_sync_; + + private: + CoreAccountInfo GetCoreAccountInfoFrom(const char* account_name) { + CoreAccountInfo account_info; + account_info.account_id = CoreAccountId(account_name); + account_info.gaia = account_info.email = account_name; + + return account_info; + } +}; + +TEST_F(PrimaryAccountChangeEventTest, NoStateChange) { + PrimaryAccountChangeEvent event(empty_not_required_, empty_not_required_); + EXPECT_EQ(Type::kNone, event.GetEventTypeFor(ConsentLevel::kNotRequired)); + EXPECT_EQ(Type::kNone, event.GetEventTypeFor(ConsentLevel::kSync)); + + event = + PrimaryAccountChangeEvent(account1_not_required_, account1_not_required_); + EXPECT_EQ(Type::kNone, event.GetEventTypeFor(ConsentLevel::kNotRequired)); + EXPECT_EQ(Type::kNone, event.GetEventTypeFor(ConsentLevel::kSync)); + + event = PrimaryAccountChangeEvent(account1_sync_, account1_sync_); + EXPECT_EQ(Type::kNone, event.GetEventTypeFor(ConsentLevel::kNotRequired)); + EXPECT_EQ(Type::kNone, event.GetEventTypeFor(ConsentLevel::kSync)); +} + +TEST_F(PrimaryAccountChangeEventTest, + ConsentLevelChangeFromNotRequiredToNotRequired) { + PrimaryAccountChangeEvent event(empty_not_required_, account1_not_required_); + EXPECT_EQ(Type::kSet, event.GetEventTypeFor(ConsentLevel::kNotRequired)); + EXPECT_EQ(Type::kNone, event.GetEventTypeFor(ConsentLevel::kSync)); + + event = + PrimaryAccountChangeEvent(account1_not_required_, account2_not_required_); + EXPECT_EQ(Type::kSet, event.GetEventTypeFor(ConsentLevel::kNotRequired)); + EXPECT_EQ(Type::kNone, event.GetEventTypeFor(ConsentLevel::kSync)); + + event = + PrimaryAccountChangeEvent(account1_not_required_, empty_not_required_); + EXPECT_EQ(Type::kCleared, event.GetEventTypeFor(ConsentLevel::kNotRequired)); + EXPECT_EQ(Type::kNone, event.GetEventTypeFor(ConsentLevel::kSync)); +} + +TEST_F(PrimaryAccountChangeEventTest, ConsentLevelChangeFromNotRequiredToSync) { + PrimaryAccountChangeEvent event(empty_not_required_, account1_sync_); + EXPECT_EQ(Type::kSet, event.GetEventTypeFor(ConsentLevel::kNotRequired)); + EXPECT_EQ(Type::kSet, event.GetEventTypeFor(ConsentLevel::kSync)); + + event = PrimaryAccountChangeEvent(account1_not_required_, account1_sync_); + EXPECT_EQ(Type::kNone, event.GetEventTypeFor(ConsentLevel::kNotRequired)); + EXPECT_EQ(Type::kSet, event.GetEventTypeFor(ConsentLevel::kSync)); + + event = PrimaryAccountChangeEvent(account1_not_required_, account2_sync_); + EXPECT_EQ(Type::kSet, event.GetEventTypeFor(ConsentLevel::kNotRequired)); + EXPECT_EQ(Type::kSet, event.GetEventTypeFor(ConsentLevel::kSync)); +} + +TEST_F(PrimaryAccountChangeEventTest, ConsentLevelChangeFromSyncToNotRequired) { + PrimaryAccountChangeEvent event(account1_sync_, account1_not_required_); + EXPECT_EQ(Type::kNone, event.GetEventTypeFor(ConsentLevel::kNotRequired)); + EXPECT_EQ(Type::kCleared, event.GetEventTypeFor(ConsentLevel::kSync)); + + event = PrimaryAccountChangeEvent(account1_sync_, empty_not_required_); + EXPECT_EQ(Type::kCleared, event.GetEventTypeFor(ConsentLevel::kNotRequired)); + EXPECT_EQ(Type::kCleared, event.GetEventTypeFor(ConsentLevel::kSync)); +}
diff --git a/components/subresource_filter/content/browser/BUILD.gn b/components/subresource_filter/content/browser/BUILD.gn index bbb65761..5179bb69 100644 --- a/components/subresource_filter/content/browser/BUILD.gn +++ b/components/subresource_filter/content/browser/BUILD.gn
@@ -14,6 +14,8 @@ "content_activation_list_utils.h", "content_subresource_filter_throttle_manager.cc", "content_subresource_filter_throttle_manager.h", + "devtools_interaction_tracker.cc", + "devtools_interaction_tracker.h", "navigation_console_logger.cc", "navigation_console_logger.h", "page_load_statistics.cc",
diff --git a/components/subresource_filter/content/browser/devtools_interaction_tracker.cc b/components/subresource_filter/content/browser/devtools_interaction_tracker.cc new file mode 100644 index 0000000..fd6c9feb --- /dev/null +++ b/components/subresource_filter/content/browser/devtools_interaction_tracker.cc
@@ -0,0 +1,25 @@ +// Copyright 2020 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/subresource_filter/content/browser/devtools_interaction_tracker.h" + +#include "components/subresource_filter/content/browser/content_subresource_filter_throttle_manager.h" + +namespace subresource_filter { + +DevtoolsInteractionTracker::DevtoolsInteractionTracker( + content::WebContents* web_contents) {} + +DevtoolsInteractionTracker::~DevtoolsInteractionTracker() = default; + +void DevtoolsInteractionTracker::ToggleForceActivation(bool force_activation) { + if (!activated_via_devtools_ && force_activation) + ContentSubresourceFilterThrottleManager::LogAction( + SubresourceFilterAction::kForcedActivationEnabled); + activated_via_devtools_ = force_activation; +} + +WEB_CONTENTS_USER_DATA_KEY_IMPL(DevtoolsInteractionTracker) + +} // namespace subresource_filter
diff --git a/components/subresource_filter/content/browser/devtools_interaction_tracker.h b/components/subresource_filter/content/browser/devtools_interaction_tracker.h new file mode 100644 index 0000000..85481aa --- /dev/null +++ b/components/subresource_filter/content/browser/devtools_interaction_tracker.h
@@ -0,0 +1,45 @@ +// Copyright 2020 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_SUBRESOURCE_FILTER_CONTENT_BROWSER_DEVTOOLS_INTERACTION_TRACKER_H_ +#define COMPONENTS_SUBRESOURCE_FILTER_CONTENT_BROWSER_DEVTOOLS_INTERACTION_TRACKER_H_ + +#include "content/public/browser/web_contents_user_data.h" + +namespace subresource_filter { + +// Can be used to track whether forced activation has been set by devtools +// within a given WebContents. +// Scoped to the lifetime of a WebContents. +class DevtoolsInteractionTracker + : public content::WebContentsUserData<DevtoolsInteractionTracker> { + public: + explicit DevtoolsInteractionTracker(content::WebContents* web_contents); + ~DevtoolsInteractionTracker() override; + + DevtoolsInteractionTracker(const DevtoolsInteractionTracker&) = delete; + DevtoolsInteractionTracker& operator=(const DevtoolsInteractionTracker&) = + delete; + + // Should be called by devtools in response to a protocol command to enable ad + // blocking in this WebContents. Should only persist while devtools is + // attached. + void ToggleForceActivation(bool force_activation); + + bool activated_via_devtools() { return activated_via_devtools_; } + + private: + friend class content::WebContentsUserData<DevtoolsInteractionTracker>; + + // Corresponds to a devtools command which triggers filtering on all page + // loads. We must be careful to ensure this boolean does not persist after the + // devtools window is closed, which should be handled by the devtools system. + bool activated_via_devtools_ = false; + + WEB_CONTENTS_USER_DATA_KEY_DECL(); +}; + +} // namespace subresource_filter + +#endif // COMPONENTS_SUBRESOURCE_FILTER_CONTENT_BROWSER_DEVTOOLS_INTERACTION_TRACKER_H_
diff --git a/components/subresource_filter/content/browser/subresource_filter_safe_browsing_activation_throttle.cc b/components/subresource_filter/content/browser/subresource_filter_safe_browsing_activation_throttle.cc index 4d1124f6..3f444aa 100644 --- a/components/subresource_filter/content/browser/subresource_filter_safe_browsing_activation_throttle.cc +++ b/components/subresource_filter/content/browser/subresource_filter_safe_browsing_activation_throttle.cc
@@ -15,6 +15,7 @@ #include "base/trace_event/trace_event.h" #include "base/trace_event/traced_value.h" #include "components/subresource_filter/content/browser/content_activation_list_utils.h" +#include "components/subresource_filter/content/browser/devtools_interaction_tracker.h" #include "components/subresource_filter/content/browser/navigation_console_logger.h" #include "components/subresource_filter/content/browser/subresource_filter_client.h" #include "components/subresource_filter/content/browser/subresource_filter_observer_manager.h" @@ -194,8 +195,17 @@ activation_level = mojom::ActivationLevel::kDisabled; } + auto* devtools_interaction_tracker = + DevtoolsInteractionTracker::FromWebContents( + navigation_handle()->GetWebContents()); + + if (devtools_interaction_tracker && + devtools_interaction_tracker->activated_via_devtools()) { + activation_level = mojom::ActivationLevel::kEnabled; + activation_decision = ActivationDecision::FORCED_ACTIVATION; + } + // Let the embedder get the last word when it comes to activation level. - // TODO(csharrison): Move all ActivationDecision code to the embedder. activation_level = client_->OnPageActivationComputed( navigation_handle(), activation_level, &activation_decision);
diff --git a/components/subresource_filter/content/browser/subresource_filter_safe_browsing_activation_throttle_unittest.cc b/components/subresource_filter/content/browser/subresource_filter_safe_browsing_activation_throttle_unittest.cc index a53efc30..08f1cc5 100644 --- a/components/subresource_filter/content/browser/subresource_filter_safe_browsing_activation_throttle_unittest.cc +++ b/components/subresource_filter/content/browser/subresource_filter_safe_browsing_activation_throttle_unittest.cc
@@ -22,6 +22,7 @@ #include "components/safe_browsing/core/db/database_manager.h" #include "components/safe_browsing/core/db/test_database_manager.h" #include "components/subresource_filter/content/browser/content_subresource_filter_throttle_manager.h" +#include "components/subresource_filter/content/browser/devtools_interaction_tracker.h" #include "components/subresource_filter/content/browser/fake_safe_browsing_database_manager.h" #include "components/subresource_filter/content/browser/subresource_filter_client.h" #include "components/subresource_filter/content/browser/subresource_filter_observer_test_utils.h" @@ -66,6 +67,7 @@ "SubresourceFilter.SafeBrowsing.TotalCheckTime"; const char kActivationListHistogram[] = "SubresourceFilter.PageLoad.ActivationList"; +const char kSubresourceFilterActionsHistogram[] = "SubresourceFilter.Actions2"; class MockSubresourceFilterClient : public SubresourceFilterClient { public: @@ -87,7 +89,6 @@ } MOCK_METHOD0(ShowNotification, void()); - MOCK_METHOD0(ForceActivationInCurrentWebContents, bool()); MOCK_METHOD2(OnAdsViolationTriggered, void(content::RenderFrameHost*, subresource_filter::mojom::AdsViolation)); @@ -720,6 +721,63 @@ } } +TEST_F(SubresourceFilterSafeBrowsingActivationThrottleTest, + ToggleForceActivation) { + auto* web_contents = RenderViewHostTestHarness::web_contents(); + DevtoolsInteractionTracker::CreateForWebContents(web_contents); + auto* devtools_interaction_tracker = + DevtoolsInteractionTracker::FromWebContents(web_contents); + + base::HistogramTester histogram_tester; + const GURL url("https://example.test/"); + + // Navigate initially, should be no activation. + SimulateNavigateAndCommit({url}, main_rfh()); + EXPECT_CALL(*client(), ShowNotification()).Times(0); + EXPECT_TRUE(CreateAndNavigateDisallowedSubframe(main_rfh())); + + // Simulate opening devtools and forcing activation. + devtools_interaction_tracker->ToggleForceActivation(true); + histogram_tester.ExpectBucketCount( + kSubresourceFilterActionsHistogram, + subresource_filter::SubresourceFilterAction::kForcedActivationEnabled, 1); + + SimulateNavigateAndCommit({url}, main_rfh()); + EXPECT_CALL(*client(), ShowNotification()).Times(1); + EXPECT_FALSE(CreateAndNavigateDisallowedSubframe(main_rfh())); + + histogram_tester.ExpectBucketCount( + "SubresourceFilter.PageLoad.ActivationDecision", + subresource_filter::ActivationDecision::FORCED_ACTIVATION, 1); + + // Simulate closing devtools. + devtools_interaction_tracker->ToggleForceActivation(false); + + SimulateNavigateAndCommit({url}, main_rfh()); + EXPECT_TRUE(CreateAndNavigateDisallowedSubframe(main_rfh())); + histogram_tester.ExpectBucketCount( + kSubresourceFilterActionsHistogram, + subresource_filter::SubresourceFilterAction::kForcedActivationEnabled, 1); +} + +TEST_F(SubresourceFilterSafeBrowsingActivationThrottleTest, + ToggleOffForceActivation_AfterCommit) { + auto* web_contents = RenderViewHostTestHarness::web_contents(); + DevtoolsInteractionTracker::CreateForWebContents(web_contents); + auto* devtools_interaction_tracker = + DevtoolsInteractionTracker::FromWebContents(web_contents); + + base::HistogramTester histogram_tester; + devtools_interaction_tracker->ToggleForceActivation(true); + const GURL url("https://example.test/"); + SimulateNavigateAndCommit({url}, main_rfh()); + devtools_interaction_tracker->ToggleForceActivation(false); + + // Resource should be disallowed, since navigation commit had activation. + EXPECT_CALL(*client(), ShowNotification()).Times(1); + EXPECT_FALSE(CreateAndNavigateDisallowedSubframe(main_rfh())); +} + TEST_P(SubresourceFilterSafeBrowsingActivationThrottleScopeTest, ActivateForScopeType) { const ActivationScopeTestData& test_data = GetParam();
diff --git a/components/sync/base/user_selectable_type.cc b/components/sync/base/user_selectable_type.cc index b82e5dd8..2085c746 100644 --- a/components/sync/base/user_selectable_type.cc +++ b/components/sync/base/user_selectable_type.cc
@@ -196,13 +196,6 @@ return GetUserSelectableTypeInfo(type).canonical_model_type; } -int UserSelectableTypeToHistogramInt(UserSelectableType type) { - // TODO(crbug.com/1007293): Use ModelTypeHistogramValue instead of casting to - // int. - return static_cast<int>( - ModelTypeHistogramValue(UserSelectableTypeToCanonicalModelType(type))); -} - #if BUILDFLAG(IS_CHROMEOS_ASH) const char* GetUserSelectableOsTypeName(UserSelectableOsType type) { return GetUserSelectableOsTypeInfo(type).type_name;
diff --git a/components/sync/base/user_selectable_type.h b/components/sync/base/user_selectable_type.h index 2b918df..629b877 100644 --- a/components/sync/base/user_selectable_type.h +++ b/components/sync/base/user_selectable_type.h
@@ -43,11 +43,6 @@ ModelTypeSet UserSelectableTypeToAllModelTypes(UserSelectableType type); ModelType UserSelectableTypeToCanonicalModelType(UserSelectableType type); -int UserSelectableTypeToHistogramInt(UserSelectableType type); - -constexpr int UserSelectableTypeHistogramNumEntries() { - return static_cast<int>(ModelType::NUM_ENTRIES); -} #if BUILDFLAG(IS_CHROMEOS_ASH) // Chrome OS provides a separate UI with sync controls for OS data types. Note
diff --git a/components/sync/driver/glue/sync_engine_backend.cc b/components/sync/driver/glue/sync_engine_backend.cc index 9910e61..d6dd6d2 100644 --- a/components/sync/driver/glue/sync_engine_backend.cc +++ b/components/sync/driver/glue/sync_engine_backend.cc
@@ -196,10 +196,8 @@ << invalidation.version() << ", last seen version was " << last_invalidation->second; redundant_invalidation = true; - // TODO(crbug.com/1158476): ModelTypeHistogramValue() should be used instead - // of |type|, this is incorrect. Deprecate and add a new correct histogram. - UMA_HISTOGRAM_ENUMERATION("Sync.RedundantInvalidationPerModelType", type, - static_cast<int>(syncer::ModelType::NUM_ENTRIES)); + UMA_HISTOGRAM_ENUMERATION("Sync.RedundantInvalidationPerModelType2", + ModelTypeHistogramValue(type)); } return !fcm_invalidation && redundant_invalidation;
diff --git a/components/sync/driver/profile_sync_service.cc b/components/sync/driver/profile_sync_service.cc index 8c03a77..cadc4a8b 100644 --- a/components/sync/driver/profile_sync_service.cc +++ b/components/sync/driver/profile_sync_service.cc
@@ -1330,22 +1330,22 @@ kTransport = 1, kMaxValue = kTransport }; - UMA_HISTOGRAM_ENUMERATION("Sync.ConfigureDataTypeManagerOption", - use_transport_only_mode - ? ConfigureDataTypeManagerOption::kTransport - : ConfigureDataTypeManagerOption::kFeature); + base::UmaHistogramEnumeration("Sync.ConfigureDataTypeManagerOption", + use_transport_only_mode + ? ConfigureDataTypeManagerOption::kTransport + : ConfigureDataTypeManagerOption::kFeature); // Only if it's the full Sync feature, also record the user's choice of data // types. if (!use_transport_only_mode) { bool sync_everything = sync_prefs_.HasKeepEverythingSynced(); - UMA_HISTOGRAM_BOOLEAN("Sync.SyncEverything2", sync_everything); + base::UmaHistogramBoolean("Sync.SyncEverything2", sync_everything); if (!sync_everything) { for (UserSelectableType type : user_settings_->GetSelectedTypes()) { - UMA_HISTOGRAM_ENUMERATION("Sync.CustomSync2", - UserSelectableTypeToHistogramInt(type), - UserSelectableTypeHistogramNumEntries()); + ModelTypeForHistograms canonical_model_type = ModelTypeHistogramValue( + UserSelectableTypeToCanonicalModelType(type)); + base::UmaHistogramEnumeration("Sync.CustomSync3", canonical_model_type); } } }
diff --git a/components/sync/engine/net/http_bridge.cc b/components/sync/engine/net/http_bridge.cc index 0e69ef3..d416607b 100644 --- a/components/sync/engine/net/http_bridge.cc +++ b/components/sync/engine/net/http_bridge.cc
@@ -373,8 +373,6 @@ fetch_state_.request_succeeded ? fetch_state_.http_status_code : fetch_state_.net_error_code); - UMA_HISTOGRAM_LONG_TIMES("Sync.URLFetchTime", - fetch_state_.end_time - fetch_state_.start_time); // Use a real (non-debug) log to facilitate troubleshooting in the wild. VLOG(2) << "HttpBridge::OnURLFetchComplete for: " << final_url.spec();
diff --git a/components/sync_preferences/pref_model_associator.cc b/components/sync_preferences/pref_model_associator.cc index e2d12f9..2717618e 100644 --- a/components/sync_preferences/pref_model_associator.cc +++ b/components/sync_preferences/pref_model_associator.cc
@@ -17,7 +17,6 @@ #include "base/location.h" #include "base/logging.h" #include "base/memory/ptr_util.h" -#include "base/metrics/histogram_macros.h" #include "base/strings/utf_string_conversions.h" #include "base/values.h" #include "build/chromeos_buildflags.h" @@ -629,8 +628,6 @@ // done on a higher level. user_pref_store_->RemoveValue( pref_name, WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS); - UMA_HISTOGRAM_BOOLEAN("Sync.Preferences.ClearedLocalPrefOnTypeMismatch", - true); } } }
diff --git a/components/sync_preferences/pref_service_syncable_unittest.cc b/components/sync_preferences/pref_service_syncable_unittest.cc index 87eff95..e417c89 100644 --- a/components/sync_preferences/pref_service_syncable_unittest.cc +++ b/components/sync_preferences/pref_service_syncable_unittest.cc
@@ -16,7 +16,6 @@ #include "base/macros.h" #include "base/memory/ptr_util.h" #include "base/strings/utf_string_conversions.h" -#include "base/test/metrics/histogram_tester.h" #include "build/chromeos_buildflags.h" #include "components/pref_registry/pref_registry_syncable.h" #include "components/prefs/pref_notifier_impl.h" @@ -637,7 +636,6 @@ }; TEST_F(PrefServiceSyncableMergeTest, RegisterShouldClearTypeMismatchingData) { - base::HistogramTester histogram_tester; const std::string pref_name = "testing.pref"; user_prefs_->SetString(pref_name, "string_value"); ASSERT_TRUE(user_prefs_->GetValue(pref_name, nullptr)); @@ -653,8 +651,6 @@ EXPECT_TRUE(GetPreferenceValue(pref_name).GetList().empty()); EXPECT_FALSE(user_prefs_->GetValue(pref_name, nullptr)); - histogram_tester.ExpectBucketCount( - "Sync.Preferences.ClearedLocalPrefOnTypeMismatch", true, 1); prefs_.RemoveSyncedPrefObserver(pref_name, &observer); }
diff --git a/content/browser/devtools/devtools_video_consumer_browsertest.cc b/content/browser/devtools/devtools_video_consumer_browsertest.cc index f9227e57..50d131e 100644 --- a/content/browser/devtools/devtools_video_consumer_browsertest.cc +++ b/content/browser/devtools/devtools_video_consumer_browsertest.cc
@@ -87,7 +87,7 @@ // Tests that setting new frame dimensions via SetMinAndMaxFrameSizes // produces frames of the new dimensions. IN_PROC_BROWSER_TEST_F(DevToolsVideoConsumerTest, - SetMinAndMaxFramesChangesDimensions) { + DISABLED_SetMinAndMaxFramesChangesDimensions) { ASSERT_TRUE(embedded_test_server()->Start()); // Complete navigation to a page and then start capture. Since navigation is
diff --git a/content/browser/renderer_host/render_frame_host_impl.cc b/content/browser/renderer_host/render_frame_host_impl.cc index 1b892f9..6c0bb3d6 100644 --- a/content/browser/renderer_host/render_frame_host_impl.cc +++ b/content/browser/renderer_host/render_frame_host_impl.cc
@@ -8882,25 +8882,7 @@ // renderer one. The browser will just "push" the correct value. if (navigation_request->state() >= NavigationRequest::NavigationState::WILL_PROCESS_RESPONSE) { - if (params.sandbox_flags != navigation_request->SandboxFlagsToCommit()) { - DCHECK(false); - - base::debug::ScopedCrashKeyString scoped_url( - base::debug::AllocateCrashKeyString( - "url", base::debug::CrashKeySize::Size256), - params.url.possibly_invalid_spec()); - base::debug::ScopedCrashKeyString scoped_sandbox( - base::debug::AllocateCrashKeyString( - "sandbox", base::debug::CrashKeySize::Size256), - base::StringPrintf( - "%u, %u", uint32_t(params.sandbox_flags), - uint32_t(navigation_request->SandboxFlagsToCommit()))); - base::debug::SetCrashKeyString( - base::debug::AllocateCrashKeyString( - "is_main_frame", base::debug::CrashKeySize::Size32), - frame_tree_node_->IsMainFrame() ? "true" : "false"); - base::debug::DumpWithoutCrashing(); - } + DCHECK_EQ(params.sandbox_flags, navigation_request->SandboxFlagsToCommit()); } coep_reporter_ = navigation_request->TakeCoepReporter();
diff --git a/content/browser/webid/federated_auth_request_impl.cc b/content/browser/webid/federated_auth_request_impl.cc index 8fa5af5..7366e180 100644 --- a/content/browser/webid/federated_auth_request_impl.cc +++ b/content/browser/webid/federated_auth_request_impl.cc
@@ -116,7 +116,11 @@ return; } case IdpNetworkRequestManager::FetchStatus::kFetchError: { - CompleteRequest(RequestIdTokenStatus::kError, ""); + CompleteRequest(RequestIdTokenStatus::kErrorFetchingWellKnown, ""); + return; + } + case IdpNetworkRequestManager::FetchStatus::kInvalidResponseError: { + CompleteRequest(RequestIdTokenStatus::kErrorInvalidWellKnown, ""); return; } case IdpNetworkRequestManager::FetchStatus::kSuccess: { @@ -187,7 +191,11 @@ return; } case IdpNetworkRequestManager::SigninResponse::kSigninError: { - CompleteRequest(RequestIdTokenStatus::kError, ""); + CompleteRequest(RequestIdTokenStatus::kErrorFetchingSignin, ""); + return; + } + case IdpNetworkRequestManager::SigninResponse::kInvalidResponseError: { + CompleteRequest(RequestIdTokenStatus::kErrorInvalidSigninResponse, ""); return; } }
diff --git a/content/browser/webid/idp_network_request_manager.cc b/content/browser/webid/idp_network_request_manager.cc index 4117e73..5f0d5cc 100644 --- a/content/browser/webid/idp_network_request_manager.cc +++ b/content/browser/webid/idp_network_request_manager.cc
@@ -230,7 +230,7 @@ data_decoder::DataDecoder::ValueOrError result) { if (!result.value) { std::move(idp_well_known_callback_) - .Run(FetchStatus::kFetchError, std::string()); + .Run(FetchStatus::kInvalidResponseError, std::string()); return; } @@ -238,7 +238,7 @@ if (!response.is_dict()) { std::move(idp_well_known_callback_) - .Run(FetchStatus::kFetchError, std::string()); + .Run(FetchStatus::kInvalidResponseError, std::string()); return; } @@ -246,7 +246,7 @@ if (!idp_endpoint || !idp_endpoint->is_string()) { std::move(idp_well_known_callback_) - .Run(FetchStatus::kFetchError, std::string()); + .Run(FetchStatus::kInvalidResponseError, std::string()); return; } @@ -278,7 +278,7 @@ data_decoder::DataDecoder::ValueOrError result) { if (!result.value) { std::move(signin_request_callback_) - .Run(SigninResponse::kSigninError, std::string()); + .Run(SigninResponse::kInvalidResponseError, std::string()); return; } @@ -286,7 +286,7 @@ if (!response.is_dict()) { std::move(signin_request_callback_) - .Run(SigninResponse::kSigninError, std::string()); + .Run(SigninResponse::kInvalidResponseError, std::string()); return; } @@ -302,7 +302,7 @@ bool both_present = signin_url_present && token_present; if (!(signin_url_present || token_present) || both_present) { std::move(signin_request_callback_) - .Run(SigninResponse::kSigninError, std::string()); + .Run(SigninResponse::kInvalidResponseError, std::string()); return; }
diff --git a/content/browser/webid/idp_network_request_manager.h b/content/browser/webid/idp_network_request_manager.h index dbf7958..2833ba1 100644 --- a/content/browser/webid/idp_network_request_manager.h +++ b/content/browser/webid/idp_network_request_manager.h
@@ -54,12 +54,14 @@ kSuccess, kWebIdNotSupported, kFetchError, + kInvalidResponseError, }; enum class SigninResponse { kLoadIdp, kTokenGranted, kSigninError, + kInvalidResponseError, }; using FetchWellKnownCallback =
diff --git a/content/test/data/accessibility/html/img-expected-android.txt b/content/test/data/accessibility/html/img-expected-android.txt index c58bed9..75a396a 100644 --- a/content/test/data/accessibility/html/img-expected-android.txt +++ b/content/test/data/accessibility/html/img-expected-android.txt
@@ -3,4 +3,6 @@ ++++android.widget.Image role_description='graphic' has_image name='pipe' ++++android.widget.TextView name=' ' ++++android.widget.TextView name=' ' -++++android.widget.Image role_description='graphic' has_image name=' ' \ No newline at end of file +++++android.widget.Image role_description='graphic' has_image name=' ' +++++android.widget.TextView name=' ' +++++android.widget.Image role_description='graphic' has_image name='SVG face'
diff --git a/content/test/data/accessibility/html/img-expected-auralinux.txt b/content/test/data/accessibility/html/img-expected-auralinux.txt index fc193e0..715f68f 100644 --- a/content/test/data/accessibility/html/img-expected-auralinux.txt +++ b/content/test/data/accessibility/html/img-expected-auralinux.txt
@@ -4,3 +4,5 @@ ++++[static] name=' ' ++++[static] name=' ' ++++[image] name=' ' xml-roles:img +++++[static] name=' ' +++++[image] name='SVG face' xml-roles:img
diff --git a/content/test/data/accessibility/html/img-expected-blink.txt b/content/test/data/accessibility/html/img-expected-blink.txt index 98185c0e..c90e4cd 100644 --- a/content/test/data/accessibility/html/img-expected-blink.txt +++ b/content/test/data/accessibility/html/img-expected-blink.txt
@@ -7,3 +7,5 @@ ++++++staticText name=' ' ++++++++inlineTextBox name=' ' ++++++image name=' ' +++++++staticText name=' ' +++++++image name='SVG face'
diff --git a/content/test/data/accessibility/html/img-expected-mac.txt b/content/test/data/accessibility/html/img-expected-mac.txt index bb9aa663..5f952574 100644 --- a/content/test/data/accessibility/html/img-expected-mac.txt +++ b/content/test/data/accessibility/html/img-expected-mac.txt
@@ -4,3 +4,5 @@ ++++AXStaticText AXValue=' ' ++++AXStaticText AXValue=' ' ++++AXImage AXDescription=' ' AXRoleDescription='image' +++++AXStaticText AXValue=' ' +++++AXImage AXDescription='SVG face' AXRoleDescription='image'
diff --git a/content/test/data/accessibility/html/img-expected-uia-win.txt b/content/test/data/accessibility/html/img-expected-uia-win.txt index e14113e..8a066b7 100644 --- a/content/test/data/accessibility/html/img-expected-uia-win.txt +++ b/content/test/data/accessibility/html/img-expected-uia-win.txt
@@ -4,3 +4,5 @@ ++++Text Name=' ' ++++Text Name=' ' ++++Image Name=' ' +++++Text Name=' ' +++++Image Name='SVG face'
diff --git a/content/test/data/accessibility/html/img-expected-win.txt b/content/test/data/accessibility/html/img-expected-win.txt index af254395..f8012a1 100644 --- a/content/test/data/accessibility/html/img-expected-win.txt +++ b/content/test/data/accessibility/html/img-expected-win.txt
@@ -4,3 +4,5 @@ ++++ROLE_SYSTEM_STATICTEXT name=' ' ++++ROLE_SYSTEM_STATICTEXT name=' ' ++++ROLE_SYSTEM_GRAPHIC name=' ' READONLY xml-roles:img +++++ROLE_SYSTEM_STATICTEXT name=' ' +++++ROLE_SYSTEM_GRAPHIC name='SVG face' READONLY xml-roles:img
diff --git a/content/test/data/accessibility/html/img.html b/content/test/data/accessibility/html/img.html index 39cea3a..33e904a7 100644 --- a/content/test/data/accessibility/html/img.html +++ b/content/test/data/accessibility/html/img.html
@@ -9,5 +9,6 @@ <img src="pipe.jpg" alt="pipe"> <img src="pipe.jpg" alt=""> <img src="pipe.jpg" alt=" "> + <img src="svg-face.svg" alt="SVG face"> </body> </html>
diff --git a/third_party/blink/web_tests/accessibility/resources/svg-face.svg b/content/test/data/accessibility/html/svg-face.svg similarity index 100% rename from third_party/blink/web_tests/accessibility/resources/svg-face.svg rename to content/test/data/accessibility/html/svg-face.svg
diff --git a/content/test/data/accessibility/html/svg-style-element-expected-blink.txt b/content/test/data/accessibility/html/svg-style-element-expected-blink.txt index e874f9c3..c8654017 100644 --- a/content/test/data/accessibility/html/svg-style-element-expected-blink.txt +++ b/content/test/data/accessibility/html/svg-style-element-expected-blink.txt
@@ -3,6 +3,5 @@ ++++genericContainer ignored ++++++genericContainer ++++++++button name='Kettle' -++++++++++presentational ++++++++++staticText name='Kettle' -++++++++++++inlineTextBox name='Kettle' +++++++++++++inlineTextBox name='Kettle' \ No newline at end of file
diff --git a/content/test/data/accessibility/html/svg-style-element-expected-mac.txt b/content/test/data/accessibility/html/svg-style-element-expected-mac.txt index 8c3fb3c..9d1f1ba 100644 --- a/content/test/data/accessibility/html/svg-style-element-expected-mac.txt +++ b/content/test/data/accessibility/html/svg-style-element-expected-mac.txt
@@ -1,5 +1,3 @@ AXWebArea ++AXGroup -++++AXButton AXTitle='Kettle' -++++++AXGroup -++++++AXStaticText AXValue='Kettle' +++++AXButton AXTitle='Kettle' \ No newline at end of file
diff --git a/content/test/data/accessibility/html/svg-style-element-expected-win.txt b/content/test/data/accessibility/html/svg-style-element-expected-win.txt index f39ecfaae..2025a8a3 100644 --- a/content/test/data/accessibility/html/svg-style-element-expected-win.txt +++ b/content/test/data/accessibility/html/svg-style-element-expected-win.txt
@@ -1,5 +1,3 @@ ROLE_SYSTEM_DOCUMENT READONLY FOCUSABLE ++IA2_ROLE_SECTION ++++ROLE_SYSTEM_PUSHBUTTON name='Kettle' FOCUSABLE -++++++ROLE_SYSTEM_PANE -++++++ROLE_SYSTEM_STATICTEXT name='Kettle'
diff --git a/google_apis/test/embedded_setup_chromeos.html b/google_apis/test/embedded_setup_chromeos.html index f99d8e73..c38684b 100644 --- a/google_apis/test/embedded_setup_chromeos.html +++ b/google_apis/test/embedded_setup_chromeos.html
@@ -61,19 +61,9 @@ passwordBytes: password, keyType: 'KEY_TYPE_PASSWORD_PLAIN'} }, '/'); - var services = document.getElementById("services").value; - if (services) { - services = JSON.parse(services); - if (!services) - services = "Failed to parse test services JSON."; - } else if (email.endsWith('@corp.example.com') || - email.endsWith('@example.test')) { - // SAML tests. - services = []; - } else { - services = "Services are not set for testing."; - } +}; +gaia.chromeOSLogin.sendUserInfo = function(services) { msg = { 'method': 'userInfo', 'services': services, @@ -124,11 +114,24 @@ } else if (!document.getElementById("page2").hidden) { var email = document.getElementById("identifier").value; var password = document.getElementById("password").value; + var services = document.getElementById("services").value; + if (services) { + services = JSON.parse(services); + if (!services) + services = "Failed to parse test services JSON."; + } else if (email.endsWith('@corp.example.com') || + email.endsWith('@example.test')) { + // SAML tests. + services = []; + } else { + services = "Services are not set for testing."; + } request = new XMLHttpRequest(); request.open('POST', '/_/embedded/signin/challenge', true); request.onreadystatechange = function() { if (request.readyState == 4 && request.status == 200) { + gaia.chromeOSLogin.sendUserInfo(services); history.pushState({}, "", window.location.pathname + "#close"); } };
diff --git a/ios/chrome/browser/passwords/ios_chrome_password_check_manager_unittest.mm b/ios/chrome/browser/passwords/ios_chrome_password_check_manager_unittest.mm index 5a110ebc..2826913 100644 --- a/ios/chrome/browser/passwords/ios_chrome_password_check_manager_unittest.mm +++ b/ios/chrome/browser/passwords/ios_chrome_password_check_manager_unittest.mm
@@ -108,7 +108,8 @@ CompromiseType compromise_type = CompromiseType::kLeaked) { return CompromisedCredentials( std::string(signon_realm), base::ASCIIToUTF16(username), - base::Time::Now() - time_since_creation, compromise_type, false); + base::Time::Now() - time_since_creation, compromise_type, + password_manager::IsMuted(false)); } PasswordForm MakeSavedPassword(
diff --git a/ios/chrome/browser/tabs/tab_helper_util.mm b/ios/chrome/browser/tabs/tab_helper_util.mm index 0fdf37c1..0880696e 100644 --- a/ios/chrome/browser/tabs/tab_helper_util.mm +++ b/ios/chrome/browser/tabs/tab_helper_util.mm
@@ -67,6 +67,7 @@ #import "ios/chrome/browser/ui/ui_feature_flags.h" #import "ios/chrome/browser/voice/voice_search_navigations_tab_helper.h" #import "ios/chrome/browser/web/blocked_popup_tab_helper.h" +#include "ios/chrome/browser/web/error_page_controller_bridge.h" #import "ios/chrome/browser/web/features.h" #import "ios/chrome/browser/web/font_size_tab_helper.h" #import "ios/chrome/browser/web/image_fetch_tab_helper.h" @@ -120,6 +121,7 @@ web_state); password_manager::WellKnownChangePasswordTabHelper::CreateForWebState( web_state); + ErrorPageControllerBridge::CreateForWebState(web_state); if (base::FeatureList::IsEnabled(web::features::kUseJSForErrorPage)) { InvalidUrlTabHelper::CreateForWebState(web_state);
diff --git a/ios/chrome/browser/ui/first_run/location_permissions_field_trial.cc b/ios/chrome/browser/ui/first_run/location_permissions_field_trial.cc index 3c401bd..c5c6ed1 100644 --- a/ios/chrome/browser/ui/first_run/location_permissions_field_trial.cc +++ b/ios/chrome/browser/ui/first_run/location_permissions_field_trial.cc
@@ -28,10 +28,10 @@ const char kDisabledGroup[] = "Disabled"; const char kDefaultGroup[] = "Default"; // Experiment IDs defined for the above field trial groups. -const variations::VariationID kDefaultTrialID = 3329331; -const variations::VariationID kDisabledTrialID = 3329332; -const variations::VariationID kLocationRemoveFirstRunPromptTrialID = 3329333; -const variations::VariationID kLocationFirstRunModalTrialID = 3329334; +const variations::VariationID kDefaultTrialID = 3329335; +const variations::VariationID kDisabledTrialID = 3329336; +const variations::VariationID kLocationRemoveFirstRunPromptTrialID = 3329337; +const variations::VariationID kLocationFirstRunModalTrialID = 3329338; // Default local state pref value. const int kDefaultPrefValue = -1;
diff --git a/ios/chrome/browser/ui/settings/password/password_issues_mediator_unittest.mm b/ios/chrome/browser/ui/settings/password/password_issues_mediator_unittest.mm index f80d841..7eca44a0 100644 --- a/ios/chrome/browser/ui/settings/password/password_issues_mediator_unittest.mm +++ b/ios/chrome/browser/ui/settings/password/password_issues_mediator_unittest.mm
@@ -58,7 +58,8 @@ base::StringPiece username) { return CompromisedCredentials(std::string(signon_realm), base::ASCIIToUTF16(username), base::Time::Now(), - CompromiseType::kLeaked, false); + CompromiseType::kLeaked, + password_manager::IsMuted(false)); } } // namespace
diff --git a/ios/chrome/browser/ui/settings/password/passwords_table_view_controller_unittest.mm b/ios/chrome/browser/ui/settings/password/passwords_table_view_controller_unittest.mm index 33ee823..15e52851 100644 --- a/ios/chrome/browser/ui/settings/password/passwords_table_view_controller_unittest.mm +++ b/ios/chrome/browser/ui/settings/password/passwords_table_view_controller_unittest.mm
@@ -235,7 +235,8 @@ base::StringPiece username) { return password_manager::CompromisedCredentials( std::string(signon_realm), base::ASCIIToUTF16(username), - base::Time::Now(), CompromiseType::kLeaked, false); + base::Time::Now(), CompromiseType::kLeaked, + password_manager::IsMuted(false)); } void AddCompromisedCredential1() {
diff --git a/ios/chrome/browser/ui/settings/safety_check/safety_check_mediator_unittest.mm b/ios/chrome/browser/ui/settings/safety_check/safety_check_mediator_unittest.mm index 3c0801bd..05381b2 100644 --- a/ios/chrome/browser/ui/settings/safety_check/safety_check_mediator_unittest.mm +++ b/ios/chrome/browser/ui/settings/safety_check/safety_check_mediator_unittest.mm
@@ -199,7 +199,8 @@ base::StringPiece username) { return password_manager::CompromisedCredentials( std::string(signon_realm), base::ASCIIToUTF16(username), - base::Time::Now(), CompromiseType::kLeaked, false); + base::Time::Now(), CompromiseType::kLeaked, + password_manager::IsMuted(false)); } TestPasswordStore& GetTestStore() {
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_strip/BUILD.gn b/ios/chrome/browser/ui/tab_switcher/tab_strip/BUILD.gn index 8bab8a6..2a7acb6 100644 --- a/ios/chrome/browser/ui/tab_switcher/tab_strip/BUILD.gn +++ b/ios/chrome/browser/ui/tab_switcher/tab_strip/BUILD.gn
@@ -41,6 +41,7 @@ "//ios/chrome/browser/tabs", "//ios/chrome/browser/ui/image_util", "//ios/chrome/browser/ui/tab_switcher", + "//ios/chrome/browser/ui/util", "//ios/chrome/browser/web:tab_id_tab_helper", "//ios/chrome/browser/web_state_list", "//ios/chrome/common/ui/colors",
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_strip/tab_strip_cell.h b/ios/chrome/browser/ui/tab_switcher/tab_strip/tab_strip_cell.h index b53ebdf..19ecfbe 100644 --- a/ios/chrome/browser/ui/tab_switcher/tab_strip/tab_strip_cell.h +++ b/ios/chrome/browser/ui/tab_switcher/tab_strip/tab_strip_cell.h
@@ -19,6 +19,9 @@ // and a close tab button. @interface TabStripCell : UICollectionViewCell +// The close button associated with this cell. +@property(nonatomic, strong) UIButton* closeButton; +// Title is displayed by this label. @property(nonatomic, strong) UILabel* titleLabel; // View for displaying the favicon. @property(nonatomic, strong) UIImageView* faviconView; @@ -27,6 +30,10 @@ @property(nonatomic, copy) NSString* itemIdentifier; // Delegate to inform the TabStrip on the cell. @property(nonatomic, weak) id<TabStripCellDelegate> delegate; +// YES if dark mode is needed for incognito on iOS 12 and less. +// iOS 13 there is no need to pick custom incognito assets because +// |overrideUserInterfaceStyle| is set to dark mode when in incognito. +@property(nonatomic) BOOL useIncognitoFallback; @end
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_strip/tab_strip_cell.mm b/ios/chrome/browser/ui/tab_switcher/tab_strip/tab_strip_cell.mm index 5c2433a..2729bac 100644 --- a/ios/chrome/browser/ui/tab_switcher/tab_strip/tab_strip_cell.mm +++ b/ios/chrome/browser/ui/tab_switcher/tab_strip/tab_strip_cell.mm
@@ -16,6 +16,7 @@ const CGFloat kTabBackgroundLeftCapInset = 34.0; const CGFloat kFaviconInset = 28; const CGFloat kTitleInset = 10.0; +const CGFloat kFontSize = 14.0; } // namespace @implementation TabStripCell @@ -26,50 +27,49 @@ UIImage* favicon = [[UIImage imageNamed:@"default_world_favicon"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; - UIImageView* faviconView = [[UIImageView alloc] initWithImage:favicon]; - faviconView.tintColor = [UIColor colorNamed:kGrey500Color]; - [self.contentView addSubview:faviconView]; - faviconView.translatesAutoresizingMaskIntoConstraints = NO; + _faviconView = [[UIImageView alloc] initWithImage:favicon]; + [self.contentView addSubview:_faviconView]; + _faviconView.translatesAutoresizingMaskIntoConstraints = NO; [NSLayoutConstraint activateConstraints:@[ - [faviconView.leadingAnchor + [_faviconView.leadingAnchor constraintEqualToAnchor:self.contentView.leadingAnchor constant:kFaviconInset], - [faviconView.centerYAnchor + [_faviconView.centerYAnchor constraintEqualToAnchor:self.contentView.centerYAnchor], ]]; UIImage* close = [[UIImage imageNamed:@"grid_cell_close_button"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; - UIButton* closeButton = [UIButton buttonWithType:UIButtonTypeCustom]; - [closeButton setImage:close forState:UIControlStateNormal]; - closeButton.tintColor = [UIColor colorNamed:kGrey500Color]; - [self.contentView addSubview:closeButton]; - closeButton.translatesAutoresizingMaskIntoConstraints = NO; + _closeButton = [UIButton buttonWithType:UIButtonTypeCustom]; + [_closeButton setImage:close forState:UIControlStateNormal]; + [self.contentView addSubview:_closeButton]; + _closeButton.translatesAutoresizingMaskIntoConstraints = NO; [NSLayoutConstraint activateConstraints:@[ - [closeButton.trailingAnchor + [_closeButton.trailingAnchor constraintEqualToAnchor:self.contentView.trailingAnchor constant:-kFaviconInset], - [closeButton.centerYAnchor + [_closeButton.centerYAnchor constraintEqualToAnchor:self.contentView.centerYAnchor], ]]; - [closeButton addTarget:self - action:@selector(closeButtonTapped:) - forControlEvents:UIControlEventTouchUpInside]; + [_closeButton addTarget:self + action:@selector(closeButtonTapped:) + forControlEvents:UIControlEventTouchUpInside]; - UILabel* titleLabel = [[UILabel alloc] init]; - [self.contentView addSubview:titleLabel]; - titleLabel.translatesAutoresizingMaskIntoConstraints = NO; + _titleLabel = [[UILabel alloc] init]; + _titleLabel.font = [UIFont systemFontOfSize:kFontSize + weight:UIFontWeightMedium]; + [self.contentView addSubview:_titleLabel]; + _titleLabel.translatesAutoresizingMaskIntoConstraints = NO; [NSLayoutConstraint activateConstraints:@[ - [titleLabel.leadingAnchor - constraintEqualToAnchor:faviconView.trailingAnchor + [_titleLabel.leadingAnchor + constraintEqualToAnchor:_faviconView.trailingAnchor constant:kTitleInset], - [titleLabel.trailingAnchor - constraintLessThanOrEqualToAnchor:closeButton.leadingAnchor + [_titleLabel.trailingAnchor + constraintLessThanOrEqualToAnchor:_closeButton.leadingAnchor constant:-kTitleInset], - [titleLabel.centerYAnchor - constraintEqualToAnchor:faviconView.centerYAnchor], + [_titleLabel.centerYAnchor + constraintEqualToAnchor:_faviconView.centerYAnchor], ]]; - self.titleLabel = titleLabel; } return self; } @@ -79,6 +79,7 @@ self.titleLabel.text = nil; self.itemIdentifier = nil; self.selected = NO; + self.faviconView = nil; } - (void)setupBackgroundViews { @@ -122,4 +123,35 @@ [self.delegate closeButtonTappedForCell:self]; } +- (void)setSelected:(BOOL)selected { + [super setSelected:selected]; + // Style the favicon tint color. + self.faviconView.tintColor = selected ? [UIColor colorNamed:kCloseButtonColor] + : [UIColor colorNamed:kGrey500Color]; + // Style the close button tint color. + self.closeButton.tintColor = selected ? [UIColor colorNamed:kCloseButtonColor] + : [UIColor colorNamed:kGrey500Color]; + // Style the title tint color. + self.titleLabel.textColor = selected ? [UIColor colorNamed:kTextPrimaryColor] + : [UIColor colorNamed:kGrey600Color]; + // These dark-theme specific colorsets should only be used for iOS 12 + // dark theme, as they will be removed along with iOS 12. + // TODO (crbug.com/981889): The following lines will be removed + // along with iOS 12 + if (self.useIncognitoFallback) { + // Style the favicon tint color. + self.faviconView.tintColor = + selected ? [UIColor colorNamed:kCloseButtonDarkColor] + : [UIColor colorNamed:kGrey500Color]; + // Style the close button tint color. + self.closeButton.tintColor = + selected ? [UIColor colorNamed:kCloseButtonDarkColor] + : [UIColor colorNamed:kGrey500Color]; + // Style the title tint color. + self.titleLabel.textColor = selected + ? [UIColor colorNamed:kTextPrimaryDarkColor] + : [UIColor colorNamed:kGrey600Color]; + } +} + @end
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_strip/tab_strip_consumer.h b/ios/chrome/browser/ui/tab_switcher/tab_strip/tab_strip_consumer.h index 8058faf..3e94535e 100644 --- a/ios/chrome/browser/ui/tab_switcher/tab_strip/tab_strip_consumer.h +++ b/ios/chrome/browser/ui/tab_switcher/tab_strip/tab_strip_consumer.h
@@ -12,6 +12,9 @@ // TabStripConsumer sets the current appearance of the TabStrip. @protocol TabStripConsumer +// YES if the state is incognito. +@property(nonatomic) BOOL isOffTheRecord; + // Tells the consumer to replace its current set of items with |items| and // update the selected item ID to be |selectedItemID|. It's an error to pass // an |items| array containing items without unique IDs.
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_strip/tab_strip_coordinator.mm b/ios/chrome/browser/ui/tab_switcher/tab_strip/tab_strip_coordinator.mm index f80713b7..aa827bd9 100644 --- a/ios/chrome/browser/ui/tab_switcher/tab_strip/tab_strip_coordinator.mm +++ b/ios/chrome/browser/ui/tab_switcher/tab_strip/tab_strip_coordinator.mm
@@ -45,6 +45,8 @@ self.browser->GetBrowserState()->IsOffTheRecord() ? UIUserInterfaceStyleDark : UIUserInterfaceStyleUnspecified; + self.tabStripViewController.isOffTheRecord = + self.browser->GetBrowserState()->IsOffTheRecord(); } self.mediator =
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_strip/tab_strip_mediator.mm b/ios/chrome/browser/ui/tab_switcher/tab_strip/tab_strip_mediator.mm index c69a594..c783d6d 100644 --- a/ios/chrome/browser/ui/tab_switcher/tab_strip/tab_strip_mediator.mm +++ b/ios/chrome/browser/ui/tab_switcher/tab_strip/tab_strip_mediator.mm
@@ -251,6 +251,9 @@ if (self.webStateList->count() > 0) { [self.consumer populateItems:CreateItems(self.webStateList) selectedItemID:GetActiveTabId(self.webStateList)]; + self.consumer.isOffTheRecord = self.webStateList->GetWebStateAt(0) + ->GetBrowserState() + ->IsOffTheRecord(); } }
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_strip/tab_strip_view_controller.mm b/ios/chrome/browser/ui/tab_switcher/tab_strip/tab_strip_view_controller.mm index fc03a4f..38e4fe2 100644 --- a/ios/chrome/browser/ui/tab_switcher/tab_strip/tab_strip_view_controller.mm +++ b/ios/chrome/browser/ui/tab_switcher/tab_strip/tab_strip_view_controller.mm
@@ -5,6 +5,8 @@ #import "ios/chrome/browser/ui/tab_switcher/tab_strip/tab_strip_view_controller.h" #import "base/allocator/partition_allocator/partition_alloc.h" +#import "base/ios/ios_util.h" +#import "base/mac/foundation_util.h" #import "ios/chrome/browser/ui/tab_switcher/tab_strip/tab_strip_cell.h" #import "ios/chrome/browser/ui/tab_switcher/tab_strip/tab_strip_mediator.h" #import "ios/chrome/browser/ui/tab_switcher/tab_strip/tab_strip_view_layout.h" @@ -47,6 +49,8 @@ @implementation TabStripViewController +@synthesize isOffTheRecord = _isOffTheRecord; + - (instancetype)init { TabStripViewLayout* layout = [[TabStripViewLayout alloc] init]; if (self = [super initWithCollectionViewLayout:layout]) { @@ -110,11 +114,14 @@ itemIndex = self.items.count - 1; TabSwitcherItem* item = self.items[itemIndex]; - TabStripCell* cell = (TabStripCell*)[collectionView + TabStripCell* cell = base::mac::ObjCCastStrict<TabStripCell>([collectionView dequeueReusableCellWithReuseIdentifier:kReuseIdentifier - forIndexPath:indexPath]; + forIndexPath:indexPath]); [self configureCell:cell withItem:item]; + cell.useIncognitoFallback = + self.isOffTheRecord && !base::ios::IsRunningOnIOS13OrLater(); + cell.selected = (self.selectedItemID == cell.itemIdentifier) ? YES : NO; return cell; } @@ -185,11 +192,19 @@ [self.collectionView deselectItemAtIndexPath:CreateIndexPath(self.selectedIndex) animated:YES]; + UICollectionViewCell* cell = [self.collectionView + cellForItemAtIndexPath:CreateIndexPath(self.selectedIndex)]; + cell.selected = NO; + self.selectedItemID = selectedItemID; + [self.collectionView selectItemAtIndexPath:CreateIndexPath(self.selectedIndex) animated:YES scrollPosition:UICollectionViewScrollPositionNone]; + cell = [self.collectionView + cellForItemAtIndexPath:CreateIndexPath(self.selectedIndex)]; + cell.selected = YES; [self orderBySelectedTab]; } @@ -212,6 +227,7 @@ if (cell.itemIdentifier == itemIdentifier) cell.faviconView.image = icon; }]; + cell.selected = (cell.itemIdentifier == self.selectedItemID) ? YES : NO; } }
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_strip/tab_strip_view_layout.mm b/ios/chrome/browser/ui/tab_switcher/tab_strip/tab_strip_view_layout.mm index 7c652390..b62a5b99 100644 --- a/ios/chrome/browser/ui/tab_switcher/tab_strip/tab_strip_view_layout.mm +++ b/ios/chrome/browser/ui/tab_switcher/tab_strip/tab_strip_view_layout.mm
@@ -4,6 +4,10 @@ #import "ios/chrome/browser/ui/tab_switcher/tab_strip/tab_strip_view_layout.h" +#import "base/numerics/ranges.h" +#import "ios/chrome/browser/ui/util/ui_util.h" +#import "ios/chrome/browser/ui/util/uikit_ui_util.h" + #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support." #endif @@ -11,19 +15,35 @@ namespace { // Tab dimensions. -const CGFloat kTabOverlapStacked = 32.0; -const CGFloat kMinTabWidthStacked = 200.0; +const CGFloat kTabOverlap = 32.0; +const CGFloat kNewTabOverlap = 13.0; +const CGFloat kMaxTabWidth = 265.0; +const CGFloat kMinTabWidth = 200.0; + +// The size of the new tab button. +const CGFloat kNewTabButtonWidth = 44; } // namespace +@interface TabStripViewLayout () + +// The current tab width. Recomputed whenever a tab is added or removed. +@property(nonatomic) CGFloat currentTabWidth; + +@end + @implementation TabStripViewLayout - (CGSize)collectionViewContentSize { UICollectionView* collection = self.collectionView; NSInteger num = [collection numberOfItemsInSection:0]; - CGFloat width = kMinTabWidthStacked * num; - width -= (num - 1) * kTabOverlapStacked; + CGFloat visibleSpace = [self tabStripVisibleSpace]; + _currentTabWidth = (visibleSpace + (kTabOverlap * (num - 1))) / num; + _currentTabWidth = + base::ClampToRange(_currentTabWidth, kMinTabWidth, kMaxTabWidth); + + CGFloat width = _currentTabWidth * num - (num - 1) * kTabOverlap; width = MAX(width, collection.bounds.size.width); return CGSizeMake(width, collection.bounds.size.height); } @@ -36,9 +56,9 @@ CGRect bounds = collection.bounds; // Calculating tab's length size depending on the number of tabs. - CGFloat x = indexPath.row * kMinTabWidthStacked; + CGFloat x = indexPath.row * _currentTabWidth; if (indexPath.row > 0) { - x -= (kTabOverlapStacked * indexPath.row); + x -= (kTabOverlap * indexPath.row); } x = MAX(x, bounds.origin.x); @@ -46,7 +66,7 @@ UICollectionViewLayoutAttributes* attr = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath]; attr.frame = - CGRectMake(x, bounds.origin.y, kMinTabWidthStacked, bounds.size.height); + CGRectMake(x, bounds.origin.y, _currentTabWidth, bounds.size.height); return attr; } @@ -85,4 +105,14 @@ return attr; } +#pragma mark - Private + +// The available space for the tabstrip which is the view width without newtab- +// button width. +- (CGFloat)tabStripVisibleSpace { + CGFloat availableSpace = CGRectGetWidth([self.collectionView bounds]) - + kNewTabButtonWidth + kNewTabOverlap; + return availableSpace; +} + @end
diff --git a/ios/chrome/browser/web/BUILD.gn b/ios/chrome/browser/web/BUILD.gn index 98afe52b..def75a7 100644 --- a/ios/chrome/browser/web/BUILD.gn +++ b/ios/chrome/browser/web/BUILD.gn
@@ -9,6 +9,8 @@ sources = [ "dom_altering_lock.h", "dom_altering_lock.mm", + "error_page_controller_bridge.h", + "error_page_controller_bridge.mm", "error_page_util.h", "error_page_util.mm", "font_size_tab_helper.h",
diff --git a/ios/chrome/browser/web/chrome_web_client.mm b/ios/chrome/browser/web/chrome_web_client.mm index 2f0b144..d5ab352 100644 --- a/ios/chrome/browser/web/chrome_web_client.mm +++ b/ios/chrome/browser/web/chrome_web_client.mm
@@ -29,6 +29,7 @@ #include "ios/chrome/browser/ssl/ios_ssl_error_handler.h" #import "ios/chrome/browser/ui/elements/windowed_container_view.h" #include "ios/chrome/browser/ui/ui_feature_flags.h" +#include "ios/chrome/browser/web/error_page_controller_bridge.h" #import "ios/chrome/browser/web/error_page_util.h" #include "ios/chrome/browser/web/features.h" #import "ios/components/security_interstitials/ios_blocking_page_tab_helper.h" @@ -378,6 +379,13 @@ } else { std::move(error_html_callback) .Run(GetErrorPage(url, error, is_post, is_off_the_record)); + ErrorPageControllerBridge* error_page_controller = + ErrorPageControllerBridge::FromWebState(web_state); + if (error_page_controller) { + // ErrorPageControllerBridge may not be created for web_state not attached + // to a tab. + error_page_controller->StartHandlingJavascriptCommands(); + } } }
diff --git a/ios/chrome/browser/web/chrome_web_client_unittest.mm b/ios/chrome/browser/web/chrome_web_client_unittest.mm index 191834e..f714a80 100644 --- a/ios/chrome/browser/web/chrome_web_client_unittest.mm +++ b/ios/chrome/browser/web/chrome_web_client_unittest.mm
@@ -27,6 +27,7 @@ #import "ios/chrome/browser/safe_browsing/safe_browsing_unsafe_resource_container.h" #import "ios/chrome/browser/ssl/captive_portal_detector_tab_helper.h" #import "ios/chrome/browser/ssl/captive_portal_detector_tab_helper_delegate.h" +#include "ios/chrome/browser/web/error_page_controller_bridge.h" #import "ios/chrome/browser/web/error_page_util.h" #include "ios/chrome/browser/web/features.h" #import "ios/components/security_interstitials/ios_blocking_page_tab_helper.h" @@ -187,6 +188,7 @@ page = error_html; }); web::FakeWebState web_state; + ErrorPageControllerBridge::CreateForWebState(&web_state); web_client.PrepareErrorPage(&web_state, GURL(kTestUrl), error, /*is_post=*/false, /*is_off_the_record=*/false, @@ -213,6 +215,7 @@ page = error_html; }); web::FakeWebState web_state; + ErrorPageControllerBridge::CreateForWebState(&web_state); web_client.PrepareErrorPage(&web_state, GURL(kTestUrl), error, /*is_post=*/true, /*is_off_the_record=*/false, @@ -239,6 +242,7 @@ page = error_html; }); web::FakeWebState web_state; + ErrorPageControllerBridge::CreateForWebState(&web_state); web_client.PrepareErrorPage(&web_state, GURL(kTestUrl), error, /*is_post=*/false, /*is_off_the_record=*/true, @@ -265,6 +269,7 @@ page = error_html; }); web::FakeWebState web_state; + ErrorPageControllerBridge::CreateForWebState(&web_state); web_client.PrepareErrorPage(&web_state, GURL(kTestUrl), error, /*is_post=*/true, /*is_off_the_record=*/true,
diff --git a/ios/chrome/browser/web/error_page_controller_bridge.h b/ios/chrome/browser/web/error_page_controller_bridge.h new file mode 100644 index 0000000..11eb1a2 --- /dev/null +++ b/ios/chrome/browser/web/error_page_controller_bridge.h
@@ -0,0 +1,54 @@ +// Copyright 2020 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_CHROME_BROWSER_WEB_ERROR_PAGE_CONTROLLER_BRIDGE_H_ +#define IOS_CHROME_BROWSER_WEB_ERROR_PAGE_CONTROLLER_BRIDGE_H_ + +#include "ios/web/public/web_state_observer.h" +#import "ios/web/public/web_state_user_data.h" + +namespace web { +class WebState; +} + +// A class to bridge the JS errorPageController object in the error page. +// The class receives the JS messages and handle/dispatch them when needed. +// Messages are sent in +// components/neterror/resources/error_page_controller_ios.js. +class ErrorPageControllerBridge + : public web::WebStateObserver, + public web::WebStateUserData<ErrorPageControllerBridge> { + public: + ~ErrorPageControllerBridge() override; + + // Start observing "errorPageController" commands until next navigation. + void StartHandlingJavascriptCommands(); + + // WebStateObserver overrides + void DidStartNavigation(web::WebState* web_state, + web::NavigationContext* navigation_context) override; + void WebStateDestroyed(web::WebState* web_state) override; + + private: + friend class WebStateUserData<ErrorPageControllerBridge>; + + ErrorPageControllerBridge(web::WebState* web_state); + + // Handler for "errorPageController.*" JavaScript command. + void OnErrorPageCommand(const base::DictionaryValue& message, + const GURL& url, + bool user_is_interacting, + web::WebFrame* sender_frame); + + // The WebState this instance is observing. Will be null after + // WebStateDestroyed has been called. + web::WebState* web_state_ = nullptr; + + // Subscription for JS message. + base::CallbackListSubscription subscription_; + + WEB_STATE_USER_DATA_KEY_DECL(); +}; + +#endif // IOS_CHROME_BROWSER_WEB_ERROR_PAGE_CONTROLLER_BRIDGE_H_
diff --git a/ios/chrome/browser/web/error_page_controller_bridge.mm b/ios/chrome/browser/web/error_page_controller_bridge.mm new file mode 100644 index 0000000..a7b1db66 --- /dev/null +++ b/ios/chrome/browser/web/error_page_controller_bridge.mm
@@ -0,0 +1,88 @@ +// Copyright 2020 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 "ios/chrome/browser/web/error_page_controller_bridge.h" + +#import <Foundation/Foundation.h> + +#include "base/strings/string_number_conversions.h" +#include "base/values.h" +#include "ios/web/public/js_messaging/web_frame.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +namespace { +// Prefix for the errorPageController activity event commands. +// Must be kept in sync with +// components/neterror/resources/error_page_controller_ios.js. +const char kCommandPrefix[] = "errorPageController"; + +// The NSUserDefault key to store the easter egg game on error page high score. +NSString* const kEasterEggHighScore = @"EasterEggHighScore"; +} // namespace + +ErrorPageControllerBridge::ErrorPageControllerBridge(web::WebState* web_state) + : web_state_(web_state) {} + +ErrorPageControllerBridge::~ErrorPageControllerBridge() {} + +void ErrorPageControllerBridge::StartHandlingJavascriptCommands() { + web_state_->AddObserver(this); + subscription_ = web_state_->AddScriptCommandCallback( + base::BindRepeating(&ErrorPageControllerBridge::OnErrorPageCommand, + base::Unretained(this)), + kCommandPrefix); +} + +void ErrorPageControllerBridge::OnErrorPageCommand( + const base::DictionaryValue& message, + const GURL& url, + bool user_is_interacting, + web::WebFrame* sender_frame) { + std::string command; + if (!message.GetString("command", &command)) { + return; + } + if (command == "errorPageController.updateEasterEggHighScore") { + std::string high_score_string; + if (!message.GetString("highScore", &high_score_string)) { + return; + } + int high_score; + if (!base::StringToInt(high_score_string, &high_score)) { + return; + } + [[NSUserDefaults standardUserDefaults] setInteger:high_score + forKey:kEasterEggHighScore]; + } + if (command == "errorPageController.resetEasterEggHighScore") { + [[NSUserDefaults standardUserDefaults] + removeObjectForKey:kEasterEggHighScore]; + } + if (command == "errorPageController.trackEasterEgg") { + int high_score = [[NSUserDefaults standardUserDefaults] + integerForKey:kEasterEggHighScore]; + std::vector<base::Value> parameters; + parameters.push_back(base::Value(high_score)); + sender_frame->CallJavaScriptFunction( + "errorPageController.initializeEasterEggHighScore", parameters); + } +} + +#pragma mark WebStateObserver + +void ErrorPageControllerBridge::DidStartNavigation( + web::WebState* web_state, + web::NavigationContext* navigation_context) { + subscription_ = base::CallbackListSubscription(); + web_state_->RemoveObserver(this); +} + +void ErrorPageControllerBridge::WebStateDestroyed(web::WebState* web_state) { + web_state_->RemoveObserver(this); +} + +WEB_STATE_USER_DATA_KEY_IMPL(ErrorPageControllerBridge)
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 d4c8083..56371f5 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 @@ -09f5e9e6fd9a03986fdca73d1f5bb799165cdb6a \ No newline at end of file +007525822c0412a6bd0c1d65fbe58d3ba96fce12 \ 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 8146536..e897ab42 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 @@ -b02a12ffa132578d5bd7eaedaec6daf7ab7fb55f \ No newline at end of file +d2ff5c31c703178b4d77c016eb8955f172b4e977 \ 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 ee77eea..61ca384 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 @@ -b41a5b45785bd97e9089a06e1d4b7853204dbedd \ No newline at end of file +5de3632f4616a649ee5d54f5045ce4fa67cf243e \ 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 b10a9a2..6595a8a 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 @@ -269513051141507be86a9cf852ff9534b8ba8d31 \ No newline at end of file +d38a9cd1e9045dc0a0118c76d312c10cadedd611 \ 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 99872152..850d35b 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 @@ -5757c66ac70fe7f237ab7adde499254e41a6e4f1 \ No newline at end of file +b2baad9993ddb7d625b42bbfdbfe9c611f853c3b \ 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 aac795a..29291508 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 @@ -8fa54abbfe799c05d2e85bdf3f5a989357494098 \ No newline at end of file +62455b7671269cbcd94966da3547f93e102c0362 \ 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 7ae2d44..f8ec414 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 @@ -29505483040ef6c2fae9b09f8d784bc33d246aa2 \ No newline at end of file +b49d3ea1f889d93e4091f0fed83d596372b957a9 \ 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 6033e06..ef5fbf3 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 @@ -d6c7316f355fcbb3c5c6d1da08904f1a39686fd4 \ No newline at end of file +d9365568cb99a51f25a79edd1a091f8ac32a1b95 \ No newline at end of file
diff --git a/net/http/http_stream_factory_job_controller_unittest.cc b/net/http/http_stream_factory_job_controller_unittest.cc index c3f150de..b5934c35 100644 --- a/net/http/http_stream_factory_job_controller_unittest.cc +++ b/net/http/http_stream_factory_job_controller_unittest.cc
@@ -2953,11 +2953,12 @@ HttpRequestInfo request_info; request_info.method = "GET"; request_info.url = GURL("https://example.com"); - Initialize(request_info); - url::SchemeHostPort origin(request_info.url); NetworkIsolationKey network_isolation_key( SchemefulSite(GURL("https://example.com")), SchemefulSite(GURL("https://example.com"))); + request_info.network_isolation_key = network_isolation_key; + Initialize(request_info); + url::SchemeHostPort origin(request_info.url); scoped_refptr<HttpResponseHeaders> headers( base::MakeRefCounted<HttpResponseHeaders>("")); headers->AddHeader("alt-svc", alt_svc_header);
diff --git a/sandbox/linux/seccomp-bpf-helpers/baseline_policy.cc b/sandbox/linux/seccomp-bpf-helpers/baseline_policy.cc index 3c67b124..e00e3125 100644 --- a/sandbox/linux/seccomp-bpf-helpers/baseline_policy.cc +++ b/sandbox/linux/seccomp-bpf-helpers/baseline_policy.cc
@@ -205,17 +205,21 @@ } if (sysno == __NR_madvise) { - // Only allow MADV_DONTNEED, MADV_RANDOM, MADV_NORMAL and MADV_FREE. + // Only allow MADV_DONTNEED, MADV_RANDOM, MADV_REMOVE, MADV_NORMAL and + // MADV_FREE. const Arg<int> advice(2); - return If(AnyOf(advice == MADV_DONTNEED, - advice == MADV_RANDOM, + return If(AnyOf(advice == MADV_DONTNEED, advice == MADV_RANDOM, + advice == MADV_REMOVE, advice == MADV_NORMAL #if defined(MADV_FREE) // MADV_FREE was introduced in Linux 4.5 and started being // defined in glibc 2.24. - , advice == MADV_FREE + , + advice == MADV_FREE #endif - ), Allow()).Else(Error(EPERM)); + ), + Allow()) + .Else(Error(EPERM)); } #if defined(__i386__) || defined(__x86_64__) || defined(__mips__) || \
diff --git a/services/network/public/cpp/is_potentially_trustworthy_unittest.cc b/services/network/public/cpp/is_potentially_trustworthy_unittest.cc index ab20533c..7e3d1e3 100644 --- a/services/network/public/cpp/is_potentially_trustworthy_unittest.cc +++ b/services/network/public/cpp/is_potentially_trustworthy_unittest.cc
@@ -10,6 +10,7 @@ #include "testing/gtest/include/gtest/gtest.h" #include "url/gurl.h" #include "url/origin.h" +#include "url/url_util.h" namespace network { @@ -49,6 +50,10 @@ EXPECT_FALSE(IsOriginPotentiallyTrustworthy("about:srcdoc")); EXPECT_FALSE(IsOriginPotentiallyTrustworthy("javascript:alert('blah')")); EXPECT_FALSE(IsOriginPotentiallyTrustworthy("data:test/plain;blah")); + + EXPECT_FALSE(IsOriginPotentiallyTrustworthy("custom-scheme://example.com")); + EXPECT_TRUE( + IsOriginPotentiallyTrustworthy("quic-transport://example.com/counter")); } TEST(IsPotentiallyTrustworthy, Url) { @@ -134,6 +139,31 @@ IsUrlPotentiallyTrustworthy("blob:ftp://127.0.0.1/guid-goes-here")); EXPECT_TRUE(IsUrlPotentiallyTrustworthy( "blob:https://www.example.com/guid-goes-here")); + + EXPECT_FALSE(IsUrlPotentiallyTrustworthy("blob:data:text/html,Hello")); + EXPECT_FALSE(IsUrlPotentiallyTrustworthy("blob:about:blank")); + EXPECT_FALSE(IsUrlPotentiallyTrustworthy("filesystem:data:text/html,Hello")); + EXPECT_FALSE(IsUrlPotentiallyTrustworthy("filesystem:about:blank")); + EXPECT_FALSE(IsUrlPotentiallyTrustworthy( + "blob:blob:https://example.com/578223a1-8c13-17b3-84d5-eca045ae384a")); + EXPECT_FALSE( + IsUrlPotentiallyTrustworthy("filesystem:blob:https://example.com/" + "578223a1-8c13-17b3-84d5-eca045ae384a")); + + EXPECT_TRUE( + IsUrlPotentiallyTrustworthy("quic-transport://example.com/counter")); + EXPECT_FALSE(IsUrlPotentiallyTrustworthy("custom-scheme://example.com")); +} + +TEST(IsPotentiallyTrustworthy, CustomScheme) { + url::ScopedSchemeRegistryForTests scoped_registry; + url::AddSecureScheme("custom-scheme"); + + // TODO(crbug.com/1159371): These tests should return true. + EXPECT_FALSE(IsOriginPotentiallyTrustworthy( + "custom-scheme://578223a1-8c13-17b3-84d5-eca045ae384a/fun.js")); + EXPECT_FALSE(IsUrlPotentiallyTrustworthy( + "custom-scheme://578223a1-8c13-17b3-84d5-eca045ae384a/fun.js")); } // Tests that were for the removed blink::network_utils::IsOriginSecure.
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index 89e4af88..d72a0db 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -8531,6 +8531,27 @@ ] } ], + "WebRtcDistinctWorkerThread": [ + { + "platforms": [ + "windows", + "mac", + "chromeos", + "linux", + "ios", + "android", + "android_weblayer" + ], + "experiments": [ + { + "name": "Enabled", + "enable_features": [ + "WebRtcDistinctWorkerThread" + ] + } + ] + } + ], "WebRtcHybridAgc": [ { "platforms": [
diff --git a/third_party/blink/public/mojom/webid/federated_auth_request.mojom b/third_party/blink/public/mojom/webid/federated_auth_request.mojom index 9ed7158..4e4d543f 100644 --- a/third_party/blink/public/mojom/webid/federated_auth_request.mojom +++ b/third_party/blink/public/mojom/webid/federated_auth_request.mojom
@@ -15,6 +15,10 @@ kApprovalDeclined, kErrorTooManyRequests, kErrorWebIdNotSupportedByProvider, + kErrorFetchingWellKnown, + kErrorInvalidWellKnown, + kErrorFetchingSignin, + kErrorInvalidSigninResponse, kError, };
diff --git a/third_party/blink/renderer/bindings/core/v8/module_record.cc b/third_party/blink/renderer/bindings/core/v8/module_record.cc index 364be175..e5ce258 100644 --- a/third_party/blink/renderer/bindings/core/v8/module_record.cc +++ b/third_party/blink/renderer/bindings/core/v8/module_record.cc
@@ -48,7 +48,6 @@ v8::Local<v8::Module> ModuleRecord::Compile( v8::Isolate* isolate, const ModuleScriptCreationParams& params, - const KURL& base_url, const ScriptFetchOptions& options, const TextPosition& text_position, ExceptionState& exception_state, @@ -76,7 +75,7 @@ if (!V8ScriptRunner::CompileModule( isolate, params, text_position, compile_options, no_cache_reason, - ReferrerScriptInfo(base_url, options, + ReferrerScriptInfo(params.BaseURL(), options, ReferrerScriptInfo::BaseUrlSource::kOther)) .ToLocal(&module)) { DCHECK(try_catch.HasCaught());
diff --git a/third_party/blink/renderer/bindings/core/v8/module_record.h b/third_party/blink/renderer/bindings/core/v8/module_record.h index 0b1779c..6e3be7e 100644 --- a/third_party/blink/renderer/bindings/core/v8/module_record.h +++ b/third_party/blink/renderer/bindings/core/v8/module_record.h
@@ -65,7 +65,6 @@ static v8::Local<v8::Module> Compile( v8::Isolate*, const ModuleScriptCreationParams& params, - const KURL& base_url, const ScriptFetchOptions&, const TextPosition&, ExceptionState&,
diff --git a/third_party/blink/renderer/bindings/core/v8/script_streamer.cc b/third_party/blink/renderer/bindings/core/v8/script_streamer.cc index 63b9ae1..a62b433 100644 --- a/third_party/blink/renderer/bindings/core/v8/script_streamer.cc +++ b/third_party/blink/renderer/bindings/core/v8/script_streamer.cc
@@ -19,6 +19,7 @@ #include "third_party/blink/renderer/core/inspector/inspector_trace_events.h" #include "third_party/blink/renderer/core/loader/resource/script_resource.h" #include "third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h" +#include "third_party/blink/renderer/platform/instrumentation/histogram.h" #include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h" #include "third_party/blink/renderer/platform/loader/fetch/cached_metadata.h" #include "third_party/blink/renderer/platform/loader/fetch/resource.h" @@ -266,6 +267,100 @@ size_t ScriptStreamer::small_script_threshold_ = 30 * 1024; +std::tuple<ScriptStreamer*, ScriptStreamer::NotStreamingReason> +ScriptStreamer::TakeFrom(ScriptResource* script_resource) { + ScriptStreamer::NotStreamingReason not_streamed_reason = + script_resource->NoStreamerReason(); + ScriptStreamer* streamer = script_resource->TakeStreamer(); + if (streamer) { + if (streamer->IsStreamingSuppressed()) { + not_streamed_reason = streamer->StreamingSuppressedReason(); + streamer = nullptr; + } else { + DCHECK_EQ(not_streamed_reason, + ScriptStreamer::NotStreamingReason::kInvalid); + } + } + return std::make_tuple(streamer, not_streamed_reason); +} + +namespace { + +enum class StreamedBoolean { + // Must match BooleanStreamed in enums.xml. + kNotStreamed = 0, + kStreamed = 1, + kMaxValue = kStreamed +}; + +void RecordStartedStreamingHistogram(ScriptSchedulingType type, + bool did_use_streamer) { + StreamedBoolean streamed = did_use_streamer ? StreamedBoolean::kStreamed + : StreamedBoolean::kNotStreamed; + switch (type) { + case ScriptSchedulingType::kParserBlocking: { + UMA_HISTOGRAM_ENUMERATION( + "WebCore.Scripts.ParsingBlocking.StartedStreaming", streamed); + break; + } + case ScriptSchedulingType::kDefer: { + UMA_HISTOGRAM_ENUMERATION("WebCore.Scripts.Deferred.StartedStreaming", + streamed); + break; + } + case ScriptSchedulingType::kAsync: { + UMA_HISTOGRAM_ENUMERATION("WebCore.Scripts.Async.StartedStreaming", + streamed); + break; + } + default: { + UMA_HISTOGRAM_ENUMERATION("WebCore.Scripts.Other.StartedStreaming", + streamed); + break; + } + } +} + +void RecordNotStreamingReasonHistogram( + ScriptSchedulingType type, + ScriptStreamer::NotStreamingReason reason) { + switch (type) { + case ScriptSchedulingType::kParserBlocking: { + UMA_HISTOGRAM_ENUMERATION( + "WebCore.Scripts.ParsingBlocking.NotStreamingReason", reason); + break; + } + case ScriptSchedulingType::kDefer: { + UMA_HISTOGRAM_ENUMERATION("WebCore.Scripts.Deferred.NotStreamingReason", + reason); + break; + } + case ScriptSchedulingType::kAsync: { + UMA_HISTOGRAM_ENUMERATION("WebCore.Scripts.Async.NotStreamingReason", + reason); + break; + } + default: { + UMA_HISTOGRAM_ENUMERATION("WebCore.Scripts.Other.NotStreamingReason", + reason); + break; + } + } +} + +} // namespace + +void ScriptStreamer::RecordStreamingHistogram( + ScriptSchedulingType type, + bool can_use_streamer, + ScriptStreamer::NotStreamingReason reason) { + RecordStartedStreamingHistogram(type, can_use_streamer); + if (!can_use_streamer) { + DCHECK_NE(ScriptStreamer::NotStreamingReason::kInvalid, reason); + RecordNotStreamingReasonHistogram(type, reason); + } +} + bool ScriptStreamer::ConvertEncoding( const char* encoding_name, v8::ScriptCompiler::StreamedSource::Encoding* encoding) { @@ -485,11 +580,15 @@ source_ = std::make_unique<v8::ScriptCompiler::StreamedSource>( std::move(stream_ptr), encoding_); - // TODO(crbug.com/1061857) Pass ScriptResource::ScriptType to the streaming - // task. std::unique_ptr<v8::ScriptCompiler::ScriptStreamingTask> - script_streaming_task(base::WrapUnique(v8::ScriptCompiler::StartStreaming( - V8PerIsolateData::MainThreadIsolate(), source_.get()))); + script_streaming_task = + base::WrapUnique(v8::ScriptCompiler::StartStreaming( + V8PerIsolateData::MainThreadIsolate(), source_.get(), + script_resource_->GetScriptType() == + mojom::blink::ScriptType::kClassic + ? v8::ScriptType::kClassic + : v8::ScriptType::kModule)); + if (!script_streaming_task) { // V8 cannot stream the script. stream_ = nullptr;
diff --git a/third_party/blink/renderer/bindings/core/v8/script_streamer.h b/third_party/blink/renderer/bindings/core/v8/script_streamer.h index 13e25e7..2275f212 100644 --- a/third_party/blink/renderer/bindings/core/v8/script_streamer.h +++ b/third_party/blink/renderer/bindings/core/v8/script_streamer.h
@@ -6,11 +6,13 @@ #define THIRD_PARTY_BLINK_RENDERER_BINDINGS_CORE_V8_SCRIPT_STREAMER_H_ #include <memory> +#include <tuple> #include "base/macros.h" #include "base/single_thread_task_runner.h" #include "mojo/public/cpp/system/data_pipe.h" #include "third_party/blink/renderer/core/core_export.h" +#include "third_party/blink/renderer/core/script/script_scheduling_type.h" #include "third_party/blink/renderer/platform/heap/handle.h" #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" #include "v8/include/v8.h" @@ -73,6 +75,12 @@ ~ScriptStreamer(); void Trace(Visitor*) const; + static std::tuple<ScriptStreamer*, NotStreamingReason> TakeFrom( + ScriptResource*); + static void RecordStreamingHistogram(ScriptSchedulingType type, + bool can_use_streamer, + ScriptStreamer::NotStreamingReason); + // Returns false if we cannot stream the given encoding. static bool ConvertEncoding(const char* encoding_name, v8::ScriptCompiler::StreamedSource::Encoding*);
diff --git a/third_party/blink/renderer/bindings/core/v8/v8_script_runner.cc b/third_party/blink/renderer/bindings/core/v8/v8_script_runner.cc index bb8584a..2693444d 100644 --- a/third_party/blink/renderer/bindings/core/v8/v8_script_runner.cc +++ b/third_party/blink/renderer/bindings/core/v8/v8_script_runner.cc
@@ -271,8 +271,16 @@ true, // is_module referrer_info.ToV8HostDefinedOptions(isolate)); - // TODO(crbug.com/1061857): Finalize module streaming here. v8::Local<v8::String> code = V8String(isolate, params.GetSourceText()); + if (ScriptStreamer* streamer = params.GetScriptStreamer()) { + // Final compile call for a streamed compilation. + // Streaming compilation may involve use of code cache. + // TODO(leszeks): Add compile timer to streaming compilation. + DCHECK(streamer->IsFinished()); + DCHECK(!streamer->IsStreamingSuppressed()); + return v8::ScriptCompiler::CompileModule(isolate->GetCurrentContext(), + streamer->Source(), code, origin); + } v8::MaybeLocal<v8::Module> script; inspector_compile_script_event::V8CacheResult cache_result;
diff --git a/third_party/blink/renderer/bindings/generated_in_modules.gni b/third_party/blink/renderer/bindings/generated_in_modules.gni index 5816e92c..7e3bb39d 100644 --- a/third_party/blink/renderer/bindings/generated_in_modules.gni +++ b/third_party/blink/renderer/bindings/generated_in_modules.gni
@@ -1749,10 +1749,10 @@ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_native_file_system_directory_iterator.h", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_native_io_file.cc", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_native_io_file.h", + "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_native_io_file_manager.cc", + "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_native_io_file_manager.h", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_native_io_file_sync.cc", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_native_io_file_sync.h", - "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_native_io_manager.cc", - "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_native_io_manager.h", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_navigation_preload_manager.cc", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_navigation_preload_manager.h", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_navigator.cc",
diff --git a/third_party/blink/renderer/bindings/idl_in_modules.gni b/third_party/blink/renderer/bindings/idl_in_modules.gni index 05a6eae..077ebec 100644 --- a/third_party/blink/renderer/bindings/idl_in_modules.gni +++ b/third_party/blink/renderer/bindings/idl_in_modules.gni
@@ -400,8 +400,8 @@ "//third_party/blink/renderer/modules/mediastream/navigator_user_media.idl", "//third_party/blink/renderer/modules/mediastream/overconstrained_error.idl", "//third_party/blink/renderer/modules/native_io/native_io_file.idl", + "//third_party/blink/renderer/modules/native_io/native_io_file_manager.idl", "//third_party/blink/renderer/modules/native_io/native_io_file_sync.idl", - "//third_party/blink/renderer/modules/native_io/native_io_manager.idl", "//third_party/blink/renderer/modules/native_io/window_native_io.idl", "//third_party/blink/renderer/modules/native_io/worker_global_scope_native_io.idl", "//third_party/blink/renderer/modules/navigatorcontentutils/navigator_content_utils.idl",
diff --git a/third_party/blink/renderer/core/css/resolver/selector_filter_parent_scope.cc b/third_party/blink/renderer/core/css/resolver/selector_filter_parent_scope.cc index 7274982..30bd28f 100644 --- a/third_party/blink/renderer/core/css/resolver/selector_filter_parent_scope.cc +++ b/third_party/blink/renderer/core/css/resolver/selector_filter_parent_scope.cc
@@ -3,20 +3,21 @@ // found in the LICENSE file. #include "third_party/blink/renderer/core/css/resolver/selector_filter_parent_scope.h" +#include "third_party/blink/renderer/core/dom/flat_tree_traversal.h" namespace blink { SelectorFilterParentScope* SelectorFilterParentScope::current_scope_ = nullptr; void SelectorFilterParentScope::PushAncestors(Element& element) { - if (Element* ancestor = element.ParentOrShadowHostElement()) { + if (Element* ancestor = FlatTreeTraversal::ParentElement(element)) { PushAncestors(*ancestor); resolver_->GetSelectorFilter().PushParent(*ancestor); } } void SelectorFilterParentScope::PopAncestors(Element& element) { - if (Element* ancestor = element.ParentOrShadowHostElement()) { + if (Element* ancestor = FlatTreeTraversal::ParentElement(element)) { resolver_->GetSelectorFilter().PopParent(*ancestor); PopAncestors(*ancestor); }
diff --git a/third_party/blink/renderer/core/css/selector_filter.cc b/third_party/blink/renderer/core/css/selector_filter.cc index 9523178..7d129889 100644 --- a/third_party/blink/renderer/core/css/selector_filter.cc +++ b/third_party/blink/renderer/core/css/selector_filter.cc
@@ -32,6 +32,7 @@ #include "third_party/blink/renderer/core/css/css_selector.h" #include "third_party/blink/renderer/core/dom/document.h" +#include "third_party/blink/renderer/core/dom/flat_tree_traversal.h" namespace blink { @@ -65,8 +66,9 @@ void SelectorFilter::PushParentStackFrame(Element& parent) { DCHECK(ancestor_identifier_filter_); DCHECK(parent_stack_.IsEmpty() || - parent_stack_.back().element == parent.ParentOrShadowHostElement()); - DCHECK(!parent_stack_.IsEmpty() || !parent.ParentOrShadowHostElement()); + parent_stack_.back().element == + FlatTreeTraversal::ParentElement(parent)); + DCHECK(!parent_stack_.IsEmpty() || !FlatTreeTraversal::ParentElement(parent)); parent_stack_.push_back(ParentStackFrame(parent)); ParentStackFrame& parent_frame = parent_stack_.back(); // Mix tags, class names and ids into some sort of weird bouillabaisse. @@ -106,7 +108,7 @@ DCHECK(ancestor_identifier_filter_); // We may get invoked for some random elements in some wacky cases during // style resolve. Pause maintaining the stack in this case. - if (parent_stack_.back().element != parent.ParentOrShadowHostElement()) + if (parent_stack_.back().element != FlatTreeTraversal::ParentElement(parent)) return; PushParentStackFrame(parent); } @@ -167,9 +169,6 @@ skip_over_subselectors = true; break; case CSSSelector::kShadowSlot: - // Disable fastRejectSelector. - *identifier_hashes = 0; - return; case CSSSelector::kDescendant: case CSSSelector::kChild: case CSSSelector::kUAShadow:
diff --git a/third_party/blink/renderer/core/css/style_engine.cc b/third_party/blink/renderer/core/css/style_engine.cc index c4dd7ea..52ca536 100644 --- a/third_party/blink/renderer/core/css/style_engine.cc +++ b/third_party/blink/renderer/core/css/style_engine.cc
@@ -2006,20 +2006,20 @@ void StyleEngine::RecalcStyle(StyleRecalcChange change) { DCHECK(GetDocument().documentElement()); - Element* root_element = &style_recalc_root_.RootElement(); - Element* parent = root_element->ParentOrShadowHostElement(); + Element& root_element = style_recalc_root_.RootElement(); + Element* parent = FlatTreeTraversal::ParentElement(root_element); SelectorFilterRootScope filter_scope(parent); - root_element->RecalcStyle(change); + root_element.RecalcStyle(change); - for (ContainerNode* ancestor = root_element->GetStyleRecalcParent(); ancestor; + for (ContainerNode* ancestor = root_element.GetStyleRecalcParent(); ancestor; ancestor = ancestor->GetStyleRecalcParent()) { if (auto* ancestor_element = DynamicTo<Element>(ancestor)) ancestor_element->RecalcStyleForTraversalRootAncestor(); ancestor->ClearChildNeedsStyleRecalc(); } style_recalc_root_.Clear(); - if (!parent || IsA<HTMLBodyElement>(*root_element)) + if (!parent || IsA<HTMLBodyElement>(root_element)) PropagateWritingModeAndDirectionToHTMLRoot(); }
diff --git a/third_party/blink/renderer/core/css/style_engine_test.cc b/third_party/blink/renderer/core/css/style_engine_test.cc index 3909117a3..896b68a2 100644 --- a/third_party/blink/renderer/core/css/style_engine_test.cc +++ b/third_party/blink/renderer/core/css/style_engine_test.cc
@@ -3836,4 +3836,86 @@ EXPECT_NE(old_inner_style, new_inner_style); } +TEST_F(StyleEngineTest, FastRejectForHostChild) { + GetDocument().body()->setInnerHTML(R"HTML( + <style> + .notfound span { + color: pink; + } + </style> + <div id="host"> + <span id="slotted"></span> + </div> + )HTML"); + + Element* host = GetDocument().getElementById("host"); + ASSERT_TRUE(host); + ShadowRoot& shadow_root = + host->AttachShadowRootInternal(ShadowRootType::kOpen); + shadow_root.setInnerHTML(R"HTML( + <slot></slot> + )HTML"); + UpdateAllLifecyclePhases(); + + StyleEngine& engine = GetStyleEngine(); + // If the Stats() were already enabled, we would not start with 0 counts. + EXPECT_FALSE(engine.Stats()); + engine.SetStatsEnabled(true); + + StyleResolverStats* stats = engine.Stats(); + ASSERT_TRUE(stats); + EXPECT_EQ(0u, stats->rules_fast_rejected); + + Element* span = GetDocument().getElementById("slotted"); + ASSERT_TRUE(span); + span->SetInlineStyleProperty(CSSPropertyID::kColor, "green"); + + GetDocument().Lifecycle().AdvanceTo(DocumentLifecycle::kInStyleRecalc); + GetStyleEngine().RecalcStyle(); + + // Should fast reject ".notfound span" + EXPECT_EQ(1u, stats->rules_fast_rejected); +} + +TEST_F(StyleEngineTest, RejectSlottedSelector) { + GetDocument().body()->setInnerHTML(R"HTML( + <div id="host"> + <span id="slotted"></span> + </div> + )HTML"); + + Element* host = GetDocument().getElementById("host"); + ASSERT_TRUE(host); + ShadowRoot& shadow_root = + host->AttachShadowRootInternal(ShadowRootType::kOpen); + shadow_root.setInnerHTML(R"HTML( + <style> + .notfound ::slotted(span) { + color: pink; + } + </style> + <slot></slot> + )HTML"); + UpdateAllLifecyclePhases(); + + StyleEngine& engine = GetStyleEngine(); + // If the Stats() were already enabled, we would not start with 0 counts. + EXPECT_FALSE(engine.Stats()); + engine.SetStatsEnabled(true); + + StyleResolverStats* stats = engine.Stats(); + ASSERT_TRUE(stats); + EXPECT_EQ(0u, stats->rules_fast_rejected); + + Element* span = GetDocument().getElementById("slotted"); + ASSERT_TRUE(span); + span->SetInlineStyleProperty(CSSPropertyID::kColor, "green"); + + GetDocument().Lifecycle().AdvanceTo(DocumentLifecycle::kInStyleRecalc); + GetStyleEngine().RecalcStyle(); + + // Should fast reject ".notfound ::slotted(span)" + EXPECT_EQ(1u, stats->rules_fast_rejected); +} + } // namespace blink
diff --git a/third_party/blink/renderer/core/html/media/html_media_element.cc b/third_party/blink/renderer/core/html/media/html_media_element.cc index c23d0d5..d2f5a72f 100644 --- a/third_party/blink/renderer/core/html/media/html_media_element.cc +++ b/third_party/blink/renderer/core/html/media/html_media_element.cc
@@ -4116,9 +4116,15 @@ void HTMLMediaElement::BindMediaPlayerReceiver( mojo::PendingReceiver<media::mojom::blink::MediaPlayer> receiver) { - media_player_receiver_set_.Add( + mojo::ReceiverId receiver_id = media_player_receiver_set_.Add( std::move(receiver), GetDocument().GetTaskRunner(TaskType::kInternalMedia)); + + media_player_receiver_set_.set_disconnect_handler(WTF::BindRepeating( + [](HTMLMediaElement* html_media_element, mojo::ReceiverId receiver_id) { + html_media_element->media_player_receiver_set_.Remove(receiver_id); + }, + WrapWeakPersistent(this), receiver_id)); } void HTMLMediaElement::Trace(Visitor* visitor) const {
diff --git a/third_party/blink/renderer/core/layout/ng/mathml/ng_math_layout_utils.cc b/third_party/blink/renderer/core/layout/ng/mathml/ng_math_layout_utils.cc index 0dc66e71..46c2de49 100644 --- a/third_party/blink/renderer/core/layout/ng/mathml/ng_math_layout_utils.cc +++ b/third_party/blink/renderer/core/layout/ng/mathml/ng_math_layout_utils.cc
@@ -79,13 +79,15 @@ if (!child || IsPrescriptDelimiter(child)) return false; bool number_of_scripts_is_even = true; + bool prescript_delimiter_found = false; while (child) { child = To<NGBlockNode>(NextSiblingInFlow(child)); if (!child) continue; if (IsPrescriptDelimiter(child)) { - if (!number_of_scripts_is_even) + if (!number_of_scripts_is_even || prescript_delimiter_found) return false; + prescript_delimiter_found = true; continue; } number_of_scripts_is_even = !number_of_scripts_is_even;
diff --git a/third_party/blink/renderer/core/layout/ng/mathml/ng_math_scripts_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/mathml/ng_math_scripts_layout_algorithm.cc index 56a9d5e..4a62899 100644 --- a/third_party/blink/renderer/core/layout/ng/mathml/ng_math_scripts_layout_algorithm.cc +++ b/third_party/blink/renderer/core/layout/ng/mathml/ng_math_scripts_layout_algorithm.cc
@@ -148,7 +148,7 @@ // The structure of mmultiscripts is specified here: // https://mathml-refresh.github.io/mathml-core/#prescripts-and-tensor-indices-mmultiscripts if (IsPrescriptDelimiter(block_child)) { - if (!number_of_scripts_is_even || *first_prescript_index > 0) { + if (!number_of_scripts_is_even || *prescripts) { NOTREACHED(); return; }
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_path.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_path.cc index 6e6a77d..aac0aba 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_path.cc +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_path.cc
@@ -33,9 +33,22 @@ namespace blink { +namespace { + +bool SupportsMarkers(const SVGGeometryElement& element) { + return element.HasTagName(svg_names::kLineTag) || + element.HasTagName(svg_names::kPathTag) || + element.HasTagName(svg_names::kPolygonTag) || + element.HasTagName(svg_names::kPolylineTag); +} + +} // namespace + LayoutSVGPath::LayoutSVGPath(SVGGeometryElement* node) // <line> elements have no joins and thus needn't care about miters. - : LayoutSVGShape(node, IsA<SVGLineElement>(node) ? kNoMiters : kComplex) {} + : LayoutSVGShape(node, IsA<SVGLineElement>(node) ? kNoMiters : kComplex) { + DCHECK(SupportsMarkers(*node)); +} LayoutSVGPath::~LayoutSVGPath() = default; @@ -70,8 +83,7 @@ marker_positions_.clear(); const SVGComputedStyle& svg_style = StyleRef().SvgStyle(); - if (!svg_style.HasMarkers() || - !SVGResources::SupportsMarkers(*To<SVGGraphicsElement>(GetElement()))) + if (!svg_style.HasMarkers()) return; SVGElementResourceClient* client = SVGResources::GetClient(*this); if (!client)
diff --git a/third_party/blink/renderer/core/layout/svg/svg_resources.cc b/third_party/blink/renderer/core/layout/svg/svg_resources.cc index 27093f372..2afe8794 100644 --- a/third_party/blink/renderer/core/layout/svg/svg_resources.cc +++ b/third_party/blink/renderer/core/layout/svg/svg_resources.cc
@@ -30,7 +30,6 @@ #include "third_party/blink/renderer/core/svg/graphics/filters/svg_filter_builder.h" #include "third_party/blink/renderer/core/svg/svg_filter_primitive_standard_attributes.h" #include "third_party/blink/renderer/core/svg/svg_resource.h" -#include "third_party/blink/renderer/core/svg_names.h" #include "third_party/blink/renderer/platform/graphics/filters/filter.h" #include "third_party/blink/renderer/platform/graphics/filters/filter_effect.h" #include "third_party/blink/renderer/platform/graphics/filters/paint_filter_builder.h" @@ -63,17 +62,6 @@ return obb_layout_object->ObjectBoundingBox(); } -bool SVGResources::SupportsMarkers(const SVGElement& element) { - DEFINE_STATIC_LOCAL(HashSet<AtomicString>, tag_list, - ({ - svg_names::kLineTag.LocalName(), - svg_names::kPathTag.LocalName(), - svg_names::kPolygonTag.LocalName(), - svg_names::kPolylineTag.LocalName(), - })); - return tag_list.Contains(element.localName()); -} - void SVGResources::UpdateClipPathFilterMask(SVGElement& element, const ComputedStyle* old_style, const ComputedStyle& style) {
diff --git a/third_party/blink/renderer/core/layout/svg/svg_resources.h b/third_party/blink/renderer/core/layout/svg/svg_resources.h index d7c3427a..38e6a0d 100644 --- a/third_party/blink/renderer/core/layout/svg/svg_resources.h +++ b/third_party/blink/renderer/core/layout/svg/svg_resources.h
@@ -54,8 +54,6 @@ const ComputedStyle* old_style, const ComputedStyle&); static void ClearMarkers(SVGElement&, const ComputedStyle*); - - static bool SupportsMarkers(const SVGElement&); }; class SVGElementResourceClient final
diff --git a/third_party/blink/renderer/core/loader/modulescript/document_module_script_fetcher.cc b/third_party/blink/renderer/core/loader/modulescript/document_module_script_fetcher.cc index f28f2f5a..7f173c4 100644 --- a/third_party/blink/renderer/core/loader/modulescript/document_module_script_fetcher.cc +++ b/third_party/blink/renderer/core/loader/modulescript/document_module_script_fetcher.cc
@@ -8,6 +8,7 @@ #include "third_party/blink/renderer/bindings/core/v8/script_streamer.h" #include "third_party/blink/renderer/core/inspector/console_message.h" #include "third_party/blink/renderer/core/loader/resource/script_resource.h" +#include "third_party/blink/renderer/core/script/pending_script.h" #include "third_party/blink/renderer/platform/bindings/parkable_string.h" #include "third_party/blink/renderer/platform/heap/heap.h" #include "third_party/blink/renderer/platform/wtf/vector.h" @@ -37,20 +38,37 @@ auto* script_resource = To<ScriptResource>(resource); - HeapVector<Member<ConsoleMessage>> error_messages; ModuleScriptCreationParams::ModuleType module_type; - if (!WasModuleLoadSuccessful(script_resource, &error_messages, - &module_type)) { - client_->NotifyFetchFinished(base::nullopt, error_messages); - return; + { + HeapVector<Member<ConsoleMessage>> error_messages; + if (!WasModuleLoadSuccessful(script_resource, &error_messages, + &module_type)) { + client_->NotifyFetchFinishedError(error_messages); + return; + } } + // Check if we can use the script streamer. + ScriptStreamer* streamer; + ScriptStreamer::NotStreamingReason not_streamed_reason; + std::tie(streamer, not_streamed_reason) = + ScriptStreamer::TakeFrom(script_resource); + + ScriptStreamer::RecordStreamingHistogram(ScriptSchedulingType::kAsync, + streamer, not_streamed_reason); + + TRACE_EVENT_WITH_FLOW1(TRACE_DISABLED_BY_DEFAULT("v8.compile"), + "DocumentModuleScriptFetcher::NotifyFinished", this, + TRACE_EVENT_FLAG_FLOW_IN, "not_streamed_reason", + not_streamed_reason); // TODO(crbug.com/1061857): Pass ScriptStreamer to the client here. - ModuleScriptCreationParams params( - script_resource->GetResponse().CurrentRequestUrl(), module_type, + const KURL& url = script_resource->GetResponse().CurrentRequestUrl(); + // Create an external module script where base_url == source_url. + // https://html.spec.whatwg.org/multipage/webappapis.html#concept-script-base-url + client_->NotifyFetchFinishedSuccess(ModuleScriptCreationParams( + /*source_url=*/url, /*base_url=*/url, module_type, script_resource->SourceText(), script_resource->CacheHandler(), - script_resource->GetResourceRequest().GetCredentialsMode(), nullptr, - ScriptStreamer::NotStreamingReason::kStreamingDisabled); - client_->NotifyFetchFinished(params, error_messages); + script_resource->GetResourceRequest().GetCredentialsMode(), streamer, + not_streamed_reason)); } void DocumentModuleScriptFetcher::Trace(Visitor* visitor) const {
diff --git a/third_party/blink/renderer/core/loader/modulescript/installed_service_worker_module_script_fetcher.cc b/third_party/blink/renderer/core/loader/modulescript/installed_service_worker_module_script_fetcher.cc index 0b711b4c..c7e41452 100644 --- a/third_party/blink/renderer/core/loader/modulescript/installed_service_worker_module_script_fetcher.cc +++ b/third_party/blink/renderer/core/loader/modulescript/installed_service_worker_module_script_fetcher.cc
@@ -46,7 +46,7 @@ mojom::ConsoleMessageLevel::kError, "Failed to load the script unexpectedly", fetch_params.Url().GetString(), nullptr, 0)); - client->NotifyFetchFinished(base::nullopt, error_messages); + client->NotifyFetchFinishedError(error_messages); return; } @@ -99,16 +99,17 @@ mojom::ConsoleMessageLevel::kError, "Failed to load the script unexpectedly", fetch_params.Url().GetString(), nullptr, 0)); - client->NotifyFetchFinished(base::nullopt, error_messages); + client->NotifyFetchFinishedError(error_messages); return; } - ModuleScriptCreationParams params( - fetch_params.Url(), module_type, - ParkableString(script_data->TakeSourceText().Impl()), - nullptr /* cache_handler */, - fetch_params.GetResourceRequest().GetCredentialsMode()); - client->NotifyFetchFinished(params, HeapVector<Member<ConsoleMessage>>()); + // Create an external module script where base_url == source_url. + // https://html.spec.whatwg.org/multipage/webappapis.html#concept-script-base-url + client->NotifyFetchFinishedSuccess(ModuleScriptCreationParams( + /*source_url=*/fetch_params.Url(), /*base_url=*/fetch_params.Url(), + module_type, ParkableString(script_data->TakeSourceText().Impl()), + /*cache_handler=*/nullptr, + fetch_params.GetResourceRequest().GetCredentialsMode())); } void InstalledServiceWorkerModuleScriptFetcher::Trace(Visitor* visitor) const {
diff --git a/third_party/blink/renderer/core/loader/modulescript/module_script_creation_params.h b/third_party/blink/renderer/core/loader/modulescript/module_script_creation_params.h index 258f3646..8fdfb2a 100644 --- a/third_party/blink/renderer/core/loader/modulescript/module_script_creation_params.h +++ b/third_party/blink/renderer/core/loader/modulescript/module_script_creation_params.h
@@ -27,6 +27,7 @@ public: ModuleScriptCreationParams( const KURL& source_url, + const KURL& base_url, const ModuleScriptCreationParams::ModuleType module_type, const ParkableString& source_text, SingleCachedMetadataHandler* cache_handler, @@ -35,6 +36,7 @@ ScriptStreamer::NotStreamingReason not_streaming_reason = ScriptStreamer::NotStreamingReason::kStreamingDisabled) : source_url_(source_url), + base_url_(base_url), module_type_(module_type), is_isolated_(false), source_text_(source_text), @@ -54,8 +56,8 @@ String isolated_source_text = isolated_source_text_ ? isolated_source_text_.IsolatedCopy() : GetSourceText().ToString().IsolatedCopy(); - return ModuleScriptCreationParams(SourceURL().Copy(), module_type_, - isolated_source_text, + return ModuleScriptCreationParams(SourceURL().Copy(), BaseURL().Copy(), + module_type_, isolated_source_text, GetFetchCredentialsMode()); } @@ -64,6 +66,7 @@ } const KURL& SourceURL() const { return source_url_; } + const KURL& BaseURL() const { return base_url_; } const ParkableString& GetSourceText() const { if (is_isolated_) { @@ -74,11 +77,10 @@ return source_text_; } - // TODO(crbug.com/1154943): Make this non-const. - void ClearSourceText() const { - source_text_ = ParkableString(); - isolated_source_text_ = String(); - is_isolated_ = false; + ModuleScriptCreationParams CopyWithClearedSourceText() const { + return ModuleScriptCreationParams( + source_url_, base_url_, module_type_, ParkableString(), cache_handler_, + credentials_mode_, script_streamer_, not_streaming_reason_); } SingleCachedMetadataHandler* CacheHandler() const { return cache_handler_; } @@ -88,17 +90,22 @@ } bool IsSafeToSendToAnotherThread() const { - return source_url_.IsSafeToSendToAnotherThread() && is_isolated_; + return source_url_.IsSafeToSendToAnotherThread() && + base_url_.IsSafeToSendToAnotherThread() && is_isolated_; } + ScriptStreamer* GetScriptStreamer() const { return script_streamer_; } + private: // Creates an isolated copy. ModuleScriptCreationParams( const KURL& source_url, + const KURL& base_url, const ModuleScriptCreationParams::ModuleType& module_type, const String& isolated_source_text, network::mojom::CredentialsMode credentials_mode) : source_url_(source_url), + base_url_(base_url), module_type_(module_type), is_isolated_(true), source_text_(), @@ -113,6 +120,7 @@ ScriptStreamer::NotStreamingReason::kStreamingDisabled) {} const KURL source_url_; + const KURL base_url_; const ModuleType module_type_; // Mutable because an isolated copy can become bound to a thread when
diff --git a/third_party/blink/renderer/core/loader/modulescript/module_script_fetcher.cc b/third_party/blink/renderer/core/loader/modulescript/module_script_fetcher.cc index 9b3f8cc..62d8346 100644 --- a/third_party/blink/renderer/core/loader/modulescript/module_script_fetcher.cc +++ b/third_party/blink/renderer/core/loader/modulescript/module_script_fetcher.cc
@@ -21,12 +21,12 @@ base::PassKey<ModuleScriptLoader> pass_key) {} void ModuleScriptFetcher::Client::OnFetched( - const base::Optional<ModuleScriptCreationParams>& params) { - NotifyFetchFinished(params, HeapVector<Member<ConsoleMessage>>()); + const ModuleScriptCreationParams& params) { + NotifyFetchFinishedSuccess(params); } void ModuleScriptFetcher::Client::OnFailed() { - NotifyFetchFinished(base::nullopt, HeapVector<Member<ConsoleMessage>>()); + NotifyFetchFinishedError(HeapVector<Member<ConsoleMessage>>()); } void ModuleScriptFetcher::Trace(Visitor* visitor) const {
diff --git a/third_party/blink/renderer/core/loader/modulescript/module_script_fetcher.h b/third_party/blink/renderer/core/loader/modulescript/module_script_fetcher.h index a47aefdc..0b286f1 100644 --- a/third_party/blink/renderer/core/loader/modulescript/module_script_fetcher.h +++ b/third_party/blink/renderer/core/loader/modulescript/module_script_fetcher.h
@@ -29,13 +29,14 @@ class CORE_EXPORT Client : public GarbageCollectedMixin { public: - virtual void NotifyFetchFinished( - const base::Optional<ModuleScriptCreationParams>&, + virtual void NotifyFetchFinishedError( const HeapVector<Member<ConsoleMessage>>& error_messages) = 0; + virtual void NotifyFetchFinishedSuccess( + const ModuleScriptCreationParams&) = 0; // These helpers are used only from WorkletModuleResponsesMap. // TODO(nhiroki): Move these helpers to WorkletModuleResponsesMap. - void OnFetched(const base::Optional<ModuleScriptCreationParams>&); + void OnFetched(const ModuleScriptCreationParams&); void OnFailed(); };
diff --git a/third_party/blink/renderer/core/loader/modulescript/module_script_loader.cc b/third_party/blink/renderer/core/loader/modulescript/module_script_loader.cc index d529d21..db7ed5d 100644 --- a/third_party/blink/renderer/core/loader/modulescript/module_script_loader.cc +++ b/third_party/blink/renderer/core/loader/modulescript/module_script_loader.cc
@@ -224,8 +224,7 @@ } // <specdef href="https://html.spec.whatwg.org/C/#fetch-a-single-module-script"> -void ModuleScriptLoader::NotifyFetchFinished( - const base::Optional<ModuleScriptCreationParams>& params, +void ModuleScriptLoader::NotifyFetchFinishedError( const HeapVector<Member<ConsoleMessage>>& error_messages) { // [nospec] Abort the steps if the browsing context is discarded. if (!modulator_->HasValidContext()) { @@ -238,11 +237,17 @@ // <spec step="9">If any of the following conditions are met, set // moduleMap[url] to null, asynchronously complete this algorithm with null, // and abort these steps: ...</spec> - if (!params.has_value()) { - for (ConsoleMessage* error_message : error_messages) { - ExecutionContext::From(modulator_->GetScriptState()) - ->AddConsoleMessage(error_message); - } + for (ConsoleMessage* error_message : error_messages) { + ExecutionContext::From(modulator_->GetScriptState()) + ->AddConsoleMessage(error_message); + } + AdvanceState(State::kFinished); +} + +void ModuleScriptLoader::NotifyFetchFinishedSuccess( + const ModuleScriptCreationParams& params) { + // [nospec] Abort the steps if the browsing context is discarded. + if (!modulator_->HasValidContext()) { AdvanceState(State::kFinished); return; } @@ -253,7 +258,7 @@ // <spec step="12.2">Set module script to the result of creating a JavaScript // module script given source text, module map settings object, response's // url, and options.</spec> - switch (params->GetModuleType()) { + switch (params.GetModuleType()) { case ModuleScriptCreationParams::ModuleType::kJSONModule: DCHECK(base::FeatureList::IsEnabled(blink::features::kJSONModules)); module_script_ = ValueWrapperSyntheticModuleScript:: @@ -264,16 +269,17 @@ module_script_ = ValueWrapperSyntheticModuleScript:: CreateCSSWrapperSyntheticModuleScript(params, modulator_); break; - case ModuleScriptCreationParams::ModuleType::kJavaScriptModule: + case ModuleScriptCreationParams::ModuleType::kJavaScriptModule: { // Step 9. "Let source text be the result of UTF-8 decoding response's // body." [spec text] // Step 10. "Let module script be the result of creating // a module script given source text, module map settings object, // response's url, and options." [spec text] module_script_ = JSModuleScript::Create( - params.value(), params->SourceURL() /* base URL */, - ScriptSourceLocationType::kExternalFile, modulator_, options_); + params, ScriptSourceLocationType::kExternalFile, modulator_, + options_); break; + }; } AdvanceState(State::kFinished);
diff --git a/third_party/blink/renderer/core/loader/modulescript/module_script_loader.h b/third_party/blink/renderer/core/loader/modulescript/module_script_loader.h index 5c90418..1681aec4 100644 --- a/third_party/blink/renderer/core/loader/modulescript/module_script_loader.h +++ b/third_party/blink/renderer/core/loader/modulescript/module_script_loader.h
@@ -58,8 +58,8 @@ ModuleScriptLoaderClient*); // Implements ModuleScriptFetcher::Client. - void NotifyFetchFinished( - const base::Optional<ModuleScriptCreationParams>&, + void NotifyFetchFinishedSuccess(const ModuleScriptCreationParams&) override; + void NotifyFetchFinishedError( const HeapVector<Member<ConsoleMessage>>& error_messages) override; bool IsInitialState() const { return state_ == State::kInitial; }
diff --git a/third_party/blink/renderer/core/loader/modulescript/worker_module_script_fetcher.cc b/third_party/blink/renderer/core/loader/modulescript/worker_module_script_fetcher.cc index 03418efe..6b059a5 100644 --- a/third_party/blink/renderer/core/loader/modulescript/worker_module_script_fetcher.cc +++ b/third_party/blink/renderer/core/loader/modulescript/worker_module_script_fetcher.cc
@@ -90,12 +90,14 @@ ClearResource(); auto* script_resource = To<ScriptResource>(resource); - HeapVector<Member<ConsoleMessage>> error_messages; ModuleScriptCreationParams::ModuleType module_type; - if (!WasModuleLoadSuccessful(script_resource, &error_messages, - &module_type)) { - client_->NotifyFetchFinished(base::nullopt, error_messages); - return; + { + HeapVector<Member<ConsoleMessage>> error_messages; + if (!WasModuleLoadSuccessful(script_resource, &error_messages, + &module_type)) { + client_->NotifyFetchFinishedError(error_messages); + return; + } } NotifyClient(resource->Url(), module_type, @@ -147,7 +149,7 @@ mojom::ConsoleMessageSource::kSecurity, mojom::ConsoleMessageLevel::kError, "Refused to cross-origin redirects of the top-level worker script.")); - client_->NotifyFetchFinished(base::nullopt, error_messages); + client_->NotifyFetchFinishedError(error_messages); return; } @@ -176,13 +178,15 @@ response_origin_trial_tokens.get(), response.AppCacheID()); } - ModuleScriptCreationParams params(response.CurrentRequestUrl(), module_type, - source_text, cache_handler, - credentials_mode); // <spec step="12.7">Asynchronously complete the perform the fetch steps with // response.</spec> - client_->NotifyFetchFinished(params, error_messages); + const KURL& url = response.CurrentRequestUrl(); + // Create an external module script where base_url == source_url. + // https://html.spec.whatwg.org/multipage/webappapis.html#concept-script-base-url + client_->NotifyFetchFinishedSuccess(ModuleScriptCreationParams( + /*source_url=*/url, /*base_url=*/url, module_type, source_text, + cache_handler, credentials_mode)); } void WorkerModuleScriptFetcher::DidReceiveData(base::span<const char> span) { @@ -213,7 +217,7 @@ resource_response.CurrentRequestUrl().GetString(), /*loader=*/nullptr, -1)); worker_main_script_loader_->Cancel(); - client_->NotifyFetchFinished(base::nullopt, error_messages); + client_->NotifyFetchFinishedError(error_messages); return; } } @@ -230,8 +234,7 @@ } void WorkerModuleScriptFetcher::OnFailedLoadingWorkerMainScript() { - client_->NotifyFetchFinished(base::nullopt, - HeapVector<Member<ConsoleMessage>>()); + client_->NotifyFetchFinishedError(HeapVector<Member<ConsoleMessage>>()); } } // namespace blink
diff --git a/third_party/blink/renderer/core/loader/modulescript/worklet_module_script_fetcher.cc b/third_party/blink/renderer/core/loader/modulescript/worklet_module_script_fetcher.cc index f329dcc..f625741b 100644 --- a/third_party/blink/renderer/core/loader/modulescript/worklet_module_script_fetcher.cc +++ b/third_party/blink/renderer/core/loader/modulescript/worklet_module_script_fetcher.cc
@@ -49,8 +49,11 @@ HeapVector<Member<ConsoleMessage>> error_messages; ModuleScriptCreationParams::ModuleType module_type; if (WasModuleLoadSuccessful(script_resource, &error_messages, &module_type)) { - params.emplace(script_resource->GetResponse().CurrentRequestUrl(), - module_type, script_resource->SourceText(), + const KURL& url = script_resource->GetResponse().CurrentRequestUrl(); + // Create an external module script where base_url == source_url. + // https://html.spec.whatwg.org/multipage/webappapis.html#concept-script-base-url + params.emplace(/*source_url=*/url, /*base_url=*/url, module_type, + script_resource->SourceText(), script_resource->CacheHandler(), script_resource->GetResourceRequest().GetCredentialsMode()); }
diff --git a/third_party/blink/renderer/core/script/classic_pending_script.cc b/third_party/blink/renderer/core/script/classic_pending_script.cc index 35523e3..460936df 100644 --- a/third_party/blink/renderer/core/script/classic_pending_script.cc +++ b/third_party/blink/renderer/core/script/classic_pending_script.cc
@@ -126,71 +126,6 @@ DCHECK_EQ(is_external_, !!GetResource()); } -namespace { - -enum class StreamedBoolean { - // Must match BooleanStreamed in enums.xml. - kNotStreamed = 0, - kStreamed = 1, - kMaxValue = kStreamed -}; - -void RecordStartedStreamingHistogram(ScriptSchedulingType type, - bool did_use_streamer) { - StreamedBoolean streamed = did_use_streamer ? StreamedBoolean::kStreamed - : StreamedBoolean::kNotStreamed; - switch (type) { - case ScriptSchedulingType::kParserBlocking: { - UMA_HISTOGRAM_ENUMERATION( - "WebCore.Scripts.ParsingBlocking.StartedStreaming", streamed); - break; - } - case ScriptSchedulingType::kDefer: { - UMA_HISTOGRAM_ENUMERATION("WebCore.Scripts.Deferred.StartedStreaming", - streamed); - break; - } - case ScriptSchedulingType::kAsync: { - UMA_HISTOGRAM_ENUMERATION("WebCore.Scripts.Async.StartedStreaming", - streamed); - break; - } - default: { - UMA_HISTOGRAM_ENUMERATION("WebCore.Scripts.Other.StartedStreaming", - streamed); - break; - } - } -} - -void RecordNotStreamingReasonHistogram( - ScriptSchedulingType type, - ScriptStreamer::NotStreamingReason reason) { - switch (type) { - case ScriptSchedulingType::kParserBlocking: { - UMA_HISTOGRAM_ENUMERATION( - "WebCore.Scripts.ParsingBlocking.NotStreamingReason", reason); - break; - } - case ScriptSchedulingType::kDefer: { - UMA_HISTOGRAM_ENUMERATION("WebCore.Scripts.Deferred.NotStreamingReason", - reason); - break; - } - case ScriptSchedulingType::kAsync: { - UMA_HISTOGRAM_ENUMERATION("WebCore.Scripts.Async.NotStreamingReason", - reason); - break; - } - default: { - UMA_HISTOGRAM_ENUMERATION("WebCore.Scripts.Other.NotStreamingReason", - reason); - break; - } - } -} - -} // namespace void ClassicPendingScript::RecordThirdPartyRequestWithCookieIfNeeded( const ResourceResponse& response) const { @@ -236,16 +171,6 @@ kUndeferrableThirdPartySubresourceRequestWithCookie); } -void ClassicPendingScript::RecordStreamingHistogram( - ScriptSchedulingType type, - bool can_use_streamer, - ScriptStreamer::NotStreamingReason reason) { - RecordStartedStreamingHistogram(type, can_use_streamer); - if (!can_use_streamer) { - DCHECK_NE(ScriptStreamer::NotStreamingReason::kInvalid, reason); - RecordNotStreamingReasonHistogram(type, reason); - } -} void ClassicPendingScript::DisposeInternal() { MemoryPressureListenerRegistry::Instance().UnregisterClient(this); @@ -373,8 +298,9 @@ } DCHECK(!GetResource()); - RecordStreamingHistogram(GetSchedulingType(), false, - ScriptStreamer::NotStreamingReason::kInlineScript); + ScriptStreamer::RecordStreamingHistogram( + GetSchedulingType(), false, + ScriptStreamer::NotStreamingReason::kInlineScript); ScriptSourceCode source_code(source_text_for_inline_script_, source_location_type_, cache_handler, @@ -398,34 +324,25 @@ } // Check if we can use the script streamer. - bool did_stream = false; - ScriptStreamer::NotStreamingReason not_streamed_reason = - resource->NoStreamerReason(); - ScriptStreamer* streamer = resource->TakeStreamer(); - if (streamer) { - DCHECK_EQ(not_streamed_reason, - ScriptStreamer::NotStreamingReason::kInvalid); - if (streamer->IsStreamingSuppressed()) { - not_streamed_reason = streamer->StreamingSuppressedReason(); - } else if (ready_state_ == kErrorOccurred) { - not_streamed_reason = ScriptStreamer::NotStreamingReason::kErrorOccurred; - } else if (not_streamed_reason == - ScriptStreamer::NotStreamingReason::kInvalid) { - // streamer can be used to compile script. - CHECK_EQ(ready_state_, kReady); - did_stream = true; - } + ScriptStreamer* streamer; + ScriptStreamer::NotStreamingReason not_streamed_reason; + std::tie(streamer, not_streamed_reason) = ScriptStreamer::TakeFrom(resource); + + if (ready_state_ == kErrorOccurred) { + not_streamed_reason = ScriptStreamer::NotStreamingReason::kErrorOccurred; + streamer = nullptr; } - RecordStreamingHistogram(GetSchedulingType(), did_stream, - not_streamed_reason); + if (streamer) + CHECK_EQ(ready_state_, kReady); + ScriptStreamer::RecordStreamingHistogram(GetSchedulingType(), streamer, + not_streamed_reason); TRACE_EVENT_WITH_FLOW1(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "ClassicPendingScript::GetSource", this, TRACE_EVENT_FLAG_FLOW_IN, "not_streamed_reason", not_streamed_reason); - ScriptSourceCode source_code(did_stream ? streamer : nullptr, resource, - not_streamed_reason); + ScriptSourceCode source_code(streamer, resource, not_streamed_reason); // The base URL for external classic script is // // <spec href="https://html.spec.whatwg.org/C/#concept-script-base-url">
diff --git a/third_party/blink/renderer/core/script/classic_pending_script.h b/third_party/blink/renderer/core/script/classic_pending_script.h index 842eed8..503c7138 100644 --- a/third_party/blink/renderer/core/script/classic_pending_script.h +++ b/third_party/blink/renderer/core/script/classic_pending_script.h
@@ -97,10 +97,6 @@ void NotifyFinished(Resource*) override; String DebugName() const override { return "PendingScript"; } - static void RecordStreamingHistogram( - ScriptSchedulingType type, - bool can_use_streamer, - ScriptStreamer::NotStreamingReason reason); void RecordThirdPartyRequestWithCookieIfNeeded(const ResourceResponse&) const; // MemoryPressureListener
diff --git a/third_party/blink/renderer/core/script/js_module_script.cc b/third_party/blink/renderer/core/script/js_module_script.cc index d4d38ad..000b8815 100644 --- a/third_party/blink/renderer/core/script/js_module_script.cc +++ b/third_party/blink/renderer/core/script/js_module_script.cc
@@ -18,16 +18,17 @@ // <specdef // href="https://html.spec.whatwg.org/C/#creating-a-javascript-module-script"> JSModuleScript* JSModuleScript::Create( - const ModuleScriptCreationParams& params, - const KURL& base_url, + const ModuleScriptCreationParams& original_params, ScriptSourceLocationType source_location_type, Modulator* modulator, const ScriptFetchOptions& options, const TextPosition& start_position) { // <spec step="1">If scripting is disabled for settings's responsible browsing // context, then set source to the empty string.</spec> - if (modulator->IsScriptingDisabled()) - params.ClearSourceText(); + const ModuleScriptCreationParams& params = + modulator->IsScriptingDisabled() + ? original_params.CopyWithClearedSourceText() + : original_params; // <spec step="2">Let script be a new module script that this algorithm will // subsequently initialize.</spec> @@ -47,7 +48,7 @@ ModuleRecordProduceCacheData* produce_cache_data = nullptr; v8::Local<v8::Module> result = - ModuleRecord::Compile(isolate, params, base_url, options, start_position, + ModuleRecord::Compile(isolate, params, options, start_position, exception_state, modulator->GetV8CacheOptions(), source_location_type, &produce_cache_data); @@ -59,7 +60,7 @@ // be used for the speced algorithms, but may be used from inspector. JSModuleScript* script = CreateInternal( params.GetSourceText().length(), modulator, result, params.SourceURL(), - base_url, options, start_position, produce_cache_data); + params.BaseURL(), options, start_position, produce_cache_data); // <spec step="8">If result is a list of errors, then:</spec> if (exception_state.HadException()) {
diff --git a/third_party/blink/renderer/core/script/js_module_script.h b/third_party/blink/renderer/core/script/js_module_script.h index 93996d34..47464bc 100644 --- a/third_party/blink/renderer/core/script/js_module_script.h +++ b/third_party/blink/renderer/core/script/js_module_script.h
@@ -26,7 +26,6 @@ // https://html.spec.whatwg.org/C/#creating-a-javascript-module-script static JSModuleScript* Create( const ModuleScriptCreationParams& params, - const KURL& base_url, ScriptSourceLocationType, Modulator*, const ScriptFetchOptions&,
diff --git a/third_party/blink/renderer/core/script/module_map_test.cc b/third_party/blink/renderer/core/script/module_map_test.cc index 146bf8bd..2e76379 100644 --- a/third_party/blink/renderer/core/script/module_map_test.cc +++ b/third_party/blink/renderer/core/script/module_map_test.cc
@@ -21,6 +21,7 @@ #include "third_party/blink/renderer/platform/heap/handle.h" #include "third_party/blink/renderer/platform/loader/fetch/fetch_client_settings_object_snapshot.h" #include "third_party/blink/renderer/platform/testing/testing_platform_support_with_mock_scheduler.h" +#include "third_party/blink/renderer/platform/weborigin/kurl.h" namespace blink { @@ -116,11 +117,7 @@ ModuleScriptFetcher::Client* client) override { CHECK_EQ(request.GetScriptType(), mojom::blink::ScriptType::kModule); TestRequest* test_request = MakeGarbageCollected<TestRequest>( - ModuleScriptCreationParams( - request.Url(), - ModuleScriptCreationParams::ModuleType::kJavaScriptModule, - ParkableString(String("").ReleaseImpl()), nullptr, - request.GetResourceRequest().GetCredentialsMode()), + request.Url(), request.GetResourceRequest().GetCredentialsMode(), client); modulator_->test_requests_.push_back(test_request); } @@ -150,17 +147,20 @@ } struct TestRequest final : public GarbageCollected<TestRequest> { - TestRequest(const ModuleScriptCreationParams& params, + TestRequest(const KURL& url, + network::mojom::CredentialsMode credential_mode, ModuleScriptFetcher::Client* client) - : params_(params), client_(client) {} + : url_(url), credential_mode_(credential_mode), client_(client) {} void NotifyFetchFinished() { - client_->NotifyFetchFinished(*params_, - HeapVector<Member<ConsoleMessage>>()); + client_->NotifyFetchFinishedSuccess(ModuleScriptCreationParams( + url_, url_, ModuleScriptCreationParams::ModuleType::kJavaScriptModule, + ParkableString(String("").ReleaseImpl()), nullptr, credential_mode_)); } void Trace(Visitor* visitor) const { visitor->Trace(client_); } private: - base::Optional<ModuleScriptCreationParams> params_; + const KURL url_; + const network::mojom::CredentialsMode credential_mode_; Member<ModuleScriptFetcher::Client> client_; }; HeapVector<Member<TestRequest>> test_requests_;
diff --git a/third_party/blink/renderer/core/script/module_script_test.cc b/third_party/blink/renderer/core/script/module_script_test.cc index 8f5db341..407062c2 100644 --- a/third_party/blink/renderer/core/script/module_script_test.cc +++ b/third_party/blink/renderer/core/script/module_script_test.cc
@@ -82,11 +82,11 @@ const String& source_text, SingleCachedMetadataHandler* cache_handler) { ModuleScriptCreationParams params( - KURL("https://fox.url/script.js"), + KURL("https://fox.url/script.js"), KURL("https://fox.url/"), ModuleScriptCreationParams::ModuleType::kJavaScriptModule, ParkableString(source_text.IsolatedCopy().ReleaseImpl()), cache_handler, network::mojom::CredentialsMode::kOmit); - return JSModuleScript::Create(params, KURL("https://fox.url/"), + return JSModuleScript::Create(params, ScriptSourceLocationType::kExternalFile, modulator, ScriptFetchOptions()); }
diff --git a/third_party/blink/renderer/core/script/script_loader.cc b/third_party/blink/renderer/core/script/script_loader.cc index bb39a76..2a1971c 100644 --- a/third_party/blink/renderer/core/script/script_loader.cc +++ b/third_party/blink/renderer/core/script/script_loader.cc
@@ -464,11 +464,6 @@ SecurityPolicy::ReferrerPolicyFromString( referrerpolicy_attr, kDoNotSupportReferrerPolicyLegacyKeywords, &referrer_policy); - if (context_window->IsSecureContext() && - referrer_policy == network::mojom::ReferrerPolicy::kAlways) { - UseCounter::Count(*context_window, - WebFeature::kSetReferrerPolicyUnsafeUrlInSecureContext); - } } // Priority Hints is currently a non-standard feature, but we can assume the @@ -715,13 +710,13 @@ // text, settings object, base URL, and options.</spec> ModuleScriptCreationParams params( - source_url, + source_url, base_url, ModuleScriptCreationParams::ModuleType::kJavaScriptModule, ParkableString(source_text.Impl()), nullptr, options.CredentialsMode()); - ModuleScript* module_script = JSModuleScript::Create( - params, base_url, ScriptSourceLocationType::kInline, modulator, - options, position); + ModuleScript* module_script = + JSModuleScript::Create(params, ScriptSourceLocationType::kInline, + modulator, options, position); // <spec label="fetch-an-inline-module-script-graph" step="2">If script // is null, asynchronously complete this algorithm with null, and abort
diff --git a/third_party/blink/renderer/core/script/value_wrapper_synthetic_module_script.cc b/third_party/blink/renderer/core/script/value_wrapper_synthetic_module_script.cc index d61fa63..e3650df6 100644 --- a/third_party/blink/renderer/core/script/value_wrapper_synthetic_module_script.cc +++ b/third_party/blink/renderer/core/script/value_wrapper_synthetic_module_script.cc
@@ -25,7 +25,7 @@ // https://whatpr.org/html/4898/webappapis.html#creating-a-css-module-script ValueWrapperSyntheticModuleScript* ValueWrapperSyntheticModuleScript::CreateCSSWrapperSyntheticModuleScript( - const base::Optional<ModuleScriptCreationParams>& params, + const ModuleScriptCreationParams& params, Modulator* settings_object) { DCHECK(settings_object->HasValidContext()); ScriptState* script_state = settings_object->GetScriptState(); @@ -40,7 +40,7 @@ v8::Local<v8::Value> error = V8ThrowException::CreateTypeError( isolate, "Cannot create CSS Module in non-document context"); return ValueWrapperSyntheticModuleScript::CreateWithError( - v8::Local<v8::Value>(), settings_object, params->SourceURL(), KURL(), + v8::Local<v8::Value>(), settings_object, params.SourceURL(), KURL(), ScriptFetchOptions(), error); } CSSStyleSheetInit* init = CSSStyleSheetInit::Create(); @@ -50,26 +50,26 @@ v8::Local<v8::Value> error = exception_state.GetException(); exception_state.ClearException(); return ValueWrapperSyntheticModuleScript::CreateWithError( - v8::Local<v8::Value>(), settings_object, params->SourceURL(), KURL(), + v8::Local<v8::Value>(), settings_object, params.SourceURL(), KURL(), ScriptFetchOptions(), error); } - style_sheet->replaceSync(params->GetSourceText().ToString(), exception_state); + style_sheet->replaceSync(params.GetSourceText().ToString(), exception_state); if (exception_state.HadException()) { v8::Local<v8::Value> error = exception_state.GetException(); exception_state.ClearException(); return ValueWrapperSyntheticModuleScript::CreateWithError( - v8::Local<v8::Value>(), settings_object, params->SourceURL(), KURL(), + v8::Local<v8::Value>(), settings_object, params.SourceURL(), KURL(), ScriptFetchOptions(), error); } v8::Local<v8::Value> v8_value_stylesheet = ToV8(style_sheet, script_state); return ValueWrapperSyntheticModuleScript::CreateWithDefaultExport( - v8_value_stylesheet, settings_object, params->SourceURL(), KURL(), + v8_value_stylesheet, settings_object, params.SourceURL(), KURL(), ScriptFetchOptions()); } ValueWrapperSyntheticModuleScript* ValueWrapperSyntheticModuleScript::CreateJSONWrapperSyntheticModuleScript( - const base::Optional<ModuleScriptCreationParams>& params, + const ModuleScriptCreationParams& params, Modulator* settings_object) { DCHECK(settings_object->HasValidContext()); ScriptState::Scope scope(settings_object->GetScriptState()); @@ -78,7 +78,7 @@ v8::Isolate* isolate = context->GetIsolate(); v8::TryCatch try_catch(isolate); v8::Local<v8::String> original_json = - V8String(isolate, params->GetSourceText()); + V8String(isolate, params.GetSourceText()); v8::Local<v8::Value> parsed_json; ExceptionState exception_state(isolate, ExceptionState::kExecutionContext, "ModuleScriptLoader", @@ -102,11 +102,11 @@ v8::Local<v8::Value> error = exception_state.GetException(); exception_state.ClearException(); return ValueWrapperSyntheticModuleScript::CreateWithError( - parsed_json, settings_object, params->SourceURL(), KURL(), + parsed_json, settings_object, params.SourceURL(), KURL(), ScriptFetchOptions(), error); } else { return ValueWrapperSyntheticModuleScript::CreateWithDefaultExport( - parsed_json, settings_object, params->SourceURL(), KURL(), + parsed_json, settings_object, params.SourceURL(), KURL(), ScriptFetchOptions()); } }
diff --git a/third_party/blink/renderer/core/script/value_wrapper_synthetic_module_script.h b/third_party/blink/renderer/core/script/value_wrapper_synthetic_module_script.h index 184fe69..edb234e 100644 --- a/third_party/blink/renderer/core/script/value_wrapper_synthetic_module_script.h +++ b/third_party/blink/renderer/core/script/value_wrapper_synthetic_module_script.h
@@ -26,14 +26,12 @@ : public ModuleScript { public: static ValueWrapperSyntheticModuleScript* - CreateCSSWrapperSyntheticModuleScript( - const base::Optional<ModuleScriptCreationParams>& params, - Modulator* settings_object); + CreateCSSWrapperSyntheticModuleScript(const ModuleScriptCreationParams&, + Modulator* settings_object); static ValueWrapperSyntheticModuleScript* - CreateJSONWrapperSyntheticModuleScript( - const base::Optional<ModuleScriptCreationParams>& params, - Modulator* settings_object); + CreateJSONWrapperSyntheticModuleScript(const ModuleScriptCreationParams&, + Modulator* settings_object); static ValueWrapperSyntheticModuleScript* CreateWithDefaultExport( v8::Local<v8::Value> value, @@ -78,4 +76,4 @@ } // namespace blink -#endif // THIRD_PARTY_BLINK_RENDERER_CORE_SCRIPT_VALUE_WRAPPER_SYNTHETIC_MODULE_SCRIPT_H_ \ No newline at end of file +#endif // THIRD_PARTY_BLINK_RENDERER_CORE_SCRIPT_VALUE_WRAPPER_SYNTHETIC_MODULE_SCRIPT_H_
diff --git a/third_party/blink/renderer/core/testing/module_test_base.cc b/third_party/blink/renderer/core/testing/module_test_base.cc index 0d94895..41aa9e82 100644 --- a/third_party/blink/renderer/core/testing/module_test_base.cc +++ b/third_party/blink/renderer/core/testing/module_test_base.cc
@@ -27,10 +27,11 @@ const KURL& url, ExceptionState& exception_state) { ModuleScriptCreationParams params( - url, ModuleScriptCreationParams::ModuleType::kJavaScriptModule, + /*source_url=*/url, /*base_url=*/url, + ModuleScriptCreationParams::ModuleType::kJavaScriptModule, ParkableString(source.Impl()), nullptr, network::mojom::CredentialsMode::kOmit); - return ModuleRecord::Compile(isolate, params, url, ScriptFetchOptions(), + return ModuleRecord::Compile(isolate, params, ScriptFetchOptions(), TextPosition::MinimumPosition(), exception_state); }
diff --git a/third_party/blink/renderer/core/workers/worklet_module_responses_map_test.cc b/third_party/blink/renderer/core/workers/worklet_module_responses_map_test.cc index 731ba99..64d82de4 100644 --- a/third_party/blink/renderer/core/workers/worklet_module_responses_map_test.cc +++ b/third_party/blink/renderer/core/workers/worklet_module_responses_map_test.cc
@@ -47,22 +47,21 @@ public: enum class Result { kInitial, kOK, kFailed }; - void NotifyFetchFinished( - const base::Optional<ModuleScriptCreationParams>& params, + void NotifyFetchFinishedError( const HeapVector<Member<ConsoleMessage>>&) override { ASSERT_EQ(Result::kInitial, result_); - if (params) { - result_ = Result::kOK; - params_.emplace(*params); - } else { - result_ = Result::kFailed; - } + result_ = Result::kFailed; + } + + void NotifyFetchFinishedSuccess( + const ModuleScriptCreationParams& params) override { + ASSERT_EQ(Result::kInitial, result_); + result_ = Result::kOK; + params_.emplace(std::move(params)); } Result GetResult() const { return result_; } - base::Optional<ModuleScriptCreationParams> GetParams() const { - return params_; - } + bool HasParams() const { return params_.has_value(); } private: Result result_ = Result::kInitial; @@ -108,7 +107,7 @@ clients.push_back(MakeGarbageCollected<ClientImpl>()); Fetch(kUrl, clients[0]); EXPECT_EQ(ClientImpl::Result::kInitial, clients[0]->GetResult()); - EXPECT_FALSE(clients[0]->GetParams().has_value()); + EXPECT_FALSE(clients[0]->HasParams()); // The entry is now being fetched. Following read calls should wait for the // completion. @@ -125,7 +124,7 @@ RunUntilIdle(); for (auto client : clients) { EXPECT_EQ(ClientImpl::Result::kOK, client->GetResult()); - EXPECT_TRUE(client->GetParams().has_value()); + EXPECT_TRUE(client->HasParams()); } } @@ -139,7 +138,7 @@ clients.push_back(MakeGarbageCollected<ClientImpl>()); Fetch(kUrl, clients[0]); EXPECT_EQ(ClientImpl::Result::kInitial, clients[0]->GetResult()); - EXPECT_FALSE(clients[0]->GetParams().has_value()); + EXPECT_FALSE(clients[0]->HasParams()); // The entry is now being fetched. Following read calls should wait for the // completion. @@ -156,7 +155,7 @@ RunUntilIdle(); for (auto client : clients) { EXPECT_EQ(ClientImpl::Result::kFailed, client->GetResult()); - EXPECT_FALSE(client->GetParams().has_value()); + EXPECT_FALSE(client->HasParams()); } } @@ -174,7 +173,7 @@ clients.push_back(MakeGarbageCollected<ClientImpl>()); Fetch(kUrl1, clients[0]); EXPECT_EQ(ClientImpl::Result::kInitial, clients[0]->GetResult()); - EXPECT_FALSE(clients[0]->GetParams().has_value()); + EXPECT_FALSE(clients[0]->HasParams()); // The entry is now being fetched. Following read calls for |kUrl1| should // wait for the completion. @@ -186,7 +185,7 @@ clients.push_back(MakeGarbageCollected<ClientImpl>()); Fetch(kUrl2, clients[2]); EXPECT_EQ(ClientImpl::Result::kInitial, clients[2]->GetResult()); - EXPECT_FALSE(clients[2]->GetParams().has_value()); + EXPECT_FALSE(clients[2]->HasParams()); // The entry is now being fetched. Following read calls for |kUrl2| should // wait for the completion. @@ -201,13 +200,13 @@ platform_->GetURLLoaderMockFactory()->ServeAsynchronousRequests(); RunUntilIdle(); EXPECT_EQ(ClientImpl::Result::kFailed, clients[0]->GetResult()); - EXPECT_FALSE(clients[0]->GetParams().has_value()); + EXPECT_FALSE(clients[0]->HasParams()); EXPECT_EQ(ClientImpl::Result::kFailed, clients[1]->GetResult()); - EXPECT_FALSE(clients[1]->GetParams().has_value()); + EXPECT_FALSE(clients[1]->HasParams()); EXPECT_EQ(ClientImpl::Result::kOK, clients[2]->GetResult()); - EXPECT_TRUE(clients[2]->GetParams().has_value()); + EXPECT_TRUE(clients[2]->HasParams()); EXPECT_EQ(ClientImpl::Result::kOK, clients[3]->GetResult()); - EXPECT_TRUE(clients[3]->GetParams().has_value()); + EXPECT_TRUE(clients[3]->HasParams()); } TEST_F(WorkletModuleResponsesMapTest, InvalidURL) { @@ -217,7 +216,7 @@ Fetch(kEmptyURL, client1); RunUntilIdle(); EXPECT_EQ(ClientImpl::Result::kFailed, client1->GetResult()); - EXPECT_FALSE(client1->GetParams().has_value()); + EXPECT_FALSE(client1->HasParams()); const KURL kNullURL = NullURL(); ASSERT_TRUE(kNullURL.IsNull()); @@ -225,7 +224,7 @@ Fetch(kNullURL, client2); RunUntilIdle(); EXPECT_EQ(ClientImpl::Result::kFailed, client2->GetResult()); - EXPECT_FALSE(client2->GetParams().has_value()); + EXPECT_FALSE(client2->HasParams()); const KURL kInvalidURL; ASSERT_FALSE(kInvalidURL.IsValid()); @@ -233,7 +232,7 @@ Fetch(kInvalidURL, client3); RunUntilIdle(); EXPECT_EQ(ClientImpl::Result::kFailed, client3->GetResult()); - EXPECT_FALSE(client3->GetParams().has_value()); + EXPECT_FALSE(client3->HasParams()); } TEST_F(WorkletModuleResponsesMapTest, Dispose) { @@ -252,7 +251,7 @@ clients.push_back(MakeGarbageCollected<ClientImpl>()); Fetch(kUrl1, clients[0]); EXPECT_EQ(ClientImpl::Result::kInitial, clients[0]->GetResult()); - EXPECT_FALSE(clients[0]->GetParams().has_value()); + EXPECT_FALSE(clients[0]->HasParams()); // The entry is now being fetched. Following read calls for |kUrl1| should // wait for the completion. @@ -265,7 +264,7 @@ clients.push_back(MakeGarbageCollected<ClientImpl>()); Fetch(kUrl2, clients[2]); EXPECT_EQ(ClientImpl::Result::kInitial, clients[2]->GetResult()); - EXPECT_FALSE(clients[2]->GetParams().has_value()); + EXPECT_FALSE(clients[2]->HasParams()); // The entry is now being fetched. Following read calls for |kUrl2| should // wait for the completion. @@ -278,7 +277,7 @@ RunUntilIdle(); for (auto client : clients) { EXPECT_EQ(ClientImpl::Result::kFailed, client->GetResult()); - EXPECT_FALSE(client->GetParams().has_value()); + EXPECT_FALSE(client->HasParams()); } }
diff --git a/third_party/blink/renderer/modules/accessibility/BUILD.gn b/third_party/blink/renderer/modules/accessibility/BUILD.gn index 87f1b2f..c9b2ea07 100644 --- a/third_party/blink/renderer/modules/accessibility/BUILD.gn +++ b/third_party/blink/renderer/modules/accessibility/BUILD.gn
@@ -50,8 +50,6 @@ "ax_slider.h", "ax_sparse_attribute_setter.cc", "ax_sparse_attribute_setter.h", - "ax_svg_root.cc", - "ax_svg_root.h", "ax_validation_message.cc", "ax_validation_message.h", "ax_virtual_object.cc",
diff --git a/third_party/blink/renderer/modules/accessibility/ax_layout_object.cc b/third_party/blink/renderer/modules/accessibility/ax_layout_object.cc index c2c3e6c..a3c15ce 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_layout_object.cc +++ b/third_party/blink/renderer/modules/accessibility/ax_layout_object.cc
@@ -91,7 +91,6 @@ #include "third_party/blink/renderer/modules/accessibility/ax_inline_text_box.h" #include "third_party/blink/renderer/modules/accessibility/ax_mock_object.h" #include "third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.h" -#include "third_party/blink/renderer/modules/accessibility/ax_svg_root.h" #include "third_party/blink/renderer/platform/bindings/exception_state.h" #include "third_party/blink/renderer/platform/text/platform_locale.h" #include "third_party/blink/renderer/platform/text/text_direction.h" @@ -199,8 +198,6 @@ return ax::mojom::blink::Role::kImageMap; if (IsA<HTMLInputElement>(node)) return ButtonRoleType(); - if (IsSVGImage()) - return ax::mojom::blink::Role::kSvgRoot; return ax::mojom::blink::Role::kImage; } @@ -292,8 +289,6 @@ void AXLayoutObject::Detach() { AXNodeObject::Detach(); - DetachRemoteSVGRoot(); - #if DCHECK_IS_ON() if (layout_object_) layout_object_->SetHasAXObject(false); @@ -1534,14 +1529,6 @@ return result; } -AXObject* AXLayoutObject::ElementAccessibilityHitTest( - const IntPoint& point) const { - if (IsSVGImage()) - return RemoteSVGElementHitTest(point); - - return AXObject::ElementAccessibilityHitTest(point); -} - // // Low-level accessibility tree exploration, only for use within the // accessibility module. @@ -2449,34 +2436,4 @@ return nullptr; } -void AXLayoutObject::DetachRemoteSVGRoot() { - if (AXSVGRoot* root = RemoteSVGRootElement()) - root->SetParent(nullptr); -} - -AXObject* AXLayoutObject::RemoteSVGElementHitTest(const IntPoint& point) const { - AXObject* remote = RemoteSVGRootElement(); - if (!remote) - return nullptr; - - IntSize offset = - point - RoundedIntPoint(GetBoundsInFrameCoordinates().Location()); - return remote->AccessibilityHitTest(IntPoint(offset)); -} - -// The boundingBox for elements within the remote SVG element needs to be offset -// by its position within the parent page, otherwise they are in relative -// coordinates only. -void AXLayoutObject::OffsetBoundingBoxForRemoteSVGElement( - LayoutRect& rect) const { - for (AXObject* parent = ParentObject(); parent; - parent = parent->ParentObject()) { - if (parent->IsAXSVGRoot()) { - rect.MoveBy( - parent->ParentObject()->GetBoundsInFrameCoordinates().Location()); - break; - } - } -} - } // namespace blink
diff --git a/third_party/blink/renderer/modules/accessibility/ax_layout_object.h b/third_party/blink/renderer/modules/accessibility/ax_layout_object.h index 799fb9a..aefa84c 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_layout_object.h +++ b/third_party/blink/renderer/modules/accessibility/ax_layout_object.h
@@ -135,7 +135,6 @@ // Hit testing. AXObject* AccessibilityHitTest(const IntPoint&) const override; - AXObject* ElementAccessibilityHitTest(const IntPoint&) const override; // High-level accessibility tree access. Other modules should only use these // functions. @@ -183,9 +182,6 @@ bool IsTabItemSelected() const; AXObject* AccessibilityImageMapHitTest(HTMLAreaElement*, const IntPoint&) const; - void DetachRemoteSVGRoot(); - AXObject* RemoteSVGElementHitTest(const IntPoint&) const; - void OffsetBoundingBoxForRemoteSVGElement(LayoutRect&) const; bool FindAllTableCellsWithRole(ax::mojom::blink::Role, AXObjectVector&) const; LayoutRect ComputeElementRect() const;
diff --git a/third_party/blink/renderer/modules/accessibility/ax_node_object.cc b/third_party/blink/renderer/modules/accessibility/ax_node_object.cc index 0c083f2..f056d5a 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_node_object.cc +++ b/third_party/blink/renderer/modules/accessibility/ax_node_object.cc
@@ -99,14 +99,12 @@ #include "third_party/blink/renderer/core/page/focus_controller.h" #include "third_party/blink/renderer/core/page/page.h" #include "third_party/blink/renderer/core/svg/svg_element.h" -#include "third_party/blink/renderer/core/svg/svg_svg_element.h" #include "third_party/blink/renderer/modules/accessibility/ax_image_map_link.h" #include "third_party/blink/renderer/modules/accessibility/ax_inline_text_box.h" #include "third_party/blink/renderer/modules/accessibility/ax_layout_object.h" #include "third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.h" #include "third_party/blink/renderer/modules/accessibility/ax_position.h" #include "third_party/blink/renderer/modules/accessibility/ax_range.h" -#include "third_party/blink/renderer/modules/accessibility/ax_svg_root.h" #include "third_party/blink/renderer/modules/media_controls/elements/media_control_elements_helper.h" #include "third_party/blink/renderer/platform/graphics/image_data_buffer.h" #include "third_party/blink/renderer/platform/keyboard_codes.h" @@ -3213,17 +3211,6 @@ } } -AXSVGRoot* AXNodeObject::RemoteSVGRootElement() const { - // FIXME(dmazzoni): none of this code properly handled multiple references to - // the same remote SVG document. I'm disabling this support until it can be - // fixed properly. - return nullptr; -} - -void AXNodeObject::AddRemoteSVGChildren() { - AddChild(RemoteSVGRootElement()); -} - void AXNodeObject::AddNodeChildren() { if (!node_) return; @@ -3262,7 +3249,6 @@ AddNodeChildren(); AddPopupChildren(); - AddRemoteSVGChildren(); AddImageMapChildren(); AddInlineTextBoxChildren(false); AddValidationMessageChild();
diff --git a/third_party/blink/renderer/modules/accessibility/ax_node_object.h b/third_party/blink/renderer/modules/accessibility/ax_node_object.h index edc1999..124ca76 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_node_object.h +++ b/third_party/blink/renderer/modules/accessibility/ax_node_object.h
@@ -37,7 +37,6 @@ namespace blink { class AXObjectCacheImpl; -class AXSVGRoot; class Element; class HTMLLabelElement; class Node; @@ -270,10 +269,6 @@ // Inline text boxes. void LoadInlineTextBoxes() override; - // SVG. - bool IsSVGImage() const { return RemoteSVGRootElement(); } - AXSVGRoot* RemoteSVGRootElement() const; - virtual LayoutBoxModelObject* GetLayoutBoxModelObject() const { return nullptr; } @@ -313,7 +308,6 @@ void AddInlineTextBoxChildren(bool force); void AddImageMapChildren(); void AddPopupChildren(); - void AddRemoteSVGChildren(); bool IsHtmlTable() const; void AddTableChildren(); void AddValidationMessageChild();
diff --git a/third_party/blink/renderer/modules/accessibility/ax_object.cc b/third_party/blink/renderer/modules/accessibility/ax_object.cc index 5a4d9ba5..67164e5 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_object.cc +++ b/third_party/blink/renderer/modules/accessibility/ax_object.cc
@@ -1183,10 +1183,6 @@ return false; } -bool AXObject::IsAXSVGRoot() const { - return false; -} - bool AXObject::IsValidationMessage() const { return false; }
diff --git a/third_party/blink/renderer/modules/accessibility/ax_object.h b/third_party/blink/renderer/modules/accessibility/ax_object.h index 4b52e757..0715d9d2 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_object.h +++ b/third_party/blink/renderer/modules/accessibility/ax_object.h
@@ -409,7 +409,6 @@ virtual bool IsProgressIndicator() const; virtual bool IsAXRadioInput() const; virtual bool IsSlider() const; - virtual bool IsAXSVGRoot() const; virtual bool IsValidationMessage() const; virtual bool IsVirtualObject() const;
diff --git a/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.cc b/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.cc index 61423b6..9b0611f 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.cc +++ b/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.cc
@@ -86,7 +86,6 @@ #include "third_party/blink/renderer/modules/accessibility/ax_progress_indicator.h" #include "third_party/blink/renderer/modules/accessibility/ax_relation_cache.h" #include "third_party/blink/renderer/modules/accessibility/ax_slider.h" -#include "third_party/blink/renderer/modules/accessibility/ax_svg_root.h" #include "third_party/blink/renderer/modules/accessibility/ax_validation_message.h" #include "third_party/blink/renderer/modules/accessibility/ax_virtual_object.h" #include "third_party/blink/renderer/modules/media_controls/elements/media_control_elements_helper.h" @@ -454,9 +453,6 @@ return MakeGarbageCollected<AXSlider>(layout_object, *this); } - if (layout_object->IsSVGRoot()) - return MakeGarbageCollected<AXSVGRoot>(layout_object, *this); - if (layout_object->IsBoxModelObject()) { auto* css_box = To<LayoutBoxModelObject>(layout_object); if (auto* select_element = DynamicTo<HTMLSelectElement>(node)) {
diff --git a/third_party/blink/renderer/modules/accessibility/ax_svg_root.cc b/third_party/blink/renderer/modules/accessibility/ax_svg_root.cc deleted file mode 100644 index 6bee578..0000000 --- a/third_party/blink/renderer/modules/accessibility/ax_svg_root.cc +++ /dev/null
@@ -1,77 +0,0 @@ -/* - * Copyright (C) 2012 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "third_party/blink/renderer/modules/accessibility/ax_svg_root.h" - -#include "third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.h" - -namespace blink { - -AXSVGRoot::AXSVGRoot(LayoutObject* layout_object, - AXObjectCacheImpl& ax_object_cache) - : AXLayoutObject(layout_object, ax_object_cache) {} - -AXSVGRoot::~AXSVGRoot() = default; - -void AXSVGRoot::SetParent(AXObject* parent) { - // Only update the parent to another objcet if it wasn't already set to - // something. Multiple elements in an HTML document can reference - // the same remote SVG document, and in that case the parent should just - // stay with the first one. - if (!parent_ || !parent) - parent_ = parent; -} - -AXObject* AXSVGRoot::ComputeParent() const { - DCHECK(!IsDetached()); - // If a parent was set because this is a remote SVG resource, use that - // but otherwise, we should rely on the standard layout tree for the parent. - if (parent_) - return parent_; - - return AXLayoutObject::ComputeParent(); -} - -// SVG AAM 1.0 S8.2: the default role for an SVG root is "group". -ax::mojom::Role AXSVGRoot::DetermineAccessibilityRole() { - ax::mojom::Role role = AXLayoutObject::DetermineAccessibilityRole(); - if (role == ax::mojom::Role::kUnknown) - role = ax::mojom::Role::kGroup; - return role; -} - -// SVG elements are only ignored if they are a descendant of a leaf or when a -// generic element would also be ignored. -bool AXSVGRoot::ComputeAccessibilityIsIgnored(IgnoredReasons* reasons) const { - if (IsDescendantOfLeafNode()) - return AXLayoutObject::ComputeAccessibilityIsIgnored(reasons); - - return AccessibilityIsIgnoredByDefault(reasons); -} - -} // namespace blink
diff --git a/third_party/blink/renderer/modules/accessibility/ax_svg_root.h b/third_party/blink/renderer/modules/accessibility/ax_svg_root.h deleted file mode 100644 index 32ce72f..0000000 --- a/third_party/blink/renderer/modules/accessibility/ax_svg_root.h +++ /dev/null
@@ -1,58 +0,0 @@ -/* - * Copyright (C) 2012 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of - * its contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_ACCESSIBILITY_AX_SVG_ROOT_H_ -#define THIRD_PARTY_BLINK_RENDERER_MODULES_ACCESSIBILITY_AX_SVG_ROOT_H_ - -#include "base/macros.h" -#include "third_party/blink/renderer/modules/accessibility/ax_layout_object.h" - -namespace blink { - -class AXObjectCacheImpl; - -class AXSVGRoot final : public AXLayoutObject { - public: - AXSVGRoot(LayoutObject*, AXObjectCacheImpl&); - ~AXSVGRoot() override; - - void SetParent(AXObject*) override; - - ax::mojom::Role DetermineAccessibilityRole() override; - bool ComputeAccessibilityIsIgnored(IgnoredReasons*) const override; - - private: - AXObject* ComputeParent() const override; - bool IsAXSVGRoot() const override { return true; } - - DISALLOW_COPY_AND_ASSIGN(AXSVGRoot); -}; - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_ACCESSIBILITY_AX_SVG_ROOT_H_
diff --git a/third_party/blink/renderer/modules/native_io/BUILD.gn b/third_party/blink/renderer/modules/native_io/BUILD.gn index f06538c..0ca85149 100644 --- a/third_party/blink/renderer/modules/native_io/BUILD.gn +++ b/third_party/blink/renderer/modules/native_io/BUILD.gn
@@ -12,10 +12,10 @@ "native_io_error.h", "native_io_file.cc", "native_io_file.h", + "native_io_file_manager.cc", + "native_io_file_manager.h", "native_io_file_sync.cc", "native_io_file_sync.h", - "native_io_manager.cc", - "native_io_manager.h", ] deps = [ "//third_party/blink/renderer/platform" ]
diff --git a/third_party/blink/renderer/modules/native_io/global_native_io.cc b/third_party/blink/renderer/modules/native_io/global_native_io.cc index b381fe7..a0418c0f 100644 --- a/third_party/blink/renderer/modules/native_io/global_native_io.cc +++ b/third_party/blink/renderer/modules/native_io/global_native_io.cc
@@ -13,7 +13,7 @@ #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/workers/worker_global_scope.h" -#include "third_party/blink/renderer/modules/native_io/native_io_manager.h" +#include "third_party/blink/renderer/modules/native_io/native_io_file_manager.h" #include "third_party/blink/renderer/platform/heap/handle.h" #include "third_party/blink/renderer/platform/mojo/heap_mojo_remote.h" #include "third_party/blink/renderer/platform/supplementable.h" @@ -41,8 +41,8 @@ explicit GlobalNativeIOImpl(T& supplementable) : Supplement<T>(supplementable) {} - NativeIOManager* GetNativeIOManager(T& scope) { - if (!native_io_manager_) { + NativeIOFileManager* GetNativeIOFileManager(T& scope) { + if (!native_io_file_manager_) { ExecutionContext* execution_context = scope.GetExecutionContext(); if (&execution_context->GetBrowserInterfaceBroker() == &GetEmptyBrowserInterfaceBroker()) { @@ -53,19 +53,19 @@ execution_context->GetBrowserInterfaceBroker().GetInterface( backend.BindNewPipeAndPassReceiver( execution_context->GetTaskRunner(TaskType::kMiscPlatformAPI))); - native_io_manager_ = MakeGarbageCollected<NativeIOManager>( + native_io_file_manager_ = MakeGarbageCollected<NativeIOFileManager>( execution_context, std::move(backend)); } - return native_io_manager_; + return native_io_file_manager_; } void Trace(Visitor* visitor) const override { - visitor->Trace(native_io_manager_); + visitor->Trace(native_io_file_manager_); Supplement<T>::Trace(visitor); } private: - Member<NativeIOManager> native_io_manager_; + Member<NativeIOFileManager> native_io_file_manager_; }; // static @@ -75,15 +75,15 @@ } // namespace // static -NativeIOManager* GlobalNativeIO::nativeIO(LocalDOMWindow& window) { - return GlobalNativeIOImpl<LocalDOMWindow>::From(window).GetNativeIOManager( - window); +NativeIOFileManager* GlobalNativeIO::nativeIO(LocalDOMWindow& window) { + return GlobalNativeIOImpl<LocalDOMWindow>::From(window) + .GetNativeIOFileManager(window); } // static -NativeIOManager* GlobalNativeIO::nativeIO(WorkerGlobalScope& worker) { - return GlobalNativeIOImpl<WorkerGlobalScope>::From(worker).GetNativeIOManager( - worker); +NativeIOFileManager* GlobalNativeIO::nativeIO(WorkerGlobalScope& worker) { + return GlobalNativeIOImpl<WorkerGlobalScope>::From(worker) + .GetNativeIOFileManager(worker); } } // namespace blink
diff --git a/third_party/blink/renderer/modules/native_io/global_native_io.h b/third_party/blink/renderer/modules/native_io/global_native_io.h index bb9b05b..1a9bc02 100644 --- a/third_party/blink/renderer/modules/native_io/global_native_io.h +++ b/third_party/blink/renderer/modules/native_io/global_native_io.h
@@ -10,7 +10,7 @@ namespace blink { class LocalDOMWindow; -class NativeIOManager; +class NativeIOFileManager; class WorkerGlobalScope; // The "nativeIO" attribute on the Window global and Worker global scope. @@ -18,8 +18,8 @@ STATIC_ONLY(GlobalNativeIO); public: - static NativeIOManager* nativeIO(LocalDOMWindow&); - static NativeIOManager* nativeIO(WorkerGlobalScope&); + static NativeIOFileManager* nativeIO(LocalDOMWindow&); + static NativeIOFileManager* nativeIO(WorkerGlobalScope&); }; } // namespace blink
diff --git a/third_party/blink/renderer/modules/native_io/idls.gni b/third_party/blink/renderer/modules/native_io/idls.gni index 694bfa92..5f9a67a 100644 --- a/third_party/blink/renderer/modules/native_io/idls.gni +++ b/third_party/blink/renderer/modules/native_io/idls.gni
@@ -4,8 +4,8 @@ modules_idl_files = [ "native_io_file.idl", + "native_io_file_manager.idl", "native_io_file_sync.idl", - "native_io_manager.idl", ] modules_dependency_idl_files = [
diff --git a/third_party/blink/renderer/modules/native_io/native_io_manager.cc b/third_party/blink/renderer/modules/native_io/native_io_file_manager.cc similarity index 87% rename from third_party/blink/renderer/modules/native_io/native_io_manager.cc rename to third_party/blink/renderer/modules/native_io/native_io_file_manager.cc index deb3548..d25e795 100644 --- a/third_party/blink/renderer/modules/native_io/native_io_manager.cc +++ b/third_party/blink/renderer/modules/native_io/native_io_file_manager.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "third_party/blink/renderer/modules/native_io/native_io_manager.h" +#include "third_party/blink/renderer/modules/native_io/native_io_file_manager.h" #include <algorithm> #include <utility> @@ -120,7 +120,7 @@ } // namespace -NativeIOManager::NativeIOManager( +NativeIOFileManager::NativeIOFileManager( ExecutionContext* execution_context, HeapMojoRemote<mojom::blink::NativeIOHost> backend) : ExecutionContextClient(execution_context), @@ -129,14 +129,14 @@ execution_context->GetTaskRunner(TaskType::kMiscPlatformAPI)), backend_(std::move(backend)) { backend_.set_disconnect_handler(WTF::Bind( - &NativeIOManager::OnBackendDisconnect, WrapWeakPersistent(this))); + &NativeIOFileManager::OnBackendDisconnect, WrapWeakPersistent(this))); } -NativeIOManager::~NativeIOManager() = default; +NativeIOFileManager::~NativeIOFileManager() = default; -ScriptPromise NativeIOManager::open(ScriptState* script_state, - String name, - ExceptionState& exception_state) { +ScriptPromise NativeIOFileManager::open(ScriptState* script_state, + String name, + ExceptionState& exception_state) { if (!IsValidNativeIOName(name)) { exception_state.ThrowTypeError("Invalid file name"); return ScriptPromise(); @@ -166,9 +166,9 @@ return resolver->Promise(); } -ScriptPromise NativeIOManager::Delete(ScriptState* script_state, - String name, - ExceptionState& exception_state) { +ScriptPromise NativeIOFileManager::Delete(ScriptState* script_state, + String name, + ExceptionState& exception_state) { if (!IsValidNativeIOName(name)) { exception_state.ThrowTypeError("Invalid file name"); return ScriptPromise(); @@ -188,8 +188,8 @@ return resolver->Promise(); } -ScriptPromise NativeIOManager::getAll(ScriptState* script_state, - ExceptionState& exception_state) { +ScriptPromise NativeIOFileManager::getAll(ScriptState* script_state, + ExceptionState& exception_state) { if (!backend_.is_bound()) { ThrowNativeIOWithError(exception_state, mojom::blink::NativeIOError::New( @@ -204,10 +204,10 @@ return resolver->Promise(); } -ScriptPromise NativeIOManager::rename(ScriptState* script_state, - String old_name, - String new_name, - ExceptionState& exception_state) { +ScriptPromise NativeIOFileManager::rename(ScriptState* script_state, + String old_name, + String new_name, + ExceptionState& exception_state) { if (!IsValidNativeIOName(old_name) || !IsValidNativeIOName(new_name)) { exception_state.ThrowTypeError("Invalid file name"); return ScriptPromise(); @@ -227,8 +227,9 @@ return resolver->Promise(); } -NativeIOFileSync* NativeIOManager::openSync(String name, - ExceptionState& exception_state) { +NativeIOFileSync* NativeIOFileManager::openSync( + String name, + ExceptionState& exception_state) { if (!IsValidNativeIOName(name)) { exception_state.ThrowTypeError("Invalid file name"); return nullptr; @@ -266,7 +267,8 @@ std::move(backing_file), std::move(backend_file), execution_context); } -void NativeIOManager::deleteSync(String name, ExceptionState& exception_state) { +void NativeIOFileManager::deleteSync(String name, + ExceptionState& exception_state) { if (!IsValidNativeIOName(name)) { exception_state.ThrowTypeError("Invalid file name"); return; @@ -290,7 +292,8 @@ DCHECK(call_succeeded) << "Mojo call failed"; } -Vector<String> NativeIOManager::getAllSync(ExceptionState& exception_state) { +Vector<String> NativeIOFileManager::getAllSync( + ExceptionState& exception_state) { Vector<String> result; if (!backend_.is_bound()) { ThrowNativeIOWithError(exception_state, @@ -311,9 +314,9 @@ return result; } -void NativeIOManager::renameSync(String old_name, - String new_name, - ExceptionState& exception_state) { +void NativeIOFileManager::renameSync(String old_name, + String new_name, + ExceptionState& exception_state) { if (!IsValidNativeIOName(old_name) || !IsValidNativeIOName(new_name)) { exception_state.ThrowTypeError("Invalid file name"); return; @@ -338,13 +341,13 @@ DCHECK(call_succeeded) << "Mojo call failed"; } -void NativeIOManager::Trace(Visitor* visitor) const { +void NativeIOFileManager::Trace(Visitor* visitor) const { visitor->Trace(backend_); ScriptWrappable::Trace(visitor); ExecutionContextClient::Trace(visitor); } -void NativeIOManager::OnBackendDisconnect() { +void NativeIOFileManager::OnBackendDisconnect() { backend_.reset(); }
diff --git a/third_party/blink/renderer/modules/native_io/native_io_manager.h b/third_party/blink/renderer/modules/native_io/native_io_file_manager.h similarity index 78% rename from third_party/blink/renderer/modules/native_io/native_io_manager.h rename to third_party/blink/renderer/modules/native_io/native_io_file_manager.h index 52d0771f..f85808ad 100644 --- a/third_party/blink/renderer/modules/native_io/native_io_manager.h +++ b/third_party/blink/renderer/modules/native_io/native_io_file_manager.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_NATIVE_IO_NATIVE_IO_MANAGER_H_ -#define THIRD_PARTY_BLINK_RENDERER_MODULES_NATIVE_IO_NATIVE_IO_MANAGER_H_ +#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_NATIVE_IO_NATIVE_IO_FILE_MANAGER_H_ +#define THIRD_PARTY_BLINK_RENDERER_MODULES_NATIVE_IO_NATIVE_IO_FILE_MANAGER_H_ #include "third_party/blink/public/mojom/native_io/native_io.mojom-blink.h" #include "third_party/blink/renderer/bindings/core/v8/script_promise.h" @@ -21,20 +21,21 @@ class NativeIOFileSync; class ScriptState; -class NativeIOManager final : public ScriptWrappable, - public ExecutionContextClient { +class NativeIOFileManager final : public ScriptWrappable, + public ExecutionContextClient { DEFINE_WRAPPERTYPEINFO(); public: - explicit NativeIOManager(ExecutionContext*, - HeapMojoRemote<mojom::blink::NativeIOHost> backend); + explicit NativeIOFileManager( + ExecutionContext*, + HeapMojoRemote<mojom::blink::NativeIOHost> backend); - NativeIOManager(const NativeIOManager&) = delete; - NativeIOManager& operator=(const NativeIOManager&) = delete; + NativeIOFileManager(const NativeIOFileManager&) = delete; + NativeIOFileManager& operator=(const NativeIOFileManager&) = delete; // Needed because of the // mojo::Remote<blink::mojom::NativeIOHost> - ~NativeIOManager() override; + ~NativeIOFileManager() override; ScriptPromise open(ScriptState*, String name, ExceptionState&); ScriptPromise Delete(ScriptState*, String name, ExceptionState&); @@ -65,4 +66,4 @@ } // namespace blink -#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_NATIVE_IO_NATIVE_IO_MANAGER_H_ +#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_NATIVE_IO_NATIVE_IO_FILE_MANAGER_H_
diff --git a/third_party/blink/renderer/modules/native_io/native_io_file_manager.idl b/third_party/blink/renderer/modules/native_io/native_io_file_manager.idl new file mode 100644 index 0000000..911642d --- /dev/null +++ b/third_party/blink/renderer/modules/native_io/native_io_file_manager.idl
@@ -0,0 +1,29 @@ +// Copyright 2020 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. + +// https://github.com/fivedots/nativeio-explainer + +[Exposed = (Window, Worker), + RuntimeEnabled = NativeIO, + SecureContext] interface NativeIOFileManager { + [ CallWith = ScriptState, RaisesException ] Promise<NativeIOFile> open( + DOMString name); + [ Exposed = DedicatedWorker, RaisesException ] NativeIOFileSync openSync( + DOMString name); + + [ CallWith = ScriptState, ImplementedAs = Delete, + RaisesException ] Promise<void> delete (DOMString name); + [ Exposed = DedicatedWorker, RaisesException ] void deleteSync( + DOMString name); + + [ CallWith = ScriptState, RaisesException ] Promise<sequence<DOMString>> + getAll(); + [ Exposed = DedicatedWorker, RaisesException ] sequence<DOMString> + getAllSync(); + + [ CallWith = ScriptState, RaisesException ] Promise<void> rename( + DOMString old_name, DOMString new_name); + [ Exposed = DedicatedWorker, RaisesException ] void renameSync( + DOMString old_name, DOMString new_name); +};
diff --git a/third_party/blink/renderer/modules/native_io/native_io_manager.idl b/third_party/blink/renderer/modules/native_io/native_io_manager.idl deleted file mode 100644 index 860eff12..0000000 --- a/third_party/blink/renderer/modules/native_io/native_io_manager.idl +++ /dev/null
@@ -1,33 +0,0 @@ -// Copyright 2020 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. - -// https://github.com/fivedots/nativeio-explainer - -[ - Exposed=(Window,Worker), - RuntimeEnabled=NativeIO, - SecureContext -] interface NativeIOManager { - [ - CallWith=ScriptState, RaisesException - ] Promise<NativeIOFile> open(DOMString name); - [ - Exposed=DedicatedWorker, RaisesException - ] NativeIOFileSync openSync(DOMString name); - - [ - CallWith=ScriptState, ImplementedAs=Delete, RaisesException - ] Promise<void> delete(DOMString name); - [Exposed=DedicatedWorker, RaisesException] void deleteSync(DOMString name); - - [ - CallWith=ScriptState, RaisesException - ] Promise<sequence<DOMString>> getAll(); - [Exposed=DedicatedWorker, RaisesException] sequence<DOMString> getAllSync(); - - [ - CallWith=ScriptState, RaisesException - ] Promise<void> rename(DOMString old_name, DOMString new_name); - [Exposed=DedicatedWorker, RaisesException] void renameSync(DOMString old_name, DOMString new_name); -};
diff --git a/third_party/blink/renderer/modules/native_io/window_native_io.idl b/third_party/blink/renderer/modules/native_io/window_native_io.idl index 1b78cc42..45844fa 100644 --- a/third_party/blink/renderer/modules/native_io/window_native_io.idl +++ b/third_party/blink/renderer/modules/native_io/window_native_io.idl
@@ -9,5 +9,5 @@ RuntimeEnabled=NativeIO, SecureContext ] partial interface Window { - readonly attribute NativeIOManager nativeIO; + readonly attribute NativeIOFileManager nativeIO; };
diff --git a/third_party/blink/renderer/modules/native_io/worker_global_scope_native_io.idl b/third_party/blink/renderer/modules/native_io/worker_global_scope_native_io.idl index aa03a6c..a960868 100644 --- a/third_party/blink/renderer/modules/native_io/worker_global_scope_native_io.idl +++ b/third_party/blink/renderer/modules/native_io/worker_global_scope_native_io.idl
@@ -9,5 +9,5 @@ RuntimeEnabled=NativeIO, SecureContext ] partial interface WorkerGlobalScope { - readonly attribute NativeIOManager nativeIO; + readonly attribute NativeIOFileManager nativeIO; };
diff --git a/third_party/blink/renderer/modules/webid/web_id.cc b/third_party/blink/renderer/modules/webid/web_id.cc index 85a0622..119757dd 100644 --- a/third_party/blink/renderer/modules/webid/web_id.cc +++ b/third_party/blink/renderer/modules/webid/web_id.cc
@@ -21,14 +21,59 @@ void OnRequestIdToken(ScriptPromiseResolver* resolver, mojom::blink::RequestIdTokenStatus status, const WTF::String& id_token) { - // TODO(kenrb): Provide better messages for different error codes. - if (status != mojom::blink::RequestIdTokenStatus::kSuccess) { - resolver->Reject(MakeGarbageCollected<DOMException>( - DOMExceptionCode::kNetworkError, - "Error loading the identity provider.")); - return; + switch (status) { + case mojom::blink::RequestIdTokenStatus::kApprovalDeclined: { + resolver->Reject(MakeGarbageCollected<DOMException>( + DOMExceptionCode::kAbortError, "User declined the sign-in attempt.")); + return; + } + case mojom::blink::RequestIdTokenStatus::kErrorTooManyRequests: { + resolver->Reject(MakeGarbageCollected<DOMException>( + DOMExceptionCode::kAbortError, + "Only one WebID request may be outstanding at one time.")); + return; + } + case mojom::blink::RequestIdTokenStatus:: + kErrorWebIdNotSupportedByProvider: { + resolver->Reject(MakeGarbageCollected<DOMException>( + DOMExceptionCode::kNetworkError, + "The indicated provider does not support WebID.")); + return; + } + case mojom::blink::RequestIdTokenStatus::kErrorFetchingWellKnown: { + resolver->Reject(MakeGarbageCollected<DOMException>( + DOMExceptionCode::kNetworkError, + "Error fetching the provider's .well-known configuration.")); + return; + } + case mojom::blink::RequestIdTokenStatus::kErrorInvalidWellKnown: { + resolver->Reject(MakeGarbageCollected<DOMException>( + DOMExceptionCode::kNetworkError, + "Provider's .well-known configuration is invalid.")); + return; + } + case mojom::blink::RequestIdTokenStatus::kErrorFetchingSignin: { + resolver->Reject(MakeGarbageCollected<DOMException>( + DOMExceptionCode::kNetworkError, + "Error attempting to reach the provider's sign-in endpoint.")); + return; + } + case mojom::blink::RequestIdTokenStatus::kErrorInvalidSigninResponse: { + resolver->Reject(MakeGarbageCollected<DOMException>( + DOMExceptionCode::kNetworkError, + "Provider's sign-in response is invalid")); + return; + } + case mojom::blink::RequestIdTokenStatus::kError: { + resolver->Reject(MakeGarbageCollected<DOMException>( + DOMExceptionCode::kNetworkError, "Error retrieving an id token.")); + return; + } + case mojom::blink::RequestIdTokenStatus::kSuccess: { + resolver->Resolve(); + return; + } } - resolver->Resolve(id_token); } void OnProvideIdToken(ScriptPromiseResolver* resolver,
diff --git a/third_party/blink/renderer/platform/instrumentation/partition_alloc_memory_dump_provider.cc b/third_party/blink/renderer/platform/instrumentation/partition_alloc_memory_dump_provider.cc index 5bc0a994..026b6634 100644 --- a/third_party/blink/renderer/platform/instrumentation/partition_alloc_memory_dump_provider.cc +++ b/third_party/blink/renderer/platform/instrumentation/partition_alloc_memory_dump_provider.cc
@@ -92,6 +92,13 @@ all_thread_caches_stats.alloc_count); base::UmaHistogramPercentage("Memory.PartitionAlloc.ThreadCache.HitRate", hit_rate_percent); + + int batch_fill_rate_percent = + static_cast<int>((100 * all_thread_caches_stats.batch_fill_count) / + all_thread_caches_stats.alloc_count); + base::UmaHistogramPercentage( + "Memory.PartitionAlloc.ThreadCache.BatchFillRate", + batch_fill_rate_percent); } if (thread_cache_stats.alloc_count) { @@ -101,6 +108,13 @@ base::UmaHistogramPercentage( "Memory.PartitionAlloc.ThreadCache.HitRate.MainThread", hit_rate_percent); + + int batch_fill_rate_percent = + static_cast<int>((100 * thread_cache_stats.batch_fill_count) / + thread_cache_stats.alloc_count); + base::UmaHistogramPercentage( + "Memory.PartitionAlloc.ThreadCache.BatchFillRate.MainThread", + batch_fill_rate_percent); } } }
diff --git a/third_party/blink/renderer/platform/instrumentation/partition_alloc_memory_dump_provider_test.cc b/third_party/blink/renderer/platform/instrumentation/partition_alloc_memory_dump_provider_test.cc index b15bf31a..7010e7b 100644 --- a/third_party/blink/renderer/platform/instrumentation/partition_alloc_memory_dump_provider_test.cc +++ b/third_party/blink/renderer/platform/instrumentation/partition_alloc_memory_dump_provider_test.cc
@@ -30,11 +30,20 @@ 1); histogram_tester.ExpectTotalCount( "Memory.PartitionAlloc.ThreadCache.HitRate.MainThread", 1); + + histogram_tester.ExpectTotalCount( + "Memory.PartitionAlloc.ThreadCache.BatchFillRate", 1); + histogram_tester.ExpectTotalCount( + "Memory.PartitionAlloc.ThreadCache.HitRate.MainThread", 1); #else histogram_tester.ExpectTotalCount("Memory.PartitionAlloc.ThreadCache.HitRate", 0); histogram_tester.ExpectTotalCount( "Memory.PartitionAlloc.ThreadCache.HitRate.MainThread", 0); + histogram_tester.ExpectTotalCount( + "Memory.PartitionAlloc.ThreadCache.BatchFillRate", 0); + histogram_tester.ExpectTotalCount( + "Memory.PartitionAlloc.ThreadCache.BatchFillRate.MainThread", 0); #endif // !BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) && // defined(PA_THREAD_CACHE_SUPPORTED) && // !defined(MEMORY_TOOL_REPLACES_ALLOCATOR)
diff --git a/third_party/blink/renderer/platform/mojo/heap_mojo_receiver_set.h b/third_party/blink/renderer/platform/mojo/heap_mojo_receiver_set.h index 8cb14a2..81bf5e0 100644 --- a/third_party/blink/renderer/platform/mojo/heap_mojo_receiver_set.h +++ b/third_party/blink/renderer/platform/mojo/heap_mojo_receiver_set.h
@@ -44,6 +44,16 @@ HeapMojoReceiverSet& operator=(const HeapMojoReceiverSet&) = delete; // Methods to redirect to mojo::ReceiverSet: + void set_disconnect_handler(base::RepeatingClosure handler) { + wrapper_->receiver_set().set_disconnect_handler(std::move(handler)); + } + + void set_disconnect_with_reason_handler( + mojo::RepeatingConnectionErrorWithReasonCallback handler) { + wrapper_->receiver_set().set_disconnect_with_reason_handler( + std::move(handler)); + } + mojo::ReceiverId Add(mojo::PendingReceiver<Interface> receiver, scoped_refptr<base::SequencedTaskRunner> task_runner) { DCHECK(task_runner);
diff --git a/third_party/blink/renderer/platform/weborigin/security_origin_test.cc b/third_party/blink/renderer/platform/weborigin/security_origin_test.cc index ef61940..64d19c23 100644 --- a/third_party/blink/renderer/platform/weborigin/security_origin_test.cc +++ b/third_party/blink/renderer/platform/weborigin/security_origin_test.cc
@@ -210,6 +210,9 @@ bool is_secure; const char* url; } inputs[] = { + // TODO(crbug.com/1153336): Should SecurityOrigin::IsSecure be aligned + // with network::IsURLPotentiallyTrustworthy? + // https://w3c.github.io/webappsec-secure-contexts/#is-url-trustworthy {false, "blob:ftp://evil:99/578223a1-8c13-17b3-84d5-eca045ae384a"}, {false, "blob:http://example.com/578223a1-8c13-17b3-84d5-eca045ae384a"}, {false, "file:///etc/passwd"}, @@ -219,8 +222,25 @@ {true, "blob:https://example.com/578223a1-8c13-17b3-84d5-eca045ae384a"}, {true, "https://example.com/"}, {true, "wss://example.com/"}, - {true, "about:blank"}, + {true, "about:srcdoc"}, + {true, "about:about"}, + {true, "data:text/html,Hello"}, + {false, + "filesystem:http://example.com/578223a1-8c13-17b3-84d5-eca045ae384a"}, + {true, + "filesystem:https://example.com/578223a1-8c13-17b3-84d5-eca045ae384a"}, + {true, "blob:data:text/html,Hello"}, + {true, "blob:about:blank"}, + {false, "filesystem:data:text/html,Hello"}, + {false, "filesystem:about:blank"}, + {false, + "blob:blob:https://example.com/578223a1-8c13-17b3-84d5-eca045ae384a"}, + {false, + "filesystem:blob:https://example.com/" + "578223a1-8c13-17b3-84d5-eca045ae384a"}, + {false, "custom-scheme://example.com"}, + {true, "quic-transport://example.com/counter"}, {false, ""}, {false, "\0"}, }; @@ -232,10 +252,19 @@ EXPECT_FALSE(SecurityOrigin::IsSecure(NullURL())); } +TEST_F(SecurityOriginTest, IsCustomSchemeSecure) { + url::ScopedSchemeRegistryForTests scoped_registry; + url::AddSecureScheme("custom-scheme"); + EXPECT_TRUE(SecurityOrigin::IsSecure(KURL("custom-scheme://example.com"))); +} + TEST_F(SecurityOriginTest, IsSecureViaTrustworthy) { + // TODO(crbug.com/1153336): Should SecurityOrigin::IsSecure be aligned with + // network::IsURLPotentiallyTrustworthy? + // https://w3c.github.io/webappsec-secure-contexts/#is-url-trustworthy const char* urls[] = {"http://localhost/", "http://localhost:8080/", "http://127.0.0.1/", "http://127.0.0.1:8080/", - "http://[::1]/"}; + "http://[::1]/", "http://vhost.localhost/"}; for (const char* test : urls) { KURL url(test);
diff --git a/third_party/blink/web_tests/FlagExpectations/disable-layout-ng b/third_party/blink/web_tests/FlagExpectations/disable-layout-ng index f0c5d33..c31694d2 100644 --- a/third_party/blink/web_tests/FlagExpectations/disable-layout-ng +++ b/third_party/blink/web_tests/FlagExpectations/disable-layout-ng
@@ -13,6 +13,7 @@ # Tests that fail in legacy but pass in NG # accessibility/ +crbug.com/1159730 accessibility/inline-text-box-next-on-line.html [ Failure ] crbug.com/591099 accessibility/listitem-presentation-inherited.html [ Failure ] crbug.com/591099 accessibility/presentation-owned-elements.html [ Failure ] crbug.com/591099 accessibility/role-attribute.html [ Failure ] @@ -59,16 +60,24 @@ ### external/wpt/css/css-flexbox/ crbug.com/591099 external/wpt/css/css-flexbox/dynamic-baseline-change.html [ Failure ] crbug.com/591099 external/wpt/css/css-flexbox/dynamic-baseline-change-nested.html [ Failure ] +crbug.com/1132627 external/wpt/css/css-flexbox/flex-minimum-width-flex-items-007.xht [ Failure ] +crbug.com/591099 external/wpt/css/css-flexbox/flexbox-align-self-horiz-002.xhtml [ Failure ] +crbug.com/553838 external/wpt/css/css-flexbox/flexbox-min-height-auto-002a.html [ Failure ] +crbug.com/553838 external/wpt/css/css-flexbox/flexbox-min-height-auto-002c.html [ Failure ] +crbug.com/1132627 external/wpt/css/css-flexbox/flexbox-min-width-auto-002a.html [ Failure ] +crbug.com/1132627 external/wpt/css/css-flexbox/flexbox-min-width-auto-002c.html [ Failure ] crbug.com/591099 external/wpt/css/css-flexbox/image-as-flexitem-size-003.html [ Failure ] crbug.com/591099 external/wpt/css/css-flexbox/image-as-flexitem-size-003v.html [ Failure ] crbug.com/591099 external/wpt/css/css-flexbox/image-as-flexitem-size-004.html [ Failure ] crbug.com/591099 external/wpt/css/css-flexbox/image-as-flexitem-size-004v.html [ Failure ] -crbug.com/1132627 external/wpt/css/css-flexbox/flex-minimum-width-flex-items-007.xht [ Failure ] ### external/wpt/css/css-fonts/ crbug.com/591099 external/wpt/css/css-fonts/font-features-across-space-1.html [ Failure ] crbug.com/591099 external/wpt/css/css-fonts/font-features-across-space-3.html [ Failure ] +### external/wpt/css/css-images +crbug.com/1076121 external/wpt/css/css-images/image-orientation/image-orientation-list-style-image.html [ Failure ] + ### external/wpt/css/css-layout-api/ crbug.com/591099 external/wpt/css/css-layout-api/* [ Skip ] @@ -226,8 +235,17 @@ crbug.com/591099 external/wpt/css/css-text/white-space/line-edge-white-space-collapse-001.html [ Failure ] crbug.com/591099 external/wpt/css/css-text/white-space/line-edge-white-space-collapse-002.html [ Failure ] crbug.com/591099 external/wpt/css/css-text/white-space/pre-line-with-space-and-newline.html [ Failure ] +crbug.com/1155633 external/wpt/css/css-text/white-space/break-spaces-with-ideographic-space-001.html [ Failure ] +crbug.com/1155633 external/wpt/css/css-text/white-space/break-spaces-with-ideographic-space-005.html [ Failure ] crbug.com/1151784 external/wpt/css/css-text/white-space/seg-break-transformation-016.tentative.html [ Failure ] crbug.com/1151784 external/wpt/css/css-text/white-space/seg-break-transformation-017.tentative.html [ Failure ] +crbug.com/1155633 external/wpt/css/css-text/white-space/trailing-ideographic-space-break-spaces-001.html [ Failure ] +crbug.com/1155633 external/wpt/css/css-text/white-space/trailing-ideographic-space-break-spaces-002.html [ Failure ] +crbug.com/1155633 external/wpt/css/css-text/white-space/trailing-ideographic-space-break-spaces-003.html [ Failure ] +crbug.com/1155633 external/wpt/css/css-text/white-space/trailing-ideographic-space-break-spaces-004.html [ Failure ] +crbug.com/1155633 external/wpt/css/css-text/white-space/trailing-ideographic-space-break-spaces-005.html [ Failure ] +crbug.com/1155633 external/wpt/css/css-text/white-space/trailing-ideographic-space-break-spaces-006.html [ Failure ] +crbug.com/1155633 external/wpt/css/css-text/white-space/trailing-ideographic-space-break-spaces-007.html [ Failure ] ### external/wpt/css/css-text/word-break/ crbug.com/591099 external/wpt/css/css-text/word-break/word-break-break-all-004.html [ Failure ] @@ -373,10 +391,7 @@ crbug.com/591099 external/wpt/css/css-content/quotes-033.html [ Failure ] ### external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/ -crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-align-self-horiz-002.xhtml [ Failure ] crbug.com/886592 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/align3/flex-abspos-staticpos-margin-002.html [ Failure ] -crbug.com/1132627 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-min-width-auto-002a.html [ Failure ] -crbug.com/1132627 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-min-width-auto-002c.html [ Failure ] ### external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/ib-split/ crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/ib-split/emptyspan-1.html [ Failure ] @@ -384,6 +399,10 @@ crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/ib-split/remove-from-split-inline-6.html [ Failure ] crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/ib-split/split-inner-inline-2.html [ Failure ] +### external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/selectors4/ +crbug.com/576815 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/selectors4/dir-style-01a.html [ Failure ] +crbug.com/576815 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/selectors4/dir-style-01b.html [ Failure ] + ### external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/sizing/ crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/sizing/block-size-with-min-or-max-content-1a.html [ Failure ] crbug.com/591099 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/sizing/block-size-with-min-or-max-content-1b.html [ Failure ] @@ -498,6 +517,9 @@ ### virtual/layout_ng_printing/ virtual/layout_ng_printing/* [ Skip ] +### virtual/layout_ng_table/ +virtual/layout_ng_table/* [ Skip ] + ### virtual/plz-dedicated-worker/external/wpt/service-workers/service-worker/ crbug.com/591099 virtual/plz-dedicated-worker/external/wpt/service-workers/service-worker/registration-updateviacache.https.html [ Failure ] @@ -558,8 +580,6 @@ crbug.com/987000 external/wpt/css/css-flexbox/flex-aspect-ratio-img-column-012.html [ Failure ] crbug.com/987000 external/wpt/css/css-flexbox/flex-aspect-ratio-img-column-015.html [ Failure ] crbug.com/987000 external/wpt/css/css-flexbox/svg-root-as-flex-item-002.html [ Failure ] -crbug.com/553838 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-min-height-auto-002a.html [ Failure ] -crbug.com/553838 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-min-height-auto-002c.html [ Failure ] # These would need a rebaseline back from LayoutNGBlockFlow to LayoutBlockFlow crbug.com/864567 paint/float/float-under-inline-self-painting-change.html [ Failure ]
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index c1e15f2..d565972 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -5906,3 +5906,11 @@ # Sheriff 2020-12-14 crbug.com/1046784 http/tests/devtools/console/console-context-selector.js [ Pass Timeout ] + +# Sheriff 2020-12-17 +crbug.com/1043488 [ Win7 ] fast/forms/suggestion-picker/datetimelocal-suggestion-picker-appearance-with-scroll-bar.html [ Pass Failure ] +crbug.com/1043488 [ Win7 ] fast/forms/suggestion-picker/time-suggestion-picker-appearance-with-scroll-bar.html [ Pass Failure ] +crbug.com/1043488 [ Win7 ] fast/forms/suggestion-picker/time-suggestion-picker-appearance-locale-hebrew.html [ Pass Failure ] +crbug.com/1043488 [ Win7 ] fast/forms/suggestion-picker/month-suggestion-picker-appearance-rtl.html [ Pass Failure ] +crbug.com/1043488 [ Win7 ] fast/forms/suggestion-picker/week-suggestion-picker-appearance-rtl.html [ Pass Failure ] +crbug.com/1043488 [ Win7 ] fast/forms/suggestion-picker/date-suggestion-picker-appearance-rtl.html [ Pass Failure ]
diff --git a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json index 946a89c..6b0b6033 100644 --- a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json +++ b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json
@@ -1074,6 +1074,13 @@ {} ] ], + "mmultiscripts-with-two-prescripts.html": [ + "54f938460636bb351d9da20611fd872d6b888ca6", + [ + null, + {} + ] + ], "multicol-on-token-elements.html": [ "9fc00eb6911b625a7443a3e1ec65ada7daf25105", [ @@ -255690,11 +255697,11 @@ [] ], "android_weblayer.py": [ - "6110450b7282c6cfa4afaca1ec2b2ef580f7a714", + "ca93004b6e75822a6dbae7d2d4beacacd94f86e7", [] ], "android_webview.py": [ - "d0773873508fe7f327afe751d32eaddbecea9a3f", + "27a09f5d2cdeb5557118a059e0dcb2a88f967c1b", [] ], "base.py": [ @@ -255702,15 +255709,15 @@ [] ], "chrome.py": [ - "fd251a431c306f3bb3b12b848f548d8eff07a466", + "d3e27a9c5f65f7aa754263cb57846285d2857540", [] ], "chrome_android.py": [ - "485b96f31e7deafdddf82fd375aea7d7497e9fa7", + "607b783566e1b751dc9d37936a6c64f4d843e3df", [] ], "chrome_ios.py": [ - "6db0188e55ebff8d3a40f9a15dc714419edacbeb", + "ecdbc3a17623907dc9bd99505d1e5ee0bc747c7b", [] ], "chrome_spki_certs.py": [ @@ -255718,7 +255725,7 @@ [] ], "edge.py": [ - "bdb37b3f84c2cdc4010a7a289a53564822a3a34c", + "b908684bbb3e7eae9982173ed26a9a9e39b6b437", [] ], "edge_webdriver.py": [ @@ -255726,51 +255733,51 @@ [] ], "edgechromium.py": [ - "9e1ef3836bebffd1f21ea1fb1aea458a78f12a1f", + "67105e425c794c32cd99f8216418d47e640dc7ba", [] ], "epiphany.py": [ - "f6c4c602a38c043637cf9dbc8bbb5350ec94527e", + "a3384436a1d643c6576ebb731db5c458f8ad2687", [] ], "firefox.py": [ - "e95bc93deca0ef0f825e9d7997450f16a7353819", + "1fa0bceb17bd436d5463ebc5938e41d511009e38", [] ], "firefox_android.py": [ - "b219079de3df793ba5c74de8706d4c9ad0526194", + "ca6ea96013b67ed548f5487520253ca61e0ae32c", [] ], "ie.py": [ - "78c22b909acf410038ff06769366662ab0c589a0", + "3a86c1b6ccb5aabfe210158f6be613f690543375", [] ], "opera.py": [ - "805fedee636cd22155ed143cf1148f3c2f5d98e7", + "a34f41955383c08e98c4d38d7804231c17e9297a", [] ], "safari.py": [ - "cb2b175d4dfbc3166e4ad5a6afe174ffdbc6ff8a", + "312d4db9c6382f7aff5cd75772f0edf73e538565", [] ], "sauce.py": [ - "c57ac942ed4e7624a0a7d115df3a210aec5d9ee1", + "3497c5c277288e51f6677000e57057ebcd99a210", [] ], "servo.py": [ - "b9476540ac7c53162e70669c4b7ba4883fd75f75", + "a65ed5ead4e55c45cfd7aa7921f0717216ce6a45", [] ], "servodriver.py": [ - "43794e41706d6ccc1f686655c8edeca95e3c4c62", + "ed85cbf3b9bd04ea192641b480ace44dc6d433bf", [] ], "webkit.py": [ - "da93cf1643995d95b8d6de1f70c7731b5559768b", + "590e472aca961b865bf0dbc836c942f62b506ae8", [] ], "webkitgtk_minibrowser.py": [ - "d8b9744bd743e39ce19f008e7f40cbc80e80107c", + "5b7a360fb608352e26971570af06c5bb8466255b", [] ] }, @@ -255792,7 +255799,7 @@ [] ], "base.py": [ - "55518685494e2464354250ae6e72babdef46dcf7", + "51d752cdebc61976066a15c5dd9e778f9378ff00", [] ], "executorchrome.py": [ @@ -255857,7 +255864,7 @@ [] ], "runner.py": [ - "3d32917659b3900f9e464670d2cdc39b8ff180a0", + "113eff99fee8d4a126d9c741b36cbfb8e8a1eebd", [] ] }, @@ -256099,7 +256106,7 @@ } }, "wptrunner.py": [ - "e1d9ef8b1a91dd2d44458c8c9d027537991f4cc9", + "b02805ff7e3df6645722e63fbc2d9715959c1ce6", [] ], "wpttest.py": [
diff --git a/third_party/blink/web_tests/external/wpt/mathml/crashtests/mmultiscripts-with-two-prescripts.html b/third_party/blink/web_tests/external/wpt/mathml/crashtests/mmultiscripts-with-two-prescripts.html new file mode 100644 index 0000000..54f9384 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/mathml/crashtests/mmultiscripts-with-two-prescripts.html
@@ -0,0 +1,8 @@ +<!DOCTYPE html> +<math> + <mmultiscripts> + <mrow></mrow> + <mprescripts></mprescripts> + <mprescripts></mprescripts> + </mmultiscripts> +</math>
diff --git a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/browsers/android_weblayer.py b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/browsers/android_weblayer.py index 6110450..ca93004b 100644 --- a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/browsers/android_weblayer.py +++ b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/browsers/android_weblayer.py
@@ -28,14 +28,14 @@ require_arg(kwargs, "webdriver_binary") -def browser_kwargs(test_type, run_info_data, config, **kwargs): +def browser_kwargs(logger, test_type, run_info_data, config, **kwargs): return {"binary": kwargs["binary"], "device_serial": kwargs["device_serial"], "webdriver_binary": kwargs["webdriver_binary"], "webdriver_args": kwargs.get("webdriver_args")} -def executor_kwargs(test_type, server_config, cache_manager, run_info_data, +def executor_kwargs(logger, test_type, server_config, cache_manager, run_info_data, **kwargs): # Use update() to modify the global list in place. _wptserve_ports.update(set(
diff --git a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/browsers/android_webview.py b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/browsers/android_webview.py index d0773873..27a09f5 100644 --- a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/browsers/android_webview.py +++ b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/browsers/android_webview.py
@@ -28,14 +28,14 @@ require_arg(kwargs, "webdriver_binary") -def browser_kwargs(test_type, run_info_data, config, **kwargs): +def browser_kwargs(logger, test_type, run_info_data, config, **kwargs): return {"binary": kwargs["binary"], "device_serial": kwargs["device_serial"], "webdriver_binary": kwargs["webdriver_binary"], "webdriver_args": kwargs.get("webdriver_args")} -def executor_kwargs(test_type, server_config, cache_manager, run_info_data, +def executor_kwargs(logger, test_type, server_config, cache_manager, run_info_data, **kwargs): # Use update() to modify the global list in place. _wptserve_ports.update(set(
diff --git a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/browsers/chrome.py b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/browsers/chrome.py index fd251a431..d3e27a9 100644 --- a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/browsers/chrome.py +++ b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/browsers/chrome.py
@@ -28,13 +28,13 @@ require_arg(kwargs, "webdriver_binary") -def browser_kwargs(test_type, run_info_data, config, **kwargs): +def browser_kwargs(logger, test_type, run_info_data, config, **kwargs): return {"binary": kwargs["binary"], "webdriver_binary": kwargs["webdriver_binary"], "webdriver_args": kwargs.get("webdriver_args")} -def executor_kwargs(test_type, server_config, cache_manager, run_info_data, +def executor_kwargs(logger, test_type, server_config, cache_manager, run_info_data, **kwargs): executor_kwargs = base_executor_kwargs(test_type, server_config, cache_manager, run_info_data,
diff --git a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/browsers/chrome_android.py b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/browsers/chrome_android.py index 485b96f..607b7835 100644 --- a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/browsers/chrome_android.py +++ b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/browsers/chrome_android.py
@@ -29,14 +29,14 @@ require_arg(kwargs, "webdriver_binary") -def browser_kwargs(test_type, run_info_data, config, **kwargs): +def browser_kwargs(logger, test_type, run_info_data, config, **kwargs): return {"package_name": kwargs["package_name"], "device_serial": kwargs["device_serial"], "webdriver_binary": kwargs["webdriver_binary"], "webdriver_args": kwargs.get("webdriver_args")} -def executor_kwargs(test_type, server_config, cache_manager, run_info_data, +def executor_kwargs(logger, test_type, server_config, cache_manager, run_info_data, **kwargs): # Use update() to modify the global list in place. _wptserve_ports.update(set(
diff --git a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/browsers/chrome_ios.py b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/browsers/chrome_ios.py index 6db0188e..ecdbc3a 100644 --- a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/browsers/chrome_ios.py +++ b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/browsers/chrome_ios.py
@@ -22,12 +22,12 @@ require_arg(kwargs, "webdriver_binary") -def browser_kwargs(test_type, run_info_data, config, **kwargs): +def browser_kwargs(logger, test_type, run_info_data, config, **kwargs): return {"webdriver_binary": kwargs["webdriver_binary"], "webdriver_args": kwargs.get("webdriver_args")} -def executor_kwargs(test_type, server_config, cache_manager, run_info_data, +def executor_kwargs(logger, test_type, server_config, cache_manager, run_info_data, **kwargs): executor_kwargs = base_executor_kwargs(test_type, server_config, cache_manager, run_info_data, **kwargs)
diff --git a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/browsers/edge.py b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/browsers/edge.py index bdb37b3f..b908684 100644 --- a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/browsers/edge.py +++ b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/browsers/edge.py
@@ -34,7 +34,7 @@ require_arg(kwargs, "webdriver_binary") -def browser_kwargs(test_type, run_info_data, config, **kwargs): +def browser_kwargs(logger, test_type, run_info_data, config, **kwargs): return {"webdriver_binary": kwargs["webdriver_binary"], "webdriver_args": kwargs.get("webdriver_args"), "timeout_multiplier": get_timeout_multiplier(test_type, @@ -42,7 +42,7 @@ **kwargs)} -def executor_kwargs(test_type, server_config, cache_manager, run_info_data, +def executor_kwargs(logger, test_type, server_config, cache_manager, run_info_data, **kwargs): executor_kwargs = base_executor_kwargs(test_type, server_config, cache_manager, run_info_data, **kwargs)
diff --git a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/browsers/edgechromium.py b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/browsers/edgechromium.py index 9e1ef38..1d45983 100644 --- a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/browsers/edgechromium.py +++ b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/browsers/edgechromium.py
@@ -24,13 +24,13 @@ require_arg(kwargs, "webdriver_binary") -def browser_kwargs(test_type, run_info_data, config, **kwargs): +def browser_kwargs(logger, test_type, run_info_data, config, **kwargs): return {"binary": kwargs["binary"], "webdriver_binary": kwargs["webdriver_binary"], "webdriver_args": kwargs.get("webdriver_args")} -def executor_kwargs(test_type, server_config, cache_manager, run_info_data, +def executor_kwargs(logger, test_type, server_config, cache_manager, run_info_data, **kwargs): executor_kwargs = base_executor_kwargs(test_type, server_config, cache_manager, run_info_data,
diff --git a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/browsers/epiphany.py b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/browsers/epiphany.py index f6c4c602..a338443 100644 --- a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/browsers/epiphany.py +++ b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/browsers/epiphany.py
@@ -25,7 +25,7 @@ pass -def browser_kwargs(test_type, run_info_data, config, **kwargs): +def browser_kwargs(logger, test_type, run_info_data, config, **kwargs): # Workaround for https://gitlab.gnome.org/GNOME/libsoup/issues/172 webdriver_required_args = ["--host=127.0.0.1"] webdriver_args = maybe_add_args(webdriver_required_args, kwargs.get("webdriver_args")) @@ -49,7 +49,7 @@ "certificates": certificate_domain_list(server_config.domains_set, kwargs["host_cert_path"])}} -def executor_kwargs(test_type, server_config, cache_manager, run_info_data, +def executor_kwargs(logger, test_type, server_config, cache_manager, run_info_data, **kwargs): executor_kwargs = base_executor_kwargs(test_type, server_config, cache_manager, run_info_data, **kwargs)
diff --git a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/browsers/firefox.py b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/browsers/firefox.py index e95bc93..1fa0bce 100644 --- a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/browsers/firefox.py +++ b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/browsers/firefox.py
@@ -76,7 +76,7 @@ require_arg(kwargs, "binary") -def browser_kwargs(test_type, run_info_data, config, **kwargs): +def browser_kwargs(logger, test_type, run_info_data, config, **kwargs): return {"binary": kwargs["binary"], "prefs_root": kwargs["prefs_root"], "extra_prefs": kwargs["extra_prefs"], @@ -105,7 +105,7 @@ "specialpowers_path": kwargs["specialpowers_path"]} -def executor_kwargs(test_type, server_config, cache_manager, run_info_data, +def executor_kwargs(logger, test_type, server_config, cache_manager, run_info_data, **kwargs): executor_kwargs = base_executor_kwargs(test_type, server_config, cache_manager, run_info_data, @@ -138,6 +138,16 @@ for pref, value in kwargs["extra_prefs"]: options["prefs"].update({pref: Preferences.cast(value)}) capabilities["moz:firefoxOptions"] = options + + environ = get_environ(logger, + kwargs["binary"], + kwargs["debug_info"], + kwargs["stylo_threads"], + kwargs["headless"], + kwargs["enable_webrender"], + kwargs["chaos_mode_flags"]) + + executor_kwargs["environ"] = environ if kwargs["certutil_binary"] is None: capabilities["acceptInsecureCerts"] = True if capabilities: @@ -213,6 +223,26 @@ {"os": ["version"], "processor": ["bits"]}) +def get_environ(logger, binary, debug_info, stylo_threads, headless, enable_webrender, + chaos_mode_flags=None): + env = test_environment(xrePath=os.path.abspath(os.path.dirname(binary)), + debugger=debug_info is not None, + useLSan=True, + log=logger) + + env["STYLO_THREADS"] = str(stylo_threads) + if chaos_mode_flags is not None: + env["MOZ_CHAOSMODE"] = str(chaos_mode_flags) + if headless: + env["MOZ_HEADLESS"] = "1" + if enable_webrender: + env["MOZ_WEBRENDER"] = "1" + env["MOZ_ACCELERATED"] = "1" + else: + env["MOZ_WEBRENDER"] = "0" + return env + + class FirefoxInstanceManager(object): __metaclass__ = ABCMeta @@ -268,20 +298,8 @@ marionette_port = get_free_port() profile.set_preferences({"marionette.port": marionette_port}) - env = test_environment(xrePath=os.path.abspath(os.path.dirname(self.binary)), - debugger=self.debug_info is not None, - useLSan=True, log=self.logger) - - env["STYLO_THREADS"] = str(self.stylo_threads) - if self.chaos_mode_flags is not None: - env["MOZ_CHAOSMODE"] = str(self.chaos_mode_flags) - if self.headless: - env["MOZ_HEADLESS"] = "1" - if self.enable_webrender: - env["MOZ_WEBRENDER"] = "1" - env["MOZ_ACCELERATED"] = "1" - else: - env["MOZ_WEBRENDER"] = "0" + env = get_environ(self.logger, self.binary, self.debug_info, self.stylo_threads, + self.headless, self.enable_webrender, self.chaos_mode_flags) args = self.binary_args[:] if self.binary_args else [] args += [cmd_arg("marionette"), "about:blank"]
diff --git a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/browsers/firefox_android.py b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/browsers/firefox_android.py index b219079d..ca6ea96 100644 --- a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/browsers/firefox_android.py +++ b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/browsers/firefox_android.py
@@ -38,7 +38,7 @@ pass -def browser_kwargs(test_type, run_info_data, config, **kwargs): +def browser_kwargs(logger, test_type, run_info_data, config, **kwargs): return {"package_name": kwargs["package_name"], "device_serial": kwargs["device_serial"], "prefs_root": kwargs["prefs_root"],
diff --git a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/browsers/ie.py b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/browsers/ie.py index 78c22b9..3a86c1b6 100644 --- a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/browsers/ie.py +++ b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/browsers/ie.py
@@ -18,11 +18,11 @@ def check_args(**kwargs): require_arg(kwargs, "webdriver_binary") -def browser_kwargs(test_type, run_info_data, config, **kwargs): +def browser_kwargs(logger, test_type, run_info_data, config, **kwargs): return {"webdriver_binary": kwargs["webdriver_binary"], "webdriver_args": kwargs.get("webdriver_args")} -def executor_kwargs(test_type, server_config, cache_manager, run_info_data, +def executor_kwargs(logger, test_type, server_config, cache_manager, run_info_data, **kwargs): options = {} options["requireWindowFocus"] = True
diff --git a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/browsers/opera.py b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/browsers/opera.py index 805fede..a34f419 100644 --- a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/browsers/opera.py +++ b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/browsers/opera.py
@@ -24,13 +24,13 @@ require_arg(kwargs, "webdriver_binary") -def browser_kwargs(test_type, run_info_data, config, **kwargs): +def browser_kwargs(logger, test_type, run_info_data, config, **kwargs): return {"binary": kwargs["binary"], "webdriver_binary": kwargs["webdriver_binary"], "webdriver_args": kwargs.get("webdriver_args")} -def executor_kwargs(test_type, server_config, cache_manager, run_info_data, +def executor_kwargs(logger, test_type, server_config, cache_manager, run_info_data, **kwargs): from selenium.webdriver import DesiredCapabilities
diff --git a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/browsers/safari.py b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/browsers/safari.py index cb2b175..312d4db9 100644 --- a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/browsers/safari.py +++ b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/browsers/safari.py
@@ -26,12 +26,12 @@ require_arg(kwargs, "webdriver_binary") -def browser_kwargs(test_type, run_info_data, config, **kwargs): +def browser_kwargs(logger, test_type, run_info_data, config, **kwargs): return {"webdriver_binary": kwargs["webdriver_binary"], "webdriver_args": kwargs.get("webdriver_args")} -def executor_kwargs(test_type, server_config, cache_manager, run_info_data, +def executor_kwargs(logger, test_type, server_config, cache_manager, run_info_data, **kwargs): executor_kwargs = base_executor_kwargs(test_type, server_config, cache_manager, run_info_data, **kwargs)
diff --git a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/browsers/sauce.py b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/browsers/sauce.py index c57ac94..3497c5c 100644 --- a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/browsers/sauce.py +++ b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/browsers/sauce.py
@@ -95,13 +95,13 @@ require_arg(kwargs, "sauce_key") -def browser_kwargs(test_type, run_info_data, config, **kwargs): +def browser_kwargs(logger, test_type, run_info_data, config, **kwargs): sauce_config = get_sauce_config(**kwargs) return {"sauce_config": sauce_config} -def executor_kwargs(test_type, server_config, cache_manager, run_info_data, +def executor_kwargs(logger, test_type, server_config, cache_manager, run_info_data, **kwargs): executor_kwargs = base_executor_kwargs(test_type, server_config, cache_manager, run_info_data, **kwargs)
diff --git a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/browsers/servo.py b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/browsers/servo.py index b947654..a65ed5ea 100644 --- a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/browsers/servo.py +++ b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/browsers/servo.py
@@ -33,7 +33,7 @@ require_arg(kwargs, "binary") -def browser_kwargs(test_type, run_info_data, config, **kwargs): +def browser_kwargs(logger, test_type, run_info_data, config, **kwargs): return { "binary": kwargs["binary"], "debug_info": kwargs["debug_info"], @@ -43,7 +43,7 @@ } -def executor_kwargs(test_type, server_config, cache_manager, run_info_data, +def executor_kwargs(logger, test_type, server_config, cache_manager, run_info_data, **kwargs): rv = base_executor_kwargs(test_type, server_config, cache_manager, run_info_data, **kwargs)
diff --git a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/browsers/servodriver.py b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/browsers/servodriver.py index 43794e4..ed85cbf 100644 --- a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/browsers/servodriver.py +++ b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/browsers/servodriver.py
@@ -36,7 +36,7 @@ require_arg(kwargs, "binary") -def browser_kwargs(test_type, run_info_data, config, **kwargs): +def browser_kwargs(logger, test_type, run_info_data, config, **kwargs): return { "binary": kwargs["binary"], "binary_args": kwargs["binary_args"], @@ -47,7 +47,7 @@ } -def executor_kwargs(test_type, server_config, cache_manager, run_info_data, **kwargs): +def executor_kwargs(logger, test_type, server_config, cache_manager, run_info_data, **kwargs): rv = base_executor_kwargs(test_type, server_config, cache_manager, run_info_data, **kwargs) return rv
diff --git a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/browsers/webkit.py b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/browsers/webkit.py index da93cf1..590e472 100644 --- a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/browsers/webkit.py +++ b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/browsers/webkit.py
@@ -29,7 +29,7 @@ require_arg(kwargs, "webkit_port") -def browser_kwargs(test_type, run_info_data, config, **kwargs): +def browser_kwargs(logger, test_type, run_info_data, config, **kwargs): return {"binary": kwargs["binary"], "webdriver_binary": kwargs["webdriver_binary"], "webdriver_args": kwargs.get("webdriver_args")} @@ -54,7 +54,7 @@ return {} -def executor_kwargs(test_type, server_config, cache_manager, run_info_data, +def executor_kwargs(logger, test_type, server_config, cache_manager, run_info_data, **kwargs): executor_kwargs = base_executor_kwargs(test_type, server_config, cache_manager, run_info_data, **kwargs)
diff --git a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/browsers/webkitgtk_minibrowser.py b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/browsers/webkitgtk_minibrowser.py index d8b9744..5b7a360f 100644 --- a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/browsers/webkitgtk_minibrowser.py +++ b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/browsers/webkitgtk_minibrowser.py
@@ -25,7 +25,7 @@ pass -def browser_kwargs(test_type, run_info_data, config, **kwargs): +def browser_kwargs(logger, test_type, run_info_data, config, **kwargs): # Workaround for https://gitlab.gnome.org/GNOME/libsoup/issues/172 webdriver_required_args = ["--host=127.0.0.1"] webdriver_args = maybe_add_args(webdriver_required_args, kwargs.get("webdriver_args")) @@ -53,7 +53,7 @@ "certificates": certificate_domain_list(server_config.domains_set, kwargs["host_cert_path"])}} -def executor_kwargs(test_type, server_config, cache_manager, run_info_data, +def executor_kwargs(logger, test_type, server_config, cache_manager, run_info_data, **kwargs): executor_kwargs = base_executor_kwargs(test_type, server_config, cache_manager, run_info_data, **kwargs)
diff --git a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/executors/base.py b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/executors/base.py index 5551868..51d752cd 100644 --- a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/executors/base.py +++ b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/executors/base.py
@@ -598,7 +598,7 @@ def __init__(self, logger, browser, server_config, webdriver_binary, webdriver_args, timeout_multiplier=1, capabilities=None, - debug_info=None, **kwargs): + debug_info=None, environ=None, **kwargs): self.do_delayed_imports() TestExecutor.__init__(self, logger, browser, server_config, timeout_multiplier=timeout_multiplier, @@ -607,6 +607,7 @@ self.webdriver_args = webdriver_args self.timeout_multiplier = timeout_multiplier self.capabilities = capabilities + self.environ = environ if environ is not None else {} self.protocol = self.protocol_cls(self, browser) def is_alive(self): @@ -632,7 +633,8 @@ return pytestrunner.run(path, self.server_config, session_config, - timeout=timeout) + timeout=timeout, + environ=self.environ) def do_delayed_imports(self): global pytestrunner
diff --git a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/executors/pytestrunner/runner.py b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/executors/pytestrunner/runner.py index 3d32917..113eff99 100644 --- a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/executors/pytestrunner/runner.py +++ b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/executors/pytestrunner/runner.py
@@ -24,7 +24,7 @@ import pytest -def run(path, server_config, session_config, timeout=0): +def run(path, server_config, session_config, timeout=0, environ=None): """ Run Python test at ``path`` in pytest. The provided ``session`` is exposed as a fixture available in the scope of the test functions. @@ -41,28 +41,35 @@ if pytest is None: do_delayed_imports() - os.environ["WD_HOST"] = session_config["host"] - os.environ["WD_PORT"] = str(session_config["port"]) - os.environ["WD_CAPABILITIES"] = json.dumps(session_config["capabilities"]) - os.environ["WD_SERVER_CONFIG"] = json.dumps(server_config.as_dict_for_wd_env_variable()) + old_environ = os.environ.copy() + try: + os.environ["WD_HOST"] = session_config["host"] + os.environ["WD_PORT"] = str(session_config["port"]) + os.environ["WD_CAPABILITIES"] = json.dumps(session_config["capabilities"]) + os.environ["WD_SERVER_CONFIG"] = json.dumps(server_config.as_dict_for_wd_env_variable()) + if environ: + os.environ.update(environ) - harness = HarnessResultRecorder() - subtests = SubtestResultRecorder() + harness = HarnessResultRecorder() + subtests = SubtestResultRecorder() - with TemporaryDirectory() as cache: - try: - pytest.main(["--strict", # turn warnings into errors - "-vv", # show each individual subtest and full failure logs - "--capture", "no", # enable stdout/stderr from tests - "--basetemp", cache, # temporary directory - "--showlocals", # display contents of variables in local scope - "-p", "no:mozlog", # use the WPT result recorder - "-p", "no:cacheprovider", # disable state preservation across invocations - "-o=console_output_style=classic", # disable test progress bar - path], - plugins=[harness, subtests]) - except Exception as e: - harness.outcome = ("INTERNAL-ERROR", str(e)) + with TemporaryDirectory() as cache: + try: + pytest.main(["--strict", # turn warnings into errors + "-vv", # show each individual subtest and full failure logs + "--capture", "no", # enable stdout/stderr from tests + "--basetemp", cache, # temporary directory + "--showlocals", # display contents of variables in local scope + "-p", "no:mozlog", # use the WPT result recorder + "-p", "no:cacheprovider", # disable state preservation across invocations + "-o=console_output_style=classic", # disable test progress bar + path], + plugins=[harness, subtests]) + except Exception as e: + harness.outcome = ("INTERNAL-ERROR", str(e)) + + finally: + os.environ = old_environ return (harness.outcome, subtests.results)
diff --git a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/wptrunner.py b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/wptrunner.py index e1d9ef8..b02805f 100644 --- a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/wptrunner.py +++ b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/wptrunner.py
@@ -275,13 +275,15 @@ else: browser_cls = product.browser_cls - browser_kwargs = product.get_browser_kwargs(test_type, + browser_kwargs = product.get_browser_kwargs(logger, + test_type, run_info, config=test_environment.config, **kwargs) executor_cls = product.executor_classes.get(test_type) - executor_kwargs = product.get_executor_kwargs(test_type, + executor_kwargs = product.get_executor_kwargs(logger, + test_type, test_environment.config, test_environment.cache_manager, run_info,
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/accessibility/element-role-mapping-normal-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/accessibility/element-role-mapping-normal-expected.txt index e524bc1..17e176d 100644 --- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/accessibility/element-role-mapping-normal-expected.txt +++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/accessibility/element-role-mapping-normal-expected.txt
@@ -61,11 +61,9 @@ AXRole: AXStaticText "Paragraph" AXRole: AXInlineTextBox "Paragraph" AXRole: AXRuby - AXRole: AXRubyAnnotation - AXRole: AXStaticText "한국" - AXRole: AXInlineTextBox "한국" AXRole: AXStaticText "韓國" AXRole: AXInlineTextBox "韓國" + AXRole: AXRubyAnnotation "한국" AXRole: AXDescriptionList AXRole: AXDescriptionListTerm AXRole: AXStaticText "Coffee"
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/external/wpt/css/css-grid/alignment/grid-self-alignment-non-static-positioned-items-009-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/external/wpt/css/css-grid/alignment/grid-self-alignment-non-static-positioned-items-009-expected.txt index 1b32cf43..10a17be7 100644 --- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/external/wpt/css/css-grid/alignment/grid-self-alignment-non-static-positioned-items-009-expected.txt +++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/external/wpt/css/css-grid/alignment/grid-self-alignment-non-static-positioned-items-009-expected.txt
@@ -12,7 +12,7 @@ <div data-offset-x="155" data-offset-y="0" data-expected-width="40" data-expected-height="80" class="firstRowFirstColumn verticalLR">X XX X</div> <div data-offset-x="80" data-offset-y="60" data-expected-width="60" data-expected-height="90" class="firstRowSecondColumn verticalRL">XX X<br>X XXX X<br>XX XXX</div> <div data-offset-x="160" data-offset-y="160" data-expected-width="90" data-expected-height="30" class="secondRowFirstColumn LTR">X XX X</div> - <div data-offset-x="35" data-offset-y="160" data-expected-width="70" data-expected-height="80" class="secondRowSecondColumn verticalRL RTL">XX X<br>X XXX<br>X<br>XX XXX</div> + <div data-offset-x="5" data-offset-y="160" data-expected-width="70" data-expected-height="80" class="secondRowSecondColumn verticalRL RTL">XX X<br>X XXX<br>X<br>XX XXX</div> </div> offsetLeft expected 80 but got 110 PASS .grid 3 @@ -21,7 +21,7 @@ <div data-offset-x="105" data-offset-y="70" data-expected-width="90" data-expected-height="30" class="firstRowFirstColumn horizontal">X XX X</div> <div data-offset-x="140" data-offset-y="150" data-expected-width="100" data-expected-height="50" class="firstRowSecondColumn horizontal">XX X<br>X XXX X<br>XX XXX</div> <div data-offset-x="5" data-offset-y="10" data-expected-width="90" data-expected-height="30" class="secondRowFirstColumn horizontal RTL">X XX X</div> - <div data-offset-x="5" data-offset-y="115" data-expected-width="70" data-expected-height="80" class="secondRowSecondColumn verticalLR">XX X<br>X XXX<br>X<br>XX XXX</div> + <div data-offset-x="5" data-offset-y="110" data-expected-width="70" data-expected-height="80" class="secondRowSecondColumn verticalLR">XX X<br>X XXX<br>X<br>XX XXX</div> </div> offsetLeft expected 105 but got 75 Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/external/wpt/css/css-grid/alignment/grid-self-alignment-non-static-positioned-items-010-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/external/wpt/css/css-grid/alignment/grid-self-alignment-non-static-positioned-items-010-expected.txt index 1b32cf43..10a17be7 100644 --- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/external/wpt/css/css-grid/alignment/grid-self-alignment-non-static-positioned-items-010-expected.txt +++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/external/wpt/css/css-grid/alignment/grid-self-alignment-non-static-positioned-items-010-expected.txt
@@ -12,7 +12,7 @@ <div data-offset-x="155" data-offset-y="0" data-expected-width="40" data-expected-height="80" class="firstRowFirstColumn verticalLR">X XX X</div> <div data-offset-x="80" data-offset-y="60" data-expected-width="60" data-expected-height="90" class="firstRowSecondColumn verticalRL">XX X<br>X XXX X<br>XX XXX</div> <div data-offset-x="160" data-offset-y="160" data-expected-width="90" data-expected-height="30" class="secondRowFirstColumn LTR">X XX X</div> - <div data-offset-x="35" data-offset-y="160" data-expected-width="70" data-expected-height="80" class="secondRowSecondColumn verticalRL RTL">XX X<br>X XXX<br>X<br>XX XXX</div> + <div data-offset-x="5" data-offset-y="160" data-expected-width="70" data-expected-height="80" class="secondRowSecondColumn verticalRL RTL">XX X<br>X XXX<br>X<br>XX XXX</div> </div> offsetLeft expected 80 but got 110 PASS .grid 3 @@ -21,7 +21,7 @@ <div data-offset-x="105" data-offset-y="70" data-expected-width="90" data-expected-height="30" class="firstRowFirstColumn horizontal">X XX X</div> <div data-offset-x="140" data-offset-y="150" data-expected-width="100" data-expected-height="50" class="firstRowSecondColumn horizontal">XX X<br>X XXX X<br>XX XXX</div> <div data-offset-x="5" data-offset-y="10" data-expected-width="90" data-expected-height="30" class="secondRowFirstColumn horizontal RTL">X XX X</div> - <div data-offset-x="5" data-offset-y="115" data-expected-width="70" data-expected-height="80" class="secondRowSecondColumn verticalLR">XX X<br>X XXX<br>X<br>XX XXX</div> + <div data-offset-x="5" data-offset-y="110" data-expected-width="70" data-expected-height="80" class="secondRowSecondColumn verticalLR">XX X<br>X XXX<br>X<br>XX XXX</div> </div> offsetLeft expected 105 but got 75 Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/external/wpt/css/css-grid/alignment/grid-self-alignment-non-static-positioned-items-011-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/external/wpt/css/css-grid/alignment/grid-self-alignment-non-static-positioned-items-011-expected.txt index dcdaf1f..34a027a 100644 --- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/external/wpt/css/css-grid/alignment/grid-self-alignment-non-static-positioned-items-011-expected.txt +++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/external/wpt/css/css-grid/alignment/grid-self-alignment-non-static-positioned-items-011-expected.txt
@@ -2,34 +2,27 @@ FAIL .grid 1 assert_equals: <div class="grid"> <div data-offset-x="13" data-offset-y="2" data-expected-width="26" data-expected-height="70" class="firstRowFirstColumn verticalLR">X XX X</div> - <div data-offset-x="180" data-offset-y="60" data-expected-width="46" data-expected-height="80" class="firstRowSecondColumn verticalRL">XX X<br>X XXX X<br>XX XXX</div> - <div data-offset-x="0" data-offset-y="160" data-expected-width="76" data-expected-height="20" class="secondRowFirstColumn RTL">X XX X</div> - <div data-offset-x="105" data-offset-y="160" data-expected-width="56" data-expected-height="70" class="secondRowSecondColumn verticalLR RTL">XX X<br>X XXX<br>X<br>XX XXX</div> + <div data-offset-x="190" data-offset-y="64" data-expected-width="46" data-expected-height="80" class="firstRowSecondColumn verticalRL">XX X<br>X XXX X<br>XX XXX</div> + <div data-offset-x="8" data-offset-y="162" data-expected-width="76" data-expected-height="20" class="secondRowFirstColumn RTL">X XX X</div> + <div data-offset-x="113" data-offset-y="162" data-expected-width="56" data-expected-height="70" class="secondRowSecondColumn verticalLR RTL">XX X<br>X XXX<br>X<br>XX XXX</div> </div> -offsetLeft expected 180 but got 210 +offsetLeft expected 190 but got 210 FAIL .grid 2 assert_equals: <div class="grid RTL"> - <div data-offset-x="155" data-offset-y="0" data-expected-width="26" data-expected-height="70" class="firstRowFirstColumn verticalLR">X XX X</div> - <div data-offset-x="80" data-offset-y="60" data-expected-width="46" data-expected-height="80" class="firstRowSecondColumn verticalRL">XX X<br>X XXX X<br>XX XXX</div> - <div data-offset-x="160" data-offset-y="160" data-expected-width="76" data-expected-height="20" class="secondRowFirstColumn LTR">X XX X</div> - <div data-offset-x="35" data-offset-y="160" data-expected-width="56" data-expected-height="70" class="secondRowSecondColumn verticalRL RTL">XX X<br>X XXX<br>X<br>XX XXX</div> + <div data-offset-x="163" data-offset-y="2" data-expected-width="26" data-expected-height="70" class="firstRowFirstColumn verticalLR">X XX X</div> + <div data-offset-x="90" data-offset-y="64" data-expected-width="46" data-expected-height="80" class="firstRowSecondColumn verticalRL">XX X<br>X XXX X<br>XX XXX</div> + <div data-offset-x="170" data-offset-y="162" data-expected-width="76" data-expected-height="20" class="secondRowFirstColumn LTR">X XX X</div> + <div data-offset-x="13" data-offset-y="162" data-expected-width="56" data-expected-height="70" class="secondRowSecondColumn verticalRL RTL">XX X<br>X XXX<br>X<br>XX XXX</div> </div> -offsetLeft expected 155 but got 163 -FAIL .grid 3 assert_equals: -<div class="grid verticalLR"> - <div data-offset-x="5" data-offset-y="70" data-expected-width="76" data-expected-height="20" class="firstRowFirstColumn horizontal">X XX X</div> - <div data-offset-x="40" data-offset-y="150" data-expected-width="86" data-expected-height="40" class="firstRowSecondColumn horizontal">XX X<br>X XXX X<br>XX XXX</div> - <div data-offset-x="180" data-offset-y="10" data-expected-width="26" data-expected-height="20" class="secondRowFirstColumn verticalRL">X XX X</div> - <div data-offset-x="155" data-offset-y="110" data-expected-width="76" data-expected-height="50" class="secondRowSecondColumn horizontal RTL">XX X<br>X XXX<br>X<br>XX XXX</div> -</div> -offsetLeft expected 5 but got 13 +offsetLeft expected 90 but got 110 +PASS .grid 3 FAIL .grid 4 assert_equals: <div class="grid verticalRL"> - <div data-offset-x="105" data-offset-y="70" data-expected-width="76" data-expected-height="20" class="firstRowFirstColumn horizontal">X XX X</div> - <div data-offset-x="140" data-offset-y="150" data-expected-width="86" data-expected-height="40" class="firstRowSecondColumn horizontal">XX X<br>X XXX X<br>XX XXX</div> - <div data-offset-x="5" data-offset-y="10" data-expected-width="76" data-expected-height="20" class="secondRowFirstColumn horizontal RTL">X XX X</div> - <div data-offset-x="5" data-offset-y="115" data-expected-width="56" data-expected-height="70" class="secondRowSecondColumn verticalLR">XX X<br>X XXX<br>X<br>XX XXX</div> + <div data-offset-x="113" data-offset-y="74" data-expected-width="76" data-expected-height="20" class="firstRowFirstColumn horizontal">X XX X</div> + <div data-offset-x="150" data-offset-y="153" data-expected-width="86" data-expected-height="40" class="firstRowSecondColumn horizontal">XX X<br>X XXX X<br>XX XXX</div> + <div data-offset-x="14" data-offset-y="12" data-expected-width="76" data-expected-height="20" class="secondRowFirstColumn horizontal RTL">X XX X</div> + <div data-offset-x="13" data-offset-y="112" data-expected-width="56" data-expected-height="70" class="secondRowSecondColumn verticalLR">XX X<br>X XXX<br>X<br>XX XXX</div> </div> -offsetLeft expected 105 but got 101 +offsetLeft expected 113 but got 101 Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/http/tests/devtools/elements/highlight/highlight-css-flex-alignment-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/http/tests/devtools/elements/highlight/highlight-css-flex-alignment-expected.txt new file mode 100644 index 0000000..de34f2a8 --- /dev/null +++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/http/tests/devtools/elements/highlight/highlight-css-flex-alignment-expected.txt
@@ -0,0 +1,783 @@ +This test verifies the flex self-alignment value sent by the backend. + +flex-start{ + "paths": [ + { + "path": [ + "M", + 0, + 0, + "L", + 100, + 0, + "L", + 100, + 100, + "L", + 0, + 100, + "Z" + ], + "fillColor": "rgba(255, 0, 0, 0)", + "outlineColor": "rgba(128, 0, 0, 0)", + "name": "content" + }, + { + "path": [ + "M", + 0, + 0, + "L", + 100, + 0, + "L", + 100, + 100, + "L", + 0, + 100, + "Z" + ], + "fillColor": "rgba(0, 255, 0, 0)", + "name": "padding" + }, + { + "path": [ + "M", + 0, + 0, + "L", + 100, + 0, + "L", + 100, + 100, + "L", + 0, + 100, + "Z" + ], + "fillColor": "rgba(0, 0, 255, 0)", + "name": "border" + }, + { + "path": [ + "M", + 0, + 0, + "L", + 800, + 0, + "L", + 800, + 100, + "L", + 0, + 100, + "Z" + ], + "fillColor": "rgba(255, 255, 255, 0)", + "name": "margin" + } + ], + "showRulers": true, + "showExtensionLines": true, + "showAccessibilityInfo": true, + "colorFormat": "hex", + "elementInfo": { + "tagName": "div", + "idValue": "flex-start", + "className": ".container", + "nodeWidth": "100", + "nodeHeight": "100", + "isKeyboardFocusable": false, + "accessibleName": "", + "accessibleRole": "generic", + "layoutObjectName": "LayoutFlexibleBox", + "showAccessibilityInfo": true + }, + "flexInfo": [ + { + "containerBorder": [ + "M", + 0, + 0, + "L", + 100, + 0, + "L", + 100, + 100, + "L", + 0, + 100, + "Z" + ], + "lines": [], + "isHorizontalFlow": true, + "isReverse": false, + "alignItemsStyle": "flex-start", + "mainGap": 0, + "crossGap": 0, + "flexContainerHighlightConfig": { + "containerBorder": { + "color": "rgba(255, 0, 0, 0)", + "pattern": "solid" + }, + "lineSeparator": { + "color": "rgba(255, 0, 0, 0)", + "pattern": "solid" + }, + "itemSeparator": { + "color": "rgba(255, 0, 0, 0)", + "pattern": "solid" + }, + "mainDistributedSpace": { + "fillColor": "rgba(255, 0, 0, 0)", + "hatchColor": "rgba(255, 0, 0, 0)" + }, + "crossDistributedSpace": { + "fillColor": "rgba(255, 0, 0, 0)", + "hatchColor": "rgba(255, 0, 0, 0)" + }, + "rowGapSpace": { + "fillColor": "rgba(255, 0, 0, 0)", + "hatchColor": "rgba(255, 0, 0, 0)" + }, + "columnGapSpace": { + "fillColor": "rgba(255, 0, 0, 0)", + "hatchColor": "rgba(255, 0, 0, 0)" + }, + "crossAlignment": { + "color": "rgba(255, 0, 0, 0)", + "pattern": "solid" + } + } + } + ] +} +flex-end{ + "paths": [ + { + "path": [ + "M", + 0, + 100, + "L", + 100, + 100, + "L", + 100, + 200, + "L", + 0, + 200, + "Z" + ], + "fillColor": "rgba(255, 0, 0, 0)", + "outlineColor": "rgba(128, 0, 0, 0)", + "name": "content" + }, + { + "path": [ + "M", + 0, + 100, + "L", + 100, + 100, + "L", + 100, + 200, + "L", + 0, + 200, + "Z" + ], + "fillColor": "rgba(0, 255, 0, 0)", + "name": "padding" + }, + { + "path": [ + "M", + 0, + 100, + "L", + 100, + 100, + "L", + 100, + 200, + "L", + 0, + 200, + "Z" + ], + "fillColor": "rgba(0, 0, 255, 0)", + "name": "border" + }, + { + "path": [ + "M", + 0, + 100, + "L", + 800, + 100, + "L", + 800, + 200, + "L", + 0, + 200, + "Z" + ], + "fillColor": "rgba(255, 255, 255, 0)", + "name": "margin" + } + ], + "showRulers": true, + "showExtensionLines": true, + "showAccessibilityInfo": true, + "colorFormat": "hex", + "elementInfo": { + "tagName": "div", + "idValue": "flex-end", + "className": ".container", + "nodeWidth": "100", + "nodeHeight": "100", + "isKeyboardFocusable": false, + "accessibleName": "", + "accessibleRole": "generic", + "layoutObjectName": "LayoutFlexibleBox", + "showAccessibilityInfo": true + }, + "flexInfo": [ + { + "containerBorder": [ + "M", + 0, + 100, + "L", + 100, + 100, + "L", + 100, + 200, + "L", + 0, + 200, + "Z" + ], + "lines": [], + "isHorizontalFlow": true, + "isReverse": false, + "alignItemsStyle": "flex-end", + "mainGap": 0, + "crossGap": 0, + "flexContainerHighlightConfig": { + "containerBorder": { + "color": "rgba(255, 0, 0, 0)", + "pattern": "solid" + }, + "lineSeparator": { + "color": "rgba(255, 0, 0, 0)", + "pattern": "solid" + }, + "itemSeparator": { + "color": "rgba(255, 0, 0, 0)", + "pattern": "solid" + }, + "mainDistributedSpace": { + "fillColor": "rgba(255, 0, 0, 0)", + "hatchColor": "rgba(255, 0, 0, 0)" + }, + "crossDistributedSpace": { + "fillColor": "rgba(255, 0, 0, 0)", + "hatchColor": "rgba(255, 0, 0, 0)" + }, + "rowGapSpace": { + "fillColor": "rgba(255, 0, 0, 0)", + "hatchColor": "rgba(255, 0, 0, 0)" + }, + "columnGapSpace": { + "fillColor": "rgba(255, 0, 0, 0)", + "hatchColor": "rgba(255, 0, 0, 0)" + }, + "crossAlignment": { + "color": "rgba(255, 0, 0, 0)", + "pattern": "solid" + } + } + } + ] +} +center{ + "paths": [ + { + "path": [ + "M", + 0, + 200, + "L", + 100, + 200, + "L", + 100, + 300, + "L", + 0, + 300, + "Z" + ], + "fillColor": "rgba(255, 0, 0, 0)", + "outlineColor": "rgba(128, 0, 0, 0)", + "name": "content" + }, + { + "path": [ + "M", + 0, + 200, + "L", + 100, + 200, + "L", + 100, + 300, + "L", + 0, + 300, + "Z" + ], + "fillColor": "rgba(0, 255, 0, 0)", + "name": "padding" + }, + { + "path": [ + "M", + 0, + 200, + "L", + 100, + 200, + "L", + 100, + 300, + "L", + 0, + 300, + "Z" + ], + "fillColor": "rgba(0, 0, 255, 0)", + "name": "border" + }, + { + "path": [ + "M", + 0, + 200, + "L", + 800, + 200, + "L", + 800, + 300, + "L", + 0, + 300, + "Z" + ], + "fillColor": "rgba(255, 255, 255, 0)", + "name": "margin" + } + ], + "showRulers": true, + "showExtensionLines": true, + "showAccessibilityInfo": true, + "colorFormat": "hex", + "elementInfo": { + "tagName": "div", + "idValue": "center", + "className": ".container", + "nodeWidth": "100", + "nodeHeight": "100", + "isKeyboardFocusable": false, + "accessibleName": "", + "accessibleRole": "generic", + "layoutObjectName": "LayoutFlexibleBox", + "showAccessibilityInfo": true + }, + "flexInfo": [ + { + "containerBorder": [ + "M", + 0, + 200, + "L", + 100, + 200, + "L", + 100, + 300, + "L", + 0, + 300, + "Z" + ], + "lines": [], + "isHorizontalFlow": true, + "isReverse": false, + "alignItemsStyle": "center", + "mainGap": 0, + "crossGap": 0, + "flexContainerHighlightConfig": { + "containerBorder": { + "color": "rgba(255, 0, 0, 0)", + "pattern": "solid" + }, + "lineSeparator": { + "color": "rgba(255, 0, 0, 0)", + "pattern": "solid" + }, + "itemSeparator": { + "color": "rgba(255, 0, 0, 0)", + "pattern": "solid" + }, + "mainDistributedSpace": { + "fillColor": "rgba(255, 0, 0, 0)", + "hatchColor": "rgba(255, 0, 0, 0)" + }, + "crossDistributedSpace": { + "fillColor": "rgba(255, 0, 0, 0)", + "hatchColor": "rgba(255, 0, 0, 0)" + }, + "rowGapSpace": { + "fillColor": "rgba(255, 0, 0, 0)", + "hatchColor": "rgba(255, 0, 0, 0)" + }, + "columnGapSpace": { + "fillColor": "rgba(255, 0, 0, 0)", + "hatchColor": "rgba(255, 0, 0, 0)" + }, + "crossAlignment": { + "color": "rgba(255, 0, 0, 0)", + "pattern": "solid" + } + } + } + ] +} +stretch{ + "paths": [ + { + "path": [ + "M", + 0, + 300, + "L", + 100, + 300, + "L", + 100, + 400, + "L", + 0, + 400, + "Z" + ], + "fillColor": "rgba(255, 0, 0, 0)", + "outlineColor": "rgba(128, 0, 0, 0)", + "name": "content" + }, + { + "path": [ + "M", + 0, + 300, + "L", + 100, + 300, + "L", + 100, + 400, + "L", + 0, + 400, + "Z" + ], + "fillColor": "rgba(0, 255, 0, 0)", + "name": "padding" + }, + { + "path": [ + "M", + 0, + 300, + "L", + 100, + 300, + "L", + 100, + 400, + "L", + 0, + 400, + "Z" + ], + "fillColor": "rgba(0, 0, 255, 0)", + "name": "border" + }, + { + "path": [ + "M", + 0, + 300, + "L", + 800, + 300, + "L", + 800, + 400, + "L", + 0, + 400, + "Z" + ], + "fillColor": "rgba(255, 255, 255, 0)", + "name": "margin" + } + ], + "showRulers": true, + "showExtensionLines": true, + "showAccessibilityInfo": true, + "colorFormat": "hex", + "elementInfo": { + "tagName": "div", + "idValue": "stretch", + "className": ".container", + "nodeWidth": "100", + "nodeHeight": "100", + "isKeyboardFocusable": false, + "accessibleName": "", + "accessibleRole": "generic", + "layoutObjectName": "LayoutFlexibleBox", + "showAccessibilityInfo": true + }, + "flexInfo": [ + { + "containerBorder": [ + "M", + 0, + 300, + "L", + 100, + 300, + "L", + 100, + 400, + "L", + 0, + 400, + "Z" + ], + "lines": [], + "isHorizontalFlow": true, + "isReverse": false, + "alignItemsStyle": "stretch", + "mainGap": 0, + "crossGap": 0, + "flexContainerHighlightConfig": { + "containerBorder": { + "color": "rgba(255, 0, 0, 0)", + "pattern": "solid" + }, + "lineSeparator": { + "color": "rgba(255, 0, 0, 0)", + "pattern": "solid" + }, + "itemSeparator": { + "color": "rgba(255, 0, 0, 0)", + "pattern": "solid" + }, + "mainDistributedSpace": { + "fillColor": "rgba(255, 0, 0, 0)", + "hatchColor": "rgba(255, 0, 0, 0)" + }, + "crossDistributedSpace": { + "fillColor": "rgba(255, 0, 0, 0)", + "hatchColor": "rgba(255, 0, 0, 0)" + }, + "rowGapSpace": { + "fillColor": "rgba(255, 0, 0, 0)", + "hatchColor": "rgba(255, 0, 0, 0)" + }, + "columnGapSpace": { + "fillColor": "rgba(255, 0, 0, 0)", + "hatchColor": "rgba(255, 0, 0, 0)" + }, + "crossAlignment": { + "color": "rgba(255, 0, 0, 0)", + "pattern": "solid" + } + } + } + ] +} +normal{ + "paths": [ + { + "path": [ + "M", + 0, + 400, + "L", + 100, + 400, + "L", + 100, + 500, + "L", + 0, + 500, + "Z" + ], + "fillColor": "rgba(255, 0, 0, 0)", + "outlineColor": "rgba(128, 0, 0, 0)", + "name": "content" + }, + { + "path": [ + "M", + 0, + 400, + "L", + 100, + 400, + "L", + 100, + 500, + "L", + 0, + 500, + "Z" + ], + "fillColor": "rgba(0, 255, 0, 0)", + "name": "padding" + }, + { + "path": [ + "M", + 0, + 400, + "L", + 100, + 400, + "L", + 100, + 500, + "L", + 0, + 500, + "Z" + ], + "fillColor": "rgba(0, 0, 255, 0)", + "name": "border" + }, + { + "path": [ + "M", + 0, + 400, + "L", + 800, + 400, + "L", + 800, + 500, + "L", + 0, + 500, + "Z" + ], + "fillColor": "rgba(255, 255, 255, 0)", + "name": "margin" + } + ], + "showRulers": true, + "showExtensionLines": true, + "showAccessibilityInfo": true, + "colorFormat": "hex", + "elementInfo": { + "tagName": "div", + "idValue": "normal", + "className": ".container", + "nodeWidth": "100", + "nodeHeight": "100", + "isKeyboardFocusable": false, + "accessibleName": "", + "accessibleRole": "generic", + "layoutObjectName": "LayoutFlexibleBox", + "showAccessibilityInfo": true + }, + "flexInfo": [ + { + "containerBorder": [ + "M", + 0, + 400, + "L", + 100, + 400, + "L", + 100, + 500, + "L", + 0, + 500, + "Z" + ], + "lines": [], + "isHorizontalFlow": true, + "isReverse": false, + "alignItemsStyle": "normal", + "mainGap": 0, + "crossGap": 0, + "flexContainerHighlightConfig": { + "containerBorder": { + "color": "rgba(255, 0, 0, 0)", + "pattern": "solid" + }, + "lineSeparator": { + "color": "rgba(255, 0, 0, 0)", + "pattern": "solid" + }, + "itemSeparator": { + "color": "rgba(255, 0, 0, 0)", + "pattern": "solid" + }, + "mainDistributedSpace": { + "fillColor": "rgba(255, 0, 0, 0)", + "hatchColor": "rgba(255, 0, 0, 0)" + }, + "crossDistributedSpace": { + "fillColor": "rgba(255, 0, 0, 0)", + "hatchColor": "rgba(255, 0, 0, 0)" + }, + "rowGapSpace": { + "fillColor": "rgba(255, 0, 0, 0)", + "hatchColor": "rgba(255, 0, 0, 0)" + }, + "columnGapSpace": { + "fillColor": "rgba(255, 0, 0, 0)", + "hatchColor": "rgba(255, 0, 0, 0)" + }, + "crossAlignment": { + "color": "rgba(255, 0, 0, 0)", + "pattern": "solid" + } + } + } + ] +} +
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/http/tests/devtools/elements/highlight/highlight-css-flex-gap-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/http/tests/devtools/elements/highlight/highlight-css-flex-gap-expected.txt new file mode 100644 index 0000000..93afb58b --- /dev/null +++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/http/tests/devtools/elements/highlight/highlight-css-flex-gap-expected.txt
@@ -0,0 +1,627 @@ +This test verifies the gap information sent to the overlay frontend for flex contains with gaps. + +test-1{ + "paths": [ + { + "path": [ + "M", + 100, + 100, + "L", + 500, + 100, + "L", + 500, + 500, + "L", + 100, + 500, + "Z" + ], + "fillColor": "rgba(255, 0, 0, 0)", + "outlineColor": "rgba(128, 0, 0, 0)", + "name": "content" + }, + { + "path": [ + "M", + 100, + 100, + "L", + 500, + 100, + "L", + 500, + 500, + "L", + 100, + 500, + "Z" + ], + "fillColor": "rgba(0, 255, 0, 0)", + "name": "padding" + }, + { + "path": [ + "M", + 100, + 100, + "L", + 500, + 100, + "L", + 500, + 500, + "L", + 100, + 500, + "Z" + ], + "fillColor": "rgba(0, 0, 255, 0)", + "name": "border" + }, + { + "path": [ + "M", + 100, + 100, + "L", + 500, + 100, + "L", + 500, + 500, + "L", + 100, + 500, + "Z" + ], + "fillColor": "rgba(255, 255, 255, 0)", + "name": "margin" + } + ], + "showRulers": true, + "showExtensionLines": true, + "showAccessibilityInfo": true, + "colorFormat": "hex", + "elementInfo": { + "tagName": "div", + "idValue": "test-1", + "className": ".container", + "nodeWidth": "400", + "nodeHeight": "400", + "isKeyboardFocusable": false, + "accessibleName": "", + "accessibleRole": "generic", + "layoutObjectName": "LayoutFlexibleBox", + "showAccessibilityInfo": true + }, + "flexInfo": [ + { + "containerBorder": [ + "M", + 100, + 100, + "L", + 500, + 100, + "L", + 500, + 500, + "L", + 100, + 500, + "Z" + ], + "lines": [], + "isHorizontalFlow": true, + "isReverse": false, + "alignItemsStyle": "normal", + "mainGap": 10, + "crossGap": 20, + "flexContainerHighlightConfig": { + "containerBorder": { + "color": "rgba(255, 0, 0, 0)", + "pattern": "solid" + }, + "lineSeparator": { + "color": "rgba(255, 0, 0, 0)", + "pattern": "solid" + }, + "itemSeparator": { + "color": "rgba(255, 0, 0, 0)", + "pattern": "solid" + }, + "mainDistributedSpace": { + "fillColor": "rgba(255, 0, 0, 0)", + "hatchColor": "rgba(255, 0, 0, 0)" + }, + "crossDistributedSpace": { + "fillColor": "rgba(255, 0, 0, 0)", + "hatchColor": "rgba(255, 0, 0, 0)" + }, + "rowGapSpace": { + "fillColor": "rgba(255, 0, 0, 0)", + "hatchColor": "rgba(255, 0, 0, 0)" + }, + "columnGapSpace": { + "fillColor": "rgba(255, 0, 0, 0)", + "hatchColor": "rgba(255, 0, 0, 0)" + }, + "crossAlignment": { + "color": "rgba(255, 0, 0, 0)", + "pattern": "solid" + } + } + } + ] +} +test-2{ + "paths": [ + { + "path": [ + "M", + 100, + 100, + "L", + 500, + 100, + "L", + 500, + 500, + "L", + 100, + 500, + "Z" + ], + "fillColor": "rgba(255, 0, 0, 0)", + "outlineColor": "rgba(128, 0, 0, 0)", + "name": "content" + }, + { + "path": [ + "M", + 100, + 100, + "L", + 500, + 100, + "L", + 500, + 500, + "L", + 100, + 500, + "Z" + ], + "fillColor": "rgba(0, 255, 0, 0)", + "name": "padding" + }, + { + "path": [ + "M", + 100, + 100, + "L", + 500, + 100, + "L", + 500, + 500, + "L", + 100, + 500, + "Z" + ], + "fillColor": "rgba(0, 0, 255, 0)", + "name": "border" + }, + { + "path": [ + "M", + 100, + 100, + "L", + 500, + 100, + "L", + 500, + 500, + "L", + 100, + 500, + "Z" + ], + "fillColor": "rgba(255, 255, 255, 0)", + "name": "margin" + } + ], + "showRulers": true, + "showExtensionLines": true, + "showAccessibilityInfo": true, + "colorFormat": "hex", + "elementInfo": { + "tagName": "div", + "idValue": "test-2", + "className": ".container", + "nodeWidth": "400", + "nodeHeight": "400", + "isKeyboardFocusable": false, + "accessibleName": "", + "accessibleRole": "generic", + "layoutObjectName": "LayoutFlexibleBox", + "showAccessibilityInfo": true + }, + "flexInfo": [ + { + "containerBorder": [ + "M", + 100, + 100, + "L", + 500, + 100, + "L", + 500, + 500, + "L", + 100, + 500, + "Z" + ], + "lines": [], + "isHorizontalFlow": true, + "isReverse": true, + "alignItemsStyle": "normal", + "mainGap": 10, + "crossGap": 20, + "flexContainerHighlightConfig": { + "containerBorder": { + "color": "rgba(255, 0, 0, 0)", + "pattern": "solid" + }, + "lineSeparator": { + "color": "rgba(255, 0, 0, 0)", + "pattern": "solid" + }, + "itemSeparator": { + "color": "rgba(255, 0, 0, 0)", + "pattern": "solid" + }, + "mainDistributedSpace": { + "fillColor": "rgba(255, 0, 0, 0)", + "hatchColor": "rgba(255, 0, 0, 0)" + }, + "crossDistributedSpace": { + "fillColor": "rgba(255, 0, 0, 0)", + "hatchColor": "rgba(255, 0, 0, 0)" + }, + "rowGapSpace": { + "fillColor": "rgba(255, 0, 0, 0)", + "hatchColor": "rgba(255, 0, 0, 0)" + }, + "columnGapSpace": { + "fillColor": "rgba(255, 0, 0, 0)", + "hatchColor": "rgba(255, 0, 0, 0)" + }, + "crossAlignment": { + "color": "rgba(255, 0, 0, 0)", + "pattern": "solid" + } + } + } + ] +} +test-3{ + "paths": [ + { + "path": [ + "M", + 100, + 100, + "L", + 500, + 100, + "L", + 500, + 500, + "L", + 100, + 500, + "Z" + ], + "fillColor": "rgba(255, 0, 0, 0)", + "outlineColor": "rgba(128, 0, 0, 0)", + "name": "content" + }, + { + "path": [ + "M", + 100, + 100, + "L", + 500, + 100, + "L", + 500, + 500, + "L", + 100, + 500, + "Z" + ], + "fillColor": "rgba(0, 255, 0, 0)", + "name": "padding" + }, + { + "path": [ + "M", + 100, + 100, + "L", + 500, + 100, + "L", + 500, + 500, + "L", + 100, + 500, + "Z" + ], + "fillColor": "rgba(0, 0, 255, 0)", + "name": "border" + }, + { + "path": [ + "M", + 100, + 100, + "L", + 500, + 100, + "L", + 500, + 500, + "L", + 100, + 500, + "Z" + ], + "fillColor": "rgba(255, 255, 255, 0)", + "name": "margin" + } + ], + "showRulers": true, + "showExtensionLines": true, + "showAccessibilityInfo": true, + "colorFormat": "hex", + "elementInfo": { + "tagName": "div", + "idValue": "test-3", + "className": ".container", + "nodeWidth": "400", + "nodeHeight": "400", + "isKeyboardFocusable": false, + "accessibleName": "", + "accessibleRole": "generic", + "layoutObjectName": "LayoutFlexibleBox", + "showAccessibilityInfo": true + }, + "flexInfo": [ + { + "containerBorder": [ + "M", + 100, + 100, + "L", + 500, + 100, + "L", + 500, + 500, + "L", + 100, + 500, + "Z" + ], + "lines": [], + "isHorizontalFlow": false, + "isReverse": false, + "alignItemsStyle": "normal", + "mainGap": 20, + "crossGap": 10, + "flexContainerHighlightConfig": { + "containerBorder": { + "color": "rgba(255, 0, 0, 0)", + "pattern": "solid" + }, + "lineSeparator": { + "color": "rgba(255, 0, 0, 0)", + "pattern": "solid" + }, + "itemSeparator": { + "color": "rgba(255, 0, 0, 0)", + "pattern": "solid" + }, + "mainDistributedSpace": { + "fillColor": "rgba(255, 0, 0, 0)", + "hatchColor": "rgba(255, 0, 0, 0)" + }, + "crossDistributedSpace": { + "fillColor": "rgba(255, 0, 0, 0)", + "hatchColor": "rgba(255, 0, 0, 0)" + }, + "rowGapSpace": { + "fillColor": "rgba(255, 0, 0, 0)", + "hatchColor": "rgba(255, 0, 0, 0)" + }, + "columnGapSpace": { + "fillColor": "rgba(255, 0, 0, 0)", + "hatchColor": "rgba(255, 0, 0, 0)" + }, + "crossAlignment": { + "color": "rgba(255, 0, 0, 0)", + "pattern": "solid" + } + } + } + ] +} +test-4{ + "paths": [ + { + "path": [ + "M", + 100, + 100, + "L", + 500, + 100, + "L", + 500, + 500, + "L", + 100, + 500, + "Z" + ], + "fillColor": "rgba(255, 0, 0, 0)", + "outlineColor": "rgba(128, 0, 0, 0)", + "name": "content" + }, + { + "path": [ + "M", + 100, + 100, + "L", + 500, + 100, + "L", + 500, + 500, + "L", + 100, + 500, + "Z" + ], + "fillColor": "rgba(0, 255, 0, 0)", + "name": "padding" + }, + { + "path": [ + "M", + 100, + 100, + "L", + 500, + 100, + "L", + 500, + 500, + "L", + 100, + 500, + "Z" + ], + "fillColor": "rgba(0, 0, 255, 0)", + "name": "border" + }, + { + "path": [ + "M", + 100, + 100, + "L", + 500, + 100, + "L", + 500, + 500, + "L", + 100, + 500, + "Z" + ], + "fillColor": "rgba(255, 255, 255, 0)", + "name": "margin" + } + ], + "showRulers": true, + "showExtensionLines": true, + "showAccessibilityInfo": true, + "colorFormat": "hex", + "elementInfo": { + "tagName": "div", + "idValue": "test-4", + "className": ".container", + "nodeWidth": "400", + "nodeHeight": "400", + "isKeyboardFocusable": false, + "accessibleName": "", + "accessibleRole": "generic", + "layoutObjectName": "LayoutFlexibleBox", + "showAccessibilityInfo": true + }, + "flexInfo": [ + { + "containerBorder": [ + "M", + 100, + 100, + "L", + 500, + 100, + "L", + 500, + 500, + "L", + 100, + 500, + "Z" + ], + "lines": [], + "isHorizontalFlow": false, + "isReverse": true, + "alignItemsStyle": "normal", + "mainGap": 20, + "crossGap": 10, + "flexContainerHighlightConfig": { + "containerBorder": { + "color": "rgba(255, 0, 0, 0)", + "pattern": "solid" + }, + "lineSeparator": { + "color": "rgba(255, 0, 0, 0)", + "pattern": "solid" + }, + "itemSeparator": { + "color": "rgba(255, 0, 0, 0)", + "pattern": "solid" + }, + "mainDistributedSpace": { + "fillColor": "rgba(255, 0, 0, 0)", + "hatchColor": "rgba(255, 0, 0, 0)" + }, + "crossDistributedSpace": { + "fillColor": "rgba(255, 0, 0, 0)", + "hatchColor": "rgba(255, 0, 0, 0)" + }, + "rowGapSpace": { + "fillColor": "rgba(255, 0, 0, 0)", + "hatchColor": "rgba(255, 0, 0, 0)" + }, + "columnGapSpace": { + "fillColor": "rgba(255, 0, 0, 0)", + "hatchColor": "rgba(255, 0, 0, 0)" + }, + "crossAlignment": { + "color": "rgba(255, 0, 0, 0)", + "pattern": "solid" + } + } + } + ] +} +
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/http/tests/devtools/elements/highlight/highlight-css-flex-reverse-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/http/tests/devtools/elements/highlight/highlight-css-flex-reverse-expected.txt new file mode 100644 index 0000000..232c024 --- /dev/null +++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/http/tests/devtools/elements/highlight/highlight-css-flex-reverse-expected.txt
@@ -0,0 +1,315 @@ +This test verifies that the flex overlay creates the right lines and items for reverse direction flex containers. See crbug.com/1153272. + +test-1{ + "paths": [ + { + "path": [ + "M", + 8, + 8, + "L", + 108, + 8, + "L", + 108, + 108, + "L", + 8, + 108, + "Z" + ], + "fillColor": "rgba(255, 0, 0, 0)", + "outlineColor": "rgba(128, 0, 0, 0)", + "name": "content" + }, + { + "path": [ + "M", + 8, + 8, + "L", + 108, + 8, + "L", + 108, + 108, + "L", + 8, + 108, + "Z" + ], + "fillColor": "rgba(0, 255, 0, 0)", + "name": "padding" + }, + { + "path": [ + "M", + 8, + 8, + "L", + 108, + 8, + "L", + 108, + 108, + "L", + 8, + 108, + "Z" + ], + "fillColor": "rgba(0, 0, 255, 0)", + "name": "border" + }, + { + "path": [ + "M", + 8, + 8, + "L", + 792, + 8, + "L", + 792, + 108, + "L", + 8, + 108, + "Z" + ], + "fillColor": "rgba(255, 255, 255, 0)", + "name": "margin" + } + ], + "showRulers": true, + "showExtensionLines": true, + "showAccessibilityInfo": true, + "colorFormat": "hex", + "elementInfo": { + "tagName": "div", + "idValue": "test-1", + "className": ".container", + "nodeWidth": "100", + "nodeHeight": "100", + "isKeyboardFocusable": false, + "accessibleName": "", + "accessibleRole": "generic", + "layoutObjectName": "LayoutFlexibleBox", + "showAccessibilityInfo": true + }, + "flexInfo": [ + { + "containerBorder": [ + "M", + 8, + 8, + "L", + 108, + 8, + "L", + 108, + 108, + "L", + 8, + 108, + "Z" + ], + "lines": [], + "isHorizontalFlow": true, + "isReverse": true, + "alignItemsStyle": "flex-start", + "mainGap": 10, + "crossGap": 10, + "flexContainerHighlightConfig": { + "containerBorder": { + "color": "rgba(255, 0, 0, 0)", + "pattern": "solid" + }, + "lineSeparator": { + "color": "rgba(255, 0, 0, 0)", + "pattern": "solid" + }, + "itemSeparator": { + "color": "rgba(255, 0, 0, 0)", + "pattern": "solid" + }, + "mainDistributedSpace": { + "fillColor": "rgba(255, 0, 0, 0)", + "hatchColor": "rgba(255, 0, 0, 0)" + }, + "crossDistributedSpace": { + "fillColor": "rgba(255, 0, 0, 0)", + "hatchColor": "rgba(255, 0, 0, 0)" + }, + "rowGapSpace": { + "fillColor": "rgba(255, 0, 0, 0)", + "hatchColor": "rgba(255, 0, 0, 0)" + }, + "columnGapSpace": { + "fillColor": "rgba(255, 0, 0, 0)", + "hatchColor": "rgba(255, 0, 0, 0)" + }, + "crossAlignment": { + "color": "rgba(255, 0, 0, 0)", + "pattern": "solid" + } + } + } + ] +} +test-2{ + "paths": [ + { + "path": [ + "M", + 8, + 108, + "L", + 108, + 108, + "L", + 108, + 208, + "L", + 8, + 208, + "Z" + ], + "fillColor": "rgba(255, 0, 0, 0)", + "outlineColor": "rgba(128, 0, 0, 0)", + "name": "content" + }, + { + "path": [ + "M", + 8, + 108, + "L", + 108, + 108, + "L", + 108, + 208, + "L", + 8, + 208, + "Z" + ], + "fillColor": "rgba(0, 255, 0, 0)", + "name": "padding" + }, + { + "path": [ + "M", + 8, + 108, + "L", + 108, + 108, + "L", + 108, + 208, + "L", + 8, + 208, + "Z" + ], + "fillColor": "rgba(0, 0, 255, 0)", + "name": "border" + }, + { + "path": [ + "M", + 8, + 108, + "L", + 792, + 108, + "L", + 792, + 208, + "L", + 8, + 208, + "Z" + ], + "fillColor": "rgba(255, 255, 255, 0)", + "name": "margin" + } + ], + "showRulers": true, + "showExtensionLines": true, + "showAccessibilityInfo": true, + "colorFormat": "hex", + "elementInfo": { + "tagName": "div", + "idValue": "test-2", + "className": ".container", + "nodeWidth": "100", + "nodeHeight": "100", + "isKeyboardFocusable": false, + "accessibleName": "", + "accessibleRole": "generic", + "layoutObjectName": "LayoutFlexibleBox", + "showAccessibilityInfo": true + }, + "flexInfo": [ + { + "containerBorder": [ + "M", + 8, + 108, + "L", + 108, + 108, + "L", + 108, + 208, + "L", + 8, + 208, + "Z" + ], + "lines": [], + "isHorizontalFlow": false, + "isReverse": true, + "alignItemsStyle": "flex-start", + "mainGap": 10, + "crossGap": 10, + "flexContainerHighlightConfig": { + "containerBorder": { + "color": "rgba(255, 0, 0, 0)", + "pattern": "solid" + }, + "lineSeparator": { + "color": "rgba(255, 0, 0, 0)", + "pattern": "solid" + }, + "itemSeparator": { + "color": "rgba(255, 0, 0, 0)", + "pattern": "solid" + }, + "mainDistributedSpace": { + "fillColor": "rgba(255, 0, 0, 0)", + "hatchColor": "rgba(255, 0, 0, 0)" + }, + "crossDistributedSpace": { + "fillColor": "rgba(255, 0, 0, 0)", + "hatchColor": "rgba(255, 0, 0, 0)" + }, + "rowGapSpace": { + "fillColor": "rgba(255, 0, 0, 0)", + "hatchColor": "rgba(255, 0, 0, 0)" + }, + "columnGapSpace": { + "fillColor": "rgba(255, 0, 0, 0)", + "hatchColor": "rgba(255, 0, 0, 0)" + }, + "crossAlignment": { + "color": "rgba(255, 0, 0, 0)", + "pattern": "solid" + } + } + } + ] +} +
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/http/tests/devtools/elements/highlight/highlight-display-locked-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/http/tests/devtools/elements/highlight/highlight-display-locked-expected.txt index 7313b14..d7c3b61 100644 --- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/http/tests/devtools/elements/highlight/highlight-display-locked-expected.txt +++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/http/tests/devtools/elements/highlight/highlight-display-locked-expected.txt
@@ -93,6 +93,7 @@ "accessibleName": "", "accessibleRole": "generic", "layoutObjectName": "LayoutBlockFlow", + "isLocked": true, "showAccessibilityInfo": true } } @@ -189,7 +190,7 @@ "accessibleName": "", "accessibleRole": "generic", "layoutObjectName": "LayoutBlockFlow", - "isLockedAncestor": "true", + "isLockedAncestor": true, "showAccessibilityInfo": true } }
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 743963e9..f1fcb0f 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
@@ -901,7 +901,7 @@ method read method setLength method write -interface NativeIOManager +interface NativeIOFileManager attribute @@toStringTag method constructor method delete
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 a4a864d..95b5641 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
@@ -902,16 +902,7 @@ [Worker] method read [Worker] method setLength [Worker] method write -[Worker] interface NativeIOFileSync -[Worker] attribute @@toStringTag -[Worker] method close -[Worker] method constructor -[Worker] method flush -[Worker] method getLength -[Worker] method read -[Worker] method setLength -[Worker] method write -[Worker] interface NativeIOManager +[Worker] interface NativeIOFileManager [Worker] attribute @@toStringTag [Worker] method constructor [Worker] method delete @@ -922,6 +913,15 @@ [Worker] method openSync [Worker] method rename [Worker] method renameSync +[Worker] interface NativeIOFileSync +[Worker] attribute @@toStringTag +[Worker] method close +[Worker] method constructor +[Worker] method flush +[Worker] method getLength +[Worker] method read +[Worker] method setLength +[Worker] method write [Worker] interface NavigationPreloadManager [Worker] attribute @@toStringTag [Worker] method constructor
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 e2c052b38..9f13f56b 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
@@ -5417,7 +5417,7 @@ method read method setLength method write -interface NativeIOManager +interface NativeIOFileManager attribute @@toStringTag method constructor method delete
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 8e58c16..7daabc8 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
@@ -827,7 +827,7 @@ [Worker] method read [Worker] method setLength [Worker] method write -[Worker] interface NativeIOManager +[Worker] interface NativeIOFileManager [Worker] attribute @@toStringTag [Worker] method constructor [Worker] method delete
diff --git a/third_party/freetype/README.chromium b/third_party/freetype/README.chromium index b5bc062d..7bb37ec 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-49-gf6be92767 -Revision: f6be92767d1d002f5e90a4673ee4e6d4f1e1744f +Version: VER-2-10-4-50-g84b3616c9 +Revision: 84b3616c94f48726c596ead4150218d4431b3412 CPEPrefix: cpe:/a:freetype:freetype:2.10.1 License: Custom license "inspired by the BSD, Artistic, and IJG (Independent JPEG Group) licenses"
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index 8359490..ebd131f 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -74707,6 +74707,7 @@ <int value="60" label="kErrorCodeNotEnoughSpace"/> <int value="61" label="kErrorCodeDeviceCorrupted"/> <int value="62" label="kErrorCodePackageExcludedFromUpdate"/> + <int value="63" label="kErrorCodeDownloadCancelledPerPolicy"/> </enum> <enum name="UpdateEngineInstallDateProvisioningSource">
diff --git a/tools/metrics/histograms/histograms_xml/histogram_suffixes_list.xml b/tools/metrics/histograms/histograms_xml/histogram_suffixes_list.xml index 491274c..17ae8fc 100644 --- a/tools/metrics/histograms/histograms_xml/histogram_suffixes_list.xml +++ b/tools/metrics/histograms/histograms_xml/histogram_suffixes_list.xml
@@ -14669,6 +14669,9 @@ <histogram_suffixes name="ProcessMemoryAllocatorSmall2" separator="."> <suffix name="Discardable.FreelistSize" label="Freelist size used by ClientDiscardableMemoryManager."/> + <suffix name="Discardable.ResidentSize" + label="Amount of resident memory held by + ClientDiscardableSharedMemoryManager."/> <suffix name="Discardable.VirtualSize" label="Virtual memory used by ClientDiscardableMemoryManager."/> <suffix name="DownloadService"
diff --git a/tools/metrics/histograms/histograms_xml/memory/histograms.xml b/tools/metrics/histograms/histograms_xml/memory/histograms.xml index fcc09261..2beabbd 100644 --- a/tools/metrics/histograms/histograms_xml/memory/histograms.xml +++ b/tools/metrics/histograms/histograms_xml/memory/histograms.xml
@@ -388,6 +388,16 @@ <summary>TBD.</summary> </histogram> +<histogram name="Memory.Discardable.FreeListReleaseTime" units="ms" + expires_after="2021-08-01"> + <owner>thiabaud@google.com</owner> + <owner>lizeb@chromium.org</owner> + <summary> + Records how long it takes for memory to be released from the freelist of the + discardable shared memory allocator with |madvise|. + </summary> +</histogram> + <histogram name="Memory.Discardable.FreelistSize.Foreground" units="KiB" expires_after="2021-05-30"> <owner>thiabaud@google.com</owner> @@ -1995,6 +2005,22 @@ <summary>Throughput of a ParkableString disk write.</summary> </histogram> +<histogram name="Memory.PartitionAlloc.ThreadCache.BatchFillRate{ThreadType}" + units="%" expires_after="M92"> + <owner>lizeb@chromium.org</owner> + <owner>bartekn@chromium.org</owner> + <summary> + Fraction of PartitionAlloc's thread cache allocations requests that required + a batch fill, that is cache hits touching the central allocator. Recorded + during memory dumps, at the same time as the Memory.*.PartitionAlloc.* + histograms. Data is collected for {ThreadType}. + </summary> + <token key="ThreadType"> + <variant name="" summary="all threads"/> + <variant name=".MainThread" summary="the main thread only"/> + </token> +</histogram> + <histogram name="Memory.PartitionAlloc.ThreadCache.HitRate{ThreadType}" units="%" expires_after="M92"> <owner>lizeb@chromium.org</owner>
diff --git a/tools/metrics/histograms/histograms_xml/others/histograms.xml b/tools/metrics/histograms/histograms_xml/others/histograms.xml index 26730dda8..322ecb3 100644 --- a/tools/metrics/histograms/histograms_xml/others/histograms.xml +++ b/tools/metrics/histograms/histograms_xml/others/histograms.xml
@@ -123,7 +123,7 @@ </histogram> <histogram name="AccountManager.ManageAccountsServiceType" - enum="GaiaServiceType" expires_after="2021-01-24"> + enum="GaiaServiceType" expires_after="2022-01-24"> <owner>sinhak@chromium.org</owner> <owner>anastasiian@chromium.org</owner> <summary>
diff --git a/tools/metrics/histograms/histograms_xml/signin/histograms.xml b/tools/metrics/histograms/histograms_xml/signin/histograms.xml index 4439565e..d05ec0aa 100644 --- a/tools/metrics/histograms/histograms_xml/signin/histograms.xml +++ b/tools/metrics/histograms/histograms_xml/signin/histograms.xml
@@ -40,6 +40,27 @@ </summary> </histogram> +<histogram name="Signin.AccountConsistencyPromoAction.Shown.Count" + units="counts" expires_after="2021-08-31"> + <owner>aliceywang@chromium.org</owner> + <owner>triploblastic@chromium.org</owner> + <summary> + Every time the account picker bottom sheet is shown as part of the web + sign-in flow this histogram records the number of times bottom sheet was + shown (Android only). + </summary> +</histogram> + +<histogram name="Signin.AccountConsistencyPromoAction.SignedIn.Count" + units="counts" expires_after="2021-08-31"> + <owner>aliceywang@chromium.org</owner> + <owner>triploblastic@chromium.org</owner> + <summary> + This histogram records the number of times the account picker bottom sheet + was shown before the user signed-in through the bottom sheet (Android only). + </summary> +</histogram> + <histogram name="Signin.AccountEquality" enum="SigninAccountEquality" expires_after="2021-03-06"> <owner>droger@chromium.org</owner>
diff --git a/tools/metrics/histograms/histograms_xml/sync/histograms.xml b/tools/metrics/histograms/histograms_xml/sync/histograms.xml index 5f1e5ca0..d288a7c 100644 --- a/tools/metrics/histograms/histograms_xml/sync/histograms.xml +++ b/tools/metrics/histograms/histograms_xml/sync/histograms.xml
@@ -302,7 +302,11 @@ </summary> </histogram> -<histogram name="Sync.CustomSync2" enum="SyncModelTypes" expires_after="M90"> +<histogram name="Sync.CustomSync2" enum="SyncModelTypes" + expires_after="2020-12-16"> + <obsolete> + Replaced with Sync.CustomSync3 in 12/2020 (M89) due to crbug.com/1154396. + </obsolete> <owner>treib@chromium.org</owner> <owner>mastiz@chromium.org</owner> <summary> @@ -313,6 +317,22 @@ </summary> </histogram> +<histogram name="Sync.CustomSync3" enum="SyncModelTypes" + expires_after="2021-12-16"> + <owner>treib@chromium.org</owner> + <owner>mastiz@chromium.org</owner> + <summary> + For users who have *not* selected the "Sync Everything" option, + this records all the data types they have selected to sync. Samples are + taken every time the Sync data types are (re)configured, which typically + happens during startup and when the user changes any Sync settings. + + NOTE: this may stop showing OS datatypes like WIFI_CONFIGURATIONS once the + SplitSettingsSync feature is enabled. New metrics will be added for those + (crbug.com/1105956). + </summary> +</histogram> + <histogram name="Sync.DataTypeRunFailures2" enum="SyncModelTypes" expires_after="2021-06-13"> <owner>jkrcal@chromium.org</owner> @@ -818,7 +838,10 @@ </histogram> <histogram name="Sync.Preferences.ClearedLocalPrefOnTypeMismatch" - units="BooleanHit" expires_after="M88"> + units="BooleanHit" expires_after="2020-12-16"> + <obsolete> + Deprecated in 12/2020. + </obsolete> <owner>tschumann@chromium.org</owner> <owner>treib@chromium.org</owner> <summary> @@ -849,16 +872,31 @@ </histogram> <histogram name="Sync.RedundantInvalidationPerModelType" enum="SyncModelTypes" - expires_after="2021-06-13"> + expires_after="2020-12-16"> + <obsolete> + Replaced with Sync.RedundantInvalidationPerModelType2 in M89 (12/2020). + </obsolete> <owner>melandory@chromium.org</owner> <owner>treib@chromium.org</owner> <summary> - WARNING: The recordings here are incorrect (crbug.com/1158476). + WARNING: The recordings here are incorrect (crbug.com/1158476), see + Sync.RedundantInvalidationPerModelType2 instead. The sync datatype of the received invalidation with not-fresh version. </summary> </histogram> +<histogram name="Sync.RedundantInvalidationPerModelType2" enum="SyncModelTypes" + expires_after="2021-12-16"> + <owner>melandory@chromium.org</owner> + <owner>treib@chromium.org</owner> + <summary> + Recorded whenever Sync receives an invalidation with a non-fresh version, + i.e. a smaller version number than Sync already knew about. The recorded + value is the data type of the invalidation. + </summary> +</histogram> + <histogram name="Sync.SessionTabs" units="tabs" expires_after="2021-01-31"> <owner>mastiz@chromium.org</owner> <owner>treib@chromium.org</owner> @@ -904,12 +942,16 @@ </summary> </histogram> -<histogram name="Sync.Startup.TimeDeferred2" units="ms" expires_after="M88"> +<histogram name="Sync.Startup.TimeDeferred2" units="ms" + expires_after="2021-12-16"> <owner>mastiz@chromium.org</owner> <owner>treib@chromium.org</owner> <summary> - Time spent after ProfileSyncService *creation* but before SyncEngine - initialization. + Recorded on browser startup if the SyncEngine initialization is deferred by + a fixed (configurable) delay due to performance reasons. In some cases, a + data type may force sync to start before the delay finishes, causing the + recorded time to be smaller. This histogram records the time spent after the + ProfileSyncService *creation* but before the SyncEngine initialization. </summary> </histogram> @@ -1047,7 +1089,10 @@ </summary> </histogram> -<histogram name="Sync.URLFetchTime" units="ms" expires_after="M88"> +<histogram name="Sync.URLFetchTime" units="ms" expires_after="2020-12-16"> + <obsolete> + Deprecated in 12/2020. + </obsolete> <owner>mastiz@chromium.org</owner> <owner>treib@chromium.org</owner> <summary>
diff --git a/ui/base/clipboard/clipboard_non_backed.cc b/ui/base/clipboard/clipboard_non_backed.cc index d8315cb..6cf921a 100644 --- a/ui/base/clipboard/clipboard_non_backed.cc +++ b/ui/base/clipboard/clipboard_non_backed.cc
@@ -38,12 +38,13 @@ namespace { +using InstanceRegistry = std::set<const ClipboardNonBacked*, std::less<>>; // Returns the registry which tracks all instances of ClipboardNonBacked in // existence. This allows us to determine if any arbitrary Clipboard pointer in // fact points to a ClipboardNonBacked instance. Only if a pointer exists in // this registry is it safe to cast to ClipboardNonBacked*. -std::set<const ClipboardNonBacked*>* GetInstanceRegistry() { - static base::NoDestructor<std::set<const ClipboardNonBacked*>> registry; +InstanceRegistry* GetInstanceRegistry() { + static base::NoDestructor<InstanceRegistry> registry; return registry.get(); }
diff --git a/ui/file_manager/BUILD.gn b/ui/file_manager/BUILD.gn index 6652eda..048f10a 100644 --- a/ui/file_manager/BUILD.gn +++ b/ui/file_manager/BUILD.gn
@@ -87,6 +87,7 @@ in_files = [ "audio_player/js/main.m.js", "audio_player/js/main_background.m.js", + "video_player/js/main_background.m.js", ] deps = [ "//ui/file_manager/audio_player/js:main.m" ] @@ -122,6 +123,7 @@ "file_manager/common/js/file_type.m.js", "file_manager/common/js/files_app_entry_types.m.js", "file_manager/common/js/lru_cache.m.js", + "file_manager/common/js/metrics_base.m.js", # Externs: "externs/entry_location.m.js", @@ -177,6 +179,12 @@ "file_manager/foreground/js/metadata/function_parallel.m.js", "file_manager/foreground/js/metadata/function_sequence.m.js", "file_manager/foreground/js/metadata/exif_constants.m.js", + + # Video Player: + "video_player/js/error_util.m.js", + "video_player/js/test_util.m.js", + "video_player/js/background.m.js", + "video_player/js/video_player_metrics.m.js", ] deps = [ @@ -191,6 +199,7 @@ "//ui/file_manager/file_manager/foreground/js:modulize", "//ui/file_manager/file_manager/foreground/js/metadata:modulize", "//ui/file_manager/image_loader:modulize", + "//ui/file_manager/video_player/js:modulize", ] } @@ -209,12 +218,15 @@ "file_manager/foreground/elements/files_icon_button.m.js", "file_manager/foreground/elements/files_toggle_ripple.m.js", "file_manager/foreground/elements/files_ripple.m.js", + + "video_player/js/main_background.m.rollup.js", ] resource_path_rewrites = [ "audio_player/js/main.m.rollup.js|audio_player/js/main.m.js", "audio_player/js/main_background.m.rollup.js|audio_player/js/main_background.m.js", "audio_player/js/metadata_worker.m.rollup.js|audio_player/js/metadata_worker.m.js", + "video_player/js/main_background.m.rollup.js|video_player/js/main_background.m.js", ] grdp_files = [ @@ -229,6 +241,7 @@ "//ui/file_manager/audio_player/js:build_background", "//ui/file_manager/audio_player/js:build_worker", "//ui/file_manager/file_manager/foreground/elements:elements", + "//ui/file_manager/video_player/js:build_background", ] }
diff --git a/ui/file_manager/externs/background/BUILD.gn b/ui/file_manager/externs/background/BUILD.gn index 5ee3283..d0a5d3e 100644 --- a/ui/file_manager/externs/background/BUILD.gn +++ b/ui/file_manager/externs/background/BUILD.gn
@@ -16,7 +16,6 @@ "file_browser_background_full.js", "file_operation_manager.js", "import_history.js", - "import_runner.js", "media_import_handler.js", "media_scanner.js", "progress_center.js", @@ -43,6 +42,18 @@ extra_deps = [ ":modulize" ] } +js_library("duplicate_finder.m") { + sources = [ + "$root_gen_dir/ui/file_manager/externs/background/duplicate_finder.m.js", + ] + deps = [ + ":import_history.m", + "//ui/file_manager/file_manager/common/js:importer_common.m", + ] + + extra_deps = [ ":modulize" ] +} + js_library("crostini.m") { sources = [ "$root_gen_dir/ui/file_manager/externs/background/crostini.m.js" ] deps = [ "..:volume_manager.m" ] @@ -68,6 +79,29 @@ extra_deps = [ ":modulize" ] } +js_library("media_import_handler.m") { + sources = [ "$root_gen_dir/ui/file_manager/externs/background/media_import_handler.m.js" ] + deps = [ + ":drive_sync_handler.m", + ":duplicate_finder.m", + ":import_history.m", + ":media_scanner.m", + ":progress_center.m", + ":task_queue.m", + "//ui/file_manager/file_manager/common/js:importer_common.m", + ] + + extra_deps = [ ":modulize" ] +} + +js_library("media_scanner.m") { + sources = + [ "$root_gen_dir/ui/file_manager/externs/background/media_scanner.m.js" ] + deps = [ "//ui/file_manager/file_manager/common/js:importer_common.m" ] + + extra_deps = [ ":modulize" ] +} + js_library("progress_center.m") { sources = [ "$root_gen_dir/ui/file_manager/externs/background/progress_center.m.js", @@ -93,8 +127,11 @@ "background_base.js", "crostini.js", "drive_sync_handler.js", + "duplicate_finder.js", "file_operation_manager.js", "import_history.js", + "media_import_handler.js", + "media_scanner.js", "progress_center.js", "task_queue.js", ]
diff --git a/ui/file_manager/externs/background/duplicate_finder.js b/ui/file_manager/externs/background/duplicate_finder.js index 67d5b63..b0d475ba 100644 --- a/ui/file_manager/externs/background/duplicate_finder.js +++ b/ui/file_manager/externs/background/duplicate_finder.js
@@ -2,21 +2,23 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +// #import {importer} from '../../file_manager/common/js/importer_common.m.js'; +// #import {importerHistoryInterfaces} from './import_history.m.js'; + // Namespace -// eslint-disable-next-line no-var -var importer = importer || {}; +/* #export */ const duplicateFinderInterfaces = {}; /** * Declare DispositionChecker class. * @interface */ -importer.DispositionChecker = class { +duplicateFinderInterfaces.DispositionChecker = class { /** * Factory for a function that returns a file entry's content disposition. * * @param {!importerHistoryInterfaces.HistoryLoader} historyLoader * - * @return {!importer.DispositionChecker.CheckerFunction} + * @return {!duplicateFinderInterfaces.DispositionChecker.CheckerFunction} */ static createChecker(historyLoader) {} }; @@ -28,4 +30,4 @@ * @typedef {function(!FileEntry, !importer.Destination, !importer.ScanMode): * !Promise<!importer.Disposition>} */ -importer.DispositionChecker.CheckerFunction; +duplicateFinderInterfaces.DispositionChecker.CheckerFunction;
diff --git a/ui/file_manager/externs/background/file_browser_background_full.js b/ui/file_manager/externs/background/file_browser_background_full.js index aa47640..b5e6435 100644 --- a/ui/file_manager/externs/background/file_browser_background_full.js +++ b/ui/file_manager/externs/background/file_browser_background_full.js
@@ -29,12 +29,12 @@ this.fileOperationManager; /** - * @type {!importer.ImportRunner} + * @type {!mediaImportInterfaces.ImportRunner} */ this.mediaImportHandler; /** - * @type {!importer.MediaScanner} + * @type {!mediaScannerInterfaces.MediaScanner} */ this.mediaScanner;
diff --git a/ui/file_manager/externs/background/import_runner.js b/ui/file_manager/externs/background/import_runner.js deleted file mode 100644 index e10514d7..0000000 --- a/ui/file_manager/externs/background/import_runner.js +++ /dev/null
@@ -1,24 +0,0 @@ -// 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. - -// Namespace -var importer = importer || {}; - -/** - * Interface providing access to information about active import processes. - * - * @interface - */ -importer.ImportRunner = class { - /** - * Imports all media identified by a scanResult. - * - * @param {!importer.ScanResult} scanResult - * @param {!importer.Destination} destination - * @param {!Promise<!DirectoryEntry>} directoryPromise - * - * @return {!importer.MediaImportHandler.ImportTask} The media import task. - */ - importFromScanResult(scanResult, destination, directoryPromise) {} -};
diff --git a/ui/file_manager/externs/background/media_import_handler.js b/ui/file_manager/externs/background/media_import_handler.js index ef82133..83a359bf 100644 --- a/ui/file_manager/externs/background/media_import_handler.js +++ b/ui/file_manager/externs/background/media_import_handler.js
@@ -2,30 +2,60 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Namespace -// eslint-disable-next-line no-var -var importer = importer || {}; - -/* +/** + * @fileoverview * Externs definition for MediaImportHandler to allow for Closure compilation * of its media import unittest and caller sites. */ +// #import {DriveSyncHandler} from './drive_sync_handler.m.js'; +// #import {importer} from '../../file_manager/common/js/importer_common.m.js'; +// #import {importerHistoryInterfaces} from './import_history.m.js'; +// #import {duplicateFinderInterfaces} from './duplicate_finder.m.js'; +// #import {mediaScannerInterfaces} from './media_scanner.m.js'; +// #import {taskQueueInterfaces} from './task_queue.m.js'; +// #import {ProgressCenter} from './progress_center.m.js'; + +/* #export */ const mediaImportInterfaces = {}; + +/** + * Interface providing access to information about active import processes. + * + * @interface + */ +mediaImportInterfaces.ImportRunner = class { + /** + * Imports all media identified by a scanResult. + * + * @param {!mediaScannerInterfaces.ScanResult} scanResult + * @param {!importer.Destination} destination + * @param {!Promise<!DirectoryEntry>} directoryPromise + * + * @return {!mediaImportInterfaces.MediaImportHandler.ImportTask} The media + * import task. + */ + importFromScanResult(scanResult, destination, directoryPromise) {} +}; + /** * Define MediaImportHandler constructor: handler for importing media from * removable devices into the user's Drive. * * @interface */ -importer.MediaImportHandler = class extends importer.ImportRunner { +mediaImportInterfaces.MediaImportHandler = + class extends mediaImportInterfaces.ImportRunner { /** * @param {!ProgressCenter} progressCenter * @param {!importerHistoryInterfaces.HistoryLoader} historyLoader - * @param {!importer.DispositionChecker.CheckerFunction} dispositionChecker + * @param {!duplicateFinderInterfaces.DispositionChecker.CheckerFunction} + * dispositionChecker * @param {!DriveSyncHandler} driveSyncHandler */ constructor( - progressCenter, historyLoader, dispositionChecker, driveSyncHandler) {} + progressCenter, historyLoader, dispositionChecker, driveSyncHandler) { + super(); + } }; /** @@ -38,14 +68,15 @@ * @extends {taskQueueInterfaces.BaseTask} * @interface */ -importer.MediaImportHandler.ImportTask = class { +mediaImportInterfaces.MediaImportHandler.ImportTask = class { /** * @param {string} taskId * @param {!importerHistoryInterfaces.HistoryLoader} historyLoader - * @param {!importer.ScanResult} scanResult + * @param {!mediaScannerInterfaces.ScanResult} scanResult * @param {!Promise<!DirectoryEntry>} directoryPromise * @param {!importer.Destination} destination The logical destination. - * @param {!importer.DispositionChecker.CheckerFunction} dispositionChecker + * @param {!duplicateFinderInterfaces.DispositionChecker.CheckerFunction} + * dispositionChecker */ constructor( taskId, historyLoader, scanResult, directoryPromise, destination, @@ -71,4 +102,4 @@ * destination: !Entry * }} */ -importer.MediaImportHandler.ImportTask.EntryChangedInfo; +mediaImportInterfaces.MediaImportHandler.ImportTask.EntryChangedInfo;
diff --git a/ui/file_manager/externs/background/media_scanner.js b/ui/file_manager/externs/background/media_scanner.js index b4be080..f40525b 100644 --- a/ui/file_manager/externs/background/media_scanner.js +++ b/ui/file_manager/externs/background/media_scanner.js
@@ -2,21 +2,22 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -var importer = importer || {}; +// #import {importer} from '../../file_manager/common/js/importer_common.m.js'; +/* #export */ const mediaScannerInterfaces = {}; /** * Class representing the results of a scan operation. * * @interface */ -importer.MediaScanner = class { +mediaScannerInterfaces.MediaScanner = class { /** * Initiates scanning. * * @param {!DirectoryEntry} directory * @param {!importer.ScanMode} mode - * @return {!importer.ScanResult} ScanResult object representing the scan - * job both while in-progress and when completed. + * @return {!mediaScannerInterfaces.ScanResult} ScanResult object representing + * the scan job both while in-progress and when completed. */ scanDirectory(directory, mode) {} @@ -27,37 +28,37 @@ * must be of a supported media type. Individually supplied files * are not subject to deduplication. * @param {!importer.ScanMode} mode The method to detect new files. - * @return {!importer.ScanResult} ScanResult object representing the scan - * job for the explicitly supplied entries. + * @return {!mediaScannerInterfaces.ScanResult} ScanResult object representing + * the scan job for the explicitly supplied entries. */ scanFiles(entries, mode) {} /** * Adds an observer, which will be notified on scan events. * - * @param {!importer.ScanObserver} observer + * @param {!mediaScannerInterfaces.ScanObserver} observer */ addObserver(observer) {} /** * Remove a previously registered observer. * - * @param {!importer.ScanObserver} observer + * @param {!mediaScannerInterfaces.ScanObserver} observer */ removeObserver(observer) {} }; /** - * @typedef {function(!importer.ScanEvent, importer.ScanResult)} + * @typedef {function(!importer.ScanEvent, mediaScannerInterfaces.ScanResult)} */ -importer.ScanObserver; +mediaScannerInterfaces.ScanObserver; /** * Class representing the results of a scan operation. * * @interface */ -importer.ScanResult = class { +mediaScannerInterfaces.ScanResult = class { /** * @return {boolean} true if scanning is complete. */ @@ -116,12 +117,12 @@ * Returns a promise that fires when scanning is finished * normally or has been canceled. * - * @return {!Promise<!importer.ScanResult>} + * @return {!Promise<!mediaScannerInterfaces.ScanResult>} */ whenFinal() {} /** - * @return {!importer.ScanResult.Statistics} + * @return {!mediaScannerInterfaces.ScanResult.Statistics} */ getStatistics() {} }; @@ -139,4 +140,4 @@ * progress: number * }} */ -importer.ScanResult.Statistics; +mediaScannerInterfaces.ScanResult.Statistics;
diff --git a/ui/file_manager/file_manager/background/js/BUILD.gn b/ui/file_manager/file_manager/background/js/BUILD.gn index 3a0aeac..56fb50cf 100644 --- a/ui/file_manager/file_manager/background/js/BUILD.gn +++ b/ui/file_manager/file_manager/background/js/BUILD.gn
@@ -78,9 +78,12 @@ ":background_base.m", ":crostini.m", ":drive_sync_handler.m", + ":duplicate_finder.m", ":entry_location_impl.m", ":file_operation_util.m", ":import_history.m", + ":media_import_handler.m", + ":media_scanner.m", ":metadata_proxy.m", ":mock_drive_sync_handler.m", ":mock_file_operation_manager.m", @@ -109,6 +112,7 @@ uses_js_modules = true deps = [ ":mock_crostini.m", + ":mock_media_scanner.m", ":mock_volume_manager.m", ":test_import_history.m", ] @@ -144,7 +148,6 @@ "//ui/file_manager/externs/background/file_browser_background_full.js", "//ui/file_manager/externs/background/file_operation_manager.js", "//ui/file_manager/externs/background/import_history.js", - "//ui/file_manager/externs/background/import_runner.js", "//ui/file_manager/externs/background/media_import_handler.js", "//ui/file_manager/externs/background/media_scanner.js", "//ui/file_manager/externs/background/progress_center.js", @@ -387,14 +390,36 @@ externs_list = [ "//ui/file_manager/externs/background/duplicate_finder.js" ] } -js_unittest("duplicate_finder_unittest") { +js_library("duplicate_finder.m") { + sources = [ "$root_gen_dir/ui/file_manager/file_manager/background/js/duplicate_finder.m.js" ] deps = [ - ":duplicate_finder", - ":mock_volume_manager", - ":test_import_history", - "//ui/file_manager/base/js:mock_chrome", - "//ui/file_manager/file_manager/common/js:mock_entry", - "//ui/file_manager/file_manager/common/js:test_importer_common", + ":import_history.m", + ":volume_manager_factory.m", + "//ui/file_manager/base/js:volume_manager_types.m", + "//ui/file_manager/externs:volume_manager.m", + "//ui/file_manager/externs/background:duplicate_finder.m", + "//ui/file_manager/externs/background:import_history.m", + "//ui/file_manager/file_manager/common/js:importer_common.m", + "//ui/file_manager/file_manager/common/js:lru_cache.m", + "//ui/file_manager/file_manager/common/js:metrics.m", + ] + + extra_deps = [ ":modulize" ] +} + +js_unittest("duplicate_finder_unittest.m") { + deps = [ + ":duplicate_finder.m", + ":mock_volume_manager.m", + ":test_import_history.m", + "//chrome/test/data/webui:chai_assert", + "//ui/file_manager/base/js:mock_chrome.m", + "//ui/file_manager/base/js:test_error_reporting.m", + "//ui/file_manager/base/js:volume_manager_types.m", + "//ui/file_manager/externs:volume_info.m", + "//ui/file_manager/externs/background:duplicate_finder.m", + "//ui/file_manager/file_manager/common/js:importer_common.m", + "//ui/file_manager/file_manager/common/js:mock_entry.m", ] } @@ -549,6 +574,7 @@ "//ui/file_manager/base/js:mock_chrome.m", "//ui/file_manager/base/js:test_error_reporting.m", "//ui/file_manager/externs/background:import_history.m", + "//ui/file_manager/file_manager/common/js:importer_common.m", "//ui/file_manager/file_manager/common/js:mock_entry.m", "//ui/file_manager/file_manager/common/js:test_importer_common.m", "//ui/file_manager/file_manager/common/js:unittest_util.m", @@ -582,26 +608,55 @@ "//ui/file_manager/file_manager/common/js:metrics", ] externs_list = [ - "//ui/file_manager/externs/background/import_runner.js", "//ui/file_manager/externs/background/duplicate_finder.js", "//ui/file_manager/externs/background/task_queue.js", "//ui/file_manager/externs/background/media_import_handler.js", ] } -js_unittest("media_import_handler_unittest") { +js_library("media_import_handler.m") { + sources = [ "$root_gen_dir/ui/file_manager/file_manager/background/js/media_import_handler.m.js" ] deps = [ - ":file_operation_util", - ":media_import_handler", - ":mock_drive_sync_handler", - ":mock_media_scanner", - ":mock_progress_center", - ":mock_volume_manager", - ":test_import_history", - "//ui/file_manager/base/js:mock_chrome", - "//ui/file_manager/base/js:test_error_reporting", - "//ui/file_manager/file_manager/common/js:mock_entry", - "//ui/file_manager/file_manager/common/js:test_importer_common", + ":file_operation_util.m", + ":task_queue.m", + "//ui/file_manager/externs/background:drive_sync_handler.m", + "//ui/file_manager/externs/background:duplicate_finder.m", + "//ui/file_manager/externs/background:import_history.m", + "//ui/file_manager/externs/background:media_import_handler.m", + "//ui/file_manager/externs/background:media_scanner.m", + "//ui/file_manager/externs/background:progress_center.m", + "//ui/file_manager/externs/background:task_queue.m", + "//ui/file_manager/file_manager/common/js:async_util.m", + "//ui/file_manager/file_manager/common/js:importer_common.m", + "//ui/file_manager/file_manager/common/js:metrics.m", + "//ui/file_manager/file_manager/common/js:progress_center_common.m", + "//ui/file_manager/file_manager/common/js:util.m", + "//ui/webui/resources/js:assert.m", + ] + + extra_deps = [ ":modulize" ] +} + +js_unittest("media_import_handler_unittest.m") { + deps = [ + ":file_operation_util.m", + ":media_import_handler.m", + ":mock_drive_sync_handler.m", + ":mock_media_scanner.m", + ":mock_progress_center.m", + ":mock_volume_manager.m", + ":test_import_history.m", + "//chrome/test/data/webui:chai_assert", + "//ui/file_manager/base/js:mock_chrome.m", + "//ui/file_manager/base/js:test_error_reporting.m", + "//ui/file_manager/base/js:volume_manager_types.m", + "//ui/file_manager/externs:volume_info.m", + "//ui/file_manager/externs/background:duplicate_finder.m", + "//ui/file_manager/externs/background:import_history.m", + "//ui/file_manager/externs/background:media_import_handler.m", + "//ui/file_manager/file_manager/common/js:importer_common.m", + "//ui/file_manager/file_manager/common/js:mock_entry.m", + "//ui/file_manager/file_manager/common/js:test_importer_common.m", ] } @@ -616,6 +671,18 @@ visibility = [ "//ui/file_manager/file_manager/*" ] } +js_library("mock_media_scanner.m") { + sources = [ "$root_gen_dir/ui/file_manager/file_manager/background/js/mock_media_scanner.m.js" ] + deps = [ + ":media_scanner.m", + "//chrome/test/data/webui:chai_assert", + "//ui/file_manager/externs/background:media_scanner.m", + "//ui/file_manager/file_manager/common/js:importer_common.m", + ] + + extra_deps = [ ":modulize" ] +} + js_library("media_scanner") { deps = [ ":file_operation_util", @@ -624,11 +691,30 @@ externs_list = [ "//ui/file_manager/externs/background/media_scanner.js" ] } -js_unittest("media_scanner_unittest") { +js_library("media_scanner.m") { + sources = [ "$root_gen_dir/ui/file_manager/file_manager/background/js/media_scanner.m.js" ] deps = [ - ":media_scanner", - ":mock_media_scanner", - "//ui/file_manager/file_manager/common/js:test_importer_common", + ":file_operation_util.m", + ":metadata_proxy.m", + "//ui/file_manager/externs/background:media_scanner.m", + "//ui/file_manager/file_manager/common/js:importer_common.m", + "//ui/webui/resources/js:assert.m", + ] + + extra_deps = [ ":modulize" ] +} + +js_unittest("media_scanner_unittest.m") { + deps = [ + ":file_operation_util.m", + ":media_scanner.m", + ":mock_media_scanner.m", + ":test_import_history.m", + "//chrome/test/data/webui:chai_assert", + "//ui/file_manager/base/js:test_error_reporting.m", + "//ui/file_manager/externs/background:media_scanner.m", + "//ui/file_manager/file_manager/common/js:importer_common.m", + "//ui/file_manager/file_manager/common/js:unittest_util.m", ] } @@ -734,7 +820,6 @@ "//ui/file_manager/externs/background_window.js", "//ui/file_manager/externs/background/file_operation_manager.js", "//ui/file_manager/externs/background/import_history.js", - "//ui/file_manager/externs/background/import_runner.js", "//ui/file_manager/externs/background/background_base.js", "//ui/file_manager/externs/background/file_browser_background_full.js", ] @@ -952,7 +1037,10 @@ deps = [ ":crostini_unittest.m", ":drive_sync_handler_unittest.m", + ":duplicate_finder_unittest.m", ":import_history_unittest.m", + ":media_import_handler_unittest.m", + ":media_scanner_unittest.m", ":metadata_proxy_unittest.m", ":mount_metrics_unittest.m", ":task_queue_unittest.m", @@ -971,11 +1059,8 @@ js_test_gen_html("js_test_gen_html") { deps = [ ":device_handler_unittest", - ":duplicate_finder_unittest", ":file_operation_handler_unittest", ":file_operation_manager_unittest", - ":media_import_handler_unittest", - ":media_scanner_unittest", ":trash_unittest", ":volume_manager_unittest", ] @@ -1006,6 +1091,10 @@ "test_import_history.js", "import_history.js", "drive_sync_handler.js", + "media_scanner.js", + "mock_media_scanner.js", + "duplicate_finder.js", + "media_import_handler.js", ] namespace_rewrites = cr_namespace_rewrites
diff --git a/ui/file_manager/file_manager/background/js/background.js b/ui/file_manager/file_manager/background/js/background.js index 11b99a4..c2cbf62 100644 --- a/ui/file_manager/file_manager/background/js/background.js +++ b/ui/file_manager/file_manager/background/js/background.js
@@ -56,25 +56,26 @@ this.driveSyncHandler = new DriveSyncHandlerImpl(this.progressCenter); /** - * @type {!importer.DispositionChecker.CheckerFunction} + * @type {!duplicateFinderInterfaces.DispositionChecker.CheckerFunction} */ this.dispositionChecker_ = - importer.DispositionCheckerImpl.createChecker(this.historyLoader); + duplicateFinder.DispositionCheckerImpl.createChecker( + this.historyLoader); /** * Provides support for scanning media devices as part of Cloud Import. - * @type {!importer.MediaScanner} + * @type {!mediaScannerInterfaces.MediaScanner} */ - this.mediaScanner = new importer.DefaultMediaScanner( + this.mediaScanner = new mediaScanner.DefaultMediaScanner( importerHistory.createMetadataHashcode, this.dispositionChecker_, - importer.DefaultDirectoryWatcher.create); + mediaScanner.DefaultDirectoryWatcher.create); /** * Handles importing of user media (e.g. photos, videos) from removable * devices. - * @type {!importer.MediaImportHandler} + * @type {!mediaImportInterfaces.MediaImportHandler} */ - this.mediaImportHandler = new importer.MediaImportHandlerImpl( + this.mediaImportHandler = new mediaImport.MediaImportHandlerImpl( this.progressCenter, this.historyLoader, this.dispositionChecker_, this.driveSyncHandler);
diff --git a/ui/file_manager/file_manager/background/js/duplicate_finder.js b/ui/file_manager/file_manager/background/js/duplicate_finder.js index 46da4164..d1c0317 100644 --- a/ui/file_manager/file_manager/background/js/duplicate_finder.js +++ b/ui/file_manager/file_manager/background/js/duplicate_finder.js
@@ -2,14 +2,32 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Namespace -window.importer = window.importer || {}; +/** + * @fileoverview + * @suppress {uselessCode} Temporary suppress because of the line exporting. + */ + +// clang-format off +// #import {VolumeManagerCommon} from '../../../base/js/volume_manager_types.m.js'; + +// #import {VolumeManager} from '../../../externs/volume_manager.m.js'; +// #import {importerHistoryInterfaces} from '../../../externs/background/import_history.m.js'; +// #import {duplicateFinderInterfaces} from '../../../externs/background/duplicate_finder.m.js'; +// #import {volumeManagerFactory} from './volume_manager_factory.m.js'; +// #import {metrics} from '../../common/js/metrics.m.js'; +// #import {importerHistory} from './import_history.m.js'; +// #import {LRUCache} from '../../common/js/lru_cache.m.js'; +// #import {importer} from '../../common/js/importer_common.m.js'; +// clang-format on + +// eslint-disable-next-line no-var +var duplicateFinder = {}; /** * A duplicate finder for Google Drive. * */ -importer.DriveDuplicateFinder = class DriveDuplicateFinder { +duplicateFinder.DriveDuplicateFinder = class { constructor() { /** @private {Promise<string>} */ this.driveIdPromise_ = null; @@ -18,8 +36,8 @@ * An bounded cache of most recently calculated file content hashcodes. * @private {!LRUCache<!Promise<string>>} */ - this.hashCache_ = - new LRUCache(importer.DriveDuplicateFinder.MAX_CACHED_HASHCODES_); + this.hashCache_ = new LRUCache( + duplicateFinder.DriveDuplicateFinder.MAX_CACHED_HASHCODES_); } /** @@ -54,22 +72,22 @@ } const hashPromise = new Promise( - /** @this {importer.DriveDuplicateFinder} */ + /** @this {duplicateFinder.DriveDuplicateFinder} */ (resolve, reject) => { const startTime = new Date().getTime(); chrome.fileManagerPrivate.computeChecksum( entry, /** * @param {string|undefined} result The content hash. - * @this {importer.DriveDuplicateFinder} + * @this {duplicateFinder.DriveDuplicateFinder} */ result => { const elapsedTime = new Date().getTime() - startTime; // Send the timing to GA only if it is sorta exceptionally // long. A one second, CPU intensive operation, is pretty // long. - if (elapsedTime >= - importer.DriveDuplicateFinder.HASH_EVENT_THRESHOLD_) { + if (elapsedTime >= duplicateFinder.DriveDuplicateFinder + .HASH_EVENT_THRESHOLD_) { console.info( 'Content hash computation took ' + elapsedTime + ' ms.'); @@ -131,7 +149,7 @@ */ searchFilesByHash_(hash, volumeId) { return new Promise( - /** @this {importer.DriveDuplicateFinder} */ + /** @this {duplicateFinder.DriveDuplicateFinder} */ (resolve, reject) => { const startTime = new Date().getTime(); chrome.fileManagerPrivate.searchFilesByHashes( @@ -142,8 +160,8 @@ urls => { const elapsedTime = new Date().getTime() - startTime; // Send the timing to GA only if it is sorta exceptionally long. - if (elapsedTime >= - importer.DriveDuplicateFinder.SEARCH_EVENT_THRESHOLD_) { + if (elapsedTime >= duplicateFinder.DriveDuplicateFinder + .SEARCH_EVENT_THRESHOLD_) { metrics.recordTime( 'DriveDuplicateFinder.LongSearchByHash', elapsedTime); } @@ -158,13 +176,13 @@ }; /** @private @const {number} */ -importer.DriveDuplicateFinder.HASH_EVENT_THRESHOLD_ = 5000; +duplicateFinder.DriveDuplicateFinder.HASH_EVENT_THRESHOLD_ = 5000; /** @private @const {number} */ -importer.DriveDuplicateFinder.SEARCH_EVENT_THRESHOLD_ = 1000; +duplicateFinder.DriveDuplicateFinder.SEARCH_EVENT_THRESHOLD_ = 1000; /** @private @const {number} */ -importer.DriveDuplicateFinder.MAX_CACHED_HASHCODES_ = 10000; +duplicateFinder.DriveDuplicateFinder.MAX_CACHED_HASHCODES_ = 10000; /** @@ -173,18 +191,18 @@ * primary source for duplicate checking (with the exception * of in-scan deduplication, where duplicate results that * are within the scan are ignored). - * @implements {importer.DispositionChecker} + * @implements {duplicateFinderInterfaces.DispositionChecker} */ -importer.DispositionCheckerImpl = class { +duplicateFinder.DispositionCheckerImpl = class { /** * @param {!importerHistoryInterfaces.HistoryLoader} historyLoader - * @param {!importer.DriveDuplicateFinder} contentMatcher + * @param {!duplicateFinder.DriveDuplicateFinder} contentMatcher */ constructor(historyLoader, contentMatcher) { /** @private {!importerHistoryInterfaces.HistoryLoader} */ this.historyLoader_ = historyLoader; - /** @private {!importer.DriveDuplicateFinder} */ + /** @private {!duplicateFinder.DriveDuplicateFinder} */ this.contentMatcher_ = contentMatcher; } @@ -200,7 +218,7 @@ } return new Promise( - /** @this {importer.DispositionChecker} */ + /** @this {duplicateFinderInterfaces.DispositionChecker} */ (resolve, reject) => { this.hasHistoryDuplicate_(entry, destination) .then( @@ -264,11 +282,14 @@ * * @param {!importerHistoryInterfaces.HistoryLoader} historyLoader * - * @return {!importer.DispositionChecker.CheckerFunction} + * @return {!duplicateFinderInterfaces.DispositionChecker.CheckerFunction} */ static createChecker(historyLoader) { - const checker = new importer.DispositionCheckerImpl( - historyLoader, new importer.DriveDuplicateFinder()); + const checker = new duplicateFinder.DispositionCheckerImpl( + historyLoader, new duplicateFinder.DriveDuplicateFinder()); return checker.getDisposition.bind(checker); } }; + +// eslint-disable-next-line semi,no-extra-semi +/* #export */ {duplicateFinder};
diff --git a/ui/file_manager/file_manager/background/js/duplicate_finder_unittest.js b/ui/file_manager/file_manager/background/js/duplicate_finder_unittest.m.js similarity index 73% rename from ui/file_manager/file_manager/background/js/duplicate_finder_unittest.js rename to ui/file_manager/file_manager/background/js/duplicate_finder_unittest.m.js index 14c06a8e..c559168 100644 --- a/ui/file_manager/file_manager/background/js/duplicate_finder_unittest.js +++ b/ui/file_manager/file_manager/background/js/duplicate_finder_unittest.m.js
@@ -2,8 +2,22 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -/** @type {!importer.DriveDuplicateFinder} */ -let duplicateFinder; +import {assertEquals, assertFalse, assertTrue} from 'chrome://test/chai_assert.js'; + +import {installMockChrome, MockCommandLinePrivate} from '../../../base/js/mock_chrome.m.js'; +import {reportPromise} from '../../../base/js/test_error_reporting.m.js'; +import {VolumeManagerCommon} from '../../../base/js/volume_manager_types.m.js'; +import {duplicateFinderInterfaces} from '../../../externs/background/duplicate_finder.m.js'; +import {VolumeInfo} from '../../../externs/volume_info.m.js'; +import {importer} from '../../common/js/importer_common.m.js'; +import {MockFileSystem} from '../../common/js/mock_entry.m.js'; + +import {duplicateFinder} from './duplicate_finder.m.js'; +import {MockVolumeManager} from './mock_volume_manager.m.js'; +import {importerTestHistory} from './test_import_history.m.js'; + +/** @type {!duplicateFinder.DriveDuplicateFinder} */ +let duplicateFinderTest; /** @type {VolumeInfo} */ let drive; @@ -26,14 +40,14 @@ /** @type {!importerTestHistory.TestImportHistory} */ let testHistory; -/** @type {importer.DispositionChecker.CheckerFunction} */ +/** @type {duplicateFinderInterfaces.DispositionChecker.CheckerFunction} */ let getDisposition; window.metrics = { recordTime: function() {}, }; -function setUp() { +export function setUp() { window.loadTimeData.getString = id => id; const mockChrome = { fileManagerPrivate: { @@ -64,7 +78,6 @@ installMockChrome(mockChrome); new MockCommandLinePrivate(); - // importer.setupTestLogger(); fileSystem = new MockFileSystem('fake-filesystem'); const volumeManager = new MockVolumeManager(); @@ -75,25 +88,26 @@ MockVolumeManager.installMockSingleton(volumeManager); testHistory = new importerTestHistory.TestImportHistory(); - duplicateFinder = new importer.DriveDuplicateFinder(); - getDisposition = importer.DispositionCheckerImpl.createChecker(testHistory); + duplicateFinderTest = new duplicateFinder.DriveDuplicateFinder(); + getDisposition = + duplicateFinder.DispositionCheckerImpl.createChecker(testHistory); } // Verifies the correct result when a duplicate exists. -function testCheckDuplicateTrue(callback) { +export function testCheckDuplicateTrue(callback) { const filePaths = ['/foo.txt']; const fileHashes = ['abc123']; const files = setupHashes(filePaths, fileHashes); reportPromise( - duplicateFinder.isDuplicate(files[0]).then(isDuplicate => { + duplicateFinderTest.isDuplicate(files[0]).then(isDuplicate => { assertTrue(isDuplicate); }), callback); } // Verifies the correct result when a duplicate doesn't exist. -function testCheckDuplicateFalse(callback) { +export function testCheckDuplicateFalse(callback) { const filePaths = ['/foo.txt']; const fileHashes = ['abc123']; const files = setupHashes(filePaths, fileHashes); @@ -104,13 +118,13 @@ const newFile = /** @type {!FileEntry} */ (fileSystem.entries[newFilePath]); reportPromise( - duplicateFinder.isDuplicate(newFile).then(isDuplicate => { + duplicateFinderTest.isDuplicate(newFile).then(isDuplicate => { assertFalse(isDuplicate); }), callback); } -function testDispositionChecker_ContentDupe(callback) { +export function testDispositionChecker_ContentDupe(callback) { const filePaths = ['/foo.txt']; const fileHashes = ['abc123']; const files = setupHashes(filePaths, fileHashes); @@ -125,7 +139,7 @@ callback); } -function testDispositionChecker_HistoryDupe(callback) { +export function testDispositionChecker_HistoryDupe(callback) { const filePaths = ['/foo.txt']; const fileHashes = ['abc123']; const files = setupHashes(filePaths, fileHashes); @@ -142,7 +156,7 @@ callback); } -function testDispositionChecker_Original(callback) { +export function testDispositionChecker_Original(callback) { const filePaths = ['/foo.txt']; const fileHashes = ['abc123']; const files = setupHashes(filePaths, fileHashes);
diff --git a/ui/file_manager/file_manager/background/js/import_history_unittest.m.js b/ui/file_manager/file_manager/background/js/import_history_unittest.m.js index af103199..a5e5c70 100644 --- a/ui/file_manager/file_manager/background/js/import_history_unittest.m.js +++ b/ui/file_manager/file_manager/background/js/import_history_unittest.m.js
@@ -8,8 +8,9 @@ import {MockChromeStorageAPI} from '../../../base/js/mock_chrome.m.js'; import {reportPromise} from '../../../base/js/test_error_reporting.m.js'; import {importerHistoryInterfaces} from '../../../externs/background/import_history.m.js'; -import { MockFileEntry,MockFileSystem} from '../../common/js/mock_entry.m.js'; -import {importer} from '../../common/js/test_importer_common.m.js'; +import {importer} from '../../common/js/importer_common.m.js'; +import {MockFileEntry,MockFileSystem} from '../../common/js/mock_entry.m.js'; +import {importerTest} from '../../common/js/test_importer_common.m.js'; import {TestCallRecorder} from '../../common/js/unittest_util.m.js'; import {importerHistory} from './import_history.m.js'; @@ -42,7 +43,7 @@ /** @type {!FileEntry} */ let testFileEntry; -/** @type {!importer.TestLogger} */ +/** @type {!importerTest.TestLogger} */ let testLogger; /** @type {!importerHistory.RecordStorage} */ @@ -297,8 +298,8 @@ * Installs importer test logger. */ function installTestLogger() { - testLogger = new importer.TestLogger(); - importer.getLogger = () => { + testLogger = new importerTest.TestLogger(); + importerTest.getLogger = () => { return testLogger; }; }
diff --git a/ui/file_manager/file_manager/background/js/media_import_handler.js b/ui/file_manager/file_manager/background/js/media_import_handler.js index 2c24b2f..e47190a 100644 --- a/ui/file_manager/file_manager/background/js/media_import_handler.js +++ b/ui/file_manager/file_manager/background/js/media_import_handler.js
@@ -2,24 +2,41 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Namespace -window.importer = window.importer || {}; +// clang-format off +// #import {assert} from 'chrome://resources/js/assert.m.js'; +// #import {AsyncUtil} from '../../common/js/async_util.m.js'; +// #import {strf, util} from '../../common/js/util.m.js'; +// #import {ProgressCenterItem, ProgressItemType, ProgressItemState} from '../../common/js/progress_center_common.m.js'; +// #import {fileOperationUtil} from './file_operation_util.m.js'; +// #import {taskQueue} from './task_queue.m.js'; +// #import {metrics} from '../../common/js/metrics.m.js'; -importer.MediaImportHandler = importer.MediaImportHandler || {}; -importer.MediaImportHandler.ImportTask = - importer.MediaImportHandler.ImportTask || {}; +// #import {importer} from '../../common/js/importer_common.m.js'; +// #import {DriveSyncHandler} from '../../../externs/background/drive_sync_handler.m.js'; +// #import {importerHistoryInterfaces} from '../../../externs/background/import_history.m.js'; +// #import {duplicateFinderInterfaces} from '../../../externs/background/duplicate_finder.m.js'; +// #import {mediaScannerInterfaces} from '../../../externs/background/media_scanner.m.js'; +// #import {mediaImportInterfaces} from '../../../externs/background/media_import_handler.m.js'; +// #import {taskQueueInterfaces} from '../../../externs/background/task_queue.m.js'; +// #import {ProgressCenter} from '../../../externs/background/progress_center.m.js'; +// clang-format on + + +// Namespace +/* #export */ const mediaImport = {}; /** * Handler for importing media from removable devices into the user's Drive. * - * @implements {importer.ImportRunner} - * @implements {importer.MediaImportHandler} + * @implements {mediaImportInterfaces.ImportRunner} + * @implements {mediaImportInterfaces.MediaImportHandler} */ -importer.MediaImportHandlerImpl = class { +mediaImport.MediaImportHandlerImpl = class { /** * @param {!ProgressCenter} progressCenter * @param {!importerHistoryInterfaces.HistoryLoader} historyLoader - * @param {!importer.DispositionChecker.CheckerFunction} dispositionChecker + * @param {!duplicateFinderInterfaces.DispositionChecker.CheckerFunction} + * dispositionChecker * @param {!DriveSyncHandler} driveSyncHandler */ constructor( @@ -44,7 +61,9 @@ /** @private {number} */ this.nextTaskId_ = 0; - /** @private {!importer.DispositionChecker.CheckerFunction} */ + /** + * @private {!duplicateFinderInterfaces.DispositionChecker.CheckerFunction} + */ this.getDisposition_ = dispositionChecker; /** @@ -71,7 +90,7 @@ /** @override */ importFromScanResult(scanResult, destination, directoryPromise) { - const task = new importer.MediaImportHandler.ImportTaskImpl( + const task = new mediaImport.ImportTaskImpl( this.generateTaskId_(), this.historyLoader_, scanResult, directoryPromise, destination, this.getDisposition_); @@ -99,7 +118,7 @@ /** * Sends updates to the ProgressCenter when an import is happening. * - * @param {!importer.MediaImportHandler.ImportTaskImpl} task + * @param {!mediaImport.ImportTaskImpl} task * @param {string} updateType * @private */ @@ -175,7 +194,7 @@ /** * Restarts a task with failed entries. - * @param {!importer.MediaImportHandler.ImportTaskImpl} task + * @param {!mediaImport.ImportTaskImpl} task */ retryTaskFailedEntries_(task) { // Reset the entry lists. @@ -198,17 +217,17 @@ * the FileOperationManager (and thus *spawns* an associated * FileOperationManager.CopyTask) but this is a temporary state of affairs. * - * @implements {importer.MediaImportHandler.ImportTask} + * @implements {mediaImportInterfaces.MediaImportHandler.ImportTask} */ -importer.MediaImportHandler.ImportTaskImpl = - class extends taskQueue.BaseTaskImpl { +mediaImport.ImportTaskImpl = class extends taskQueue.BaseTaskImpl { /** * @param {string} taskId * @param {!importerHistoryInterfaces.HistoryLoader} historyLoader - * @param {!importer.ScanResult} scanResult + * @param {!mediaScannerInterfaces.ScanResult} scanResult * @param {!Promise<!DirectoryEntry>} directoryPromise * @param {!importer.Destination} destination The logical destination. - * @param {!importer.DispositionChecker.CheckerFunction} dispositionChecker + * @param {!duplicateFinderInterfaces.DispositionChecker.CheckerFunction} + * dispositionChecker */ constructor( taskId, historyLoader, scanResult, directoryPromise, destination, @@ -224,7 +243,7 @@ /** @private {!Promise<!DirectoryEntry>} */ this.directoryPromise_ = directoryPromise; - /** @private {!importer.ScanResult} */ + /** @private {!mediaScannerInterfaces.ScanResult} */ this.scanResult_ = scanResult; /** @private {!importerHistoryInterfaces.HistoryLoader} */ @@ -254,7 +273,9 @@ /** @private {number} */ this.errorCount_ = 0; - /** @private {!importer.DispositionChecker.CheckerFunction} */ + /** + * @private {!duplicateFinderInterfaces.DispositionChecker.CheckerFunction} + */ this.getDisposition_ = dispositionChecker; /** @@ -381,7 +402,7 @@ this.scanResult_.getDuplicateFileEntries().forEach( /** * @param {!FileEntry} entry - * @this {importer.MediaImportHandler.ImportTask} + * @this {mediaImportInterfaces.MediaImportHandler.ImportTask} */ entry => { history.markImported(entry, this.destination_); @@ -450,7 +471,7 @@ * Updates the task when the copy code reports progress. * @param {string} sourceUrl * @param {number} processedBytes - * @this {importer.MediaImportHandler.ImportTask} + * @this {mediaImportInterfaces.MediaImportHandler.ImportTask} */ const onProgress = (sourceUrl, processedBytes) => { // Update the running total, then send a progress update. @@ -464,7 +485,7 @@ * Updates the task when the new file has been created. * @param {string} sourceUrl * @param {Entry} destinationEntry - * @this {importer.MediaImportHandler.ImportTask} + * @this {mediaImportInterfaces.MediaImportHandler.ImportTask} */ const onEntryChanged = (sourceUrl, destinationEntry) => { this.processedBytes_ -= currentBytes; @@ -472,7 +493,7 @@ destinationEntry.size = entry.size; this.notify( /** @type {importer.UpdateType} */ - (importer.MediaImportHandler.ImportTask.UpdateType.ENTRY_CHANGED), { + (mediaImport.UpdateType.ENTRY_CHANGED), { sourceUrl: sourceUrl, destination: destinationEntry, }); @@ -481,7 +502,7 @@ /** * @param {Entry} destinationEntry The new destination entry. - * @this {importer.MediaImportHandler.ImportTask} + * @this {mediaImportInterfaces.MediaImportHandler.ImportTask} */ const onComplete = destinationEntry => { this.cancelCallback_ = null; @@ -490,7 +511,7 @@ resolver.resolve(destinationEntry); }; - /** @this {importer.MediaImportHandler.ImportTask} */ + /** @this {mediaImportInterfaces.MediaImportHandler.ImportTask} */ const onError = error => { this.cancelCallback_ = null; if (error.name === util.FileError.ABORT_ERR) { @@ -599,6 +620,6 @@ * ImportTask to listen for these kinds of updates. * @enum {string} */ -importer.MediaImportHandler.ImportTask.UpdateType = { +mediaImport.UpdateType = { ENTRY_CHANGED: 'ENTRY_CHANGED' };
diff --git a/ui/file_manager/file_manager/background/js/media_import_handler_unittest.js b/ui/file_manager/file_manager/background/js/media_import_handler_unittest.m.js similarity index 88% rename from ui/file_manager/file_manager/background/js/media_import_handler_unittest.js rename to ui/file_manager/file_manager/background/js/media_import_handler_unittest.m.js index ff7d9c19..a852add9 100644 --- a/ui/file_manager/file_manager/background/js/media_import_handler_unittest.js +++ b/ui/file_manager/file_manager/background/js/media_import_handler_unittest.m.js
@@ -2,18 +2,37 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -'use strict'; +import {assertEquals, assertFalse, assertTrue} from 'chrome://test/chai_assert.js'; + +import {installMockChrome, MockCommandLinePrivate} from '../../../base/js/mock_chrome.m.js'; +import {reportPromise} from '../../../base/js/test_error_reporting.m.js'; +import {VolumeManagerCommon} from '../../../base/js/volume_manager_types.m.js'; +import {duplicateFinderInterfaces} from '../../../externs/background/duplicate_finder.m.js'; +import {importerHistoryInterfaces} from '../../../externs/background/import_history.m.js'; +import {mediaImportInterfaces} from '../../../externs/background/media_import_handler.m.js'; +import {VolumeInfo} from '../../../externs/volume_info.m.js'; +import {importer} from '../../common/js/importer_common.m.js'; +import {MockDirectoryEntry, MockFileSystem} from '../../common/js/mock_entry.m.js'; +import {importerTest} from '../../common/js/test_importer_common.m.js'; + +import {fileOperationUtil} from './file_operation_util.m.js'; +import {mediaImport} from './media_import_handler.m.js'; +import {MockDriveSyncHandler} from './mock_drive_sync_handler.m.js'; +import {TestScanResult} from './mock_media_scanner.m.js'; +import {MockProgressCenter} from './mock_progress_center.m.js'; +import {MockVolumeManager} from './mock_volume_manager.m.js'; +import {importerTestHistory} from './test_import_history.m.js'; /** @type {!MockProgressCenter} */ let progressCenter; -/** @type {!importer.MediaImportHandler} */ +/** @type {!mediaImportInterfaces.MediaImportHandler} */ let mediaImporter; /** @type {!importerTestHistory.TestImportHistory} */ let importHistory; -/** @type {!importer.DispositionChecker.CheckerFunction} */ +/** @type {!duplicateFinderInterfaces.DispositionChecker.CheckerFunction} */ let dispositionChecker; /** @type {!MockCopyTo} */ @@ -46,7 +65,7 @@ let mockChrome; // Set up the test components. -function setUp() { +export function setUp() { // Mock loadTimeData strings. window.loadTimeData.getString = id => id; @@ -93,8 +112,8 @@ progressCenter = new MockProgressCenter(); importHistory = new importerTestHistory.TestImportHistory(); driveSyncHandler = new MockDriveSyncHandler(); - importer.setupTestLogger(); - mediaImporter = new importer.MediaImportHandlerImpl( + importerTest.setupTestLogger(); + mediaImporter = new mediaImport.MediaImportHandlerImpl( progressCenter, importHistory, dispositionChecker, driveSyncHandler); // Setup the copy destination. @@ -105,7 +124,7 @@ /** * Tests media imports. */ -function testImportMedia(callback) { +export function testImportMedia(callback) { const media = setupFileSystem([ '/DCIM/photos0/IMG00001.jpg', '/DCIM/photos0/IMG00002.jpg', @@ -152,7 +171,7 @@ /** * Tests media import duplicate detection. */ -function testImportMedia_skipAndMarkDuplicatedFiles(callback) { +export function testImportMedia_skipAndMarkDuplicatedFiles(callback) { const DUPLICATED_FILE_PATH_1 = '/DCIM/photos0/duplicated_1.jpg'; const DUPLICATED_FILE_PATH_2 = '/DCIM/photos0/duplicated_2.jpg'; const ORIGINAL_FILE_NAME = 'new_image.jpg'; @@ -173,7 +192,7 @@ } return Promise.resolve(importer.Disposition.ORIGINAL); }; - mediaImporter = new importer.MediaImportHandlerImpl( + mediaImporter = new mediaImport.MediaImportHandlerImpl( progressCenter, importHistory, dispositionChecker, driveSyncHandler); const scanResult = new TestScanResult(media); const importTask = mediaImporter.importFromScanResult( @@ -223,7 +242,7 @@ /** * Tests media import uses encoded URLs. */ -function testImportMedia_EmploysEncodedUrls(callback) { +export function testImportMedia_EmploysEncodedUrls(callback) { const media = setupFileSystem([ '/DCIM/photos0/Mom and Dad.jpg', ]); @@ -267,7 +286,7 @@ * Tests that when files with duplicate names are imported, that they don't * overwrite one another. */ -function testImportMediaWithDuplicateFilenames(callback) { +export function testImportMediaWithDuplicateFilenames(callback) { const media = setupFileSystem([ '/DCIM/photos0/IMG00001.jpg', '/DCIM/photos0/IMG00002.jpg', @@ -315,7 +334,7 @@ /** * Tests that active media imports keep chrome.power awake. */ -function testKeepAwakeDuringImport(callback) { +export function testKeepAwakeDuringImport(callback) { const media = setupFileSystem([ '/DCIM/photos0/IMG00001.jpg', '/DCIM/photos0/IMG00002.jpg', @@ -366,7 +385,7 @@ /** * Tests that media imports update import history. */ -function testUpdatesHistoryAfterImport(callback) { +export function testUpdatesHistoryAfterImport(callback) { const entries = setupFileSystem([ '/DCIM/photos0/IMG00001.jpg', '/DCIM/photos1/IMG00003.jpg', @@ -422,7 +441,7 @@ /** * Tests cancelling a media import. */ -function testImportCancellation(callback) { +export function testImportCancellation(callback) { const media = setupFileSystem([ '/DCIM/photos0/IMG00001.jpg', '/DCIM/photos0/IMG00002.jpg', @@ -455,8 +474,7 @@ // Simulate cancellation after the expected number of copies is done. let copyCount = 0; importTask.addObserver(updateType => { - if (updateType === - importer.MediaImportHandler.ImportTask.UpdateType.ENTRY_CHANGED) { + if (updateType === mediaImport.UpdateType.ENTRY_CHANGED) { copyCount++; if (copyCount === EXPECTED_COPY_COUNT) { importTask.requestCancel(); @@ -479,10 +497,10 @@ /** * Tests media imports with errors. */ -function testImportWithErrors(callback) { +export function testImportWithErrors(callback) { // Quieten the logger just in this test, since we expect errors. // Elsewhere, it's better for errors to be seen by test authors. - importer.setupTestLogger().quiet(); + importerTest.setupTestLogger().quiet(); const media = setupFileSystem([ '/DCIM/photos0/IMG00001.jpg', @@ -516,8 +534,7 @@ // Simulate an error after 3 imports. let copyCount = 0; importTask.addObserver(updateType => { - if (updateType === - importer.MediaImportHandler.ImportTask.UpdateType.ENTRY_CHANGED) { + if (updateType === mediaImport.UpdateType.ENTRY_CHANGED) { copyCount++; if (copyCount === 3) { mockCopier.simulateOneError();
diff --git a/ui/file_manager/file_manager/background/js/media_scanner.js b/ui/file_manager/file_manager/background/js/media_scanner.js index 18b3205..51db1f1a 100644 --- a/ui/file_manager/file_manager/background/js/media_scanner.js +++ b/ui/file_manager/file_manager/background/js/media_scanner.js
@@ -2,32 +2,43 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +// clang-format off +// #import {assert} from 'chrome://resources/js/assert.m.js'; +// #import {metadataProxy} from './metadata_proxy.m.js'; +// #import {fileOperationUtil} from './file_operation_util.m.js'; +// #import {importer} from '../../common/js/importer_common.m.js'; +// #import {mediaScannerInterfaces} from '../../../externs/background/media_scanner.m.js'; +// clang-format on + +// Namespace +/* #export */ const mediaScanner = {}; + /** * Recursively scans through a list of given files and directories, and creates * a list of media files. * - * @implements {importer.MediaScanner} + * @implements {mediaScannerInterfaces.MediaScanner} */ -importer.DefaultMediaScanner = class { +mediaScanner.DefaultMediaScanner = class { /** * @param {function(!FileEntry): !Promise<string>} hashGenerator * @param {function(!FileEntry, !importer.Destination, * !importer.ScanMode): * !Promise<!importer.Disposition>} dispositionChecker - * @param {!importer.DirectoryWatcherFactory} watcherFactory + * @param {!mediaScanner.DirectoryWatcherFactory} watcherFactory */ constructor(hashGenerator, dispositionChecker, watcherFactory) { /** * A little factory for DefaultScanResults which allows us to forgo * the saving it's dependencies in our fields. * @param {importer.ScanMode} mode Mode of the scan to find new files. - * @return {!importer.DefaultScanResult} + * @return {!mediaScanner.DefaultScanResult} */ this.createScanResult_ = mode => { - return new importer.DefaultScanResult(mode, hashGenerator); + return new mediaScanner.DefaultScanResult(mode, hashGenerator); }; - /** @private {!Array<!importer.ScanObserver>} */ + /** @private {!Array<!mediaScannerInterfaces.ScanObserver>} */ this.observers_ = []; /** @@ -39,7 +50,7 @@ this.getDisposition_ = dispositionChecker; /** - * @private {!importer.DirectoryWatcherFactory} + * @private {!mediaScanner.DirectoryWatcherFactory} * @const */ this.watcherFactory_ = watcherFactory; @@ -67,7 +78,7 @@ console.info(scan.name + ': Scanning directory ' + directory.fullPath); const watcher = this.watcherFactory_( - /** @this {importer.DefaultMediaScanner} */ + /** @this {mediaScanner.DefaultMediaScanner} */ () => { scan.cancel(); this.notify_(importer.ScanEvent.INVALIDATED, scan); @@ -119,7 +130,7 @@ /** - * @param {!importer.DefaultScanResult} scan + * @param {!mediaScanner.DefaultScanResult} scan * @param {!Array<!FileEntry>} entries * @return {!Promise} Resolves when scanning is finished normally * or canceled. @@ -143,7 +154,7 @@ } // the second arg to slice is an exclusive end index, so we +1 batch size. - const end = begin + importer.DefaultMediaScanner.SCAN_BATCH_SIZE; + const end = begin + mediaScanner.DefaultMediaScanner.SCAN_BATCH_SIZE; console.log(scan.name + ': Processing batch ' + begin + '-' + (end - 1)); const batch = entries.slice(begin, end); @@ -161,12 +172,12 @@ * Notifies all listeners at some point in the near future. * * @param {!importer.ScanEvent} event - * @param {!importer.DefaultScanResult} result + * @param {!mediaScanner.DefaultScanResult} result * @private */ notify_(event, result) { this.observers_.forEach( - /** @param {!importer.ScanObserver} observer */ + /** @param {!mediaScannerInterfaces.ScanObserver} observer */ observer => { observer(event, result); }); @@ -177,7 +188,7 @@ * watchers for each encountered directory. * * @param {!DirectoryEntry} directory - * @param {!importer.DirectoryWatcher} watcher + * @param {!mediaScanner.DirectoryWatcher} watcher * @return {!Promise<!Array<!FileEntry>>} * @private */ @@ -210,7 +221,7 @@ /** * Finds all files beneath directory. * - * @param {!importer.DefaultScanResult} scan + * @param {!mediaScanner.DefaultScanResult} scan * @param {!FileEntry} entry * @return {!Promise} * @private @@ -234,7 +245,7 @@ /** * Adds a newly discovered file to the given scan result. * - * @param {!importer.DefaultScanResult} scan + * @param {!mediaScanner.DefaultScanResult} scan * @param {!FileEntry} entry * @return {!Promise} * @private @@ -261,7 +272,7 @@ * Adds a duplicate file to the given scan result. This is to track the * number of duplicates that are being encountered. * - * @param {!importer.DefaultScanResult} scan + * @param {!mediaScanner.DefaultScanResult} scan * @param {!FileEntry} entry * @param {!importer.Disposition} disposition * @return {!Promise} @@ -276,7 +287,7 @@ }; /** @const {number} */ -importer.DefaultMediaScanner.SCAN_BATCH_SIZE = 1; +mediaScanner.DefaultMediaScanner.SCAN_BATCH_SIZE = 1; /** * Results of a scan operation. The object is "live" in that data can and @@ -288,9 +299,9 @@ * Note that classes implementing this should provide a read-only * {@code name} field. * - * @implements {importer.ScanResult} + * @implements {mediaScannerInterfaces.ScanResult} */ -importer.DefaultScanResult = class { +mediaScanner.DefaultScanResult = class { /** * @param {importer.ScanMode} mode The scan mode applied for finding new * files. @@ -365,7 +376,7 @@ */ this.canceled_ = false; - /** @private {!importer.Resolver.<!importer.ScanResult>} */ + /** @private {!importer.Resolver.<!mediaScannerInterfaces.ScanResult>} */ this.resolver_ = new importer.Resolver(); } @@ -520,7 +531,7 @@ * Watcher for directories. * @interface */ -importer.DirectoryWatcher = class { +mediaScanner.DirectoryWatcher = class { constructor() { /** @type {boolean} */ this.triggered = false; @@ -536,19 +547,19 @@ /** * @typedef {function()} */ -importer.DirectoryWatcherFactoryCallback; +mediaScanner.DirectoryWatcherFactoryCallback; /** - * @typedef {function(importer.DirectoryWatcherFactoryCallback): - * !importer.DirectoryWatcher} + * @typedef {function(mediaScanner.DirectoryWatcherFactoryCallback): + * !mediaScanner.DirectoryWatcher} */ -importer.DirectoryWatcherFactory; +mediaScanner.DirectoryWatcherFactory; /** * Watcher for directories. - * @implements {importer.DirectoryWatcher} + * @implements {mediaScanner.DirectoryWatcher} */ -importer.DefaultDirectoryWatcher = class { +mediaScanner.DefaultDirectoryWatcher = class { /** * @param {function()} callback Callback to be invoked when one of watched * directories is changed. @@ -564,10 +575,10 @@ * Creates new directory watcher. * @param {function()} callback Callback to be invoked when one of watched * directories is changed. - * @return {!importer.DirectoryWatcher} + * @return {!mediaScanner.DirectoryWatcher} */ static create(callback) { - return new importer.DefaultDirectoryWatcher(callback); + return new mediaScanner.DefaultDirectoryWatcher(callback); } /**
diff --git a/ui/file_manager/file_manager/background/js/media_scanner_unittest.js b/ui/file_manager/file_manager/background/js/media_scanner_unittest.m.js similarity index 88% rename from ui/file_manager/file_manager/background/js/media_scanner_unittest.js rename to ui/file_manager/file_manager/background/js/media_scanner_unittest.m.js index 98c2c3c..8c21b90 100644 --- a/ui/file_manager/file_manager/background/js/media_scanner_unittest.js +++ b/ui/file_manager/file_manager/background/js/media_scanner_unittest.m.js
@@ -2,6 +2,18 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import {assertEquals, assertFalse, assertThrows} from 'chrome://test/chai_assert.js'; + +import {reportPromise} from '../../../base/js/test_error_reporting.m.js'; +import {mediaScannerInterfaces} from '../../../externs/background/media_scanner.m.js'; +import {importer} from '../../common/js/importer_common.m.js'; +import {assertFileEntryPathsEqual} from '../../common/js/unittest_util.m.js'; + +import {fileOperationUtil} from './file_operation_util.m.js'; +import {mediaScanner} from './media_scanner.m.js'; +import {TestDirectoryWatcher} from './mock_media_scanner.m.js'; +import {importerTestHistory} from './test_import_history.m.js'; + /** * Stub out the metrics package. * @type {!Object<!string, !Function>} @@ -11,7 +23,7 @@ recordValue: function() {} }; -/** @type {!importer.DefaultMediaScanner} */ +/** @type {!mediaScanner.DefaultMediaScanner} */ let scanner; /** @@ -32,7 +44,7 @@ let dispositionChecker; // Set up the test components. -function setUp() { +export function setUp() { importHistory = new importerTestHistory.TestImportHistory(); // Setup a default disposition checker. Tests can replace it at runtime @@ -41,7 +53,7 @@ return Promise.resolve(importer.Disposition.ORIGINAL); }; - scanner = new importer.DefaultMediaScanner( + scanner = new mediaScanner.DefaultMediaScanner( /** @param {!FileEntry} entry */ entry => { return Promise.resolve(entry.name); @@ -58,13 +70,13 @@ /** * Verifies that scanning an empty filesystem produces an empty list. */ -function testEmptySourceList() { +export function testEmptySourceList() { assertThrows(() => { scanner.scanFiles([], scanMode); }); } -function testIsScanning(callback) { +export function testIsScanning(callback) { const filenames = [ 'happy', 'thoughts', @@ -84,7 +96,7 @@ callback); } -function testObserverNotifiedOnScanFinish(callback) { +export function testObserverNotifiedOnScanFinish(callback) { const filenames = [ 'happy', 'thoughts', @@ -116,7 +128,7 @@ /** * Verifies that scanFiles slurps up all specified files. */ -function testScanFiles(callback) { +export function testScanFiles(callback) { const filenames = [ 'foo', 'foo.jpg', @@ -144,7 +156,7 @@ /** * Verifies that scanFiles skips duplicated files. */ -function testScanFilesIgnoresPreviousImports(callback) { +export function testScanFilesIgnoresPreviousImports(callback) { const filenames = [ 'oldimage1234.jpg', // a history duplicate 'driveimage1234.jpg', // a content duplicate @@ -186,7 +198,7 @@ /** * Verifies that scanning a simple single-level directory structure works. */ -function testEmptyScanResults(callback) { +export function testEmptyScanResults(callback) { const filenames = [ 'happy', 'thoughts', @@ -209,7 +221,7 @@ /** * Verifies that scanning a simple single-level directory structure works. */ -function testSingleLevel(callback) { +export function testSingleLevel(callback) { const filenames = [ 'foo', 'foo.jpg', @@ -242,7 +254,7 @@ * Verifies that scanning a simple single-level directory produces 100% * progress at completion. */ -function testProgress(callback) { +export function testProgress(callback) { const filenames = [ 'foo', 'foo.jpg', @@ -274,7 +286,7 @@ /** * Verifies that scanning ignores previously imported entries. */ -function testIgnoresPreviousImports(callback) { +export function testIgnoresPreviousImports(callback) { importHistory.importedPaths['/testIgnoresPreviousImports/oldimage1234.jpg'] = [importer.Destination.GOOGLE_DRIVE]; const filenames = [ @@ -319,7 +331,7 @@ reportPromise(promise, callback); } -function testTracksDuplicates(callback) { +export function testTracksDuplicates(callback) { importHistory.importedPaths['/testTracksDuplicates/oldimage1234.jpg'] = [importer.Destination.GOOGLE_DRIVE]; const filenames = [ @@ -366,7 +378,7 @@ reportPromise(promise, callback); } -function testMultiLevel(callback) { +export function testMultiLevel(callback) { const filenames = [ 'foo.jpg', 'bar', [ @@ -404,7 +416,7 @@ callback); } -function testDedupesFilesInScanResult(callback) { +export function testDedupesFilesInScanResult(callback) { const filenames = [ 'foo.jpg', 'bar.jpg', [ @@ -446,11 +458,11 @@ /** * Verifies that scanning a simple single-level directory structure works. */ -function testDefaultScanResult() { +export function testDefaultScanResult() { const hashGenerator = file => { return file.toURL(); }; - const scan = new importer.DefaultScanResult(scanMode, hashGenerator); + const scan = new mediaScanner.DefaultScanResult(scanMode, hashGenerator); // 0 before we set candidate count assertProgress(0, scan); @@ -466,7 +478,7 @@ assertProgress(100, scan); } -function testInvalidation(callback) { +export function testInvalidation(callback) { const invalidatePromise = new Promise(fulfill => { scanner.addObserver(fulfill); }); @@ -489,8 +501,8 @@ /** * Verifies the results of the media scan are as expected. * @param {number} expected, 0-100 - * @param {!importer.ScanResult} scan - * @return {!importer.ScanResult} + * @param {!mediaScannerInterfaces.ScanResult} scan + * @return {!mediaScannerInterfaces.ScanResult} */ function assertProgress(expected, scan) { assertEquals(expected, scan.getStatistics().progress); @@ -500,8 +512,8 @@ /** * Verifies the results of the media scan are as expected. * @param {!Array<string>} expected - * @param {!importer.ScanResult} scan - * @return {!importer.ScanResult} + * @param {!mediaScannerInterfaces.ScanResult} scan + * @return {!mediaScannerInterfaces.ScanResult} */ function assertFilesFound(expected, scan) { assertFileEntryPathsEqual(expected, scan.getFileEntries()); @@ -512,8 +524,8 @@ /** * Verifies the results of the media scan are as expected. * @param {!Array<string>} expected - * @param {!importer.ScanResult} scan - * @return {!importer.ScanResult} + * @param {!mediaScannerInterfaces.ScanResult} scan + * @return {!mediaScannerInterfaces.ScanResult} */ function assertDuplicatesFound(expected, scan) { assertFileEntryPathsEqual(expected, scan.getDuplicateFileEntries());
diff --git a/ui/file_manager/file_manager/background/js/mock_media_scanner.js b/ui/file_manager/file_manager/background/js/mock_media_scanner.js index ea9d677..ea9b14f 100644 --- a/ui/file_manager/file_manager/background/js/mock_media_scanner.js +++ b/ui/file_manager/file_manager/background/js/mock_media_scanner.js
@@ -2,14 +2,22 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +// clang-format off +// #import {assertTrue, assertEquals} from 'chrome://test/chai_assert.js'; +// #import {importer} from '../../common/js/importer_common.m.js'; +// #import {mediaScannerInterfaces} from '../../../externs/background/media_scanner.m.js'; +// #import {mediaScanner} from './media_scanner.m.js'; +// clang-format on + /** - * importer.MediaScanner and importer.ScanResult test double. + * mediaScannerInterfaces.MediaScanner and mediaScannerInterfaces.ScanResult + * test double. * - * @implements {importer.MediaScanner} + * @implements {mediaScannerInterfaces.MediaScanner} */ -class TestMediaScanner { +/* #export */ class TestMediaScanner { constructor() { - /** @private {!Array<!importer.ScanResult>} */ + /** @private {!Array<!mediaScannerInterfaces.ScanResult>} */ this.scans_ = []; /** @@ -26,7 +34,7 @@ /** * List of scan observers. - * @private {!Array<!importer.ScanObserver>} + * @private {!Array<!mediaScannerInterfaces.ScanObserver>} */ this.observers = []; @@ -90,7 +98,7 @@ /** * Notifies observers that a scan has finished. - * @param {!importer.ScanResult} scan + * @param {!mediaScannerInterfaces.ScanResult} scan */ finalize(scan) { // Note the |scan| has {!TestScanResult} type in test, and needs a @@ -120,11 +128,12 @@ } /** - * importer.MediaScanner and importer.ScanResult test double. + * mediaScannerInterfaces.MediaScanner and mediaScannerInterfaces.ScanResult + * test double. * - * @implements {importer.ScanResult} + * @implements {mediaScannerInterfaces.ScanResult} */ -class TestScanResult { +/* #export */ class TestScanResult { /** * @param {!Array<!FileEntry>} fileEntries */ @@ -162,7 +171,7 @@ /** @private {boolean} */ this.canceled_ = false; - /** @type {!Promise<!importer.ScanResult>} */ + /** @type {!Promise<!mediaScannerInterfaces.ScanResult>} */ this.whenFinal_ = new Promise((resolve, reject) => { this.resolveResult_ = result => { this.settled_ = true; @@ -226,7 +235,7 @@ duplicates[importer.Disposition.CONTENT_DUPLICATE] = 0; duplicates[importer.Disposition.HISTORY_DUPLICATE] = 0; duplicates[importer.Disposition.SCAN_DUPLICATE] = 0; - return /** @type {importer.ScanResult.Statistics} */ ({ + return /** @type {mediaScannerInterfaces.ScanResult.Statistics} */ ({ scanDuration: this.scanDuration, newFileCount: this.fileEntries.length, duplicates: duplicates, @@ -243,9 +252,9 @@ TestScanResult.lastId_ = 0; /** - * @implements {importer.DirectoryWatcher} + * @implements {mediaScanner.DirectoryWatcher} */ -class TestDirectoryWatcher { +/* #export */ class TestDirectoryWatcher { constructor(callback) { /** * @public {function()}
diff --git a/ui/file_manager/file_manager/common/js/importer_common_unittest.m.js b/ui/file_manager/file_manager/common/js/importer_common_unittest.m.js index 6ffe1e6e..b38530cd 100644 --- a/ui/file_manager/file_manager/common/js/importer_common_unittest.m.js +++ b/ui/file_manager/file_manager/common/js/importer_common_unittest.m.js
@@ -10,8 +10,9 @@ import {VolumeInfo} from '../../../externs/volume_info.m.js'; import {MockVolumeManager} from '../../background/js/mock_volume_manager.m.js'; +import {importer} from './importer_common.m.js'; import {MockDirectoryEntry, MockFileEntry} from './mock_entry.m.js'; -import {importer} from './test_importer_common.m.js'; +import {importerTest} from './test_importer_common.m.js'; /** @type {!MockVolumeManager} */ let volumeManager; @@ -42,7 +43,7 @@ window.loadTimeData.getString = id => id; new MockCommandLinePrivate(); new MockChromeStorageAPI(); - importer.setupTestLogger(); + importerTest.setupTestLogger(); cameraVolume = MockVolumeManager.createMockVolumeInfo( VolumeManagerCommon.VolumeType.MTP, 'camera-fs', 'Some Camera');
diff --git a/ui/file_manager/file_manager/common/js/test_importer_common.js b/ui/file_manager/file_manager/common/js/test_importer_common.js index 9ac429d..384bc21 100644 --- a/ui/file_manager/file_manager/common/js/test_importer_common.js +++ b/ui/file_manager/file_manager/common/js/test_importer_common.js
@@ -2,26 +2,20 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -/** - * @fileoverview - * @suppress {uselessCode} Temporary suppress because of the line exporting. - */ - // #import {importer} from './importer_common.m.js'; // #import {TestCallRecorder} from './unittest_util.m.js'; -// Shared cloud importer namespace -// eslint-disable-next-line no-var -/* #ignore */ var importer = importer || {}; +// Namespace +/* #export */ const importerTest = {}; /** * Sets up a logger for use in unit tests. The test logger doesn't attempt to * access chrome's sync file system. Call this during setUp. - * @return {!importer.TestLogger} + * @return {!importerTest.TestLogger} * @suppress{accessControls} For testing. */ -importer.setupTestLogger = () => { - const logger = new importer.TestLogger(); +importerTest.setupTestLogger = () => { + const logger = new importerTest.TestLogger(); importer.logger_ = logger; return logger; }; @@ -32,7 +26,7 @@ * @implements {importer.Logger} * @final */ -importer.TestLogger = class { +importerTest.TestLogger = class { constructor() { /** @public {!TestCallRecorder} */ this.errorRecorder = new TestCallRecorder(); @@ -77,6 +71,3 @@ }; } }; - -// eslint-disable-next-line semi,no-extra-semi -/* #export */ {importer};
diff --git a/ui/file_manager/file_manager/foreground/js/BUILD.gn b/ui/file_manager/file_manager/foreground/js/BUILD.gn index 676d7e4..5233d72 100644 --- a/ui/file_manager/file_manager/foreground/js/BUILD.gn +++ b/ui/file_manager/file_manager/foreground/js/BUILD.gn
@@ -103,7 +103,6 @@ "//ui/file_manager/externs/background/background_base.js", "//ui/file_manager/externs/background/file_browser_background_full.js", "//ui/file_manager/externs/background/file_operation_manager.js", - "//ui/file_manager/externs/background/import_runner.js", "//ui/file_manager/externs/background/media_import_handler.js", "//ui/file_manager/externs/background/task_queue.js", "//ui/file_manager/externs/background/duplicate_finder.js", @@ -576,7 +575,6 @@ "//ui/file_manager/file_manager/common/js:importer_common", ] externs_list = [ - "//ui/file_manager/externs/background/import_runner.js", "//ui/file_manager/externs/background/media_import_handler.js", "//ui/file_manager/externs/background/duplicate_finder.js", "//ui/file_manager/externs/background/task_queue.js",
diff --git a/ui/file_manager/file_manager/foreground/js/file_manager.js b/ui/file_manager/file_manager/foreground/js/file_manager.js index 4c2308a..b8d13a2 100644 --- a/ui/file_manager/file_manager/foreground/js/file_manager.js +++ b/ui/file_manager/file_manager/foreground/js/file_manager.js
@@ -50,13 +50,13 @@ */ this.onHistoryChangedBound_ = this.onHistoryChanged_.bind(this); - /** @private {?importer.MediaScanner} */ + /** @private {?mediaScannerInterfaces.MediaScanner} */ this.mediaScanner_ = null; /** @private {?importer.ImportController} */ this.importController_ = null; - /** @private {?importer.ImportRunner} */ + /** @private {?mediaImportInterfaces.ImportRunner} */ this.mediaImportHandler_ = null; /** @private {?MetadataModel} */ @@ -487,7 +487,7 @@ } /** - * @return {importer.ImportRunner} + * @return {mediaImportInterfaces.ImportRunner} */ get mediaImportHandler() { return this.mediaImportHandler_;
diff --git a/ui/file_manager/file_manager/foreground/js/import_controller.js b/ui/file_manager/file_manager/foreground/js/import_controller.js index 30383cc..8f0f8b4 100644 --- a/ui/file_manager/file_manager/foreground/js/import_controller.js +++ b/ui/file_manager/file_manager/foreground/js/import_controller.js
@@ -26,8 +26,8 @@ * @param {!importer.ControllerEnvironment} environment The class providing * access to runtime environmental information, like the current * directory, volume lookup and so-on. - * @param {!importer.MediaScanner} scanner - * @param {!importer.ImportRunner} importRunner + * @param {!mediaScannerInterfaces.MediaScanner} scanner + * @param {!mediaImportInterfaces.ImportRunner} importRunner * @param {!importer.CommandWidget} commandWidget */ constructor(environment, scanner, importRunner, commandWidget) { @@ -37,10 +37,10 @@ /** @private @const {!importer.ChromeLocalStorage} */ this.storage_ = importer.ChromeLocalStorage.getInstance(); - /** @private @const {!importer.ImportRunner} */ + /** @private @const {!mediaImportInterfaces.ImportRunner} */ this.importRunner_ = importRunner; - /** @private @const {!importer.MediaScanner} */ + /** @private @const {!mediaScannerInterfaces.MediaScanner} */ this.scanner_ = scanner; /** @private @const {!importer.CommandWidget} */ @@ -101,7 +101,7 @@ /** * @param {!importer.ScanEvent} event Command event. - * @param {importer.ScanResult} scan + * @param {mediaScannerInterfaces.ScanResult} scan * @private */ onScanEvent_(event, scan) { @@ -181,7 +181,7 @@ } /** - * @param {!importer.MediaImportHandler.ImportTask} task + * @param {!mediaImportInterfaces.MediaImportHandler.ImportTask} task * @private */ onImportFinished_(task) { @@ -305,7 +305,7 @@ /** * Checks the environment and updates UI as needed. - * @param {importer.ScanResult=} opt_scan If supplied, + * @param {mediaScannerInterfaces.ScanResult=} opt_scan If supplied, * @private */ checkState_(opt_scan) { @@ -414,7 +414,7 @@ /** * @param {importer.ActivityState} activityState - * @param {importer.ScanResult=} opt_scan + * @param {mediaScannerInterfaces.ScanResult=} opt_scan * @param {number=} opt_destinationSizeBytes specifies the destination size in * bytes in case of space issues. * @private @@ -439,7 +439,7 @@ * Attempts to scan the current context. * * @param {importer.ScanMode} mode How to detect new files. - * @return {importer.ScanResult} A scan object, + * @return {mediaScannerInterfaces.ScanResult} A scan object, * or null if scan is not possible in current context. * @private */ @@ -462,8 +462,8 @@ * Collection of import task related details. * * @typedef {{ - * scan: !importer.ScanResult, - * task: !importer.MediaImportHandler.ImportTask, + * scan: !mediaScannerInterfaces.ScanResult, + * task: !mediaImportInterfaces.MediaImportHandler.ImportTask, * started: !Date * }} * @@ -488,7 +488,7 @@ /** * @param {importer.ActivityState} activityState - * @param {importer.ScanResult=} opt_scan + * @param {mediaScannerInterfaces.ScanResult=} opt_scan * @param {number=} opt_destinationSizeBytes specifies the destination size in * bytes in case of space issues. */ @@ -919,24 +919,24 @@ importer.ScanManager = class { /** * @param {!importer.ControllerEnvironment} environment - * @param {!importer.MediaScanner} scanner + * @param {!mediaScannerInterfaces.MediaScanner} scanner */ constructor(environment, scanner) { /** @private {!importer.ControllerEnvironment} */ this.environment_ = environment; - /** @private @const {!importer.MediaScanner} */ + /** @private @const {!mediaScannerInterfaces.MediaScanner} */ this.scanner_ = scanner; /** * The active files scan, if any. - * @private {?importer.ScanResult} + * @private {?mediaScannerInterfaces.ScanResult} */ this.selectionScan_ = null; /** * The active directory scan, if any. - * @private {?importer.ScanResult} + * @private {?mediaScannerInterfaces.ScanResult} */ this.directoryScan_ = null; } @@ -968,13 +968,16 @@ this.directoryScan_ = null; } - /** @return {importer.ScanResult} Current active scan, or null if none. */ + /** + * @return {mediaScannerInterfaces.ScanResult} Current active scan, or null + * if none. + */ getActiveScan() { return this.selectionScan_ || this.directoryScan_; } /** - * @param {importer.ScanResult} scan + * @param {mediaScannerInterfaces.ScanResult} scan * @return {boolean} True if scan is the active scan...meaning the current * selection scan or the scan for the current directory. */ @@ -989,7 +992,7 @@ * @param {!Array<!FileEntry>} entries * @param {!importer.ScanMode} mode * - * @return {!importer.ScanResult} + * @return {!mediaScannerInterfaces.ScanResult} */ getSelectionScan(entries, mode) { console.assert( @@ -1003,7 +1006,7 @@ * Returns a scan for the directory. * * @param {!importer.ScanMode} mode - * @return {importer.ScanResult} + * @return {mediaScannerInterfaces.ScanResult} */ getDirectoryScan(mode) { if (!this.directoryScan_) {
diff --git a/ui/file_manager/file_manager/foreground/js/import_controller_unittest.js b/ui/file_manager/file_manager/foreground/js/import_controller_unittest.js index beb18fa..76d5dca1 100644 --- a/ui/file_manager/file_manager/foreground/js/import_controller_unittest.js +++ b/ui/file_manager/file_manager/foreground/js/import_controller_unittest.js
@@ -9,7 +9,7 @@ let volumeManager; /** @type {!TestMediaScanner} */ -let mediaScanner; +let mediaScannerTest; /** @type {!TestImportRunner} */ let mediaImporter; @@ -61,7 +61,7 @@ assert(downloads); destinationVolume = downloads; - mediaScanner = new TestMediaScanner(); + mediaScannerTest = new TestMediaScanner(); mediaImporter = new TestImportRunner(); } @@ -116,7 +116,7 @@ return widget.updateResolver.promise; }) .then(() => { - mediaScanner.assertScanCount(2); + mediaScannerTest.assertScanCount(2); }); reportPromise(promise, callback); @@ -160,8 +160,8 @@ environment.directoryChangedListener(EMPTY_EVENT); }) .then(() => { - mediaScanner.assertScanCount(1); - mediaScanner.assertLastScanCanceled(); + mediaScannerTest.assertScanCount(1); + mediaScannerTest.assertLastScanCanceled(); }); reportPromise(promise, callback); @@ -190,8 +190,8 @@ environment.windowCloseListener(); }) .then(() => { - mediaScanner.assertScanCount(1); - mediaScanner.assertLastScanCanceled(); + mediaScannerTest.assertScanCount(1); + mediaScannerTest.assertLastScanCanceled(); }); reportPromise(promise, callback); @@ -213,7 +213,7 @@ // Ensure there is some content in the scan so the code that depends // on this state doesn't croak which it finds it missing. - mediaScanner.fileEntries.push(MockFileEntry.create( + mediaScannerTest.fileEntries.push(MockFileEntry.create( fileSystem, '/DCIM/photos0/IMG00001.jpg', getDefaultMetadata())); // Make controller enter a scanning state. @@ -225,7 +225,7 @@ // "scanning..." assertFalse(widget.detailsVisible); widget.resetPromises(); - mediaScanner.finalizeScans(); + mediaScannerTest.finalizeScans(); return widget.updateResolver.promise; }) .then(() => { @@ -276,7 +276,7 @@ fileSystem, '/DCIM/photos0/IMG00001.jpg', getDefaultMetadata())); environment.selectionChangedListener(); - mediaScanner.finalizeScans(); + mediaScannerTest.finalizeScans(); reportPromise(widget.updateResolver.promise, callback); } @@ -294,12 +294,12 @@ // Ensure there is some content in the scan so the code that depends // on this state doesn't croak which it finds it missing. - mediaScanner.fileEntries.push(MockFileEntry.create( + mediaScannerTest.fileEntries.push(MockFileEntry.create( fileSystem, '/DCIM/photos0/IMG00001.jpg', getDefaultMetadata())); environment.directoryChangedListener(EMPTY_EVENT); // initiates a scan. widget.resetPromises(); - mediaScanner.finalizeScans(); + mediaScannerTest.finalizeScans(); reportPromise(widget.updateResolver.promise, callback); } @@ -345,7 +345,7 @@ // Ensure there is some content in the scan so the code that depends // on this state doesn't croak which it finds it missing. - mediaScanner.fileEntries.push(MockFileEntry.create( + mediaScannerTest.fileEntries.push(MockFileEntry.create( fileSystem, '/DCIM/photos0/IMG00001.jpg', getDefaultMetadata())); // First we need to force the controller into a scanning state. @@ -353,7 +353,7 @@ return widget.updateResolver.promise.then(() => { widget.resetPromises(); - mediaScanner.finalizeScans(); + mediaScannerTest.finalizeScans(); return widget.updateResolver.promise.then(() => { widget.resetPromises(); widget.click(clickSource); @@ -368,12 +368,12 @@ */ class TestImportTask { /** - * @param {!importer.ScanResult} scan + * @param {!mediaScannerInterfaces.ScanResult} scan * @param {!importer.Destination} destination * @param {!Promise<!DirectoryEntry>} destinationDirectory */ constructor(scan, destination, destinationDirectory) { - /** @public {!importer.ScanResult} */ + /** @public {!mediaScannerInterfaces.ScanResult} */ this.scan = scan; /** @type {!importer.Destination} */ @@ -407,11 +407,11 @@ /** * Test import runner. * - * @implements {importer.ImportRunner} + * @implements {mediaImportInterfaces.ImportRunner} */ class TestImportRunner { constructor() { - /** @public {!Array<!importer.ScanResult>} */ + /** @public {!Array<!mediaScannerInterfaces.ScanResult>} */ this.imported = []; /** @@ -434,13 +434,14 @@ } /** - * Returns |task| as importer.MediaImportHandler.ImportTask type. + * Returns |task| as mediaImportInterfaces.MediaImportHandler.ImportTask type. * @param {!Object} task - * @return {!importer.MediaImportHandler.ImportTask} + * @return {!mediaImportInterfaces.MediaImportHandler.ImportTask} * @private */ toMediaImportTask_(task) { - return /** @type {!importer.MediaImportHandler.ImportTask} */ (task); + return /** @type {!mediaImportInterfaces.MediaImportHandler.ImportTask} */ ( + task); } finishImportTasks() { @@ -664,7 +665,7 @@ sourceVolume.fileSystem.entries[currentDirectory]); return new importer.ImportController( - environment, mediaScanner, mediaImporter, widget); + environment, mediaScannerTest, mediaImporter, widget); } /**
diff --git a/ui/file_manager/video_player/background.html b/ui/file_manager/video_player/background.html index 1f5034b..39b8e67 100644 --- a/ui/file_manager/video_player/background.html +++ b/ui/file_manager/video_player/background.html
@@ -1,10 +1,4 @@ <!DOCTYPE html> <meta charset="utf-8"> -<script src="chrome://resources/js/cr.js"></script> -<script src="chrome://resources/js/cr/event_target.js"></script> -<script src="chrome://resources/js/assert.js"></script> -<script src="chrome://resources/js/cr/ui/array_data_model.js"></script> -<script src="chrome://resources/js/load_time_data.js"></script> -<script src="chrome-extension://hhaomjibdihmijegdhdafkllkbggdgoj/background/js/background_common_scripts.js"></script> -<script src="js/background_scripts.js"></script> +<script type="module" src="js/main_background.m.js"></script>
diff --git a/ui/file_manager/video_player/js/BUILD.gn b/ui/file_manager/video_player/js/BUILD.gn index 68045a35..a4698e6 100644 --- a/ui/file_manager/video_player/js/BUILD.gn +++ b/ui/file_manager/video_player/js/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("//chrome/browser/resources/optimize_webui.gni") import("//third_party/closure_compiler/compile_js.gni") import("//third_party/closure_compiler/js_unit_tests.gni") import("//ui/file_manager/base/gn/js_test_gen_html.gni") @@ -202,3 +203,23 @@ "video_player.js", ] } + +preprocess_folder = + rebase_path("$target_gen_dir/../../preprocessed/video_player/js", + root_build_dir) + +optimize_webui("build_background") { + host = "video_player" + + input = preprocess_folder + js_module_in_files = [ "main_background.m.js" ] + + js_out_files = [ "main_background.m.rollup.js" ] + + deps = [ + ":main_background.m", + "//ui/file_manager:preprocess_generated", + "//ui/file_manager:preprocess_static", + "//ui/webui/resources:preprocess", + ] +}
diff --git a/ui/webui/resources/js/BUILD.gn b/ui/webui/resources/js/BUILD.gn index 190efd1..13edc73 100644 --- a/ui/webui/resources/js/BUILD.gn +++ b/ui/webui/resources/js/BUILD.gn
@@ -70,6 +70,13 @@ "web_ui_listener_behavior.js", ] } + + if (is_ios) { + in_files += [ + "ios/mojo_api.js", + "ios/web_ui.js", + ] + } } preprocess_if_expr("preprocess_generated") {
diff --git a/ui/webui/resources/webui_resources.grd b/ui/webui/resources/webui_resources.grd index ebb38c3..ab8cc7b 100644 --- a/ui/webui/resources/webui_resources.grd +++ b/ui/webui/resources/webui_resources.grd
@@ -44,13 +44,6 @@ use_base_dir="false" /> </if> - <if expr="is_ios"> - <structure name="IDR_WEBUI_JS_IOS_WEB_UI" - file="js/ios/web_ui.js" type="chrome_html" /> - <structure name="IDR_WEBUI_JS_IOS_MOJO_API" - file="js/ios/mojo_api.js" type="chrome_html" /> - </if> - <if expr="not is_android and not is_ios"> <structure name="IDR_LOTTIE_LOTTIE_WORKER_MIN_JS" file="../../../third_party/lottie/lottie_worker.min.js"
diff --git a/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/FullscreenCallbackTest.java b/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/FullscreenCallbackTest.java index 65eaa1c..c6ff6f0e 100644 --- a/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/FullscreenCallbackTest.java +++ b/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/FullscreenCallbackTest.java
@@ -4,6 +4,8 @@ package org.chromium.weblayer.test; +import android.os.Build; + import androidx.test.filters.SmallTest; import org.junit.Assert; @@ -12,6 +14,7 @@ import org.junit.runner.RunWith; import org.chromium.base.test.util.CallbackHelper; +import org.chromium.base.test.util.DisableIf; import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.weblayer.Browser; import org.chromium.weblayer.BrowserControlsOffsetCallback; @@ -111,6 +114,8 @@ @Test @SmallTest + @DisableIf. + Build(sdk_is_less_than = Build.VERSION_CODES.M, message = "https://crbug.com/1159781") public void testTopViewRemainsHiddenOnFullscreenRotation() throws Exception { String url = mActivityTestRule.getTestDataURL("rotation2.html"); mActivity = mActivityTestRule.launchShellWithUrl(url);
diff --git a/weblayer/browser/content_browser_client_impl.cc b/weblayer/browser/content_browser_client_impl.cc index f457899b..28c3b85 100644 --- a/weblayer/browser/content_browser_client_impl.cc +++ b/weblayer/browser/content_browser_client_impl.cc
@@ -437,7 +437,6 @@ if (prerender_contents && prerender_contents->prerender_mode() != prerender::mojom::PrerenderMode::kNoPrerender) { result.push_back(std::make_unique<prerender::PrerenderURLLoaderThrottle>( - prerender_contents->prerender_mode(), prerender::PrerenderHistograms::GetHistogramPrefix( prerender_contents->origin()), GetPrerenderCanceler(web_contents)));
diff --git a/weblayer/renderer/content_renderer_client_impl.cc b/weblayer/renderer/content_renderer_client_impl.cc index 58e681d2..4cbac11 100644 --- a/weblayer/renderer/content_renderer_client_impl.cc +++ b/weblayer/renderer/content_renderer_client_impl.cc
@@ -135,7 +135,6 @@ // Avoid any race conditions from having the browser tell subframes that // they're prerendering. new prerender::PrerenderHelper(render_frame, - prerender_helper->prerender_mode(), prerender_helper->histogram_prefix()); } }