diff --git a/AUTHORS b/AUTHORS index 29011ff..61e471e 100644 --- a/AUTHORS +++ b/AUTHORS
@@ -260,6 +260,7 @@ Deokjin Kim <deokjin81.kim@samsung.com> Derek Halman <d.halman@gmail.com> Devlin Cronin <rdevlin.cronin@gmail.com> +Dhi Aurrahman <dio@rockybars.com> Diana Suvorova <diana.suvorova@gmail.com> Diego Ferreiro Val <elfogris@gmail.com> Dillon Sellars <dill.sellars@gmail.com>
diff --git a/DEPS b/DEPS index 65b47cb..6cd0aeb1 100644 --- a/DEPS +++ b/DEPS
@@ -200,11 +200,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': '39b4c86fe9146508a2d92d5775331c8aa1a04693', + 'skia_revision': '48a99420a2495a665a732a7fe335e93ec7a83418', # 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': 'fe46597df7664f8fe317c2363cfad28007283e75', + 'v8_revision': '8040ad59abd7119457d5acbde8602fde8a5291e5', # 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. @@ -212,11 +212,11 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ANGLE # and whatever else without interference from each other. - 'angle_revision': '939fcd1a14f5ddc43e300bcb2d5d1f680c50ab85', + 'angle_revision': '8420c5acaa568cacb7283116fce3ad283075166e', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling SwiftShader # and whatever else without interference from each other. - 'swiftshader_revision': '43bb60e1fa119d80b449c6550dd2b72328b101b9', + 'swiftshader_revision': '9dff6a3bb5950edd890e5141f2d3d2f3b4ef351e', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling PDFium # and whatever else without interference from each other. @@ -259,7 +259,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling HarfBuzz # and whatever else without interference from each other. - 'harfbuzz_revision': 'c39ab82c90479341dcf28eaa8174af6f08c0d7ae', + 'harfbuzz_revision': '53806e5b83cee0e275eac038d0780f95ac56588c', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling Emoji Segmenter # and whatever else without interference from each other. @@ -275,7 +275,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': 'abee7cf3a9897cce6d02571c4aa37a06509c2358', + 'devtools_frontend_revision': '3383020812d40c5b2839233c6817d2d8f84eff43', # 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. @@ -327,7 +327,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': '9175f00eec91c6c9b3c3e264d6d8ec7879881844', + 'dawn_revision': '71279dcde7cd1b718b137b9ed0384803f347a359', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. @@ -899,7 +899,7 @@ # Tools used when building Chrome for Chrome OS. This affects both the Simple # Chrome workflow, as well as the chromeos-chrome ebuild. 'src/third_party/chromite': { - 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '9ed30bc3ed292b02d85fde89c64207484b7a3aa4', + 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'fc23bc1c96acb0fa2fcc526204333fb9a373ecb6', 'condition': 'checkout_chromeos', }, @@ -1369,7 +1369,7 @@ 'packages': [ { 'package': 'fuchsia/third_party/aemu/linux-amd64', - 'version': 'pYEJYcwmc7764Ioa_c8OSqFs8pflIE1Y-yEvVdFb3zUC' + 'version': 'Ts7JI7CLxH4-h5lAQEsDnba0CD6d4ACU00UDPQXaW0wC' }, ], 'condition': 'host_os == "linux" and checkout_fuchsia', @@ -1551,7 +1551,7 @@ }, 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + 'b6b599fc588e59142df343d2d2897203468aacea', + Var('webrtc_git') + '/src.git' + '@' + '0d863f72a8c747c1b41f2798e5201e1abcdaec2b', 'src/third_party/libgifcodec': Var('skia_git') + '/libgifcodec' + '@'+ Var('libgifcodec_revision'), @@ -1623,7 +1623,7 @@ Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'), 'src-internal': { - 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@dee1cdf147f77fcf5597d87931226c519f49c66c', + 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@d90991c959bad057c3109394079ce08097d66e43', 'condition': 'checkout_src_internal', }, @@ -1642,7 +1642,7 @@ 'packages': [ { 'package': 'chromeos_internal/apps/media_app/app', - 'version': 'UEDryZf_VuC_LfcEXlTJ_7tEzVfL6qKZIy8qC-wjmbIC', + 'version': '2vgKL8p-SUW0S-OFCowtelp1xuW-s-25Zm0z7AwTFPMC', }, ], 'condition': 'checkout_chromeos and checkout_src_internal',
diff --git a/ash/login/ui/login_user_view.cc b/ash/login/ui/login_user_view.cc index 1e46272..95589bc 100644 --- a/ash/login/ui/login_user_view.cc +++ b/ash/login/ui/login_user_view.cc
@@ -17,6 +17,7 @@ #include "ash/public/cpp/login_constants.h" #include "ash/public/cpp/session/user_info.h" #include "ash/resources/vector_icons/vector_icons.h" +#include "ash/shell.h" #include "ash/strings/grit/ash_strings.h" #include "ash/style/ash_color_provider.h" #include "base/bind.h" @@ -171,6 +172,7 @@ enterprise_icon_->SetVisible(false); AddChildView(enterprise_icon_); } + ~UserImage() override = default; void UpdateForUser(const LoginUserInfo& user) { @@ -461,6 +463,9 @@ hover_notifier_ = std::make_unique<HoverNotifier>( this, base::BindRepeating(&LoginUserView::OnHover, base::Unretained(this))); + + if (ash::Shell::HasInstance()) + display_observation_.Observe(ash::Shell::Get()->display_configurator()); } LoginUserView::~LoginUserView() = default; @@ -538,6 +543,12 @@ : FocusBehavior::NEVER); } +void LoginUserView::OnPowerStateChanged( + chromeos::DisplayPowerState power_state) { + bool is_display_on = power_state != chromeos::DISPLAY_POWER_ALL_OFF; + user_image_->SetAnimationEnabled(is_display_on && is_opaque_); +} + const char* LoginUserView::GetClassName() const { return kUserViewClassName; }
diff --git a/ash/login/ui/login_user_view.h b/ash/login/ui/login_user_view.h index a333c751..f3bfa31 100644 --- a/ash/login/ui/login_user_view.h +++ b/ash/login/ui/login_user_view.h
@@ -11,6 +11,8 @@ #include "ash/login/ui/login_user_menu_view.h" #include "ash/public/cpp/login_types.h" #include "base/macros.h" +#include "base/scoped_observation.h" +#include "ui/display/manager/display_configurator.h" #include "ui/views/view.h" namespace ash { @@ -20,7 +22,8 @@ // Display the user's profile icon, name, and a menu icon in various layout // styles. -class ASH_EXPORT LoginUserView : public views::View { +class ASH_EXPORT LoginUserView : public views::View, + public display::DisplayConfigurator::Observer { public: // TestApi is used for tests to get internal implementation details. class ASH_EXPORT TestApi { @@ -71,6 +74,9 @@ // Enables or disables tapping the view. void SetTapEnabled(bool enabled); + // DisplayConfigurator::Observer + void OnPowerStateChanged(chromeos::DisplayPowerState power_state) override; + const LoginUserInfo& current_user() const { return current_user_; } // views::View: @@ -128,6 +134,10 @@ // state. bool force_opaque_ = false; + base::ScopedObservation<display::DisplayConfigurator, + display::DisplayConfigurator::Observer> + display_observation_{this}; + DISALLOW_COPY_AND_ASSIGN(LoginUserView); };
diff --git a/base/BUILD.gn b/base/BUILD.gn index 5830912..05fb2f7d 100644 --- a/base/BUILD.gn +++ b/base/BUILD.gn
@@ -3865,6 +3865,7 @@ ] sources = [ + "test/android/javatests/src/org/chromium/base/test/BaseActivityTestRule.java", "test/android/javatests/src/org/chromium/base/test/BaseChromiumAndroidJUnitRunner.java", "test/android/javatests/src/org/chromium/base/test/BaseChromiumRunnerCommon.java", "test/android/javatests/src/org/chromium/base/test/BaseJUnit4ClassRunner.java",
diff --git a/base/allocator/partition_allocator/partition_bucket.cc b/base/allocator/partition_allocator/partition_bucket.cc index a2570a5a..be169dac 100644 --- a/base/allocator/partition_allocator/partition_bucket.cc +++ b/base/allocator/partition_allocator/partition_bucket.cc
@@ -55,12 +55,11 @@ root->total_size_of_direct_mapped_pages.fetch_add(reserved_size, std::memory_order_relaxed); - root->IncreaseCommittedPages(slot_size); char* slot = ptr + PartitionPageSize(); RecommitSystemPages(ptr + SystemPageSize(), SystemPageSize(), PageReadWrite, PageUpdatePermissions); - RecommitSystemPages(slot, slot_size, PageReadWrite, PageUpdatePermissions); + root->RecommitSystemPagesForData(slot, slot_size, PageUpdatePermissions); auto* metadata = reinterpret_cast<PartitionDirectMapMetadata<thread_safe>*>( PartitionSuperPageToMetadataArea(ptr)); @@ -220,9 +219,8 @@ // System pages in the super page come in a decommited state. Commit them // before vending them back. - RecommitSystemPages(ret, slot_span_committed_size, PageReadWrite, - PageUpdatePermissions); - root->IncreaseCommittedPages(slot_span_committed_size); + root->RecommitSystemPagesForData(ret, slot_span_committed_size, + PageUpdatePermissions); root->next_partition_page += slot_span_reserved_size; // Double check that we had enough space in the super page for the new slot // span. @@ -569,9 +567,9 @@ PA_DCHECK(new_slot_span->is_decommitted()); decommitted_slot_spans_head = new_slot_span->next_slot_span; void* addr = SlotSpanMetadata<thread_safe>::ToPointer(new_slot_span); - root->RecommitSystemPages(addr, - new_slot_span->bucket->get_bytes_per_span(), - PageKeepPermissionsIfPossible); + root->RecommitSystemPagesForData( + addr, new_slot_span->bucket->get_bytes_per_span(), + PageKeepPermissionsIfPossible); new_slot_span->Reset(); *is_already_zeroed = kDecommittedPagesAreAlwaysZeroed; }
diff --git a/base/allocator/partition_allocator/partition_page.cc b/base/allocator/partition_allocator/partition_page.cc index e65c795..aafb7ba0 100644 --- a/base/allocator/partition_allocator/partition_page.cc +++ b/base/allocator/partition_allocator/partition_page.cc
@@ -41,6 +41,7 @@ extent->next_extent->prev_extent = extent->prev_extent; } + // The actual decommit is deferred, when releasing the reserved memory region. root->DecreaseCommittedPages(slot_span->bucket->slot_size); size_t reserved_size = @@ -166,8 +167,8 @@ PA_DCHECK(is_empty()); PA_DCHECK(!bucket->is_direct_mapped()); void* addr = SlotSpanMetadata::ToPointer(this); - root->DecommitSystemPages(addr, bucket->get_bytes_per_span(), - PageKeepPermissionsIfPossible); + root->DecommitSystemPagesForData(addr, bucket->get_bytes_per_span(), + PageKeepPermissionsIfPossible); // We actually leave the decommitted slot span in the active list. We'll sweep // it on to the decommitted list when we next walk the active list.
diff --git a/base/allocator/partition_allocator/partition_root.cc b/base/allocator/partition_allocator/partition_root.cc index 95243580..fb63b42a 100644 --- a/base/allocator/partition_allocator/partition_root.cc +++ b/base/allocator/partition_allocator/partition_root.cc
@@ -456,15 +456,16 @@ // Shrink by decommitting unneeded pages and making them inaccessible. size_t decommit_size = current_slot_size - new_slot_size; - DecommitSystemPages(char_ptr + new_slot_size, decommit_size, - PageUpdatePermissions); + DecommitSystemPagesForData(char_ptr + new_slot_size, decommit_size, + PageUpdatePermissions); } else if (new_slot_size <= DirectMapExtent::FromSlotSpan(slot_span)->map_size) { // Grow within the actually allocated memory. Just need to make the // pages accessible again. size_t recommit_slot_size_growth = new_slot_size - current_slot_size; - RecommitSystemPages(char_ptr + current_slot_size, recommit_slot_size_growth, - PageUpdatePermissions); + RecommitSystemPagesForData(char_ptr + current_slot_size, + recommit_slot_size_growth, + PageUpdatePermissions); #if DCHECK_IS_ON() memset(char_ptr + current_slot_size, kUninitializedByte, @@ -596,10 +597,12 @@ template <bool thread_safe> void PartitionRoot<thread_safe>::PurgeMemory(int flags) { // TODO(chromium:1129751): Change to LIKELY once PCScan is enabled by default. - if (UNLIKELY(IsScanEnabled()) && (flags & PartitionPurgeForceAllFreed)) { - PCScan::Instance().PerformScanIfNeeded(PCScan::InvocationMode::kBlocking); + if (UNLIKELY(IsScanEnabled())) { + if (flags & PartitionPurgeForceAllFreed) + PCScan::Instance().PerformScan(PCScan::InvocationMode::kBlocking); + else + PCScan::Instance().PerformScanIfNeeded(PCScan::InvocationMode::kBlocking); } - { ScopedGuard guard{lock_}; if (flags & PartitionPurgeDecommitEmptySlotSpans)
diff --git a/base/allocator/partition_allocator/partition_root.h b/base/allocator/partition_allocator/partition_root.h index fe5008e0..5406b25d 100644 --- a/base/allocator/partition_allocator/partition_root.h +++ b/base/allocator/partition_allocator/partition_root.h
@@ -212,12 +212,12 @@ ALWAYS_INLINE void IncreaseCommittedPages(size_t len); ALWAYS_INLINE void DecreaseCommittedPages(size_t len); - ALWAYS_INLINE void DecommitSystemPages( + ALWAYS_INLINE void DecommitSystemPagesForData( void* address, size_t length, PageAccessibilityDisposition accessibility_disposition) EXCLUSIVE_LOCKS_REQUIRED(lock_); - ALWAYS_INLINE void RecommitSystemPages( + ALWAYS_INLINE void RecommitSystemPagesForData( void* address, size_t length, PageAccessibilityDisposition accessibility_disposition) @@ -856,21 +856,21 @@ } template <bool thread_safe> -ALWAYS_INLINE void PartitionRoot<thread_safe>::DecommitSystemPages( +ALWAYS_INLINE void PartitionRoot<thread_safe>::DecommitSystemPagesForData( void* address, size_t length, PageAccessibilityDisposition accessibility_disposition) { - ::base::DecommitSystemPages(address, length, accessibility_disposition); + DecommitSystemPages(address, length, accessibility_disposition); DecreaseCommittedPages(length); } template <bool thread_safe> -ALWAYS_INLINE void PartitionRoot<thread_safe>::RecommitSystemPages( +ALWAYS_INLINE void PartitionRoot<thread_safe>::RecommitSystemPagesForData( void* address, size_t length, PageAccessibilityDisposition accessibility_disposition) { - ::base::RecommitSystemPages(address, length, PageReadWrite, - accessibility_disposition); + RecommitSystemPages(address, length, PageReadWrite, + accessibility_disposition); IncreaseCommittedPages(length); }
diff --git a/base/allocator/partition_allocator/pcscan.cc b/base/allocator/partition_allocator/pcscan.cc index 05825b2..49ccdc0 100644 --- a/base/allocator/partition_allocator/pcscan.cc +++ b/base/allocator/partition_allocator/pcscan.cc
@@ -533,13 +533,11 @@ auto task = std::make_unique<PCScanTask>(*this); // Post PCScan task. - const auto callback = [](PCScanTask task) { std::move(task).RunOnce(); }; - if (UNLIKELY(invocation_mode == InvocationMode::kBlocking)) { - // Blocking is only used for testing. - callback(std::move(*task)); - } else { - PA_DCHECK(InvocationMode::kNonBlocking == invocation_mode); + if (LIKELY(invocation_mode == InvocationMode::kNonBlocking)) { PCScanThread::Instance().PostTask(std::move(task)); + } else { + PA_DCHECK(InvocationMode::kBlocking == invocation_mode); + std::move(*task).RunOnce(); } }
diff --git a/base/allocator/partition_allocator/pcscan.h b/base/allocator/partition_allocator/pcscan.h index 8bc1410..dca4d9b 100644 --- a/base/allocator/partition_allocator/pcscan.h +++ b/base/allocator/partition_allocator/pcscan.h
@@ -66,6 +66,9 @@ ALWAYS_INLINE void MoveToQuarantine(void* ptr, SlotSpan* slot_span); + // Performs scanning unconditionally. + void PerformScan(InvocationMode invocation_mode); + // Performs scanning only if a certain quarantine threshold was reached. void PerformScanIfNeeded(InvocationMode invocation_mode); void ClearRootsForTesting(); @@ -135,8 +138,6 @@ constexpr PCScan() = default; - void PerformScan(InvocationMode invocation_mode); - static PCScan instance_ PA_CONSTINIT; Roots roots_{};
diff --git a/base/allocator/partition_allocator/thread_cache.cc b/base/allocator/partition_allocator/thread_cache.cc index 1ca1fe1..ebe3d58 100644 --- a/base/allocator/partition_allocator/thread_cache.cc +++ b/base/allocator/partition_allocator/thread_cache.cc
@@ -148,6 +148,24 @@ ThreadCache::ThreadCache(PartitionRoot<ThreadSafe>* root) : buckets_(), stats_(), root_(root), next_(nullptr), prev_(nullptr) { ThreadCacheRegistry::Instance().RegisterThreadCache(this); + + for (int index = 0; index < kBucketCount; index++) { + const auto& root_bucket = root->buckets[index]; + // Invalid bucket. + if (!root_bucket.active_slot_spans_head) + continue; + + // Smaller allocations are more frequent, and more performance-sensitive. + // Cache more small objects, and fewer larger ones, to save memory. + size_t element_size = root_bucket.slot_size; + if (element_size <= 128) { + buckets_[index].limit = 128; + } else if (element_size <= 256) { + buckets_[index].limit = 64; + } else { + buckets_[index].limit = 32; + } + } } ThreadCache::~ThreadCache() {
diff --git a/base/allocator/partition_allocator/thread_cache.h b/base/allocator/partition_allocator/thread_cache.h index 10805e7..3d4f3ffd 100644 --- a/base/allocator/partition_allocator/thread_cache.h +++ b/base/allocator/partition_allocator/thread_cache.h
@@ -161,8 +161,9 @@ private: struct Bucket { - size_t count; PartitionFreelistEntry* freelist_head; + uint16_t count; + uint16_t limit; }; explicit ThreadCache(PartitionRoot<ThreadSafe>* root); @@ -172,16 +173,13 @@ // TODO(lizeb): Optimize the threshold. static constexpr size_t kSizeThreshold = 512; - static constexpr size_t kBucketCount = + static constexpr uint16_t kBucketCount = ((ConstexprLog2(kSizeThreshold) - kMinBucketedOrder + 1) << kNumBucketsPerOrderBits) + 1; static_assert( kBucketCount < kNumBuckets, "Cannot have more cached buckets than what the allocator supports"); - // TODO(lizeb): Tune this constant, and adapt it to the bucket size / - // allocation patterns. - static constexpr size_t kMaxCountPerBucket = 100; std::atomic<bool> should_purge_; Bucket buckets_[kBucketCount]; @@ -208,7 +206,7 @@ INCREMENT_COUNTER(stats_.cache_fill_count); - if (bucket_index >= kBucketCount) { + if (UNLIKELY(bucket_index >= kBucketCount)) { INCREMENT_COUNTER(stats_.cache_fill_misses); return false; } @@ -225,8 +223,8 @@ INCREMENT_COUNTER(stats_.cache_fill_hits); // Batched deallocation, amortizing lock acquisitions. - if (bucket.count >= kMaxCountPerBucket) { - ClearBucket(bucket, kMaxCountPerBucket / 2); + if (UNLIKELY(bucket.count >= bucket.limit)) { + ClearBucket(bucket, bucket.limit >> 1); } return true; @@ -235,7 +233,7 @@ ALWAYS_INLINE void* ThreadCache::GetFromCache(size_t bucket_index) { INCREMENT_COUNTER(stats_.alloc_count); // Only handle "small" allocations. - if (bucket_index >= kBucketCount) { + if (UNLIKELY(bucket_index >= kBucketCount)) { INCREMENT_COUNTER(stats_.alloc_miss_too_large); INCREMENT_COUNTER(stats_.alloc_misses); return nullptr; @@ -243,7 +241,7 @@ auto& bucket = buckets_[bucket_index]; auto* result = bucket.freelist_head; - if (!result) { + if (UNLIKELY(!result)) { PA_DCHECK(bucket.count == 0); INCREMENT_COUNTER(stats_.alloc_miss_empty); INCREMENT_COUNTER(stats_.alloc_misses);
diff --git a/base/allocator/partition_allocator/thread_cache_unittest.cc b/base/allocator/partition_allocator/thread_cache_unittest.cc index cf40720..b92d817d 100644 --- a/base/allocator/partition_allocator/thread_cache_unittest.cc +++ b/base/allocator/partition_allocator/thread_cache_unittest.cc
@@ -299,19 +299,20 @@ tcache->Purge(); cache_fill_counter.Reset(); - // Bucket are never full, fill always succeeds. - size_t bucket_index = FillThreadCacheAndReturnIndex( - kTestSize, ThreadCache::kMaxCountPerBucket + 10); - EXPECT_EQ(ThreadCache::kMaxCountPerBucket + 10, cache_fill_counter.Delta()); + constexpr size_t kMaxCountForBucket = 128; + // Buckets are never full, fill always succeeds. + size_t bucket_index = + FillThreadCacheAndReturnIndex(kTestSize, kMaxCountForBucket + 10); + EXPECT_EQ(kMaxCountForBucket + 10, cache_fill_counter.Delta()); EXPECT_EQ(0u, cache_fill_misses_counter.Delta()); // Memory footprint. ThreadCacheStats stats; ThreadCacheRegistry::Instance().DumpStats(true, &stats); // Bucket was cleared (count halved, then refilled). - EXPECT_EQ(g_root->buckets[bucket_index].slot_size * - (ThreadCache::kMaxCountPerBucket / 2 + 10), - stats.bucket_total_memory); + EXPECT_EQ( + g_root->buckets[bucket_index].slot_size * (kMaxCountForBucket / 2 + 10), + stats.bucket_total_memory); EXPECT_EQ(sizeof(ThreadCache), stats.metadata_overhead); }
diff --git a/base/android/java/src/org/chromium/base/JNIUtils.java b/base/android/java/src/org/chromium/base/JNIUtils.java index 1b53b9f06..44c6a83 100644 --- a/base/android/java/src/org/chromium/base/JNIUtils.java +++ b/base/android/java/src/org/chromium/base/JNIUtils.java
@@ -4,6 +4,9 @@ package org.chromium.base; +import android.content.Context; +import android.text.TextUtils; + import org.chromium.base.annotations.CalledByNative; import org.chromium.base.annotations.MainDex; @@ -20,14 +23,24 @@ * is needed for the few cases where the JNI mechanism is unable to automatically determine the * appropriate ClassLoader instance. */ - @CalledByNative - public static Object getClassLoader() { + private static ClassLoader getClassLoader() { if (sJniClassLoader == null) { return JNIUtils.class.getClassLoader(); } return sJniClassLoader; } + /** Returns a ClassLoader which can load Java classes from the specified split. */ + @CalledByNative + public static ClassLoader getSplitClassLoader(String splitName) { + Context context = ContextUtils.getApplicationContext(); + if (!TextUtils.isEmpty(splitName) + && BundleUtils.isIsolatedSplitInstalled(context, splitName)) { + return BundleUtils.createIsolatedSplitContext(context, splitName).getClassLoader(); + } + return getClassLoader(); + } + /** * Sets the ClassLoader to be used for loading Java classes from native. * @param classLoader the ClassLoader to use.
diff --git a/base/android/jni_android.cc b/base/android/jni_android.cc index 679a7d2..1f02bbd0 100644 --- a/base/android/jni_android.cc +++ b/base/android/jni_android.cc
@@ -11,19 +11,22 @@ #include "base/android/java_exception_reporter.h" #include "base/android/jni_string.h" +#include "base/android/jni_utils.h" +#include "base/containers/flat_map.h" #include "base/debug/debugging_buildflags.h" #include "base/lazy_instance.h" #include "base/logging.h" +#include "base/no_destructor.h" +#include "base/synchronization/lock.h" #include "base/threading/thread_local.h" +namespace base { +namespace android { namespace { -using base::android::GetClass; -using base::android::MethodID; -using base::android::ScopedJavaLocalRef; JavaVM* g_jvm = NULL; -base::LazyInstance<base::android::ScopedJavaGlobalRef<jobject>>::Leaky - g_class_loader = LAZY_INSTANCE_INITIALIZER; +base::LazyInstance<ScopedJavaGlobalRef<jobject>>::Leaky g_class_loader = + LAZY_INSTANCE_INITIALIZER; jmethodID g_class_loader_load_class_method_id = 0; #if BUILDFLAG(CAN_UNWIND_WITH_FRAME_POINTERS) @@ -33,10 +36,61 @@ bool g_fatal_exception_occurred = false; -} // namespace +// Returns a ClassLoader instance which will be able to load classes from the +// specified split. +jobject GetCachedClassLoader(JNIEnv* env, const std::string& split_name) { + DCHECK(!split_name.empty()); + static base::NoDestructor<base::Lock> lock; + static base::NoDestructor< + base::flat_map<std::string, ScopedJavaGlobalRef<jobject>>> + split_class_loader_map; -namespace base { -namespace android { + base::AutoLock guard(*lock); + auto it = split_class_loader_map->find(split_name); + if (it != split_class_loader_map->end()) { + return it->second.obj(); + } + + ScopedJavaGlobalRef<jobject> class_loader( + GetSplitClassLoader(env, split_name)); + jobject class_loader_obj = class_loader.obj(); + split_class_loader_map->insert({split_name, std::move(class_loader)}); + return class_loader_obj; +} + +ScopedJavaLocalRef<jclass> GetClassInternal(JNIEnv* env, + const char* class_name, + jobject class_loader) { + jclass clazz; + if (class_loader != nullptr) { + // ClassLoader.loadClass expects a classname with components separated by + // dots instead of the slashes that JNIEnv::FindClass expects. The JNI + // generator generates names with slashes, so we have to replace them here. + // TODO(torne): move to an approach where we always use ClassLoader except + // for the special case of base::android::GetClassLoader(), and change the + // JNI generator to generate dot-separated names. http://crbug.com/461773 + size_t bufsize = strlen(class_name) + 1; + char dotted_name[bufsize]; + memmove(dotted_name, class_name, bufsize); + for (size_t i = 0; i < bufsize; ++i) { + if (dotted_name[i] == '/') { + dotted_name[i] = '.'; + } + } + + clazz = static_cast<jclass>( + env->CallObjectMethod(class_loader, g_class_loader_load_class_method_id, + ConvertUTF8ToJavaString(env, dotted_name).obj())); + } else { + clazz = env->FindClass(class_name); + } + if (ClearException(env) || !clazz) { + LOG(FATAL) << "Failed to find class " << class_name; + } + return ScopedJavaLocalRef<jclass>(env, clazz); +} + +} // namespace JNIEnv* AttachCurrentThread() { DCHECK(g_jvm); @@ -109,41 +163,44 @@ g_class_loader.Get().Reset(class_loader); } -ScopedJavaLocalRef<jclass> GetClass(JNIEnv* env, const char* class_name) { - jclass clazz; - if (!g_class_loader.Get().is_null()) { - // ClassLoader.loadClass expects a classname with components separated by - // dots instead of the slashes that JNIEnv::FindClass expects. The JNI - // generator generates names with slashes, so we have to replace them here. - // TODO(torne): move to an approach where we always use ClassLoader except - // for the special case of base::android::GetClassLoader(), and change the - // JNI generator to generate dot-separated names. http://crbug.com/461773 - size_t bufsize = strlen(class_name) + 1; - char dotted_name[bufsize]; - memmove(dotted_name, class_name, bufsize); - for (size_t i = 0; i < bufsize; ++i) { - if (dotted_name[i] == '/') { - dotted_name[i] = '.'; - } - } - - clazz = static_cast<jclass>( - env->CallObjectMethod(g_class_loader.Get().obj(), - g_class_loader_load_class_method_id, - ConvertUTF8ToJavaString(env, dotted_name).obj())); - } else { - clazz = env->FindClass(class_name); - } - if (ClearException(env) || !clazz) { - LOG(FATAL) << "Failed to find class " << class_name; - } - return ScopedJavaLocalRef<jclass>(env, clazz); +ScopedJavaLocalRef<jclass> GetClass(JNIEnv* env, + const char* class_name, + const std::string& split_name) { + return GetClassInternal(env, class_name, + GetCachedClassLoader(env, split_name)); } -jclass LazyGetClass( - JNIEnv* env, - const char* class_name, - std::atomic<jclass>* atomic_class_id) { +ScopedJavaLocalRef<jclass> GetClass(JNIEnv* env, const char* class_name) { + return GetClassInternal(env, class_name, g_class_loader.Get().obj()); +} + +// This is duplicated with LazyGetClass below because these are performance +// sensitive. +jclass LazyGetClass(JNIEnv* env, + const char* class_name, + const std::string& split_name, + std::atomic<jclass>* atomic_class_id) { + const jclass value = std::atomic_load(atomic_class_id); + if (value) + return value; + ScopedJavaGlobalRef<jclass> clazz; + clazz.Reset(GetClass(env, class_name, split_name)); + jclass cas_result = nullptr; + if (std::atomic_compare_exchange_strong(atomic_class_id, &cas_result, + clazz.obj())) { + // We intentionally leak the global ref since we now storing it as a raw + // pointer in |atomic_class_id|. + return clazz.Release(); + } else { + return cas_result; + } +} + +// This is duplicated with LazyGetClass above because these are performance +// sensitive. +jclass LazyGetClass(JNIEnv* env, + const char* class_name, + std::atomic<jclass>* atomic_class_id) { const jclass value = std::atomic_load(atomic_class_id); if (value) return value;
diff --git a/base/android/jni_android.h b/base/android/jni_android.h index 0e8e322..41ab9c3 100644 --- a/base/android/jni_android.h +++ b/base/android/jni_android.h
@@ -96,6 +96,9 @@ // This method triggers a fatal assertion if the class could not be found. // Use HasClass if you need to check whether the class exists. BASE_EXPORT ScopedJavaLocalRef<jclass> GetClass(JNIEnv* env, + const char* class_name, + const std::string& split_name); +BASE_EXPORT ScopedJavaLocalRef<jclass> GetClass(JNIEnv* env, const char* class_name); // The method will initialize |atomic_class_id| to contain a global ref to the @@ -104,6 +107,10 @@ // The caller is responsible to zero-initialize |atomic_method_id|. // It's fine to simultaneously call this on multiple threads referencing the // same |atomic_method_id|. +BASE_EXPORT jclass LazyGetClass(JNIEnv* env, + const char* class_name, + const std::string& split_name, + std::atomic<jclass>* atomic_class_id); BASE_EXPORT jclass LazyGetClass( JNIEnv* env, const char* class_name,
diff --git a/base/android/jni_generator/golden/SampleForTestsWithSplit_jni.golden b/base/android/jni_generator/golden/SampleForTestsWithSplit_jni.golden new file mode 100644 index 0000000..c7bd774e --- /dev/null +++ b/base/android/jni_generator/golden/SampleForTestsWithSplit_jni.golden
@@ -0,0 +1,527 @@ +// Copyright 2014 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 file is autogenerated by +// base/android/jni_generator/jni_generator.py +// For +// org/chromium/example/jni_generator/SampleForTests + +#ifndef org_chromium_example_jni_generator_SampleForTests_JNI +#define org_chromium_example_jni_generator_SampleForTests_JNI + +#include <jni.h> + +#include "base/android/jni_generator/jni_generator_helper.h" + + +// Step 1: Forward declarations. + +JNI_REGISTRATION_EXPORT extern const char + kClassPath_org_chromium_example_jni_1generator_SampleForTests[]; +const char kClassPath_org_chromium_example_jni_1generator_SampleForTests[] = + "org/chromium/example/jni_generator/SampleForTests"; + +JNI_REGISTRATION_EXPORT extern const char + kClassPath_org_chromium_example_jni_1generator_SampleForTests_00024InnerStructA[]; +const char kClassPath_org_chromium_example_jni_1generator_SampleForTests_00024InnerStructA[] = + "org/chromium/example/jni_generator/SampleForTests$InnerStructA"; + +JNI_REGISTRATION_EXPORT extern const char + kClassPath_org_chromium_example_jni_1generator_SampleForTests_00024InnerStructB[]; +const char kClassPath_org_chromium_example_jni_1generator_SampleForTests_00024InnerStructB[] = + "org/chromium/example/jni_generator/SampleForTests$InnerStructB"; +// Leaking this jclass as we cannot use LazyInstance from some threads. +JNI_REGISTRATION_EXPORT std::atomic<jclass> + g_org_chromium_example_jni_1generator_SampleForTests_clazz(nullptr); +#ifndef org_chromium_example_jni_1generator_SampleForTests_clazz_defined +#define org_chromium_example_jni_1generator_SampleForTests_clazz_defined +inline jclass org_chromium_example_jni_1generator_SampleForTests_clazz(JNIEnv* env) { + return base::android::LazyGetClass(env, + kClassPath_org_chromium_example_jni_1generator_SampleForTests, "sample", + &g_org_chromium_example_jni_1generator_SampleForTests_clazz); +} +#endif +// Leaking this jclass as we cannot use LazyInstance from some threads. +JNI_REGISTRATION_EXPORT std::atomic<jclass> + g_org_chromium_example_jni_1generator_SampleForTests_00024InnerStructA_clazz(nullptr); +#ifndef org_chromium_example_jni_1generator_SampleForTests_00024InnerStructA_clazz_defined +#define org_chromium_example_jni_1generator_SampleForTests_00024InnerStructA_clazz_defined +inline jclass org_chromium_example_jni_1generator_SampleForTests_00024InnerStructA_clazz(JNIEnv* + env) { + return base::android::LazyGetClass(env, + kClassPath_org_chromium_example_jni_1generator_SampleForTests_00024InnerStructA, "sample", + &g_org_chromium_example_jni_1generator_SampleForTests_00024InnerStructA_clazz); +} +#endif +// Leaking this jclass as we cannot use LazyInstance from some threads. +JNI_REGISTRATION_EXPORT std::atomic<jclass> + g_org_chromium_example_jni_1generator_SampleForTests_00024InnerStructB_clazz(nullptr); +#ifndef org_chromium_example_jni_1generator_SampleForTests_00024InnerStructB_clazz_defined +#define org_chromium_example_jni_1generator_SampleForTests_00024InnerStructB_clazz_defined +inline jclass org_chromium_example_jni_1generator_SampleForTests_00024InnerStructB_clazz(JNIEnv* + env) { + return base::android::LazyGetClass(env, + kClassPath_org_chromium_example_jni_1generator_SampleForTests_00024InnerStructB, "sample", + &g_org_chromium_example_jni_1generator_SampleForTests_00024InnerStructB_clazz); +} +#endif + + +// Step 2: Constants (optional). + + +// Step 3: Method stubs. +namespace base { +namespace android { + +static jlong JNI_SampleForTests_Init(JNIEnv* env, const base::android::JavaParamRef<jobject>& + caller, + const base::android::JavaParamRef<jstring>& param); + +JNI_GENERATOR_EXPORT jlong + Java_org_chromium_base_natives_GEN_1JNI_org_1chromium_1example_1jni_11generator_1SampleForTests_1init( + JNIEnv* env, + jclass jcaller, + jobject caller, + jstring param) { + return JNI_SampleForTests_Init(env, base::android::JavaParamRef<jobject>(env, caller), + base::android::JavaParamRef<jstring>(env, param)); +} + +JNI_GENERATOR_EXPORT void + Java_org_chromium_base_natives_GEN_1JNI_org_1chromium_1example_1jni_11generator_1SampleForTests_1destroy( + JNIEnv* env, + jclass jcaller, + jlong nativeCPPClass, + jobject caller) { + CPPClass* native = reinterpret_cast<CPPClass*>(nativeCPPClass); + CHECK_NATIVE_PTR(env, jcaller, native, "Destroy"); + return native->Destroy(env, base::android::JavaParamRef<jobject>(env, caller)); +} + +static jdouble JNI_SampleForTests_GetDoubleFunction(JNIEnv* env, const + base::android::JavaParamRef<jobject>& caller); + +JNI_GENERATOR_EXPORT jdouble + Java_org_chromium_base_natives_GEN_1JNI_org_1chromium_1example_1jni_11generator_1SampleForTests_1getDoubleFunction( + JNIEnv* env, + jclass jcaller, + jobject caller) { + return JNI_SampleForTests_GetDoubleFunction(env, base::android::JavaParamRef<jobject>(env, + caller)); +} + +static jfloat JNI_SampleForTests_GetFloatFunction(JNIEnv* env); + +JNI_GENERATOR_EXPORT jfloat + Java_org_chromium_base_natives_GEN_1JNI_org_1chromium_1example_1jni_11generator_1SampleForTests_1getFloatFunction( + JNIEnv* env, + jclass jcaller) { + return JNI_SampleForTests_GetFloatFunction(env); +} + +static void JNI_SampleForTests_SetNonPODDatatype(JNIEnv* env, const + base::android::JavaParamRef<jobject>& caller, + const base::android::JavaParamRef<jobject>& rect); + +JNI_GENERATOR_EXPORT void + Java_org_chromium_base_natives_GEN_1JNI_org_1chromium_1example_1jni_11generator_1SampleForTests_1setNonPODDatatype( + JNIEnv* env, + jclass jcaller, + jobject caller, + jobject rect) { + return JNI_SampleForTests_SetNonPODDatatype(env, base::android::JavaParamRef<jobject>(env, + caller), base::android::JavaParamRef<jobject>(env, rect)); +} + +static base::android::ScopedJavaLocalRef<jobject> JNI_SampleForTests_GetNonPODDatatype(JNIEnv* env, + const base::android::JavaParamRef<jobject>& caller); + +JNI_GENERATOR_EXPORT jobject + Java_org_chromium_base_natives_GEN_1JNI_org_1chromium_1example_1jni_11generator_1SampleForTests_1getNonPODDatatype( + JNIEnv* env, + jclass jcaller, + jobject caller) { + return JNI_SampleForTests_GetNonPODDatatype(env, base::android::JavaParamRef<jobject>(env, + caller)).Release(); +} + +JNI_GENERATOR_EXPORT jint + Java_org_chromium_base_natives_GEN_1JNI_org_1chromium_1example_1jni_11generator_1SampleForTests_1method( + JNIEnv* env, + jclass jcaller, + jlong nativeCPPClass, + jobject caller) { + CPPClass* native = reinterpret_cast<CPPClass*>(nativeCPPClass); + CHECK_NATIVE_PTR(env, jcaller, native, "Method", 0); + return native->Method(env, base::android::JavaParamRef<jobject>(env, caller)); +} + +JNI_GENERATOR_EXPORT jdouble + Java_org_chromium_base_natives_GEN_1JNI_org_1chromium_1example_1jni_11generator_1SampleForTests_1methodOtherP0( + JNIEnv* env, + jclass jcaller, + jlong nativePtr, + jobject caller) { + CPPClass::InnerClass* native = reinterpret_cast<CPPClass::InnerClass*>(nativePtr); + CHECK_NATIVE_PTR(env, jcaller, native, "MethodOtherP0", 0); + return native->MethodOtherP0(env, base::android::JavaParamRef<jobject>(env, caller)); +} + +JNI_GENERATOR_EXPORT void + Java_org_chromium_base_natives_GEN_1JNI_org_1chromium_1example_1jni_11generator_1SampleForTests_1addStructB( + JNIEnv* env, + jclass jcaller, + jlong nativeCPPClass, + jobject caller, + jobject b) { + CPPClass* native = reinterpret_cast<CPPClass*>(nativeCPPClass); + CHECK_NATIVE_PTR(env, jcaller, native, "AddStructB"); + return native->AddStructB(env, base::android::JavaParamRef<jobject>(env, caller), + base::android::JavaParamRef<jobject>(env, b)); +} + +JNI_GENERATOR_EXPORT void + Java_org_chromium_base_natives_GEN_1JNI_org_1chromium_1example_1jni_11generator_1SampleForTests_1iterateAndDoSomethingWithStructB( + JNIEnv* env, + jclass jcaller, + jlong nativeCPPClass, + jobject caller) { + CPPClass* native = reinterpret_cast<CPPClass*>(nativeCPPClass); + CHECK_NATIVE_PTR(env, jcaller, native, "IterateAndDoSomethingWithStructB"); + return native->IterateAndDoSomethingWithStructB(env, base::android::JavaParamRef<jobject>(env, + caller)); +} + +JNI_GENERATOR_EXPORT jstring + Java_org_chromium_base_natives_GEN_1JNI_org_1chromium_1example_1jni_11generator_1SampleForTests_1returnAString( + JNIEnv* env, + jclass jcaller, + jlong nativeCPPClass, + jobject caller) { + CPPClass* native = reinterpret_cast<CPPClass*>(nativeCPPClass); + CHECK_NATIVE_PTR(env, jcaller, native, "ReturnAString", NULL); + return native->ReturnAString(env, base::android::JavaParamRef<jobject>(env, caller)).Release(); +} + + +static std::atomic<jmethodID> + g_org_chromium_example_jni_1generator_SampleForTests_javaMethod(nullptr); +static jint Java_SampleForTests_javaMethod(JNIEnv* env, const base::android::JavaRef<jobject>& obj, + JniIntWrapper foo, + JniIntWrapper bar) { + jclass clazz = org_chromium_example_jni_1generator_SampleForTests_clazz(env); + CHECK_CLAZZ(env, obj.obj(), + org_chromium_example_jni_1generator_SampleForTests_clazz(env), 0); + + jni_generator::JniJavaCallContextChecked call_context; + call_context.Init< + base::android::MethodID::TYPE_INSTANCE>( + env, + clazz, + "javaMethod", + "(II)I", + &g_org_chromium_example_jni_1generator_SampleForTests_javaMethod); + + jint ret = + env->CallIntMethod(obj.obj(), + call_context.base.method_id, as_jint(foo), as_jint(bar)); + return ret; +} + +static std::atomic<jmethodID> + g_org_chromium_example_jni_1generator_SampleForTests_staticJavaMethod(nullptr); +static jboolean Java_SampleForTests_staticJavaMethod(JNIEnv* env) { + jclass clazz = org_chromium_example_jni_1generator_SampleForTests_clazz(env); + CHECK_CLAZZ(env, clazz, + org_chromium_example_jni_1generator_SampleForTests_clazz(env), false); + + jni_generator::JniJavaCallContextChecked call_context; + call_context.Init< + base::android::MethodID::TYPE_STATIC>( + env, + clazz, + "staticJavaMethod", + "()Z", + &g_org_chromium_example_jni_1generator_SampleForTests_staticJavaMethod); + + jboolean ret = + env->CallStaticBooleanMethod(clazz, + call_context.base.method_id); + return ret; +} + +static std::atomic<jmethodID> + g_org_chromium_example_jni_1generator_SampleForTests_packagePrivateJavaMethod(nullptr); +static void Java_SampleForTests_packagePrivateJavaMethod(JNIEnv* env, const + base::android::JavaRef<jobject>& obj) { + jclass clazz = org_chromium_example_jni_1generator_SampleForTests_clazz(env); + CHECK_CLAZZ(env, obj.obj(), + org_chromium_example_jni_1generator_SampleForTests_clazz(env)); + + jni_generator::JniJavaCallContextChecked call_context; + call_context.Init< + base::android::MethodID::TYPE_INSTANCE>( + env, + clazz, + "packagePrivateJavaMethod", + "()V", + &g_org_chromium_example_jni_1generator_SampleForTests_packagePrivateJavaMethod); + + env->CallVoidMethod(obj.obj(), + call_context.base.method_id); +} + +static std::atomic<jmethodID> + g_org_chromium_example_jni_1generator_SampleForTests_methodWithGenericParams(nullptr); +static void Java_SampleForTests_methodWithGenericParams(JNIEnv* env, const + base::android::JavaRef<jobject>& obj, const base::android::JavaRef<jobject>& foo, + const base::android::JavaRef<jobject>& bar) { + jclass clazz = org_chromium_example_jni_1generator_SampleForTests_clazz(env); + CHECK_CLAZZ(env, obj.obj(), + org_chromium_example_jni_1generator_SampleForTests_clazz(env)); + + jni_generator::JniJavaCallContextChecked call_context; + call_context.Init< + base::android::MethodID::TYPE_INSTANCE>( + env, + clazz, + "methodWithGenericParams", + "(Ljava/util/Map;Ljava/util/LinkedList;)V", + &g_org_chromium_example_jni_1generator_SampleForTests_methodWithGenericParams); + + env->CallVoidMethod(obj.obj(), + call_context.base.method_id, foo.obj(), bar.obj()); +} + +static std::atomic<jmethodID> + g_org_chromium_example_jni_1generator_SampleForTests_Constructor(nullptr); +static base::android::ScopedJavaLocalRef<jobject> Java_SampleForTests_Constructor(JNIEnv* env, + JniIntWrapper foo, + JniIntWrapper bar) { + jclass clazz = org_chromium_example_jni_1generator_SampleForTests_clazz(env); + CHECK_CLAZZ(env, clazz, + org_chromium_example_jni_1generator_SampleForTests_clazz(env), NULL); + + jni_generator::JniJavaCallContextChecked call_context; + call_context.Init< + base::android::MethodID::TYPE_INSTANCE>( + env, + clazz, + "<init>", + "(II)V", + &g_org_chromium_example_jni_1generator_SampleForTests_Constructor); + + jobject ret = + env->NewObject(clazz, + call_context.base.method_id, as_jint(foo), as_jint(bar)); + return base::android::ScopedJavaLocalRef<jobject>(env, ret); +} + +static std::atomic<jmethodID> + g_org_chromium_example_jni_1generator_SampleForTests_methodThatThrowsException(nullptr); +static void Java_SampleForTests_methodThatThrowsException(JNIEnv* env, const + base::android::JavaRef<jobject>& obj) { + jclass clazz = org_chromium_example_jni_1generator_SampleForTests_clazz(env); + CHECK_CLAZZ(env, obj.obj(), + org_chromium_example_jni_1generator_SampleForTests_clazz(env)); + + jni_generator::JniJavaCallContextUnchecked call_context; + call_context.Init< + base::android::MethodID::TYPE_INSTANCE>( + env, + clazz, + "methodThatThrowsException", + "()V", + &g_org_chromium_example_jni_1generator_SampleForTests_methodThatThrowsException); + + env->CallVoidMethod(obj.obj(), + call_context.method_id); +} + +static std::atomic<jmethodID> + g_org_chromium_example_jni_1generator_SampleForTests_javaMethodWithAnnotatedParam(nullptr); +static void Java_SampleForTests_javaMethodWithAnnotatedParam(JNIEnv* env, const + base::android::JavaRef<jobject>& obj, JniIntWrapper foo, + JniIntWrapper bar, + JniIntWrapper baz, + JniIntWrapper bat) { + jclass clazz = org_chromium_example_jni_1generator_SampleForTests_clazz(env); + CHECK_CLAZZ(env, obj.obj(), + org_chromium_example_jni_1generator_SampleForTests_clazz(env)); + + jni_generator::JniJavaCallContextChecked call_context; + call_context.Init< + base::android::MethodID::TYPE_INSTANCE>( + env, + clazz, + "javaMethodWithAnnotatedParam", + "(IIII)V", + &g_org_chromium_example_jni_1generator_SampleForTests_javaMethodWithAnnotatedParam); + + env->CallVoidMethod(obj.obj(), + call_context.base.method_id, as_jint(foo), as_jint(bar), as_jint(baz), as_jint(bat)); +} + +static std::atomic<jmethodID> + g_org_chromium_example_jni_1generator_SampleForTests_00024InnerStructA_create(nullptr); +static base::android::ScopedJavaLocalRef<jobject> Java_InnerStructA_create(JNIEnv* env, jlong l, + JniIntWrapper i, + const base::android::JavaRef<jstring>& s) { + jclass clazz = org_chromium_example_jni_1generator_SampleForTests_00024InnerStructA_clazz(env); + CHECK_CLAZZ(env, clazz, + org_chromium_example_jni_1generator_SampleForTests_00024InnerStructA_clazz(env), NULL); + + jni_generator::JniJavaCallContextChecked call_context; + call_context.Init< + base::android::MethodID::TYPE_STATIC>( + env, + clazz, + "create", + "(JILjava/lang/String;)Lorg/chromium/example/jni_generator/SampleForTests$InnerStructA;", + &g_org_chromium_example_jni_1generator_SampleForTests_00024InnerStructA_create); + + jobject ret = + env->CallStaticObjectMethod(clazz, + call_context.base.method_id, l, as_jint(i), s.obj()); + return base::android::ScopedJavaLocalRef<jobject>(env, ret); +} + +static std::atomic<jmethodID> + g_org_chromium_example_jni_1generator_SampleForTests_addStructA(nullptr); +static void Java_SampleForTests_addStructA(JNIEnv* env, const base::android::JavaRef<jobject>& obj, + const base::android::JavaRef<jobject>& a) { + jclass clazz = org_chromium_example_jni_1generator_SampleForTests_clazz(env); + CHECK_CLAZZ(env, obj.obj(), + org_chromium_example_jni_1generator_SampleForTests_clazz(env)); + + jni_generator::JniJavaCallContextChecked call_context; + call_context.Init< + base::android::MethodID::TYPE_INSTANCE>( + env, + clazz, + "addStructA", + "(Lorg/chromium/example/jni_generator/SampleForTests$InnerStructA;)V", + &g_org_chromium_example_jni_1generator_SampleForTests_addStructA); + + env->CallVoidMethod(obj.obj(), + call_context.base.method_id, a.obj()); +} + +static std::atomic<jmethodID> + g_org_chromium_example_jni_1generator_SampleForTests_iterateAndDoSomething(nullptr); +static void Java_SampleForTests_iterateAndDoSomething(JNIEnv* env, const + base::android::JavaRef<jobject>& obj) { + jclass clazz = org_chromium_example_jni_1generator_SampleForTests_clazz(env); + CHECK_CLAZZ(env, obj.obj(), + org_chromium_example_jni_1generator_SampleForTests_clazz(env)); + + jni_generator::JniJavaCallContextChecked call_context; + call_context.Init< + base::android::MethodID::TYPE_INSTANCE>( + env, + clazz, + "iterateAndDoSomething", + "()V", + &g_org_chromium_example_jni_1generator_SampleForTests_iterateAndDoSomething); + + env->CallVoidMethod(obj.obj(), + call_context.base.method_id); +} + +static std::atomic<jmethodID> + g_org_chromium_example_jni_1generator_SampleForTests_00024InnerStructB_getKey(nullptr); +static jlong Java_InnerStructB_getKey(JNIEnv* env, const base::android::JavaRef<jobject>& obj) { + jclass clazz = org_chromium_example_jni_1generator_SampleForTests_00024InnerStructB_clazz(env); + CHECK_CLAZZ(env, obj.obj(), + org_chromium_example_jni_1generator_SampleForTests_00024InnerStructB_clazz(env), 0); + + jni_generator::JniJavaCallContextChecked call_context; + call_context.Init< + base::android::MethodID::TYPE_INSTANCE>( + env, + clazz, + "getKey", + "()J", + &g_org_chromium_example_jni_1generator_SampleForTests_00024InnerStructB_getKey); + + jlong ret = + env->CallLongMethod(obj.obj(), + call_context.base.method_id); + return ret; +} + +static std::atomic<jmethodID> + g_org_chromium_example_jni_1generator_SampleForTests_00024InnerStructB_getValue(nullptr); +static base::android::ScopedJavaLocalRef<jstring> Java_InnerStructB_getValue(JNIEnv* env, const + base::android::JavaRef<jobject>& obj) { + jclass clazz = org_chromium_example_jni_1generator_SampleForTests_00024InnerStructB_clazz(env); + CHECK_CLAZZ(env, obj.obj(), + org_chromium_example_jni_1generator_SampleForTests_00024InnerStructB_clazz(env), NULL); + + jni_generator::JniJavaCallContextChecked call_context; + call_context.Init< + base::android::MethodID::TYPE_INSTANCE>( + env, + clazz, + "getValue", + "()Ljava/lang/String;", + &g_org_chromium_example_jni_1generator_SampleForTests_00024InnerStructB_getValue); + + jstring ret = + static_cast<jstring>(env->CallObjectMethod(obj.obj(), + call_context.base.method_id)); + return base::android::ScopedJavaLocalRef<jstring>(env, ret); +} + +static std::atomic<jmethodID> + g_org_chromium_example_jni_1generator_SampleForTests_getInnerInterface(nullptr); +static base::android::ScopedJavaLocalRef<jobject> Java_SampleForTests_getInnerInterface(JNIEnv* env) + { + jclass clazz = org_chromium_example_jni_1generator_SampleForTests_clazz(env); + CHECK_CLAZZ(env, clazz, + org_chromium_example_jni_1generator_SampleForTests_clazz(env), NULL); + + jni_generator::JniJavaCallContextChecked call_context; + call_context.Init< + base::android::MethodID::TYPE_STATIC>( + env, + clazz, + "getInnerInterface", + "()Lorg/chromium/example/jni_generator/SampleForTests$InnerInterface;", + &g_org_chromium_example_jni_1generator_SampleForTests_getInnerInterface); + + jobject ret = + env->CallStaticObjectMethod(clazz, + call_context.base.method_id); + return base::android::ScopedJavaLocalRef<jobject>(env, ret); +} + +static std::atomic<jmethodID> + g_org_chromium_example_jni_1generator_SampleForTests_getInnerEnum(nullptr); +static base::android::ScopedJavaLocalRef<jobject> Java_SampleForTests_getInnerEnum(JNIEnv* env) { + jclass clazz = org_chromium_example_jni_1generator_SampleForTests_clazz(env); + CHECK_CLAZZ(env, clazz, + org_chromium_example_jni_1generator_SampleForTests_clazz(env), NULL); + + jni_generator::JniJavaCallContextChecked call_context; + call_context.Init< + base::android::MethodID::TYPE_STATIC>( + env, + clazz, + "getInnerEnum", + "()Lorg/chromium/example/jni_generator/SampleForTests$InnerEnum;", + &g_org_chromium_example_jni_1generator_SampleForTests_getInnerEnum); + + jobject ret = + env->CallStaticObjectMethod(clazz, + call_context.base.method_id); + return base::android::ScopedJavaLocalRef<jobject>(env, ret); +} + +} // namespace android +} // namespace base + +#endif // org_chromium_example_jni_generator_SampleForTests_JNI
diff --git a/base/android/jni_generator/jni_generator.py b/base/android/jni_generator/jni_generator.py index 6de4ea7..743e694 100755 --- a/base/android/jni_generator/jni_generator.py +++ b/base/android/jni_generator/jni_generator.py
@@ -363,6 +363,7 @@ 'Ljava/lang/Object', 'Ljava/lang/String', 'Ljava/lang/Class', + 'Ljava/lang/ClassLoader', 'Ljava/lang/CharSequence', 'Ljava/lang/Runnable', 'Ljava/lang/Throwable', @@ -969,10 +970,12 @@ class HeaderFileGeneratorHelper(object): """Include helper methods for header generators.""" - def __init__(self, class_name, fully_qualified_class, use_proxy_hash): + def __init__(self, class_name, fully_qualified_class, use_proxy_hash, + split_name): self.class_name = class_name self.fully_qualified_class = fully_qualified_class self.use_proxy_hash = use_proxy_hash + self.split_name = split_name def GetStubName(self, native): """Return the name of the stub function for this native method. @@ -1043,7 +1046,7 @@ #define ${JAVA_CLASS}_clazz_defined inline jclass ${JAVA_CLASS}_clazz(JNIEnv* env) { return base::android::LazyGetClass(env, kClassPath_${JAVA_CLASS}, \ -&g_${JAVA_CLASS}_clazz); +${MAYBE_SPLIT_NAME_ARG}&g_${JAVA_CLASS}_clazz); } #endif """ @@ -1059,7 +1062,10 @@ for full_clazz in classes.values(): values = { - 'JAVA_CLASS': EscapeClassName(full_clazz), + 'JAVA_CLASS': + EscapeClassName(full_clazz), + 'MAYBE_SPLIT_NAME_ARG': + (('"%s", ' % self.split_name) if self.split_name else '') } # Since all proxy methods use the same class, defining this in every # header file would result in duplicated extern initializations. @@ -1083,8 +1089,10 @@ self.constant_fields = constant_fields self.jni_params = jni_params self.options = options - self.helper = HeaderFileGeneratorHelper( - self.class_name, fully_qualified_class, self.options.use_proxy_hash) + self.helper = HeaderFileGeneratorHelper(self.class_name, + fully_qualified_class, + self.options.use_proxy_hash, + self.options.split_name) def GetContent(self): """Returns the content of the JNI binding file.""" @@ -1578,6 +1586,9 @@ action='store_true', help='Hashes the native declaration of methods used ' 'in @JniNatives interface.') + parser.add_argument( + '--split_name', + help='Split name that the Java classes should be loaded from.') args = parser.parse_args() input_files = args.input_files output_files = args.output_files
diff --git a/base/android/jni_generator/jni_generator_tests.py b/base/android/jni_generator/jni_generator_tests.py index fbaf9fb..934dea9e 100755 --- a/base/android/jni_generator/jni_generator_tests.py +++ b/base/android/jni_generator/jni_generator_tests.py
@@ -52,6 +52,7 @@ self.enable_tracing = False self.use_proxy_hash = False self.always_mangle = False + self.split_name = None class BaseTest(unittest.TestCase): @@ -1264,6 +1265,15 @@ TestOptions()) self.AssertGoldenTextEquals(jni_from_java.GetContent()) + def testSplitNameExample(self): + opts = TestOptions() + opts.split_name = "sample" + generated_text = self._CreateJniHeaderFromFile( + os.path.join(_JAVA_SRC_DIR, 'SampleForTests.java'), + 'org/chromium/example/jni_generator/SampleForTests', opts) + self.AssertGoldenTextEquals( + generated_text, golden_file='SampleForTestsWithSplit_jni.golden') + class ProxyTestGenerator(BaseTest):
diff --git a/base/android/jni_generator/jni_registration_generator.py b/base/android/jni_generator/jni_registration_generator.py index 7665671..66fa71cf 100755 --- a/base/android/jni_generator/jni_registration_generator.py +++ b/base/android/jni_generator/jni_registration_generator.py
@@ -326,7 +326,7 @@ self.class_name = self.fully_qualified_class.split('/')[-1] self.main_dex = main_dex self.helper = jni_generator.HeaderFileGeneratorHelper( - self.class_name, fully_qualified_class, use_proxy_hash) + self.class_name, fully_qualified_class, use_proxy_hash, None) self.use_proxy_hash = use_proxy_hash self.registration_dict = None
diff --git a/base/android/jni_utils.cc b/base/android/jni_utils.cc index 7ca8a64c..ebcd1e1 100644 --- a/base/android/jni_utils.cc +++ b/base/android/jni_utils.cc
@@ -4,6 +4,7 @@ #include "base/android/jni_utils.h" +#include "base/android/jni_string.h" #include "base/android/scoped_java_ref.h" #include "base/base_jni_headers/JNIUtils_jni.h" @@ -12,7 +13,14 @@ namespace android { ScopedJavaLocalRef<jobject> GetClassLoader(JNIEnv* env) { - return Java_JNIUtils_getClassLoader(env); + return Java_JNIUtils_getSplitClassLoader(env, + ConvertUTF8ToJavaString(env, "")); +} + +ScopedJavaLocalRef<jobject> GetSplitClassLoader(JNIEnv* env, + const std::string& split_name) { + return Java_JNIUtils_getSplitClassLoader( + env, ConvertUTF8ToJavaString(env, split_name)); } bool IsSelectiveJniRegistrationEnabled(JNIEnv* env) {
diff --git a/base/android/jni_utils.h b/base/android/jni_utils.h index c626ba4..d5e08e16 100644 --- a/base/android/jni_utils.h +++ b/base/android/jni_utils.h
@@ -18,6 +18,12 @@ // via JNI from Java. BASE_EXPORT ScopedJavaLocalRef<jobject> GetClassLoader(JNIEnv* env); +// Gets a ClassLoader instance which can load Java classes from the specified +// split. +BASE_EXPORT ScopedJavaLocalRef<jobject> GetSplitClassLoader( + JNIEnv* env, + const std::string& split_name); + // Returns true if the current process permits selective JNI registration. BASE_EXPORT bool IsSelectiveJniRegistrationEnabled(JNIEnv* env);
diff --git a/base/files/important_file_writer.cc b/base/files/important_file_writer.cc index 36bc0929..351a079 100644 --- a/base/files/important_file_writer.cc +++ b/base/files/important_file_writer.cc
@@ -371,8 +371,15 @@ void ImportantFileWriter::DoScheduledWrite() { DCHECK(serializer_); - std::unique_ptr<std::string> data(new std::string); + auto data = std::make_unique<std::string>(); + + // Pre-allocate previously needed memory plus 1kB for potential growth of + // data. Reduces the number of memory allocations to grow |data| step by step + // from tiny to very large. + data->reserve(previous_data_size_ + 1024); + if (serializer_->SerializeData(data.get())) { + previous_data_size_ = data->size(); WriteNow(std::move(data)); } else { DLOG(WARNING) << "failed to serialize data to be saved in "
diff --git a/base/files/important_file_writer.h b/base/files/important_file_writer.h index 1accf1d8..6358d5b 100644 --- a/base/files/important_file_writer.h +++ b/base/files/important_file_writer.h
@@ -117,6 +117,10 @@ // Overrides the timer to use for scheduling writes with |timer_override|. void SetTimerForTesting(OneShotTimer* timer_override); +#if defined(UNIT_TEST) + size_t previous_data_size() const { return previous_data_size_; } +#endif + private: const OneShotTimer& timer() const { return timer_override_ ? *timer_override_ : timer_; @@ -169,6 +173,11 @@ // Custom histogram suffix. const std::string histogram_suffix_; + // Memorizes the amount of data written on the previous write. This helps + // preallocating memory for the data serialization. It is only used for + // scheduled writes. + size_t previous_data_size_ = 0; + SEQUENCE_CHECKER(sequence_checker_); WeakPtrFactory<ImportantFileWriter> weak_factory_{this};
diff --git a/base/files/important_file_writer_unittest.cc b/base/files/important_file_writer_unittest.cc index baa1d5d..00dcadb 100644 --- a/base/files/important_file_writer_unittest.cc +++ b/base/files/important_file_writer_unittest.cc
@@ -234,6 +234,7 @@ MockOneShotTimer timer; ImportantFileWriter writer(file_, ThreadTaskRunnerHandle::Get(), kCommitInterval); + EXPECT_EQ(0u, writer.previous_data_size()); writer.SetTimerForTesting(&timer); EXPECT_FALSE(writer.HasPendingWrite()); DataSerializer serializer("foo"); @@ -247,6 +248,7 @@ RunLoop().RunUntilIdle(); ASSERT_TRUE(PathExists(writer.path())); EXPECT_EQ("foo", GetFileContent(writer.path())); + EXPECT_EQ(3u, writer.previous_data_size()); } TEST_F(ImportantFileWriterTest, DoScheduledWrite) {
diff --git a/base/task/sequence_manager/sequence_manager_impl_unittest.cc b/base/task/sequence_manager/sequence_manager_impl_unittest.cc index 12986dc..ff2394b 100644 --- a/base/task/sequence_manager/sequence_manager_impl_unittest.cc +++ b/base/task/sequence_manager/sequence_manager_impl_unittest.cc
@@ -236,10 +236,11 @@ .SetRandomisedSamplingEnabled(false) .SetTickClock(mock_tick_clock()) .Build(); - sequence_manager_ = SequenceManagerForTest::Create( + auto thread_controller = std::make_unique<ThreadControllerWithMessagePumpImpl>(std::move(pump), - settings), - std::move(settings)); + settings); + sequence_manager_ = SequenceManagerForTest::Create( + std::move(thread_controller), std::move(settings)); sequence_manager_->SetDefaultTaskRunner(MakeRefCounted<NullTaskRunner>()); // The SequenceManager constructor calls Now() once for setting up
diff --git a/base/test/android/javatests/src/org/chromium/base/test/BaseActivityTestRule.java b/base/test/android/javatests/src/org/chromium/base/test/BaseActivityTestRule.java new file mode 100644 index 0000000..af570fb --- /dev/null +++ b/base/test/android/javatests/src/org/chromium/base/test/BaseActivityTestRule.java
@@ -0,0 +1,94 @@ +// 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.base.test; + +import android.app.Activity; +import android.content.Intent; +import android.support.test.runner.lifecycle.Stage; +import android.text.TextUtils; + +import androidx.annotation.NonNull; + +import org.junit.Assert; +import org.junit.rules.TestRule; +import org.junit.runner.Description; +import org.junit.runners.model.Statement; + +import org.chromium.base.ContextUtils; +import org.chromium.base.Log; +import org.chromium.base.test.util.ApplicationTestUtils; + +/** + * A replacement for ActivityTestRule, designed for use in Chromium. This implementation supports + * launching the target activity through a launcher or redirect from another Activity. + * + * @param <T> The type of Activity this Rule will use. + */ +public class BaseActivityTestRule<T extends Activity> implements TestRule { + private static final String TAG = "BaseActivityTestRule"; + + private final Class<T> mActivityClass; + private boolean mFinishActivity = true; + private T mActivity; + + /** + * @param activityClass The Class of the Activity the TestRule will use. + */ + public BaseActivityTestRule(Class<T> activityClass) { + mActivityClass = activityClass; + } + + @Override + public Statement apply(final Statement base, final Description desc) { + return new Statement() { + @Override + public void evaluate() throws Throwable { + base.evaluate(); + if (mFinishActivity && mActivity != null) { + ApplicationTestUtils.finishActivity(mActivity); + } + } + }; + } + + /** + * @param finishActivity Whether to finish the Activity between tests. This is only meaningful + * in the context of {@link Batch} tests. Non-batched tests will always finish Activities + * between tests. + */ + public void setFinishActivity(boolean finishActivity) { + mFinishActivity = finishActivity; + } + + /** + * @return The activity under test. + */ + public T getActivity() { + return mActivity; + } + + /** + * Set the Activity to be used by this TestRule. + */ + public void setActivity(T activity) { + mActivity = activity; + } + + /** + * Launches the Activity under test using the provided intent. + */ + public void launchActivity(@NonNull Intent startIntent) { + String packageName = ContextUtils.getApplicationContext().getPackageName(); + Assert.assertTrue(TextUtils.equals(startIntent.getPackage(), packageName) + || TextUtils.equals(startIntent.getComponent().getPackageName(), packageName)); + + startIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + + Log.d(TAG, String.format("Launching activity %s", mActivityClass.getName())); + + mActivity = ApplicationTestUtils.waitForActivityWithClass(mActivityClass, Stage.CREATED, + () -> ContextUtils.getApplicationContext().startActivity(startIntent)); + } +}
diff --git a/base/test/android/javatests/src/org/chromium/base/test/util/ApplicationTestUtils.java b/base/test/android/javatests/src/org/chromium/base/test/util/ApplicationTestUtils.java index 799c803..c044cb4 100644 --- a/base/test/android/javatests/src/org/chromium/base/test/util/ApplicationTestUtils.java +++ b/base/test/android/javatests/src/org/chromium/base/test/util/ApplicationTestUtils.java
@@ -5,6 +5,9 @@ package org.chromium.base.test.util; import android.app.Activity; +import android.content.Intent; +import android.os.Build; +import android.provider.Settings; import android.support.test.runner.lifecycle.ActivityLifecycleCallback; import android.support.test.runner.lifecycle.ActivityLifecycleMonitor; import android.support.test.runner.lifecycle.ActivityLifecycleMonitorRegistry; @@ -26,9 +29,16 @@ /** Waits until the given activity transitions to the given state. */ public static void waitForActivityState(Activity activity, Stage stage) { - CriteriaHelper.pollUiThread(() -> { - return sMonitor.getLifecycleStageOf(activity) == stage; - }, ScalableTimeout.scaleTimeout(10000), CriteriaHelper.DEFAULT_POLLING_INTERVAL); + waitForActivityState(null, activity, stage); + } + + /** Waits until the given activity transitions to the given state. */ + public static void waitForActivityState(String failureReason, Activity activity, Stage stage) { + CriteriaHelper.pollUiThread( + () + -> { return sMonitor.getLifecycleStageOf(activity) == stage; }, + failureReason, ScalableTimeout.scaleTimeout(10000), + CriteriaHelper.DEFAULT_POLLING_INTERVAL); } /** Finishes the given activity and waits for its onDestroy() to be called. */ @@ -38,7 +48,24 @@ activity.finish(); } }); - waitForActivityState(activity, Stage.DESTROYED); + try { + waitForActivityState( + "Failed to finish the Activity. Did you start a second Activity and not finish" + + " it?", + activity, Stage.DESTROYED); + } catch (Throwable e) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) throw e; + + // On L, there's a framework bug where Activities sometimes just don't get finished + // unless you start another Activity. + Intent intent = new Intent(Settings.ACTION_SETTINGS); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + activity.startActivity(intent); + waitForActivityState( + "Failed to finish the Activity. Did you start a second Activity and not finish" + + " it?", + activity, Stage.DESTROYED); + } } /** @@ -48,11 +75,25 @@ * @return The newly created Activity. */ public static <T extends Activity> T recreateActivity(T activity) { - final Class<?> activityClass = activity.getClass(); + return waitForActivityWithClass( + activity.getClass(), Stage.RESUMED, () -> activity.recreate()); + } + + /** + * Waits for an activity of the specified class to reach the specified Activity {@link Stage}, + * triggered by running the provided trigger. + * + * @param activityClass The class type to wait for. + * @param state The Activity {@link Stage} to wait for an activity of the right class type to + * reach. + * @param trigger The Runnable that will trigger the state change to wait for. + */ + public static <T extends Activity> T waitForActivityWithClass( + Class<? extends Activity> activityClass, Stage stage, Runnable trigger) { final CallbackHelper activityCallback = new CallbackHelper(); final AtomicReference<T> activityRef = new AtomicReference<>(); - ActivityLifecycleCallback stateListener = (Activity newActivity, Stage stage) -> { - if (stage == Stage.RESUMED) { + ActivityLifecycleCallback stateListener = (Activity newActivity, Stage newStage) -> { + if (newStage == stage) { if (!activityClass.isAssignableFrom(newActivity.getClass())) return; activityRef.set((T) newActivity); @@ -62,8 +103,8 @@ sMonitor.addLifecycleCallback(stateListener); try { - ThreadUtils.runOnUiThreadBlocking(() -> activity.recreate()); - activityCallback.waitForCallback("Activity did not start as expected", 0); + ThreadUtils.runOnUiThreadBlocking(() -> trigger.run()); + activityCallback.waitForCallback("No Activity reached target state.", 0); T createdActivity = activityRef.get(); Assert.assertNotNull("Activity reference is null.", createdActivity); return createdActivity;
diff --git a/build/config/android/rules.gni b/build/config/android/rules.gni index c6cd584c..a453337 100644 --- a/build/config/android/rules.gni +++ b/build/config/android/rules.gni
@@ -192,6 +192,9 @@ args += [ "-n ${invoker.namespace}" ] } } + if (defined(invoker.split_name)) { + args += [ "--split_name=${invoker.split_name}" ] + } outputs = [] foreach(_name, _input_names) {
diff --git a/build/config/mac/base_rules.gni b/build/config/mac/base_rules.gni index 4678e95..d767ce82 100644 --- a/build/config/mac/base_rules.gni +++ b/build/config/mac/base_rules.gni
@@ -24,7 +24,7 @@ # string, path to the converted plist, must be under $root_build_dir # # format: -# string, the format to `plutil -convert` the plist to. +# string, the format to convert the plist to. Either "binary1" or "xml1". template("convert_plist") { assert(defined(invoker.source), "source must be defined for $target_name") assert(defined(invoker.output), "output must be defined for $target_name") @@ -38,17 +38,12 @@ "deps", ]) - script = "//build/gn_run_binary.py" + script = "//build/config/mac/plist_util.py" sources = [ invoker.source ] outputs = [ invoker.output ] - - # /usr/bin/plutil is present on all images of macOS. If at some point in the - # future we need to ship our own copy [e.g. for cross-compile], we can add a - # layer of indirection. args = [ - "/usr/bin/plutil", - "-convert", - invoker.format, + "merge", + "--format=${invoker.format}", "-o", rebase_path(invoker.output, root_build_dir), rebase_path(invoker.source, root_build_dir),
diff --git a/build/config/mac/plist_util.py b/build/config/mac/plist_util.py index 7c03780..e975083 100644 --- a/build/config/mac/plist_util.py +++ b/build/config/mac/plist_util.py
@@ -109,15 +109,15 @@ def SavePList(path, format, data): """Saves |data| as a Plist to |path| in the specified |format|.""" + # The below does not replace the destination file but update it in place, + # so if more than one hardlink points to destination all of them will be + # modified. This is not what is expected, so delete destination file if + # it does exist. + if os.path.exists(path): + os.unlink(path) if sys.version_info.major == 2: fd, name = tempfile.mkstemp() try: - # "plutil" does not replace the destination file but update it in place, - # so if more than one hardlink points to destination all of them will be - # modified. This is not what is expected, so delete destination file if - # it does exist. - if os.path.exists(path): - os.unlink(path) with os.fdopen(fd, 'wb') as f: plistlib.writePlist(data, f) subprocess.check_call(['plutil', '-convert', format, '-o', path, name])
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1 index b1e0b1d..3208790d 100644 --- a/build/fuchsia/linux.sdk.sha1 +++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@ -0.20201125.2.1 +0.20201126.0.1
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1 index b1e0b1d..3208790d 100644 --- a/build/fuchsia/mac.sdk.sha1 +++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@ -0.20201125.2.1 +0.20201126.0.1
diff --git a/build/sanitizers/tsan_suppressions.cc b/build/sanitizers/tsan_suppressions.cc index 26b42ef..982e79da 100644 --- a/build/sanitizers/tsan_suppressions.cc +++ b/build/sanitizers/tsan_suppressions.cc
@@ -45,9 +45,6 @@ // http://crbug.com/244856 "race:libpulsecommon*.so\n" - // http://crbug.com/246968 - "race:webrtc::VideoCodingModuleImpl::RegisterPacketRequestCallback\n" - // http://crbug.com/258479 "race:g_trace_state\n" @@ -73,10 +70,6 @@ // http://crbug.com/328868 "race:PR_Lock\n" - // http://crbug.com/348982 - "race:cricket::P2PTransportChannel::OnConnectionDestroyed\n" - "race:cricket::P2PTransportChannel::AddConnection\n" - // http://crbug.com/348984 "race:sctp_express_handle_sack\n" "race:system_base_info\n"
diff --git a/cc/layers/layer.cc b/cc/layers/layer.cc index aca2eaf..3f187ae 100644 --- a/cc/layers/layer.cc +++ b/cc/layers/layer.cc
@@ -59,7 +59,6 @@ int int_fields[6]; gfx::Vector2dF offset; unsigned bitfields; - SkColor safe_opaque_background_color; void* debug_info; }; @@ -87,19 +86,13 @@ Layer::Inputs::~Inputs() = default; Layer::LayerTreeInputs::LayerTreeInputs() - : mask_layer(nullptr), - opacity(1.f), - blend_mode(SkBlendMode::kSrcOver), - masks_to_bounds(false), + : masks_to_bounds(false), is_fast_rounded_corner(false), user_scrollable_horizontal(true), user_scrollable_vertical(true), trilinear_filtering(false), hide_layer_and_subtree(false), - scrollable(false), - backdrop_filter_quality(1.0f), - mirror_count(0), - corner_radii({0, 0, 0, 0}) {} + scrollable(false) {} Layer::LayerTreeInputs::~LayerTreeInputs() = default; @@ -128,8 +121,7 @@ needs_show_scrollbars_(false), has_transform_node_(false), has_clip_node_(false), - subtree_has_copy_request_(false), - safe_opaque_background_color_(0) {} + subtree_has_copy_request_(false) {} Layer::~Layer() { // Our parent should be holding a reference to us so there should be no @@ -496,25 +488,41 @@ void Layer::SetSafeOpaqueBackgroundColor(SkColor background_color) { DCHECK(IsPropertyChangeAllowed()); - SkColor opaque_color = SkColorSetA(background_color, 255); - if (safe_opaque_background_color_ == opaque_color) + SkColor opaque_color = SkColorSetA(background_color, SK_AlphaOPAQUE); + auto& inputs = EnsureLayerTreeInputs(); + if (inputs.safe_opaque_background_color == opaque_color) return; - safe_opaque_background_color_ = opaque_color; + inputs.safe_opaque_background_color = opaque_color; SetNeedsPushProperties(); } SkColor Layer::SafeOpaqueBackgroundColor() const { if (contents_opaque()) { - // TODO(936906): We should uncomment this DCHECK, since the - // |safe_opaque_background_color_| could be transparent if it is never set - // (the default is 0). But to do that, one test needs to be fixed. - // DCHECK_EQ(SkColorGetA(safe_opaque_background_color_), SK_AlphaOPAQUE); - return safe_opaque_background_color_; + if (!layer_tree_host_ || !layer_tree_host_->IsUsingLayerLists()) { + // In layer tree mode, PropertyTreeBuilder should have calculated the safe + // opaque background color and called SetSafeOpaqueBackgroundColor(). + DCHECK(layer_tree_inputs()); + DCHECK_EQ(SkColorGetA(layer_tree_inputs()->safe_opaque_background_color), + SK_AlphaOPAQUE); + return layer_tree_inputs()->safe_opaque_background_color; + } + // In layer list mode, the PropertyTreeBuilder algorithm doesn't apply + // because it depends on the layer tree hierarchy. Instead we use + // background_color() if it's not transparent, or layer_tree_host_'s + // background_color(), with the alpha channel forced to be opaque. + SkColor color = background_color() == SK_ColorTRANSPARENT + ? layer_tree_host_->background_color() + : background_color(); + return SkColorSetA(color, SK_AlphaOPAQUE); } - SkColor color = background_color(); - if (SkColorGetA(color) == 255) - color = SK_ColorTRANSPARENT; - return color; + if (SkColorGetA(background_color()) == SK_AlphaOPAQUE) { + // The layer is not opaque while the background color is, meaning that the + // background color doesn't cover the whole layer. Use SK_ColorTRANSPARENT + // to avoid intrusive checkerboard where the layer is not covered by the + // background color. + return SK_ColorTRANSPARENT; + } + return background_color(); } void Layer::SetMasksToBounds(bool masks_to_bounds) { @@ -1305,7 +1313,7 @@ layer->SetElementId(inputs_.element_id); layer->SetHasTransformNode(has_transform_node_); layer->SetBackgroundColor(inputs_.background_color); - layer->SetSafeOpaqueBackgroundColor(safe_opaque_background_color_); + layer->SetSafeOpaqueBackgroundColor(SafeOpaqueBackgroundColor()); layer->SetBounds(inputs_.bounds); layer->SetTransformTreeIndex(transform_tree_index()); layer->SetEffectTreeIndex(effect_tree_index());
diff --git a/cc/layers/layer.h b/cc/layers/layer.h index 69915971..3f4189ef 100644 --- a/cc/layers/layer.h +++ b/cc/layers/layer.h
@@ -151,22 +151,22 @@ virtual void SetBackgroundColor(SkColor background_color); SkColor background_color() const { return inputs_.background_color; } - // Internal to property tree generation. Sets an opaque background color for - // the layer, to be used in place of the background_color() if the layer says - // contents_opaque() is true. + // For layer tree mode only. In layer list mode, client doesn't need to set + // it. Sets an opaque background color for the layer, to be used in place of + // the background_color() if the layer says contents_opaque() is true. void SetSafeOpaqueBackgroundColor(SkColor background_color); - // Returns a background color with opaque-ness equal to the value of + + // Returns a background color with opaqueness equal to the value of // contents_opaque(). - // If the layer says contents_opaque() is true, this returns the value set by - // SetSafeOpaqueBackgroundColor() which should be an opaque color. Otherwise, - // it returns something non-opaque. It prefers to return the + // If the layer says contents_opaque() is true, in layer tree mode, this + // returns the value set by SetSafeOpaqueBackgroundColor() which should be an + // opaque color, and in layer list mode, returns an opaque color calculated + // from background_color() and layer_tree_host()->background_clor(). + // Otherwise, it returns something non-opaque. It prefers to return the // background_color(), but if the background_color() is opaque (and this layer - // claims to not be), then SK_ColorTRANSPARENT is returned. + // claims to not be), then SK_ColorTRANSPARENT is returned to avoid intrusive + // checkerboard where the layer is not covered by the background_color(). SkColor SafeOpaqueBackgroundColor() const; - // For testing, return the actual stored value. - SkColor ActualSafeOpaqueBackgroundColorForTesting() const { - return safe_opaque_background_color_; - } // For layer tree mode only. // Set and get the position of this layer, relative to its parent. This is @@ -862,10 +862,10 @@ // If not null, points to one of child layers which is set as mask layer // by SetMaskLayer(). - PictureLayer* mask_layer; + PictureLayer* mask_layer = nullptr; - float opacity; - SkBlendMode blend_mode; + float opacity = 1.0f; + SkBlendMode blend_mode = SkBlendMode::kSrcOver; bool masks_to_bounds : 1; @@ -889,12 +889,14 @@ gfx::Transform transform; gfx::Point3F transform_origin; + SkColor safe_opaque_background_color = SK_ColorTRANSPARENT; + FilterOperations filters; FilterOperations backdrop_filters; base::Optional<gfx::RRectF> backdrop_filter_bounds; - float backdrop_filter_quality; + float backdrop_filter_quality = 1.0f; - int mirror_count; + int mirror_count = 0; gfx::ScrollOffset scroll_offset; // Size of the scroll container that this layer scrolls in. @@ -945,8 +947,6 @@ // This value is valid only when LayerTreeHost::has_copy_request() is true bool subtree_has_copy_request_ : 1; - SkColor safe_opaque_background_color_; - std::unique_ptr<LayerDebugInfo> debug_info_; static constexpr gfx::Transform kIdentityTransform{};
diff --git a/cc/layers/layer_impl.cc b/cc/layers/layer_impl.cc index 460019a..920a3f5 100644 --- a/cc/layers/layer_impl.cc +++ b/cc/layers/layer_impl.cc
@@ -555,20 +555,6 @@ safe_opaque_background_color_ = background_color; } -SkColor LayerImpl::SafeOpaqueBackgroundColor() const { - if (contents_opaque()) { - // TODO(936906): We should uncomment this DCHECK, since the - // |safe_opaque_background_color_| could be transparent if it is never set - // (the default is 0). But to do that, one test needs to be fixed. - // DCHECK_EQ(SkColorGetA(safe_opaque_background_color_), SK_AlphaOPAQUE); - return safe_opaque_background_color_; - } - SkColor color = background_color(); - if (SkColorGetA(color) == 255) - color = SK_ColorTRANSPARENT; - return color; -} - void LayerImpl::SetContentsOpaque(bool opaque) { contents_opaque_ = opaque; contents_opaque_for_text_ = opaque;
diff --git a/cc/layers/layer_impl.h b/cc/layers/layer_impl.h index 6af8b62c..66c0b80 100644 --- a/cc/layers/layer_impl.h +++ b/cc/layers/layer_impl.h
@@ -163,9 +163,12 @@ void SetBackgroundColor(SkColor background_color); SkColor background_color() const { return background_color_; } void SetSafeOpaqueBackgroundColor(SkColor background_color); - // If contents_opaque(), return an opaque color else return a - // non-opaque color. Tries to return background_color(), if possible. - SkColor SafeOpaqueBackgroundColor() const; + SkColor safe_opaque_background_color() const { + // Layer::SafeOpaqueBackgroundColor() should ensure this. + DCHECK_EQ(contents_opaque(), + SkColorGetA(safe_opaque_background_color_) == SK_AlphaOPAQUE); + return safe_opaque_background_color_; + } // See Layer::SetContentsOpaque() and SetContentsOpaqueForText() for the // relationship between the two flags.
diff --git a/cc/layers/picture_layer_impl.cc b/cc/layers/picture_layer_impl.cc index c26d781..2f6a867 100644 --- a/cc/layers/picture_layer_impl.cc +++ b/cc/layers/picture_layer_impl.cc
@@ -511,7 +511,7 @@ if (!has_draw_quad) { // Checkerboard. - SkColor color = SafeOpaqueBackgroundColor(); + SkColor color = safe_opaque_background_color(); if (ShowDebugBorders(DebugBorderType::LAYER)) { // Fill the whole tile with the missing tile color. color = DebugColors::DefaultCheckerboardColor();
diff --git a/cc/test/test_layer_tree_host_base.cc b/cc/test/test_layer_tree_host_base.cc index 96b1b7a..26b5ef5 100644 --- a/cc/test/test_layer_tree_host_base.cc +++ b/cc/test/test_layer_tree_host_base.cc
@@ -123,6 +123,7 @@ pending_layer_->SetDrawsContent(true); // LCD-text tests require the layer to be initially opaque. pending_layer_->SetContentsOpaque(true); + pending_layer_->SetSafeOpaqueBackgroundColor(SK_ColorWHITE); pending_tree->SetElementIdsForTesting(); SetupRootProperties(pending_root);
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/AssistantOnboardingCoordinatorTest.java index 80b4009..2717c72 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/AssistantOnboardingCoordinatorTest.java
@@ -23,10 +23,9 @@ import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.verify; -import static org.chromium.chrome.browser.autofill_assistant.AutofillAssistantUiTestUtil.waitUntil; import static org.chromium.chrome.browser.autofill_assistant.AutofillAssistantUiTestUtil.waitUntilViewMatchesCondition; -import android.app.Activity; +import android.support.test.runner.lifecycle.Stage; import android.text.Spanned; import android.text.style.ClickableSpan; import android.view.View; @@ -43,10 +42,10 @@ import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; -import org.chromium.base.ActivityState; -import org.chromium.base.ApplicationStatus; import org.chromium.base.Callback; +import org.chromium.base.test.util.ApplicationTestUtils; import org.chromium.base.test.util.CommandLineFlags; +import org.chromium.base.test.util.CriteriaHelper; import org.chromium.chrome.autofill_assistant.R; import org.chromium.chrome.browser.app.ChromeActivity; import org.chromium.chrome.browser.autofill_assistant.overlay.AssistantOverlayCoordinator; @@ -57,7 +56,6 @@ import org.chromium.chrome.browser.flags.ChromeSwitches; import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; -import org.chromium.chrome.test.util.ChromeTabUtils; import org.chromium.components.browser_ui.bottomsheet.BottomSheetController; import org.chromium.components.browser_ui.widget.scrim.ScrimCoordinator; import org.chromium.content_public.browser.test.util.TestThreadUtils; @@ -295,8 +293,11 @@ spannedMessage.getSpanEnd(spans[0])) .toString()); }); - spans[0].onClick(termsMessage); - waitUntil(() -> getOpenedUrlSpec().equals(expectedTermsUrl)); + CustomTabActivity activity = ApplicationTestUtils.waitForActivityWithClass( + CustomTabActivity.class, Stage.RESUMED, () -> spans[0].onClick(termsMessage)); + CriteriaHelper.pollUiThread( + () -> activity.getActivityTab().getUrlString().equals(expectedTermsUrl)); + activity.finish(); } @Test @@ -356,12 +357,13 @@ .toString() .replaceAll("\\s+", " ")); }); - spans[0].onClick(termsMessage); - waitUntil(() - -> getOpenedUrlSpec().equals( - mActivity.getResources() - .getText(R.string.autofill_assistant_google_terms_url) - .toString())); + CustomTabActivity activity = ApplicationTestUtils.waitForActivityWithClass( + CustomTabActivity.class, Stage.RESUMED, () -> spans[0].onClick(termsMessage)); + String url = mActivity.getResources() + .getText(R.string.autofill_assistant_google_terms_url) + .toString(); + CriteriaHelper.pollUiThread(() -> activity.getActivityTab().getUrlString().equals(url)); + activity.finish(); } /** Trigger onboarding and wait until it is fully displayed. */ @@ -370,21 +372,4 @@ TestThreadUtils.runOnUiThreadBlocking(() -> coordinator.show(callback)); waitUntilViewMatchesCondition(withId(R.id.button_init_ok), isCompletelyDisplayed()); } - - // Get the newly opened Activity (through CustomTabActivity.showInfoPage) that happens on - // terms click. Return the URL of the current tab on that activity. - private String getOpenedUrlSpec() { - for (Activity runningActivity : ApplicationStatus.getRunningActivities()) { - if (runningActivity instanceof CustomTabActivity - && ApplicationStatus.getStateForActivity(runningActivity) - == ActivityState.RESUMED) { - return ChromeTabUtils - .getUrlOnUiThread(((CustomTabActivity) runningActivity) - .getTabModelSelector() - .getCurrentTab()) - .getSpec(); - } - } - return ""; - } }
diff --git a/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/InstantStartTest.java b/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/InstantStartTest.java index 51b95d2..a3ae2c4 100644 --- a/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/InstantStartTest.java +++ b/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/InstantStartTest.java
@@ -65,6 +65,7 @@ import org.chromium.base.test.util.DisableIf; import org.chromium.base.test.util.Feature; import org.chromium.base.test.util.Restriction; +import org.chromium.base.test.util.ScalableTimeout; import org.chromium.chrome.browser.ChromeTabbedActivity; import org.chromium.chrome.browser.compositor.layouts.Layout; import org.chromium.chrome.browser.compositor.layouts.LayoutManagerChromePhone; @@ -172,7 +173,7 @@ Intent intent = new Intent(Intent.ACTION_MAIN); intent.addCategory(Intent.CATEGORY_LAUNCHER); mActivityTestRule.prepareUrlIntent(intent, null); - mActivityTestRule.startActivityCompletely(intent); + mActivityTestRule.launchActivity(intent); } public static Bitmap createThumbnailBitmapAndWriteToFile(int tabId) { @@ -271,7 +272,8 @@ TestThreadUtils.runOnUiThreadBlocking( () -> mActivityTestRule.getActivity().startDelayedNativeInitializationForTests()); CriteriaHelper.pollUiThread( - mActivityTestRule.getActivity().getTabModelSelector()::isTabStateInitialized); + mActivityTestRule.getActivity().getTabModelSelector()::isTabStateInitialized, + ScalableTimeout.scaleTimeout(10000L), CriteriaHelper.DEFAULT_POLLING_INTERVAL); Assert.assertTrue(LibraryLoader.getInstance().isInitialized()); } @@ -568,6 +570,7 @@ RecyclerView.ViewHolder viewHolder = recyclerView.findViewHolderForAdapterPosition(i); if (viewHolder != null) { ImageView thumbnail = viewHolder.itemView.findViewById(R.id.tab_thumbnail); + if (!(thumbnail.getDrawable() instanceof BitmapDrawable)) return false; BitmapDrawable drawable = (BitmapDrawable) thumbnail.getDrawable(); Bitmap bitmap = drawable.getBitmap(); if (bitmap == null) return false;
diff --git a/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceNoTabsTest.java b/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceNoTabsTest.java index 19a30c7..260b84d6 100644 --- a/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceNoTabsTest.java +++ b/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceNoTabsTest.java
@@ -91,7 +91,7 @@ Intent intent = new Intent(Intent.ACTION_MAIN); intent.addCategory(Intent.CATEGORY_LAUNCHER); mActivityTestRule.prepareUrlIntent(intent, null); - mActivityTestRule.startActivityCompletely(intent); + mActivityTestRule.launchActivity(intent); } @Before
diff --git a/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceTest.java b/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceTest.java index 9d29913..c7b94a6 100644 --- a/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceTest.java +++ b/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceTest.java
@@ -811,7 +811,7 @@ @CommandLineFlags.Add({BASE_PARAMS + "/single/exclude_mv_tiles/true" + "/show_last_active_tab_only/true/show_stack_tab_switcher/true"}) public void - testShow_SingleAsHomepageV2_FromResumeShowStart() throws ExecutionException { + testShow_SingleAsHomepageV2_FromResumeShowStart() throws Exception { // clang-format on if (!mImmediateReturn) return; @@ -831,7 +831,7 @@ pressHome(); // Simulates pressing Chrome's icon and launching Chrome from warm start. - startMainActivityFromLauncher(); + mActivityTestRule.resumeMainActivityFromLauncher(); CriteriaHelper.pollUiThread( () -> cta.getLayoutManager() != null && cta.getLayoutManager().overviewVisible());
diff --git a/chrome/android/java/res/layout/custom_tabs_toolbar.xml b/chrome/android/java/res/layout/custom_tabs_toolbar.xml index fac032c..83c8fb6 100644 --- a/chrome/android/java/res/layout/custom_tabs_toolbar.xml +++ b/chrome/android/java/res/layout/custom_tabs_toolbar.xml
@@ -14,15 +14,16 @@ style="@style/ToolbarButton" android:layout_gravity="start|center_vertical" android:contentDescription="@string/close_tab" /> - <org.chromium.ui.widget.ChromeImageButton - android:id="@+id/incognito_cct_logo_button" + <org.chromium.ui.widget.ChromeImageView + android:id="@+id/incognito_cct_logo_image_view" style="@style/LocationBarButton" android:layout_width="@dimen/location_bar_icon_width" android:layout_height="match_parent" android:layout_gravity="start" android:scaleType="center" app:srcCompat="@drawable/ic_incognito_cct_24dp" - android:visibility="gone" /> + android:visibility="gone" + android:contentDescription="@string/accessibility_incognito_badge"/> <FrameLayout android:id="@+id/location_bar_frame_layout" android:layout_width="match_parent"
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManager.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManager.java index 5ab3865..84509ce 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManager.java
@@ -1097,7 +1097,7 @@ .setRedirectHandler(mRedirectHandler) .setIsMainFrame(navigationParams.isMainFrame) .build(); - if (externalNavHandler.shouldOverrideUrlLoading(params) + if (externalNavHandler.shouldOverrideUrlLoading(params).getResultType() != OverrideUrlLoadingResultType.NO_OVERRIDE) { return false; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/features/toolbar/CustomTabToolbar.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/features/toolbar/CustomTabToolbar.java index 24150a9e..18c6d73 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/features/toolbar/CustomTabToolbar.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/features/toolbar/CustomTabToolbar.java
@@ -30,6 +30,7 @@ import android.view.ViewGroup; import android.widget.FrameLayout; import android.widget.ImageButton; +import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; @@ -131,7 +132,7 @@ private View mLiteStatusView; private View mLiteStatusSeparatorView; private TextView mTitleBar; - private ImageButton mIncognitoButton; + private ImageView mIncognitoImageView; private ImageButton mSecurityButton; private LinearLayout mCustomActionButtons; private ImageButton mCloseButton; @@ -184,7 +185,7 @@ mLocationBarFrameLayout = findViewById(R.id.location_bar_frame_layout); mTitleUrlContainer = findViewById(R.id.title_url_container); mTitleUrlContainer.setOnLongClickListener(this); - mIncognitoButton = findViewById(R.id.incognito_cct_logo_button); + mIncognitoImageView = findViewById(R.id.incognito_cct_logo_image_view); mSecurityButton = findViewById(R.id.security_button); mCustomActionButtons = findViewById(R.id.action_buttons); mCloseButton = findViewById(R.id.close_button); @@ -376,7 +377,7 @@ private void updateToolbarLayoutMargin() { // We show the Incognito logo for Incognito CCT case - if (getToolbarDataProvider().isIncognito()) mIncognitoButton.setVisibility(VISIBLE); + if (getToolbarDataProvider().isIncognito()) mIncognitoImageView.setVisibility(VISIBLE); int startMargin = calculateStartMarginWhenCloseButtonVisibilityGone();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/externalnav/ExternalNavigationDelegateImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/externalnav/ExternalNavigationDelegateImpl.java index 01441c0e..9297716 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/externalnav/ExternalNavigationDelegateImpl.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/externalnav/ExternalNavigationDelegateImpl.java
@@ -35,7 +35,7 @@ import org.chromium.components.external_intents.ExternalNavigationDelegate; import org.chromium.components.external_intents.ExternalNavigationDelegate.StartActivityIfNeededResult; import org.chromium.components.external_intents.ExternalNavigationHandler; -import org.chromium.components.external_intents.ExternalNavigationHandler.OverrideUrlLoadingResultType; +import org.chromium.components.external_intents.ExternalNavigationHandler.OverrideUrlLoadingResult; import org.chromium.components.external_intents.ExternalNavigationParams; import org.chromium.components.external_intents.RedirectHandler; import org.chromium.content_public.browser.LoadUrlParams; @@ -149,14 +149,13 @@ } @Override - public @OverrideUrlLoadingResultType int handleIncognitoIntentTargetingSelf( + public OverrideUrlLoadingResult handleIncognitoIntentTargetingSelf( final Intent intent, final String referrerUrl, final String fallbackUrl) { String primaryUrl = intent.getDataString(); boolean isUrlLoadedInTheSameTab = ExternalNavigationHandler.loadUrlFromIntent( referrerUrl, primaryUrl, fallbackUrl, this, false, true); - return (isUrlLoadedInTheSameTab) - ? OverrideUrlLoadingResultType.OVERRIDE_WITH_CLOBBERING_TAB - : OverrideUrlLoadingResultType.OVERRIDE_WITH_EXTERNAL_INTENT; + return (isUrlLoadedInTheSameTab) ? OverrideUrlLoadingResult.forClobberingTab() + : OverrideUrlLoadingResult.forExternalIntent(); } @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/ProfileDataCache.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/ProfileDataCache.java index 3991bede..a1e05b8 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/signin/ProfileDataCache.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/ProfileDataCache.java
@@ -45,8 +45,7 @@ * should be provided by calling {@link #update(List)} */ @MainThread -public class ProfileDataCache implements ProfileDownloader.Observer, ProfileDataSource.Observer, - IdentityManager.Observer { +public class ProfileDataCache implements ProfileDataSource.Observer, IdentityManager.Observer { /** * Observer to get notifications about changes in profile data. */ @@ -151,7 +150,7 @@ for (int i = 0; i < accounts.size(); i++) { if (mCachedProfileData.get(accounts.get(i)) == null) { - ProfileDownloader.startFetchingAccountInfoFor( + ProfileDownloader.get().startFetchingAccountInfoFor( mContext, accounts.get(i), mImageSize, true); } } @@ -204,7 +203,7 @@ mProfileDataSource.addObserver(this); updateCacheFromProfileDataSource(); } else { - ProfileDownloader.addObserver(this); + ProfileDownloader.get().addObserver(this); } mIdentityManager.addObserver(this); } @@ -221,7 +220,7 @@ if (mProfileDataSource != null) { mProfileDataSource.removeObserver(this); } else { - ProfileDownloader.removeObserver(this); + ProfileDownloader.get().removeObserver(this); } mIdentityManager.removeObserver(this); } @@ -242,11 +241,9 @@ } @Override - public void onProfileDownloaded( - String accountEmail, String fullName, String givenName, Bitmap bitmap) { + public void onProfileDataUpdated(ProfileDataSource.ProfileData profileData) { ThreadUtils.assertOnUiThread(); - updateCachedProfileDataAndNotifyObservers(new DisplayableProfileData( - accountEmail, prepareAvatar(bitmap, accountEmail), fullName, givenName)); + updateCachedProfileDataAndNotifyObservers(createDisplayableProfileData(profileData)); } @Override @@ -255,13 +252,18 @@ ProfileDataSource.ProfileData profileData = mProfileDataSource.getProfileDataForAccount(accountEmail); if (profileData == null) { - mCachedProfileData.remove(accountEmail); - notifyObservers(accountEmail); + removeProfileData(accountEmail); } else { - updateCachedProfileDataAndNotifyObservers(createDisplayableProfileData(profileData)); + onProfileDataUpdated(profileData); } } + @Override + public void removeProfileData(String accountEmail) { + mCachedProfileData.remove(accountEmail); + notifyObservers(accountEmail); + } + /** * Implements {@link IdentityManager.Observer}. */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/ProfileDownloader.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/ProfileDownloader.java index 2cb164a..804be944 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/signin/ProfileDownloader.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/ProfileDownloader.java
@@ -13,6 +13,7 @@ import org.chromium.base.annotations.NativeMethods; import org.chromium.chrome.browser.profiles.Profile; import org.chromium.components.signin.AccountTrackerService; +import org.chromium.components.signin.ProfileDataSource; import java.util.ArrayList; @@ -21,38 +22,38 @@ * The native ProfileDownloader requires its access to be in the UI thread. * See chrome/browser/profiles/profile_downloader.h/cc for more details. */ -public class ProfileDownloader { - private static final ObserverList<Observer> sObservers = new ObserverList<Observer>(); +class ProfileDownloader { + private static ProfileDownloader sInstance; - /** - * Interface for receiving notifications on account information updates. - */ - public interface Observer { - /** - * Notifies that an account data in the profile has been updated. - * @param accountEmail An account email. - * @param fullName A full name. - * @param givenName A given name. - * @param bitmap A user picture. - */ - void onProfileDownloaded( - String accountEmail, String fullName, String givenName, Bitmap bitmap); + private final ObserverList<ProfileDataSource.Observer> mObservers = new ObserverList<>(); + + static synchronized ProfileDownloader get() { + if (sInstance == null) { + sInstance = new ProfileDownloader(); + } + return sInstance; } /** * Add an observer. * @param observer An observer. */ - public static void addObserver(Observer observer) { - sObservers.addObserver(observer); + public void addObserver(ProfileDataSource.Observer observer) { + mObservers.addObserver(observer); } /** * Remove an observer. * @param observer An observer. */ - public static void removeObserver(Observer observer) { - sObservers.removeObserver(observer); + public void removeObserver(ProfileDataSource.Observer observer) { + mObservers.removeObserver(observer); + } + + private void notifyObservers(ProfileDataSource.ProfileData profileData) { + for (ProfileDataSource.Observer observer : mObservers) { + observer.onProfileDataUpdated(profileData); + } } /** @@ -74,7 +75,7 @@ mImageSidePixels = new ArrayList<>(); } - public static PendingProfileDownloads get(Context context) { + static PendingProfileDownloads get(Context context) { ThreadUtils.assertOnUiThread(); if (sPendingProfileDownloads == null) { sPendingProfileDownloads = new PendingProfileDownloads(); @@ -120,7 +121,7 @@ * @param accountEmail Account email to fetch the information for * @param imageSidePixels Request image side (in pixels) */ - public static void startFetchingAccountInfoFor( + public void startFetchingAccountInfoFor( Context context, String accountEmail, int imageSidePixels, boolean isPreSignin) { ThreadUtils.assertOnUiThread(); Profile profile = Profile.getLastUsedRegularProfile(); @@ -137,11 +138,10 @@ @CalledByNative private static void onProfileDownloadSuccess( - String accountEmail, String fullName, String givenName, Bitmap bitmap) { + String accountEmail, String fullName, String givenName, Bitmap avatar) { ThreadUtils.assertOnUiThread(); - for (Observer observer : sObservers) { - observer.onProfileDownloaded(accountEmail, fullName, givenName, bitmap); - } + ProfileDownloader.get().notifyObservers( + new ProfileDataSource.ProfileData(accountEmail, avatar, fullName, givenName)); } /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/LocationBarModel.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/LocationBarModel.java index 2d53db6..55cc509 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/LocationBarModel.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/LocationBarModel.java
@@ -130,10 +130,10 @@ @Override public boolean hasTab() { - // TODO(dtrainor, tedchoc): Remove the isInitialized() check when we no longer wait for - // TAB_CLOSED events to remove this tab. Otherwise there is a chance we use this tab after - // {@link ChromeTab#destroy()} is called. - return mTab != null && mTab.isInitialized(); + // TODO(https://crbug.com/1147131): Remove the isInitialized() and isDestroyed checks when + // we no longer wait for TAB_CLOSED events to remove this tab. Otherwise there is a chance + // we use this tab after {@link Tab#destroy()} is called. + return mTab != null && mTab.isInitialized() && !mTab.isDestroyed(); } @Override
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/CopylessPasteTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/CopylessPasteTest.java index 279eb8d3..d2e0260 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/CopylessPasteTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/CopylessPasteTest.java
@@ -15,7 +15,6 @@ import org.junit.Test; import org.junit.runner.RunWith; -import org.chromium.base.test.util.ApplicationTestUtils; import org.chromium.base.test.util.Batch; import org.chromium.base.test.util.CallbackHelper; import org.chromium.base.test.util.CommandLineFlags; @@ -72,7 +71,6 @@ @After public void tearDown() throws Exception { AppIndexingUtil.setCallbackForTesting(null); - ApplicationTestUtils.finishActivity(mActivityTestRule.getActivity()); } private static class CopylessHelper extends CallbackHelper {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/MainActivityWithURLTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/MainActivityWithURLTest.java index cee2800..723653c 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/MainActivityWithURLTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/MainActivityWithURLTest.java
@@ -8,13 +8,11 @@ import androidx.test.filters.SmallTest; -import org.junit.After; import org.junit.Assert; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; -import org.chromium.base.test.util.ApplicationTestUtils; import org.chromium.base.test.util.Batch; import org.chromium.base.test.util.CommandLineFlags; import org.chromium.base.test.util.Feature; @@ -36,11 +34,6 @@ @Rule public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule(); - @After - public void tearDown() throws Exception { - ApplicationTestUtils.finishActivity(mActivityTestRule.getActivity()); - } - /** * Verify launch the activity with URL. */
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkPersonalizedSigninPromoDismissTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkPersonalizedSigninPromoDismissTest.java index 2d586b71..8640a48 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkPersonalizedSigninPromoDismissTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkPersonalizedSigninPromoDismissTest.java
@@ -11,8 +11,11 @@ import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed; import static androidx.test.espresso.matcher.ViewMatchers.withId; +import static org.hamcrest.CoreMatchers.allOf; import static org.junit.Assert.assertEquals; +import static org.chromium.chrome.test.util.ViewUtils.onViewWaiting; + import android.support.test.InstrumentationRegistry; import androidx.test.filters.MediumTest; @@ -81,7 +84,7 @@ @MediumTest public void testPromoNotShownAfterBeingDismissed() { mBookmarkTestRule.showBookmarkManager(mSyncTestRule.getActivity()); - onView(withId(R.id.signin_promo_view_container)).check(matches(isDisplayed())); + onViewWaiting(allOf(withId(R.id.signin_promo_view_container), isDisplayed())); onView(withId(R.id.signin_promo_close_button)).perform(click()); onView(withId(R.id.signin_promo_view_container)).check(doesNotExist());
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkTest.java index 645fad0..733c40d 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkTest.java
@@ -204,8 +204,9 @@ } @After - public void tearDown() { + public void tearDown() throws Exception { if (mTestServer != null) mTestServer.stopAndDestroyServer(); + if (mBookmarkActivity != null) ApplicationTestUtils.finishActivity(mBookmarkActivity); } @AfterClass @@ -283,7 +284,7 @@ // Click the star button again to launch the edit activity. MenuUtils.invokeCustomMenuActionSync(InstrumentationRegistry.getInstrumentation(), mActivityTestRule.getActivity(), R.id.bookmark_this_page_id); - waitForEditActivity(); + waitForEditActivity().finish(); } @Test @@ -314,8 +315,9 @@ currentSnackbar.getController().onAction(null); }); - waitForEditActivity(); + BookmarkEditActivity activity = waitForEditActivity(); SnackbarManager.setDurationForTesting(0); + activity.finish(); } @Test @@ -1731,12 +1733,13 @@ RecyclerViewTestUtils.waitForStableRecyclerView(mItemsContainer); } - private void waitForEditActivity() { + private BookmarkEditActivity waitForEditActivity() { CriteriaHelper.pollUiThread(() -> { Criteria.checkThat(ApplicationStatus.getLastTrackedFocusedActivity(), IsInstanceOf.instanceOf(BookmarkEditActivity.class)); }); InstrumentationRegistry.getInstrumentation().waitForIdleSync(); + return (BookmarkEditActivity) ApplicationStatus.getLastTrackedFocusedActivity(); } private ChromeTabbedActivity waitForTabbedActivity() {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/browsing_data/ClearBrowsingDataFragmentBasicTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/browsing_data/ClearBrowsingDataFragmentBasicTest.java index 6fc157e..c6d9b533 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/browsing_data/ClearBrowsingDataFragmentBasicTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/browsing_data/ClearBrowsingDataFragmentBasicTest.java
@@ -17,6 +17,7 @@ import org.junit.Before; import org.junit.Rule; import org.junit.Test; +import org.junit.rules.RuleChain; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.junit.MockitoJUnit; @@ -44,14 +45,18 @@ @RunWith(ChromeJUnit4ClassRunner.class) @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) public class ClearBrowsingDataFragmentBasicTest { - @Rule public final ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule(); - @Rule public final SettingsActivityTestRule<ClearBrowsingDataFragmentBasic> mSettingsActivityTestRule = new SettingsActivityTestRule<>(ClearBrowsingDataFragmentBasic.class); + // SettingsActivity has to be finished before the outer CTA can be finished or trying to finish + // CTA won't work. + @Rule + public final RuleChain mRuleChain = + RuleChain.outerRule(mActivityTestRule).around(mSettingsActivityTestRule); + @Rule public final AccountManagerTestRule mAccountManagerTestRule = new AccountManagerTestRule();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityIncognitoTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityIncognitoTest.java index 1225843..193430a1 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityIncognitoTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityIncognitoTest.java
@@ -196,7 +196,7 @@ public void toolbarHasIncognitoLogo() throws Exception { Intent intent = createMinimalIncognitoCustomTabIntent(); launchIncognitoCustomTab(intent); - Espresso.onView(withId(R.id.incognito_cct_logo_button)).check(matches(isDisplayed())); + Espresso.onView(withId(R.id.incognito_cct_logo_image_view)).check(matches(isDisplayed())); } @Test @@ -205,7 +205,8 @@ public void toolbarDoesNotHaveIncognitoLogo() throws Exception { Intent intent = createMinimalIncognitoCustomTabIntent(); launchIncognitoCustomTab(intent); - Espresso.onView(withId(R.id.incognito_cct_logo_button)).check(matches(not(isDisplayed()))); + Espresso.onView(withId(R.id.incognito_cct_logo_image_view)) + .check(matches(not(isDisplayed()))); } @Test
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java index 8101eec..96b2323a 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java
@@ -707,7 +707,7 @@ IntentFilter filter = new IntentFilter(Intent.ACTION_VIEW); filter.addDataScheme(Uri.parse(mTestServer.getURL("/")).getScheme()); final ActivityMonitor monitor = - InstrumentationRegistry.getInstrumentation().addMonitor(filter, null, false); + InstrumentationRegistry.getInstrumentation().addMonitor(filter, null, true); openAppMenuAndAssertMenuShown(); PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> { MenuItem item =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTestRule.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTestRule.java index ff48c21..e832ecf 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTestRule.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTestRule.java
@@ -4,29 +4,20 @@ package org.chromium.chrome.browser.customtabs; -import android.app.Activity; import android.content.Intent; -import android.support.test.InstrumentationRegistry; -import org.hamcrest.Matchers; +import androidx.annotation.NonNull; + import org.junit.Assert; -import org.chromium.base.ApplicationStatus; import org.chromium.base.FeatureList; -import org.chromium.base.test.util.CallbackHelper; -import org.chromium.base.test.util.Criteria; -import org.chromium.base.test.util.CriteriaHelper; import org.chromium.base.test.util.ScalableTimeout; -import org.chromium.chrome.browser.DeferredStartupHandler; import org.chromium.chrome.browser.flags.ChromeFeatureList; -import org.chromium.chrome.browser.tab.EmptyTabObserver; import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tab.TabTestUtils; import org.chromium.chrome.test.ChromeActivityTestRule; import java.util.Collections; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; /** * Custom ActivityTestRule for all instrumentation tests that require a {@link CustomTabActivity}. @@ -54,29 +45,13 @@ } @Override - public void startActivityCompletely(Intent intent) { + public void launchActivity(@NonNull Intent intent) { if (!FeatureList.hasTestFeatures()) { FeatureList.setTestFeatures( Collections.singletonMap(ChromeFeatureList.SHARE_BY_DEFAULT_IN_CCT, true)); } putCustomTabIdInIntent(intent); - int currentIntentId = getCustomTabIdFromIntent(intent); - - Activity activity = InstrumentationRegistry.getInstrumentation().startActivitySync(intent); - Assert.assertNotNull("Main activity did not start", activity); - CriteriaHelper.pollUiThread(() -> { - for (Activity runningActivity : ApplicationStatus.getRunningActivities()) { - if (runningActivity instanceof CustomTabActivity) { - CustomTabActivity customTabActivity = (CustomTabActivity) runningActivity; - final int customTabIdInActivity = - getCustomTabIdFromIntent(customTabActivity.getIntent()); - if (currentIntentId != customTabIdInActivity) continue; - setActivity(customTabActivity); - return true; - } - } - return false; - }); + super.launchActivity(intent); } /** @@ -84,33 +59,8 @@ * initialized. */ public void startCustomTabActivityWithIntent(Intent intent) { - DeferredStartupHandler.setExpectingActivityStartupForTesting(); startActivityCompletely(intent); - waitForActivityNativeInitializationComplete(); - CriteriaHelper.pollUiThread(() -> { - Criteria.checkThat(getActivity().getActivityTab(), Matchers.notNullValue()); - }); final Tab tab = getActivity().getActivityTab(); - final CallbackHelper pageLoadFinishedHelper = new CallbackHelper(); - tab.addObserver(new EmptyTabObserver() { - @Override - public void onLoadStopped(Tab tab, boolean toDifferentDocument) { - pageLoadFinishedHelper.notifyCalled(); - } - }); - try { - if (tab.isLoading()) { - pageLoadFinishedHelper.waitForCallback( - 0, 1, LONG_TIMEOUT_MS, TimeUnit.MILLISECONDS); - } - } catch (TimeoutException e) { - Assert.fail(); - } - Assert.assertTrue("Deferred startup never completed", - DeferredStartupHandler.waitForDeferredStartupCompleteForTesting( - STARTUP_TIMEOUT_MS)); - Assert.assertNotNull(tab); - Assert.assertNotNull(tab.getView()); Assert.assertTrue(TabTestUtils.isCustomTab(tab)); } }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabExternalNavigationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabExternalNavigationTest.java index 7a6fbb1a..a39d907 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabExternalNavigationTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabExternalNavigationTest.java
@@ -27,6 +27,7 @@ import org.chromium.chrome.browser.tab.TabTestUtils; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.components.external_intents.ExternalNavigationHandler; +import org.chromium.components.external_intents.ExternalNavigationHandler.OverrideUrlLoadingResult; import org.chromium.components.external_intents.ExternalNavigationHandler.OverrideUrlLoadingResultType; import org.chromium.components.external_intents.ExternalNavigationParams; import org.chromium.net.test.EmbeddedTestServer; @@ -107,9 +108,9 @@ final String testUrl = "customtab://customtabtest/intent"; ExternalNavigationParams params = new ExternalNavigationParams.Builder(testUrl, false) .build(); - @OverrideUrlLoadingResultType - int result = mUrlHandler.shouldOverrideUrlLoading(params); - Assert.assertEquals(OverrideUrlLoadingResultType.OVERRIDE_WITH_EXTERNAL_INTENT, result); + OverrideUrlLoadingResult result = mUrlHandler.shouldOverrideUrlLoading(params); + Assert.assertEquals( + OverrideUrlLoadingResultType.OVERRIDE_WITH_EXTERNAL_INTENT, result.getResultType()); Assert.assertTrue("A dummy activity should have been started to handle the special url.", mNavigationDelegate.hasExternalActivityStarted()); } @@ -124,9 +125,8 @@ final String testUrl = "http://customtabtest.com"; ExternalNavigationParams params = new ExternalNavigationParams.Builder(testUrl, false) .build(); - @OverrideUrlLoadingResultType - int result = mUrlHandler.shouldOverrideUrlLoading(params); - Assert.assertEquals(OverrideUrlLoadingResultType.NO_OVERRIDE, result); + OverrideUrlLoadingResult result = mUrlHandler.shouldOverrideUrlLoading(params); + Assert.assertEquals(OverrideUrlLoadingResultType.NO_OVERRIDE, result.getResultType()); Assert.assertFalse("External activities should not be started to handle the url", mNavigationDelegate.hasExternalActivityStarted()); }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabFromChromeExternalNavigationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabFromChromeExternalNavigationTest.java index a07414a0..3821874 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabFromChromeExternalNavigationTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabFromChromeExternalNavigationTest.java
@@ -111,8 +111,7 @@ @Test @Feature("CustomTabFromChrome") @LargeTest - public void - testIntentWithRedirectToApp() { + public void testIntentWithRedirectToApp() { final String redirectUrl = "https://maps.google.com/maps?q=1600+amphitheatre+parkway"; final String initialUrl = mServerRule.getServer().getURL("/chrome/test/data/android/redirect/js_redirect.html" @@ -123,7 +122,7 @@ + Base64.encodeToString( ApiCompatibilityUtils.getBytesUtf8(redirectUrl), Base64.URL_SAFE)); - mActivityRule.startActivityCompletely(getCustomTabFromChromeIntent(initialUrl, true)); + mActivityRule.launchActivity(getCustomTabFromChromeIntent(initialUrl, true)); mActivityRule.waitForActivityNativeInitializationComplete(); final AtomicReference<InterceptNavigationDelegateImpl> navigationDelegate =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/display_cutout/DisplayCutoutTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/display_cutout/DisplayCutoutTest.java index 0899713..af9727f 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/display_cutout/DisplayCutoutTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/display_cutout/DisplayCutoutTest.java
@@ -9,12 +9,10 @@ import androidx.test.filters.LargeTest; -import org.junit.After; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; -import org.chromium.base.test.util.ApplicationTestUtils; import org.chromium.base.test.util.Batch; import org.chromium.base.test.util.CommandLineFlags; import org.chromium.base.test.util.MinAndroidSdkLevel; @@ -37,11 +35,6 @@ public DisplayCutoutTestRule mTestRule = new DisplayCutoutTestRule<ChromeActivity>(ChromeActivity.class); - @After - public void tearDown() throws Exception { - ApplicationTestUtils.finishActivity(mTestRule.getActivity()); - } - /** * Test that no safe area is applied when we have viewport fit auto */
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 3dc82eb..cc76495e 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
@@ -13,6 +13,7 @@ import android.net.Uri; import android.os.SystemClock; import android.support.test.InstrumentationRegistry; +import android.support.test.runner.lifecycle.Stage; import android.text.TextUtils; import android.util.Base64; @@ -28,10 +29,14 @@ import org.junit.runner.RunWith; import org.chromium.base.ApiCompatibilityUtils; +import org.chromium.base.ContextUtils; +import org.chromium.base.test.util.ApplicationTestUtils; import org.chromium.base.test.util.CallbackHelper; 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.ScalableTimeout; +import org.chromium.chrome.browser.ChromeTabbedActivity; import org.chromium.chrome.browser.document.ChromeLauncherActivity; import org.chromium.chrome.browser.flags.ChromeSwitches; import org.chromium.chrome.browser.tab.EmptyTabObserver; @@ -424,24 +429,36 @@ @Test @SmallTest - public void testRedirectionFromIntent() { - // Test cold-start. + public void testRedirectionFromIntentCold() throws Exception { + Context context = ContextUtils.getApplicationContext(); Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(mTestServer.getURL(NAVIGATION_FROM_JAVA_REDIRECTION_PAGE))); - Context targetContext = InstrumentationRegistry.getTargetContext(); - intent.setClassName(targetContext, ChromeLauncherActivity.class.getName()); + intent.setClassName(context, ChromeLauncherActivity.class.getName()); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - InstrumentationRegistry.getInstrumentation().startActivitySync(intent); + + ChromeTabbedActivity activity = ApplicationTestUtils.waitForActivityWithClass( + ChromeTabbedActivity.class, Stage.CREATED, () -> context.startActivity(intent)); + mActivityTestRule.setActivity(activity); + + CriteriaHelper.pollUiThread(() -> { + Criteria.checkThat(mActivityMonitor.getHits(), Matchers.is(1)); + }, ScalableTimeout.scaleTimeout(10000L), CriteriaHelper.DEFAULT_POLLING_INTERVAL); + ApplicationTestUtils.waitForActivityState(activity, Stage.STOPPED); + } + + @Test + @SmallTest + public void testRedirectionFromIntentWarm() throws Exception { + Context context = ContextUtils.getApplicationContext(); + mActivityTestRule.startMainActivityOnBlankPage(); + Intent intent = new Intent(Intent.ACTION_VIEW, + Uri.parse(mTestServer.getURL(NAVIGATION_FROM_JAVA_REDIRECTION_PAGE))); + intent.setClassName(context, ChromeLauncherActivity.class.getName()); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + context.startActivity(intent); CriteriaHelper.pollUiThread( () -> Criteria.checkThat(mActivityMonitor.getHits(), Matchers.is(1))); - - // Test warm start. - mActivityTestRule.startMainActivityOnBlankPage(); - targetContext.startActivity(intent); - - CriteriaHelper.pollUiThread( - () -> Criteria.checkThat(mActivityMonitor.getHits(), Matchers.is(2))); } @Test @@ -489,7 +506,6 @@ String originalUrl = mTestServer.getURL(NAVIGATION_TO_FILE_SCHEME_FROM_INTENT_URI); loadUrlAndWaitForIntentUrl(originalUrl, true, false, false, null, false, "null_scheme"); } - @Test @LargeTest public void testIntentURIWithEmptySchemeDoesNothing() throws TimeoutException {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/homepage/HomepagePolicyIntegrationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/homepage/HomepagePolicyIntegrationTest.java index 7934a16..3579486 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/homepage/HomepagePolicyIntegrationTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/homepage/HomepagePolicyIntegrationTest.java
@@ -16,6 +16,7 @@ import org.junit.Before; import org.junit.Rule; import org.junit.Test; +import org.junit.rules.RuleChain; import org.junit.runner.RunWith; import org.chromium.base.ActivityState; @@ -64,12 +65,16 @@ private EmbeddedTestServer mTestServer; - @Rule public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule(); - @Rule public SettingsActivityTestRule<HomepageSettings> mSettingsActivityTestRule = new SettingsActivityTestRule<>(HomepageSettings.class); + // SettingsActivity has to be finished before the outer CTA can be finished or trying to finish + // CTA won't work. + @Rule + public final RuleChain mRuleChain = + RuleChain.outerRule(mActivityTestRule).around(mSettingsActivityTestRule); + @Rule public HomepageTestRule mHomepageTestRule = new HomepageTestRule();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/homepage/settings/HomepageSettingsFragmentTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/homepage/settings/HomepageSettingsFragmentTest.java index 703521dd..a273db8 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/homepage/settings/HomepageSettingsFragmentTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/homepage/settings/HomepageSettingsFragmentTest.java
@@ -14,6 +14,7 @@ import org.junit.Test; import org.junit.runner.RunWith; +import org.chromium.base.test.util.ApplicationTestUtils; import org.chromium.base.test.util.CriteriaHelper; import org.chromium.base.test.util.Feature; import org.chromium.base.test.util.UserActionTester; @@ -104,9 +105,8 @@ Assert.assertNotNull("Custom URI radio button is null.", mCustomUriRadioButton); } - private void finishSettingsActivity() { - mTestRule.getActivity().finish(); - mTestRule.waitTillActivityIsDestroyed(); + private void finishSettingsActivity() throws Exception { + ApplicationTestUtils.finishActivity(mTestRule.getActivity()); } @Test @@ -394,7 +394,7 @@ @Test @SmallTest @Feature({"Homepage"}) - public void testCheckRadioButtons() { + public void testCheckRadioButtons() throws Exception { mHomepageTestRule.useCustomizedHomepageForTest(TEST_URL_FOO); launchSettingsActivity(); LocationChangedCounter counter = new LocationChangedCounter(); @@ -446,7 +446,7 @@ @Test @SmallTest @Feature({"Homepage"}) - public void testChangeCustomized() { + public void testChangeCustomized() throws Exception { mHomepageTestRule.useChromeNTPForTest(); launchSettingsActivity(); LocationChangedCounter actionCounter = new LocationChangedCounter();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/metrics/StartupLoadingMetricsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/metrics/StartupLoadingMetricsTest.java index 5c0af74..98254843 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/metrics/StartupLoadingMetricsTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/metrics/StartupLoadingMetricsTest.java
@@ -218,7 +218,7 @@ // mSlowPage will hang for 2 seconds before sending a response. It should be enough to // put Chrome in background before the page is committed. mTabbedActivityTestRule.prepareUrlIntent(intent, mSlowPage); - mTabbedActivityTestRule.startActivityCompletely(intent); + mTabbedActivityTestRule.launchActivity(intent); // Put Chrome in background before the page is committed. ChromeApplicationTestUtils.fireHomeScreenIntent(
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/indicator/OfflineIndicatorControllerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/indicator/OfflineIndicatorControllerTest.java index cdbf6b55..8c2cbab 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/indicator/OfflineIndicatorControllerTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/offlinepages/indicator/OfflineIndicatorControllerTest.java
@@ -250,6 +250,7 @@ // Offline indicator should not be shown. checkOfflineIndicatorVisibility(downloadActivity, false); + downloadActivity.finish(); } @Test
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/voice/AssistantVoiceSearchConsentUiTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/voice/AssistantVoiceSearchConsentUiTest.java index 4485b232..012b466 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/voice/AssistantVoiceSearchConsentUiTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/voice/AssistantVoiceSearchConsentUiTest.java
@@ -13,6 +13,8 @@ import static org.chromium.chrome.browser.preferences.ChromePreferenceKeys.ASSISTANT_VOICE_SEARCH_ENABLED; +import android.support.test.runner.lifecycle.Stage; + import androidx.test.filters.MediumTest; import org.junit.After; @@ -26,6 +28,7 @@ import org.mockito.junit.MockitoRule; import org.chromium.base.Callback; +import org.chromium.base.test.util.ApplicationTestUtils; import org.chromium.base.test.util.CommandLineFlags; import org.chromium.base.test.util.Criteria; import org.chromium.base.test.util.CriteriaHelper; @@ -33,6 +36,7 @@ import org.chromium.chrome.browser.ChromeTabbedActivity; import org.chromium.chrome.browser.flags.ChromeSwitches; import org.chromium.chrome.browser.preferences.SharedPreferencesManager; +import org.chromium.chrome.browser.settings.SettingsActivity; import org.chromium.chrome.browser.settings.SettingsLauncherImpl; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.chrome.test.ChromeTabbedActivityTestRule; @@ -130,16 +134,19 @@ public void testDialogInteractivity_LearnMoreButton() { showConsentUi(); - TestThreadUtils.runOnUiThreadBlocking(() -> { - ClickUtils.clickButton(mAssistantVoiceSearchConsentUi.getContentView().findViewById( - R.id.avs_consent_ui_learn_more)); - mBottomSheetTestSupport.endAllAnimations(); - }); + SettingsActivity activity = ApplicationTestUtils.waitForActivityWithClass( + SettingsActivity.class, Stage.RESUMED, () -> { + ClickUtils.clickButton( + mAssistantVoiceSearchConsentUi.getContentView().findViewById( + R.id.avs_consent_ui_learn_more)); + mBottomSheetTestSupport.endAllAnimations(); + }); onView(withText(mActivityTestRule.getActivity().getResources().getString( R.string.avs_setting_category_title))) .check(matches(isDisplayed())); Mockito.verify(mCallback, Mockito.times(0)).onResult(/* meaningless value */ true); + activity.finish(); } @Test @@ -156,4 +163,4 @@ }); Mockito.verify(mCallback, Mockito.timeout(1000)).onResult(false); } -} \ No newline at end of file +}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/page_info/PageInfoViewTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/page_info/PageInfoViewTest.java index 61515dd..419276e 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/page_info/PageInfoViewTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/page_info/PageInfoViewTest.java
@@ -108,7 +108,7 @@ private void loadUrlAndOpenPageInfo(String url) { mActivityTestRule.loadUrl(url); - onView(withId(R.id.location_bar_status_icon)).perform(click()); + onViewWaiting(allOf(withId(R.id.location_bar_status_icon), isDisplayed())).perform(click()); } private View getPageInfoView() { @@ -187,8 +187,6 @@ // Choose a fixed, "random" port to create stable screenshots. mTestServerRule.setServerPort(424242); mTestServerRule.setServerUsesHttps(true); - - mActivityTestRule.startMainActivityOnBlankPage(); } @After @@ -212,6 +210,7 @@ @Feature({"RenderTest"}) @Features.DisableFeatures(PageInfoFeatureList.PAGE_INFO_V2) public void testShowOnInsecureHttpWebsite() throws IOException { + mActivityTestRule.startMainActivityOnBlankPage(); mTestServerRule.setServerUsesHttps(false); loadUrlAndOpenPageInfo(mTestServerRule.getServer().getURL(sSimpleHtml)); mRenderTestRule.render(getPageInfoView(), "PageInfo_HttpWebsite"); @@ -225,6 +224,7 @@ @Feature({"RenderTest"}) @Features.DisableFeatures(PageInfoFeatureList.PAGE_INFO_V2) public void testShowOnSecureWebsite() throws IOException { + mActivityTestRule.startMainActivityOnBlankPage(); loadUrlAndOpenPageInfo(mTestServerRule.getServer().getURL(sSimpleHtml)); mRenderTestRule.render(getPageInfoView(), "PageInfo_SecureWebsite"); } @@ -238,6 +238,7 @@ @DisabledTest(message = "https://crbug.com/1133770") @Features.DisableFeatures(PageInfoFeatureList.PAGE_INFO_V2) public void testShowOnExpiredCertificateWebsite() throws IOException { + mActivityTestRule.startMainActivityOnBlankPage(); mTestServerRule.setCertificateType(ServerCertificate.CERT_EXPIRED); loadUrlAndOpenPageInfo(mTestServerRule.getServer().getURL(sSimpleHtml)); mRenderTestRule.render(getPageInfoView(), "PageInfo_ExpiredCertWebsite"); @@ -251,6 +252,7 @@ @Feature({"RenderTest"}) @Features.DisableFeatures(PageInfoFeatureList.PAGE_INFO_V2) public void testChromePage() throws IOException { + mActivityTestRule.startMainActivityOnBlankPage(); loadUrlAndOpenPageInfo("chrome://version/"); mRenderTestRule.render(getPageInfoView(), "PageInfo_InternalSite"); } @@ -264,6 +266,7 @@ @Feature({"RenderTest"}) @Features.DisableFeatures(PageInfoFeatureList.PAGE_INFO_V2) public void testShowWithPermissions() throws IOException { + mActivityTestRule.startMainActivityOnBlankPage(); mIsSystemLocationSettingEnabled = false; addSomePermissions(mTestServerRule.getServer().getURL("/")); loadUrlAndOpenPageInfo(mTestServerRule.getServer().getURL(sSimpleHtml)); @@ -278,6 +281,7 @@ @Feature({"RenderTest"}) @Features.DisableFeatures(PageInfoFeatureList.PAGE_INFO_V2) public void testShowWithCookieBlocking() throws IOException { + mActivityTestRule.startMainActivityOnBlankPage(); setThirdPartyCookieBlocking(CookieControlsMode.BLOCK_THIRD_PARTY); loadUrlAndOpenPageInfo(mTestServerRule.getServer().getURL(sSimpleHtml)); mRenderTestRule.render(getPageInfoView(), "PageInfo_CookieBlocking"); @@ -291,6 +295,7 @@ @Feature({"RenderTest"}) @Features.DisableFeatures(PageInfoFeatureList.PAGE_INFO_V2) public void testShowWithPermissionsAndCookieBlocking() throws IOException { + mActivityTestRule.startMainActivityOnBlankPage(); addSomePermissions(mTestServerRule.getServer().getURL("/")); setThirdPartyCookieBlocking(CookieControlsMode.BLOCK_THIRD_PARTY); loadUrlAndOpenPageInfo(mTestServerRule.getServer().getURL(sSimpleHtml)); @@ -305,6 +310,7 @@ @Feature({"RenderTest"}) @Features.DisableFeatures(PageInfoFeatureList.PAGE_INFO_V2) public void testShowWithDefaultSettingPermissions() throws IOException { + mActivityTestRule.startMainActivityOnBlankPage(); addDefaultSettingPermissions(mTestServerRule.getServer().getURL("/")); loadUrlAndOpenPageInfo(mTestServerRule.getServer().getURL(sSimpleHtml)); mRenderTestRule.render(getPageInfoView(), "PageInfo_DefaultSettingPermissions"); @@ -318,6 +324,7 @@ @Feature({"RenderTest"}) @Features.EnableFeatures(PageInfoFeatureList.PAGE_INFO_V2) public void testShowOnSecureWebsiteV2() throws IOException { + mActivityTestRule.startMainActivityOnBlankPage(); loadUrlAndOpenPageInfo(mTestServerRule.getServer().getURL(sSimpleHtml)); mRenderTestRule.render(getPageInfoView(), "PageInfo_SecureWebsiteV2"); } @@ -346,6 +353,7 @@ @Feature({"RenderTest"}) @Features.EnableFeatures(PageInfoFeatureList.PAGE_INFO_V2) public void testShowConnectionInfoSubpage() throws IOException { + mActivityTestRule.startMainActivityOnBlankPage(); loadUrlAndOpenPageInfo(mTestServerRule.getServer().getURL(sSimpleHtml)); onView(withId(R.id.page_info_connection_row)).perform(click()); mRenderTestRule.render(getPageInfoView(), "PageInfo_ConnectionInfoSubpage"); @@ -359,6 +367,7 @@ @Feature({"RenderTest"}) @Features.EnableFeatures(PageInfoFeatureList.PAGE_INFO_V2) public void testShowPermissionsSubpage() throws IOException { + mActivityTestRule.startMainActivityOnBlankPage(); addSomePermissions(mTestServerRule.getServer().getURL("/")); loadUrlAndOpenPageInfo(mTestServerRule.getServer().getURL(sSimpleHtml)); onView(withId(R.id.page_info_permissions_row)).perform(click()); @@ -373,6 +382,7 @@ @Feature({"RenderTest"}) @Features.EnableFeatures(PageInfoFeatureList.PAGE_INFO_V2) public void testShowCookiesSubpage() throws IOException { + mActivityTestRule.startMainActivityOnBlankPage(); setThirdPartyCookieBlocking(CookieControlsMode.BLOCK_THIRD_PARTY); loadUrlAndOpenPageInfo(mTestServerRule.getServer().getURL(sSimpleHtml)); onView(withId(R.id.page_info_cookies_row)).perform(click()); @@ -387,6 +397,7 @@ @MediumTest @Features.EnableFeatures(PageInfoFeatureList.PAGE_INFO_V2) public void testNoPermissionsSubpage() throws IOException { + mActivityTestRule.startMainActivityOnBlankPage(); loadUrlAndOpenPageInfo(mTestServerRule.getServer().getURL(sSimpleHtml)); View dialog = (View) getPageInfoView().getParent(); onView(withId(R.id.page_info_permissions_row)) @@ -401,6 +412,7 @@ @Features.EnableFeatures(PageInfoFeatureList.PAGE_INFO_V2) @FlakyTest(message = "https://crbug.com/1147236") public void testClearCookiesOnSubpage() throws Exception { + mActivityTestRule.startMainActivityOnBlankPage(); mActivityTestRule.loadUrl(mTestServerRule.getServer().getURL(sSiteDataHtml)); // Create cookies. expectHasCookies(false); @@ -426,6 +438,7 @@ @MediumTest @Features.EnableFeatures(PageInfoFeatureList.PAGE_INFO_V2) public void testResetPermissionsOnSubpage() throws Exception { + mActivityTestRule.startMainActivityOnBlankPage(); mActivityTestRule.loadUrl(mTestServerRule.getServer().getURL(sSiteDataHtml)); String url = mTestServerRule.getServer().getURL("/"); // Create permissions. @@ -453,6 +466,7 @@ @MediumTest @Features.EnableFeatures(PageInfoFeatureList.PAGE_INFO_V2) public void testPaintPreview() { + mActivityTestRule.startMainActivityOnBlankPage(); TestThreadUtils.runOnUiThreadBlocking(() -> { final ChromeActivity activity = mActivityTestRule.getActivity(); final Tab tab = activity.getActivityTab();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestTestRule.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestTestRule.java index 3b5375ab2..2c90ae80 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestTestRule.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestTestRule.java
@@ -1245,6 +1245,7 @@ @Override public void create(PaymentAppFactoryDelegate delegate) { Runnable createApp = () -> { + if (delegate.getParams().hasClosed()) return; boolean canMakePayment = delegate.getParams().getMethodData().containsKey(mAppMethodName); delegate.onCanMakePaymentCalculated(canMakePayment);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/settings/MainSettingsFragmentTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/settings/MainSettingsFragmentTest.java index aa1888d..947221f 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/settings/MainSettingsFragmentTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/settings/MainSettingsFragmentTest.java
@@ -15,6 +15,7 @@ import static org.mockito.Mockito.verify; import android.app.Activity; +import android.support.test.InstrumentationRegistry; import android.text.TextUtils; import android.view.View; @@ -101,7 +102,7 @@ private final SyncTestRule mSyncTestRule = new SyncTestRule(); private final SettingsActivityTestRule<MainSettings> mSettingsActivityTestRule = - new SettingsActivityTestRule<>(MainSettings.class, true); + new SettingsActivityTestRule<>(MainSettings.class); // SettingsActivity needs to be initialized and destroyed with the mock // signin environment setup in SyncTestRule @@ -133,6 +134,7 @@ @Before public void setup() { MockitoAnnotations.initMocks(this); + InstrumentationRegistry.getInstrumentation().setInTouchMode(true); PasswordCheckFactory.setPasswordCheckForTesting(mPasswordCheck); SigninActivityLauncherImpl.setLauncherForTest(mMockSigninActivityLauncherImpl); DeveloperSettings.setIsEnabledForTests(true);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/AccountPickerBottomSheetRenderTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/AccountPickerBottomSheetRenderTest.java index 516bc1db0..67834235 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/AccountPickerBottomSheetRenderTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/AccountPickerBottomSheetRenderTest.java
@@ -22,7 +22,6 @@ import androidx.recyclerview.widget.RecyclerView; import androidx.test.filters.MediumTest; -import org.junit.After; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; @@ -34,7 +33,6 @@ import org.chromium.base.Callback; import org.chromium.base.test.params.ParameterAnnotations; import org.chromium.base.test.params.ParameterizedRunner; -import org.chromium.base.test.util.ApplicationTestUtils; import org.chromium.base.test.util.Batch; import org.chromium.base.test.util.CommandLineFlags; import org.chromium.base.test.util.CriteriaHelper; @@ -120,11 +118,6 @@ mActivityTestRule.startMainActivityOnBlankPage(); } - @After - public void tearDown() throws Exception { - ApplicationTestUtils.finishActivity(mActivityTestRule.getActivity()); - } - @AfterClass public static void tearDownAfterActivityDestroyed() { ChromeNightModeTestUtils.tearDownNightModeAfterChromeActivityDestroyed();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/site_settings/ManageSpaceActivityTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/site_settings/ManageSpaceActivityTest.java index 16095c4..5383798 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/site_settings/ManageSpaceActivityTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/site_settings/ManageSpaceActivityTest.java
@@ -100,7 +100,7 @@ @Test @SmallTest public void testLaunchActivity() { - startManageSpaceActivity(); + startManageSpaceActivity().finish(); } @Test
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/sync/AccountManagementFragmentTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/sync/AccountManagementFragmentTest.java index b42cd0d..d0a1c47 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/sync/AccountManagementFragmentTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/sync/AccountManagementFragmentTest.java
@@ -18,6 +18,7 @@ import org.junit.Before; import org.junit.Rule; import org.junit.Test; +import org.junit.rules.RuleChain; import org.junit.runner.RunWith; import org.chromium.base.test.util.CommandLineFlags; @@ -40,14 +41,18 @@ @RunWith(ChromeJUnit4ClassRunner.class) @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) public class AccountManagementFragmentTest { - @Rule public final SettingsActivityTestRule<AccountManagementFragment> mSettingsActivityTestRule = new SettingsActivityTestRule<>(AccountManagementFragment.class); - @Rule public final ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule(); + // SettingsActivity has to be finished before the outer CTA can be finished or trying to finish + // CTA won't work. + @Rule + public final RuleChain mRuleChain = + RuleChain.outerRule(mActivityTestRule).around(mSettingsActivityTestRule); + @Rule public final AccountManagerTestRule mAccountManagerTestRule = new AccountManagerTestRule();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/sync/GoogleServicesSettingsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/sync/GoogleServicesSettingsTest.java index dc9d76a..9b38421 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/sync/GoogleServicesSettingsTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/sync/GoogleServicesSettingsTest.java
@@ -16,6 +16,7 @@ import org.junit.Before; import org.junit.Rule; import org.junit.Test; +import org.junit.rules.RuleChain; import org.junit.runner.RunWith; import org.chromium.base.test.util.CommandLineFlags; @@ -51,13 +52,17 @@ @Rule public final AccountManagerTestRule mAccountManagerTestRule = new AccountManagerTestRule(); - @Rule public final ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule(); - @Rule public final SettingsActivityTestRule<GoogleServicesSettings> mSettingsActivityTestRule = - new SettingsActivityTestRule<>(GoogleServicesSettings.class, true); + new SettingsActivityTestRule<>(GoogleServicesSettings.class); + + // SettingsActivity has to be finished before the outer CTA can be finished or trying to finish + // CTA won't work. + @Rule + public final RuleChain mRuleChain = + RuleChain.outerRule(mActivityTestRule).around(mSettingsActivityTestRule); @Before public void setUp() {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/sync/ManageSyncSettingsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/sync/ManageSyncSettingsTest.java index 9c90fe6..2acd095 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/sync/ManageSyncSettingsTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/sync/ManageSyncSettingsTest.java
@@ -90,7 +90,7 @@ private final SyncTestRule mSyncTestRule = new SyncTestRule(); private final SettingsActivityTestRule<ManageSyncSettings> mSettingsActivityTestRule = - new SettingsActivityTestRule<>(ManageSyncSettings.class, true); + new SettingsActivityTestRule<>(ManageSyncSettings.class); // SettingsActivity needs to be initialized and destroyed with the mock // signin environment setup in SyncTestRule
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/sync/SyncErrorCardPreferenceTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/sync/SyncErrorCardPreferenceTest.java index 76da0b0..559a75f 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/sync/SyncErrorCardPreferenceTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/sync/SyncErrorCardPreferenceTest.java
@@ -62,7 +62,7 @@ @Rule public final SettingsActivityTestRule<ManageSyncSettings> mSettingsActivityTestRule = - new SettingsActivityTestRule<>(ManageSyncSettings.class, true); + new SettingsActivityTestRule<>(ManageSyncSettings.class); @Rule public final ChromeRenderTestRule mRenderTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/sync/SyncTestRule.java b/chrome/android/javatests/src/org/chromium/chrome/browser/sync/SyncTestRule.java index cfd5d948..458cdfa 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/sync/SyncTestRule.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/sync/SyncTestRule.java
@@ -4,6 +4,12 @@ package org.chromium.chrome.browser.sync; +import static androidx.test.espresso.Espresso.onView; +import static androidx.test.espresso.action.ViewActions.click; +import static androidx.test.espresso.matcher.ViewMatchers.hasDescendant; +import static androidx.test.espresso.matcher.ViewMatchers.withId; +import static androidx.test.espresso.matcher.ViewMatchers.withText; + import android.app.Activity; import android.app.PendingIntent; import android.content.Context; @@ -13,6 +19,7 @@ import androidx.annotation.Nullable; import androidx.preference.TwoStatePreference; +import androidx.test.espresso.contrib.RecyclerViewActions; import org.junit.Assert; import org.junit.runner.Description; @@ -31,6 +38,7 @@ import org.chromium.chrome.test.util.browser.signin.AccountManagerTestRule; import org.chromium.chrome.test.util.browser.signin.SigninTestUtil; import org.chromium.chrome.test.util.browser.sync.SyncTestUtil; +import org.chromium.components.browser_ui.widget.R; import org.chromium.components.signin.base.CoreAccountInfo; import org.chromium.components.sync.ModelType; import org.chromium.components.sync.protocol.AutofillWalletSpecifics; @@ -410,12 +418,9 @@ // UI interaction convenience methods. public void togglePreference(final TwoStatePreference pref) { - TestThreadUtils.runOnUiThreadBlocking(() -> { - boolean newValue = !pref.isChecked(); - pref.getOnPreferenceChangeListener().onPreferenceChange(pref, newValue); - pref.setChecked(newValue); - }); - InstrumentationRegistry.getInstrumentation().waitForIdleSync(); + onView(withId(R.id.recycler_view)) + .perform(RecyclerViewActions.actionOnItem( + hasDescendant(withText(pref.getTitle().toString())), click())); } /**
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tab/InterceptNavigationDelegateTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tab/InterceptNavigationDelegateTest.java index 41f76677..ba3b0bbc 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/tab/InterceptNavigationDelegateTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tab/InterceptNavigationDelegateTest.java
@@ -76,10 +76,9 @@ } @Override - public @OverrideUrlLoadingResultType int shouldOverrideUrlLoading( - ExternalNavigationParams params) { + public OverrideUrlLoadingResult shouldOverrideUrlLoading(ExternalNavigationParams params) { mExternalNavParamHistory.add(params); - return OverrideUrlLoadingResultType.NO_OVERRIDE; + return OverrideUrlLoadingResult.forNoOverride(); } }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tab/state/LevelDBPersistedTabDataStorageFactoryTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tab/state/LevelDBPersistedTabDataStorageFactoryTest.java index 2611d9a5..c715a63 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/tab/state/LevelDBPersistedTabDataStorageFactoryTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tab/state/LevelDBPersistedTabDataStorageFactoryTest.java
@@ -64,9 +64,11 @@ LevelDBPersistedTabDataStorage.setSkipNativeAssertionsForTesting(true); } + @UiThreadTest @SmallTest @Test public void testFactoryMethod() { + Profile realProfile = Profile.getLastUsedRegularProfile(); LevelDBPersistedTabDataStorageFactory factory = new LevelDBPersistedTabDataStorageFactory(); Profile.setLastUsedProfileForTesting(mProfile1); LevelDBPersistedTabDataStorage profile1Storage = factory.create(); @@ -76,6 +78,8 @@ LevelDBPersistedTabDataStorage profile1StorageAgain = factory.create(); Assert.assertEquals(profile1Storage, profile1StorageAgain); Assert.assertNotEquals(profile1Storage, profile2Storage); + // Restore the original profile so the Activity can shut down correctly. + Profile.setLastUsedProfileForTesting(realProfile); } @UiThreadTest
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tasks/ReturnToChromeTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tasks/ReturnToChromeTest.java index 12907e88..cf1a94e0 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/tasks/ReturnToChromeTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tasks/ReturnToChromeTest.java
@@ -597,7 +597,7 @@ intent.addCategory(Intent.CATEGORY_LAUNCHER); mActivityTestRule.prepareUrlIntent(intent, url); Assert.assertFalse(mInflated.get()); - mActivityTestRule.startActivityCompletely(intent); + mActivityTestRule.launchActivity(intent); if (mUseInstantStart) { CriteriaHelper.pollUiThread(mInflated::get); } else {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappNavigationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappNavigationTest.java index 33af8329..fc5fc02 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappNavigationTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebappNavigationTest.java
@@ -263,7 +263,7 @@ IntentFilter filter = new IntentFilter(Intent.ACTION_VIEW); filter.addDataScheme("https"); final ActivityMonitor monitor = - InstrumentationRegistry.getInstrumentation().addMonitor(filter, null, false); + InstrumentationRegistry.getInstrumentation().addMonitor(filter, null, true); RevampedContextMenuUtils.selectContextMenuItem(InstrumentationRegistry.getInstrumentation(), null /* activity to check for focus after click */,
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index 6facf83b..8e92d67 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -2277,7 +2277,6 @@ "//net", "//net:extras", "//ppapi/buildflags", - "//ppapi/host", "//printing", "//printing/buildflags", "//rlz/buildflags", @@ -5988,15 +5987,12 @@ "plugins/reload_plugin_infobar_delegate.h", "renderer_host/pepper/chrome_browser_pepper_host_factory.cc", "renderer_host/pepper/chrome_browser_pepper_host_factory.h", - "renderer_host/pepper/device_id_fetcher.cc", - "renderer_host/pepper/device_id_fetcher.h", "renderer_host/pepper/pepper_isolated_file_system_message_filter.cc", "renderer_host/pepper/pepper_isolated_file_system_message_filter.h", ] deps += [ "//components/pdf/browser", "//media:media_buildflags", - "//ppapi/buildflags", "//ppapi/host", "//ppapi/proxy:ipc", "//services/device/public/mojom",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index 774391e..fdbf07f 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -3685,6 +3685,10 @@ flag_descriptions::kImeAssistAutocorrectName, flag_descriptions::kImeAssistAutocorrectDescription, kOsCrOS, FEATURE_VALUE_TYPE(chromeos::features::kAssistAutoCorrect)}, + {"enable-cros-ime-assist-multi-word", + flag_descriptions::kImeAssistMultiWordName, + flag_descriptions::kImeAssistMultiWordDescription, kOsCrOS, + FEATURE_VALUE_TYPE(chromeos::features::kAssistMultiWord)}, {"enable-cros-ime-assist-personal-info", flag_descriptions::kImeAssistPersonalInfoName, flag_descriptions::kImeAssistPersonalInfoDescription, kOsCrOS,
diff --git a/chrome/browser/android/contextualsearch/contextual_search_delegate.cc b/chrome/browser/android/contextualsearch/contextual_search_delegate.cc index ee626e5..2754381 100644 --- a/chrome/browser/android/contextualsearch/contextual_search_delegate.cc +++ b/chrome/browser/android/contextualsearch/contextual_search_delegate.cc
@@ -77,7 +77,7 @@ const int kContextualSearchMaxSelection = 1000; const char kXssiEscape[] = ")]}'\n"; -const char kDiscourseContextHeaderPrefix[] = "X-Additional-Discourse-Context: "; +const char kDiscourseContextHeaderName[] = "X-Additional-Discourse-Context"; const char kDoPreventPreloadValue[] = "1"; const int kResponseCodeUninitialized = -1; @@ -162,8 +162,7 @@ // Populates the discourse context and adds it to the HTTP header of the // search term resolution request. - resource_request->headers.AddHeadersFromString( - GetDiscourseContext(*context_)); + resource_request->headers.CopyFrom(GetDiscourseContext(*context_)); // Disable cookies for this request. resource_request->credentials_mode = network::mojom::CredentialsMode::kOmit; @@ -396,7 +395,7 @@ selection_end); } -std::string ContextualSearchDelegate::GetDiscourseContext( +const net::HttpRequestHeaders ContextualSearchDelegate::GetDiscourseContext( const ContextualSearchContext& context) { discourse_context::ClientDiscourseContext proto; discourse_context::Display* display = proto.add_display(); @@ -419,7 +418,10 @@ // The server memoizer expects a web-safe encoding. std::replace(encoded_context.begin(), encoded_context.end(), '+', '-'); std::replace(encoded_context.begin(), encoded_context.end(), '/', '_'); - return kDiscourseContextHeaderPrefix + encoded_context; + + net::HttpRequestHeaders headers; + headers.SetHeader(kDiscourseContextHeaderName, encoded_context); + return headers; } // Decodes the given response from the search term resolution request and sets
diff --git a/chrome/browser/android/contextualsearch/contextual_search_delegate.h b/chrome/browser/android/contextualsearch/contextual_search_delegate.h index 4137d68e..5b21dca4 100644 --- a/chrome/browser/android/contextualsearch/contextual_search_delegate.h +++ b/chrome/browser/android/contextualsearch/contextual_search_delegate.h
@@ -17,6 +17,7 @@ #include "base/values.h" #include "chrome/browser/android/contextualsearch/contextual_search_context.h" #include "chrome/browser/android/contextualsearch/resolved_search_term.h" +#include "net/http/http_request_headers.h" namespace content { class WebContents; @@ -127,7 +128,8 @@ uint32_t end_offset); // Populates and returns the discourse context. - std::string GetDiscourseContext(const ContextualSearchContext& context); + const net::HttpRequestHeaders GetDiscourseContext( + const ContextualSearchContext& context); // Builds a Resolved Search Term by decoding the given JSON string. std::unique_ptr<ResolvedSearchTerm> GetResolvedSearchTermFromJson(
diff --git a/chrome/browser/autofill/autofill_browsertest.cc b/chrome/browser/autofill/autofill_browsertest.cc index bd93553a..b730d63 100644 --- a/chrome/browser/autofill/autofill_browsertest.cc +++ b/chrome/browser/autofill/autofill_browsertest.cc
@@ -117,11 +117,6 @@ // Don't want Keychain coming up on Mac. test::DisableSystemServices(browser()->profile()->GetPrefs()); - // Load the MatchingPattern definitions. - base::RunLoop run_loop; - field_type_parsing::PopulateFromResourceBundle(run_loop.QuitClosure()); - run_loop.Run(); - ASSERT_TRUE(embedded_test_server()->Start()); }
diff --git a/chrome/browser/autofill/autofill_interactive_uitest.cc b/chrome/browser/autofill/autofill_interactive_uitest.cc index b20f0ab..d3513ccd 100644 --- a/chrome/browser/autofill/autofill_interactive_uitest.cc +++ b/chrome/browser/autofill/autofill_interactive_uitest.cc
@@ -302,11 +302,6 @@ &AutofillInteractiveTestBase::HandleTestURL, base::Unretained(this))); embedded_test_server()->StartAcceptingConnections(); - // Load the MatchingPattern definitions. - base::RunLoop run_loop; - field_type_parsing::PopulateFromResourceBundle(run_loop.QuitClosure()); - run_loop.Run(); - // By default, all SSL cert checks are valid. Can be overriden in tests if // needed. cert_verifier_.mock_cert_verifier()->set_default_result(net::OK);
diff --git a/chrome/browser/autofill/form_structure_browsertest.cc b/chrome/browser/autofill/form_structure_browsertest.cc index ed3c554..5debbc4 100644 --- a/chrome/browser/autofill/form_structure_browsertest.cc +++ b/chrome/browser/autofill/form_structure_browsertest.cc
@@ -195,11 +195,6 @@ void FormStructureBrowserTest::SetUpOnMainThread() { InProcessBrowserTest::SetUpOnMainThread(); - // Load the MatchingPattern definitions. - base::RunLoop run_loop; - field_type_parsing::PopulateFromResourceBundle(run_loop.QuitClosure()); - run_loop.Run(); - embedded_test_server()->RegisterRequestHandler(base::BindRepeating( &FormStructureBrowserTest::HandleRequest, base::Unretained(this))); ASSERT_TRUE(embedded_test_server()->Start());
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc index 9c711e3..2b457739 100644 --- a/chrome/browser/chrome_content_browser_client.cc +++ b/chrome/browser/chrome_content_browser_client.cc
@@ -345,7 +345,6 @@ #include "net/ssl/ssl_cert_request_info.h" #include "pdf/buildflags.h" #include "ppapi/buildflags/buildflags.h" -#include "ppapi/host/ppapi_host.h" #include "printing/buildflags/buildflags.h" #include "sandbox/policy/features.h" #include "sandbox/policy/sandbox_type.h"
diff --git a/chrome/browser/chromeos/login/enrollment/auto_enrollment_check_screen.cc b/chrome/browser/chromeos/login/enrollment/auto_enrollment_check_screen.cc index 5eaca153..90f90cf 100644 --- a/chrome/browser/chromeos/login/enrollment/auto_enrollment_check_screen.cc +++ b/chrome/browser/chromeos/login/enrollment/auto_enrollment_check_screen.cc
@@ -30,13 +30,6 @@ } // namespace -// static -AutoEnrollmentCheckScreen* AutoEnrollmentCheckScreen::Get( - ScreenManager* manager) { - return static_cast<AutoEnrollmentCheckScreen*>( - manager->GetScreen(AutoEnrollmentCheckScreenView::kScreenId)); -} - AutoEnrollmentCheckScreen::AutoEnrollmentCheckScreen( AutoEnrollmentCheckScreenView* view, ErrorScreen* error_screen,
diff --git a/chrome/browser/chromeos/login/enrollment/auto_enrollment_check_screen.h b/chrome/browser/chromeos/login/enrollment/auto_enrollment_check_screen.h index ba5c9ff..fb29d7b 100644 --- a/chrome/browser/chromeos/login/enrollment/auto_enrollment_check_screen.h +++ b/chrome/browser/chromeos/login/enrollment/auto_enrollment_check_screen.h
@@ -21,7 +21,6 @@ namespace chromeos { class ErrorScreensHistogramHelper; -class ScreenManager; // Handles the control flow after OOBE auto-update completes to wait for the // enterprise auto-enrollment check that happens as part of OOBE. This includes @@ -33,13 +32,13 @@ public BaseScreen, public NetworkPortalDetector::Observer { public: + using TView = AutoEnrollmentCheckScreenView; + AutoEnrollmentCheckScreen(AutoEnrollmentCheckScreenView* view, ErrorScreen* error_screen, const base::RepeatingClosure& exit_callback); ~AutoEnrollmentCheckScreen() override; - static AutoEnrollmentCheckScreen* Get(ScreenManager* manager); - // Clears the cached state causing the forced enrollment check to be retried. void ClearState();
diff --git a/chrome/browser/chromeos/login/enrollment/enrollment_local_policy_server_browsertest.cc b/chrome/browser/chromeos/login/enrollment/enrollment_local_policy_server_browsertest.cc index 32aa1a5..181523ef 100644 --- a/chrome/browser/chromeos/login/enrollment/enrollment_local_policy_server_browsertest.cc +++ b/chrome/browser/chromeos/login/enrollment/enrollment_local_policy_server_browsertest.cc
@@ -112,8 +112,8 @@ AutoEnrollmentCheckScreen* auto_enrollment_screen() { EXPECT_NE(WizardController::default_controller(), nullptr); AutoEnrollmentCheckScreen* auto_enrollment_screen = - AutoEnrollmentCheckScreen::Get( - WizardController::default_controller()->screen_manager()); + WizardController::default_controller() + ->GetScreen<AutoEnrollmentCheckScreen>(); EXPECT_NE(auto_enrollment_screen, nullptr); return auto_enrollment_screen; }
diff --git a/chrome/browser/chromeos/login/wizard_controller.cc b/chrome/browser/chromeos/login/wizard_controller.cc index 75b4c77..9df1100 100644 --- a/chrome/browser/chromeos/login/wizard_controller.cc +++ b/chrome/browser/chromeos/login/wizard_controller.cc
@@ -832,8 +832,7 @@ } void WizardController::ShowAutoEnrollmentCheckScreen() { - AutoEnrollmentCheckScreen* screen = - AutoEnrollmentCheckScreen::Get(screen_manager()); + AutoEnrollmentCheckScreen* screen = GetScreen<AutoEnrollmentCheckScreen>(); if (retry_auto_enrollment_check_) screen->ClearState(); screen->set_auto_enrollment_controller(GetAutoEnrollmentController());
diff --git a/chrome/browser/chromeos/policy/dlp/data_transfer_dlp_controller_browsertest.cc b/chrome/browser/chromeos/policy/dlp/data_transfer_dlp_controller_browsertest.cc new file mode 100644 index 0000000..bef0996 --- /dev/null +++ b/chrome/browser/chromeos/policy/dlp/data_transfer_dlp_controller_browsertest.cc
@@ -0,0 +1,188 @@ +// // 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 <memory> + +#include "base/strings/string16.h" +#include "base/strings/utf_string_conversions.h" +#include "chrome/browser/chromeos/policy/dlp/data_transfer_dlp_controller.h" +#include "chrome/browser/chromeos/policy/dlp/dlp_rules_manager.h" +#include "chrome/browser/chromeos/policy/dlp/dlp_rules_manager_test_utils.h" +#include "chrome/browser/policy/policy_test_utils.h" +#include "chrome/test/base/in_process_browser_test.h" +#include "components/policy/core/common/policy_map.h" +#include "components/policy/policy_constants.h" +#include "content/public/test/browser_test.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "ui/base/clipboard/clipboard.h" +#include "ui/base/clipboard/clipboard_buffer.h" +#include "ui/base/clipboard/scoped_clipboard_writer.h" +#include "ui/base/data_transfer_policy/data_transfer_endpoint.h" +#include "url/origin.h" + +namespace policy { + +namespace { + +constexpr char kClipboardText[] = "Hello World"; + +} // namespace + +class DataTransferDlpBrowserTest : public PolicyTest { + public: + DataTransferDlpBrowserTest() = default; +}; + +IN_PROC_BROWSER_TEST_F(DataTransferDlpBrowserTest, EmptyPolicy) { + PolicyMap policies; + policies.Set(key::kDataLeakPreventionRulesList, POLICY_LEVEL_MANDATORY, + POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD, /*value=*/base::nullopt, + nullptr); + UpdateProviderPolicy(policies); + + { + ui::ScopedClipboardWriter writer(ui::ClipboardBuffer::kCopyPaste); + writer.WriteText(base::UTF8ToUTF16(kClipboardText)); + } + ui::DataTransferEndpoint data_dst( + url::Origin::Create(GURL("https://google.com"))); + base::string16 result; + ui::Clipboard::GetForCurrentThread()->ReadText( + ui::ClipboardBuffer::kCopyPaste, &data_dst, &result); + EXPECT_EQ(base::UTF8ToUTF16(kClipboardText), result); +} + +IN_PROC_BROWSER_TEST_F(DataTransferDlpBrowserTest, RestrictedUrl) { + const std::string kUrl1 = "https://mail.google.com"; + const std::string kUrl2 = "https://docs.google.com"; + const std::string kUrl3 = "https://example.com"; + + base::Value rules(base::Value::Type::LIST); + + base::Value src_urls1(base::Value::Type::LIST); + src_urls1.Append(kUrl1); + base::Value dst_urls1(base::Value::Type::LIST); + dst_urls1.Append("*"); + base::Value restrictions1(base::Value::Type::LIST); + restrictions1.Append(dlp_test_util::CreateRestrictionWithLevel( + dlp::kClipboardRestriction, dlp::kBlockLevel)); + rules.Append(dlp_test_util::CreateRule( + "rule #1", "Block Gmail", std::move(src_urls1), std::move(dst_urls1), + /*dst_components=*/base::Value(base::Value::Type::LIST), + std::move(restrictions1))); + + base::Value src_urls2(base::Value::Type::LIST); + src_urls2.Append(kUrl1); + base::Value dst_urls2(base::Value::Type::LIST); + dst_urls2.Append(kUrl2); + base::Value restrictions2(base::Value::Type::LIST); + restrictions2.Append(dlp_test_util::CreateRestrictionWithLevel( + dlp::kClipboardRestriction, dlp::kAllowLevel)); + rules.Append(dlp_test_util::CreateRule( + "rule #2", "Allow Gmail for work purposes", std::move(src_urls2), + std::move(dst_urls2), + /*dst_components=*/base::Value(base::Value::Type::LIST), + std::move(restrictions2))); + + PolicyMap policies; + policies.Set(key::kDataLeakPreventionRulesList, POLICY_LEVEL_MANDATORY, + POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD, std::move(rules), + nullptr); + UpdateProviderPolicy(policies); + + { + ui::ScopedClipboardWriter writer(ui::ClipboardBuffer::kCopyPaste, + std::make_unique<ui::DataTransferEndpoint>( + url::Origin::Create(GURL(kUrl1)))); + writer.WriteText(base::UTF8ToUTF16(kClipboardText)); + } + ui::DataTransferEndpoint data_dst1(url::Origin::Create(GURL(kUrl1))); + base::string16 result1; + ui::Clipboard::GetForCurrentThread()->ReadText( + ui::ClipboardBuffer::kCopyPaste, &data_dst1, &result1); + EXPECT_EQ(base::UTF8ToUTF16(kClipboardText), result1); + + ui::DataTransferEndpoint data_dst2(url::Origin::Create(GURL(kUrl2))); + base::string16 result2; + ui::Clipboard::GetForCurrentThread()->ReadText( + ui::ClipboardBuffer::kCopyPaste, &data_dst2, &result2); + EXPECT_EQ(base::UTF8ToUTF16(kClipboardText), result2); + + ui::DataTransferEndpoint data_dst3(url::Origin::Create(GURL(kUrl3))); + base::string16 result3; + ui::Clipboard::GetForCurrentThread()->ReadText( + ui::ClipboardBuffer::kCopyPaste, &data_dst3, &result3); + EXPECT_EQ(base::string16(), result3); + + { + ui::ScopedClipboardWriter writer(ui::ClipboardBuffer::kCopyPaste, + std::make_unique<ui::DataTransferEndpoint>( + url::Origin::Create(GURL(kUrl3)))); + writer.WriteText(base::UTF8ToUTF16(kClipboardText)); + } + ui::DataTransferEndpoint data_dst4(url::Origin::Create(GURL(kUrl1))); + base::string16 result4; + ui::Clipboard::GetForCurrentThread()->ReadText( + ui::ClipboardBuffer::kCopyPaste, &data_dst1, &result4); + EXPECT_EQ(base::UTF8ToUTF16(kClipboardText), result4); +} + +IN_PROC_BROWSER_TEST_F(DataTransferDlpBrowserTest, RestrictedComponent) { + const std::string kUrl1 = "https://mail.google.com"; + + base::Value rules(base::Value::Type::LIST); + + base::Value src_urls(base::Value::Type::LIST); + src_urls.Append(kUrl1); + base::Value dst_components(base::Value::Type::LIST); + dst_components.Append(dlp::kArc); + dst_components.Append(dlp::kPluginVm); + base::Value restrictions(base::Value::Type::LIST); + restrictions.Append(dlp_test_util::CreateRestrictionWithLevel( + dlp::kClipboardRestriction, dlp::kBlockLevel)); + rules.Append(dlp_test_util::CreateRule( + "rule #1", "Block Gmail", std::move(src_urls), + /*dst_urls=*/base::Value(base::Value::Type::LIST), + std::move(dst_components), std::move(restrictions))); + + PolicyMap policies; + policies.Set(key::kDataLeakPreventionRulesList, POLICY_LEVEL_MANDATORY, + POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD, std::move(rules), + nullptr); + UpdateProviderPolicy(policies); + + { + ui::ScopedClipboardWriter writer(ui::ClipboardBuffer::kCopyPaste, + std::make_unique<ui::DataTransferEndpoint>( + url::Origin::Create(GURL(kUrl1)))); + writer.WriteText(base::UTF8ToUTF16(kClipboardText)); + } + ui::DataTransferEndpoint data_dst1(ui::EndpointType::kDefault); + base::string16 result1; + ui::Clipboard::GetForCurrentThread()->ReadText( + ui::ClipboardBuffer::kCopyPaste, &data_dst1, &result1); + EXPECT_EQ(base::UTF8ToUTF16(kClipboardText), result1); + + // `notify_if_restricted` should be set false, otherwise the test would fail, + // because no guest os is actually running. + ui::DataTransferEndpoint data_dst2(ui::EndpointType::kArc, + /*notify_if_restricted=*/false); + base::string16 result2; + ui::Clipboard::GetForCurrentThread()->ReadText( + ui::ClipboardBuffer::kCopyPaste, &data_dst2, &result2); + EXPECT_EQ(base::string16(), result2); + + // `notify_if_restricted` should be set false, otherwise the test would fail, + // because no guest os is actually running. + ui::DataTransferEndpoint data_dst3(ui::EndpointType::kGuestOs, + /*notify_if_restricted=*/false); + base::string16 result3; + ui::Clipboard::GetForCurrentThread()->ReadText( + ui::ClipboardBuffer::kCopyPaste, &data_dst3, &result3); + EXPECT_EQ(base::string16(), result3); +} + +// TODO(crbug.com/1139884): Add browsertests for the clipboard notifications. + +} // namespace policy
diff --git a/chrome/browser/chromeos/preferences.cc b/chrome/browser/chromeos/preferences.cc index 8c5e520e..9cc52c47 100644 --- a/chrome/browser/chromeos/preferences.cc +++ b/chrome/browser/chromeos/preferences.cc
@@ -491,6 +491,10 @@ registry->RegisterBooleanPref( chromeos::prefs::kLauncherResultEverLaunched, false, user_prefs::PrefRegistrySyncable::SYNCABLE_OS_PREF); + + registry->RegisterBooleanPref( + chromeos::prefs::kHasCameraAppMigratedToSWA, false, + user_prefs::PrefRegistrySyncable::SYNCABLE_OS_PREF); } void Preferences::InitUserPrefs(sync_preferences::PrefServiceSyncable* prefs) { @@ -1108,9 +1112,8 @@ rate.repeat_interval_in_ms = xkb_auto_repeat_interval_pref_.GetValue(); DCHECK(rate.initial_delay_in_ms > 0); DCHECK(rate.repeat_interval_in_ms > 0); - input_method::InputMethodManager::Get() - ->GetImeKeyboard() - ->SetAutoRepeatRate(rate); + input_method::InputMethodManager::Get()->GetImeKeyboard()->SetAutoRepeatRate( + rate); user_manager::known_user::SetIntegerPref(user_->GetAccountId(), ash::prefs::kXkbAutoRepeatDelay,
diff --git a/chrome/browser/chromeos/web_applications/camera_system_web_app_info.cc b/chrome/browser/chromeos/web_applications/camera_system_web_app_info.cc index bf9b674..1bbd1137 100644 --- a/chrome/browser/chromeos/web_applications/camera_system_web_app_info.cc +++ b/chrome/browser/chromeos/web_applications/camera_system_web_app_info.cc
@@ -14,7 +14,7 @@ std::unique_ptr<WebApplicationInfo> CreateWebAppInfoForCameraSystemWebApp() { auto info = std::make_unique<WebApplicationInfo>(); info->start_url = GURL(chromeos::kChromeUICameraAppMainURL); - info->scope = GURL(chromeos::kChromeUICameraAppURL); + info->scope = GURL(chromeos::kChromeUICameraAppScopeURL); info->title = l10n_util::GetStringUTF16(IDS_NAME); web_app::CreateIconInfoForSystemWebApp(
diff --git a/chrome/browser/extensions/api/passwords_private/password_check_delegate.cc b/chrome/browser/extensions/api/passwords_private/password_check_delegate.cc index 1d86988..f373950 100644 --- a/chrome/browser/extensions/api/passwords_private/password_check_delegate.cc +++ b/chrome/browser/extensions/api/passwords_private/password_check_delegate.cc
@@ -12,6 +12,7 @@ #include <memory> #include <utility> +#include "base/bind.h" #include "base/containers/flat_set.h" #include "base/memory/ref_counted.h" #include "base/numerics/safe_conversions.h" @@ -346,9 +347,13 @@ return; } + // In case the Weakness Check feature is enabled start the check, and notify + // observers once done. if (base::FeatureList::IsEnabled( password_manager::features::kPasswordsWeaknessCheck)) { - insecure_credentials_manager_.StartWeakCheck(); + insecure_credentials_manager_.StartWeakCheck(base::BindOnce( + &PasswordCheckDelegate::RecordAndNotifyAboutCompletedWeakPasswordCheck, + weak_ptr_factory_.GetWeakPtr())); } auto progress = base::MakeRefCounted<PasswordCheckProgress>(); @@ -378,13 +383,15 @@ PasswordCheckDelegate::GetPasswordCheckStatus() const { api::passwords_private::PasswordCheckStatus result; - // Obtain the timestamp of the last completed check. This is 0.0 in case the - // check never completely ran before. - const double last_check_completed = profile_->GetPrefs()->GetDouble( - password_manager::prefs::kLastTimePasswordCheckCompleted); - if (last_check_completed) { - result.elapsed_time_since_last_check = std::make_unique<std::string>( - FormatElapsedTime(base::Time::FromDoubleT(last_check_completed))); + // Obtain the timestamp of the last completed password or weak check. This + // will be null in case no check has completely ran before. + base::Time last_check_completed = + std::max(base::Time::FromTimeT(profile_->GetPrefs()->GetDouble( + password_manager::prefs::kLastTimePasswordCheckCompleted)), + last_completed_weak_check_); + if (!last_check_completed.is_null()) { + result.elapsed_time_since_last_check = + std::make_unique<std::string>(FormatElapsedTime(last_check_completed)); } State state = bulk_leak_check_service_adapter_.GetBulkLeakCheckState(); @@ -455,18 +462,7 @@ if (state == State::kIdle && std::exchange(is_check_running_, false)) { // When the service transitions from running into idle it has finished a // check. - profile_->GetPrefs()->SetDouble( - password_manager::prefs::kLastTimePasswordCheckCompleted, - base::Time::Now().ToDoubleT()); - - // In case the check run to completion delay the last Check Status update by - // a second. This avoids flickering of the UI if the full check ran from - // start to finish almost immediately. - base::SequencedTaskRunnerHandle::Get()->PostDelayedTask( - FROM_HERE, - base::BindOnce(&PasswordCheckDelegate::NotifyPasswordCheckStatusChanged, - weak_ptr_factory_.GetWeakPtr()), - base::TimeDelta::FromSeconds(1)); + RecordAndNotifyAboutCompletedCompromisedPasswordCheck(); return; } @@ -514,6 +510,29 @@ return insecure_credential; } +void PasswordCheckDelegate:: + RecordAndNotifyAboutCompletedCompromisedPasswordCheck() { + profile_->GetPrefs()->SetDouble( + password_manager::prefs::kLastTimePasswordCheckCompleted, + base::Time::Now().ToDoubleT()); + + // Delay the last Check Status update by a second. This avoids flickering of + // the UI if the full check ran from start to finish almost immediately. + base::SequencedTaskRunnerHandle::Get()->PostDelayedTask( + FROM_HERE, + base::BindOnce(&PasswordCheckDelegate::NotifyPasswordCheckStatusChanged, + weak_ptr_factory_.GetWeakPtr()), + base::TimeDelta::FromSeconds(1)); +} + +void PasswordCheckDelegate::RecordAndNotifyAboutCompletedWeakPasswordCheck() { + last_completed_weak_check_ = base::Time::Now(); + // Note: In contrast to the compromised password check we do not does not + // artificially delay the response, Since this check is expected to complete + // quickly. + NotifyPasswordCheckStatusChanged(); +} + void PasswordCheckDelegate::NotifyPasswordCheckStatusChanged() { if (auto* event_router = PasswordsPrivateEventRouterFactory::GetForProfile(profile_)) {
diff --git a/chrome/browser/extensions/api/passwords_private/password_check_delegate.h b/chrome/browser/extensions/api/passwords_private/password_check_delegate.h index ab7abc2fc..257c99a 100644 --- a/chrome/browser/extensions/api/passwords_private/password_check_delegate.h +++ b/chrome/browser/extensions/api/passwords_private/password_check_delegate.h
@@ -10,6 +10,7 @@ #include "base/memory/scoped_refptr.h" #include "base/memory/weak_ptr.h" #include "base/scoped_observer.h" +#include "base/time/time.h" #include "chrome/browser/extensions/api/passwords_private/passwords_private_delegate.h" #include "chrome/browser/extensions/api/passwords_private/passwords_private_utils.h" #include "chrome/common/extensions/api/passwords_private.h" @@ -122,6 +123,14 @@ FindMatchingInsecureCredential( const api::passwords_private::InsecureCredential& credential) const; + // Invoked when a compromised password check completes. Records the current + // timestamp in `kLastTimePasswordCheckCompleted` pref. + void RecordAndNotifyAboutCompletedCompromisedPasswordCheck(); + + // Invoked when a weak password check completes. Records the current timestamp + // in `last_completed_weak_check_`. + void RecordAndNotifyAboutCompletedWeakPasswordCheck(); + // Tries to notify the PasswordsPrivateEventRouter that the password check // status has changed. Invoked after OnSavedPasswordsChanged and // OnStateChanged. @@ -162,6 +171,9 @@ // Remembers whether a password check is running right now. bool is_check_running_ = false; + // Store when the last weak check was completed. + base::Time last_completed_weak_check_; + // A scoped observer for |saved_passwords_presenter_|. ScopedObserver<password_manager::SavedPasswordsPresenter, password_manager::SavedPasswordsPresenter::Observer>
diff --git a/chrome/browser/extensions/api/storage/setting_sync_data.cc b/chrome/browser/extensions/api/storage/setting_sync_data.cc index 4dce6ce..ce7dd47c 100644 --- a/chrome/browser/extensions/api/storage/setting_sync_data.cc +++ b/chrome/browser/extensions/api/storage/setting_sync_data.cc
@@ -22,7 +22,7 @@ } SettingSyncData::SettingSyncData(const syncer::SyncData& sync_data) - : change_type_(syncer::SyncChange::ACTION_INVALID) { + : change_type_(base::nullopt) { ExtractSyncData(sync_data); }
diff --git a/chrome/browser/extensions/api/storage/setting_sync_data.h b/chrome/browser/extensions/api/storage/setting_sync_data.h index 6522f30..fca45377 100644 --- a/chrome/browser/extensions/api/storage/setting_sync_data.h +++ b/chrome/browser/extensions/api/storage/setting_sync_data.h
@@ -9,6 +9,7 @@ #include <string> #include "base/macros.h" +#include "base/optional.h" #include "base/values.h" #include "components/sync/model/sync_change.h" @@ -25,7 +26,7 @@ // Creates from a sync change. explicit SettingSyncData(const syncer::SyncChange& sync_change); - // Creates from sync data. |change_type| will be ACTION_INVALID. + // Creates from sync data. |change_type| will be base::nullopt. explicit SettingSyncData(const syncer::SyncData& sync_data); // Creates explicitly. @@ -36,9 +37,10 @@ ~SettingSyncData(); - // May return ACTION_INVALID if this object represents sync data that isn't + // May return base::nullopt if this object represents sync data that isn't // associated with a sync operation. - syncer::SyncChange::SyncChangeType change_type() const { + const base::Optional<syncer::SyncChange::SyncChangeType>& change_type() + const { return change_type_; } const std::string& extension_id() const { return extension_id_; } @@ -55,7 +57,7 @@ // either an extension or app settings data type. void ExtractSyncData(const syncer::SyncData& sync_data); - syncer::SyncChange::SyncChangeType change_type_; + base::Optional<syncer::SyncChange::SyncChangeType> change_type_; std::string extension_id_; std::string key_; std::unique_ptr<base::Value> value_;
diff --git a/chrome/browser/extensions/api/storage/syncable_settings_storage.cc b/chrome/browser/extensions/api/storage/syncable_settings_storage.cc index 9291132..3457a1f 100644 --- a/chrome/browser/extensions/api/storage/syncable_settings_storage.cc +++ b/chrome/browser/extensions/api/storage/syncable_settings_storage.cc
@@ -289,7 +289,9 @@ syncer::SyncError error; - switch (sync_change->change_type()) { + DCHECK(sync_change->change_type().has_value()); + + switch (*sync_change->change_type()) { case syncer::SyncChange::ACTION_ADD: if (!current_value.get()) { error = OnSyncAdd(key, std::move(change_value), &changes); @@ -324,9 +326,6 @@ extension_id_ << "/" << key; } break; - - default: - NOTREACHED(); } if (error.IsSet()) {
diff --git a/chrome/browser/extensions/api/virtual_keyboard_private/chrome_virtual_keyboard_delegate.cc b/chrome/browser/extensions/api/virtual_keyboard_private/chrome_virtual_keyboard_delegate.cc index f52ce98..07ba5a3 100644 --- a/chrome/browser/extensions/api/virtual_keyboard_private/chrome_virtual_keyboard_delegate.cc +++ b/chrome/browser/extensions/api/virtual_keyboard_private/chrome_virtual_keyboard_delegate.cc
@@ -407,6 +407,9 @@ base::FeatureList::IsEnabled( chromeos::features::kHandwritingGestureEditing))); features->AppendString(GenerateFeatureFlag( + "multiword", + base::FeatureList::IsEnabled(chromeos::features::kAssistMultiWord))); + features->AppendString(GenerateFeatureFlag( "floatingkeyboarddefault", base::FeatureList::IsEnabled( chromeos::features::kVirtualKeyboardFloatingDefault)));
diff --git a/chrome/browser/extensions/component_loader.cc b/chrome/browser/extensions/component_loader.cc index cdfc420..d082efa8a 100644 --- a/chrome/browser/extensions/component_loader.cc +++ b/chrome/browser/extensions/component_loader.cc
@@ -53,6 +53,7 @@ #if BUILDFLAG(IS_CHROMEOS_ASH) #include "ash/keyboard/ui/grit/keyboard_resources.h" #include "chromeos/constants/chromeos_features.h" +#include "chromeos/constants/chromeos_pref_names.h" #include "chromeos/constants/chromeos_switches.h" #include "components/user_manager/user_manager.h" #include "content/public/browser/site_instance.h" @@ -396,7 +397,15 @@ } void ComponentLoader::AddChromeCameraApp() { - if (base::FeatureList::IsEnabled(chromeos::features::kCameraSystemWebApp)) { + // TODO(crbug.com/1135280): Remove all the logic here once CCA is fully + // migrated to SWA. + + // If users should use the SWA version of CCA and the status from the platform + // app version is already migrated, there is no need to install the platform + // version of CCA. + if (base::FeatureList::IsEnabled(chromeos::features::kCameraSystemWebApp) && + profile_->GetPrefs()->GetBoolean( + chromeos::prefs::kHasCameraAppMigratedToSWA)) { return; }
diff --git a/chrome/browser/extensions/corb_and_cors_extension_browsertest.cc b/chrome/browser/extensions/corb_and_cors_extension_browsertest.cc index d4fe18e1..a970c52d 100644 --- a/chrome/browser/extensions/corb_and_cors_extension_browsertest.cc +++ b/chrome/browser/extensions/corb_and_cors_extension_browsertest.cc
@@ -71,18 +71,6 @@ namespace { -enum TestParam { - // Whether the extension under test is "allowlisted" (see - // GetExtensionsAllowlist in - // //extensions/browser/url_loader_factory_manager.cc). - kAllowlisted = 1 << 0, - - // Whether network::features:: - // kDeriveOriginFromUrlForNeitherGetNorHeadRequestWhenHavingSpecialAccess is - // enabled. - kDeriveOriginFromUrl = 1 << 2, -}; - const char kCorsErrorWhenFetching[] = "error: TypeError: Failed to fetch"; // The manifest.json used by tests uses |kExpectedKey| that will result in the @@ -197,7 +185,7 @@ class CorbAndCorsExtensionBrowserTest : public CorbAndCorsExtensionTestBase, - public ::testing::WithParamInterface<TestParam> { + public ::testing::WithParamInterface<bool> { public: using Base = CorbAndCorsExtensionTestBase; @@ -206,17 +194,6 @@ std::vector<base::test::ScopedFeatureList::FeatureAndParams> enabled_features; - if (DeriveOriginFromUrl()) { - enabled_features.emplace_back( - network::features:: - kDeriveOriginFromUrlForNeitherGetNorHeadRequestWhenHavingSpecialAccess, - base::FieldTrialParams()); - } else { - disabled_features.push_back( - network::features:: - kDeriveOriginFromUrlForNeitherGetNorHeadRequestWhenHavingSpecialAccess); - } - if (IsExtensionAllowlisted()) { base::FieldTrialParams field_trial_params; field_trial_params.emplace( @@ -240,13 +217,7 @@ &policy_provider_); } - bool IsExtensionAllowlisted() { - return (GetParam() & TestParam::kAllowlisted) != 0; - } - - bool DeriveOriginFromUrl() { - return (GetParam() & TestParam::kDeriveOriginFromUrl) != 0; - } + bool IsExtensionAllowlisted() { return GetParam(); } const Extension* InstallExtension( GURL resource_to_fetch_from_declarative_content_script = GURL()) { @@ -1288,7 +1259,7 @@ }; INSTANTIATE_TEST_SUITE_P(Allowlisted_AllowlistForCors, TrustTokenExtensionBrowserTest, - ::testing::Values(TestParam::kAllowlisted)); + ::testing::Values(true)); IN_PROC_BROWSER_TEST_P( TrustTokenExtensionBrowserTest, FromProgrammaticContentScript_TrustTokenRedemptionAllowed) { @@ -2296,23 +2267,16 @@ INSTANTIATE_TEST_SUITE_P(Allowlisted, CorbAndCorsExtensionBrowserTest, - ::testing::Values(TestParam::kAllowlisted)); + ::testing::Values(true)); INSTANTIATE_TEST_SUITE_P(NotAllowlisted, CorbAndCorsExtensionBrowserTest, - ::testing::Values(0)); + ::testing::Values(false)); INSTANTIATE_TEST_SUITE_P(Allowlisted_LegacyOriginHeaderBehavior, OriginHeaderExtensionBrowserTest, - ::testing::Values(TestParam::kAllowlisted)); -INSTANTIATE_TEST_SUITE_P(Allowlisted_NewOriginHeaderBehavior, - OriginHeaderExtensionBrowserTest, - ::testing::Values(TestParam::kAllowlisted | - TestParam::kDeriveOriginFromUrl)); + ::testing::Values(true)); INSTANTIATE_TEST_SUITE_P(NotAllowlisted_LegacyOriginHeaderBehavior, OriginHeaderExtensionBrowserTest, - ::testing::Values(0)); -INSTANTIATE_TEST_SUITE_P(NotAllowlisted_NewOriginHeaderBehavior, - OriginHeaderExtensionBrowserTest, - ::testing::Values(TestParam::kDeriveOriginFromUrl)); + ::testing::Values(false)); } // namespace extensions
diff --git a/chrome/browser/extensions/extension_samesite_cookies_browsertest.cc b/chrome/browser/extensions/extension_samesite_cookies_browsertest.cc index 6cc76d4..6cb45ce 100644 --- a/chrome/browser/extensions/extension_samesite_cookies_browsertest.cc +++ b/chrome/browser/extensions/extension_samesite_cookies_browsertest.cc
@@ -362,8 +362,9 @@ // Extension is site_for_cookies, initiator and requested URL are permitted, // initiator and requested URL are same-site => SameSite cookies are sent. +// crbug.com/1153083: flaky on linux, win, and mac IN_PROC_BROWSER_TEST_P(ExtensionSameSiteCookiesTest, - OnePermittedSameSiteFrame_Navigation) { + DISABLED_OnePermittedSameSiteFrame_Navigation) { SetCookies(kPermittedHost); content::RenderFrameHost* main_frame = NavigateMainFrameToExtensionPage(); content::RenderFrameHost* child_frame =
diff --git a/chrome/browser/extensions/fetch_apitest.cc b/chrome/browser/extensions/fetch_apitest.cc index bfeac5a..b40a047 100644 --- a/chrome/browser/extensions/fetch_apitest.cc +++ b/chrome/browser/extensions/fetch_apitest.cc
@@ -287,28 +287,7 @@ EXPECT_EQ("basic", ExecuteScriptInBackgroundPage(extension->id(), script)); } -class ExtensionFetchPostOriginTest : public ExtensionFetchTest, - public testing::WithParamInterface<bool> { - protected: - void SetUp() override { - if (GetParam()) { - scoped_feature_list_.InitAndEnableFeature( - network::features:: - kDeriveOriginFromUrlForNeitherGetNorHeadRequestWhenHavingSpecialAccess); - } else { - scoped_feature_list_.InitAndDisableFeature( - network::features:: - kDeriveOriginFromUrlForNeitherGetNorHeadRequestWhenHavingSpecialAccess); - } - ExtensionFetchTest::SetUp(); - } - - private: - base::test::ScopedFeatureList scoped_feature_list_; -}; - -IN_PROC_BROWSER_TEST_P(ExtensionFetchPostOriginTest, - OriginOnPostWithPermissions) { +IN_PROC_BROWSER_TEST_F(ExtensionFetchTest, OriginOnPostWithPermissions) { TestExtensionDir dir; dir.WriteManifest(R"JSON( { @@ -324,15 +303,12 @@ GURL destination_url = embedded_test_server()->GetURL("example.com", "/echo-origin"); std::string script = content::JsReplace(kFetchPostScript, destination_url); - std::string origin_string = - GetParam() ? url::Origin::Create(destination_url).Serialize() - : url::Origin::Create(extension->url()).Serialize(); + std::string origin_string = url::Origin::Create(extension->url()).Serialize(); EXPECT_EQ(origin_string, ExecuteScriptInBackgroundPage(extension->id(), script)); } -IN_PROC_BROWSER_TEST_P(ExtensionFetchPostOriginTest, - OriginOnPostWithoutPermissions) { +IN_PROC_BROWSER_TEST_F(ExtensionFetchTest, OriginOnPostWithoutPermissions) { TestExtensionDir dir; dir.WriteManifest(R"JSON( { @@ -352,14 +328,6 @@ ExecuteScriptInBackgroundPage(extension->id(), script)); } -INSTANTIATE_TEST_SUITE_P(UseExtensionOrigin, - ExtensionFetchPostOriginTest, - testing::Values(false)); - -INSTANTIATE_TEST_SUITE_P(UseDestinationUrlOrigin, - ExtensionFetchPostOriginTest, - testing::Values(true)); - // An extension background script should be able to fetch resources contained in // the extension, and those resources should not be opaque. IN_PROC_BROWSER_TEST_F(ExtensionFetchTest, ExtensionResourceShouldNotBeOpaque) {
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json index 2d7886c..184be0b 100644 --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json
@@ -1395,6 +1395,11 @@ "expiry_milestone": 90 }, { + "name": "enable-cros-ime-assist-multi-word", + "owners": [ "curtismcmullan", "essential-inputs-team@google.com" ], + "expiry_milestone": 95 + }, + { "name": "enable-cros-ime-assist-personal-info", "owners": [ "jiwan", "essential-inputs-team@google.com" ], "expiry_milestone": 90
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index 3cb19219..4fa6c8d9 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -4281,6 +4281,11 @@ const char kImeAssistAutocorrectDescription[] = "Enable assistive auto-correct features for native IME"; +const char kImeAssistMultiWordName[] = + "Enable assistive multi word suggestions"; +const char kImeAssistMultiWordDescription[] = + "Enable assistive multi word suggestions for native IME"; + const char kImeAssistPersonalInfoName[] = "Enable assistive personal info"; const char kImeAssistPersonalInfoDescription[] = "Enable auto-complete suggestions on personal infomation for native IME.";
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index 36e207b..667be75 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -2498,6 +2498,9 @@ extern const char kImeAssistAutocorrectName[]; extern const char kImeAssistAutocorrectDescription[]; +extern const char kImeAssistMultiWordName[]; +extern const char kImeAssistMultiWordDescription[]; + extern const char kImeAssistPersonalInfoName[]; extern const char kImeAssistPersonalInfoDescription[];
diff --git a/chrome/browser/paint_preview/android/javatests/src/org/chromium/chrome/browser/paint_preview/services/PaintPreviewTabServiceTest.java b/chrome/browser/paint_preview/android/javatests/src/org/chromium/chrome/browser/paint_preview/services/PaintPreviewTabServiceTest.java index 0e65d8c..cb72f9c6 100644 --- a/chrome/browser/paint_preview/android/javatests/src/org/chromium/chrome/browser/paint_preview/services/PaintPreviewTabServiceTest.java +++ b/chrome/browser/paint_preview/android/javatests/src/org/chromium/chrome/browser/paint_preview/services/PaintPreviewTabServiceTest.java
@@ -99,6 +99,8 @@ activity.getWindow().setLocalFocus(true, true); TestThreadUtils.runOnUiThreadBlocking(() -> { InstrumentationRegistry.getInstrumentation().callActivityOnRestart(activity); + InstrumentationRegistry.getInstrumentation().callActivityOnStart(activity); + InstrumentationRegistry.getInstrumentation().callActivityOnResume(activity); }); TestThreadUtils.runOnUiThreadBlocking(() -> {
diff --git a/chrome/browser/permissions/prediction_based_permission_ui_selector.cc b/chrome/browser/permissions/prediction_based_permission_ui_selector.cc index 2cddc45..50b4d53 100644 --- a/chrome/browser/permissions/prediction_based_permission_ui_selector.cc +++ b/chrome/browser/permissions/prediction_based_permission_ui_selector.cc
@@ -51,6 +51,8 @@ return; } + last_request_grant_likelihood_ = base::nullopt; + DCHECK(!request_); permissions::PredictionService* service = PredictionServiceFactory::GetForProfile(profile_); @@ -67,6 +69,11 @@ callback_.Reset(); } +base::Optional<permissions::PermissionUmaUtil::PredictionGrantLikelihood> +PredictionBasedPermissionUiSelector::PredictedGrantLikelihoodForUKM() { + return last_request_grant_likelihood_; +} + permissions::PredictionRequestFeatures PredictionBasedPermissionUiSelector::BuildPredictionRequestFeatures( permissions::PermissionRequest* request) { @@ -129,6 +136,9 @@ return; } + last_request_grant_likelihood_ = + response->suggestion(0).grant_likelihood().discretized_likelihood(); + if (response->suggestion(0).grant_likelihood().discretized_likelihood() == VeryUnlikely) { std::move(callback_).Run(Decision(
diff --git a/chrome/browser/permissions/prediction_based_permission_ui_selector.h b/chrome/browser/permissions/prediction_based_permission_ui_selector.h index d8511911..20781d33 100644 --- a/chrome/browser/permissions/prediction_based_permission_ui_selector.h +++ b/chrome/browser/permissions/prediction_based_permission_ui_selector.h
@@ -38,6 +38,9 @@ void Cancel() override; + base::Optional<permissions::PermissionUmaUtil::PredictionGrantLikelihood> + PredictedGrantLikelihoodForUKM() override; + private: permissions::PredictionRequestFeatures BuildPredictionRequestFeatures( permissions::PermissionRequest* request); @@ -49,6 +52,9 @@ Profile* profile_; std::unique_ptr<PredictionServiceRequest> request_; + base::Optional<permissions::PermissionUmaUtil::PredictionGrantLikelihood> + last_request_grant_likelihood_; + DecisionMadeCallback callback_; };
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc index 1cfa576..8c4da83d 100644 --- a/chrome/browser/prefs/browser_prefs.cc +++ b/chrome/browser/prefs/browser_prefs.cc
@@ -194,7 +194,6 @@ #if BUILDFLAG(ENABLE_PLUGINS) #include "chrome/browser/plugins/plugin_info_host_impl.h" #include "chrome/browser/plugins/plugins_resource_service.h" -#include "chrome/browser/renderer_host/pepper/device_id_fetcher.h" #endif #if BUILDFLAG(ENABLE_SUPERVISED_USERS) @@ -491,6 +490,9 @@ const char kSettingsLaunchedPasswordChecks[] = "profile.settings_launched_password_checks"; +// Deprecated 11/2020 +const char kDRMSalt[] = "settings.privacy.drm_salt"; + // Register local state used only for migration (clearing or moving to a new // key). void RegisterLocalStatePrefsForMigration(PrefRegistrySimple* registry) { @@ -568,6 +570,7 @@ #endif registry->RegisterIntegerPref(kSettingsLaunchedPasswordChecks, 0); + registry->RegisterStringPref(kDRMSalt, ""); } } // namespace @@ -866,7 +869,6 @@ #endif #if BUILDFLAG(ENABLE_PLUGINS) - DeviceIDFetcher::RegisterProfilePrefs(registry); PluginInfoHostImpl::RegisterUserPrefs(registry); #endif @@ -1172,4 +1174,7 @@ // Added 11/2020 profile_prefs->ClearPref(kSettingsLaunchedPasswordChecks); + + // Added 11/2020 + profile_prefs->ClearPref(kDRMSalt); }
diff --git a/chrome/browser/profiles/profile_metrics.h b/chrome/browser/profiles/profile_metrics.h index 044deee..440fc1c 100644 --- a/chrome/browser/profiles/profile_metrics.h +++ b/chrome/browser/profiles/profile_metrics.h
@@ -79,10 +79,10 @@ // These values are persisted to logs. Entries should not be renumbered and // numeric values should never be reused. enum ProfileSync { - SYNC_CUSTOMIZE = 0, // User decided to customize sync - SYNC_CHOOSE, // User chose what to sync - SYNC_ENCRYPT, // User has chosen to encrypt all data - SYNC_PASSPHRASE, // User is using a passphrase + SYNC_CUSTOMIZE = 0, // User decided to customize sync + SYNC_CHOOSE, // User chose what to sync + SYNC_CREATED_NEW_PASSPHRASE, // User created a passphrase to encrypt data + SYNC_ENTERED_EXISTING_PASSPHRASE, // User entered an existing passphrase NUM_PROFILE_SYNC_METRICS };
diff --git a/chrome/browser/renderer_host/pepper/device_id_fetcher.cc b/chrome/browser/renderer_host/pepper/device_id_fetcher.cc deleted file mode 100644 index ac59ea46..0000000 --- a/chrome/browser/renderer_host/pepper/device_id_fetcher.cc +++ /dev/null
@@ -1,15 +0,0 @@ -// Copyright (c) 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/renderer_host/pepper/device_id_fetcher.h" - -#include "chrome/common/pref_names.h" -#include "components/pref_registry/pref_registry_syncable.h" - -// static -void DeviceIDFetcher::RegisterProfilePrefs( - user_prefs::PrefRegistrySyncable* prefs) { - prefs->RegisterBooleanPref(prefs::kEnableDRM, true); - prefs->RegisterStringPref(prefs::kDRMSalt, ""); -}
diff --git a/chrome/browser/renderer_host/pepper/device_id_fetcher.h b/chrome/browser/renderer_host/pepper/device_id_fetcher.h deleted file mode 100644 index f5892c06c..0000000 --- a/chrome/browser/renderer_host/pepper/device_id_fetcher.h +++ /dev/null
@@ -1,22 +0,0 @@ -// Copyright (c) 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_RENDERER_HOST_PEPPER_DEVICE_ID_FETCHER_H_ -#define CHROME_BROWSER_RENDERER_HOST_PEPPER_DEVICE_ID_FETCHER_H_ - -namespace user_prefs { -class PrefRegistrySyncable; -} - -// This class has been followed out and now simply hosts a profile pref. -// TODO(crbug.com/1152871): Remove or migrate those, too. -class DeviceIDFetcher { - public: - DeviceIDFetcher() = delete; - - // Called to register the |kEnableDRM| and |kDRMSalt| preferences. - static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* prefs); -}; - -#endif // CHROME_BROWSER_RENDERER_HOST_PEPPER_DEVICE_ID_FETCHER_H_
diff --git a/chrome/browser/resources/chromeos/login/BUILD.gn b/chrome/browser/resources/chromeos/login/BUILD.gn index 5db088b..d3d4e10a 100644 --- a/chrome/browser/resources/chromeos/login/BUILD.gn +++ b/chrome/browser/resources/chromeos/login/BUILD.gn
@@ -43,6 +43,7 @@ ":oobe_network", ":oobe_reset", ":oobe_screen_assistant_optin_flow", + ":oobe_screen_auto_enrollment_check", ":oobe_screen_enable_debugging", ":oobe_select", ":oobe_supervision_transition", @@ -99,7 +100,7 @@ js_library("active_directory_password_change") { deps = [ "components/oobe_dialog:oobe_dialog", - "components/oobe_i18n_behavior:oobe_i18n_behavior" + "components/oobe_i18n_behavior:oobe_i18n_behavior", ] } @@ -255,8 +256,8 @@ deps = [ ":web_view_helper", "components:login_screen_behavior", - "components/oobe_dialog:oobe_dialog", "components:oobe_dialog_host_behavior", + "components/oobe_dialog:oobe_dialog", "components/oobe_i18n_behavior:oobe_i18n_behavior", ] } @@ -290,6 +291,13 @@ ] } +js_library("oobe_screen_auto_enrollment_check") { + deps = [ + "components:login_screen_behavior", + "components/oobe_i18n_behavior:oobe_i18n_behavior", + ] +} + js_library("oobe_screen_enable_debugging") { deps = [ "components:login_screen_behavior",
diff --git a/chrome/browser/resources/chromeos/login/md_login.html b/chrome/browser/resources/chromeos/login/md_login.html index 045e89af..43df1b66 100644 --- a/chrome/browser/resources/chromeos/login/md_login.html +++ b/chrome/browser/resources/chromeos/login/md_login.html
@@ -55,7 +55,6 @@ <script defer src="chrome://oobe/test_api.js"></script> <link rel="stylesheet" href="api_keys_notice.css"> <link rel="stylesheet" href="oobe_screen_autolaunch.css"> -<link rel="stylesheet" href="oobe_screen_auto_enrollment_check.css"> <link rel="stylesheet" href="screen_error_message.css"> <script src="chrome://oobe/keyboard_utils.js"></script>
diff --git a/chrome/browser/resources/chromeos/login/oobe.html b/chrome/browser/resources/chromeos/login/oobe.html index 36890e6..d0957100 100644 --- a/chrome/browser/resources/chromeos/login/oobe.html +++ b/chrome/browser/resources/chromeos/login/oobe.html
@@ -60,7 +60,6 @@ <link rel="stylesheet" href="api_keys_notice.css"> <link rel="stylesheet" href="oobe_screen_autolaunch.css"> -<link rel="stylesheet" href="oobe_screen_auto_enrollment_check.css"> <link rel="stylesheet" href="screen_error_message.css">
diff --git a/chrome/browser/resources/chromeos/login/oobe.js b/chrome/browser/resources/chromeos/login/oobe.js index 2115305..ce4dd5cf 100644 --- a/chrome/browser/resources/chromeos/login/oobe.js +++ b/chrome/browser/resources/chromeos/login/oobe.js
@@ -28,7 +28,6 @@ // <include src="screen_multidevice_setup.js"> // <include src="../../gaia_auth_host/authenticator.js"> -// <include src="oobe_screen_auto_enrollment_check.js"> // <include src="multi_tap_detector.js"> // <include src="web_view_helper.js"> @@ -41,7 +40,6 @@ */ initialize() { cr.ui.login.DisplayManager.initialize(); - login.AutoEnrollmentCheckScreen.register(); login.AutolaunchScreen.register(); login.AccountPickerScreen.register(); login.ErrorMessageScreen.register();
diff --git a/chrome/browser/resources/chromeos/login/oobe_screen_auto_enrollment_check.css b/chrome/browser/resources/chromeos/login/oobe_screen_auto_enrollment_check.css deleted file mode 100644 index f718523..0000000 --- a/chrome/browser/resources/chromeos/login/oobe_screen_auto_enrollment_check.css +++ /dev/null
@@ -1,16 +0,0 @@ -/* Copyright 2014 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. */ - -#auto-enrollment-check { - min-height: 395px; - padding: 70px 17px 21px; -} - -#auto-enrollment-check #auto-enrollment-check-progress { - color: #9c9c9c; - display: flex; - justify-content: center; - margin-top: 130px; - min-height: 0; -}
diff --git a/chrome/browser/resources/chromeos/login/oobe_screen_auto_enrollment_check.html b/chrome/browser/resources/chromeos/login/oobe_screen_auto_enrollment_check.html index 3990cab..cbaf814a 100644 --- a/chrome/browser/resources/chromeos/login/oobe_screen_auto_enrollment_check.html +++ b/chrome/browser/resources/chromeos/login/oobe_screen_auto_enrollment_check.html
@@ -1,9 +1,33 @@ -<div class="step hidden" id="auto-enrollment-check" role="group" - i18n-values="aria-label:autoEnrollmentCheckScreenHeader" hidden> - <div class="step-contents"> - <div id="auto-enrollment-check-progress" aria-live="polite"> - <div class="throbber"></div> - <div i18n-content="autoEnrollmentCheckMessage"></div> +<!-- 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. --> + +<dom-module id="auto-enrollment-check-element"> + <template> + <link rel="stylesheet" href="chrome://resources/css/throbber.css"> + <link rel="stylesheet" href="../../../../../ui/login/oobe.css"> + <style> + #auto-enrollment-check { + min-height: 395px; + padding: 70px 17px 21px; + } + + #auto-enrollment-check #auto-enrollment-check-progress { + color: #9c9c9c; + display: flex; + justify-content: center; + margin-top: 130px; + min-height: 0; + } + </style> + <div id="auto-enrollment-check" role="group" + i18n-values="aria-label:autoEnrollmentCheckScreenHeader"> + <div class="step-contents"> + <div id="auto-enrollment-check-progress" aria-live="polite"> + <div class="throbber"></div> + [[i18nDynamic(locale, 'autoEnrollmentCheckMessage')]] + </div> + </div> </div> - </div> -</div> + </template> +</dom-module>
diff --git a/chrome/browser/resources/chromeos/login/oobe_screen_auto_enrollment_check.js b/chrome/browser/resources/chromeos/login/oobe_screen_auto_enrollment_check.js index 1065eb88..70eea170 100644 --- a/chrome/browser/resources/chromeos/login/oobe_screen_auto_enrollment_check.js +++ b/chrome/browser/resources/chromeos/login/oobe_screen_auto_enrollment_check.js
@@ -6,7 +6,14 @@ * @fileoverview Oobe Auto-enrollment check screen implementation. */ -login.createScreen( - 'AutoEnrollmentCheckScreen', 'auto-enrollment-check', function() { - return {EXTERNAL_API: []}; +Polymer({ + is: 'auto-enrollment-check-element', + + behaviors: [OobeI18nBehavior, LoginScreenBehavior], + + ready() { + this.initializeLoginScreen('AutoEnrollmentCheckScreen', { + resetAllowed: true, }); + }, +});
diff --git a/chrome/browser/resources/chromeos/login/structure/components_oobe.html b/chrome/browser/resources/chromeos/login/structure/components_oobe.html index 2618d65..1689a189 100644 --- a/chrome/browser/resources/chromeos/login/structure/components_oobe.html +++ b/chrome/browser/resources/chromeos/login/structure/components_oobe.html
@@ -6,6 +6,7 @@ <include src="../oobe_hid_detection.html"> <include src="../oobe_i18n_dropdown.html"> +<include src="../oobe_screen_auto_enrollment_check.html"> <include src="../oobe_screen_enable_debugging.html"> <include src="../oobe_welcome_dialog.html"> <include src="../oobe_welcome.html">
diff --git a/chrome/browser/resources/chromeos/login/structure/components_oobe.js b/chrome/browser/resources/chromeos/login/structure/components_oobe.js index 0f246fd..1f4b99dd6 100644 --- a/chrome/browser/resources/chromeos/login/structure/components_oobe.js +++ b/chrome/browser/resources/chromeos/login/structure/components_oobe.js
@@ -4,6 +4,7 @@ // <include src="../oobe_hid_detection.js"> // <include src="../oobe_i18n_dropdown.js"> +// <include src="../oobe_screen_auto_enrollment_check.js"> // <include src="../oobe_screen_enable_debugging.js"> // <include src="../oobe_welcome_dialog.js"> // <include src="../oobe_welcome.js">
diff --git a/chrome/browser/resources/chromeos/login/structure/screens_oobe.html b/chrome/browser/resources/chromeos/login/structure/screens_oobe.html index a6c4b83..17e8c2f 100644 --- a/chrome/browser/resources/chromeos/login/structure/screens_oobe.html +++ b/chrome/browser/resources/chromeos/login/structure/screens_oobe.html
@@ -18,7 +18,8 @@ </oobe-eula-element> <oobe-update-element id="oobe-update" class="step hidden" hidden> </oobe-update-element> -<include src="../oobe_screen_auto_enrollment_check.html"> +<auto-enrollment-check-element id="auto-enrollment-check" class="step hidden" hidden> +</auto-enrollment-check-element> <demo-preferences-element id="demo-preferences" class="step hidden" hidden> </demo-preferences-element> <enterprise-enrollment-element id="enterprise-enrollment" class="step hidden"
diff --git a/chrome/browser/resources/settings/autofill_page/password_check.js b/chrome/browser/resources/settings/autofill_page/password_check.js index f193afc..c8c52b1 100644 --- a/chrome/browser/resources/settings/autofill_page/password_check.js +++ b/chrome/browser/resources/settings/autofill_page/password_check.js
@@ -530,8 +530,10 @@ * @private */ showsTimestamp_() { - return this.status.state === CheckState.IDLE && - !!this.status.elapsedTimeSinceLastCheck; + return !!this.status.elapsedTimeSinceLastCheck && + (this.status.state === CheckState.IDLE || + (this.status.state === CheckState.SIGNED_OUT && + this.passwordsWeaknessCheckEnabled)); }, /**
diff --git a/chrome/browser/resources/settings/people_page/sync_browser_proxy.js b/chrome/browser/resources/settings/people_page/sync_browser_proxy.js index eb9e0ef99..a3f55743 100644 --- a/chrome/browser/resources/settings/people_page/sync_browser_proxy.js +++ b/chrome/browser/resources/settings/people_page/sync_browser_proxy.js
@@ -72,7 +72,6 @@ * extensionsRegistered: boolean, * extensionsSynced: boolean, * fullEncryptionBody: string, - * passphrase: (string|undefined), * passphraseRequired: boolean, * passwordsRegistered: boolean, * passwordsSynced: boolean, @@ -81,7 +80,6 @@ * preferencesSynced: boolean, * readingListRegistered: boolean, * readingListSynced: boolean, - * setNewPassphrase: (boolean|undefined), * syncAllDataTypes: boolean, * tabsRegistered: boolean, * tabsSynced: boolean, @@ -198,13 +196,20 @@ setSyncDatatypes(syncPrefs) {} /** - * Sets the sync encryption options. - * @param {!settings.SyncPrefs} syncPrefs - * @return {!Promise<!settings.PageStatus>} + * Attempts to set up a new passphrase to encrypt Sync data. + * @param {string} passphrase + * @return {!Promise<boolean>} Whether the passphrase was successfully set. + * The call can fail, for example, if encrypting the data is disallowed. */ - // TODO(crbug.com/1139060): Use a clear signature which doesn't rely on - // syncPrefs. - setSyncEncryption(syncPrefs) {} + setEncryptionPassphrase(passphrase) {} + + /** + * Attempts to set the passphrase to decrypt Sync data. + * @param {string} passphrase + * @return {!Promise<boolean>} Whether the passphrase was successfully set. + * The call can fail, for example, if the passphrase is incorrect. + */ + setDecryptionPassphrase(passphrase) {} /** * Start syncing with an account, specified by its email. @@ -312,9 +317,13 @@ } /** @override */ - setSyncEncryption(syncPrefs) { - return cr.sendWithPromise( - 'SyncSetupSetEncryption', JSON.stringify(syncPrefs)); + setEncryptionPassphrase(passphrase) { + return cr.sendWithPromise('SyncSetupSetEncryptionPassphrase', passphrase); + } + + /** @override */ + setDecryptionPassphrase(passphrase) { + return cr.sendWithPromise('SyncSetupSetDecryptionPassphrase', passphrase); } /** @override */
diff --git a/chrome/browser/resources/settings/people_page/sync_encryption_options.js b/chrome/browser/resources/settings/people_page/sync_encryption_options.js index 98d8f48..0708d6c 100644 --- a/chrome/browser/resources/settings/people_page/sync_encryption_options.js +++ b/chrome/browser/resources/settings/people_page/sync_encryption_options.js
@@ -68,6 +68,13 @@ }, /** + * Whether there's a setEncryptionPassphrase() call pending response, in which + * case the component should wait before making a new call. + * @private {boolean} + */ + isSettingEncryptionPassphrase_: false, + + /** * Returns the encryption options CrRadioGroupElement. * @return {?CrRadioGroupElement} */ @@ -137,24 +144,26 @@ saveNewPassphrase_() { assert(this.creatingNewPassphrase_); chrome.metricsPrivate.recordUserAction('Sync_SaveNewPassphraseClicked'); - // Might happen within the transient time between the request to - // |setSyncEncryption| and receiving the response. - if (this.syncPrefs.setNewPassphrase) { + + if (this.isSettingEncryptionPassphrase_) { return; } + // If a new password has been entered but it is invalid, do not send the // sync state to the API. if (!this.validateCreatedPassphrases_()) { return; } - this.syncPrefs.setNewPassphrase = true; - this.syncPrefs.passphrase = this.passphrase_; - + this.isSettingEncryptionPassphrase_ = true; settings.SyncBrowserProxyImpl.getInstance() - .setSyncEncryption(this.syncPrefs) - .then(pageStatus => { - this.fire('passphrase-changed', pageStatus); + .setEncryptionPassphrase(this.passphrase_) + .then(successfullySet => { + // TODO(crbug.com/1139060): Rename the event, there is no change if + // |successfullySet| is false. It should also mention 'encryption + // passphrase' in its name. + this.fire('passphrase-changed', {didChange: successfullySet}); + this.isSettingEncryptionPassphrase_ = false; }); },
diff --git a/chrome/browser/resources/settings/people_page/sync_page.js b/chrome/browser/resources/settings/people_page/sync_page.js index 6469b5f..f31b881 100644 --- a/chrome/browser/resources/settings/people_page/sync_page.js +++ b/chrome/browser/resources/settings/people_page/sync_page.js
@@ -491,22 +491,23 @@ return; } - this.syncPrefs.setNewPassphrase = false; + this.browserProxy_.setDecryptionPassphrase(this.existingPassphrase_) + .then( + sucessfullySet => this.handlePageStatusChanged_( + sucessfullySet ? settings.PageStatus.DONE : + settings.PageStatus.PASSPHRASE_FAILED)); - this.syncPrefs.passphrase = this.existingPassphrase_; this.existingPassphrase_ = ''; - - this.browserProxy_.setSyncEncryption(this.syncPrefs) - .then(this.handlePageStatusChanged_.bind(this)); }, /** * @private - * @param {!CustomEvent<!settings.PageStatus>} e + * @param {!CustomEvent<!{didChange: boolean}>} e */ onPassphraseChanged_(e) { this.handlePageStatusChanged_( - /** @type {!settings.PageStatus} */ (e.detail)); + e.detail.didChange ? settings.PageStatus.DONE : + settings.PageStatus.PASSPHRASE_FAILED); }, /**
diff --git a/chrome/browser/search_engines/template_url_service_sync_unittest.cc b/chrome/browser/search_engines/template_url_service_sync_unittest.cc index e2d2c10..27a851fb 100644 --- a/chrome/browser/search_engines/template_url_service_sync_unittest.cc +++ b/chrome/browser/search_engines/template_url_service_sync_unittest.cc
@@ -143,7 +143,8 @@ change_map_.erase(change_map_.begin(), change_map_.end()); for (auto iter = change_list.begin(); iter != change_list.end(); ++iter) - change_map_[GetGUID(iter->sync_data())] = *iter; + change_map_.emplace(GetGUID(iter->sync_data()), *iter); + return base::nullopt; }
diff --git a/chrome/browser/settings/android/java/src/org/chromium/chrome/browser/settings/SettingsActivityTestRule.java b/chrome/browser/settings/android/java/src/org/chromium/chrome/browser/settings/SettingsActivityTestRule.java index 250dbd2e..22bcb58 100644 --- a/chrome/browser/settings/android/java/src/org/chromium/chrome/browser/settings/SettingsActivityTestRule.java +++ b/chrome/browser/settings/android/java/src/org/chromium/chrome/browser/settings/SettingsActivityTestRule.java
@@ -8,17 +8,15 @@ import android.content.Intent; import android.os.Bundle; import android.support.test.InstrumentationRegistry; -import android.support.test.rule.ActivityTestRule; +import android.support.test.runner.lifecycle.Stage; import androidx.fragment.app.Fragment; -import org.hamcrest.Matchers; import org.junit.Assert; -import org.chromium.base.ActivityState; -import org.chromium.base.ApplicationStatus; -import org.chromium.base.test.util.Criteria; -import org.chromium.base.test.util.CriteriaHelper; +import org.chromium.base.test.BaseActivityTestRule; +import org.chromium.base.test.util.ApplicationTestUtils; + /** * Activity test rule that launch {@link SettingsActivity} in tests. * @@ -28,7 +26,7 @@ * @param <T> Fragment that will be attached to the SettingsActivity. */ public class SettingsActivityTestRule<T extends Fragment> - extends ActivityTestRule<SettingsActivity> { + extends BaseActivityTestRule<SettingsActivity> { private final Class<T> mFragmentClass; /** @@ -36,16 +34,7 @@ * @param fragmentClass Fragment that will be attached after the activity starts. */ public SettingsActivityTestRule(Class<T> fragmentClass) { - this(fragmentClass, false); - } - - /** - * Create the settings activity test rule with an specific fragment class. - * @param fragmentClass Fragment that will be attached after the activity starts. - * @param initialTouchMode Whether in touch mode after the activity starts. - */ - public SettingsActivityTestRule(Class<T> fragmentClass, boolean initialTouchMode) { - super(SettingsActivity.class, initialTouchMode, false); + super(SettingsActivity.class); mFragmentClass = fragmentClass; } @@ -67,35 +56,9 @@ SettingsLauncher settingsLauncher = new SettingsLauncherImpl(); Intent intent = settingsLauncher.createSettingsActivityIntent( context, mFragmentClass.getName(), fragmentArgs); - SettingsActivity activity = super.launchActivity(intent); - Assert.assertNotNull(activity); - - return activity; - } - - /** - * We need to ensure that SettingsActivity gets destroyed in the TestRule because sometimes - * it uses the mock signin environment like fake AccountManagerFacade, if the activity starts - * with the stub then it also needs to finish with it. That's why we need to wait till the - * activity state becomes destroyed before tearing down the mock signin environment. - */ - @Override - protected void afterActivityFinished() { - super.afterActivityFinished(); - waitTillActivityIsDestroyed(); - } - - /** - * Block the execution till the SettingsActivity is destroyed. - */ - public void waitTillActivityIsDestroyed() { - SettingsActivity activity = getActivity(); - if (activity != null) { - CriteriaHelper.pollUiThread(() -> { - Criteria.checkThat(ApplicationStatus.getStateForActivity(activity), - Matchers.is(ActivityState.DESTROYED)); - }); - } + launchActivity(intent); + ApplicationTestUtils.waitForActivityState(getActivity(), Stage.RESUMED); + return getActivity(); } /**
diff --git a/chrome/browser/spellchecker/spellcheck_custom_dictionary.cc b/chrome/browser/spellchecker/spellcheck_custom_dictionary.cc index 887452b..57cfd3c 100644 --- a/chrome/browser/spellchecker/spellcheck_custom_dictionary.cc +++ b/chrome/browser/spellchecker/spellcheck_custom_dictionary.cc
@@ -401,8 +401,6 @@ dictionary_change->RemoveWord(word); break; case syncer::SyncChange::ACTION_UPDATE: - // Intentionally fall through. - case syncer::SyncChange::ACTION_INVALID: return syncer::ConvertToModelError( sync_error_handler_->CreateAndUploadError( FROM_HERE, "Processing sync changes failed on change type " +
diff --git a/chrome/browser/supervised_user/supervised_user_allowlist_service.cc b/chrome/browser/supervised_user/supervised_user_allowlist_service.cc index 2d8454a3..f03cf92 100644 --- a/chrome/browser/supervised_user/supervised_user_allowlist_service.cc +++ b/chrome/browser/supervised_user/supervised_user_allowlist_service.cc
@@ -258,10 +258,6 @@ allowlists_removed = true; break; } - case syncer::SyncChange::ACTION_INVALID: { - NOTREACHED(); - break; - } } }
diff --git a/chrome/browser/supervised_user/supervised_user_settings_service.cc b/chrome/browser/supervised_user/supervised_user_settings_service.cc index 0460c14d..4682b00 100644 --- a/chrome/browser/supervised_user/supervised_user_settings_service.cc +++ b/chrome/browser/supervised_user/supervised_user_settings_service.cc
@@ -351,10 +351,6 @@ dict->RemoveKey(key); break; } - case SyncChange::ACTION_INVALID: { - NOTREACHED(); - break; - } } } store_->ReportValueChanged(kAtomicSettings,
diff --git a/chrome/browser/ui/prefs/prefs_tab_helper.cc b/chrome/browser/ui/prefs/prefs_tab_helper.cc index 4a60728..1d2032c 100644 --- a/chrome/browser/ui/prefs/prefs_tab_helper.cc +++ b/chrome/browser/ui/prefs/prefs_tab_helper.cc
@@ -357,6 +357,7 @@ prefs::kEnableReferrers, !base::FeatureList::IsEnabled(features::kNoReferrers)); registry->RegisterBooleanPref(prefs::kEnableEncryptedMedia, true); + registry->RegisterBooleanPref(prefs::kEnableDRM, true); registry->RegisterBooleanPref(prefs::kScrollToTextFragmentEnabled, true); #if defined(OS_ANDROID) registry->RegisterDoublePref(prefs::kWebKitFontScaleFactor, 1.0);
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view.cc b/chrome/browser/ui/views/frame/browser_non_client_frame_view.cc index 06693bc..0a3adea 100644 --- a/chrome/browser/ui/views/frame/browser_non_client_frame_view.cc +++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view.cc
@@ -303,13 +303,13 @@ } bool should_leave_to_top_container = false; -#if BUILDFLAG(IS_CHROMEOS_ASH) +#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS) // In immersive mode, the caption buttons container is reparented to the // TopContainerView and hence |rect| should not be claimed here. See - // BrowserNonClientFrameViewAsh::OnImmersiveRevealStarted(). + // BrowserNonClientFrameViewChromeOS::OnImmersiveRevealStarted(). should_leave_to_top_container = browser_view_->immersive_mode_controller()->IsRevealed(); -#endif // BUILDFLAG(IS_CHROMEOS_ASH) +#endif if (!browser_view_->IsTabStripVisible()) { // Claim |rect| if it is above the top of the topmost client area view.
diff --git a/chrome/browser/ui/views/profiles/profile_picker_interactive_uitest.cc b/chrome/browser/ui/views/profiles/profile_picker_interactive_uitest.cc new file mode 100644 index 0000000..0410261 --- /dev/null +++ b/chrome/browser/ui/views/profiles/profile_picker_interactive_uitest.cc
@@ -0,0 +1,196 @@ +// 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 "chrome/browser/ui/views/profiles/profile_picker_view.h" + +#include "base/check.h" +#include "base/run_loop.h" +#include "base/test/mock_callback.h" +#include "build/build_config.h" +#include "chrome/browser/chrome_notification_types.h" +#include "chrome/browser/lifetime/browser_shutdown.h" +#include "chrome/browser/ui/profile_picker.h" +#include "chrome/browser/ui/views/profiles/profile_picker_test_base.h" +#include "chrome/test/base/interactive_test_utils.h" +#include "content/public/browser/notification_source.h" +#include "content/public/test/browser_test.h" +#include "content/public/test/browser_test_utils.h" +#include "content/public/test/test_utils.h" +#include "google_apis/gaia/gaia_urls.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "ui/events/keycodes/dom/dom_key.h" +#include "ui/views/view.h" +#include "ui/views/view_observer.h" +#include "ui/views/widget/widget.h" +#include "ui/views/widget/widget_observer.h" + +namespace { + +// Waits until a view is deleted. +class ViewDeletedWaiter : public views::ViewObserver { + public: + explicit ViewDeletedWaiter(views::View* view) { + DCHECK(view); + observation_.Observe(view); + } + ~ViewDeletedWaiter() override = default; + + // Waits until the view is deleted. + void Wait() { run_loop_.Run(); } + + private: + // ViewObserver: + void OnViewIsDeleting(views::View* observed_view) override { + run_loop_.Quit(); + } + + base::RunLoop run_loop_; + base::ScopedObservation<views::View, views::ViewObserver> observation_{this}; +}; + +// Waits until the widget bounds change. +class WidgetBoundsChangeWaiter : public views::WidgetObserver { + public: + explicit WidgetBoundsChangeWaiter(views::Widget* widget) { + DCHECK(widget); + observation_.Observe(widget); + } + + // Waits until the widget bounds change. + void Wait() { run_loop_.Run(); } + + private: + // WidgetObserver: + void OnWidgetBoundsChanged(views::Widget* widget, + const gfx::Rect& new_bounds) override { + run_loop_.Quit(); + } + + base::RunLoop run_loop_; + base::ScopedObservation<views::Widget, views::WidgetObserver> observation_{ + this}; +}; + +} // namespace + +class ProfilePickerInteractiveUiTest : public ProfilePickerTestBase { + public: + ProfilePickerInteractiveUiTest() = default; + ~ProfilePickerInteractiveUiTest() override = default; + + void SendCloseWindowKeyboardCommand() { + // Close window using keyboard. +#if defined(OS_MAC) + // Use Cmd-W on Mac. + bool control = false; + bool shift = false; + bool command = true; +#else + // Use Ctrl-Shift-W on other platforms. + bool control = true; + bool shift = true; + bool command = false; +#endif + ASSERT_TRUE(ui_test_utils::SendKeyPressToWindowSync( + widget()->GetNativeWindow(), ui::VKEY_W, control, shift, /*alt=*/false, + command)); + } + + void WaitForPickerClosed() { + if (!ProfilePicker::IsOpen()) + return; + ViewDeletedWaiter(view()).Wait(); + ASSERT_FALSE(ProfilePicker::IsOpen()); + } +}; + +// Checks that the main picker view can be closed with keyboard shortcut. +IN_PROC_BROWSER_TEST_F(ProfilePickerInteractiveUiTest, CloseWithKeyboard) { + // Open a new picker. + ProfilePicker::Show(ProfilePicker::EntryPoint::kProfileMenuManageProfiles); + WaitForNewWebView(); + WaitForFirstPaint(web_contents(), GURL("chrome://profile-picker")); + EXPECT_TRUE(ProfilePicker::IsOpen()); + SendCloseWindowKeyboardCommand(); + WaitForPickerClosed(); + // Closing the picker does not exit Chrome. + EXPECT_FALSE(browser_shutdown::IsTryingToQuit()); +} + +#if defined(OS_MAC) +// Checks that Chrome be closed with keyboard shortcut. Only MacOS has a +// keyboard shortcut to exit Chrome. +IN_PROC_BROWSER_TEST_F(ProfilePickerInteractiveUiTest, ExitWithKeyboard) { + // Open a new picker. + ProfilePicker::Show(ProfilePicker::EntryPoint::kProfileMenuManageProfiles); + WaitForNewWebView(); + WaitForFirstPaint(web_contents(), GURL("chrome://profile-picker")); + EXPECT_TRUE(ProfilePicker::IsOpen()); + + content::WindowedNotificationObserver terminate_observer( + chrome::NOTIFICATION_APP_TERMINATING, + content::NotificationService::AllSources()); + // Send Cmd-Q. + ASSERT_TRUE(ui_test_utils::SendKeyPressToWindowSync( + widget()->GetNativeWindow(), ui::VKEY_Q, /*control=*/false, + /*shift=*/false, /*alt=*/false, /*command=*/true)); + // Check that Chrome is quitting. + terminate_observer.Wait(); + WaitForPickerClosed(); + EXPECT_TRUE(browser_shutdown::IsTryingToQuit()); +} +#endif + +// Checks that the main picker view can switch to full screen. +IN_PROC_BROWSER_TEST_F(ProfilePickerInteractiveUiTest, FullscreenWithKeyboard) { + // Open a new picker. + ProfilePicker::Show(ProfilePicker::EntryPoint::kProfileMenuManageProfiles); + WaitForNewWebView(); + WaitForFirstPaint(web_contents(), GURL("chrome://profile-picker")); + EXPECT_TRUE(ProfilePicker::IsOpen()); + + EXPECT_FALSE(widget()->IsFullscreen()); + WidgetBoundsChangeWaiter bounds_waiter(widget()); + + // Toggle fullscreen with keyboard. +#if defined(OS_MAC) + // Use Cmd-Ctrl-F on Mac. + bool control = true; + bool command = true; + ui::KeyboardCode key_code = ui::VKEY_F; +#else + // Use F11 on other platforms. + bool control = false; + bool command = false; + ui::KeyboardCode key_code = ui::VKEY_F11; +#endif + ASSERT_TRUE(ui_test_utils::SendKeyPressToWindowSync( + widget()->GetNativeWindow(), key_code, control, /*shift=*/false, + /*alt=*/false, command)); + // Fullscreen causes the bounds of the widget to change. + bounds_waiter.Wait(); + EXPECT_TRUE(widget()->IsFullscreen()); +} + +// Checks that the signin web view is able to process keyboard events. +IN_PROC_BROWSER_TEST_F(ProfilePickerInteractiveUiTest, + CloseSigninWithKeyboard) { + ProfilePicker::Show(ProfilePicker::EntryPoint::kProfileMenuAddNewProfile); + WaitForNewWebView(); + + // Simulate a click on the signin button. + base::MockCallback<base::OnceClosure> switch_failure_callback; + EXPECT_CALL(switch_failure_callback, Run()).Times(0); + ProfilePicker::SwitchToSignIn(SK_ColorRED, switch_failure_callback.Get()); + + // Switch to the signin webview. + WaitForNewWebView(); + WaitForFirstPaint(web_contents(), + GaiaUrls::GetInstance()->signin_chrome_sync_dice()); + + // Close the picker with the keyboard. + EXPECT_TRUE(ProfilePicker::IsOpen()); + SendCloseWindowKeyboardCommand(); + WaitForPickerClosed(); +}
diff --git a/chrome/browser/ui/views/profiles/profile_picker_test_base.cc b/chrome/browser/ui/views/profiles/profile_picker_test_base.cc new file mode 100644 index 0000000..ac452a3 --- /dev/null +++ b/chrome/browser/ui/views/profiles/profile_picker_test_base.cc
@@ -0,0 +1,122 @@ +// 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 "chrome/browser/ui/views/profiles/profile_picker_test_base.h" + +#include "base/callback.h" +#include "base/run_loop.h" +#include "base/scoped_observation.h" +#include "chrome/browser/ui/profile_picker.h" +#include "chrome/browser/ui/ui_features.h" +#include "content/public/browser/web_contents.h" +#include "content/public/browser/web_contents_observer.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "ui/views/controls/webview/webview.h" +#include "ui/views/view.h" +#include "ui/views/view_observer.h" +#include "url/gurl.h" + +namespace { + +// Waits until a web view is added as a child view of the given view. +class WebViewAddedWaiter : public views::ViewObserver { + public: + WebViewAddedWaiter( + views::View* top_view, + base::RepeatingCallback<views::WebView*()> current_web_view_getter) + : current_web_view_getter_(current_web_view_getter) { + observation_.Observe(top_view); + } + ~WebViewAddedWaiter() override = default; + + void Wait() { run_loop_.Run(); } + + private: + // ViewObserver: + void OnChildViewAdded(views::View* observed_view, + views::View* child) override { + if (child == current_web_view_getter_.Run()) { + ASSERT_TRUE(child); + run_loop_.Quit(); + } + } + + base::RunLoop run_loop_; + base::RepeatingCallback<views::WebView*()> current_web_view_getter_; + base::ScopedObservation<views::View, views::ViewObserver> observation_{this}; +}; + +// Waits until a first non empty paint for given `url`. +class FirstVisuallyNonEmptyPaintObserver : public content::WebContentsObserver { + public: + explicit FirstVisuallyNonEmptyPaintObserver(content::WebContents* contents, + const GURL& url) + : content::WebContentsObserver(contents), url_(url) {} + + // Waits for the first paint. + void Wait() { + if (IsExitConditionSatisfied()) { + return; + } + run_loop_.Run(); + EXPECT_TRUE(IsExitConditionSatisfied()) + << web_contents()->GetVisibleURL() << " != " << url_; + } + + private: + // WebContentsObserver: + void DidFirstVisuallyNonEmptyPaint() override { + if (web_contents()->GetVisibleURL() == url_) + run_loop_.Quit(); + } + + bool IsExitConditionSatisfied() { + return (web_contents()->GetVisibleURL() == url_ && + web_contents()->CompletedFirstVisuallyNonEmptyPaint()); + } + + base::RunLoop run_loop_{base::RunLoop::Type::kNestableTasksAllowed}; + GURL url_; +}; + +} // namespace + +ProfilePickerTestBase::ProfilePickerTestBase() { + feature_list_.InitAndEnableFeature(features::kNewProfilePicker); +} + +ProfilePickerTestBase::~ProfilePickerTestBase() = default; + +views::View* ProfilePickerTestBase::view() { + return ProfilePicker::GetViewForTesting(); +} + +views::Widget* ProfilePickerTestBase::widget() { + return view() ? view()->GetWidget() : nullptr; +} + +views::WebView* ProfilePickerTestBase::web_view() { + return ProfilePicker::GetWebViewForTesting(); +} + +void ProfilePickerTestBase::WaitForNewWebView() { + ASSERT_TRUE(view()); + WebViewAddedWaiter(view(), + base::BindRepeating(&ProfilePickerTestBase::web_view, + base::Unretained(this))) + .Wait(); + EXPECT_TRUE(web_view()); +} + +void ProfilePickerTestBase::WaitForFirstPaint(content::WebContents* contents, + const GURL& url) { + DCHECK(contents); + FirstVisuallyNonEmptyPaintObserver(contents, url).Wait(); +} + +content::WebContents* ProfilePickerTestBase::web_contents() { + if (!web_view()) + return nullptr; + return web_view()->GetWebContents(); +}
diff --git a/chrome/browser/ui/views/profiles/profile_picker_test_base.h b/chrome/browser/ui/views/profiles/profile_picker_test_base.h new file mode 100644 index 0000000..7176045 --- /dev/null +++ b/chrome/browser/ui/views/profiles/profile_picker_test_base.h
@@ -0,0 +1,50 @@ +// 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 CHROME_BROWSER_UI_VIEWS_PROFILES_PROFILE_PICKER_TEST_BASE_H_ +#define CHROME_BROWSER_UI_VIEWS_PROFILES_PROFILE_PICKER_TEST_BASE_H_ + +#include "base/test/scoped_feature_list.h" +#include "chrome/test/base/in_process_browser_test.h" + +namespace content { +class WebContents; +} + +namespace views { +class View; +class WebView; +class Widget; +} // namespace views + +class GURL; + +class ProfilePickerTestBase : public InProcessBrowserTest { + public: + ProfilePickerTestBase(); + ~ProfilePickerTestBase() override; + + // Returns the ProfilePickerView that is currently displayed. + views::View* view(); + + // Returns the widget associated with the profile picker. + views::Widget* widget(); + + // Returns the internal web view for the profile picker. + views::WebView* web_view(); + + // Waits until a new internal web view has been added to the main picker view. + void WaitForNewWebView(); + + // Waits until the web contents does the first non-empty paint for `url`. + void WaitForFirstPaint(content::WebContents* contents, const GURL& url); + + // Gets the picker's web contents. + content::WebContents* web_contents(); + + private: + base::test::ScopedFeatureList feature_list_; +}; + +#endif // CHROME_BROWSER_UI_VIEWS_PROFILES_PROFILE_PICKER_TEST_BASE_H_
diff --git a/chrome/browser/ui/views/profiles/profile_picker_view.cc b/chrome/browser/ui/views/profiles/profile_picker_view.cc index 4e272524..3c0a000 100644 --- a/chrome/browser/ui/views/profiles/profile_picker_view.cc +++ b/chrome/browser/ui/views/profiles/profile_picker_view.cc
@@ -10,8 +10,10 @@ #include "base/metrics/histogram_functions.h" #include "base/strings/utf_string_conversions.h" #include "build/build_config.h" +#include "chrome/app/chrome_command_ids.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/extensions/chrome_extension_web_contents_observer.h" +#include "chrome/browser/lifetime/application_lifetime.h" #include "chrome/browser/profiles/profile_attributes_entry.h" #include "chrome/browser/profiles/profile_attributes_storage.h" #include "chrome/browser/profiles/profile_avatar_icon_util.h" @@ -24,11 +26,13 @@ #include "chrome/browser/ui/browser_finder.h" #include "chrome/browser/ui/browser_navigator.h" #include "chrome/browser/ui/browser_navigator_params.h" +#include "chrome/browser/ui/views/accelerator_table.h" #include "chrome/browser/ui/views/profiles/profile_picker_view_sync_delegate.h" #include "chrome/browser/ui/webui/signin/dice_turn_sync_on_helper.h" #include "chrome/browser/ui/webui/signin/profile_picker_ui.h" #include "chrome/browser/ui/webui/signin/signin_web_dialog_ui.h" #include "chrome/browser/ui/webui/signin/sync_confirmation_ui.h" +#include "chrome/common/pref_names.h" #include "chrome/common/webui_url_constants.h" #include "chrome/grit/chromium_strings.h" #include "chrome/grit/google_chrome_strings.h" @@ -51,6 +55,10 @@ #include "ui/views/win/hwnd_util.h" #endif +#if defined(OS_MAC) +#include "chrome/browser/global_keyboard_shortcuts_mac.h" +#endif + namespace { ProfilePickerView* g_profile_picker_view = nullptr; @@ -61,6 +69,10 @@ constexpr base::TimeDelta kExtendedAccountInfoTimeout = base::TimeDelta::FromSeconds(10); +constexpr int kSupportedAcceleratorCommands[] = { + IDC_CLOSE_TAB, IDC_CLOSE_WINDOW, IDC_EXIT, IDC_FULLSCREEN, + IDC_MINIMIZE_WINDOW}; + GURL CreateURLForEntryPoint(ProfilePicker::EntryPoint entry_point) { GURL base_url = GURL(chrome::kChromeUIProfilePickerUrl); switch (entry_point) { @@ -144,6 +156,7 @@ SetButtons(ui::DIALOG_BUTTON_NONE); SetTitle(IDS_PRODUCT_NAME); set_use_custom_frame(false); + ConfigureAccelerators(); // TODO(crbug.com/1063856): Add |RecordDialogCreation|. } @@ -201,16 +214,11 @@ void ProfilePickerView::Init(ProfilePicker::EntryPoint entry_point, Profile* system_profile) { DCHECK_EQ(state_, kInitializing); - auto web_view = std::make_unique<views::WebView>(system_profile); - web_view->GetWebContents()->SetDelegate(this); + CreateWebView(system_profile); + DCHECK(web_view_); // To record metrics using javascript, extensions are needed. extensions::ChromeExtensionWebContentsObserver::CreateForWebContents( - web_view->GetWebContents()); - // Set the member before adding to the hieararchy to make it easier for tests - // to detect that a new WebView has been created. - web_view_ = web_view.get(); - AddChildView(std::move(web_view)); - SetLayoutManager(std::make_unique<views::FillLayout>()); + web_view_->GetWebContents()); CreateDialogWidget(this, nullptr, nullptr); @@ -309,13 +317,7 @@ // Rebuild the view. // TODO(crbug.com/1126913): Add the simple toolbar with the back button. RemoveAllChildViews(true); - auto web_view = std::make_unique<views::WebView>(profile); - web_view->GetWebContents()->SetDelegate(this); - // Set the member before adding to the hieararchy to make it easier for tests - // to detect that a new WebView has been created. - web_view_ = web_view.get(); - AddChildView(std::move(web_view)); - SetLayoutManager(std::make_unique<views::FillLayout>()); + CreateWebView(profile); web_view_->LoadInitialURL(GaiaUrls::GetInstance()->signin_chrome_sync_dice()); web_view_->RequestFocus(); } @@ -359,6 +361,43 @@ return minimum_size; } +bool ProfilePickerView::AcceleratorPressed(const ui::Accelerator& accelerator) { + // Ignore presses of the Escape key. The profile picker may be Chrome's only + // top-level window, in which case we don't want presses of Esc to maybe quit + // the entire browser. This has higher priority than the default dialog Esc + // accelerator (which would otherwise close the window). + if (accelerator.key_code() == ui::VKEY_ESCAPE && + accelerator.modifiers() == ui::EF_NONE) { + return true; + } + + const auto& iter = accelerator_table_.find(accelerator); + DCHECK(iter != accelerator_table_.end()); + int command_id = iter->second; + switch (command_id) { + case IDC_CLOSE_TAB: + case IDC_CLOSE_WINDOW: + // kEscKeyPressed is used although that shortcut is disabled (this is + // Ctrl-Shift-W instead). + GetWidget()->CloseWithReason(views::Widget::ClosedReason::kEscKeyPressed); + break; + case IDC_EXIT: + chrome::AttemptUserExit(); + break; + case IDC_FULLSCREEN: + GetWidget()->SetFullscreen(!GetWidget()->IsFullscreen()); + break; + case IDC_MINIMIZE_WINDOW: + GetWidget()->Minimize(); + break; + default: + NOTREACHED() << "Unexpected command_id: " << command_id; + break; + } + + return true; +} + bool ProfilePickerView::HandleContextMenu( content::RenderFrameHost* render_frame_host, const content::ContextMenuParams& params) { @@ -366,6 +405,15 @@ return true; } +bool ProfilePickerView::HandleKeyboardEvent( + content::WebContents* source, + const content::NativeWebKeyboardEvent& event) { + // Forward the keyboard event to AcceleratorPressed() through the + // FocusManager. + return unhandled_keyboard_event_handler_.HandleKeyboardEvent( + event, GetFocusManager()); +} + void ProfilePickerView::AddNewContents( content::WebContents* source, std::unique_ptr<content::WebContents> new_contents, @@ -487,6 +535,10 @@ entry->SetIsEphemeral(false); entry->SetLocalProfileName(name_for_signed_in_profile_); + // Skip the FRE for this profile as it's replaced by profile creation flow. + signed_in_profile_being_created_->GetPrefs()->SetBoolean( + prefs::kHasSeenWelcomePage, true); + // TODO(crbug.com/1126913): Change the callback of // profiles::OpenBrowserWindowForProfile() to be a OnceCallback as it is only // called once. @@ -521,3 +573,44 @@ DCHECK(browser); std::move(finish_flow_callback).Run(browser); } + +void ProfilePickerView::ConfigureAccelerators() { + // By default, dialog views close when pressing escape. Override this + // behavior as the profile picker should not close in that case. + AddAccelerator(ui::Accelerator(ui::VKEY_ESCAPE, ui::EF_NONE)); + + const std::vector<AcceleratorMapping> accelerator_list(GetAcceleratorList()); + for (const auto& entry : accelerator_list) { + if (!base::Contains(kSupportedAcceleratorCommands, entry.command_id)) + continue; + ui::Accelerator accelerator(entry.keycode, entry.modifiers); + accelerator_table_[accelerator] = entry.command_id; + AddAccelerator(accelerator); + } + +#if defined(OS_MAC) + // Check Mac-specific accelerators. Note: Chrome does not support dynamic or + // user-configured accelerators on Mac. Default static accelerators are used + // instead. + for (int command_id : kSupportedAcceleratorCommands) { + ui::Accelerator accelerator; + bool mac_accelerator_found = + GetDefaultMacAcceleratorForCommandId(command_id, &accelerator); + if (mac_accelerator_found) { + accelerator_table_[accelerator] = command_id; + AddAccelerator(accelerator); + } + } +#endif // OS_MAC +} + +void ProfilePickerView::CreateWebView(Profile* profile) { + auto web_view = std::make_unique<views::WebView>(profile); + web_view->GetWebContents()->SetDelegate(this); + web_view->set_allow_accelerators(true); + // Set the member before adding to the hieararchy to make it easier for tests + // to detect that a new WebView has been created. + web_view_ = web_view.get(); + AddChildView(std::move(web_view)); + SetLayoutManager(std::make_unique<views::FillLayout>()); +}
diff --git a/chrome/browser/ui/views/profiles/profile_picker_view.h b/chrome/browser/ui/views/profiles/profile_picker_view.h index 7c470c2a..9141802 100644 --- a/chrome/browser/ui/views/profiles/profile_picker_view.h +++ b/chrome/browser/ui/views/profiles/profile_picker_view.h
@@ -11,6 +11,7 @@ #include "components/keep_alive_registry/scoped_keep_alive.h" #include "components/signin/public/identity_manager/identity_manager.h" #include "content/public/browser/web_contents_delegate.h" +#include "ui/views/controls/webview/unhandled_keyboard_event_handler.h" #include "ui/views/controls/webview/webview.h" #include "ui/views/window/dialog_delegate.h" @@ -72,6 +73,7 @@ // views::View; gfx::Size GetMinimumSize() const override; + bool AcceleratorPressed(const ui::Accelerator& accelerator) override; // content::WebContentsDelegate: bool HandleContextMenu(content::RenderFrameHost* render_frame_host, @@ -83,6 +85,9 @@ const gfx::Rect& initial_rect, bool user_gesture, bool* was_blocked) override; + bool HandleKeyboardEvent( + content::WebContents* source, + const content::NativeWebKeyboardEvent& event) override; // IdentityManager::Observer: void OnRefreshTokenUpdatedForAccount( @@ -104,9 +109,22 @@ Profile* profile, Profile::CreateStatus profile_create_status); + // Register basic keyboard accelerators such as closing the window (Alt-F4 + // on Windows). + void ConfigureAccelerators(); + + // Creates and configures the internal web view, and adds it as a child view. + void CreateWebView(Profile* profile); + ScopedKeepAlive keep_alive_; State state_ = State::kNotStarted; + // A mapping between accelerators and command IDs. + std::map<ui::Accelerator, int> accelerator_table_; + + // Handler for unhandled key events from renderer. + views::UnhandledKeyboardEventHandler unhandled_keyboard_event_handler_; + // The current WebView object, owned by the view hierarchy. views::WebView* web_view_ = nullptr;
diff --git a/chrome/browser/ui/views/profiles/profile_picker_view_browsertest.cc b/chrome/browser/ui/views/profiles/profile_picker_view_browsertest.cc index c22da81..f7f4af18 100644 --- a/chrome/browser/ui/views/profiles/profile_picker_view_browsertest.cc +++ b/chrome/browser/ui/views/profiles/profile_picker_view_browsertest.cc
@@ -25,6 +25,7 @@ #include "chrome/browser/ui/sync/profile_signin_confirmation_helper.h" #include "chrome/browser/ui/tab_dialogs.h" #include "chrome/browser/ui/ui_features.h" +#include "chrome/browser/ui/views/profiles/profile_picker_test_base.h" #include "chrome/browser/ui/webui/signin/login_ui_service.h" #include "chrome/browser/ui/webui/signin/login_ui_service_factory.h" #include "chrome/test/base/in_process_browser_test.h" @@ -38,12 +39,12 @@ #include "components/sync/driver/sync_driver_switches.h" #include "components/sync/driver/sync_service.h" #include "components/sync/driver/sync_user_settings.h" -#include "content/public/browser/web_contents_observer.h" +#include "content/public/browser/web_contents.h" #include "content/public/test/browser_test.h" #include "content/public/test/browser_test_utils.h" #include "google_apis/gaia/gaia_urls.h" #include "third_party/skia/include/core/SkColor.h" -#include "ui/views/view_observer.h" +#include "url/gurl.h" namespace { @@ -69,64 +70,6 @@ return account_info; } -// Waits until a first non empty paint for given `url`. -class FirstVisuallyNonEmptyPaintObserver : public content::WebContentsObserver { - public: - explicit FirstVisuallyNonEmptyPaintObserver(content::WebContents* contents, - const GURL& url) - : content::WebContentsObserver(contents), url_(url) {} - - void DidFirstVisuallyNonEmptyPaint() override { - if (web_contents()->GetVisibleURL() == url_) - run_loop_.Quit(); - } - - void Wait() { - if (IsExitConditionSatisfied()) { - return; - } - run_loop_.Run(); - EXPECT_TRUE(IsExitConditionSatisfied()) - << web_contents()->GetVisibleURL() << " != " << url_; - } - - private: - bool IsExitConditionSatisfied() { - return (web_contents()->GetVisibleURL() == url_ && - web_contents()->CompletedFirstVisuallyNonEmptyPaint()); - } - - base::RunLoop run_loop_{base::RunLoop::Type::kNestableTasksAllowed}; - GURL url_; -}; - -class WebViewAddedWaiter : public views::ViewObserver { - public: - WebViewAddedWaiter( - views::View* top_view, - base::RepeatingCallback<views::WebView*()> current_web_view_getter) - : current_web_view_getter_(current_web_view_getter) { - observation_.Observe(top_view); - } - ~WebViewAddedWaiter() override = default; - - void Wait() { run_loop_.Run(); } - - private: - // ViewObserver: - void OnChildViewAdded(views::View* observed_view, - views::View* child) override { - if (child == current_web_view_getter_.Run()) { - ASSERT_TRUE(child); - run_loop_.Quit(); - } - } - - base::RunLoop run_loop_; - base::RepeatingCallback<views::WebView*()> current_web_view_getter_; - base::ScopedObservation<views::View, views::ViewObserver> observation_{this}; -}; - class BrowserAddedWaiter : public BrowserListObserver { public: explicit BrowserAddedWaiter(size_t total_count) : total_count_(total_count) { @@ -256,15 +199,14 @@ base::RunLoop* run_loop_; }; -class ProfilePickerCreationFlowBrowserTest : public InProcessBrowserTest { +class ProfilePickerCreationFlowBrowserTest : public ProfilePickerTestBase { public: ProfilePickerCreationFlowBrowserTest() { - feature_list_.InitWithFeatures( - {features::kProfilesUIRevamp, features::kNewProfilePicker}, {}); + feature_list_.InitAndEnableFeature(features::kProfilesUIRevamp); } void SetUpInProcessBrowserTestFixture() override { - InProcessBrowserTest::SetUpInProcessBrowserTestFixture(); + ProfilePickerTestBase::SetUpInProcessBrowserTestFixture(); create_services_subscription_ = BrowserContextDependencyManager::GetInstance() ->RegisterCreateServicesCallbackForTesting( @@ -279,26 +221,6 @@ context, base::BindRepeating(&FakeUserPolicySigninService::Build)); } - views::View* view() { return ProfilePicker::GetViewForTesting(); } - - views::WebView* web_view() { return ProfilePicker::GetWebViewForTesting(); } - - void WaitForNewWebView() { - ASSERT_TRUE(view()); - WebViewAddedWaiter( - view(), - base::BindRepeating(&ProfilePickerCreationFlowBrowserTest::web_view, - base::Unretained(this))) - .Wait(); - EXPECT_TRUE(web_view()); - } - - content::WebContents* web_contents() { - if (!web_view()) - return nullptr; - return web_view()->GetWebContents(); - } - private: base::CallbackListSubscription create_services_subscription_; base::test::ScopedFeatureList feature_list_; @@ -324,9 +246,8 @@ ProfilePicker::Show(ProfilePicker::EntryPoint::kProfileMenuAddNewProfile); WaitForNewWebView(); EXPECT_TRUE(ProfilePicker::IsOpen()); - FirstVisuallyNonEmptyPaintObserver( - web_contents(), GURL("chrome://profile-picker/new-profile")) - .Wait(); + WaitForFirstPaint(web_contents(), + GURL("chrome://profile-picker/new-profile")); } IN_PROC_BROWSER_TEST_F(ProfilePickerCreationFlowBrowserTest, @@ -344,9 +265,8 @@ // The DICE navigation happens in a new web view (for the profile being // created), wait for it. WaitForNewWebView(); - FirstVisuallyNonEmptyPaintObserver( - web_contents(), GaiaUrls::GetInstance()->signin_chrome_sync_dice()) - .Wait(); + WaitForFirstPaint(web_contents(), + GaiaUrls::GetInstance()->signin_chrome_sync_dice()); // Add an account - simulate a successful Gaia sign-in. Profile* profile_being_created = @@ -365,18 +285,14 @@ // Wait for the sign-in to propagate to the flow, resulting in sync // confirmation screen getting displayed. - FirstVisuallyNonEmptyPaintObserver(web_contents(), - GURL("chrome://sync-confirmation/")) - .Wait(); + WaitForFirstPaint(web_contents(), GURL("chrome://sync-confirmation/")); // Simulate closing the UI with "Yes, I'm in". LoginUIServiceFactory::GetForProfile(profile_being_created) ->SyncConfirmationUIClosed(LoginUIService::SYNC_WITH_DEFAULT_SETTINGS); Browser* new_browser = BrowserAddedWaiter(2u).Wait(); - FirstVisuallyNonEmptyPaintObserver( - new_browser->tab_strip_model()->GetActiveWebContents(), - GURL("chrome://newtab/")) - .Wait(); + WaitForFirstPaint(new_browser->tab_strip_model()->GetActiveWebContents(), + GURL("chrome://newtab/")); // Check expectations when the profile creation flow is done. EXPECT_FALSE(ProfilePicker::IsOpen()); @@ -411,9 +327,8 @@ // The DICE navigation happens in a new web view (for the profile being // created), wait for it. WaitForNewWebView(); - FirstVisuallyNonEmptyPaintObserver( - web_contents(), GaiaUrls::GetInstance()->signin_chrome_sync_dice()) - .Wait(); + WaitForFirstPaint(web_contents(), + GaiaUrls::GetInstance()->signin_chrome_sync_dice()); // Disable sync by setting the device as managed in prefs. Profile* profile_being_created = @@ -437,10 +352,8 @@ // Wait for the sign-in to propagate to the flow, resulting in new browser // getting opened. Browser* new_browser = BrowserAddedWaiter(2u).Wait(); - FirstVisuallyNonEmptyPaintObserver( - new_browser->tab_strip_model()->GetActiveWebContents(), - GURL("chrome://newtab/")) - .Wait(); + WaitForFirstPaint(new_browser->tab_strip_model()->GetActiveWebContents(), + GURL("chrome://newtab/")); EXPECT_FALSE(ProfilePicker::IsOpen()); @@ -478,9 +391,8 @@ // The DICE navigation happens in a new web view (for the profile being // created), wait for it. WaitForNewWebView(); - FirstVisuallyNonEmptyPaintObserver( - web_contents(), GaiaUrls::GetInstance()->signin_chrome_sync_dice()) - .Wait(); + WaitForFirstPaint(web_contents(), + GaiaUrls::GetInstance()->signin_chrome_sync_dice()); // Add an account - simulate a successful Gaia sign-in. Profile* profile_being_created = @@ -497,18 +409,14 @@ // Wait for the sign-in to propagate to the flow, resulting in sync // confirmation screen getting displayed. - FirstVisuallyNonEmptyPaintObserver(web_contents(), - GURL("chrome://sync-confirmation/")) - .Wait(); + WaitForFirstPaint(web_contents(), GURL("chrome://sync-confirmation/")); // Simulate closing the UI with "Yes, I'm in". LoginUIServiceFactory::GetForProfile(profile_being_created) ->SyncConfirmationUIClosed(LoginUIService::CONFIGURE_SYNC_FIRST); Browser* new_browser = BrowserAddedWaiter(2u).Wait(); - FirstVisuallyNonEmptyPaintObserver( - new_browser->tab_strip_model()->GetActiveWebContents(), - GURL("chrome://settings/syncSetup")) - .Wait(); + WaitForFirstPaint(new_browser->tab_strip_model()->GetActiveWebContents(), + GURL("chrome://settings/syncSetup")); // Check expectations when the profile creation flow is done. EXPECT_FALSE(ProfilePicker::IsOpen()); @@ -544,9 +452,8 @@ // The DICE navigation happens in a new web view (for the profile being // created), wait for it. WaitForNewWebView(); - FirstVisuallyNonEmptyPaintObserver( - web_contents(), GaiaUrls::GetInstance()->signin_chrome_sync_dice()) - .Wait(); + WaitForFirstPaint(web_contents(), + GaiaUrls::GetInstance()->signin_chrome_sync_dice()); // Simulate clicking on a link that opens in a new window. const GURL kURL("https://foo.google.com"); @@ -561,9 +468,8 @@ // A new pppup browser is displayed (with the specified URL). Browser* new_browser = BrowserAddedWaiter(2u).Wait(); EXPECT_EQ(new_browser->type(), Browser::TYPE_POPUP); - FirstVisuallyNonEmptyPaintObserver( - new_browser->tab_strip_model()->GetActiveWebContents(), kURL) - .Wait(); + WaitForFirstPaint(new_browser->tab_strip_model()->GetActiveWebContents(), + kURL); } // TODO(crbug.com/1144065): Flaky on multiple platforms. @@ -606,9 +512,8 @@ // The DICE navigation happens in a new web view (for the profile being // created), wait for it. WaitForNewWebView(); - FirstVisuallyNonEmptyPaintObserver( - web_contents(), GaiaUrls::GetInstance()->signin_chrome_sync_dice()) - .Wait(); + WaitForFirstPaint(web_contents(), + GaiaUrls::GetInstance()->signin_chrome_sync_dice()); // Add an account - simulate a successful Gaia sign-in. Profile* profile_being_created = @@ -625,10 +530,8 @@ // Instead of sync confirmation, a browser is displayed (with a login error). Browser* new_browser = BrowserAddedWaiter(2u).Wait(); - FirstVisuallyNonEmptyPaintObserver( - new_browser->tab_strip_model()->GetActiveWebContents(), - GURL("chrome://newtab/")) - .Wait(); + WaitForFirstPaint(new_browser->tab_strip_model()->GetActiveWebContents(), + GURL("chrome://newtab/")); // Check expectations when the profile creation flow is done. EXPECT_FALSE(ProfilePicker::IsOpen()); @@ -659,9 +562,8 @@ // The DICE navigation happens in a new web view (for the profile being // created), wait for it. WaitForNewWebView(); - FirstVisuallyNonEmptyPaintObserver( - web_contents(), GaiaUrls::GetInstance()->signin_chrome_sync_dice()) - .Wait(); + WaitForFirstPaint(web_contents(), + GaiaUrls::GetInstance()->signin_chrome_sync_dice()); Profile* profile_being_created = static_cast<Profile*>(web_view()->GetBrowserContext()); @@ -680,18 +582,14 @@ // Wait for the sign-in to propagate to the flow, resulting in sync // confirmation screen getting displayed. - FirstVisuallyNonEmptyPaintObserver(web_contents(), - GURL("chrome://sync-confirmation/")) - .Wait(); + WaitForFirstPaint(web_contents(), GURL("chrome://sync-confirmation/")); // Simulate closing the UI with "Yes, I'm in". LoginUIServiceFactory::GetForProfile(profile_being_created) ->SyncConfirmationUIClosed(LoginUIService::SYNC_WITH_DEFAULT_SETTINGS); Browser* new_browser = BrowserAddedWaiter(2u).Wait(); - FirstVisuallyNonEmptyPaintObserver( - new_browser->tab_strip_model()->GetActiveWebContents(), - GURL("chrome://newtab/")) - .Wait(); + WaitForFirstPaint(new_browser->tab_strip_model()->GetActiveWebContents(), + GURL("chrome://newtab/")); // Check expectations when the profile creation flow is done. EXPECT_FALSE(ProfilePicker::IsOpen()); @@ -740,9 +638,8 @@ // The DICE navigation happens in a new web view (for the profile being // created), wait for it. WaitForNewWebView(); - FirstVisuallyNonEmptyPaintObserver( - web_contents(), GaiaUrls::GetInstance()->signin_chrome_sync_dice()) - .Wait(); + WaitForFirstPaint(web_contents(), + GaiaUrls::GetInstance()->signin_chrome_sync_dice()); // Add an account - simulate a successful Gaia sign-in. Profile* profile_being_created = @@ -775,10 +672,8 @@ // The picker should be closed even before the enterprise confirmation but it // is closed asynchronously after opening the browser so after the NTP // renders, it is safe to check. - FirstVisuallyNonEmptyPaintObserver( - new_browser->tab_strip_model()->GetActiveWebContents(), - GURL("chrome://newtab/")) - .Wait(); + WaitForFirstPaint(new_browser->tab_strip_model()->GetActiveWebContents(), + GURL("chrome://newtab/")); EXPECT_FALSE(ProfilePicker::IsOpen()); // Now the sync consent screen is shown, simulate closing the UI with "Yes, @@ -814,9 +709,8 @@ // The DICE navigation happens in a new web view (for the profile being // created), wait for it. WaitForNewWebView(); - FirstVisuallyNonEmptyPaintObserver( - web_contents(), GaiaUrls::GetInstance()->signin_chrome_sync_dice()) - .Wait(); + WaitForFirstPaint(web_contents(), + GaiaUrls::GetInstance()->signin_chrome_sync_dice()); // Add an account - simulate a successful Gaia sign-in. Profile* profile_being_created = @@ -849,10 +743,8 @@ // "Configure sync". LoginUIServiceFactory::GetForProfile(profile_being_created) ->SyncConfirmationUIClosed(LoginUIService::CONFIGURE_SYNC_FIRST); - FirstVisuallyNonEmptyPaintObserver( - new_browser->tab_strip_model()->GetActiveWebContents(), - GURL("chrome://settings/syncSetup")) - .Wait(); + WaitForFirstPaint(new_browser->tab_strip_model()->GetActiveWebContents(), + GURL("chrome://settings/syncSetup")); // Check expectations when the profile creation flow is done. EXPECT_FALSE(ProfilePicker::IsOpen());
diff --git a/chrome/browser/ui/webui/settings/people_handler.cc b/chrome/browser/ui/webui/settings/people_handler.cc index 66cfbd2b..b31cbad 100644 --- a/chrome/browser/ui/webui/settings/people_handler.cc +++ b/chrome/browser/ui/webui/settings/people_handler.cc
@@ -84,8 +84,6 @@ bool sync_everything; syncer::UserSelectableTypeSet selected_types; bool payments_integration_enabled; - std::string passphrase; - bool set_new_passphrase; }; bool IsSyncSubpage(const GURL& current_url) { @@ -93,9 +91,7 @@ } SyncConfigInfo::SyncConfigInfo() - : sync_everything(false), - payments_integration_enabled(false), - set_new_passphrase(false) {} + : sync_everything(false), payments_integration_enabled(false) {} SyncConfigInfo::~SyncConfigInfo() {} @@ -132,13 +128,6 @@ config->selected_types.Put(type); } - // Passphrase settings. - if (result->GetString("passphrase", &config->passphrase) && - !config->passphrase.empty() && - !result->GetBoolean("setNewPassphrase", &config->set_new_passphrase)) { - DLOG(ERROR) << "GetConfiguration() not passed a set_new_passphrase value"; - return false; - } return true; } @@ -276,8 +265,12 @@ base::BindRepeating(&PeopleHandler::HandleSetDatatypes, base::Unretained(this))); web_ui()->RegisterMessageCallback( - "SyncSetupSetEncryption", - base::BindRepeating(&PeopleHandler::HandleSetEncryption, + "SyncSetupSetEncryptionPassphrase", + base::BindRepeating(&PeopleHandler::HandleSetEncryptionPassphrase, + base::Unretained(this))); + web_ui()->RegisterMessageCallback( + "SyncSetupSetDecryptionPassphrase", + base::BindRepeating(&PeopleHandler::HandleSetDecryptionPassphrase, base::Unretained(this))); web_ui()->RegisterMessageCallback( "SyncSetupShowSetupUI", @@ -527,79 +520,72 @@ #endif } -void PeopleHandler::HandleSetEncryption(const base::ListValue* args) { - SyncConfigInfo configuration; - const base::Value* callback_id = nullptr; - ParseConfigurationArguments(args, &configuration, &callback_id); +void PeopleHandler::HandleSetEncryptionPassphrase(const base::ListValue* args) { + const base::Value& callback_id = args->GetList()[0]; - // Start configuring the SyncService using the configuration passed to us from - // the JS layer. - syncer::SyncService* service = GetSyncService(); - - // If the sync engine has shutdown for some reason, just close the sync - // dialog. - if (!service || !service->IsEngineInitialized()) { + // Check the SyncService is up and running before retrieving SyncUserSettings, + // which contains the encryption-related APIs. + if (!GetSyncService() || !GetSyncService()->IsEngineInitialized()) { + // TODO(crbug.com/1139060): HandleSetDatatypes() also returns a success + // status in this case. Consider returning a failure in both methods. Maybe + // the CloseSyncSetup() call can also be removed. CloseSyncSetup(); - ResolveJavascriptCallback(*callback_id, base::Value(kDonePageStatus)); + ResolveJavascriptCallback(callback_id, base::Value(true)); return; } + syncer::SyncUserSettings* sync_user_settings = + GetSyncService()->GetUserSettings(); - if (service->GetUserSettings()->IsEncryptEverythingAllowed()) { - ProfileMetrics::LogProfileSyncInfo(ProfileMetrics::SYNC_ENCRYPT); + const std::string& passphrase = args->GetList()[1].GetString(); + bool successfully_set = false; + if (passphrase.empty()) { + successfully_set = false; + } else if (!sync_user_settings->IsEncryptEverythingAllowed()) { + successfully_set = false; + } else if (sync_user_settings->IsUsingSecondaryPassphrase()) { + // In case a passphrase is already being used, changing to a new one isn't + // currently supported (one must reset all the Sync data). + successfully_set = false; + } else if (sync_user_settings->IsPassphraseRequired() || + sync_user_settings->IsTrustedVaultKeyRequired()) { + // Can't re-encrypt the data with |passphrase| if some of it hasn't even + // been decrypted yet due to a pending passphrase / trusted vault key. + successfully_set = false; } else { - // Don't allow "set new passphrase" if the SyncService doesn't allow it. - // The UI is hidden, but the user may have enabled it e.g. by fiddling with - // the web inspector. - configuration.set_new_passphrase = false; + sync_user_settings->SetEncryptionPassphrase(passphrase); + successfully_set = true; + ProfileMetrics::LogProfileSyncInfo( + ProfileMetrics::SYNC_CREATED_NEW_PASSPHRASE); } + ResolveJavascriptCallback(callback_id, base::Value(successfully_set)); +} - bool passphrase_failed = false; - if (!configuration.passphrase.empty()) { - // We call IsPassphraseRequired() here (instead of - // IsPassphraseRequiredForPreferredDataTypes()) because the user may try to - // enter a passphrase even though no encrypted data types are enabled. - if (service->GetUserSettings()->IsPassphraseRequired()) { - // If we have pending keys, try to decrypt them with the provided - // passphrase. We track if this succeeds or fails because a failed - // decryption should result in an error even if there aren't any encrypted - // data types. - passphrase_failed = !service->GetUserSettings()->SetDecryptionPassphrase( - configuration.passphrase); - } else if (service->GetUserSettings()->IsTrustedVaultKeyRequired()) { - // There are pending keys due to trusted vault keys being required, likely - // because something changed since the UI was displayed. A passphrase - // cannot be set in such circumstances. - passphrase_failed = true; - } else { - // OK, the user sent us a passphrase, but we don't have pending keys. So - // it either means that the pending keys were resolved somehow since the - // time the UI was displayed (re-encryption, pending passphrase change, - // etc) or the user wants to re-encrypt. - if (configuration.set_new_passphrase && - !service->GetUserSettings()->IsUsingSecondaryPassphrase()) { - service->GetUserSettings()->SetEncryptionPassphrase( - configuration.passphrase); - } +void PeopleHandler::HandleSetDecryptionPassphrase(const base::ListValue* args) { + const base::Value& callback_id = args->GetList()[0]; + + // Check the SyncService is up and running before retrieving SyncUserSettings, + // which contains the encryption-related APIs. + if (!GetSyncService() || !GetSyncService()->IsEngineInitialized()) { + // TODO(crbug.com/1139060): HandleSetDatatypes() also returns a success + // status in this case. Consider returning a failure in both methods. Maybe + // the CloseSyncSetup() call can also be removed. + CloseSyncSetup(); + ResolveJavascriptCallback(callback_id, base::Value(true)); + return; + } + syncer::SyncUserSettings* sync_user_settings = + GetSyncService()->GetUserSettings(); + + const std::string& passphrase = args->GetList()[1].GetString(); + bool successfully_set = false; + if (!passphrase.empty() && sync_user_settings->IsPassphraseRequired()) { + successfully_set = sync_user_settings->SetDecryptionPassphrase(passphrase); + if (successfully_set) { + ProfileMetrics::LogProfileSyncInfo( + ProfileMetrics::SYNC_ENTERED_EXISTING_PASSPHRASE); } } - - if (passphrase_failed || - service->GetUserSettings()->IsPassphraseRequiredForPreferredDataTypes()) { - // If the user doesn't enter any passphrase, we won't call - // SetDecryptionPassphrase() (passphrase_failed == false), but we still - // want to display an error message to let the user know that their blank - // passphrase entry is not acceptable. - - // TODO(tommycli): Switch this to RejectJavascriptCallback once the - // Sync page JavaScript has been further refactored. - ResolveJavascriptCallback(*callback_id, - base::Value(kPassphraseFailedPageStatus)); - } else { - ResolveJavascriptCallback(*callback_id, base::Value(kConfigurePageStatus)); - } - - if (!configuration.set_new_passphrase && !configuration.passphrase.empty()) - ProfileMetrics::LogProfileSyncInfo(ProfileMetrics::SYNC_PASSPHRASE); + ResolveJavascriptCallback(callback_id, base::Value(successfully_set)); } void PeopleHandler::HandleShowSyncSetupUI(const base::ListValue* args) {
diff --git a/chrome/browser/ui/webui/settings/people_handler.h b/chrome/browser/ui/webui/settings/people_handler.h index b6013d93..c50237f 100644 --- a/chrome/browser/ui/webui/settings/people_handler.h +++ b/chrome/browser/ui/webui/settings/people_handler.h
@@ -87,14 +87,16 @@ FRIEND_TEST_ALL_PREFIXES(PeopleHandlerTest, TestSyncEverything); FRIEND_TEST_ALL_PREFIXES(PeopleHandlerTest, TestSyncAllManually); FRIEND_TEST_ALL_PREFIXES(PeopleHandlerTest, NonRegisteredType); - FRIEND_TEST_ALL_PREFIXES(PeopleHandlerTest, TestPassphraseStillRequired); + FRIEND_TEST_ALL_PREFIXES(PeopleHandlerTest, EnterCorrectExistingPassphrase); FRIEND_TEST_ALL_PREFIXES(PeopleHandlerTest, TestSyncIndividualTypes); FRIEND_TEST_ALL_PREFIXES(PeopleHandlerTest, - EnterExistingFrozenImplicitPassword); - FRIEND_TEST_ALL_PREFIXES(PeopleHandlerTest, SetNewCustomPassphrase); + SuccessfullyCreateCustomPassphrase); FRIEND_TEST_ALL_PREFIXES(PeopleHandlerTest, EnterWrongExistingPassphrase); - FRIEND_TEST_ALL_PREFIXES(PeopleHandlerTest, EnterBlankExistingPassphrase); - FRIEND_TEST_ALL_PREFIXES(PeopleHandlerTest, TurnOnEncryptAllDisallowed); + FRIEND_TEST_ALL_PREFIXES(PeopleHandlerTest, CannotCreateBlankPassphrase); + FRIEND_TEST_ALL_PREFIXES(PeopleHandlerTest, + CannotCreatePassphraseIfEncryptEverythingDisallowed); + FRIEND_TEST_ALL_PREFIXES(PeopleHandlerTest, + CannotOverwritePassphraseWithNewOne); FRIEND_TEST_ALL_PREFIXES(PeopleHandlerTest, UnrecoverableErrorInitializingSync); FRIEND_TEST_ALL_PREFIXES(PeopleHandlerTest, GaiaErrorInitializingSync); @@ -152,7 +154,8 @@ void HandleGetProfileInfo(const base::ListValue* args); void OnDidClosePage(const base::ListValue* args); void HandleSetDatatypes(const base::ListValue* args); - void HandleSetEncryption(const base::ListValue* args); + void HandleSetEncryptionPassphrase(const base::ListValue* args); + void HandleSetDecryptionPassphrase(const base::ListValue* args); void HandleShowSyncSetupUI(const base::ListValue* args); void HandleSyncPrefsDispatch(const base::ListValue* args); #if BUILDFLAG(IS_CHROMEOS_ASH)
diff --git a/chrome/browser/ui/webui/settings/people_handler_unittest.cc b/chrome/browser/ui/webui/settings/people_handler_unittest.cc index ccc0fcaf..1700d9e7 100644 --- a/chrome/browser/ui/webui/settings/people_handler_unittest.cc +++ b/chrome/browser/ui/webui/settings/people_handler_unittest.cc
@@ -78,26 +78,12 @@ CHOOSE_WHAT_TO_SYNC }; -enum EncryptAllConfig { - ENCRYPT_ALL_DATA, - ENCRYPT_PASSWORDS -}; - // Create a json-format string with the key/value pairs appropriate for a call -// to HandleSetEncryption(). If |extra_values| is non-null, then the values from -// the passed dictionary are added to the json. -std::string GetConfiguration(const base::DictionaryValue* extra_values, - SyncAllDataConfig sync_all, - syncer::UserSelectableTypeSet types, - const std::string& passphrase, - EncryptAllConfig encrypt_all) { +// to HandleSetDatatypes(). +std::string GetConfiguration(SyncAllDataConfig sync_all, + syncer::UserSelectableTypeSet types) { base::DictionaryValue result; - if (extra_values) - result.MergeDictionary(extra_values); result.SetBoolean("syncAllDataTypes", sync_all == SYNC_ALL_DATA); - result.SetBoolean("encryptAllData", encrypt_all == ENCRYPT_ALL_DATA); - if (!passphrase.empty()) - result.SetString("passphrase", passphrase); // Add all of our data types. result.SetBoolean("appsSynced", types.Has(syncer::UserSelectableType::kApps)); result.SetBoolean("autofillSynced", @@ -314,6 +300,21 @@ EXPECT_EQ(expected_status, status); } + // Expects a call to ResolveJavascriptCallback() with |should_succeed| as its + // argument. + void ExpectSetPassphraseSuccess(bool should_succeed) { + EXPECT_EQ(1u, web_ui_.call_data().size()); + const auto& data = *web_ui_.call_data()[0]; + EXPECT_EQ("cr.webUIResponse", data.function_name()); + EXPECT_TRUE(data.arg2()->is_bool()); + EXPECT_TRUE(data.arg2()->GetBool()) + << "Callback should be resolved with a boolean indicating the success, " + "never rejected."; + + EXPECT_TRUE(data.arg3()->is_bool()); + EXPECT_EQ(should_succeed, data.arg3()->GetBool()); + } + const base::DictionaryValue* ExpectSyncPrefsChanged() { const content::TestWebUI::CallData& data1 = *web_ui_.call_data().back(); EXPECT_EQ("cr.webUIListenerCallback", data1.function_name()); @@ -638,8 +639,7 @@ TEST_F(PeopleHandlerTest, TestSyncEverything) { SigninUser(); CreatePeopleHandler(); - std::string args = GetConfiguration(nullptr, SYNC_ALL_DATA, GetAllTypes(), - std::string(), ENCRYPT_PASSWORDS); + std::string args = GetConfiguration(SYNC_ALL_DATA, GetAllTypes()); base::ListValue list_args; list_args.AppendString(kTestCallbackId); list_args.AppendString(args); @@ -656,147 +656,119 @@ ExpectPageStatusResponse(PeopleHandler::kConfigurePageStatus); } -TEST_F(PeopleHandlerTest, TestPassphraseStillRequired) { +TEST_F(PeopleHandlerTest, EnterCorrectExistingPassphrase) { SigninUser(); CreatePeopleHandler(); - std::string args = GetConfiguration(nullptr, SYNC_ALL_DATA, GetAllTypes(), - std::string(), ENCRYPT_PASSWORDS); - base::ListValue list_args; - list_args.AppendString(kTestCallbackId); - list_args.AppendString(args); - ON_CALL(*mock_sync_service_->GetMockUserSettings(), - IsPassphraseRequiredForPreferredDataTypes()) - .WillByDefault(Return(true)); + SetupInitializedSyncService(); + ON_CALL(*mock_sync_service_->GetMockUserSettings(), IsPassphraseRequired()) .WillByDefault(Return(true)); ON_CALL(*mock_sync_service_->GetMockUserSettings(), - IsUsingSecondaryPassphrase()) - .WillByDefault(Return(false)); - SetupInitializedSyncService(); - SetDefaultExpectationsForConfigPage(); - - handler_->HandleSetEncryption(&list_args); - // We should navigate back to the configure page since we need a passphrase. - ExpectPageStatusResponse(PeopleHandler::kPassphraseFailedPageStatus); -} - -TEST_F(PeopleHandlerTest, EnterExistingFrozenImplicitPassword) { - SigninUser(); - CreatePeopleHandler(); - base::DictionaryValue dict; - dict.SetBoolean("setNewPassphrase", false); - std::string args = GetConfiguration(&dict, SYNC_ALL_DATA, GetAllTypes(), - "oldGaiaPassphrase", ENCRYPT_PASSWORDS); - base::ListValue list_args; - list_args.AppendString(kTestCallbackId); - list_args.AppendString(args); - // Act as if an encryption passphrase is required the first time, then never - // again after that. - EXPECT_CALL(*mock_sync_service_->GetMockUserSettings(), - IsPassphraseRequired()) - .WillOnce(Return(true)); - ON_CALL(*mock_sync_service_->GetMockUserSettings(), - IsPassphraseRequiredForPreferredDataTypes()) + IsTrustedVaultKeyRequired()) .WillByDefault(Return(false)); ON_CALL(*mock_sync_service_->GetMockUserSettings(), IsUsingSecondaryPassphrase()) - .WillByDefault(Return(false)); - SetupInitializedSyncService(); - EXPECT_CALL(*mock_sync_service_->GetMockUserSettings(), - SetDecryptionPassphrase("oldGaiaPassphrase")) - .WillOnce(Return(true)); - - handler_->HandleSetEncryption(&list_args); - ExpectPageStatusResponse(PeopleHandler::kConfigurePageStatus); -} - -TEST_F(PeopleHandlerTest, SetNewCustomPassphrase) { - SigninUser(); - CreatePeopleHandler(); - base::DictionaryValue dict; - dict.SetBoolean("setNewPassphrase", true); - std::string args = GetConfiguration(&dict, SYNC_ALL_DATA, GetAllTypes(), - "custom_passphrase", ENCRYPT_ALL_DATA); - base::ListValue list_args; - list_args.AppendString(kTestCallbackId); - list_args.AppendString(args); + .WillByDefault(Return(true)); ON_CALL(*mock_sync_service_->GetMockUserSettings(), IsEncryptEverythingAllowed()) .WillByDefault(Return(true)); - ON_CALL(*mock_sync_service_->GetMockUserSettings(), - IsPassphraseRequiredForPreferredDataTypes()) - .WillByDefault(Return(false)); + + EXPECT_CALL(*mock_sync_service_->GetMockUserSettings(), + SetDecryptionPassphrase("correct_passphrase")) + .WillOnce(Return(true)); + + base::ListValue list_args; + list_args.AppendString(kTestCallbackId); + list_args.AppendString("correct_passphrase"); + handler_->HandleSetDecryptionPassphrase(&list_args); + + ExpectSetPassphraseSuccess(true); +} + +TEST_F(PeopleHandlerTest, SuccessfullyCreateCustomPassphrase) { + SigninUser(); + CreatePeopleHandler(); + SetupInitializedSyncService(); + ON_CALL(*mock_sync_service_->GetMockUserSettings(), IsPassphraseRequired()) .WillByDefault(Return(false)); ON_CALL(*mock_sync_service_->GetMockUserSettings(), + IsTrustedVaultKeyRequired()) + .WillByDefault(Return(false)); + ON_CALL(*mock_sync_service_->GetMockUserSettings(), IsUsingSecondaryPassphrase()) .WillByDefault(Return(false)); - SetupInitializedSyncService(); + ON_CALL(*mock_sync_service_->GetMockUserSettings(), + IsEncryptEverythingAllowed()) + .WillByDefault(Return(true)); + EXPECT_CALL(*mock_sync_service_->GetMockUserSettings(), SetEncryptionPassphrase("custom_passphrase")); - handler_->HandleSetEncryption(&list_args); - ExpectPageStatusResponse(PeopleHandler::kConfigurePageStatus); + base::ListValue list_args; + list_args.AppendString(kTestCallbackId); + list_args.AppendString("custom_passphrase"); + handler_->HandleSetEncryptionPassphrase(&list_args); + + ExpectSetPassphraseSuccess(true); } TEST_F(PeopleHandlerTest, EnterWrongExistingPassphrase) { SigninUser(); CreatePeopleHandler(); - base::DictionaryValue dict; - dict.SetBoolean("setNewPassphrase", false); - std::string args = GetConfiguration(&dict, SYNC_ALL_DATA, GetAllTypes(), - "invalid_passphrase", ENCRYPT_ALL_DATA); - base::ListValue list_args; - list_args.AppendString(kTestCallbackId); - list_args.AppendString(args); - ON_CALL(*mock_sync_service_->GetMockUserSettings(), - IsPassphraseRequiredForPreferredDataTypes()) - .WillByDefault(Return(true)); + SetupInitializedSyncService(); + ON_CALL(*mock_sync_service_->GetMockUserSettings(), IsPassphraseRequired()) .WillByDefault(Return(true)); ON_CALL(*mock_sync_service_->GetMockUserSettings(), - IsUsingSecondaryPassphrase()) + IsTrustedVaultKeyRequired()) .WillByDefault(Return(false)); - SetupInitializedSyncService(); + ON_CALL(*mock_sync_service_->GetMockUserSettings(), + IsUsingSecondaryPassphrase()) + .WillByDefault(Return(true)); + ON_CALL(*mock_sync_service_->GetMockUserSettings(), + IsEncryptEverythingAllowed()) + .WillByDefault(Return(true)); + EXPECT_CALL(*mock_sync_service_->GetMockUserSettings(), SetDecryptionPassphrase("invalid_passphrase")) .WillOnce(Return(false)); - SetDefaultExpectationsForConfigPage(); - - handler_->HandleSetEncryption(&list_args); - // We should navigate back to the configure page since we need a passphrase. - ExpectPageStatusResponse(PeopleHandler::kPassphraseFailedPageStatus); -} - -TEST_F(PeopleHandlerTest, EnterBlankExistingPassphrase) { - SigninUser(); - CreatePeopleHandler(); - base::DictionaryValue dict; - dict.SetBoolean("setNewPassphrase", false); - std::string args = GetConfiguration(&dict, - SYNC_ALL_DATA, - GetAllTypes(), - "", - ENCRYPT_PASSWORDS); base::ListValue list_args; list_args.AppendString(kTestCallbackId); - list_args.AppendString(args); - ON_CALL(*mock_sync_service_->GetMockUserSettings(), - IsPassphraseRequiredForPreferredDataTypes()) - .WillByDefault(Return(true)); + list_args.AppendString("invalid_passphrase"); + handler_->HandleSetDecryptionPassphrase(&list_args); + + ExpectSetPassphraseSuccess(false); +} + +TEST_F(PeopleHandlerTest, CannotCreateBlankPassphrase) { + SigninUser(); + CreatePeopleHandler(); + SetupInitializedSyncService(); + ON_CALL(*mock_sync_service_->GetMockUserSettings(), IsPassphraseRequired()) - .WillByDefault(Return(true)); + .WillByDefault(Return(false)); + ON_CALL(*mock_sync_service_->GetMockUserSettings(), + IsTrustedVaultKeyRequired()) + .WillByDefault(Return(false)); ON_CALL(*mock_sync_service_->GetMockUserSettings(), IsUsingSecondaryPassphrase()) .WillByDefault(Return(false)); - SetupInitializedSyncService(); + ON_CALL(*mock_sync_service_->GetMockUserSettings(), + IsEncryptEverythingAllowed()) + .WillByDefault(Return(true)); - SetDefaultExpectationsForConfigPage(); + EXPECT_CALL(*mock_sync_service_->GetMockUserSettings(), + SetEncryptionPassphrase) + .Times(0); - handler_->HandleSetEncryption(&list_args); - // We should navigate back to the configure page since we need a passphrase. - ExpectPageStatusResponse(PeopleHandler::kPassphraseFailedPageStatus); + base::ListValue list_args; + list_args.AppendString(kTestCallbackId); + list_args.AppendString(""); + handler_->HandleSetEncryptionPassphrase(&list_args); + + ExpectSetPassphraseSuccess(false); } // Walks through each user selectable type, and tries to sync just that single @@ -808,9 +780,7 @@ for (syncer::UserSelectableType type : GetAllTypes()) { syncer::UserSelectableTypeSet type_to_set; type_to_set.Put(type); - std::string args = - GetConfiguration(nullptr, CHOOSE_WHAT_TO_SYNC, type_to_set, - std::string(), ENCRYPT_PASSWORDS); + std::string args = GetConfiguration(CHOOSE_WHAT_TO_SYNC, type_to_set); base::ListValue list_args; list_args.AppendString(kTestCallbackId); list_args.AppendString(args); @@ -833,9 +803,7 @@ SigninUser(); CreatePeopleHandler(); SetDefaultExpectationsForConfigPage(); - std::string args = - GetConfiguration(nullptr, CHOOSE_WHAT_TO_SYNC, GetAllTypes(), - std::string(), ENCRYPT_PASSWORDS); + std::string args = GetConfiguration(CHOOSE_WHAT_TO_SYNC, GetAllTypes()); base::ListValue list_args; list_args.AppendString(kTestCallbackId); list_args.AppendString(args); @@ -867,9 +835,7 @@ // Simulate "Sync everything" being turned off, but all individual // toggles left on. - std::string config = - GetConfiguration(/*extra_values=*/nullptr, CHOOSE_WHAT_TO_SYNC, - GetAllTypes(), std::string(), ENCRYPT_PASSWORDS); + std::string config = GetConfiguration(CHOOSE_WHAT_TO_SYNC, GetAllTypes()); base::ListValue list_args; list_args.AppendString(kTestCallbackId); list_args.AppendString(config); @@ -1078,34 +1044,62 @@ CheckBool(dictionary, "encryptAllDataAllowed", false); } -TEST_F(PeopleHandlerTest, TurnOnEncryptAllDisallowed) { +TEST_F(PeopleHandlerTest, CannotCreatePassphraseIfEncryptEverythingDisallowed) { SigninUser(); CreatePeopleHandler(); - ON_CALL(*mock_sync_service_->GetMockUserSettings(), - IsPassphraseRequiredForPreferredDataTypes()) - .WillByDefault(Return(false)); + SetupInitializedSyncService(); + ON_CALL(*mock_sync_service_->GetMockUserSettings(), IsPassphraseRequired()) .WillByDefault(Return(false)); - SetupInitializedSyncService(); + ON_CALL(*mock_sync_service_->GetMockUserSettings(), + IsTrustedVaultKeyRequired()) + .WillByDefault(Return(false)); + ON_CALL(*mock_sync_service_->GetMockUserSettings(), + IsUsingSecondaryPassphrase()) + .WillByDefault(Return(false)); ON_CALL(*mock_sync_service_->GetMockUserSettings(), IsEncryptEverythingAllowed()) .WillByDefault(Return(false)); - base::DictionaryValue dict; - dict.SetBoolean("setNewPassphrase", true); - std::string args = GetConfiguration(&dict, SYNC_ALL_DATA, GetAllTypes(), - "password", ENCRYPT_ALL_DATA); - base::ListValue list_args; - list_args.AppendString(kTestCallbackId); - list_args.AppendString(args); - EXPECT_CALL(*mock_sync_service_->GetMockUserSettings(), - SetEncryptionPassphrase(_)) + SetEncryptionPassphrase) .Times(0); - handler_->HandleSetEncryption(&list_args); + base::ListValue list_args; + list_args.AppendString(kTestCallbackId); + list_args.AppendString("passphrase123"); + handler_->HandleSetEncryptionPassphrase(&list_args); - ExpectPageStatusResponse(PeopleHandler::kConfigurePageStatus); + ExpectSetPassphraseSuccess(false); +} + +TEST_F(PeopleHandlerTest, CannotOverwritePassphraseWithNewOne) { + SigninUser(); + CreatePeopleHandler(); + SetupInitializedSyncService(); + + ON_CALL(*mock_sync_service_->GetMockUserSettings(), IsPassphraseRequired()) + .WillByDefault(Return(false)); + ON_CALL(*mock_sync_service_->GetMockUserSettings(), + IsTrustedVaultKeyRequired()) + .WillByDefault(Return(false)); + ON_CALL(*mock_sync_service_->GetMockUserSettings(), + IsUsingSecondaryPassphrase()) + .WillByDefault(Return(true)); + ON_CALL(*mock_sync_service_->GetMockUserSettings(), + IsEncryptEverythingAllowed()) + .WillByDefault(Return(true)); + + EXPECT_CALL(*mock_sync_service_->GetMockUserSettings(), + SetEncryptionPassphrase) + .Times(0); + + base::ListValue list_args; + list_args.AppendString(kTestCallbackId); + list_args.AppendString("passphrase123"); + handler_->HandleSetEncryptionPassphrase(&list_args); + + ExpectSetPassphraseSuccess(false); } TEST_F(PeopleHandlerTest, DashboardClearWhileSettingsOpen_ConfirmSoon) {
diff --git a/chrome/browser/web_applications/BUILD.gn b/chrome/browser/web_applications/BUILD.gn index 36cd911..55f09a6f 100644 --- a/chrome/browser/web_applications/BUILD.gn +++ b/chrome/browser/web_applications/BUILD.gn
@@ -87,6 +87,7 @@ "//components/services/app_service/public/cpp:app_url_handling", "//components/services/app_service/public/cpp:protocol_handling", "//components/sync", + "//components/user_manager", "//content/public/browser", "//services/metrics/public/cpp:ukm_builders", "//skia",
diff --git a/chrome/browser/web_applications/system_web_app_manager.cc b/chrome/browser/web_applications/system_web_app_manager.cc index b883366..38ba6ff 100644 --- a/chrome/browser/web_applications/system_web_app_manager.cc +++ b/chrome/browser/web_applications/system_web_app_manager.cc
@@ -35,6 +35,7 @@ #include "chrome/grit/generated_resources.h" #include "components/pref_registry/pref_registry_syncable.h" #include "components/prefs/pref_service.h" +#include "components/user_manager/user_manager.h" #include "components/version_info/version_info.h" #include "content/public/browser/navigation_handle.h" #include "content/public/browser/url_data_source.h" @@ -62,6 +63,7 @@ #include "chromeos/components/help_app_ui/url_constants.h" #include "chromeos/components/media_app_ui/url_constants.h" #include "chromeos/constants/chromeos_features.h" +#include "chromeos/constants/chromeos_pref_names.h" #include "chromeos/strings/grit/chromeos_strings.h" #include "components/policy/core/common/policy_pref_names.h" #include "extensions/common/constants.h" @@ -103,7 +105,8 @@ } #endif // BUILDFLAG(IS_CHROMEOS_ASH) -base::flat_map<SystemAppType, SystemAppInfo> CreateSystemWebApps() { +base::flat_map<SystemAppType, SystemAppInfo> CreateSystemWebApps( + Profile* profile) { base::flat_map<SystemAppType, SystemAppInfo> infos; // TODO(calamity): Split this into per-platform functions. #if BUILDFLAG(IS_CHROMEOS_ASH) @@ -117,8 +120,11 @@ SystemAppInfo( "Camera", GURL("chrome://camera-app/views/main.html"), base::BindRepeating(&CreateWebAppInfoForCameraSystemWebApp))); - infos.at(SystemAppType::CAMERA).uninstall_and_replace = { - extension_misc::kCameraAppId}; + if (!profile->GetPrefs()->GetBoolean( + chromeos::prefs::kHasCameraAppMigratedToSWA)) { + infos.at(SystemAppType::CAMERA).uninstall_and_replace = { + extension_misc::kCameraAppId}; + } // We need "FileHandling" to use File Handling API to set launch directory. // And we need "NativeFileSystem2" to use Native File System API. infos.at(SystemAppType::CAMERA).enabled_origin_trials = @@ -339,7 +345,8 @@ return true; case SystemAppType::CAMERA: return base::FeatureList::IsEnabled( - chromeos::features::kCameraSystemWebApp); + chromeos::features::kCameraSystemWebApp) && + !user_manager::UserManager::Get()->IsLoggedInAsGuest(); case SystemAppType::TERMINAL: return true; case SystemAppType::MEDIA: @@ -385,7 +392,7 @@ // Populate with real system apps if the test asks for it. if (base::FeatureList::IsEnabled(features::kEnableAllSystemWebApps)) - system_app_infos_ = CreateSystemWebApps(); + system_app_infos_ = CreateSystemWebApps(profile_); return; } @@ -398,7 +405,7 @@ update_policy_ = UpdatePolicy::kAlwaysUpdate; #endif - system_app_infos_ = CreateSystemWebApps(); + system_app_infos_ = CreateSystemWebApps(profile_); } SystemWebAppManager::~SystemWebAppManager() = default; @@ -491,7 +498,7 @@ void SystemWebAppManager::InstallSystemAppsForTesting() { on_apps_synchronized_.reset(new base::OneShotEvent()); - system_app_infos_ = CreateSystemWebApps(); + system_app_infos_ = CreateSystemWebApps(profile_); Start(); // Wait for the System Web Apps to install. @@ -804,6 +811,13 @@ on_apps_synchronized_->Signal(); OnAppsPolicyChanged(); } + +#if BUILDFLAG(IS_CHROMEOS_ASH) + bool is_camera_app_installed = + system_app_infos_.find(SystemAppType::CAMERA) != system_app_infos_.end(); + profile_->GetPrefs()->SetBoolean(chromeos::prefs::kHasCameraAppMigratedToSWA, + is_camera_app_installed); +#endif // BUILDFLAG(IS_CHROMEOS_ASH) } bool SystemWebAppManager::ShouldForceInstallApps() const {
diff --git a/chrome/browser/webshare/share_service_impl.cc b/chrome/browser/webshare/share_service_impl.cc index d249c55..7bfc923 100644 --- a/chrome/browser/webshare/share_service_impl.cc +++ b/chrome/browser/webshare/share_service_impl.cc
@@ -177,7 +177,8 @@ #elif defined(OS_WIN) auto share_operation = std::make_unique<webshare::ShareOperation>( title, text, share_url, std::move(files), web_contents); - share_operation->Run(base::BindOnce( + auto* const share_operation_ptr = share_operation.get(); + share_operation_ptr->Run(base::BindOnce( [](std::unique_ptr<webshare::ShareOperation> share_operation, ShareCallback callback, blink::mojom::ShareError result) { std::move(callback).Run(result); },
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt index 2730933..3e9e892 100644 --- a/chrome/build/linux.pgo.txt +++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@ -chrome-linux-master-1606348564-f9ad4c8126c0686f48279a254d0d8ff9696d692f.profdata +chrome-linux-master-1606391943-c49ce66f4f03ab73428a9c9ccbc70b089767b5c2.profdata
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt index db33405..d5b80cf3 100644 --- a/chrome/build/mac.pgo.txt +++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@ -chrome-mac-master-1606348564-46558a518073e70dc3e85439edab882c7abb26f5.profdata +chrome-mac-master-1606391943-6f31c76b4f9e93d1de26d5f38d730905e1d3f7a7.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt index db14604..1b89595 100644 --- a/chrome/build/win32.pgo.txt +++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@ -chrome-win32-master-1606066622-6c4da226bf03284a24fb3e251f76a24f1e8c9c69.profdata +chrome-win32-master-1606359294-a78100f1c02315e3a2df0ee09ef21dd127ea538b.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt index 9b9063e..f88a255 100644 --- a/chrome/build/win64.pgo.txt +++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@ -chrome-win64-master-1606316157-945260897cb0815b47df3e1edecdf8b6cf6cb896.profdata +chrome-win64-master-1606380888-a2312ebb2792a371a28e16249fe53f8f1a9dbcea.profdata
diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc index 28df0b0..bc11079b 100644 --- a/chrome/common/pref_names.cc +++ b/chrome/common/pref_names.cc
@@ -2633,8 +2633,6 @@ // re-created. const char kAppShortcutsArch[] = "apps.shortcuts_arch"; -// A string pref for storing the salt used to compute the pepper device ID. -const char kDRMSalt[] = "settings.privacy.drm_salt"; // A boolean pref that enables the (private) pepper GetDeviceID() call and // enables the use of remote attestation for content protection. const char kEnableDRM[] = "settings.privacy.drm_enabled";
diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h index c3f3597..f8eb7798 100644 --- a/chrome/common/pref_names.h +++ b/chrome/common/pref_names.h
@@ -885,7 +885,6 @@ extern const char kAppShortcutsVersion[]; extern const char kAppShortcutsArch[]; -extern const char kDRMSalt[]; extern const char kEnableDRM[]; extern const char kWatchdogExtensionActive[];
diff --git a/chrome/renderer/BUILD.gn b/chrome/renderer/BUILD.gn index 03d9d4c..01fc562 100644 --- a/chrome/renderer/BUILD.gn +++ b/chrome/renderer/BUILD.gn
@@ -197,7 +197,6 @@ "//mojo/public/cpp/bindings", "//net", "//ppapi/buildflags", - "//ppapi/shared_impl", "//printing/buildflags", "//services/metrics/public/cpp:metrics_cpp", "//services/metrics/public/cpp:ukm_builders",
diff --git a/chrome/renderer/chrome_content_renderer_client.cc b/chrome/renderer/chrome_content_renderer_client.cc index b0b945a..79159efa 100644 --- a/chrome/renderer/chrome_content_renderer_client.cc +++ b/chrome/renderer/chrome_content_renderer_client.cc
@@ -128,7 +128,6 @@ #include "mojo/public/cpp/bindings/remote.h" #include "net/base/net_errors.h" #include "ppapi/buildflags/buildflags.h" -#include "ppapi/shared_impl/ppapi_switches.h" #include "printing/buildflags/buildflags.h" #include "services/network/public/cpp/is_potentially_trustworthy.h" #include "services/service_manager/public/cpp/interface_provider.h" @@ -196,6 +195,7 @@ #if BUILDFLAG(ENABLE_PLUGINS) #include "chrome/common/plugin_utils.h" #include "chrome/renderer/plugins/chrome_plugin_placeholder.h" +#include "ppapi/shared_impl/ppapi_switches.h" // nogncheck crbug.com/1125897 #else #include "components/plugins/renderer/plugin_placeholder.h" #endif
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index b8c9b01..569cddb 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -2679,6 +2679,7 @@ "../browser/chromeos/policy/device_system_use_24hour_clock_browsertest.cc", "../browser/chromeos/policy/display_resolution_handler_browsertest.cc", "../browser/chromeos/policy/display_rotation_default_handler_browsertest.cc", + "../browser/chromeos/policy/dlp/data_transfer_dlp_controller_browsertest.cc", "../browser/chromeos/policy/dlp/dlp_content_manager_browsertest.cc", "../browser/chromeos/policy/dlp/dlp_rules_manager_browsertest.cc", "../browser/chromeos/policy/dlp/dlp_rules_manager_test_utils.cc", @@ -3182,8 +3183,7 @@ [ "../browser/site_isolation/spellcheck_per_process_browsertest.cc" ] } - if (is_win || is_mac || - ((is_linux || is_chromeos_lacros) && !is_chromeos_lacros)) { + if (is_win || is_mac || (is_linux && !is_chromeos_lacros)) { sources += [ "../browser/ui/views/profiles/profile_picker_view_browsertest.cc" ] } @@ -6319,6 +6319,12 @@ "../browser/password_manager/password_manager_signin_intercept_test_helper.h", ] } + if (is_win || is_mac || (is_linux && !is_chromeos_lacros)) { + sources += [ + "../browser/ui/views/profiles/profile_picker_test_base.cc", + "../browser/ui/views/profiles/profile_picker_test_base.h", + ] + } } proto_library("test_proto") { @@ -6474,37 +6480,6 @@ "ppapi/ppapi_interactive_browsertest.cc", ] - if (is_mac) { - sources += [ - "../browser/apps/platform_apps/app_shim_interactive_uitest_mac.mm", - "../browser/apps/platform_apps/app_shim_quit_interactive_uitest_mac.mm", - "../browser/global_keyboard_shortcuts_mac_browsertest.mm", - "../browser/spellchecker/spellcheck_mac_view_interactive_uitest.mm", - "../browser/ui/cocoa/apps/quit_with_apps_controller_mac_interactive_uitest.mm", - "../browser/ui/cocoa/status_bubble_mac_interactive_uitest.mm", - "../browser/ui/cocoa/tab_contents/web_contents_view_mac_interactive_uitest.mm", - "base/interactive_test_utils_mac.mm", - ] - } - - if (is_win) { - sources += [ - "../browser/ui/send_mouse_move_uitest_win.cc", - "../browser/ui/views/accessibility/navigation_accessibility_uitest_win.cc", - "base/always_on_top_window_killer_win.cc", - "base/always_on_top_window_killer_win.h", - "base/interactive_test_utils_win.cc", - "base/save_desktop_snapshot_win.cc", - "base/save_desktop_snapshot_win.h", - "base/window_contents_as_string_win.cc", - "base/window_contents_as_string_win.h", - ] - - if (use_aura) { - sources += [ "../browser/ui/views/autofill/autofill_accessibility_win_browsertest.cc" ] - } - } - configs += [ "//build/config:precompiled_headers" ] if ((is_linux || is_chromeos) && !is_component_build) { configs += [ "//build/config/gcc:rpath_for_built_shared_libraries" ] @@ -6695,11 +6670,6 @@ } } - if (is_mac) { - sources += - [ "../browser/notifications/notification_interactive_uitest_mac.mm" ] - } - if (is_chromeos_ash) { deps += [ "//chrome/browser/media/router:test_support", @@ -6726,10 +6696,24 @@ "../browser/notifications/notification_platform_bridge_win_interactive_uitest.cc", "../browser/notifications/win/fake_itoastnotifier.cc", "../browser/notifications/win/fake_itoastnotifier.h", + "../browser/ui/send_mouse_move_uitest_win.cc", + "../browser/ui/views/accessibility/navigation_accessibility_uitest_win.cc", "../browser/ui/views/accessibility/uia_accessibility_event_waiter.cc", "../browser/ui/views/accessibility/uia_accessibility_event_waiter.h", "../browser/ui/views/touch_events_interactive_uitest_win.cc", + "base/always_on_top_window_killer_win.cc", + "base/always_on_top_window_killer_win.h", + "base/interactive_test_utils_win.cc", + "base/save_desktop_snapshot_win.cc", + "base/save_desktop_snapshot_win.h", + "base/window_contents_as_string_win.cc", + "base/window_contents_as_string_win.h", ] + + if (use_aura) { + sources += [ "../browser/ui/views/autofill/autofill_accessibility_win_browsertest.cc" ] + } + deps += [ "//chrome:other_version", "//chrome/app:chrome_dll_resources", @@ -6750,7 +6734,18 @@ } if (is_mac) { - sources += [ "../browser/ui/find_bar/find_bar_platform_helper_mac_interactive_uitest.mm" ] + sources += [ + "../browser/apps/platform_apps/app_shim_interactive_uitest_mac.mm", + "../browser/apps/platform_apps/app_shim_quit_interactive_uitest_mac.mm", + "../browser/global_keyboard_shortcuts_mac_browsertest.mm", + "../browser/notifications/notification_interactive_uitest_mac.mm", + "../browser/spellchecker/spellcheck_mac_view_interactive_uitest.mm", + "../browser/ui/cocoa/apps/quit_with_apps_controller_mac_interactive_uitest.mm", + "../browser/ui/cocoa/status_bubble_mac_interactive_uitest.mm", + "../browser/ui/cocoa/tab_contents/web_contents_view_mac_interactive_uitest.mm", + "../browser/ui/find_bar/find_bar_platform_helper_mac_interactive_uitest.mm", + "base/interactive_test_utils_mac.mm", + ] sources -= [ # TODO(crbug.com/1026820): Re-enable this test when history backend failures are addressed. @@ -6813,6 +6808,12 @@ sources += [ "../browser/ui/views/frame/webui_tab_strip_interactive_uitest.cc" ] } + + if (is_win || is_mac || (is_linux && !is_chromeos_lacros)) { + sources += [ + "../browser/ui/views/profiles/profile_picker_interactive_uitest.cc", + ] + } } }
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeActivityTestRule.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeActivityTestRule.java index be13b4b..ec2abf63 100644 --- a/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeActivityTestRule.java +++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeActivityTestRule.java
@@ -5,30 +5,31 @@ package org.chromium.chrome.test; import android.app.Activity; -import android.app.Instrumentation; import android.content.ComponentName; import android.content.Intent; import android.net.Uri; import android.os.Bundle; import android.support.test.InstrumentationRegistry; import android.support.test.internal.runner.listener.InstrumentationResultPrinter; -import android.support.test.rule.ActivityTestRule; import android.view.Menu; +import androidx.annotation.NonNull; + import org.hamcrest.Matchers; import org.junit.Assert; import org.junit.Rule; import org.junit.runner.Description; import org.junit.runners.model.Statement; -import org.chromium.base.ActivityState; import org.chromium.base.ApplicationStatus; -import org.chromium.base.ApplicationStatus.ActivityStateListener; import org.chromium.base.CommandLine; -import org.chromium.base.Log; +import org.chromium.base.ThreadUtils; +import org.chromium.base.test.BaseActivityTestRule; import org.chromium.base.test.util.CallbackHelper; import org.chromium.base.test.util.Criteria; import org.chromium.base.test.util.CriteriaHelper; +import org.chromium.base.test.util.ScalableTimeout; +import org.chromium.chrome.browser.DeferredStartupHandler; import org.chromium.chrome.browser.app.ChromeActivity; import org.chromium.chrome.browser.document.ChromeLauncherActivity; import org.chromium.chrome.browser.flags.ChromeFeatureList; @@ -41,7 +42,9 @@ import org.chromium.chrome.browser.ui.appmenu.AppMenuTestSupport; import org.chromium.chrome.test.util.ChromeApplicationTestUtils; import org.chromium.chrome.test.util.ChromeTabUtils; +import org.chromium.chrome.test.util.NewTabPageTestUtils; import org.chromium.chrome.test.util.browser.Features; +import org.chromium.components.embedder_support.util.UrlUtilities; import org.chromium.components.infobars.InfoBar; import org.chromium.content_public.browser.LoadUrlParams; import org.chromium.content_public.browser.WebContents; @@ -59,14 +62,13 @@ import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicReference; /** * Custom {@link ActivityTestRule} for test using {@link ChromeActivity}. * * @param <T> The {@link Activity} class under test. */ -public class ChromeActivityTestRule<T extends ChromeActivity> extends ActivityTestRule<T> { +public class ChromeActivityTestRule<T extends ChromeActivity> extends BaseActivityTestRule<T> { private static final String TAG = "ChromeATR"; // The number of ms to wait for the rendering activity to be started. @@ -75,20 +77,13 @@ private static final long OMNIBOX_FIND_SUGGESTION_TIMEOUT_MS = 10 * 1000; private Thread.UncaughtExceptionHandler mDefaultUncaughtExceptionHandler; - private Class<T> mChromeActivityClass; - private T mSetActivity; private String mCurrentTestName; @Rule private EmbeddedTestServerRule mTestServerRule = new EmbeddedTestServerRule(); protected ChromeActivityTestRule(Class<T> activityClass) { - this(activityClass, false); - } - - protected ChromeActivityTestRule(Class<T> activityClass, boolean initialTouchMode) { - super(activityClass, initialTouchMode, false); - mChromeActivityClass = activityClass; + super(activityClass); } @Override @@ -135,13 +130,11 @@ return ACTIVITY_START_TIMEOUT_MS; } - // TODO(yolandyan): remove this once startActivityCompletely is refactored out of - // ChromeActivityTestRule + // This has to be here or getActivity will return a T that extends Activity, not a T that + // extends ChromeActivity. @Override + @SuppressWarnings("RedundantOverride") public T getActivity() { - if (mSetActivity != null) { - return mSetActivity; - } return super.getActivity(); } @@ -152,6 +145,14 @@ } /** + * TODO(https://crbug.com/1146574): This only exists here because legacy ActivityTestRule + * inherited from UiThreadTestRule. This function should be removed. + */ + public void runOnUiThread(Runnable r) { + ThreadUtils.runOnUiThreadBlocking(r); + } + + /** * @return The {@link AppMenuCoordinator} for the activity. */ public AppMenuCoordinator getAppMenuCoordinator() { @@ -196,49 +197,37 @@ } /** - * Invokes {@link Instrumentation#startActivitySync(Intent)} and sets the - * test case's activity to the result. See the documentation for - * {@link Instrumentation#startActivitySync(Intent)} on the timing of the - * return, but generally speaking the activity's "onCreate" has completed - * and the activity's main looper has become idle. - * - * TODO(yolandyan): very similar to ActivityTestRule#launchActivity(Intent), - * yet small differences remains (e.g. launchActivity() uses FLAG_ACTIVITY_NEW_TASK while - * startActivityCompletely doesn't), need to refactor and use only launchActivity - * after the JUnit4 migration + * Similar to #launchActivity(Intent), but waits for the Activity tab to be initialized. */ public void startActivityCompletely(Intent intent) { - Features.ensureCommandLineIsUpToDate(); + DeferredStartupHandler.setExpectingActivityStartupForTesting(); + launchActivity(intent); + waitForActivityNativeInitializationComplete(); - final CallbackHelper activityCallback = new CallbackHelper(); - final AtomicReference<T> activityRef = new AtomicReference<>(); - ActivityStateListener stateListener = new ActivityStateListener() { - @SuppressWarnings("unchecked") - @Override - public void onActivityStateChange(Activity activity, int newState) { - if (newState == ActivityState.RESUMED) { - if (!mChromeActivityClass.isAssignableFrom(activity.getClass())) return; + CriteriaHelper.pollUiThread( + () -> getActivity().getActivityTab() != null, "Tab never selected/initialized."); + Tab tab = getActivity().getActivityTab(); - activityRef.set((T) activity); - activityCallback.notifyCalled(); - ApplicationStatus.unregisterActivityStateListener(this); - } - } - }; - ApplicationStatus.registerStateListenerForAllActivities(stateListener); + ChromeTabUtils.waitForTabPageLoaded(tab, (String) null); - try { - InstrumentationRegistry.getInstrumentation().startActivitySync(intent); - activityCallback.waitForCallback("Activity did not start as expected", 0); - T activity = activityRef.get(); - Assert.assertNotNull("Activity reference is null.", activity); - setActivity(activity); - Log.d(TAG, "startActivityCompletely <<"); - } catch (TimeoutException e) { - throw new RuntimeException(e); - } finally { - ApplicationStatus.unregisterActivityStateListener(stateListener); + if (tab != null && UrlUtilities.isNTPUrl(ChromeTabUtils.getUrlStringOnUiThread(tab)) + && !getActivity().isInOverviewMode()) { + NewTabPageTestUtils.waitForNtpLoaded(tab); } + + Assert.assertTrue("Deferred startup never completed. Did you try to start an Activity " + + "that was already started?", + DeferredStartupHandler.waitForDeferredStartupCompleteForTesting( + ScalableTimeout.scaleTimeout(CriteriaHelper.DEFAULT_MAX_TIME_TO_POLL))); + + Assert.assertNotNull(tab); + Assert.assertNotNull(tab.getView()); + } + + @Override + public void launchActivity(@NonNull Intent startIntent) { + Features.ensureCommandLineIsUpToDate(); + super.launchActivity(startIntent); } /** @@ -472,10 +461,6 @@ return getActivity().getWindowAndroid().getKeyboardDelegate(); } - public void setActivity(T chromeActivity) { - mSetActivity = chromeActivity; - } - /** * Waits for an Activity of the given class to be started. * @return The Activity.
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeTabbedActivityTestRule.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeTabbedActivityTestRule.java index cc708d7..65e683d2 100644 --- a/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeTabbedActivityTestRule.java +++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeTabbedActivityTestRule.java
@@ -20,11 +20,8 @@ import org.chromium.base.Log; import org.chromium.base.test.util.ApplicationTestUtils; import org.chromium.base.test.util.CallbackHelper; -import org.chromium.base.test.util.CriteriaHelper; -import org.chromium.base.test.util.ScalableTimeout; import org.chromium.chrome.R; import org.chromium.chrome.browser.ChromeTabbedActivity; -import org.chromium.chrome.browser.DeferredStartupHandler; import org.chromium.chrome.browser.omnibox.UrlBar; import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tab.TabCreationState; @@ -36,7 +33,6 @@ import org.chromium.chrome.test.util.MenuUtils; import org.chromium.chrome.test.util.NewTabPageTestUtils; import org.chromium.chrome.test.util.WaitForFocusHelper; -import org.chromium.components.embedder_support.util.UrlUtilities; import org.chromium.content_public.browser.test.util.TestThreadUtils; import java.util.concurrent.TimeoutException; @@ -113,31 +109,7 @@ */ public void startMainActivityFromIntent(Intent intent, String url) { prepareUrlIntent(intent, url); - - DeferredStartupHandler.setExpectingActivityStartupForTesting(); startActivityCompletely(intent); - waitForActivityNativeInitializationComplete(); - - CriteriaHelper.pollUiThread( - () -> getActivity().getActivityTab() != null, "Tab never selected/initialized."); - Tab tab = getActivity().getActivityTab(); - - ChromeTabUtils.waitForTabPageLoaded(tab, (String) null); - - if (tab != null && UrlUtilities.isNTPUrl(ChromeTabUtils.getUrlStringOnUiThread(tab)) - && !getActivity().isInOverviewMode()) { - NewTabPageTestUtils.waitForNtpLoaded(tab); - } - - Assert.assertTrue("Deferred startup never completed. Did you try to start an Activity " - + "that was already started?", - DeferredStartupHandler.waitForDeferredStartupCompleteForTesting( - ScalableTimeout.scaleTimeout(CriteriaHelper.DEFAULT_MAX_TIME_TO_POLL))); - - Assert.assertNotNull(tab); - Assert.assertNotNull(tab.getView()); - - InstrumentationRegistry.getInstrumentation().waitForIdleSync(); } /**
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/batch/BlankCTATabInitialStateRule.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/batch/BlankCTATabInitialStateRule.java index e401694..dba985d0 100644 --- a/chrome/test/android/javatests/src/org/chromium/chrome/test/batch/BlankCTATabInitialStateRule.java +++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/batch/BlankCTATabInitialStateRule.java
@@ -39,6 +39,7 @@ super(); mActivityTestRule = activityTestRule; mClearAllTabState = clearAllTabState; + mActivityTestRule.setFinishActivity(false); } @Override
diff --git a/chrome/test/data/webui/settings/password_check_test.js b/chrome/test/data/webui/settings/password_check_test.js index 4e7cc9a3..a530a8b 100644 --- a/chrome/test/data/webui/settings/password_check_test.js +++ b/chrome/test/data/webui/settings/password_check_test.js
@@ -982,6 +982,27 @@ expectFalse(isElementVisible(section.$.subtitle)); }); + // When the user is signed out but has run a weak check a timestamp should be + // shown. + test('showWeakCheckTimestampWhenSignedOut', async function() { + loadTimeData.overrideValues({passwordsWeaknessCheck: true}); + passwordManager.data.checkStatus = makePasswordCheckStatus( + /*state=*/ PasswordCheckState.SIGNED_OUT, + /*checked=*/ 0, + /*remaining=*/ 0, + /*lastCheck=*/ 'Just now'); + + const section = createCheckPasswordSection(); + await passwordManager.whenCalled('getPasswordCheckStatus'); + flush(); + const titleRow = section.$.titleRow; + const subtitle = section.$.subtitle; + assertTrue(isElementVisible(titleRow)); + assertTrue(isElementVisible(subtitle)); + expectEquals( + section.i18n('checkedPasswords') + ' • Just now', titleRow.innerText); + }); + // If |passwordsWeaknessCheck| is true, user is signed out and has // compromised credentials that were found in the past, shows "Checked // passwords" and correct label in the top of comromised passwords section.
diff --git a/chrome/test/data/webui/settings/people_page_sync_page_test.js b/chrome/test/data/webui/settings/people_page_sync_page_test.js index 624cd363..913638f 100644 --- a/chrome/test/data/webui/settings/people_page_sync_page_test.js +++ b/chrome/test/data/webui/settings/people_page_sync_page_test.js
@@ -337,7 +337,7 @@ assertTrue(passphraseConfirmationInput.invalid); }); - test('CreatingPassphraseValidPassphrase', function() { + test('CreatingPassphraseValidPassphrase', async function() { encryptWithPassphrase.click(); flush(); @@ -350,34 +350,31 @@ encryptionElement.$$('#passphraseConfirmationInput'); passphraseInput.value = 'foo'; passphraseConfirmationInput.value = 'foo'; + browserProxy.encryptionPassphraseSuccess = true; saveNewPassphrase.click(); - function verifySetSyncEncryption(args) { - assertTrue(args.setNewPassphrase); - assertEquals('foo', args.passphrase); + const passphrase = await browserProxy.whenCalled('setEncryptionPassphrase'); - // Fake backend response. - const newPrefs = getSyncAllPrefs(); - newPrefs.fullEncryptionBody = 'Encrypted with custom passphrase'; - newPrefs.encryptAllData = true; - webUIListenerCallback('sync-prefs-changed', newPrefs); + assertEquals('foo', passphrase); - flush(); + // Fake backend response. + const newPrefs = getSyncAllPrefs(); + newPrefs.fullEncryptionBody = 'Encrypted with custom passphrase'; + newPrefs.encryptAllData = true; + webUIListenerCallback('sync-prefs-changed', newPrefs); - return waitBeforeNextRender(syncPage).then(() => { - // Need to re-retrieve this, as a different show passphrase radio - // button is shown once |syncPrefs.fullEncryptionBody| is non-empty. - encryptWithPassphrase = encryptionElement.$$( - 'cr-radio-button[name="encrypt-with-passphrase"]'); + flush(); - // Assert that the radio boxes are disabled after encryption enabled. - assertTrue(encryptionRadioGroup.disabled); - assertEquals(-1, encryptWithGoogle.$.button.tabIndex); - assertEquals(-1, encryptWithPassphrase.$.button.tabIndex); - }); - } - return browserProxy.whenCalled('setSyncEncryption') - .then(verifySetSyncEncryption); + await waitBeforeNextRender(syncPage); + // Need to re-retrieve this, as a different show passphrase radio + // button is shown once |syncPrefs.fullEncryptionBody| is non-empty. + encryptWithPassphrase = + encryptionElement.$$('cr-radio-button[name="encrypt-with-passphrase"]'); + + // Assert that the radio boxes are disabled after encryption enabled. + assertTrue(encryptionRadioGroup.disabled); + assertEquals(-1, encryptWithGoogle.$.button.tabIndex); + assertEquals(-1, encryptWithPassphrase.$.button.tabIndex); }); test('RadioBoxesHiddenWhenPassphraseRequired', function() { @@ -415,7 +412,7 @@ assertFalse(submitExistingPassphrase.disabled); }); - test('EnterExistingWrongPassphrase', function() { + test('EnterExistingWrongPassphrase', async function() { const prefs = getSyncAllPrefs(); prefs.encryptAllData = true; prefs.passphraseRequired = true; @@ -425,21 +422,19 @@ const existingPassphraseInput = syncPage.$$('#existingPassphraseInput'); assertTrue(!!existingPassphraseInput); existingPassphraseInput.value = 'wrong'; - browserProxy.encryptionResponse = PageStatus.PASSPHRASE_FAILED; + browserProxy.decryptionPassphraseSuccess = false; const submitExistingPassphrase = syncPage.$$('#submitExistingPassphrase'); assertTrue(!!submitExistingPassphrase); submitExistingPassphrase.click(); - return browserProxy.whenCalled('setSyncEncryption').then(function(args) { - assertFalse(args.setNewPassphrase); - assertEquals('wrong', args.passphrase); - assertTrue(args.passphraseRequired); - assertTrue(existingPassphraseInput.invalid); - }); + const passphrase = await browserProxy.whenCalled('setDecryptionPassphrase'); + + assertEquals('wrong', passphrase); + assertTrue(existingPassphraseInput.invalid); }); - test('EnterExistingCorrectPassphrase', function() { + test('EnterExistingCorrectPassphrase', async function() { const prefs = getSyncAllPrefs(); prefs.encryptAllData = true; prefs.passphraseRequired = true; @@ -449,29 +444,27 @@ const existingPassphraseInput = syncPage.$$('#existingPassphraseInput'); assertTrue(!!existingPassphraseInput); existingPassphraseInput.value = 'right'; - browserProxy.encryptionResponse = PageStatus.CONFIGURE; + browserProxy.decryptionPassphraseSuccess = true; const submitExistingPassphrase = syncPage.$$('#submitExistingPassphrase'); assertTrue(!!submitExistingPassphrase); submitExistingPassphrase.click(); - return browserProxy.whenCalled('setSyncEncryption').then(function(args) { - assertFalse(args.setNewPassphrase); - assertEquals('right', args.passphrase); - assertTrue(args.passphraseRequired); + const passphrase = await browserProxy.whenCalled('setDecryptionPassphrase'); - // Fake backend response. - const newPrefs = getSyncAllPrefs(); - newPrefs.encryptAllData = true; - webUIListenerCallback('sync-prefs-changed', newPrefs); + assertEquals('right', passphrase); - flush(); + // Fake backend response. + const newPrefs = getSyncAllPrefs(); + newPrefs.encryptAllData = true; + webUIListenerCallback('sync-prefs-changed', newPrefs); - // Verify that the encryption radio boxes are shown but disabled. - assertTrue(encryptionRadioGroup.disabled); - assertEquals(-1, encryptWithGoogle.$.button.tabIndex); - assertEquals(-1, encryptWithPassphrase.$.button.tabIndex); - }); + flush(); + + // Verify that the encryption radio boxes are shown but disabled. + assertTrue(encryptionRadioGroup.disabled); + assertEquals(-1, encryptWithGoogle.$.button.tabIndex); + assertEquals(-1, encryptWithPassphrase.$.button.tabIndex); }); test('SyncAdvancedRow', function() {
diff --git a/chrome/test/data/webui/settings/test_sync_browser_proxy.js b/chrome/test/data/webui/settings/test_sync_browser_proxy.js index 5537f5f..567f747 100644 --- a/chrome/test/data/webui/settings/test_sync_browser_proxy.js +++ b/chrome/test/data/webui/settings/test_sync_browser_proxy.js
@@ -19,7 +19,8 @@ 'getSyncStatus', 'incrementPromoImpressionCount', 'setSyncDatatypes', - 'setSyncEncryption', + 'setEncryptionPassphrase', + 'setDecryptionPassphrase', 'signOut', 'pauseSync', 'sendSyncPrefsChanged', @@ -37,8 +38,10 @@ this.impressionCount_ = 0; // Settable fake data. - /** @type {!settings.PageStatus} */ - this.encryptionResponse = settings.PageStatus.CONFIGURE; + /** @type {boolean} */ + this.encryptionPassphraseSuccess = false; + /** @type {boolean} */ + this.decryptionPassphraseSuccess = false; /** @type {!Array<!settings.StoredAccount>} */ this.storedAccounts = []; /** @type {!settings.SyncStatus} */ @@ -111,9 +114,15 @@ } /** @override */ - setSyncEncryption(syncPrefs) { - this.methodCalled('setSyncEncryption', syncPrefs); - return Promise.resolve(this.encryptionResponse); + setEncryptionPassphrase(passphrase) { + this.methodCalled('setEncryptionPassphrase', passphrase); + return Promise.resolve(this.encryptionPassphraseSuccess); + } + + /** @override */ + setDecryptionPassphrase(passphrase) { + this.methodCalled('setDecryptionPassphrase', passphrase); + return Promise.resolve(this.decryptionPassphraseSuccess); } /** @override */
diff --git a/chrome/updater/test/integration_tests.cc b/chrome/updater/test/integration_tests.cc index 26f75e1..9fdc15b 100644 --- a/chrome/updater/test/integration_tests.cc +++ b/chrome/updater/test/integration_tests.cc
@@ -183,7 +183,7 @@ Uninstall(); } -TEST_F(IntegrationTest, UnregisterUninstalledApp) { +TEST_F(IntegrationTest, DISABLED_UnregisterUninstalledApp) { RegisterTestApp(); ExpectInstalled(); ExpectActiveVersion(UPDATER_VERSION_STRING);
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 830e9f1b..46a3a80c 100644 --- a/chromeos/components/camera_app_ui/resources/camera_app_resources.grd +++ b/chromeos/components/camera_app_ui/resources/camera_app_resources.grd
@@ -68,7 +68,8 @@ <structure name="IDR_CAMERA_SOUND_JS" file="js/sound.js" type="chrome_html" /> <structure name="IDR_CAMERA_STATE_JS" file="js/state.js" type="chrome_html" /> <structure name="IDR_CAMERA_TEST_BRIDGE_JS" file="js/test_bridge.js" type="chrome_html" /> - <structure name="IDR_CAMERA_TEST_HTML" file="views/test.html" type="chrome_html" /> + <structure name="IDR_CAMERA_TEST_HTML" file="test/test.html" type="chrome_html" /> + <structure name="IDR_CAMERA_TEST_LEGACY_HTML" file="views/test.html" type="chrome_html" /> <structure name="IDR_CAMERA_TIMERTICK_JS" file="js/views/camera/timertick.js" type="chrome_html" /> <structure name="IDR_CAMERA_TOAST_JS" file="js/toast.js" type="chrome_html" /> <structure name="IDR_CAMERA_TOOLTIP_JS" file="js/tooltip.js" type="chrome_html" />
diff --git a/chromeos/components/camera_app_ui/resources/js/dom.js b/chromeos/components/camera_app_ui/resources/js/dom.js index 6caa43f..c6bb118 100644 --- a/chromeos/components/camera_app_ui/resources/js/dom.js +++ b/chromeos/components/camera_app_ui/resources/js/dom.js
@@ -12,7 +12,7 @@ * type. * @param {!Node} target * @param {string} selector - * @param {function(new: T, ...)} type A user-defined constructor. + * @param {function(new: T, ...)} type The expected element type. * @return {T} * @template T */ @@ -25,7 +25,7 @@ * their type to be specific type. * @param {!Node} target * @param {string} selector - * @param {function(new: T, ...)} type A user-defined constructor. + * @param {function(new: T, ...)} type The expected element type. * @return {!NodeList<T>} * @template T */ @@ -40,7 +40,7 @@ /** * Gets an element in document matching css selector and checks its type. * @param {string} selector - * @param {function(new: T, ...)} type A user-defined constructor. + * @param {function(new: T, ...)} type The expected element type. * @return {T} * @template T */ @@ -52,7 +52,7 @@ * Gets all elements in document matching css selector and asserts their type to * be specific type. * @param {string} selector - * @param {function(new: T, ...)} type A user-defined constructor. + * @param {function(new: T, ...)} type The expected element type. * @return {!NodeList<T>} * @template T */ @@ -60,4 +60,16 @@ return getAllFrom(document, selector, type); } +/** + * Creates a typed element. + * @param {string} tag The HTML tag of the element to be created. + * @param {function(new: T, ...)} type The expected element type. + * @return {!T} + * @template T + */ +export function create(tag, type) { + const el = document.createElement(tag); + return assertInstanceof(el, type); +} + /* eslint-enable valid-jsdoc */
diff --git a/chromeos/components/camera_app_ui/resources/js/main.js b/chromeos/components/camera_app_ui/resources/js/main.js index 1486db3b..879daee 100644 --- a/chromeos/components/camera_app_ui/resources/js/main.js +++ b/chromeos/components/camera_app_ui/resources/js/main.js
@@ -266,8 +266,7 @@ const preloadImages = (async () => { const loadImage = (url) => new Promise((resolve, reject) => { - const link = - /** @type {!HTMLLinkElement} */ (document.createElement('link')); + const link = dom.create('link', HTMLLinkElement); link.rel = 'preload'; link.as = 'image'; link.href = url;
diff --git a/chromeos/components/camera_app_ui/resources/js/util.js b/chromeos/components/camera_app_ui/resources/js/util.js index b4c2a89..92693ac 100644 --- a/chromeos/components/camera_app_ui/resources/js/util.js +++ b/chromeos/components/camera_app_ui/resources/js/util.js
@@ -24,8 +24,7 @@ * Returns canvas element and the context for 2D drawing. */ export function newDrawingCanvas({width, height}) { - const canvas = - assertInstanceof(document.createElement('canvas'), HTMLCanvasElement); + const canvas = dom.create('canvas', HTMLCanvasElement); canvas.width = width; canvas.height = height; const ctx = @@ -169,8 +168,7 @@ if (orientation.rotation === 0 && !orientation.flip) { onSuccess(blob); } else { - const original = - assertInstanceof(document.createElement('img'), HTMLImageElement); + const original = dom.create('img', HTMLImageElement); original.onload = function() { drawPhoto(original, orientation, onSuccess, onFailure); }; @@ -361,9 +359,8 @@ * @return {!Promise<!Blob>} Promise for the result. */ export async function scalePicture(url, isVideo, width, height = undefined) { - const element = - /** @type {(!HTMLImageElement|!HTMLVideoElement)} */ ( - document.createElement(isVideo ? 'video' : 'img')); + const element = isVideo ? dom.create('video', HTMLVideoElement) : + dom.create('img', HTMLImageElement); if (isVideo) { element.preload = 'auto'; } @@ -486,8 +483,7 @@ */ export async function createUntrustedJSModule(scriptUrl, origin) { const untrustedPageReady = new WaitableEvent(); - const iFrame = - /** @type {!HTMLIFrameElement} */ (document.createElement('iframe')); + const iFrame = dom.create('iframe', HTMLIFrameElement); iFrame.addEventListener('load', () => untrustedPageReady.signal()); iFrame.setAttribute('src', `${origin}/views/untrusted_script_loader.html`); iFrame.hidden = true;
diff --git a/chromeos/components/camera_app_ui/resources/test/test.html b/chromeos/components/camera_app_ui/resources/test/test.html new file mode 100644 index 0000000..82c75d87 --- /dev/null +++ b/chromeos/components/camera_app_ui/resources/test/test.html
@@ -0,0 +1,8 @@ +<!doctype html> +<!-- 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. --> +<html> + <head> + </head> +</html>
diff --git a/chromeos/components/camera_app_ui/url_constants.cc b/chromeos/components/camera_app_ui/url_constants.cc index 6e1a8b9..b131281 100644 --- a/chromeos/components/camera_app_ui/url_constants.cc +++ b/chromeos/components/camera_app_ui/url_constants.cc
@@ -8,6 +8,7 @@ const char kChromeUICameraAppHost[] = "camera-app"; const char kChromeUICameraAppMainURL[] = "chrome://camera-app/views/main.html"; +const char kChromeUICameraAppScopeURL[] = "chrome://camera-app/views"; const char kChromeUICameraAppURL[] = "chrome://camera-app/"; const char kChromeUIUntrustedCameraAppURL[] = "chrome-untrusted://camera-app/";
diff --git a/chromeos/components/camera_app_ui/url_constants.h b/chromeos/components/camera_app_ui/url_constants.h index 4a81ad5e..95b78c7 100644 --- a/chromeos/components/camera_app_ui/url_constants.h +++ b/chromeos/components/camera_app_ui/url_constants.h
@@ -9,6 +9,7 @@ extern const char kChromeUICameraAppHost[]; extern const char kChromeUICameraAppMainURL[]; +extern const char kChromeUICameraAppScopeURL[]; extern const char kChromeUICameraAppURL[]; extern const char kChromeUIUntrustedCameraAppURL[];
diff --git a/chromeos/constants/chromeos_features.cc b/chromeos/constants/chromeos_features.cc index c0f56da..59fc41a 100644 --- a/chromeos/constants/chromeos_features.cc +++ b/chromeos/constants/chromeos_features.cc
@@ -100,6 +100,10 @@ const base::Feature kAssistAutoCorrect{"AssistAutoCorrect", base::FEATURE_DISABLED_BY_DEFAULT}; +// Controls whether to enable assistive multi word suggestions. +const base::Feature kAssistMultiWord{"AssistMultiWord", + base::FEATURE_DISABLED_BY_DEFAULT}; + // Controls whether to enable assistive personal information. const base::Feature kAssistPersonalInfo{"AssistPersonalInfo", base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/chromeos/constants/chromeos_features.h b/chromeos/constants/chromeos_features.h index 834d1ee4..b9cd168 100644 --- a/chromeos/constants/chromeos_features.h +++ b/chromeos/constants/chromeos_features.h
@@ -62,6 +62,8 @@ COMPONENT_EXPORT(CHROMEOS_CONSTANTS) extern const base::Feature kAssistAutoCorrect; COMPONENT_EXPORT(CHROMEOS_CONSTANTS) +extern const base::Feature kAssistMultiWord; +COMPONENT_EXPORT(CHROMEOS_CONSTANTS) extern const base::Feature kAssistPersonalInfo; COMPONENT_EXPORT(CHROMEOS_CONSTANTS) extern const base::Feature kAssistPersonalInfoAddress;
diff --git a/chromeos/constants/chromeos_pref_names.cc b/chromeos/constants/chromeos_pref_names.cc index 1d44149..c92dd814 100644 --- a/chromeos/constants/chromeos_pref_names.cc +++ b/chromeos/constants/chromeos_pref_names.cc
@@ -124,5 +124,9 @@ // the Chrome OS launcher. const char kLauncherResultEverLaunched[] = "launcher.result_ever_launched"; +// Whether the status of the platform app version of camera app is migrated to +// SWA. +const char kHasCameraAppMigratedToSWA[] = "camera.has_migrated_to_swa"; + } // namespace prefs } // namespace chromeos
diff --git a/chromeos/constants/chromeos_pref_names.h b/chromeos/constants/chromeos_pref_names.h index f5447d5c..09a586c 100644 --- a/chromeos/constants/chromeos_pref_names.h +++ b/chromeos/constants/chromeos_pref_names.h
@@ -54,6 +54,8 @@ extern const char kSuggestedContentEnabled[]; COMPONENT_EXPORT(CHROMEOS_CONSTANTS) extern const char kLauncherResultEverLaunched[]; +COMPONENT_EXPORT(CHROMEOS_CONSTANTS) +extern const char kHasCameraAppMigratedToSWA[]; } // namespace prefs } // namespace chromeos
diff --git a/chromeos/profiles/atom.afdo.newest.txt b/chromeos/profiles/atom.afdo.newest.txt index 88ac294c..ff53f0f 100644 --- a/chromeos/profiles/atom.afdo.newest.txt +++ b/chromeos/profiles/atom.afdo.newest.txt
@@ -1 +1 @@ -chromeos-chrome-amd64-atom-89-4324.9-1606128713-benchmark-89.0.4335.0-r1-redacted.afdo.xz +chromeos-chrome-amd64-atom-89-4324.9-1606128713-benchmark-89.0.4336.0-r1-redacted.afdo.xz
diff --git a/chromeos/profiles/bigcore.afdo.newest.txt b/chromeos/profiles/bigcore.afdo.newest.txt index f333af2f..e3916aa 100644 --- a/chromeos/profiles/bigcore.afdo.newest.txt +++ b/chromeos/profiles/bigcore.afdo.newest.txt
@@ -1 +1 @@ -chromeos-chrome-amd64-bigcore-89-4324.9-1606129869-benchmark-89.0.4335.0-r1-redacted.afdo.xz +chromeos-chrome-amd64-bigcore-89-4324.9-1606129869-benchmark-89.0.4336.0-r1-redacted.afdo.xz
diff --git a/components/autofill/content/renderer/password_autofill_agent.cc b/components/autofill/content/renderer/password_autofill_agent.cc index dd0a03a..83a970cc 100644 --- a/components/autofill/content/renderer/password_autofill_agent.cc +++ b/components/autofill/content/renderer/password_autofill_agent.cc
@@ -1403,8 +1403,8 @@ WebFormElement form = cleared_element.Form(); if (form.IsNull()) { // Process password field clearing for fields outside the <form> tag. - GetPasswordManagerDriver()->PasswordFormCleared( - *GetFormDataFromUnownedInputElements()); + if (auto unowned_form_data = GetFormDataFromUnownedInputElements()) + GetPasswordManagerDriver()->PasswordFormCleared(*unowned_form_data); return; } // Process field clearing for a form under a <form> tag.
diff --git a/components/autofill/core/browser/autofill_download_manager_unittest.cc b/components/autofill/core/browser/autofill_download_manager_unittest.cc index c78f7da..419e5cd 100644 --- a/components/autofill/core/browser/autofill_download_manager_unittest.cc +++ b/components/autofill/core/browser/autofill_download_manager_unittest.cc
@@ -1946,7 +1946,7 @@ AutofillDownloadManager download_manager(driver_.get(), this); FormStructure form_structure(form); - form_structure.set_page_language(LanguageCode("fr")); + form_structure.set_original_page_language(LanguageCode("fr")); pref_service_->SetBoolean( RandomizedEncoder::kUrlKeyedAnonymizedDataCollectionEnabled, true); @@ -1983,7 +1983,8 @@ ASSERT_TRUE(request.ParseFromString(payloads_.front())); ASSERT_TRUE(request.has_upload()); const AutofillUploadContents& upload = request.upload(); - EXPECT_EQ(upload.language(), form_structure.page_language().value()); + EXPECT_EQ(upload.language(), + form_structure.original_page_language().value()); ASSERT_TRUE(upload.has_randomized_form_metadata()); EXPECT_TRUE(upload.randomized_form_metadata().has_id()); EXPECT_TRUE(upload.randomized_form_metadata().has_name());
diff --git a/components/autofill/core/browser/autofill_handler.cc b/components/autofill/core/browser/autofill_handler.cc index f4082434..914fb25 100644 --- a/components/autofill/core/browser/autofill_handler.cc +++ b/components/autofill/core/browser/autofill_handler.cc
@@ -40,9 +40,14 @@ return nullptr; } -// Returns true if |live_form| does not match |cached_form|. +// Returns true if |live_form| does not match |cached_form|, assuming that +// |live_form|'s language is |live_form_language|. bool CachedFormNeedsUpdate(const FormData& live_form, + const LanguageCode& live_form_language, const FormStructure& cached_form) { + if (cached_form.original_page_language() != live_form_language) + return true; + if (live_form.fields.size() != cached_form.field_count()) return true; @@ -201,6 +206,7 @@ driver_->SendFormDataToRenderer(query_id, action, data); } +// Returns true if |live_form| does not match |cached_form|. bool AutofillHandler::GetCachedFormAndField(const FormData& form, const FormFieldData& field, FormStructure** form_structure, @@ -210,7 +216,7 @@ FindCachedFormByRendererId(form.unique_renderer_id); if (cached_form) { DCHECK(cached_form); - if (!CachedFormNeedsUpdate(form, *cached_form)) { + if (!CachedFormNeedsUpdate(form, GetPageLanguage(), *cached_form)) { // There is no data to return if there are no auto-fillable fields. if (!cached_form->autofill_count()) return false; @@ -288,7 +294,7 @@ value_from_dynamic_change_form_ = true; } - form_structure->set_page_language(GetPageLanguage()); + form_structure->set_original_page_language(GetPageLanguage()); form_structure->DetermineHeuristicTypes(log_manager_);
diff --git a/components/autofill/core/browser/autofill_manager.cc b/components/autofill/core/browser/autofill_manager.cc index 1015ea9..bb716b1 100644 --- a/components/autofill/core/browser/autofill_manager.cc +++ b/components/autofill/core/browser/autofill_manager.cc
@@ -797,7 +797,7 @@ copied_credit_cards.push_back(*card); // Annotate the form with the source language of the page. - form_structure->set_page_language(LanguageCode(GetPageLanguage())); + form_structure->set_original_page_language(GetPageLanguage()); // Attach the Randomized Encoder. form_structure->set_randomized_encoder( @@ -2796,9 +2796,9 @@ LanguageCode AutofillManager::GetPageLanguage() const { DCHECK(client_); const translate::LanguageState* language_state = client_->GetLanguageState(); - if (language_state) - return LanguageCode(language_state->original_language()); - return LanguageCode(); + if (!language_state) + return LanguageCode(); + return LanguageCode(language_state->original_language()); } } // namespace autofill
diff --git a/components/autofill/core/browser/autofill_manager.h b/components/autofill/core/browser/autofill_manager.h index 2f0eae83..82af7ed6 100644 --- a/components/autofill/core/browser/autofill_manager.h +++ b/components/autofill/core/browser/autofill_manager.h
@@ -390,6 +390,8 @@ FormData* pending_form_data() { return pending_form_data_.get(); } private: + FRIEND_TEST_ALL_PREFIXES(AutofillManagerTest, PageLanguageGetsCorrectlySet); + // Keeps track of the filling context for a form, used to make refill attemps. struct FillingContext { // |optional_profile| or |optional_credit_card| must be non-null.
diff --git a/components/autofill/core/browser/autofill_manager_unittest.cc b/components/autofill/core/browser/autofill_manager_unittest.cc index 2cd3b31..5f29a9f 100644 --- a/components/autofill/core/browser/autofill_manager_unittest.cc +++ b/components/autofill/core/browser/autofill_manager_unittest.cc
@@ -8455,17 +8455,25 @@ } TEST_F(AutofillManagerTest, PageLanguageGetsCorrectlySet) { - const char* kTestLanguage = "zh"; FormData form; test::CreateTestAddressFormData(&form); - // Set up language state mock. - autofill_client_.GetLanguageState()->SetOriginalLanguage(kTestLanguage); + autofill_client_.GetLanguageState()->SetOriginalLanguage("und"); - FormStructure* parsed_form = autofill_manager_->ParseFormForTest(form); + autofill_manager_->OnFormsSeen({form}, base::TimeTicks()); + FormStructure* parsed_form = + autofill_manager_->FindCachedFormByRendererId(form.unique_renderer_id); ASSERT_TRUE(parsed_form); - ASSERT_EQ(LanguageCode(kTestLanguage), parsed_form->page_language()); + ASSERT_EQ(LanguageCode("und"), parsed_form->original_page_language()); + + autofill_client_.GetLanguageState()->SetOriginalLanguage("zh"); + + autofill_manager_->OnFormsSeen({form}, base::TimeTicks()); + parsed_form = + autofill_manager_->FindCachedFormByRendererId(form.unique_renderer_id); + + ASSERT_EQ(LanguageCode("zh"), parsed_form->original_page_language()); } // AutofillManagerTest with kAutofillDisabledMixedForms feature enabled.
diff --git a/components/autofill/core/browser/autofill_profile_sync_util.cc b/components/autofill/core/browser/autofill_profile_sync_util.cc index 267ad01..f82bcdf 100644 --- a/components/autofill/core/browser/autofill_profile_sync_util.cc +++ b/components/autofill/core/browser/autofill_profile_sync_util.cc
@@ -48,6 +48,8 @@ return VerificationStatus::kObserved; case sync_pb::AutofillProfileSpecifics_VerificationStatus_USER_VERIFIED: return VerificationStatus::kUserVerified; + case sync_pb::AutofillProfileSpecifics_VerificationStatus_SERVER_PARSED: + return VerificationStatus::kServerParsed; } } @@ -67,6 +69,8 @@ return sync_pb::AutofillProfileSpecifics_VerificationStatus_OBSERVED; case (VerificationStatus::kUserVerified): return sync_pb::AutofillProfileSpecifics_VerificationStatus_USER_VERIFIED; + case (VerificationStatus::kServerParsed): + return sync_pb::AutofillProfileSpecifics_VerificationStatus_SERVER_PARSED; } }
diff --git a/components/autofill/core/browser/data_model/autofill_profile.cc b/components/autofill/core/browser/data_model/autofill_profile.cc index d74c8d2..72de7229 100644 --- a/components/autofill/core/browser/data_model/autofill_profile.cc +++ b/components/autofill/core/browser/data_model/autofill_profile.cc
@@ -451,10 +451,14 @@ } for (ServerFieldType type : types) { - if (GetVerificationStatus(type) < profile.GetVerificationStatus(type)) + if (structured_address::IsLessSignificantVerificationStatus( + GetVerificationStatus(type), profile.GetVerificationStatus(type))) { return -1; - if (GetVerificationStatus(type) > profile.GetVerificationStatus(type)) + } + if (structured_address::IsLessSignificantVerificationStatus( + profile.GetVerificationStatus(type), GetVerificationStatus(type))) { return 1; + } } // TODO(crbug.com/1130194): Remove feature check once structured addresses are @@ -475,11 +479,17 @@ return comparison; } - for (ServerFieldType type : new_types) { - if (GetVerificationStatus(type) < profile.GetVerificationStatus(type)) + for (ServerFieldType type : types) { + if (structured_address::IsLessSignificantVerificationStatus( + GetVerificationStatus(type), + profile.GetVerificationStatus(type))) { return -1; - if (GetVerificationStatus(type) > profile.GetVerificationStatus(type)) + } + if (structured_address::IsLessSignificantVerificationStatus( + profile.GetVerificationStatus(type), + GetVerificationStatus(type))) { return 1; + } } }
diff --git a/components/autofill/core/browser/data_model/autofill_structured_address.cc b/components/autofill/core/browser/data_model/autofill_structured_address.cc index 9bdc8a9..49232c5 100644 --- a/components/autofill/core/browser/data_model/autofill_structured_address.cc +++ b/components/autofill/core/browser/data_model/autofill_structured_address.cc
@@ -135,7 +135,8 @@ bool StreetAddress::HasNewerValuePrecendenceInMerging( const AddressComponent& newer_component) const { // If the newer component has a better verification status, use the newer one. - if (GetVerificationStatus() < newer_component.GetVerificationStatus()) + if (IsLessSignificantVerificationStatus( + GetVerificationStatus(), newer_component.GetVerificationStatus())) return true; // If the verification statuses are the same, do not use the newer component
diff --git a/components/autofill/core/browser/data_model/autofill_structured_address_component.cc b/components/autofill/core/browser/data_model/autofill_structured_address_component.cc index 3d13303..c32c74b 100644 --- a/components/autofill/core/browser/data_model/autofill_structured_address_component.cc +++ b/components/autofill/core/browser/data_model/autofill_structured_address_component.cc
@@ -27,6 +27,28 @@ namespace structured_address { +bool IsLessSignificantVerificationStatus(VerificationStatus left, + VerificationStatus right) { + // Both the KUserVerified and kObserved are larger then kServerParsed although + // the underlying integer suggests differently. + if (left == VerificationStatus::kServerParsed && + (right == VerificationStatus::kObserved || + right == VerificationStatus::kUserVerified)) { + return true; + } + + if (right == VerificationStatus::kServerParsed && + (left == VerificationStatus::kObserved || + left == VerificationStatus::kUserVerified)) { + return false; + } + + // In all other cases, it is sufficient to compare the underlying integer + // values. + return static_cast<std::underlying_type_t<VerificationStatus>>(left) < + static_cast<std::underlying_type_t<VerificationStatus>>(right); +} + AddressComponent::AddressComponent(ServerFieldType storage_type, AddressComponent* parent, std::vector<AddressComponent*> subcomponents, @@ -701,7 +723,7 @@ void AddressComponent::MergeVerificationStatuses( const AddressComponent& newer_component) { if (IsValueAssigned() && (GetValue() == newer_component.GetValue()) && - (GetVerificationStatus() < newer_component.GetVerificationStatus())) { + HasNewerValuePrecendenceInMerging(newer_component)) { value_verification_status_ = newer_component.GetVerificationStatus(); } @@ -811,7 +833,7 @@ // If the normalized values are the same, optimize the verification status. if ((merge_mode_ & kUseBetterOrNewerForSameValue) && (value == value_newer)) { - if (newer_component.GetVerificationStatus() >= GetVerificationStatus()) { + if (HasNewerValuePrecendenceInMerging(newer_component)) { *this = newer_component; } return true; @@ -904,7 +926,8 @@ bool AddressComponent::HasNewerValuePrecendenceInMerging( const AddressComponent& newer_component) const { - return newer_component.GetVerificationStatus() >= GetVerificationStatus(); + return !IsLessSignificantVerificationStatus( + newer_component.GetVerificationStatus(), GetVerificationStatus()); } bool AddressComponent::MergeTokenEquivalentComponent( @@ -1113,6 +1136,7 @@ case VerificationStatus::kNoStatus: case VerificationStatus::kParsed: case VerificationStatus::kFormatted: + case VerificationStatus::kServerParsed: break; case VerificationStatus::kObserved: result += 1;
diff --git a/components/autofill/core/browser/data_model/autofill_structured_address_component.h b/components/autofill/core/browser/data_model/autofill_structured_address_component.h index 9cfc4d1..913bebf2 100644 --- a/components/autofill/core/browser/data_model/autofill_structured_address_component.h +++ b/components/autofill/core/browser/data_model/autofill_structured_address_component.h
@@ -37,8 +37,15 @@ kObserved = 3, // The user used the autofill settings to verify and store this token. kUserVerified = 4, + // The token was parsed by the server. + kServerParsed = 5, }; +// Returns true if |left| has a less significant verification status compared to +// |right|. +bool IsLessSignificantVerificationStatus(VerificationStatus left, + VerificationStatus right); + // The merge mode defines if and how two components are merged. enum MergeMode { // If one component has an empty value, use the non-empty one.
diff --git a/components/autofill/core/browser/data_model/autofill_structured_address_component_unittest.cc b/components/autofill/core/browser/data_model/autofill_structured_address_component_unittest.cc index b0c79ee..41034c8d 100644 --- a/components/autofill/core/browser/data_model/autofill_structured_address_component_unittest.cc +++ b/components/autofill/core/browser/data_model/autofill_structured_address_component_unittest.cc
@@ -1663,5 +1663,26 @@ VerifyTestValues(&older, older_values); } +// Test the comparison of different Verification statuses. +TEST(AutofillStructuredAddressAddressComponent, + TestIsLessSignificantVerificationStatus) { + EXPECT_TRUE(IsLessSignificantVerificationStatus( + VerificationStatus::kParsed, VerificationStatus::kFormatted)); + EXPECT_TRUE(IsLessSignificantVerificationStatus( + VerificationStatus::kParsed, VerificationStatus::kServerParsed)); + EXPECT_TRUE(IsLessSignificantVerificationStatus( + VerificationStatus::kServerParsed, VerificationStatus::kObserved)); + EXPECT_TRUE(IsLessSignificantVerificationStatus( + VerificationStatus::kServerParsed, VerificationStatus::kUserVerified)); + EXPECT_FALSE(IsLessSignificantVerificationStatus( + VerificationStatus::kServerParsed, VerificationStatus::kFormatted)); + EXPECT_FALSE(IsLessSignificantVerificationStatus( + VerificationStatus::kServerParsed, VerificationStatus::kParsed)); + EXPECT_FALSE(IsLessSignificantVerificationStatus( + VerificationStatus::kObserved, VerificationStatus::kServerParsed)); + EXPECT_FALSE(IsLessSignificantVerificationStatus( + VerificationStatus::kUserVerified, VerificationStatus::kServerParsed)); +} + } // namespace structured_address } // namespace autofill
diff --git a/components/autofill/core/browser/form_structure.cc b/components/autofill/core/browser/form_structure.cc index d2fa11d..ac7434b 100644 --- a/components/autofill/core/browser/form_structure.cc +++ b/components/autofill/core/browser/form_structure.cc
@@ -658,7 +658,7 @@ // prediction routines. if (ShouldRunHeuristics()) { const FieldCandidatesMap field_type_map = FormField::ParseFormFields( - fields_, page_language_, is_form_tag_, log_manager); + fields_, original_page_language_, is_form_tag_, log_manager); for (const auto& field : fields_) { const auto iter = field_type_map.find(field->unique_renderer_id); if (iter != field_type_map.end()) { @@ -711,8 +711,8 @@ upload->set_data_present(EncodeFieldTypes(available_field_types)); upload->set_passwords_revealed(passwords_were_revealed_); upload->set_has_form_tag(is_form_tag_); - if (!page_language_->empty() && randomized_encoder_ != nullptr) { - upload->set_language(page_language_.value()); + if (!original_page_language_->empty() && randomized_encoder_ != nullptr) { + upload->set_language(original_page_language_.value()); } auto triggering_event = (submission_event_ != SubmissionIndicatorEvent::NONE)
diff --git a/components/autofill/core/browser/form_structure.h b/components/autofill/core/browser/form_structure.h index f4e54f9..cee4187 100644 --- a/components/autofill/core/browser/form_structure.h +++ b/components/autofill/core/browser/form_structure.h
@@ -366,10 +366,12 @@ void set_is_rich_query_enabled(bool v) { is_rich_query_enabled_ = v; } - const LanguageCode& page_language() const { return page_language_; } + const LanguageCode& original_page_language() const { + return original_page_language_; + } - void set_page_language(LanguageCode language) { - page_language_ = std::move(language); + void set_original_page_language(LanguageCode language) { + original_page_language_ = std::move(language); } bool value_from_dynamic_change_form() const { @@ -584,9 +586,9 @@ static base::string16 FindLongestCommonPrefix( const std::vector<base::string16>& strings); - // The language detected for this form's page, prior to any translations + // The language detected for this form's page, before any translations // performed by Chrome. - LanguageCode page_language_; + LanguageCode original_page_language_; // The id attribute of the form. base::string16 id_attribute_;
diff --git a/components/autofill/core/browser/pattern_provider/pattern_configuration_parser.cc b/components/autofill/core/browser/pattern_provider/pattern_configuration_parser.cc index 0dd1e6c..28fbe66 100644 --- a/components/autofill/core/browser/pattern_provider/pattern_configuration_parser.cc +++ b/components/autofill/core/browser/pattern_provider/pattern_configuration_parser.cc
@@ -5,12 +5,14 @@ #include "components/autofill/core/browser/pattern_provider/pattern_configuration_parser.h" #include "base/bind.h" +#include "base/feature_list.h" #include "base/task/task_traits.h" #include "base/task/thread_pool.h" #include "base/values.h" #include "components/autofill/core/browser/autofill_type.h" #include "components/autofill/core/browser/field_types.h" #include "components/autofill/core/browser/pattern_provider/pattern_provider.h" +#include "components/autofill/core/common/autofill_features.h" #include "components/autofill/core/common/language_code.h" #include "components/grit/components_resources.h" #include "ui/base/resource/resource_bundle.h" @@ -76,18 +78,17 @@ return true; } -// Callback which is used once the JSON is parsed. -// |overwrite_equal_version| should be true when loading a remote -// configuration. If the configuration versions are equal or -// both unspecified (i.e. set to 0) this prioritizes the remote +// Callback which is used once the JSON is parsed. If the configuration versions +// are equal or both unspecified (i.e. set to 0) this prioritizes the remote // configuration over the local one. -void OnJsonParsed(bool overwrite_equal_version, - base::OnceClosure done_callback, - data_decoder::DataDecoder::ValueOrError result) { - // Skip any processing in case of an error. +void OnJsonParsed(data_decoder::DataDecoder::ValueOrError result) { + if (!base::FeatureList::IsEnabled(features::kAutofillUseRemotePatterns)) { + DVLOG(1) << "Remote patterns are disabled."; + return; + } + if (!result.value) { DVLOG(1) << "Failed to parse PatternProvider configuration JSON string."; - std::move(done_callback).Run(); return; } @@ -97,15 +98,12 @@ if (patterns && version.IsValid()) { DVLOG(1) << "Successfully parsed PatternProvider configuration."; - PatternProvider& pattern_provider = PatternProvider::GetInstance(); pattern_provider.SetPatterns(std::move(patterns.value()), - std::move(version), overwrite_equal_version); + std::move(version)); } else { DVLOG(1) << "Failed to parse PatternProvider configuration JSON object."; } - - std::move(done_callback).Run(); } } // namespace @@ -169,35 +167,8 @@ } void PopulateFromJsonString(std::string json_string) { - data_decoder::DataDecoder::ParseJsonIsolated( - std::move(json_string), - base::BindOnce(&OnJsonParsed, true, base::DoNothing::Once())); -} - -void PopulateFromResourceBundle(base::OnceClosure done_callback) { - if (!ui::ResourceBundle::HasSharedInstance()) { - VLOG(1) << "Resource Bundle unavailable to load Autofill Matching Pattern " - "definitions."; - std::move(done_callback).Run(); - return; - } - - ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance(); - - // Load the string from the Resource Bundle on a worker thread, then - // securely parse the JSON in a separate process and call |OnJsonParsed| - // with the result. - base::ThreadPool::PostTaskAndReplyWithResult( - FROM_HERE, {base::MayBlock()}, - base::BindOnce(&ui::ResourceBundle::LoadDataResourceString, - base::Unretained(&bundle), IDR_AUTOFILL_REGEX_JSON), - base::BindOnce( - [](base::OnceClosure done_callback, std::string resource_string) { - data_decoder::DataDecoder::ParseJsonIsolated( - std::move(resource_string), - base::BindOnce(&OnJsonParsed, false, std::move(done_callback))); - }, - std::move(done_callback))); + data_decoder::DataDecoder::ParseJsonIsolated(std::move(json_string), + base::BindOnce(&OnJsonParsed)); } base::Optional<PatternProvider::Map>
diff --git a/components/autofill/core/browser/pattern_provider/pattern_configuration_parser_unittest.cc b/components/autofill/core/browser/pattern_provider/pattern_configuration_parser_unittest.cc index 17765439..de78bc2 100644 --- a/components/autofill/core/browser/pattern_provider/pattern_configuration_parser_unittest.cc +++ b/components/autofill/core/browser/pattern_provider/pattern_configuration_parser_unittest.cc
@@ -23,7 +23,7 @@ // parsed to the map structure used by |PatternProvider| as // expected, given the input is valid. TEST(PatternConfigurationParserTest, WellFormedParsedCorrectly) { - std::string JSON_message = R"( + std::string json_message = R"( { "version": "1.0", "FULL_NAME": { @@ -61,14 +61,14 @@ ] } })"; - base::Optional<base::Value> JSON_object = - base::JSONReader::Read(JSON_message); + base::Optional<base::Value> json_object = + base::JSONReader::Read(json_message); - ASSERT_TRUE(JSON_object) << "Incorrectly formatted JSON string."; + ASSERT_TRUE(json_object) << "Incorrectly formatted JSON string."; - base::Version version = ExtractVersionFromJsonObject(JSON_object.value()); + base::Version version = ExtractVersionFromJsonObject(json_object.value()); base::Optional<PatternProvider::Map> optional_patterns = - GetConfigurationFromJsonObject(JSON_object.value()); + GetConfigurationFromJsonObject(json_object.value()); ASSERT_TRUE(version.IsValid()); ASSERT_TRUE(optional_patterns); @@ -101,7 +101,7 @@ // Test that the parser does not return anything if some |MatchingPattern| // object is missing a property. TEST(PatternConfigurationParserTest, MalformedMissingProperty) { - std::string JSON_message = R"( + std::string json_message = R"( { "version": "1.0", "FULL_NAME": { @@ -126,13 +126,13 @@ ] } })"; - base::Optional<base::Value> JSON_object = - base::JSONReader::Read(JSON_message); + base::Optional<base::Value> json_object = + base::JSONReader::Read(json_message); - ASSERT_TRUE(JSON_object) << "Incorrectly formatted JSON string."; + ASSERT_TRUE(json_object) << "Incorrectly formatted JSON string."; base::Optional<PatternProvider::Map> optional_patterns = - GetConfigurationFromJsonObject(JSON_object.value()); + GetConfigurationFromJsonObject(json_object.value()); ASSERT_FALSE(optional_patterns); } @@ -140,7 +140,7 @@ // Test that the parser correctly sets the default version if // it is not present in the configuration. TEST(PatternConfigurationParserTest, MalformedMissingVersion) { - std::string JSON_message = R"( + std::string json_message = R"( { "FULL_NAME": { "en": [ @@ -154,12 +154,12 @@ ] } })"; - base::Optional<base::Value> JSON_object = - base::JSONReader::Read(JSON_message); + base::Optional<base::Value> json_object = + base::JSONReader::Read(json_message); - ASSERT_TRUE(JSON_object) << "Incorrectly formatted JSON string."; + ASSERT_TRUE(json_object) << "Incorrectly formatted JSON string."; - base::Version version = ExtractVersionFromJsonObject(JSON_object.value()); + base::Version version = ExtractVersionFromJsonObject(json_object.value()); ASSERT_EQ(base::Version("0"), version); } @@ -167,7 +167,7 @@ // Test that the parser does not return anything if the inner key points // to a single object instead of a list. TEST(PatternConfigurationParserTest, MalformedNotList) { - std::string JSON_message = R"( + std::string json_message = R"( { "FULL_NAME": { "en": { @@ -179,13 +179,13 @@ } } })"; - base::Optional<base::Value> JSON_object = - base::JSONReader::Read(JSON_message); + base::Optional<base::Value> json_object = + base::JSONReader::Read(json_message); - ASSERT_TRUE(JSON_object) << "Incorrectly formatted JSON string."; + ASSERT_TRUE(json_object) << "Incorrectly formatted JSON string."; base::Optional<PatternProvider::Map> optional_patterns = - GetConfigurationFromJsonObject(JSON_object.value()); + GetConfigurationFromJsonObject(json_object.value()); ASSERT_FALSE(optional_patterns); }
diff --git a/components/autofill/core/browser/pattern_provider/pattern_provider.cc b/components/autofill/core/browser/pattern_provider/pattern_provider.cc index 73fbc08..f7d56f5 100644 --- a/components/autofill/core/browser/pattern_provider/pattern_provider.cc +++ b/components/autofill/core/browser/pattern_provider/pattern_provider.cc
@@ -71,7 +71,7 @@ static base::NoDestructor<PatternProvider> instance; static bool initialized = false; if (!initialized) { - instance->SetPatterns(CreateDefaultRegexPatterns(), base::Version(), true); + instance->SetPatterns(CreateDefaultRegexPatterns(), base::Version()); initialized = true; } return *instance; @@ -81,15 +81,12 @@ PatternProvider::~PatternProvider() = default; void PatternProvider::SetPatterns(PatternProvider::Map patterns, - const base::Version version, - const bool overwrite_equal_version) { + const base::Version& version) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (!pattern_version_.IsValid() || - (version.IsValid() && pattern_version_ < version) || - (version.IsValid() && pattern_version_ == version && - overwrite_equal_version)) { - patterns_ = patterns; + (version.IsValid() && pattern_version_ <= version)) { + patterns_ = std::move(patterns); pattern_version_ = version; EnrichPatternsWithEnVersion(&patterns_); SortPatternsByScore(&patterns_);
diff --git a/components/autofill/core/browser/pattern_provider/pattern_provider.h b/components/autofill/core/browser/pattern_provider/pattern_provider.h index 3ae65738..767ad35 100644 --- a/components/autofill/core/browser/pattern_provider/pattern_provider.h +++ b/components/autofill/core/browser/pattern_provider/pattern_provider.h
@@ -27,7 +27,6 @@ public: // The outer keys are field types or other pattern names. The inner keys are // page languages in lower case. - // TODO(crbug/1142413): decide on uppercase or lowercase. using Map = std::map<std::string, std::map<LanguageCode, std::vector<MatchingPattern>>>; @@ -35,9 +34,7 @@ static PatternProvider& GetInstance(); // Setter for loading patterns from external storage. - void SetPatterns(const Map patterns, - const base::Version version, - const bool overwrite_equal_version); + void SetPatterns(const Map patterns, const base::Version& version); // Find the patterns for a given ServerFieldType and for a given // |page_language|.
diff --git a/components/autofill/core/browser/pattern_provider/pattern_provider_unittest.cc b/components/autofill/core/browser/pattern_provider/pattern_provider_unittest.cc index 56b3990..9152d3c 100644 --- a/components/autofill/core/browser/pattern_provider/pattern_provider_unittest.cc +++ b/components/autofill/core/browser/pattern_provider/pattern_provider_unittest.cc
@@ -18,9 +18,11 @@ #include "components/autofill/core/browser/pattern_provider/pattern_provider.h" #include "components/autofill/core/common/autofill_features.h" #include "components/autofill/core/common/language_code.h" +#include "components/grit/components_resources.h" #include "services/data_decoder/public/cpp/test_support/in_process_data_decoder.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +#include "ui/base/resource/resource_bundle.h" namespace autofill { @@ -65,10 +67,44 @@ patterns[AutofillType::ServerFieldTypeToString(COMPANY_NAME)]; company_patterns[kLanguageDe] = de_patterns; company_patterns[kLanguageEn] = en_patterns; - SetPatterns(patterns, base::Version(), true); + SetPatterns(std::move(patterns), base::Version()); } }; +// Called when the JSON bundle has been parsed, and sets the PatternProvider's +// patterns. +void OnJsonParsed(base::OnceClosure done_callback, + data_decoder::DataDecoder::ValueOrError result) { + base::Version version = + field_type_parsing::ExtractVersionFromJsonObject(result.value.value()); + base::Optional<PatternProvider::Map> patterns = + field_type_parsing::GetConfigurationFromJsonObject(result.value.value()); + ASSERT_TRUE(patterns); + ASSERT_TRUE(version.IsValid()); + PatternProvider& pattern_provider = PatternProvider::GetInstance(); + pattern_provider.SetPatterns(std::move(patterns.value()), std::move(version)); + std::move(done_callback).Run(); +} + +// Loads the string from the Resource Bundle on a worker thread. +void LoadPatternsFromResourceBundle() { + ASSERT_TRUE(ui::ResourceBundle::HasSharedInstance()); + ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance(); + base::RunLoop run_loop; + base::ThreadPool::PostTaskAndReplyWithResult( + FROM_HERE, {base::MayBlock()}, + base::BindOnce(&ui::ResourceBundle::LoadDataResourceString, + base::Unretained(&bundle), IDR_AUTOFILL_REGEX_JSON), + base::BindOnce( + [](base::OnceClosure done_callback, std::string resource_string) { + data_decoder::DataDecoder::ParseJsonIsolated( + std::move(resource_string), + base::BindOnce(&OnJsonParsed, std::move(done_callback))); + }, + run_loop.QuitClosure())); + run_loop.Run(); +} + } // namespace bool operator==(const MatchingPattern& mp1, const MatchingPattern& mp2) { @@ -115,9 +151,7 @@ ASSERT_NE(default_patterns, PatternProvider::GetInstance().patterns_); // Load the JSON explicitly from the file. - base::RunLoop run_loop; - field_type_parsing::PopulateFromResourceBundle(run_loop.QuitClosure()); - run_loop.Run(); + LoadPatternsFromResourceBundle(); auto json_version = PatternProvider::GetInstance().pattern_version_; auto json_patterns = PatternProvider::GetInstance().patterns_;
diff --git a/components/autofill/core/browser/personal_data_manager_unittest.cc b/components/autofill/core/browser/personal_data_manager_unittest.cc index e09998c..50fcc72 100644 --- a/components/autofill/core/browser/personal_data_manager_unittest.cc +++ b/components/autofill/core/browser/personal_data_manager_unittest.cc
@@ -3924,18 +3924,21 @@ TestAutofillClock test_clock; test_clock.SetNow(kArbitraryTime); + auto Check = [](const AutofillDataModel& data_model, size_t use_count, + base::Time use_date, base::Time modification_date) { + EXPECT_EQ(use_count, data_model.use_count()); + EXPECT_EQ(use_date, data_model.use_date()); + EXPECT_EQ(modification_date, data_model.modification_date()); + }; + AutofillProfile profile(test::GetFullProfile()); - EXPECT_EQ(1U, profile.use_count()); - EXPECT_EQ(kArbitraryTime, profile.use_date()); - EXPECT_EQ(kArbitraryTime, profile.modification_date()); + Check(profile, 1u, kArbitraryTime, kArbitraryTime); AddProfileToPersonalDataManager(profile); CreditCard credit_card(base::GenerateGUID(), test::kEmptyOrigin); test::SetCreditCardInfo(&credit_card, "John Dillinger", "4234567890123456" /* Visa */, "01", "2999", "1"); - EXPECT_EQ(1U, credit_card.use_count()); - EXPECT_EQ(kArbitraryTime, credit_card.use_date()); - EXPECT_EQ(kArbitraryTime, credit_card.modification_date()); + Check(credit_card, 1u, kArbitraryTime, kArbitraryTime); personal_data_->AddCreditCard(credit_card); // Make sure everything is set up correctly. @@ -3950,40 +3953,43 @@ personal_data_->GetProfileByGUID(profile.guid()); ASSERT_TRUE(added_profile); EXPECT_EQ(*added_profile, profile); - EXPECT_EQ(1U, added_profile->use_count()); - EXPECT_EQ(kArbitraryTime, added_profile->use_date()); - EXPECT_EQ(kArbitraryTime, added_profile->modification_date()); - - base::RunLoop run_loop; - EXPECT_CALL(personal_data_observer_, OnPersonalDataFinishedProfileTasks()) - .WillOnce(QuitMessageLoop(&run_loop)); - EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged()).Times(1); - - personal_data_->RecordUseOf(profile); - - run_loop.Run(); + Check(*added_profile, 1u, kArbitraryTime, kArbitraryTime); CreditCard* added_card = personal_data_->GetCreditCardByGUID(credit_card.guid()); ASSERT_TRUE(added_card); EXPECT_EQ(*added_card, credit_card); - EXPECT_EQ(1U, added_card->use_count()); - EXPECT_EQ(kArbitraryTime, added_card->use_date()); - EXPECT_EQ(kArbitraryTime, added_card->modification_date()); - personal_data_->RecordUseOf(credit_card); + Check(*added_card, 1u, kArbitraryTime, kArbitraryTime); - // Verify usage stats are updated. + // Use |profile|, then verify usage stats. + base::RunLoop profile_run_loop; + EXPECT_CALL(personal_data_observer_, OnPersonalDataFinishedProfileTasks()) + .WillOnce(QuitMessageLoop(&profile_run_loop)); + EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged()).Times(1); + personal_data_->RecordUseOf(profile); + profile_run_loop.Run(); + added_profile = personal_data_->GetProfileByGUID(profile.guid()); - ASSERT_TRUE(added_profile); - EXPECT_EQ(2U, added_profile->use_count()); - EXPECT_EQ(kSomeLaterTime, added_profile->use_date()); - EXPECT_EQ(kArbitraryTime, added_profile->modification_date()); - added_card = personal_data_->GetCreditCardByGUID(credit_card.guid()); + ASSERT_TRUE(added_profile); ASSERT_TRUE(added_card); - EXPECT_EQ(2U, added_card->use_count()); - EXPECT_EQ(kSomeLaterTime, added_card->use_date()); - EXPECT_EQ(kArbitraryTime, added_card->modification_date()); + Check(*added_profile, 2u, kSomeLaterTime, kArbitraryTime); + Check(*added_card, 1u, kArbitraryTime, kArbitraryTime); + + // Use |credit_card|, then verify usage stats. + base::RunLoop credit_card_run_loop; + EXPECT_CALL(personal_data_observer_, OnPersonalDataFinishedProfileTasks()) + .WillOnce(QuitMessageLoop(&credit_card_run_loop)); + EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged()).Times(1); + personal_data_->RecordUseOf(credit_card); + credit_card_run_loop.Run(); + + added_profile = personal_data_->GetProfileByGUID(profile.guid()); + added_card = personal_data_->GetCreditCardByGUID(credit_card.guid()); + ASSERT_TRUE(added_profile); + ASSERT_TRUE(added_card); + Check(*added_profile, 2u, kSomeLaterTime, kArbitraryTime); + Check(*added_card, 2u, kSomeLaterTime, kArbitraryTime); } TEST_F(PersonalDataManagerTest, ClearAllServerData) {
diff --git a/components/autofill/core/common/autofill_features.cc b/components/autofill/core/common/autofill_features.cc index 5a5c6a33..1899168 100644 --- a/components/autofill/core/common/autofill_features.cc +++ b/components/autofill/core/common/autofill_features.cc
@@ -161,12 +161,12 @@ const base::Feature kAutofillNameSectionsWithRendererIds{ "AutofillNameSectionsWithRendererIds", base::FEATURE_DISABLED_BY_DEFAULT}; -// When enabled, autofill suggestions are displayed in the keyboard accessory +// When enabled, Autofill suggestions are displayed in the keyboard accessory // instead of the regular popup. const base::Feature kAutofillKeyboardAccessory{ "AutofillKeyboardAccessory", base::FEATURE_DISABLED_BY_DEFAULT}; -// When enabled, autofill will use new logic to strip both prefixes +// When enabled, Autofill will use new logic to strip both prefixes // and suffixes when setting FormStructure::parseable_name_ extern const base::Feature kAutofillLabelAffixRemoval{ "AutofillLabelAffixRemoval", base::FEATURE_DISABLED_BY_DEFAULT}; @@ -180,7 +180,7 @@ const base::Feature kAutofillOffNoServerData{"AutofillOffNoServerData", base::FEATURE_DISABLED_BY_DEFAULT}; -// If feature is enabled, autofill will be disabled for mixed forms (forms on +// If feature is enabled, Autofill will be disabled for mixed forms (forms on // HTTPS sites that submit over HTTP). const base::Feature kAutofillPreventMixedFormsFilling{ "AutofillPreventMixedFormsFilling", base::FEATURE_DISABLED_BY_DEFAULT}; @@ -285,6 +285,11 @@ "AutofillUsePageLanguageToSelectFieldParsingPatterns", base::FEATURE_DISABLED_BY_DEFAULT}; +// When enabled, Autofill will load remote patterns via the component updater. +// TODO(crbug/1121990): Remove once launched. +extern const base::Feature kAutofillUseRemotePatterns{ + "AutofillUseRemotePatterns", base::FEATURE_DISABLED_BY_DEFAULT}; + #if defined(OS_ANDROID) // Controls whether the Autofill manual fallback for Addresses and Payments is // present on Android.
diff --git a/components/autofill/core/common/autofill_features.h b/components/autofill/core/common/autofill_features.h index 304bfd0..010fbda5 100644 --- a/components/autofill/core/common/autofill_features.h +++ b/components/autofill/core/common/autofill_features.h
@@ -71,6 +71,7 @@ extern const base::Feature kAutofillUseImprovedLabelDisambiguation; extern const base::Feature kAutofillUseNewSectioningMethod; extern const base::Feature kAutofillUsePageLanguageToSelectFieldParsingPatterns; +extern const base::Feature kAutofillUseRemotePatterns; #if defined(OS_ANDROID) extern const base::Feature kAutofillManualFallbackAndroid;
diff --git a/components/autofill/core/common/language_code.h b/components/autofill/core/common/language_code.h index eb7a6789..ae6570fe 100644 --- a/components/autofill/core/common/language_code.h +++ b/components/autofill/core/common/language_code.h
@@ -9,15 +9,18 @@ #include <string> #include <utility> +#include "base/check.h" #include "base/ranges/algorithm.h" #include "base/types/strong_alias.h" namespace autofill { // Following the implicit conventions in //components/translate, a LanguageCode -// in is a lowercase alphabetic string of length up to 3, or "zh-CN", or -// "zh-TW". A non-exhaustive list of common values is +// is a lowercase alphabetic string of length up to 3, or "zh-CN", or "zh-TW". A +// non-exhaustive list of common values is // translate::kDefaultSupportedLanguages. +// C++ small string optimization keeps these objects lightweight so that copying +// should not be a worry. class LanguageCode : public base::StrongAlias<class LanguageCodeTag, std::string> { private:
diff --git a/components/external_intents/android/java/src/org/chromium/components/external_intents/ExternalNavigationDelegate.java b/components/external_intents/android/java/src/org/chromium/components/external_intents/ExternalNavigationDelegate.java index 62b3ff7..72a6336 100644 --- a/components/external_intents/android/java/src/org/chromium/components/external_intents/ExternalNavigationDelegate.java +++ b/components/external_intents/android/java/src/org/chromium/components/external_intents/ExternalNavigationDelegate.java
@@ -11,7 +11,7 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import org.chromium.components.external_intents.ExternalNavigationHandler.OverrideUrlLoadingResultType; +import org.chromium.components.external_intents.ExternalNavigationHandler.OverrideUrlLoadingResult; import org.chromium.content_public.browser.LoadUrlParams; import org.chromium.content_public.browser.WebContents; import org.chromium.ui.base.WindowAndroid; @@ -100,10 +100,10 @@ * @param intent The intent to be handled by the embedder. * @param referrerUrl The referrer for the current navigation. * @param fallbackUrl The fallback URL to load if the intent cannot be handled by the embedder. - * @return The OverrideUrlLoadingResultType for the action taken by the embedder. + * @return The OverrideUrlLoadingResult for the action taken by the embedder. */ - @OverrideUrlLoadingResultType - int handleIncognitoIntentTargetingSelf(Intent intent, String referrerUrl, String fallbackUrl); + OverrideUrlLoadingResult handleIncognitoIntentTargetingSelf( + Intent intent, String referrerUrl, String fallbackUrl); /** * Loads a URL as specified by |loadUrlParams| if possible. May fail in exceptional conditions
diff --git a/components/external_intents/android/java/src/org/chromium/components/external_intents/ExternalNavigationHandler.java b/components/external_intents/android/java/src/org/chromium/components/external_intents/ExternalNavigationHandler.java index a89afce..86feda6 100644 --- a/components/external_intents/android/java/src/org/chromium/components/external_intents/ExternalNavigationHandler.java +++ b/components/external_intents/android/java/src/org/chromium/components/external_intents/ExternalNavigationHandler.java
@@ -204,6 +204,38 @@ } /** + * Packages information about the result of a check of whether we should override URL loading. + */ + public static class OverrideUrlLoadingResult { + @OverrideUrlLoadingResultType + int mResultType; + + OverrideUrlLoadingResult(@OverrideUrlLoadingResultType int resultType) { + mResultType = resultType; + } + + public @OverrideUrlLoadingResultType int getResultType() { + return mResultType; + } + + public static OverrideUrlLoadingResult forAsyncAction() { + return new OverrideUrlLoadingResult( + OverrideUrlLoadingResultType.OVERRIDE_WITH_ASYNC_ACTION); + } + public static OverrideUrlLoadingResult forNoOverride() { + return new OverrideUrlLoadingResult(OverrideUrlLoadingResultType.NO_OVERRIDE); + } + public static OverrideUrlLoadingResult forClobberingTab() { + return new OverrideUrlLoadingResult( + OverrideUrlLoadingResultType.OVERRIDE_WITH_CLOBBERING_TAB); + } + public static OverrideUrlLoadingResult forExternalIntent() { + return new OverrideUrlLoadingResult( + OverrideUrlLoadingResultType.OVERRIDE_WITH_EXTERNAL_INTENT); + } + } + + /** * Constructs a new instance of {@link ExternalNavigationHandler}, using the injected * {@link ExternalNavigationDelegate}. */ @@ -217,8 +249,7 @@ * @return Whether the URL generated an intent, caused a navigation in * current tab, or wasn't handled at all. */ - public @OverrideUrlLoadingResultType int shouldOverrideUrlLoading( - ExternalNavigationParams params) { + public OverrideUrlLoadingResult shouldOverrideUrlLoading(ExternalNavigationParams params) { if (DEBUG) Log.i(TAG, "shouldOverrideUrlLoading called on " + params.getUrl()); Intent targetIntent; // Perform generic parsing of the URI to turn it into an Intent. @@ -226,7 +257,7 @@ targetIntent = Intent.parseUri(params.getUrl(), Intent.URI_INTENT_SCHEME); } catch (Exception ex) { Log.w(TAG, "Bad URI %s", params.getUrl(), ex); - return OverrideUrlLoadingResultType.NO_OVERRIDE; + return OverrideUrlLoadingResult.forNoOverride(); } String browserFallbackUrl = @@ -241,14 +272,13 @@ MutableBoolean canLaunchExternalFallbackResult = new MutableBoolean(); long time = SystemClock.elapsedRealtime(); - @OverrideUrlLoadingResultType - int result = shouldOverrideUrlLoadingInternal( + OverrideUrlLoadingResult result = shouldOverrideUrlLoadingInternal( params, targetIntent, browserFallbackUrl, canLaunchExternalFallbackResult); assert canLaunchExternalFallbackResult.get() != null; RecordHistogram.recordTimesHistogram( "Android.StrictMode.OverrideUrlLoadingTime", SystemClock.elapsedRealtime() - time); - if (result != OverrideUrlLoadingResultType.NO_OVERRIDE) { + if (result.getResultType() != OverrideUrlLoadingResultType.NO_OVERRIDE) { int pageTransitionCore = params.getPageTransition() & PageTransition.CORE_MASK; boolean isFormSubmit = pageTransitionCore == PageTransition.FORM_SUBMIT; boolean isRedirectFromFormSubmit = isFormSubmit && params.isRedirect(); @@ -257,7 +287,8 @@ "Android.Intent.LaunchExternalAppFormSubmitHasUserGesture", params.hasUserGesture()); } - } else if (result == OverrideUrlLoadingResultType.NO_OVERRIDE && browserFallbackUrl != null + } else if (result.getResultType() == OverrideUrlLoadingResultType.NO_OVERRIDE + && browserFallbackUrl != null && (params.getRedirectHandler() == null // For instance, if this is a chained fallback URL, we ignore it. || !params.getRedirectHandler().shouldNotOverrideUrlLoading())) { @@ -268,7 +299,7 @@ return result; } - private @OverrideUrlLoadingResultType int handleFallbackUrl(ExternalNavigationParams params, + private OverrideUrlLoadingResult handleFallbackUrl(ExternalNavigationParams params, Intent targetIntent, String browserFallbackUrl, boolean canLaunchExternalFallback) { if (mDelegate.isIntentToInstantApp(targetIntent)) { RecordHistogram.recordEnumeratedHistogram("Android.InstantApps.DirectInstantAppsIntent", @@ -286,7 +317,7 @@ List<ResolveInfo> resolvingInfos = queryIntentActivities(intent); if (!isAlreadyInTargetWebApk(resolvingInfos, params) && launchWebApkIfSoleIntentHandler(resolvingInfos, intent)) { - return OverrideUrlLoadingResultType.OVERRIDE_WITH_EXTERNAL_INTENT; + return OverrideUrlLoadingResult.forExternalIntent(); } } catch (Exception e) { if (DEBUG) Log.i(TAG, "Could not parse fallback url as intent"); @@ -307,7 +338,7 @@ // http://crbug.com/364522. if (!params.isMainFrame()) { if (DEBUG) Log.i(TAG, "Don't support fallback url in subframes"); - return OverrideUrlLoadingResultType.NO_OVERRIDE; + return OverrideUrlLoadingResult.forNoOverride(); } // NOTE: any further redirection from fall-back URL should not override URL loading. @@ -321,9 +352,9 @@ return clobberCurrentTab(browserFallbackUrl, params.getReferrerUrl()); } - private void printDebugShouldOverrideUrlLoadingResultType(int result) { + private void printDebugShouldOverrideUrlLoadingResultType(OverrideUrlLoadingResult result) { String resultString; - switch (result) { + switch (result.getResultType()) { case OverrideUrlLoadingResultType.OVERRIDE_WITH_EXTERNAL_INTENT: resultString = "OVERRIDE_WITH_EXTERNAL_INTENT"; break; @@ -471,7 +502,7 @@ * intent.) */ @VisibleForTesting - protected @OverrideUrlLoadingResultType int clobberCurrentTab(String url, String referrerUrl) { + protected OverrideUrlLoadingResult clobberCurrentTab(String url, String referrerUrl) { int transitionType = PageTransition.LINK; final LoadUrlParams loadUrlParams = new LoadUrlParams(url, transitionType); if (!TextUtils.isEmpty(referrerUrl)) { @@ -488,7 +519,7 @@ mDelegate.loadUrlIfPossible(loadUrlParams); } }); - return OverrideUrlLoadingResultType.OVERRIDE_WITH_CLOBBERING_TAB; + return OverrideUrlLoadingResult.forClobberingTab(); } else { assert false : "clobberCurrentTab was called with an empty tab."; Uri uri = Uri.parse(url); @@ -498,7 +529,7 @@ intent.addCategory(Intent.CATEGORY_BROWSABLE); intent.setPackage(packageName); startActivity(intent, false, mDelegate); - return OverrideUrlLoadingResultType.OVERRIDE_WITH_EXTERNAL_INTENT; + return OverrideUrlLoadingResult.forExternalIntent(); } } @@ -779,17 +810,17 @@ * If the intent can't be resolved, we should fall back to the browserFallbackUrl, or try to * find the app on the market if no fallback is provided. */ - private int handleUnresolvableIntent( + private OverrideUrlLoadingResult handleUnresolvableIntent( ExternalNavigationParams params, Intent targetIntent, String browserFallbackUrl) { // Fallback URL will be handled by the caller of shouldOverrideUrlLoadingInternal. - if (browserFallbackUrl != null) return OverrideUrlLoadingResultType.NO_OVERRIDE; + if (browserFallbackUrl != null) return OverrideUrlLoadingResult.forNoOverride(); if (targetIntent.getPackage() != null) return handleWithMarketIntent(params, targetIntent); if (DEBUG) Log.i(TAG, "Could not find an external activity to use"); - return OverrideUrlLoadingResultType.NO_OVERRIDE; + return OverrideUrlLoadingResult.forNoOverride(); } - private @OverrideUrlLoadingResultType int handleWithMarketIntent( + private OverrideUrlLoadingResult handleWithMarketIntent( ExternalNavigationParams params, Intent intent) { String marketReferrer = IntentUtils.safeGetStringExtra(intent, EXTRA_MARKET_REFERRER); if (TextUtils.isEmpty(marketReferrer)) { @@ -851,9 +882,9 @@ * This is the catch-all path for any intent that the app can handle that doesn't have a * specialized external app handling it. */ - private @OverrideUrlLoadingResultType int fallBackToHandlingInApp() { + private OverrideUrlLoadingResult fallBackToHandlingInApp() { if (DEBUG) Log.i(TAG, "No specialized handler for URL"); - return OverrideUrlLoadingResultType.NO_OVERRIDE; + return OverrideUrlLoadingResult.forNoOverride(); } /** @@ -950,7 +981,7 @@ params.isRendererInitiated(), params.getInitiatorOrigin()); } - private @OverrideUrlLoadingResultType int handleExternalIncognitoIntent(Intent targetIntent, + private OverrideUrlLoadingResult handleExternalIncognitoIntent(Intent targetIntent, ExternalNavigationParams params, String browserFallbackUrl, boolean shouldProxyForInstantApps) { // This intent may leave this app. Warn the user that incognito does not carry over @@ -959,10 +990,10 @@ params.shouldCloseContentsOnOverrideUrlLoadingAndLaunchIntent(), shouldProxyForInstantApps)) { if (DEBUG) Log.i(TAG, "Incognito navigation out"); - return OverrideUrlLoadingResultType.OVERRIDE_WITH_ASYNC_ACTION; + return OverrideUrlLoadingResult.forAsyncAction(); } if (DEBUG) Log.i(TAG, "Failed to show incognito alert dialog."); - return OverrideUrlLoadingResultType.NO_OVERRIDE; + return OverrideUrlLoadingResult.forNoOverride(); } /** @@ -1129,7 +1160,7 @@ || blockExternalNavFromBackgroundTab(params) || ignoreBackForwardNav(params); } - private @OverrideUrlLoadingResultType int shouldOverrideUrlLoadingInternal( + private OverrideUrlLoadingResult shouldOverrideUrlLoadingInternal( ExternalNavigationParams params, Intent targetIntent, @Nullable String browserFallbackUrl, MutableBoolean canLaunchExternalFallbackResult) { sanitizeQueryIntentActivitiesIntent(targetIntent); @@ -1137,29 +1168,29 @@ canLaunchExternalFallbackResult.set(false); if (shouldBlockAllExternalAppLaunches(params)) { - return OverrideUrlLoadingResultType.NO_OVERRIDE; + return OverrideUrlLoadingResult.forNoOverride(); } if (handleWithAutofillAssistant(params, targetIntent, browserFallbackUrl)) { - return OverrideUrlLoadingResultType.NO_OVERRIDE; + return OverrideUrlLoadingResult.forNoOverride(); } boolean isExternalProtocol = !UrlUtilities.isAcceptedScheme(params.getUrl()); if (isInternalPdfDownload(isExternalProtocol, params)) { - return OverrideUrlLoadingResultType.NO_OVERRIDE; + return OverrideUrlLoadingResult.forNoOverride(); } // This check should happen for reloads, navigations, etc..., which is why // it occurs before the subsequent blocks. if (startFileIntentIfNecessary(params, targetIntent)) { - return OverrideUrlLoadingResultType.OVERRIDE_WITH_ASYNC_ACTION; + return OverrideUrlLoadingResult.forAsyncAction(); } // This should come after file intents, but before any returns of // OVERRIDE_WITH_EXTERNAL_INTENT. if (externalIntentRequestsDisabledForUrl(params)) { - return OverrideUrlLoadingResultType.NO_OVERRIDE; + return OverrideUrlLoadingResult.forNoOverride(); } int pageTransitionCore = params.getPageTransition() & PageTransition.CORE_MASK; @@ -1178,42 +1209,42 @@ (isLink && isFromIntent && params.isRedirect()) || isOnEffectiveIntentRedirect; if (handleCCTRedirectsToInstantApps(params, isExternalProtocol, incomingIntentRedirect)) { - return OverrideUrlLoadingResultType.OVERRIDE_WITH_EXTERNAL_INTENT; + return OverrideUrlLoadingResult.forExternalIntent(); } else if (redirectShouldStayInApp(params, isExternalProtocol, targetIntent)) { - return OverrideUrlLoadingResultType.NO_OVERRIDE; + return OverrideUrlLoadingResult.forNoOverride(); } if (!preferToShowIntentPicker(params, pageTransitionCore, isExternalProtocol, isFormSubmit, linkNotFromIntent, incomingIntentRedirect)) { - return OverrideUrlLoadingResultType.NO_OVERRIDE; + return OverrideUrlLoadingResult.forNoOverride(); } - if (isLinkFromChromeInternalPage(params)) return OverrideUrlLoadingResultType.NO_OVERRIDE; + if (isLinkFromChromeInternalPage(params)) return OverrideUrlLoadingResult.forNoOverride(); if (handleWtaiMcProtocol(params)) { - return OverrideUrlLoadingResultType.OVERRIDE_WITH_EXTERNAL_INTENT; + return OverrideUrlLoadingResult.forExternalIntent(); } // TODO: handle other WTAI schemes. - if (isUnhandledWtaiProtocol(params)) return OverrideUrlLoadingResultType.NO_OVERRIDE; + if (isUnhandledWtaiProtocol(params)) return OverrideUrlLoadingResult.forNoOverride(); boolean hasIntentScheme = params.getUrl().startsWith(UrlConstants.INTENT_URL_SHORT_PREFIX) || params.getUrl().startsWith(UrlConstants.APP_INTENT_URL_SHORT_PREFIX); if (hasInternalScheme(params, targetIntent, hasIntentScheme)) { - return OverrideUrlLoadingResultType.NO_OVERRIDE; + return OverrideUrlLoadingResult.forNoOverride(); } if (hasContentScheme(params, targetIntent, hasIntentScheme)) { - return OverrideUrlLoadingResultType.NO_OVERRIDE; + return OverrideUrlLoadingResult.forNoOverride(); } if (hasFileSchemeInIntentURI(targetIntent, hasIntentScheme)) { - return OverrideUrlLoadingResultType.NO_OVERRIDE; + return OverrideUrlLoadingResult.forNoOverride(); } - if (isYoutubePairingCode(params)) return OverrideUrlLoadingResultType.NO_OVERRIDE; + if (isYoutubePairingCode(params)) return OverrideUrlLoadingResult.forNoOverride(); if (shouldStayInIncognito(params, isExternalProtocol)) { - return OverrideUrlLoadingResultType.NO_OVERRIDE; + return OverrideUrlLoadingResult.forNoOverride(); } if (!maybeSetSmsPackage(targetIntent)) maybeRecordPhoneIntentMetrics(targetIntent); @@ -1236,7 +1267,7 @@ if (!isExternalProtocol && !hasSpecializedHandler) { if (fallBackToHandlingWithInstantApp( params, incomingIntentRedirect, linkNotFromIntent)) { - return OverrideUrlLoadingResultType.OVERRIDE_WITH_EXTERNAL_INTENT; + return OverrideUrlLoadingResult.forExternalIntent(); } return fallBackToHandlingInApp(); } @@ -1246,14 +1277,14 @@ if (shouldStayWithinHost( params, isLink, isFormSubmit, resolvingInfos, isExternalProtocol)) { - return OverrideUrlLoadingResultType.NO_OVERRIDE; + return OverrideUrlLoadingResult.forNoOverride(); } boolean isDirectInstantAppsIntent = isExternalProtocol && mDelegate.isIntentToInstantApp(targetIntent); boolean shouldProxyForInstantApps = isDirectInstantAppsIntent && isSerpReferrer(); if (preventDirectInstantAppsIntent(isDirectInstantAppsIntent, shouldProxyForInstantApps)) { - return OverrideUrlLoadingResultType.NO_OVERRIDE; + return OverrideUrlLoadingResult.forNoOverride(); } prepareExternalIntent(targetIntent, params, resolvingInfos, shouldProxyForInstantApps); @@ -1279,18 +1310,18 @@ if (shouldKeepIntentRedirectInApp( params, incomingIntentRedirect, resolvingInfos, isExternalProtocol)) { - return OverrideUrlLoadingResultType.NO_OVERRIDE; + return OverrideUrlLoadingResult.forNoOverride(); } if (isAlreadyInTargetWebApk(resolvingInfos, params)) { - return OverrideUrlLoadingResultType.NO_OVERRIDE; + return OverrideUrlLoadingResult.forNoOverride(); } else if (launchWebApkIfSoleIntentHandler(resolvingInfos, targetIntent)) { - return OverrideUrlLoadingResultType.OVERRIDE_WITH_EXTERNAL_INTENT; + return OverrideUrlLoadingResult.forExternalIntent(); } if (launchExternalIntent(targetIntent, shouldProxyForInstantApps)) { - return OverrideUrlLoadingResultType.OVERRIDE_WITH_EXTERNAL_INTENT; + return OverrideUrlLoadingResult.forExternalIntent(); } - return OverrideUrlLoadingResultType.NO_OVERRIDE; + return OverrideUrlLoadingResult.forNoOverride(); } /** @@ -1312,7 +1343,7 @@ * @return OVERRIDE_WITH_EXTERNAL_INTENT when we successfully started market activity, * NO_OVERRIDE otherwise. */ - private @OverrideUrlLoadingResultType int sendIntentToMarket( + private OverrideUrlLoadingResult sendIntentToMarket( String packageName, String marketReferrer, ExternalNavigationParams params) { Uri marketUri = new Uri.Builder() @@ -1332,7 +1363,7 @@ if (!deviceCanHandleIntent(intent)) { // Exit early if the Play Store isn't available. (https://crbug.com/820709) if (DEBUG) Log.i(TAG, "Play Store not installed."); - return OverrideUrlLoadingResultType.NO_OVERRIDE; + return OverrideUrlLoadingResult.forNoOverride(); } if (params.isIncognito()) { @@ -1340,14 +1371,14 @@ params.shouldCloseContentsOnOverrideUrlLoadingAndLaunchIntent(), false)) { if (DEBUG) Log.i(TAG, "Failed to show incognito alert dialog."); - return OverrideUrlLoadingResultType.NO_OVERRIDE; + return OverrideUrlLoadingResult.forNoOverride(); } if (DEBUG) Log.i(TAG, "Incognito intent to Play Store."); - return OverrideUrlLoadingResultType.OVERRIDE_WITH_ASYNC_ACTION; + return OverrideUrlLoadingResult.forAsyncAction(); } else { startActivity(intent, false, mDelegate); if (DEBUG) Log.i(TAG, "Intent to Play Store."); - return OverrideUrlLoadingResultType.OVERRIDE_WITH_EXTERNAL_INTENT; + return OverrideUrlLoadingResult.forExternalIntent(); } }
diff --git a/components/external_intents/android/java/src/org/chromium/components/external_intents/InterceptNavigationDelegateImpl.java b/components/external_intents/android/java/src/org/chromium/components/external_intents/InterceptNavigationDelegateImpl.java index 7b46d1a..817f638 100644 --- a/components/external_intents/android/java/src/org/chromium/components/external_intents/InterceptNavigationDelegateImpl.java +++ b/components/external_intents/android/java/src/org/chromium/components/external_intents/InterceptNavigationDelegateImpl.java
@@ -81,7 +81,8 @@ ExternalNavigationParams params = new ExternalNavigationParams.Builder(url, incognito).setOpenInNewTab(true).build(); - mLastOverrideUrlLoadingResultType = mExternalNavHandler.shouldOverrideUrlLoading(params); + mLastOverrideUrlLoadingResultType = + mExternalNavHandler.shouldOverrideUrlLoading(params).getResultType(); return mLastOverrideUrlLoadingResultType != ExternalNavigationHandler.OverrideUrlLoadingResultType.NO_OVERRIDE; } @@ -131,7 +132,7 @@ buildExternalNavigationParams(navigationParams, redirectHandler, shouldCloseTab) .build(); @OverrideUrlLoadingResultType - int result = mExternalNavHandler.shouldOverrideUrlLoading(params); + int result = mExternalNavHandler.shouldOverrideUrlLoading(params).getResultType(); mLastOverrideUrlLoadingResultType = result; switch (result) {
diff --git a/components/external_intents/android/javatests/src/org/chromium/components/external_intents/ExternalNavigationHandlerTest.java b/components/external_intents/android/javatests/src/org/chromium/components/external_intents/ExternalNavigationHandlerTest.java index 5165306..fe07bf1 100644 --- a/components/external_intents/android/javatests/src/org/chromium/components/external_intents/ExternalNavigationHandlerTest.java +++ b/components/external_intents/android/javatests/src/org/chromium/components/external_intents/ExternalNavigationHandlerTest.java
@@ -34,6 +34,7 @@ import org.chromium.base.metrics.RecordHistogram; import org.chromium.base.test.BaseJUnit4ClassRunner; import org.chromium.base.test.util.Batch; +import org.chromium.components.external_intents.ExternalNavigationHandler.OverrideUrlLoadingResult; import org.chromium.components.external_intents.ExternalNavigationHandler.OverrideUrlLoadingResultType; import org.chromium.content_public.browser.LoadUrlParams; import org.chromium.content_public.browser.WebContents; @@ -1235,9 +1236,9 @@ new ExternalNavigationParams.Builder(YOUTUBE_MOBILE_URL, false) .setOpenInNewTab(true) .build(); - @OverrideUrlLoadingResultType - int result = mUrlHandler.shouldOverrideUrlLoading(params); - Assert.assertEquals(OverrideUrlLoadingResultType.OVERRIDE_WITH_EXTERNAL_INTENT, result); + OverrideUrlLoadingResult result = mUrlHandler.shouldOverrideUrlLoading(params); + Assert.assertEquals( + OverrideUrlLoadingResultType.OVERRIDE_WITH_EXTERNAL_INTENT, result.getResultType()); Assert.assertTrue(mDelegate.startActivityIntent != null); Assert.assertTrue( mDelegate.startActivityIntent.getBooleanExtra(Browser.EXTRA_CREATE_NEW_TAB, false)); @@ -2031,11 +2032,10 @@ } @Override - protected @OverrideUrlLoadingResultType int clobberCurrentTab( - String url, String referrerUrl) { + protected OverrideUrlLoadingResult clobberCurrentTab(String url, String referrerUrl) { mNewUrlAfterClobbering = url; mReferrerUrlForClobbering = referrerUrl; - return OverrideUrlLoadingResultType.OVERRIDE_WITH_CLOBBERING_TAB; + return OverrideUrlLoadingResult.forClobberingTab(); } }; @@ -2115,11 +2115,11 @@ } @Override - public @OverrideUrlLoadingResultType int handleIncognitoIntentTargetingSelf( + public OverrideUrlLoadingResult handleIncognitoIntentTargetingSelf( Intent intent, String referrerUrl, String fallbackUrl) { handleIncognitoIntentTargetingSelfCalled = true; - if (mCanLoadUrlInTab) return OverrideUrlLoadingResultType.OVERRIDE_WITH_CLOBBERING_TAB; - return OverrideUrlLoadingResultType.OVERRIDE_WITH_EXTERNAL_INTENT; + if (mCanLoadUrlInTab) return OverrideUrlLoadingResult.forClobberingTab(); + return OverrideUrlLoadingResult.forExternalIntent(); } @Override @@ -2412,8 +2412,7 @@ .setHasUserGesture(mHasUserGesture) .setIsRendererInitiated(mIsRendererInitiated) .build(); - @OverrideUrlLoadingResultType - int result = mUrlHandler.shouldOverrideUrlLoading(params); + OverrideUrlLoadingResult result = mUrlHandler.shouldOverrideUrlLoading(params); boolean startActivityCalled = false; boolean startWebApkCalled = false; @@ -2431,7 +2430,7 @@ } } - Assert.assertEquals(expectedOverrideResult, result); + Assert.assertEquals(expectedOverrideResult, result.getResultType()); Assert.assertEquals(expectStartIncognito, mUrlHandler.mStartIncognitoIntentCalled); Assert.assertEquals(expectStartActivity, startActivityCalled); Assert.assertEquals(expectStartWebApk, startWebApkCalled);
diff --git a/components/omnibox/browser/autocomplete_controller.cc b/components/omnibox/browser/autocomplete_controller.cc index 70b9a2aa..fef8a67 100644 --- a/components/omnibox/browser/autocomplete_controller.cc +++ b/components/omnibox/browser/autocomplete_controller.cc
@@ -317,7 +317,6 @@ OnDeviceHeadProvider::Create(provider_client_.get(), this); if (on_device_head_provider_) { providers_.push_back(on_device_head_provider_); - on_device_head_provider_->AddModelUpdateCallback(); } } if (provider_types & AutocompleteProvider::TYPE_CLIPBOARD) {
diff --git a/components/omnibox/browser/on_device_head_provider.cc b/components/omnibox/browser/on_device_head_provider.cc index b142afb..3c93e13b 100644 --- a/components/omnibox/browser/on_device_head_provider.cc +++ b/components/omnibox/browser/on_device_head_provider.cc
@@ -22,6 +22,7 @@ #include "components/omnibox/browser/base_search_provider.h" #include "components/omnibox/browser/omnibox_field_trial.h" #include "components/omnibox/browser/on_device_head_provider.h" +#include "components/omnibox/browser/on_device_model_update_listener.h" #include "components/omnibox/common/omnibox_features.h" #include "components/search_engines/omnibox_focus_type.h" #include "components/search_engines/search_terms_data.h" @@ -94,20 +95,6 @@ OnDeviceHeadProvider::~OnDeviceHeadProvider() {} -void OnDeviceHeadProvider::AddModelUpdateCallback() { - // Bail out if we have already subscribed. - if (model_update_subscription_) { - return; - } - - auto* model_update_listener = OnDeviceModelUpdateListener::GetInstance(); - if (model_update_listener) { - model_update_subscription_ = model_update_listener->AddModelUpdateCallback( - base::BindRepeating(&OnDeviceHeadProvider::OnModelUpdate, - weak_ptr_factory_.GetWeakPtr())); - } -} - bool OnDeviceHeadProvider::IsOnDeviceHeadProviderAllowed( const AutocompleteInput& input) { DCHECK_CALLED_ON_VALID_SEQUENCE(main_sequence_checker_); @@ -158,7 +145,7 @@ return; matches_.clear(); - if (input.text().empty() || model_filename_.empty()) + if (input.text().empty() || GetOnDeviceHeadModelFilename().empty()) return; // Note |on_device_search_request_id_| has already been changed in |Stop| so @@ -198,13 +185,6 @@ done_ = true; } -void OnDeviceHeadProvider::OnModelUpdate( - const std::string& new_model_filename) { - DCHECK_CALLED_ON_VALID_SEQUENCE(main_sequence_checker_); - if (!new_model_filename.empty()) - model_filename_ = new_model_filename; -} - // TODO(crbug.com/925072): post OnDeviceHeadModel::GetSuggestionsForPrefix // directly and remove this function. // static @@ -252,7 +232,8 @@ base::PostTaskAndReplyWithResult( worker_task_runner_.get(), FROM_HERE, base::BindOnce(&OnDeviceHeadProvider::GetSuggestionsFromModel, - model_filename_, provider_max_matches_, std::move(params)), + GetOnDeviceHeadModelFilename(), provider_max_matches_, + std::move(params)), base::BindOnce(&OnDeviceHeadProvider::SearchDone, weak_ptr_factory_.GetWeakPtr())); } @@ -302,3 +283,10 @@ done_ = true; listener_->OnProviderUpdate(true); } + +std::string OnDeviceHeadProvider::GetOnDeviceHeadModelFilename() const { + auto* model_update_listener = OnDeviceModelUpdateListener::GetInstance(); + return model_update_listener != nullptr + ? model_update_listener->model_filename() + : ""; +}
diff --git a/components/omnibox/browser/on_device_head_provider.h b/components/omnibox/browser/on_device_head_provider.h index 26273b2..8035214f 100644 --- a/components/omnibox/browser/on_device_head_provider.h +++ b/components/omnibox/browser/on_device_head_provider.h
@@ -14,7 +14,6 @@ #include "components/omnibox/browser/autocomplete_provider.h" #include "components/omnibox/browser/autocomplete_provider_client.h" #include "components/omnibox/browser/on_device_head_model.h" -#include "components/omnibox/browser/on_device_model_update_listener.h" class AutocompleteProviderListener; @@ -32,10 +31,6 @@ static OnDeviceHeadProvider* Create(AutocompleteProviderClient* client, AutocompleteProviderListener* listener); - // Adds a callback to on device head model updater listener which will update - // |model_filename_| once the model is ready on disk. - void AddModelUpdateCallback(); - void Start(const AutocompleteInput& input, bool minimal_changes) override; void Stop(bool clear_cached_results, bool due_to_user_inactivity) override; void AddProviderInfo(ProvidersInfo* provider_info) const override; @@ -67,9 +62,9 @@ // fetches by DoSearch and then calls OnProviderUpdate. void SearchDone(std::unique_ptr<OnDeviceHeadProviderParams> params); - // Used by OnDeviceModelUpdateListener to notify this provider when new model - // is available. - void OnModelUpdate(const std::string& new_model_filename); + // Helper functions to read model filename from the static + // OnDeviceModelUpdateListener instance. + std::string GetOnDeviceHeadModelFilename() const; // Fetches suggestions matching the params from the given on device head // model. @@ -85,22 +80,15 @@ // added to offload expensive operations out of the UI sequence. scoped_refptr<base::SequencedTaskRunner> worker_task_runner_; - // Sequence checker that ensure utocomplete request handling will only happen - // main thread. + // Sequence checker that ensure autocomplete request handling will only happen + // on main thread. SEQUENCE_CHECKER(main_sequence_checker_); - // The filename points to the on device head model on the disk. - std::string model_filename_; - // The request id used to trace current request to the on device head model. // The id will be increased whenever a new request is received from the // AutocompleteController. size_t on_device_search_request_id_; - // Owns the callback added to the listener such that it can be removed - // automatically from the listener on provider's deconstruction. - base::CallbackListSubscription model_update_subscription_; - base::WeakPtrFactory<OnDeviceHeadProvider> weak_ptr_factory_{this}; };
diff --git a/components/omnibox/browser/on_device_head_provider_unittest.cc b/components/omnibox/browser/on_device_head_provider_unittest.cc index 2bb3ce6..4f03c7e 100644 --- a/components/omnibox/browser/on_device_head_provider_unittest.cc +++ b/components/omnibox/browser/on_device_head_provider_unittest.cc
@@ -15,6 +15,7 @@ #include "components/omnibox/browser/autocomplete_provider_listener.h" #include "components/omnibox/browser/fake_autocomplete_provider_client.h" #include "components/omnibox/browser/on_device_head_model.h" +#include "components/omnibox/browser/on_device_model_update_listener.h" #include "components/omnibox/browser/test_scheme_classifier.h" #include "components/omnibox/common/omnibox_features.h" #include "components/search_engines/omnibox_focus_type.h" @@ -32,7 +33,6 @@ client_.reset(new FakeAutocompleteProviderClient()); SetTestOnDeviceHeadModel(); provider_ = OnDeviceHeadProvider::Create(client_.get(), this); - provider_->AddModelUpdateCallback(); task_environment_.RunUntilIdle(); } @@ -60,9 +60,9 @@ } void ResetModelInstance() { - if (provider_) { - provider_->model_filename_.clear(); - } + auto* update_listener = OnDeviceModelUpdateListener::GetInstance(); + if (update_listener) + update_listener->ResetListenerForTest(); } bool IsOnDeviceHeadProviderAllowed(const AutocompleteInput& input) {
diff --git a/components/omnibox/browser/on_device_model_update_listener.cc b/components/omnibox/browser/on_device_model_update_listener.cc index 1cd0fa23..5a67609 100644 --- a/components/omnibox/browser/on_device_model_update_listener.cc +++ b/components/omnibox/browser/on_device_model_update_listener.cc
@@ -8,7 +8,6 @@ #include "base/strings/utf_string_conversions.h" #include "base/task/post_task.h" #include "base/task/thread_pool.h" -#include "base/task_runner_util.h" #include "build/build_config.h" namespace { @@ -41,35 +40,28 @@ return listener.get(); } -OnDeviceModelUpdateListener::OnDeviceModelUpdateListener() - : task_runner_(base::ThreadPool::CreateSequencedTaskRunner( - {base::TaskPriority::BEST_EFFORT, - base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN, base::MayBlock()})) {} +std::string OnDeviceModelUpdateListener::model_filename() const { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + return model_filename_; +} + +OnDeviceModelUpdateListener::OnDeviceModelUpdateListener() = default; OnDeviceModelUpdateListener::~OnDeviceModelUpdateListener() = default; -base::CallbackListSubscription -OnDeviceModelUpdateListener::AddModelUpdateCallback( - ModelUpdateCallback callback) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - if (!model_filename_.empty()) - callback.Run(model_filename_); - return model_update_callbacks_.Add(callback); -} - void OnDeviceModelUpdateListener::OnModelUpdate( const base::FilePath& model_dir) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); if (!model_dir.empty() && model_dir != model_dir_) { model_dir_ = model_dir; - base::PostTaskAndReplyWithResult( - task_runner_.get(), FROM_HERE, + base::ThreadPool::PostTaskAndReplyWithResult( + FROM_HERE, + {base::TaskPriority::BEST_EFFORT, + base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN, base::MayBlock()}, base::BindOnce(&GetModelFilenameFromDirectory, model_dir), base::BindOnce([](const std::string filename) { - if (!filename.empty()) { + if (!filename.empty()) GetInstance()->model_filename_ = filename; - GetInstance()->model_update_callbacks_.Notify(filename); - } })); } }
diff --git a/components/omnibox/browser/on_device_model_update_listener.h b/components/omnibox/browser/on_device_model_update_listener.h index e162176..1d8d32c 100644 --- a/components/omnibox/browser/on_device_model_update_listener.h +++ b/components/omnibox/browser/on_device_model_update_listener.h
@@ -7,33 +7,22 @@ #include <memory> -#include "base/callback.h" -#include "base/callback_list.h" #include "base/files/file_path.h" #include "base/no_destructor.h" #include "base/threading/thread_checker.h" -// This class is used by OnDeviceHeadSuggestComponentInstaller to notify -// OnDeviceHeadProvider when on device model update is finished. +// This class is used by OnDeviceHeadSuggestComponentInstaller to hold the +// directory & filename for the on device model downloaded by Component Updater. class OnDeviceModelUpdateListener { public: - using ModelUpdateCallback = - base::RepeatingCallback<void(const std::string& new_model_filename)>; - using UpdateCallbacks = base::CallbackList<void(const std::string&)>; - using UpdateSubscription = UpdateCallbacks::Subscription; static OnDeviceModelUpdateListener* GetInstance(); - // Adds a callback which will be run on model update. This method will also - // notify the provider immediately if a model is available. - base::CallbackListSubscription AddModelUpdateCallback( - ModelUpdateCallback callback); - - // Called by Component Updater when model update is completed to notify the - // on device head provider to reload the model. + // Called by Component Updater when model update is completed to update + // |model_dir_| and |model_filename_|. void OnModelUpdate(const base::FilePath& model_dir); - std::string model_filename() const { return model_filename_; } + std::string model_filename() const; private: friend class base::NoDestructor<OnDeviceModelUpdateListener>; @@ -53,13 +42,6 @@ // The filename of the model. std::string model_filename_; - // A list of callbacks which will be run on model update. - UpdateCallbacks model_update_callbacks_; - - // The task runner which will be used to run file operations and - // |model_update_callbacks_|. - scoped_refptr<base::SequencedTaskRunner> task_runner_; - THREAD_CHECKER(thread_checker_); };
diff --git a/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoController.java b/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoController.java index 665c995..b0cb261 100644 --- a/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoController.java +++ b/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoController.java
@@ -488,10 +488,6 @@ mPendingRunAfterDismissTask.run(); mPendingRunAfterDismissTask = null; } - if (mSubpageController != null) { - mSubpageController.onSubpageRemoved(); - mSubpageController = null; - } mWebContentsObserver.destroy(); mWebContentsObserver = null; PageInfoControllerJni.get().destroy(mNativePageInfoController, PageInfoController.this);
diff --git a/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoCookiesController.java b/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoCookiesController.java index 9e7ff66..5b170292 100644 --- a/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoCookiesController.java +++ b/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoCookiesController.java
@@ -122,8 +122,10 @@ public void onSubpageRemoved() { assert mSubPage != null; AppCompatActivity host = (AppCompatActivity) mRowView.getContext(); - host.getSupportFragmentManager().beginTransaction().remove(mSubPage).commitNow(); + PageInfoCookiesPreference subBage = mSubPage; mSubPage = null; + if (host.isFinishing()) return; + host.getSupportFragmentManager().beginTransaction().remove(subBage).commitNow(); } @Override
diff --git a/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoPermissionsController.java b/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoPermissionsController.java index f99090b7..fb30cfa 100644 --- a/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoPermissionsController.java +++ b/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoPermissionsController.java
@@ -65,8 +65,10 @@ public void onSubpageRemoved() { assert mSubpageFragment != null; AppCompatActivity host = (AppCompatActivity) mRowView.getContext(); - host.getSupportFragmentManager().beginTransaction().remove(mSubpageFragment).commitNow(); + SingleWebsiteSettings fragment = mSubpageFragment; mSubpageFragment = null; + if (host.isFinishing()) return; + host.getSupportFragmentManager().beginTransaction().remove(fragment).commitNow(); } public void setPermissions(PageInfoView.PermissionParams params) {
diff --git a/components/password_manager/core/browser/login_database.cc b/components/password_manager/core/browser/login_database.cc index 3108abe3..f57a05f 100644 --- a/components/password_manager/core/browser/login_database.cc +++ b/components/password_manager/core/browser/login_database.cc
@@ -594,16 +594,6 @@ } #endif -// This converts `i` to type `Enum`. Terminates in case `i` is outside the valid -// ranges for `Enum`. Requires `Enum::kMinValue` and `Enum::kMaxValue` to exist -// and have correct semantics. -template <typename Enum> -Enum ToEnumOrDie(int i) { - CHECK_LE(static_cast<int>(Enum::kMinValue), i); - CHECK_GE(static_cast<int>(Enum::kMaxValue), i); - return static_cast<Enum>(i); -} - } // namespace struct LoginDatabase::PrimaryKeyAndPassword { @@ -1437,9 +1427,11 @@ form->date_created = base::Time::FromInternalValue(s.ColumnInt64(COLUMN_DATE_CREATED)); form->blocked_by_user = (s.ColumnInt(COLUMN_BLACKLISTED_BY_USER) > 0); - form->scheme = ToEnumOrDie<PasswordForm::Scheme>(s.ColumnInt(COLUMN_SCHEME)); + // TODO(crbug.com/1151214): Add metrics to capture how often these values fall + // out of the valid enum range. + form->scheme = static_cast<PasswordForm::Scheme>(s.ColumnInt(COLUMN_SCHEME)); form->type = - ToEnumOrDie<PasswordForm::Type>(s.ColumnInt(COLUMN_PASSWORD_TYPE)); + static_cast<PasswordForm::Type>(s.ColumnInt(COLUMN_PASSWORD_TYPE)); if (s.ColumnByteLength(COLUMN_POSSIBLE_USERNAME_PAIRS)) { base::Pickle pickle( static_cast<const char*>(s.ColumnBlob(COLUMN_POSSIBLE_USERNAME_PAIRS)), @@ -1467,7 +1459,7 @@ url::Origin::Create(GURL(s.ColumnString(COLUMN_FEDERATION_URL))); form->skip_zero_click = (s.ColumnInt(COLUMN_SKIP_ZERO_CLICK) > 0); form->generation_upload_status = - ToEnumOrDie<PasswordForm::GenerationUploadStatus>( + static_cast<PasswordForm::GenerationUploadStatus>( s.ColumnInt(COLUMN_GENERATION_UPLOAD_STATUS)); form->date_last_used = base::Time::FromDeltaSinceWindowsEpoch( base::TimeDelta::FromMicroseconds(s.ColumnInt64(COLUMN_DATE_LAST_USED)));
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 56d3800..131f87b 100644 --- a/components/password_manager/core/browser/ui/insecure_credentials_manager.cc +++ b/components/password_manager/core/browser/ui/insecure_credentials_manager.cc
@@ -9,6 +9,7 @@ #include <set> #include "base/bind.h" +#include "base/callback.h" #include "base/containers/flat_set.h" #include "base/metrics/histogram_functions.h" #include "base/ranges/algorithm.h" @@ -238,13 +239,15 @@ compromised_credentials_reader_.Init(); } -void InsecureCredentialsManager::StartWeakCheck() { +void InsecureCredentialsManager::StartWeakCheck( + base::OnceClosure on_check_done) { base::ThreadPool::PostTaskAndReplyWithResult( FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE}, base::BindOnce(&BulkWeakCheck, ExtractPasswords(presenter_->GetSavedPasswords())), base::BindOnce(&InsecureCredentialsManager::OnWeakCheckDone, - weak_ptr_factory_.GetWeakPtr(), base::ElapsedTimer())); + weak_ptr_factory_.GetWeakPtr(), base::ElapsedTimer()) + .Then(std::move(on_check_done))); } void InsecureCredentialsManager::SaveCompromisedCredential(
diff --git a/components/password_manager/core/browser/ui/insecure_credentials_manager.h b/components/password_manager/core/browser/ui/insecure_credentials_manager.h index 5527477..f1e21e5 100644 --- a/components/password_manager/core/browser/ui/insecure_credentials_manager.h +++ b/components/password_manager/core/browser/ui/insecure_credentials_manager.h
@@ -8,6 +8,8 @@ #include <map> #include <vector> +#include "base/callback_forward.h" +#include "base/callback_helpers.h" #include "base/containers/flat_set.h" #include "base/containers/span.h" #include "base/memory/scoped_refptr.h" @@ -164,7 +166,7 @@ // Computes weak credentials in a separate thread and then passes the result // to OnWeakCheckDone. - void StartWeakCheck(); + void StartWeakCheck(base::OnceClosure on_check_done = base::DoNothing()); // Marks all saved credentials which have same username & password as // compromised.
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 bcc2bde6..9ef6d5b 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
@@ -8,6 +8,7 @@ #include "base/strings/string_piece_forward.h" #include "base/strings/utf_string_conversions.h" #include "base/test/metrics/histogram_tester.h" +#include "base/test/mock_callback.h" #include "base/test/task_environment.h" #include "base/timer/elapsed_timer.h" #include "build/build_config.h" @@ -509,6 +510,13 @@ ElementsAreArray(store().stored_passwords().at(kExampleOrg))); } +TEST_F(InsecureCredentialsManagerTest, StartWeakCheckNotifiesOnCompletion) { + base::MockOnceClosure closure; + provider().StartWeakCheck(closure.Get()); + EXPECT_CALL(closure, Run); + RunUntilIdle(); +} + TEST_F(InsecureCredentialsManagerTest, StartWeakCheckOnEmptyPasswordsList) { EXPECT_THAT( histogram_tester().GetTotalCountsForPrefix("PasswordManager.WeakCheck"),
diff --git a/components/password_manager/core/browser/votes_uploader.cc b/components/password_manager/core/browser/votes_uploader.cc index f6b904d..7eeae75 100644 --- a/components/password_manager/core/browser/votes_uploader.cc +++ b/components/password_manager/core/browser/votes_uploader.cc
@@ -369,7 +369,7 @@ } // Annotate the form with the source language of the page. - form_structure.set_page_language(client_->GetPageLanguage()); + form_structure.set_original_page_language(client_->GetPageLanguage()); // Attach the Randomized Encoder. form_structure.set_randomized_encoder( @@ -423,7 +423,7 @@ form_structure.set_upload_required(UPLOAD_REQUIRED); // Annotate the form with the source language of the page. - form_structure.set_page_language(client_->GetPageLanguage()); + form_structure.set_original_page_language(client_->GetPageLanguage()); // Attach the Randomized Encoder. form_structure.set_randomized_encoder(
diff --git a/components/permissions/notification_permission_ui_selector.cc b/components/permissions/notification_permission_ui_selector.cc index b7e0a12..226b7e6 100644 --- a/components/permissions/notification_permission_ui_selector.cc +++ b/components/permissions/notification_permission_ui_selector.cc
@@ -37,4 +37,9 @@ return Decision(UseNormalUi(), ShowNoWarning()); } +base::Optional<PermissionUmaUtil::PredictionGrantLikelihood> +NotificationPermissionUiSelector::PredictedGrantLikelihoodForUKM() { + return base::nullopt; +} + } // namespace permissions
diff --git a/components/permissions/notification_permission_ui_selector.h b/components/permissions/notification_permission_ui_selector.h index 9888bc5..c2dca79f 100644 --- a/components/permissions/notification_permission_ui_selector.h +++ b/components/permissions/notification_permission_ui_selector.h
@@ -8,6 +8,7 @@ #include "base/callback_forward.h" #include "base/optional.h" #include "components/permissions/permission_request.h" +#include "components/permissions/permission_uma_util.h" namespace permissions { @@ -79,6 +80,12 @@ // can be issued. Can be called when there is no pending request which will // simply be a no-op. virtual void Cancel() {} + + // Will return the selector's discretized prediction value, if any is + // applicable to be recorded in UKMs. This is specific only to a selector that + // makes use of the Web Permission Predictions Service to make decisions. + virtual base::Optional<PermissionUmaUtil::PredictionGrantLikelihood> + PredictedGrantLikelihoodForUKM(); }; } // namespace permissions
diff --git a/components/permissions/permission_request_manager.cc b/components/permissions/permission_request_manager.cc index 2a52cec..c11b3c2 100644 --- a/components/permissions/permission_request_manager.cc +++ b/components/permissions/permission_request_manager.cc
@@ -23,7 +23,6 @@ #include "components/permissions/permission_prompt.h" #include "components/permissions/permission_request.h" #include "components/permissions/permission_request_id.h" -#include "components/permissions/permission_uma_util.h" #include "components/permissions/permissions_client.h" #include "components/permissions/switches.h" #include "content/public/browser/back_forward_cache.h" @@ -598,6 +597,7 @@ selector->Cancel(); current_request_already_displayed_ = false; + prediction_grant_likelihood_.reset(); current_request_ui_to_use_.reset(); selector_decisions_.clear(); @@ -611,7 +611,9 @@ PermissionUmaUtil::PermissionPromptResolved( requests_, web_contents(), permission_action, - DetermineCurrentRequestUIDispositionForUMA()); + DetermineCurrentRequestUIDispositionForUMA(), + DetermineCurrentRequestUIDispositionReasonForUMA(), + prediction_grant_likelihood_); content::BrowserContext* browser_context = web_contents()->GetBrowserContext(); @@ -793,6 +795,12 @@ } } + if (!prediction_grant_likelihood_.has_value()) { + prediction_grant_likelihood_ = + notification_permission_ui_selectors_[selector_index] + ->PredictedGrantLikelihoodForUKM(); + } + // We have already made a decision because of a higher priority selector // therefore this selector's decision can be discarded. if (current_request_ui_to_use_.has_value()) @@ -831,6 +839,24 @@ return PermissionPromptDisposition::NONE_VISIBLE; } +PermissionPromptDispositionReason +PermissionRequestManager::DetermineCurrentRequestUIDispositionReasonForUMA() { + if (!ShouldCurrentRequestUseQuietUI()) { + return PermissionPromptDispositionReason::DEFAULT_FALLBACK; + } + + switch (ReasonForUsingQuietUi()) { + case QuietUiReason::kEnabledInPrefs: + return PermissionPromptDispositionReason::USER_PREFERENCE_IN_SETTINGS; + case QuietUiReason::kTriggeredByCrowdDeny: + case QuietUiReason::kTriggeredDueToAbusiveRequests: + case QuietUiReason::kTriggeredDueToAbusiveContent: + return PermissionPromptDispositionReason::SAFE_BROWSING_VERDICT; + case QuietUiReason::kPredictedVeryUnlikelyGrant: + return PermissionPromptDispositionReason::PREDICTION_SERVICE; + } +} + void PermissionRequestManager::LogWarningToConsole(const char* message) { web_contents()->GetMainFrame()->AddMessageToConsole( blink::mojom::ConsoleMessageLevel::kWarning, message);
diff --git a/components/permissions/permission_request_manager.h b/components/permissions/permission_request_manager.h index 3ccdbff..f12a19f 100644 --- a/components/permissions/permission_request_manager.h +++ b/components/permissions/permission_request_manager.h
@@ -16,6 +16,7 @@ #include "base/observer_list.h" #include "components/permissions/notification_permission_ui_selector.h" #include "components/permissions/permission_prompt.h" +#include "components/permissions/permission_uma_util.h" #include "content/public/browser/web_contents_observer.h" #include "content/public/browser/web_contents_user_data.h" @@ -33,6 +34,7 @@ class PermissionRequest; enum class PermissionAction; enum class PermissionPromptDisposition; +enum class PermissionPromptDispositionReason; // The message to be printed in the Developer Tools console when the quiet // notification permission prompt UI is shown on sites with abusive permission @@ -235,6 +237,8 @@ const UiDecision& decision); PermissionPromptDisposition DetermineCurrentRequestUIDispositionForUMA(); + PermissionPromptDispositionReason + DetermineCurrentRequestUIDispositionReasonForUMA(); void LogWarningToConsole(const char* message); @@ -307,6 +311,11 @@ // still waiting on the result from |notification_permission_ui_selectors_|. base::Optional<UiDecision> current_request_ui_to_use_; + // The likelihood value returned by the Web Permission Predictions Service, + // to be recoreded in UKM. + base::Optional<PermissionUmaUtil::PredictionGrantLikelihood> + prediction_grant_likelihood_; + // Whether the bubble is being destroyed by this class, rather than in // response to a UI event. In this case, callbacks from the bubble itself // should be ignored.
diff --git a/components/permissions/permission_uma_util.cc b/components/permissions/permission_uma_util.cc index aef1b9e..393dca1 100644 --- a/components/permissions/permission_uma_util.cc +++ b/components/permissions/permission_uma_util.cc
@@ -127,8 +127,11 @@ int ignore_count, PermissionSourceUI source_ui, PermissionPromptDisposition ui_disposition, + base::Optional<PermissionPromptDispositionReason> ui_reason, base::Optional<bool> has_three_consecutive_denies, base::Optional<bool> has_previously_revoked_permission, + base::Optional<PermissionUmaUtil::PredictionGrantLikelihood> + predicted_grant_likelihood, base::Optional<ukm::SourceId> source_id) { // Only record the permission change if the origin is in the history. if (!source_id.has_value()) @@ -146,6 +149,14 @@ .SetSource(static_cast<int64_t>(source_ui)) .SetPromptDisposition(static_cast<int64_t>(ui_disposition)); + if (ui_reason.has_value()) + builder.SetPromptDispositionReason(static_cast<int64_t>(ui_reason.value())); + + if (predicted_grant_likelihood.has_value()) { + builder.SetPredictionsApiResponse_GrantLikelihood( + static_cast<int64_t>(predicted_grant_likelihood.value())); + } + if (has_three_consecutive_denies.has_value()) { int64_t satisfied_adaptive_triggers = 0; if (has_three_consecutive_denies.value()) @@ -284,8 +295,9 @@ RecordPermissionAction(permission, PermissionAction::REVOKED, source_ui, PermissionRequestGestureType::UNKNOWN, PermissionPromptDisposition::NOT_APPLICABLE, - revoked_origin, - /*web_contents=*/nullptr, browser_context); + base::nullopt /* ui_reason */, revoked_origin, + nullptr /* web_contents */, browser_context, + base::nullopt /* predicted_grant_likelihood */); } } @@ -349,7 +361,9 @@ const std::vector<PermissionRequest*>& requests, content::WebContents* web_contents, PermissionAction permission_action, - PermissionPromptDisposition ui_disposition) { + PermissionPromptDisposition ui_disposition, + base::Optional<PermissionPromptDispositionReason> ui_reason, + base::Optional<PredictionGrantLikelihood> predicted_grant_likelihood) { std::string action_string; switch (permission_action) { @@ -388,10 +402,10 @@ PermissionRequestGestureType gesture_type = request->GetGestureType(); const GURL& requesting_origin = request->GetOrigin(); - RecordPermissionAction(permission, permission_action, - PermissionSourceUI::PROMPT, gesture_type, - ui_disposition, requesting_origin, web_contents, - web_contents->GetBrowserContext()); + RecordPermissionAction( + permission, permission_action, PermissionSourceUI::PROMPT, gesture_type, + ui_disposition, ui_reason, requesting_origin, web_contents, + web_contents->GetBrowserContext(), predicted_grant_likelihood); std::string priorDismissPrefix = "Permissions.Prompt." + action_string + ".PriorDismissCount2."; @@ -552,9 +566,11 @@ PermissionSourceUI source_ui, PermissionRequestGestureType gesture_type, PermissionPromptDisposition ui_disposition, + base::Optional<PermissionPromptDispositionReason> ui_reason, const GURL& requesting_origin, const content::WebContents* web_contents, - content::BrowserContext* browser_context) { + content::BrowserContext* browser_context, + base::Optional<PredictionGrantLikelihood> predicted_grant_likelihood) { PermissionDecisionAutoBlocker* autoblocker = PermissionsClient::Get()->GetPermissionDecisionAutoBlocker( browser_context); @@ -566,14 +582,15 @@ browser_context, web_contents, requesting_origin, base::BindOnce( &RecordPermissionActionUkm, action, gesture_type, permission, - dismiss_count, ignore_count, source_ui, ui_disposition, + dismiss_count, ignore_count, source_ui, ui_disposition, ui_reason, permission == ContentSettingsType::NOTIFICATIONS ? PermissionsClient::Get() ->HadThreeConsecutiveNotificationPermissionDenies( browser_context) : base::nullopt, PermissionsClient::Get()->HasPreviouslyAutoRevokedPermission( - browser_context, requesting_origin, permission))); + browser_context, requesting_origin, permission), + predicted_grant_likelihood)); switch (permission) { case ContentSettingsType::GEOLOCATION:
diff --git a/components/permissions/permission_uma_util.h b/components/permissions/permission_uma_util.h index 4bf397f..21833073 100644 --- a/components/permissions/permission_uma_util.h +++ b/components/permissions/permission_uma_util.h
@@ -13,6 +13,7 @@ #include "components/permissions/permission_request.h" #include "components/permissions/permission_result.h" #include "components/permissions/permission_util.h" +#include "components/permissions/prediction_service/prediction_service_messages.pb.h" namespace content { class BrowserContext; @@ -106,6 +107,25 @@ NONE_VISIBLE = 7, }; +// The reason why the permission prompt disposition was used. Enum used in UKMs, +// do not re-order or change values. Deprecated items should only be commented +// out. +enum class PermissionPromptDispositionReason { + // Disposition was selected in prefs. + USER_PREFERENCE_IN_SETTINGS = 0, + + // Disposition was chosen because Safe Browsing classifies the origin + // as being spammy or abusive with permission requests. + SAFE_BROWSING_VERDICT = 1, + + // Disposition was chosen based on grant likelihood predicted by the + // Web Permission Prediction Service. + PREDICTION_SERVICE = 2, + + // Disposition was used as a fallback, if no selector made a decision. + DEFAULT_FALLBACK = 3, +}; + enum class AdaptiveTriggers { // None of the adaptive triggers were met. Currently this means two or less // consecutive denies in a row. @@ -126,6 +146,9 @@ // Provides a convenient way of logging UMA for permission related operations. class PermissionUmaUtil { public: + using PredictionGrantLikelihood = + PermissionSuggestion_Likelihood_DiscretizedLikelihood; + static const char kPermissionsPromptShown[]; static const char kPermissionsPromptShownGesture[]; static const char kPermissionsPromptShownNoGesture[]; @@ -167,7 +190,9 @@ const std::vector<PermissionRequest*>& requests, content::WebContents* web_contents, PermissionAction permission_action, - PermissionPromptDisposition ui_disposition); + PermissionPromptDisposition ui_disposition, + base::Optional<PermissionPromptDispositionReason> ui_reason, + base::Optional<PredictionGrantLikelihood> predicted_grant_likelihood); static void RecordWithBatteryBucket(const std::string& histogram); @@ -225,14 +250,17 @@ friend class PermissionUmaUtilTest; // web_contents may be null when for recording non-prompt actions. - static void RecordPermissionAction(ContentSettingsType permission, - PermissionAction action, - PermissionSourceUI source_ui, - PermissionRequestGestureType gesture_type, - PermissionPromptDisposition ui_disposition, - const GURL& requesting_origin, - const content::WebContents* web_contents, - content::BrowserContext* browser_context); + static void RecordPermissionAction( + ContentSettingsType permission, + PermissionAction action, + PermissionSourceUI source_ui, + PermissionRequestGestureType gesture_type, + PermissionPromptDisposition ui_disposition, + base::Optional<PermissionPromptDispositionReason> ui_reason, + const GURL& requesting_origin, + const content::WebContents* web_contents, + content::BrowserContext* browser_context, + base::Optional<PredictionGrantLikelihood> predicted_grant_likelihood); // Records |count| total prior actions for a prompt of type |permission| // for a single origin using |prefix| for the metric.
diff --git a/components/permissions/prediction_service/BUILD.gn b/components/permissions/prediction_service/BUILD.gn index 18d731d6..96b42b9 100644 --- a/components/permissions/prediction_service/BUILD.gn +++ b/components/permissions/prediction_service/BUILD.gn
@@ -18,12 +18,12 @@ "prediction_service_common.h", ] deps = [ - ":prediction_service_messages_proto", "//components/keyed_service/content", "//components/permissions:permissions_common", "//services/network/public/cpp:cpp", "//third_party/protobuf:protobuf_lite", ] + public_deps = [ ":prediction_service_messages_proto" ] } source_set("unit_tests") { @@ -31,7 +31,6 @@ sources = [ "prediction_service_unittest.cc" ] deps = [ ":prediction_service", - ":prediction_service_messages_proto", "//base/test:test_support", "//components/permissions:permissions_common", "//services/network:test_support",
diff --git a/components/search_engines/template_url_service.cc b/components/search_engines/template_url_service.cc index 2e488fc6..206536aa 100644 --- a/components/search_engines/template_url_service.cc +++ b/components/search_engines/template_url_service.cc
@@ -1007,11 +1007,6 @@ const std::string error_msg = "ProcessSyncChanges failed on ChangeType " + syncer::SyncChange::ChangeTypeToString(iter->change_type()); - if (iter->change_type() == syncer::SyncChange::ACTION_INVALID) { - error = sync_error_factory_->CreateAndUploadError(FROM_HERE, error_msg); - continue; - } - if (iter->change_type() == syncer::SyncChange::ACTION_DELETE) { if (!existing_turl) { // Can't DELETE a non-existent engine, although we log it. @@ -1231,7 +1226,6 @@ const base::Location& from_here, const TemplateURL* turl, syncer::SyncChange::SyncChangeType type) { - DCHECK_NE(type, syncer::SyncChange::ACTION_INVALID); DCHECK(turl); if (!models_associated_)
diff --git a/components/signin/core/browser/android/java/src/org/chromium/components/signin/ProfileDataSource.java b/components/signin/core/browser/android/java/src/org/chromium/components/signin/ProfileDataSource.java index a8a81015..617e077 100644 --- a/components/signin/core/browser/android/java/src/org/chromium/components/signin/ProfileDataSource.java +++ b/components/signin/core/browser/android/java/src/org/chromium/components/signin/ProfileDataSource.java
@@ -72,8 +72,21 @@ /** * Notifies that an account's profile data has been updated. * @param accountEmail An account email. + * + * This method will be removed after migrating all the callers to the second method */ + @Deprecated void onProfileDataUpdated(String accountEmail); + + /** + * Notifies that an account's profile data has been updated. + */ + void onProfileDataUpdated(ProfileData profileData); + + /** + * Removes the profile data of a given accountEmail. + */ + void removeProfileData(String accountEmail); } /**
diff --git a/components/sync/BUILD.gn b/components/sync/BUILD.gn index 7bba5178..fb8dc3637 100644 --- a/components/sync/BUILD.gn +++ b/components/sync/BUILD.gn
@@ -476,6 +476,7 @@ "nigori/nigori_unittest.cc", "protocol/proto_enum_conversions_unittest.cc", "protocol/proto_value_conversions_unittest.cc", + "trusted_vault/download_keys_response_handler_unittest.cc", "trusted_vault/securebox_unittest.cc", "trusted_vault/standalone_trusted_vault_backend_unittest.cc", "trusted_vault/trusted_vault_access_token_fetcher_frontend_unittest.cc",
diff --git a/components/sync/model/sync_change.cc b/components/sync/model/sync_change.cc index 8b56fbe..c618a23 100644 --- a/components/sync/model/sync_change.cc +++ b/components/sync/model/sync_change.cc
@@ -10,8 +10,6 @@ namespace syncer { -SyncChange::SyncChange() : change_type_(ACTION_INVALID) {} - SyncChange::SyncChange(const base::Location& from_here, SyncChangeType change_type, const SyncData& sync_data) @@ -22,7 +20,9 @@ SyncChange::~SyncChange() {} bool SyncChange::IsValid() const { - if (change_type_ == ACTION_INVALID || !sync_data_.IsValid()) + // TODO(crbug.com/1152824): This implementation could be simplified if the + // public API provides guarantees around when it returns false. + if (!sync_data_.IsValid()) return false; // Data from the syncer must always have valid specifics. @@ -57,8 +57,6 @@ // static std::string SyncChange::ChangeTypeToString(SyncChangeType change_type) { switch (change_type) { - case ACTION_INVALID: - return "ACTION_INVALID"; case ACTION_ADD: return "ACTION_ADD"; case ACTION_UPDATE:
diff --git a/components/sync/model/sync_change.h b/components/sync/model/sync_change.h index 93a4798..8b786c1 100644 --- a/components/sync/model/sync_change.h +++ b/components/sync/model/sync_change.h
@@ -22,28 +22,28 @@ class SyncChange { public: enum SyncChangeType { - ACTION_INVALID, ACTION_ADD, ACTION_UPDATE, ACTION_DELETE, }; - // Default constructor creates an invalid change. - SyncChange(); // Create a new change with the specified sync data. SyncChange(const base::Location& from_here, SyncChangeType change_type, const SyncData& sync_data); + // Copy constructor and assignment operator welcome. + SyncChange(const SyncChange&) = default; + SyncChange& operator=(const SyncChange&) = default; + // Move constructor and assignment operator allowed (although questionable). + // TODO(crbug.com/1152824): Avoid move semantics if that leads invalid state. + SyncChange(SyncChange&&) = default; + SyncChange& operator=(SyncChange&&) = default; ~SyncChange(); - // Copy constructor and assignment operator welcome. - // Whether this change is valid. This must be true before attempting to access - // the data. - // Deletes: Requires valid tag when going to the syncer. Requires valid - // specifics when coming from the syncer. - // Adds, Updates: Require valid tag and specifics when going to the syncer. - // Require only valid specifics when coming from the syncer. + // the data. It may only return false for moved-away instances (unspecified + // behavior). Otherwise it's guaranteed to return true. + // TODO(crbug.com/1152824): Remove this API once move semantics are removed. bool IsValid() const; // Getters.
diff --git a/components/sync/model_impl/syncable_service_based_bridge.cc b/components/sync/model_impl/syncable_service_based_bridge.cc index 5852bbb..2895911 100644 --- a/components/sync/model_impl/syncable_service_based_bridge.cc +++ b/components/sync/model_impl/syncable_service_based_bridge.cc
@@ -70,7 +70,7 @@ return SyncChange::ACTION_UPDATE; } NOTREACHED(); - return SyncChange::ACTION_INVALID; + return SyncChange::ACTION_UPDATE; } // Parses the content of |record_list| into |*in_memory_store|. The output @@ -133,10 +133,6 @@ for (const SyncChange& change : change_list) { switch (change.change_type()) { - case SyncChange::ACTION_INVALID: - NOTREACHED() << " from " << change.location().ToString(); - break; - case SyncChange::ACTION_ADD: case SyncChange::ACTION_UPDATE: { DCHECK_EQ(type_, change.sync_data().GetDataType());
diff --git a/components/sync/protocol/autofill_specifics.proto b/components/sync/protocol/autofill_specifics.proto index 671413b3..d8dd598 100644 --- a/components/sync/protocol/autofill_specifics.proto +++ b/components/sync/protocol/autofill_specifics.proto
@@ -40,6 +40,8 @@ // This is currently only applicable to the full name, since users cannot // edit individual components of their name. USER_VERIFIED = 4; + // The token was parsed remotely. + SERVER_PARSED = 5; } optional string guid = 15;
diff --git a/components/sync/protocol/proto_enum_conversions.cc b/components/sync/protocol/proto_enum_conversions.cc index 853885b..a2f6ee73 100644 --- a/components/sync/protocol/proto_enum_conversions.cc +++ b/components/sync/protocol/proto_enum_conversions.cc
@@ -49,7 +49,7 @@ const char* ProtoEnumToString( sync_pb::AutofillProfileSpecifics::VerificationStatus status) { ASSERT_ENUM_BOUNDS(sync_pb::AutofillProfileSpecifics, VerificationStatus, - VERIFICATION_STATUS_UNSPECIFIED, USER_VERIFIED); + VERIFICATION_STATUS_UNSPECIFIED, SERVER_PARSED); switch (status) { ENUM_CASE(sync_pb::AutofillProfileSpecifics, VERIFICATION_STATUS_UNSPECIFIED); @@ -57,6 +57,7 @@ ENUM_CASE(sync_pb::AutofillProfileSpecifics, FORMATTED); ENUM_CASE(sync_pb::AutofillProfileSpecifics, OBSERVED); ENUM_CASE(sync_pb::AutofillProfileSpecifics, USER_VERIFIED); + ENUM_CASE(sync_pb::AutofillProfileSpecifics, SERVER_PARSED); } NOTREACHED(); return "";
diff --git a/components/sync/protocol/vault.proto b/components/sync/protocol/vault.proto index ebc51e1..55a3835 100644 --- a/components/sync/protocol/vault.proto +++ b/components/sync/protocol/vault.proto
@@ -13,6 +13,7 @@ optional int32 epoch = 1; optional bytes wrapped_key = 2; optional bytes member_proof = 3; + optional bytes key_proof = 4; } message SecurityDomain { @@ -29,3 +30,7 @@ message JoinSecurityDomainsRequest { repeated SecurityDomain security_domains = 1; } + +message ListSecurityDomainsResponse { + repeated SecurityDomain security_domains = 1; +}
diff --git a/components/sync/trusted_vault/BUILD.gn b/components/sync/trusted_vault/BUILD.gn index 8494610..fb4341b 100644 --- a/components/sync/trusted_vault/BUILD.gn +++ b/components/sync/trusted_vault/BUILD.gn
@@ -4,6 +4,8 @@ static_library("trusted_vault") { sources = [ + "download_keys_response_handler.cc", + "download_keys_response_handler.h", "securebox.cc", "securebox.h", "standalone_trusted_vault_backend.cc",
diff --git a/components/sync/trusted_vault/download_keys_response_handler.cc b/components/sync/trusted_vault/download_keys_response_handler.cc new file mode 100644 index 0000000..b733635 --- /dev/null +++ b/components/sync/trusted_vault/download_keys_response_handler.cc
@@ -0,0 +1,220 @@ +// 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/sync/trusted_vault/download_keys_response_handler.h" + +#include <algorithm> +#include <utility> + +#include "components/sync/protocol/vault.pb.h" +#include "components/sync/trusted_vault/securebox.h" +#include "crypto/hmac.h" + +namespace syncer { + +namespace { + +// TODO(crbug.com/1113598): move these constants to a dedicated header, since +// they are used in multiple places already. +const size_t kKeyProofLength = 32; +const uint8_t kWrappedKeyHeader[] = {'V', '1', ' ', 's', 'h', 'a', 'r', + 'e', 'd', '_', 'k', 'e', 'y'}; +const char kSecurityDomainName[] = "chromesync"; + +struct ExtractedSharedKey { + int version; + std::vector<uint8_t> trusted_vault_key; + std::vector<uint8_t> key_proof; +}; + +// Returns pointer to sync security domain in |response|. Returns nullptr if +// there is no sync security domain. +const sync_pb::SecurityDomain* FindSyncSecurityDomain( + const sync_pb::ListSecurityDomainsResponse& response) { + for (const sync_pb::SecurityDomain& security_domain : + response.security_domains()) { + if (security_domain.name() == kSecurityDomainName) { + return &security_domain; + } + } + return nullptr; +} + +// Returns pointer to the member in |response| corresponding to +// |member_public_key|. Returns nullptr if sync security domain doesn't exist +// in |response| or there is no such member in sync security domain. +const sync_pb::SecurityDomain::Member* FindMember( + const sync_pb::ListSecurityDomainsResponse& response, + const std::vector<uint8_t>& member_public_key_bytes) { + const sync_pb::SecurityDomain* sync_security_domain = + FindSyncSecurityDomain(response); + if (!sync_security_domain) { + return nullptr; + } + + const std::string member_public_key_string(member_public_key_bytes.begin(), + member_public_key_bytes.end()); + for (const sync_pb::SecurityDomain::Member& member : + sync_security_domain->members()) { + if (member.public_key() == member_public_key_string) { + return &member; + } + } + return nullptr; +} + +// Extracts (decrypts |wrapped_key| and converts to ExtractedSharedKey) shared +// keys from |member| and sorts them by version. +std::vector<ExtractedSharedKey> ExtractAndSortSharedKeys( + const sync_pb::SecurityDomain::Member& member, + const SecureBoxPrivateKey& member_private_key) { + std::vector<ExtractedSharedKey> result; + for (const sync_pb::SharedKey& shared_key : member.keys()) { + std::vector<uint8_t> wrapped_key(shared_key.wrapped_key().begin(), + shared_key.wrapped_key().end()); + base::Optional<std::vector<uint8_t>> decrypted_key = + member_private_key.Decrypt(base::span<const uint8_t>(), + kWrappedKeyHeader, wrapped_key); + if (!decrypted_key.has_value()) { + // Decryption failed. + return std::vector<ExtractedSharedKey>(); + } + result.push_back( + ExtractedSharedKey{/*version=*/shared_key.epoch(), *decrypted_key, + /*key_proof=*/ + std::vector<uint8_t>(shared_key.key_proof().begin(), + shared_key.key_proof().end())}); + } + + std::sort(result.begin(), result.end(), + [](const ExtractedSharedKey& a, const ExtractedSharedKey& b) { + return a.version < b.version; + }); + return result; +} + +// Validates |key_proof| starting from the key next to +// |last_known_trusted_vault_key|, returns false if validation fails or |keys| +// doesn't have a key next to |last_known_trusted_vault_key|. +bool IsValidKeyChain(const std::vector<ExtractedSharedKey>& key_chain, + const std::vector<uint8_t>& last_known_trusted_vault_key, + const int last_known_trusted_vault_key_version) { + DCHECK(!key_chain.empty()); + if (key_chain.back().version <= last_known_trusted_vault_key_version) { + // |keys| doesn't contain any new key. Note: this may mean that key rotation + // happened, but state corresponding to the current member wasn't updated. + return false; + } + int last_valid_key_version = last_known_trusted_vault_key_version; + std::vector<uint8_t> last_valid_key = last_known_trusted_vault_key; + for (const ExtractedSharedKey& next_key : key_chain) { + if (next_key.version <= last_valid_key_version) { + continue; + } + if (next_key.version != last_valid_key_version + 1) { + // Missing intermediate key. + return false; + } + + crypto::HMAC hmac(crypto::HMAC::SHA256); + CHECK(hmac.Init(last_valid_key)); + + std::vector<uint8_t> digest_bytes(kKeyProofLength); + if (!hmac.Verify(next_key.trusted_vault_key, next_key.key_proof)) { + // |key_proof| isn't valid. + return false; + } + last_valid_key_version = next_key.version; + last_valid_key = next_key.trusted_vault_key; + } + + return true; +} + +} // namespace + +DownloadKeysResponseHandler::ProcessedResponse::ProcessedResponse( + TrustedVaultRequestStatus status) + : status(status), last_key_version(0) {} + +DownloadKeysResponseHandler::ProcessedResponse::ProcessedResponse( + TrustedVaultRequestStatus status, + std::vector<std::vector<uint8_t>> keys, + int last_key_version) + : status(status), keys(keys), last_key_version(last_key_version) {} + +DownloadKeysResponseHandler::ProcessedResponse::ProcessedResponse( + const ProcessedResponse& other) = default; + +DownloadKeysResponseHandler::ProcessedResponse& +DownloadKeysResponseHandler::ProcessedResponse::operator=( + const ProcessedResponse& other) = default; + +DownloadKeysResponseHandler::ProcessedResponse::~ProcessedResponse() = default; + +DownloadKeysResponseHandler::DownloadKeysResponseHandler( + const std::vector<uint8_t>& last_trusted_vault_key, + int last_trusted_vault_key_version, + std::unique_ptr<SecureBoxKeyPair> device_key_pair) + : last_trusted_vault_key_(last_trusted_vault_key), + last_trusted_vault_key_version_(last_trusted_vault_key_version), + device_key_pair_(std::move(device_key_pair)) { + DCHECK(device_key_pair_); +} + +DownloadKeysResponseHandler::~DownloadKeysResponseHandler() = default; + +DownloadKeysResponseHandler::ProcessedResponse +DownloadKeysResponseHandler::ProcessResponse( + TrustedVaultRequest::HttpStatus http_status, + const std::string& response_body) const { + switch (http_status) { + case TrustedVaultRequest::HttpStatus::kSuccess: + break; + case TrustedVaultRequest::HttpStatus::kOtherError: + case TrustedVaultRequest::HttpStatus::kBadRequest: + // Don't distinguish kBadRequest here, because request content doesn't + // depend on the local state. + return ProcessedResponse( + /*status=*/TrustedVaultRequestStatus::kOtherError); + } + + sync_pb::ListSecurityDomainsResponse deserialized_response; + if (!deserialized_response.ParseFromString(response_body)) { + return ProcessedResponse(/*status=*/TrustedVaultRequestStatus::kOtherError); + } + + const sync_pb::SecurityDomain::Member* current_member = FindMember( + deserialized_response, device_key_pair_->public_key().ExportToBytes()); + if (!current_member) { + // |device_key_pair_| isn't registered server-side, while client assumes + // it's registered when downloading keys. + return ProcessedResponse( + /*status=*/TrustedVaultRequestStatus::kLocalDataObsolete); + } + + std::vector<ExtractedSharedKey> extracted_keys = ExtractAndSortSharedKeys( + *current_member, device_key_pair_->private_key()); + if (extracted_keys.empty() || + !IsValidKeyChain(extracted_keys, last_trusted_vault_key_, + last_trusted_vault_key_version_)) { + return ProcessedResponse( + /*status=*/TrustedVaultRequestStatus::kLocalDataObsolete); + } + + std::vector<std::vector<uint8_t>> new_keys; + for (const ExtractedSharedKey& key : extracted_keys) { + if (key.version >= last_trusted_vault_key_version_) { + // Don't include previous keys into the result, because they weren't + // validated using |last_trusted_vault_key_| and client should be already + // aware of them. + new_keys.push_back(key.trusted_vault_key); + } + } + return ProcessedResponse(/*status=*/TrustedVaultRequestStatus::kSuccess, + new_keys, + /*last_key_version=*/extracted_keys.back().version); +} + +} // namespace syncer
diff --git a/components/sync/trusted_vault/download_keys_response_handler.h b/components/sync/trusted_vault/download_keys_response_handler.h new file mode 100644 index 0000000..f8fe26b9 --- /dev/null +++ b/components/sync/trusted_vault/download_keys_response_handler.h
@@ -0,0 +1,73 @@ +// 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_SYNC_TRUSTED_VAULT_DOWNLOAD_KEYS_RESPONSE_HANDLER_H_ +#define COMPONENTS_SYNC_TRUSTED_VAULT_DOWNLOAD_KEYS_RESPONSE_HANDLER_H_ + +#include <memory> +#include <string> +#include <vector> + +#include "components/sync/trusted_vault/trusted_vault_connection.h" +#include "components/sync/trusted_vault/trusted_vault_request.h" + +namespace syncer { + +class SecureBoxKeyPair; + +// Helper class to extract and validate trusted vault keys from +// ListSecurityDomainsResponse. +class DownloadKeysResponseHandler { + public: + struct ProcessedResponse { + explicit ProcessedResponse(TrustedVaultRequestStatus status); + ProcessedResponse(TrustedVaultRequestStatus status, + std::vector<std::vector<uint8_t>> keys, + int last_key_version); + ProcessedResponse(const ProcessedResponse& other); + ProcessedResponse& operator=(const ProcessedResponse& other); + ~ProcessedResponse(); + + // kSuccess is reported if extraction was successful and there are new + // trusted vault keys. + // kLocalDataObsolete is reported if it's impossible to extract keys due to + // data corruption or absence of SecurityDomain/Member or if there is no new + // keys. + // kOtherError is reported in case of http/network errors or if the response + // isn't valid serialized ListSecurityDomainsResponse proto. + TrustedVaultRequestStatus status; + + // Contains new keys and potentially |last_trusted_vault_key| if it wasn't + // removed server-side. Doesn't contain keys that predate + // |last_trusted_vault_key|, because it's impossible to validate them and + // the client should be aware of them already. + std::vector<std::vector<uint8_t>> keys; + int last_key_version; + }; + + // |device_key_pair| must not be null. This class doesn't make an assumption + // of |last_trusted_vault_key| being non-empty or + // |last_trusted_vault_key_version| being non-negative. + DownloadKeysResponseHandler( + const std::vector<uint8_t>& last_trusted_vault_key, + int last_trusted_vault_key_version, + std::unique_ptr<SecureBoxKeyPair> device_key_pair); + DownloadKeysResponseHandler(const DownloadKeysResponseHandler& other) = + delete; + DownloadKeysResponseHandler& operator=( + const DownloadKeysResponseHandler& other) = delete; + ~DownloadKeysResponseHandler(); + + ProcessedResponse ProcessResponse(TrustedVaultRequest::HttpStatus http_status, + const std::string& response_body) const; + + private: + const std::vector<uint8_t> last_trusted_vault_key_; + const int last_trusted_vault_key_version_; + const std::unique_ptr<SecureBoxKeyPair> device_key_pair_; +}; + +} // namespace syncer + +#endif // COMPONENTS_SYNC_TRUSTED_VAULT_DOWNLOAD_KEYS_RESPONSE_HANDLER_H_
diff --git a/components/sync/trusted_vault/download_keys_response_handler_unittest.cc b/components/sync/trusted_vault/download_keys_response_handler_unittest.cc new file mode 100644 index 0000000..608fc17 --- /dev/null +++ b/components/sync/trusted_vault/download_keys_response_handler_unittest.cc
@@ -0,0 +1,492 @@ +// 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/sync/trusted_vault/download_keys_response_handler.h" + +#include <vector> + +#include "base/strings/string_number_conversions.h" +#include "components/sync/protocol/vault.pb.h" +#include "components/sync/trusted_vault/securebox.h" +#include "crypto/hmac.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace syncer { + +namespace { + +using testing::ElementsAre; +using testing::Eq; +using testing::IsEmpty; + +const size_t kKeyProofLength = 32; +const char kEncodedPrivateKey[] = + "49e052293c29b5a50b0013eec9d030ac2ad70a42fe093be084264647cb04e16f"; +const uint8_t kWrappedKeyHeader[] = {'V', '1', ' ', 's', 'h', 'a', 'r', + 'e', 'd', '_', 'k', 'e', 'y'}; +const char kSecurityDomainName[] = "chromesync"; + +void AssignBytesToProtoString(base::span<const uint8_t> bytes, + std::string* bytes_proto_field) { + *bytes_proto_field = std::string(bytes.begin(), bytes.end()); +} + +std::unique_ptr<SecureBoxKeyPair> MakeTestKeyPair() { + std::vector<uint8_t> private_key_bytes; + bool success = base::HexStringToBytes(kEncodedPrivateKey, &private_key_bytes); + DCHECK(success); + return SecureBoxKeyPair::CreateByPrivateKeyImport(private_key_bytes); +} + +void FillSecurityDomainMember( + const SecureBoxPublicKey& public_key, + const std::vector<std::vector<uint8_t>>& trusted_vault_keys, + const std::vector<int> trusted_vault_keys_versions, + const std::vector<std::vector<uint8_t>>& signing_keys, + sync_pb::SecurityDomain::Member* member) { + DCHECK(member); + DCHECK_EQ(trusted_vault_keys.size(), trusted_vault_keys_versions.size()); + DCHECK_EQ(trusted_vault_keys.size(), signing_keys.size()); + + std::vector<uint8_t> public_key_bytes = public_key.ExportToBytes(); + AssignBytesToProtoString(public_key.ExportToBytes(), + member->mutable_public_key()); + + for (size_t i = 0; i < trusted_vault_keys.size(); ++i) { + sync_pb::SharedKey* shared_key = member->add_keys(); + shared_key->set_epoch(trusted_vault_keys_versions[i]); + AssignBytesToProtoString( + public_key.Encrypt( + /*shared_secret=*/base::span<const uint8_t>(), kWrappedKeyHeader, + /*payload=*/trusted_vault_keys[i]), + shared_key->mutable_wrapped_key()); + + if (!signing_keys[i].empty()) { + crypto::HMAC hmac(crypto::HMAC::SHA256); + CHECK(hmac.Init(signing_keys[i])); + + std::vector<uint8_t> key_proof_bytes(kKeyProofLength); + CHECK(hmac.Sign(trusted_vault_keys[i], key_proof_bytes)); + AssignBytesToProtoString(key_proof_bytes, + shared_key->mutable_key_proof()); + } + } +} + +std::string CreateListSecurityDomainsResponseWithSingleSyncMember( + const std::vector<std::vector<uint8_t>>& trusted_vault_keys, + const std::vector<int> trusted_vault_keys_versions, + const std::vector<std::vector<uint8_t>>& signing_keys) { + sync_pb::ListSecurityDomainsResponse response; + sync_pb::SecurityDomain* security_domain = response.add_security_domains(); + security_domain->set_name(kSecurityDomainName); + FillSecurityDomainMember(MakeTestKeyPair()->public_key(), trusted_vault_keys, + trusted_vault_keys_versions, signing_keys, + security_domain->add_members()); + return response.SerializeAsString(); +} + +class DownloadKeysResponseHandlerTest : public testing::Test { + public: + DownloadKeysResponseHandlerTest() + : handler_(kKnownTrustedVaultKey, + kKnownTrustedVaultKeyVersion, + MakeTestKeyPair()) {} + + ~DownloadKeysResponseHandlerTest() override = default; + + const DownloadKeysResponseHandler& handler() const { return handler_; } + + const int kKnownTrustedVaultKeyVersion = 5; + const std::vector<uint8_t> kKnownTrustedVaultKey = {1, 2, 3, 4}; + const std::vector<uint8_t> kTrustedVaultKey1 = {1, 2, 3, 5}; + const std::vector<uint8_t> kTrustedVaultKey2 = {1, 2, 3, 6}; + const std::vector<uint8_t> kTrustedVaultKey3 = {1, 2, 3, 7}; + + private: + const DownloadKeysResponseHandler handler_; +}; + +// All HttpStatuses except kSuccess should end up in kOtherError reporting, +// because underlying request doesn't have any parameters inferred from local +// state. +TEST_F(DownloadKeysResponseHandlerTest, ShouldHandleHttpErrors) { + EXPECT_THAT( + handler() + .ProcessResponse( + /*http_status=*/TrustedVaultRequest::HttpStatus::kBadRequest, + /*response_body=*/std::string()) + .status, + Eq(TrustedVaultRequestStatus::kOtherError)); + EXPECT_THAT( + handler() + .ProcessResponse( + /*http_status=*/TrustedVaultRequest::HttpStatus::kOtherError, + /*response_body=*/std::string()) + .status, + Eq(TrustedVaultRequestStatus::kOtherError)); +} + +// Simplest legitimate case of key rotation, server side state corresponds to +// kKnownTrustedVaultKey -> kTrustedVaultKey1 key chain. +TEST_F(DownloadKeysResponseHandlerTest, ShouldHandleSingleKeyRotation) { + const DownloadKeysResponseHandler::ProcessedResponse processed_response = + handler().ProcessResponse( + /*http_status=*/TrustedVaultRequest::HttpStatus::kSuccess, + /*response_body=*/ + CreateListSecurityDomainsResponseWithSingleSyncMember( + /*trusted_vault_keys=*/{kKnownTrustedVaultKey, kTrustedVaultKey1}, + /*trusted_vault_keys_versions=*/ + {kKnownTrustedVaultKeyVersion, kKnownTrustedVaultKeyVersion + 1}, + /*signing_keys=*/{{}, kKnownTrustedVaultKey})); + + EXPECT_THAT(processed_response.status, + Eq(TrustedVaultRequestStatus::kSuccess)); + EXPECT_THAT(processed_response.keys, + ElementsAre(kKnownTrustedVaultKey, kTrustedVaultKey1)); + EXPECT_THAT(processed_response.last_key_version, + Eq(kKnownTrustedVaultKeyVersion + 1)); +} + +// Multiple key rotations may happen while client is offline, server-side key +// chain is kKnownTrustedVaultKey -> kTrustedVaultKey1 -> kTrustedVaultKey2. +TEST_F(DownloadKeysResponseHandlerTest, ShouldHandleMultipleKeyRotations) { + const DownloadKeysResponseHandler::ProcessedResponse processed_response = + handler().ProcessResponse( + /*http_status=*/TrustedVaultRequest::HttpStatus::kSuccess, + /*response_body=*/ + CreateListSecurityDomainsResponseWithSingleSyncMember( + /*trusted_vault_keys=*/ + {kKnownTrustedVaultKey, kTrustedVaultKey1, kTrustedVaultKey2}, + /*trusted_vault_keys_versions=*/ + {kKnownTrustedVaultKeyVersion, kKnownTrustedVaultKeyVersion + 1, + kKnownTrustedVaultKeyVersion + 2}, + /*signing_keys=*/{{}, kKnownTrustedVaultKey, kTrustedVaultKey1})); + + EXPECT_THAT(processed_response.status, + Eq(TrustedVaultRequestStatus::kSuccess)); + EXPECT_THAT( + processed_response.keys, + ElementsAre(kKnownTrustedVaultKey, kTrustedVaultKey1, kTrustedVaultKey2)); + EXPECT_THAT(processed_response.last_key_version, + Eq(kKnownTrustedVaultKeyVersion + 2)); +} + +// There might be keys, that predates latest client-side trusted vault key. +// Server-side key chain is kTrustedVaultKey1 -> kKnownTrustedVaultKey -> +// kTrustedVaultKey2 -> kTrustedVaultKey3. +// Since kTrustedVaultKey1 can't be validated using kKnownTrustedVaultKey it +// shouldn't be included in processed response. +TEST_F(DownloadKeysResponseHandlerTest, ShouldHandlePriorKeys) { + const DownloadKeysResponseHandler::ProcessedResponse processed_response = + handler().ProcessResponse( + /*http_status=*/TrustedVaultRequest::HttpStatus::kSuccess, + /*response_body=*/ + CreateListSecurityDomainsResponseWithSingleSyncMember( + /*trusted_vault_keys=*/ + {kTrustedVaultKey1, kKnownTrustedVaultKey, kTrustedVaultKey2, + kTrustedVaultKey3}, + /*trusted_vault_keys_versions=*/ + {kKnownTrustedVaultKeyVersion - 1, kKnownTrustedVaultKeyVersion, + kKnownTrustedVaultKeyVersion + 1, + kKnownTrustedVaultKeyVersion + 2}, + /*signing_keys=*/ + {{}, + kTrustedVaultKey1, + kKnownTrustedVaultKey, + kTrustedVaultKey2})); + + EXPECT_THAT(processed_response.status, + Eq(TrustedVaultRequestStatus::kSuccess)); + EXPECT_THAT( + processed_response.keys, + ElementsAre(kKnownTrustedVaultKey, kTrustedVaultKey2, kTrustedVaultKey3)); + EXPECT_THAT(processed_response.last_key_version, + Eq(kKnownTrustedVaultKeyVersion + 2)); +} + +// Server can already clean-up kKnownTrustedVaultKey, but it might still be +// possible to validate the key-chain. +// Full key chain is: kKnownTrustedVaultKey -> kTrustedVaultKey1 -> +// kTrustedVaultKey2. +// Server-side key chain is: kTrustedVaultKey1 -> kTrustedVaultKey2. +TEST_F(DownloadKeysResponseHandlerTest, + ShouldHandleAbsenseOfKnownKeyWhenKeyChainIsRecoverable) { + const DownloadKeysResponseHandler::ProcessedResponse processed_response = + handler().ProcessResponse( + /*http_status=*/TrustedVaultRequest::HttpStatus::kSuccess, + /*response_body=*/ + CreateListSecurityDomainsResponseWithSingleSyncMember( + /*trusted_vault_keys=*/ + {kTrustedVaultKey1, kTrustedVaultKey2}, + /*trusted_vault_keys_versions=*/ + {kKnownTrustedVaultKeyVersion + 1, + kKnownTrustedVaultKeyVersion + 2}, + /*signing_keys=*/ + {kKnownTrustedVaultKey, kTrustedVaultKey1})); + + EXPECT_THAT(processed_response.status, + Eq(TrustedVaultRequestStatus::kSuccess)); + EXPECT_THAT(processed_response.keys, + ElementsAre(kTrustedVaultKey1, kTrustedVaultKey2)); + EXPECT_THAT(processed_response.last_key_version, + Eq(kKnownTrustedVaultKeyVersion + 2)); +} + +// Server can already clean-up kKnownTrustedVaultKey and the following key. In +// this case client state is not sufficient to silently download keys and +// kLocalDataObsolete should be reported. +// Possible full key chain is: kKnownTrustedVaultKey -> kTrustedVaultKey1 -> +// kTrustedVaultKey2 -> kTrustedVaultKey3. +// Server side key chain is: kTrustedVaultKey2 -> kTrustedVaultKey3. +TEST_F(DownloadKeysResponseHandlerTest, + ShouldHandleAbsenseOfKnownKeyWhenKeyChainIsNotRecoverable) { + const DownloadKeysResponseHandler::ProcessedResponse processed_response = + handler().ProcessResponse( + /*http_status=*/TrustedVaultRequest::HttpStatus::kSuccess, + /*response_body=*/ + CreateListSecurityDomainsResponseWithSingleSyncMember( + /*trusted_vault_keys=*/ + {kTrustedVaultKey2, kTrustedVaultKey3}, + /*trusted_vault_keys_versions=*/ + {kKnownTrustedVaultKeyVersion + 2, + kKnownTrustedVaultKeyVersion + 3}, + /*signing_keys=*/ + {kTrustedVaultKey1, kTrustedVaultKey2})); + + EXPECT_THAT(processed_response.status, + Eq(TrustedVaultRequestStatus::kLocalDataObsolete)); + EXPECT_THAT(processed_response.keys, IsEmpty()); +} + +// The test populates undecryptable/corrupted |wrapped_key| field, handler +// should return kLocalDataObsolete to allow client to restore Member by +// re-registration. +TEST_F(DownloadKeysResponseHandlerTest, ShouldHandleUndecryptableKey) { + sync_pb::ListSecurityDomainsResponse response; + sync_pb::SecurityDomain* security_domain = response.add_security_domains(); + security_domain->set_name(kSecurityDomainName); + sync_pb::SecurityDomain::Member* member = security_domain->add_members(); + FillSecurityDomainMember( + MakeTestKeyPair()->public_key(), + /*trusted_vault_keys=*/{kKnownTrustedVaultKey, kTrustedVaultKey1}, + /*trusted_vault_keys_versions=*/ + {kKnownTrustedVaultKeyVersion, kKnownTrustedVaultKeyVersion + 1}, + /*signing_keys=*/{{}, kKnownTrustedVaultKey}, member); + + // Corrupt wrapped key corresponding to kTrustedVaultKey1. + member->mutable_keys(1)->set_wrapped_key("undecryptable_key"); + + EXPECT_THAT(handler() + .ProcessResponse( + /*http_status=*/TrustedVaultRequest::HttpStatus::kSuccess, + /*response_body=*/response.SerializeAsString()) + .status, + Eq(TrustedVaultRequestStatus::kLocalDataObsolete)); +} + +// The test populates invalid |key_proof| field for the single key rotation. +// kTrustedVaultKey1 is expected to be signed with kKnownTrustedVaultKey, but +// instead it's signed with kTrustedVaultKey2. +TEST_F(DownloadKeysResponseHandlerTest, + ShouldHandleInvalidKeyProofOnSingleKeyRotation) { + const DownloadKeysResponseHandler::ProcessedResponse processed_response = + handler().ProcessResponse( + /*http_status=*/TrustedVaultRequest::HttpStatus::kSuccess, + /*response_body=*/ + CreateListSecurityDomainsResponseWithSingleSyncMember( + /*trusted_vault_keys=*/{kKnownTrustedVaultKey, kTrustedVaultKey1}, + /*trusted_vault_keys_versions=*/ + {kKnownTrustedVaultKeyVersion, kKnownTrustedVaultKeyVersion + 1}, + /*signing_keys=*/{{}, kTrustedVaultKey2})); + + EXPECT_THAT(processed_response.status, + Eq(TrustedVaultRequestStatus::kLocalDataObsolete)); + EXPECT_THAT(processed_response.keys, IsEmpty()); +} + +// The test populates invalid |key_proof| field for intermediate key when +// multiple key rotations have happened. +// kTrustedVaultKey1 is expected to be signed with kKnownTrustedVaultKey, but +// instead it's signed with kTrustedVaultKey2. +TEST_F(DownloadKeysResponseHandlerTest, + ShouldHandleInvalidKeyProofOnMultipleKeyRotations) { + const DownloadKeysResponseHandler::ProcessedResponse processed_response = + handler().ProcessResponse( + /*http_status=*/TrustedVaultRequest::HttpStatus::kSuccess, + /*response_body=*/ + CreateListSecurityDomainsResponseWithSingleSyncMember( + /*trusted_vault_keys=*/{kKnownTrustedVaultKey, kTrustedVaultKey1, + kTrustedVaultKey2}, + /*trusted_vault_keys_versions=*/ + {kKnownTrustedVaultKeyVersion, kKnownTrustedVaultKeyVersion + 1, + kKnownTrustedVaultKeyVersion + 2}, + /*signing_keys=*/{{}, kTrustedVaultKey2, kTrustedVaultKey1})); + + EXPECT_THAT(processed_response.status, + Eq(TrustedVaultRequestStatus::kLocalDataObsolete)); + EXPECT_THAT(processed_response.keys, IsEmpty()); +} + +// In this scenario client already has most recent trusted vault key. It should +// be reported as kLocalDataObsolete, because by issuing the request client +// indicates that there should be new keys and it's possible that key rotation +// has happened by Member state wasn't updated (requires re-registration). +TEST_F(DownloadKeysResponseHandlerTest, ShouldHandleAbsenseOfNewKeys) { + EXPECT_THAT(handler() + .ProcessResponse( + /*http_status=*/TrustedVaultRequest::HttpStatus::kSuccess, + /*response_body=*/ + CreateListSecurityDomainsResponseWithSingleSyncMember( + /*trusted_vault_keys=*/{kKnownTrustedVaultKey}, + /*trusted_vault_keys_versions=*/ + {kKnownTrustedVaultKeyVersion}, + /*signing_keys=*/{{}})) + .status, + Eq(TrustedVaultRequestStatus::kLocalDataObsolete)); +} + +// Tests handling the situation, when response isn't a valid serialized +// ListSecurityDomains proto. +TEST_F(DownloadKeysResponseHandlerTest, ShouldHandleCorruptedResponseProto) { + EXPECT_THAT(handler() + .ProcessResponse( + /*http_status=*/TrustedVaultRequest::HttpStatus::kSuccess, + /*response_body=*/"corrupted_proto") + .status, + Eq(TrustedVaultRequestStatus::kOtherError)); +} + +// Client expects that the security domain exists, but the response indicates +// it doesn't by having no security domains. +TEST_F(DownloadKeysResponseHandlerTest, ShouldHandleEmptyResponse) { + EXPECT_THAT(handler() + .ProcessResponse( + /*http_status=*/TrustedVaultRequest::HttpStatus::kSuccess, + /*response_body=*/std::string()) + .status, + Eq(TrustedVaultRequestStatus::kLocalDataObsolete)); +} + +// Same as above, but there is a different security domain. +TEST_F(DownloadKeysResponseHandlerTest, ShouldHandleAbsenseOfSecurityDomain) { + sync_pb::ListSecurityDomainsResponse response; + sync_pb::SecurityDomain* security_domain = response.add_security_domains(); + security_domain->set_name("other_domain"); + + EXPECT_THAT(handler() + .ProcessResponse( + /*http_status=*/TrustedVaultRequest::HttpStatus::kSuccess, + /*response_body=*/response.SerializeAsString()) + .status, + Eq(TrustedVaultRequestStatus::kLocalDataObsolete)); +} + +// Tests handling presence of other security domains. +TEST_F(DownloadKeysResponseHandlerTest, ShouldHandleMultipleSecurityDomains) { + sync_pb::ListSecurityDomainsResponse response; + sync_pb::SecurityDomain* other_domain = response.add_security_domains(); + other_domain->set_name("other_domain"); + + sync_pb::SecurityDomain* sync_domain = response.add_security_domains(); + sync_domain->set_name(kSecurityDomainName); + FillSecurityDomainMember( + /*public_key=*/MakeTestKeyPair()->public_key(), + /*trusted_vault_keys=*/{kKnownTrustedVaultKey, kTrustedVaultKey1}, + /*trusted_vault_keys_versions=*/ + {kKnownTrustedVaultKeyVersion, kKnownTrustedVaultKeyVersion + 1}, + /*signing_keys=*/{{}, kKnownTrustedVaultKey}, sync_domain->add_members()); + + const DownloadKeysResponseHandler::ProcessedResponse processed_response = + handler().ProcessResponse( + /*http_status=*/TrustedVaultRequest::HttpStatus::kSuccess, + /*response_body=*/response.SerializeAsString()); + + EXPECT_THAT(processed_response.status, + Eq(TrustedVaultRequestStatus::kSuccess)); + EXPECT_THAT(processed_response.keys, + ElementsAre(kKnownTrustedVaultKey, kTrustedVaultKey1)); + EXPECT_THAT(processed_response.last_key_version, + Eq(kKnownTrustedVaultKeyVersion + 1)); +} + +// Security domain exists, but doesn't contain member corresponding to the +// current device. +TEST_F(DownloadKeysResponseHandlerTest, ShouldHandleAbsenseOfMember) { + sync_pb::ListSecurityDomainsResponse response; + sync_pb::SecurityDomain* security_domain = response.add_security_domains(); + security_domain->set_name(kSecurityDomainName); + + FillSecurityDomainMember( + /*public_key=*/SecureBoxKeyPair::GenerateRandom()->public_key(), + /*trusted_vault_keys=*/{kKnownTrustedVaultKey, kTrustedVaultKey1}, + /*trusted_vault_keys_versions=*/ + {kKnownTrustedVaultKeyVersion, kKnownTrustedVaultKeyVersion + 1}, + /*signing_keys=*/{{}, kKnownTrustedVaultKey}, + security_domain->add_members()); + + EXPECT_THAT(handler() + .ProcessResponse( + /*http_status=*/TrustedVaultRequest::HttpStatus::kSuccess, + /*response_body=*/response.SerializeAsString()) + .status, + Eq(TrustedVaultRequestStatus::kLocalDataObsolete)); +} + +// Tests handling presence of other members. +TEST_F(DownloadKeysResponseHandlerTest, ShouldHandleMultipleMembers) { + sync_pb::ListSecurityDomainsResponse response; + sync_pb::SecurityDomain* security_domain = response.add_security_domains(); + security_domain->set_name(kSecurityDomainName); + + // Other member. + FillSecurityDomainMember( + /*public_key=*/SecureBoxKeyPair::GenerateRandom()->public_key(), + /*trusted_vault_keys=*/{kKnownTrustedVaultKey, kTrustedVaultKey1}, + /*trusted_vault_keys_versions=*/ + {kKnownTrustedVaultKeyVersion, kKnownTrustedVaultKeyVersion + 1}, + /*signing_keys=*/{{}, kKnownTrustedVaultKey}, + security_domain->add_members()); + + // Member corresponding to the current device. + FillSecurityDomainMember( + /*public_key=*/MakeTestKeyPair()->public_key(), + /*trusted_vault_keys=*/{kKnownTrustedVaultKey, kTrustedVaultKey1}, + /*trusted_vault_keys_versions=*/ + {kKnownTrustedVaultKeyVersion, kKnownTrustedVaultKeyVersion + 1}, + /*signing_keys=*/{{}, kKnownTrustedVaultKey}, + security_domain->add_members()); + + const DownloadKeysResponseHandler::ProcessedResponse processed_response = + handler().ProcessResponse( + /*http_status=*/TrustedVaultRequest::HttpStatus::kSuccess, + /*response_body=*/response.SerializeAsString()); + + EXPECT_THAT(processed_response.status, + Eq(TrustedVaultRequestStatus::kSuccess)); + EXPECT_THAT(processed_response.keys, + ElementsAre(kKnownTrustedVaultKey, kTrustedVaultKey1)); + EXPECT_THAT(processed_response.last_key_version, + Eq(kKnownTrustedVaultKeyVersion + 1)); +} + +// Corrupted data case: the member corresponding to the current device exists, +// but has no keys. +TEST_F(DownloadKeysResponseHandlerTest, ShouldHandleEmptyMember) { + EXPECT_THAT(handler() + .ProcessResponse( + /*http_status=*/TrustedVaultRequest::HttpStatus::kSuccess, + /*response_body=*/ + CreateListSecurityDomainsResponseWithSingleSyncMember( + /*trusted_vault_keys=*/{}, + /*trusted_vault_keys_versions=*/{}, + /*signing_keys=*/{})) + .status, + Eq(TrustedVaultRequestStatus::kLocalDataObsolete)); +} + +} // namespace + +} // namespace syncer
diff --git a/components/sync/trusted_vault/standalone_trusted_vault_backend.cc b/components/sync/trusted_vault/standalone_trusted_vault_backend.cc index 54751cf..fa8ea11 100644 --- a/components/sync/trusted_vault/standalone_trusted_vault_backend.cc +++ b/components/sync/trusted_vault/standalone_trusted_vault_backend.cc
@@ -357,6 +357,7 @@ switch (status) { case TrustedVaultRequestStatus::kSuccess: + // TODO(crbug.com/1102340): consider keeping old keys as well. StoreKeys(gaia_id, vault_keys, last_vault_key_version); break; case TrustedVaultRequestStatus::kLocalDataObsolete: {
diff --git a/components/sync/trusted_vault/trusted_vault_connection_impl.cc b/components/sync/trusted_vault/trusted_vault_connection_impl.cc index 5293bce..15311fdc 100644 --- a/components/sync/trusted_vault/trusted_vault_connection_impl.cc +++ b/components/sync/trusted_vault/trusted_vault_connection_impl.cc
@@ -9,6 +9,7 @@ #include "base/containers/span.h" #include "components/signin/public/identity_manager/account_info.h" #include "components/sync/protocol/vault.pb.h" +#include "components/sync/trusted_vault/download_keys_response_handler.h" #include "components/sync/trusted_vault/securebox.h" #include "components/sync/trusted_vault/trusted_vault_access_token_fetcher.h" #include "components/sync/trusted_vault/trusted_vault_request.h" @@ -23,11 +24,15 @@ const uint8_t kWrappedKeyHeader[] = {'V', '1', ' ', 's', 'h', 'a', 'r', 'e', 'd', '_', 'k', 'e', 'y'}; const char kJoinSecurityDomainsURLPath[] = "/domain:join"; +const char kListSecurityDomainsURLPathAndQuery[] = "/domain:list?view=1"; const char kSecurityDomainName[] = "chromesync"; // Helper function for filling protobuf bytes field: protobuf represent them as // std::string, while in code std::vector<uint8_t> or base::span<uint8_t> is // more common. +// TODO(crbug.com/1113598): this function and its counterpart (proto string to +// bytes vector) is useful in many places under trusted_vault directory, +// consider moving it to some utility file. void AssignBytesToProtoString(base::span<const uint8_t> bytes, std::string* bytes_proto_field) { *bytes_proto_field = std::string(bytes.begin(), bytes.end()); @@ -106,6 +111,17 @@ return result; } +void ProcessDownloadKeysResponse( + std::unique_ptr<DownloadKeysResponseHandler> response_handler, + TrustedVaultConnection::DownloadKeysCallback callback, + TrustedVaultRequest::HttpStatus http_status, + const std::string& response_body) { + DownloadKeysResponseHandler::ProcessedResponse processed_response = + response_handler->ProcessResponse(http_status, response_body); + std::move(callback).Run(processed_response.status, processed_response.keys, + processed_response.last_key_version); +} + } // namespace TrustedVaultConnectionImpl::TrustedVaultConnectionImpl( @@ -149,9 +165,23 @@ int last_trusted_vault_key_version, std::unique_ptr<SecureBoxKeyPair> device_key_pair, DownloadKeysCallback callback) { - NOTIMPLEMENTED(); - // TODO(crbug.com/1113598): implement logic. - return std::make_unique<Request>(); + auto request = std::make_unique<TrustedVaultRequest>( + TrustedVaultRequest::HttpMethod::kGet, + GURL(trusted_vault_service_url_.spec() + + kListSecurityDomainsURLPathAndQuery), + /*serialized_request_proto=*/base::nullopt); + + request->FetchAccessTokenAndSendRequest( + account_info.account_id, GetOrCreateURLLoaderFactory(), + access_token_fetcher_.get(), + base::BindOnce(ProcessDownloadKeysResponse, + /*response_processor=*/ + std::make_unique<DownloadKeysResponseHandler>( + last_trusted_vault_key, last_trusted_vault_key_version, + std::move(device_key_pair)), + std::move(callback))); + + return request; } scoped_refptr<network::SharedURLLoaderFactory>
diff --git a/components/sync/trusted_vault/trusted_vault_connection_impl_unittest.cc b/components/sync/trusted_vault/trusted_vault_connection_impl_unittest.cc index ec38e05..a8023b0 100644 --- a/components/sync/trusted_vault/trusted_vault_connection_impl_unittest.cc +++ b/components/sync/trusted_vault/trusted_vault_connection_impl_unittest.cc
@@ -39,6 +39,8 @@ const char kTestURL[] = "https://test.com/test"; const char kTestJoinSecurityDomainsURL[] = "https://test.com/test/domain:join?alt=proto"; +const char kTestListSecurityDomainsURL[] = + "https://test.com/test/domain:list?view=1&alt=proto"; const uint8_t kWrappedKeyHeader[] = {'V', '1', ' ', 's', 'h', 'a', 'r', 'e', 'd', '_', 'k', 'e', 'y'}; @@ -115,6 +117,15 @@ /*content=*/std::string(), response_http_code); } + bool RespondToListSecurityDomainsRequest( + net::HttpStatusCode response_http_code) { + // Allow request to reach |test_url_loader_factory_|. + base::RunLoop().RunUntilIdle(); + return test_url_loader_factory_.SimulateResponseForPendingRequest( + kTestListSecurityDomainsURL, /*content=*/std::string(), + response_http_code); + } + const std::vector<uint8_t> kTrustedVaultKey = {1, 2, 3, 4}; private: @@ -300,6 +311,86 @@ RespondToJoinSecurityDomainsRequest(net::HTTP_OK); } +TEST_F(TrustedVaultConnectionImplTest, ShouldSendListSecurityDomainsRequest) { + std::unique_ptr<TrustedVaultConnection::Request> request = + connection()->DownloadKeys( + /*account_info=*/CoreAccountInfo(), + /*last_trusted_vault_key=*/std::vector<uint8_t>(), + /*last_trusted_vault_key_version=*/0, + /*device_key_pair=*/MakeTestKeyPair(), base::DoNothing()); + EXPECT_THAT(request, NotNull()); + + network::TestURLLoaderFactory::PendingRequest* pending_http_request = + GetPendingHTTPRequest(); + ASSERT_THAT(pending_http_request, NotNull()); + + const network::ResourceRequest& resource_request = + pending_http_request->request; + EXPECT_THAT(resource_request.method, Eq("GET")); + EXPECT_THAT(resource_request.url, Eq(GURL(kTestListSecurityDomainsURL))); +} + +// TODO(crbug.com/1113598): add coverage for at least one successful case +// (need to share some helper functions with +// download_keys_response_handler_unittest.cc). +TEST_F(TrustedVaultConnectionImplTest, + ShouldHandleFailedListSecurityDomainsRequest) { + base::MockCallback<TrustedVaultConnection::DownloadKeysCallback> callback; + + std::unique_ptr<TrustedVaultConnection::Request> request = + connection()->DownloadKeys( + /*account_info=*/CoreAccountInfo(), + /*last_trusted_vault_key=*/std::vector<uint8_t>(), + /*last_trusted_vault_key_version=*/0, + /*device_key_pair=*/MakeTestKeyPair(), callback.Get()); + ASSERT_THAT(request, NotNull()); + + EXPECT_CALL(callback, Run(Eq(TrustedVaultRequestStatus::kOtherError), _, _)); + EXPECT_TRUE( + RespondToListSecurityDomainsRequest(net::HTTP_INTERNAL_SERVER_ERROR)); +} + +TEST_F(TrustedVaultConnectionImplTest, + ShouldHandleAccessTokenFetchingFailureWhenDownloadingKeys) { + std::unique_ptr<TrustedVaultConnectionImpl> connection = + CreateConnectionWithAccessToken( + /*access_token=*/base::nullopt); + + base::MockCallback<TrustedVaultConnection::DownloadKeysCallback> callback; + + // |callback| is called immediately after DownloadKeys(), because there is no + // access token. + EXPECT_CALL(callback, Run(Eq(TrustedVaultRequestStatus::kOtherError), _, _)); + std::unique_ptr<TrustedVaultConnection::Request> request = + connection->DownloadKeys( + /*account_info=*/CoreAccountInfo(), + /*last_trusted_vault_key=*/std::vector<uint8_t>(), + /*last_trusted_vault_key_version=*/0, + /*device_key_pair=*/MakeTestKeyPair(), callback.Get()); + ASSERT_THAT(request, NotNull()); + + // No requests should be sent to the network. + EXPECT_THAT(GetPendingHTTPRequest(), IsNull()); +} + +TEST_F(TrustedVaultConnectionImplTest, ShouldCancelListSecurityDomainsRequest) { + base::MockCallback<TrustedVaultConnection::DownloadKeysCallback> callback; + + std::unique_ptr<TrustedVaultConnection::Request> request = + connection()->DownloadKeys( + /*account_info=*/CoreAccountInfo(), + /*last_trusted_vault_key=*/std::vector<uint8_t>(), + /*last_trusted_vault_key_version=*/0, + /*device_key_pair=*/MakeTestKeyPair(), callback.Get()); + ASSERT_THAT(request, NotNull()); + + EXPECT_CALL(callback, Run).Times(0); + request.reset(); + // Returned value isn't checked here, because the request can be cancelled + // before reaching TestURLLoaderFactory. + RespondToListSecurityDomainsRequest(net::HTTP_OK); +} + } // namespace } // namespace syncer
diff --git a/components/sync_preferences/pref_service_syncable_unittest.cc b/components/sync_preferences/pref_service_syncable_unittest.cc index e689cba..f99ea09 100644 --- a/components/sync_preferences/pref_service_syncable_unittest.cc +++ b/components/sync_preferences/pref_service_syncable_unittest.cc
@@ -132,8 +132,8 @@ syncer::ModelType model_type) { std::string serialized; JSONStringValueSerializer json(&serialized); - if (!json.Serialize(value)) - return syncer::SyncChange(); + bool success = json.Serialize(value); + DCHECK(success); sync_pb::EntitySpecifics entity; sync_pb::PreferenceSpecifics* pref = PrefModelAssociator::GetMutableSpecifics(model_type, &entity);
diff --git a/components/ui_devtools/BUILD.gn b/components/ui_devtools/BUILD.gn index 4063225..7bccde2 100644 --- a/components/ui_devtools/BUILD.gn +++ b/components/ui_devtools/BUILD.gn
@@ -153,6 +153,7 @@ "//base/test:test_support", "//net:test_support", "//services/network:network_service", + "//services/network:test_support", "//testing/gtest", ]
diff --git a/components/ui_devtools/DEPS b/components/ui_devtools/DEPS index 454d9846..1251e4bb 100644 --- a/components/ui_devtools/DEPS +++ b/components/ui_devtools/DEPS
@@ -14,5 +14,6 @@ "devtools_server_unittest\.cc": [ "+services/network/network_context.h", "+services/network/network_service.h", + "+services/network/test/fake_test_cert_verifier_params_factory.h", ] }
diff --git a/components/ui_devtools/devtools_server_unittest.cc b/components/ui_devtools/devtools_server_unittest.cc index 07a30f7..f7439ede 100644 --- a/components/ui_devtools/devtools_server_unittest.cc +++ b/components/ui_devtools/devtools_server_unittest.cc
@@ -15,6 +15,7 @@ #include "net/socket/tcp_client_socket.h" #include "services/network/network_context.h" #include "services/network/network_service.h" +#include "services/network/test/fake_test_cert_verifier_params_factory.h" #include "testing/gtest/include/gtest/gtest.h" namespace ui_devtools { @@ -39,10 +40,17 @@ mojo::Remote<network::mojom::NetworkService> network_service_remote; auto network_service = network::NetworkService::Create( network_service_remote.BindNewPipeAndPassReceiver()); + + network::mojom::NetworkContextParamsPtr context_params = + network::mojom::NetworkContextParams::New(); + // Use a dummy CertVerifier that always passes cert verification, since + // these unittests don't need to test CertVerifier behavior. + context_params->cert_verifier_params = + network::FakeTestCertVerifierParamsFactory::GetCertVerifierParams(); mojo::Remote<network::mojom::NetworkContext> network_context_remote; network_service_remote->CreateNetworkContext( network_context_remote.BindNewPipeAndPassReceiver(), - network::mojom::NetworkContextParams::New()); + std::move(context_params)); std::unique_ptr<UiDevToolsServer> server = UiDevToolsServer::CreateForViews(network_context_remote.get(), fake_port);
diff --git a/components/update_client/background_downloader_win.cc b/components/update_client/background_downloader_win.cc index 682c357..dc9c961 100644 --- a/components/update_client/background_downloader_win.cc +++ b/components/update_client/background_downloader_win.cc
@@ -25,6 +25,7 @@ #include "base/strings/string_piece.h" #include "base/strings/sys_string_conversions.h" #include "base/task/thread_pool.h" +#include "base/threading/scoped_thread_priority.h" #include "base/win/atl.h" #include "base/win/scoped_co_mem.h" #include "components/update_client/task_traits.h" @@ -139,6 +140,9 @@ // Retrieves the singleton instance of GIT for this process. HRESULT GetGit(ComPtr<IGlobalInterfaceTable>* git) { + // Mitigate the issues caused by loading DLLs on a background thread + // (http://crbug/973868). + SCOPED_MAY_LOAD_LIBRARY_AT_BACKGROUND_PRIORITY(); return ::CoCreateInstance(CLSID_StdGlobalInterfaceTable, nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&(*git))); }
diff --git a/components/viz/service/display_embedder/skia_output_device_buffer_queue.cc b/components/viz/service/display_embedder/skia_output_device_buffer_queue.cc index e4c0e24a..c358b62 100644 --- a/components/viz/service/display_embedder/skia_output_device_buffer_queue.cc +++ b/components/viz/service/display_embedder/skia_output_device_buffer_queue.cc
@@ -77,6 +77,8 @@ } } + void OnContextLost() { representation_->OnContextLost(); } + bool unique() const { return ref_ == 1; } const gpu::Mailbox& mailbox() const { return representation_->mailbox(); } gpu::SharedImageRepresentationOverlay::ScopedReadAccess* scoped_read_access() @@ -389,6 +391,18 @@ it->Unref(); } + // Code below can destroy last representation of the overlay shared image. On + // MacOS it needs context to be current. +#if defined(OS_APPLE) + // TODO(vasilyt): We shouldn't need this after we stop using + // SharedImageBackingGLImage as backing. + if (!dependency_->GetSharedContextState()->MakeCurrent(nullptr)) { + for (auto& overlay : overlays_) { + overlay.OnContextLost(); + } + } +#endif + // Go through backings of all overlays, and release overlay backings which are // not used. std::vector<gpu::Mailbox> released_overlays; @@ -409,10 +423,11 @@ }); DCHECK(!result.gpu_fence); + const auto& mailbox = + image ? image->skia_representation()->mailbox() : gpu::Mailbox(); FinishSwapBuffers(std::move(result), size, latency_info, - /*damage_area=*/base::nullopt, - std::move(released_overlays), - image ? image->skia_representation()->mailbox() : gpu::Mailbox()); + /*damage_area=*/base::nullopt, std::move(released_overlays), + mailbox); PageFlipComplete(image.get()); }
diff --git a/components/viz/service/display_embedder/skia_output_surface_impl.cc b/components/viz/service/display_embedder/skia_output_surface_impl.cc index 463dc99..a75f9bef5 100644 --- a/components/viz/service/display_embedder/skia_output_surface_impl.cc +++ b/components/viz/service/display_embedder/skia_output_surface_impl.cc
@@ -467,8 +467,10 @@ // callbacks. auto task = base::BindOnce(&SkiaOutputSurfaceImplOnGpu::SwapBuffersSkipped, base::Unretained(impl_on_gpu_.get())); + // SwapBuffersSkipped currently does mostly the same as SwapBuffers and needs + // MakeCurrent. EnqueueGpuTask(std::move(task), std::move(resource_sync_tokens_), - /*make_current=*/false, /*need_framebuffer=*/false); + /*make_current=*/true, /*need_framebuffer=*/false); // TODO(vasilyt): reuse root recorder RecreateRootRecorder(); @@ -657,7 +659,8 @@ base::BindOnce(&SkiaOutputSurfaceImplOnGpu::RemoveRenderPassResource, base::Unretained(impl_on_gpu_.get()), std::move(ids), std::move(image_contexts)); - EnqueueGpuTask(std::move(callback), {}, /*make_current=*/false, + // RemoveRenderPassResources will delete gpu resources and needs MakeCurrent. + EnqueueGpuTask(std::move(callback), {}, /*make_current=*/true, /*need_framebuffer=*/false); }
diff --git a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc index 3d96b81..42ef422 100644 --- a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc +++ b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc
@@ -1384,7 +1384,11 @@ #if defined(OS_APPLE) // Release any backings which are not reused by the current frame, probably // because the properties of render passes are changed or render passes are - // removed. + // removed + if (context_is_lost_) { + for (auto& image : available_render_pass_overlay_backings_) + image->OnContextLost(); + } available_render_pass_overlay_backings_.clear(); #endif
diff --git a/content/browser/accessibility/accessibility_tree_formatter_android.cc b/content/browser/accessibility/accessibility_tree_formatter_android.cc index e3e9ebe5..1a497c9 100644 --- a/content/browser/accessibility/accessibility_tree_formatter_android.cc +++ b/content/browser/accessibility/accessibility_tree_formatter_android.cc
@@ -99,8 +99,7 @@ base::DictionaryValue* dict) const; std::string ProcessTreeForOutput( - const base::DictionaryValue& node, - base::DictionaryValue* filtered_dict_result = nullptr) const override; + const base::DictionaryValue& node) const override; }; // static @@ -244,8 +243,7 @@ } std::string AccessibilityTreeFormatterAndroid::ProcessTreeForOutput( - const base::DictionaryValue& dict, - base::DictionaryValue* filtered_dict_result) const { + const base::DictionaryValue& dict) const { std::string error_value; if (dict.GetString("error", &error_value)) return error_value;
diff --git a/content/browser/accessibility/accessibility_tree_formatter_auralinux.cc b/content/browser/accessibility/accessibility_tree_formatter_auralinux.cc index 8a14d708..d150bf30 100644 --- a/content/browser/accessibility/accessibility_tree_formatter_auralinux.cc +++ b/content/browser/accessibility/accessibility_tree_formatter_auralinux.cc
@@ -39,8 +39,7 @@ private: std::string ProcessTreeForOutput( - const base::DictionaryValue& node, - base::DictionaryValue* filtered_dict_result = nullptr) const override; + const base::DictionaryValue& node) const override; base::Value BuildTree(BrowserAccessibility* root) const override; base::Value BuildTreeForWindow(gfx::AcceleratedWidget hwnd) const override; @@ -608,8 +607,7 @@ }; std::string AccessibilityTreeFormatterAuraLinux::ProcessTreeForOutput( - const base::DictionaryValue& node, - base::DictionaryValue* filtered_dict_result) const { + const base::DictionaryValue& node) const { std::string error_value; if (node.GetString("error", &error_value)) return error_value;
diff --git a/content/browser/accessibility/accessibility_tree_formatter_base.cc b/content/browser/accessibility/accessibility_tree_formatter_base.cc index 337da77..32d2fc8 100644 --- a/content/browser/accessibility/accessibility_tree_formatter_base.cc +++ b/content/browser/accessibility/accessibility_tree_formatter_base.cc
@@ -71,22 +71,6 @@ return contents; } -base::Value AccessibilityTreeFormatterBase::FilterTree( - const base::Value& dict) const { - base::DictionaryValue filtered_dict; - ProcessTreeForOutput(base::Value::AsDictionaryValue(dict), &filtered_dict); - const base::Value* children = dict.FindListPath(kChildrenDictAttr); - if (children && !children->GetList().empty()) { - base::Value filtered_children(base::Value::Type::LIST); - for (const auto& child_dict : children->GetList()) { - auto filtered_child = FilterTree(child_dict); - filtered_children.Append(std::move(filtered_child)); - } - filtered_dict.SetPath(kChildrenDictAttr, std::move(filtered_children)); - } - return std::move(filtered_dict); -} - void AccessibilityTreeFormatterBase::RecursiveFormatTree( const base::Value& dict, std::string* contents,
diff --git a/content/browser/accessibility/accessibility_tree_formatter_base.h b/content/browser/accessibility/accessibility_tree_formatter_base.h index b211183..5af8d38 100644 --- a/content/browser/accessibility/accessibility_tree_formatter_base.h +++ b/content/browser/accessibility/accessibility_tree_formatter_base.h
@@ -74,7 +74,6 @@ // AXTreeFormatter overrides. void AddDefaultFilters( std::vector<AXPropertyFilter>* property_filters) override; - base::Value FilterTree(const base::Value& dict) const override; std::string FormatTree(const base::Value& tree_node) const override; void SetPropertyFilters( const std::vector<AXPropertyFilter>& property_filters) override; @@ -102,8 +101,7 @@ // - Provides a filtered version of the dictionary in an out param, // (only if the out param is provided). virtual std::string ProcessTreeForOutput( - const base::DictionaryValue& node, - base::DictionaryValue* filtered_dict_result = nullptr) const = 0; + const base::DictionaryValue& node) const = 0; // // Utility functions to be used by each platform.
diff --git a/content/browser/accessibility/accessibility_tree_formatter_blink.cc b/content/browser/accessibility/accessibility_tree_formatter_blink.cc index 2179f6c..d3fe32da 100644 --- a/content/browser/accessibility/accessibility_tree_formatter_blink.cc +++ b/content/browser/accessibility/accessibility_tree_formatter_blink.cc
@@ -402,8 +402,7 @@ } std::string AccessibilityTreeFormatterBlink::ProcessTreeForOutput( - const base::DictionaryValue& dict, - base::DictionaryValue* filtered_dict_result) const { + const base::DictionaryValue& dict) const { std::string error_value; if (dict.GetString("error", &error_value)) return error_value;
diff --git a/content/browser/accessibility/accessibility_tree_formatter_blink.h b/content/browser/accessibility/accessibility_tree_formatter_blink.h index 80312d3..0bd1c570 100644 --- a/content/browser/accessibility/accessibility_tree_formatter_blink.h +++ b/content/browser/accessibility/accessibility_tree_formatter_blink.h
@@ -41,8 +41,7 @@ base::DictionaryValue* dict) const; std::string ProcessTreeForOutput( - const base::DictionaryValue& node, - base::DictionaryValue* filtered_dict_result = nullptr) const override; + const base::DictionaryValue& node) const override; }; } // namespace content
diff --git a/content/browser/accessibility/accessibility_tree_formatter_mac.mm b/content/browser/accessibility/accessibility_tree_formatter_mac.mm index ee70a95..d5742c5 100644 --- a/content/browser/accessibility/accessibility_tree_formatter_mac.mm +++ b/content/browser/accessibility/accessibility_tree_formatter_mac.mm
@@ -102,8 +102,7 @@ std::string NodeToLineIndex(id, const LineIndexer*) const; std::string ProcessTreeForOutput( - const base::DictionaryValue& node, - base::DictionaryValue* filtered_dict_result = nullptr) const override; + const base::DictionaryValue& node) const override; std::string FormatAttributeValue(const base::Value& value) const; }; @@ -453,8 +452,7 @@ } std::string AccessibilityTreeFormatterMac::ProcessTreeForOutput( - const base::DictionaryValue& dict, - base::DictionaryValue* filtered_dict_result) const { + const base::DictionaryValue& dict) const { std::string error_value; if (dict.GetString("error", &error_value)) return error_value;
diff --git a/content/browser/accessibility/accessibility_tree_formatter_uia_win.cc b/content/browser/accessibility/accessibility_tree_formatter_uia_win.cc index 2a76c2e..d033e0d 100644 --- a/content/browser/accessibility/accessibility_tree_formatter_uia_win.cc +++ b/content/browser/accessibility/accessibility_tree_formatter_uia_win.cc
@@ -996,8 +996,7 @@ } std::string AccessibilityTreeFormatterUia::ProcessTreeForOutput( - const base::DictionaryValue& dict, - base::DictionaryValue* filtered_result) const { + const base::DictionaryValue& dict) const { std::unique_ptr<base::DictionaryValue> tree; std::string line; @@ -1006,16 +1005,10 @@ dict.GetString(UiaIdentifierToCondensedString(UIA_ControlTypePropertyId), &control_type_value); WriteAttribute(true, control_type_value, &line); - if (filtered_result) { - filtered_result->SetString( - UiaIdentifierToStringUTF8(UIA_ControlTypePropertyId), - control_type_value); - } // properties for (long i : properties_) { - ProcessPropertyForOutput(UiaIdentifierToCondensedString(i), dict, line, - filtered_result); + ProcessPropertyForOutput(UiaIdentifierToCondensedString(i), dict, line); } // patterns @@ -1049,8 +1042,7 @@ "Window.IsModal"}; for (const std::string& pattern_property_name : pattern_property_names) { - ProcessPropertyForOutput(pattern_property_name, dict, line, - filtered_result); + ProcessPropertyForOutput(pattern_property_name, dict, line); } return line; @@ -1059,75 +1051,60 @@ void AccessibilityTreeFormatterUia::ProcessPropertyForOutput( const std::string& property_name, const base::DictionaryValue& dict, - std::string& line, - base::DictionaryValue* filtered_result) const { + std::string& line) const { // const base::Value* value; if (dict.Get(property_name, &value)) - ProcessValueForOutput(property_name, value, line, filtered_result); + ProcessValueForOutput(property_name, value, line); } void AccessibilityTreeFormatterUia::ProcessValueForOutput( const std::string& name, const base::Value* value, - std::string& line, - base::DictionaryValue* filtered_result) const { + std::string& line) const { switch (value->type()) { case base::Value::Type::STRING: { std::string string_value; value->GetAsString(&string_value); - bool did_pass_filters = WriteAttribute( + WriteAttribute( false, base::StringPrintf("%s='%s'", name.c_str(), string_value.c_str()), &line); - if (filtered_result && did_pass_filters) - filtered_result->SetString(name, string_value); break; } case base::Value::Type::BOOLEAN: { bool bool_value = 0; value->GetAsBoolean(&bool_value); - bool did_pass_filters = WriteAttribute(false, base::StringPrintf("%s=%s", name.c_str(), (bool_value ? "true" : "false")), &line); - if (filtered_result && did_pass_filters) - filtered_result->SetBoolean(name, bool_value); break; } case base::Value::Type::INTEGER: { int int_value = 0; value->GetAsInteger(&int_value); - bool did_pass_filters = WriteAttribute( + WriteAttribute( false, base::StringPrintf("%s=%d", name.c_str(), int_value), &line); - if (filtered_result && did_pass_filters) - filtered_result->SetInteger(name, int_value); break; } case base::Value::Type::DOUBLE: { double double_value = 0.0; value->GetAsDouble(&double_value); - bool did_pass_filters = WriteAttribute( - false, base::StringPrintf("%s=%.2f", name.c_str(), double_value), - &line); - if (filtered_result && did_pass_filters) - filtered_result->SetDouble(name, double_value); + WriteAttribute(false, + base::StringPrintf("%s=%.2f", name.c_str(), double_value), + &line); break; } case base::Value::Type::DICTIONARY: { const base::DictionaryValue* dict_value = nullptr; value->GetAsDictionary(&dict_value); - bool did_pass_filters = false; if (name == "BoundingRectangle") { - did_pass_filters = - WriteAttribute(false, - FormatRectangle(*dict_value, "BoundingRectangle", - "left", "top", "width", "height"), - &line); + WriteAttribute(false, + FormatRectangle(*dict_value, "BoundingRectangle", "left", + "top", "width", "height"), + &line); } - if (filtered_result && did_pass_filters) - filtered_result->SetKey(name, dict_value->Clone()); break; } default:
diff --git a/content/browser/accessibility/accessibility_tree_formatter_uia_win.h b/content/browser/accessibility/accessibility_tree_formatter_uia_win.h index d0c8eec..be0c6b0 100644 --- a/content/browser/accessibility/accessibility_tree_formatter_uia_win.h +++ b/content/browser/accessibility/accessibility_tree_formatter_uia_win.h
@@ -91,16 +91,13 @@ base::DictionaryValue* dict) const; base::string16 GetNodeName(IUIAutomationElement* node) const; std::string ProcessTreeForOutput( - const base::DictionaryValue& node, - base::DictionaryValue* filtered_result = nullptr) const override; + const base::DictionaryValue& node) const override; void ProcessPropertyForOutput(const std::string& property_name, const base::DictionaryValue& dict, - std::string& line, - base::DictionaryValue* filtered_result) const; + std::string& line) const; void ProcessValueForOutput(const std::string& name, const base::Value* value, - std::string& line, - base::DictionaryValue* filtered_result) const; + std::string& line) const; Microsoft::WRL::ComPtr<IUIAutomation> uia_; Microsoft::WRL::ComPtr<IUIAutomationCacheRequest> element_cache_request_; Microsoft::WRL::ComPtr<IUIAutomationCacheRequest> children_cache_request_;
diff --git a/content/browser/accessibility/accessibility_tree_formatter_win.cc b/content/browser/accessibility/accessibility_tree_formatter_win.cc index 9684afd..ba79ad75 100644 --- a/content/browser/accessibility/accessibility_tree_formatter_win.cc +++ b/content/browser/accessibility/accessibility_tree_formatter_win.cc
@@ -79,8 +79,7 @@ void AddIA2ValueProperties(const Microsoft::WRL::ComPtr<IAccessible>, base::DictionaryValue* dict) const; std::string ProcessTreeForOutput( - const base::DictionaryValue& node, - base::DictionaryValue* filtered_dict_result = nullptr) const override; + const base::DictionaryValue& node) const override; }; // static @@ -872,16 +871,13 @@ } std::string AccessibilityTreeFormatterWin::ProcessTreeForOutput( - const base::DictionaryValue& dict, - base::DictionaryValue* filtered_dict_result) const { + const base::DictionaryValue& dict) const { std::string line; // Always show role, and show it first. std::string role_value; dict.GetString("role", &role_value); WriteAttribute(true, role_value, &line); - if (filtered_dict_result) - filtered_dict_result->SetString("role", role_value); for (const char* attribute_name : ALL_ATTRIBUTES) { const base::Value* value; @@ -892,32 +888,26 @@ case base::Value::Type::STRING: { std::string string_value; value->GetAsString(&string_value); - bool did_pass_filters = WriteAttribute( + WriteAttribute( false, base::StringPrintf("%s='%s'", attribute_name, string_value.c_str()), &line); - if (filtered_dict_result && did_pass_filters) - filtered_dict_result->SetString(attribute_name, string_value); break; } case base::Value::Type::INTEGER: { int int_value = 0; value->GetAsInteger(&int_value); - bool did_pass_filters = WriteAttribute( - false, base::StringPrintf("%s=%d", attribute_name, int_value), - &line); - if (filtered_dict_result && did_pass_filters) - filtered_dict_result->SetInteger(attribute_name, int_value); + WriteAttribute(false, + base::StringPrintf("%s=%d", attribute_name, int_value), + &line); break; } case base::Value::Type::DOUBLE: { double double_value = 0.0; value->GetAsDouble(&double_value); - bool did_pass_filters = WriteAttribute( + WriteAttribute( false, base::StringPrintf("%s=%.2f", attribute_name, double_value), &line); - if (filtered_dict_result && did_pass_filters) - filtered_dict_result->SetDouble(attribute_name, double_value); break; } case base::Value::Type::LIST: { @@ -934,8 +924,6 @@ if (WriteAttribute(false, string_value, &line)) filtered_list->AppendString(string_value); } - if (filtered_dict_result && !filtered_list->empty()) - filtered_dict_result->Set(attribute_name, std::move(filtered_list)); break; } case base::Value::Type::DICTIONARY: { @@ -943,18 +931,15 @@ // Revisit this if that changes. const base::DictionaryValue* dict_value; value->GetAsDictionary(&dict_value); - bool did_pass_filters = false; if (strcmp(attribute_name, "size") == 0) { - did_pass_filters = WriteAttribute( + WriteAttribute( false, FormatCoordinates(*dict_value, "size", "width", "height"), &line); } else if (strcmp(attribute_name, "location") == 0) { - did_pass_filters = WriteAttribute( - false, FormatCoordinates(*dict_value, "location", "x", "y"), - &line); + WriteAttribute(false, + FormatCoordinates(*dict_value, "location", "x", "y"), + &line); } - if (filtered_dict_result && did_pass_filters) - filtered_dict_result->SetKey(attribute_name, dict_value->Clone()); break; } default:
diff --git a/content/browser/devtools/devtools_instrumentation.cc b/content/browser/devtools/devtools_instrumentation.cc index 4c1ef76..97e6f89d 100644 --- a/content/browser/devtools/devtools_instrumentation.cc +++ b/content/browser/devtools/devtools_instrumentation.cc
@@ -271,7 +271,8 @@ DispatchToAgents(frame_tree_node, &protocol::NetworkHandler::RequestSent, request_id.ToString(), loader_id.ToString(), request, protocol::Network::Initiator::TypeEnum::SignedExchange, - signed_exchange_url, timestamp); + signed_exchange_url, /*initiator_devtools_request_id=*/"", + timestamp); auto value = std::make_unique<base::trace_event::TracedValue>(); value->SetString("requestId", request_id.ToString()); @@ -719,21 +720,17 @@ int32_t render_frame_id, const base::UnguessableToken& devtools_request_id, const network::ResourceRequest& request, - const GURL& initiator_url) { + const GURL& initiator_url, + const std::string& initiator_devtools_request_id) { FrameTreeNode* ftn = GetFtnForNetworkRequest(process_id, render_frame_id); if (!ftn) return; auto timestamp = base::TimeTicks::Now(); auto id = devtools_request_id.ToString(); - // TODO(crbug.com/941297): Currently we are using an empty string for - // |loader_id|. But when we will introduce a better UI for preflight requests, - // consider using the navigation token which is same as the |loader_id| of the - // original request or the |devtools_request_id| of the original request, so - // that we can associate the requests in the DevTools front end. DispatchToAgents(ftn, &protocol::NetworkHandler::RequestSent, id, /* loader_id=*/"", request, - protocol::Network::Initiator::TypeEnum::Other, initiator_url, - timestamp); + protocol::Network::Initiator::TypeEnum::Preflight, + initiator_url, initiator_devtools_request_id, timestamp); } void OnCorsPreflightResponse(int32_t process_id, @@ -747,7 +744,7 @@ auto id = devtools_request_id.ToString(); DispatchToAgents(ftn, &protocol::NetworkHandler::ResponseReceived, id, /* loader_id=*/"", url, - protocol::Network::ResourceTypeEnum::Other, *head, + protocol::Network::ResourceTypeEnum::Preflight, *head, protocol::Maybe<std::string>()); } @@ -761,7 +758,7 @@ return; auto id = devtools_request_id.ToString(); DispatchToAgents(ftn, &protocol::NetworkHandler::LoadingComplete, id, - protocol::Network::ResourceTypeEnum::Other, status); + protocol::Network::ResourceTypeEnum::Preflight, status); } namespace {
diff --git a/content/browser/devtools/devtools_instrumentation.h b/content/browser/devtools/devtools_instrumentation.h index 5636489..736e746 100644 --- a/content/browser/devtools/devtools_instrumentation.h +++ b/content/browser/devtools/devtools_instrumentation.h
@@ -160,7 +160,8 @@ int32_t render_frame_id, const base::UnguessableToken& devtools_request_id, const network::ResourceRequest& request, - const GURL& signed_exchange_url); + const GURL& signed_exchange_url, + const std::string& initiator_devtools_request_id); void OnCorsPreflightResponse(int32_t process_id, int32_t render_frame_id, const base::UnguessableToken& devtools_request_id,
diff --git a/content/browser/devtools/protocol/network_handler.cc b/content/browser/devtools/protocol/network_handler.cc index 7085282..4b8442f2 100644 --- a/content/browser/devtools/protocol/network_handler.cc +++ b/content/browser/devtools/protocol/network_handler.cc
@@ -1776,12 +1776,14 @@ common_params.has_user_gesture); } -void NetworkHandler::RequestSent(const std::string& request_id, - const std::string& loader_id, - const network::ResourceRequest& request, - const char* initiator_type, - const base::Optional<GURL>& initiator_url, - base::TimeTicks timestamp) { +void NetworkHandler::RequestSent( + const std::string& request_id, + const std::string& loader_id, + const network::ResourceRequest& request, + const char* initiator_type, + const base::Optional<GURL>& initiator_url, + const std::string& initiator_devtools_request_id, + base::TimeTicks timestamp) { if (!enabled_) return; std::unique_ptr<DictionaryValue> headers_dict(DictionaryValue::create()); @@ -1791,6 +1793,8 @@ Network::Initiator::Create().SetType(initiator_type).Build(); if (initiator_url) initiator->SetUrl(initiator_url->spec()); + if (initiator_devtools_request_id.size()) + initiator->SetRequestId(initiator_devtools_request_id); std::string url_fragment; std::string url_without_fragment = ExtractFragment(request.url, &url_fragment);
diff --git a/content/browser/devtools/protocol/network_handler.h b/content/browser/devtools/protocol/network_handler.h index d03370b..735b49e1 100644 --- a/content/browser/devtools/protocol/network_handler.h +++ b/content/browser/devtools/protocol/network_handler.h
@@ -177,6 +177,7 @@ const network::ResourceRequest& request, const char* initiator_type, const base::Optional<GURL>& initiator_url, + const std::string& initiator_devtools_request_id, base::TimeTicks timestamp); void ResponseReceived(const std::string& request_id, const std::string& loader_id,
diff --git a/content/browser/devtools/service_worker_devtools_manager.cc b/content/browser/devtools/service_worker_devtools_manager.cc index f8003e1..fd1c524 100644 --- a/content/browser/devtools/service_worker_devtools_manager.cc +++ b/content/browser/devtools/service_worker_devtools_manager.cc
@@ -216,7 +216,8 @@ protocol::NetworkHandler::ForAgentHost(it->second.get())) { network->RequestSent(request_id, std::string(), request, protocol::Network::Initiator::TypeEnum::Preload, - base::nullopt /* initiator_url */, timestamp); + /*initiator_url=*/base::nullopt, + /*initiator_devtools_request_id=*/"", timestamp); } }
diff --git a/content/browser/net/cross_origin_opener_policy_reporter.cc b/content/browser/net/cross_origin_opener_policy_reporter.cc index 422c43d2..395d780 100644 --- a/content/browser/net/cross_origin_opener_policy_reporter.cc +++ b/content/browser/net/cross_origin_opener_policy_reporter.cc
@@ -76,18 +76,15 @@ std::vector<FrameTreeNode*> CollectOtherWindowForCoopAccess( FrameTreeNode* frame) { DCHECK(frame->IsMainFrame()); - SiteInstance* site_instance = frame->current_frame_host()->GetSiteInstance(); int virtual_browsing_context_group = frame->current_frame_host()->virtual_browsing_context_group(); std::vector<FrameTreeNode*> out; - for (WebContentsImpl* wc : WebContentsImpl::GetAllWebContents()) { - RenderFrameHostImpl* rfh = wc->GetMainFrame(); - - // Filters out windows from a different browsing context group. - if (!rfh->GetSiteInstance()->IsRelatedSiteInstance(site_instance)) - continue; - + for (RenderFrameHostImpl* rfh : + frame->current_frame_host() + ->delegate() + ->GetActiveTopLevelDocumentsInBrowsingContextGroup( + frame->current_frame_host())) { // Filter out windows from the same virtual browsing context group. if (rfh->virtual_browsing_context_group() == virtual_browsing_context_group) continue;
diff --git a/content/browser/network_service_client.cc b/content/browser/network_service_client.cc index 44e8b72..38ab568 100644 --- a/content/browser/network_service_client.cc +++ b/content/browser/network_service_client.cc
@@ -236,9 +236,11 @@ int32_t render_frame_id, const base::UnguessableToken& devtools_request_id, const network::ResourceRequest& request, - const GURL& initiator_url) { + const GURL& initiator_url, + const std::string& initiator_devtools_request_id) { devtools_instrumentation::OnCorsPreflightRequest( - process_id, render_frame_id, devtools_request_id, request, initiator_url); + process_id, render_frame_id, devtools_request_id, request, initiator_url, + initiator_devtools_request_id); } void NetworkServiceClient::OnCorsPreflightResponse(
diff --git a/content/browser/network_service_client.h b/content/browser/network_service_client.h index 6849c44..2eb3415 100644 --- a/content/browser/network_service_client.h +++ b/content/browser/network_service_client.h
@@ -64,11 +64,13 @@ const net::CookieAndLineAccessResultList& cookies_with_access_result, std::vector<network::mojom::HttpRawHeaderPairPtr> headers, const base::Optional<std::string>& raw_response_headers) override; - void OnCorsPreflightRequest(int32_t process_id, - int32_t render_frame_id, - const base::UnguessableToken& devtool_request_id, - const network::ResourceRequest& request, - const GURL& initiator_url) override; + void OnCorsPreflightRequest( + int32_t process_id, + int32_t render_frame_id, + const base::UnguessableToken& devtool_request_id, + const network::ResourceRequest& request, + const GURL& initiator_url, + const std::string& initiator_devtools_request_id) override; void OnCorsPreflightResponse( int32_t process_id, int32_t render_frame_id,
diff --git a/content/browser/renderer_host/cross_origin_opener_policy_status.cc b/content/browser/renderer_host/cross_origin_opener_policy_status.cc index 3296a4c..58d11400 100644 --- a/content/browser/renderer_host/cross_origin_opener_policy_status.cc +++ b/content/browser/renderer_host/cross_origin_opener_policy_status.cc
@@ -9,6 +9,7 @@ #include "base/feature_list.h" #include "base/time/time.h" #include "content/browser/renderer_host/frame_tree_node.h" +#include "content/browser/renderer_host/render_frame_host_delegate.h" #include "services/network/public/cpp/features.h" #include "services/network/public/cpp/is_potentially_trustworthy.h" #include "third_party/blink/public/common/origin_trials/trial_token_validator.h" @@ -84,7 +85,6 @@ : frame_tree_node_(frame_tree_node), virtual_browsing_context_group_(frame_tree_node->current_frame_host() ->virtual_browsing_context_group()), - had_opener_(!!frame_tree_node->opener()), is_initial_navigation_(!frame_tree_node_->has_committed_real_load()), current_coop_( frame_tree_node->current_frame_host()->cross_origin_opener_policy()), @@ -176,17 +176,20 @@ current_coop_.report_only_value, current_origin_, is_initial_navigation_, response_coop.value, response_origin); + bool has_other_window_in_browsing_context_group = + frame_tree_node_->current_frame_host() + ->delegate() + ->GetActiveTopLevelDocumentsInBrowsingContextGroup( + frame_tree_node_->current_frame_host()) + .size() > 1; + if (cross_origin_policy_swap) { require_browsing_instance_swap_ = true; - // If this response's COOP causes a BrowsingInstance swap that severs an - // opener, report this to the previous COOP reporter and/or the COOP - // reporter of the response if they exist. - // TODO(clamy): This is not correct. We should be sending a report if there - // is any other top-level browsing context in the browsing context group, - // and not only when the browsing context has an opener. Otherwise, we - // would not emit a report when the opener of a window has a bcg switch. - if (had_opener_) { + // If this response's COOP causes a BrowsingInstance swap that severs + // communication with another page, report this to the previous COOP + // reporter and/or the COOP reporter of the response if they exist. + if (has_other_window_in_browsing_context_group) { response_reporter->QueueNavigationToCOOPReport( current_url_, current_origin_.IsSameOriginWith(response_origin), false /* is_report_only */); @@ -205,13 +208,10 @@ navigating_from_report_only_coop_swap); if (virtual_browsing_instance_swap) { // If this response's report-only COOP would cause a BrowsingInstance swap - // that would sever an opener, report this to the previous COOP reporter - // and/or the COOP reporter of the response if they exist. - // TODO(clamy): This is not correct. We should be sending a report if there - // is any other top-level browsing context in the browsing context group, - // and not only when the browsing context has an opener. Otherwise, we - // would not emit a report when the opener of a window has a bcg switch. - if (had_opener_) { + // that would sever communication with another page, report this to the + // previous COOP reporter and/or the COOP reporter of the response if they + // exist. + if (has_other_window_in_browsing_context_group) { response_reporter->QueueNavigationToCOOPReport( current_url_, current_origin_.IsSameOriginWith(response_origin), true /* is_report_only */);
diff --git a/content/browser/renderer_host/cross_origin_opener_policy_status.h b/content/browser/renderer_host/cross_origin_opener_policy_status.h index ceaeb87..0eea5fe 100644 --- a/content/browser/renderer_host/cross_origin_opener_policy_status.h +++ b/content/browser/renderer_host/cross_origin_opener_policy_status.h
@@ -88,11 +88,6 @@ int virtual_browsing_context_group_; - // When a page has a reachable opener and COOP triggers a browsing instance - // swap we sever the window.open relationship. This is one of the cases that - // can be reported using the COOP reporting API. - const bool had_opener_; - // Whether this is the first navigation happening in the browsing context. const bool is_initial_navigation_;
diff --git a/content/browser/renderer_host/render_frame_host_delegate.cc b/content/browser/renderer_host/render_frame_host_delegate.cc index bd009ae..a50786d6 100644 --- a/content/browser/renderer_host/render_frame_host_delegate.cc +++ b/content/browser/renderer_host/render_frame_host_delegate.cc
@@ -199,4 +199,10 @@ return false; } +std::vector<RenderFrameHostImpl*> +RenderFrameHostDelegate::GetActiveTopLevelDocumentsInBrowsingContextGroup( + RenderFrameHostImpl* render_frame_host) { + return std::vector<RenderFrameHostImpl*>(); +} + } // namespace content
diff --git a/content/browser/renderer_host/render_frame_host_delegate.h b/content/browser/renderer_host/render_frame_host_delegate.h index 2d2d197..32c0a67 100644 --- a/content/browser/renderer_host/render_frame_host_delegate.h +++ b/content/browser/renderer_host/render_frame_host_delegate.h
@@ -637,6 +637,12 @@ // The page is trying to move the main frame's representation in the client. virtual void SetWindowRect(const gfx::Rect& new_bounds) {} + // Returns the list of top-level RenderFrameHosts hosting active documents + // that belong to the same browsing context group as |render_frame_host|. + virtual std::vector<RenderFrameHostImpl*> + GetActiveTopLevelDocumentsInBrowsingContextGroup( + RenderFrameHostImpl* render_frame_host); + protected: virtual ~RenderFrameHostDelegate() = default; };
diff --git a/content/browser/renderer_host/render_frame_host_impl.cc b/content/browser/renderer_host/render_frame_host_impl.cc index 68b2d351..5da79c8 100644 --- a/content/browser/renderer_host/render_frame_host_impl.cc +++ b/content/browser/renderer_host/render_frame_host_impl.cc
@@ -8727,7 +8727,25 @@ // renderer one. The browser will just "push" the correct value. if (navigation_request->state() >= NavigationRequest::NavigationState::WILL_PROCESS_RESPONSE) { - DCHECK_EQ(params.sandbox_flags, navigation_request->SandboxFlagsToCommit()); + 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(); + } } coep_reporter_ = navigation_request->TakeCoepReporter();
diff --git a/content/browser/renderer_host/render_frame_host_impl_browsertest.cc b/content/browser/renderer_host/render_frame_host_impl_browsertest.cc index 6dc4ca9e..adf1c1a 100644 --- a/content/browser/renderer_host/render_frame_host_impl_browsertest.cc +++ b/content/browser/renderer_host/render_frame_host_impl_browsertest.cc
@@ -4167,7 +4167,7 @@ GURL url = InsecureURL(*embedded_test_server(), "/empty.html"); - content::TestNavigationManager child_navigation_manager(web_contents(), url); + TestNavigationManager child_navigation_manager(web_contents(), url); EXPECT_TRUE(ExecJs(root_frame_host(), R"( const iframe = document.createElement("iframe"); @@ -4204,7 +4204,7 @@ GURL url = InsecureURL(*embedded_test_server(), "/empty.html"); - content::TestNavigationManager child_navigation_manager(web_contents(), url); + TestNavigationManager child_navigation_manager(web_contents(), url); EXPECT_TRUE(ExecJs(root_frame_host(), R"( const iframe = document.createElement("iframe"); @@ -4224,6 +4224,123 @@ EXPECT_FALSE(child_frame->GetLastCommittedOrigin().opaque()); } +// TODO(https://crbug.com/1129326): Revisit this when main-frame navigations are +// subject to CORS-RFC1918 checks. +IN_PROC_BROWSER_TEST_F( + RenderFrameHostImplBrowserTestWithInsecurePrivateNetworkRequestsBlocked, + FormSubmissionFromInsecurePublictoLocalIsNotBlockedInMainFrame) { + EXPECT_TRUE(NavigateToURL( + shell(), InsecureTreatAsPublicAddressURL(*embedded_test_server()))); + + GURL url = InsecureDefaultURL(*embedded_test_server()); + TestNavigationManager navigation_manager(web_contents(), url); + + base::StringPiece script_template = R"( + const form = document.createElement("form"); + form.action = $1; + form.method = "post"; + document.body.appendChild(form); + form.submit(); + )"; + + EXPECT_TRUE(ExecJs(root_frame_host(), JsReplace(script_template, url))); + + navigation_manager.WaitForNavigationFinished(); + + // Check that the child iframe was not blocked. + EXPECT_TRUE(navigation_manager.was_successful()); + + EXPECT_EQ(url, EvalJs(root_frame_host(), "document.location.href")); + EXPECT_EQ(url, root_frame_host()->GetLastCommittedURL()); + EXPECT_FALSE(root_frame_host()->GetLastCommittedOrigin().opaque()); +} + +IN_PROC_BROWSER_TEST_F( + RenderFrameHostImplBrowserTestWithInsecurePrivateNetworkRequestsBlocked, + FormSubmissionFromInsecurePublictoLocalIsBlockedInChildFrame) { + EXPECT_TRUE(NavigateToURL( + shell(), InsecureTreatAsPublicAddressURL(*embedded_test_server()))); + + GURL url = InsecureDefaultURL(*embedded_test_server()); + TestNavigationManager navigation_manager(web_contents(), url); + + base::StringPiece script_template = R"( + const iframe = document.createElement("iframe"); + document.body.appendChild(iframe); + + const childDoc = iframe.contentDocument; + const form = childDoc.createElement("form"); + form.action = $1; + form.method = "post"; + childDoc.body.appendChild(form); + form.submit(); + )"; + + EXPECT_TRUE(ExecJs(root_frame_host(), JsReplace(script_template, url))); + + navigation_manager.WaitForNavigationFinished(); + + // Check that the child iframe was blocked. + EXPECT_FALSE(navigation_manager.was_successful()); + + ASSERT_EQ(1ul, root_frame_host()->child_count()); + auto* child_frame = root_frame_host()->child_at(0)->current_frame_host(); + + // Failed navigation. + EXPECT_EQ(GURL(kUnreachableWebDataURL), + EvalJs(child_frame, "document.location.href")); + + // The URL is the form target URL, to allow for reloading. + // The origin is opaque though, a symptom of the failed navigation. + EXPECT_EQ(url, child_frame->GetLastCommittedURL()); + EXPECT_TRUE(child_frame->GetLastCommittedOrigin().opaque()); +} + +IN_PROC_BROWSER_TEST_F( + RenderFrameHostImplBrowserTestWithInsecurePrivateNetworkRequestsBlocked, + FormSubmissionGetFromInsecurePublictoLocalIsBlockedInChildFrame) { + EXPECT_TRUE(NavigateToURL( + shell(), InsecureTreatAsPublicAddressURL(*embedded_test_server()))); + + GURL target_url = InsecureDefaultURL(*embedded_test_server()); + + // The page navigates to `url` followed by an empty query: '?'. + GURL expected_url = GURL(target_url.spec() + "?"); + TestNavigationManager navigation_manager(web_contents(), expected_url); + + base::StringPiece script_template = R"( + const iframe = document.createElement("iframe"); + document.body.appendChild(iframe); + + const childDoc = iframe.contentDocument; + const form = childDoc.createElement("form"); + form.action = $1; + form.method = "get"; + childDoc.body.appendChild(form); + form.submit(); + )"; + + EXPECT_TRUE( + ExecJs(root_frame_host(), JsReplace(script_template, target_url))); + + navigation_manager.WaitForNavigationFinished(); + + // Check that the child iframe was blocked. + EXPECT_FALSE(navigation_manager.was_successful()); + + ASSERT_EQ(1ul, root_frame_host()->child_count()); + auto* child_frame = root_frame_host()->child_at(0)->current_frame_host(); + + // Failed navigation. + EXPECT_EQ(GURL(kUnreachableWebDataURL), + EvalJs(child_frame, "document.location.href")); + + // The URL is the form target URL, to allow for reloading. + // The origin is opaque though, a symptom of the failed navigation. + EXPECT_EQ(expected_url, child_frame->GetLastCommittedURL()); + EXPECT_TRUE(child_frame->GetLastCommittedOrigin().opaque()); +} + // TODO(https://crbug.com/1134601): `about:` URLs are all treated as `kUnknown` // today. This is ~incorrect, but safe, as their web-facing behavior will be // equivalent to "public".
diff --git a/content/browser/service_worker/service_worker_context_core_unittest.cc b/content/browser/service_worker/service_worker_context_core_unittest.cc index 68126309..e94a17a 100644 --- a/content/browser/service_worker/service_worker_context_core_unittest.cc +++ b/content/browser/service_worker/service_worker_context_core_unittest.cc
@@ -312,7 +312,7 @@ loop.Run(); // The operation should still complete. - EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorFailed, status); + EXPECT_EQ(blink::ServiceWorkerStatusCode::kErrorAbort, status); } } // namespace content
diff --git a/content/browser/service_worker/service_worker_registry.cc b/content/browser/service_worker/service_worker_registry.cc index 01eceb12..f0fe587 100644 --- a/content/browser/service_worker/service_worker_registry.cc +++ b/content/browser/service_worker/service_worker_registry.cc
@@ -202,9 +202,11 @@ blink::mojom::ServiceWorkerRegistrationOptions options, NewRegistrationCallback callback) { DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId()); - GetRemoteStorageControl()->GetNewRegistrationId(base::BindOnce( - &ServiceWorkerRegistry::DidGetNewRegistrationId, - weak_factory_.GetWeakPtr(), std::move(options), std::move(callback))); + CreateInvokerAndStartRemoteCall( + &storage::mojom::ServiceWorkerStorageControl::GetNewRegistrationId, + base::BindRepeating(&ServiceWorkerRegistry::DidGetNewRegistrationId, + weak_factory_.GetWeakPtr(), base::Passed(&options), + base::Passed(&callback))); } void ServiceWorkerRegistry::CreateNewVersion( @@ -214,9 +216,11 @@ NewVersionCallback callback) { DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId()); DCHECK(registration); - GetRemoteStorageControl()->GetNewVersionId(base::BindOnce( - &ServiceWorkerRegistry::DidGetNewVersionId, weak_factory_.GetWeakPtr(), - std::move(registration), script_url, script_type, std::move(callback))); + CreateInvokerAndStartRemoteCall( + &storage::mojom::ServiceWorkerStorageControl::GetNewVersionId, + base::BindRepeating(&ServiceWorkerRegistry::DidGetNewVersionId, + weak_factory_.GetWeakPtr(), registration, script_url, + script_type, base::Passed(&callback))); } void ServiceWorkerRegistry::FindRegistrationForClientUrl( @@ -230,11 +234,14 @@ TRACE_EVENT_ASYNC_BEGIN1( "ServiceWorker", "ServiceWorkerRegistry::FindRegistrationForClientUrl", trace_event_id, "URL", client_url.spec()); - GetRemoteStorageControl()->FindRegistrationForClientUrl( - client_url, - base::BindOnce(&ServiceWorkerRegistry::DidFindRegistrationForClientUrl, - weak_factory_.GetWeakPtr(), client_url, trace_event_id, - std::move(callback))); + CreateInvokerAndStartRemoteCall( + &storage::mojom::ServiceWorkerStorageControl:: + FindRegistrationForClientUrl, + base::BindRepeating( + &ServiceWorkerRegistry::DidFindRegistrationForClientUrl, + weak_factory_.GetWeakPtr(), client_url, trace_event_id, + base::Passed(&callback)), + client_url); } void ServiceWorkerRegistry::FindRegistrationForScope( @@ -258,9 +265,11 @@ return; } - GetRemoteStorageControl()->FindRegistrationForScope( - scope, base::BindOnce(&ServiceWorkerRegistry::DidFindRegistrationForScope, - weak_factory_.GetWeakPtr(), std::move(callback))); + CreateInvokerAndStartRemoteCall( + &storage::mojom::ServiceWorkerStorageControl::FindRegistrationForScope, + base::BindRepeating(&ServiceWorkerRegistry::DidFindRegistrationForScope, + weak_factory_.GetWeakPtr(), base::Passed(&callback)), + scope); } void ServiceWorkerRegistry::FindRegistrationForId( @@ -281,10 +290,12 @@ const url::Origin& origin, GetRegistrationsCallback callback) { DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId()); - GetRemoteStorageControl()->GetRegistrationsForOrigin( - origin, - base::BindOnce(&ServiceWorkerRegistry::DidGetRegistrationsForOrigin, - weak_factory_.GetWeakPtr(), std::move(callback), origin)); + CreateInvokerAndStartRemoteCall( + &storage::mojom::ServiceWorkerStorageControl::GetRegistrationsForOrigin, + base::BindRepeating(&ServiceWorkerRegistry::DidGetRegistrationsForOrigin, + weak_factory_.GetWeakPtr(), base::Passed(&callback), + origin), + origin); } void ServiceWorkerRegistry::GetStorageUsageForOrigin( @@ -301,9 +312,11 @@ void ServiceWorkerRegistry::GetAllRegistrationsInfos( GetRegistrationsInfosCallback callback) { DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId()); - GetRemoteStorageControl()->GetAllRegistrationsDeprecated( - base::BindOnce(&ServiceWorkerRegistry::DidGetAllRegistrations, - weak_factory_.GetWeakPtr(), std::move(callback))); + CreateInvokerAndStartRemoteCall( + &storage::mojom::ServiceWorkerStorageControl:: + GetAllRegistrationsDeprecated, + base::BindRepeating(&ServiceWorkerRegistry::DidGetAllRegistrations, + weak_factory_.GetWeakPtr(), base::Passed(&callback))); } ServiceWorkerRegistration* ServiceWorkerRegistry::GetUninstallingRegistration( @@ -422,11 +435,12 @@ DCHECK(!registration->is_deleted()) << "attempt to delete a registration twice"; - GetRemoteStorageControl()->DeleteRegistration( - registration->id(), origin, - base::BindOnce(&ServiceWorkerRegistry::DidDeleteRegistration, - weak_factory_.GetWeakPtr(), registration->id(), origin, - std::move(callback))); + CreateInvokerAndStartRemoteCall( + &storage::mojom::ServiceWorkerStorageControl::DeleteRegistration, + base::BindRepeating(&ServiceWorkerRegistry::DidDeleteRegistration, + weak_factory_.GetWeakPtr(), registration->id(), + origin, base::Passed(&callback)), + registration->id(), origin); DCHECK(!base::Contains(uninstalling_registrations_, registration->id())); uninstalling_registrations_[registration->id()] = registration; @@ -470,10 +484,11 @@ const GURL& origin, StatusCallback callback) { DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId()); - GetRemoteStorageControl()->UpdateToActiveState( - registration_id, origin, - base::BindOnce(&ServiceWorkerRegistry::DidUpdateRegistration, - weak_factory_.GetWeakPtr(), std::move(callback))); + CreateInvokerAndStartRemoteCall( + &storage::mojom::ServiceWorkerStorageControl::UpdateToActiveState, + base::BindRepeating(&ServiceWorkerRegistry::DidUpdateRegistration, + weak_factory_.GetWeakPtr(), base::Passed(&callback)), + static_cast<const int64_t>(registration_id), origin); } void ServiceWorkerRegistry::UpdateLastUpdateCheckTime( @@ -482,10 +497,12 @@ base::Time last_update_check_time, StatusCallback callback) { DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId()); - GetRemoteStorageControl()->UpdateLastUpdateCheckTime( - registration_id, origin, last_update_check_time, - base::BindOnce(&ServiceWorkerRegistry::DidUpdateRegistration, - weak_factory_.GetWeakPtr(), std::move(callback))); + CreateInvokerAndStartRemoteCall( + &storage::mojom::ServiceWorkerStorageControl::UpdateLastUpdateCheckTime, + base::BindRepeating(&ServiceWorkerRegistry::DidUpdateRegistration, + weak_factory_.GetWeakPtr(), base::Passed(&callback)), + static_cast<const int64_t>(registration_id), origin, + static_cast<const base::Time&>(last_update_check_time)); } void ServiceWorkerRegistry::UpdateNavigationPreloadEnabled( @@ -494,10 +511,13 @@ bool enable, StatusCallback callback) { DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId()); - GetRemoteStorageControl()->UpdateNavigationPreloadEnabled( - registration_id, origin, enable, - base::BindOnce(&ServiceWorkerRegistry::DidUpdateRegistration, - weak_factory_.GetWeakPtr(), std::move(callback))); + CreateInvokerAndStartRemoteCall( + &storage::mojom::ServiceWorkerStorageControl:: + UpdateNavigationPreloadEnabled, + base::BindRepeating(&ServiceWorkerRegistry::DidUpdateRegistration, + weak_factory_.GetWeakPtr(), base::Passed(&callback)), + static_cast<const int64_t>(registration_id), origin, + static_cast<const bool>(enable)); } void ServiceWorkerRegistry::UpdateNavigationPreloadHeader( @@ -506,10 +526,12 @@ const std::string& value, StatusCallback callback) { DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId()); - GetRemoteStorageControl()->UpdateNavigationPreloadHeader( - registration_id, origin, value, - base::BindOnce(&ServiceWorkerRegistry::DidUpdateRegistration, - weak_factory_.GetWeakPtr(), std::move(callback))); + CreateInvokerAndStartRemoteCall( + &storage::mojom::ServiceWorkerStorageControl:: + UpdateNavigationPreloadHeader, + base::BindRepeating(&ServiceWorkerRegistry::DidUpdateRegistration, + weak_factory_.GetWeakPtr(), base::Passed(&callback)), + static_cast<const int64_t>(registration_id), origin, value); } void ServiceWorkerRegistry::StoreUncommittedResourceId(int64_t resource_id, @@ -843,9 +865,11 @@ const GURL& client_url, int64_t trace_event_id, FindRegistrationCallback callback, + uint64_t call_id, storage::mojom::ServiceWorkerDatabaseStatus database_status, storage::mojom::ServiceWorkerFindRegistrationResultPtr result) { DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId()); + FinishRemoteCall(call_id); if (database_status != storage::mojom::ServiceWorkerDatabaseStatus::kOk && database_status != storage::mojom::ServiceWorkerDatabaseStatus::kErrorNotFound) { @@ -895,9 +919,11 @@ void ServiceWorkerRegistry::DidFindRegistrationForScope( FindRegistrationCallback callback, + uint64_t call_id, storage::mojom::ServiceWorkerDatabaseStatus database_status, storage::mojom::ServiceWorkerFindRegistrationResultPtr result) { DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId()); + FinishRemoteCall(call_id); if (database_status != storage::mojom::ServiceWorkerDatabaseStatus::kOk && database_status != storage::mojom::ServiceWorkerDatabaseStatus::kErrorNotFound) { @@ -962,10 +988,12 @@ void ServiceWorkerRegistry::DidGetRegistrationsForOrigin( GetRegistrationsCallback callback, const url::Origin& origin_filter, + uint64_t call_id, storage::mojom::ServiceWorkerDatabaseStatus database_status, std::vector<storage::mojom::ServiceWorkerFindRegistrationResultPtr> entries) { DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId()); + FinishRemoteCall(call_id); blink::ServiceWorkerStatusCode status = DatabaseStatusToStatusCode(database_status); @@ -1004,9 +1032,11 @@ void ServiceWorkerRegistry::DidGetAllRegistrations( GetRegistrationsInfosCallback callback, + uint64_t call_id, storage::mojom::ServiceWorkerDatabaseStatus database_status, RegistrationList registration_data_list) { DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId()); + FinishRemoteCall(call_id); blink::ServiceWorkerStatusCode status = DatabaseStatusToStatusCode(database_status); @@ -1147,9 +1177,11 @@ int64_t registration_id, const GURL& origin, StatusCallback callback, + uint64_t call_id, storage::mojom::ServiceWorkerDatabaseStatus database_status, ServiceWorkerStorage::OriginState origin_state) { DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId()); + FinishRemoteCall(call_id); blink::ServiceWorkerStatusCode status = DatabaseStatusToStatusCode(database_status); @@ -1177,8 +1209,10 @@ void ServiceWorkerRegistry::DidUpdateRegistration( StatusCallback callback, + uint64_t call_id, storage::mojom::ServiceWorkerDatabaseStatus status) { DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId()); + FinishRemoteCall(call_id); if (status != storage::mojom::ServiceWorkerDatabaseStatus::kOk && status != storage::mojom::ServiceWorkerDatabaseStatus::kErrorNotFound) { ScheduleDeleteAndStartOver(); @@ -1264,8 +1298,10 @@ void ServiceWorkerRegistry::DidGetNewRegistrationId( blink::mojom::ServiceWorkerRegistrationOptions options, NewRegistrationCallback callback, + uint64_t call_id, int64_t registration_id) { DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId()); + FinishRemoteCall(call_id); if (registration_id == blink::mojom::kInvalidServiceWorkerRegistrationId) { std::move(callback).Run(nullptr); return; @@ -1279,10 +1315,12 @@ const GURL& script_url, blink::mojom::ScriptType script_type, NewVersionCallback callback, + uint64_t call_id, int64_t version_id, mojo::PendingRemote<storage::mojom::ServiceWorkerLiveVersionRef> version_reference) { DCHECK_CURRENTLY_ON(ServiceWorkerContext::GetCoreThreadId()); + FinishRemoteCall(call_id); if (version_id == blink::mojom::kInvalidServiceWorkerVersionId) { std::move(callback).Run(nullptr); return;
diff --git a/content/browser/service_worker/service_worker_registry.h b/content/browser/service_worker/service_worker_registry.h index 4dbdeec..2b2a37f 100644 --- a/content/browser/service_worker/service_worker_registry.h +++ b/content/browser/service_worker/service_worker_registry.h
@@ -281,10 +281,12 @@ const GURL& client_url, int64_t trace_event_id, FindRegistrationCallback callback, + uint64_t call_id, storage::mojom::ServiceWorkerDatabaseStatus database_status, storage::mojom::ServiceWorkerFindRegistrationResultPtr result); void DidFindRegistrationForScope( FindRegistrationCallback callback, + uint64_t call_id, storage::mojom::ServiceWorkerDatabaseStatus database_status, storage::mojom::ServiceWorkerFindRegistrationResultPtr result); void DidFindRegistrationForId( @@ -296,11 +298,13 @@ void DidGetRegistrationsForOrigin( GetRegistrationsCallback callback, const url::Origin& origin_filter, + uint64_t call_id, storage::mojom::ServiceWorkerDatabaseStatus database_status, std::vector<storage::mojom::ServiceWorkerFindRegistrationResultPtr> entries); void DidGetAllRegistrations( GetRegistrationsInfosCallback callback, + uint64_t call_id, storage::mojom::ServiceWorkerDatabaseStatus database_status, RegistrationList registration_data_list); void DidGetStorageUsageForOrigin( @@ -320,11 +324,13 @@ int64_t registration_id, const GURL& origin, StatusCallback callback, + uint64_t call_id, storage::mojom::ServiceWorkerDatabaseStatus database_status, ServiceWorkerStorage::OriginState origin_state); void DidUpdateRegistration( StatusCallback callback, + uint64_t call_id, storage::mojom::ServiceWorkerDatabaseStatus status); void DidWriteUncommittedResourceIds( storage::mojom::ServiceWorkerDatabaseStatus status); @@ -349,12 +355,14 @@ void DidGetNewRegistrationId( blink::mojom::ServiceWorkerRegistrationOptions options, NewRegistrationCallback callback, + uint64_t call_id, int64_t registration_id); void DidGetNewVersionId( scoped_refptr<ServiceWorkerRegistration> registration, const GURL& script_url, blink::mojom::ScriptType script_type, NewVersionCallback callback, + uint64_t call_id, int64_t version_id, mojo::PendingRemote<storage::mojom::ServiceWorkerLiveVersionRef> version_reference);
diff --git a/content/browser/service_worker/service_worker_registry_unittest.cc b/content/browser/service_worker/service_worker_registry_unittest.cc index 951cf42..982a0e4 100644 --- a/content/browser/service_worker/service_worker_registry_unittest.cc +++ b/content/browser/service_worker/service_worker_registry_unittest.cc
@@ -1290,6 +1290,7 @@ CreateServiceWorkerRegistrationAndVersion(context(), kScope2, kScriptUrl2, /*resource_id=*/2); + // Store two registrations. Restart the remote storage several times. { registry()->SimulateStorageRestartForTesting(); @@ -1311,10 +1312,184 @@ loop2.Quit(); })); + EXPECT_EQ(inflight_call_count(), 2U); registry()->SimulateStorageRestartForTesting(); loop1.Run(); loop2.Run(); + EXPECT_EQ(inflight_call_count(), 0U); + } + + // Finding registrations stored in the previous block. + { + base::RunLoop loop1; + registry()->FindRegistrationForClientUrl( + kScope1, + base::BindLambdaForTesting( + [&](blink::ServiceWorkerStatusCode status, + scoped_refptr<ServiceWorkerRegistration> found_registration) { + EXPECT_EQ(status, blink::ServiceWorkerStatusCode::kOk); + EXPECT_EQ(found_registration, registration1); + loop1.Quit(); + })); + + base::RunLoop loop2; + registry()->FindRegistrationForScope( + GURL("http://www.example.com/not-in-scope"), + base::BindLambdaForTesting( + [&](blink::ServiceWorkerStatusCode status, + scoped_refptr<ServiceWorkerRegistration> found_registration) { + EXPECT_EQ(status, blink::ServiceWorkerStatusCode::kErrorNotFound); + EXPECT_EQ(found_registration, nullptr); + loop2.Quit(); + })); + + EXPECT_EQ(inflight_call_count(), 2U); + registry()->SimulateStorageRestartForTesting(); + + // TODO(crbug.com/1133143): Add test for FindRegistrationForId(). + + loop1.Run(); + loop2.Run(); + EXPECT_EQ(inflight_call_count(), 0U); + } + + // Get both of the registrations by these APIs. + { + base::RunLoop loop1; + registry()->GetRegistrationsForOrigin( + kOrigin1, + base::BindLambdaForTesting( + [&](blink::ServiceWorkerStatusCode status, + const std::vector<scoped_refptr<ServiceWorkerRegistration>>& + registrations) { + EXPECT_EQ(status, blink::ServiceWorkerStatusCode::kOk); + EXPECT_EQ(registrations.size(), 2U); + loop1.Quit(); + })); + + base::RunLoop loop2; + registry()->GetAllRegistrationsInfos(base::BindLambdaForTesting( + [&](blink::ServiceWorkerStatusCode status, + const std::vector<ServiceWorkerRegistrationInfo>& registrations) { + EXPECT_EQ(status, blink::ServiceWorkerStatusCode::kOk); + EXPECT_EQ(registrations.size(), 2U); + loop2.Quit(); + })); + + EXPECT_EQ(inflight_call_count(), 2U); + registry()->SimulateStorageRestartForTesting(); + + loop1.Run(); + loop2.Run(); + EXPECT_EQ(inflight_call_count(), 0U); + } + + // Delete `registrations` from the storage. + { + base::RunLoop loop; + registry()->DeleteRegistration( + registration2, kScope2.GetOrigin(), + base::BindLambdaForTesting([&](blink::ServiceWorkerStatusCode status) { + EXPECT_EQ(status, blink::ServiceWorkerStatusCode::kOk); + loop.Quit(); + })); + + EXPECT_EQ(inflight_call_count(), 1U); + registry()->SimulateStorageRestartForTesting(); + + loop.Run(); + EXPECT_EQ(inflight_call_count(), 0U); + } + + // Update fields of `registration1` in the storage. + { + base::RunLoop loop1; + registry()->UpdateToActiveState( + registration1->id(), kScope1.GetOrigin(), + base::BindLambdaForTesting([&](blink::ServiceWorkerStatusCode status) { + EXPECT_EQ(status, blink::ServiceWorkerStatusCode::kOk); + loop1.Quit(); + })); + + base::RunLoop loop2; + registry()->UpdateLastUpdateCheckTime( + registration1->id(), kScope1.GetOrigin(), base::Time::Now(), + base::BindLambdaForTesting([&](blink::ServiceWorkerStatusCode status) { + EXPECT_EQ(status, blink::ServiceWorkerStatusCode::kOk); + loop2.Quit(); + })); + + base::RunLoop loop3; + registry()->UpdateNavigationPreloadEnabled( + registration1->id(), kScope1.GetOrigin(), /*enable=*/true, + base::BindLambdaForTesting([&](blink::ServiceWorkerStatusCode status) { + EXPECT_EQ(status, blink::ServiceWorkerStatusCode::kOk); + loop3.Quit(); + })); + + base::RunLoop loop4; + registry()->UpdateNavigationPreloadHeader( + registration1->id(), kScope1.GetOrigin(), "header", + base::BindLambdaForTesting([&](blink::ServiceWorkerStatusCode status) { + EXPECT_EQ(status, blink::ServiceWorkerStatusCode::kOk); + loop4.Quit(); + })); + + EXPECT_EQ(inflight_call_count(), 4U); + registry()->SimulateStorageRestartForTesting(); + + loop1.Run(); + loop2.Run(); + loop3.Run(); + loop4.Run(); + EXPECT_EQ(inflight_call_count(), 0U); + } +} + +TEST_F(ServiceWorkerRegistryTest, + RetryInflightCalls_CreateNewRegistrationAndVersion) { + const GURL kScope("http://www.example.com/scope/"); + const GURL kScriptUrl("http://www.example.com/script.js"); + + scoped_refptr<ServiceWorkerRegistration> registration; + + { + blink::mojom::ServiceWorkerRegistrationOptions options; + options.scope = kScope; + base::RunLoop loop; + registry()->CreateNewRegistration( + std::move(options), + base::BindLambdaForTesting( + [&](scoped_refptr<ServiceWorkerRegistration> new_registration) { + EXPECT_EQ(new_registration->scope(), kScope); + registration = new_registration; + loop.Quit(); + })); + + registry()->SimulateStorageRestartForTesting(); + EXPECT_EQ(inflight_call_count(), 1U); + + loop.Run(); + EXPECT_EQ(inflight_call_count(), 0U); + } + + { + base::RunLoop loop; + registry()->CreateNewVersion( + registration, kScriptUrl, blink::mojom::ScriptType::kClassic, + base::BindLambdaForTesting( + [&](scoped_refptr<ServiceWorkerVersion> new_version) { + EXPECT_EQ(new_version->script_url(), kScriptUrl); + EXPECT_EQ(new_version->registration_id(), registration->id()); + loop.Quit(); + })); + + registry()->SimulateStorageRestartForTesting(); + EXPECT_EQ(inflight_call_count(), 1U); + + loop.Run(); + EXPECT_EQ(inflight_call_count(), 0U); } }
diff --git a/content/browser/site_per_process_browsertest.cc b/content/browser/site_per_process_browsertest.cc index 5f9e1190..e3f0f5cb 100644 --- a/content/browser/site_per_process_browsertest.cc +++ b/content/browser/site_per_process_browsertest.cc
@@ -9023,6 +9023,19 @@ } IN_PROC_BROWSER_TEST_F(SitePerProcessFeaturePolicyBrowserTest, + HeaderPolicyOnXSLTNavigation) { + GURL url(embedded_test_server()->GetURL("a.com", "/permissions-policy.xml")); + + EXPECT_TRUE(NavigateToURL(shell(), url)); + + FrameTreeNode* root = web_contents()->GetFrameTree()->root(); + EXPECT_EQ(CreateParsedFeaturePolicy( + {blink::mojom::FeaturePolicyFeature::kGeolocation}, + {url.GetOrigin()}), + root->current_replication_state().feature_policy_header); +} + +IN_PROC_BROWSER_TEST_F(SitePerProcessFeaturePolicyBrowserTest, TestPolicyReplicationOnSameOriginNavigation) { GURL start_url( embedded_test_server()->GetURL("a.com", "/feature-policy1.html"));
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc index 718f4c2..66018d8 100644 --- a/content/browser/web_contents/web_contents_impl.cc +++ b/content/browser/web_contents/web_contents_impl.cc
@@ -7024,6 +7024,30 @@ delegate_->SetContentsBounds(this, bounds); } +std::vector<RenderFrameHostImpl*> +WebContentsImpl::GetActiveTopLevelDocumentsInBrowsingContextGroup( + RenderFrameHostImpl* render_frame_host) { + std::vector<RenderFrameHostImpl*> out; + for (WebContentsImpl* web_contents : GetAllWebContents()) { + RenderFrameHostImpl* other_render_frame_host = web_contents->GetMainFrame(); + + // Filters out inactive documents. + if (other_render_frame_host->lifecycle_state() != + RenderFrameHostImpl::LifecycleState::kActive) { + continue; + } + + // Filters out documents from a different browsing context group. + if (!render_frame_host->GetSiteInstance()->IsRelatedSiteInstance( + other_render_frame_host->GetSiteInstance())) { + continue; + } + + out.push_back(other_render_frame_host); + } + return out; +} + void WebContentsImpl::DidStartLoading(FrameTreeNode* frame_tree_node, bool to_different_document) { OPTIONAL_TRACE_EVENT1("content", "WebContentsImpl::DidStartLoading",
diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h index 03778c5..3db90d0 100644 --- a/content/browser/web_contents/web_contents_impl.h +++ b/content/browser/web_contents/web_contents_impl.h
@@ -765,6 +765,9 @@ RenderFrameHostImpl::LifecycleState old_state, RenderFrameHostImpl::LifecycleState new_state) override; void SetWindowRect(const gfx::Rect& new_bounds) override; + std::vector<RenderFrameHostImpl*> + GetActiveTopLevelDocumentsInBrowsingContextGroup( + RenderFrameHostImpl* render_frame_host) override; // RenderViewHostDelegate ---------------------------------------------------- RenderViewHostDelegateView* GetDelegateView() override;
diff --git a/content/test/data/permissions-policy.xml b/content/test/data/permissions-policy.xml new file mode 100644 index 0000000..cbf667f --- /dev/null +++ b/content/test/data/permissions-policy.xml
@@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="UTF-8"?> +<?xml-stylesheet href="permissions-policy.xslt" type="text/xsl"?> +<!-- This page has a 'Permissions-Policy' header. --> +<page> +</page>
diff --git a/content/test/data/permissions-policy.xml.mock-http-headers b/content/test/data/permissions-policy.xml.mock-http-headers new file mode 100644 index 0000000..a17e049 --- /dev/null +++ b/content/test/data/permissions-policy.xml.mock-http-headers
@@ -0,0 +1,2 @@ +HTTP/1.1 200 OK +Permissions-Policy: geolocation=self \ No newline at end of file
diff --git a/content/test/data/permissions-policy.xslt b/content/test/data/permissions-policy.xslt new file mode 100644 index 0000000..50c6e66c --- /dev/null +++ b/content/test/data/permissions-policy.xslt
@@ -0,0 +1,9 @@ +<?xml version="1.0"?> +<xsl:stylesheet version="1.0" + xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> + +<xsl:template match="page"> + <html></html> +</xsl:template> + +</xsl:stylesheet> \ No newline at end of file
diff --git a/content/test/gpu/gpu_tests/gpu_integration_test.py b/content/test/gpu/gpu_tests/gpu_integration_test.py index 7039af0..4823598 100644 --- a/content/test/gpu/gpu_tests/gpu_integration_test.py +++ b/content/test/gpu/gpu_tests/gpu_integration_test.py
@@ -22,6 +22,8 @@ _SUPPORTED_WIN_VERSIONS = ['win7', 'win10'] _SUPPORTED_WIN_VERSIONS_WITH_DIRECT_COMPOSITION = ['win10'] _SUPPORTED_WIN_GPU_VENDORS = [0x8086, 0x10de, 0x1002] +_SUPPORTED_WIN_AMD_GPUS = [0x6613, 0x699f, 0x7340] +_SUPPORTED_WIN_AMD_GPUS_WITH_NV12_OVERLAYS = [0x7340] _SUPPORTED_WIN_INTEL_GPUS = [0x5912, 0x3e92] _SUPPORTED_WIN_INTEL_GPUS_WITH_YUY2_OVERLAYS = [0x5912, 0x3e92] _SUPPORTED_WIN_INTEL_GPUS_WITH_NV12_OVERLAYS = [0x5912, 0x3e92] @@ -458,7 +460,11 @@ config['supports_overlays'] = True config['yuy2_overlay_support'] = 'SOFTWARE' config['nv12_overlay_support'] = 'SOFTWARE' - if gpu_vendor_id == 0x8086: + if gpu_vendor_id == 0x1002: + assert gpu_device_id in _SUPPORTED_WIN_AMD_GPUS + if gpu_device_id in _SUPPORTED_WIN_AMD_GPUS_WITH_NV12_OVERLAYS: + config['nv12_overlay_support'] = 'SCALING' + elif gpu_vendor_id == 0x8086: assert gpu_device_id in _SUPPORTED_WIN_INTEL_GPUS gpu_device_and_driver = ('%x-' + gpu.driver_version) % gpu_device_id if gpu_device_id in _SUPPORTED_WIN_INTEL_GPUS_WITH_YUY2_OVERLAYS:
diff --git a/content/test/gpu/gpu_tests/pixel_test_pages.py b/content/test/gpu/gpu_tests/pixel_test_pages.py index 2fd788522..fab3f804 100644 --- a/content/test/gpu/gpu_tests/pixel_test_pages.py +++ b/content/test/gpu/gpu_tests/pixel_test_pages.py
@@ -72,7 +72,7 @@ self.restart_browser_after_test = restart_browser_after_test # These are used to pass additional arguments to the test harness. # VideoPathTraceTest and OverlayModeTest support the following boolean - # arguments: pixel_format, zero_copy, no_overlay, and presentation_mode. + # arguments: pixel_format, zero_copy, no_overlay and video_is_rotated. self.other_args = other_args # This allows a newly added test to be exempted from failures for a # (hopefully) short period after being added. This is so that any slightly @@ -764,21 +764,21 @@ '_DirectComposition_Video_MP4_FourColors_Rot_90', test_rect=[0, 0, 270, 240], browser_args=browser_args, - other_args={'presentation_mode': 'COMPOSED'}, + other_args={'video_is_rotated': True}, matching_algorithm=strict_dc_sobel_algorithm), PixelTestPage('pixel_video_mp4_four_colors_rot_180.html', base_name + '_DirectComposition_Video_MP4_FourColors_Rot_180', test_rect=[0, 0, 240, 135], browser_args=browser_args, - other_args={'presentation_mode': 'COMPOSED'}, + other_args={'video_is_rotated': True}, matching_algorithm=strict_dc_sobel_algorithm), PixelTestPage('pixel_video_mp4_four_colors_rot_270.html', base_name + '_DirectComposition_Video_MP4_FourColors_Rot_270', test_rect=[0, 0, 270, 240], browser_args=browser_args, - other_args={'presentation_mode': 'COMPOSED'}, + other_args={'video_is_rotated': True}, matching_algorithm=strict_dc_sobel_algorithm), PixelTestPage('pixel_video_vp9.html', base_name + '_DirectComposition_Video_VP9',
diff --git a/content/test/gpu/gpu_tests/test_expectations/context_lost_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/context_lost_expectations.txt index dbb3dd1d..97b8f51 100644 --- a/content/test/gpu/gpu_tests/test_expectations/context_lost_expectations.txt +++ b/content/test/gpu/gpu_tests/test_expectations/context_lost_expectations.txt
@@ -21,7 +21,7 @@ # debug debug-x64 # release release-x64 ] # GPU -# tags: [ amd amd-0x6613 amd-0x679e amd-0x6821 amd-0x699f +# tags: [ amd amd-0x6613 amd-0x679e amd-0x6821 amd-0x699f amd-0x7340 # apple apple-apple-a12z # arm # google google-0xffff
diff --git a/content/test/gpu/gpu_tests/test_expectations/depth_capture_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/depth_capture_expectations.txt index 2eb5a5a1..7da651cbc 100644 --- a/content/test/gpu/gpu_tests/test_expectations/depth_capture_expectations.txt +++ b/content/test/gpu/gpu_tests/test_expectations/depth_capture_expectations.txt
@@ -21,7 +21,7 @@ # debug debug-x64 # release release-x64 ] # GPU -# tags: [ amd amd-0x6613 amd-0x679e amd-0x6821 amd-0x699f +# tags: [ amd amd-0x6613 amd-0x679e amd-0x6821 amd-0x699f amd-0x7340 # apple apple-apple-a12z # arm # google google-0xffff
diff --git a/content/test/gpu/gpu_tests/test_expectations/gpu_process_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/gpu_process_expectations.txt index 43a39a16..a18abf2e 100644 --- a/content/test/gpu/gpu_tests/test_expectations/gpu_process_expectations.txt +++ b/content/test/gpu/gpu_tests/test_expectations/gpu_process_expectations.txt
@@ -21,7 +21,7 @@ # debug debug-x64 # release release-x64 ] # GPU -# tags: [ amd amd-0x6613 amd-0x679e amd-0x6821 amd-0x699f +# tags: [ amd amd-0x6613 amd-0x679e amd-0x6821 amd-0x699f amd-0x7340 # apple apple-apple-a12z # arm # google google-0xffff
diff --git a/content/test/gpu/gpu_tests/test_expectations/hardware_accelerated_feature_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/hardware_accelerated_feature_expectations.txt index 60d1a298..84505ac 100644 --- a/content/test/gpu/gpu_tests/test_expectations/hardware_accelerated_feature_expectations.txt +++ b/content/test/gpu/gpu_tests/test_expectations/hardware_accelerated_feature_expectations.txt
@@ -21,7 +21,7 @@ # debug debug-x64 # release release-x64 ] # GPU -# tags: [ amd amd-0x6613 amd-0x679e amd-0x6821 amd-0x699f +# tags: [ amd amd-0x6613 amd-0x679e amd-0x6821 amd-0x699f amd-0x7340 # apple apple-apple-a12z # arm # google google-0xffff
diff --git a/content/test/gpu/gpu_tests/test_expectations/info_collection_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/info_collection_expectations.txt index 0d839c0..cd0863e 100644 --- a/content/test/gpu/gpu_tests/test_expectations/info_collection_expectations.txt +++ b/content/test/gpu/gpu_tests/test_expectations/info_collection_expectations.txt
@@ -21,7 +21,7 @@ # debug debug-x64 # release release-x64 ] # GPU -# tags: [ amd amd-0x6613 amd-0x679e amd-0x6821 amd-0x699f +# tags: [ amd amd-0x6613 amd-0x679e amd-0x6821 amd-0x699f amd-0x7340 # apple apple-apple-a12z # arm # google google-0xffff
diff --git a/content/test/gpu/gpu_tests/test_expectations/maps_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/maps_expectations.txt index c95443e..1cbc0c8 100644 --- a/content/test/gpu/gpu_tests/test_expectations/maps_expectations.txt +++ b/content/test/gpu/gpu_tests/test_expectations/maps_expectations.txt
@@ -21,7 +21,7 @@ # debug debug-x64 # release release-x64 ] # GPU -# tags: [ amd amd-0x6613 amd-0x679e amd-0x6821 amd-0x699f +# tags: [ amd amd-0x6613 amd-0x679e amd-0x6821 amd-0x699f amd-0x7340 # apple apple-apple-a12z # arm # google google-0xffff
diff --git a/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt index 10647a7..d1623f1 100644 --- a/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt +++ b/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt
@@ -21,7 +21,7 @@ # debug debug-x64 # release release-x64 ] # GPU -# tags: [ amd amd-0x6613 amd-0x679e amd-0x6821 amd-0x699f +# tags: [ amd amd-0x6613 amd-0x679e amd-0x6821 amd-0x699f amd-0x7340 # apple apple-apple-a12z # arm # google google-0xffff @@ -435,3 +435,7 @@ crbug.com/1129879 [ android ] Pixel_Video_Media_Stream_Incompatible_Stride [ Skip ] crbug.com/1129879 [ chromeos ] Pixel_Video_Media_Stream_Incompatible_Stride [ Skip ] crbug.com/1129879 [ fuchsia ] Pixel_Video_Media_Stream_Incompatible_Stride [ Skip ] + +# Produce incorrect image on Win10 AMD RX 5500 XT +crbug.com/1151797 [ win10 amd-0x7340 skia-renderer-gl ] Pixel_DirectComposition_Video_VP9_YUY2 [ Failure ] +crbug.com/1151797 [ win10 amd-0x7340 skia-renderer-gl ] Pixel_DirectComposition_Video_VP9_BGRA [ Failure ]
diff --git a/content/test/gpu/gpu_tests/test_expectations/power_measurement_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/power_measurement_expectations.txt index fea271bc..d0cd708 100644 --- a/content/test/gpu/gpu_tests/test_expectations/power_measurement_expectations.txt +++ b/content/test/gpu/gpu_tests/test_expectations/power_measurement_expectations.txt
@@ -21,7 +21,7 @@ # debug debug-x64 # release release-x64 ] # GPU -# tags: [ amd amd-0x6613 amd-0x679e amd-0x6821 amd-0x699f +# tags: [ amd amd-0x6613 amd-0x679e amd-0x6821 amd-0x699f amd-0x7340 # apple apple-apple-a12z # arm # google google-0xffff
diff --git a/content/test/gpu/gpu_tests/test_expectations/screenshot_sync_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/screenshot_sync_expectations.txt index 06e0d5c..9ac4cbc1 100644 --- a/content/test/gpu/gpu_tests/test_expectations/screenshot_sync_expectations.txt +++ b/content/test/gpu/gpu_tests/test_expectations/screenshot_sync_expectations.txt
@@ -21,7 +21,7 @@ # debug debug-x64 # release release-x64 ] # GPU -# tags: [ amd amd-0x6613 amd-0x679e amd-0x6821 amd-0x699f +# tags: [ amd amd-0x6613 amd-0x679e amd-0x6821 amd-0x699f amd-0x7340 # apple apple-apple-a12z # arm # google google-0xffff
diff --git a/content/test/gpu/gpu_tests/test_expectations/trace_test_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/trace_test_expectations.txt index 8d4debd..3588d61 100644 --- a/content/test/gpu/gpu_tests/test_expectations/trace_test_expectations.txt +++ b/content/test/gpu/gpu_tests/test_expectations/trace_test_expectations.txt
@@ -21,7 +21,7 @@ # debug debug-x64 # release release-x64 ] # GPU -# tags: [ amd amd-0x6613 amd-0x679e amd-0x6821 amd-0x699f +# tags: [ amd amd-0x6613 amd-0x679e amd-0x6821 amd-0x699f amd-0x7340 # apple apple-apple-a12z # arm # google google-0xffff @@ -185,3 +185,6 @@ # YUY2 swap chains don't work on AMD. crbug.com/1132381 [ win amd-0x699f ] VideoPathTraceTest_DirectComposition_Video_MP4_YUY2 [ Failure ] crbug.com/1132381 [ win amd-0x699f ] VideoPathTraceTest_DirectComposition_Video_VP9_YUY2 [ Failure ] +# Failed to create YUY2 swap chain on Win10 AMD RX 5500 XT +crbug.com/1151767 [ win10 amd-0x7340 ] VideoPathTraceTest_DirectComposition_Video_MP4_YUY2 [ Failure ] +crbug.com/1151767 [ win10 amd-0x7340 ] VideoPathTraceTest_DirectComposition_Video_VP9_YUY2 [ Failure ]
diff --git a/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt index 1850c83..4c6b151 100644 --- a/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt +++ b/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt
@@ -21,7 +21,7 @@ # debug debug-x64 # release release-x64 ] # GPU -# tags: [ amd amd-0x6613 amd-0x679e amd-0x6821 amd-0x699f +# tags: [ amd amd-0x6613 amd-0x679e amd-0x6821 amd-0x699f amd-0x7340 # apple apple-apple-a12z # arm # google google-0xffff @@ -336,6 +336,18 @@ # Failing on AMD RX 550 crbug.com/angleproject/3354 [ win amd-0x699f ] deqp/functional/gles3/fborender/shared_colorbuffer_02.html [ Skip ] +# Failing on AMD RX 5500 XT +crbug.com/1152597 [ win amd-0x7340 angle-d3d11 ] conformance/renderbuffers/framebuffer-state-restoration.html [ Failure ] +crbug.com/1152599 [ win amd-0x7340 angle-d3d11 ] conformance/rendering/polygon-offset.html [ Failure ] +crbug.com/1152602 [ win amd-0x7340 angle-d3d11 ] conformance/canvas/drawingbuffer-static-canvas-test.html [ RetryOnFailure ] +crbug.com/1152603 [ win amd-0x7340 angle-d3d11 ] conformance2/renderbuffers/multisampled-depth-renderbuffer-initialization.html [ Failure ] +crbug.com/1152606 [ win amd-0x7340 angle-d3d11 ] deqp/functional/gles3/fboinvalidate/* [ Failure ] +crbug.com/1152606 [ win amd-0x7340 angle-d3d11 ] deqp/functional/gles3/fbomultisample.2_samples.html [ Failure ] +crbug.com/1152606 [ win amd-0x7340 angle-d3d11 ] deqp/functional/gles3/fborender/shared_colorbuffer_01.html [ Failure ] +crbug.com/1152606 [ win amd-0x7340 angle-d3d11 ] deqp/functional/gles3/fborender/shared_colorbuffer_02.html [ Failure ] +crbug.com/1152606 [ win amd-0x7340 angle-d3d11 ] deqp/functional/gles3/fragdepth.html [ Failure ] +crbug.com/1152606 [ win amd-0x7340 angle-d3d11 ] deqp/functional/gles3/framebufferblit/depth_stencil.html [ Failure ] + # Flaky on AMD Win7 crbug.com/989050 [ angle-d3d11 win7 amd ] conformance2/textures/misc/tex-unpack-params-imagedata.html [ RetryOnFailure ] @@ -891,6 +903,12 @@ crbug.com/809237 [ linux amd-0x6613 ] conformance2/uniforms/incompatible-texture-type-for-sampler.html [ Skip ] crbug.com/1018028 [ linux amd-0x6613 ] conformance/rendering/bind-framebuffer-flush-bug.html [ Failure ] +# Linux AMD RX 5500 XT +crbug.com/1147232 [ linux amd-0x7340 no-passthrough ] conformance/textures/misc/texture-size-limit.html [ Skip ] +crbug.com/1152588 [ linux amd-0x7340 ] conformance2/rendering/multisampling-fragment-evaluation.html [ Failure ] +crbug.com/1152590 [ linux amd-0x7340 no-passthrough ] conformance2/state/gl-get-calls.html [ Failure ] +crbug.com/1152590 [ linux amd-0x7340 no-passthrough ] deqp/functional/gles3/integerstatequery.html [ Failure ] + #################### # Android failures # ####################
diff --git a/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt index 01c413b..6e4f8cb 100644 --- a/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt +++ b/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt
@@ -21,7 +21,7 @@ # debug debug-x64 # release release-x64 ] # GPU -# tags: [ amd amd-0x6613 amd-0x679e amd-0x6821 amd-0x699f +# tags: [ amd amd-0x6613 amd-0x679e amd-0x6821 amd-0x699f amd-0x7340 # apple apple-apple-a12z # arm # google google-0xffff @@ -236,7 +236,9 @@ crbug.com/979444 [ chromeos ] conformance/textures/misc/texture-corner-case-videos.html [ RetryOnFailure ] crbug.com/979444 [ linux ] conformance/textures/misc/texture-corner-case-videos.html [ RetryOnFailure ] crbug.com/979444 [ mac no-passthrough no-asan ] conformance/textures/misc/texture-corner-case-videos.html [ RetryOnFailure ] -crbug.com/979444 [ win ] conformance/textures/misc/texture-corner-case-videos.html [ RetryOnFailure ] +crbug.com/979444 [ win intel ] conformance/textures/misc/texture-corner-case-videos.html [ RetryOnFailure ] +crbug.com/979444 [ win nvidia ] conformance/textures/misc/texture-corner-case-videos.html [ RetryOnFailure ] +crbug.com/979444 [ win7 amd ] conformance/textures/misc/texture-corner-case-videos.html [ RetryOnFailure ] crbug.com/979444 [ android ] conformance/textures/misc/texture-corner-case-videos.html [ RetryOnFailure ] # TODO(crbug.com/1097338): simplify this expectation once fuchsia case is fixed @@ -366,6 +368,15 @@ # Win / AMD D3D9 failures crbug.com/475095 [ win amd angle-d3d9 ] conformance/extensions/angle-instanced-arrays.html [ Failure ] +# Win / AMD RX 5500 XT failures +crbug.com/1152597 [ win amd-0x7340 angle-d3d11 ] conformance/renderbuffers/framebuffer-state-restoration.html [ Failure ] +crbug.com/1152599 [ win amd-0x7340 angle-d3d11 ] conformance/rendering/polygon-offset.html [ Failure ] +crbug.com/1152602 [ win amd-0x7340 angle-d3d11 ] conformance/canvas/drawingbuffer-static-canvas-test.html [ RetryOnFailure ] +crbug.com/1152619 [ win10 amd-0x7340 angle-d3d9 ] conformance/textures/misc/texture-corner-case-videos.html [ Failure ] +crbug.com/1152619 [ win amd-0x7340 angle-d3d9 ] conformance/textures/misc/texture-npot-video.html [ Failure ] +crbug.com/1152621 [ win amd-0x7340 angle-vulkan ] conformance/attribs/gl-vertexattribpointer-offsets.html [ Failure ] +crbug.com/1152623 [ win amd-0x7340 angle-vulkan ] conformance/extensions/webgl-draw-buffers.html [ Failure ] + # Win / D3D9 failures # Skipping these two tests because they're causing assertion failures. crbug.com/angleproject/896 [ win angle-d3d9 no-passthrough ] conformance/extensions/oes-texture-float-with-canvas.html [ Skip ] @@ -565,6 +576,9 @@ crbug.com/642822 [ linux amd ] conformance/rendering/clipping-wide-points.html [ Failure ] crbug.com/1018028 [ linux amd-0x6613 ] conformance/rendering/bind-framebuffer-flush-bug.html [ Failure ] +# Linux AMD RX 5500 XT +crbug.com/1147232 [ linux amd-0x7340 no-passthrough ] conformance/textures/misc/texture-size-limit.html [ Skip ] + # Linux passthrough AMD crbug.com/1143392 [ linux amd passthrough ] conformance/glsl/misc/shader-with-non-reserved-words.html [ Failure ] crbug.com/998498 [ linux amd passthrough ] conformance/textures/misc/tex-input-validation.html [ Failure ]
diff --git a/content/test/gpu/gpu_tests/trace_integration_test.py b/content/test/gpu/gpu_tests/trace_integration_test.py index 0318384..0f7926e 100644 --- a/content/test/gpu/gpu_tests/trace_integration_test.py +++ b/content/test/gpu/gpu_tests/trace_integration_test.py
@@ -88,6 +88,8 @@ _PRESENT_MAIN_SWAP_CHAIN_EVENT_NAME =\ 'DirectCompositionChildSurfaceWin::PresentSwapChain' +_SUPPORTED_WIN_AMD_GPUS_WITH_NV12_ROTATED_OVERLAYS = [0x7340] + class _TraceTestArguments(object): """Struct-like object for passing trace test arguments instead of dicts.""" @@ -285,7 +287,7 @@ expected.zero_copy = other_args.get('zero_copy', None) expected.pixel_format = other_args.get('pixel_format', None) expected.no_overlay = other_args.get('no_overlay', False) - expected.presentation_mode = other_args.get('presentation_mode', None) + video_is_rotated = other_args.get('video_is_rotated', False) if overlay_bot_config.get('supports_overlays', False): supports_hw_nv12_overlays = overlay_bot_config[ @@ -304,18 +306,25 @@ assert supports_sw_nv12_overlays expected.pixel_format = 'NV12' - if expected.presentation_mode is None: - if supports_hw_nv12_overlays or supports_hw_yuy2_overlays: - expected.presentation_mode = 'OVERLAY' - else: - expected.presentation_mode = 'COMPOSED' + gpu = self.browser.GetSystemInfo().gpu.devices[0] + supports_rotated_video_overlays = ( + gpu.vendor_id == 0x1002 and + gpu.device_id in _SUPPORTED_WIN_AMD_GPUS_WITH_NV12_ROTATED_OVERLAYS) + + if (((supports_hw_nv12_overlays and expected.pixel_format == 'NV12') + or supports_hw_yuy2_overlays) + and (not video_is_rotated or supports_rotated_video_overlays)): + expected.presentation_mode = 'OVERLAY' + else: + expected.presentation_mode = 'COMPOSED' if expected.zero_copy is None: # TODO(sunnyps): Check for overlay scaling support after making the same # change in SwapChainPresenter. expected.zero_copy = (expected.presentation_mode == 'OVERLAY' and expected.pixel_format == 'NV12' - and supports_hw_nv12_overlays) + and supports_hw_nv12_overlays + and not video_is_rotated) return expected
diff --git a/content/test/gpu/validate_tag_consistency.py b/content/test/gpu/validate_tag_consistency.py index b4ff2621..a3d028b 100755 --- a/content/test/gpu/validate_tag_consistency.py +++ b/content/test/gpu/validate_tag_consistency.py
@@ -32,7 +32,7 @@ # debug debug-x64 # release release-x64 ] # GPU -# tags: [ amd amd-0x6613 amd-0x679e amd-0x6821 amd-0x699f +# tags: [ amd amd-0x6613 amd-0x679e amd-0x6821 amd-0x699f amd-0x7340 # apple apple-apple-a12z # arm # google google-0xffff
diff --git a/docs/origin_trials_integration.md b/docs/origin_trials_integration.md index 2ca187f..f17efb9 100644 --- a/docs/origin_trials_integration.md +++ b/docs/origin_trials_integration.md
@@ -7,6 +7,11 @@ ## Code Changes +NOTE: You can land these code changes before requesting to run an origin trial. +These code changes make it possible to control a feature via an origin trial, +but don't require an origin trial to be approved. For more on the process, see +[Running an Origin Trial]. + ### Runtime Enabled Features First, you’ll need to configure [runtime\_enabled\_features.json5]. This is @@ -186,6 +191,14 @@ tools/origin_trials/generate_token.py http://localhost:8000 MyFeature ``` + There are additional flags to generate third-party tokens, set the expiry + date, and control other options. See the command help for details (`--help`). + For example, to generate a third-party token, with [user subset exclusion]: + + ``` + tools/origin_trials/generate_token.py --is-third-party --usage-restriction=subset http://localhost:8000 MyFeature + ``` + 2. Copy the token from the end of the output and use it in a `<meta>` tag or an `Origin-Trial` header as described in the [Developer Guide]. @@ -236,4 +249,5 @@ [css\_properties.json5]: /third_party/blink/renderer/core/css/css_properties.json5 [origin-trial-test-property]: https://chromium.googlesource.com/chromium/src/+/ff2ab8b89745602c8300322c2a0158e210178c7e/third_party/blink/renderer/core/css/css_properties.json5#2635 [CSSStyleDeclaration]: /third_party/blink/renderer/core/css/css_style_declaration.idl - +[Running an Origin Trial]: https://www.chromium.org/blink/origin-trials/running-an-origin-trial +[user subset exclusion]: https://docs.google.com/document/d/1xALH9W7rWmX0FpjudhDeS2TNTEOXuPn4Tlc9VmuPdHA/edit#heading=h.myaz1twlipw
diff --git a/gpu/command_buffer/service/shared_image_backing_gl_texture.cc b/gpu/command_buffer/service/shared_image_backing_gl_texture.cc index 354d494..e68d819 100644 --- a/gpu/command_buffer/service/shared_image_backing_gl_texture.cc +++ b/gpu/command_buffer/service/shared_image_backing_gl_texture.cc
@@ -253,8 +253,9 @@ return nullptr; } + const gfx::GpuMemoryBufferType handle_type = handle.type; GLenum target = - (handle.type == gfx::SHARED_MEMORY_BUFFER || + (handle_type == gfx::SHARED_MEMORY_BUFFER || !NativeBufferNeedsPlatformSpecificTextureTarget(buffer_format)) ? GL_TEXTURE_2D : gpu::GetPlatformSpecificTextureTarget(); @@ -279,7 +280,7 @@ texture_2d_support = (gpu::GetPlatformSpecificTextureTarget() == GL_TEXTURE_2D); #endif // defined(OS_MAC) - DCHECK(handle.type == gfx::SHARED_MEMORY_BUFFER || target != GL_TEXTURE_2D || + DCHECK(handle_type == gfx::SHARED_MEMORY_BUFFER || target != GL_TEXTURE_2D || texture_2d_support || image->ShouldBindOrCopy() == gl::GLImage::BIND); #endif // DCHECK_IS_ON() if (color_space.IsValid())
diff --git a/ios/chrome/app/startup/chrome_app_startup_parameters.mm b/ios/chrome/app/startup/chrome_app_startup_parameters.mm index 0f7e23a..8b9de6a 100644 --- a/ios/chrome/app/startup/chrome_app_startup_parameters.mm +++ b/ios/chrome/app/startup/chrome_app_startup_parameters.mm
@@ -556,7 +556,7 @@ if (![_declaredSourceApp length]) { if (self.completeURL.SchemeIs(url::kHttpScheme) || - self.completeURL.SchemeIs(url::kHttpScheme)) { + self.completeURL.SchemeIs(url::kHttpsScheme)) { // If Chrome is opened via the system default browser mechanism, the // action should be differentiated from the case where the source is // unknown.
diff --git a/ios/chrome/browser/link_to_text/BUILD.gn b/ios/chrome/browser/link_to_text/BUILD.gn index 1006f36..4f138b9c 100644 --- a/ios/chrome/browser/link_to_text/BUILD.gn +++ b/ios/chrome/browser/link_to_text/BUILD.gn
@@ -14,6 +14,7 @@ deps = [ ":internal", "//components/shared_highlighting/core/common", + "//components/ukm/ios:ukm_url_recorder", "//ios/chrome/browser/tabs", "//ios/web/public", "//ios/web/public/js_messaging",
diff --git a/ios/chrome/browser/link_to_text/link_to_text_response.h b/ios/chrome/browser/link_to_text/link_to_text_response.h index d752e79..400340b 100644 --- a/ios/chrome/browser/link_to_text/link_to_text_response.h +++ b/ios/chrome/browser/link_to_text/link_to_text_response.h
@@ -30,8 +30,8 @@ // Parses a serialized response stored in |value| into a LinkToTextResponse // instance. -+ (instancetype)createFromValue:(const base::Value*)value - webState:(web::WebState*)webState; ++ (instancetype)linkToTextResponseWithValue:(const base::Value*)value + webState:(web::WebState*)webState; // Response payload. Nil when an error occurred. @property(nonatomic, readonly) LinkToTextPayload* payload; @@ -42,6 +42,9 @@ base::Optional<shared_highlighting::LinkGenerationError> error; +// Source ID for the associated WebState. +@property(nonatomic, readonly) ukm::SourceId sourceID; + @end #endif // IOS_CHROME_BROWSER_LINK_TO_TEXT_LINK_TO_TEXT_RESPONSE_H_
diff --git a/ios/chrome/browser/link_to_text/link_to_text_response.mm b/ios/chrome/browser/link_to_text/link_to_text_response.mm index 6c336454..0c31be0 100644 --- a/ios/chrome/browser/link_to_text/link_to_text_response.mm +++ b/ios/chrome/browser/link_to_text/link_to_text_response.mm
@@ -8,6 +8,7 @@ #import "base/values.h" #import "components/shared_highlighting/core/common/text_fragment.h" #import "components/shared_highlighting/core/common/text_fragments_utils.h" +#import "components/ukm/ios/ukm_url_recorder.h" #import "ios/chrome/browser/link_to_text/link_to_text_payload.h" #import "ios/chrome/browser/link_to_text/link_to_text_utils.h" #import "ios/chrome/browser/tabs/tab_title_util.h" @@ -24,50 +25,72 @@ @interface LinkToTextResponse () -// Initializes an object with the given |payload| of the link generation -// request. -- (instancetype)initWithPayload:(LinkToTextPayload*)payload +// Initializes an object with a |sourceID| representing the current WebState. +- (instancetype)initWithSourceID:(ukm::SourceId)sourceID NS_DESIGNATED_INITIALIZER; +// Initializes an object with the given |payload| of the link generation +// request, and a |sourceID| representing the current WebState. +- (instancetype)initWithPayload:(LinkToTextPayload*)payload + sourceID:(ukm::SourceId)sourceID; + // Initializes an object with the given |error| which occurred while trying to -// generate a link. -- (instancetype)initWithError:(LinkGenerationError)error; +// generate a link, and a |sourceID| representing the current WebState. +- (instancetype)initWithError:(LinkGenerationError)error + sourceID:(ukm::SourceId)sourceID; @end @implementation LinkToTextResponse -- (instancetype)initWithPayload:(LinkToTextPayload*)payload { +- (instancetype)initWithSourceID:(ukm::SourceId)sourceID { if (self = [super init]) { - // Payload may be nil in cases of link generation error. + _sourceID = sourceID; + } + return self; +} + +- (instancetype)initWithPayload:(LinkToTextPayload*)payload + sourceID:(ukm::SourceId)sourceID { + DCHECK(payload); + DCHECK(sourceID != ukm::kInvalidSourceId); + if (self = [self initWithSourceID:sourceID]) { _payload = payload; } return self; } -- (instancetype)initWithError:(LinkGenerationError)error { - if (self = [self initWithPayload:nil]) { +- (instancetype)initWithError:(LinkGenerationError)error + sourceID:(ukm::SourceId)sourceID { + if (self = [self initWithSourceID:sourceID]) { _error = error; } return self; } -+ (instancetype)createFromValue:(const base::Value*)value - webState:(web::WebState*)webState { - if (!webState || !link_to_text::IsValidDictValue(value)) { - return [LinkToTextResponse unknownError]; ++ (instancetype)linkToTextResponseWithValue:(const base::Value*)value + webState:(web::WebState*)webState { + if (!webState) { + return [LinkToTextResponse linkToTextResponseWithUnknownError]; + } + + ukm::SourceId sourceID = ukm::GetSourceIdForWebStateDocument(webState); + + if (!link_to_text::IsValidDictValue(value)) { + return [self linkToTextResponseWithUnknownErrorAndSourceID:sourceID]; } base::Optional<LinkGenerationOutcome> outcome = link_to_text::ParseStatus(value->FindDoubleKey("status")); if (!outcome.has_value()) { - return [LinkToTextResponse unknownError]; + return [self linkToTextResponseWithUnknownErrorAndSourceID:sourceID]; } if (outcome.value() != LinkGenerationOutcome::kSuccess) { // Convert to Error. - return [[LinkToTextResponse alloc] - initWithError:link_to_text::OutcomeToError(outcome.value())]; + return [[self alloc] + initWithError:link_to_text::OutcomeToError(outcome.value()) + sourceID:sourceID]; } // Attempts to parse a payload from the response. @@ -81,7 +104,7 @@ // All values must be present to have a valid payload. if (!title || !fragment || !selectedText || !sourceRect) { // Library replied Success but some values are missing. - return [LinkToTextResponse unknownError]; + return [self linkToTextResponseWithUnknownErrorAndSourceID:sourceID]; } // Create the deep-link. @@ -95,14 +118,20 @@ sourceView:webState->GetView() sourceRect:link_to_text::ConvertToBrowserRect(sourceRect.value(), webState)]; - return [[LinkToTextResponse alloc] initWithPayload:payload]; + return [[self alloc] initWithPayload:payload sourceID:sourceID]; } #pragma mark - Private -+ (instancetype)unknownError { - return - [[LinkToTextResponse alloc] initWithError:LinkGenerationError::kUnknown]; ++ (instancetype)linkToTextResponseWithUnknownError { + return [[self alloc] initWithError:LinkGenerationError::kUnknown + sourceID:ukm::kInvalidSourceId]; +} + ++ (instancetype)linkToTextResponseWithUnknownErrorAndSourceID: + (ukm::SourceId)sourceID { + return [[self alloc] initWithError:LinkGenerationError::kUnknown + sourceID:sourceID]; } @end
diff --git a/ios/chrome/browser/link_to_text/link_to_text_tab_helper.mm b/ios/chrome/browser/link_to_text/link_to_text_tab_helper.mm index cbb0698..f978804 100644 --- a/ios/chrome/browser/link_to_text/link_to_text_tab_helper.mm +++ b/ios/chrome/browser/link_to_text/link_to_text_tab_helper.mm
@@ -59,7 +59,8 @@ LinkToTextCallback callback, const base::Value* response) { if (callback) { - callback([LinkToTextResponse createFromValue:response webState:web_state_]); + callback([LinkToTextResponse linkToTextResponseWithValue:response + webState:web_state_]); } }
diff --git a/ios/chrome/browser/ui/infobars/banners/infobar_banner_view_controller.mm b/ios/chrome/browser/ui/infobars/banners/infobar_banner_view_controller.mm index ac036faa..1be5f61 100644 --- a/ios/chrome/browser/ui/infobars/banners/infobar_banner_view_controller.mm +++ b/ios/chrome/browser/ui/infobars/banners/infobar_banner_view_controller.mm
@@ -114,6 +114,7 @@ _metricsRecorder = [[InfobarMetricsRecorder alloc] initWithType:infobarType]; _presentsModal = presentsModal; + _useIconBackgroundTint = YES; } return self; } @@ -147,6 +148,12 @@ // Icon setup. UIView* iconContainerView = nil; if (self.iconImage) { + // If the icon image requires a background tint, ignore the original color + // information and draw the image as a template image. + if (self.useIconBackgroundTint) { + self.iconImage = [self.iconImage + imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; + } UIImageView* iconImageView = [[UIImageView alloc] initWithImage:self.iconImage]; iconImageView.contentMode = UIViewContentModeScaleAspectFit; @@ -155,15 +162,10 @@ UIView* backgroundIconView = [[UIView alloc] initWithFrame:iconImageView.frame]; backgroundIconView.layer.cornerRadius = kIconCornerRadius; - backgroundIconView.translatesAutoresizingMaskIntoConstraints = NO; - - // If the icon image requires a background tint, ignore the original color - // information and draw the image as a template image. if (self.useIconBackgroundTint) { - self.iconImage = [self.iconImage - imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; backgroundIconView.backgroundColor = [UIColor colorNamed:kBlueHaloColor]; } + backgroundIconView.translatesAutoresizingMaskIntoConstraints = NO; iconContainerView = [[UIView alloc] init]; [iconContainerView addSubview:backgroundIconView];
diff --git a/ios/chrome/browser/ui/link_to_text/BUILD.gn b/ios/chrome/browser/ui/link_to_text/BUILD.gn index ef619ad..5086f90 100644 --- a/ios/chrome/browser/ui/link_to_text/BUILD.gn +++ b/ios/chrome/browser/ui/link_to_text/BUILD.gn
@@ -28,6 +28,8 @@ "//base", "//base/test:test_support", "//components/shared_highlighting/core/common", + "//components/ukm:test_support", + "//components/ukm/ios:ukm_url_recorder", "//ios/chrome/browser/link_to_text", "//ios/chrome/browser/link_to_text:internal", "//ios/chrome/browser/ui:feature_flags",
diff --git a/ios/chrome/browser/ui/link_to_text/link_to_text_mediator.mm b/ios/chrome/browser/ui/link_to_text/link_to_text_mediator.mm index 38f24eda..4968d8d 100644 --- a/ios/chrome/browser/ui/link_to_text/link_to_text_mediator.mm +++ b/ios/chrome/browser/ui/link_to_text/link_to_text_mediator.mm
@@ -66,8 +66,12 @@ - (void)receivedLinkToTextResponse:(LinkToTextResponse*)response { DCHECK(response); if (response.error.has_value()) { - [self linkGenerationFailedWithError:response.error.value()]; + LinkGenerationError error = response.error.value(); + shared_highlighting::LogLinkGeneratedErrorUkmEvent(response.sourceID, + error); + [self linkGenerationFailedWithError:error]; } else { + shared_highlighting::LogLinkGeneratedSuccessUkmEvent(response.sourceID); [self shareLinkToText:response.payload]; } }
diff --git a/ios/chrome/browser/ui/link_to_text/link_to_text_mediator_unittest.mm b/ios/chrome/browser/ui/link_to_text/link_to_text_mediator_unittest.mm index 3fd940d..4adc93c2a 100644 --- a/ios/chrome/browser/ui/link_to_text/link_to_text_mediator_unittest.mm +++ b/ios/chrome/browser/ui/link_to_text/link_to_text_mediator_unittest.mm
@@ -16,6 +16,8 @@ #import "base/values.h" #import "components/shared_highlighting/core/common/shared_highlighting_metrics.h" #import "components/shared_highlighting/core/common/text_fragment.h" +#import "components/ukm/ios/ukm_url_recorder.h" +#import "components/ukm/test_ukm_recorder.h" #import "ios/chrome/browser/link_to_text/link_generation_outcome.h" #import "ios/chrome/browser/link_to_text/link_to_text_payload.h" #import "ios/chrome/browser/link_to_text/link_to_text_tab_helper.h" @@ -24,12 +26,14 @@ #import "ios/chrome/browser/web_state_list/web_state_list.h" #import "ios/chrome/browser/web_state_list/web_state_list_delegate.h" #import "ios/chrome/browser/web_state_list/web_state_opener.h" +#import "ios/web/public/test/fakes/fake_navigation_context.h" #import "ios/web/public/test/fakes/fake_web_frame.h" #import "ios/web/public/test/fakes/fake_web_frames_manager.h" #import "ios/web/public/test/fakes/test_web_state.h" #import "ios/web/public/test/web_task_environment.h" #import "ios/web/public/ui/crw_web_view_proxy.h" #import "ios/web/public/ui/crw_web_view_scroll_view_proxy.h" +#import "services/metrics/public/cpp/ukm_builders.h" #import "testing/platform_test.h" #import "third_party/ocmock/OCMock/OCMock.h" #import "third_party/ocmock/gtest_support.h" @@ -51,6 +55,9 @@ const char kTestBaseURL[] = "https://www.chromium.org/"; const TextFragment kTestTextFragment = TextFragment("selected text"); +const char kSuccessUkmMetric[] = "Success"; +const char kErrorUkmMetric[] = "Error"; + class TestWebStateListDelegate : public WebStateListDelegate { void WillAddWebState(web::WebState* web_state) override {} void WebStateDetached(web::WebState* web_state) override {} @@ -90,6 +97,14 @@ web_state_->SetWebViewProxy(mocked_webview_proxy); web_state_->SetCurrentURL(GURL(kTestBaseURL)); + // Fake Navigation End for UKM setup. + ukm::InitializeSourceUrlRecorderForWebState(web_state_); + web::FakeNavigationContext context; + context.SetHasCommitted(true); + context.SetIsSameDocument(false); + web_state_->OnNavigationStarted(&context); + web_state_->OnNavigationFinished(&context); + LinkToTextTabHelper::CreateForWebState(web_state_); mediator_ = @@ -139,11 +154,33 @@ return response_value; } + void ValidateLinkGeneratedSuccessUkm() { + auto entries = ukm_recorder_.GetEntriesByName( + ukm::builders::SharedHighlights_LinkGenerated::kEntryName); + ASSERT_EQ(1u, entries.size()); + const ukm::mojom::UkmEntry* entry = entries[0]; + EXPECT_NE(ukm::kInvalidSourceId, entry->source_id); + ukm_recorder_.ExpectEntryMetric(entry, kSuccessUkmMetric, true); + EXPECT_FALSE(ukm_recorder_.GetEntryMetric(entry, kErrorUkmMetric)); + } + + void ValidateLinkGeneratedErrorUkm(LinkGenerationError error) { + auto entries = ukm_recorder_.GetEntriesByName( + ukm::builders::SharedHighlights_LinkGenerated::kEntryName); + ASSERT_EQ(1u, entries.size()); + const ukm::mojom::UkmEntry* entry = entries[0]; + EXPECT_NE(ukm::kInvalidSourceId, entry->source_id); + ukm_recorder_.ExpectEntryMetric(entry, kSuccessUkmMetric, false); + ukm_recorder_.ExpectEntryMetric(entry, kErrorUkmMetric, + static_cast<int64_t>(error)); + } + web::WebTaskEnvironment task_environment_; base::test::ScopedFeatureList feature_list_; TestWebStateListDelegate web_state_list_delegate_; WebStateList web_state_list_; TestWebState* web_state_; + ukm::TestAutoSetUkmRecorder ukm_recorder_; web::FakeWebFramesManager* web_frames_manager_; web::FakeWebFrame* main_frame_; UIView* fake_view_; @@ -196,6 +233,7 @@ // Make sure the correct metric were recorded. histogram_tester.ExpectUniqueSample("SharedHighlights.LinkGenerated", true, 1); + ValidateLinkGeneratedSuccessUkm(); } // Tests that the shareHighlight command is triggered with the right parameters @@ -238,6 +276,7 @@ // Make sure the correct metric were recorded. histogram_tester.ExpectUniqueSample("SharedHighlights.LinkGenerated", true, 1); + ValidateLinkGeneratedSuccessUkm(); } // Tests that the consumer is informed of a failure to generate a link when an @@ -264,11 +303,12 @@ [mocked_consumer_ verify]; // Make sure the correct metric were recorded. + LinkGenerationError error = LinkGenerationError::kIncorrectSelector; histogram_tester.ExpectUniqueSample("SharedHighlights.LinkGenerated", false, 1); histogram_tester.ExpectBucketCount("SharedHighlights.LinkGenerated.Error", - LinkGenerationError::kIncorrectSelector, - 1); + error, 1); + ValidateLinkGeneratedErrorUkm(error); } // Tests that the consumer is informed of a failure to generate a link when an @@ -294,10 +334,12 @@ [mocked_consumer_ verify]; // Make sure the correct metric were recorded. + LinkGenerationError error = LinkGenerationError::kUnknown; histogram_tester.ExpectUniqueSample("SharedHighlights.LinkGenerated", false, 1); histogram_tester.ExpectBucketCount("SharedHighlights.LinkGenerated.Error", - LinkGenerationError::kUnknown, 1); + error, 1); + ValidateLinkGeneratedErrorUkm(error); } // Tests that the consumer is informed of a failure to generate a link when an @@ -325,10 +367,12 @@ [mocked_consumer_ verify]; // Make sure the correct metric were recorded. + LinkGenerationError error = LinkGenerationError::kUnknown; histogram_tester.ExpectUniqueSample("SharedHighlights.LinkGenerated", false, 1); histogram_tester.ExpectBucketCount("SharedHighlights.LinkGenerated.Error", - LinkGenerationError::kUnknown, 1); + error, 1); + ValidateLinkGeneratedErrorUkm(error); } // Tests that the consumer is informed of a failure to generate a link when an @@ -355,10 +399,12 @@ [mocked_consumer_ verify]; // Make sure the correct metric were recorded. + LinkGenerationError error = LinkGenerationError::kUnknown; histogram_tester.ExpectUniqueSample("SharedHighlights.LinkGenerated", false, 1); histogram_tester.ExpectBucketCount("SharedHighlights.LinkGenerated.Error", - LinkGenerationError::kUnknown, 1); + error, 1); + ValidateLinkGeneratedErrorUkm(error); } // Tests that the consumer is informed of a failure to generate a link when a @@ -385,8 +431,10 @@ [mocked_consumer_ verify]; // Make sure the correct metric were recorded. + LinkGenerationError error = LinkGenerationError::kUnknown; histogram_tester.ExpectUniqueSample("SharedHighlights.LinkGenerated", false, 1); histogram_tester.ExpectBucketCount("SharedHighlights.LinkGenerated.Error", - LinkGenerationError::kUnknown, 1); + error, 1); + ValidateLinkGeneratedErrorUkm(error); }
diff --git a/ios/chrome/browser/ui/main/scene_controller.mm b/ios/chrome/browser/ui/main/scene_controller.mm index 55cfc3dcd..fe6b8703 100644 --- a/ios/chrome/browser/ui/main/scene_controller.mm +++ b/ios/chrome/browser/ui/main/scene_controller.mm
@@ -1609,6 +1609,9 @@ }; case START_QR_CODE_SCANNER: return ^{ + if (!self.currentInterface.browser) { + return; + } id<QRScannerCommands> QRHandler = HandlerForProtocol( self.currentInterface.browser->GetCommandDispatcher(), QRScannerCommands); @@ -1616,6 +1619,9 @@ }; case FOCUS_OMNIBOX: return ^{ + if (!self.currentInterface.browser) { + return; + } id<OmniboxCommands> focusHandler = HandlerForProtocol( self.currentInterface.browser->GetCommandDispatcher(), OmniboxCommands);
diff --git a/ios/chrome/browser/ui/settings/BUILD.gn b/ios/chrome/browser/ui/settings/BUILD.gn index 70b1d9c..460e2d5 100644 --- a/ios/chrome/browser/ui/settings/BUILD.gn +++ b/ios/chrome/browser/ui/settings/BUILD.gn
@@ -316,7 +316,6 @@ "//ios/chrome/browser/sync", "//ios/chrome/browser/sync:test_support", "//ios/chrome/browser/translate", - "//ios/chrome/browser/ui:feature_flags", "//ios/chrome/browser/ui/commands", "//ios/chrome/browser/ui/icons", "//ios/chrome/browser/ui/settings:constants",
diff --git a/ios/chrome/browser/ui/settings/settings_root_table_view_controller.mm b/ios/chrome/browser/ui/settings/settings_root_table_view_controller.mm index 4879895..33e40b8 100644 --- a/ios/chrome/browser/ui/settings/settings_root_table_view_controller.mm +++ b/ios/chrome/browser/ui/settings/settings_root_table_view_controller.mm
@@ -13,7 +13,6 @@ #import "ios/chrome/browser/ui/settings/settings_navigation_controller.h" #import "ios/chrome/browser/ui/settings/settings_root_table_constants.h" #import "ios/chrome/browser/ui/table_view/chrome_table_view_styler.h" -#include "ios/chrome/browser/ui/ui_feature_flags.h" #import "ios/chrome/browser/ui/util/uikit_ui_util.h" #import "ios/chrome/common/ui/colors/UIColor+cr_semantic_colors.h" #import "ios/chrome/common/ui/colors/semantic_color_names.h" @@ -124,9 +123,6 @@ self.styler.tableViewBackgroundColor = UIColor.cr_systemGroupedBackgroundColor; [super viewDidLoad]; - if (base::FeatureList::IsEnabled(kSettingsRefresh)) { - self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone; - } self.styler.cellBackgroundColor = UIColor.cr_secondarySystemGroupedBackgroundColor; self.styler.cellTitleColor = UIColor.cr_labelColor; @@ -207,18 +203,6 @@ return kDefaultHeaderFooterHeight; } -#pragma mark - UITableViewDataSource - -- (UITableViewCell*)tableView:(UITableView*)tableView - cellForRowAtIndexPath:(NSIndexPath*)indexPath { - if (base::FeatureList::IsEnabled(kSettingsRefresh)) { - TableViewItem* item = [self.tableViewModel itemAtIndexPath:indexPath]; - item.useCustomSeparator = YES; - } - - return [super tableView:tableView cellForRowAtIndexPath:indexPath]; -} - #pragma mark - TableViewLinkHeaderFooterItemDelegate - (void)view:(TableViewLinkHeaderFooterView*)view didTapLinkURL:(GURL)URL {
diff --git a/ios/chrome/browser/ui/table_view/cells/table_view_link_header_footer_item.mm b/ios/chrome/browser/ui/table_view/cells/table_view_link_header_footer_item.mm index 36d3b16a..3f70c8a 100644 --- a/ios/chrome/browser/ui/table_view/cells/table_view_link_header_footer_item.mm +++ b/ios/chrome/browser/ui/table_view/cells/table_view_link_header_footer_item.mm
@@ -5,6 +5,8 @@ #import "ios/chrome/browser/ui/table_view/cells/table_view_link_header_footer_item.h" #import "ios/chrome/browser/ui/table_view/cells/table_view_cells_constants.h" +#include "ios/chrome/browser/ui/ui_feature_flags.h" +#import "ios/chrome/browser/ui/util/ui_util.h" #import "ios/chrome/browser/ui/util/uikit_ui_util.h" #import "ios/chrome/common/string_util.h" #import "ios/chrome/common/ui/colors/UIColor+cr_semantic_colors.h" @@ -16,12 +18,20 @@ #endif namespace { + // Padding used on the leading and trailing edges of the cell. const CGFloat kHorizontalPadding = 16; // Padding used on the top and bottom edges of the cell. const CGFloat kVerticalPadding = 8; +// Returns a padding according to the width of the current device. +CGFloat HorizontalPadding() { + if (base::FeatureList::IsEnabled(kSettingsRefresh) && !IsSmallDevice()) + return 0; + return kHorizontalPadding; +} + } // namespace @implementation TableViewLinkHeaderFooterItem @@ -88,10 +98,10 @@ constant:-kVerticalPadding], [_textView.trailingAnchor constraintEqualToAnchor:self.contentView.trailingAnchor - constant:-kHorizontalPadding], + constant:-HorizontalPadding()], [_textView.leadingAnchor constraintEqualToAnchor:self.contentView.leadingAnchor - constant:kHorizontalPadding], + constant:HorizontalPadding()], ]]; } return self;
diff --git a/ios/web/BUILD.gn b/ios/web/BUILD.gn index d99ad49..691aee0 100644 --- a/ios/web/BUILD.gn +++ b/ios/web/BUILD.gn
@@ -232,6 +232,8 @@ ":web", "//base", "//base/test:test_support", + "//components/shared_highlighting/core/common", + "//components/ukm:test_support", "//components/url_formatter", "//ios/net", "//ios/testing:ocmock_support", @@ -253,6 +255,7 @@ "//ios/web/web_state/ui:crw_web_view_navigation_proxy", "//ios/web/web_state/ui:web_view_handler", "//net:test_support", + "//services/metrics/public/cpp:ukm_builders", "//testing/gmock", "//testing/gtest", "//third_party/ocmock",
diff --git a/ios/web/DEPS b/ios/web/DEPS index 3eb9d1c..61c5722 100644 --- a/ios/web/DEPS +++ b/ios/web/DEPS
@@ -15,6 +15,7 @@ # For tests. "+components/crash/core/common/objc_zombie.h", + "+components/ukm/test_ukm_recorder.h", "+ios/testing", # TODO(crbug.com/1101077): Disallow direct import of eg2 headers.
diff --git a/ios/web/navigation/BUILD.gn b/ios/web/navigation/BUILD.gn index 2403edd6..3935920 100644 --- a/ios/web/navigation/BUILD.gn +++ b/ios/web/navigation/BUILD.gn
@@ -37,6 +37,7 @@ "//ios/web/web_state/ui:web_view_handler", "//ios/web/web_view:util", "//net", + "//services/metrics/public/cpp:metrics_cpp", "//ui/base", "//url", ]
diff --git a/ios/web/navigation/crw_text_fragments_handler.mm b/ios/web/navigation/crw_text_fragments_handler.mm index 8e54273..9a4caeb 100644 --- a/ios/web/navigation/crw_text_fragments_handler.mm +++ b/ios/web/navigation/crw_text_fragments_handler.mm
@@ -15,6 +15,7 @@ #import "ios/web/public/navigation/referrer.h" #import "ios/web/web_state/ui/crw_web_view_handler_delegate.h" #import "ios/web/web_state/web_state_impl.h" +#import "services/metrics/public/cpp/ukm_source_id.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support." @@ -39,6 +40,14 @@ // Returns the WebStateImpl from self.delegate. @property(nonatomic, readonly, assign) web::WebStateImpl* webStateImpl; +// Cached value of the source ID representing the last navigation to have text +// fragments. +@property(nonatomic, assign) ukm::SourceId latestSourceId; + +// Cached value of the latest referrer's URL to have triggered a navigation +// with text fragments. +@property(nonatomic, assign) GURL latestReferrerURL; + @end @implementation CRWTextFragmentsHandler @@ -80,9 +89,13 @@ return; } + // Log metrics and cache Referrer for UKM logging. shared_highlighting::LogTextFragmentSelectorCount( parsedFragments.GetList().size()); shared_highlighting::LogTextFragmentLinkOpenSource(referrer.url); + self.latestSourceId = ukm::ConvertToSourceId( + context->GetNavigationId(), ukm::SourceIdType::NAVIGATION_ID); + self.latestReferrerURL = referrer.url; std::string fragmentParam; base::JSONWriter::Write(parsedFragments, &fragmentParam); @@ -158,6 +171,10 @@ shared_highlighting::LogTextFragmentMatchRate(successCount, fragmentCount); shared_highlighting::LogTextFragmentAmbiguousMatch( /*ambiguous_match=*/successCount != fragmentCount); + + shared_highlighting::LogLinkOpenedUkmEvent( + self.latestSourceId, self.latestReferrerURL, + /*success=*/successCount == fragmentCount); } @end
diff --git a/ios/web/navigation/crw_text_fragments_handler_unittest.mm b/ios/web/navigation/crw_text_fragments_handler_unittest.mm index d49a06a..969156a 100644 --- a/ios/web/navigation/crw_text_fragments_handler_unittest.mm +++ b/ios/web/navigation/crw_text_fragments_handler_unittest.mm
@@ -7,6 +7,8 @@ #import "base/strings/utf_string_conversions.h" #import "base/test/metrics/histogram_tester.h" #import "base/test/scoped_feature_list.h" +#import "components/shared_highlighting/core/common/shared_highlighting_metrics.h" +#import "components/ukm/test_ukm_recorder.h" #import "ios/web/common/features.h" #import "ios/web/public/navigation/referrer.h" #import "ios/web/public/test/fakes/fake_navigation_context.h" @@ -14,6 +16,7 @@ #import "ios/web/public/test/web_test.h" #import "ios/web/web_state/ui/crw_web_view_handler_delegate.h" #import "ios/web/web_state/web_state_impl.h" +#import "services/metrics/public/cpp/ukm_builders.h" #import "testing/gmock/include/gmock/gmock.h" #import "testing/gtest/include/gtest/gtest.h" #import "third_party/ocmock/OCMock/OCMock.h" @@ -26,6 +29,7 @@ using web::Referrer; using ::testing::_; using ::testing::ReturnRefOfCopy; +using shared_highlighting::TextFragmentLinkOpenSource; namespace { @@ -42,6 +46,9 @@ const char kSearchEngineURL[] = "https://google.com"; const char kNonSearchEngineURL[] = "https://notasearchengine.com"; +const char kSuccessUkmMetric[] = "Success"; +const char kSourceUkmMetric[] = "Source"; + } // namespace class MockWebStateImpl : public web::WebStateImpl { @@ -130,6 +137,25 @@ referrer:GetSearchEngineReferrer()]; } + void ValidateLinkOpenedUkm(const ukm::TestAutoSetUkmRecorder& recorder, + bool success, + TextFragmentLinkOpenSource source) { + auto entries = recorder.GetEntriesByName( + ukm::builders::SharedHighlights_LinkOpened::kEntryName); + ASSERT_EQ(1u, entries.size()); + const ukm::mojom::UkmEntry* entry = entries[0]; + EXPECT_NE(ukm::kInvalidSourceId, entry->source_id); + recorder.ExpectEntryMetric(entry, kSuccessUkmMetric, success); + recorder.ExpectEntryMetric(entry, kSourceUkmMetric, + static_cast<int64_t>(source)); + } + + void ValidateNoLinkOpenedUkm(const ukm::TestAutoSetUkmRecorder& recorder) { + auto entries = recorder.GetEntriesByName( + ukm::builders::SharedHighlights_LinkOpened::kEntryName); + EXPECT_EQ(0u, entries.size()); + } + web::FakeNavigationContext context_; MockWebStateImpl* web_state_; base::test::ScopedFeatureList feature_list_; @@ -283,6 +309,7 @@ TEST_F(CRWTextFragmentsHandlerTest, NoMetricsRecordedIfNoFragmentPresentWithFragmentId) { base::HistogramTester histogram_tester; + ukm::TestAutoSetUkmRecorder ukm_recorder; // Set a URL without text fragments, but with an id fragment. SetLastURL(GURL("https://www.chromium.org/#FragmentID")); @@ -303,6 +330,7 @@ // from a search engine. TEST_F(CRWTextFragmentsHandlerTest, LinkSourceMetricSearchEngine) { base::HistogramTester histogram_tester; + ukm::TestAutoSetUkmRecorder ukm_recorder; SetLastURL(GURL(kValidFragmentsURL)); CRWTextFragmentsHandler* handler = CreateDefaultHandler(); @@ -318,6 +346,7 @@ // come from a search engine. TEST_F(CRWTextFragmentsHandlerTest, LinkSourceMetricNonSearchEngine) { base::HistogramTester histogram_tester; + ukm::TestAutoSetUkmRecorder ukm_recorder; SetLastURL(GURL(kValidFragmentsURL)); CRWTextFragmentsHandler* handler = CreateDefaultHandler(); @@ -375,6 +404,7 @@ // 100% rate case. { base::HistogramTester histogram_tester; + ukm::TestAutoSetUkmRecorder ukm_recorder; base::DictionaryValue js_response = base::DictionaryValue(); js_response.SetKey("command", base::Value("textFragments.response")); @@ -387,11 +417,15 @@ histogram_tester.ExpectUniqueSample("TextFragmentAnchor.AmbiguousMatch", 0, 1); histogram_tester.ExpectUniqueSample("TextFragmentAnchor.MatchRate", 100, 1); + + ValidateLinkOpenedUkm(ukm_recorder, /*success=*/true, + TextFragmentLinkOpenSource::kSearchEngine); } // 50% rate case. { base::HistogramTester histogram_tester; + ukm::TestAutoSetUkmRecorder ukm_recorder; base::DictionaryValue js_response = base::DictionaryValue(); js_response.SetKey("command", base::Value("textFragments.response")); @@ -404,11 +438,15 @@ histogram_tester.ExpectUniqueSample("TextFragmentAnchor.AmbiguousMatch", 1, 1); histogram_tester.ExpectUniqueSample("TextFragmentAnchor.MatchRate", 50, 1); + + ValidateLinkOpenedUkm(ukm_recorder, /*success=*/false, + TextFragmentLinkOpenSource::kSearchEngine); } // 0% rate case. { base::HistogramTester histogram_tester; + ukm::TestAutoSetUkmRecorder ukm_recorder; base::DictionaryValue js_response = base::DictionaryValue(); js_response.SetKey("command", base::Value("textFragments.response")); @@ -421,11 +459,15 @@ histogram_tester.ExpectUniqueSample("TextFragmentAnchor.AmbiguousMatch", 1, 1); histogram_tester.ExpectUniqueSample("TextFragmentAnchor.MatchRate", 0, 1); + + ValidateLinkOpenedUkm(ukm_recorder, /*success=*/false, + TextFragmentLinkOpenSource::kSearchEngine); } // Invalid values case - negative numbers. { base::HistogramTester histogram_tester; + ukm::TestAutoSetUkmRecorder ukm_recorder; base::DictionaryValue js_response = base::DictionaryValue(); js_response.SetKey("command", base::Value("textFragments.response")); @@ -437,11 +479,14 @@ histogram_tester.ExpectTotalCount("TextFragmentAnchor.AmbiguousMatch", 0); histogram_tester.ExpectTotalCount("TextFragmentAnchor.MatchRate", 0); + + ValidateNoLinkOpenedUkm(ukm_recorder); } // Invalid values case - not numbers. { base::HistogramTester histogram_tester; + ukm::TestAutoSetUkmRecorder ukm_recorder; base::DictionaryValue js_response = base::DictionaryValue(); js_response.SetKey("command", base::Value("textFragments.response")); @@ -453,5 +498,7 @@ histogram_tester.ExpectTotalCount("TextFragmentAnchor.AmbiguousMatch", 0); histogram_tester.ExpectTotalCount("TextFragmentAnchor.MatchRate", 0); + + ValidateNoLinkOpenedUkm(ukm_recorder); } }
diff --git a/services/device/geolocation/core_location_provider_unittest.mm b/services/device/geolocation/core_location_provider_unittest.mm index 43218df..cc5af46 100644 --- a/services/device/geolocation/core_location_provider_unittest.mm +++ b/services/device/geolocation/core_location_provider_unittest.mm
@@ -112,7 +112,8 @@ provider_.reset(); } -TEST_F(CoreLocationProviderTest, DontStartUpdatingIfPermissionDenied) { +// crbug.com/1153412: disabled due to flakiness. +TEST_F(CoreLocationProviderTest, DISABLED_DontStartUpdatingIfPermissionDenied) { InitializeProvider(); [fake_location_manager_ fakeUpdatePermission:kCLAuthorizationStatusDenied]; provider_->StartProvider(/*high_accuracy=*/true);
diff --git a/services/network/cors/cors_url_loader.cc b/services/network/cors/cors_url_loader.cc index d7d1d2aa..0286bad 100644 --- a/services/network/cors/cors_url_loader.cc +++ b/services/network/cors/cors_url_loader.cc
@@ -452,18 +452,6 @@ if (tainted_) { request_.headers.SetHeader(net::HttpRequestHeaders::kOrigin, url::Origin().Serialize()); - } else if ( - base::FeatureList::IsEnabled( - features:: - kDeriveOriginFromUrlForNeitherGetNorHeadRequestWhenHavingSpecialAccess) && - !request_.isolated_world_origin && HasSpecialAccessToDestination()) { - DCHECK(!fetch_cors_flag_); - // When request's origin has an access to the destination URL (via - // |origin_access_list_| and |factory_bound_origin_access_list_|), we - // attach destination URL's origin instead of request's origin to the - // "origin" request header. - request_.headers.SetHeader(net::HttpRequestHeaders::kOrigin, - url::Origin::Create(request_.url).Serialize()); } else { request_.headers.SetHeader(net::HttpRequestHeaders::kOrigin, request_.request_initiator->Serialize());
diff --git a/services/network/cors/preflight_controller.cc b/services/network/cors/preflight_controller.cc index 14e7347..c6867eac 100644 --- a/services/network/cors/preflight_controller.cc +++ b/services/network/cors/preflight_controller.cc
@@ -227,7 +227,8 @@ DCHECK(devtools_request_id_); network_service_client->OnCorsPreflightRequest( process_id_, original_request_.render_frame_id, *devtools_request_id_, - *preflight_request, original_request_.url); + *preflight_request, original_request_.url, + original_request_.devtools_request_id.value_or("")); } loader_ = SimpleURLLoader::Create(std::move(preflight_request), annotation_tag);
diff --git a/services/network/cors/preflight_controller_unittest.cc b/services/network/cors/preflight_controller_unittest.cc index 59ad51ae..e01e76f9 100644 --- a/services/network/cors/preflight_controller_unittest.cc +++ b/services/network/cors/preflight_controller_unittest.cc
@@ -284,6 +284,9 @@ const { return preflight_status_; } + const std::string& initiator_devtools_request_id() const { + return initiator_devtools_request_id_; + } private: // mojom::NetworkServiceClient: @@ -305,12 +308,15 @@ const base::Optional<std::string>& raw_response_headers) override { on_raw_response_called_ = true; } - void OnCorsPreflightRequest(int32_t process_id, - int32_t routing_id, - const base::UnguessableToken& devtool_request_id, - const network::ResourceRequest& request, - const GURL& initiator_url) override { + void OnCorsPreflightRequest( + int32_t process_id, + int32_t routing_id, + const base::UnguessableToken& devtool_request_id, + const network::ResourceRequest& request, + const GURL& initiator_url, + const std::string& initiator_devtools_request_id) override { preflight_request_ = request; + initiator_devtools_request_id_ = initiator_devtools_request_id; } void OnCorsPreflightResponse( int32_t process_id, @@ -338,6 +344,7 @@ base::Optional<network::ResourceRequest> preflight_request_; network::mojom::URLResponseHeadPtr preflight_response_; base::Optional<network::URLLoaderCompletionStatus> preflight_status_; + std::string initiator_devtools_request_id_; }; class PreflightControllerTest : public testing::Test { @@ -660,6 +667,7 @@ network_service_client->preflight_response()->headers->response_code()); ASSERT_TRUE(network_service_client->preflight_status().has_value()); EXPECT_EQ(net::OK, network_service_client->preflight_status()->error_code); + EXPECT_EQ("TEST", network_service_client->initiator_devtools_request_id()); } } // namespace
diff --git a/services/network/public/cpp/features.cc b/services/network/public/cpp/features.cc index 4ac478d3..d936ceb 100644 --- a/services/network/public/cpp/features.cc +++ b/services/network/public/cpp/features.cc
@@ -146,12 +146,6 @@ const base::Feature kDisableKeepaliveFetch{"DisableKeepaliveFetch", base::FEATURE_DISABLED_BY_DEFAULT}; -// Attach the origin of the destination URL to the "origin" header -const base::Feature - kDeriveOriginFromUrlForNeitherGetNorHeadRequestWhenHavingSpecialAccess{ - "DeriveOriginFromUrlForNeitherGetNorHeadRequestWhenHavingSpecialAccess", - base::FEATURE_DISABLED_BY_DEFAULT}; - // Controls whether a |request_initiator| that mismatches // |request_initiator_origin_lock| leads to 1) failing the HTTP request and 2) // calling mojo::ReportBadMessage (on desktop platforms, where NetworkService
diff --git a/services/network/public/cpp/features.h b/services/network/public/cpp/features.h index b4899fcb..fe8b2c4 100644 --- a/services/network/public/cpp/features.h +++ b/services/network/public/cpp/features.h
@@ -56,9 +56,6 @@ COMPONENT_EXPORT(NETWORK_CPP) extern const base::Feature kDisableKeepaliveFetch; COMPONENT_EXPORT(NETWORK_CPP) -extern const base::Feature - kDeriveOriginFromUrlForNeitherGetNorHeadRequestWhenHavingSpecialAccess; -COMPONENT_EXPORT(NETWORK_CPP) extern const base::Feature kRequestInitiatorSiteLockEnfocement; COMPONENT_EXPORT(NETWORK_CPP) extern const base::Feature kCertVerifierService;
diff --git a/services/network/public/mojom/network_service.mojom b/services/network/public/mojom/network_service.mojom index 3d2a5703..6e5025c 100644 --- a/services/network/public/mojom/network_service.mojom +++ b/services/network/public/mojom/network_service.mojom
@@ -88,7 +88,8 @@ int32 render_frame_id, mojo_base.mojom.UnguessableToken devtool_request_id, URLRequest request, - url.mojom.Url initiator_url); + url.mojom.Url initiator_url, + string initiator_devtool_request_id); // Called to send the CORS preflight response information. Only called when // |devtool_request_id| is available on the original request.
diff --git a/services/network/test/test_network_service_client.cc b/services/network/test/test_network_service_client.cc index db13adc..5a6fef8a 100644 --- a/services/network/test/test_network_service_client.cc +++ b/services/network/test/test_network_service_client.cc
@@ -50,7 +50,8 @@ int32_t routing_id, const base::UnguessableToken& devtools_request_id, const network::ResourceRequest& request, - const GURL& initiator_url) {} + const GURL& initiator_url, + const std::string& initiator_devtools_request_id) {} void TestNetworkServiceClient::OnCorsPreflightResponse( int32_t process_id,
diff --git a/services/network/test/test_network_service_client.h b/services/network/test/test_network_service_client.h index 1b7b8d0..a277f71 100644 --- a/services/network/test/test_network_service_client.h +++ b/services/network/test/test_network_service_client.h
@@ -46,11 +46,13 @@ const net::CookieAndLineAccessResultList& cookies_with_access_result, std::vector<network::mojom::HttpRawHeaderPairPtr> headers, const base::Optional<std::string>& raw_response_headers) override; - void OnCorsPreflightRequest(int32_t process_id, - int32_t routing_id, - const base::UnguessableToken& devtool_request_id, - const network::ResourceRequest& request, - const GURL& initiator_url) override; + void OnCorsPreflightRequest( + int32_t process_id, + int32_t routing_id, + const base::UnguessableToken& devtool_request_id, + const network::ResourceRequest& request, + const GURL& initiator_url, + const std::string& initiator_devtools_request_id) override; void OnCorsPreflightResponse( int32_t process_id, int32_t routing_id,
diff --git a/testing/buildbot/chromium.gpu.fyi.json b/testing/buildbot/chromium.gpu.fyi.json index 234a63e..b5856e9 100644 --- a/testing/buildbot/chromium.gpu.fyi.json +++ b/testing/buildbot/chromium.gpu.fyi.json
@@ -10562,22 +10562,297 @@ ] }, "Linux FYI Release (AMD RX 5500 XT)": { + "gtest_tests": [ + { + "args": [ + "angle_end2end_tests", + "--gtest_filter=-*Vulkan_SwiftShader*", + "--bot-mode", + "--max-processes=4" + ], + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "containment_type": "AUTO", + "dimension_sets": [ + { + "gpu": "1002:7340", + "os": "Ubuntu", + "pool": "chromium.tests.gpu.experimental" + } + ], + "expiration": 21600, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 2 + }, + "test": "angle_end2end_tests", + "test_id_prefix": "ninja://third_party/angle/src/tests:angle_end2end_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "angle_unittests" + ], + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "containment_type": "AUTO", + "dimension_sets": [ + { + "gpu": "1002:7340", + "os": "Ubuntu", + "pool": "chromium.tests.gpu.experimental" + } + ], + "expiration": 21600, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_unittests", + "test_id_prefix": "ninja://third_party/angle/src/tests:angle_unittests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "angle_white_box_tests", + "--bot-mode" + ], + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "containment_type": "AUTO", + "dimension_sets": [ + { + "gpu": "1002:7340", + "os": "Ubuntu", + "pool": "chromium.tests.gpu.experimental" + } + ], + "expiration": 21600, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_white_box_tests", + "test_id_prefix": "ninja://third_party/angle/src/tests:angle_white_box_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--enable-gpu", + "--test-launcher-bot-mode", + "--test-launcher-jobs=1", + "--gtest_filter=CastStreamingApiTestWithPixelOutput.EndToEnd*:TabCaptureApiPixelTest.EndToEnd*", + "--no-xvfb" + ], + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "name": "tab_capture_end2end_tests", + "swarming": { + "can_use_on_swarming_builders": true, + "containment_type": "AUTO", + "dimension_sets": [ + { + "gpu": "1002:7340", + "os": "Ubuntu", + "pool": "chromium.tests.gpu.experimental" + } + ], + "expiration": 21600, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "browser_tests", + "test_id_prefix": "ninja://chrome/test:browser_tests/" + }, + { + "args": [ + "--use-cmd-decoder=passthrough", + "--use-gl=angle", + "--use-gpu-in-tests", + "--no-xvfb" + ], + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "name": "gl_tests_passthrough", + "swarming": { + "can_use_on_swarming_builders": true, + "containment_type": "AUTO", + "dimension_sets": [ + { + "gpu": "1002:7340", + "os": "Ubuntu", + "pool": "chromium.tests.gpu.experimental" + } + ], + "expiration": 21600, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "gl_tests", + "test_id_prefix": "ninja://gpu:gl_tests/" + }, + { + "args": [ + "--use-cmd-decoder=validating", + "--use-gpu-in-tests", + "--no-xvfb" + ], + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "name": "gl_tests_validating", + "swarming": { + "can_use_on_swarming_builders": true, + "containment_type": "AUTO", + "dimension_sets": [ + { + "gpu": "1002:7340", + "os": "Ubuntu", + "pool": "chromium.tests.gpu.experimental" + } + ], + "expiration": 21600, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "gl_tests", + "test_id_prefix": "ninja://gpu:gl_tests/" + }, + { + "args": [ + "--use-gpu-in-tests", + "--no-xvfb" + ], + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "containment_type": "AUTO", + "dimension_sets": [ + { + "gpu": "1002:7340", + "os": "Ubuntu", + "pool": "chromium.tests.gpu.experimental" + } + ], + "expiration": 21600, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "gl_unittests", + "test_id_prefix": "ninja://ui/gl:gl_unittests/" + }, + { + "args": [ + "--use-gpu-in-tests" + ], + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "containment_type": "AUTO", + "dimension_sets": [ + { + "gpu": "1002:7340", + "os": "Ubuntu", + "pool": "chromium.tests.gpu.experimental" + } + ], + "expiration": 21600, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "gles2_conform_test", + "test_id_prefix": "ninja://gpu/gles2_conform_support:gles2_conform_test/" + }, + { + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "containment_type": "AUTO", + "dimension_sets": [ + { + "gpu": "1002:7340", + "os": "Ubuntu", + "pool": "chromium.tests.gpu.experimental" + } + ], + "expiration": 21600, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "swiftshader_unittests", + "test_id_prefix": "ninja://third_party/swiftshader/tests/GLESUnitTests:swiftshader_unittests/" + } + ], "isolated_scripts": [ { "args": [ - "noop_sleep", + "angle_perftests", + "--non-telemetry=true", + "--gtest-benchmark-name=angle_perftests", + "-v", + "--one-frame-only", + "--test-timeout=100", + "--batch-size=1", + "--bot-mode", + "--max-processes=1", + "--print-test-stdout" + ], + "isolate_name": "angle_perftests", + "merge": { + "args": [ + "--smoke-test-mode" + ], + "script": "//tools/perf/process_perf_results.py" + }, + "name": "angle_perftests", + "swarming": { + "can_use_on_swarming_builders": true, + "containment_type": "AUTO", + "dimension_sets": [ + { + "gpu": "1002:7340", + "os": "Ubuntu", + "pool": "chromium.tests.gpu.experimental" + } + ], + "expiration": 21600, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://third_party/angle/src/tests:angle_perftests/" + }, + { + "args": [ + "context_lost", "--show-stdout", "--browser=release", "--passthrough", "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle" ], "isolate_name": "telemetry_gpu_integration_test", "merge": { "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "noop_sleep_tests", + "name": "context_lost_passthrough_tests", + "resultdb": { + "enable": true + }, "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, @@ -10594,6 +10869,618 @@ "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/" + }, + { + "args": [ + "context_lost", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating" + ], + "isolate_name": "telemetry_gpu_integration_test", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "context_lost_validating_tests", + "resultdb": { + "enable": true + }, + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "containment_type": "AUTO", + "dimension_sets": [ + { + "gpu": "1002:7340", + "os": "Ubuntu", + "pool": "chromium.tests.gpu.experimental" + } + ], + "expiration": 21600, + "idempotent": false, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/" + }, + { + "args": [ + "depth_capture", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" + ], + "isolate_name": "telemetry_gpu_integration_test", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "depth_capture_tests", + "resultdb": { + "enable": true + }, + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "containment_type": "AUTO", + "dimension_sets": [ + { + "gpu": "1002:7340", + "os": "Ubuntu", + "pool": "chromium.tests.gpu.experimental" + } + ], + "expiration": 21600, + "idempotent": false, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/" + }, + { + "args": [ + "gpu_process", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" + ], + "isolate_name": "telemetry_gpu_integration_test", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "gpu_process_launch_tests", + "resultdb": { + "enable": true + }, + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "containment_type": "AUTO", + "dimension_sets": [ + { + "gpu": "1002:7340", + "os": "Ubuntu", + "pool": "chromium.tests.gpu.experimental" + } + ], + "expiration": 21600, + "idempotent": false, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/" + }, + { + "args": [ + "hardware_accelerated_feature", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" + ], + "isolate_name": "telemetry_gpu_integration_test", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "hardware_accelerated_feature_tests", + "resultdb": { + "enable": true + }, + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "containment_type": "AUTO", + "dimension_sets": [ + { + "gpu": "1002:7340", + "os": "Ubuntu", + "pool": "chromium.tests.gpu.experimental" + } + ], + "expiration": 21600, + "idempotent": false, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/" + }, + { + "args": [ + "info_collection", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --force_high_performance_gpu", + "--expected-vendor-id", + "1002", + "--expected-device-id", + "7340" + ], + "isolate_name": "telemetry_gpu_integration_test", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "info_collection_tests", + "resultdb": { + "enable": true + }, + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "containment_type": "AUTO", + "dimension_sets": [ + { + "gpu": "1002:7340", + "os": "Ubuntu", + "pool": "chromium.tests.gpu.experimental" + } + ], + "expiration": 21600, + "idempotent": false, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/" + }, + { + "args": [ + "maps", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle", + "--dont-restore-color-profile-after-test", + "--test-machine-name", + "${buildername}", + "--git-revision=${got_revision}" + ], + "isolate_name": "telemetry_gpu_integration_test", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "maps_pixel_passthrough_test", + "precommit_args": [ + "--gerrit-issue=${patch_issue}", + "--gerrit-patchset=${patch_set}", + "--buildbucket-id=${buildbucket_build_id}" + ], + "resultdb": { + "enable": true + }, + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "containment_type": "AUTO", + "dimension_sets": [ + { + "gpu": "1002:7340", + "os": "Ubuntu", + "pool": "chromium.tests.gpu.experimental" + } + ], + "expiration": 21600, + "idempotent": false, + "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/" + }, + { + "args": [ + "maps", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating", + "--dont-restore-color-profile-after-test", + "--test-machine-name", + "${buildername}", + "--git-revision=${got_revision}" + ], + "isolate_name": "telemetry_gpu_integration_test", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "maps_pixel_validating_test", + "precommit_args": [ + "--gerrit-issue=${patch_issue}", + "--gerrit-patchset=${patch_set}", + "--buildbucket-id=${buildbucket_build_id}" + ], + "resultdb": { + "enable": true + }, + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "containment_type": "AUTO", + "dimension_sets": [ + { + "gpu": "1002:7340", + "os": "Ubuntu", + "pool": "chromium.tests.gpu.experimental" + } + ], + "expiration": 21600, + "idempotent": false, + "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/" + }, + { + "args": [ + "pixel", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle", + "--dont-restore-color-profile-after-test", + "--test-machine-name", + "${buildername}", + "--git-revision=${got_revision}" + ], + "isolate_name": "telemetry_gpu_integration_test", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "pixel_skia_gold_passthrough_test", + "precommit_args": [ + "--gerrit-issue=${patch_issue}", + "--gerrit-patchset=${patch_set}", + "--buildbucket-id=${buildbucket_build_id}" + ], + "resultdb": { + "enable": true + }, + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "containment_type": "AUTO", + "dimension_sets": [ + { + "gpu": "1002:7340", + "os": "Ubuntu", + "pool": "chromium.tests.gpu.experimental" + } + ], + "expiration": 21600, + "idempotent": false, + "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/" + }, + { + "args": [ + "pixel", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating", + "--dont-restore-color-profile-after-test", + "--test-machine-name", + "${buildername}", + "--git-revision=${got_revision}" + ], + "isolate_name": "telemetry_gpu_integration_test", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "pixel_skia_gold_validating_test", + "precommit_args": [ + "--gerrit-issue=${patch_issue}", + "--gerrit-patchset=${patch_set}", + "--buildbucket-id=${buildbucket_build_id}" + ], + "resultdb": { + "enable": true + }, + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "containment_type": "AUTO", + "dimension_sets": [ + { + "gpu": "1002:7340", + "os": "Ubuntu", + "pool": "chromium.tests.gpu.experimental" + } + ], + "expiration": 21600, + "idempotent": false, + "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/" + }, + { + "args": [ + "screenshot_sync", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle", + "--dont-restore-color-profile-after-test" + ], + "isolate_name": "telemetry_gpu_integration_test", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "screenshot_sync_passthrough_tests", + "resultdb": { + "enable": true + }, + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "containment_type": "AUTO", + "dimension_sets": [ + { + "gpu": "1002:7340", + "os": "Ubuntu", + "pool": "chromium.tests.gpu.experimental" + } + ], + "expiration": 21600, + "idempotent": false, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/" + }, + { + "args": [ + "screenshot_sync", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating", + "--dont-restore-color-profile-after-test" + ], + "isolate_name": "telemetry_gpu_integration_test", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "screenshot_sync_validating_tests", + "resultdb": { + "enable": true + }, + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "containment_type": "AUTO", + "dimension_sets": [ + { + "gpu": "1002:7340", + "os": "Ubuntu", + "pool": "chromium.tests.gpu.experimental" + } + ], + "expiration": 21600, + "idempotent": false, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/" + }, + { + "args": [ + "trace_test", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" + ], + "isolate_name": "telemetry_gpu_integration_test", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "trace_test", + "resultdb": { + "enable": true + }, + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "containment_type": "AUTO", + "dimension_sets": [ + { + "gpu": "1002:7340", + "os": "Ubuntu", + "pool": "chromium.tests.gpu.experimental" + } + ], + "expiration": 21600, + "idempotent": false, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/" + }, + { + "args": [ + "webgl_conformance", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-gl=angle --use-angle=gl --use-cmd-decoder=passthrough --force_high_performance_gpu", + "--webgl-conformance-version=2.0.1", + "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl2_conformance_tests_output.json" + ], + "isolate_name": "telemetry_gpu_integration_test", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "webgl2_conformance_gl_passthrough_tests", + "resultdb": { + "enable": true + }, + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "containment_type": "AUTO", + "dimension_sets": [ + { + "gpu": "1002:7340", + "os": "Ubuntu", + "pool": "chromium.tests.gpu.experimental" + } + ], + "expiration": 21600, + "idempotent": false, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 20 + }, + "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/" + }, + { + "args": [ + "webgl_conformance", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating --force_high_performance_gpu", + "--webgl-conformance-version=2.0.1", + "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl2_conformance_tests_output.json" + ], + "isolate_name": "telemetry_gpu_integration_test", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "webgl2_conformance_validating_tests", + "resultdb": { + "enable": true + }, + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "containment_type": "AUTO", + "dimension_sets": [ + { + "gpu": "1002:7340", + "os": "Ubuntu", + "pool": "chromium.tests.gpu.experimental" + } + ], + "expiration": 21600, + "idempotent": false, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 20 + }, + "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/" + }, + { + "args": [ + "webgl_conformance", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-gl=angle --use-angle=gl --use-cmd-decoder=passthrough --force_high_performance_gpu", + "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl_conformance_tests_output.json" + ], + "isolate_name": "telemetry_gpu_integration_test", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "webgl_conformance_gl_passthrough_tests", + "resultdb": { + "enable": true + }, + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "containment_type": "AUTO", + "dimension_sets": [ + { + "gpu": "1002:7340", + "os": "Ubuntu", + "pool": "chromium.tests.gpu.experimental" + } + ], + "expiration": 21600, + "idempotent": false, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 2 + }, + "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/" + }, + { + "args": [ + "webgl_conformance", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating --force_high_performance_gpu", + "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl_conformance_tests_output.json" + ], + "isolate_name": "telemetry_gpu_integration_test", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "webgl_conformance_validating_tests", + "resultdb": { + "enable": true + }, + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "containment_type": "AUTO", + "dimension_sets": [ + { + "gpu": "1002:7340", + "os": "Ubuntu", + "pool": "chromium.tests.gpu.experimental" + } + ], + "expiration": 21600, + "idempotent": false, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 2 + }, + "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/" } ] }, @@ -30378,22 +31265,447 @@ ] }, "Win10 FYI x64 Release (AMD RX 5500 XT)": { + "gtest_tests": [ + { + "args": [ + "angle_end2end_tests", + "--gtest_filter=-*Vulkan_SwiftShader*", + "--bot-mode" + ], + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "containment_type": "AUTO", + "dimension_sets": [ + { + "gpu": "1002:7340", + "os": "Windows-10", + "pool": "chromium.tests.gpu.experimental" + } + ], + "expiration": 21600, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 2 + }, + "test": "angle_end2end_tests", + "test_id_prefix": "ninja://third_party/angle/src/tests:angle_end2end_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "angle_gles1_conformance_tests", + "--bot-mode" + ], + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "containment_type": "AUTO", + "dimension_sets": [ + { + "gpu": "1002:7340", + "os": "Windows-10", + "pool": "chromium.tests.gpu.experimental" + } + ], + "expiration": 21600, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_gles1_conformance_tests", + "test_id_prefix": "ninja://third_party/angle/src/tests:angle_gles1_conformance_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "angle_unittests" + ], + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "containment_type": "AUTO", + "dimension_sets": [ + { + "gpu": "1002:7340", + "os": "Windows-10", + "pool": "chromium.tests.gpu.experimental" + } + ], + "expiration": 21600, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_unittests", + "test_id_prefix": "ninja://third_party/angle/src/tests:angle_unittests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "angle_white_box_tests", + "--bot-mode" + ], + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "containment_type": "AUTO", + "dimension_sets": [ + { + "gpu": "1002:7340", + "os": "Windows-10", + "pool": "chromium.tests.gpu.experimental" + } + ], + "expiration": 21600, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_white_box_tests", + "test_id_prefix": "ninja://third_party/angle/src/tests:angle_white_box_tests/", + "use_isolated_scripts_api": true + }, + { + "args": [ + "--enable-gpu", + "--test-launcher-bot-mode", + "--test-launcher-jobs=1", + "--gtest_filter=CastStreamingApiTestWithPixelOutput.EndToEnd*:TabCaptureApiPixelTest.EndToEnd*" + ], + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "name": "tab_capture_end2end_tests", + "swarming": { + "can_use_on_swarming_builders": true, + "containment_type": "AUTO", + "dimension_sets": [ + { + "gpu": "1002:7340", + "os": "Windows-10", + "pool": "chromium.tests.gpu.experimental" + } + ], + "expiration": 21600, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "browser_tests", + "test_id_prefix": "ninja://chrome/test:browser_tests/" + }, + { + "args": [ + "--use-cmd-decoder=passthrough", + "--use-gl=angle", + "--use-gpu-in-tests" + ], + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "name": "gl_tests_passthrough", + "swarming": { + "can_use_on_swarming_builders": true, + "containment_type": "AUTO", + "dimension_sets": [ + { + "gpu": "1002:7340", + "os": "Windows-10", + "pool": "chromium.tests.gpu.experimental" + } + ], + "expiration": 21600, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "gl_tests", + "test_id_prefix": "ninja://gpu:gl_tests/" + }, + { + "args": [ + "--use-gpu-in-tests" + ], + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "containment_type": "AUTO", + "dimension_sets": [ + { + "gpu": "1002:7340", + "os": "Windows-10", + "pool": "chromium.tests.gpu.experimental" + } + ], + "expiration": 21600, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "gl_unittests", + "test_id_prefix": "ninja://ui/gl:gl_unittests/" + }, + { + "args": [ + "--use-gpu-in-tests" + ], + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "containment_type": "AUTO", + "dimension_sets": [ + { + "gpu": "1002:7340", + "os": "Windows-10", + "pool": "chromium.tests.gpu.experimental" + } + ], + "expiration": 21600, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "gles2_conform_test", + "test_id_prefix": "ninja://gpu/gles2_conform_support:gles2_conform_test/" + }, + { + "args": [ + "--use-gpu-in-tests", + "--use-angle=d3d9" + ], + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "name": "gles2_conform_d3d9_test", + "swarming": { + "can_use_on_swarming_builders": true, + "containment_type": "AUTO", + "dimension_sets": [ + { + "gpu": "1002:7340", + "os": "Windows-10", + "pool": "chromium.tests.gpu.experimental" + } + ], + "expiration": 21600, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "gles2_conform_test", + "test_id_prefix": "ninja://gpu/gles2_conform_support:gles2_conform_test/" + }, + { + "args": [ + "--use-gpu-in-tests", + "--use-angle=gl", + "--disable-gpu-sandbox" + ], + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "name": "gles2_conform_gl_test", + "swarming": { + "can_use_on_swarming_builders": true, + "containment_type": "AUTO", + "dimension_sets": [ + { + "gpu": "1002:7340", + "os": "Windows-10", + "pool": "chromium.tests.gpu.experimental" + } + ], + "expiration": 21600, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "gles2_conform_test", + "test_id_prefix": "ninja://gpu/gles2_conform_support:gles2_conform_test/" + }, + { + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "containment_type": "AUTO", + "dimension_sets": [ + { + "gpu": "1002:7340", + "os": "Windows-10", + "pool": "chromium.tests.gpu.experimental" + } + ], + "expiration": 21600, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "gpu_unittests", + "test_id_prefix": "ninja://gpu:gpu_unittests/" + }, + { + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "containment_type": "AUTO", + "dimension_sets": [ + { + "gpu": "1002:7340", + "os": "Windows-10", + "pool": "chromium.tests.gpu.experimental" + } + ], + "expiration": 21600, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "swiftshader_unittests", + "test_id_prefix": "ninja://third_party/swiftshader/tests/GLESUnitTests:swiftshader_unittests/" + }, + { + "args": [ + "--use-gpu-in-tests" + ], + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "containment_type": "AUTO", + "dimension_sets": [ + { + "gpu": "1002:7340", + "os": "Windows-10", + "pool": "chromium.tests.gpu.experimental" + } + ], + "expiration": 21600, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "vulkan_tests", + "test_id_prefix": "ninja://gpu/vulkan:vulkan_tests/" + }, + { + "args": [ + "--ignore-runtime-requirements=*" + ], + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "name": "xr_browser_tests", + "swarming": { + "can_use_on_swarming_builders": true, + "containment_type": "AUTO", + "dimension_sets": [ + { + "gpu": "1002:7340", + "os": "Windows-10", + "pool": "chromium.tests.gpu.experimental" + } + ], + "expiration": 21600, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "xr_browser_tests", + "test_id_prefix": "ninja://chrome/test:xr_browser_tests/" + } + ], "isolated_scripts": [ { "args": [ - "noop_sleep", + "angle_perftests", + "--non-telemetry=true", + "--gtest-benchmark-name=angle_perftests", + "-v", + "--one-frame-only", + "--test-timeout=100", + "--batch-size=1", + "--bot-mode", + "--max-processes=1", + "--print-test-stdout" + ], + "isolate_name": "angle_perftests", + "merge": { + "args": [ + "--smoke-test-mode" + ], + "script": "//tools/perf/process_perf_results.py" + }, + "name": "angle_perftests", + "swarming": { + "can_use_on_swarming_builders": true, + "containment_type": "AUTO", + "dimension_sets": [ + { + "gpu": "1002:7340", + "os": "Windows-10", + "pool": "chromium.tests.gpu.experimental" + } + ], + "expiration": 21600, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://third_party/angle/src/tests:angle_perftests/" + }, + { + "args": [ + "--test-machine-name", + "${buildername}", + "--git-revision=${got_angle_revision}" + ], + "isolate_name": "angle_restricted_trace_gold_tests", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "angle_restricted_trace_gold_tests", + "precommit_args": [ + "--gerrit-issue=${patch_issue}", + "--gerrit-patchset=${patch_set}", + "--buildbucket-id=${buildbucket_build_id}" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "containment_type": "AUTO", + "dimension_sets": [ + { + "gpu": "1002:7340", + "os": "Windows-10", + "pool": "chromium.tests.gpu.experimental" + } + ], + "expiration": 21600, + "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://third_party/angle/src/tests/restricted_traces:angle_restricted_trace_gold_tests/" + }, + { + "args": [ + "context_lost", "--show-stdout", "--browser=release_x64", "--passthrough", "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle" ], "isolate_name": "telemetry_gpu_integration_test", "merge": { "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "noop_sleep_tests", + "name": "context_lost_passthrough_tests", + "resultdb": { + "enable": true + }, "should_retry_with_patch": false, "swarming": { "can_use_on_swarming_builders": true, @@ -30410,6 +31722,484 @@ "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/" + }, + { + "args": [ + "depth_capture", + "--show-stdout", + "--browser=release_x64", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" + ], + "isolate_name": "telemetry_gpu_integration_test", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "depth_capture_tests", + "resultdb": { + "enable": true + }, + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "containment_type": "AUTO", + "dimension_sets": [ + { + "gpu": "1002:7340", + "os": "Windows-10", + "pool": "chromium.tests.gpu.experimental" + } + ], + "expiration": 21600, + "idempotent": false, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/" + }, + { + "args": [ + "gpu_process", + "--show-stdout", + "--browser=release_x64", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" + ], + "isolate_name": "telemetry_gpu_integration_test", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "gpu_process_launch_tests", + "resultdb": { + "enable": true + }, + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "containment_type": "AUTO", + "dimension_sets": [ + { + "gpu": "1002:7340", + "os": "Windows-10", + "pool": "chromium.tests.gpu.experimental" + } + ], + "expiration": 21600, + "idempotent": false, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/" + }, + { + "args": [ + "hardware_accelerated_feature", + "--show-stdout", + "--browser=release_x64", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" + ], + "isolate_name": "telemetry_gpu_integration_test", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "hardware_accelerated_feature_tests", + "resultdb": { + "enable": true + }, + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "containment_type": "AUTO", + "dimension_sets": [ + { + "gpu": "1002:7340", + "os": "Windows-10", + "pool": "chromium.tests.gpu.experimental" + } + ], + "expiration": 21600, + "idempotent": false, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/" + }, + { + "args": [ + "info_collection", + "--show-stdout", + "--browser=release_x64", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --force_high_performance_gpu", + "--expected-vendor-id", + "1002", + "--expected-device-id", + "7340" + ], + "isolate_name": "telemetry_gpu_integration_test", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "info_collection_tests", + "resultdb": { + "enable": true + }, + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "containment_type": "AUTO", + "dimension_sets": [ + { + "gpu": "1002:7340", + "os": "Windows-10", + "pool": "chromium.tests.gpu.experimental" + } + ], + "expiration": 21600, + "idempotent": false, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/" + }, + { + "args": [ + "maps", + "--show-stdout", + "--browser=release_x64", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle", + "--dont-restore-color-profile-after-test", + "--test-machine-name", + "${buildername}", + "--git-revision=${got_revision}" + ], + "isolate_name": "telemetry_gpu_integration_test", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "maps_pixel_passthrough_test", + "precommit_args": [ + "--gerrit-issue=${patch_issue}", + "--gerrit-patchset=${patch_set}", + "--buildbucket-id=${buildbucket_build_id}" + ], + "resultdb": { + "enable": true + }, + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "containment_type": "AUTO", + "dimension_sets": [ + { + "gpu": "1002:7340", + "os": "Windows-10", + "pool": "chromium.tests.gpu.experimental" + } + ], + "expiration": 21600, + "idempotent": false, + "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/" + }, + { + "args": [ + "pixel", + "--show-stdout", + "--browser=release_x64", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle", + "--dont-restore-color-profile-after-test", + "--test-machine-name", + "${buildername}", + "--git-revision=${got_revision}" + ], + "isolate_name": "telemetry_gpu_integration_test", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "pixel_skia_gold_passthrough_test", + "precommit_args": [ + "--gerrit-issue=${patch_issue}", + "--gerrit-patchset=${patch_set}", + "--buildbucket-id=${buildbucket_build_id}" + ], + "resultdb": { + "enable": true + }, + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "containment_type": "AUTO", + "dimension_sets": [ + { + "gpu": "1002:7340", + "os": "Windows-10", + "pool": "chromium.tests.gpu.experimental" + } + ], + "expiration": 21600, + "idempotent": false, + "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/" + }, + { + "args": [ + "../../tools/perf/run_benchmark", + "--benchmarks=rendering.desktop", + "--browser=release_x64" + ], + "isolate_name": "rendering_representative_perf_tests", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "rendering_representative_perf_tests", + "swarming": { + "can_use_on_swarming_builders": true, + "containment_type": "AUTO", + "dimension_sets": [ + { + "gpu": "1002:7340", + "os": "Windows-10", + "pool": "chromium.tests.gpu.experimental" + } + ], + "expiration": 21600, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://chrome/test:rendering_representative_perf_tests/" + }, + { + "args": [ + "screenshot_sync", + "--show-stdout", + "--browser=release_x64", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle", + "--dont-restore-color-profile-after-test" + ], + "isolate_name": "telemetry_gpu_integration_test", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "screenshot_sync_passthrough_tests", + "resultdb": { + "enable": true + }, + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "containment_type": "AUTO", + "dimension_sets": [ + { + "gpu": "1002:7340", + "os": "Windows-10", + "pool": "chromium.tests.gpu.experimental" + } + ], + "expiration": 21600, + "idempotent": false, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/" + }, + { + "args": [ + "trace_test", + "--show-stdout", + "--browser=release_x64", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc" + ], + "isolate_name": "telemetry_gpu_integration_test", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "trace_test", + "resultdb": { + "enable": true + }, + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "containment_type": "AUTO", + "dimension_sets": [ + { + "gpu": "1002:7340", + "os": "Windows-10", + "pool": "chromium.tests.gpu.experimental" + } + ], + "expiration": 21600, + "idempotent": false, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/" + }, + { + "args": [ + "webgl_conformance", + "--show-stdout", + "--browser=release_x64", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-gl=angle --use-angle=d3d11 --use-cmd-decoder=passthrough --force_high_performance_gpu", + "--webgl-conformance-version=2.0.1", + "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl2_conformance_tests_output.json" + ], + "isolate_name": "telemetry_gpu_integration_test", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "webgl2_conformance_d3d11_passthrough_tests", + "resultdb": { + "enable": true + }, + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "containment_type": "AUTO", + "dimension_sets": [ + { + "gpu": "1002:7340", + "os": "Windows-10", + "pool": "chromium.tests.gpu.experimental" + } + ], + "expiration": 21600, + "idempotent": false, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 20 + }, + "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/" + }, + { + "args": [ + "webgl_conformance", + "--show-stdout", + "--browser=release_x64", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-gl=angle --use-angle=d3d11 --use-cmd-decoder=passthrough --force_high_performance_gpu", + "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl_conformance_tests_output.json" + ], + "isolate_name": "telemetry_gpu_integration_test", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "webgl_conformance_d3d11_passthrough_tests", + "resultdb": { + "enable": true + }, + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "containment_type": "AUTO", + "dimension_sets": [ + { + "gpu": "1002:7340", + "os": "Windows-10", + "pool": "chromium.tests.gpu.experimental" + } + ], + "expiration": 21600, + "idempotent": false, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 2 + }, + "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/" + }, + { + "args": [ + "webgl_conformance", + "--show-stdout", + "--browser=release_x64", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-gl=angle --use-angle=d3d9 --use-cmd-decoder=passthrough --force_high_performance_gpu", + "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl_conformance_tests_output.json" + ], + "isolate_name": "telemetry_gpu_integration_test", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "webgl_conformance_d3d9_passthrough_tests", + "resultdb": { + "enable": true + }, + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "containment_type": "AUTO", + "dimension_sets": [ + { + "gpu": "1002:7340", + "os": "Windows-10", + "pool": "chromium.tests.gpu.experimental" + } + ], + "expiration": 21600, + "idempotent": false, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 2 + }, + "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/" + }, + { + "args": [ + "webgl_conformance", + "--show-stdout", + "--browser=release_x64", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-angle=vulkan --use-cmd-decoder=passthrough --force_high_performance_gpu" + ], + "isolate_name": "telemetry_gpu_integration_test", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "webgl_conformance_vulkan_passthrough_tests", + "resultdb": { + "enable": true + }, + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "containment_type": "AUTO", + "dimension_sets": [ + { + "gpu": "1002:7340", + "os": "Windows-10", + "pool": "chromium.tests.gpu.experimental" + } + ], + "expiration": 21600, + "idempotent": false, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 2 + }, + "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/" } ] },
diff --git a/testing/buildbot/test_suite_exceptions.pyl b/testing/buildbot/test_suite_exceptions.pyl index 3c9f115..8aa751ba 100644 --- a/testing/buildbot/test_suite_exceptions.pyl +++ b/testing/buildbot/test_suite_exceptions.pyl
@@ -2436,6 +2436,11 @@ '--browser=release_x64', ], }, + 'Win10 FYI x64 Release (AMD RX 5500 XT)': { + 'args': [ + '--browser=release_x64', + ], + }, 'Win10 FYI x64 Release (Intel HD 630)': { 'args': [ '--browser=release_x64',
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl index c709c9b..140e73b 100644 --- a/testing/buildbot/test_suites.pyl +++ b/testing/buildbot/test_suites.pyl
@@ -5718,7 +5718,7 @@ ], # TODO(crbug.com/1080424): Merge with an existing set of tests such as - # gpu_fyi_linux_intel_and_nvidia_release_telemetry_tests once all CrOS tests + # gpu_fyi_linux_release_telemetry_tests once all CrOS tests # have been enabled. 'gpu_fyi_chromeos_release_telemetry_tests': [ 'gpu_common_and_optional_telemetry_tests', @@ -5733,6 +5733,15 @@ # 'gpu_webgl_conformance_gl_passthrough_telemetry_tests', ], + 'gpu_fyi_linux_amd_r7_240_release_telemetry_tests': [ + 'gpu_common_and_optional_telemetry_tests', + 'gpu_passthrough_telemetry_tests', + 'gpu_validating_telemetry_tests', + 'gpu_webgl2_conformance_validating_telemetry_tests', + 'gpu_webgl_conformance_gl_passthrough_telemetry_tests', + 'gpu_webgl_conformance_validating_telemetry_tests', + ], + 'gpu_fyi_linux_debug_gtests': [ 'gpu_angle_end2end_gtests', 'gpu_angle_unit_gtests', @@ -5743,12 +5752,10 @@ 'gpu_swiftshader_gtests', ], - 'gpu_fyi_linux_intel_and_nvidia_release_telemetry_tests': [ + 'gpu_fyi_linux_debug_telemetry_tests': [ 'gpu_common_and_optional_telemetry_tests', 'gpu_passthrough_telemetry_tests', 'gpu_validating_telemetry_tests', - 'gpu_webgl2_conformance_gl_passthrough_telemetry_tests', - 'gpu_webgl2_conformance_validating_telemetry_tests', 'gpu_webgl_conformance_gl_passthrough_telemetry_tests', 'gpu_webgl_conformance_validating_telemetry_tests', ], @@ -5787,19 +5794,12 @@ 'gpu_common_and_optional_telemetry_tests', 'gpu_passthrough_telemetry_tests', 'gpu_validating_telemetry_tests', + 'gpu_webgl2_conformance_gl_passthrough_telemetry_tests', 'gpu_webgl2_conformance_validating_telemetry_tests', 'gpu_webgl_conformance_gl_passthrough_telemetry_tests', 'gpu_webgl_conformance_validating_telemetry_tests', ], - 'gpu_fyi_linux_telemetry_tests': [ - 'gpu_common_and_optional_telemetry_tests', - 'gpu_passthrough_telemetry_tests', - 'gpu_validating_telemetry_tests', - 'gpu_webgl_conformance_gl_passthrough_telemetry_tests', - 'gpu_webgl_conformance_validating_telemetry_tests', - ], - 'gpu_fyi_mac_debug_gtests': [ 'gpu_angle_end2end_gtests', 'gpu_angle_unit_gtests', @@ -5887,6 +5887,15 @@ 'gpu_swiftshader_gtests', ], + 'gpu_fyi_win_amd_release_telemetry_tests': [ + 'gpu_common_and_optional_telemetry_tests', + 'gpu_passthrough_telemetry_tests', + 'gpu_webgl2_conformance_d3d11_passthrough_telemetry_tests', + 'gpu_webgl_conformance_d3d11_passthrough_telemetry_tests', + 'gpu_webgl_conformance_d3d9_passthrough_telemetry_tests', + 'gpu_webgl_conformance_vulkan_passthrough_telemetry_tests', + ], + 'gpu_fyi_win_debug_telemetry_tests': [ 'gpu_common_and_optional_telemetry_tests', 'gpu_passthrough_telemetry_tests',
diff --git a/testing/buildbot/waterfalls.pyl b/testing/buildbot/waterfalls.pyl index f2b5b5ef3..8e6b8ad 100644 --- a/testing/buildbot/waterfalls.pyl +++ b/testing/buildbot/waterfalls.pyl
@@ -3725,7 +3725,7 @@ ], 'test_suites': { 'gtest_tests': 'gpu_fyi_linux_debug_gtests', - 'gpu_telemetry_tests': 'gpu_fyi_linux_telemetry_tests', + 'gpu_telemetry_tests': 'gpu_fyi_linux_debug_telemetry_tests', }, }, 'Linux FYI Experimental Release (Intel HD 630)': { @@ -3755,7 +3755,7 @@ 'test_suites': { 'gtest_tests': 'gpu_fyi_linux_release_and_dawn_gtests', 'isolated_scripts': 'gpu_angle_perf_smoke_isolated_scripts', - 'gpu_telemetry_tests': 'gpu_fyi_linux_intel_and_nvidia_release_telemetry_tests', + 'gpu_telemetry_tests': 'gpu_fyi_linux_release_telemetry_tests', }, }, 'Linux FYI GPU TSAN Release': { @@ -3795,7 +3795,7 @@ ], 'test_suites': { 'gtest_tests': 'gpu_fyi_linux_release_gtests', - 'gpu_telemetry_tests': 'gpu_fyi_linux_release_telemetry_tests', + 'gpu_telemetry_tests': 'gpu_fyi_linux_amd_r7_240_release_telemetry_tests', }, }, 'Linux FYI Release (AMD RX 5500 XT)': { @@ -3809,7 +3809,9 @@ 'linux_amd_rx_5500_xt', ], 'test_suites': { - 'gpu_telemetry_tests': 'gpu_noop_sleep_telemetry_test', + 'gtest_tests': 'gpu_fyi_linux_release_gtests', + 'isolated_scripts': 'gpu_angle_perf_smoke_isolated_scripts', + 'gpu_telemetry_tests': 'gpu_fyi_linux_release_telemetry_tests', }, }, 'Linux FYI Release (Intel HD 630)': { @@ -3820,7 +3822,7 @@ ], 'test_suites': { 'gtest_tests': 'gpu_fyi_linux_release_gtests', - 'gpu_telemetry_tests': 'gpu_fyi_linux_intel_and_nvidia_release_telemetry_tests', + 'gpu_telemetry_tests': 'gpu_fyi_linux_release_telemetry_tests', 'isolated_scripts': 'gpu_angle_restricted_trace_gold_isolated_scripts', }, }, @@ -3832,7 +3834,7 @@ ], 'test_suites': { 'gtest_tests': 'gpu_fyi_linux_release_gtests', - 'gpu_telemetry_tests': 'gpu_fyi_linux_intel_and_nvidia_release_telemetry_tests', + 'gpu_telemetry_tests': 'gpu_fyi_linux_release_telemetry_tests', 'isolated_scripts': 'gpu_angle_restricted_trace_gold_isolated_scripts', }, }, @@ -3844,7 +3846,7 @@ ], 'test_suites': { 'gtest_tests': 'gpu_fyi_linux_release_gtests', - 'gpu_telemetry_tests': 'gpu_fyi_linux_intel_and_nvidia_release_telemetry_tests', + 'gpu_telemetry_tests': 'gpu_fyi_linux_release_telemetry_tests', 'isolated_scripts': 'gpu_angle_isolated_scripts', }, }, @@ -4266,7 +4268,9 @@ 'win10_amd_rx_5500_xt', ], 'test_suites': { - 'gpu_telemetry_tests': 'gpu_noop_sleep_telemetry_test', + 'gtest_tests': 'gpu_fyi_win_gtests', + 'isolated_scripts': 'gpu_angle_and_desktop_representative_perf_fyi_isolated_scripts', + 'gpu_telemetry_tests': 'gpu_fyi_win_amd_release_telemetry_tests', }, }, 'Win10 FYI x64 Release (Intel HD 630)': {
diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/features.cc index d68e347..cbf5b3db 100644 --- a/third_party/blink/common/features.cc +++ b/third_party/blink/common/features.cc
@@ -233,6 +233,12 @@ const base::Feature kWebRtcHideLocalIpsWithMdns{ "WebRtcHideLocalIpsWithMdns", base::FEATURE_ENABLED_BY_DEFAULT}; +// Causes WebRTC to not set the color space of video frames on the receive side +// in case it's unspecified. Otherwise we will guess that the color space is +// BT709. http://crbug.com/1129243 +const base::Feature kWebRtcIgnoreUnspecifiedColorSpace{ + "WebRtcIgnoreUnspecifiedColorSpace", base::FEATURE_DISABLED_BY_DEFAULT}; + // When enabled, wake ups from throttleable TaskQueues are limited to 1 per // minute in a page that has been backgrounded for 5 minutes. //
diff --git a/third_party/blink/common/origin_trials/trial_token.cc b/third_party/blink/common/origin_trials/trial_token.cc index ce88371..8bf0ad8 100644 --- a/third_party/blink/common/origin_trials/trial_token.cc +++ b/third_party/blink/common/origin_trials/trial_token.cc
@@ -238,13 +238,10 @@ is_third_party = is_third_party_value->GetBool(); } - // The |usage| field is optional and can only be set if |isThirdParty| flag - // is true. If found, ensure its value is either empty or "subset". + // The |usage| field is optional. If found, ensure its value is either empty + // or "subset". std::string* usage_value = datadict->FindStringKey("usage"); if (usage_value) { - if (!is_third_party) { - return nullptr; - } if (usage_value->empty()) { usage = UsageRestriction::kNone; } else if (*usage_value == kUsageSubset) {
diff --git a/third_party/blink/common/origin_trials/trial_token_unittest.cc b/third_party/blink/common/origin_trials/trial_token_unittest.cc index 7f7e4a1..1cecd950 100644 --- a/third_party/blink/common/origin_trials/trial_token_unittest.cc +++ b/third_party/blink/common/origin_trials/trial_token_unittest.cc
@@ -263,6 +263,14 @@ "{\"origin\": \"https://example.com:443\", \"isSubdomain\": true, " "\"feature\": \"Frobulate\", \"expiry\": 1458766277}"; +const char kUsageEmptyTokenJSON[] = + "{\"origin\": \"https://valid.example.com:443\", \"usage\": \"\", " + "\"feature\": \"Frobulate\", \"expiry\": 1458766277}"; + +const char kUsageSubsetTokenJSON[] = + "{\"origin\": \"https://valid.example.com:443\", \"usage\": \"subset\", " + "\"feature\": \"Frobulate\", \"expiry\": 1458766277}"; + const char kSampleNonThirdPartyTokenJSON[] = "{\"origin\": \"https://valid.example.com:443\", \"isThirdParty\": false, " "\"feature\": \"Frobulate\", \"expiry\": 1458766277}"; @@ -327,10 +335,6 @@ "{\"origin\": \"https://a.a\", \"isThirdParty\": true, \"usage\": " "\"cycle\", \"feature\": \"a\", " "\"expiry\": 1458766277}", - // usage in non third party token - "{\"origin\": \"https://a.a\", \"isThirdParty\": false, \"usage\": " - "\"subset\", \"feature\": \"a\", " - "\"expiry\": 1458766277}", }; // Valid token JSON. The feature name matches matches kExpectedLongFeatureName @@ -994,6 +998,7 @@ EXPECT_FALSE(token->match_subdomains()); EXPECT_EQ(expected_origin_, token->origin()); EXPECT_EQ(expected_expiry_, token->expiry_time()); + EXPECT_EQ(TrialToken::UsageRestriction::kNone, token->usage_restriction()); } TEST_P(TrialTokenParseTest, ParseValidNonSubdomainToken) { @@ -1135,6 +1140,26 @@ EXPECT_EQ(expected_expiry_, token->expiry_time()); } +TEST_F(TrialTokenTest, ParseValidUsageEmptyToken) { + std::unique_ptr<TrialToken> token = Parse(kUsageEmptyTokenJSON, kVersion3); + ASSERT_TRUE(token); + EXPECT_EQ(kExpectedFeatureName, token->feature_name()); + EXPECT_FALSE(token->is_third_party()); + EXPECT_EQ(TrialToken::UsageRestriction::kNone, token->usage_restriction()); + EXPECT_EQ(expected_origin_, token->origin()); + EXPECT_EQ(expected_expiry_, token->expiry_time()); +} + +TEST_F(TrialTokenTest, ParseValidUsageSubsetToken) { + std::unique_ptr<TrialToken> token = Parse(kUsageSubsetTokenJSON, kVersion3); + ASSERT_TRUE(token); + EXPECT_EQ(kExpectedFeatureName, token->feature_name()); + EXPECT_FALSE(token->is_third_party()); + EXPECT_EQ(TrialToken::UsageRestriction::kSubset, token->usage_restriction()); + EXPECT_EQ(expected_origin_, token->origin()); + EXPECT_EQ(expected_expiry_, token->expiry_time()); +} + TEST_F(TrialTokenTest, ParseValidThirdPartyUsageSubsetToken) { std::unique_ptr<TrialToken> token = Parse(kSampleThirdPartyTokenUsageSubsetJSON, kVersion3);
diff --git a/third_party/blink/common/origin_trials/trial_token_validator.cc b/third_party/blink/common/origin_trials/trial_token_validator.cc index 99fafa3..76948825 100644 --- a/third_party/blink/common/origin_trials/trial_token_validator.cc +++ b/third_party/blink/common/origin_trials/trial_token_validator.cc
@@ -107,8 +107,7 @@ if (policy->IsTokenDisabled(trial_token->signature())) return TrialTokenResult(OriginTrialTokenStatus::kTokenDisabled); - if (trial_token->is_third_party() && - trial_token->usage_restriction() == + if (trial_token->usage_restriction() == TrialToken::UsageRestriction::kSubset && policy->IsFeatureDisabledForUser(trial_token->feature_name())) return TrialTokenResult(OriginTrialTokenStatus::kFeatureDisabledForUser);
diff --git a/third_party/blink/common/origin_trials/trial_token_validator_unittest.cc b/third_party/blink/common/origin_trials/trial_token_validator_unittest.cc index 8433c9e..8cc3ab2 100644 --- a/third_party/blink/common/origin_trials/trial_token_validator_unittest.cc +++ b/third_party/blink/common/origin_trials/trial_token_validator_unittest.cc
@@ -167,6 +167,17 @@ "InN1YnNldCIsICJmZWF0dXJlIjogIkZyb2J1bGF0ZVRoaXJkUGFydHkiLCAiZXhw" "aXJ5IjogMjAwMDAwMDAwMH0="; +// Well-formed token, for first party, with usage set to user subset exclusion. +// Generate this token with the command (in tools/origin_trials): +// generate_token.py valid.example.com FrobulateThirdParty +// --version 3 --usage-restriction subset --expire-timestamp=2000000000 +const char kUsageSubsetToken[] = + "Axi0wjIp8gaGr/" + "pTPzwrHqeWXnmhCiZhE2edsJ9fHX25GV6A8zg1fCv27qhBNnbxjqDpU0a+" + "xKScEiqKK1MS3QUAAAB2eyJvcmlnaW4iOiAiaHR0cHM6Ly92YWxpZC5leGFtcGxlLmNvbTo0ND" + "MiLCAidXNhZ2UiOiAic3Vic2V0IiwgImZlYXR1cmUiOiAiRnJvYnVsYXRlVGhpcmRQYXJ0eSIs" + "ICJleHBpcnkiOiAyMDAwMDAwMDAwfQ=="; + // This timestamp is set to a time after the expiry timestamp of kExpiredToken, // but before the expiry timestamp of kValidToken. double kNowTimestamp = 1500000000; @@ -372,8 +383,24 @@ validator_.ValidateToken(kSampleToken, appropriate_origin_, Now()) .status); } +TEST_F(TrialTokenValidatorTest, + ValidatorRespectsDisabledFeaturesForUserWithFirstPartyToken) { + // Token should be valid if the feature is not disabled for user. + TrialTokenResult result = + validator_.ValidateToken(kUsageSubsetToken, appropriate_origin_, Now()); + EXPECT_EQ(blink::OriginTrialTokenStatus::kSuccess, result.status); + EXPECT_EQ(kAppropriateThirdPartyFeatureName, result.feature_name); + EXPECT_EQ(kSampleTokenExpiryTime, result.expiry_time); + // Token should be invalid when the feature is disabled for user. + DisableFeatureForUser(kAppropriateThirdPartyFeatureName); + EXPECT_EQ( + blink::OriginTrialTokenStatus::kFeatureDisabledForUser, + validator_.ValidateToken(kUsageSubsetToken, appropriate_origin_, Now()) + .status); +} -TEST_F(TrialTokenValidatorTest, ValidatorRespectsDisabledFeaturesForUser) { +TEST_F(TrialTokenValidatorTest, + ValidatorRespectsDisabledFeaturesForUserWithThirdPartyToken) { // Token should be valid if the feature is not disabled for user. TrialTokenResult result = validator_.ValidateToken( kThirdPartyUsageSubsetToken, inappropriate_origin_, &appropriate_origin_,
diff --git a/third_party/blink/perf_tests/service_worker/cold-fetch.html b/third_party/blink/perf_tests/service_worker/cold-fetch.html new file mode 100644 index 0000000..3199b06f --- /dev/null +++ b/third_party/blink/perf_tests/service_worker/cold-fetch.html
@@ -0,0 +1,65 @@ +<!DOCTYPE html> +<html> +<head> +<script src='../resources/runner.js'></script> +</head> +<body> +<script> +// serviceWorkerPerfTools is defined in service_worker_perf.js. +serviceWorkerPerfTools.enable(); + +let isDone = false; +function testDone() { + isDone = true; + serviceWorkerPerfTools.quit(); +} + +function addIframe(url) { + return new Promise((resolve) => { + var frame = document.createElement('iframe'); + frame.src = url; + frame.onload = () => { resolve(frame); }; + document.body.appendChild(frame); + }); +} + +function waitForWorkerActive(worker) { + return new Promise((resolve) => { + worker.addEventListener('statechange', () => { + if (worker.state == 'activated') + resolve(); + }); + }); +} + +async function runTest() { + const script = '/service_worker/resources/fetch-service-worker.js'; + const scope = '/service_worker/resources/'; + const client = '/service_worker/resources/simple.html'; + const resource = '/service_worker/resources/data/1K_0.txt'; + + const registration = await navigator.serviceWorker.register( + script, { scope: scope }); + await waitForWorkerActive(registration.installing); + const frame = await addIframe(client); + + while (!isDone) { + await serviceWorkerPerfTools.stopWorkers(); + const startTime = performance.now(); + const response = await frame.contentWindow.fetch(resource); + PerfTestRunner.measureValueAsync(performance.now() - startTime); + } + return; +} + +PerfTestRunner.startMeasureValuesAsync({ + description: 'Measure the performance of fetch with service worker' + + ' not started.', + unit: 'ms', + run: runTest, + done: testDone, + iterationCount: 30 +}); +</script> +</body> +</html>
diff --git a/third_party/blink/perf_tests/service_worker/hot-fetch.html b/third_party/blink/perf_tests/service_worker/hot-fetch.html new file mode 100644 index 0000000..562091b --- /dev/null +++ b/third_party/blink/perf_tests/service_worker/hot-fetch.html
@@ -0,0 +1,59 @@ +<!DOCTYPE html> +<html> +<head> +<script src='../resources/runner.js'></script> +</head> +<body> +<script> +let isDone = false; +function testDone() { + isDone = true; +} + +function addIframe(url) { + return new Promise((resolve) => { + var frame = document.createElement('iframe'); + frame.src = url; + frame.onload = () => { resolve(frame); }; + document.body.appendChild(frame); + }); +} + +function waitForWorkerActive(worker) { + return new Promise((resolve) => { + worker.addEventListener('statechange', () => { + if (worker.state == 'activated') + resolve(); + }); + }); +} + +async function runTest() { + const script = '/service_worker/resources/fetch-service-worker.js'; + const scope = '/service_worker/resources/'; + const client = '/service_worker/resources/simple.html'; + const resource = '/service_worker/resources/data/1K_0.txt'; + + const registration = await navigator.serviceWorker.register( + script, { scope: scope }); + await waitForWorkerActive(registration.installing); + const frame = await addIframe(client); + + while (!isDone) { + const startTime = performance.now(); + const response = await frame.contentWindow.fetch(resource); + PerfTestRunner.measureValueAsync(performance.now() - startTime); + } + return; +} + +PerfTestRunner.startMeasureValuesAsync({ + description: 'Measure the performance of fetch with live service worker.', + unit: 'ms', + run: runTest, + done: testDone, + iterationCount: 30 +}); +</script> +</body> +</html>
diff --git a/third_party/blink/perf_tests/service_worker/register-and-unregister.html b/third_party/blink/perf_tests/service_worker/register-and-unregister.html new file mode 100644 index 0000000..20161a5 --- /dev/null +++ b/third_party/blink/perf_tests/service_worker/register-and-unregister.html
@@ -0,0 +1,39 @@ +<!DOCTYPE html> +<html> +<head> +<script src='../resources/runner.js'></script> +</head> +<body> +<script> +let isDone = false; +function testDone() { + isDone = true; +} + +async function runTest() { + let index = 0; + while (!isDone) { + const script = + `/service_worker/resources/service-worker-${index}.generated.js`; + const scope = `/service_worker/resources/scope_${index}`; + + const startTime = performance.now(); + const registration = await navigator.serviceWorker.register( + script, { scope: scope }); + await registration.unregister(); + PerfTestRunner.measureValueAsync(performance.now() - startTime); + index++; + } + return; +} + +PerfTestRunner.startMeasureValuesAsync({ + description: 'Measure performance of register and unregister service worker.', + unit: 'ms', + run: runTest, + done: testDone, + iterationCount: 30 +}); +</script> +</body> +</html>
diff --git a/third_party/blink/perf_tests/service_worker/resources/fetch-service-worker.js b/third_party/blink/perf_tests/service_worker/resources/fetch-service-worker.js new file mode 100644 index 0000000..c6ee2d3 --- /dev/null +++ b/third_party/blink/perf_tests/service_worker/resources/fetch-service-worker.js
@@ -0,0 +1,15 @@ +self.addEventListener('install', (event) => { + event.waitUntil(caches.open('test_cache').then((cache) => { + return cache.add('/service_worker/resources/data/1K_0.txt'); + })); +}); + +self.addEventListener('fetch', (event) => { + event.respondWith(async function() { + const cachedResponse = await caches.match(event.request); + if (cachedResponse) { + return cachedResponse; + } + return fetch(event.request); + }()); +});
diff --git a/third_party/blink/perf_tests/service_worker/resources/simple.html b/third_party/blink/perf_tests/service_worker/resources/simple.html new file mode 100644 index 0000000..0c3e3e7 --- /dev/null +++ b/third_party/blink/perf_tests/service_worker/resources/simple.html
@@ -0,0 +1,3 @@ +<!DOCTYPE html> +<title>Simple</title> +Here's a simple html file.
diff --git a/third_party/blink/perf_tests/service_worker/update.html b/third_party/blink/perf_tests/service_worker/update.html new file mode 100644 index 0000000..489b4d9 --- /dev/null +++ b/third_party/blink/perf_tests/service_worker/update.html
@@ -0,0 +1,48 @@ +<!DOCTYPE html> +<html> +<head> +<script src='../resources/runner.js'></script> +</head> +<body> +<script> +let isDone = false; +function testDone() { + isDone = true; +} + +function waitForWorkerActive(worker) { + return new Promise((resolve) => { + worker.addEventListener('statechange', () => { + if (worker.state == 'activated') + resolve(); + }); + }); +} + +async function runTest() { + const script = + `/service_worker/resources/changing-service-worker.generated.js`; + const scope = `/service_worker/resources/`; + const registration = await navigator.serviceWorker.register( + script, { scope: scope }); + await waitForWorkerActive(registration.installing); + + while (!isDone) { + const registrations = await navigator.serviceWorker.getRegistrations(); + const startTime = performance.now(); + await registrations[0].update(); + PerfTestRunner.measureValueAsync(performance.now() - startTime); + } + return; +} + +PerfTestRunner.startMeasureValuesAsync({ + description: 'Measure performance of update service worker.', + unit: 'ms', + run: runTest, + done: testDone, + iterationCount: 30 +}); +</script> +</body> +</html>
diff --git a/third_party/blink/public/common/features.h b/third_party/blink/public/common/features.h index abd3314..db5d622 100644 --- a/third_party/blink/public/common/features.h +++ b/third_party/blink/public/common/features.h
@@ -67,6 +67,8 @@ kWebMeasureMemoryViaPerformanceManager; BLINK_COMMON_EXPORT extern const base::Feature kWebRtcMultiplexCodec; BLINK_COMMON_EXPORT extern const base::Feature kWebRtcHideLocalIpsWithMdns; +BLINK_COMMON_EXPORT extern const base::Feature + kWebRtcIgnoreUnspecifiedColorSpace; BLINK_COMMON_EXPORT extern const base::Feature kIntensiveWakeUpThrottling; BLINK_COMMON_EXPORT extern const char
diff --git a/third_party/blink/public/devtools_protocol/browser_protocol.pdl b/third_party/blink/public/devtools_protocol/browser_protocol.pdl index 3cbe7ebd..e8e390f 100644 --- a/third_party/blink/public/devtools_protocol/browser_protocol.pdl +++ b/third_party/blink/public/devtools_protocol/browser_protocol.pdl
@@ -4276,6 +4276,7 @@ SignedExchange Ping CSPViolationReport + Preflight Other # Unique loader identifier. @@ -4682,6 +4683,7 @@ script preload SignedExchange + preflight other # Initiator JavaScript stack trace, set for Script only. optional Runtime.StackTrace stack @@ -4693,6 +4695,8 @@ # Initiator column number, set for Parser type or for Script type (when script is importing # module) (0-based). optional number columnNumber + # Set if another request triggered this request (e.g. preflight). + optional RequestId requestId # Cookie object type Cookie extends object @@ -5680,6 +5684,8 @@ optional BoxStyle rowGapSpace # Style of empty space caused by columns gaps (gap/column-gap). optional BoxStyle columnGapSpace + # Style of the self-alignment line (align-items). + optional LineStyle crossAlignment # Style information for drawing a line. type LineStyle extends object
diff --git a/third_party/blink/renderer/bindings/generated_in_core.gni b/third_party/blink/renderer/bindings/generated_in_core.gni index d824770d..7bc97a2 100644 --- a/third_party/blink/renderer/bindings/generated_in_core.gni +++ b/third_party/blink/renderer/bindings/generated_in_core.gni
@@ -185,14 +185,12 @@ "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_keyframe_animation_options.h", "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_keyframe_effect_options.cc", "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_keyframe_effect_options.h", - "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_measure_memory.cc", - "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_measure_memory.h", - "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_measure_memory_breakdown.cc", - "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_measure_memory_breakdown.h", "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_media_query_list_event_init.cc", "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_media_query_list_event_init.h", "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_memory_attribution.cc", "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_memory_attribution.h", + "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_memory_attribution_container.cc", + "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_memory_attribution_container.h", "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_memory_breakdown_entry.cc", "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_memory_breakdown_entry.h", "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_memory_measurement.cc",
diff --git a/third_party/blink/renderer/core/css/document_style_sheet_collection.cc b/third_party/blink/renderer/core/css/document_style_sheet_collection.cc index ab9f78d..bb6ff07 100644 --- a/third_party/blink/renderer/core/css/document_style_sheet_collection.cc +++ b/third_party/blink/renderer/core/css/document_style_sheet_collection.cc
@@ -30,7 +30,6 @@ #include "third_party/blink/renderer/core/css/document_style_sheet_collector.h" #include "third_party/blink/renderer/core/css/resolver/style_resolver.h" -#include "third_party/blink/renderer/core/css/resolver/viewport_style_resolver.h" #include "third_party/blink/renderer/core/css/style_change_reason.h" #include "third_party/blink/renderer/core/css/style_engine.h" #include "third_party/blink/renderer/core/css/style_sheet_candidate.h" @@ -127,22 +126,4 @@ ApplyActiveStyleSheetChanges(*collection); } -void DocumentStyleSheetCollection::CollectViewportRules( - ViewportStyleResolver& viewport_resolver) { - for (Node* node : style_sheet_candidate_nodes_) { - StyleSheetCandidate candidate(*node); - - if (candidate.IsImport()) - continue; - StyleSheet* sheet = candidate.Sheet(); - if (!sheet) - continue; - if (!candidate.CanBeActivated( - GetDocument().GetStyleEngine().PreferredStylesheetSetName())) - continue; - viewport_resolver.CollectViewportRulesFromAuthorSheet( - To<CSSStyleSheet>(*sheet)); - } -} - } // namespace blink
diff --git a/third_party/blink/renderer/core/css/document_style_sheet_collection.h b/third_party/blink/renderer/core/css/document_style_sheet_collection.h index 6abcc04..d234c2c8 100644 --- a/third_party/blink/renderer/core/css/document_style_sheet_collection.h +++ b/third_party/blink/renderer/core/css/document_style_sheet_collection.h
@@ -37,7 +37,6 @@ class DocumentStyleSheetCollector; class StyleEngine; class TreeScope; -class ViewportStyleResolver; class DocumentStyleSheetCollection final : public TreeScopeStyleSheetCollection { @@ -49,7 +48,6 @@ void UpdateActiveStyleSheets(StyleEngine&); void CollectStyleSheets(StyleEngine&, DocumentStyleSheetCollector&); - void CollectViewportRules(ViewportStyleResolver&); void Trace(Visitor* visitor) const override { TreeScopeStyleSheetCollection::Trace(visitor);
diff --git a/third_party/blink/renderer/core/css/resolver/viewport_style_resolver.cc b/third_party/blink/renderer/core/css/resolver/viewport_style_resolver.cc index 978975c..1501af0 100644 --- a/third_party/blink/renderer/core/css/resolver/viewport_style_resolver.cc +++ b/third_party/blink/renderer/core/css/resolver/viewport_style_resolver.cc
@@ -72,10 +72,7 @@ } void ViewportStyleResolver::Reset() { - viewport_dependent_media_query_results_.clear(); - device_dependent_media_query_results_.clear(); property_set_ = nullptr; - has_author_style_ = false; has_viewport_units_ = false; DCHECK(initial_style_); initial_style_->SetHasViewportUnits(false); @@ -101,92 +98,38 @@ break; } if (viewport_contents) - CollectViewportChildRules(viewport_contents->ChildRules(), - kUserAgentOrigin); + CollectViewportRules(viewport_contents->ChildRules()); if (document_->IsMobileDocument()) { - CollectViewportChildRules( - default_style_sheets.EnsureXHTMLMobileProfileStyleSheet()->ChildRules(), - kUserAgentOrigin); + CollectViewportRules( + default_style_sheets.EnsureXHTMLMobileProfileStyleSheet() + ->ChildRules()); } DCHECK(!default_style_sheets.DefaultStyleSheet()->HasViewportRule()); } -void ViewportStyleResolver::CollectViewportChildRules( - const HeapVector<Member<StyleRuleBase>>& rules, - Origin origin) { +void ViewportStyleResolver::CollectViewportRules( + const HeapVector<Member<StyleRuleBase>>& rules) { for (auto& rule : rules) { - if (auto* viewport_rule = DynamicTo<StyleRuleViewport>(rule.Get())) { - AddViewportRule(*viewport_rule, origin); - } else if (auto* media_rule = DynamicTo<StyleRuleMedia>(rule.Get())) { - if (!media_rule->MediaQueries() || - initial_viewport_medium_->Eval( - *media_rule->MediaQueries(), - &viewport_dependent_media_query_results_, - &device_dependent_media_query_results_)) - CollectViewportChildRules(media_rule->ChildRules(), origin); - } else if (auto* supports_rule = DynamicTo<StyleRuleSupports>(rule.Get())) { - if (supports_rule->ConditionIsSupported()) - CollectViewportChildRules(supports_rule->ChildRules(), origin); - } + if (auto* viewport_rule = DynamicTo<StyleRuleViewport>(rule.Get())) + AddViewportRule(*viewport_rule); } } -void ViewportStyleResolver::CollectViewportRulesFromImports( - StyleSheetContents& contents) { - for (const auto& import_rule : contents.ImportRules()) { - if (!import_rule->GetStyleSheet()) - continue; - if (!import_rule->GetStyleSheet()->HasViewportRule()) - continue; - if (import_rule->MediaQueries() && - initial_viewport_medium_->Eval(*import_rule->MediaQueries(), - &viewport_dependent_media_query_results_, - &device_dependent_media_query_results_)) - CollectViewportRulesFromAuthorSheetContents( - *import_rule->GetStyleSheet()); - } -} - -void ViewportStyleResolver::CollectViewportRulesFromAuthorSheetContents( - StyleSheetContents& contents) { - CollectViewportRulesFromImports(contents); - if (contents.HasViewportRule()) - CollectViewportChildRules(contents.ChildRules(), kAuthorOrigin); -} - -void ViewportStyleResolver::CollectViewportRulesFromAuthorSheet( - const CSSStyleSheet& sheet) { - DCHECK(sheet.Contents()); - StyleSheetContents& contents = *sheet.Contents(); - if (!contents.HasViewportRule() && contents.ImportRules().IsEmpty()) - return; - if (sheet.MediaQueries() && - !initial_viewport_medium_->Eval(*sheet.MediaQueries(), - &viewport_dependent_media_query_results_, - &device_dependent_media_query_results_)) - return; - CollectViewportRulesFromAuthorSheetContents(contents); -} - -void ViewportStyleResolver::AddViewportRule(StyleRuleViewport& viewport_rule, - Origin origin) { +void ViewportStyleResolver::AddViewportRule(StyleRuleViewport& viewport_rule) { CSSPropertyValueSet& property_set = viewport_rule.MutableProperties(); unsigned property_count = property_set.PropertyCount(); if (!property_count) return; - if (origin == kAuthorOrigin) - has_author_style_ = true; - if (!property_set_) { property_set_ = property_set.MutableCopy(); return; } - // We cannot use mergeAndOverrideOnConflict() here because it doesn't - // respect the !important declaration (but addRespectingCascade() does). + // We cannot use MergeAndOverrideOnConflict() here because it doesn't + // respect the !important declaration (but AddRespectingCascade() does). for (unsigned i = 0; i < property_count; ++i) { CSSPropertyValueSet::PropertyReference property = property_set.PropertyAt(i); @@ -202,9 +145,7 @@ return; } - ViewportDescription description( - has_author_style_ ? ViewportDescription::kAuthorStyleSheet - : ViewportDescription::kUserAgentStyleSheet); + ViewportDescription description(ViewportDescription::kUserAgentStyleSheet); description.user_zoom = ViewportArgumentValue(CSSPropertyID::kUserZoom); description.zoom = ViewportArgumentValue(CSSPropertyID::kZoom); @@ -357,11 +298,6 @@ return; if (has_viewport_units_) needs_update_ = kResolve; - - if (initial_viewport_medium_->DidResultsChange( - viewport_dependent_media_query_results_)) { - needs_update_ = kCollectRules; - } if (needs_update_ == kNoUpdate) return; document_->ScheduleLayoutTreeUpdateIfNeeded();
diff --git a/third_party/blink/renderer/core/css/resolver/viewport_style_resolver.h b/third_party/blink/renderer/core/css/resolver/viewport_style_resolver.h index 4ce4c71f..f3a84a9 100644 --- a/third_party/blink/renderer/core/css/resolver/viewport_style_resolver.h +++ b/third_party/blink/renderer/core/css/resolver/viewport_style_resolver.h
@@ -63,15 +63,11 @@ void Reset(); void Resolve(); - enum Origin { kUserAgentOrigin, kAuthorOrigin }; enum UpdateType { kNoUpdate, kResolve, kCollectRules }; void CollectViewportRulesFromUASheets(); - void CollectViewportChildRules(const HeapVector<Member<StyleRuleBase>>&, - Origin); - void CollectViewportRulesFromImports(StyleSheetContents&); - void CollectViewportRulesFromAuthorSheetContents(StyleSheetContents&); - void AddViewportRule(StyleRuleViewport&, Origin); + void CollectViewportRules(const HeapVector<Member<StyleRuleBase>>&); + void AddViewportRule(StyleRuleViewport&); float ViewportArgumentValue(CSSPropertyID) const; Length ViewportLengthValue(CSSPropertyID); @@ -81,9 +77,6 @@ Member<MutableCSSPropertyValueSet> property_set_; Member<MediaQueryEvaluator> initial_viewport_medium_; scoped_refptr<ComputedStyle> initial_style_; - MediaQueryResultList viewport_dependent_media_query_results_; - MediaQueryResultList device_dependent_media_query_results_; - bool has_author_style_ = false; bool has_viewport_units_ = false; UpdateType needs_update_ = kCollectRules; };
diff --git a/third_party/blink/renderer/core/editing/selection_modifier_line.cc b/third_party/blink/renderer/core/editing/selection_modifier_line.cc index 8111b2a..7ee6536 100644 --- a/third_party/blink/renderer/core/editing/selection_modifier_line.cc +++ b/third_party/blink/renderer/core/editing/selection_modifier_line.cc
@@ -164,7 +164,7 @@ GetRootInlineBox().BlockDirectionPointInLine()); } const PhysicalOffset physical_offset = - cursor_.Current().OffsetInContainerBlock(); + cursor_.Current().OffsetInContainerFragment(); return cursor_.Current().Style().IsHorizontalWritingMode() ? physical_offset.top : physical_offset.left; @@ -213,7 +213,7 @@ const LogicalRect fragment_logical_rect = line.Current().ConvertChildToLogical( - cursor.Current().RectInContainerBlock()); + cursor.Current().RectInContainerFragment()); const LayoutUnit inline_min = fragment_logical_rect.offset.inline_offset; const LayoutUnit inline_max = fragment_logical_rect.offset.inline_offset + fragment_logical_rect.size.inline_size;
diff --git a/third_party/blink/renderer/core/fetch/body_stream_buffer.h b/third_party/blink/renderer/core/fetch/body_stream_buffer.h index adfede4..cf949e9 100644 --- a/third_party/blink/renderer/core/fetch/body_stream_buffer.h +++ b/third_party/blink/renderer/core/fetch/body_stream_buffer.h
@@ -43,7 +43,7 @@ ScriptState*, BytesConsumer* consumer, AbortSignal* signal, - ScriptCachedMetadataHandler* cached_meatadata_handler, + ScriptCachedMetadataHandler* cached_metadata_handler, scoped_refptr<BlobDataHandle> side_data_blob = nullptr); // Create() should be used instead of calling this constructor directly. @@ -51,12 +51,12 @@ ScriptState*, BytesConsumer* consumer, AbortSignal* signal, - ScriptCachedMetadataHandler* cached_meatadata_handler, + ScriptCachedMetadataHandler* cached_metadata_handler, scoped_refptr<BlobDataHandle> side_data_blob); BodyStreamBuffer(ScriptState*, ReadableStream* stream, - ScriptCachedMetadataHandler* cached_meatadata_handler, + ScriptCachedMetadataHandler* cached_metadata_handler, scoped_refptr<BlobDataHandle> side_data_blob = nullptr); ReadableStream* Stream() { return stream_; }
diff --git a/third_party/blink/renderer/core/inspector/inspector_highlight.cc b/third_party/blink/renderer/core/inspector/inspector_highlight.cc index aecbc12..f3de72c 100644 --- a/third_party/blink/renderer/core/inspector/inspector_highlight.cc +++ b/third_party/blink/renderer/core/inspector/inspector_highlight.cc
@@ -426,6 +426,8 @@ "rowGapSpace"); AppendBoxStyleConfig(flex_config.column_gap_space, flex_config_info, "columnGapSpace"); + AppendLineStyleConfig(flex_config.cross_alignment, flex_config_info, + "crossAlignment"); return flex_config_info; } @@ -923,6 +925,8 @@ const InspectorFlexContainerHighlightConfig& flex_container_highlight_config, float scale) { + CSSComputedStyleDeclaration* style = + MakeGarbageCollected<CSSComputedStyleDeclaration>(node, true); LocalFrameView* containing_view = node->GetDocument().View(); LayoutObject* layout_object = node->GetLayoutObject(); auto* layout_box = To<LayoutBox>(layout_object); @@ -964,6 +968,9 @@ flex_info->setValue("containerBorder", container_builder.Release()); flex_info->setArray("lines", std::move(lines_info)); flex_info->setBoolean("isHorizontalFlow", is_horizontal); + flex_info->setString( + "alignItemsStyle", + style->GetPropertyCSSValue(CSSPropertyID::kAlignItems)->CssText()); flex_info->setValue( "flexContainerHighlightConfig", BuildFlexContainerHighlightConfigInfo(flex_container_highlight_config)); @@ -1903,6 +1910,8 @@ base::Optional<BoxStyle>(InspectorHighlight::DefaultBoxStyle()); config.column_gap_space = base::Optional<BoxStyle>(InspectorHighlight::DefaultBoxStyle()); + config.cross_alignment = + base::Optional<LineStyle>(InspectorHighlight::DefaultLineStyle()); return config; }
diff --git a/third_party/blink/renderer/core/inspector/inspector_highlight.h b/third_party/blink/renderer/core/inspector/inspector_highlight.h index b3f8eff..2a40351e 100644 --- a/third_party/blink/renderer/core/inspector/inspector_highlight.h +++ b/third_party/blink/renderer/core/inspector/inspector_highlight.h
@@ -98,6 +98,7 @@ base::Optional<BoxStyle> cross_distributed_space; base::Optional<BoxStyle> row_gap_space; base::Optional<BoxStyle> column_gap_space; + base::Optional<LineStyle> cross_alignment; }; struct CORE_EXPORT InspectorHighlightConfig {
diff --git a/third_party/blink/renderer/core/inspector/inspector_overlay_agent.cc b/third_party/blink/renderer/core/inspector/inspector_overlay_agent.cc index 4d15d05..fdff389 100644 --- a/third_party/blink/renderer/core/inspector/inspector_overlay_agent.cc +++ b/third_party/blink/renderer/core/inspector/inspector_overlay_agent.cc
@@ -1541,6 +1541,8 @@ InspectorOverlayAgent::ToBoxStyle(config->getRowGapSpace(nullptr)); highlight_config->column_gap_space = InspectorOverlayAgent::ToBoxStyle(config->getColumnGapSpace(nullptr)); + highlight_config->cross_alignment = + InspectorOverlayAgent::ToLineStyle(config->getCrossAlignment(nullptr)); return highlight_config; }
diff --git a/third_party/blink/renderer/core/layout/layout_block_flow_line.cc b/third_party/blink/renderer/core/layout/layout_block_flow_line.cc index 66725a3..8b23bf7 100644 --- a/third_party/blink/renderer/core/layout/layout_block_flow_line.cc +++ b/third_party/blink/renderer/core/layout/layout_block_flow_line.cc
@@ -2447,7 +2447,7 @@ continue; PhysicalRect child_rect = child->InkOverflow(); if (!child_rect.IsEmpty()) { - child_rect.offset += child->OffsetInContainerBlock(); + child_rect.offset += child->OffsetInContainerFragment(); AddContentsVisualOverflow(child_rect); } } @@ -2511,7 +2511,7 @@ continue; const NGFragmentItem& child = *cursor.CurrentItem(); LogicalRect logical_rect = - fragment->ConvertChildToLogical(child.RectInContainerBlock()); + fragment->ConvertChildToLogical(child.RectInContainerFragment()); logical_rect.size.inline_size += 1; AddLayoutOverflow( fragment->ConvertChildToPhysical(logical_rect).ToLayoutRect());
diff --git a/third_party/blink/renderer/core/layout/layout_inline.cc b/third_party/blink/renderer/core/layout/layout_inline.cc index 8f52e6d..e07879f 100644 --- a/third_party/blink/renderer/core/layout/layout_inline.cc +++ b/third_party/blink/renderer/core/layout/layout_inline.cc
@@ -492,7 +492,7 @@ cursor.MoveTo(*this); if (cursor) { caret_rect.MoveBy( - cursor.Current().OffsetInContainerBlock().ToLayoutPoint()); + cursor.Current().OffsetInContainerFragment().ToLayoutPoint()); } } @@ -1126,19 +1126,18 @@ // inline may not start in the first fragment generated for the inline // formatting context. if (target_fragment_idx != -1) - target_fragment_idx += cursor.CurrentContainerFragmentIndex(); + target_fragment_idx += cursor.ContainerFragmentIndex(); for (; cursor; cursor.MoveToNextForSameLayoutObject()) { if (target_fragment_idx != -1 && - wtf_size_t(target_fragment_idx) != - cursor.CurrentContainerFragmentIndex()) + wtf_size_t(target_fragment_idx) != cursor.ContainerFragmentIndex()) continue; if (const NGPaintFragment* paint_fragment = cursor.Current().PaintFragment()) { // NGBoxFragmentPainter::NodeAtPoint() takes an offset that is // accumulated up to the fragment itself. Compute this offset. const PhysicalOffset child_offset = - accumulated_offset + paint_fragment->OffsetInContainerBlock(); + accumulated_offset + paint_fragment->OffsetInContainerFragment(); if (NGBoxFragmentPainter(*paint_fragment) .NodeAtPoint(result, hit_test_location, child_offset, hit_test_action)) @@ -1152,7 +1151,7 @@ // NGBoxFragmentPainter::NodeAtPoint() takes an offset that is accumulated // up to the fragment itself. Compute this offset. const PhysicalOffset child_offset = - accumulated_offset + item.OffsetInContainerBlock(); + accumulated_offset + item.OffsetInContainerFragment(); if (NGBoxFragmentPainter(cursor, item, *box_fragment) .NodeAtPoint(result, hit_test_location, child_offset, accumulated_offset, hit_test_action)) { @@ -1202,7 +1201,7 @@ NGInlineCursor cursor(*parent_cursor); cursor.MoveToIncludingCulledInline(*this); for (; cursor; cursor.MoveToNextForSameLayoutObject()) - yield(cursor.Current().RectInContainerBlock()); + yield(cursor.Current().RectInContainerFragment()); } else { DCHECK(!ContainingNGBlockFlow()); CollectCulledLineBoxRects(yield); @@ -1256,7 +1255,7 @@ cursor.MoveToIncludingCulledInline(*this); PhysicalRect bounding_box; for (; cursor; cursor.MoveToNextForSameLayoutObject()) - bounding_box.UniteIfNonZero(cursor.Current().RectInContainerBlock()); + bounding_box.UniteIfNonZero(cursor.Current().RectInContainerFragment()); return bounding_box; } @@ -1409,7 +1408,7 @@ cursor.MoveToIncludingCulledInline(*this); for (; cursor; cursor.MoveToNextForSameLayoutObject()) { PhysicalRect child_rect = cursor.Current().InkOverflow(); - child_rect.offset += cursor.Current().OffsetInContainerBlock(); + child_rect.offset += cursor.Current().OffsetInContainerFragment(); result.Unite(child_rect); } return result; @@ -1525,7 +1524,7 @@ NGInlineCursor cursor; cursor.MoveTo(*this); if (cursor) - return cursor.Current().RectInContainerBlock(); + return cursor.Current().RectInContainerFragment(); } if (const InlineFlowBox* flow_box = FirstLineBox()) return FlipForWritingMode(flow_box->FrameRect());
diff --git a/third_party/blink/renderer/core/layout/layout_replaced.cc b/third_party/blink/renderer/core/layout/layout_replaced.cc index 2de36b6..93d30845 100644 --- a/third_party/blink/renderer/core/layout/layout_replaced.cc +++ b/third_party/blink/renderer/core/layout/layout_replaced.cc
@@ -969,9 +969,9 @@ const ComputedStyle& line_style = line_box.Current().Style(); const auto writing_direction = line_style.GetWritingDirection(); const WritingModeConverter converter(writing_direction, - line_box.BoxFragment().Size()); + line_box.ContainerFragment().Size()); const LogicalRect logical_rect = - converter.ToLogical(line_box.Current().RectInContainerBlock()); + converter.ToLogical(line_box.Current().RectInContainerFragment()); return {logical_rect.offset.block_offset, logical_rect.BlockEndOffset()}; }
diff --git a/third_party/blink/renderer/core/layout/layout_text.cc b/third_party/blink/renderer/core/layout/layout_text.cc index 12dfd14..04c716c5 100644 --- a/third_party/blink/renderer/core/layout/layout_text.cc +++ b/third_party/blink/renderer/core/layout/layout_text.cc
@@ -433,7 +433,8 @@ // Compute rect of the legacy text box. LayoutRect rect = cursor.CurrentLocalRect(clamped_start, clamped_end).ToLayoutRect(); - rect.MoveBy(cursor.Current().OffsetInContainerBlock().ToLayoutPoint()); + rect.MoveBy( + cursor.Current().OffsetInContainerFragment().ToLayoutPoint()); // Compute start of the legacy text box. if (unit.AssociatedNode()) { @@ -570,7 +571,7 @@ if (cursor.Current().IsHiddenForPaint()) continue; } - yield(cursor.Current().RectInContainerBlock()); + yield(cursor.Current().RectInContainerFragment()); } return; } @@ -869,7 +870,7 @@ // All/LayoutViewHitTestTest.HitTestVerticalRL/* NGInlineCursor cursor; for (cursor.MoveTo(*this); cursor; cursor.MoveToNextForSameLayoutObject()) { - if (!EnclosingIntRect(cursor.Current().RectInContainerBlock()) + if (!EnclosingIntRect(cursor.Current().RectInContainerFragment()) .Contains(FlooredIntPoint(point))) continue; if (auto position_with_affinity = cursor.PositionForPointInChild(point)) { @@ -1727,7 +1728,7 @@ return PhysicalOffset(); NGInlineCursor cursor; cursor.MoveTo(*this); - return cursor ? cursor.Current().OffsetInContainerBlock() + return cursor ? cursor.Current().OffsetInContainerFragment() : PhysicalOffset(); } if (const auto* text_box = FirstTextBox()) { @@ -1750,10 +1751,11 @@ cursor.MoveTo(*this); if (!cursor) return; - PhysicalOffset physical_offset = cursor.Current().OffsetInContainerBlock(); + PhysicalOffset physical_offset = + cursor.Current().OffsetInContainerFragment(); if (StyleRef().GetWritingDirection().IsHorizontalLtr()) { cursor.MoveToLastForSameLayoutObject(); - logical_height = cursor.Current().RectInContainerBlock().Bottom() - + logical_height = cursor.Current().RectInContainerFragment().Bottom() - physical_offset.top; logical_starting_point = {physical_offset.left, physical_offset.top}; return; @@ -1762,7 +1764,8 @@ logical_starting_point = physical_offset.ConvertToLogical( StyleRef().GetWritingDirection(), outer_size, cursor.Current().Size()); cursor.MoveToLastForSameLayoutObject(); - PhysicalRect last_physical_rect = cursor.Current().RectInContainerBlock(); + PhysicalRect last_physical_rect = + cursor.Current().RectInContainerFragment(); LogicalOffset logical_ending_point = WritingModeConverter(StyleRef().GetWritingDirection(), outer_size) .ToLogical(last_physical_rect) @@ -2330,7 +2333,7 @@ if (status.start == status.end) continue; PhysicalRect item_rect = ComputeLocalSelectionRectForText(cursor, status); - item_rect.offset += cursor.Current().OffsetInContainerBlock(); + item_rect.offset += cursor.Current().OffsetInContainerFragment(); rect.Unite(item_rect); } return rect;
diff --git a/third_party/blink/renderer/core/layout/layout_tree_as_text.cc b/third_party/blink/renderer/core/layout/layout_tree_as_text.cc index a84ae32..3d9ec79 100644 --- a/third_party/blink/renderer/core/layout/layout_tree_as_text.cc +++ b/third_party/blink/renderer/core/layout/layout_tree_as_text.cc
@@ -456,7 +456,7 @@ const NGFragment fragment(paint_fragment->Style().GetWritingDirection(), *physical_text_fragment); WriteTextFragment(ts, paint_fragment->GetLayoutObject(), - paint_fragment->RectInContainerBlock(), + paint_fragment->RectInContainerFragment(), paint_fragment->Style(), physical_text_fragment->Text(), fragment.InlineSize()); return; @@ -467,7 +467,7 @@ item.Type() == NGFragmentItem::kGeneratedText); const LayoutUnit inline_size = item.IsHorizontal() ? item.Size().width : item.Size().height; - WriteTextFragment(ts, item.GetLayoutObject(), item.RectInContainerBlock(), + WriteTextFragment(ts, item.GetLayoutObject(), item.RectInContainerFragment(), item.Style(), item.Text(cursor.Items()), inline_size); }
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_abstract_inline_text_box.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_abstract_inline_text_box.cc index fb3349f..1aecb8a 100644 --- a/third_party/blink/renderer/core/layout/ng/inline/ng_abstract_inline_text_box.cc +++ b/third_party/blink/renderer/core/layout/ng/inline/ng_abstract_inline_text_box.cc
@@ -217,7 +217,7 @@ const NGInlineCursor& cursor = GetCursor(); if (!cursor) return LayoutRect(); - return cursor.Current().RectInContainerBlock().ToLayoutRect(); + return cursor.Current().RectInContainerFragment().ToLayoutRect(); } unsigned NGAbstractInlineTextBox::Len() const {
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_caret_rect.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_caret_rect.cc index 55fb454d..41f54b3 100644 --- a/third_party/blink/renderer/core/layout/ng/inline/ng_caret_rect.cc +++ b/third_party/blink/renderer/core/layout/ng/inline/ng_caret_rect.cc
@@ -22,8 +22,8 @@ line_box.MoveToContainingLine(); DCHECK(line_box); const PhysicalOffset offset_to_line_box = - cursor.Current().OffsetInContainerBlock() - - line_box.Current().OffsetInContainerBlock(); + cursor.Current().OffsetInContainerFragment() - + line_box.Current().OffsetInContainerFragment(); LayoutUnit caret_height = is_horizontal ? line_box.Current().Size().height : line_box.Current().Size().width; LayoutUnit caret_top = @@ -100,14 +100,14 @@ // Adjust the location to be relative to the inline formatting context. PhysicalOffset caret_location = PhysicalOffset(caret_left, caret_top) + - cursor.Current().OffsetInContainerBlock(); + cursor.Current().OffsetInContainerFragment(); const PhysicalSize caret_size(caret_width, caret_height); - const NGPhysicalBoxFragment& fragment = cursor.BoxFragment(); + const NGPhysicalBoxFragment& fragment = cursor.ContainerFragment(); NGInlineCursor line_box(cursor); line_box.MoveToContainingLine(); const PhysicalOffset line_box_offset = - line_box.Current().OffsetInContainerBlock(); + line_box.Current().OffsetInContainerFragment(); const PhysicalRect line_box_rect(line_box_offset, line_box.Current().Size()); const NGInlineBreakToken* break_token = line_box.Current().InlineBreakToken(); @@ -190,10 +190,10 @@ PhysicalRect rect = caret_rect.rect; if (caret_position.cursor.Current().Style().IsHorizontalWritingMode()) { - rect.SetY(line_box.Current().OffsetInContainerBlock().top); + rect.SetY(line_box.Current().OffsetInContainerFragment().top); rect.SetHeight(line_box.Current().Size().height); } else { - rect.SetX(line_box.Current().OffsetInContainerBlock().left); + rect.SetX(line_box.Current().OffsetInContainerFragment().left); rect.SetHeight(line_box.Current().Size().width); } return {caret_rect.layout_object, rect};
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.cc index 4aea022..1a066b6 100644 --- a/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.cc +++ b/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.cc
@@ -496,7 +496,7 @@ if (UNLIKELY(item.IsHiddenForPaint())) continue; PhysicalRect child_visual_rect = item.SelfInkOverflow(); - child_visual_rect.offset += item.OffsetInContainerBlock(); + child_visual_rect.offset += item.OffsetInContainerFragment(); visual_rect.Unite(child_visual_rect); } return visual_rect; @@ -526,7 +526,7 @@ PhysicalRect child_rect; item->GetMutableForPainting().RecalcInkOverflow(*cursor, &child_rect); if (!child_rect.IsEmpty()) { - child_rect.offset += item->OffsetInContainerBlock(); + child_rect.offset += item->OffsetInContainerFragment(); contents_ink_overflow.Unite(child_rect); } } @@ -584,7 +584,7 @@ // |contents_rect| is relative to the inline formatting context. Make it // relative to |this|. - contents_rect.offset -= OffsetInContainerBlock(); + contents_rect.offset -= OffsetInContainerFragment(); if (Type() == kLine) { // Line boxes don't have self overflow. Compute content overflow only.
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.h b/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.h index 96457d5a..ef61b80 100644 --- a/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.h +++ b/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item.h
@@ -160,8 +160,10 @@ } void SetDeltaToNextForSameLayoutObject(wtf_size_t delta) const; - const PhysicalRect& RectInContainerBlock() const { return rect_; } - const PhysicalOffset& OffsetInContainerBlock() const { return rect_.offset; } + const PhysicalRect& RectInContainerFragment() const { return rect_; } + const PhysicalOffset& OffsetInContainerFragment() const { + return rect_.offset; + } const PhysicalSize& Size() const { return rect_.size; } PhysicalRect LocalRect() const { return {PhysicalOffset(), Size()}; } void SetOffset(const PhysicalOffset& offset) { rect_.offset = offset; }
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item_test.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item_test.cc index c1cdf0b..56039f1b 100644 --- a/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item_test.cc +++ b/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_item_test.cc
@@ -175,14 +175,14 @@ const NGFragmentItem& text1 = *items_for_text[0]; EXPECT_EQ(text1.Type(), NGFragmentItem::kText); EXPECT_EQ(text1.GetLayoutObject(), layout_text); - EXPECT_EQ(text1.OffsetInContainerBlock(), PhysicalOffset()); + EXPECT_EQ(text1.OffsetInContainerFragment(), PhysicalOffset()); EXPECT_TRUE(text1.IsFirstForNode()); EXPECT_FALSE(text1.IsLastForNode()); const NGFragmentItem& text2 = *items_for_text[1]; EXPECT_EQ(text2.Type(), NGFragmentItem::kText); EXPECT_EQ(text2.GetLayoutObject(), layout_text); - EXPECT_EQ(text2.OffsetInContainerBlock(), PhysicalOffset(0, 10)); + EXPECT_EQ(text2.OffsetInContainerFragment(), PhysicalOffset(0, 10)); EXPECT_FALSE(text2.IsFirstForNode()); EXPECT_TRUE(text2.IsLastForNode()); } @@ -282,12 +282,12 @@ EXPECT_TRUE(items_for_span1[0]->IsFirstForNode()); EXPECT_FALSE(items_for_span1[0]->IsLastForNode()); EXPECT_EQ(PhysicalOffset(40, 0), - items_for_span1[0]->OffsetInContainerBlock()); + items_for_span1[0]->OffsetInContainerFragment()); EXPECT_EQ(PhysicalRect(0, 0, 40, 10), items_for_span1[0]->InkOverflow()); EXPECT_FALSE(items_for_span1[1]->IsFirstForNode()); EXPECT_TRUE(items_for_span1[1]->IsLastForNode()); EXPECT_EQ(PhysicalOffset(0, 10), - items_for_span1[1]->OffsetInContainerBlock()); + items_for_span1[1]->OffsetInContainerFragment()); EXPECT_EQ(PhysicalRect(0, 0, 40, 10), items_for_span1[1]->InkOverflow()); // "span2" doesn't wrap, produces only one fragment. @@ -298,7 +298,7 @@ EXPECT_TRUE(items_for_span2[0]->IsFirstForNode()); EXPECT_TRUE(items_for_span2[0]->IsLastForNode()); EXPECT_EQ(PhysicalOffset(0, 20), - items_for_span2[0]->OffsetInContainerBlock()); + items_for_span2[0]->OffsetInContainerFragment()); EXPECT_EQ(PhysicalRect(0, 0, 80, 10), items_for_span2[0]->InkOverflow()); }
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items_builder.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items_builder.cc index b38cd85..38d9dea 100644 --- a/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items_builder.cc +++ b/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items_builder.cc
@@ -246,7 +246,7 @@ DCHECK(!item.IsDirty()); const LogicalOffset item_offset = - converter.ToLogical(item.OffsetInContainerBlock(), item.Size()); + converter.ToLogical(item.OffsetInContainerFragment(), item.Size()); if (item.Type() == NGFragmentItem::kLine) { DCHECK(item.LineBoxFragment()); @@ -276,7 +276,7 @@ } items_.emplace_back(item_offset, item); - const PhysicalRect line_box_bounds = item.RectInContainerBlock(); + const PhysicalRect line_box_bounds = item.RectInContainerFragment(); line_converter.SetOuterSize(line_box_bounds.size); for (NGInlineCursor line = cursor.CursorForDescendants(); line; line.MoveToNext()) { @@ -284,7 +284,7 @@ DCHECK(line_child.CanReuse()); items_.emplace_back( line_converter.ToLogical( - line_child.OffsetInContainerBlock() - line_box_bounds.offset, + line_child.OffsetInContainerFragment() - line_box_bounds.offset, line_child.Size()), line_child); } @@ -340,7 +340,7 @@ unsigned descendants_count = item->DescendantsCount(); DCHECK(descendants_count); if (descendants_count) { - const PhysicalRect line_box_bounds = item->RectInContainerBlock(); + const PhysicalRect line_box_bounds = item->RectInContainerFragment(); line_converter.SetOuterSize(line_box_bounds.size); while (--descendants_count) { ++iter;
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.cc index a7416ca..8ba4f0f 100644 --- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.cc +++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.cc
@@ -529,11 +529,11 @@ return PhysicalRect(); } -const PhysicalOffset NGInlineCursorPosition::OffsetInContainerBlock() const { +const PhysicalOffset NGInlineCursorPosition::OffsetInContainerFragment() const { if (paint_fragment_) - return paint_fragment_->OffsetInContainerBlock(); + return paint_fragment_->OffsetInContainerFragment(); if (item_) - return item_->OffsetInContainerBlock(); + return item_->OffsetInContainerFragment(); NOTREACHED(); return PhysicalOffset(); } @@ -547,12 +547,13 @@ return PhysicalSize(); } -const PhysicalRect NGInlineCursorPosition::RectInContainerBlock() const { +const PhysicalRect NGInlineCursorPosition::RectInContainerFragment() const { if (paint_fragment_) { - return {paint_fragment_->OffsetInContainerBlock(), paint_fragment_->Size()}; + return {paint_fragment_->OffsetInContainerFragment(), + paint_fragment_->Size()}; } if (item_) - return item_->RectInContainerBlock(); + return item_->RectInContainerFragment(); NOTREACHED(); return PhysicalRect(); } @@ -654,12 +655,12 @@ } PhysicalRect NGInlineCursor::CurrentRectInBlockFlow() const { - PhysicalRect rect = Current().RectInContainerBlock(); + PhysicalRect rect = Current().RectInContainerFragment(); // We'll now convert the offset from being relative to the containing fragment // to being relative to the containing LayoutBlockFlow. For writing modes that // don't flip the block direction, this is easy: just add the block-size // consumed in previous fragments. - auto writing_direction = BoxFragment().Style().GetWritingDirection(); + auto writing_direction = ContainerFragment().Style().GetWritingDirection(); switch (writing_direction.GetWritingMode()) { default: rect.offset.top += previously_consumed_block_size_; @@ -676,9 +677,9 @@ const LayoutBlock* containing_block = Current().GetLayoutObject()->ContainingBlock(); DCHECK_EQ(containing_block->StyleRef().GetWritingDirection(), - BoxFragment().Style().GetWritingDirection()); + ContainerFragment().Style().GetWritingDirection()); LogicalOffset logical_offset = rect.offset.ConvertToLogical( - writing_direction, BoxFragment().Size(), rect.size); + writing_direction, ContainerFragment().Size(), rect.size); LogicalOffset logical_offset_in_flow_thread( logical_offset.inline_offset, logical_offset.block_offset + previously_consumed_block_size_); @@ -754,7 +755,7 @@ } // Try to resolve if |point| falls in a line box in block direction. const LayoutUnit child_block_offset = - child_item->OffsetInContainerBlock() + child_item->OffsetInContainerFragment() .ConvertToLogical(writing_direction, container_size, child_item->Size()) .block_offset; @@ -879,7 +880,7 @@ continue; } const LayoutUnit child_inline_offset = - child_item->OffsetInContainerBlock() + child_item->OffsetInContainerFragment() .ConvertToLogical(writing_direction, container_size, child_item->Size()) .inline_offset; @@ -945,7 +946,7 @@ const PhysicalOffset& point_in_container) const { if (auto* paint_fragment = CurrentPaintFragment()) { const PhysicalOffset point_in_child = - point_in_container - paint_fragment->OffsetInContainerBlock(); + point_in_container - paint_fragment->OffsetInContainerFragment(); return paint_fragment->PositionForPoint(point_in_child); } DCHECK(CurrentItem()); @@ -953,7 +954,7 @@ switch (child_item.Type()) { case NGFragmentItem::kText: return child_item.PositionForPointInText( - point_in_container - child_item.OffsetInContainerBlock(), *this); + point_in_container - child_item.OffsetInContainerFragment(), *this); case NGFragmentItem::kGeneratedText: break; case NGFragmentItem::kBox: @@ -965,7 +966,7 @@ // Example: <b style="display:inline-block"><div>b</div></b> // [1] NGInlineCursorTest.PositionForPointInChildBlockChildren return child_item.GetLayoutObject()->PositionForPoint( - point_in_container - child_item.OffsetInContainerBlock()); + point_in_container - child_item.OffsetInContainerFragment()); } } else { // |LayoutInline| used to be culled.
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.h b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.h index 0bde454..a0fd6be 100644 --- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.h +++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.h
@@ -123,8 +123,8 @@ const NGInlineBreakToken* InlineBreakToken() const; // The offset relative to the root of the inline formatting context. - const PhysicalRect RectInContainerBlock() const; - const PhysicalOffset OffsetInContainerBlock() const; + const PhysicalRect RectInContainerFragment() const; + const PhysicalOffset OffsetInContainerFragment() const; const PhysicalSize Size() const; // InkOverflow of itself, including contents if they contribute to the ink @@ -246,19 +246,19 @@ } // Returns the |NGPhysicalBoxFragment| that owns |Items|. - const NGPhysicalBoxFragment& BoxFragment() const { + const NGPhysicalBoxFragment& ContainerFragment() const { DCHECK(root_box_fragment_); return *root_box_fragment_; } + // Return the index of the current physical box fragment of the containing + // block. An inline formatting context may be block fragmented. + wtf_size_t ContainerFragmentIndex() const { return fragment_index_; } + // Returns the |LayoutBlockFlow| containing this cursor. // When |this| is a column box, returns the multicol container. const LayoutBlockFlow* GetLayoutBlockFlow() const; - // Return the index of the current physical box fragment of the containing - // block. An inline formatting context may be block fragmented. - wtf_size_t CurrentContainerFragmentIndex() const { return fragment_index_; } - // // Functions to query the current position. // @@ -320,8 +320,8 @@ // first column, and the last three lines will end up in the second column. So // we get two box fragments generated for #container - one for each column. // - // The offsets returned from these methods will be (OffsetInContainerBlock() - // values in parentheses): + // The offsets returned from these methods will be + // (OffsetInContainerFragment() values in parentheses): // // line1: 0,0 (0,0) // line2: 0,20 (0,20) @@ -334,8 +334,8 @@ // engine to calculate offsets relatively to some ancestor. PhysicalRect CurrentRectInBlockFlow() const; PhysicalOffset CurrentOffsetInBlockFlow() const { - DCHECK_EQ(Current().OffsetInContainerBlock(), - Current().RectInContainerBlock().offset); + DCHECK_EQ(Current().OffsetInContainerFragment(), + Current().RectInContainerFragment().offset); return CurrentRectInBlockFlow().offset; }
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor_test.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor_test.cc index cb8d0476..a7bfad1f 100644 --- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor_test.cc +++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor_test.cc
@@ -769,12 +769,12 @@ const auto& text = *To<Text>(GetElementById("root")->firstChild()); ASSERT_TRUE(cursor.Current().IsLineBox()); EXPECT_EQ(PhysicalRect(PhysicalOffset(10, 10), PhysicalSize(20, 20)), - cursor.Current().RectInContainerBlock()); + cursor.Current().RectInContainerFragment()); cursor.MoveTo(*text.GetLayoutObject()); EXPECT_EQ(PhysicalRect(PhysicalOffset(10, 15), PhysicalSize(20, 10)), - cursor.Current().RectInContainerBlock()); - const PhysicalOffset left_top = cursor.Current().OffsetInContainerBlock(); + cursor.Current().RectInContainerFragment()); + const PhysicalOffset left_top = cursor.Current().OffsetInContainerFragment(); EXPECT_EQ(PositionWithAffinity(Position(text, 0)), cursor.PositionForPointInChild(left_top + PhysicalOffset(-5, 0))); @@ -806,12 +806,12 @@ *To<Text>(GetElementById("root")->firstChild()->firstChild()); ASSERT_TRUE(cursor.Current().IsLineBox()); EXPECT_EQ(PhysicalRect(PhysicalOffset(754, 10), PhysicalSize(20, 20)), - cursor.Current().RectInContainerBlock()); + cursor.Current().RectInContainerFragment()); cursor.MoveTo(*text.GetLayoutObject()); EXPECT_EQ(PhysicalRect(PhysicalOffset(754, 15), PhysicalSize(20, 10)), - cursor.Current().RectInContainerBlock()); - const PhysicalOffset left_top = cursor.Current().OffsetInContainerBlock(); + cursor.Current().RectInContainerFragment()); + const PhysicalOffset left_top = cursor.Current().OffsetInContainerFragment(); EXPECT_EQ(PositionWithAffinity(Position(text, 2), TextAffinity::kUpstream), cursor.PositionForPointInChild(left_top + PhysicalOffset(-5, 0))); @@ -842,12 +842,12 @@ const auto& text = *To<Text>(GetElementById("root")->firstChild()); ASSERT_TRUE(cursor.Current().IsLineBox()); EXPECT_EQ(PhysicalRect(PhysicalOffset(10, 10), PhysicalSize(20, 20)), - cursor.Current().RectInContainerBlock()); + cursor.Current().RectInContainerFragment()); cursor.MoveTo(*text.GetLayoutObject()); EXPECT_EQ(PhysicalRect(PhysicalOffset(15, 10), PhysicalSize(10, 20)), - cursor.Current().RectInContainerBlock()); - const PhysicalOffset left_top = cursor.Current().OffsetInContainerBlock(); + cursor.Current().RectInContainerFragment()); + const PhysicalOffset left_top = cursor.Current().OffsetInContainerFragment(); EXPECT_EQ(PositionWithAffinity(Position(text, 0)), cursor.PositionForPointInChild(left_top + PhysicalOffset(0, -5))); @@ -879,12 +879,12 @@ *To<Text>(GetElementById("root")->firstChild()->firstChild()); ASSERT_TRUE(cursor.Current().IsLineBox()); EXPECT_EQ(PhysicalRect(PhysicalOffset(10, 10), PhysicalSize(20, 20)), - cursor.Current().RectInContainerBlock()); + cursor.Current().RectInContainerFragment()); cursor.MoveTo(*text.GetLayoutObject()); EXPECT_EQ(PhysicalRect(PhysicalOffset(15, 10), PhysicalSize(10, 20)), - cursor.Current().RectInContainerBlock()); - const PhysicalOffset left_top = cursor.Current().OffsetInContainerBlock(); + cursor.Current().RectInContainerFragment()); + const PhysicalOffset left_top = cursor.Current().OffsetInContainerFragment(); EXPECT_EQ(PositionWithAffinity(Position(text, 2), TextAffinity::kUpstream), cursor.PositionForPointInChild(left_top + PhysicalOffset(0, -5)));
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_fragment_traversal.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_fragment_traversal.cc index b9641ae..4007ac8 100644 --- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_fragment_traversal.cc +++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_fragment_traversal.cc
@@ -181,7 +181,7 @@ for (const NGPaintFragment* fragment : NGPaintFragment::InlineFragmentsFor(layout_object)) { result.push_back(Result{&fragment->PhysicalFragment(), - fragment->OffsetInContainerBlock()}); + fragment->OffsetInContainerFragment()}); } return result; }
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_layout_algorithm_test.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_layout_algorithm_test.cc index 8a23339..5a18b00 100644 --- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_layout_algorithm_test.cc +++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_layout_algorithm_test.cc
@@ -229,7 +229,7 @@ EXPECT_EQ(LayoutUnit(96), cursor.Current().Size().height); cursor.MoveToNext(); ASSERT_TRUE(cursor); - EXPECT_EQ(LayoutUnit(0), cursor.Current().OffsetInContainerBlock().top) + EXPECT_EQ(LayoutUnit(0), cursor.Current().OffsetInContainerFragment().top) << "Offset top of <img> should be zero."; }
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_physical_line_box_fragment.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_physical_line_box_fragment.cc index 0bfa525..a3286db 100644 --- a/third_party/blink/renderer/core/layout/ng/inline/ng_physical_line_box_fragment.cc +++ b/third_party/blink/renderer/core/layout/ng/inline/ng_physical_line_box_fragment.cc
@@ -132,8 +132,8 @@ // Make sure we include the inline-size of the line-box in the overflow. // Note, the bottom half-leading should not be included. crbug.com/996847 const WritingMode container_writing_mode = container_style.GetWritingMode(); - AddInlineSizeToOverflow(line.RectInContainerBlock(), container_writing_mode, - &overflow); + AddInlineSizeToOverflow(line.RectInContainerFragment(), + container_writing_mode, &overflow); return overflow; }
diff --git a/third_party/blink/renderer/core/layout/ng/ng_block_node.cc b/third_party/blink/renderer/core/layout/ng/ng_block_node.cc index 6c849a8..c9ab641 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_block_node.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_block_node.cc
@@ -1423,7 +1423,7 @@ continue; if (auto* layout_box = DynamicTo<LayoutBox>(layout_object)) { PhysicalOffset maybe_flipped_offset = - cursor.Current().OffsetInContainerBlock(); + cursor.Current().OffsetInContainerFragment(); if (initial_container_is_flipped) { maybe_flipped_offset.left = container.Size().width - child->Size().width -
diff --git a/third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.cc b/third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.cc index 0e4d54f..f6f52bd 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.cc
@@ -117,7 +117,7 @@ DCHECK(containing_block_geometry.has_value() || !containing_lineboxes.first); - PhysicalRect fragment_rect = item->RectInContainerBlock(); + PhysicalRect fragment_rect = item->RectInContainerFragment(); fragment_rect.offset += box_offset; if (containing_lineboxes.first == linebox) { // Unite the start rect with the fragment's rect.
diff --git a/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm.cc index 86c79ff9..cc432b217 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm.cc
@@ -321,8 +321,33 @@ scoped_refptr<const NGBlockBreakToken> content_break_token, LogicalSize adjusted_padding_box_size, bool has_legend) { + // If the following conditions meet, the content should be laid out with + // a block-size limitation: + // - The FIELDSET block-size is indefinite. + // - It has max-block-size. + // - The intrinsic block-size of the content is larger than the + // max-block-size. + if (adjusted_padding_box_size.block_size == kIndefiniteSize) { + LayoutUnit max_content_block_size = ResolveMaxBlockLength( + ConstraintSpace(), Style(), BorderPadding(), Style().LogicalMaxHeight(), + LengthResolvePhase::kLayout); + if (max_content_block_size != LayoutUnit::Max()) { + max_content_block_size -= BorderPadding().BlockSum(); + + auto child_measure_space = CreateConstraintSpaceForFieldsetContent( + fieldset_content, adjusted_padding_box_size, intrinsic_block_size_, + NGCacheSlot::kMeasure); + LayoutUnit intrinsic_content_block_size = + fieldset_content + .Layout(child_measure_space, content_break_token.get()) + ->IntrinsicBlockSize(); + if (intrinsic_content_block_size > max_content_block_size) + adjusted_padding_box_size.block_size = max_content_block_size; + } + } auto child_space = CreateConstraintSpaceForFieldsetContent( - fieldset_content, adjusted_padding_box_size, intrinsic_block_size_); + fieldset_content, adjusted_padding_box_size, intrinsic_block_size_, + NGCacheSlot::kLayout); auto result = fieldset_content.Layout(child_space, content_break_token.get()); // TODO(layout-dev): Handle abortions caused by block fragmentation. @@ -418,11 +443,13 @@ NGFieldsetLayoutAlgorithm::CreateConstraintSpaceForFieldsetContent( NGBlockNode fieldset_content, LogicalSize padding_box_size, - LayoutUnit block_offset) { + LayoutUnit block_offset, + NGCacheSlot slot) { DCHECK(fieldset_content.CreatesNewFormattingContext()); NGConstraintSpaceBuilder builder( ConstraintSpace(), fieldset_content.Style().GetWritingDirection(), /* is_new_fc */ true); + builder.SetCacheSlot(slot); builder.SetAvailableSize(padding_box_size); builder.SetStretchInlineSizeIfAuto(true); // We pass the container's PercentageResolutionSize because percentage
diff --git a/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm.h b/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm.h index d8f42ef2..1e79c03f 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm.h +++ b/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm.h
@@ -51,7 +51,8 @@ const NGConstraintSpace CreateConstraintSpaceForFieldsetContent( NGBlockNode fieldset_content, LogicalSize padding_box_size, - LayoutUnit block_offset); + LayoutUnit block_offset, + NGCacheSlot slot); bool IsFragmentainerOutOfSpace(LayoutUnit block_offset) const; const WritingDirectionMode writing_direction_;
diff --git a/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm_test.cc b/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm_test.cc index 649bbeb1..4102938 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm_test.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm_test.cc
@@ -377,7 +377,7 @@ offset:unplaced size:1000x53 offset:0,0 size:126x53 offset:13,0 size:30x30 - offset:3,30 size:120x220 + offset:3,30 size:120x0 offset:10,10 size:100x200 )DUMP"; EXPECT_EQ(expectation, dump);
diff --git a/third_party/blink/renderer/core/layout/ng/ng_fragment_child_iterator.cc b/third_party/blink/renderer/core/layout/ng/ng_fragment_child_iterator.cc index aa65979..49ed2125 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_fragment_child_iterator.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_fragment_child_iterator.cc
@@ -156,7 +156,7 @@ current_.link_.fragment = nullptr; return; } - current_.link_ = {item->BoxFragment(), item->OffsetInContainerBlock()}; + current_.link_ = {item->BoxFragment(), item->OffsetInContainerFragment()}; } void NGFragmentChildIterator::SkipToBoxFragment() {
diff --git a/third_party/blink/renderer/core/layout/ng/ng_layout_overflow_calculator.cc b/third_party/blink/renderer/core/layout/ng/ng_layout_overflow_calculator.cc index dde2465..755df23 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_layout_overflow_calculator.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_layout_overflow_calculator.cc
@@ -154,7 +154,7 @@ for (const auto& item : items) { if (const auto* line_box = item->LineBoxFragment()) { has_hanging = line_box->HasHanging(); - line_rect = item->RectInContainerBlock(); + line_rect = item->RectInContainerFragment(); if (line_rect.IsEmpty()) continue; @@ -172,7 +172,7 @@ } if (item->IsText()) { - PhysicalRect child_overflow = item->RectInContainerBlock(); + PhysicalRect child_overflow = item->RectInContainerFragment(); // Adjust the text's overflow if the line-box has hanging. if (UNLIKELY(has_hanging)) @@ -186,7 +186,7 @@ // Use the default box-fragment overflow logic. PhysicalRect child_overflow = LayoutOverflowForPropagation(*child_box_fragment); - child_overflow.offset += item->OffsetInContainerBlock(); + child_overflow.offset += item->OffsetInContainerFragment(); // Only inline-boxes (not atomic-inlines) should be adjusted if the // line-box has hanging.
diff --git a/third_party/blink/renderer/core/layout/ng/ng_outline_utils.cc b/third_party/blink/renderer/core/layout/ng/ng_outline_utils.cc index 5bddc9d..c8556ec1 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_outline_utils.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_outline_utils.cc
@@ -44,11 +44,11 @@ // fragment. To do this, return |true| if |this| is the first inline fragment // of a block fragment. while (true) { - wtf_size_t fragment_index = cursor.CurrentContainerFragmentIndex(); + wtf_size_t fragment_index = cursor.ContainerFragmentIndex(); cursor.MoveToNextForSameLayoutObject(); DCHECK(cursor); if (cursor.Current().BoxFragment() == &physical_fragment) - return fragment_index != cursor.CurrentContainerFragmentIndex(); + return fragment_index != cursor.ContainerFragmentIndex(); } }
diff --git a/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.cc b/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.cc index 022f956..aabfb7b 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.cc
@@ -559,7 +559,7 @@ DCHECK_EQ(&child, cursor.CurrentItem()); DCHECK_EQ(child.Type(), NGFragmentItem::kLine); if (padding_strut) - AddLineBoxRect(child.RectInContainerBlock()); + AddLineBoxRect(child.RectInContainerFragment()); const NGPhysicalLineBoxFragment* line_box = child.LineBoxFragment(); DCHECK(line_box); PhysicalRect child_scrollable_overflow = @@ -609,7 +609,7 @@ item->PostLayoutBoxFragment()) { if (child_box->IsFloatingOrOutOfFlowPositioned()) { context.AddFloatingOrOutOfFlowPositionedChild( - *child_box, item->OffsetInContainerBlock()); + *child_box, item->OffsetInContainerFragment()); } } } @@ -759,26 +759,26 @@ NGInlineCursor cursor; cursor.MoveTo(*layout_object); DCHECK(cursor); - wtf_size_t fragment_index = cursor.CurrentContainerFragmentIndex(); + wtf_size_t fragment_index = cursor.ContainerFragmentIndex(); bool has_this_fragment = false; for (;; cursor.MoveToNextForSameLayoutObject()) { if (!cursor) { DCHECK(has_this_fragment); break; } - if (fragment_index != cursor.CurrentContainerFragmentIndex()) { + if (fragment_index != cursor.ContainerFragmentIndex()) { // If this block fragment has |this|, exit the loop. if (has_this_fragment) break; // Otherwise clear the result and continue to the next block fragment. - fragment_index = cursor.CurrentContainerFragmentIndex(); + fragment_index = cursor.ContainerFragmentIndex(); rects->Shrink(initial_rects_size); } const NGInlineCursorPosition& current = cursor.Current(); has_this_fragment = has_this_fragment || current.BoxFragment() == this; if (!current.Size().IsZero()) - rects->push_back(current.RectInContainerBlock()); + rects->push_back(current.RectInContainerFragment()); // Add descendants if any, in the container-relative coordinate. if (!current.HasChildren())
diff --git a/third_party/blink/renderer/core/layout/ng/ng_physical_container_fragment.cc b/third_party/blink/renderer/core/layout/ng/ng_physical_container_fragment.cc index 9c63063..dd037ab 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_physical_container_fragment.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_physical_container_fragment.cc
@@ -191,7 +191,7 @@ continue; if (item.Type() == NGFragmentItem::kLine) { AddOutlineRectsForDescendant( - {item.LineBoxFragment(), item.OffsetInContainerBlock()}, + {item.LineBoxFragment(), item.OffsetInContainerFragment()}, outline_rects, additional_offset, outline_type, containing_block); continue; } @@ -199,7 +199,7 @@ if (outline_type == NGOutlineType::kDontIncludeBlockVisualOverflow) continue; outline_rects->push_back( - PhysicalRect(additional_offset + item.OffsetInContainerBlock(), + PhysicalRect(additional_offset + item.OffsetInContainerFragment(), item.Size().ToLayoutSize())); continue; } @@ -207,9 +207,9 @@ if (const NGPhysicalBoxFragment* child_box = item.PostLayoutBoxFragment()) { DCHECK(!child_box->IsOutOfFlowPositioned()); - AddOutlineRectsForDescendant({child_box, item.OffsetInContainerBlock()}, - outline_rects, additional_offset, - outline_type, containing_block); + AddOutlineRectsForDescendant( + {child_box, item.OffsetInContainerFragment()}, outline_rects, + additional_offset, outline_type, containing_block); } continue; } @@ -240,14 +240,14 @@ continue; } if (item->IsText()) { - PhysicalRect child_scroll_overflow = item->RectInContainerBlock(); + PhysicalRect child_scroll_overflow = item->RectInContainerFragment(); if (height_type == TextHeightType::kEmHeight) { child_scroll_overflow = AdjustTextRectForEmHeight( child_scroll_overflow, item->Style(), item->TextShapeResult(), container_writing_mode); } if (UNLIKELY(has_hanging)) { - AdjustScrollableOverflowForHanging(line.RectInContainerBlock(), + AdjustScrollableOverflowForHanging(line.RectInContainerFragment(), container_writing_mode, &child_scroll_overflow); } @@ -261,7 +261,7 @@ PhysicalRect child_scroll_overflow; if (height_type == TextHeightType::kNormalHeight || (child_box->BoxType() != kInlineBox && !IsRubyBox())) - child_scroll_overflow = item->RectInContainerBlock(); + child_scroll_overflow = item->RectInContainerFragment(); if (child_box->IsInlineBox()) { child_box->AddScrollableOverflowForInlineChild( container, container_style, line, has_hanging, descendants, @@ -269,14 +269,14 @@ child_box->AdjustScrollableOverflowForPropagation( container, height_type, &child_scroll_overflow); if (UNLIKELY(has_hanging)) { - AdjustScrollableOverflowForHanging(line.RectInContainerBlock(), + AdjustScrollableOverflowForHanging(line.RectInContainerFragment(), container_writing_mode, &child_scroll_overflow); } } else { child_scroll_overflow = child_box->ScrollableOverflowForPropagation(container, height_type); - child_scroll_overflow.offset += item->OffsetInContainerBlock(); + child_scroll_overflow.offset += item->OffsetInContainerFragment(); } overflow->Unite(child_scroll_overflow); descendants.MoveToNextSkippingChildren();
diff --git a/third_party/blink/renderer/core/layout/ng/ng_physical_fragment.cc b/third_party/blink/renderer/core/layout/ng/ng_physical_fragment.cc index 140c2e6..a7611dc 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_physical_fragment.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_physical_fragment.cc
@@ -196,7 +196,7 @@ const NGInlineCursorPosition& current = cursor->Current(); if (const NGPhysicalBoxFragment* box = current.BoxFragment()) { if (!box->IsInlineBox()) { - Append(box, current.OffsetInContainerBlock(), indent); + Append(box, current.OffsetInContainerFragment(), indent); continue; } } @@ -209,7 +209,7 @@ if (flags_ & NGPhysicalFragment::DumpOffset) { builder_->Append(" offset:"); - builder_->Append(current.OffsetInContainerBlock().ToString()); + builder_->Append(current.OffsetInContainerFragment().ToString()); } if (flags_ & NGPhysicalFragment::DumpSize) { builder_->Append(" size:");
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_shape.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_shape.cc index 812e89b..ca0814bd 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_shape.cc +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_shape.cc
@@ -122,7 +122,7 @@ void LayoutSVGShape::UpdateShapeFromElement() { NOT_DESTROYED(); CreatePath(); - fill_bounding_box_ = GetPath().BoundingRect(); + fill_bounding_box_ = GetPath().TightBoundingRect(); if (HasNonScalingStroke()) { // NonScalingStrokeTransform may depend on LocalTransform which in turn may
diff --git a/third_party/blink/renderer/core/loader/appcache/application_cache_host.cc b/third_party/blink/renderer/core/loader/appcache/application_cache_host.cc index 3580a09..0d011b4 100644 --- a/third_party/blink/renderer/core/loader/appcache/application_cache_host.cc +++ b/third_party/blink/renderer/core/loader/appcache/application_cache_host.cc
@@ -64,12 +64,8 @@ ApplicationCacheHost::ApplicationCacheHost( const BrowserInterfaceBrokerProxy& interface_broker_proxy, - scoped_refptr<base::SingleThreadTaskRunner> task_runner, - ContextLifecycleNotifier* notifier) - : backend_host_(notifier), - receiver_(this, notifier), - backend_remote_(notifier), - task_runner_(std::move(task_runner)), + scoped_refptr<base::SingleThreadTaskRunner> task_runner) + : task_runner_(std::move(task_runner)), interface_broker_proxy_(interface_broker_proxy) {} ApplicationCacheHost::~ApplicationCacheHost() = default;
diff --git a/third_party/blink/renderer/core/loader/appcache/application_cache_host.h b/third_party/blink/renderer/core/loader/appcache/application_cache_host.h index aa23aeb9..9481bfb 100644 --- a/third_party/blink/renderer/core/loader/appcache/application_cache_host.h +++ b/third_party/blink/renderer/core/loader/appcache/application_cache_host.h
@@ -41,7 +41,6 @@ #include "third_party/blink/public/mojom/appcache/appcache_info.mojom-blink-forward.h" #include "third_party/blink/public/mojom/devtools/console_message.mojom-blink-forward.h" #include "third_party/blink/renderer/core/core_export.h" -#include "third_party/blink/renderer/platform/context_lifecycle_notifier.h" #include "third_party/blink/renderer/platform/heap/handle.h" #include "third_party/blink/renderer/platform/loader/fetch/resource_response.h" #include "third_party/blink/renderer/platform/mojo/heap_mojo_receiver.h" @@ -59,8 +58,7 @@ public: ApplicationCacheHost( const BrowserInterfaceBrokerProxy& interface_broker_proxy, - scoped_refptr<base::SingleThreadTaskRunner> task_runner, - ContextLifecycleNotifier* notifier); + scoped_refptr<base::SingleThreadTaskRunner> task_runner); ~ApplicationCacheHost() override; virtual void Detach(); @@ -114,9 +112,9 @@ virtual void Trace(Visitor*) const; protected: - HeapMojoRemote<mojom::blink::AppCacheHost, - HeapMojoWrapperMode::kForceWithoutContextObserver> - backend_host_; + // ApplicationCacheHost will be instantiated before ExecutionContext becomes + // available. So we can't supply ExecutionContext to HeapMojoRemote. + HeapMojoRemote<mojom::blink::AppCacheHost> backend_host_{nullptr}; mojom::blink::AppCacheStatus status_ = mojom::blink::AppCacheStatus::APPCACHE_STATUS_UNCACHED; @@ -134,13 +132,13 @@ void GetAssociatedCacheInfo(CacheInfo* info); - HeapMojoReceiver<mojom::blink::AppCacheFrontend, - ApplicationCacheHost, - HeapMojoWrapperMode::kForceWithoutContextObserver> - receiver_; - HeapMojoRemote<mojom::blink::AppCacheBackend, - HeapMojoWrapperMode::kForceWithoutContextObserver> - backend_remote_; + // ApplicationCacheHost will be instantiated before ExecutionContext becomes + // available. So we can't supply ExecutionContext to HeapMojoReceiver. + HeapMojoReceiver<mojom::blink::AppCacheFrontend, ApplicationCacheHost> + receiver_{this, nullptr}; + // ApplicationCacheHost will be instantiated before ExecutionContext becomes + // available. So we can't supply ExecutionContext to HeapMojoRemote. + HeapMojoRemote<mojom::blink::AppCacheBackend> backend_remote_{nullptr}; base::UnguessableToken host_id_; mojom::blink::AppCacheInfo cache_info_;
diff --git a/third_party/blink/renderer/core/loader/appcache/application_cache_host_for_frame.cc b/third_party/blink/renderer/core/loader/appcache/application_cache_host_for_frame.cc index 68663e9..0e0f290 100644 --- a/third_party/blink/renderer/core/loader/appcache/application_cache_host_for_frame.cc +++ b/third_party/blink/renderer/core/loader/appcache/application_cache_host_for_frame.cc
@@ -47,9 +47,7 @@ const BrowserInterfaceBrokerProxy& interface_broker_proxy, scoped_refptr<base::SingleThreadTaskRunner> task_runner, const base::UnguessableToken& appcache_host_id) - : ApplicationCacheHost(interface_broker_proxy, - std::move(task_runner), - document_loader->GetFrame()->DomWindow()), + : ApplicationCacheHost(interface_broker_proxy, std::move(task_runner)), local_frame_(document_loader->GetFrame()), document_loader_(document_loader) { // PlzNavigate: The browser passes the ID to be used.
diff --git a/third_party/blink/renderer/core/loader/appcache/application_cache_host_for_worker.cc b/third_party/blink/renderer/core/loader/appcache/application_cache_host_for_worker.cc index f046a63c..9cb4e9f 100644 --- a/third_party/blink/renderer/core/loader/appcache/application_cache_host_for_worker.cc +++ b/third_party/blink/renderer/core/loader/appcache/application_cache_host_for_worker.cc
@@ -9,11 +9,8 @@ ApplicationCacheHostForWorker::ApplicationCacheHostForWorker( const base::UnguessableToken& appcache_host_id, const BrowserInterfaceBrokerProxy& interface_broker_proxy, - scoped_refptr<base::SingleThreadTaskRunner> task_runner, - ContextLifecycleNotifier* notifier) - : ApplicationCacheHost(interface_broker_proxy, - std::move(task_runner), - notifier) { + scoped_refptr<base::SingleThreadTaskRunner> task_runner) + : ApplicationCacheHost(interface_broker_proxy, std::move(task_runner)) { SetHostID(appcache_host_id ? appcache_host_id : base::UnguessableToken::Create()); BindBackend();
diff --git a/third_party/blink/renderer/core/loader/appcache/application_cache_host_for_worker.h b/third_party/blink/renderer/core/loader/appcache/application_cache_host_for_worker.h index ff632793..5a51ec7 100644 --- a/third_party/blink/renderer/core/loader/appcache/application_cache_host_for_worker.h +++ b/third_party/blink/renderer/core/loader/appcache/application_cache_host_for_worker.h
@@ -14,8 +14,7 @@ ApplicationCacheHostForWorker( const base::UnguessableToken& appcache_host_id, const BrowserInterfaceBrokerProxy& interface_broker_proxy, - scoped_refptr<base::SingleThreadTaskRunner> task_runner, - ContextLifecycleNotifier* notifier); + scoped_refptr<base::SingleThreadTaskRunner> task_runner); ~ApplicationCacheHostForWorker() override; };
diff --git a/third_party/blink/renderer/core/paint/compositing/compositing_test.cc b/third_party/blink/renderer/core/paint/compositing/compositing_test.cc index 4568bbd..9fd55179 100644 --- a/third_party/blink/renderer/core/paint/compositing/compositing_test.cc +++ b/third_party/blink/renderer/core/paint/compositing/compositing_test.cc
@@ -1193,16 +1193,88 @@ EXPECT_FALSE(inner_element_layer->subtree_property_changed()); } -TEST_P(CompositingSimTest, SafeOpaqueBackgroundColorGetsSet) { - // TODO(crbug.com/765003): CAP may make different layerization decisions and - // we cannot guarantee that both divs will be composited in this test. When - // CAP gets closer to launch, this test should be updated to pass. - if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) - return; - +TEST_P(CompositingSimTest, SafeOpaqueBackgroundColor) { InitializeWithHTML(R"HTML( - <!DOCTYPE html> - <style> + <!DOCTYPE html> + <style> + body { background: yellow; } + div { + position: absolute; + z-index: 1; + width: 20px; + height: 20px; + will-change: transform; /* Composited */ + } + #opaque-color { + background: blue; + } + #opaque-image, #opaque-image-translucent-color { + background: linear-gradient(blue, green); + } + #partly-opaque div { + width: 15px; + height: 15px; + background: blue; + will-change: initial; + } + #translucent, #opaque-image-translucent-color div { + background: rgba(0, 255, 255, 0.5); + will-change: initial; + } + </style> + <div id="opaque-color"></div> + <div id="opaque-image"></div> + <div id="opaque-image-translucent-color"> + <div></div> + </div> + <div id="partly-opaque"> + <div></div> + </div> + <div id="translucent"></div> + )HTML"); + + Compositor().BeginFrame(); + + auto* opaque_color = CcLayerByDOMElementId("opaque-color"); + EXPECT_TRUE(opaque_color->contents_opaque()); + EXPECT_EQ(SK_ColorBLUE, opaque_color->background_color()); + EXPECT_EQ(SK_ColorBLUE, opaque_color->SafeOpaqueBackgroundColor()); + + auto* opaque_image = CcLayerByDOMElementId("opaque-image"); + EXPECT_TRUE(opaque_image->contents_opaque()); + EXPECT_EQ(SK_ColorTRANSPARENT, opaque_image->background_color()); + // Fallback to use the viewport background. + EXPECT_EQ(SK_ColorYELLOW, opaque_image->SafeOpaqueBackgroundColor()); + + const SkColor kTranslucentCyan = SkColorSetARGB(128, 0, 255, 255); + auto* opaque_image_translucent_color = + CcLayerByDOMElementId("opaque-image-translucent-color"); + EXPECT_TRUE(opaque_image_translucent_color->contents_opaque()); + EXPECT_EQ(kTranslucentCyan, + opaque_image_translucent_color->background_color()); + // Use background_color() with the alpha channel forced to be opaque. + EXPECT_EQ(SK_ColorCYAN, + opaque_image_translucent_color->SafeOpaqueBackgroundColor()); + + auto* partly_opaque = CcLayerByDOMElementId("partly-opaque"); + EXPECT_FALSE(partly_opaque->contents_opaque()); + EXPECT_EQ(SK_ColorBLUE, partly_opaque->background_color()); + // SafeOpaqueBackgroundColor() returns SK_ColorTRANSPARENT when + // background_color() is opaque and contents_opaque() is false. + EXPECT_EQ(SK_ColorTRANSPARENT, partly_opaque->SafeOpaqueBackgroundColor()); + + auto* translucent = CcLayerByDOMElementId("translucent"); + EXPECT_FALSE(translucent->contents_opaque()); + EXPECT_EQ(kTranslucentCyan, translucent->background_color()); + // SafeOpaqueBackgroundColor() returns background_color() if it's not opaque + // and contents_opaque() is false. + EXPECT_EQ(kTranslucentCyan, translucent->SafeOpaqueBackgroundColor()); +} + +TEST_P(CompositingSimTest, SquashingLayerSafeOpaqueBackgroundColor) { + InitializeWithHTML(R"HTML( + <!DOCTYPE html> + <style> div { position: absolute; z-index: 1; @@ -1223,52 +1295,32 @@ #bottomright { top: 24px; left: 24px; + width: 100px; + height: 100px; background: cyan; } - </style> - <div id="behind"></div> - <div id="topleft"></div> - <div id="bottomright"></div> + </style> + <div id="behind"></div> + <div id="topleft"></div> + <div id="bottomright"></div> )HTML"); Compositor().BeginFrame(); - auto* behind_element = GetElementById("behind"); - auto* behind_layer = CcLayerByDOMElementId("behind"); - EXPECT_EQ(behind_layer->element_id(), - CompositorElementIdFromUniqueObjectId( - behind_element->GetLayoutObject()->UniqueId(), - CompositorElementIdNamespace::kPrimary)); - EXPECT_EQ(behind_layer->SafeOpaqueBackgroundColor(), SK_ColorBLUE); - - auto* grouped_mapping = - GetElementById("topleft")->GetLayoutBox()->Layer()->GroupedMapping(); - ASSERT_TRUE(grouped_mapping); - ASSERT_TRUE(grouped_mapping->NonScrollingSquashingLayer()); - auto& squashing_layer = - grouped_mapping->NonScrollingSquashingLayer()->CcLayer(); + auto* squashing_layer = CcLayerByDOMElementId("topleft"); + ASSERT_TRUE(squashing_layer); + EXPECT_EQ(gfx::Size(124, 124), squashing_layer->bounds()); // Top left and bottom right are squashed. // This squashed layer should not be opaque, as it is squashing two squares // with some gaps between them. - EXPECT_FALSE(squashing_layer.contents_opaque()); - // This shouldn't DCHECK. - squashing_layer.SafeOpaqueBackgroundColor(); - // Because contents_opaque is false, the SafeOpaqueBackgroundColor() getter - // will return SK_ColorTRANSPARENT. So we need to grab the actual color, - // to make sure it's right. - SkColor squashed_bg_color = - squashing_layer.ActualSafeOpaqueBackgroundColorForTesting(); - // The squashed layer should have a non-transparent safe opaque background - // color, that isn't blue. Exactly which color it is depends on heuristics, - // but it should be one of the two colors of the elements that created it. - EXPECT_NE(squashed_bg_color, SK_ColorBLUE); - EXPECT_EQ(SkColorGetA(squashed_bg_color), SK_AlphaOPAQUE); - // #behind is blue, which is SK_ColorBLUE - // #topleft is lime, which is SK_ColorGREEN - // #bottomright is cyan, which is SK_ColorCYAN - EXPECT_TRUE((squashed_bg_color == SK_ColorGREEN) || - (squashed_bg_color == SK_ColorCYAN)); + EXPECT_FALSE(squashing_layer->contents_opaque()); + // The background color of #bottomright is used as the background color + // because it covers the most significant area of the squashing layer. + EXPECT_EQ(squashing_layer->background_color(), SK_ColorCYAN); + // SafeOpaqueBackgroundColor() returns SK_ColorTRANSPARENT when + // background_color() is opaque and contents_opaque() is false. + EXPECT_EQ(squashing_layer->SafeOpaqueBackgroundColor(), SK_ColorTRANSPARENT); } // Test that a pleasant checkerboard color is used in the presence of blending. @@ -1283,6 +1335,7 @@ auto* scrolling_contents = ScrollingContentsCcLayerByScrollElementId( RootCcLayer(), MainFrame().GetFrameView()->LayoutViewport()->GetScrollElementId()); + EXPECT_EQ(scrolling_contents->background_color(), SK_ColorWHITE); EXPECT_EQ(scrolling_contents->SafeOpaqueBackgroundColor(), SK_ColorWHITE); }
diff --git a/third_party/blink/renderer/core/paint/image_paint_timing_detector.cc b/third_party/blink/renderer/core/paint/image_paint_timing_detector.cc index c9d8315..e1ec4037 100644 --- a/third_party/blink/renderer/core/paint/image_paint_timing_detector.cc +++ b/third_party/blink/renderer/core/paint/image_paint_timing_detector.cc
@@ -29,12 +29,12 @@ // As the image do not have a lot of content, we down scale |visual_size| by the // ratio of |intrinsic_image_size|/|displayed_image_size| = 1/10000. // -// * |visual_size| referes to the size of the |displayed_image_size| after +// * |visual_size| refers to the size of the |displayed_image_size| after // clipping and transforming. The size is in the main-frame's coordinate. -// * |displayed_image_size| refers to the paint size in the image object's -// coordinate. // * |intrinsic_image_size| refers to the the image object's original size // before scaling. The size is in the image object's coordinate. +// * |displayed_image_size| refers to the paint size in the image object's +// coordinate. uint64_t DownScaleIfIntrinsicSizeIsSmaller( uint64_t visual_size, const uint64_t& intrinsic_image_size, @@ -154,16 +154,6 @@ RegisterNotifySwapTime(); } -void ImagePaintTimingDetector::LayoutObjectWillBeDestroyed( - const LayoutObject& object) { - if (!is_recording_) - return; - - // The visible record removal has been handled by - // |NotifyImageRemoved|. - records_manager_.RemoveInvisibleRecordIfNeeded(object); -} - void ImagePaintTimingDetector::NotifyImageRemoved( const LayoutObject& object, const ImageResourceContent* cached_image) { @@ -171,6 +161,7 @@ return; RecordId record_id = std::make_pair(&object, cached_image); records_manager_.RemoveImageFinishedRecord(record_id); + records_manager_.RemoveInvisibleRecordIfNeeded(record_id); if (!records_manager_.IsRecordedVisibleImage(record_id)) return; records_manager_.RemoveVisibleRecord(record_id); @@ -235,10 +226,10 @@ Node* node = object.GetNode(); if (!node) return; - if (records_manager_.IsRecordedInvisibleImage(object)) - return; RecordId record_id = std::make_pair(&object, &cached_image); + if (records_manager_.IsRecordedInvisibleImage(record_id)) + return; bool is_recorded_visible_image = records_manager_.IsRecordedVisibleImage(record_id); if (int depth = IgnorePaintTimingScope::IgnoreDepth()) { @@ -282,7 +273,7 @@ current_paint_chunk_properties, object, cached_image); if (rect_size == 0) { - records_manager_.RecordInvisible(object); + records_manager_.RecordInvisible(record_id); } else { records_manager_.RecordVisible(record_id, rect_size); if (cached_image.IsLoaded()) {
diff --git a/third_party/blink/renderer/core/paint/image_paint_timing_detector.h b/third_party/blink/renderer/core/paint/image_paint_timing_detector.h index 2a36fc9..7b07678 100644 --- a/third_party/blink/renderer/core/paint/image_paint_timing_detector.h +++ b/third_party/blink/renderer/core/paint/image_paint_timing_detector.h
@@ -77,8 +77,8 @@ ImageRecordsManager& operator=(const ImageRecordsManager&) = delete; ImageRecord* FindLargestPaintCandidate() const; - inline void RemoveInvisibleRecordIfNeeded(const LayoutObject& object) { - invisible_images_.erase(&object); + inline void RemoveInvisibleRecordIfNeeded(const RecordId& record_id) { + invisible_images_.erase(record_id); } inline void RemoveImageFinishedRecord(const RecordId& record_id) { @@ -106,15 +106,15 @@ // record will be removed in |AssignPaintTimeToRegisteredQueuedRecords|. } - inline void RecordInvisible(const LayoutObject& object) { - invisible_images_.insert(&object); + inline void RecordInvisible(const RecordId& record_id) { + invisible_images_.insert(record_id); } void RecordVisible(const RecordId& record_id, const uint64_t& visual_size); bool IsRecordedVisibleImage(const RecordId& record_id) const { return visible_images_.Contains(record_id); } - bool IsRecordedInvisibleImage(const LayoutObject& object) const { - return invisible_images_.Contains(&object); + bool IsRecordedInvisibleImage(const RecordId& record_id) const { + return invisible_images_.Contains(record_id); } void NotifyImageFinished(const RecordId& record_id) { @@ -194,7 +194,7 @@ } HashMap<RecordId, std::unique_ptr<ImageRecord>> visible_images_; - HashSet<const LayoutObject*> invisible_images_; + HashSet<RecordId> invisible_images_; // This stores the image records, which are ordered by size. ImageRecordSet size_ordered_set_; @@ -259,7 +259,6 @@ const IntRect& image_border); void NotifyImageFinished(const LayoutObject&, const ImageResourceContent*); void OnPaintFinished(); - void LayoutObjectWillBeDestroyed(const LayoutObject&); void NotifyImageRemoved(const LayoutObject&, const ImageResourceContent*); // After the method being called, the detector stops to record new entries and // node removal. But it still observe the loading status. In other words, if
diff --git a/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.cc b/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.cc index 1402910c..79617a86a 100644 --- a/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.cc +++ b/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.cc
@@ -188,7 +188,7 @@ // To be passed as |accumulated_offset| to LayoutInline::HitTestCulledInline, // where it equals the physical offset of the containing block in paint layer. const PhysicalOffset fallback_accumulated_offset = - physical_offset - fragment.OffsetInContainerBlock(); + physical_offset - fragment.OffsetInContainerFragment(); const LayoutObject* limit_layout_object = parent.PhysicalFragment().IsLineBox() ? parent.Parent()->GetLayoutObject() : parent.GetLayoutObject(); @@ -212,7 +212,7 @@ // To be passed as |accumulated_offset| to LayoutInline::HitTestCulledInline, // where it equals the physical offset of the containing block in paint layer. const PhysicalOffset fallback_accumulated_offset = - physical_offset - item.OffsetInContainerBlock(); + physical_offset - item.OffsetInContainerFragment(); return HitTestCulledInlineAncestors( result, parent_cursor, item.GetLayoutObject(), // Limit the traversal up to the container fragment, or its container if @@ -291,7 +291,7 @@ continue; } - PhysicalRect box_rect(child->OffsetInContainerBlock() + paint_offset, + PhysicalRect box_rect(child->OffsetInContainerFragment() + paint_offset, child->Size()); backplates.AddTextRect(box_rect); } @@ -307,7 +307,7 @@ } PhysicalRect box_rect( - child_item->OffsetInContainerBlock() + paint_offset, + child_item->OffsetInContainerFragment() + paint_offset, child_item->Size()); backplates.AddTextRect(box_rect); } @@ -613,10 +613,10 @@ DCHECK(box_item_); NGInlineCursor descendants = inline_box_cursor_->CursorForDescendants(); const PhysicalOffset paint_offset_to_inline_formatting_context = - paint_offset - box_item_->OffsetInContainerBlock(); + paint_offset - box_item_->OffsetInContainerFragment(); PaintInlineItems(paint_info.ForDescendants(), paint_offset_to_inline_formatting_context, - box_item_->OffsetInContainerBlock(), &descendants); + box_item_->OffsetInContainerFragment(), &descendants); } else if (items_) { if (fragment.IsBlockFlow()) { PaintBlockFlowContents(paint_info, paint_offset); @@ -1580,7 +1580,7 @@ // because soft-wrap and <br> needs to paint outside of InkOverflow() in // inline direction. const PhysicalOffset& child_offset = - paint_offset + child_item->OffsetInContainerBlock(); + paint_offset + child_item->OffsetInContainerFragment(); const PhysicalRect child_rect = child_item->InkOverflow(); if (is_horizontal) { LayoutUnit y = child_rect.offset.top + child_offset.top; @@ -1603,7 +1603,8 @@ line_fragment_id++, paint_info, child_offset); NGInlineCursor line_box_cursor = children->CursorForDescendants(); PaintInlineItems(paint_info, paint_offset, - child_item->OffsetInContainerBlock(), &line_box_cursor); + child_item->OffsetInContainerFragment(), + &line_box_cursor); continue; } @@ -1745,7 +1746,8 @@ // Skip if this child does not intersect with CullRect. if (!paint_info.IntersectsCullRect( - item.InkOverflow(), paint_offset + item.OffsetInContainerBlock()) && + item.InkOverflow(), + paint_offset + item.OffsetInContainerFragment()) && // Don't skip <br>, it doesn't have ink but need to paint selection. !(item.IsLineBreak() && HasSelection(item.GetLayoutObject()))) return; @@ -1772,7 +1774,7 @@ // Skip if this child does not intersect with CullRect. if (!paint_info.IntersectsCullRect( - item.InkOverflow(), paint_offset + item.OffsetInContainerBlock())) + item.InkOverflow(), paint_offset + item.OffsetInContainerFragment())) return; if (child_fragment.IsAtomicInline() || child_fragment.IsListMarker()) { @@ -1804,7 +1806,7 @@ // Skip if this child does not intersect with CullRect. if (!paint_info.IntersectsCullRect( - item.InkOverflow(), paint_offset + item.OffsetInContainerBlock())) + item.InkOverflow(), paint_offset + item.OffsetInContainerFragment())) return; // This |item| is a culled inline box. @@ -1869,7 +1871,7 @@ NGInlineBoxFragmentPainter inline_box_painter(*inline_box_cursor_, *box_item_); PaintTextClipMask(paint_info, - paint_offset - box_item_->OffsetInContainerBlock(), + paint_offset - box_item_->OffsetInContainerFragment(), &inline_box_painter); } @@ -2057,14 +2059,14 @@ if (hit_test.AddNodeToResult( fragment.NodeForHitTest(), /* box_fragment */ nullptr, bounds_rect, - physical_offset - box_item_->OffsetInContainerBlock())) + physical_offset - box_item_->OffsetInContainerFragment())) return true; } else if (paint_fragment_ && paint_fragment_->PhysicalFragment().IsInline()) { if (hit_test.AddNodeToResult( fragment.NodeForHitTest(), /* box_fragment */ nullptr, bounds_rect, - physical_offset - paint_fragment_->OffsetInContainerBlock())) + physical_offset - paint_fragment_->OffsetInContainerFragment())) return true; } else { if (hit_test.AddNodeToResult(fragment.NodeForHitTest(), &box_fragment_, @@ -2140,7 +2142,7 @@ return hit_test.AddNodeToResult( text_fragment.NodeForHitTest(), /* box_fragment */ nullptr, rect, - physical_offset - text_paint_fragment->OffsetInContainerBlock()); + physical_offset - text_paint_fragment->OffsetInContainerFragment()); } bool NGBoxFragmentPainter::HitTestTextItem(const HitTestContext& hit_test, @@ -2154,7 +2156,7 @@ // TODO(layout-dev): Clip to line-top/bottom. const PhysicalOffset offset = - hit_test.inline_root_offset + text_item.OffsetInContainerBlock(); + hit_test.inline_root_offset + text_item.OffsetInContainerFragment(); PhysicalRect border_rect(offset, text_item.Size()); PhysicalRect rect(PixelSnappedIntRect(border_rect)); if (UNLIKELY(hit_test.result->GetHitTestRequest().GetType() & @@ -2225,7 +2227,7 @@ return hit_test.AddNodeToResult( fragment.NodeForHitTest(), &box_fragment_, bounds_rect, - physical_offset - cursor.Current().OffsetInContainerBlock()); + physical_offset - cursor.Current().OffsetInContainerFragment()); } bool NGBoxFragmentPainter::HitTestChildBoxFragment( @@ -2298,7 +2300,7 @@ if (const NGPhysicalBoxFragment* child_fragment = item.BoxFragment()) { const PhysicalOffset child_offset = - hit_test.inline_root_offset + item.OffsetInContainerBlock(); + hit_test.inline_root_offset + item.OffsetInContainerFragment(); return HitTestChildBoxFragment(hit_test, *child_fragment, cursor, child_offset); } @@ -2314,7 +2316,7 @@ if (hit_test.action == kHitTestForeground && IsVisibleToHitTest(item, hit_test.result->GetHitTestRequest())) { const PhysicalOffset child_offset = - hit_test.inline_root_offset + item.OffsetInContainerBlock(); + hit_test.inline_root_offset + item.OffsetInContainerFragment(); PhysicalRect bounds_rect(child_offset, item.Size()); if (UNLIKELY(hit_test.result->GetHitTestRequest().GetType() & HitTestRequest::kHitTestVisualOverflow)) { @@ -2505,7 +2507,7 @@ const NGPhysicalLineBoxFragment* child_fragment = item->LineBoxFragment(); DCHECK(child_fragment); const PhysicalOffset child_offset = - hit_test.inline_root_offset + item->OffsetInContainerBlock(); + hit_test.inline_root_offset + item->OffsetInContainerFragment(); if (HitTestLineBoxFragment(hit_test, *child_fragment, cursor, child_offset)) return true; @@ -2523,7 +2525,7 @@ // Hit test culled inline boxes between |fragment| and its parent // fragment. const PhysicalOffset child_offset = - hit_test.inline_root_offset + item->OffsetInContainerBlock(); + hit_test.inline_root_offset + item->OffsetInContainerFragment(); if (HitTestCulledInlineAncestors(*hit_test.result, container, children, *item, cursor.Current(), hit_test.location, child_offset)) @@ -2631,7 +2633,7 @@ continue; const PhysicalOffset child_offset = - accumulated_offset + item->OffsetInContainerBlock(); + accumulated_offset + item->OffsetInContainerFragment(); if (child_box->IsFloating()) { if (HitTestAllPhasesInFragment(*child_box, hit_test.location, child_offset, hit_test.result))
diff --git a/third_party/blink/renderer/core/paint/ng/ng_inline_box_fragment_painter.cc b/third_party/blink/renderer/core/paint/ng/ng_inline_box_fragment_painter.cc index 3b40844..c30180b 100644 --- a/third_party/blink/renderer/core/paint/ng/ng_inline_box_fragment_painter.cc +++ b/third_party/blink/renderer/core/paint/ng/ng_inline_box_fragment_painter.cc
@@ -63,7 +63,7 @@ const PhysicalOffset adjusted_paint_offset = paint_offset + (inline_box_paint_fragment_ ? inline_box_paint_fragment_->Offset() - : inline_box_item_->OffsetInContainerBlock()); + : inline_box_item_->OffsetInContainerFragment()); if (paint_info.phase == PaintPhase::kForeground) PaintBackgroundBorderShadow(paint_info, adjusted_paint_offset); @@ -370,7 +370,7 @@ for (const NGPaintFragment* fragment : fragments) { PhysicalOffset child_offset = paint_offset + - fragment->OffsetInContainerBlock() - + fragment->OffsetInContainerFragment() - fragment->Offset(); DCHECK(fragment->PhysicalFragment().IsBox()); NGInlineBoxFragmentPainter(*fragment).Paint(paint_info, child_offset); @@ -386,10 +386,10 @@ // inline may not start in the first fragment generated for the inline // formatting context. wtf_size_t target_fragment_idx = - cursor.CurrentContainerFragmentIndex() + + cursor.ContainerFragmentIndex() + paint_info.context.GetPaintController().CurrentFragment(); for (; cursor; cursor.MoveToNextForSameLayoutObject()) { - if (target_fragment_idx != cursor.CurrentContainerFragmentIndex()) + if (target_fragment_idx != cursor.ContainerFragmentIndex()) continue; const NGFragmentItem* item = cursor.CurrentItem(); DCHECK(item);
diff --git a/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.cc b/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.cc index ee1c786..bc83e34 100644 --- a/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.cc +++ b/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.cc
@@ -81,8 +81,8 @@ NGInlineCursor line(cursor); line.MoveToContainingLine(); const PhysicalRect line_physical_rect( - line.Current().OffsetInContainerBlock() - - cursor.Current().OffsetInContainerBlock(), + line.Current().OffsetInContainerFragment() - + cursor.Current().OffsetInContainerFragment(), line.Current().Size()); return ExpandSelectionRectToLineHeight( rect, cursor.Current().ConvertChildToLogical(line_physical_rect)); @@ -625,7 +625,7 @@ if (fragment->PhysicalFragment().IsHiddenForPaint()) continue; PhysicalRect child_visual_rect = fragment->SelfInkOverflow(); - child_visual_rect.offset += fragment->OffsetInContainerBlock(); + child_visual_rect.offset += fragment->OffsetInContainerFragment(); visual_rect.Unite(child_visual_rect); } return visual_rect;
diff --git a/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.h b/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.h index 6d6d083..40d00885 100644 --- a/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.h +++ b/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.h
@@ -155,12 +155,12 @@ bool IsDirty() const { return is_dirty_inline_; } // Returns offset to its container box for inline and line box fragments. - const PhysicalOffset& OffsetInContainerBlock() const { + const PhysicalOffset& OffsetInContainerFragment() const { DCHECK(PhysicalFragment().IsInline() || PhysicalFragment().IsLineBox()); return inline_offset_to_container_box_; } - const PhysicalRect RectInContainerBlock() const { - return PhysicalRect(OffsetInContainerBlock(), Size()); + const PhysicalRect RectInContainerFragment() const { + return PhysicalRect(OffsetInContainerFragment(), Size()); } // InkOverflow of itself, not including contents, in the local coordinate.
diff --git a/third_party/blink/renderer/core/paint/ng/ng_paint_fragment_test.cc b/third_party/blink/renderer/core/paint/ng/ng_paint_fragment_test.cc index 165c210..c51bbcd 100644 --- a/third_party/blink/renderer/core/paint/ng/ng_paint_fragment_test.cc +++ b/third_party/blink/renderer/core/paint/ng/ng_paint_fragment_test.cc
@@ -72,7 +72,7 @@ results.AppendRange(it.begin(), it.end()); EXPECT_EQ(1u, results.size()); EXPECT_EQ(text1, results[0]->GetLayoutObject()); - EXPECT_EQ(PhysicalOffset(), results[0]->OffsetInContainerBlock()); + EXPECT_EQ(PhysicalOffset(), results[0]->OffsetInContainerFragment()); results.clear(); it = NGPaintFragment::InlineFragmentsFor(box); @@ -82,15 +82,15 @@ EXPECT_EQ(box, results[1]->GetLayoutObject()); EXPECT_EQ(box, results[2]->GetLayoutObject()); - EXPECT_EQ(PhysicalOffset(60, 0), results[0]->OffsetInContainerBlock()); + EXPECT_EQ(PhysicalOffset(60, 0), results[0]->OffsetInContainerFragment()); EXPECT_EQ("789", To<NGPhysicalTextFragment>( results[0]->FirstChild()->PhysicalFragment()) .Text()); - EXPECT_EQ(PhysicalOffset(0, 10), results[1]->OffsetInContainerBlock()); + EXPECT_EQ(PhysicalOffset(0, 10), results[1]->OffsetInContainerFragment()); EXPECT_EQ("123456789", To<NGPhysicalTextFragment>( results[1]->FirstChild()->PhysicalFragment()) .Text()); - EXPECT_EQ(PhysicalOffset(0, 20), results[2]->OffsetInContainerBlock()); + EXPECT_EQ(PhysicalOffset(0, 20), results[2]->OffsetInContainerFragment()); EXPECT_EQ("123", To<NGPhysicalTextFragment>( results[2]->FirstChild()->PhysicalFragment()) .Text());
diff --git a/third_party/blink/renderer/core/paint/ng/ng_text_fragment_painter.cc b/third_party/blink/renderer/core/paint/ng/ng_text_fragment_painter.cc index b4b14cb..4de1aaa 100644 --- a/third_party/blink/renderer/core/paint/ng/ng_text_fragment_painter.cc +++ b/third_party/blink/renderer/core/paint/ng/ng_text_fragment_painter.cc
@@ -75,7 +75,7 @@ inline PhysicalRect ComputeBoxRect(const NGInlineCursor& cursor, const PhysicalOffset& paint_offset, const PhysicalOffset& parent_offset) { - PhysicalRect box_rect = cursor.CurrentItem()->RectInContainerBlock(); + PhysicalRect box_rect = cursor.CurrentItem()->RectInContainerFragment(); box_rect.offset.left += paint_offset.left; // We round the y-axis to ensure consistent line heights. box_rect.offset.top =
diff --git a/third_party/blink/renderer/core/paint/paint_timing_detector.cc b/third_party/blink/renderer/core/paint/paint_timing_detector.cc index 6eb858c..09479d6 100644 --- a/third_party/blink/renderer/core/paint/paint_timing_detector.cc +++ b/third_party/blink/renderer/core/paint/paint_timing_detector.cc
@@ -158,9 +158,6 @@ void PaintTimingDetector::LayoutObjectWillBeDestroyed( const LayoutObject& object) { text_paint_timing_detector_->LayoutObjectWillBeDestroyed(object); - - if (image_paint_timing_detector_) - image_paint_timing_detector_->LayoutObjectWillBeDestroyed(object); } void PaintTimingDetector::NotifyImageRemoved(
diff --git a/third_party/blink/renderer/core/svg/svg_path_element.cc b/third_party/blink/renderer/core/svg/svg_path_element.cc index 563e821c..82878464 100644 --- a/third_party/blink/renderer/core/svg/svg_path_element.cc +++ b/third_party/blink/renderer/core/svg/svg_path_element.cc
@@ -157,7 +157,7 @@ FloatRect SVGPathElement::GetBBox() { // We want the exact bounds. - return SVGPathElement::AsPath().BoundingRect(); + return SVGPathElement::AsPath().TightBoundingRect(); } } // namespace blink
diff --git a/third_party/blink/renderer/core/workers/shared_worker_global_scope.cc b/third_party/blink/renderer/core/workers/shared_worker_global_scope.cc index 74e2605..d0bde4c2 100644 --- a/third_party/blink/renderer/core/workers/shared_worker_global_scope.cc +++ b/third_party/blink/renderer/core/workers/shared_worker_global_scope.cc
@@ -68,7 +68,7 @@ token_(token) { appcache_host_ = MakeGarbageCollected<ApplicationCacheHostForWorker>( appcache_host_id, GetBrowserInterfaceBroker(), - GetTaskRunner(TaskType::kInternalLoading), this); + GetTaskRunner(TaskType::kInternalLoading)); } SharedWorkerGlobalScope::~SharedWorkerGlobalScope() = default;
diff --git a/third_party/blink/renderer/modules/canvas/canvas2d/canvas_path.cc b/third_party/blink/renderer/modules/canvas/canvas2d/canvas_path.cc index bd3bf105..6a67606 100644 --- a/third_party/blink/renderer/modules/canvas/canvas2d/canvas_path.cc +++ b/third_party/blink/renderer/modules/canvas/canvas2d/canvas_path.cc
@@ -50,10 +50,7 @@ void CanvasPath::closePath() { if (path_.IsEmpty()) return; - - FloatRect bound_rect = path_.BoundingRect(); - if (bound_rect.Width() || bound_rect.Height()) - path_.CloseSubpath(); + path_.CloseSubpath(); } void CanvasPath::moveTo(double double_x, double double_y) {
diff --git a/third_party/blink/renderer/modules/mediastream/media_stream_video_track_underlying_sink_test.cc b/third_party/blink/renderer/modules/mediastream/media_stream_video_track_underlying_sink_test.cc index 113b954..66131a3 100644 --- a/third_party/blink/renderer/modules/mediastream/media_stream_video_track_underlying_sink_test.cc +++ b/third_party/blink/renderer/modules/mediastream/media_stream_video_track_underlying_sink_test.cc
@@ -69,8 +69,9 @@ PushableMediaStreamVideoSource* pushable_video_source_; }; +// crbug.com/1153092: flaky on several platforms. TEST_F(MediaStreamVideoTrackUnderlyingSinkTest, - WriteToStreamForwardsToMediaStreamSink) { + DISABLED_WriteToStreamForwardsToMediaStreamSink) { V8TestingScope v8_scope; ScriptState* script_state = v8_scope.GetScriptState(); auto* underlying_sink = CreateUnderlyingSink(script_state);
diff --git a/third_party/blink/renderer/modules/mediastream/media_stream_video_track_underlying_source_test.cc b/third_party/blink/renderer/modules/mediastream/media_stream_video_track_underlying_source_test.cc index cb41a5e..3efe5ea 100644 --- a/third_party/blink/renderer/modules/mediastream/media_stream_video_track_underlying_source_test.cc +++ b/third_party/blink/renderer/modules/mediastream/media_stream_video_track_underlying_source_test.cc
@@ -121,7 +121,8 @@ EXPECT_EQ(video_track->CountSinks(), 0u); } -TEST_F(MediaStreamVideoTrackUnderlyingSourceTest, FramesAreDropped) { +// crbug.com/1153092: flaky on several platforms. +TEST_F(MediaStreamVideoTrackUnderlyingSourceTest, DISABLED_FramesAreDropped) { V8TestingScope v8_scope; ScriptState* script_state = v8_scope.GetScriptState(); auto* source = CreateSource(script_state);
diff --git a/third_party/blink/renderer/modules/peerconnection/media_stream_remote_video_source.cc b/third_party/blink/renderer/modules/peerconnection/media_stream_remote_video_source.cc index 9008049..2512403 100644 --- a/third_party/blink/renderer/modules/peerconnection/media_stream_remote_video_source.cc +++ b/third_party/blink/renderer/modules/peerconnection/media_stream_remote_video_source.cc
@@ -15,6 +15,7 @@ #include "media/base/timestamp_constants.h" #include "media/base/video_frame.h" #include "media/base/video_util.h" +#include "third_party/blink/public/common/features.h" #include "third_party/blink/public/mojom/mediastream/media_stream.mojom-blink.h" #include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h" #include "third_party/blink/renderer/platform/webrtc/track_observer.h" @@ -139,6 +140,10 @@ // Offset between NTP clock and WebRTC clock. const int64_t ntp_offset_; + + // Determined from a feature flag; if set WebRTC won't forward an unspecified + // color space. + const bool ignore_unspecified_color_space_; }; MediaStreamRemoteVideoSource::RemoteVideoSourceDelegate:: @@ -160,7 +165,9 @@ base::TimeDelta::FromMicroseconds(rtc::TimeMicros())), clock_(webrtc::Clock::GetRealTimeClock()), ntp_offset_(clock_->TimeInMilliseconds() - - clock_->CurrentNtpInMilliseconds()) {} + clock_->CurrentNtpInMilliseconds()), + ignore_unspecified_color_space_(base::FeatureList::IsEnabled( + features::kWebRtcIgnoreUnspecifiedColorSpace)) {} MediaStreamRemoteVideoSource::RemoteVideoSourceDelegate:: ~RemoteVideoSourceDelegate() = default; @@ -275,7 +282,19 @@ WebRtcToMediaVideoRotation(incoming_frame.rotation()); } - if (incoming_frame.color_space()) { + // The second clause of the condition is controlled by the feature flag + // WebRtcIgnoreUnspecifiedColorSpace. If the feature is enabled we won't try + // to guess a color space if the webrtc::ColorSpace is unspecified. If the + // feature is disabled (default), an unspecified color space will get + // converted into a gfx::ColorSpace set to BT709. + if (incoming_frame.color_space() && + !(ignore_unspecified_color_space_ && + incoming_frame.color_space()->primaries() == + webrtc::ColorSpace::PrimaryID::kUnspecified && + incoming_frame.color_space()->transfer() == + webrtc::ColorSpace::TransferID::kUnspecified && + incoming_frame.color_space()->matrix() == + webrtc::ColorSpace::MatrixID::kUnspecified)) { video_frame->set_color_space( WebRtcToMediaVideoColorSpace(*incoming_frame.color_space()) .ToGfxColorSpace());
diff --git a/third_party/blink/renderer/modules/peerconnection/media_stream_remote_video_source_test.cc b/third_party/blink/renderer/modules/peerconnection/media_stream_remote_video_source_test.cc index c7864177..0d8e50d 100644 --- a/third_party/blink/renderer/modules/peerconnection/media_stream_remote_video_source_test.cc +++ b/third_party/blink/renderer/modules/peerconnection/media_stream_remote_video_source_test.cc
@@ -13,8 +13,10 @@ #include "base/single_thread_task_runner.h" #include "base/synchronization/waitable_event.h" #include "base/test/gmock_callback_support.h" +#include "base/test/scoped_feature_list.h" #include "media/base/video_frame.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/public/common/features.h" #include "third_party/blink/public/mojom/mediastream/media_stream.mojom-blink.h" #include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h" #include "third_party/blink/public/web/modules/mediastream/media_stream_video_source.h" @@ -286,6 +288,80 @@ track->RemoveSink(&sink); } +TEST_F(MediaStreamRemoteVideoSourceTest, + UnspecifiedColorSpaceIsTreatedAsBt709) { + std::unique_ptr<blink::MediaStreamVideoTrack> track(CreateTrack()); + blink::MockMediaStreamVideoSink sink; + track->AddSink(&sink, sink.GetDeliverFrameCB(), false); + + base::RunLoop run_loop; + EXPECT_CALL(sink, OnVideoFrame) + .WillOnce(RunOnceClosure(run_loop.QuitClosure())); + rtc::scoped_refptr<webrtc::I420Buffer> buffer( + new rtc::RefCountedObject<webrtc::I420Buffer>(320, 240)); + webrtc::ColorSpace kColorSpace(webrtc::ColorSpace::PrimaryID::kUnspecified, + webrtc::ColorSpace::TransferID::kUnspecified, + webrtc::ColorSpace::MatrixID::kUnspecified, + webrtc::ColorSpace::RangeID::kLimited); + const webrtc::VideoFrame& input_frame = + webrtc::VideoFrame::Builder() + .set_video_frame_buffer(buffer) + .set_timestamp_ms(0) + .set_rotation(webrtc::kVideoRotation_0) + .set_color_space(kColorSpace) + .build(); + source()->SinkInterfaceForTesting()->OnFrame(input_frame); + run_loop.Run(); + + EXPECT_EQ(1, sink.number_of_frames()); + scoped_refptr<media::VideoFrame> output_frame = sink.last_frame(); + EXPECT_TRUE(output_frame); + EXPECT_TRUE(output_frame->ColorSpace() == + gfx::ColorSpace(gfx::ColorSpace::PrimaryID::BT709, + gfx::ColorSpace::TransferID::BT709, + gfx::ColorSpace::MatrixID::BT709, + gfx::ColorSpace::RangeID::LIMITED)); + track->RemoveSink(&sink); +} + +TEST_F(MediaStreamRemoteVideoSourceTest, UnspecifiedColorSpaceIsIgnored) { + base::test::ScopedFeatureList scoped_feauture_list; + scoped_feauture_list.InitAndEnableFeature( + blink::features::kWebRtcIgnoreUnspecifiedColorSpace); + std::unique_ptr<blink::MediaStreamVideoTrack> track(CreateTrack()); + blink::MockMediaStreamVideoSink sink; + track->AddSink(&sink, sink.GetDeliverFrameCB(), false); + + base::RunLoop run_loop; + EXPECT_CALL(sink, OnVideoFrame) + .WillOnce(RunOnceClosure(run_loop.QuitClosure())); + rtc::scoped_refptr<webrtc::I420Buffer> buffer( + new rtc::RefCountedObject<webrtc::I420Buffer>(320, 240)); + webrtc::ColorSpace kColorSpace(webrtc::ColorSpace::PrimaryID::kUnspecified, + webrtc::ColorSpace::TransferID::kUnspecified, + webrtc::ColorSpace::MatrixID::kUnspecified, + webrtc::ColorSpace::RangeID::kLimited); + const webrtc::VideoFrame& input_frame = + webrtc::VideoFrame::Builder() + .set_video_frame_buffer(buffer) + .set_timestamp_ms(0) + .set_rotation(webrtc::kVideoRotation_0) + .set_color_space(kColorSpace) + .build(); + source()->SinkInterfaceForTesting()->OnFrame(input_frame); + run_loop.Run(); + + EXPECT_EQ(1, sink.number_of_frames()); + scoped_refptr<media::VideoFrame> output_frame = sink.last_frame(); + EXPECT_TRUE(output_frame); + EXPECT_TRUE(output_frame->ColorSpace() == + gfx::ColorSpace(gfx::ColorSpace::PrimaryID::INVALID, + gfx::ColorSpace::TransferID::INVALID, + gfx::ColorSpace::MatrixID::INVALID, + gfx::ColorSpace::RangeID::INVALID)); + track->RemoveSink(&sink); +} + // These tests depend on measuring the difference between the internal WebRTC // clock and Chromium's clock. Due to this they are performance sensitive and // appear to be flaky for builds with ASAN enabled.
diff --git a/third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer.cc b/third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer.cc index 9fd095e1..13951f8 100644 --- a/third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer.cc +++ b/third_party/blink/renderer/platform/graphics/compositing/paint_chunks_to_cc_layer.cc
@@ -815,8 +815,6 @@ const EffectPaintPropertyNode& layer_effect, const PaintChunkSubset& paint_chunks) { Vector<Color, 4> background_colors; - Color safe_opaque_background_color; - float safe_opaque_background_area = 0; float min_background_area = kMinBackgroundColorCoverageRatio * layer.bounds().width() * layer.bounds().height(); for (auto it = paint_chunks.end(); it != paint_chunks.begin();) { @@ -841,20 +839,12 @@ break; } } - if (chunk.background_color_area > safe_opaque_background_area) { - // This color will be used only if we don't find proper background_color. - safe_opaque_background_color = chunk.background_color; - safe_opaque_background_area = chunk.background_color_area; - } } Color background_color; for (Color color : base::Reversed(background_colors)) background_color = background_color.Blend(color); layer.SetBackgroundColor(background_color.Rgb()); - layer.SetSafeOpaqueBackgroundColor(background_color == Color::kTransparent - ? safe_opaque_background_color.Rgb() - : background_color.Rgb()); } static void UpdateTouchActionRegion(
diff --git a/third_party/blink/renderer/platform/graphics/path.cc b/third_party/blink/renderer/platform/graphics/path.cc index 7c9fc54..b3e7bb1 100644 --- a/third_party/blink/renderer/platform/graphics/path.cc +++ b/third_party/blink/renderer/platform/graphics/path.cc
@@ -109,10 +109,14 @@ .contains(SkScalar(point.X()), SkScalar(point.Y())); } -FloatRect Path::BoundingRect() const { +FloatRect Path::TightBoundingRect() const { return path_.computeTightBounds(); } +FloatRect Path::BoundingRect() const { + return path_.getBounds(); +} + FloatRect Path::StrokeBoundingRect(const StrokeData& stroke_data) const { // Skia stroke resolution scale for reduced-precision requirements. constexpr float kStrokePrecision = 0.3f;
diff --git a/third_party/blink/renderer/platform/graphics/path.h b/third_party/blink/renderer/platform/graphics/path.h index 94d8003..84351f1d 100644 --- a/third_party/blink/renderer/platform/graphics/path.h +++ b/third_party/blink/renderer/platform/graphics/path.h
@@ -98,6 +98,10 @@ const AffineTransform&) const; SkPath StrokePath(const StrokeData&, const AffineTransform&) const; + // Tight Bounding calculation is very expensive, but it guarantees the strict + // bounding box. It's always included in BoundingRect. For a logical bounding + // box (used for clipping or damage) BoundingRect is recommended. + FloatRect TightBoundingRect() const; FloatRect BoundingRect() const; FloatRect StrokeBoundingRect(const StrokeData&) const;
diff --git a/third_party/blink/tools/blinkpy/w3c/test_importer.py b/third_party/blink/tools/blinkpy/w3c/test_importer.py index d029e7e..25bf0dfb 100644 --- a/third_party/blink/tools/blinkpy/w3c/test_importer.py +++ b/third_party/blink/tools/blinkpy/w3c/test_importer.py
@@ -565,7 +565,7 @@ # https://chromium-review.googlesource.com/c/chromium/src/+/2451504 description += ( 'Cq-Include-Trybots: luci.chromium.try:linux-wpt-identity-fyi-rel,' - 'linux-wpt-payments-fyi-rel') + 'linux-wpt-input-fyi-rel') return description
diff --git a/third_party/blink/tools/blinkpy/w3c/test_importer_unittest.py b/third_party/blink/tools/blinkpy/w3c/test_importer_unittest.py index f023cbc..4382c9c 100644 --- a/third_party/blink/tools/blinkpy/w3c/test_importer_unittest.py +++ b/third_party/blink/tools/blinkpy/w3c/test_importer_unittest.py
@@ -404,7 +404,7 @@ 'NOAUTOREVERT=true\n' 'No-Export: true\n' 'Cq-Include-Trybots: luci.chromium.try:linux-wpt-identity-fyi-rel,' - 'linux-wpt-payments-fyi-rel') + 'linux-wpt-input-fyi-rel') print host.executive.calls self.assertEqual(host.executive.calls, [MANIFEST_INSTALL_CMD] +
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index ecbc1977..f806d4c 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -5290,6 +5290,8 @@ crbug.com/1134464 http/tests/images/document-policy/document-policy-oversized-images-edge-cases.php [ Pass Timeout ] +crbug.com/1151954 http/tests/permissions-policy/permissions-policy-in-xsl.php [ Failure ] + # Skipping because of unimplemented behaviour crbug.com/965495 external/wpt/feature-policy/experimental-features/focus-without-user-activation-enabled-tentative.sub.html [ Skip ] crbug.com/965495 external/wpt/permissions-policy/experimental-features/focus-without-user-activation-enabled-tentative.sub.html [ Skip ] @@ -5917,6 +5919,7 @@ # Sheriff 2020-09-30 crbug.com/1133821 virtual/off-main-thread-css-paint/external/wpt/css/css-paint-api/one-custom-property-animation.https.html [ Pass Failure ] crbug.com/1133821 virtual/off-main-thread-css-paint/external/wpt/css/css-paint-api/two-custom-property-animation.https.html [ Pass Failure ] +crbug.com/1133821 virtual/off-main-thread-css-paint/external/wpt/css/css-paint-api/two-element-custom-property-animation.https.html [ Pass Failure ] # Sheriff 2020-10-09 crbug.com/1136687 external/wpt/pointerevents/pointerlock/pointerevent_pointerlock_supercedes_capture.html [ Pass Failure ] @@ -6023,3 +6026,7 @@ crbug.com/1092048 external/wpt/FileAPI/blob/Blob-stream.any.html [ Pass Timeout ] crbug.com/1092048 external/wpt/FileAPI/blob/Blob-stream.any.worker.html [ Pass Timeout ] crbug.com/1134459 accessibility/aom-click-action.html [ Pass Timeout ] + +#Sheriff 2020-11-26 +crbug.com/1032451 virtual/threaded-no-composited-antialiasing/animations/stability/animation-iteration-event-destroy-renderer.html [ Pass Timeout ] +crbug.com/931646 [ Mac ] http/tests/preload/meta-viewport-link-headers-imagesrcset.html [ Failure Pass ]
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 6b7b2ce..0ab8189 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
@@ -157069,6 +157069,19 @@ {} ] ], + "fieldset-max-block-size.html": [ + "170dedd6067b0d9663f5b1346a43cbeaf7d8bcf8", + [ + null, + [ + [ + "/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/fieldset-max-block-size-ref.html", + "==" + ] + ], + {} + ] + ], "fieldset-overflow-hidden.html": [ "cacbdbae00d0f7d6067323c68fc460149c524f35", [ @@ -226685,6 +226698,10 @@ "05b8ca4770b18a91aaf2d9f3038d6fe4162f289f", [] ], + "fieldset-max-block-size-ref.html": [ + "07c9da85b5347bdd2b01f3b52221dc791ed8a6f0", + [] + ], "fieldset-overflow-hidden-ref.html": [ "9fe632f7c209c42d9f24358ad6a2a56abddf97a3", [] @@ -232602,9 +232619,45 @@ "1e219ecd5bead581a7eca478bcefcdd72dc8c9be", [] ], + "input-events-exec-command.html.ini": [ + "cd807c3d4df96ac8c0558fad451840ef29c4d80d", + [] + ], + "input-events-get-target-ranges-backspace.tentative.html.ini": [ + "62a9d9068d7d3ac62354d722b211fe41f9563ba1", + [] + ], + "input-events-get-target-ranges-deleting-in-list-items.tentative.html.ini": [ + "287527c2ac935f40521c50e36bc4b708331bac92", + [] + ], + "input-events-get-target-ranges-during-and-after-dispatch.tentative.html.ini": [ + "b4a346ae68cb4726c82ff7bbdc1617164bcea293", + [] + ], + "input-events-get-target-ranges-forwarddelete.tentative.html.ini": [ + "93057d092c00c6d4295616b3590033c8ca17b313", + [] + ], + "input-events-get-target-ranges-joining-dl-element-and-another-list.tentative.html.ini": [ + "3682b5332d210f74721284474c626db0712515fc", + [] + ], + "input-events-get-target-ranges-joining-dl-elements.tentative.html.ini": [ + "d0038c797e84996751fbc50ae9659991d19da1c7", + [] + ], + "input-events-get-target-ranges-non-collapsed-selection.tentative.html.ini": [ + "a01e994f02a6c57f3e1675c0439ab338e2beb650", + [] + ], "input-events-get-target-ranges.js": [ "f9404e07a5564c64a2863a1329728517fedd5ca7", [] + ], + "input-events-typing.html.ini": [ + "9647ef7e893fc208959f3ddbfef78e11f59c4129", + [] ] }, "installedapp": { @@ -233309,7 +233362,7 @@ [] ], "webrtc.idl": [ - "d82cde768f7b5f65e78570227510f2e4f0d4b7c1", + "db644f031836bd2dfa8d046f5c78d561186490ec", [] ], "webusb.idl": [ @@ -237468,14 +237521,38 @@ "22bb34a054ec5d0f1ed837b8b23d544110d78912", [] ], + "idlharness.window.js.ini": [ + "2c8f43716403bfd4a8bd8a7bdecaf888a2bcd697", + [] + ], + "pointerevent_auxclick_is_a_pointerevent.html.ini": [ + "e4f7b0ee92d0e4d3b4bdf95c83223be85ca0b0a5", + [] + ], + "pointerevent_click_is_a_pointerevent.html.ini": [ + "3994b407af65d66547f2820b6a72e96f99ed86a7", + [] + ], "pointerevent_coalesced_events_attributes-expected.txt": [ "e9ecdaa4bfe35a4e711c10c960d3d7124c389537", [] ], + "pointerevent_iframe-touch-action-none_touch.html.ini": [ + "bee7254d54849e87c06137d7541c0da5332155c0", + [] + ], + "pointerevent_pointercapture-not-lost-in-chorded-buttons.html.ini": [ + "6b81a4d1d7d37235727f321f0f07f3a4f58b1614", + [] + ], "pointerevent_pointercapture_in_frame-expected.txt": [ "4d3d205c84983950b3a0cdee366d51ca0427f592", [] ], + "pointerevent_pointercapture_in_frame.html.ini": [ + "42b68012c5fa1510245eb54dbf95f3db321b5d03", + [] + ], "pointerevent_styles.css": [ "1ee3b0b3965ff9fb3c5960f606cca6477ce145a8", [] @@ -237485,6 +237562,30 @@ [] ], "pointerlock": { + "pointerevent_coordinates_when_locked.html.ini": [ + "04c0f72c7d99bc37a364e7192e7e65a1e6827f60", + [] + ], + "pointerevent_getCoalescedEvents_when_pointerlocked.html.ini": [ + "9e125839696524cc24cb3f91655765624854e1f8", + [] + ], + "pointerevent_movementxy_with_pointerlock.html.ini": [ + "d22487b5371f040fd3edb99ac345b2a38cc58705", + [] + ], + "pointerevent_pointerlock_after_pointercapture.html.ini": [ + "dc1a38a96f354e88d08d45bfa692583cb4dcc4ac", + [] + ], + "pointerevent_pointermove_in_pointerlock.html.ini": [ + "7c4043d0fa0abe2ae9d15c437aac8b617a3c5512", + [] + ], + "pointerevent_pointermove_on_chorded_mouse_button_when_locked.html.ini": [ + "9d0b178aa192acc5ac1428b67482728b9ee676ee", + [] + ], "resources": { "pointerevent_movementxy-iframe.html": [ "627af3b61cad74bb112558169b1e66f6a24b1129", @@ -359971,6 +360072,15 @@ } ] ], + "reporting-coop-navigated-opener.https.html": [ + "858f31b982878b34ebce744b945a7fc7b8925aa3", + [ + null, + { + "timeout": "long" + } + ] + ], "reporting-coop-navigated-popup.https.html": [ "dde4c40b38a1e541f66c47573fbd642f2e1e8289", [
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-coop-navigated-opener.https.html b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-coop-navigated-opener.https.html new file mode 100644 index 0000000..858f31b --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting/navigation-reporting/reporting-coop-navigated-opener.https.html
@@ -0,0 +1,68 @@ +<title> + Reports a browsing context group switch when an opener with COOP navigates. +</title> +<meta name=timeout content=long> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<script src=/common/get-host-info.sub.js></script> +<script src="/common/utils.js"></script> +<script src="../resources/dispatcher.js"></script> +<script> + +const directory = "/html/cross-origin-opener-policy/reporting"; +const executor_path = directory + "/resources/executor.html?pipe="; +const same_origin = get_host_info().HTTPS_ORIGIN; + +let escapeComma = url => url.replace(/,/g, '\\,'); + +promise_test(async t => { + // The test window. + const this_window_token = token(); + + // The "opener" window. + const opener_token = token(); + const opener_url = same_origin + executor_path + `&uuid=${opener_token}`; + + // The "openee" window. + const openee_token = token(); + const openee_url = same_origin + executor_path + `&uuid=${openee_token}`; + + // The "final" url the opener will navigate to. It has COOP and a reporter. + const final_report_token= token(); + const final_token = token(); + const final_reportTo = reportToHeaders(final_report_token); + const final_url = same_origin + executor_path + final_reportTo.header + + final_reportTo.coopSameOriginHeader +`&uuid=${final_token}`; + + // 1. Create the opener window and ensure it doesn't have an opener. + let opener_window_proxy = window.open(opener_url, '_blank', 'noopener'); + t.add_cleanup(() => send(opener_token, "window.close()")); + + // 2. The opener opens a window. + send(opener_token, ` + openee = window.open('${escapeComma(openee_url)}'); + send("${this_window_token}", "ACK 1"); + `); + + // 3. Ensure the openee loads. + send(openee_token, ` + send("${this_window_token}", "ACK 1"); + `); + assert_equals("ACK 1", await receive(this_window_token)); + + // 4. The opener navigates. + send(opener_token, ` + location.replace('${escapeComma(final_url)}'); + `); + + // 5. Check a report was sent to the opener. + let report = + await receiveReport(final_report_token, "navigation-to-response") + assert_equals(report.type, "coop"); + assert_equals(report.url, final_url.replace(/"/g, '%22')); + assert_equals(report.body.disposition, "enforce"); + assert_equals(report.body.effectivePolicy, "same-origin"); + assert_equals(report.body.previousResponseURL, opener_url.replace(/"/g, '%22')); +}, "navigation-report-from-opener-navigation"); + +</script>
diff --git a/third_party/blink/web_tests/external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/fieldset-max-block-size-ref.html b/third_party/blink/web_tests/external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/fieldset-max-block-size-ref.html new file mode 100644 index 0000000..07c9da8 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/fieldset-max-block-size-ref.html
@@ -0,0 +1,34 @@ +<!DOCTYPE html> +<style> +.fieldset { + border: 2px solid gray; + margin: 1em; + padding: 0; + width: 20em; +} + +.f1 { + overflow: auto; + max-height: 3em; +} +.f2 { + max-height: 0; +} +</style> + +<div class="fieldset f1"> +<div>foo</div> +<div>foo</div> +<div>foo</div> +<div>foo</div> +<div>foo</div> +</div> + +<div class="fieldset f1"> +<div>foo</div> +</div> + +<div class="fieldset f2"> +<div>foo</div> +</div> +
diff --git a/third_party/blink/web_tests/external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/fieldset-max-block-size.html b/third_party/blink/web_tests/external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/fieldset-max-block-size.html new file mode 100644 index 0000000..170dedd6 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/fieldset-max-block-size.html
@@ -0,0 +1,36 @@ +<!DOCTYPE html> +<link rel="help" href="http://crbug.com/1151858"> +<link rel="match" href="fieldset-max-block-size-ref.html"> +<style> +fieldset { + border: 2px solid gray; + margin: 1em; + padding: 0; + width: 20em; +} + +.f1 { + overflow: auto; + max-height: 3em; +} +.f2 { + max-height: 0; +} +</style> + +<fieldset class="f1"> +<div>foo</div> +<div>foo</div> +<div>foo</div> +<div>foo</div> +<div>foo</div> +</fieldset> + +<fieldset class="f1"> +<div>foo</div> +</fieldset> + +<fieldset class="f2"> +<div>foo</div> +</fieldset> +
diff --git a/third_party/blink/web_tests/external/wpt/interfaces/webrtc.idl b/third_party/blink/web_tests/external/wpt/interfaces/webrtc.idl index d82cde7..db644f03 100644 --- a/third_party/blink/web_tests/external/wpt/interfaces/webrtc.idl +++ b/third_party/blink/web_tests/external/wpt/interfaces/webrtc.idl
@@ -238,7 +238,7 @@ unsigned short? port; DOMString url; required unsigned short errorCode; - USVString statusText; + USVString errorText; }; partial interface RTCPeerConnection {
diff --git a/third_party/blink/web_tests/external/wpt/largest-contentful-paint/placeholder-image.html b/third_party/blink/web_tests/external/wpt/largest-contentful-paint/placeholder-image.html new file mode 100644 index 0000000..6a2ce5c --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/largest-contentful-paint/placeholder-image.html
@@ -0,0 +1,31 @@ +<!DOCTYPE HTML> +<meta charset=utf-8> +<title>Largest Contentful Paint: src change triggers new entry.</title> +<body> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/largest-contentful-paint-helpers.js"></script> +<img src='/images/green-1x1.png' id='image_id' width="133" height="106"/> +<script> + async_test(function (t) { + assert_implements(window.LargestContentfulPaint, "LargestContentfulPaint is not implemented"); + let beforeLoad = performance.now(); + document.getElementById('image_id').src = '/images/blue.png'; + const url = window.location.origin + '/images/blue.png'; + const observer = new PerformanceObserver( + t.step_func(function(entryList) { + let entries = entryList.getEntries().filter(e => e.url === url); + if (entries.length === 0) + return; + assert_equals(entries.length, 1); + const entry = entries[0]; + // blue.png is 133 by 106. + const size = 133 * 106; + checkImage(entry, url, 'image_id', size, beforeLoad); + t.done(); + }) + ); + observer.observe({type: 'largest-contentful-paint', buffered: true}); + }, 'Largest Contentful Paint: changing src causes a new entry to be dispatched.'); +</script> +</body>
diff --git a/third_party/blink/web_tests/fast/canvas-api/canvas-scroll-path-into-view-expected.txt b/third_party/blink/web_tests/fast/canvas-api/canvas-scroll-path-into-view-expected.txt index 08064e72..cdbeb3c 100644 --- a/third_party/blink/web_tests/fast/canvas-api/canvas-scroll-path-into-view-expected.txt +++ b/third_party/blink/web_tests/fast/canvas-api/canvas-scroll-path-into-view-expected.txt
@@ -31,11 +31,11 @@ PASS testValue is 636 PASS testValue is 1136 PASS testValue is 636 -PASS testValue is 127 -PASS testValue is 627 -PASS testValue is 627 -PASS testValue is 1127 -PASS testValue is 627 +PASS testValue is 106 +PASS testValue is 606 +PASS testValue is 606 +PASS testValue is 1106 +PASS testValue is 606 PASS testValue is 133 PASS testValue is 633 PASS testValue is 633 @@ -77,11 +77,11 @@ PASS testValue is 636 PASS testValue is 1136 PASS testValue is 636 -PASS testValue is 127 -PASS testValue is 627 -PASS testValue is 627 -PASS testValue is 1127 -PASS testValue is 627 +PASS testValue is 106 +PASS testValue is 606 +PASS testValue is 606 +PASS testValue is 1106 +PASS testValue is 606 PASS testValue is 133 PASS testValue is 633 PASS testValue is 633
diff --git a/third_party/blink/web_tests/fast/canvas-api/script-tests/canvas-scroll-path-into-view.js b/third_party/blink/web_tests/fast/canvas-api/script-tests/canvas-scroll-path-into-view.js index 63674ee..06d0c58 100644 --- a/third_party/blink/web_tests/fast/canvas-api/script-tests/canvas-scroll-path-into-view.js +++ b/third_party/blink/web_tests/fast/canvas-api/script-tests/canvas-scroll-path-into-view.js
@@ -132,7 +132,7 @@ debug("Test case 2: scrollPathIntoView() / CTM != identity"); scrollTest(CRect, 20, false, 136); -scrollTest(CCapsule, 42, false, 127); +scrollTest(CCapsule, 42, false, 106); scrollTest(CCurve, 63, false, 133); scrollTest(CStar, 40, false, 160); debug(""); @@ -146,7 +146,7 @@ debug("Test case 4: scrollPathIntoView(path2d) / CTM != identity"); scrollTest(CRect, 20, true, 136); -scrollTest(CCapsule, 42, true, 127); +scrollTest(CCapsule, 42, true, 106); scrollTest(CCurve, 63, true, 133); scrollTest(CStar, 40, true, 160); debug("");
diff --git a/third_party/blink/web_tests/http/tests/devtools/elements/highlight/highlight-css-flex-alignment-expected.txt b/third_party/blink/web_tests/http/tests/devtools/elements/highlight/highlight-css-flex-alignment-expected.txt new file mode 100644 index 0000000..02d9398 --- /dev/null +++ b/third_party/blink/web_tests/http/tests/devtools/elements/highlight/highlight-css-flex-alignment-expected.txt
@@ -0,0 +1,858 @@ +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": "LayoutNGFlexibleBox", + "showAccessibilityInfo": true + }, + "flexInfo": [ + { + "containerBorder": [ + "M", + 0, + 0, + "L", + 100, + 0, + "L", + 100, + 100, + "L", + 0, + 100, + "Z" + ], + "lines": [ + [ + [ + "M", + 0, + 0, + "L", + 0, + 0, + "L", + 0, + 0, + "L", + 0, + 0, + "Z" + ] + ] + ], + "isHorizontalFlow": true, + "alignItemsStyle": "flex-start", + "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": "LayoutNGFlexibleBox", + "showAccessibilityInfo": true + }, + "flexInfo": [ + { + "containerBorder": [ + "M", + 0, + 100, + "L", + 100, + 100, + "L", + 100, + 200, + "L", + 0, + 200, + "Z" + ], + "lines": [ + [ + [ + "M", + 0, + 200, + "L", + 0, + 200, + "L", + 0, + 200, + "L", + 0, + 200, + "Z" + ] + ] + ], + "isHorizontalFlow": true, + "alignItemsStyle": "flex-end", + "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": "LayoutNGFlexibleBox", + "showAccessibilityInfo": true + }, + "flexInfo": [ + { + "containerBorder": [ + "M", + 0, + 200, + "L", + 100, + 200, + "L", + 100, + 300, + "L", + 0, + 300, + "Z" + ], + "lines": [ + [ + [ + "M", + 0, + 250, + "L", + 0, + 250, + "L", + 0, + 250, + "L", + 0, + 250, + "Z" + ] + ] + ], + "isHorizontalFlow": true, + "alignItemsStyle": "center", + "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": "LayoutNGFlexibleBox", + "showAccessibilityInfo": true + }, + "flexInfo": [ + { + "containerBorder": [ + "M", + 0, + 300, + "L", + 100, + 300, + "L", + 100, + 400, + "L", + 0, + 400, + "Z" + ], + "lines": [ + [ + [ + "M", + 0, + 300, + "L", + 0, + 300, + "L", + 0, + 400, + "L", + 0, + 400, + "Z" + ] + ] + ], + "isHorizontalFlow": true, + "alignItemsStyle": "stretch", + "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": "LayoutNGFlexibleBox", + "showAccessibilityInfo": true + }, + "flexInfo": [ + { + "containerBorder": [ + "M", + 0, + 400, + "L", + 100, + 400, + "L", + 100, + 500, + "L", + 0, + 500, + "Z" + ], + "lines": [ + [ + [ + "M", + 0, + 400, + "L", + 0, + 400, + "L", + 0, + 500, + "L", + 0, + 500, + "Z" + ] + ] + ], + "isHorizontalFlow": true, + "alignItemsStyle": "normal", + "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/http/tests/devtools/elements/highlight/highlight-css-flex-alignment.js b/third_party/blink/web_tests/http/tests/devtools/elements/highlight/highlight-css-flex-alignment.js new file mode 100644 index 0000000..555cdad --- /dev/null +++ b/third_party/blink/web_tests/http/tests/devtools/elements/highlight/highlight-css-flex-alignment.js
@@ -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. + +(async function() { + TestRunner.addResult(`This test verifies the flex self-alignment value sent by the backend.\n`); + await TestRunner.loadModule('elements_test_runner'); + await TestRunner.showPanel('elements'); + await TestRunner.loadHTML(` + <style> + html, body { + margin: 0; + } + .container { + width: 100px; + height: 100px; + display: flex; + } + button { + width: 50px; + height: 50px; + border: 0; + padding: 0; + } + </style> + <div id="flex-start" class="container" style="align-items:flex-start"><div class="item"></div></div> + <div id="flex-end" class="container" style="align-items:flex-end"><div class="item"></div></div> + <div id="center" class="container" style="align-items:center"><div class="item"></div></div> + <div id="stretch" class="container" style="align-items:stretch"><div class="item"></div></div> + <div id="normal" class="container" style="align-items:normal"><div class="item"></div></div> + <p id="description">This test verifies the flex self-alignment value sent by the backend.</p> + `); + + function dumpFlexHighlight(id) { + return new Promise(resolve => ElementsTestRunner.dumpInspectorHighlightJSON(id, resolve)); + } + + await dumpFlexHighlight('flex-start'); + await dumpFlexHighlight('flex-end'); + await dumpFlexHighlight('center'); + await dumpFlexHighlight('stretch'); + await dumpFlexHighlight('normal'); + + TestRunner.completeTest(); +})();
diff --git a/third_party/blink/web_tests/http/tests/devtools/elements/highlight/highlight-css-flex-expected.txt b/third_party/blink/web_tests/http/tests/devtools/elements/highlight/highlight-css-flex-expected.txt index 4840cda..7193a00 100644 --- a/third_party/blink/web_tests/http/tests/devtools/elements/highlight/highlight-css-flex-expected.txt +++ b/third_party/blink/web_tests/http/tests/devtools/elements/highlight/highlight-css-flex-expected.txt
@@ -162,6 +162,7 @@ ] ], "isHorizontalFlow": true, + "alignItemsStyle": "normal", "flexContainerHighlightConfig": { "containerBorder": { "color": "rgba(255, 0, 0, 0)", @@ -190,6 +191,10 @@ "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/http/tests/devtools/elements/highlight/highlight-css-flex-multiline-expected.txt b/third_party/blink/web_tests/http/tests/devtools/elements/highlight/highlight-css-flex-multiline-expected.txt index 481d128..5f32fb1 100644 --- a/third_party/blink/web_tests/http/tests/devtools/elements/highlight/highlight-css-flex-multiline-expected.txt +++ b/third_party/blink/web_tests/http/tests/devtools/elements/highlight/highlight-css-flex-multiline-expected.txt
@@ -209,6 +209,7 @@ ] ], "isHorizontalFlow": true, + "alignItemsStyle": "normal", "flexContainerHighlightConfig": { "containerBorder": { "color": "rgba(255, 0, 0, 0)", @@ -237,6 +238,10 @@ "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/http/tests/inspector-protocol/network-fetch-content-with-error-status-code-expected.txt b/third_party/blink/web_tests/http/tests/inspector-protocol/network-fetch-content-with-error-status-code-expected.txt index 7c8a3a4..c444de4 100644 --- a/third_party/blink/web_tests/http/tests/inspector-protocol/network-fetch-content-with-error-status-code-expected.txt +++ b/third_party/blink/web_tests/http/tests/inspector-protocol/network-fetch-content-with-error-status-code-expected.txt
@@ -9,6 +9,8 @@ Method: OPTIONS Url: https://127.0.0.1:8443/inspector-protocol/resources/cors-data.php Has extra info: true + References get request: true + Initiator type: preflight GET response: Has timing info: true Has extra info: true
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/network-fetch-content-with-error-status-code.js b/third_party/blink/web_tests/http/tests/inspector-protocol/network-fetch-content-with-error-status-code.js index 32bf7afcb..11975b6 100644 --- a/third_party/blink/web_tests/http/tests/inspector-protocol/network-fetch-content-with-error-status-code.js +++ b/third_party/blink/web_tests/http/tests/inspector-protocol/network-fetch-content-with-error-status-code.js
@@ -15,6 +15,7 @@ getRequestEventParams = event.params; } else if (event.params.request.method === 'OPTIONS') { optionsRequestEventParams = event.params; + optionsRequestInitiatorRequestId = event.params.initiator.requestId; } }); @@ -53,6 +54,8 @@ }); async function printResultsAndFinish() { + const optionsRequestReferencedGetRequest = + optionsRequestInitiatorRequestId === getRequestEventParams.requestId; testRunner.log('GET Request:'); testRunner.log(` Method: ${getRequestEventParams.request.method}`); testRunner.log(` Url: ${getRequestEventParams.request.url}`); @@ -62,6 +65,10 @@ testRunner.log(` Method: ${optionsRequestEventParams.request.method}`); testRunner.log(` Url: ${optionsRequestEventParams.request.url}`); testRunner.log(` Has extra info: ${optionsRequestExtra}`); + testRunner.log( + ` References get request: ${optionsRequestReferencedGetRequest}`); + testRunner.log( + ` Initiator type: ${optionsRequestEventParams.initiator.type}`); testRunner.log('GET response:'); testRunner.log(` Has timing info: ${!!getResponseEventParams.response.timing}`);
diff --git a/third_party/blink/web_tests/http/tests/origin_trials/third-party-first-party-token-in-markup-enabled.html b/third_party/blink/web_tests/http/tests/origin_trials/third-party-first-party-token-in-markup-enabled.html new file mode 100644 index 0000000..13dc97c9 --- /dev/null +++ b/third_party/blink/web_tests/http/tests/origin_trials/third-party-first-party-token-in-markup-enabled.html
@@ -0,0 +1,16 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>Test that trial which supports third-party is enabled by valid first-party token provided in markup</title> +<!-- Generate this token with the command: +generate_token.py http://127.0.0.1:8000 FrobulateThirdParty --expire-timestamp=2000000000 +--> +<meta http-equiv="origin-trial" + content="A0TyTDFs2N+ecIcAeQo8DlipLQwIEcD+bJlRGpZj5NfDDGF8VEcEL4zByhPrdadxF1PX8VG4bfd2XZep1O6m3wsAAABbeyJvcmlnaW4iOiAiaHR0cDovLzEyNy4wLjAuMTo4MDAwIiwgImZlYXR1cmUiOiAiRnJvYnVsYXRlVGhpcmRQYXJ0eSIsICJleHBpcnkiOiAyMDAwMDAwMDAwfQ==" /> +<script src="../resources/testharness.js"></script> +<script src="../resources/testharnessreport.js"></script> +<script src="resources/origintrials.js"></script> +<script> + // The trial should be enabled, as first party tokens can be used normally, + // when the trial has third-party support enabled. + expect_success_third_party(); +</script>
diff --git a/third_party/blink/web_tests/http/tests/permissions-policy/permissions-policy-in-xsl.php b/third_party/blink/web_tests/http/tests/permissions-policy/permissions-policy-in-xsl.php new file mode 100644 index 0000000..5e418ba7 --- /dev/null +++ b/third_party/blink/web_tests/http/tests/permissions-policy/permissions-policy-in-xsl.php
@@ -0,0 +1,9 @@ +<?php +header("Permissions-Policy: document-domain=()"); +header("Content-Type: application/xml"); + +echo '<?xml version="1.0"?> +<?xml-stylesheet href="resources/permissions-policy-in-xsl.xslt" type="text/xsl"?> +<page> +</page>'; +?>
diff --git a/third_party/blink/web_tests/http/tests/permissions-policy/resources/permissions-policy-in-xsl.xslt b/third_party/blink/web_tests/http/tests/permissions-policy/resources/permissions-policy-in-xsl.xslt new file mode 100644 index 0000000..f0cee19 --- /dev/null +++ b/third_party/blink/web_tests/http/tests/permissions-policy/resources/permissions-policy-in-xsl.xslt
@@ -0,0 +1,30 @@ +<?xml version="1.0"?> +<xsl:stylesheet version="1.0" + xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> + +<xsl:template match="page"> + <html> + <head> + <title> Test XSLT </title> + <script src="../../resources/testharness.js"></script> + <script src="../../resources/testharnessreport.js"></script> + <script> + test(() => { + let feature_allowed; + try { + document.domain = document.domain; + feature_allowed = true; + } catch(e) { + feature_allowed = false; + } + + assert_false(feature_allowed, "Feature(Document Domain) should not be allowed by permissions policy."); + }); + </script> + </head> + <body bgcolor="#ffffff"> + </body> + </html> +</xsl:template> + +</xsl:stylesheet> \ No newline at end of file
diff --git a/third_party/harfbuzz-ng/README.chromium b/third_party/harfbuzz-ng/README.chromium index d34f729..fcc234f 100644 --- a/third_party/harfbuzz-ng/README.chromium +++ b/third_party/harfbuzz-ng/README.chromium
@@ -1,10 +1,10 @@ Name: harfbuzz-ng Short Name: harfbuzz-ng URL: http://harfbuzz.org -Version: 2.7.2-62 +Version: 2.7.2-137 CPEPrefix: cpe:/a:harfbuzz_project:harfbuzz:2.6.4 -Date: 20201007 -Revision: c39ab82c90479341dcf28eaa8174af6f08c0d7ae +Date: 20201126 +Revision: 53806e5b83cee0e275eac038d0780f95ac56588c Security Critical: yes License: MIT License File: src/COPYING
diff --git a/tools/accessibility/inspect/README.md b/tools/accessibility/inspect/README.md index 7874ece..b1847ae2 100644 --- a/tools/accessibility/inspect/README.md +++ b/tools/accessibility/inspect/README.md
@@ -52,7 +52,6 @@ `--pid=process_id` Other options: -`--json` to output a tree in JSON format `--filters=absolute_path_to_filters.txt` to filter properties, use where the filters text file has a series of `@ALLOW` and/or `@DENY` lines. See example-tree-filters.txt in tools/accessibility/inspect. `--help` for help
diff --git a/tools/accessibility/inspect/ax_dump_tree.cc b/tools/accessibility/inspect/ax_dump_tree.cc index e0239d2..aca2f25 100644 --- a/tools/accessibility/inspect/ax_dump_tree.cc +++ b/tools/accessibility/inspect/ax_dump_tree.cc
@@ -22,7 +22,6 @@ "pid"; #endif char kFiltersSwitch[] = "filters"; -char kJsonSwitch[] = "json"; char kHelpSwitch[] = "help"; // Convert from string to int, whether in 0x hex format or decimal format. @@ -88,8 +87,6 @@ base::FilePath filters_path = command_line->GetSwitchValuePath(kFiltersSwitch); - bool use_json = command_line->HasSwitch(kJsonSwitch); - std::string id_str = command_line->GetSwitchValueASCII(kIdSwitch); if (!id_str.empty()) { unsigned hwnd_or_pid; @@ -100,14 +97,14 @@ gfx::AcceleratedWidget widget(CastToAcceleratedWidget(hwnd_or_pid)); std::unique_ptr<content::AXTreeServer> server( - new content::AXTreeServer(widget, filters_path, use_json)); + new content::AXTreeServer(widget, filters_path)); return 0; } AXTreeSelector selector = tools::TreeSelectorFromCommandLine(command_line); if (!selector.empty()) { std::unique_ptr<content::AXTreeServer> server( - new content::AXTreeServer(selector, filters_path, use_json)); + new content::AXTreeServer(selector, filters_path)); return 0; }
diff --git a/tools/accessibility/inspect/ax_tree_server.cc b/tools/accessibility/inspect/ax_tree_server.cc index 66b2eb8f..86b5f79 100644 --- a/tools/accessibility/inspect/ax_tree_server.cc +++ b/tools/accessibility/inspect/ax_tree_server.cc
@@ -10,7 +10,6 @@ #include "base/at_exit.h" #include "base/bind.h" #include "base/files/file_util.h" -#include "base/json/json_writer.h" #include "base/logging.h" #include "base/path_service.h" #include "base/run_loop.h" @@ -41,20 +40,17 @@ } AXTreeServer::AXTreeServer(const AXTreeSelector& selector, - const base::FilePath& filters_path, - bool use_json) { - Run(base::BindOnce(&BuildTreeForSelector, selector), filters_path, use_json); + const base::FilePath& filters_path) { + Run(base::BindOnce(&BuildTreeForSelector, selector), filters_path); } AXTreeServer::AXTreeServer(gfx::AcceleratedWidget widget, - const base::FilePath& filters_path, - bool use_json) { - Run(base::BindOnce(&BuildTreeForWindow, widget), filters_path, use_json); + const base::FilePath& filters_path) { + Run(base::BindOnce(&BuildTreeForWindow, widget), filters_path); } void AXTreeServer::Run(BuildTree build_tree, - const base::FilePath& filters_path, - bool use_json) { + const base::FilePath& filters_path) { std::unique_ptr<AXTreeFormatter> formatter( AccessibilityTreeFormatter::Create()); @@ -73,8 +69,8 @@ return; } - // Format the tree. - Format(*formatter, dict, use_json); + // Write to console. + printf("%s", formatter->FormatTree(dict).c_str()); } std::vector<ui::AXPropertyFilter> AXTreeServer::GetPropertyFilters( @@ -118,23 +114,4 @@ return filters; } -void AXTreeServer::Format(const AXTreeFormatter& formatter, - const base::Value& dict, - bool use_json) { - std::string accessibility_contents; - - // Format accessibility tree as JSON or text. - if (use_json) { - const base::Value filtered_dict = formatter.FilterTree(dict); - base::JSONWriter::WriteWithOptions(filtered_dict, - base::JSONWriter::OPTIONS_PRETTY_PRINT, - &accessibility_contents); - } else { - accessibility_contents = formatter.FormatTree(dict); - } - - // Write to console. - printf("%s", accessibility_contents.c_str()); -} - } // namespace content
diff --git a/tools/accessibility/inspect/ax_tree_server.h b/tools/accessibility/inspect/ax_tree_server.h index dac139b..fa5906c 100644 --- a/tools/accessibility/inspect/ax_tree_server.h +++ b/tools/accessibility/inspect/ax_tree_server.h
@@ -20,29 +20,20 @@ class AXTreeServer final { public: AXTreeServer(gfx::AcceleratedWidget widget, - const base::FilePath& filters_path, - bool use_json); + const base::FilePath& filters_path); AXTreeServer(const ui::AXTreeSelector& selector, - const base::FilePath& filters_path, - bool use_json); + const base::FilePath& filters_path); private: using BuildTree = base::OnceCallback<base::Value(const ui::AXTreeFormatter*)>; // Builds and formats the accessible tree. - void Run(BuildTree build_tree, - const base::FilePath& filters_path, - bool use_json); + void Run(BuildTree build_tree, const base::FilePath& filters_path); // Generates property filters. std::vector<ui::AXPropertyFilter> GetPropertyFilters( const base::FilePath& filters_path); - // Formats and dumps into console the tree. - void Format(const ui::AXTreeFormatter& formatter, - const base::Value& dict, - bool use_json); - #if defined(OS_WIN) // Only one COM initializer per thread is permitted. base::win::ScopedCOMInitializer com_initializer_;
diff --git a/tools/binary_size/libsupersize/archive.py b/tools/binary_size/libsupersize/archive.py index 0597ba9..059af17 100644 --- a/tools/binary_size/libsupersize/archive.py +++ b/tools/binary_size/libsupersize/archive.py
@@ -1387,16 +1387,14 @@ def _OverwriteSymbolSizesWithRelocationCount(raw_symbols, tool_prefix, elf_path): + logging.info('Removing non-native symbols') + raw_symbols = [sym for sym in raw_symbols if sym.IsNative()] + logging.info('Overwriting symbol sizes with relocation count') - native_symbols = [sym for sym in raw_symbols if sym.IsNative()] - symbol_addresses = [0] * (1 + len(native_symbols)) - - for i, symbol in enumerate(native_symbols): - symbol_addresses[i] = symbol.address - # Last symbol address is the end of the last symbol, so we don't misattribute # all relros after the last symbol to that symbol. - symbol_addresses[-1] = native_symbols[-1].address + native_symbols[-1].size + symbol_addresses = [s.address for s in raw_symbols] + symbol_addresses.append(raw_symbols[-1].end_address) for symbol in raw_symbols: symbol.address = 0 @@ -1418,13 +1416,13 @@ for addr in relro_addresses: # Attribute relros to largest symbol start address that precede them. idx = bisect.bisect_right(symbol_addresses, addr) - 1 - if 0 <= idx < len(native_symbols): - symbol = native_symbols[idx] + if 0 <= idx < len(raw_symbols): + symbol = raw_symbols[idx] for alias in symbol.aliases or [symbol]: alias.size += 1 - logging.info('Removing non-native symbols...') - raw_symbols[:] = [sym for sym in raw_symbols if sym.size or sym.IsNative()] + raw_symbols = [sym for sym in raw_symbols if sym.size] + return raw_symbols def _AddUnattributedSectionSymbols(raw_symbols, section_ranges): @@ -1528,6 +1526,9 @@ (section_sizes maps section names to respective sizes). raw_symbols is a list of Symbol objects. """ + assert elf_path or not opts.relocations_mode, ( + '--relocations-mode requires a ELF file') + knobs = knobs or SectionSizeKnobs() if apk_path and apk_so_path: # Extraction takes around 1 second, so do it in parallel. @@ -1613,7 +1614,7 @@ pak_symbols_by_id = None other_symbols = [] - if apk_path and size_info_prefix: + if apk_path and size_info_prefix and not opts.relocations_mode: # Can modify |section_ranges|. pak_symbols_by_id = _FindPakSymbolsFromApk(opts, section_ranges, apk_path, size_info_prefix) @@ -1688,8 +1689,9 @@ logging.debug('Connecting nm aliases') _ConnectNmAliases(raw_symbols) - if elf_path and opts.relocations_mode: - _OverwriteSymbolSizesWithRelocationCount(raw_symbols, tool_prefix, elf_path) + if opts.relocations_mode: + raw_symbols = _OverwriteSymbolSizesWithRelocationCount( + raw_symbols, tool_prefix, elf_path) section_sizes = {k: size for k, (address, size) in section_ranges.items()} container = models.Container(name=container_name, @@ -1698,7 +1700,10 @@ for symbol in raw_symbols: symbol.container = container - file_format.SortSymbols(raw_symbols, check_already_mostly_sorted=True) + # Sorting for relocations mode causes .data and .data.rel.ro to be interleaved + # due to setting all addresses to 0. + if not opts.relocations_mode: + file_format.SortSymbols(raw_symbols, check_already_mostly_sorted=True) return container, raw_symbols
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index 9c38f79..5fc617f8 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -42273,6 +42273,7 @@ <int value="-1553477903" label="ash-disable-text-filtering-in-overview-mode"/> <int value="-1553280810" label="PromoBrowserCommands:enabled"/> <int value="-1552898031" label="SingleTabMode:enabled"/> + <int value="-1551197844" label="AssistMultiWord:enabled"/> <int value="-1550760918" label="PipRoundedCorners:disabled"/> <int value="-1550675387" label="CriticalPersistedTabData:enabled"/> <int value="-1550541457" label="DisplayIdentification:disabled"/> @@ -42465,6 +42466,7 @@ <int value="-1399753480" label="disable-harfbuzz-rendertext"/> <int value="-1399419572" label="enable-app-list"/> <int value="-1396974542" label="UserMediaScreenCapturing:enabled"/> + <int value="-1396434715" label="AssistMultiWord:disabled"/> <int value="-1392689905" label="ServiceWorkerLongRunningMessage:enabled"/> <int value="-1392562498" label="disable-origin-chip"/> <int value="-1391728260" label="ContextualSearchDefinitions:enabled"/> @@ -57929,6 +57931,13 @@ <int value="3" label="REPEATED_IGNORES"/> </enum> +<enum name="PermissionPromptDispositionReason"> + <int value="0" label="User preference in settings"/> + <int value="1" label="Safe Browsing verdict"/> + <int value="2" label="Prediction service"/> + <int value="3" label="Default fallback"/> +</enum> + <enum name="PermissionRequestType"> <int value="0" label="PERMISSION_BUBBLE_UNKNOWN"/> <int value="1" label="PERMISSION_BUBBLE_MULTIPLE"/> @@ -59030,6 +59039,15 @@ <int value="1" label="The pre-connect triggered host was accessed"/> </enum> +<enum name="PredictionGrantLikelihood"> + <int value="0" label="Unknown"/> + <int value="1" label="Very unlikely"/> + <int value="2" label="Unlikely"/> + <int value="3" label="Neutral"/> + <int value="4" label="Likely"/> + <int value="5" label="Very likely"/> +</enum> + <enum name="PredictionStatus"> <int value="0" label="No prediction"/> <int value="1" label="Successful prediction"/> @@ -60830,8 +60848,8 @@ <int value="2" label="Signed in to sync from secondary profile"/> <int value="3" label="Customized sync options"/> <int value="4" label="Chose what to sync"/> - <int value="5" label="Encrypted all data"/> - <int value="6" label="Selected a passphrase"/> + <int value="5" label="Encrypted data with new passphrase"/> + <int value="6" label="Entered existing passphrase"/> </enum> <enum name="ProfileSyncCustomize">
diff --git a/tools/metrics/ukm/ukm.xml b/tools/metrics/ukm/ukm.xml index e283410..bcbea7b 100644 --- a/tools/metrics/ukm/ukm.xml +++ b/tools/metrics/ukm/ukm.xml
@@ -10708,6 +10708,14 @@ An enum of type ContentSettingsType. </summary> </metric> + <metric name="PredictionsApiResponse.GrantLikelihood" + enum="PredictionGrantLikelihood"> + <summary> + An enum of type PermissionUmaUtil::PredictionGrantLikelihood describing + the likelihood returned by the Web Permission Predictions Service, if the + service was successfully queried. + </summary> + </metric> <metric name="PriorDismissals"> <summary> The number of dismissed prompts for the given (origin, permission) pair, @@ -10726,6 +10734,13 @@ permission prompt, if any. </summary> </metric> + <metric name="PromptDispositionReason" + enum="PermissionPromptDispositionReason"> + <summary> + An enum of type PermissionPromptDispositionReason. The reason why the + particular prompt disposition was used, if any. + </summary> + </metric> <metric name="SatisfiedAdaptiveTriggers"> <summary> A bitmask consisting of flags defined in enum type AdaptiveTriggers. A bit
diff --git a/tools/origin_trials/check_token.py b/tools/origin_trials/check_token.py index 9fdbef28..a18a4ba8 100755 --- a/tools/origin_trials/check_token.py +++ b/tools/origin_trials/check_token.py
@@ -222,9 +222,6 @@ if (usage_restriction is not None and version != VERSION3): print("The usage field can only be be set in Version 3 token.") sys.exit(1) - if (usage_restriction is not None and not is_third_party): - print("Only third party token supports alternative usage restriction.") - sys.exit(1) if (usage_restriction not in USAGE_RESTRICTION): print("Only empty string and \"subset\" are supported in the usage field.") sys.exit(1)
diff --git a/tools/origin_trials/generate_token.py b/tools/origin_trials/generate_token.py index 4cf740e..6e49fbf 100755 --- a/tools/origin_trials/generate_token.py +++ b/tools/origin_trials/generate_token.py
@@ -226,9 +226,6 @@ if (args.version[0] != 3): print("Only version 3 token supports alternative usage restriction.") sys.exit(1) - if (not args.is_third_party): - print("Only third party token supports alternative usage restriction.") - sys.exit(1) if (args.usage_restriction not in USAGE_RESTRICTION): print( "Only empty string and \"subset\" are supported in alternative usage "
diff --git a/tools/perf/benchmarks/blink_perf.py b/tools/perf/benchmarks/blink_perf.py index 2b6ba32..5119503 100644 --- a/tools/perf/benchmarks/blink_perf.py +++ b/tools/perf/benchmarks/blink_perf.py
@@ -13,6 +13,7 @@ from telemetry import benchmark from telemetry import page as page_module +from telemetry.core import exceptions from telemetry.core import memory_cache_http_server from telemetry.page import legacy_page_test from telemetry.page import shared_page_state @@ -46,11 +47,14 @@ baseName += "_" + query # So that queried page-names don't collide return "{b}.{e}".format(b=baseName, e=extension) -def CreateStorySetFromPath(path, skipped_file, - shared_page_state_class=( - shared_page_state.SharedPageState), - append_query=None, - extra_tags=None): + +def CreateStorySetFromPath( + path, + skipped_file, + shared_page_state_class=(shared_page_state.SharedPageState), + append_query=None, + extra_tags=None, + page_class=_BlinkPerfPage): assert os.path.exists(path) page_urls = [] @@ -98,13 +102,24 @@ common_prefix = os.path.dirname(os.path.commonprefix(all_urls)) for url in sorted(page_urls): name = StoryNameFromUrl(url, common_prefix) - ps.AddStory(_BlinkPerfPage( - url, ps, ps.base_dir, - shared_page_state_class=shared_page_state_class, - name=name, - tags=extra_tags)) + ps.AddStory( + page_class( + url, + ps, + ps.base_dir, + shared_page_state_class=shared_page_state_class, + name=name, + tags=extra_tags)) return ps + +def AddScriptToPage(page, script): + if page.script_to_evaluate_on_commit is None: + page.script_to_evaluate_on_commit = script + else: + page.script_to_evaluate_on_commit += script + + def _CreateMergedEventsBoundaries(events, max_start_time): """ Merge events with the given |event_name| and return a list of MergedEvent objects. All events that are overlapping are megred together. Same as a union @@ -255,7 +270,7 @@ def WillNavigateToPage(self, page, tab): del tab # unused - page.script_to_evaluate_on_commit = self._blink_perf_js + AddScriptToPage(page, self._blink_perf_js) def DidNavigateToPage(self, page, tab): tab.WaitForJavaScriptCondition('testRunner.isWaitingForTelemetry') @@ -396,17 +411,59 @@ return 'blink_perf.bindings' +class _ServiceWorkerPerfPage(page_module.Page): + def RunPageInteractions(self, action_runner): + action_runner.ExecuteJavaScript('testRunner.scheduleTestRun()') + + # If |serviceWorkerPerfTools| is enabled in the test, some actions are + # performed for each iteration. + perf_tools_enabled = False + try: + perf_tools_enabled = action_runner.EvaluateJavaScript( + 'serviceWorkerPerfTools.enabled') + except exceptions.EvaluateException: + pass + + if perf_tools_enabled: + done = False + while not done: + action_runner.WaitForJavaScriptCondition( + 'serviceWorkerPerfTools.actionRequired') + action = action_runner.EvaluateJavaScript( + 'serviceWorkerPerfTools.action') + if action == 'stop-workers': + action_runner.tab.StopAllServiceWorkers() + elif action == 'quit': + done = True + else: + raise Exception( + 'Not supported ServiceWorkerPerfTools action: {}'.format(action)) + action_runner.EvaluateJavaScript( + 'serviceWorkerPerfTools.notifyActionDone()') + action_runner.WaitForJavaScriptCondition('testRunner.isDone', timeout=600) + + class ServiceWorkerRequestHandler( memory_cache_http_server.MemoryCacheDynamicHTTPRequestHandler): """This handler returns dynamic responses for service worker perf tests. """ + _request_count = 0 _SIZE_1K = 1024 _SIZE_10K = 10240 _SIZE_1M = 1048576 _FILE_NAME_PATTERN_1K =\ re.compile('.*/service_worker/resources/data/1K_[0-9]+\\.txt') + _WORKER_NAME_PATTERN = re.compile(\ + '.*/service_worker/resources/service-worker-[0-9]+\\.generated\\.js') + _CHANGING_WORKER_NAME_PATTERN = re.compile(\ + '.*/service_worker/resources/changing-service-worker\\.generated\\.js') + _WORKER_BODY = ''' + self.addEventListener('fetch', (event) => { + event.respondWith(new Response('hello')); + });''' def ResponseFromHandler(self, path): + self._request_count += 1 # normalize the path by replacing backslashes with slashes. normpath = path.replace('\\', '/') if normpath.endswith('/service_worker/resources/data/10K.txt'): @@ -415,6 +472,12 @@ return self.MakeResponse('c' * self._SIZE_1M, 'text/plain', False) elif self._FILE_NAME_PATTERN_1K.match(normpath): return self.MakeResponse('c' * self._SIZE_1K, 'text/plain', False) + elif self._WORKER_NAME_PATTERN.match(normpath): + return self.MakeResponse(self._WORKER_BODY, 'text/javascript', False) + elif self._CHANGING_WORKER_NAME_PATTERN.match(normpath): + # Return different script content for each request. + new_body = self._WORKER_BODY + '//' + str(self._request_count) + return self.MakeResponse(new_body, 'text/javascript', False) return None @@ -432,8 +495,19 @@ return 'UNSCHEDULED_blink_perf.service_worker' def CreateStorySet(self, options): - story_set = super(BlinkPerfServiceWorker, self).CreateStorySet(options) + path = os.path.join(BLINK_PERF_BASE_DIR, self.SUBDIR) + story_set = CreateStorySetFromPath( + path, + SKIPPED_FILE, + extra_tags=self.TAGS, + page_class=_ServiceWorkerPerfPage) story_set.SetRequestHandlerClass(ServiceWorkerRequestHandler) + with open( + os.path.join(os.path.dirname(__file__), 'service_worker_perf.js'), + 'r') as f: + service_worker_perf_js = f.read() + for page in story_set.stories: + AddScriptToPage(page, service_worker_perf_js) return story_set
diff --git a/tools/perf/benchmarks/service_worker_perf.js b/tools/perf/benchmarks/service_worker_perf.js new file mode 100644 index 0000000..cc057b75 --- /dev/null +++ b/tools/perf/benchmarks/service_worker_perf.js
@@ -0,0 +1,59 @@ +// 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 class cooperates with blink_perf.py to perform actions. Currently only +// stopping service workers is supported. +class ServiceWorkerPerfTools { + constructor() { + this.actionDoneCallback = null; + this.actionRequired = false; + this.action = null; + this.enabled = false; + } + + // This should be called before other methods. + enable() { + this.enabled = true; + } + + // Call this to stop all service workers. When the returned promise is + // resolved, all service workers are stopped. + stopWorkers() { + return this.performAction('stop-workers'); + } + + // Call this to notify blink_perf.py to stop waiting for more actions. When + // the returned promise is resolved, blink_perf.py has stopped waiting. + quit() { + return this.performAction('quit'); + } + + // Called by blink_perf.py after an action has been performed. + notifyActionDone() { + if (!this.actionDoneCallback) + throw new Error('There is no pending action!'); + + this.actionDoneCallback(); + this.actionDoneCallback = null; + this.action = null; + this.actionRequired = false; + } + + performAction(action) { + if (!this.enabled) { + throw new TypeError('ServiceWorkerPerfTools is not enabled,' + + ' call enable() first!'); + } + if (this.actionRequired) { + throw new Error('There is already a pending action:', this.action); + } + const promise = new Promise(resolve => { + this.actionDoneCallback = resolve; + }); + this.action = action; + this.actionRequired = true; + return promise; + } +} +window.serviceWorkerPerfTools = new ServiceWorkerPerfTools; \ No newline at end of file
diff --git a/ui/accessibility/platform/inspect/tree_formatter.h b/ui/accessibility/platform/inspect/tree_formatter.h index 6468c90..41c7b9f 100644 --- a/ui/accessibility/platform/inspect/tree_formatter.h +++ b/ui/accessibility/platform/inspect/tree_formatter.h
@@ -57,10 +57,6 @@ // given pattern. virtual base::Value BuildTreeForSelector(const AXTreeSelector&) const = 0; - // Returns a filtered accessibility tree using the current property and node - // filters. - virtual base::Value FilterTree(const base::Value& dict) const = 0; - // Dumps accessibility tree. virtual std::string FormatTree(const base::Value& tree_node) const = 0;
diff --git a/ui/gl/direct_composition_surface_win_unittest.cc b/ui/gl/direct_composition_surface_win_unittest.cc index df97d0b..fc0b280 100644 --- a/ui/gl/direct_composition_surface_win_unittest.cc +++ b/ui/gl/direct_composition_surface_win_unittest.cc
@@ -1163,6 +1163,10 @@ TEST_F(DirectCompositionPixelTest, SwapChainImage) { if (!surface_) return; + // Fails on AMD RX 5500 XT. https://crbug.com/1152565. + if (context_ && context_->GetVersionInfo() && + context_->GetVersionInfo()->driver_vendor == "ANGLE (AMD)") + return; Microsoft::WRL::ComPtr<ID3D11Device> d3d11_device = QueryD3D11DeviceObjectFromANGLE();
diff --git a/ui/login/display_manager.js b/ui/login/display_manager.js index 547eee52..553c9d5 100644 --- a/ui/login/display_manager.js +++ b/ui/login/display_manager.js
@@ -19,7 +19,6 @@ /** @const */ var SCREEN_OOBE_DEMO_SETUP = 'demo-setup'; /** @const */ var SCREEN_OOBE_DEMO_PREFERENCES = 'demo-preferences'; /** @const */ var SCREEN_OOBE_KIOSK_ENABLE = 'kiosk-enable'; -/** @const */ var SCREEN_OOBE_AUTO_ENROLLMENT_CHECK = 'auto-enrollment-check'; /** @const */ var SCREEN_PACKAGED_LICENSE = 'packaged-license'; /** @const */ var SCREEN_GAIA_SIGNIN = 'gaia-signin'; /** @const */ var SCREEN_ACCOUNT_PICKER = 'account-picker'; @@ -90,7 +89,6 @@ */ var RESET_AVAILABLE_SCREEN_GROUP = [ SCREEN_OOBE_NETWORK, - SCREEN_OOBE_AUTO_ENROLLMENT_CHECK, SCREEN_GAIA_SIGNIN, SCREEN_ACCOUNT_PICKER, SCREEN_KIOSK_ENABLE,
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/ExternalNavigationDelegateImpl.java b/weblayer/browser/java/org/chromium/weblayer_private/ExternalNavigationDelegateImpl.java index 5119c15..39afc1b 100644 --- a/weblayer/browser/java/org/chromium/weblayer_private/ExternalNavigationDelegateImpl.java +++ b/weblayer/browser/java/org/chromium/weblayer_private/ExternalNavigationDelegateImpl.java
@@ -14,7 +14,7 @@ import org.chromium.components.embedder_support.util.UrlUtilities; import org.chromium.components.external_intents.ExternalNavigationDelegate; import org.chromium.components.external_intents.ExternalNavigationDelegate.StartActivityIfNeededResult; -import org.chromium.components.external_intents.ExternalNavigationHandler.OverrideUrlLoadingResultType; +import org.chromium.components.external_intents.ExternalNavigationHandler.OverrideUrlLoadingResult; import org.chromium.components.external_intents.ExternalNavigationParams; import org.chromium.content_public.browser.LoadUrlParams; import org.chromium.content_public.browser.WebContents; @@ -89,10 +89,10 @@ // This method should never be invoked as WebLayer does not handle incoming intents. @Override - public @OverrideUrlLoadingResultType int handleIncognitoIntentTargetingSelf( + public OverrideUrlLoadingResult handleIncognitoIntentTargetingSelf( final Intent intent, final String referrerUrl, final String fallbackUrl) { assert false; - return OverrideUrlLoadingResultType.NO_OVERRIDE; + return OverrideUrlLoadingResult.forNoOverride(); } @Override