diff --git a/DEPS b/DEPS index 580fa9f..3efd16dc 100644 --- a/DEPS +++ b/DEPS
@@ -190,7 +190,7 @@ # luci-go CIPD package version. # Make sure the revision is uploaded by infra-packagers builder. # https://ci.chromium.org/p/infra-internal/g/infra-packagers/console - 'luci_go': 'git_revision:2ac8bd9cbc20824bb04a39b0f1b77178ace930b3', + 'luci_go': 'git_revision:8b8a9a6040ca6debd30694a71a99a1eac97d72fd', # This can be overridden, e.g. with custom_vars, to build clang from HEAD # instead of downloading the prebuilt pinned revision. @@ -207,7 +207,7 @@ 'dawn_standalone': False, # reclient CIPD package version - 'reclient_version': 're_client_version:0.33.0.3e223d5', + 'reclient_version': 're_client_version:0.35.0.b65ab61', 'android_git': 'https://android.googlesource.com', 'aomedia_git': 'https://aomedia.googlesource.com', @@ -222,11 +222,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': '7729e0a97ec36a34207ca74c1dde8136c6b89724', + 'skia_revision': '3cf050bba6b61acdc0b134fdf495b6c004989520', # 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': '2517643909a0743cdc0e6a487f1ca4e4f41e8bd6', + 'v8_revision': '7ab0e18a9dbcd58af69ccc0b9cd09cf2befcfd0c', # 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. @@ -238,11 +238,11 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling SwiftShader # and whatever else without interference from each other. - 'swiftshader_revision': '4716eec90fcbb105b4694807121c7a57d7cf8fd9', + 'swiftshader_revision': 'ba18c78e46968726769813b68adb19466e092812', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling PDFium # and whatever else without interference from each other. - 'pdfium_revision': 'ee64a8518eaebbcdee771f08eeacbb1ad1198223', + 'pdfium_revision': '9e7388e8e7ebbf5be6964f61b040297a17a16652', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling BoringSSL # and whatever else without interference from each other. @@ -273,7 +273,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling freetype # and whatever else without interference from each other. - 'freetype_revision': 'd3dc2da9b27af5b90575d62989389cc65fe7977c', + 'freetype_revision': '59e95b014aa162393d6d569225cf713d71ffdc33', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling freetype # and whatever else without interference from each other. @@ -293,7 +293,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling catapult # and whatever else without interference from each other. - 'catapult_revision': '25ef034fbef738c4ff017d1ab1c42d7a6fad6a7f', + 'catapult_revision': '3c6345a736f4a79e85dc46dcecc71caeebcb4499', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # and whatever else without interference from each other. @@ -341,7 +341,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': 'f1c76f5dfe0669c2fb00a3a9b0a78f4b0788c465', + 'dawn_revision': 'f818d3354ceda3401abca5967aefabe74c630eb1', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. @@ -1360,7 +1360,7 @@ }, 'src/third_party/perfetto': - Var('android_git') + '/platform/external/perfetto.git' + '@' + '51a1443c7cb98f1fd50e1bb87c183704b4f5c81b', + Var('android_git') + '/platform/external/perfetto.git' + '@' + 'c70ad6b2a04526e0e0a98a93a56bbb0cefdc0aef', 'src/third_party/perl': { 'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3', @@ -1449,7 +1449,7 @@ 'packages': [ { 'package': 'fuchsia/third_party/aemu/linux-amd64', - 'version': 'qX01xcawvl_sWzKM7dt-kmo0g3eQKDU33EjLMClSPwIC' + 'version': 'ECOpPRNcAsJiX3ZM-O_BYSAL9U9eWoy69ZnKycGcFWEC' }, ], 'condition': 'host_os == "linux" and checkout_fuchsia', @@ -1553,7 +1553,7 @@ 'src/third_party/usrsctp/usrsctplib': Var('chromium_git') + '/external/github.com/sctplab/usrsctp' + '@' + '1ade45cbadfd19298d2c47dc538962d4425ad2dd', - 'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@bbd1a7b068ea2dfdda9910f1447147ff69e800cb', + 'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@36456846a4affb738fc3f012cc8f1c8c86ef0595', 'src/third_party/vulkan_memory_allocator': Var('chromium_git') + '/external/github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator.git' + '@' + 'f67d7fa397e83060b76a1ec53579116a0bbdff7a', @@ -1619,7 +1619,7 @@ 'packages': [ { 'package': 'skia/tools/goldctl/linux-amd64', - 'version': 'R0Jd4IlcndZlI5C9Pejy7DqtmVEQT8Sc6Ye09MGyFxYC', + 'version': 'McKpb1_oys52qBLvSwGec9-adPkk72RTCSdOBnzZiakC', }, ], 'dep_type': 'cipd', @@ -1629,7 +1629,7 @@ 'packages': [ { 'package': 'skia/tools/goldctl/windows-amd64', - 'version': 'M2_R9AXWaN0xmm6nz_nRzKlhpzzOp3P9EUxNaLZ5owMC', + 'version': 'hrfC-m0pHo7gMu28Bdo4wR8Fnxk_GQkMcO9LyPNPThoC', }, ], 'dep_type': 'cipd', @@ -1639,7 +1639,7 @@ 'packages': [ { 'package': 'skia/tools/goldctl/mac-amd64', - 'version': '5NoUEq08DuYUlQWnf2yj6rQvBtlMvWiDqfuUuE5nJFIC', + 'version': 'Ea5khSEBtnBiIUjc8YOW1PTAiFTBzcSCJcQXyS_RcV8C', }, ], 'dep_type': 'cipd', @@ -1653,7 +1653,7 @@ Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'), 'src-internal': { - 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@dd7a87d4d93c94c8797dedbfa497c68ddbc1873a', + 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@93d0140b3861285eecf7fa849d72c8135b1fbe33', 'condition': 'checkout_src_internal', }, @@ -1672,7 +1672,7 @@ 'packages': [ { 'package': 'chromeos_internal/apps/help_app/app', - 'version': 'N-71TcWQy-V0Y3W_Ha8EH-EdWTHJE7kOos2Hlq0z8C8C', + 'version': 'X4D56rlbi2FQDHCzzxKgtUa7i2PpYfk8RGJjwUUmrEsC', }, ], 'condition': 'checkout_chromeos and checkout_src_internal',
diff --git a/android_webview/browser/gfx/overlay_processor_webview.cc b/android_webview/browser/gfx/overlay_processor_webview.cc index cddcea0..80def3e 100644 --- a/android_webview/browser/gfx/overlay_processor_webview.cc +++ b/android_webview/browser/gfx/overlay_processor_webview.cc
@@ -127,13 +127,10 @@ }; public: - Manager(gpu::MemoryTracker* memory_tracker, - gpu::CommandBufferId command_buffer_id, - gpu::SequenceId sequence_id) + Manager(gpu::CommandBufferId command_buffer_id, gpu::SequenceId sequence_id) : shared_image_manager_( GpuServiceWebView::GetInstance()->shared_image_manager()), - memory_tracker_( - std::make_unique<gpu::MemoryTypeTracker>(memory_tracker)), + memory_tracker_(std::make_unique<gpu::MemoryTypeTracker>(nullptr)), sync_point_client_state_( CreateSyncPointClientState(command_buffer_id, sequence_id)) { DETACH_FROM_THREAD(gpu_thread_checker_); @@ -616,10 +613,9 @@ frame_sink_manager_(frame_sink_manager) { base::WaitableEvent event; render_thread_sequence_->ScheduleGpuTask( - base::BindOnce( - &OverlayProcessorWebView::CreateManagerOnRT, base::Unretained(this), - display_controller->controller_on_gpu(), command_buffer_id_, - render_thread_sequence_->GetSequenceId(), &event), + base::BindOnce(&OverlayProcessorWebView::CreateManagerOnRT, + base::Unretained(this), command_buffer_id_, + render_thread_sequence_->GetSequenceId(), &event), std::vector<gpu::SyncToken>()); event.Wait(); } @@ -635,12 +631,10 @@ } void OverlayProcessorWebView::CreateManagerOnRT( - gpu::DisplayCompositorMemoryAndTaskControllerOnGpu* controller_on_gpu, gpu::CommandBufferId command_buffer_id, gpu::SequenceId sequence_id, base::WaitableEvent* event) { - manager_ = base::MakeRefCounted<Manager>(controller_on_gpu->memory_tracker(), - command_buffer_id, sequence_id); + manager_ = base::MakeRefCounted<Manager>(command_buffer_id, sequence_id); event->Signal(); }
diff --git a/android_webview/browser/gfx/overlay_processor_webview.h b/android_webview/browser/gfx/overlay_processor_webview.h index e244fe96..3f26d2c 100644 --- a/android_webview/browser/gfx/overlay_processor_webview.h +++ b/android_webview/browser/gfx/overlay_processor_webview.h
@@ -19,10 +19,6 @@ #include "gpu/command_buffer/common/sync_token.h" #include "ui/gfx/android/android_surface_control_compat.h" -namespace gpu { -class DisplayCompositorMemoryAndTaskControllerOnGpu; -} - namespace viz { class FrameSinkManagerImpl; class ResolvedFrameData; @@ -95,7 +91,6 @@ void ReturnResource(viz::ResourceId resource_id, viz::SurfaceId surface_id); void CreateManagerOnRT( - gpu::DisplayCompositorMemoryAndTaskControllerOnGpu* controller_on_gpu, gpu::CommandBufferId command_buffer_id, gpu::SequenceId sequence_id, base::WaitableEvent* event);
diff --git a/android_webview/browser/metrics/aw_metrics_service_client.cc b/android_webview/browser/metrics/aw_metrics_service_client.cc index 58e89aa..7dfdd401 100644 --- a/android_webview/browser/metrics/aw_metrics_service_client.cc +++ b/android_webview/browser/metrics/aw_metrics_service_client.cc
@@ -77,7 +77,7 @@ AwMetricsServiceClient::AwMetricsServiceClient( std::unique_ptr<Delegate> delegate) - : delegate_(std::move(delegate)) {} + : time_created_(base::Time::Now()), delegate_(std::move(delegate)) {} AwMetricsServiceClient::~AwMetricsServiceClient() = default; @@ -126,6 +126,10 @@ local_state->Set(prefs::kMetricsAppPackageNameLoggingRule, record.value().ToDictionary()); cached_package_name_record_ = record; + + UmaHistogramTimes( + "Android.WebView.Metrics.PackagesAllowList.ResultReceivingDelay", + base::Time::Now() - time_created_); } absl::optional<AppPackageNameLoggingRule>
diff --git a/android_webview/browser/metrics/aw_metrics_service_client.h b/android_webview/browser/metrics/aw_metrics_service_client.h index fab94f7..9563708 100644 --- a/android_webview/browser/metrics/aw_metrics_service_client.h +++ b/android_webview/browser/metrics/aw_metrics_service_client.h
@@ -183,6 +183,7 @@ private: bool app_in_foreground_ = false; + base::Time time_created_; std::unique_ptr<Delegate> delegate_; absl::optional<AppPackageNameLoggingRule> cached_package_name_record_;
diff --git a/android_webview/browser/metrics/aw_metrics_service_client_unittest.cc b/android_webview/browser/metrics/aw_metrics_service_client_unittest.cc index af85617..b835e1a 100644 --- a/android_webview/browser/metrics/aw_metrics_service_client_unittest.cc +++ b/android_webview/browser/metrics/aw_metrics_service_client_unittest.cc
@@ -9,6 +9,7 @@ #include "android_webview/common/aw_features.h" #include "android_webview/common/metrics/app_package_name_logging_rule.h" #include "base/metrics/user_metrics.h" +#include "base/test/metrics/histogram_tester.h" #include "base/test/scoped_feature_list.h" #include "base/test/test_simple_task_runner.h" #include "base/time/time.h" @@ -60,6 +61,7 @@ } // namespace TEST_F(AwMetricsServiceClientTest, TestShouldRecordPackageName_CacheNotSet) { + base::HistogramTester histogram_tester; base::test::ScopedFeatureList scoped_list; scoped_list.InitAndEnableFeature( android_webview::features::kWebViewAppsPackageNamesAllowlist); @@ -67,9 +69,13 @@ AwMetricsServiceClient* client = GetClient(); EXPECT_FALSE(client->ShouldRecordPackageName()); EXPECT_FALSE(client->GetCachedAppPackageNameLoggingRule().has_value()); + + histogram_tester.ExpectTotalCount( + "Android.WebView.Metrics.PackagesAllowList.ResultReceivingDelay", 0); } TEST_F(AwMetricsServiceClientTest, TestShouldRecordPackageName_WithCache) { + base::HistogramTester histogram_tester; base::test::ScopedFeatureList scoped_list; scoped_list.InitAndEnableFeature( android_webview::features::kWebViewAppsPackageNamesAllowlist); @@ -88,10 +94,14 @@ EXPECT_TRUE(client->ShouldRecordPackageName()); ASSERT_TRUE(cached_record.has_value()); EXPECT_TRUE(expected_record.IsSameAs(cached_record.value())); + + histogram_tester.ExpectTotalCount( + "Android.WebView.Metrics.PackagesAllowList.ResultReceivingDelay", 0); } TEST_F(AwMetricsServiceClientTest, TestShouldRecordPackageName_TestShouldNotRecordPackageName) { + base::HistogramTester histogram_tester; base::test::ScopedFeatureList scoped_list; scoped_list.InitAndEnableFeature( android_webview::features::kWebViewAppsPackageNamesAllowlist); @@ -106,10 +116,14 @@ EXPECT_FALSE(client->ShouldRecordPackageName()); ASSERT_TRUE(cached_record.has_value()); EXPECT_TRUE(expected_record.IsSameAs(cached_record.value())); + + histogram_tester.ExpectTotalCount( + "Android.WebView.Metrics.PackagesAllowList.ResultReceivingDelay", 1); } TEST_F(AwMetricsServiceClientTest, TestShouldRecordPackageName_TestShouldRecordPackageName) { + base::HistogramTester histogram_tester; base::test::ScopedFeatureList scoped_list; scoped_list.InitAndEnableFeature( android_webview::features::kWebViewAppsPackageNamesAllowlist); @@ -126,10 +140,14 @@ EXPECT_TRUE(client->ShouldRecordPackageName()); ASSERT_TRUE(cached_record.has_value()); EXPECT_TRUE(expected_record.IsSameAs(cached_record.value())); + + histogram_tester.ExpectTotalCount( + "Android.WebView.Metrics.PackagesAllowList.ResultReceivingDelay", 1); } TEST_F(AwMetricsServiceClientTest, TestShouldRecordPackageName_TestFailureAfterValidResult) { + base::HistogramTester histogram_tester; base::test::ScopedFeatureList scoped_list; scoped_list.InitAndEnableFeature( android_webview::features::kWebViewAppsPackageNamesAllowlist); @@ -148,6 +166,46 @@ EXPECT_TRUE(client->ShouldRecordPackageName()); ASSERT_TRUE(cached_record.has_value()); EXPECT_TRUE(expected_record.IsSameAs(cached_record.value())); + + histogram_tester.ExpectTotalCount( + "Android.WebView.Metrics.PackagesAllowList.ResultReceivingDelay", 1); +} + +TEST_F(AwMetricsServiceClientTest, TestShouldRecordPackageName_FailedResult) { + base::HistogramTester histogram_tester; + base::test::ScopedFeatureList scoped_list; + scoped_list.InitAndEnableFeature( + android_webview::features::kWebViewAppsPackageNamesAllowlist); + + AwMetricsServiceClient* client = GetClient(); + client->SetAppPackageNameLoggingRule( + absl::optional<AppPackageNameLoggingRule>()); + + EXPECT_FALSE(client->ShouldRecordPackageName()); + + histogram_tester.ExpectTotalCount( + "Android.WebView.Metrics.PackagesAllowList.ResultReceivingDelay", 0); +} + +TEST_F(AwMetricsServiceClientTest, TestShouldRecordPackageName_SameAsCache) { + base::HistogramTester histogram_tester; + base::test::ScopedFeatureList scoped_list; + scoped_list.InitAndEnableFeature( + android_webview::features::kWebViewAppsPackageNamesAllowlist); + + AwMetricsServiceClient* client = GetClient(); + TestingPrefServiceSimple* prefs = GetPrefs(); + + AppPackageNameLoggingRule record( + base::Version(kTestAllowlistVersion), + base::Time::Now() + base::TimeDelta::FromDays(1)); + prefs->Set(prefs::kMetricsAppPackageNameLoggingRule, record.ToDictionary()); + client->SetAppPackageNameLoggingRule(record); + + EXPECT_TRUE(client->ShouldRecordPackageName()); + + histogram_tester.ExpectTotalCount( + "Android.WebView.Metrics.PackagesAllowList.ResultReceivingDelay", 0); } } // namespace android_webview
diff --git a/android_webview/nonembedded/BUILD.gn b/android_webview/nonembedded/BUILD.gn index 2b661a8b..133db408 100644 --- a/android_webview/nonembedded/BUILD.gn +++ b/android_webview/nonembedded/BUILD.gn
@@ -51,6 +51,7 @@ android_library("devui_java") { sources = [ + "java/src/org/chromium/android_webview/devui/ComponentsListFragment.java", "java/src/org/chromium/android_webview/devui/CrashesListFragment.java", "java/src/org/chromium/android_webview/devui/DevUiBaseFragment.java", "java/src/org/chromium/android_webview/devui/FlagsFragment.java", @@ -189,10 +190,12 @@ "java/res_devui/drawable/ic_devui_search.xml", "java/res_devui/drawable/ic_flag.xml", "java/res_devui/layout/activity_main.xml", + "java/res_devui/layout/components_list_item.xml", "java/res_devui/layout/crashes_list_item_body.xml", "java/res_devui/layout/crashes_list_item_header.xml", "java/res_devui/layout/flag_states.xml", "java/res_devui/layout/flag_ui_warning.xml", + "java/res_devui/layout/fragment_components_list.xml", "java/res_devui/layout/fragment_crashes_list.xml", "java/res_devui/layout/fragment_flags.xml", "java/res_devui/layout/fragment_home.xml",
diff --git a/android_webview/nonembedded/java/res_devui/layout/components_list_item.xml b/android_webview/nonembedded/java/res_devui/layout/components_list_item.xml new file mode 100644 index 0000000..b1fc72a --- /dev/null +++ b/android_webview/nonembedded/java/res_devui/layout/components_list_item.xml
@@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright 2021 The Chromium Authors. All rights reserved. Use of this + source code is governed by a BSD-style license that can be found in the + LICENSE file. +--> +<TextView xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:textAppearance="?android:attr/textAppearanceLarge"/> \ No newline at end of file
diff --git a/android_webview/nonembedded/java/res_devui/layout/fragment_components_list.xml b/android_webview/nonembedded/java/res_devui/layout/fragment_components_list.xml new file mode 100644 index 0000000..865e6b1f --- /dev/null +++ b/android_webview/nonembedded/java/res_devui/layout/fragment_components_list.xml
@@ -0,0 +1,38 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright 2021 The Chromium Authors. All rights reserved. Use of this + source code is governed by a BSD-style license that can be found in the + LICENSE file. +--> + + <LinearLayout + xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/fragment_components_list" + android:orientation="vertical" + android:layout_width="match_parent" + android:layout_height="match_parent"> + + <TextView + android:id="@+id/components_summary_textview" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:paddingTop="16dp" + android:paddingBottom="16dp" + android:paddingStart="10dp" + android:paddingEnd="10dp" + android:textAppearance="?android:attr/textAppearanceLarge"/> + + <!-- horizontal divider --> + <View + android:layout_width="match_parent" + android:layout_height="1dp" + android:background="?android:attr/listDivider"/> + + <!-- child divider is transparent (hidden) --> + <ListView + android:id="@+id/components_list" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:childDivider="#00000000"/> + + </LinearLayout> \ No newline at end of file
diff --git a/android_webview/nonembedded/java/src/org/chromium/android_webview/devui/ComponentsListFragment.java b/android_webview/nonembedded/java/src/org/chromium/android_webview/devui/ComponentsListFragment.java new file mode 100644 index 0000000..a1acf65 --- /dev/null +++ b/android_webview/nonembedded/java/src/org/chromium/android_webview/devui/ComponentsListFragment.java
@@ -0,0 +1,64 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.android_webview.devui; + +import android.app.Activity; +import android.content.Context; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ArrayAdapter; +import android.widget.ListView; +import android.widget.TextView; + +import java.util.ArrayList; +import java.util.Locale; + +/** + * A fragment to show a list of WebView components. + * <p>This feature is currently under development and therefore not exposed in the UI. + * <p>It can be launched via the adb shell by sending an intent with fragment-id = 3 + */ +public class ComponentsListFragment extends DevUiBaseFragment { + private Context mContext; + + @Override + public void onAttach(Context context) { + super.onAttach(context); + mContext = context; + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setHasOptionsMenu(true); + } + + @Override + public View onCreateView( + LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + return inflater.inflate(R.layout.fragment_components_list, null); + } + + @Override + public void onViewCreated(View view, Bundle savedInstanceState) { + Activity activity = (Activity) mContext; + activity.setTitle("WebView Components"); + + ArrayList<String> componentsInfo = new ArrayList<String>(); + + TextView componentsSummaryView = view.findViewById(R.id.components_summary_textview); + componentsSummaryView.setText( + String.format(Locale.US, "Components (%d)", componentsInfo.size())); + + ListView componentsListView = view.findViewById(R.id.components_list); + + ArrayAdapter<String> componentsInfoAdapter = + new ArrayAdapter<>(mContext, R.layout.components_list_item, componentsInfo); + + componentsListView.setAdapter(componentsInfoAdapter); + } +} \ No newline at end of file
diff --git a/android_webview/nonembedded/java/src/org/chromium/android_webview/devui/DevUiBaseFragment.java b/android_webview/nonembedded/java/src/org/chromium/android_webview/devui/DevUiBaseFragment.java index 7d492ca..01ef14d 100644 --- a/android_webview/nonembedded/java/src/org/chromium/android_webview/devui/DevUiBaseFragment.java +++ b/android_webview/nonembedded/java/src/org/chromium/android_webview/devui/DevUiBaseFragment.java
@@ -40,6 +40,8 @@ suffix = "FlagsFragment"; } else if (this instanceof CrashesListFragment) { suffix = "CrashesListFragment"; + } else if (this instanceof ComponentsListFragment) { + suffix = "ComponentsListFragment"; } // Note: keep this if-else ladder synchronized with the AndroidWebViewFragments // histogram_suffix
diff --git a/android_webview/nonembedded/java/src/org/chromium/android_webview/devui/MainActivity.java b/android_webview/nonembedded/java/src/org/chromium/android_webview/devui/MainActivity.java index d23ce79a..0e9950e 100644 --- a/android_webview/nonembedded/java/src/org/chromium/android_webview/devui/MainActivity.java +++ b/android_webview/nonembedded/java/src/org/chromium/android_webview/devui/MainActivity.java
@@ -45,6 +45,7 @@ public static final int FRAGMENT_ID_HOME = 0; public static final int FRAGMENT_ID_CRASHES = 1; public static final int FRAGMENT_ID_FLAGS = 2; + public static final int FRAGMENT_ID_COMPONENTS = 3; // These values are persisted to logs. Entries should not be renumbered and // numeric values should never be reused. @@ -72,7 +73,8 @@ int HOME_FRAGMENT = 0; int CRASHES_LIST_FRAGMENT = 1; int FLAGS_FRAGMENT = 2; - int COUNT = 3; + int COMPONENTS_LIST_FRAGMENT = 3; + int COUNT = 4; } /** @@ -99,6 +101,9 @@ case FRAGMENT_ID_FLAGS: sample = FragmentNavigation.FLAGS_FRAGMENT; break; + case FRAGMENT_ID_COMPONENTS: + sample = FragmentNavigation.COMPONENTS_LIST_FRAGMENT; + break; } RecordHistogram.recordEnumeratedHistogram( "Android.WebView.DevUi.FragmentNavigation." + histogramSuffix, sample, @@ -167,6 +172,9 @@ case FRAGMENT_ID_FLAGS: fragment = new FlagsFragment(); break; + case FRAGMENT_ID_COMPONENTS: + fragment = new ComponentsListFragment(); + break; } assert fragment != null; logFragmentNavigation("AnyMethod", chosenFragmentId);
diff --git a/ash/fast_ink/fast_ink_pointer_controller.h b/ash/fast_ink/fast_ink_pointer_controller.h index a1cf4ef1..63a0aa4 100644 --- a/ash/fast_ink/fast_ink_pointer_controller.h +++ b/ash/fast_ink/fast_ink_pointer_controller.h
@@ -48,6 +48,10 @@ // Whether the controller is ready to start handling a new gesture. virtual bool CanStartNewGesture(ui::LocatedEvent* event); // Whether the event should be processed and stop propagation. + // Default implementation will catch basic mouse events (e.g. mouse clicking) + // and touch events (e.g. touch pressing) and stop them from being further + // dispatched, so derived class should override it if the default behavior is + // not as expected. See b/191044469 as an example. virtual bool ShouldProcessEvent(ui::LocatedEvent* event); bool IsEnabledForMouseEvent() const;
diff --git a/ash/highlighter/highlighter_controller.cc b/ash/highlighter/highlighter_controller.cc index bffce0b..cffa4bf 100644 --- a/ash/highlighter/highlighter_controller.cc +++ b/ash/highlighter/highlighter_controller.cc
@@ -240,6 +240,16 @@ FastInkPointerController::CanStartNewGesture(event); } +bool HighlighterController::ShouldProcessEvent(ui::LocatedEvent* event) { + // Allow mouse clicking when Assistant tool is enabled. + if (event->type() == ui::ET_MOUSE_PRESSED || + event->type() == ui::ET_MOUSE_RELEASED) { + return false; + } + + return FastInkPointerController::ShouldProcessEvent(event); +} + void HighlighterController::DestroyHighlighterView() { highlighter_view_widget_.reset(); // |interrupted_stroke_timer_| should never be non null when
diff --git a/ash/highlighter/highlighter_controller.h b/ash/highlighter/highlighter_controller.h index 3e3f46c..23bdff7 100644 --- a/ash/highlighter/highlighter_controller.h +++ b/ash/highlighter/highlighter_controller.h
@@ -40,7 +40,8 @@ kDisabledBySessionAbort, }; -// Controller for the highlighter functionality. +// Controller for the highlighter functionality, which can be enabled/disabled +// by switching "Assistant" tool under Stylus panel on/off. // Enables/disables highlighter as well as receives points // and passes them off to be rendered. class ASH_EXPORT HighlighterController @@ -91,6 +92,7 @@ void UpdatePointerView(ui::TouchEvent* event) override; void DestroyPointerView() override; bool CanStartNewGesture(ui::LocatedEvent* event) override; + bool ShouldProcessEvent(ui::LocatedEvent* event) override; // Performs gesture recognition, initiates appropriate visual effects, // notifies the observer if necessary.
diff --git a/ash/system/accessibility/autoclick_scroll_bubble_controller.cc b/ash/system/accessibility/autoclick_scroll_bubble_controller.cc index 072f5b8f5..afdb94d 100644 --- a/ash/system/accessibility/autoclick_scroll_bubble_controller.cc +++ b/ash/system/accessibility/autoclick_scroll_bubble_controller.cc
@@ -50,7 +50,7 @@ views::BubbleBorder::Arrow alignment) { menu_bubble_rect_ = rect; menu_bubble_alignment_ = alignment; - if (set_scroll_rect_) + if (set_scroll_rect_ || !bubble_view_) return; bubble_view_->UpdateAnchorRect(rect, alignment); } @@ -60,6 +60,9 @@ const gfx::Point& scroll_point_in_dips) { // TODO(katie): Support multiple displays. + if (!bubble_view_) + return; + // Adjust the insets to be the same on all sides, so that when the bubble // lays out it isn't too close on the top or bottom. bubble_view_->UpdateInsets( @@ -237,7 +240,7 @@ void AutoclickScrollBubbleController::ClickOnBubble(gfx::Point location_in_dips, int mouse_event_flags) { - if (!bubble_widget_) + if (!bubble_widget_ || !bubble_view_) return; // Change the event location bounds to be relative to the menu bubble.
diff --git a/ash/system/message_center/message_center_scroll_bar.cc b/ash/system/message_center/message_center_scroll_bar.cc index 6e5bbe1..64d9633 100644 --- a/ash/system/message_center/message_center_scroll_bar.cc +++ b/ash/system/message_center/message_center_scroll_bar.cc
@@ -5,11 +5,23 @@ #include "ash/system/message_center/message_center_scroll_bar.h" #include "ash/constants/ash_features.h" +#include "ash/public/cpp/presentation_time_recorder.h" #include "base/metrics/histogram_macros.h" #include "ui/compositor/layer.h" +#include "ui/views/widget/widget.h" namespace { +// The UMA histogram that records presentation time for scrolling through the +// notification list in message center. +constexpr char kMessageCenterScrollHistogram[] = + "Ash.MessageCenter.Scroll.PresentationTime"; + +// The UMA histogram that records max latency of presentation time for scrolling +// through the notification list in message center. +constexpr char kMessageCenterScrollMaxLatencyHistogram[] = + "Ash.MessageCenter.Scroll.PresentationTime.MaxLatency"; + enum class ScrollActionReason { kUnknown, kByMouseWheel, @@ -34,6 +46,8 @@ GetThumb()->layer()->CompleteAllAnimations(); } +MessageCenterScrollBar::~MessageCenterScrollBar() = default; + bool MessageCenterScrollBar::OnKeyPressed(const ui::KeyEvent& event) { if (!stats_recorded_ && (event.key_code() == ui::VKEY_UP || event.key_code() == ui::VKEY_DOWN)) { @@ -62,11 +76,26 @@ } void MessageCenterScrollBar::OnGestureEvent(ui::GestureEvent* event) { - if (!stats_recorded_ && (event->type() == ui::ET_GESTURE_SCROLL_BEGIN)) { - CollectScrollActionReason(ScrollActionReason::kByTouch); - stats_recorded_ = true; + if (event->type() == ui::ET_GESTURE_SCROLL_BEGIN) { + if (!presentation_time_recorder_) { + presentation_time_recorder_ = CreatePresentationTimeHistogramRecorder( + GetWidget()->GetCompositor(), kMessageCenterScrollHistogram, + kMessageCenterScrollMaxLatencyHistogram); + } + if (!stats_recorded_) { + CollectScrollActionReason(ScrollActionReason::kByTouch); + stats_recorded_ = true; + } } + if (event->type() == ui::ET_GESTURE_SCROLL_UPDATE) { + DCHECK(presentation_time_recorder_); + presentation_time_recorder_->RequestNext(); + } + + if (event->type() == ui::ET_GESTURE_END) + presentation_time_recorder_.reset(); + views::OverlayScrollBar::OnGestureEvent(event); if (observer_) @@ -77,6 +106,18 @@ bool result = views::OverlayScrollBar::OnScroll(dx, dy); if (observer_) observer_->OnMessageCenterScrolled(); + + // Widget might be null in tests. + if (GetWidget() && !presentation_time_recorder_) { + // Create a recorder if needed. We stop and record metrics when the + // object goes out of scope (when message center is closed). + presentation_time_recorder_ = CreatePresentationTimeHistogramRecorder( + GetWidget()->GetCompositor(), kMessageCenterScrollHistogram, + kMessageCenterScrollMaxLatencyHistogram); + } + if (presentation_time_recorder_) + presentation_time_recorder_->RequestNext(); + return result; }
diff --git a/ash/system/message_center/message_center_scroll_bar.h b/ash/system/message_center/message_center_scroll_bar.h index 63eb6e9..ca4f49b 100644 --- a/ash/system/message_center/message_center_scroll_bar.h +++ b/ash/system/message_center/message_center_scroll_bar.h
@@ -5,14 +5,17 @@ #ifndef ASH_SYSTEM_MESSAGE_CENTER_MESSAGE_CENTER_SCROLL_BAR_H_ #define ASH_SYSTEM_MESSAGE_CENTER_MESSAGE_CENTER_SCROLL_BAR_H_ +#include "ash/public/cpp/presentation_time_recorder.h" #include "ui/events/event.h" #include "ui/views/controls/scrollbar/overlay_scroll_bar.h" namespace ash { +class PresentationTimeRecorder; + // The scroll bar for message center. This is basically views::OverlayScrollBar -// but also records the metrics for the type of scrolling. Only the first event -// after the message center opens is recorded. +// but also records the metrics for the type of scrolling (only the first event +// after the message center opens is recorded) and scrolling performance. class MessageCenterScrollBar : public views::OverlayScrollBar { public: class Observer { @@ -24,6 +27,7 @@ // |observer| can be null. explicit MessageCenterScrollBar(Observer* observer); + ~MessageCenterScrollBar() override; private: // View overrides: @@ -42,6 +46,9 @@ Observer* const observer_; + // Presentation time recorder for scrolling through notification list. + std::unique_ptr<PresentationTimeRecorder> presentation_time_recorder_; + DISALLOW_COPY_AND_ASSIGN(MessageCenterScrollBar); };
diff --git a/ash/webui/scanning/resources/action_toolbar.html b/ash/webui/scanning/resources/action_toolbar.html index b8d79fb..a08a56b7 100644 --- a/ash/webui/scanning/resources/action_toolbar.html +++ b/ash/webui/scanning/resources/action_toolbar.html
@@ -47,7 +47,7 @@ <div id="pageNumbers">[[pageNumberText_]]</div> <div class="separator"></div> <div> - <cr-icon-button id="removePageIcon"></cr-icon-button> - <cr-icon-button id="rescanPageIcon"></cr-icon-button> + <cr-icon-button id="removePageIcon" title="[[removeButtonTooltip_]]"></cr-icon-button> + <cr-icon-button id="rescanPageIcon" title="[[rescanButtonTooltip_]]"></cr-icon-button> </div> </div>
diff --git a/ash/webui/scanning/resources/action_toolbar.js b/ash/webui/scanning/resources/action_toolbar.js index eb0850d..b2aba8e 100644 --- a/ash/webui/scanning/resources/action_toolbar.js +++ b/ash/webui/scanning/resources/action_toolbar.js
@@ -9,6 +9,8 @@ import {I18nBehavior} from 'chrome://resources/js/i18n_behavior.m.js'; import {html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {ScanningBrowserProxy, ScanningBrowserProxyImpl} from './scanning_browser_proxy.js'; + /** * @fileoverview * 'action-toolbar' is a floating toolbar that contains post-scan page options. @@ -32,6 +34,27 @@ type: String, computed: 'computePageNumberText_(currentPageInView, numTotalPages)', }, + + /** @private {string} */ + removeButtonTooltip_: String, + + /** @private {string} */ + rescanButtonTooltip_: String, + }, + + /** @override */ + ready() { + /** @type {!ScanningBrowserProxy} */ + const browserProxy = ScanningBrowserProxyImpl.getInstance(); + browserProxy.getPluralString('removePageButtonLabel', 0) + .then(/* @type {string} */ (pluralString) => { + this.removeButtonTooltip_ = pluralString; + }); + browserProxy.getPluralString('rescanPageButtonLabel', 0) + .then( + /* @type {string} */ (pluralString) => { + this.rescanButtonTooltip_ = pluralString; + }); }, /**
diff --git a/ash/webui/scanning/scanning_ui.cc b/ash/webui/scanning/scanning_ui.cc index 34935e39..61d39ca 100644 --- a/ash/webui/scanning/scanning_ui.cc +++ b/ash/webui/scanning/scanning_ui.cc
@@ -124,6 +124,8 @@ static constexpr webui::LocalizedString kLocalizedStrings[] = { {"editButtonLabel", IDS_SCANNING_APP_EDIT_BUTTON_LABEL}, {"fileSavedText", IDS_SCANNING_APP_FILE_SAVED_TEXT}, + {"removePageButtonLabel", IDS_SCANNING_APP_REMOVE_PAGE_BUTTON_LABEL}, + {"rescanPageButtonLabel", IDS_SCANNING_APP_RESCAN_PAGE_BUTTON_LABEL}, {"scanButtonText", IDS_SCANNING_APP_SCAN_BUTTON_TEXT}, {"scannedImagesAriaLabel", IDS_SCANNING_APP_SCANNED_IMAGES_ARIA_LABEL}};
diff --git a/ash/wm/window_state.cc b/ash/wm/window_state.cc index 51d1a7c1..a7ae08c 100644 --- a/ash/wm/window_state.cc +++ b/ash/wm/window_state.cc
@@ -76,10 +76,15 @@ } // ARC windows will not be in a top level container until they are associated -// with a task. We still want a WindowState created for these windows as they -// will be moved to a top level container soon. +// with a task. We still want a WindowState created for these windows and their +// transient children as they will be moved to a top level container soon. bool IsTemporarilyHiddenForFullrestore(aura::Window* window) { - return window->GetProperty(full_restore::kParentToHiddenContainerKey); + if (window->GetProperty(full_restore::kParentToHiddenContainerKey)) + return true; + + auto* transient_parent = ::wm::GetTransientParent(window); + return transient_parent && transient_parent->GetProperty( + full_restore::kParentToHiddenContainerKey); } // A tentative class to set the bounds on the window.
diff --git a/base/android/java/src/org/chromium/base/library_loader/LegacyLinker.java b/base/android/java/src/org/chromium/base/library_loader/LegacyLinker.java index 265d2e9..b3587e13 100644 --- a/base/android/java/src/org/chromium/base/library_loader/LegacyLinker.java +++ b/base/android/java/src/org/chromium/base/library_loader/LegacyLinker.java
@@ -26,8 +26,8 @@ @Override void setApkFilePath(String path) { + ensureInitializedImplicitlyAsLastResort(); synchronized (mLock) { - ensureInitializedLocked(); nativeAddZipArchivePath(path); } }
diff --git a/base/android/java/src/org/chromium/base/library_loader/LibraryLoader.java b/base/android/java/src/org/chromium/base/library_loader/LibraryLoader.java index dcf2734..27c4815 100644 --- a/base/android/java/src/org/chromium/base/library_loader/LibraryLoader.java +++ b/base/android/java/src/org/chromium/base/library_loader/LibraryLoader.java
@@ -171,8 +171,11 @@ */ @ThreadSafe public class MultiProcessMediator { - @GuardedBy("mLock") - private long mLoadAddress; + // Currently clients initialize |mLoadAddress| strictly before any other method can get + // executed on a different thread. Hence, synchronization is not required, but verification + // of correctness is still non-trivial, and over-synchronization is cheap compared to + // library loading. + private volatile long mLoadAddress; // Used only for asserts, and only ever switched from false to true. private volatile boolean mInitDone; @@ -182,13 +185,7 @@ * @param bundle The Bundle to extract from. */ public void takeLoadAddressFromBundle(Bundle bundle) { - // Currently clients call this method strictly before any other method can get executed - // on a different thread. Hence, synchronization is not required, but verification of - // correctness is still non-trivial, and over-synchronization is cheap compared to - // library loading. - synchronized (mLock) { - mLoadAddress = Linker.extractLoadAddressFromBundle(bundle); - } + mLoadAddress = Linker.extractLoadAddressFromBundle(bundle); } /** @@ -198,7 +195,9 @@ public void ensureInitializedInMainProcess() { if (mInitDone) return; if (useChromiumLinker()) { - getLinker().initAsRelroProducer(); + // In the main process choose the loading address at random. + getLinker().ensureInitialized(/* asRelroProducer= */ true, + Linker.PreferAddress.FIND_RESERVED, /* addressHint= */ 0); } mInitDone = true; } @@ -220,9 +219,8 @@ */ public void initInChildProcess() { if (useChromiumLinker()) { - synchronized (mLock) { - getLinker().initAsRelroConsumer(mLoadAddress); - } + getLinker().ensureInitialized(/* asRelroProducer= */ false, + Linker.PreferAddress.RESERVE_HINT, mLoadAddress); } mInitDone = true; } @@ -896,16 +894,15 @@ mInitialized = true; } + // The native methods below are defined in library_loader_hooks.cc. @NativeMethods interface Natives { - // Only methods needed before or during normal JNI registration are during System.OnLoad. - // nativeLibraryLoaded is then called to register everything else. This process is called - // "initialization". This method will be mapped (by generated code) to the LibraryLoaded - // definition in base/android/library_loader/library_loader_hooks.cc. - // - // Return true on success and false on failure. + // Performs auxiliary initialization useful right after the native library load. Returns + // true on success and false on failure. boolean libraryLoaded(@LibraryProcessType int processType); + // Registers JNI for non-main processes. For details see android_native_libraries.md, + // android_dynamic_feature_modules.md and jni_generator/README.md void registerNonMainDexJni(); // Records the number of milliseconds it took to load the libraries in the renderer.
diff --git a/base/android/java/src/org/chromium/base/library_loader/Linker.java b/base/android/java/src/org/chromium/base/library_loader/Linker.java index 5c339ab..13b01bc 100644 --- a/base/android/java/src/org/chromium/base/library_loader/Linker.java +++ b/base/android/java/src/org/chromium/base/library_loader/Linker.java
@@ -61,10 +61,10 @@ * - Before loading the library, setApkFilePath() must be called when loading from the APK. * * - Early on, before the attempt to load the library, the linker needs to be initialized either as - * a producer or a consumer of the RELRO region. Depending on the choice either - * initAsRelroProducer() or initAsRelroConsumer() should be invoked. Since various Chromium - * projects have vastly different initialization paths, for convenience the initialization runs - * implicitly as part of loading the library. In this case the behaviour is of a producer. + * a producer or a consumer of the RELRO region by invoking ensureInitialized(). Since various + * Chromium projects have vastly different initialization paths, for convenience the + * initialization runs implicitly as part of loading the library. In this case the behaviour is of + * a producer. * * - When running as a RELRO consumer, the loadLibrary() may block until the RELRO section Bundle * is received. This is done by calling takeSharedRelrosFromBundle() from another thread. @@ -106,7 +106,8 @@ // value is used in tests, it is set to true so that the Linker does not have to wait for RELRO // to arrive from another process. @GuardedBy("mLock") - private boolean mRelroProducer = true; + @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) + boolean mRelroProducer = true; @GuardedBy("mLock") private boolean mLinkerWasWaitingSynchronously; @@ -161,34 +162,145 @@ sLinkerForAssert = this; } - /** - * Initializes the Linker and ensures that after loading the native library the RELRO region - * will be available for sharing with other processes via - * {@link #putSharedRelrosToBundle(Bundle)}. - */ - final void initAsRelroProducer() { - synchronized (mLock) { - mRelroProducer = true; - ensureInitializedLocked(); + @IntDef({PreferAddress.FIND_RESERVED, PreferAddress.RESERVE_HINT, PreferAddress.RESERVE_RANDOM}) + @Retention(RetentionPolicy.SOURCE) + public @interface PreferAddress { + int FIND_RESERVED = 0; + int RESERVE_HINT = 1; + int RESERVE_RANDOM = 2; + } + private String preferAddressToString(@PreferAddress int a) { + switch (a) { + case PreferAddress.FIND_RESERVED: + return "FIND_RESERVED"; + case PreferAddress.RESERVE_HINT: + return "RESERVE_HINT"; + case PreferAddress.RESERVE_RANDOM: + return "RESERVE_RANDOM"; + default: + return String.valueOf(a); } } + // Exposed to be able to mock out an assertion. + @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) + boolean isNonZeroLoadAddress(LibInfo libInfo) { + return libInfo != null && libInfo.mLoadAddress != 0; + } + /** - * Initializes the Linker in the mode prepared to receive a RELRO region information from - * another process. Arrival of the RELRO region may block loading the native library in this - * process. + * Initializes the Linker. This is the first method to be called on the instance. * - * @param baseLoadAddress the base library load address to use. + * Linker and its subclasses abstract away from knowing process types and what the role of each + * process is. The LibraryLoader and the layers above tell the singleton linker whether it needs + * to produce the RELRO region, consume it, whether to use the address hint or to synthesize + * according to a strategy. + * + * In many cases finding the library load address is on the critical path, and needs to be + * transferred to other processes as soon as possible. For this purpose initialization is + * invoked separately from loading. + * + * The caller should provide the |preference| for obtaining the address at which to load the + * native library. The value is one of these: + * + * FIND_RESERVED, RESERVE_HINT, RESERVE_RANDOM. + * + * In the vast majority of cases the chosen preference will be fulfilled and the address (with + * the size) will be saved for use during {@link Linker#loadLibrary(String)}. In case the + * preferred way fails (due to address fragmentation, for example), a fallback attempt will be + * made with |preference| to the right of the current one in the list above. There is no + * fallback for RESERVE_RANDOM. + * + * FIND_RESERVED: Finds the (named) reserved address range for library loading. The caller needs + * to make sure that this is only called on platform versions supporting this memory + * reservation (Android Q+). + * + * RESERVE_HINT: Reserves enough of address range for loading a library, starting at the + * |addressHint| provided. The latter is expected to arrive from another process (randomized + * there), hence sometimes the address range may not be available. + * + * RESERVE_RANDOM: Finds a free random address range and reserves it. + * + * With the LegacyLinker this method releases the memory reservation (or does not attempt to do + * it). This is because the LegacyLinker reserves a region using: + * + * mmap(address_hint, flags_without_MAP_FIXED ) + * + * This behavior is harmlessly racy: in case something else grabs the address range before the + * library loading starts, the dynamic linking will load at a different address and fall back to + * *not* sharing RELRO. The chances of this happening in a fresh process are low. + * + * Unmapping and then mapping the region again is likely unnecessary. Ideally both Linkers + * should start by reserving the memory region early in process lifetime, then load the library + * with mmap(nullptr, ... MAP_FIXED) on top of it. Unfortunately the crazylinker feature to load + * on top of a reserved memory region is not well tested and looks buggy. + * + * @param asRelroProducer whether the Linker instance will need to produce the shared memory + * region as part of work in {@link Linker#loadLibrary(String)}. + * @param preference the preference for obtaining the address, with fallback to a less memory + * efficient method + * @param addressHint the hint to be used when RESERVE_HINT is provided as |preference| + * */ - final void initAsRelroConsumer(long baseLoadAddress) { - if (DEBUG) Log.i(TAG, "AsRelroConsumer: given address: 0x%x", baseLoadAddress); + final void ensureInitialized( + boolean asRelroProducer, @PreferAddress int preference, long addressHint) { + if (DEBUG) { + Log.i(TAG, + "ensureInitialized(asRelroProducer=%b, preference=%s, " + + "loadAddressHint=0x%x)", + asRelroProducer, preferAddressToString(preference), addressHint); + } + assert !asRelroProducer + || preference + != PreferAddress.RESERVE_HINT + : "Producer does not accept hints from outside"; synchronized (mLock) { - mRelroProducer = false; - ensureInitializedLocked(); - mLocalLibInfo.mLoadAddress = baseLoadAddress; - if (keepMemoryReservationUntilLoad()) { - getLinkerJni().reserveMemoryForLibrary(mLocalLibInfo); + if (mState != State.UNINITIALIZED) return; + chooseAndReserveMemoryRange(asRelroProducer, preference, addressHint); + if (DEBUG) { + Log.i(TAG, "ensureInitialized: chose address=0x%x", mLocalLibInfo.mLoadAddress); } + mState = State.INITIALIZED; + } + } + + // Initializes the |mLocalLibInfo| and reserves the address range chosen (only when + // keepMemoryReservationUntilLoad() returns true). + @GuardedBy("mLock") + final void chooseAndReserveMemoryRange( + boolean asRelroProducer, @PreferAddress int preference, long addressHint) { + mLocalLibInfo = new LibInfo(); + mRelroProducer = asRelroProducer; + loadLinkerJniLibraryLocked(); + boolean keepReservation = keepMemoryReservationUntilLoad(); + switch (preference) { + case PreferAddress.FIND_RESERVED: + if (getLinkerJni().findRegionReservedByWebViewZygote(mLocalLibInfo)) { + assert isNonZeroLoadAddress(mLocalLibInfo); + if (addressHint == 0 || addressHint == mLocalLibInfo.mLoadAddress) { + // Subtle: Both the producer and the consumer are expected to find the same + // address reservation. When |addressHint != 0| the producer was quick + // enough to provide the address before the consumer started initialization. + // Choosing the hint sounds like the right thing to do, and faster than + // looking up the named address range again. However, there is not enough + // information on how the hint was obtained by the producer. If it was found + // by a fallback (less likely) then the region must be reserved in this + // process. On systems where FIND_RESERVED is the preference, the most + // likely variant is that it is already reserved, hence check for it first. + return; + } + } + // Intentional fallthrough. + case PreferAddress.RESERVE_HINT: + mLocalLibInfo.mLoadAddress = addressHint; + if (addressHint != 0) { + if (!keepReservation) return; + getLinkerJni().reserveMemoryForLibrary(mLocalLibInfo); + if (mLocalLibInfo.mLoadAddress != 0) return; + } + // Intentional fallthrough. + case PreferAddress.RESERVE_RANDOM: + getLinkerJni().findMemoryRegionAtRandomAddress(mLocalLibInfo, keepReservation); } } @@ -206,8 +318,9 @@ * @param bundle Bundle to put the address to. */ void putLoadAddressToBundle(Bundle bundle) { + if (DEBUG) Log.i(TAG, "putLoadAddressToBundle"); synchronized (mLock) { - ensureInitializedLocked(); + assert mState != State.UNINITIALIZED; if (mLocalLibInfo != null && mLocalLibInfo.mLoadAddress != 0) { bundle.putLong(BASE_LOAD_ADDRESS, mLocalLibInfo.mLoadAddress); } @@ -260,7 +373,7 @@ // produce or consume the shared relocations. Initialization here is the last resort // to choose the load address in tests that forget to decide whether they are a // producer or a consumer. - ensureInitializedLocked(); + ensureInitializedImplicitlyAsLastResort(); // Load the library. During initialization Linker subclass reserves the address // range where the library will be loaded and keeps it in |mLocalLibInfo|. @@ -291,31 +404,45 @@ assert mRelroProducer; relros = mLocalLibInfo.toBundle(); } + bundle.putBundle(SHARED_RELROS, relros); + if (DEBUG && relros != null) { + Log.i(TAG, + "putSharedRelrosToBundle() puts mLoadAddress=0x%x, mLoadSize=%d, " + + "mRelroFd=%d", + mLocalLibInfo.mLoadAddress, mLocalLibInfo.mLoadSize, + mLocalLibInfo.mRelroFd); + } } - bundle.putBundle(SHARED_RELROS, relros); - if (DEBUG) Log.i(TAG, "putSharedRelrosToBundle() puts %s", relros); } /** * Deserializes the RELRO region information that was marshalled by - * {@link #putLoadAddressToBundle(Bundle)} and wakes up the threads waiting for it to use (mmap) - * replace the RELRO section in this process with shared memory. + * {@link #putLoadAddressToBundle(Bundle)} and wakes up the threads waiting for it to replace + * the RELRO section in this process with shared memory. * @param bundle The Bundle to extract the information from. */ void takeSharedRelrosFromBundle(Bundle bundle) { if (DEBUG) Log.i(TAG, "called takeSharedRelrosFromBundle(%s)", bundle); Bundle relros = bundle.getBundle(SHARED_RELROS); - if (relros != null) { - synchronized (mLock) { - assert mRemoteLibInfo == null; - mRemoteLibInfo = LibInfo.fromBundle(relros); - if (mState == State.DONE) { - atomicReplaceRelroLocked(false /* relroAvailableImmediately */); - } else { - assert mState != State.DONE_PROVIDE_RELRO; - // Wake up blocked callers of waitForSharedRelrosLocked(). - mLock.notifyAll(); + if (relros == null) return; + LibInfo newRemote = LibInfo.fromBundle(relros); + if (newRemote == null) return; + synchronized (mLock) { + if (mRemoteLibInfo != null && mRemoteLibInfo.mRelroFd != -1) { + if (DEBUG) { + Log.i(TAG, + "Attempt to replace RELRO a second time " + + "library addr=0x%x, with new library addr=0x%x", + mRemoteLibInfo.mLoadAddress, newRemote.mLoadAddress); } + return; + } + mRemoteLibInfo = newRemote; + if (mState == State.DONE) { + atomicReplaceRelroLocked(false /* relroAvailableImmediately */); + } else if (mState != State.DONE_PROVIDE_RELRO) { + // Wake up blocked callers of waitForSharedRelrosLocked(). + mLock.notifyAll(); } } } @@ -388,35 +515,16 @@ System.loadLibrary(LINKER_JNI_LIBRARY); } - // Initializes the Linker: loads an auxiliary native library and initialize its JNI. Reserves - // the address range where the native library will later be placed. For LegacyLinker frees up - // the range immediately in order for the LegacyLinker to attempt to reserve it again. - @GuardedBy("mLock") - protected final void ensureInitializedLocked() { - if (mState != State.UNINITIALIZED) return; - - loadLinkerJniLibraryLocked(); - mLocalLibInfo = new LibInfo(); - if (mRelroProducer) { - // The LegacyLinker requires the memory reservation to be immediately unmapped because - // it reserves a region using mmap(address_hint, /* without MAP_FIXED */). This behavior - // is harmlessly racy: in case something else grabs the address range before the library - // loading starts, the dynamic linking will load at a different address and fall back to - // not sharing RELRO. The chances of this happening in a fresh process are low. - // - // Unmapping and then mapping the region again is likely unnecessary. Ideally both - // Linkers should start by reserving the memory region early in process lifetime, then - // load the library with mmap(nullptr, ... MAP_FIXED) on top of it. Unfortunately the - // crazylinker feature to load on top of a reserved memory region is not well tested and - // looks buggy. - getLinkerJni().findMemoryRegionAtRandomAddress( - mLocalLibInfo, keepMemoryReservationUntilLoad()); - if (DEBUG) { - Log.i(TAG, "AsRelroProducer: chose address: 0x%x", mLocalLibInfo.mLoadAddress); - } - } - - mState = State.INITIALIZED; + /** + * Initializes the auxiliary native library unless it was initialized before. + * + * Initializes as a RELRO producer without knowledge about preferred placement of the RELRO + * region. Should only be used as the last resort: when the simplicity of avoiding the explicit + * initialization is preferred over memory savings, such as in tests. + */ + protected final void ensureInitializedImplicitlyAsLastResort() { + ensureInitialized( + /* asRelroProducer= */ true, PreferAddress.RESERVE_RANDOM, /* addressHint= */ 0); } // Used by the LegacyLinker to wait for shared RELROs. Returns once takeSharedRelrosFromBundle() @@ -581,12 +689,24 @@ * |libInfo.mLoadAddress| to 0. */ void reserveMemoryForLibrary(@NonNull LibInfo libInfo); + + /** + * Finds the (named) address range reservation made by the system zygote and dedicated for + * loading the native library. Reads /proc/self/maps, which is a slow operation (up to a few + * ms). TODO(pasko): collect measurements of the duration. + * + * @param libInfo holds the output values: |mLoadAddress| and |mLoadSize|. On success saves + * the start address and the size of the webview memory reservation to them. + * @return whether the region was found. + */ + boolean findRegionReservedByWebViewZygote(@NonNull LibInfo libInfo); } private static Linker.Natives sNativesInstance; static void setNativesForTesting(Natives instance) { sNativesInstance = instance; + sLinkerForAssert = null; // Also allow to create Linker multiple times in tests. } @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
diff --git a/base/android/java/src/org/chromium/base/library_loader/LinkerJni.java b/base/android/java/src/org/chromium/base/library_loader/LinkerJni.java index 061e511..42af784 100644 --- a/base/android/java/src/org/chromium/base/library_loader/LinkerJni.java +++ b/base/android/java/src/org/chromium/base/library_loader/LinkerJni.java
@@ -31,7 +31,14 @@ nativeReserveMemoryForLibrary(libInfo); } + @Override + public boolean findRegionReservedByWebViewZygote(@NonNull Linker.LibInfo libInfo) { + return nativeFindRegionReservedByWebViewZygote(libInfo); + } + private static native void nativeFindMemoryRegionAtRandomAddress( @NonNull Linker.LibInfo libInfo, boolean keepReserved); private static native void nativeReserveMemoryForLibrary(@NonNull Linker.LibInfo libInfo); + private static native boolean nativeFindRegionReservedByWebViewZygote( + @NonNull Linker.LibInfo libInfo); }
diff --git a/base/android/junit/src/org/chromium/base/library_loader/LinkerTest.java b/base/android/junit/src/org/chromium/base/library_loader/LinkerTest.java index f76d360..10a2f2a7 100644 --- a/base/android/junit/src/org/chromium/base/library_loader/LinkerTest.java +++ b/base/android/junit/src/org/chromium/base/library_loader/LinkerTest.java
@@ -7,6 +7,7 @@ import androidx.test.filters.SmallTest; import org.junit.After; +import org.junit.Assert; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -19,6 +20,7 @@ import org.mockito.quality.Strictness; import org.robolectric.annotation.Config; +import org.chromium.base.library_loader.Linker.PreferAddress; import org.chromium.base.test.BaseRobolectricTestRunner; /** @@ -44,18 +46,179 @@ Linker.setNativesForTesting(null); } + static Linker.LibInfo anyLibInfo() { + return ArgumentMatchers.any(Linker.LibInfo.class); + } + @Test @SmallTest public void testConsumer() { + // Set up. Linker linker = Mockito.spy(new ModernLinker()); - Mockito.doNothing().when(linker).loadLinkerJniLibraryLocked(); + // Exercise. long someAddress = 1 << 12; - linker.initAsRelroConsumer(someAddress); + linker.ensureInitialized( + /* asRelroProducer= */ false, PreferAddress.RESERVE_HINT, someAddress); + // Verify. + Assert.assertEquals(false, linker.mRelroProducer); + Mockito.verify(linker).keepMemoryReservationUntilLoad(); + Mockito.verify(mNativeMock).reserveMemoryForLibrary(anyLibInfo()); + Assert.assertNotEquals(null, linker.mLocalLibInfo); + Assert.assertEquals(someAddress, linker.mLocalLibInfo.mLoadAddress); + } + + @Test + @SmallTest + public void testLegacyConsumer() { + // Set up. + Linker linker = Mockito.spy(new LegacyLinker()); + Mockito.doNothing().when(linker).loadLinkerJniLibraryLocked(); + + // Exercise. + long someAddress = 1 << 12; + linker.ensureInitialized( + /* asRelroProducer= */ false, PreferAddress.RESERVE_HINT, someAddress); + + // Verify. + Assert.assertEquals(false, linker.mRelroProducer); + Mockito.verify(linker).keepMemoryReservationUntilLoad(); + Mockito.verify(mNativeMock, Mockito.never()).reserveMemoryForLibrary(anyLibInfo()); + } + + @Test + @SmallTest + public void testProducer() { + // Set up. + Linker linker = Mockito.spy(new ModernLinker()); + Mockito.doNothing().when(linker).loadLinkerJniLibraryLocked(); + + // Exercise. + linker.ensureInitialized(/* asRelroProducer= */ true, PreferAddress.RESERVE_RANDOM, 0); + + // Verify. + Assert.assertEquals(true, linker.mRelroProducer); Mockito.verify(linker).keepMemoryReservationUntilLoad(); Mockito.verify(mNativeMock) - .reserveMemoryForLibrary(ArgumentMatchers.any(Linker.LibInfo.class)); + .findMemoryRegionAtRandomAddress(anyLibInfo(), ArgumentMatchers.eq(true)); + Assert.assertNotEquals(null, linker.mLocalLibInfo); + } + + @Test + @SmallTest + public void testConsumerReserveRandom() { + // Set up. + Linker linker = Mockito.spy(new ModernLinker()); + Mockito.doNothing().when(linker).loadLinkerJniLibraryLocked(); + + // Exercise. + linker.ensureInitialized(/* asRelroProducer= */ false, PreferAddress.RESERVE_RANDOM, 0); + + // Verify. + Mockito.verify(linker).keepMemoryReservationUntilLoad(); + Mockito.verify(mNativeMock) + .findMemoryRegionAtRandomAddress(anyLibInfo(), ArgumentMatchers.eq(true)); + } + + @Test + @SmallTest + public void testReservingZeroFallsBackToRandom() { + // Set up. + Linker linker = Mockito.spy(new ModernLinker()); + Mockito.doNothing().when(linker).loadLinkerJniLibraryLocked(); + + // Exercise. + linker.ensureInitialized(/* asRelroProducer= */ false, PreferAddress.RESERVE_HINT, 0); + + // Verify. + Mockito.verify(linker).keepMemoryReservationUntilLoad(); + Mockito.verify(mNativeMock) + .findMemoryRegionAtRandomAddress(anyLibInfo(), ArgumentMatchers.eq(true)); + } + + @Test + @SmallTest + public void testAppZygoteProducingRelro() { + // Set up. + Linker linker = Mockito.spy(new ModernLinker()); + Mockito.doNothing().when(linker).loadLinkerJniLibraryLocked(); + // The lookup of the region succeeds. + Mockito.when(mNativeMock.findRegionReservedByWebViewZygote(anyLibInfo())).thenReturn(true); + Mockito.when(linker.isNonZeroLoadAddress(anyLibInfo())).thenReturn(true); + + // Exercise. + linker.ensureInitialized(/* asRelroProducer= */ true, PreferAddress.FIND_RESERVED, 0); + + // Verify. + Mockito.verify(linker).keepMemoryReservationUntilLoad(); + Mockito.verify(mNativeMock).findRegionReservedByWebViewZygote(anyLibInfo()); + Mockito.verify(mNativeMock, Mockito.never()) + .findMemoryRegionAtRandomAddress(anyLibInfo(), ArgumentMatchers.anyBoolean()); + Mockito.verify(mNativeMock, Mockito.never()).reserveMemoryForLibrary(anyLibInfo()); + } + + @Test + @SmallTest + public void testAppZygoteFailsToFindReservedAddressRange() { + // Set up. + Linker linker = Mockito.spy(new ModernLinker()); + Mockito.doNothing().when(linker).loadLinkerJniLibraryLocked(); + // The lookup of the region succeeds. + Mockito.when(mNativeMock.findRegionReservedByWebViewZygote(anyLibInfo())).thenReturn(false); + + // Exercise. + linker.ensureInitialized(/* asRelroProducer= */ true, PreferAddress.FIND_RESERVED, 0); + + // Verify. + Mockito.verify(linker).keepMemoryReservationUntilLoad(); + Mockito.verify(mNativeMock).findRegionReservedByWebViewZygote(anyLibInfo()); + Mockito.verify(mNativeMock) + .findMemoryRegionAtRandomAddress(anyLibInfo(), ArgumentMatchers.anyBoolean()); + } + + @Test + @SmallTest + public void testBrowserExpectingRelroFromZygote() { + // Set up. + Linker linker = Mockito.spy(new ModernLinker()); + Mockito.doNothing().when(linker).loadLinkerJniLibraryLocked(); + // The lookup of the region succeeds. + Mockito.when(mNativeMock.findRegionReservedByWebViewZygote(anyLibInfo())).thenReturn(true); + Mockito.when(linker.isNonZeroLoadAddress(anyLibInfo())).thenReturn(true); + + // Exercise. + linker.ensureInitialized(/* asRelroProducer= */ false, PreferAddress.FIND_RESERVED, 0); + + // Verify. + Mockito.verify(linker).keepMemoryReservationUntilLoad(); + Mockito.verify(mNativeMock).findRegionReservedByWebViewZygote(anyLibInfo()); + Mockito.verify(mNativeMock, Mockito.never()) + .findMemoryRegionAtRandomAddress(anyLibInfo(), ArgumentMatchers.anyBoolean()); + Mockito.verify(mNativeMock, Mockito.never()).reserveMemoryForLibrary(anyLibInfo()); + } + + @Test + @SmallTest + public void testPrivilegedProcessWithHint() { + // Set up. + Linker linker = Mockito.spy(new ModernLinker()); + Mockito.doNothing().when(linker).loadLinkerJniLibraryLocked(); + // The lookup of the region succeeds. + Mockito.when(mNativeMock.findRegionReservedByWebViewZygote(anyLibInfo())).thenReturn(true); + Mockito.when(linker.isNonZeroLoadAddress(anyLibInfo())).thenReturn(true); + + // Exercise. + long someAddress = 1 << 12; + linker.ensureInitialized( + /* asRelroProducer= */ false, PreferAddress.FIND_RESERVED, someAddress); + + // Verify. + Mockito.verify(linker).keepMemoryReservationUntilLoad(); + Mockito.verify(mNativeMock).findRegionReservedByWebViewZygote(anyLibInfo()); + // Unfortunately there does not seem to be an elegant way to set |mLoadAddress| without + // extracting creation of mLocalLibInfo from ensureInitialized(). Hence no checks are + // present here involving the exact value of |mLoadAddress|. } }
diff --git a/base/android/linker/linker_jni.cc b/base/android/linker/linker_jni.cc index 8d84809..3d39879 100644 --- a/base/android/linker/linker_jni.cc +++ b/base/android/linker/linker_jni.cc
@@ -265,4 +265,19 @@ s_lib_info_fields.SetLoadInfo(env, lib_info_obj, address, size); } +// Performs as described in Linker.java. +JNI_GENERATOR_EXPORT jboolean +Java_org_chromium_base_library_1loader_LinkerJni_nativeFindRegionReservedByWebViewZygote( + JNIEnv* env, + jclass clazz, + jobject lib_info_obj) { + LOG_INFO("Entering"); + uintptr_t address; + size_t size; + if (!FindWebViewReservation(&address, &size)) + return false; + s_lib_info_fields.SetLoadInfo(env, lib_info_obj, address, size); + return true; +} + } // namespace chromium_android_linker
diff --git a/base/profiler/module_cache.h b/base/profiler/module_cache.h index 71f7d78..28f40d70 100644 --- a/base/profiler/module_cache.h +++ b/base/profiler/module_cache.h
@@ -16,7 +16,7 @@ #include "build/build_config.h" #if defined(OS_WIN) -#include <windows.h> +#include "base/win/windows_types.h" #endif namespace base {
diff --git a/base/profiler/stack_sampling_profiler.h b/base/profiler/stack_sampling_profiler.h index 0fbf693..00320398 100644 --- a/base/profiler/stack_sampling_profiler.h +++ b/base/profiler/stack_sampling_profiler.h
@@ -13,7 +13,6 @@ #include "base/macros.h" #include "base/profiler/profile_builder.h" #include "base/profiler/sampling_profiler_thread_token.h" -#include "base/profiler/unwinder.h" #include "base/synchronization/waitable_event.h" #include "base/threading/platform_thread.h" #include "base/time/time.h"
diff --git a/base/threading/thread_restrictions.h b/base/threading/thread_restrictions.h index c54b4e6..70bf434b 100644 --- a/base/threading/thread_restrictions.h +++ b/base/threading/thread_restrictions.h
@@ -282,6 +282,10 @@ class ScopedAllowThreadJoinForProxyResolverV8Tracing; } +namespace remote_cocoa { +class DroppedScreenShotCopierMac; +} // namespace remote_cocoa + namespace remoting { class AutoThread; class ScopedBypassIOThreadRestrictions; @@ -425,6 +429,8 @@ friend class printing::PrintBackendServiceImpl; #endif friend class printing::PrintJobWorker; + friend class remote_cocoa:: + DroppedScreenShotCopierMac; // https://crbug.com/1148078 friend class remoting::ScopedBypassIOThreadRestrictions; // crbug.com/1144161 friend class web::WebSubThread; friend class weblayer::BrowserContextImpl;
diff --git a/base/time/time.h b/base/time/time.h index d8dd738..30c6b61 100644 --- a/base/time/time.h +++ b/base/time/time.h
@@ -71,7 +71,7 @@ #include "base/base_export.h" #include "base/check_op.h" #include "base/compiler_specific.h" -#include "base/numerics/safe_math.h" +#include "base/numerics/clamped_math.h" #include "build/build_config.h" #include "build/chromeos_buildflags.h"
diff --git a/build/config/compiler/compiler.gni b/build/config/compiler/compiler.gni index 32e1200..8c259c36 100644 --- a/build/config/compiler/compiler.gni +++ b/build/config/compiler/compiler.gni
@@ -95,7 +95,11 @@ # For unofficial (e.g. development) builds and non-Chrome branded (e.g. Cronet # which doesn't use Crashpad, crbug.com/479283) builds it's useful to be able # to unwind at runtime. - exclude_unwind_tables = is_official_build + # Include the unwind tables on Android even for official builds, as otherwise + # the crash dumps generated by Android's debuggerd are largely useless, and + # having this additional mechanism to understand issues is particularly helpful + # to WebView. + exclude_unwind_tables = is_official_build && !is_android # Where to redirect clang crash diagnoses clang_diagnostic_dir =
diff --git a/build/config/fuchsia/test/README.md b/build/config/fuchsia/test/README.md index c5f1762..8427f4a 100644 --- a/build/config/fuchsia/test/README.md +++ b/build/config/fuchsia/test/README.md
@@ -56,3 +56,6 @@ Contains services that need to be present when creating a `fuchsia.web.Context`. Note that the `fuchsia.scheduler.ProfileProvider` service is only used in tests that encounter memory pressure code. + +#### web_instance_host_capabilities.test-cmx +Contains services that need to be present to use `WebInstanceHost`. \ No newline at end of file
diff --git a/build/config/fuchsia/test/web_instance_host_capabilities.test-cmx b/build/config/fuchsia/test/web_instance_host_capabilities.test-cmx new file mode 100644 index 0000000..8281176 --- /dev/null +++ b/build/config/fuchsia/test/web_instance_host_capabilities.test-cmx
@@ -0,0 +1,16 @@ +{ + "facets": { + "fuchsia.test": { + "system-services": [ + "fuchsia.sys.Environment", + "fuchsia.sys.Loader" + ] + } + }, + "sandbox": { + "services": [ + "fuchsia.sys.Environment", + "fuchsia.sys.Loader" + ] + } +} \ No newline at end of file
diff --git a/cc/benchmarks/rasterize_and_record_benchmark.cc b/cc/benchmarks/rasterize_and_record_benchmark.cc index 8095225..1be5bac5 100644 --- a/cc/benchmarks/rasterize_and_record_benchmark.cc +++ b/cc/benchmarks/rasterize_and_record_benchmark.cc
@@ -75,21 +75,24 @@ static_cast<int>(record_results_.paint_op_memory_usage)); results_->SetInteger("paint_op_count", static_cast<int>(record_results_.paint_op_count)); - results_->SetDouble("record_time_ms", paint_benchmark_result.record_time_ms); - results_->SetDouble("record_time_caching_disabled_ms", - paint_benchmark_result.record_time_caching_disabled_ms); - results_->SetDouble( + results_->SetDoubleKey("record_time_ms", + paint_benchmark_result.record_time_ms); + results_->SetDoubleKey( + "record_time_caching_disabled_ms", + paint_benchmark_result.record_time_caching_disabled_ms); + results_->SetDoubleKey( "record_time_subsequence_caching_disabled_ms", paint_benchmark_result.record_time_subsequence_caching_disabled_ms); - results_->SetDouble( + results_->SetDoubleKey( "record_time_partial_invalidation_ms", paint_benchmark_result.record_time_partial_invalidation_ms); - results_->SetDouble("record_time_small_invalidation_ms", - paint_benchmark_result.record_time_small_invalidation_ms); - results_->SetDouble( + results_->SetDoubleKey( + "record_time_small_invalidation_ms", + paint_benchmark_result.record_time_small_invalidation_ms); + results_->SetDoubleKey( "raster_invalidation_and_convert_time_ms", paint_benchmark_result.raster_invalidation_and_convert_time_ms); - results_->SetDouble( + results_->SetDoubleKey( "paint_artifact_compositor_update_time_ms", paint_benchmark_result.paint_artifact_compositor_update_time_ms); results_->SetInteger(
diff --git a/cc/benchmarks/rasterize_and_record_benchmark_impl.cc b/cc/benchmarks/rasterize_and_record_benchmark_impl.cc index b4c365d..de49b82 100644 --- a/cc/benchmarks/rasterize_and_record_benchmark_impl.cc +++ b/cc/benchmarks/rasterize_and_record_benchmark_impl.cc
@@ -9,6 +9,7 @@ #include <algorithm> #include <limits> #include <memory> +#include <utility> #include "base/timer/lap_timer.h" #include "base/values.h" @@ -166,8 +167,8 @@ } std::unique_ptr<base::DictionaryValue> result(new base::DictionaryValue()); - result->SetDouble("rasterize_time_ms", - rasterize_results_.total_best_time.InMillisecondsF()); + result->SetDoubleKey("rasterize_time_ms", + rasterize_results_.total_best_time.InMillisecondsF()); result->SetInteger("pixels_rasterized", rasterize_results_.pixels_rasterized); result->SetInteger("pixels_rasterized_with_non_solid_color", rasterize_results_.pixels_rasterized_with_non_solid_color);
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn index 053951d..de36df8 100644 --- a/chrome/android/BUILD.gn +++ b/chrome/android/BUILD.gn
@@ -396,6 +396,7 @@ "//chrome/browser/ui/android/night_mode:java", "//chrome/browser/ui/android/omnibox:java", "//chrome/browser/ui/android/quickactionsearchwidget:java", + "//chrome/browser/ui/android/searchactivityutils:java", "//chrome/browser/ui/android/theme:java", "//chrome/browser/ui/android/toolbar:java", "//chrome/browser/ui/messages/android:java", @@ -1296,6 +1297,7 @@ "//chrome/browser/ui/android/omnibox:java", "//chrome/browser/ui/android/quickactionsearchwidget:java", "//chrome/browser/ui/android/quickactionsearchwidget:javatests", + "//chrome/browser/ui/android/searchactivityutils:java", "//chrome/browser/ui/android/theme:java", "//chrome/browser/ui/android/toolbar:java", "//chrome/browser/ui/android/toolbar:javatests",
diff --git a/chrome/android/expectations/monochrome_public_bundle.AndroidManifest.expected b/chrome/android/expectations/monochrome_public_bundle.AndroidManifest.expected index 2dda1d61..a25a324 100644 --- a/chrome/android/expectations/monochrome_public_bundle.AndroidManifest.expected +++ b/chrome/android/expectations/monochrome_public_bundle.AndroidManifest.expected
@@ -1037,6 +1037,9 @@ <intent-filter> # DIFF-ANCHOR: b2859f10 <action android:name="org.chromium.chrome.browser.ui.quickactionsearchwidget.START_TEXT_QUERY"/> </intent-filter> # DIFF-ANCHOR: b2859f10 + <intent-filter> # DIFF-ANCHOR: 22a1258b + <action android:name="org.chromium.chrome.browser.ui.quickactionsearchwidget.START_VOICE_QUERY"/> + </intent-filter> # DIFF-ANCHOR: 22a1258b </receiver> # DIFF-ANCHOR: 585b7cc1 <receiver # DIFF-ANCHOR: a0d83ae5 android:name="org.chromium.chrome.browser.searchwidget.SearchWidgetProvider"
diff --git a/chrome/android/expectations/trichrome_chrome_bundle.AndroidManifest.expected b/chrome/android/expectations/trichrome_chrome_bundle.AndroidManifest.expected index 56bbb48..0a0aada2 100644 --- a/chrome/android/expectations/trichrome_chrome_bundle.AndroidManifest.expected +++ b/chrome/android/expectations/trichrome_chrome_bundle.AndroidManifest.expected
@@ -963,6 +963,9 @@ <intent-filter> # DIFF-ANCHOR: b2859f10 <action android:name="org.chromium.chrome.browser.ui.quickactionsearchwidget.START_TEXT_QUERY"/> </intent-filter> # DIFF-ANCHOR: b2859f10 + <intent-filter> # DIFF-ANCHOR: 22a1258b + <action android:name="org.chromium.chrome.browser.ui.quickactionsearchwidget.START_VOICE_QUERY"/> + </intent-filter> # DIFF-ANCHOR: 22a1258b </receiver> # DIFF-ANCHOR: 585b7cc1 <receiver # DIFF-ANCHOR: a0d83ae5 android:name="org.chromium.chrome.browser.searchwidget.SearchWidgetProvider"
diff --git a/chrome/android/features/keyboard_accessory/javatests/src/org/chromium/chrome/browser/keyboard_accessory/AutofillKeyboardAccessoryIntegrationTest.java b/chrome/android/features/keyboard_accessory/javatests/src/org/chromium/chrome/browser/keyboard_accessory/AutofillKeyboardAccessoryIntegrationTest.java index bb32fd5..9e8afba 100644 --- a/chrome/android/features/keyboard_accessory/javatests/src/org/chromium/chrome/browser/keyboard_accessory/AutofillKeyboardAccessoryIntegrationTest.java +++ b/chrome/android/features/keyboard_accessory/javatests/src/org/chromium/chrome/browser/keyboard_accessory/AutofillKeyboardAccessoryIntegrationTest.java
@@ -234,8 +234,12 @@ @Test @SmallTest + // clang-format off + @DisableIf.Build(hardware_is = "bullhead", sdk_is_greater_than = VERSION_CODES.LOLLIPOP_MR1, + sdk_is_less_than = VERSION_CODES.N, message = "https://crbug.com/1216008") public void testPressingBackButtonHidesAccessoryWithAutofillSuggestions() throws TimeoutException, ExecutionException { + // clang-format on loadTestPage(MultiWindowKeyboard::new); mHelper.clickNodeAndShowKeyboard("NAME_FIRST", 1); mHelper.waitForKeyboardAccessoryToBeShown(true); @@ -254,7 +258,11 @@ @Test @MediumTest + // clang-format off + @DisableIf.Build(hardware_is = "bullhead", sdk_is_greater_than = VERSION_CODES.LOLLIPOP_MR1, + sdk_is_less_than = VERSION_CODES.N, message = "https://crbug.com/1216008") public void testSheetHasMinimumSizeWhenTriggeredBySuggestion() throws TimeoutException { + // clang-format on MultiWindowUtils.getInstance().setIsInMultiWindowModeForTesting(true); loadTestPage(MultiWindowKeyboard::new); mHelper.clickNode("NAME_FIRST", 1, FocusedFieldType.FILLABLE_NON_SEARCH_FIELD);
diff --git a/chrome/android/features/keyboard_accessory/javatests/src/org/chromium/chrome/browser/keyboard_accessory/sheet_component/AccessorySheetRenderTest.java b/chrome/android/features/keyboard_accessory/javatests/src/org/chromium/chrome/browser/keyboard_accessory/sheet_component/AccessorySheetRenderTest.java index 9eda4b66..0689ad0 100644 --- a/chrome/android/features/keyboard_accessory/javatests/src/org/chromium/chrome/browser/keyboard_accessory/sheet_component/AccessorySheetRenderTest.java +++ b/chrome/android/features/keyboard_accessory/javatests/src/org/chromium/chrome/browser/keyboard_accessory/sheet_component/AccessorySheetRenderTest.java
@@ -38,7 +38,6 @@ import org.chromium.base.Callback; import org.chromium.base.FeatureList; -import org.chromium.base.test.BaseActivityTestRule; import org.chromium.base.test.params.ParameterAnnotations; import org.chromium.base.test.params.ParameterSet; import org.chromium.base.test.params.ParameterizedRunner; @@ -69,6 +68,7 @@ import org.chromium.ui.modelutil.PropertyModel; import org.chromium.ui.test.util.DummyUiActivity; import org.chromium.ui.test.util.NightModeTestUtils; +import org.chromium.ui.test.util.ThemedDummyUiActivityTestRule; import org.chromium.ui.test.util.ViewUtils; import java.io.IOException; @@ -95,8 +95,8 @@ // No @Rule since we only need the launching helpers. Adding the rule to the chain breaks with // any ParameterizedRunnerDelegate. - private BaseActivityTestRule<DummyUiActivity> mActivityTestRule = - new BaseActivityTestRule<>(DummyUiActivity.class); + private ThemedDummyUiActivityTestRule<DummyUiActivity> mActivityTestRule = + new ThemedDummyUiActivityTestRule<>(DummyUiActivity.class, R.style.ColorOverlay); @Rule public final ChromeRenderTestRule mRenderTestRule =
diff --git a/chrome/android/features/keyboard_accessory/javatests/src/org/chromium/chrome/browser/keyboard_accessory/tab_layout_component/KeyboardAccessoryTabLayoutViewTest.java b/chrome/android/features/keyboard_accessory/javatests/src/org/chromium/chrome/browser/keyboard_accessory/tab_layout_component/KeyboardAccessoryTabLayoutViewTest.java index 27624f9..f2a591b 100644 --- a/chrome/android/features/keyboard_accessory/javatests/src/org/chromium/chrome/browser/keyboard_accessory/tab_layout_component/KeyboardAccessoryTabLayoutViewTest.java +++ b/chrome/android/features/keyboard_accessory/javatests/src/org/chromium/chrome/browser/keyboard_accessory/tab_layout_component/KeyboardAccessoryTabLayoutViewTest.java
@@ -30,17 +30,17 @@ import org.chromium.chrome.browser.keyboard_accessory.R; import org.chromium.chrome.browser.keyboard_accessory.data.KeyboardAccessoryData; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; +import org.chromium.chrome.test.DummyUiChromeActivityTestCase; import org.chromium.ui.modelutil.ListModel; import org.chromium.ui.modelutil.PropertyModel; import org.chromium.ui.test.util.DummyUiActivity; -import org.chromium.ui.test.util.DummyUiActivityTestCase; /** * View tests for the keyboard accessory tab layout component. */ @RunWith(ChromeJUnit4ClassRunner.class) @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) -public class KeyboardAccessoryTabLayoutViewTest extends DummyUiActivityTestCase { +public class KeyboardAccessoryTabLayoutViewTest extends DummyUiChromeActivityTestCase { private PropertyModel mModel; private KeyboardAccessoryTabLayoutView mView;
diff --git a/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/FeedPlaceholderCoordinator.java b/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/FeedPlaceholderCoordinator.java index 26ada3f..dd136c0 100644 --- a/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/FeedPlaceholderCoordinator.java +++ b/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/FeedPlaceholderCoordinator.java
@@ -37,6 +37,14 @@ mParentView.addView(mFeedPlaceholderView); } + public void destroy() { + if (mFeedPlaceholderView != null) { + assert mParentView != null; + mParentView.removeView(mFeedPlaceholderView); + mFeedPlaceholderView = null; + } + } + void onOverviewShownAtLaunch(long activityCreationTimeMs) { long layoutInflationCompleteMs = mFeedPlaceholderView.getLayoutInflationCompleteMs(); assert layoutInflationCompleteMs >= activityCreationTimeMs;
diff --git a/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/StartSurfaceCoordinator.java b/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/StartSurfaceCoordinator.java index 4d150e7..7dceb536 100644 --- a/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/StartSurfaceCoordinator.java +++ b/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/StartSurfaceCoordinator.java
@@ -287,9 +287,9 @@ @Override public void destroy() { + onHide(); if (mTasksSurface != null) { mTasksSurface.removeFakeSearchBoxShrinkAnimation(); - mTasksSurface.onHide(); } if (mOffsetChangedListenerToGenerateScrollEvents != null) { removeHeaderOffsetChangeListener(mOffsetChangedListenerToGenerateScrollEvents); @@ -302,6 +302,10 @@ if (mTasksSurface != null) { mTasksSurface.onHide(); } + if (mFeedPlaceholderCoordinator != null) { + mFeedPlaceholderCoordinator.destroy(); + mFeedPlaceholderCoordinator = null; + } } @Override
diff --git a/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/BottomBarViewBinderTest.java b/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/BottomBarViewBinderTest.java index 8b92080..23bde0b 100644 --- a/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/BottomBarViewBinderTest.java +++ b/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/BottomBarViewBinderTest.java
@@ -28,16 +28,16 @@ import org.chromium.base.test.UiThreadTest; import org.chromium.chrome.start_surface.R; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; +import org.chromium.chrome.test.DummyUiChromeActivityTestCase; import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.ui.modelutil.PropertyModel; -import org.chromium.ui.test.util.DummyUiActivityTestCase; import java.util.concurrent.atomic.AtomicBoolean; /** Tests for {@link BottomBarViewBinder}. */ @SuppressWarnings("ConstantConditions") @RunWith(ChromeJUnit4ClassRunner.class) -public class BottomBarViewBinderTest extends DummyUiActivityTestCase { +public class BottomBarViewBinderTest extends DummyUiChromeActivityTestCase { @SuppressWarnings("unused") private BottomBarCoordinator mBottomBarCoordinator; private TabLayout mTabLayout;
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 4d15110..c57fd6bd 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
@@ -500,6 +500,52 @@ @Feature({"RenderTest"}) @Restriction({UiRestriction.RESTRICTION_TYPE_PHONE}) // clang-format off + @EnableFeatures({ChromeFeatureList.TAB_GROUPS_ANDROID, + ChromeFeatureList.TAB_SWITCHER_ON_RETURN + "<Study", + ChromeFeatureList.START_SURFACE_ANDROID + "<Study", + ChromeFeatureList.THEME_REFACTOR_ANDROID}) + @CommandLineFlags.Add({ChromeSwitches.DISABLE_NATIVE_INITIALIZATION, + "force-fieldtrials=Study/Group", + IMMEDIATE_RETURN_PARAMS + "/start_surface_variation/single"}) + @DisableIf.Build(message = "Flaky. See https://crbug.com/1091311", + sdk_is_greater_than = Build.VERSION_CODES.O) + public void renderTabGroups_ThemeRefactor() throws IOException { + // clang-format on + StartSurfaceTestUtils.createThumbnailBitmapAndWriteToFile(0); + StartSurfaceTestUtils.createThumbnailBitmapAndWriteToFile(1); + StartSurfaceTestUtils.createThumbnailBitmapAndWriteToFile(2); + StartSurfaceTestUtils.createThumbnailBitmapAndWriteToFile(3); + StartSurfaceTestUtils.createThumbnailBitmapAndWriteToFile(4); + StartSurfaceTestUtils.createThumbnailBitmapAndWriteToFile(5); + StartSurfaceTestUtils.createThumbnailBitmapAndWriteToFile(6); + TabAttributeCache.setRootIdForTesting(0, 0); + TabAttributeCache.setRootIdForTesting(1, 0); + TabAttributeCache.setRootIdForTesting(2, 0); + TabAttributeCache.setRootIdForTesting(3, 0); + TabAttributeCache.setRootIdForTesting(4, 0); + TabAttributeCache.setRootIdForTesting(5, 5); + TabAttributeCache.setRootIdForTesting(6, 5); + + // StartSurfaceTestUtils.createTabStateFile() has to be after setRootIdForTesting() to get + // root IDs. + StartSurfaceTestUtils.createTabStateFile(new int[] {0, 1, 2, 3, 4, 5, 6}); + + // Must be after StartSurfaceTestUtils.createTabStateFile() to read these files. + StartSurfaceTestUtils.startMainActivityFromLauncher(mActivityTestRule); + ChromeTabbedActivity cta = mActivityTestRule.getActivity(); + StartSurfaceTestUtils.waitForOverviewVisible(cta); + + RecyclerView recyclerView = cta.findViewById(R.id.tab_list_view); + CriteriaHelper.pollUiThread(() -> allCardsHaveThumbnail(recyclerView)); + mRenderTestRule.render( + cta.findViewById(R.id.tab_list_view), "tabSwitcher_tabGroups_theme_enforcement"); + } + + @Test + @SmallTest + @Feature({"RenderTest"}) + @Restriction({UiRestriction.RESTRICTION_TYPE_PHONE}) + // clang-format off @EnableFeatures({ChromeFeatureList.TAB_SWITCHER_ON_RETURN + "<Study,", ChromeFeatureList.START_SURFACE_ANDROID + "<Study"}) @CommandLineFlags.Add({ChromeSwitches.DISABLE_NATIVE_INITIALIZATION,
diff --git a/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/SecondaryTasksSurfaceViewBinderTest.java b/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/SecondaryTasksSurfaceViewBinderTest.java index 9553cb3..99cedcc 100644 --- a/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/SecondaryTasksSurfaceViewBinderTest.java +++ b/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/SecondaryTasksSurfaceViewBinderTest.java
@@ -25,14 +25,14 @@ import org.chromium.base.test.UiThreadTest; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; +import org.chromium.chrome.test.DummyUiChromeActivityTestCase; import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.ui.modelutil.PropertyModel; import org.chromium.ui.modelutil.PropertyModelChangeProcessor; -import org.chromium.ui.test.util.DummyUiActivityTestCase; /** Tests for {@link SecondaryTasksSurfaceViewBinder}. */ @RunWith(ChromeJUnit4ClassRunner.class) -public class SecondaryTasksSurfaceViewBinderTest extends DummyUiActivityTestCase { +public class SecondaryTasksSurfaceViewBinderTest extends DummyUiChromeActivityTestCase { private ViewGroup mParentView; private View mTasksSurfaceView; private View mTopToolbarPlaceholderView;
diff --git a/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/TasksSurfaceViewBinderTest.java b/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/TasksSurfaceViewBinderTest.java index cc31c10ff..f7bebd7 100644 --- a/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/TasksSurfaceViewBinderTest.java +++ b/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/TasksSurfaceViewBinderTest.java
@@ -25,14 +25,14 @@ import org.chromium.base.test.UiThreadTest; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; +import org.chromium.chrome.test.DummyUiChromeActivityTestCase; import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.ui.modelutil.PropertyModel; import org.chromium.ui.modelutil.PropertyModelChangeProcessor; -import org.chromium.ui.test.util.DummyUiActivityTestCase; /** Tests for {@link TasksSurfaceViewBinder}. */ @RunWith(ChromeJUnit4ClassRunner.class) -public class TasksSurfaceViewBinderTest extends DummyUiActivityTestCase { +public class TasksSurfaceViewBinderTest extends DummyUiChromeActivityTestCase { private ViewGroup mParentView; private ViewGroup mTasksSurfaceView; private View mTopToolbarPlaceholderView;
diff --git a/chrome/android/features/tab_ui/BUILD.gn b/chrome/android/features/tab_ui/BUILD.gn index da41bb9..277f948 100644 --- a/chrome/android/features/tab_ui/BUILD.gn +++ b/chrome/android/features/tab_ui/BUILD.gn
@@ -51,6 +51,7 @@ "java/res/drawable/selected_tab_background.xml", "java/res/drawable/selected_tab_background_incognito.xml", "java/res/drawable/single_tab_background.xml", + "java/res/drawable/tab_grid_card_background.xml", "java/res/drawable/tab_grid_dialog_background.xml", "java/res/drawable/tab_grid_dialog_background_incognito.xml", "java/res/drawable/tab_grid_selection_list_icon.xml",
diff --git a/chrome/android/features/tab_ui/java/res/drawable/tab_grid_card_background.xml b/chrome/android/features/tab_ui/java/res/drawable/tab_grid_card_background.xml new file mode 100644 index 0000000..94fb437 --- /dev/null +++ b/chrome/android/features/tab_ui/java/res/drawable/tab_grid_card_background.xml
@@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright 2021 The Chromium Authors. All rights reserved. + Use of this source code is governed by a BSD-style license that can be + found in the LICENSE file. --> + +<shape xmlns:android="http://schemas.android.com/apk/res/android"> + <solid android:color="@color/tab_grid_dialog_background_color"/> + <corners android:radius="@dimen/tab_grid_card_bg_radius" /> +</shape> \ No newline at end of file
diff --git a/chrome/android/features/tab_ui/java/res/layout/tab_grid_card_item.xml b/chrome/android/features/tab_ui/java/res/layout/tab_grid_card_item.xml index 5f3aaa3b3..bf221c5 100644 --- a/chrome/android/features/tab_ui/java/res/layout/tab_grid_card_item.xml +++ b/chrome/android/features/tab_ui/java/res/layout/tab_grid_card_item.xml
@@ -29,16 +29,14 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:layout_gravity="center" - android:background="@drawable/popup_bg_tinted" - android:layout_margin="2dp"> + android:background="?attr/tabGridBackground" + android:layout_margin="?attr/tabGridMargin"> <ImageView android:id="@+id/tab_favicon" - android:layout_width="wrap_content" - android:layout_height="@dimen/tab_list_card_title_height" - android:minWidth="8dp" android:adjustViewBounds="true" android:importantForAccessibility="no" - app:srcCompat="@drawable/ic_globe_24dp"/> + app:srcCompat="@drawable/ic_globe_24dp" + style="?attr/tabGridFaviconStyle"/> <TextView android:id="@+id/tab_title" android:layout_width="match_parent" @@ -46,7 +44,7 @@ android:layout_toEndOf="@id/tab_favicon" android:layout_marginEnd="32dp" android:gravity="center_vertical" - android:minHeight="@dimen/tab_list_card_title_height" + android:minHeight="?attr/tabGridHeaderHeight" android:requiresFadingEdge="horizontal" android:fadingEdgeLength="24dp" android:ellipsize="none" @@ -62,8 +60,7 @@ android:scaleType="fitCenter" android:importantForAccessibility="no" android:src="@color/thumbnail_placeholder_on_primary_bg" - app:cornerRadiusBottomStart="@dimen/tab_list_card_radius" - app:cornerRadiusBottomEnd="@dimen/tab_list_card_radius"/> + style="?attr/tabGridThumbnailStyle"/> <org.chromium.chrome.browser.tasks.tab_management.PriceCardView android:id="@+id/price_info_box_outer" android:layout_below="@id/tab_title" @@ -83,7 +80,7 @@ android:id="@+id/divider_view" style="@style/HorizontalDivider" android:layout_below="@id/tab_title" - android:visibility="?attr/tabDividerVisible" + android:visibility="?attr/tabGridDividerVisible" android:background="@color/divider_line_bg_color"/> <org.chromium.ui.widget.ButtonCompat android:id="@+id/create_group_button" @@ -110,10 +107,9 @@ </RelativeLayout> <org.chromium.ui.widget.ChromeImageView android:id="@+id/action_button" - android:layout_width="48dp" - android:layout_height="48dp" android:scaleType="center" android:layout_gravity="end" - android:tint="@color/default_icon_color"/> + android:tint="@color/default_icon_color" + style="?attr/tabGridActionButtonStyle"/> </FrameLayout> </merge>
diff --git a/chrome/android/features/tab_ui/java/res/values/attrs.xml b/chrome/android/features/tab_ui/java/res/values/attrs.xml index 4ff6f057..6a92f634 100644 --- a/chrome/android/features/tab_ui/java/res/values/attrs.xml +++ b/chrome/android/features/tab_ui/java/res/values/attrs.xml
@@ -11,5 +11,12 @@ </declare-styleable> <!-- Tab grid cards attributes --> - <attr name="tabDividerVisible" format="integer" /> -</resources> \ No newline at end of file + <attr name="tabGridDividerVisible" format="integer" /> + <attr name="tabGridBackground" format="reference" /> + <attr name="tabGridMargin" format="dimension" /> + <attr name="tabGridHeaderHeight" format="dimension" /> + <attr name="tabGridTitleFadingLength" format="dimension" /> + <attr name="tabGridFaviconStyle" format="reference" /> + <attr name="tabGridThumbnailStyle" format="reference" /> + <attr name="tabGridActionButtonStyle" format="reference" /> +</resources>
diff --git a/chrome/android/features/tab_ui/java/res/values/dimens.xml b/chrome/android/features/tab_ui/java/res/values/dimens.xml index 21713600..30ac6103 100644 --- a/chrome/android/features/tab_ui/java/res/values/dimens.xml +++ b/chrome/android/features/tab_ui/java/res/values/dimens.xml
@@ -47,6 +47,19 @@ <dimen name="price_tracking_dialog_items_margin">20dp</dimen> <dimen name="price_tracking_dialog_items_bottom_margin">34dp</dimen> + <!-- Dimens for theme refactor 2021 --> + <dimen name="tab_grid_card_bg_radius">16dp</dimen> + <dimen name="tab_grid_card_favicon_padding">11dp</dimen> + <dimen name="tab_grid_card_header_height">40dp</dimen> + <dimen name="tab_grid_card_margin">8dp</dimen> + <dimen name="tab_grid_card_title_fading_length">20dp</dimen> + <dimen name="tab_grid_card_thumbnail_corner_radius_top">4dp</dimen> + <dimen name="tab_grid_card_thumbnail_corner_radius_bottom">12dp</dimen> + <dimen name="tab_grid_card_thumbnail_margin">4dp</dimen> + <dimen name="tab_list_card_margin">2dp</dimen> + <dimen name="tab_list_card_action_button_size">48dp</dimen> + <dimen name="tab_list_card_title_fading_length">24dp</dimen> + <!-- Elevation --> <dimen name="tab_bg_elevation">@dimen/default_elevation_4</dimen>
diff --git a/chrome/android/features/tab_ui/java/res/values/styles.xml b/chrome/android/features/tab_ui/java/res/values/styles.xml index 6d0c8a9..0b77b3f 100644 --- a/chrome/android/features/tab_ui/java/res/values/styles.xml +++ b/chrome/android/features/tab_ui/java/res/values/styles.xml
@@ -17,12 +17,66 @@ <integer name="view_gone">2</integer> <!-- This is GONE --> <!-- Theme overlay for theme refactor 2021 --> + <style name="TabGridCardTopFaviconStyle"> + <item name="android:minWidth">@dimen/tab_list_card_padding</item> + <item name="android:layout_height">?attr/tabGridHeaderHeight</item> + <item name="android:layout_width">wrap_content</item> + </style> + + <style name="TabGridCardTopFaviconStyle.ThemeRefactor"> + <item name="android:minWidth">@dimen/tab_grid_card_favicon_padding</item> + </style> + + <style name="TabGridCardActionButtonStyle"> + <item name="android:layout_width">@dimen/tab_list_card_action_button_size</item> + <item name="android:layout_height">@dimen/tab_list_card_action_button_size</item> + </style> + + <style name="TabGridCardActionButtonStyle.ThemeRefactor"> + <item name="android:layout_width">@dimen/tab_grid_card_header_height</item> + <item name="android:layout_height">@dimen/tab_grid_card_header_height</item> + <item name="android:layout_margin">@dimen/tab_grid_card_margin</item> + </style> + + <style name="TabGridCardThumbnailStyle"> + <item name="cornerRadiusTopStart">0dp</item> + <item name="cornerRadiusTopEnd">0dp</item> + <item name="cornerRadiusBottomStart">@dimen/tab_list_card_radius</item> + <item name="cornerRadiusBottomEnd">@dimen/tab_list_card_radius</item> + </style> + + <style name="TabGridCardThumbnailStyle.ThemeRefactor"> + <item name="android:layout_marginLeft">@dimen/tab_grid_card_thumbnail_margin</item> + <item name="android:layout_marginRight">@dimen/tab_grid_card_thumbnail_margin</item> + <item name="android:layout_marginBottom">@dimen/tab_grid_card_thumbnail_margin</item> + <item name="cornerRadiusTopStart">@dimen/tab_grid_card_thumbnail_corner_radius_top</item> + <item name="cornerRadiusTopEnd">@dimen/tab_grid_card_thumbnail_corner_radius_top</item> + <item name="cornerRadiusBottomStart">@dimen/tab_grid_card_thumbnail_corner_radius_bottom</item> + <item name="cornerRadiusBottomEnd">@dimen/tab_grid_card_thumbnail_corner_radius_bottom</item> + </style> + <style name="ThemeRefactorOverlay.Disabled.TabUi" parent=""> - <item name="tabDividerVisible">@integer/view_visible</item> + <item name="tabGridDividerVisible">@integer/view_visible</item> + <item name="tabGridHeaderHeight">@dimen/tab_list_card_title_height</item> + <item name="tabGridBackground">@drawable/popup_bg_tinted</item> + <item name="tabGridMargin">@dimen/tab_list_card_margin</item> + <item name="tabGridTitleFadingLength">@dimen/tab_list_card_title_fading_length</item> + + <item name="tabGridFaviconStyle">@style/TabGridCardTopFaviconStyle</item> + <item name="tabGridActionButtonStyle">@style/TabGridCardActionButtonStyle</item> + <item name="tabGridThumbnailStyle">@style/TabGridCardThumbnailStyle</item> </style> <style name="ThemeRefactorOverlay.Enabled.TabUi" parent=""> - <item name="tabDividerVisible">@integer/view_gone</item> + <item name="tabGridDividerVisible">@integer/view_gone</item> + <item name="tabGridHeaderHeight">@dimen/tab_grid_card_header_height</item> + <item name="tabGridBackground">@drawable/tab_grid_card_background</item> + <item name="tabGridMargin">@dimen/tab_grid_card_margin</item> + <item name="tabGridTitleFadingLength">@dimen/tab_grid_card_title_fading_length</item> + + <item name="tabGridFaviconStyle">@style/TabGridCardTopFaviconStyle.ThemeRefactor</item> + <item name="tabGridActionButtonStyle">@style/TabGridCardActionButtonStyle.ThemeRefactor</item> + <item name="tabGridThumbnailStyle">@style/TabGridCardThumbnailStyle.ThemeRefactor</item> </style> <style name="TabThumbnailPlaceHolderStyle">
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/MultiThumbnailCardProvider.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/MultiThumbnailCardProvider.java index dd0ea14..f37d028 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/MultiThumbnailCardProvider.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/MultiThumbnailCardProvider.java
@@ -276,32 +276,13 @@ resource.getDimension(R.dimen.tab_grid_thumbnail_favicon_background_down_shift), resource.getColor(R.color.modern_grey_800_alpha_38)); - // Initialize Rects for thumbnails. - float thumbnailHorizontalPadding = resource.getDimension(R.dimen.tab_list_card_padding); - float thumbnailVerticalPadding = thumbnailHorizontalPadding / expectedThumbnailAspectRatio; - float thumbnailFaviconPaddingFromBackground = - resource.getDimension(R.dimen.tab_grid_thumbnail_favicon_padding_from_frame); - float centerX = mThumbnailWidth * 0.5f; - float centerY = mThumbnailHeight * 0.5f; - float halfThumbnailHorizontalPadding = thumbnailHorizontalPadding / 2; - float halfThumbnailVerticalPadding = thumbnailVerticalPadding / 2; - - mThumbnailRects.add(new RectF(thumbnailHorizontalPadding, thumbnailVerticalPadding, - centerX - halfThumbnailHorizontalPadding, centerY - halfThumbnailVerticalPadding)); - mThumbnailRects.add(new RectF(centerX + halfThumbnailHorizontalPadding, - thumbnailVerticalPadding, mThumbnailWidth - thumbnailHorizontalPadding, - centerY - halfThumbnailVerticalPadding)); - mThumbnailRects.add(new RectF(thumbnailHorizontalPadding, - centerY + halfThumbnailVerticalPadding, centerX - halfThumbnailHorizontalPadding, - mThumbnailHeight - thumbnailVerticalPadding)); - mThumbnailRects.add(new RectF(centerX + halfThumbnailHorizontalPadding, - centerY + halfThumbnailVerticalPadding, - mThumbnailWidth - thumbnailHorizontalPadding, - mThumbnailHeight - thumbnailVerticalPadding)); + initializedThumbnailRects(resource, expectedThumbnailAspectRatio); // Initialize Rects for favicons and favicon frame. final float halfFaviconFrameSize = resource.getDimension(R.dimen.tab_grid_thumbnail_favicon_frame_size) / 2f; + float thumbnailFaviconPaddingFromBackground = + resource.getDimension(R.dimen.tab_grid_thumbnail_favicon_padding_from_frame); for (int i = 0; i < 4; i++) { RectF thumbnailRect = mThumbnailRects.get(i); @@ -357,6 +338,43 @@ mTabModelSelector.removeObserver(mTabModelSelectorObserver); } + /** + * Initialize rects used for thumbnails. Depending on whether thene refacotr is enabled, the + * padding around the thumbnail is different. + */ + private void initializedThumbnailRects(Resources resource, float expectedThumbnailAspectRatio) { + boolean themeRefactorEnabled = TabUiThemeProvider.themeRefactorEnabled(); + + float thumbnailHorizontalPadding = themeRefactorEnabled + ? resource.getDimension(R.dimen.tab_grid_card_thumbnail_margin) + : resource.getDimension(R.dimen.tab_list_card_padding); + float thumbnailVerticalPadding = themeRefactorEnabled + ? thumbnailHorizontalPadding + : thumbnailHorizontalPadding / expectedThumbnailAspectRatio; + float multiThumbnailHorizontalPadding = + themeRefactorEnabled ? 0 : thumbnailHorizontalPadding; + float multiThumbnailVerticalPadding = themeRefactorEnabled ? 0 : thumbnailVerticalPadding; + + float centerX = mThumbnailWidth * 0.5f; + float centerY = mThumbnailHeight * 0.5f; + float halfThumbnailHorizontalPadding = thumbnailHorizontalPadding / 2; + float halfThumbnailVerticalPadding = thumbnailVerticalPadding / 2; + + mThumbnailRects.add(new RectF(multiThumbnailHorizontalPadding, + multiThumbnailVerticalPadding, centerX - halfThumbnailHorizontalPadding, + centerY - halfThumbnailVerticalPadding)); + mThumbnailRects.add(new RectF(centerX + halfThumbnailHorizontalPadding, + multiThumbnailVerticalPadding, mThumbnailWidth - multiThumbnailHorizontalPadding, + centerY - halfThumbnailVerticalPadding)); + mThumbnailRects.add(new RectF(multiThumbnailHorizontalPadding, + centerY + halfThumbnailVerticalPadding, centerX - halfThumbnailHorizontalPadding, + mThumbnailHeight - multiThumbnailVerticalPadding)); + mThumbnailRects.add(new RectF(centerX + halfThumbnailHorizontalPadding, + centerY + halfThumbnailVerticalPadding, + mThumbnailWidth - multiThumbnailHorizontalPadding, + mThumbnailHeight - multiThumbnailVerticalPadding)); + } + @Override public void getTabThumbnailWithCallback( int tabId, Callback<Bitmap> finalCallback, boolean forceUpdate, boolean writeToCache) {
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridViewBinder.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridViewBinder.java index 8dac4fb..9d158fc 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridViewBinder.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridViewBinder.java
@@ -28,8 +28,6 @@ import org.chromium.base.ApiCompatibilityUtils; import org.chromium.base.Callback; import org.chromium.base.MathUtils; -import org.chromium.chrome.browser.flags.CachedFeatureFlags; -import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.tab_ui.R; import org.chromium.ui.modelutil.PropertyKey; import org.chromium.ui.modelutil.PropertyModel; @@ -111,7 +109,7 @@ tabTitleView.setContentDescription( view.getResources().getString(R.string.accessibility_tabstrip_tab, title)); } else if (TabProperties.IS_SELECTED == propertyKey) { - if (CachedFeatureFlags.isEnabled(ChromeFeatureList.THEME_REFACTOR_ANDROID)) { + if (TabUiThemeProvider.themeRefactorEnabled()) { updateColor(view, model.get(TabProperties.IS_INCOGNITO), model.get(TabProperties.IS_SELECTED)); updateThumbnail(view, model); @@ -152,7 +150,7 @@ faviconView.setImageDrawable(favicon); int padding = favicon == null ? 0 - : (int) view.getResources().getDimension(R.dimen.tab_list_card_padding); + : (int) TabUiThemeProvider.getTabCardTopFaviconPadding(view.getContext()); faviconView.setPadding(padding, padding, padding, padding); } else if (TabProperties.THUMBNAIL_FETCHER == propertyKey) { updateThumbnail(view, model); @@ -417,7 +415,7 @@ if (thumbnail.getDrawable() == null) { thumbnail.setImageResource( TabUiThemeProvider.getThumbnailPlaceHolderColorResource(isIncognito)); - if (CachedFeatureFlags.isEnabled(ChromeFeatureList.THEME_REFACTOR_ANDROID)) { + if (TabUiThemeProvider.themeRefactorEnabled()) { thumbnail.setImageTintList( ColorStateList.valueOf(TabUiThemeProvider.getMiniThumbnailPlaceHolderColor( backgroundView.getContext(), isIncognito, isSelected)));
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabUiThemeProvider.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabUiThemeProvider.java index 4722d22..6886c6e 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabUiThemeProvider.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabUiThemeProvider.java
@@ -341,6 +341,17 @@ } /** + * Return the padding around favicon if it is visible. + * @param context {@link Context} used to retrieve dimension. + * @return The padding space around favicon. + */ + public static float getTabCardTopFaviconPadding(Context context) { + return context.getResources().getDimension(themeRefactorEnabled() + ? R.dimen.tab_grid_card_favicon_padding + : R.dimen.tab_list_card_padding); + } + + /** * Returns the style resource Id that requires for Tab UI. * * @return The resource Id for the theme overlay used for tab UI. @@ -351,7 +362,8 @@ : R.style.ThemeRefactorOverlay_Disabled_TabUi; } - private static boolean themeRefactorEnabled() { + /** Return if theme refactor is enabled. **/ + static boolean themeRefactorEnabled() { return CachedFeatureFlags.isEnabled(ChromeFeatureList.THEME_REFACTOR_ANDROID); } }
diff --git a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/SingleTabViewBinderTest.java b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/SingleTabViewBinderTest.java index 92ccddd..5d3fc86c 100644 --- a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/SingleTabViewBinderTest.java +++ b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/SingleTabViewBinderTest.java
@@ -32,14 +32,14 @@ import org.chromium.base.test.UiThreadTest; import org.chromium.chrome.tab_ui.R; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; +import org.chromium.chrome.test.DummyUiChromeActivityTestCase; import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.ui.modelutil.PropertyModel; import org.chromium.ui.modelutil.PropertyModelChangeProcessor; -import org.chromium.ui.test.util.DummyUiActivityTestCase; /** Tests for {@link SingleTabViewBinder}. */ @RunWith(ChromeJUnit4ClassRunner.class) -public class SingleTabViewBinderTest extends DummyUiActivityTestCase { +public class SingleTabViewBinderTest extends DummyUiChromeActivityTestCase { private SingleTabView mSingleTabView; private PropertyModelChangeProcessor mPropertyModelChangeProcessor; private PropertyModel mPropertyModel;
diff --git a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/TasksViewBinderTest.java b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/TasksViewBinderTest.java index deb02ea2..ddf5c2b8 100644 --- a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/TasksViewBinderTest.java +++ b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/TasksViewBinderTest.java
@@ -61,17 +61,17 @@ import org.chromium.chrome.browser.ntp.IncognitoCookieControlsManager; import org.chromium.chrome.tab_ui.R; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; +import org.chromium.chrome.test.DummyUiChromeActivityTestCase; import org.chromium.components.browser_ui.styles.ChromeColors; import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.ui.modelutil.PropertyModel; import org.chromium.ui.modelutil.PropertyModelChangeProcessor; -import org.chromium.ui.test.util.DummyUiActivityTestCase; import java.util.concurrent.atomic.AtomicBoolean; /** Tests for {@link TasksViewBinder}. */ @RunWith(ChromeJUnit4ClassRunner.class) -public class TasksViewBinderTest extends DummyUiActivityTestCase { +public class TasksViewBinderTest extends DummyUiChromeActivityTestCase { private TasksView mTasksView; private PropertyModel mTasksViewPropertyModel; private AtomicBoolean mViewClicked = new AtomicBoolean();
diff --git a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/LargeMessageCardViewBinderTest.java b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/LargeMessageCardViewBinderTest.java index 4d650e5..089661df 100644 --- a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/LargeMessageCardViewBinderTest.java +++ b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/LargeMessageCardViewBinderTest.java
@@ -25,10 +25,10 @@ import org.chromium.chrome.browser.tab.state.ShoppingPersistedTabData; import org.chromium.chrome.tab_ui.R; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; +import org.chromium.chrome.test.DummyUiChromeActivityTestCase; import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.ui.modelutil.PropertyModel; import org.chromium.ui.modelutil.PropertyModelChangeProcessor; -import org.chromium.ui.test.util.DummyUiActivityTestCase; import org.chromium.ui.widget.ButtonCompat; import org.chromium.ui.widget.ChromeImageView; @@ -38,7 +38,7 @@ * Tests for {@link LargeMessageCardViewBinder}. */ @RunWith(ChromeJUnit4ClassRunner.class) -public class LargeMessageCardViewBinderTest extends DummyUiActivityTestCase { +public class LargeMessageCardViewBinderTest extends DummyUiChromeActivityTestCase { private static final String TITLE_TEXT = "titleText"; private static final String ACTION_TEXT = "actionText"; private static final String DESCRIPTION_TEXT = "descriptionText";
diff --git a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/MessageCardProviderTest.java b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/MessageCardProviderTest.java index 99aba01..e305160 100644 --- a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/MessageCardProviderTest.java +++ b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/MessageCardProviderTest.java
@@ -31,12 +31,12 @@ import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.tasks.tab_management.suggestions.TabSuggestion; import org.chromium.chrome.tab_ui.R; +import org.chromium.chrome.test.DummyUiChromeActivityTestCase; import org.chromium.chrome.test.util.browser.Features; import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.ui.modelutil.LayoutViewBuilder; import org.chromium.ui.modelutil.MVCListAdapter; import org.chromium.ui.modelutil.SimpleRecyclerViewAdapter; -import org.chromium.ui.test.util.DummyUiActivityTestCase; import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; @@ -45,7 +45,7 @@ * Integration tests for MessageCardProvider component. */ @Features.DisableFeatures(ChromeFeatureList.TAB_TO_GTS_ANIMATION) -public class MessageCardProviderTest extends DummyUiActivityTestCase { +public class MessageCardProviderTest extends DummyUiChromeActivityTestCase { private static final int SUGGESTED_TAB_COUNT = 2; @Rule
diff --git a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/MessageCardViewBinderTest.java b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/MessageCardViewBinderTest.java index 5b1c1bd..5f1ade9 100644 --- a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/MessageCardViewBinderTest.java +++ b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/MessageCardViewBinderTest.java
@@ -24,10 +24,10 @@ import org.chromium.base.test.UiThreadTest; import org.chromium.chrome.tab_ui.R; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; +import org.chromium.chrome.test.DummyUiChromeActivityTestCase; import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.ui.modelutil.PropertyModel; import org.chromium.ui.modelutil.PropertyModelChangeProcessor; -import org.chromium.ui.test.util.DummyUiActivityTestCase; import java.util.concurrent.atomic.AtomicBoolean; @@ -35,7 +35,7 @@ * Tests for {@link MessageCardViewBinder}. */ @RunWith(ChromeJUnit4ClassRunner.class) -public class MessageCardViewBinderTest extends DummyUiActivityTestCase { +public class MessageCardViewBinderTest extends DummyUiChromeActivityTestCase { private static final String ACTION_TEXT = "actionText"; private static final String DESCRIPTION_TEXT = "descriptionText"; private static final String DISMISS_BUTTON_CONTENT_DESCRIPTION = "dismiss";
diff --git a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogViewTest.java b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogViewTest.java index 5f8ee309..2e72177 100644 --- a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogViewTest.java +++ b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogViewTest.java
@@ -29,9 +29,9 @@ import org.chromium.base.test.util.CriteriaHelper; import org.chromium.chrome.tab_ui.R; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; +import org.chromium.chrome.test.DummyUiChromeActivityTestCase; import org.chromium.components.browser_ui.widget.scrim.ScrimCoordinator; import org.chromium.content_public.browser.test.util.TestThreadUtils; -import org.chromium.ui.test.util.DummyUiActivityTestCase; import java.util.concurrent.atomic.AtomicReference; @@ -39,7 +39,7 @@ * DummyUiActivity Tests for the {@link TabGridDialogView}. */ @RunWith(ChromeJUnit4ClassRunner.class) -public class TabGridDialogViewTest extends DummyUiActivityTestCase { +public class TabGridDialogViewTest extends DummyUiChromeActivityTestCase { private int mToolbarHeight; private int mTopMargin; private int mSideMargin;
diff --git a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridPanelViewBinderTest.java b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridPanelViewBinderTest.java index 207844f8..4346afa 100644 --- a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridPanelViewBinderTest.java +++ b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridPanelViewBinderTest.java
@@ -34,11 +34,11 @@ import org.chromium.chrome.browser.theme.ThemeUtils; import org.chromium.chrome.tab_ui.R; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; +import org.chromium.chrome.test.DummyUiChromeActivityTestCase; import org.chromium.components.browser_ui.widget.scrim.ScrimCoordinator; import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.ui.modelutil.PropertyModel; import org.chromium.ui.modelutil.PropertyModelChangeProcessor; -import org.chromium.ui.test.util.DummyUiActivityTestCase; import org.chromium.ui.widget.ChromeImageView; import java.util.concurrent.atomic.AtomicBoolean; @@ -47,7 +47,7 @@ * Tests for {@link TabGridPanelViewBinder}. */ @RunWith(ChromeJUnit4ClassRunner.class) -public class TabGridPanelViewBinderTest extends DummyUiActivityTestCase { +public class TabGridPanelViewBinderTest extends DummyUiChromeActivityTestCase { private static final int CONTENT_TOP_MARGIN = 56; private PropertyModel mModel; private PropertyModelChangeProcessor mMCP;
diff --git a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiViewBinderTest.java b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiViewBinderTest.java index 1509f39b..a956340 100644 --- a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiViewBinderTest.java +++ b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiViewBinderTest.java
@@ -31,9 +31,9 @@ import org.chromium.chrome.browser.theme.ThemeUtils; import org.chromium.chrome.tab_ui.R; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; +import org.chromium.chrome.test.DummyUiChromeActivityTestCase; import org.chromium.ui.modelutil.PropertyModel; import org.chromium.ui.modelutil.PropertyModelChangeProcessor; -import org.chromium.ui.test.util.DummyUiActivityTestCase; import java.util.concurrent.atomic.AtomicBoolean; @@ -41,7 +41,7 @@ * Tests for {@link TabGroupUiViewBinder}. */ @RunWith(ChromeJUnit4ClassRunner.class) -public class TabGroupUiViewBinderTest extends DummyUiActivityTestCase { +public class TabGroupUiViewBinderTest extends DummyUiChromeActivityTestCase { private ImageView mLeftButton; private ImageView mRightButton; private ViewGroup mContainerView;
diff --git a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabListContainerViewBinderTest.java b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabListContainerViewBinderTest.java index a59a2fb..8a347a5 100644 --- a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabListContainerViewBinderTest.java +++ b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabListContainerViewBinderTest.java
@@ -6,8 +6,8 @@ import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.instanceOf; -import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThat; import static org.chromium.chrome.browser.tasks.tab_management.TabUiTestHelper.areAnimatorsEnabled; @@ -37,19 +37,19 @@ import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.tab_ui.R; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; +import org.chromium.chrome.test.DummyUiChromeActivityTestCase; import org.chromium.chrome.test.util.browser.Features; import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.ui.modelutil.PropertyModel; import org.chromium.ui.modelutil.PropertyModelChangeProcessor; import org.chromium.ui.test.util.DummyUiActivity; -import org.chromium.ui.test.util.DummyUiActivityTestCase; /** * Tests for {@link TabListRecyclerView} and {@link TabListContainerViewBinder} */ @RunWith(ChromeJUnit4ClassRunner.class) @Features.EnableFeatures({ChromeFeatureList.TAB_GRID_LAYOUT_ANDROID}) -public class TabListContainerViewBinderTest extends DummyUiActivityTestCase { +public class TabListContainerViewBinderTest extends DummyUiChromeActivityTestCase { /** * DummyUiActivityTestCase also needs {@link ChromeFeatureList}'s * internal test-only feature map, not the {@link CommandLine} provided by
diff --git a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabListViewHolderTest.java b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabListViewHolderTest.java index 2049fe75..fb163dc 100644 --- a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabListViewHolderTest.java +++ b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabListViewHolderTest.java
@@ -67,6 +67,7 @@ import org.chromium.chrome.browser.tab.state.ShoppingPersistedTabData; import org.chromium.chrome.tab_ui.R; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; +import org.chromium.chrome.test.DummyUiChromeActivityTestCase; import org.chromium.components.browser_ui.widget.selectable_list.SelectionDelegate; import org.chromium.components.embedder_support.browser_context.BrowserContextHandle; import org.chromium.components.embedder_support.util.UrlUtilities; @@ -78,7 +79,6 @@ import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.ui.modelutil.PropertyModel; import org.chromium.ui.modelutil.PropertyModelChangeProcessor; -import org.chromium.ui.test.util.DummyUiActivityTestCase; import org.chromium.ui.widget.ButtonCompat; import org.chromium.ui.widget.ChipView; import org.chromium.ui.widget.ChromeImageView; @@ -96,7 +96,7 @@ @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE, "enable-features=" + ChromeFeatureList.COMMERCE_PRICE_TRACKING + "<Study", "force-fieldtrials=Study/Group"}) -public class TabListViewHolderTest extends DummyUiActivityTestCase { +public class TabListViewHolderTest extends DummyUiChromeActivityTestCase { @Rule public JniMocker mMocker = new JniMocker();
diff --git a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSelectionEditorLayoutBinderTest.java b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSelectionEditorLayoutBinderTest.java index ab7d66a..2ad56927 100644 --- a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSelectionEditorLayoutBinderTest.java +++ b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSelectionEditorLayoutBinderTest.java
@@ -27,11 +27,11 @@ import org.chromium.base.test.UiThreadTest; import org.chromium.chrome.tab_ui.R; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; +import org.chromium.chrome.test.DummyUiChromeActivityTestCase; import org.chromium.components.browser_ui.widget.selectable_list.SelectionDelegate; import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.ui.modelutil.PropertyModel; import org.chromium.ui.modelutil.PropertyModelChangeProcessor; -import org.chromium.ui.test.util.DummyUiActivityTestCase; import java.util.Arrays; import java.util.HashSet; @@ -42,7 +42,7 @@ */ @SuppressWarnings("ArraysAsListWithZeroOrOneArgument") @RunWith(ChromeJUnit4ClassRunner.class) -public class TabSelectionEditorLayoutBinderTest extends DummyUiActivityTestCase { +public class TabSelectionEditorLayoutBinderTest extends DummyUiChromeActivityTestCase { private TabSelectionEditorLayout mEditorLayoutView; private PropertyModel mModel = new PropertyModel(TabSelectionEditorProperties.ALL_KEYS); private PropertyModelChangeProcessor mMCP;
diff --git a/chrome/android/java/AndroidManifest.xml b/chrome/android/java/AndroidManifest.xml index 840f741..99edfde 100644 --- a/chrome/android/java/AndroidManifest.xml +++ b/chrome/android/java/AndroidManifest.xml
@@ -945,6 +945,9 @@ <action android:name="org.chromium.chrome.browser.ui.quickactionsearchwidget.START_TEXT_QUERY" /> </intent-filter> <intent-filter> + <action android:name="org.chromium.chrome.browser.ui.quickactionsearchwidget.START_VOICE_QUERY" /> + </intent-filter> + <intent-filter> <action android:name="org.chromium.chrome.browser.ui.quickactionsearchwidget.START_DINO_GAME" /> </intent-filter> </receiver>
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeBaseAppCompatActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeBaseAppCompatActivity.java index 5e86507..1ed65945 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeBaseAppCompatActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeBaseAppCompatActivity.java
@@ -30,13 +30,14 @@ import org.chromium.chrome.browser.night_mode.NightModeUtils; import org.chromium.chrome.browser.ui.theme.ColorDelegateImpl; import org.chromium.ui.modaldialog.ModalDialogManager; +import org.chromium.ui.modaldialog.ModalDialogManagerHolder; /** * A subclass of {@link AppCompatActivity} that maintains states and objects applied to all * activities in {@link ChromeApplication} (e.g. night mode). */ -public class ChromeBaseAppCompatActivity - extends AppCompatActivity implements NightModeStateProvider.Observer { +public class ChromeBaseAppCompatActivity extends AppCompatActivity + implements NightModeStateProvider.Observer, ModalDialogManagerHolder { private final ObservableSupplierImpl<ModalDialogManager> mModalDialogManagerSupplier = new ObservableSupplierImpl<>(); private NightModeStateProvider mNightModeStateProvider; @@ -103,6 +104,17 @@ this, mNightModeStateProvider.isInNightMode(), newConfig, mThemeResId); } + // Implementation of ModalDialogManagerHolder + /** + * @return The {@link ModalDialogManager} that manages the display of modal dialogs (e.g. + * JavaScript dialogs). + */ + @Override + public ModalDialogManager getModalDialogManager() { + // TODO(jinsukkim): Remove this method in favor of getModalDialogManagerSupplier(). + return getModalDialogManagerSupplier().get(); + } + /** * Returns the supplier of {@link ModalDialogManager} that manages the display of modal dialogs. */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/app/flags/ChromeCachedFlags.java b/chrome/android/java/src/org/chromium/chrome/browser/app/flags/ChromeCachedFlags.java index 61a13b9..1586e50 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/app/flags/ChromeCachedFlags.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/app/flags/ChromeCachedFlags.java
@@ -119,8 +119,9 @@ add(LensFeature.DISABLE_LENS_CAMERA_ASSISTED_SEARCH_ON_INCOGNITO); add(LensFeature.ENABLE_LENS_CAMERA_ASSISTED_SEARCH_ON_LOW_END_DEVICE); add(LensFeature.ENABLE_LENS_CAMERA_ASSISTED_SEARCH_ON_TABLET); - add(LensFeature.SEARCH_BOX_START_VARIANT_LENS_CAMERA_ASSISTED_SEARCH); add(LensFeature.MIN_AGSA_VERSION_LENS_CAMERA_ASSISTED_SEARCH); + add(LensFeature.SEARCH_BOX_START_VARIANT_LENS_CAMERA_ASSISTED_SEARCH); + add(LensFeature.SKIP_AGSA_VERSION_CHECK); add(MerchantViewerConfig.DEFAULT_TRUST_SIGNALS_MESSAGE_DELAY); add(MerchantViewerConfig.TRUST_SIGNALS_MESSAGE_USE_RATING_BAR); add(MerchantViewerConfig.TRUST_SIGNALS_MESSAGE_WINDOW_DURATION_SECONDS);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunActivity.java index 2b465ad..480b20f 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunActivity.java
@@ -199,7 +199,7 @@ // An optional sign-in page. if (mFreProperties.getBoolean(SHOW_SIGNIN_PAGE)) { - mPages.add(new SyncConsentFirstRunFragment.Page(getModalDialogManagerSupplier().get())); + mPages.add(SyncConsentFirstRunFragment::new); mFreProgressStates.add(FRE_PROGRESS_SIGNIN_SHOWN); notifyAdapter = true; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/SyncConsentFirstRunFragment.java b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/SyncConsentFirstRunFragment.java index dd4c461..35e96d8 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/SyncConsentFirstRunFragment.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/SyncConsentFirstRunFragment.java
@@ -18,7 +18,6 @@ import org.chromium.components.signin.AccountUtils; import org.chromium.components.signin.ChildAccountStatus; import org.chromium.components.signin.metrics.SigninAccessPoint; -import org.chromium.ui.modaldialog.ModalDialogManager; import java.util.List; @@ -27,26 +26,13 @@ */ public class SyncConsentFirstRunFragment extends SyncConsentFragmentBase implements FirstRunFragment { - /** FRE page that instantiates this fragment. */ - public static class Page implements FirstRunPage<SyncConsentFirstRunFragment> { - private final ModalDialogManager mModalDialogManager; - - public Page(ModalDialogManager modalDialogManager) { - mModalDialogManager = modalDialogManager; - } - - @Override - public SyncConsentFirstRunFragment instantiateFragment() { - return new SyncConsentFirstRunFragment(mModalDialogManager); - } - } // Per-page parameters: // TODO(crbug/1168516): Remove CHILD_ACCOUNT_STATUS public static final String CHILD_ACCOUNT_STATUS = "ChildAccountStatus"; - public SyncConsentFirstRunFragment(ModalDialogManager modalDialogManager) { - super(modalDialogManager); - } + // Do not remove. Empty fragment constructor is required for re-creating the fragment from a + // saved state bundle. See crbug.com/1225102 + public SyncConsentFirstRunFragment() {} @Override public void onAttach(Context context) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryAdapter.java b/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryAdapter.java index 07d69cf..248eebb4 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryAdapter.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryAdapter.java
@@ -396,11 +396,18 @@ // If the history header is not showing (e.g. when there is no browsing history), // mClearBrowsingDataButton will be null. if (mClearBrowsingDataButton == null) return; - boolean shouldShowButton = UserPrefs.get(Profile.getLastUsedRegularProfile()) - .getBoolean(Pref.ALLOW_DELETING_BROWSER_HISTORY); + + boolean shouldShowButton; + if (mManager.getShouldShowClearDataIfAvailable()) { + shouldShowButton = UserPrefs.get(Profile.getLastUsedRegularProfile()) + .getBoolean(Pref.ALLOW_DELETING_BROWSER_HISTORY); + } else { + shouldShowButton = false; + } if (mClearBrowsingDataButtonVisible == shouldShowButton) return; mClearBrowsingDataButtonVisible = shouldShowButton; mPrivacyDisclaimerBottomSpace.setVisibility(shouldShowButton ? View.GONE : View.VISIBLE); + if (mAreHeadersInitialized) setHeaders(); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryContentManager.java b/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryContentManager.java index 0a39bec6..373becd 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryContentManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryContentManager.java
@@ -97,6 +97,7 @@ private final boolean mIsSeparateActivity; private final boolean mIsIncognito; private final boolean mIsScrollToLoadDisabled; + private final boolean mShouldShowClearData; private final String mHostName; private final TabCreatorManager mTabCreatorManager; private final Supplier<Tab> mTabSupplier; @@ -116,6 +117,8 @@ * @param isIncognito Whether the incognito tab model is currently selected. * @param shouldShowPrivacyDisclaimers Whether the privacy disclaimers should be shown, if * available. + * @param shouldShowClearData Whether the the clear history data button should be shown, if + * available. * @param hostName The hostName to retrieve history entries for, or null for all hosts. * @param selectionDelegate A class responsible for handling list item selection, null for * unselectable items. @@ -126,13 +129,15 @@ */ public HistoryContentManager(@NonNull Activity activity, @NonNull Observer observer, boolean isSeparateActivity, boolean isIncognito, boolean shouldShowPrivacyDisclaimers, - @Nullable String hostName, @Nullable SelectionDelegate<HistoryItem> selectionDelegate, + boolean shouldShowClearData, @Nullable String hostName, + @Nullable SelectionDelegate<HistoryItem> selectionDelegate, @Nullable TabCreatorManager tabCreatorManager, @Nullable Supplier<Tab> tabSupplier) { mActivity = activity; mObserver = observer; mIsSeparateActivity = isSeparateActivity; mIsIncognito = isIncognito; mShouldShowPrivacyDisclaimers = shouldShowPrivacyDisclaimers; + mShouldShowClearData = shouldShowClearData; mHostName = hostName; mIsScrollToLoadDisabled = ChromeAccessibilityUtil.get().isAccessibilityEnabled() || ChromeAccessibilityUtil.isHardwareKeyboardAttached( @@ -309,7 +314,7 @@ * @return True if the available privacy disclaimers should be shown. * Note that this may return true even if there are currently no privacy disclaimers. */ - public boolean getShouldShowPrivacyDisclaimersIfAvailable() { + boolean getShouldShowPrivacyDisclaimersIfAvailable() { return mShouldShowPrivacyDisclaimers; } @@ -329,6 +334,14 @@ } /** + * @return True if the clear history data button should be shown. + * Note that this may return true even if we are not showing the button. + */ + boolean getShouldShowClearDataIfAvailable() { + return mShouldShowClearData; + } + + /** * Open the provided url. * @param url The url to open. * @param isIncognito Whether to open the url in an incognito tab. If null, the tab
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryManager.java b/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryManager.java index 3562fd9a..08485a6 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryManager.java
@@ -110,8 +110,8 @@ boolean shouldShowInfoHeader = SharedPreferencesManager.getInstance().readBoolean( ChromePreferenceKeys.HISTORY_SHOW_HISTORY_INFO, true); mContentManager = new HistoryContentManager(mActivity, this, isSeparateActivity, - isIncognito, shouldShowInfoHeader, /* hostName */ null, mSelectionDelegate, - tabCreatorManager, tabSupplier); + isIncognito, shouldShowInfoHeader, /* shouldShowClearData */ true, + /* hostName */ null, mSelectionDelegate, tabCreatorManager, tabSupplier); mSelectableListLayout.initializeRecyclerView( mContentManager.getAdapter(), mContentManager.getRecyclerView());
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/init/AsyncInitializationActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/init/AsyncInitializationActivity.java index aefc7b2..68100d56 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/init/AsyncInitializationActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/init/AsyncInitializationActivity.java
@@ -51,16 +51,14 @@ import org.chromium.ui.base.WindowAndroid; import org.chromium.ui.display.DisplayAndroid; import org.chromium.ui.display.DisplayUtil; -import org.chromium.ui.modaldialog.ModalDialogManager; -import org.chromium.ui.modaldialog.ModalDialogManagerHolder; import java.lang.reflect.Field; /** * An activity that talks with application and activity level delegates for async initialization. */ -public abstract class AsyncInitializationActivity extends ChromeBaseAppCompatActivity - implements ChromeActivityNativeDelegate, BrowserParts, ModalDialogManagerHolder { +public abstract class AsyncInitializationActivity + extends ChromeBaseAppCompatActivity implements ChromeActivityNativeDelegate, BrowserParts { @VisibleForTesting public static final String FIRST_DRAW_COMPLETED_TIME_MS_UMA = "FirstDrawCompletedTime"; private static final String TAG = "AsyncInitActivity"; @@ -662,16 +660,6 @@ } /** - * @return The {@link ModalDialogManager} that manages the display of modal dialogs (e.g. - * JavaScript dialogs). - */ - @Override - public ModalDialogManager getModalDialogManager() { - // TODO(jinsukkim): Remove this method in favor of super.getModalDialogManagerSupplier(). - return getModalDialogManagerSupplier().get(); - } - - /** * This will handle passing {@link Intent} results back to the {@link WindowAndroid}. It will * return whether or not the {@link WindowAndroid} has consumed the event or not. */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/page_info/PageInfoHistoryController.java b/chrome/android/java/src/org/chromium/chrome/browser/page_info/PageInfoHistoryController.java index 9368aa9..2eeb48f0 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/page_info/PageInfoHistoryController.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/page_info/PageInfoHistoryController.java
@@ -53,7 +53,8 @@ assert !mDelegate.isIncognito(); mContentManager = new HistoryContentManager(mMainController.getActivity(), this, /* isSeparateActivity */ false, - /* isIncognito */ false, /* shouldShowPrivacyDisclaimers */ true, mHost, + /* isIncognito */ false, /* shouldShowPrivacyDisclaimers */ true, + /* shouldShowClearData */ false, mHost, /* selectionDelegate */ null, /* tabCreatorManager */ null, /* tabSupplier */ null); mContentManager.initialize();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/searchwidget/SearchActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/searchwidget/SearchActivity.java index de0612e..0eacd8f 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/searchwidget/SearchActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/searchwidget/SearchActivity.java
@@ -52,6 +52,7 @@ import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager; import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager.SnackbarManageable; import org.chromium.chrome.browser.ui.native_page.NativePage; +import org.chromium.chrome.browser.ui.searchactivityutils.SearchActivityConstants; import org.chromium.components.browser_ui.modaldialog.AppModalPresenter; import org.chromium.components.browser_ui.util.BrowserControlsVisibilityDelegate; import org.chromium.components.external_intents.ExternalNavigationHandler; @@ -343,7 +344,7 @@ private boolean isVoiceSearchIntent() { return IntentUtils.safeGetBooleanExtra( - getIntent(), SearchWidgetProvider.EXTRA_START_VOICE_SEARCH, false); + getIntent(), SearchActivityConstants.EXTRA_SHOULD_START_VOICE_SEARCH, false); } private boolean isFromSearchWidget() {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/searchwidget/SearchWidgetProvider.java b/chrome/android/java/src/org/chromium/chrome/browser/searchwidget/SearchWidgetProvider.java index d4f59f6..ff28927 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/searchwidget/SearchWidgetProvider.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/searchwidget/SearchWidgetProvider.java
@@ -34,6 +34,7 @@ import org.chromium.chrome.browser.preferences.ChromePreferenceKeys; import org.chromium.chrome.browser.preferences.SharedPreferencesManager; import org.chromium.chrome.browser.search_engines.TemplateUrlServiceFactory; +import org.chromium.chrome.browser.ui.searchactivityutils.SearchActivityConstants; import org.chromium.components.search_engines.TemplateUrl; import org.chromium.components.search_engines.TemplateUrlService; import org.chromium.components.search_engines.TemplateUrlService.LoadListener; @@ -114,8 +115,6 @@ static final String ACTION_UPDATE_ALL_WIDGETS = "org.chromium.chrome.browser.searchwidget.UPDATE_ALL_WIDGETS"; - public static final String EXTRA_START_VOICE_SEARCH = - "org.chromium.chrome.browser.searchwidget.START_VOICE_SEARCH"; public static final String EXTRA_FROM_SEARCH_WIDGET = "org.chromium.chrome.browser.searchwidget.FROM_SEARCH_WIDGET"; @@ -194,9 +193,9 @@ static void handleAction(Intent intent) { String action = intent.getAction(); if (ACTION_START_TEXT_QUERY.equals(action)) { - startSearchActivity(intent, false); + startSearchActivity(intent, /*shouldStartVoiceSearch=*/false); } else if (ACTION_START_VOICE_QUERY.equals(action)) { - startSearchActivity(intent, true); + startSearchActivity(intent, /*shouldStartVoiceSearch=*/true); } else if (ACTION_UPDATE_ALL_WIDGETS.equals(action)) { performUpdate(null); } else { @@ -205,8 +204,8 @@ } @VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE) - public static void startSearchActivity(Intent intent, boolean startVoiceSearch) { - Log.d(SearchActivity.TAG, "Launching SearchActivity: VOICE=" + startVoiceSearch); + public static void startSearchActivity(Intent intent, boolean shouldStartVoiceSearch) { + Log.d(SearchActivity.TAG, "Launching SearchActivity: VOICE=" + shouldStartVoiceSearch); Context context = getDelegate().getContext(); // Abort if the user needs to go through First Run. @@ -220,7 +219,9 @@ searchIntent.setClass(context, SearchActivity.class); searchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); searchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT); - searchIntent.putExtra(EXTRA_START_VOICE_SEARCH, startVoiceSearch); + searchIntent.putExtra( + SearchActivityConstants.EXTRA_SHOULD_START_VOICE_SEARCH, shouldStartVoiceSearch); + searchIntent.putExtra(EXTRA_FROM_SEARCH_WIDGET, true); Bundle optionsBundle =
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/SyncConsentActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/SyncConsentActivity.java index 50e107d..656687f9 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/signin/SyncConsentActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/SyncConsentActivity.java
@@ -39,7 +39,7 @@ Fragment fragment = fragmentManager.findFragmentById(R.id.fragment_container); if (fragment == null) { Bundle fragmentArgs = getIntent().getBundleExtra(ARGUMENT_FRAGMENT_ARGS); - fragment = new SyncConsentFragment(getModalDialogManagerSupplier().get()); + fragment = new SyncConsentFragment(); fragment.setArguments(fragmentArgs); fragmentManager.beginTransaction().add(R.id.fragment_container, fragment).commit(); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/SyncConsentFragment.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/SyncConsentFragment.java index de4a85cb..5224d9af 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/signin/SyncConsentFragment.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/SyncConsentFragment.java
@@ -24,7 +24,6 @@ import org.chromium.components.signin.AccountManagerFacadeProvider; import org.chromium.components.signin.AccountUtils; import org.chromium.components.signin.metrics.SigninAccessPoint; -import org.chromium.ui.modaldialog.ModalDialogManager; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -83,10 +82,6 @@ return result; } - public SyncConsentFragment(ModalDialogManager modalDialogManager) { - super(modalDialogManager); - } - @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/SyncConsentFragmentBase.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/SyncConsentFragmentBase.java index b7c549e..6d951466 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/signin/SyncConsentFragmentBase.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/SyncConsentFragmentBase.java
@@ -7,6 +7,7 @@ import android.accounts.Account; import android.accounts.AccountManager; import android.app.Activity; +import android.content.Context; import android.content.Intent; import android.graphics.drawable.Drawable; import android.os.Bundle; @@ -49,6 +50,7 @@ import org.chromium.components.signin.metrics.SigninAccessPoint; import org.chromium.components.user_prefs.UserPrefs; import org.chromium.ui.modaldialog.ModalDialogManager; +import org.chromium.ui.modaldialog.ModalDialogManagerHolder; import org.chromium.ui.text.NoUnderlineClickableSpan; import org.chromium.ui.text.SpanApplier; @@ -97,7 +99,6 @@ private @Nullable String mRequestedAccountName; private final ProfileDataCache.Observer mProfileDataCacheObserver; - private final ModalDialogManager mModalDialogManager; private String mSelectedAccountName; private boolean mIsDefaultAccountSelected; private ProfileDataCache mProfileDataCache; @@ -106,6 +107,7 @@ private boolean mCanUseGooglePlayServices; private boolean mRecordUndoSignin; protected @SigninAccessPoint int mSigninAccessPoint; + private ModalDialogManager mModalDialogManager; private ConfirmSyncDataStateMachine mConfirmSyncDataStateMachine; private AccountPickerDialogCoordinator mAccountPickerDialogCoordinator; @@ -163,11 +165,10 @@ return result; } - protected SyncConsentFragmentBase(ModalDialogManager modalDialogManager) { + protected SyncConsentFragmentBase() { mAccountManagerFacade = AccountManagerFacadeProvider.getInstance(); mProfileDataCacheObserver = this::updateProfileData; mCanUseGooglePlayServices = true; - mModalDialogManager = modalDialogManager; } /** The sign-in was refused. */ @@ -184,6 +185,12 @@ boolean settingsClicked, Runnable callback); @Override + public void onAttach(Context context) { + super.onAttach(context); + mModalDialogManager = ((ModalDialogManagerHolder) getActivity()).getModalDialogManager(); + } + + @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/app/metrics/TabbedActivityLaunchCauseMetricsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/app/metrics/TabbedActivityLaunchCauseMetricsTest.java index 00c98e40..dde3c8f5 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/app/metrics/TabbedActivityLaunchCauseMetricsTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/app/metrics/TabbedActivityLaunchCauseMetricsTest.java
@@ -73,6 +73,8 @@ @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) @Batch(Batch.PER_CLASS) public final class TabbedActivityLaunchCauseMetricsTest { + private static final long CHROME_LAUNCH_TIMEOUT = 10000L; + @Rule public final ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule(); @@ -180,7 +182,7 @@ Criteria.checkThat( histogramCountForValue(LaunchCauseMetrics.LaunchCause.HOME_SCREEN_WIDGET), Matchers.is(count)); - }, 5000L, CriteriaHelper.DEFAULT_POLLING_INTERVAL); + }, CHROME_LAUNCH_TIMEOUT, CriteriaHelper.DEFAULT_POLLING_INTERVAL); } private static class TestContext extends ContextWrapper { @@ -230,7 +232,7 @@ histogramCountForValue( LaunchCauseMetrics.LaunchCause.EXTERNAL_SEARCH_ACTION_INTENT), Matchers.is(count)); - }, 5000L, CriteriaHelper.DEFAULT_POLLING_INTERVAL); + }, CHROME_LAUNCH_TIMEOUT, CriteriaHelper.DEFAULT_POLLING_INTERVAL); ApplicationTestUtils.finishActivity(cta); ApplicationTestUtils.finishActivity(searchActivity); @@ -252,6 +254,6 @@ CriteriaHelper.pollInstrumentationThread(() -> { Criteria.checkThat(histogramCountForValue(LaunchCauseMetrics.LaunchCause.NOTIFICATION), Matchers.is(count)); - }, 5000L, CriteriaHelper.DEFAULT_POLLING_INTERVAL); + }, CHROME_LAUNCH_TIMEOUT, CriteriaHelper.DEFAULT_POLLING_INTERVAL); } }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelBaseTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelBaseTest.java index 99067206..5c562f8 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelBaseTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelBaseTest.java
@@ -28,17 +28,17 @@ import org.chromium.chrome.browser.compositor.layouts.LayoutManagerImpl; import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; +import org.chromium.chrome.test.DummyUiChromeActivityTestCase; import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.ui.base.ActivityWindowAndroid; import org.chromium.ui.base.IntentRequestTracker; import org.chromium.ui.base.WindowAndroid; -import org.chromium.ui.test.util.DummyUiActivityTestCase; /** * Tests logic in the OverlayPanelBase. */ @RunWith(ChromeJUnit4ClassRunner.class) -public class OverlayPanelBaseTest extends DummyUiActivityTestCase { +public class OverlayPanelBaseTest extends DummyUiChromeActivityTestCase { private static final float UPWARD_VELOCITY = -1.0f; private static final float DOWNWARD_VELOCITY = 1.0f;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelEventFilterTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelEventFilterTest.java index 86cde8b1..c84f896 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelEventFilterTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelEventFilterTest.java
@@ -30,16 +30,16 @@ import org.chromium.chrome.browser.compositor.layouts.eventfilter.OverlayPanelEventFilter; import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; +import org.chromium.chrome.test.DummyUiChromeActivityTestCase; import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.ui.base.ActivityWindowAndroid; import org.chromium.ui.base.IntentRequestTracker; import org.chromium.ui.base.WindowAndroid; -import org.chromium.ui.test.util.DummyUiActivityTestCase; /** * Class responsible for testing the OverlayPanelEventFilter. */ @RunWith(ChromeJUnit4ClassRunner.class) -public class OverlayPanelEventFilterTest extends DummyUiActivityTestCase { +public class OverlayPanelEventFilterTest extends DummyUiChromeActivityTestCase { private static final float PANEL_ALMOST_MAXIMIZED_OFFSET_Y_DP = 50.f; private static final float BAR_HEIGHT_DP = 100.f;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelManagerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelManagerTest.java index d9a75adb..8588740 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelManagerTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanelManagerTest.java
@@ -31,12 +31,12 @@ import org.chromium.chrome.browser.compositor.layouts.LayoutManagerImpl; import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; +import org.chromium.chrome.test.DummyUiChromeActivityTestCase; import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.ui.base.ActivityWindowAndroid; import org.chromium.ui.base.IntentRequestTracker; import org.chromium.ui.base.WindowAndroid; import org.chromium.ui.resources.dynamics.DynamicResourceLoader; -import org.chromium.ui.test.util.DummyUiActivityTestCase; import java.util.concurrent.TimeoutException; @@ -44,7 +44,7 @@ * Class responsible for testing the OverlayPanelManager. */ @RunWith(ChromeJUnit4ClassRunner.class) -public class OverlayPanelManagerTest extends DummyUiActivityTestCase { +public class OverlayPanelManagerTest extends DummyUiChromeActivityTestCase { private static final int MOCK_TOOLBAR_HEIGHT = 100; @Rule
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/ContextMenuChipControllerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/ContextMenuChipControllerTest.java index d0a991a..7322170 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/ContextMenuChipControllerTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/ContextMenuChipControllerTest.java
@@ -25,15 +25,15 @@ import org.chromium.chrome.R; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; +import org.chromium.chrome.test.DummyUiChromeActivityTestCase; import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.ui.test.util.DummyUiActivity; -import org.chromium.ui.test.util.DummyUiActivityTestCase; /** * Tests for ContextMenuHeader view and {@link ContextMenuHeaderViewBinder} */ @RunWith(ChromeJUnit4ClassRunner.class) -public class ContextMenuChipControllerTest extends DummyUiActivityTestCase { +public class ContextMenuChipControllerTest extends DummyUiChromeActivityTestCase { // This is the combination of the expected vertical margins and the chip height. private static final int EXPECTED_VERTICAL_DP = 80; // Computed by taking the 338dp max width and subtracting:
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/ContextMenuHeaderViewTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/ContextMenuHeaderViewTest.java index 8d23759..08b756a4 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/ContextMenuHeaderViewTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/ContextMenuHeaderViewTest.java
@@ -26,17 +26,17 @@ import org.chromium.chrome.R; import org.chromium.chrome.browser.performance_hints.PerformanceHintsObserver.PerformanceClass; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; +import org.chromium.chrome.test.DummyUiChromeActivityTestCase; import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.ui.modelutil.PropertyModel; import org.chromium.ui.modelutil.PropertyModelChangeProcessor; import org.chromium.ui.test.util.DummyUiActivity; -import org.chromium.ui.test.util.DummyUiActivityTestCase; /** * Tests for ContextMenuHeader view and {@link ContextMenuHeaderViewBinder} */ @RunWith(ChromeJUnit4ClassRunner.class) -public class ContextMenuHeaderViewTest extends DummyUiActivityTestCase { +public class ContextMenuHeaderViewTest extends DummyUiChromeActivityTestCase { private static final String TITLE_STRING = "Some Very Cool Title"; private static final String URL_STRING = "www.website.com";
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/ContextMenuItemViewTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/ContextMenuItemViewTest.java index b8f87df..2ab86c2 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/ContextMenuItemViewTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/ContextMenuItemViewTest.java
@@ -24,18 +24,18 @@ import org.chromium.base.test.UiThreadTest; import org.chromium.chrome.R; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; +import org.chromium.chrome.test.DummyUiChromeActivityTestCase; import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.ui.modelutil.PropertyModel; import org.chromium.ui.modelutil.PropertyModelChangeProcessor; import org.chromium.ui.test.util.DummyUiActivity; -import org.chromium.ui.test.util.DummyUiActivityTestCase; /** * Tests for ContextMenu item view, {@link ContextMenuItemViewBinder}, and {@link * ContextMenuItemWithIconButtonViewBinder}. */ @RunWith(ChromeJUnit4ClassRunner.class) -public class ContextMenuItemViewTest extends DummyUiActivityTestCase { +public class ContextMenuItemViewTest extends DummyUiChromeActivityTestCase { private static final String TEXT = "Useful menu item"; private static final String APP = "Some app";
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/ContextMenuRenderTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/ContextMenuRenderTest.java index c24e6c2..e361266 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/ContextMenuRenderTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/ContextMenuRenderTest.java
@@ -24,6 +24,7 @@ import org.chromium.chrome.R; import org.chromium.chrome.browser.contextmenu.ContextMenuCoordinator.ListItemType; import org.chromium.chrome.test.ChromeJUnit4RunnerDelegate; +import org.chromium.chrome.test.DummyUiChromeActivityTestCase; import org.chromium.chrome.test.util.ChromeRenderTestRule; import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.ui.modelutil.LayoutViewBuilder; @@ -31,7 +32,6 @@ import org.chromium.ui.modelutil.MVCListAdapter.ModelList; import org.chromium.ui.modelutil.ModelListAdapter; import org.chromium.ui.modelutil.PropertyModel; -import org.chromium.ui.test.util.DummyUiActivityTestCase; import org.chromium.ui.test.util.NightModeTestUtils; import java.io.IOException; @@ -42,7 +42,7 @@ */ @RunWith(ParameterizedRunner.class) @ParameterAnnotations.UseRunnerDelegate(ChromeJUnit4RunnerDelegate.class) -public class ContextMenuRenderTest extends DummyUiActivityTestCase { +public class ContextMenuRenderTest extends DummyUiChromeActivityTestCase { @ParameterAnnotations.ClassParameter private static List<ParameterSet> sClassParams = new NightModeTestUtils.NightModeParams().getParameters();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/download/dialogs/DownloadLocationDialogTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/download/dialogs/DownloadLocationDialogTest.java index 2b70a5e2..0d97d781 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/download/dialogs/DownloadLocationDialogTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/download/dialogs/DownloadLocationDialogTest.java
@@ -42,6 +42,7 @@ import org.chromium.chrome.browser.preferences.Pref; import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; +import org.chromium.chrome.test.DummyUiChromeActivityTestCase; import org.chromium.components.browser_ui.modaldialog.AppModalPresenter; import org.chromium.components.browser_ui.util.DownloadUtils; import org.chromium.components.prefs.PrefService; @@ -49,7 +50,6 @@ import org.chromium.components.user_prefs.UserPrefsJni; import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.ui.modaldialog.ModalDialogManager; -import org.chromium.ui.test.util.DummyUiActivityTestCase; import java.util.ArrayList; import java.util.HashMap; @@ -60,7 +60,7 @@ */ @RunWith(ChromeJUnit4ClassRunner.class) @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) -public class DownloadLocationDialogTest extends DummyUiActivityTestCase { +public class DownloadLocationDialogTest extends DummyUiChromeActivityTestCase { private static final long TOTAL_BYTES = 1024L; private static final String SUGGESTED_PATH = "download.png"; private static final String PRIMARY_STORAGE_PATH = "/sdcard";
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/init/FirstDrawDetectorTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/init/FirstDrawDetectorTest.java index 51c70bb..2819ec3 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/init/FirstDrawDetectorTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/init/FirstDrawDetectorTest.java
@@ -13,10 +13,11 @@ import org.junit.Test; import org.junit.runner.RunWith; -import org.chromium.base.test.BaseActivityTestRule; +import org.chromium.chrome.R; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.ui.test.util.DummyUiActivity; +import org.chromium.ui.test.util.ThemedDummyUiActivityTestRule; import java.util.concurrent.CountDownLatch; @@ -24,8 +25,8 @@ @RunWith(ChromeJUnit4ClassRunner.class) public class FirstDrawDetectorTest { @Rule - public BaseActivityTestRule<DummyUiActivity> mActivityTestRule = - new BaseActivityTestRule<>(DummyUiActivity.class); + public ThemedDummyUiActivityTestRule<DummyUiActivity> mActivityTestRule = + new ThemedDummyUiActivityTestRule<>(DummyUiActivity.class, R.style.ColorOverlay); @Test @SmallTest
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/modaldialog/ModalDialogViewRenderTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/modaldialog/ModalDialogViewRenderTest.java index 19ad17c..43d5479 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/modaldialog/ModalDialogViewRenderTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/modaldialog/ModalDialogViewRenderTest.java
@@ -30,6 +30,7 @@ import org.chromium.base.test.params.ParameterizedRunner; import org.chromium.base.test.util.Feature; import org.chromium.chrome.test.ChromeJUnit4RunnerDelegate; +import org.chromium.chrome.test.DummyUiChromeActivityTestCase; import org.chromium.components.browser_ui.modaldialog.ModalDialogTestUtils; import org.chromium.components.browser_ui.modaldialog.ModalDialogView; import org.chromium.components.browser_ui.modaldialog.test.R; @@ -37,7 +38,6 @@ import org.chromium.ui.UiUtils; import org.chromium.ui.modaldialog.ModalDialogProperties; import org.chromium.ui.modelutil.PropertyModel; -import org.chromium.ui.test.util.DummyUiActivityTestCase; import org.chromium.ui.test.util.NightModeTestUtils; import org.chromium.ui.test.util.RenderTestRule; @@ -50,7 +50,7 @@ */ @RunWith(ParameterizedRunner.class) @ParameterAnnotations.UseRunnerDelegate(ChromeJUnit4RunnerDelegate.class) -public class ModalDialogViewRenderTest extends DummyUiActivityTestCase { +public class ModalDialogViewRenderTest extends DummyUiChromeActivityTestCase { @ParameterAnnotations.ClassParameter private static List<ParameterSet> sClassParams = new NightModeTestUtils.NightModeParams().getParameters();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/IncognitoDescriptionViewRenderTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/IncognitoDescriptionViewRenderTest.java index 6acc943c..26e0609 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/IncognitoDescriptionViewRenderTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/IncognitoDescriptionViewRenderTest.java
@@ -20,9 +20,9 @@ import org.chromium.base.test.util.Feature; import org.chromium.chrome.R; import org.chromium.chrome.test.ChromeJUnit4RunnerDelegate; +import org.chromium.chrome.test.DummyUiChromeActivityTestCase; import org.chromium.chrome.test.util.ChromeRenderTestRule; import org.chromium.content_public.browser.test.util.TestThreadUtils; -import org.chromium.ui.test.util.DummyUiActivityTestCase; import org.chromium.ui.test.util.NightModeTestUtils; import java.io.IOException; @@ -33,7 +33,7 @@ */ @RunWith(ParameterizedRunner.class) @UseRunnerDelegate(ChromeJUnit4RunnerDelegate.class) -public class IncognitoDescriptionViewRenderTest extends DummyUiActivityTestCase { +public class IncognitoDescriptionViewRenderTest extends DummyUiChromeActivityTestCase { @ParameterAnnotations.ClassParameter private static List<ParameterSet> sClassParams = new NightModeTestUtils.NightModeParams().getParameters();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/UrlBarTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/UrlBarTest.java index baf86b6..3736946 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/UrlBarTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/UrlBarTest.java
@@ -45,10 +45,10 @@ import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.omnibox.UrlBar.UrlBarDelegate; import org.chromium.chrome.test.ChromeJUnit4RunnerDelegate; +import org.chromium.chrome.test.DummyUiChromeActivityTestCase; import org.chromium.chrome.test.util.OmniboxTestUtils; import org.chromium.content_public.browser.test.util.KeyUtils; import org.chromium.content_public.browser.test.util.TestThreadUtils; -import org.chromium.ui.test.util.DummyUiActivityTestCase; import java.util.Arrays; import java.util.HashMap; @@ -64,7 +64,7 @@ */ @RunWith(ParameterizedRunner.class) @UseRunnerDelegate(ChromeJUnit4RunnerDelegate.class) -public class UrlBarTest extends DummyUiActivityTestCase { +public class UrlBarTest extends DummyUiChromeActivityTestCase { @ClassParameter private static List<ParameterSet> sClassParams = Arrays.asList(new ParameterSet().value(false).name("DisableSpannableInline"),
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/status/StatusViewRenderTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/status/StatusViewRenderTest.java index 16afb59..aba475e 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/status/StatusViewRenderTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/status/StatusViewRenderTest.java
@@ -33,6 +33,7 @@ import org.chromium.chrome.browser.omnibox.status.StatusProperties.StatusIconResource; import org.chromium.chrome.browser.toolbar.LocationBarModel; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; +import org.chromium.chrome.test.DummyUiChromeActivityTestCase; import org.chromium.chrome.test.util.ChromeRenderTestRule; import org.chromium.chrome.test.util.ToolbarTestUtils; import org.chromium.chrome.test.util.browser.Features; @@ -42,7 +43,6 @@ import org.chromium.components.content_settings.ContentSettingsType; import org.chromium.ui.modelutil.PropertyModel; import org.chromium.ui.modelutil.PropertyModelChangeProcessor; -import org.chromium.ui.test.util.DummyUiActivityTestCase; import java.io.IOException; @@ -50,7 +50,7 @@ * Render tests for {@link StatusView}. */ @RunWith(ChromeJUnit4ClassRunner.class) -public class StatusViewRenderTest extends DummyUiActivityTestCase { +public class StatusViewRenderTest extends DummyUiChromeActivityTestCase { @Rule public ChromeRenderTestRule mRenderTestRule = ChromeRenderTestRule.Builder.withPublicCorpus().build();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/status/StatusViewTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/status/StatusViewTest.java index bf29751..d045a980 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/status/StatusViewTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/status/StatusViewTest.java
@@ -39,18 +39,18 @@ import org.chromium.chrome.browser.omnibox.status.StatusProperties.StatusIconResource; import org.chromium.chrome.browser.toolbar.LocationBarModel; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; +import org.chromium.chrome.test.DummyUiChromeActivityTestCase; import org.chromium.chrome.test.util.ToolbarTestUtils; import org.chromium.components.browser_ui.widget.CompositeTouchDelegate; import org.chromium.ui.modelutil.PropertyModel; import org.chromium.ui.modelutil.PropertyModelChangeProcessor; -import org.chromium.ui.test.util.DummyUiActivityTestCase; import org.chromium.ui.test.util.UiRestriction; /** * Tests for {@link StatusView} and {@link StatusViewBinder}. */ @RunWith(ChromeJUnit4ClassRunner.class) -public class StatusViewTest extends DummyUiActivityTestCase { +public class StatusViewTest extends DummyUiChromeActivityTestCase { @Mock private SearchEngineLogoUtils mSearchEngineLogoUtils;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/voice/AssistantVoiceSearchConsentUiRenderTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/voice/AssistantVoiceSearchConsentUiRenderTest.java index 75d8ffe5..009be6e 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/voice/AssistantVoiceSearchConsentUiRenderTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/voice/AssistantVoiceSearchConsentUiRenderTest.java
@@ -19,16 +19,16 @@ import org.chromium.chrome.R; import org.chromium.chrome.browser.flags.ChromeSwitches; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; +import org.chromium.chrome.test.DummyUiChromeActivityTestCase; import org.chromium.chrome.test.util.ChromeRenderTestRule; import org.chromium.content_public.browser.test.util.TestThreadUtils; -import org.chromium.ui.test.util.DummyUiActivityTestCase; import java.io.IOException; /** Render tests for AssistantVoiceSearchConsentDialog */ @RunWith(ChromeJUnit4ClassRunner.class) @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) -public class AssistantVoiceSearchConsentUiRenderTest extends DummyUiActivityTestCase { +public class AssistantVoiceSearchConsentUiRenderTest extends DummyUiChromeActivityTestCase { @Rule public ChromeRenderTestRule mRenderTestRule = ChromeRenderTestRule.Builder.withPublicCorpus().build();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/AndroidPaymentAppFinderUnitTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/AndroidPaymentAppFinderUnitTest.java index 6705659..287cb33 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/AndroidPaymentAppFinderUnitTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/AndroidPaymentAppFinderUnitTest.java
@@ -32,6 +32,7 @@ import org.chromium.chrome.browser.tabmodel.TabModelSelector; import org.chromium.chrome.browser.tabmodel.TabModelSelectorSupplier; import org.chromium.chrome.test.ChromeBrowserTestRule; +import org.chromium.chrome.test.DummyUiChromeActivityTestCase; import org.chromium.components.payments.AndroidPaymentAppFinder; import org.chromium.components.payments.PackageManagerDelegate; import org.chromium.components.payments.PaymentApp; @@ -49,7 +50,6 @@ import org.chromium.ui.base.ActivityWindowAndroid; import org.chromium.ui.base.IntentRequestTracker; import org.chromium.ui.base.WindowAndroid; -import org.chromium.ui.test.util.DummyUiActivityTestCase; import org.chromium.url.GURL; import org.chromium.url.Origin; @@ -61,7 +61,7 @@ /** Tests for the native Android payment app finder. */ @RunWith(BaseJUnit4ClassRunner.class) @Batch(AndroidPaymentAppFinderUnitTest.PAYMENTS_BROWSER_UNIT_TESTS) -public class AndroidPaymentAppFinderUnitTest extends DummyUiActivityTestCase { +public class AndroidPaymentAppFinderUnitTest extends DummyUiChromeActivityTestCase { // Collection of payments unit tests that require the browser process to be initialized. static final String PAYMENTS_BROWSER_UNIT_TESTS = "PaymentsBrowserUnitTests"; private static final IntentArgumentMatcher sPayIntentArgumentMatcher =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/searchwidget/SearchWidgetProviderTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/searchwidget/SearchWidgetProviderTest.java index d155bc3..8274f58 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/searchwidget/SearchWidgetProviderTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/searchwidget/SearchWidgetProviderTest.java
@@ -36,6 +36,7 @@ import org.chromium.chrome.browser.preferences.ChromePreferenceKeys; import org.chromium.chrome.browser.preferences.SharedPreferencesManager; import org.chromium.chrome.browser.searchwidget.SearchActivity.SearchActivityDelegate; +import org.chromium.chrome.browser.ui.searchactivityutils.SearchActivityConstants; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.chrome.test.util.ChromeApplicationTestUtils; import org.chromium.content_public.browser.test.util.TestThreadUtils; @@ -285,7 +286,7 @@ // Check that the Activity was launched in the right mode. Intent intent = activity.getIntent(); boolean microphoneState = IntentUtils.safeGetBooleanExtra( - intent, SearchWidgetProvider.EXTRA_START_VOICE_SEARCH, false); + intent, SearchActivityConstants.EXTRA_SHOULD_START_VOICE_SEARCH, false); Assert.assertEquals(clickTarget == R.id.microphone_icon, microphoneState); boolean fromWidget = IntentUtils.safeGetBooleanExtra( intent, SearchWidgetProvider.EXTRA_FROM_SEARCH_WIDGET, false);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SyncConsentFragmentTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SyncConsentFragmentTest.java index 272c3ad..5f61697 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SyncConsentFragmentTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SyncConsentFragmentTest.java
@@ -15,7 +15,6 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.when; -import android.content.Context; import android.os.Bundle; import android.support.test.InstrumentationRegistry; import android.support.test.runner.lifecycle.Stage; @@ -42,7 +41,6 @@ import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; -import org.chromium.base.test.BaseActivityTestRule; import org.chromium.base.test.util.ApplicationTestUtils; import org.chromium.base.test.util.CommandLineFlags; import org.chromium.base.test.util.CriteriaHelper; @@ -62,17 +60,15 @@ import org.chromium.chrome.test.util.ChromeRenderTestRule; import org.chromium.chrome.test.util.browser.signin.AccountManagerTestRule; import org.chromium.chrome.test.util.browser.sync.SyncTestUtil; -import org.chromium.components.browser_ui.modaldialog.AppModalPresenter; import org.chromium.components.externalauth.ExternalAuthUtils; import org.chromium.components.signin.ChildAccountStatus; import org.chromium.components.signin.base.CoreAccountInfo; import org.chromium.components.signin.metrics.SigninAccessPoint; import org.chromium.components.signin.test.util.FakeAccountInfoService; import org.chromium.content_public.browser.test.util.TestThreadUtils; -import org.chromium.ui.modaldialog.ModalDialogManager; -import org.chromium.ui.modaldialog.ModalDialogManager.ModalDialogType; import org.chromium.ui.test.util.DisableAnimationsTestRule; import org.chromium.ui.test.util.DummyUiActivity; +import org.chromium.ui.test.util.ThemedDummyUiActivityTestRule; import java.io.IOException; @@ -90,10 +86,6 @@ public static class CustomSyncConsentFirstRunFragment extends SyncConsentFirstRunFragment { private FirstRunPageDelegate mFirstRunPageDelegate; - public CustomSyncConsentFirstRunFragment(Context context) { - super(new ModalDialogManager(new AppModalPresenter(context), ModalDialogType.APP)); - } - @Override public FirstRunPageDelegate getPageDelegate() { return mFirstRunPageDelegate; @@ -119,8 +111,8 @@ new ChromeTabbedActivityTestRule(); @Rule - public final BaseActivityTestRule<DummyUiActivity> mActivityTestRule = - new BaseActivityTestRule<>(DummyUiActivity.class); + public final ThemedDummyUiActivityTestRule<DummyUiActivity> mActivityTestRule = + new ThemedDummyUiActivityTestRule<>(DummyUiActivity.class, R.style.ColorOverlay); @Rule public final ChromeRenderTestRule mRenderTestRule = @@ -226,8 +218,7 @@ new HistogramDelta("Signin.AndroidDeviceAccountsNumberWhenEnteringFRE", 0); HistogramDelta startPageHistogram = new HistogramDelta("Signin.SigninStartedAccessPoint", SigninAccessPoint.START_PAGE); - CustomSyncConsentFirstRunFragment fragment = - new CustomSyncConsentFirstRunFragment(mActivityTestRule.getActivity()); + CustomSyncConsentFirstRunFragment fragment = new CustomSyncConsentFirstRunFragment(); Bundle bundle = new Bundle(); bundle.putInt( SyncConsentFirstRunFragment.CHILD_ACCOUNT_STATUS, ChildAccountStatus.NOT_CHILD); @@ -250,8 +241,7 @@ HistogramDelta startPageHistogram = new HistogramDelta("Signin.SigninStartedAccessPoint", SigninAccessPoint.START_PAGE); mAccountManagerTestRule.addAccount(AccountManagerTestRule.TEST_ACCOUNT_EMAIL); - CustomSyncConsentFirstRunFragment fragment = - new CustomSyncConsentFirstRunFragment(mActivityTestRule.getActivity()); + CustomSyncConsentFirstRunFragment fragment = new CustomSyncConsentFirstRunFragment(); Bundle bundle = new Bundle(); bundle.putInt( SyncConsentFirstRunFragment.CHILD_ACCOUNT_STATUS, ChildAccountStatus.NOT_CHILD); @@ -274,8 +264,7 @@ HistogramDelta startPageHistogram = new HistogramDelta("Signin.SigninStartedAccessPoint", SigninAccessPoint.START_PAGE); mAccountManagerTestRule.addAccount(AccountManagerTestRule.TEST_ACCOUNT_EMAIL); - CustomSyncConsentFirstRunFragment fragment = - new CustomSyncConsentFirstRunFragment(mActivityTestRule.getActivity()); + CustomSyncConsentFirstRunFragment fragment = new CustomSyncConsentFirstRunFragment(); Bundle bundle = new Bundle(); bundle.putInt( SyncConsentFirstRunFragment.CHILD_ACCOUNT_STATUS, ChildAccountStatus.REGULAR_CHILD); @@ -298,8 +287,7 @@ HistogramDelta startPageHistogram = new HistogramDelta("Signin.SigninStartedAccessPoint", SigninAccessPoint.START_PAGE); mAccountManagerTestRule.addAccount(AccountManagerTestRule.TEST_ACCOUNT_EMAIL); - CustomSyncConsentFirstRunFragment fragment = - new CustomSyncConsentFirstRunFragment(mActivityTestRule.getActivity()); + CustomSyncConsentFirstRunFragment fragment = new CustomSyncConsentFirstRunFragment(); Bundle bundle = new Bundle(); bundle.putInt( SyncConsentFirstRunFragment.CHILD_ACCOUNT_STATUS, ChildAccountStatus.USM_CHILD);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/status_indicator/StatusIndicatorViewBinderTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/status_indicator/StatusIndicatorViewBinderTest.java index 3f33d6f6..31714cf 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/status_indicator/StatusIndicatorViewBinderTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/status_indicator/StatusIndicatorViewBinderTest.java
@@ -29,19 +29,19 @@ import org.chromium.base.test.UiThreadTest; import org.chromium.chrome.R; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; +import org.chromium.chrome.test.DummyUiChromeActivityTestCase; import org.chromium.components.browser_ui.widget.ViewResourceFrameLayout; import org.chromium.components.browser_ui.widget.text.TextViewWithCompoundDrawables; import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.ui.modelutil.PropertyModel; import org.chromium.ui.modelutil.PropertyModelChangeProcessor; import org.chromium.ui.test.util.DummyUiActivity; -import org.chromium.ui.test.util.DummyUiActivityTestCase; /** * Tests for {@link StatusIndicatorViewBinder}. */ @RunWith(ChromeJUnit4ClassRunner.class) -public class StatusIndicatorViewBinderTest extends DummyUiActivityTestCase { +public class StatusIndicatorViewBinderTest extends DummyUiChromeActivityTestCase { private static final String STATUS_TEXT = "Offline"; private ViewResourceFrameLayout mContainer;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/HomeButtonTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/HomeButtonTest.java index a429c0c1..0252096 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/HomeButtonTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/HomeButtonTest.java
@@ -32,17 +32,17 @@ import org.chromium.chrome.browser.homepage.HomepageTestRule; import org.chromium.chrome.browser.homepage.settings.HomepageSettings; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; +import org.chromium.chrome.test.DummyUiChromeActivityTestCase; import org.chromium.chrome.test.util.browser.Features; import org.chromium.components.browser_ui.settings.SettingsLauncher; import org.chromium.content_public.browser.test.util.TestThreadUtils; -import org.chromium.ui.test.util.DummyUiActivityTestCase; /** * Test related to {@link HomeButton}. * TODO: Add more test when features related has update. */ @RunWith(ChromeJUnit4ClassRunner.class) -public class HomeButtonTest extends DummyUiActivityTestCase { +public class HomeButtonTest extends DummyUiChromeActivityTestCase { private static final String ASSERT_MSG_MENU_IS_CREATED = "ContextMenu is not created after long press."; private static final String ASSERT_MSG_MENU_SIZE =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveButtonActionMenuRenderTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveButtonActionMenuRenderTest.java index e08aeef1..5cd331f 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveButtonActionMenuRenderTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveButtonActionMenuRenderTest.java
@@ -21,7 +21,6 @@ import org.junit.runner.RunWith; import org.chromium.base.ApiCompatibilityUtils; -import org.chromium.base.test.BaseActivityTestRule; import org.chromium.base.test.params.ParameterAnnotations; import org.chromium.base.test.params.ParameterSet; import org.chromium.base.test.params.ParameterizedRunner; @@ -38,6 +37,7 @@ import org.chromium.ui.test.util.DisableAnimationsTestRule; import org.chromium.ui.test.util.DummyUiActivity; import org.chromium.ui.test.util.NightModeTestUtils; +import org.chromium.ui.test.util.ThemedDummyUiActivityTestRule; import java.io.IOException; import java.util.List; @@ -58,8 +58,8 @@ public static DisableAnimationsTestRule disableAnimationsRule = new DisableAnimationsTestRule(); @Rule - public BaseActivityTestRule<DummyUiActivity> mActivityTestRule = - new BaseActivityTestRule<>(DummyUiActivity.class); + public ThemedDummyUiActivityTestRule<DummyUiActivity> mActivityTestRule = + new ThemedDummyUiActivityTestRule<>(DummyUiActivity.class, R.style.ColorOverlay); @Rule public ChromeRenderTestRule mRenderTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/top/TabSwitcherActionMenuRenderTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/top/TabSwitcherActionMenuRenderTest.java index b8bd9c6..17e6784f 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/top/TabSwitcherActionMenuRenderTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/top/TabSwitcherActionMenuRenderTest.java
@@ -24,10 +24,10 @@ import org.chromium.base.test.util.Feature; import org.chromium.chrome.R; import org.chromium.chrome.test.ChromeJUnit4RunnerDelegate; +import org.chromium.chrome.test.DummyUiChromeActivityTestCase; import org.chromium.chrome.test.util.ChromeRenderTestRule; import org.chromium.components.browser_ui.widget.listmenu.ListMenuButton; import org.chromium.content_public.browser.test.util.TestThreadUtils; -import org.chromium.ui.test.util.DummyUiActivityTestCase; import org.chromium.ui.test.util.NightModeTestUtils; import java.io.IOException; @@ -38,7 +38,7 @@ */ @RunWith(ParameterizedRunner.class) @ParameterAnnotations.UseRunnerDelegate(ChromeJUnit4RunnerDelegate.class) -public class TabSwitcherActionMenuRenderTest extends DummyUiActivityTestCase { +public class TabSwitcherActionMenuRenderTest extends DummyUiChromeActivityTestCase { @ParameterAnnotations.ClassParameter private static List<ParameterSet> sClassParams = new NightModeTestUtils.NightModeParams().getParameters();
diff --git a/chrome/android/profiles/newest.txt b/chrome/android/profiles/newest.txt index f3d229c..63968fc 100644 --- a/chrome/android/profiles/newest.txt +++ b/chrome/android/profiles/newest.txt
@@ -1 +1 @@ -chromeos-chrome-amd64-93.0.4573.0_rc-r1-merged.afdo.bz2 +chromeos-chrome-amd64-93.0.4574.0_rc-r1-merged.afdo.bz2
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index cea5ab0..18edff5 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd
@@ -5892,10 +5892,10 @@ Why am I seeing this? </message> <message name="IDS_NTP_MODULES_TASKS_INFO" desc="Text shown in the body of the info dialog of a task module."> - You're seeing this item based on your previous activity using Google services. You can see your data, delete it, and change your settings at <ph name="BEGIN_LINK"><a href="https://myactivity.google.com/" target="_blank"></ph>myactivity.google.com<ph name="END_LINK"></a></ph>. + You're seeing this item based on your previous activity using Google services. You can see your data, delete it, and change your settings at <ph name="BEGIN_LINK1"><a href="https://myactivity.google.com/" target="_blank"></ph>myactivity.google.com<ph name="END_LINK1"></a></ph>. <ph name="BREAK"><br></ph> <ph name="BREAK"><br></ph> - Learn about the data Google collects and why at <ph name="BEGIN_LINK"><a href="https://policies.google.com/" target="_blank"></ph>policies.google.com<ph name="END_LINK"></a></ph>. + Learn about the data Google collects and why at <ph name="BEGIN_LINK2"><a href="https://policies.google.com/" target="_blank"></ph>policies.google.com<ph name="END_LINK2"></a></ph>. </message> <message name="IDS_NTP_MODULES_SHOPPING_TASKS_INFO_CLOSE" desc="Text shown on close button of a task module."> Close @@ -10622,9 +10622,32 @@ <message name="IDS_WEB_APP_FILE_HANDLING_PERMISSION_TEXT" desc="Permission request shown if the user is opening a file using a PWA with registered file handlers. Follows a prompt: 'This site would like to:'"> Open <ph name="FILE_EXTENSIONS">$1<ex>.txt, .csv, .md</ex></ph> files </message> - <message name="IDS_WEB_APP_FILE_HANDLING_EXTENSION_LIST_SEPARATOR" desc="Text/punctuation that separates a list of file types/extensions, such as .txt or .csv." meaning="List separator for file extensions."> + <message name="IDS_WEB_APP_FILE_HANDLING_LIST_SEPARATOR" desc="Text/punctuation that separates items in a lists. For example, this is used in a list of files, such as 'todo_list.txt, shopping_list.txt', and file types/extensions, such as '.txt, .csv.'" meaning="List separator for files."> , ''' </message> + <message name="IDS_WEB_APP_FILE_HANDLING_PERMISSION_TITLE" desc="Title of permission request dialog that is when the user is opening a file using a PWA."> + Open file? + </message> + <message name="IDS_WEB_APP_FILE_HANDLING_PERMISSION_TITLE_MULTIPLE" desc="Title of permission request dialog that is shown when the user is opening multiple files using a PWA."> + Open files? + </message> + <message name="IDS_WEB_APP_FILE_HANDLING_PERMISSION_DESCRIPTION" desc="Descriptive text in permission request dialog that is shown when the user is opening a file using a PWA."> + <ph name="APP_ORIGIN">$1<ex>example.com</ex></ph> wants to open this file: + </message> + <message name="IDS_WEB_APP_FILE_HANDLING_PERMISSION_DESCRIPTION_MULTIPLE" desc="Descriptive text in permission request dialog that is shown when the user is opening multiple files using a PWA."> + <ph name="APP_ORIGIN">$1<ex>example.com</ex></ph> wants to open these files: + </message> + <message name="IDS_WEB_APP_FILE_HANDLING_PERMISSION_STICKY_CHOICE" desc="In permission request dialog that is shown when the user is opening files in a PWA: text for a toggle that makes the permission decision permanent (single file format)."> + Don't ask again when opening this file format in this app: +<ph name="FILE_FORMAT">$1<ex>TXT</ex></ph> + </message> + <message name="IDS_WEB_APP_FILE_HANDLING_PERMISSION_STICKY_CHOICE_MULTIPLE" desc="In permission request dialog that is shown when the user is opening files in a PWA: text for a toggle that makes the permission decision permanent (multiple file formats)."> + Don't ask again when opening these file formats in this app: +<ph name="FILE_FORMATS">$1<ex>TXT, CSV, DOC</ex></ph> + </message> + <message name="IDS_WEB_APP_FILE_HANDLING_PERMISSION_DONT_ALLOW" desc="In permission request dialog that is shown when the user is opening files in a PWA: text for button that doesn't allow PWA to open the file(s)."> + Don't allow + </message> </if> <!-- Font Access chooser -->
diff --git a/chrome/app/generated_resources_grd/IDS_WEB_APP_FILE_HANDLING_EXTENSION_LIST_SEPARATOR.png.sha1 b/chrome/app/generated_resources_grd/IDS_WEB_APP_FILE_HANDLING_LIST_SEPARATOR.png.sha1 similarity index 100% rename from chrome/app/generated_resources_grd/IDS_WEB_APP_FILE_HANDLING_EXTENSION_LIST_SEPARATOR.png.sha1 rename to chrome/app/generated_resources_grd/IDS_WEB_APP_FILE_HANDLING_LIST_SEPARATOR.png.sha1
diff --git a/chrome/app/generated_resources_grd/IDS_WEB_APP_FILE_HANDLING_PERMISSION_DESCRIPTION.png.sha1 b/chrome/app/generated_resources_grd/IDS_WEB_APP_FILE_HANDLING_PERMISSION_DESCRIPTION.png.sha1 new file mode 100644 index 0000000..90b41fb --- /dev/null +++ b/chrome/app/generated_resources_grd/IDS_WEB_APP_FILE_HANDLING_PERMISSION_DESCRIPTION.png.sha1
@@ -0,0 +1 @@ +2e3b70c3afda28604af395714e4d2bcf4ef8f89f \ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_WEB_APP_FILE_HANDLING_PERMISSION_DESCRIPTION_MULTIPLE.png.sha1 b/chrome/app/generated_resources_grd/IDS_WEB_APP_FILE_HANDLING_PERMISSION_DESCRIPTION_MULTIPLE.png.sha1 new file mode 100644 index 0000000..a712c0d --- /dev/null +++ b/chrome/app/generated_resources_grd/IDS_WEB_APP_FILE_HANDLING_PERMISSION_DESCRIPTION_MULTIPLE.png.sha1
@@ -0,0 +1 @@ +565f6ddb59e65f617babe0cf5286d2843d0e6120 \ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_WEB_APP_FILE_HANDLING_PERMISSION_DONT_ALLOW.png.sha1 b/chrome/app/generated_resources_grd/IDS_WEB_APP_FILE_HANDLING_PERMISSION_DONT_ALLOW.png.sha1 new file mode 100644 index 0000000..1a688b54 --- /dev/null +++ b/chrome/app/generated_resources_grd/IDS_WEB_APP_FILE_HANDLING_PERMISSION_DONT_ALLOW.png.sha1
@@ -0,0 +1 @@ +e302453e3e592a8697d428a56c8c1624cdb02bf6 \ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_WEB_APP_FILE_HANDLING_PERMISSION_STICKY_CHOICE.png.sha1 b/chrome/app/generated_resources_grd/IDS_WEB_APP_FILE_HANDLING_PERMISSION_STICKY_CHOICE.png.sha1 new file mode 100644 index 0000000..1892b2f4 --- /dev/null +++ b/chrome/app/generated_resources_grd/IDS_WEB_APP_FILE_HANDLING_PERMISSION_STICKY_CHOICE.png.sha1
@@ -0,0 +1 @@ +9ab540beeab926d3a6c59c6081513f59d5ccc1ea \ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_WEB_APP_FILE_HANDLING_PERMISSION_STICKY_CHOICE_MULTIPLE.png.sha1 b/chrome/app/generated_resources_grd/IDS_WEB_APP_FILE_HANDLING_PERMISSION_STICKY_CHOICE_MULTIPLE.png.sha1 new file mode 100644 index 0000000..ad500dd --- /dev/null +++ b/chrome/app/generated_resources_grd/IDS_WEB_APP_FILE_HANDLING_PERMISSION_STICKY_CHOICE_MULTIPLE.png.sha1
@@ -0,0 +1 @@ +6237570155ccf65f00150083132016cda1224d19 \ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_WEB_APP_FILE_HANDLING_PERMISSION_TITLE.png.sha1 b/chrome/app/generated_resources_grd/IDS_WEB_APP_FILE_HANDLING_PERMISSION_TITLE.png.sha1 new file mode 100644 index 0000000..3de860179 --- /dev/null +++ b/chrome/app/generated_resources_grd/IDS_WEB_APP_FILE_HANDLING_PERMISSION_TITLE.png.sha1
@@ -0,0 +1 @@ +4efe55940e48c51fce986a63b27fd97c9e326b31 \ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_WEB_APP_FILE_HANDLING_PERMISSION_TITLE_MULTIPLE.png.sha1 b/chrome/app/generated_resources_grd/IDS_WEB_APP_FILE_HANDLING_PERMISSION_TITLE_MULTIPLE.png.sha1 new file mode 100644 index 0000000..8d1598b --- /dev/null +++ b/chrome/app/generated_resources_grd/IDS_WEB_APP_FILE_HANDLING_PERMISSION_TITLE_MULTIPLE.png.sha1
@@ -0,0 +1 @@ +841e991301745ea9e2616c0c64a0b5a94bbadc65 \ No newline at end of file
diff --git a/chrome/app/os_settings_strings.grdp b/chrome/app/os_settings_strings.grdp index 395f893..a6131db 100644 --- a/chrome/app/os_settings_strings.grdp +++ b/chrome/app/os_settings_strings.grdp
@@ -1093,6 +1093,15 @@ <message name="IDS_SETTINGS_ACCESSIBILITY_DICTATION_SUBTITLE_SODA_DOWNLOAD_ERROR" desc="Description explaining that there was an error with the speech recognition library download."> Can't download speech files. Dictation will continue to work by sending your voice to Google. </message> + <message name="IDS_SETTINGS_ACCESSIBILITY_DICTATION_LOCALE_MENU_LABEL" desc="Description of a drop-down menu to select the language to use for Dictation's speech recognition."> + Language + </message> + <message name="IDS_SETTINGS_ACCESSIBILITY_DICTATION_LOCALE_SUB_LABEL_OFFLINE" desc="Sub-label for a drop-down menu to select the language to use for Dictation. Describes how that language can be processed offline with no network connection."> + <ph name="language">$1<ex>English</ex></ph> is processed locally and works offline. + </message> + <message name="IDS_SETTINGS_ACCESSIBILITY_DICTATION_LOCALE_SUB_LABEL_NETWORK" desc="Sub-label for a drop-down menu to select the language to use for Dictation. Describes how speech will be sent over the network to Google for processing to create text."> + <ph name="language">$1<ex>English</ex></ph> speech is sent to Google for processing. + </message> <message name="IDS_SETTINGS_ON_SCREEN_KEYBOARD_LABEL" desc="Label for checkbox which enables an on-screen keyboard."> Enable on-screen keyboard </message>
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_ACCESSIBILITY_DICTATION_LOCALE_MENU_LABEL.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_ACCESSIBILITY_DICTATION_LOCALE_MENU_LABEL.png.sha1 new file mode 100644 index 0000000..9361ec0 --- /dev/null +++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_ACCESSIBILITY_DICTATION_LOCALE_MENU_LABEL.png.sha1
@@ -0,0 +1 @@ +995720813c5b48b83e31eaa26c55ef1e5f79c330 \ No newline at end of file
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_ACCESSIBILITY_DICTATION_LOCALE_SUB_LABEL_NETWORK.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_ACCESSIBILITY_DICTATION_LOCALE_SUB_LABEL_NETWORK.png.sha1 new file mode 100644 index 0000000..1e31d04 --- /dev/null +++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_ACCESSIBILITY_DICTATION_LOCALE_SUB_LABEL_NETWORK.png.sha1
@@ -0,0 +1 @@ +f02732774218df53887165d7fda94c372723a451 \ No newline at end of file
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_ACCESSIBILITY_DICTATION_LOCALE_SUB_LABEL_OFFLINE.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_ACCESSIBILITY_DICTATION_LOCALE_SUB_LABEL_OFFLINE.png.sha1 new file mode 100644 index 0000000..9361ec0 --- /dev/null +++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_ACCESSIBILITY_DICTATION_LOCALE_SUB_LABEL_OFFLINE.png.sha1
@@ -0,0 +1 @@ +995720813c5b48b83e31eaa26c55ef1e5f79c330 \ No newline at end of file
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index afcdeb4..a532d96 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -4554,6 +4554,10 @@ "notifications/notification_platform_bridge_chromeos.h", "notifications/notification_platform_bridge_delegate.h", "notifications/notifier_controller.h", + "notifications/notifier_dataset.cc", + "notifications/notifier_dataset.h", + "notifications/pwa_notifier_controller.cc", + "notifications/pwa_notifier_controller.h", "notifications/web_page_notifier_controller.cc", "notifications/web_page_notifier_controller.h", "performance_manager/mechanisms/userspace_swap_chromeos.cc",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index 67b4993..d72c25c 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -2022,11 +2022,25 @@ const FeatureEntry::FeatureParam kLensCameraAssistedSearchLensButtonEnd[] = { {"searchBoxStartVariantForLensCameraAssistedSearch", "false"}}; +const FeatureEntry::FeatureParam + kLensCameraAssistedSkipAgsaVersionCheckEnabled[] = { + {"skipAgsaVersionCheck", "true"}}; + +const FeatureEntry::FeatureParam + kLensCameraAssistedSkipAgsaVersionCheckDisabled[] = { + {"skipAgsaVersionCheck", "false"}}; + const FeatureEntry::FeatureVariation kLensCameraAssistedSearchVariations[] = { {"(Lens then Mic)", kLensCameraAssistedSearchLensButtonStart, base::size(kLensCameraAssistedSearchLensButtonStart), nullptr}, {"(Mic then Lens)", kLensCameraAssistedSearchLensButtonEnd, - base::size(kLensCameraAssistedSearchLensButtonEnd), nullptr}}; + base::size(kLensCameraAssistedSearchLensButtonEnd), nullptr}, + {"(without AGSA version check)", + kLensCameraAssistedSkipAgsaVersionCheckEnabled, + base::size(kLensCameraAssistedSkipAgsaVersionCheckEnabled), nullptr}, + {"(with AGSA version check )", + kLensCameraAssistedSkipAgsaVersionCheckDisabled, + base::size(kLensCameraAssistedSkipAgsaVersionCheckDisabled), nullptr}}; const FeatureEntry::FeatureParam kLensContextMenuTranslateHideRemoveIcon[] = { {"hideChipRemoveIcon", "true"}}; @@ -4632,6 +4646,11 @@ flag_descriptions::kDoubleTapToZoomInTabletModeName, flag_descriptions::kDoubleTapToZoomInTabletModeDescription, kOsCrOS, FEATURE_VALUE_TYPE(features::kDoubleTapToZoomInTabletMode)}, + + {"quick-settings-pwa-notifications", + flag_descriptions::kQuickSettingsPWANotificationsName, + flag_descriptions::kQuickSettingsPWANotificationsDescription, kOsCrOS, + FEATURE_VALUE_TYPE(features::kQuickSettingsPWANotifications)}, #endif // BUILDFLAG(IS_CHROMEOS_ASH) {flag_descriptions::kReadLaterFlagId, flag_descriptions::kReadLaterName,
diff --git a/chrome/browser/apps/app_service/publishers/standalone_browser_extension_apps.cc b/chrome/browser/apps/app_service/publishers/standalone_browser_extension_apps.cc index 3e0b703..adeb36d 100644 --- a/chrome/browser/apps/app_service/publishers/standalone_browser_extension_apps.cc +++ b/chrome/browser/apps/app_service/publishers/standalone_browser_extension_apps.cc
@@ -4,6 +4,8 @@ #include "chrome/browser/apps/app_service/publishers/standalone_browser_extension_apps.h" +#include <utility> + #include "chrome/browser/apps/app_service/app_service_proxy.h" #include "chrome/browser/apps/app_service/app_service_proxy_factory.h" #include "chrome/browser/ash/crosapi/browser_util.h" @@ -25,6 +27,20 @@ StandaloneBrowserExtensionApps::~StandaloneBrowserExtensionApps() = default; +void StandaloneBrowserExtensionApps::RegisterChromeAppsCrosapiHost( + mojo::PendingReceiver<crosapi::mojom::AppPublisher> receiver) { + // At the moment the app service publisher will only accept one client + // publishing apps to ash chrome. Any extra clients will be ignored. + // TODO(crbug.com/1174246): Support SxS lacros. + if (receiver_.is_bound()) { + return; + } + receiver_.Bind(std::move(receiver)); + receiver_.set_disconnect_handler( + base::BindOnce(&StandaloneBrowserExtensionApps::OnReceiverDisconnected, + weak_factory_.GetWeakPtr())); +} + void StandaloneBrowserExtensionApps::Connect( mojo::PendingRemote<apps::mojom::Subscriber> subscriber_remote, apps::mojom::ConnectOptionsPtr opts) { @@ -52,6 +68,7 @@ apps::mojom::LaunchSource launch_source, apps::mojom::WindowInfoPtr window_info) { // TODO(https://crbug.com/1225848): Implement. + NOTIMPLEMENTED(); } void StandaloneBrowserExtensionApps::GetMenuModel( @@ -60,6 +77,40 @@ int64_t display_id, GetMenuModelCallback callback) { // TODO(https://crbug.com/1225848): Implement. + NOTIMPLEMENTED(); +} + +void StandaloneBrowserExtensionApps::OnApps( + std::vector<apps::mojom::AppPtr> deltas) { + // TODO(https://crbug.com/1225848): Implement. + NOTIMPLEMENTED(); +} + +void StandaloneBrowserExtensionApps::RegisterAppController( + mojo::PendingRemote<crosapi::mojom::AppController> controller) { + if (controller_.is_bound()) { + return; + } + controller_.Bind(std::move(controller)); + controller_.set_disconnect_handler( + base::BindOnce(&StandaloneBrowserExtensionApps::OnControllerDisconnected, + weak_factory_.GetWeakPtr())); +} + +void StandaloneBrowserExtensionApps::OnCapabilityAccesses( + std::vector<apps::mojom::CapabilityAccessPtr> deltas) { + // TODO(https://crbug.com/1225848): Implement. + NOTIMPLEMENTED(); +} + +void StandaloneBrowserExtensionApps::OnReceiverDisconnected() { + receiver_.reset(); + controller_.reset(); +} + +void StandaloneBrowserExtensionApps::OnControllerDisconnected() { + receiver_.reset(); + controller_.reset(); } } // namespace apps
diff --git a/chrome/browser/apps/app_service/publishers/standalone_browser_extension_apps.h b/chrome/browser/apps/app_service/publishers/standalone_browser_extension_apps.h index 0e8482a4..0246414 100644 --- a/chrome/browser/apps/app_service/publishers/standalone_browser_extension_apps.h +++ b/chrome/browser/apps/app_service/publishers/standalone_browser_extension_apps.h
@@ -5,6 +5,8 @@ #ifndef CHROME_BROWSER_APPS_APP_SERVICE_PUBLISHERS_STANDALONE_BROWSER_EXTENSION_APPS_H_ #define CHROME_BROWSER_APPS_APP_SERVICE_PUBLISHERS_STANDALONE_BROWSER_EXTENSION_APPS_H_ +#include "base/memory/weak_ptr.h" +#include "chromeos/crosapi/mojom/app_service.mojom.h" #include "components/keyed_service/core/keyed_service.h" #include "components/services/app_service/public/cpp/publisher_base.h" #include "components/services/app_service/public/mojom/app_service.mojom-forward.h" @@ -33,7 +35,8 @@ // ScopedKeepAlive. We would like to eventually remove this assumption. This // requires caching a copy of installed apps in this class. class StandaloneBrowserExtensionApps : public KeyedService, - public apps::PublisherBase { + public apps::PublisherBase, + public crosapi::mojom::AppPublisher { public: explicit StandaloneBrowserExtensionApps(Profile* profile); ~StandaloneBrowserExtensionApps() override; @@ -43,6 +46,11 @@ StandaloneBrowserExtensionApps& operator=( const StandaloneBrowserExtensionApps&) = delete; + // Register the chrome apps host from lacros-chrome to allow lacros-chrome + // to publish chrome apps to the app service in ash-chrome. + void RegisterChromeAppsCrosapiHost( + mojo::PendingReceiver<crosapi::mojom::AppPublisher> receiver); + private: // apps::PublisherBase: void Connect(mojo::PendingRemote<apps::mojom::Subscriber> subscriber_remote, @@ -62,7 +70,29 @@ int64_t display_id, GetMenuModelCallback callback) override; + // crosapi::mojom::AppPublisher overrides. + void OnApps(std::vector<apps::mojom::AppPtr> deltas) override; + void RegisterAppController( + mojo::PendingRemote<crosapi::mojom::AppController> controller) override; + void OnCapabilityAccesses( + std::vector<apps::mojom::CapabilityAccessPtr> deltas) override; + + // Called when the crosapi termination is terminated [e.g. Lacros is closed]. + // The ordering of these two disconnect methods is non-deterministic. When + // either is called we close both connections since this class requires both + // to be functional. + void OnReceiverDisconnected(); + void OnControllerDisconnected(); + mojo::RemoteSet<apps::mojom::Subscriber> subscribers_; + + // Receives chrome app publisher events from Lacros. + mojo::Receiver<crosapi::mojom::AppPublisher> receiver_{this}; + + // Used to send chrome app publisher actions to Lacros. + mojo::Remote<crosapi::mojom::AppController> controller_; + + base::WeakPtrFactory<StandaloneBrowserExtensionApps> weak_factory_{this}; }; } // namespace apps
diff --git a/chrome/browser/ash/accessibility/select_to_speak_browsertest.cc b/chrome/browser/ash/accessibility/select_to_speak_browsertest.cc index 1f305818..c092718 100644 --- a/chrome/browser/ash/accessibility/select_to_speak_browsertest.cc +++ b/chrome/browser/ash/accessibility/select_to_speak_browsertest.cc
@@ -380,7 +380,13 @@ sm_.Replay(); } -IN_PROC_BROWSER_TEST_F(SelectToSpeakTest, BreaksAtParagraphBounds) { +// Flaky on ChromeOS MSAN bots: https://crbug.com/1227368 +#if defined(OS_CHROMEOS) && defined(MEMORY_SANITIZER) +#define MAYBE_BreaksAtParagraphBounds DISABLED_BreaksAtParagraphBounds +#else +#define MAYBE_BreaksAtParagraphBounds BreaksAtParagraphBounds +#endif +IN_PROC_BROWSER_TEST_F(SelectToSpeakTest, MAYBE_BreaksAtParagraphBounds) { ActivateSelectToSpeakInWindowBounds( "data:text/html;charset=utf-8,<div><p>First paragraph</p>" "<p>Second paragraph</p></div>");
diff --git a/chrome/browser/ash/app_mode/kiosk_cryptohome_remover.cc b/chrome/browser/ash/app_mode/kiosk_cryptohome_remover.cc index b14897c3..0b2a017 100644 --- a/chrome/browser/ash/app_mode/kiosk_cryptohome_remover.cc +++ b/chrome/browser/ash/app_mode/kiosk_cryptohome_remover.cc
@@ -74,7 +74,8 @@ local_state->GetDictionary(prefs::kAllKioskUsersToRemove); for (const auto& it : dict->DictItems()) { std::string app_id; - it.second.GetAsString(&app_id); + if (it.second.is_string()) + app_id = it.second.GetString(); VLOG(1) << "Removing obsolete cryptohome for " << app_id; const cryptohome::Identification cryptohome_id(
diff --git a/chrome/browser/ash/crosapi/browser_util.cc b/chrome/browser/ash/crosapi/browser_util.cc index 96812625..ed0f64b 100644 --- a/chrome/browser/ash/crosapi/browser_util.cc +++ b/chrome/browser/ash/crosapi/browser_util.cc
@@ -354,7 +354,7 @@ } static_assert( - crosapi::mojom::Crosapi::Version_ == 37, + crosapi::mojom::Crosapi::Version_ == 38, "if you add a new crosapi, please add it to kInterfaceVersionEntries"); static_assert(!HasDuplicatedUuid(), "Each Crosapi Mojom interface should have unique UUID.");
diff --git a/chrome/browser/ash/crosapi/crosapi_ash.cc b/chrome/browser/ash/crosapi/crosapi_ash.cc index d1f74ef8..6d84bd9 100644 --- a/chrome/browser/ash/crosapi/crosapi_ash.cc +++ b/chrome/browser/ash/crosapi/crosapi_ash.cc
@@ -11,6 +11,8 @@ #include "ash/components/account_manager/account_manager_ash.h" #include "ash/components/account_manager/account_manager_factory.h" #include "base/dcheck_is_on.h" +#include "chrome/browser/apps/app_service/publishers/standalone_browser_extension_apps.h" +#include "chrome/browser/apps/app_service/publishers/standalone_browser_extension_apps_factory.h" #include "chrome/browser/apps/app_service/publishers/web_apps_crosapi.h" #include "chrome/browser/apps/app_service/publishers/web_apps_crosapi_factory.h" #include "chrome/browser/ash/crosapi/automation_ash.h" @@ -175,6 +177,14 @@ std::move(receiver)); } +void CrosapiAsh::BindChromeAppPublisher( + mojo::PendingReceiver<mojom::AppPublisher> receiver) { + Profile* profile = ProfileManager::GetPrimaryUserProfile(); + apps::StandaloneBrowserExtensionApps* chrome_apps = + apps::StandaloneBrowserExtensionAppsFactory::GetForProfile(profile); + chrome_apps->RegisterChromeAppsCrosapiHost(std::move(receiver)); +} + void CrosapiAsh::BindFileManager( mojo::PendingReceiver<crosapi::mojom::FileManager> receiver) { file_manager_ash_->BindReceiver(std::move(receiver)); @@ -355,7 +365,7 @@ video_capture_device_factory_ash_->BindReceiver(std::move(receiver)); } -void CrosapiAsh::BindAppPublisher( +void CrosapiAsh::BindWebAppPublisher( mojo::PendingReceiver<mojom::AppPublisher> receiver) { Profile* profile = ProfileManager::GetPrimaryUserProfile(); apps::WebAppsCrosapi* web_apps =
diff --git a/chrome/browser/ash/crosapi/crosapi_ash.h b/chrome/browser/ash/crosapi/crosapi_ash.h index 27a24f0..5a54415 100644 --- a/chrome/browser/ash/crosapi/crosapi_ash.h +++ b/chrome/browser/ash/crosapi/crosapi_ash.h
@@ -73,6 +73,8 @@ mojo::PendingReceiver<mojom::BrowserServiceHost> receiver) override; void BindCertDatabase( mojo::PendingReceiver<mojom::CertDatabase> receiver) override; + void BindChromeAppPublisher( + mojo::PendingReceiver<mojom::AppPublisher> receiver) override; void BindClipboard(mojo::PendingReceiver<mojom::Clipboard> receiver) override; void BindClipboardHistory( mojo::PendingReceiver<mojom::ClipboardHistory> receiver) override; @@ -144,7 +146,7 @@ void BindVideoCaptureDeviceFactory( mojo::PendingReceiver<mojom::VideoCaptureDeviceFactory> receiver) override; - void BindAppPublisher( + void BindWebAppPublisher( mojo::PendingReceiver<mojom::AppPublisher> receiver) override; BrowserServiceHostAsh* browser_service_host_ash() {
diff --git a/chrome/browser/ash/file_system_provider/registry.cc b/chrome/browser/ash/file_system_provider/registry.cc index 1fcb6cf2..6c07e6c 100644 --- a/chrome/browser/ash/file_system_provider/registry.cc +++ b/chrome/browser/ash/file_system_provider/registry.cc
@@ -231,12 +231,11 @@ restored_watcher.recursive = recursive.value(); restored_watcher.last_tag = last_tag; for (const auto& persistent_origin : persistent_origins->GetList()) { - std::string origin; - if (persistent_origin.GetAsString(&origin)) { + if (!persistent_origin.is_string()) { LOG(ERROR) << "Malformed subscriber information in preferences."; continue; } - const GURL origin_as_gurl(origin); + const GURL origin_as_gurl(persistent_origin.GetString()); restored_watcher.subscribers[origin_as_gurl].origin = origin_as_gurl; restored_watcher.subscribers[origin_as_gurl].persistent = true; }
diff --git a/chrome/browser/ash/login/chrome_restart_request.cc b/chrome/browser/ash/login/chrome_restart_request.cc index 4de6f9b..4614275 100644 --- a/chrome/browser/ash/login/chrome_restart_request.cc +++ b/chrome/browser/ash/login/chrome_restart_request.cc
@@ -232,9 +232,7 @@ for (base::DictionaryValue::Iterator it(new_switches); !it.IsAtEnd(); it.Advance()) { - std::string value; - CHECK(it.value().GetAsString(&value)); - command_line->AppendSwitchASCII(it.key(), value); + command_line->AppendSwitchASCII(it.key(), it.value().GetString()); } }
diff --git a/chrome/browser/ash/login/lock_screen_utils.cc b/chrome/browser/ash/login/lock_screen_utils.cc index c85fe4d..a801b673 100644 --- a/chrome/browser/ash/login/lock_screen_utils.cc +++ b/chrome/browser/ash/login/lock_screen_utils.cc
@@ -130,10 +130,9 @@ allowed_input_methods.push_back(user_input_method); } - std::string input_method; for (const auto& input_method_entry : login_screen_input_methods->GetList()) { - if (input_method_entry.GetAsString(&input_method)) - allowed_input_methods.push_back(input_method); + if (input_method_entry.is_string()) + allowed_input_methods.push_back(input_method_entry.GetString()); } chromeos::input_method::InputMethodManager* imm = chromeos::input_method::InputMethodManager::Get();
diff --git a/chrome/browser/ash/login/screens/chrome_user_selection_screen.cc b/chrome/browser/ash/login/screens/chrome_user_selection_screen.cc index 3dd15ff..8dec396 100644 --- a/chrome/browser/ash/login/screens/chrome_user_selection_screen.cc +++ b/chrome/browser/ash/login/screens/chrome_user_selection_screen.cc
@@ -125,13 +125,12 @@ if (entry && entry->level == policy::POLICY_LEVEL_RECOMMENDED && entry->value() && entry->value()->GetAsList(&list)) { for (const auto& entry : list->GetList()) { - std::string locale; - if (!entry.GetAsString(&locale)) { + if (!entry.is_string()) { NOTREACHED(); new_recommended_locales.clear(); break; } - new_recommended_locales.push_back(locale); + new_recommended_locales.push_back(entry.GetString()); } }
diff --git a/chrome/browser/ash/login/signin/device_id_browsertest.cc b/chrome/browser/ash/login/signin/device_id_browsertest.cc index 27cf3d4..2a96292 100644 --- a/chrome/browser/ash/login/signin/device_id_browsertest.cc +++ b/chrome/browser/ash/login/signin/device_id_browsertest.cc
@@ -154,9 +154,8 @@ FakeGaia::RefreshTokenToDeviceIdMap map; for (base::DictionaryValue::Iterator it(*dictionary); !it.IsAtEnd(); it.Advance()) { - std::string device_id; - EXPECT_TRUE(it.value().GetAsString(&device_id)); - map[it.key()] = device_id; + ASSERT_TRUE(it.value().is_string()); + map[it.key()] = it.value().GetString(); } fake_gaia_.fake_gaia()->SetRefreshTokenToDeviceIdMap(map); }
diff --git a/chrome/browser/ash/ownership/owner_settings_service_ash.cc b/chrome/browser/ash/ownership/owner_settings_service_ash.cc index 95e777a..0afe77da 100644 --- a/chrome/browser/ash/ownership/owner_settings_service_ash.cc +++ b/chrome/browser/ash/ownership/owner_settings_service_ash.cc
@@ -528,9 +528,8 @@ } else if (path == kAccountsPrefDeviceLocalAccountAutoLoginId) { em::DeviceLocalAccountsProto* device_local_accounts = settings.mutable_device_local_accounts(); - std::string id; - if (value.GetAsString(&id)) - device_local_accounts->set_auto_login_id(id); + if (value.is_string()) + device_local_accounts->set_auto_login_id(value.GetString()); else NOTREACHED(); } else if (path == kAccountsPrefDeviceLocalAccountAutoLoginDelay) { @@ -566,8 +565,8 @@ em::ReleaseChannelProto* release_channel = settings.mutable_release_channel(); std::string channel_value; - if (value.GetAsString(&channel_value)) - release_channel->set_release_channel(channel_value); + if (value.is_string()) + release_channel->set_release_channel(value.GetString()); else NOTREACHED(); } else if (path == kStatsReportingPref) { @@ -655,6 +654,7 @@ // kHeartbeatFrequency // kReleaseChannelDelegated // kReportDeviceActivityTimes + // kReportDeviceAudioStatus // KReportDeviceBacklightInfo // kReportDeviceBluetoothInfo // kReportDeviceBoardStatus
diff --git a/chrome/browser/ash/ownership/owner_settings_service_ash_unittest.cc b/chrome/browser/ash/ownership/owner_settings_service_ash_unittest.cc index 2d26de32..03c7292 100644 --- a/chrome/browser/ash/ownership/owner_settings_service_ash_unittest.cc +++ b/chrome/browser/ash/ownership/owner_settings_service_ash_unittest.cc
@@ -181,9 +181,10 @@ TEST_F(OwnerSettingsServiceAshTest, FailedSetRequest) { session_manager_client_.ForceStorePolicyFailure(true); - std::string current_channel; - ASSERT_TRUE(provider_->Get(kReleaseChannel)->GetAsString(¤t_channel)); - ASSERT_NE(current_channel, "stable-channel"); + ASSERT_TRUE(provider_->Get(kReleaseChannel)->is_string()); + const std::string current_channel = + provider_->Get(kReleaseChannel)->GetString(); + ASSERT_NE("stable-channel", current_channel); // Check that DeviceSettingsProvider's cache is updated. PrefsChecker checker(service_, provider_.get());
diff --git a/chrome/browser/ash/policy/core/device_policy_decoder_chromeos.cc b/chrome/browser/ash/policy/core/device_policy_decoder_chromeos.cc index 4b0e729..30a377f 100644 --- a/chrome/browser/ash/policy/core/device_policy_decoder_chromeos.cc +++ b/chrome/browser/ash/policy/core/device_policy_decoder_chromeos.cc
@@ -697,6 +697,11 @@ POLICY_SCOPE_MACHINE, POLICY_SOURCE_CLOUD, base::Value(container.report_activity_times()), nullptr); } + if (container.has_report_audio_status()) { + policies->Set(key::kReportDeviceAudioStatus, POLICY_LEVEL_MANDATORY, + POLICY_SCOPE_MACHINE, POLICY_SOURCE_CLOUD, + base::Value(container.report_audio_status()), nullptr); + } if (container.has_report_boot_mode()) { policies->Set(key::kReportDeviceBootMode, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE, POLICY_SOURCE_CLOUD,
diff --git a/chrome/browser/ash/policy/core/device_policy_decoder_chromeos_unittest.cc b/chrome/browser/ash/policy/core/device_policy_decoder_chromeos_unittest.cc index 06090a2..0b238223 100644 --- a/chrome/browser/ash/policy/core/device_policy_decoder_chromeos_unittest.cc +++ b/chrome/browser/ash/policy/core/device_policy_decoder_chromeos_unittest.cc
@@ -199,6 +199,29 @@ EXPECT_TRUE(report_device_login_logout_bool); } +TEST_F(DevicePolicyDecoderChromeOSTest, ReportDeviceAudioStatus) { + PolicyBundle bundle; + PolicyMap& policies = bundle.Get(PolicyNamespace(POLICY_DOMAIN_CHROME, "")); + + base::WeakPtr<ExternalDataManager> external_data_manager; + + em::ChromeDeviceSettingsProto device_policy; + device_policy.mutable_device_reporting()->set_report_audio_status(true); + + DecodeDevicePolicy(device_policy, external_data_manager, &policies); + + const base::Value* report_device_audio_status_value = + policies.GetValue(key::kReportDeviceAudioStatus); + ASSERT_NE(report_device_audio_status_value, nullptr); + ASSERT_TRUE(report_device_audio_status_value->is_bool()); + + bool report_device_audio_status_bool = false; + report_device_audio_status_value->GetAsBoolean( + &report_device_audio_status_bool); + + EXPECT_TRUE(report_device_audio_status_bool); +} + TEST_F(DevicePolicyDecoderChromeOSTest, DecodeServiceUUIDListSuccess) { std::string error; absl::optional<base::Value> decoded_json = DecodeJsonStringAndNormalize(
diff --git a/chrome/browser/ash/settings/cros_settings.cc b/chrome/browser/ash/settings/cros_settings.cc index 50c34956..23552ce 100644 --- a/chrome/browser/ash/settings/cros_settings.cc +++ b/chrome/browser/ash/settings/cros_settings.cc
@@ -163,8 +163,10 @@ std::string* out_value) const { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); const base::Value* value = GetPref(path); - if (value) - return value->GetAsString(out_value); + if (value && value->is_string()) { + *out_value = value->GetString(); + return true; + } return false; }
diff --git a/chrome/browser/ash/settings/device_settings_provider.cc b/chrome/browser/ash/settings/device_settings_provider.cc index 8bd8f35..0ecba654 100644 --- a/chrome/browser/ash/settings/device_settings_provider.cc +++ b/chrome/browser/ash/settings/device_settings_provider.cc
@@ -119,6 +119,7 @@ kReleaseLtsTag, kDeviceChannelDowngradeBehavior, kReportDeviceActivityTimes, + kReportDeviceAudioStatus, kReportDeviceBluetoothInfo, kReportDeviceBoardStatus, kReportDeviceBootMode, @@ -565,6 +566,10 @@ new_values_cache->SetBoolean(kReportDeviceActivityTimes, reporting_policy.report_activity_times()); } + if (reporting_policy.has_report_audio_status()) { + new_values_cache->SetBoolean(kReportDeviceAudioStatus, + reporting_policy.report_audio_status()); + } if (reporting_policy.has_report_boot_mode()) { new_values_cache->SetBoolean(kReportDeviceBootMode, reporting_policy.report_boot_mode());
diff --git a/chrome/browser/ash/settings/device_settings_provider_unittest.cc b/chrome/browser/ash/settings/device_settings_provider_unittest.cc index 130e964..efc9cf92 100644 --- a/chrome/browser/ash/settings/device_settings_provider_unittest.cc +++ b/chrome/browser/ash/settings/device_settings_provider_unittest.cc
@@ -91,6 +91,7 @@ device_policy_->payload().mutable_device_reporting(); proto->set_report_version_info(enable_reporting); proto->set_report_activity_times(enable_reporting); + proto->set_report_audio_status(enable_reporting); proto->set_report_boot_mode(enable_reporting); proto->set_report_location(enable_reporting); proto->set_report_network_interfaces(enable_reporting); @@ -170,6 +171,7 @@ const char* reporting_settings[] = { kReportDeviceVersionInfo, kReportDeviceActivityTimes, + kReportDeviceAudioStatus, kReportDeviceBoardStatus, kReportDeviceBootMode, // Device location reporting is not currently supported. @@ -501,9 +503,8 @@ EXPECT_TRUE(closure); // Ownership of |closure| was not taken. const base::Value* value = provider_->Get(kReleaseChannel); ASSERT_TRUE(value); - std::string string_value; - EXPECT_TRUE(value->GetAsString(&string_value)); - EXPECT_TRUE(string_value.empty()); + ASSERT_TRUE(value->is_string()); + EXPECT_TRUE(value->GetString().empty()); // Sets should succeed though and be readable from the cache. EXPECT_CALL(*this, SettingChanged(_)).Times(AnyNumber()); @@ -520,8 +521,8 @@ // Verify the change has been applied. const base::Value* saved_value = provider_->Get(kReleaseChannel); ASSERT_TRUE(saved_value); - EXPECT_TRUE(saved_value->GetAsString(&string_value)); - ASSERT_EQ("stable-channel", string_value); + ASSERT_TRUE(saved_value->is_string()); + ASSERT_EQ("stable-channel", saved_value->GetString()); } TEST_F(DeviceSettingsProviderTestEnterprise, NoPolicyDefaultsOn) {
diff --git a/chrome/browser/ash/system_logs/crosapi_system_log_source.cc b/chrome/browser/ash/system_logs/crosapi_system_log_source.cc index 058f7ec47..25703c43 100644 --- a/chrome/browser/ash/system_logs/crosapi_system_log_source.cc +++ b/chrome/browser/ash/system_logs/crosapi_system_log_source.cc
@@ -47,9 +47,8 @@ if (system_infos.GetAsDictionary(&sysinfo_dict)) { for (const auto& item : sysinfo_dict->DictItems()) { std::string log_entry_key = kLacrosLogEntryPrefix + item.first; - std::string log_entry_value; - if (item.second.GetAsString(&log_entry_value)) { - response->emplace(log_entry_key, log_entry_value); + if (item.second.is_string()) { + response->emplace(log_entry_key, item.second.GetString()); } else { LOG(ERROR) << "Failed to retrieve the content for log entry: " << log_entry_key;
diff --git a/chrome/browser/ash/web_applications/personalization_app/chrome_personalization_app_ui_delegate.cc b/chrome/browser/ash/web_applications/personalization_app/chrome_personalization_app_ui_delegate.cc index 6e99c0a..df4c584bd 100644 --- a/chrome/browser/ash/web_applications/personalization_app/chrome_personalization_app_ui_delegate.cc +++ b/chrome/browser/ash/web_applications/personalization_app/chrome_personalization_app_ui_delegate.cc
@@ -42,11 +42,27 @@ #include "third_party/skia/include/core/SkBitmap.h" #include "ui/base/webui/web_ui_util.h" #include "ui/gfx/geometry/size.h" +#include "ui/gfx/image/image_skia.h" #include "ui/gfx/image/image_skia_operations.h" #include "url/gurl.h" namespace { -constexpr int kLocalImageThumbnailSizeDip = 128; +constexpr int kLocalImageThumbnailSizeDip = 256; + +const gfx::ImageSkia GetResizedImage(const gfx::ImageSkia& image) { + // Resize the image maintaining our aspect ratio. + float aspect_ratio = + static_cast<float>(image.width()) / static_cast<float>(image.height()); + int height = kLocalImageThumbnailSizeDip; + int width = static_cast<int>(aspect_ratio * height); + if (width > kLocalImageThumbnailSizeDip) { + width = kLocalImageThumbnailSizeDip; + height = static_cast<int>(width / aspect_ratio); + } + return gfx::ImageSkiaOperations::CreateResizedImage( + image, skia::ImageOperations::RESIZE_BEST, gfx::Size(width, height)); +} + } // namespace namespace mojo { @@ -193,9 +209,7 @@ ash::WallpaperInfo info = client->GetActiveUserWallpaperInfo(); const gfx::ImageSkia& current_wallpaper = controller->GetWallpaperImage(); const gfx::ImageSkia& current_wallpaper_resized = - gfx::ImageSkiaOperations::CreateResizedImage( - current_wallpaper, skia::ImageOperations::RESIZE_BEST, - gfx::Size(kLocalImageThumbnailSizeDip, kLocalImageThumbnailSizeDip)); + GetResizedImage(current_wallpaper); const GURL& gurl = GURL(webui::GetBitmapDataUrl(*current_wallpaper_resized.bitmap())); std::vector<std::string> attribution;
diff --git a/chrome/browser/attribution_reporting/android/internal/java/src/org/chromium/chrome/browser/attribution_reporting/InputEventValidatorManualTest.java b/chrome/browser/attribution_reporting/android/internal/java/src/org/chromium/chrome/browser/attribution_reporting/InputEventValidatorManualTest.java index 4559fdf..8d96109 100644 --- a/chrome/browser/attribution_reporting/android/internal/java/src/org/chromium/chrome/browser/attribution_reporting/InputEventValidatorManualTest.java +++ b/chrome/browser/attribution_reporting/android/internal/java/src/org/chromium/chrome/browser/attribution_reporting/InputEventValidatorManualTest.java
@@ -17,7 +17,7 @@ import org.chromium.base.ThreadUtils; import org.chromium.base.test.util.Manual; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; -import org.chromium.ui.test.util.DummyUiActivityTestCase; +import org.chromium.chrome.test.DummyUiChromeActivityTestCase; import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicReference; @@ -32,7 +32,7 @@ * These tests only work on R+. */ @RunWith(ChromeJUnit4ClassRunner.class) -public class InputEventValidatorManualTest extends DummyUiActivityTestCase { +public class InputEventValidatorManualTest extends DummyUiChromeActivityTestCase { private String mPackageName = "com.android.packageName"; private byte mPackageMac[];
diff --git a/chrome/browser/browser_features.cc b/chrome/browser/browser_features.cc index 8f75874..97989a3 100644 --- a/chrome/browser/browser_features.cc +++ b/chrome/browser/browser_features.cc
@@ -30,6 +30,11 @@ const char kPromoBrowserCommandIdParam[] = "PromoBrowserCommandIdParam"; #if BUILDFLAG(IS_CHROMEOS_ASH) +// Enables reading and writing PWA notification permissions from quick settings +// menu. +const base::Feature kQuickSettingsPWANotifications{ + "QuickSettingsPWA", base::FEATURE_DISABLED_BY_DEFAULT}; + // Enables being able to zoom a web page by double tapping in Chrome OS tablet // mode. const base::Feature kDoubleTapToZoomInTabletMode{
diff --git a/chrome/browser/browser_features.h b/chrome/browser/browser_features.h index 7a0a22d9..b6a67eb 100644 --- a/chrome/browser/browser_features.h +++ b/chrome/browser/browser_features.h
@@ -26,6 +26,7 @@ #if BUILDFLAG(IS_CHROMEOS_ASH) extern const base::Feature kDoubleTapToZoomInTabletMode; +extern const base::Feature kQuickSettingsPWANotifications; #endif #if !defined(OS_ANDROID)
diff --git a/chrome/browser/cart/fetch_discount_worker.cc b/chrome/browser/cart/fetch_discount_worker.cc index ec650fb..fa7ce12 100644 --- a/chrome/browser/cart/fetch_discount_worker.cc +++ b/chrome/browser/cart/fetch_discount_worker.cc
@@ -20,7 +20,6 @@ &ntp_features::kNtpChromeCartModule, "delay-fetch-discount", base::TimeDelta::FromHours(6)); -const int kImmediateFetchSec = 0; } // namespace CartLoader::CartLoader(Profile* profile) @@ -78,27 +77,23 @@ // Post a delay task to avoid an infinite loop for creating the CartService. // Since CartLoader and CartDiscountUpdater both depend on CartService. content::GetUIThreadTaskRunner({base::TaskPriority::BEST_EFFORT}) - ->PostDelayedTask( - FROM_HERE, - base::BindOnce(&FetchDiscountWorker::PrepareToFetch, - weak_ptr_factory_.GetWeakPtr(), - base::TimeDelta::FromSeconds(kImmediateFetchSec)), - delay); + ->PostDelayedTask(FROM_HERE, + base::BindOnce(&FetchDiscountWorker::PrepareToFetch, + weak_ptr_factory_.GetWeakPtr()), + delay); } -void FetchDiscountWorker::PrepareToFetch(base::TimeDelta delay_fetch) { +void FetchDiscountWorker::PrepareToFetch() { DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); // Load all active carts. - auto cart_loaded_callback = - base::BindOnce(&FetchDiscountWorker::ReadyToFetch, - weak_ptr_factory_.GetWeakPtr(), std::move(delay_fetch)); + auto cart_loaded_callback = base::BindOnce(&FetchDiscountWorker::ReadyToFetch, + weak_ptr_factory_.GetWeakPtr()); auto loader = cart_loader_and_updater_factory_->createCartLoader(); loader->LoadAllCarts(std::move(cart_loaded_callback)); } void FetchDiscountWorker::ReadyToFetch( - base::TimeDelta delay_fetch, bool success, std::vector<CartDB::KeyAndValue> proto_pairs) { DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); @@ -109,12 +104,11 @@ base::BindOnce(&FetchDiscountWorker::AfterDiscountFetched, weak_ptr_factory_.GetWeakPtr()); - backend_task_runner_->PostDelayedTask( + backend_task_runner_->PostTask( FROM_HERE, base::BindOnce(&FetchInBackground, std::move(pending_factory), std::move(fetcher), std::move(done_fetching_callback), - std::move(proto_pairs)), - delay_fetch); + std::move(proto_pairs))); } void FetchDiscountWorker::FetchInBackground( @@ -205,6 +199,6 @@ ntp_features::kNtpChromeCartModuleAbandonedCartDiscountParam, false)) { // Continue to work - PrepareToFetch(kDelayFetchParam.Get()); + Start(kDelayFetchParam.Get()); } }
diff --git a/chrome/browser/cart/fetch_discount_worker.h b/chrome/browser/cart/fetch_discount_worker.h index 8793f2e..97fae3c 100644 --- a/chrome/browser/cart/fetch_discount_worker.h +++ b/chrome/browser/cart/fetch_discount_worker.h
@@ -55,13 +55,14 @@ // // UI Thread | backend_task_runner_ // =========================================== -// 1) PrepareToFetch | -// 2) ReadyToFetch | -// 3) | FetchInBackground -// 4) | DoneFetchingInBackground -// 5) AfterDiscountFetched | -// 6) OnUpdatingDiscounts | -// 7) Restart PrepareToFetch| +// 1) Start | +// 2) PrepareToFetch (delay)| +// 3) ReadyToFetch | +// 4) | FetchInBackground +// 5) | DoneFetchingInBackground +// 6) AfterDiscountFetched | +// 7) OnUpdatingDiscounts | +// 8) Start | // TODO(meiliang): Add an API to allow ending the work earlier. e.g. when user // has hidden the cart module. @@ -93,13 +94,11 @@ // This is run in the UI thread, it creates a `CartLoader` and loads all // active carts. - void PrepareToFetch(base::TimeDelta delay_fetch); + void PrepareToFetch(); // This is run in the UI thread, it posts the discount fetching work, - // FetchInBackground(), to another thread as a delayed background task. - void ReadyToFetch(base::TimeDelta delay_fetch, - bool success, - std::vector<CartDB::KeyAndValue> proto_pairs); + // FetchInBackground(), to another thread as a background task. + void ReadyToFetch(bool success, std::vector<CartDB::KeyAndValue> proto_pairs); // TODO(crbug.com/1207197): Change these two static method to anonymous // namespace in the cc file. This is run in a background thread, it fetches
diff --git a/chrome/browser/cart/fetch_discount_worker_unittest.cc b/chrome/browser/cart/fetch_discount_worker_unittest.cc index ec17b0a..b2b0b17 100644 --- a/chrome/browser/cart/fetch_discount_worker_unittest.cc +++ b/chrome/browser/cart/fetch_discount_worker_unittest.cc
@@ -3,9 +3,12 @@ // found in the LICENSE file. #include "chrome/browser/cart/fetch_discount_worker.h" +#include "base/test/scoped_feature_list.h" +#include "base/test/task_environment.h" #include "chrome/browser/cart/cart_discount_fetcher.h" #include "chrome/browser/endpoint_fetcher/endpoint_fetcher.h" #include "chrome/test/base/testing_profile.h" +#include "components/search/ntp_features.h" #include "content/public/test/browser_task_environment.h" #include "net/traffic_annotation/network_traffic_annotation_test_helper.h" #include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h" @@ -78,17 +81,25 @@ std::unique_ptr<network::PendingSharedURLLoaderFactory> pending_factory, CartDiscountFetcherCallback callback, std::vector<CartDB::KeyAndValue> proto_pairs) override { - std::move(callback).Run(std::move(fake_result_)); + FakeCartDiscountFetcher::fetcher_fetch_count_++; + std::move(callback).Run(fake_result_); } void SetFakeFetcherResult(CartDiscountFetcher::CartDiscountMap fake_result) { fake_result_ = std::move(fake_result); } + static int GetFetchCount() { return fetcher_fetch_count_; } + + static void ClearFetchCount() { fetcher_fetch_count_ = 0; } + private: CartDiscountFetcher::CartDiscountMap fake_result_; + static int fetcher_fetch_count_; }; +int FakeCartDiscountFetcher::fetcher_fetch_count_ = 0; + class MockCartDiscountFetcher : public CartDiscountFetcher { public: MOCK_METHOD( @@ -102,8 +113,8 @@ void DelegateToFake(CartDiscountMap fake_result) { fake_cart_discount_fetcher_.SetFakeFetcherResult(std::move(fake_result)); - ON_CALL(*this, Fetch) - .WillByDefault( + EXPECT_CALL(*this, Fetch) + .WillRepeatedly( [this](std::unique_ptr<network::PendingSharedURLLoaderFactory> pending_factory, CartDiscountFetcherCallback callback, @@ -120,16 +131,19 @@ class FakeCartDiscountFetcherFactory : public CartDiscountFetcherFactory { public: - explicit FakeCartDiscountFetcherFactory( - std::unique_ptr<CartDiscountFetcher> fakeFetcher) - : fake_fetcher_(std::move(fakeFetcher)) {} - std::unique_ptr<CartDiscountFetcher> createFetcher() override { - return std::move(fake_fetcher_); + auto fetcher = std::make_unique<MockCartDiscountFetcher>(); + fetcher->DelegateToFake(fetcher_fake_result_); + return std::move(fetcher); + } + + void SetFetcherFakeResult( + CartDiscountFetcher::CartDiscountMap fetcher_fake_result) { + fetcher_fake_result_ = std::move(fetcher_fake_result); } private: - std::unique_ptr<CartDiscountFetcher> fake_fetcher_; + CartDiscountFetcher::CartDiscountMap fetcher_fake_result_; }; class FakeCartLoader : public CartLoader { @@ -235,6 +249,12 @@ class FetchDiscountWorkerTest : public testing::Test { public: + FetchDiscountWorkerTest() { + features_.InitAndEnableFeatureWithParameters( + ntp_features::kNtpChromeCartModule, + {{ntp_features::kNtpChromeCartModuleAbandonedCartDiscountParam, + "true"}}); + } void SetUp() override { test_shared_url_loader_factory_ = base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>( @@ -246,12 +266,15 @@ std::make_unique<FakeCartLoaderAndUpdaterFactory>(&profile_); } + void TearDown() override { FakeCartDiscountFetcher::ClearFetchCount(); } + // This method transfers mock_fetcher_ ownership. Set all expectations for // mock_fetcher_ before calling this method. - void CreateCartDiscountFetcherFactory() { - fake_cart_discount_fetcher_factory_ = - std::make_unique<FakeCartDiscountFetcherFactory>( - std::move(mock_fetcher_)); + void CreateCartDiscountFetcherFactory( + CartDiscountFetcher::CartDiscountMap fetcher_fake_result) { + auto factory = std::make_unique<FakeCartDiscountFetcherFactory>(); + factory->SetFetcherFakeResult(std::move(fetcher_fake_result)); + fake_cart_discount_fetcher_factory_ = std::move(factory); } // This method transfers ownership of the following objects, please set all @@ -268,7 +291,11 @@ void CreateFakeFetchedResult() {} protected: - content::BrowserTaskEnvironment task_environment_; + // This needs to be destroyed after task_environment, so that any tasks on + // other threads that might check if features are enabled complete first. + base::test::ScopedFeatureList features_; + content::BrowserTaskEnvironment task_environment_{ + base::test::TaskEnvironment::TimeSource::MOCK_TIME}; network::TestURLLoaderFactory test_url_loader_factory_; scoped_refptr<network::SharedURLLoaderFactory> @@ -285,21 +312,10 @@ TestingProfile profile_; }; -TEST_F(FetchDiscountWorkerTest, TestStart_FetcherFetched) { - EXPECT_CALL(*mock_fetcher_, Fetch); - - CreateCartDiscountFetcherFactory(); - CreateWorker(); - - fetch_discount_worker_->Start(base::TimeDelta::FromMilliseconds(0)); - task_environment_.RunUntilIdle(); -} TEST_F(FetchDiscountWorkerTest, TestStart_EndToEnd) { CartDiscountFetcher::CartDiscountMap fake_result; - mock_fetcher_->DelegateToFake(std::move(fake_result)); - - CreateCartDiscountFetcherFactory(); + CreateCartDiscountFetcherFactory(std::move(fake_result)); CreateWorker(); fetch_discount_worker_->Start(base::TimeDelta::FromMilliseconds(0)); @@ -312,9 +328,8 @@ kMockMerchantACartUrl, MerchantIdAndDiscounts(kMockMerchantAId, kMockMerchantADiscounts, kMockMerchantAHighestPercentOff)); - mock_fetcher_->DelegateToFake(std::move(fake_result)); + CreateCartDiscountFetcherFactory(std::move(fake_result)); - CreateCartDiscountFetcherFactory(); CartDB::KeyAndValue mockMerchantACartContentKeyAndProto = std::make_pair(kMockMerchantA, kMockMerchantACartContentProto); std::vector<CartDB::KeyAndValue> loader_fake_data( @@ -338,9 +353,7 @@ TEST_F(FetchDiscountWorkerTest, TestStart_DiscountUpdatedClearDiscount) { // No discount available. CartDiscountFetcher::CartDiscountMap fake_result; - mock_fetcher_->DelegateToFake(std::move(fake_result)); - - CreateCartDiscountFetcherFactory(); + CreateCartDiscountFetcherFactory(std::move(fake_result)); // Loader fake data contatins discount. cart_db::ChromeCartContentProto cart_content_proto = BuildCartContentProto( @@ -365,3 +378,36 @@ fetch_discount_worker_->Start(base::TimeDelta::FromMilliseconds(0)); task_environment_.RunUntilIdle(); } + +TEST_F(FetchDiscountWorkerTest, TestStart_FetcherRefetched) { + CartDiscountFetcher::CartDiscountMap fake_result; + fake_result.emplace( + kMockMerchantACartUrl, + MerchantIdAndDiscounts(kMockMerchantAId, kMockMerchantADiscounts, + kMockMerchantAHighestPercentOff)); + CreateCartDiscountFetcherFactory(std::move(fake_result)); + + CartDB::KeyAndValue mockMerchantACartContentKeyAndProto = + std::make_pair(kMockMerchantA, kMockMerchantACartContentProto); + std::vector<CartDB::KeyAndValue> loader_fake_data( + 1, mockMerchantACartContentKeyAndProto); + fake_cart_loader_and_updater_factory_->setCartLoaderFakeData( + loader_fake_data); + + cart_db::ChromeCartContentProto cart_content_proto = BuildCartContentProto( + kMockMerchantA, kMockMerchantACartUrl, kMockMerchantATimestamp); + cart_db::ChromeCartContentProto updater_expected_data = AddDiscountToProto( + cart_content_proto, kMockMerchantAId, kMockMerchantADiscounts[0]); + fake_cart_loader_and_updater_factory_->setCartDiscountUpdaterExpectedData( + updater_expected_data, true, kMockMerchantAHighestPercentOff); + + CreateWorker(); + + fetch_discount_worker_->Start(base::TimeDelta::FromMilliseconds(0)); + task_environment_.FastForwardBy(base::TimeDelta::FromMilliseconds(1)); + EXPECT_EQ(1, FakeCartDiscountFetcher::GetFetchCount()); + + task_environment_.FastForwardBy(base::TimeDelta::FromHours(7)); + task_environment_.RunUntilIdle(); + EXPECT_EQ(2, FakeCartDiscountFetcher::GetFetchCount()); +}
diff --git a/chrome/browser/chrome_browser_interface_binders.cc b/chrome/browser/chrome_browser_interface_binders.cc index 5c6148e..b181c03 100644 --- a/chrome/browser/chrome_browser_interface_binders.cc +++ b/chrome/browser/chrome_browser_interface_binders.cc
@@ -617,8 +617,7 @@ #endif #if defined(OS_WIN) || defined(OS_MAC) || defined(OS_LINUX) - if (base::FeatureList::IsEnabled(features::kWebAppWindowControlsOverlay) && - !render_frame_host->GetParent()) { + if (!render_frame_host->GetParent()) { map->Add<chrome::mojom::DraggableRegions>( base::BindRepeating(&DraggableRegionsHostImpl::CreateIfAllowed)); }
diff --git a/chrome/browser/chrome_content_browser_client_receiver_bindings.cc b/chrome/browser/chrome_content_browser_client_receiver_bindings.cc index 5a6558c..759b6bb99 100644 --- a/chrome/browser/chrome_content_browser_client_receiver_bindings.cc +++ b/chrome/browser/chrome_content_browser_client_receiver_bindings.cc
@@ -30,6 +30,7 @@ #include "components/safe_browsing/buildflags.h" #include "components/safe_browsing/content/browser/mojo_safe_browsing_impl.h" #include "components/spellcheck/spellcheck_buildflags.h" +#include "components/subresource_filter/content/browser/content_subresource_filter_throttle_manager.h" #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/render_process_host.h" @@ -333,6 +334,16 @@ return true; } + if (interface_name == + subresource_filter::mojom::SubresourceFilterHost::Name_) { + subresource_filter::ContentSubresourceFilterThrottleManager::BindReceiver( + mojo::PendingAssociatedReceiver< + subresource_filter::mojom::SubresourceFilterHost>( + std::move(*handle)), + render_frame_host); + return true; + } + return false; }
diff --git a/chrome/browser/commerce/merchant_viewer/android/javatests/src/org/chromium/chrome/browser/merchant_viewer/BottomSheetToolbarViewBinderTest.java b/chrome/browser/commerce/merchant_viewer/android/javatests/src/org/chromium/chrome/browser/merchant_viewer/BottomSheetToolbarViewBinderTest.java index ec81921..f93b725f 100644 --- a/chrome/browser/commerce/merchant_viewer/android/javatests/src/org/chromium/chrome/browser/merchant_viewer/BottomSheetToolbarViewBinderTest.java +++ b/chrome/browser/commerce/merchant_viewer/android/javatests/src/org/chromium/chrome/browser/merchant_viewer/BottomSheetToolbarViewBinderTest.java
@@ -21,12 +21,12 @@ import org.chromium.base.test.UiThreadTest; import org.chromium.chrome.tab_ui.R; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; +import org.chromium.chrome.test.DummyUiChromeActivityTestCase; import org.chromium.components.url_formatter.SchemeDisplay; import org.chromium.components.url_formatter.UrlFormatter; import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.ui.modelutil.PropertyModel; import org.chromium.ui.modelutil.PropertyModelChangeProcessor; -import org.chromium.ui.test.util.DummyUiActivityTestCase; import org.chromium.url.GURL; import java.util.concurrent.atomic.AtomicBoolean; @@ -35,7 +35,7 @@ * Tests for {@link BottomSheetToolbarViewBinder}. */ @RunWith(ChromeJUnit4ClassRunner.class) -public class BottomSheetToolbarViewBinderTest extends DummyUiActivityTestCase { +public class BottomSheetToolbarViewBinderTest extends DummyUiChromeActivityTestCase { private final AtomicBoolean mIconClicked = new AtomicBoolean(); private BottomSheetToolbarView mItemView;
diff --git a/chrome/browser/commerce/merchant_viewer/android/javatests/src/org/chromium/chrome/browser/merchant_viewer/MerchantTrustMessageViewTest.java b/chrome/browser/commerce/merchant_viewer/android/javatests/src/org/chromium/chrome/browser/merchant_viewer/MerchantTrustMessageViewTest.java index b8bcce9d..12ea6c0f 100644 --- a/chrome/browser/commerce/merchant_viewer/android/javatests/src/org/chromium/chrome/browser/merchant_viewer/MerchantTrustMessageViewTest.java +++ b/chrome/browser/commerce/merchant_viewer/android/javatests/src/org/chromium/chrome/browser/merchant_viewer/MerchantTrustMessageViewTest.java
@@ -25,6 +25,7 @@ import org.chromium.base.test.util.Feature; import org.chromium.chrome.browser.merchant_viewer.proto.MerchantTrustSignalsOuterClass.MerchantTrustSignals; import org.chromium.chrome.test.ChromeJUnit4RunnerDelegate; +import org.chromium.chrome.test.DummyUiChromeActivityTestCase; import org.chromium.chrome.test.util.ChromeRenderTestRule; import org.chromium.components.messages.MessageBannerView; import org.chromium.components.messages.MessageBannerViewBinder; @@ -32,7 +33,6 @@ import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.ui.modelutil.PropertyModel; import org.chromium.ui.modelutil.PropertyModelChangeProcessor; -import org.chromium.ui.test.util.DummyUiActivityTestCase; import org.chromium.ui.test.util.NightModeTestUtils; import java.io.IOException; @@ -43,7 +43,7 @@ */ @RunWith(ParameterizedRunner.class) @ParameterAnnotations.UseRunnerDelegate(ChromeJUnit4RunnerDelegate.class) -public class MerchantTrustMessageViewTest extends DummyUiActivityTestCase { +public class MerchantTrustMessageViewTest extends DummyUiChromeActivityTestCase { @ClassParameter private static List<ParameterSet> sClassParams = new NightModeTestUtils.NightModeParams().getParameters();
diff --git a/chrome/browser/dev_ui/android/dev_ui_loader_throttle.cc b/chrome/browser/dev_ui/android/dev_ui_loader_throttle.cc index b2f7ca1..02265a1 100644 --- a/chrome/browser/dev_ui/android/dev_ui_loader_throttle.cc +++ b/chrome/browser/dev_ui/android/dev_ui_loader_throttle.cc
@@ -57,7 +57,6 @@ host == chrome::kChromeUISignInInternalsHost || host == chrome::kChromeUISiteEngagementHost || host == chrome::kChromeUISnippetsInternalsHost || - host == chrome::kChromeUISuggestionsHost || host == chrome::kChromeUISyncInternalsHost || host == chrome::kChromeUITranslateInternalsHost || host == chrome::kChromeUIUsbInternalsHost ||
diff --git a/chrome/browser/devtools/devtools_window.cc b/chrome/browser/devtools/devtools_window.cc index eccb36f..9d731a1 100644 --- a/chrome/browser/devtools/devtools_window.cc +++ b/chrome/browser/devtools/devtools_window.cc
@@ -1403,7 +1403,7 @@ return; if (is_docked_ && GetInspectedBrowserWindow()) main_web_contents_->Focus(); - else if (!is_docked_ && !browser_->window()->IsActive()) + else if (!is_docked_ && browser_ && !browser_->window()->IsActive()) browser_->window()->Activate(); } @@ -1456,7 +1456,7 @@ if (dock_requested == was_docked) return; - if (dock_requested && !was_docked) { + if (dock_requested && !was_docked && browser_) { // Detach window from the external devtools browser. It will lead to // the browser object's close and delete. Remove observer first. TabStripModel* tab_strip_model = browser_->tab_strip_model();
diff --git a/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/DownloadActivityV2Test.java b/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/DownloadActivityV2Test.java index e7b450b..daa26b0a 100644 --- a/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/DownloadActivityV2Test.java +++ b/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/DownloadActivityV2Test.java
@@ -61,6 +61,7 @@ import org.chromium.chrome.browser.preferences.Pref; import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; +import org.chromium.chrome.test.DummyUiChromeActivityTestCase; import org.chromium.components.browser_ui.modaldialog.AppModalPresenter; import org.chromium.components.embedder_support.util.UrlConstants; import org.chromium.components.feature_engagement.Tracker; @@ -76,7 +77,6 @@ import org.chromium.content_public.browser.UiThreadTaskTraits; import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.ui.modaldialog.ModalDialogManager; -import org.chromium.ui.test.util.DummyUiActivityTestCase; import org.chromium.ui.test.util.UiRestriction; import java.util.ArrayList; @@ -86,7 +86,7 @@ /** Tests the DownloadActivity home V2. */ @RunWith(ChromeJUnit4ClassRunner.class) @Restriction(UiRestriction.RESTRICTION_TYPE_PHONE) -public class DownloadActivityV2Test extends DummyUiActivityTestCase { +public class DownloadActivityV2Test extends DummyUiChromeActivityTestCase { @Mock private Tracker mTracker; @Mock
diff --git a/chrome/browser/download/notification/download_item_notification.cc b/chrome/browser/download/notification/download_item_notification.cc index 7f0f15d..6e685ad1 100644 --- a/chrome/browser/download/notification/download_item_notification.cc +++ b/chrome/browser/download/notification/download_item_notification.cc
@@ -1024,7 +1024,9 @@ return std::u16string(); if (IsScanning()) { - return l10n_util::GetStringUTF16(IDS_PROMPT_DEEP_SCANNING_APP_DOWNLOAD); + return l10n_util::GetStringFUTF16( + IDS_PROMPT_DEEP_SCANNING_APP_DOWNLOAD, + item_->GetFileNameToReportUser().LossyDisplayName()); } // The hostname. (E.g.:"example.com" or "127.0.0.1")
diff --git a/chrome/browser/download/notification/download_item_notification_unittest.cc b/chrome/browser/download/notification/download_item_notification_unittest.cc index 2bfde274..9ff94d1 100644 --- a/chrome/browser/download/notification/download_item_notification_unittest.cc +++ b/chrome/browser/download/notification/download_item_notification_unittest.cc
@@ -145,6 +145,10 @@ *download_item_notification_->notification_, /*metadata=*/nullptr); } + std::u16string GetStatusString() { + return download_item_notification_->GetStatusString(); + } + content::BrowserTaskEnvironment task_environment_; std::unique_ptr<TestingProfileManager> profile_manager_; @@ -324,6 +328,7 @@ )"); EXPECT_CALL(*download_item_, OpenDownload()).Times(0); EXPECT_CALL(*download_item_, SetOpenWhenComplete(true)).Times(1); + EXPECT_EQ(u"TITLE.bin is being scanned.", GetStatusString()); download_item_notification_->Click(absl::nullopt, absl::nullopt); // Can be opened while scanning. @@ -337,6 +342,7 @@ } )"); EXPECT_CALL(*download_item_, OpenDownload()).Times(1); + EXPECT_EQ(u"TITLE.bin is being scanned.", GetStatusString()); download_item_notification_->Click(absl::nullopt, absl::nullopt); // Scanning finished, warning.
diff --git a/chrome/browser/enterprise/connectors/analysis/content_analysis_delegate.cc b/chrome/browser/enterprise/connectors/analysis/content_analysis_delegate.cc index 93042fff..6db49fe 100644 --- a/chrome/browser/enterprise/connectors/analysis/content_analysis_delegate.cc +++ b/chrome/browser/enterprise/connectors/analysis/content_analysis_delegate.cc
@@ -5,10 +5,13 @@ #include "chrome/browser/enterprise/connectors/analysis/content_analysis_delegate.h" #include <algorithm> +#include <atomic> #include <numeric> #include <string> #include <utility> +#include "base/bind.h" +#include "base/command_line.h" #include "base/feature_list.h" #include "base/files/file_path.h" #include "base/memory/scoped_refptr.h" @@ -17,6 +20,7 @@ #include "base/no_destructor.h" #include "base/strings/string_number_conversions.h" #include "base/strings/utf_string_conversions.h" +#include "base/task/post_job.h" #include "base/task/post_task.h" #include "base/task/task_traits.h" #include "base/task/thread_pool.h" @@ -138,6 +142,26 @@ : safe_browsing::EventResult::BLOCKED); } +constexpr char kMaxFileOpeningThreads[] = "wp-max-file-opening-threads"; +constexpr size_t kDefaultMaxFileOpeningThreads = 5; + +size_t GetMaxFileOpeningThreads() { + base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); + if (command_line->HasSwitch(kMaxFileOpeningThreads)) { + int parsed_max; + if (base::StringToInt( + command_line->GetSwitchValueASCII(kMaxFileOpeningThreads), + &parsed_max) && + parsed_max > 0) { + return parsed_max; + } else { + LOG(ERROR) << kMaxFileOpeningThreads << " had invalid value"; + } + } + + return kDefaultMaxFileOpeningThreads; +} + } // namespace ContentAnalysisDelegate::Data::Data() = default; @@ -162,7 +186,55 @@ ContentAnalysisDelegate::FileContents& ContentAnalysisDelegate::FileContents::operator=( ContentAnalysisDelegate::FileContents&& other) = default; -ContentAnalysisDelegate::~ContentAnalysisDelegate() = default; + +ContentAnalysisDelegate::FileOpeningTask::FileOpeningTask() = default; +ContentAnalysisDelegate::FileOpeningTask::~FileOpeningTask() = default; + +ContentAnalysisDelegate::FileOpeningJob::FileOpeningJob( + std::vector<FileOpeningTask> tasks) + : tasks_(std::move(tasks)), max_threads_flag_(GetMaxFileOpeningThreads()) { + num_unopened_files_ = tasks_.size(); +} + +ContentAnalysisDelegate::FileOpeningJob::~FileOpeningJob() = default; + +void ContentAnalysisDelegate::FileOpeningJob::ProcessNextTask( + base::JobDelegate* job_delegate) { + // Loop over |tasks_| until one can safely be taken by this thread. + for (size_t i = 0; i < tasks_.size() && num_unopened_files() != 0 && + !job_delegate->ShouldYield(); + ++i) { + // The task's |taken| value is atomic, so exchanging it to find it used to + // be true indicates we were the not the thread that took it. + // std::memory_order_relaxed is safe here since |taken| is not synchronized + // with other state. + if (tasks_[i].taken.exchange(true, std::memory_order_relaxed)) + continue; + + // Since we know we now have taken |tasks_[i]|, we can do the file opening + // work safely. + tasks_[i].request->OpenFile(); + + // Now that the file opening work is done, |num_unopened_files_| is + // decremented atomically and we return to free the thread. + num_unopened_files_.fetch_sub(1, std::memory_order_relaxed); + return; + } +} + +size_t ContentAnalysisDelegate::FileOpeningJob::num_unopened_files() { + return num_unopened_files_.load(std::memory_order_relaxed); +} + +size_t ContentAnalysisDelegate::FileOpeningJob::MaxConcurrentThreads( + size_t /*worker_count*/) { + return std::min(num_unopened_files(), max_threads_flag_); +} + +ContentAnalysisDelegate::~ContentAnalysisDelegate() { + if (file_opening_job_handle_) + file_opening_job_handle_.Cancel(); +} void ContentAnalysisDelegate::BypassWarnings() { if (callback_.is_null()) @@ -486,10 +558,25 @@ safe_browsing::IncrementCrashKey( safe_browsing::ScanningCrashKey::PENDING_FILE_UPLOADS, data_.paths.size()); - safe_browsing::IncrementCrashKey( - safe_browsing::ScanningCrashKey::TOTAL_FILE_UPLOADS, data_.paths.size()); - for (const base::FilePath& path : data_.paths) - PrepareFileRequest(path); + if (!data_.paths.empty()) { + safe_browsing::IncrementCrashKey( + safe_browsing::ScanningCrashKey::TOTAL_FILE_UPLOADS, + data_.paths.size()); + + std::vector<FileOpeningTask> tasks(data_.paths.size()); + for (size_t i = 0; i < data_.paths.size(); ++i) + tasks[i].request = PrepareFileRequest(data_.paths[i]); + + file_opening_job_ = std::make_unique<FileOpeningJob>(std::move(tasks)); + file_opening_job_handle_ = base::PostJob( + FROM_HERE, + {base::TaskPriority::USER_VISIBLE, base::MayBlock(), + base::ThreadPolicy::PREFER_BACKGROUND}, + base::BindRepeating(&FileOpeningJob::ProcessNextTask, + base::Unretained(file_opening_job_.get())), + base::BindRepeating(&FileOpeningJob::MaxConcurrentThreads, + base::Unretained(file_opening_job_.get()))); + } data_uploaded_ = true; // Do not add code under this comment. The above line should be the last thing @@ -529,17 +616,20 @@ } } -void ContentAnalysisDelegate::PrepareFileRequest(const base::FilePath& path) { +safe_browsing::FileAnalysisRequest* ContentAnalysisDelegate::PrepareFileRequest( + const base::FilePath& path) { auto request = std::make_unique<safe_browsing::FileAnalysisRequest>( data_.settings, path, path.BaseName(), /*mime_type*/ "", + /* delay_opening_file */ true, base::BindOnce(&ContentAnalysisDelegate::FileRequestCallback, weak_ptr_factory_.GetWeakPtr(), path)); safe_browsing::FileAnalysisRequest* request_raw = request.get(); PrepareRequest(enterprise_connectors::FILE_ATTACHED, request_raw); - request_raw->GetRequestData( base::BindOnce(&ContentAnalysisDelegate::OnGotFileInfo, weak_ptr_factory_.GetWeakPtr(), std::move(request), path)); + + return request_raw; } void ContentAnalysisDelegate::PrepareRequest(
diff --git a/chrome/browser/enterprise/connectors/analysis/content_analysis_delegate.h b/chrome/browser/enterprise/connectors/analysis/content_analysis_delegate.h index cc78a14..00077f9c 100644 --- a/chrome/browser/enterprise/connectors/analysis/content_analysis_delegate.h +++ b/chrome/browser/enterprise/connectors/analysis/content_analysis_delegate.h
@@ -5,7 +5,9 @@ #ifndef CHROME_BROWSER_ENTERPRISE_CONNECTORS_ANALYSIS_CONTENT_ANALYSIS_DELEGATE_H_ #define CHROME_BROWSER_ENTERPRISE_CONNECTORS_ANALYSIS_CONTENT_ANALYSIS_DELEGATE_H_ +#include <atomic> #include <memory> +#include <queue> #include <string> #include <utility> #include <vector> @@ -14,12 +16,14 @@ #include "base/files/file_path.h" #include "base/macros.h" #include "base/memory/weak_ptr.h" +#include "base/task/post_job.h" #include "base/time/time.h" #include "chrome/browser/enterprise/connectors/analysis/content_analysis_delegate_base.h" #include "chrome/browser/enterprise/connectors/common.h" #include "chrome/browser/enterprise/connectors/connectors_manager.h" #include "chrome/browser/safe_browsing/cloud_content_scanning/binary_upload_service.h" #include "chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_utils.h" +#include "chrome/browser/safe_browsing/cloud_content_scanning/file_analysis_request.h" #include "chrome/browser/ui/tab_modal_confirm_dialog.h" #include "chrome/browser/ui/tab_modal_confirm_dialog_delegate.h" #include "components/enterprise/common/proto/connectors.pb.h" @@ -135,6 +139,38 @@ std::string sha256; }; + // Struct to store information required by a synchronized file opening task. + struct FileOpeningTask { + FileOpeningTask(); + ~FileOpeningTask(); + + safe_browsing::FileAnalysisRequest* request = nullptr; + std::atomic_bool taken{false}; + }; + + // Class to encapsulate the process of opening multiple files in parallel. + class FileOpeningJob { + public: + explicit FileOpeningJob(std::vector<FileOpeningTask> tasks); + ~FileOpeningJob(); + + // Synchronized getter method to read |num_unopened_files_|. + size_t num_unopened_files(); + + // Processes the next file opening task that hasn't been taken so far. + void ProcessNextTask(base::JobDelegate* job_delegate); + + // Returns the maximum number of threads that should be opening files. This + // is dependant on the corresponding flags and on the number of remaining + // files to open. + size_t MaxConcurrentThreads(size_t /*worker_count*/); + + private: + std::atomic_size_t num_unopened_files_; + std::vector<FileOpeningTask> tasks_; + size_t max_threads_flag_; + }; + // Callback used with CreateForWebContents() that informs caller of verdict // of deep scans. using CompletionCallback = @@ -242,8 +278,8 @@ // Prepares an upload request for the file at |path|. If the file // cannot be uploaded it will have a failure verdict added to |result_|. - // Virtual so that it can be overridden in tests. - void PrepareFileRequest(const base::FilePath& path); + safe_browsing::FileAnalysisRequest* PrepareFileRequest( + const base::FilePath& path); // Adds required fields to |request| before sending it to the binary upload // service. @@ -349,6 +385,13 @@ // more data should be upload for |this| at that point. bool throttled_ = false; + // Owner of the FileOpeningJob responsible for opening files on parallel + // threads. Always nullptr for non-file content scanning. + std::unique_ptr<FileOpeningJob> file_opening_job_; + + // Points to a job initialized with |file_opening_job_| if it is not null. + base::JobHandle file_opening_job_handle_; + base::TimeTicks upload_start_time_; base::WeakPtrFactory<ContentAnalysisDelegate> weak_ptr_factory_{this};
diff --git a/chrome/browser/enterprise/connectors/file_system/box_uploader.cc b/chrome/browser/enterprise/connectors/file_system/box_uploader.cc index c734394..926c89f 100644 --- a/chrome/browser/enterprise/connectors/file_system/box_uploader.cc +++ b/chrome/browser/enterprise/connectors/file_system/box_uploader.cc
@@ -224,9 +224,8 @@ DCHECK(reroute_info().file_id().empty()); DCHECK(!file_id.empty()); reroute_info().set_file_id(file_id); - SendProgressUpdate(); } - + SendProgressUpdate(); PostDeleteFileTask(reason); }
diff --git a/chrome/browser/enterprise/connectors/file_system/box_uploader_test_helper.cc b/chrome/browser/enterprise/connectors/file_system/box_uploader_test_helper.cc index 4a7412d..6ccb39a 100644 --- a/chrome/browser/enterprise/connectors/file_system/box_uploader_test_helper.cc +++ b/chrome/browser/enterprise/connectors/file_system/box_uploader_test_helper.cc
@@ -153,7 +153,7 @@ void BoxUploaderTestBase::OnProgressUpdate( const download::DownloadItemRenameProgressUpdate& update) { ++progress_update_cb_called_; - validated_file_name_ = update.target_file_name; + file_name_reported_back_ = update.target_file_name; } void BoxUploaderTestBase::OnUploaderFinished( @@ -164,7 +164,7 @@ reason_ = reason; DLOG(INFO) << reason; if (upload_success_) - validated_file_name_ = final_name; + file_name_reported_back_ = final_name; Quit(); }
diff --git a/chrome/browser/enterprise/connectors/file_system/box_uploader_test_helper.h b/chrome/browser/enterprise/connectors/file_system/box_uploader_test_helper.h index 53966bc..e28e862 100644 --- a/chrome/browser/enterprise/connectors/file_system/box_uploader_test_helper.h +++ b/chrome/browser/enterprise/connectors/file_system/box_uploader_test_helper.h
@@ -86,7 +86,7 @@ bool upload_success_{false}; download::DownloadInterruptReason reason_{ download::DOWNLOAD_INTERRUPT_REASON_NONE}; - base::FilePath validated_file_name_; + base::FilePath file_name_reported_back_; private: content::BrowserTaskEnvironment task_environment_;
diff --git a/chrome/browser/enterprise/connectors/file_system/box_uploader_unittest.cc b/chrome/browser/enterprise/connectors/file_system/box_uploader_unittest.cc index 7745060..37d8da7b 100644 --- a/chrome/browser/enterprise/connectors/file_system/box_uploader_unittest.cc +++ b/chrome/browser/enterprise/connectors/file_system/box_uploader_unittest.cc
@@ -153,8 +153,7 @@ // InterceptedPreUpload(), so file was not deleted. EXPECT_EQ(upload_initiated_, base::PathExists(GetFilePath())); // Only 1 update in StartUpload() when PreflightCheck succeeds. - EXPECT_LE(progress_update_cb_called_, 1); - EXPECT_EQ(progress_update_cb_called_, upload_initiated_); + EXPECT_EQ(progress_update_cb_called_, 1); } void InterceptedPreUpload() { @@ -280,6 +279,7 @@ class BoxUploader_PreflightCheckTest : public BoxUploaderTest { public: + using AttemptCount = BoxUploader::UploadAttemptCount; void SetUp() override { // Assume there is already a folder_id stored in prefs; will skip directly // to preflight check. @@ -300,7 +300,7 @@ ASSERT_EQ(authentication_retry_, 0); EXPECT_EQ(kFileSystemBoxFolderIdInPref, uploader_->GetFolderIdForTesting()); EXPECT_EQ(kUploadFileName, uploader_->GetUploadFileName().value()); - EXPECT_EQ(kUploadFileName, validated_file_name_.value()); + EXPECT_EQ(kUploadFileName, file_name_reported_back_.value()); ASSERT_TRUE(upload_initiated_); EXPECT_FALSE(download_thread_cb_called_); // InterceptedPreUpload() above. } @@ -337,9 +337,8 @@ // --------------------------------------------------------------------------- EXPECT_EQ(uploader_->GetUploadFileName().MaybeAsASCII(), expected_name); - histogram_tester.ExpectUniqueSample( - kUniquifierUmaLabel, BoxUploader::UploadAttemptCount::kTimestampBasedName, - 1); + histogram_tester.ExpectUniqueSample(kUniquifierUmaLabel, + AttemptCount::kTimestampBasedName, 1); EXPECT_FALSE(download_thread_cb_called_); // InterceptedPreUpload() above. } @@ -358,15 +357,15 @@ RunWithQuitClosure(); ASSERT_EQ(authentication_retry_, 0); EXPECT_EQ(uploader_->GetFolderIdForTesting(), kFileSystemBoxFolderIdInPref); - EXPECT_TRUE(validated_file_name_.empty()) << validated_file_name_; ASSERT_FALSE(upload_initiated_); // The last tried filename is timestamp based even though it also fails. - EXPECT_EQ(uploader_->GetUploadFileName().MaybeAsASCII(), - "box_uploader_test.abandoned.txt"); - histogram_tester.ExpectUniqueSample( - kUniquifierUmaLabel, BoxUploader::UploadAttemptCount::kAbandonedUpload, - 1); + const base::FilePath expected_file_name( + FILE_PATH_LITERAL("box_uploader_test.abandoned.txt")); + EXPECT_EQ(uploader_->GetUploadFileName(), expected_file_name); + EXPECT_EQ(file_name_reported_back_, expected_file_name); + histogram_tester.ExpectUniqueSample(kUniquifierUmaLabel, + AttemptCount::kAbandonedUpload, 1); EXPECT_TRUE(download_thread_cb_called_) << "Conflict, including with timestamp, should terminate flow."; } @@ -424,7 +423,7 @@ EXPECT_EQ(uploader_->GetFolderIdForTesting(), kFileSystemBoxFindFolderResponseFolderId); EXPECT_EQ(kUploadFileName, uploader_->GetUploadFileName().value()); - EXPECT_EQ(kUploadFileName, validated_file_name_.value()); + EXPECT_EQ(kUploadFileName, file_name_reported_back_.value()); ASSERT_TRUE(upload_initiated_); EXPECT_FALSE(download_thread_cb_called_); // InterceptedPreUpload() above. } @@ -459,7 +458,7 @@ EXPECT_EQ(uploader_->GetFolderIdForTesting(), kFileSystemBoxCreateFolderResponseFolderId); EXPECT_EQ(kUploadFileName, uploader_->GetUploadFileName().value()); - EXPECT_EQ(kUploadFileName, validated_file_name_.value()); + EXPECT_EQ(kUploadFileName, file_name_reported_back_.value()); ASSERT_TRUE(upload_initiated_); EXPECT_FALSE(download_thread_cb_called_); // InterceptedPreUpload() above. } @@ -492,7 +491,7 @@ ASSERT_EQ(authentication_retry_, 1); EXPECT_EQ(uploader_->GetFolderIdForTesting(), kFileSystemBoxFolderIdInPref); EXPECT_EQ(kUploadFileName, uploader_->GetUploadFileName().value()); - EXPECT_EQ(kUploadFileName, validated_file_name_.value()); + EXPECT_EQ(kUploadFileName, file_name_reported_back_.value()); ASSERT_TRUE(upload_initiated_); EXPECT_FALSE(download_thread_cb_called_); // InterceptedPreUpload() above. } @@ -559,8 +558,9 @@ // If upload was not initiated due to some error, file should've been // deleted as part of error handling. EXPECT_FALSE(base::PathExists(GetFilePath())); - // Only 1 update in StartUpload() when PreflightCheck succeeds. - EXPECT_LE(progress_update_cb_called_, 1); + // 1 update in StartUpload() when PreflightCheck succeeds, and 1 update in + // OnApiCallFlowDone(). + EXPECT_EQ(progress_update_cb_called_, 2); } std::unique_ptr<BoxUploaderForNetErrorTest> uploader_; }; @@ -616,6 +616,7 @@ void TearDown() override { EXPECT_EQ(authentication_retry_, 0); + EXPECT_EQ(progress_update_cb_called_ > 0, download_thread_cb_called_); EXPECT_FALSE(test_item_.GetFileExternallyRemoved()); } @@ -630,6 +631,7 @@ RunWithQuitClosure(); EXPECT_FALSE(base::PathExists(GetFilePath())); // Make sure file is deleted. + EXPECT_TRUE(progress_update_cb_called_); ASSERT_TRUE(upload_success_); } @@ -643,6 +645,7 @@ RunWithQuitClosure(); EXPECT_FALSE(base::PathExists(GetFilePath())) << "No file should be created."; + EXPECT_TRUE(progress_update_cb_called_); EXPECT_TRUE(download_thread_cb_called_); ASSERT_FALSE(upload_success_); } @@ -656,6 +659,7 @@ RunWithQuitClosure(); EXPECT_FALSE(base::PathExists(GetFilePath())); // Make sure file is deleted. + EXPECT_TRUE(progress_update_cb_called_); EXPECT_TRUE(download_thread_cb_called_); ASSERT_FALSE(upload_success_); } @@ -668,6 +672,7 @@ RunWithQuitClosure(); EXPECT_FALSE(base::PathExists(GetFilePath())); // Make sure file is deleted. + EXPECT_TRUE(progress_update_cb_called_); EXPECT_TRUE(download_thread_cb_called_); ASSERT_FALSE(upload_success_); } @@ -696,7 +701,7 @@ ASSERT_FALSE(authentication_retry_); EXPECT_TRUE(download_thread_cb_called_); - EXPECT_EQ(progress_update_cb_called_, 1); + EXPECT_TRUE(progress_update_cb_called_); ASSERT_TRUE(upload_success_); EXPECT_FALSE(base::PathExists(GetFilePath())); // File deleted. } @@ -719,7 +724,7 @@ ASSERT_FALSE(authentication_retry_); EXPECT_FALSE(download_thread_cb_called_); // No upload call was made. - EXPECT_EQ(progress_update_cb_called_, 0); + EXPECT_FALSE(progress_update_cb_called_); EXPECT_FALSE(base::PathExists(GetFilePath())); // File not created. }
diff --git a/chrome/browser/enterprise/connectors/file_system/rename_handler.cc b/chrome/browser/enterprise/connectors/file_system/rename_handler.cc index d2ad2245..3623fa4 100644 --- a/chrome/browser/enterprise/connectors/file_system/rename_handler.cc +++ b/chrome/browser/enterprise/connectors/file_system/rename_handler.cc
@@ -88,20 +88,20 @@ // static std::unique_ptr<download::DownloadItemRenameHandler> -FileSystemRenameHandler::Create(download::DownloadItem* download_item, - FileSystemSettings settings) { - return std::make_unique<FileSystemRenameHandler>(download_item, - std::move(settings)); -} - -// static -std::unique_ptr<download::DownloadItemRenameHandler> FileSystemRenameHandler::CreateIfNeeded(download::DownloadItem* download_item) { - auto settings = IsEnabled(download_item); - if (!settings.has_value()) - return nullptr; - - return Create(download_item, std::move(settings.value())); + if (download_item->GetState() == download::DownloadItem::COMPLETE) { + return download_item->GetRerouteInfo().IsInitialized() + ? std::make_unique<FileSystemRenameHandler>(download_item) + : nullptr; + } + // TODO(https://crbug.com/1213761) Resume upload if state is IN_PROGRESS, and + // perhaps also INTERRUPTED and CANCELLED. + absl::optional<FileSystemSettings> settings = IsEnabled(download_item); + if (settings.has_value()) { + return std::make_unique<FileSystemRenameHandler>( + download_item, std::move(settings.value())); + } + return nullptr; } // The only permitted use of |download_item| in this class other than the ctor @@ -116,6 +116,11 @@ DCHECK_EQ(settings_.service_provider, kBoxProviderName); } +FileSystemRenameHandler::FileSystemRenameHandler( + download::DownloadItem* download_item) + : download::DownloadItemRenameHandler(download_item), + uploader_(BoxUploader::Create(download_item)) {} + FileSystemRenameHandler::~FileSystemRenameHandler() = default; void FileSystemRenameHandler::Start(ProgressUpdateCallback progress_update_cb,
diff --git a/chrome/browser/enterprise/connectors/file_system/rename_handler.h b/chrome/browser/enterprise/connectors/file_system/rename_handler.h index 66149e5..165190f 100644 --- a/chrome/browser/enterprise/connectors/file_system/rename_handler.h +++ b/chrome/browser/enterprise/connectors/file_system/rename_handler.h
@@ -40,6 +40,7 @@ FileSystemRenameHandler(download::DownloadItem* download_item, FileSystemSettings settings); + explicit FileSystemRenameHandler(download::DownloadItem* download_item); ~FileSystemRenameHandler() override; protected: @@ -72,10 +73,6 @@ static absl::optional<FileSystemSettings> IsEnabled( download::DownloadItem* download_item); - static std::unique_ptr<download::DownloadItemRenameHandler> Create( - download::DownloadItem* download_item, - FileSystemSettings settings); - void StartInternal(std::string access_token = std::string()); scoped_refptr<network::SharedURLLoaderFactory> GetURLLoaderFactory( content::BrowserContext* context);
diff --git a/chrome/browser/enterprise/connectors/file_system/rename_handler_unittest.cc b/chrome/browser/enterprise/connectors/file_system/rename_handler_unittest.cc index aff91b5e..ac95a1e32 100644 --- a/chrome/browser/enterprise/connectors/file_system/rename_handler_unittest.cc +++ b/chrome/browser/enterprise/connectors/file_system/rename_handler_unittest.cc
@@ -107,6 +107,31 @@ ASSERT_EQ(enable_feature_flag(), handler.get() != nullptr); } +TEST_P(RenameHandlerCreateTest, Completed_LoadFromRerouteInfo) { + DownloadItemForTest test_item_(FILE_PATH_LITERAL("handler_loaded_info.txt")); + test_item_.SetState(DownloadItemForTest::DownloadState::COMPLETE); + + DownloadItemRerouteInfo rerouted_info; + rerouted_info.set_service_provider(BoxUploader::kServiceProvider); + rerouted_info.mutable_box()->set_file_id("12345"); + test_item_.SetRerouteInfo(rerouted_info); + + // Handler should be created regardless of settings/policies since item upload + // was already completed. + auto handler = RenameHandler::CreateIfNeeded(&test_item_); + ASSERT_TRUE(handler.get()); +} + +TEST_P(RenameHandlerCreateTest, Completed_NoRerouteInfo) { + DownloadItemForTest test_item_(FILE_PATH_LITERAL("handler_loaded_info.txt")); + test_item_.SetState(DownloadItemForTest::DownloadState::COMPLETE); + + // Handler should NOT be created regardless of settings/policies since item + // download was already completed without upload previously. + auto handler = RenameHandler::CreateIfNeeded(&test_item_); + ASSERT_FALSE(handler.get()); +} + INSTANTIATE_TEST_CASE_P(, RenameHandlerCreateTest, testing::Bool()); class RenameHandlerCreateTest_ByUrl : public RenameHandlerCreateTestBase { @@ -314,17 +339,22 @@ ASSERT_TRUE(base::WriteFile(item_.GetFullPath(), "RenameHandlerTest")) << "Failed to create " << item_.GetFullPath(); + handler_ = CreateHandler(); + } + + virtual std::unique_ptr<RenameHandlerForTest> CreateHandler() { ConnectorsService* service = ConnectorsServiceFactory::GetForBrowserContext( content::DownloadItemUtils::GetBrowserContext(&item_)); auto settings = service->GetFileSystemSettings( item_.GetURL(), FileSystemConnector::SEND_DOWNLOAD_TO_CLOUD); settings->service_provider = kBox; - handler_ = std::make_unique<RenameHandlerForTest>( + auto handler = std::make_unique<RenameHandlerForTest>( &item_, std::move(settings.value())); auto uploader = std::make_unique<MockUploader>(&item_); uploader_ = uploader.get(); - handler_->SetUploaderForTesting(std::move(uploader)); + handler->SetUploaderForTesting(std::move(uploader)); + return handler; } void TearDown() { @@ -356,7 +386,6 @@ } void SetUp() override { - testing::Test::SetUp(); OSCryptMocker::SetUp(); RenameHandlerTestBase::SetUp(profile_); EXPECT_CALL(*uploader(), GetDestinationFolderUrl()).Times(0); @@ -366,7 +395,6 @@ ASSERT_EQ(download_cb_reason_, uploader()->expected_reason_); RenameHandlerTestBase::TearDown(); OSCryptMocker::TearDown(); - testing::Test::TearDown(); } protected: @@ -451,7 +479,6 @@ ASSERT_EQ(download_cb_count_, 1); ASSERT_FALSE(uploaded_file_url_.is_valid()); - ASSERT_TRUE(uploaded_file_name_.empty()); // Verify that the tokens stored are not updated. std::string atoken, rtoken; @@ -503,7 +530,6 @@ ASSERT_EQ(download_cb_count_, 1); ASSERT_TRUE(uploaded_file_url_.is_empty()); - ASSERT_TRUE(uploaded_file_name_.empty()) << uploaded_file_name_; VerifyBothTokensClear(); } @@ -535,7 +561,6 @@ ASSERT_EQ(authen_cb, 2); ASSERT_EQ(download_cb_count_, 1); ASSERT_TRUE(uploaded_file_url_.is_empty()); // Notified failure to terminate. - ASSERT_TRUE(uploaded_file_name_.empty()) << uploaded_file_name_; VerifyBothTokensClear(); } @@ -557,7 +582,6 @@ ASSERT_EQ(download_cb_count_, 1); ASSERT_TRUE(uploaded_file_url_.is_empty()); // Notified failure to terminate. - ASSERT_TRUE(uploaded_file_name_.empty()) << uploaded_file_name_; } //////////////////////////////////////////////////////////////////////////////// @@ -658,7 +682,6 @@ ASSERT_EQ(download_cb_count_, 1); ASSERT_TRUE(uploaded_file_url_.is_empty()); - ASSERT_TRUE(uploaded_file_name_.empty()) << uploaded_file_name_; // Verify that uploader failure did not affect stored credentials. VerifyBothTokensSetByFetcher(); } @@ -705,7 +728,6 @@ ASSERT_EQ(download_cb_count_, 1); ASSERT_TRUE(uploaded_file_url_.is_empty()); - ASSERT_TRUE(uploaded_file_name_.empty()) << uploaded_file_name_; // Verify that access token stored is cleared. std::string atoken, rtoken; ASSERT_TRUE(GetFileSystemOAuth2Tokens(prefs(), kBox, &atoken, &rtoken)); @@ -734,7 +756,6 @@ ASSERT_EQ(download_cb_count_, 1); ASSERT_TRUE(uploaded_file_url_.is_empty()); // Notified failure to terminate. - ASSERT_TRUE(uploaded_file_name_.empty()) << uploaded_file_name_; } class RenameHandlerOpenDownloadTest : public BrowserWithTestWindowTest,
diff --git a/chrome/browser/extensions/activity_log/activity_database.cc b/chrome/browser/extensions/activity_log/activity_database.cc index edd089c..9467665 100644 --- a/chrome/browser/extensions/activity_log/activity_database.cc +++ b/chrome/browser/extensions/activity_log/activity_database.cc
@@ -39,7 +39,13 @@ ActivityDatabase::ActivityDatabase(ActivityDatabase::Delegate* delegate) : delegate_(delegate), - db_({.exclusive_locking = true, .page_size = 4096, .cache_size = 32}), + db_({ + .exclusive_locking = true, + .page_size = 4096, + .cache_size = 32, + // TODO(pwnall): Add a meta table and remove this option. + .mmap_alt_status_discouraged = true, + }), valid_db_(false), batch_mode_(true), already_closed_(false), @@ -67,9 +73,6 @@ db_.set_error_callback(base::BindRepeating( &ActivityDatabase::DatabaseErrorCallback, base::Unretained(this))); - // This db does not use [meta] table, store mmap status data elsewhere. - db_.set_mmap_alt_status(); - if (!db_.Open(db_name)) { LOG(ERROR) << db_.GetErrorMessage(); return LogInitFailure();
diff --git a/chrome/browser/extensions/content_script_tracker_browsertest.cc b/chrome/browser/extensions/content_script_tracker_browsertest.cc index 680de88..5a45d18 100644 --- a/chrome/browser/extensions/content_script_tracker_browsertest.cc +++ b/chrome/browser/extensions/content_script_tracker_browsertest.cc
@@ -277,8 +277,9 @@ } )"; dir.WriteManifest(kManifestTemplate); dir.WriteFile(FILE_PATH_LITERAL("content_script.js"), R"( - document.body.innerText = 'content script has run'; - chrome.test.sendMessage('Hello from content script!'); )"); + document.body.innerText = 'content script has run'; + chrome.test.sendMessage('Hello from content script!'); + )"); const Extension* extension = LoadExtension(dir.UnpackedPath()); ASSERT_TRUE(extension); @@ -327,6 +328,79 @@ *first_tab->GetMainFrame()->GetProcess(), extension->id())); } +// Ensure ContentScriptTracker correctly tracks script injections in frames +// which undergo non-network (i.e. no ReadyToCommitNavigation notification) +// navigations after an extension is loaded. For more details about the +// particular race condition covered by this test please see +// https://docs.google.com/document/d/1Z0-C3Bstva_-NK_bKhcyj4f2kdWjXv8pscuHre7UlSk/edit?usp=sharing +IN_PROC_BROWSER_TEST_F( + ContentScriptTrackerBrowserTest, + AboutBlankNavigationAfterLoadingExtensionMidwayThroughTest) { + // Navigate to a test page that *is* covered by `content_scripts.matches` + // manifest entry below (the extension is *not* installed at this point yet). + GURL injected_url = + embedded_test_server()->GetURL("example.com", "/title1.html"); + ui_test_utils::NavigateToURL(browser(), injected_url); + content::WebContents* first_tab = + browser()->tab_strip_model()->GetActiveWebContents(); + + // Create the test extension. + TestExtensionDir dir; + const char kManifestTemplate[] = R"( + { + "name": "ContentScriptTrackerBrowserTest - Declarative", + "version": "1.0", + "manifest_version": 2, + "permissions": [ "tabs", "<all_urls>" ], + "content_scripts": [{ + "all_frames": true, + "match_about_blank": true, + "matches": ["*://example.com/*"], + "js": ["content_script.js"], + "run_at": "document_end" + }], + "background": {"scripts": ["background_script.js"]} + } )"; + dir.WriteManifest(kManifestTemplate); + dir.WriteFile(FILE_PATH_LITERAL("background_script.js"), ""); + dir.WriteFile(FILE_PATH_LITERAL("content_script.js"), R"( + document.body.innerText = 'content script has run'; + chrome.test.sendMessage('Hello from content script!'); + )"); + + // Load the test extension. Note that the LoadExtension call below will + // internally wait for content scripts to be sent to the renderer processes + // (see ContentScriptLoadWaiter usage in the WaitForExtensionReady method). + const Extension* extension = LoadExtension(dir.UnpackedPath()); + ASSERT_TRUE(extension); + std::string extension_id = extension->id(); + + // Open a new tab with 'about:blank'. This may be tricky, because 1) the + // initial empty document commits synchronously, without going through + // ReadyToCommit step and 2) when this test was being written, the initial + // 'about:blank' did not send a DidCommit IPC to the Browser process. + ExtensionTestMessageListener listener("Hello from content script!", false); + content::WebContentsAddedObserver popup_observer; + ExecuteScriptAsync(first_tab, "window.open('about:blank', '_blank')"); + + // Verify that the content script has been run. + ASSERT_TRUE(listener.WaitUntilSatisfied()); + content::WebContents* popup = popup_observer.GetWebContents(); + EXPECT_EQ("content script has run", + content::EvalJs(popup, "document.body.innerText")); + + // Verify that content script didn't run in the opener. This mostly verifies + // the test setup/steps. + EXPECT_NE("content script has run", + content::EvalJs(first_tab, "document.body.innerText")); + + // Verify that ContentScriptTracker correctly says that a content script has + // been run in the `popup`. This verifies product code - this is the main + // verification in this test. + EXPECT_TRUE(ContentScriptTracker::DidProcessRunContentScriptFromExtension( + *popup->GetMainFrame()->GetProcess(), extension_id)); +} + class ContentScriptTrackerMatchOriginAsFallbackBrowserTest : public ContentScriptTrackerBrowserTest { public:
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json index baa10ae..ad8f6061c 100644 --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json
@@ -4589,6 +4589,11 @@ "expiry_milestone": 95 }, { + "name": "quick-settings-pwa-notifications", + "owners": [ "yulunwu" ], + "expiry_milestone": 100 + }, + { "name": "quiet-notification-prompts", "owners": [ "engedy", "mkwst", "andypaicu", "hkamila" ], "expiry_milestone": 93
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index 7495b4a4..acd3e38 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -4313,6 +4313,13 @@ "If Enabled, double tapping in webpages while in tablet mode will zoom the " "page."; +const char kQuickSettingsPWANotificationsName[] = + "Enable setting of PWA notification permissions in quick settings "; +const char kQuickSettingsPWANotificationsDescription[] = + "Replace website notification permissions with PWA notification " + "permissions in the quick settings menu. Website notification permissions " + "settings will be migrated to the lacros - chrome browser."; + const char kDriveFsBidirectionalNativeMessagingName[] = "Enable bidirectional native messaging for DriveFS"; const char kDriveFsBidirectionalNativeMessagingDescription[] =
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index 359a13d..c085739 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -2473,6 +2473,9 @@ extern const char kDoubleTapToZoomInTabletModeName[]; extern const char kDoubleTapToZoomInTabletModeDescription[]; +extern const char kQuickSettingsPWANotificationsName[]; +extern const char kQuickSettingsPWANotificationsDescription[]; + extern const char kDriveFsBidirectionalNativeMessagingName[]; extern const char kDriveFsBidirectionalNativeMessagingDescription[];
diff --git a/chrome/browser/flags/android/chrome_session_state.cc b/chrome/browser/flags/android/chrome_session_state.cc index faa3211..0ebdce4 100644 --- a/chrome/browser/flags/android/chrome_session_state.cc +++ b/chrome/browser/flags/android/chrome_session_state.cc
@@ -46,10 +46,11 @@ static void JNI_ChromeSessionState_SetActivityType(JNIEnv* env, jint type) { activity_type = static_cast<ActivityType>(type); - // TODO(peconn): Look into adding this for UKM as well. + // TODO(crbug/1228735): deprecate custom tab field. ukm::UkmSource::SetCustomTabVisible( GetCustomTabsVisibleValue(activity_type) == chrome::android::VISIBLE_CUSTOM_TAB); + ukm::UkmSource::SetAndroidActivityTypeState(type); } static void JNI_ChromeSessionState_SetIsInMultiWindowMode(
diff --git a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/CachedFeatureFlagsSafeModeUnitTest.java b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/CachedFeatureFlagsSafeModeUnitTest.java index c45a6d8..b6efedf5 100644 --- a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/CachedFeatureFlagsSafeModeUnitTest.java +++ b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/CachedFeatureFlagsSafeModeUnitTest.java
@@ -103,8 +103,8 @@ // Crash streak is 2. Engage Safe Mode. // Safe values are false/true, and are used during this run. // Cached values remain true(crashy)/true, but are not used because Safe Mode is engaged. - assertEquals(Behavior.ENGAGED_WITH_SAFE_VALUES, - CachedFeatureFlags.getSafeModeBehaviorForTesting()); + // TODO(crbug.com/1217708): Assert CachedFeatureFlags.getSafeModeBehaviorForTesting()) is + // Behavior.ENGAGED_WITH_SAFE_VALUES. // TODO(crbug.com/1217708): Assert cached flags values are false/true. endCleanRun(false, false); // Cached values became false/false, cached from native.
diff --git a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/CachedFlagsSafeMode.java b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/CachedFlagsSafeMode.java index eab5972..bc8122e 100644 --- a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/CachedFlagsSafeMode.java +++ b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/CachedFlagsSafeMode.java
@@ -144,27 +144,7 @@ } private void writeSafeValues(ValuesReturned safeValuesReturned) { - SharedPreferencesManager prefs = SharedPreferencesManager.getInstance(); - - Map<String, Boolean> boolValuesToWrite = prependPrefixToKeys( - ChromePreferenceKeys.FLAGS_CACHED_SAFE_VALUES_BOOL, safeValuesReturned.boolMap()); - prefs.writeBooleans(boolValuesToWrite); - - Map<String, Integer> intValuesToWrite = prependPrefixToKeys( - ChromePreferenceKeys.FLAGS_CACHED_SAFE_VALUES_INT, safeValuesReturned.intMap()); - prefs.writeInts(intValuesToWrite); - - Map<String, Double> doubleValuesToWrite = - prependPrefixToKeys(ChromePreferenceKeys.FLAGS_CACHED_SAFE_VALUES_DOUBLE, - safeValuesReturned.doubleMap()); - prefs.writeDoubles(doubleValuesToWrite); - - Map<String, String> stringValuesToWrite = - prependPrefixToKeys(ChromePreferenceKeys.FLAGS_CACHED_SAFE_VALUES_STRING, - safeValuesReturned.stringMap()); - stringValuesToWrite.put(ChromePreferenceKeys.FLAGS_CACHED_SAFE_VALUES_VERSION, - ChromeVersionInfo.getProductVersion()); - prefs.writeStrings(stringValuesToWrite); + // TODO(crbug.com/1217708): Write safe values. } private static <T> Map<String, T> prependPrefixToKeys(KeyPrefix prefix, Map<String, T> map) {
diff --git a/chrome/browser/image_descriptions/android/java/src/org/chromium/chrome/browser/image_descriptions/ImageDescriptionsControllerTest.java b/chrome/browser/image_descriptions/android/java/src/org/chromium/chrome/browser/image_descriptions/ImageDescriptionsControllerTest.java index 99a00a6..cb0a834 100644 --- a/chrome/browser/image_descriptions/android/java/src/org/chromium/chrome/browser/image_descriptions/ImageDescriptionsControllerTest.java +++ b/chrome/browser/image_descriptions/android/java/src/org/chromium/chrome/browser/image_descriptions/ImageDescriptionsControllerTest.java
@@ -42,6 +42,7 @@ import org.chromium.chrome.browser.preferences.SharedPreferencesManager; import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; +import org.chromium.chrome.test.DummyUiChromeActivityTestCase; import org.chromium.components.prefs.PrefService; import org.chromium.components.user_prefs.UserPrefs; import org.chromium.components.user_prefs.UserPrefsJni; @@ -49,14 +50,13 @@ import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.net.ConnectionType; import org.chromium.ui.modaldialog.ModalDialogManager; -import org.chromium.ui.test.util.DummyUiActivityTestCase; /** * Unit tests for {@link ImageDescriptionsController} */ @RunWith(ChromeJUnit4ClassRunner.class) @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) -public class ImageDescriptionsControllerTest extends DummyUiActivityTestCase { +public class ImageDescriptionsControllerTest extends DummyUiChromeActivityTestCase { @Rule public JniMocker mJniMocker = new JniMocker();
diff --git a/chrome/browser/image_descriptions/android/java/src/org/chromium/chrome/browser/image_descriptions/ImageDescriptionsDialogTest.java b/chrome/browser/image_descriptions/android/java/src/org/chromium/chrome/browser/image_descriptions/ImageDescriptionsDialogTest.java index 8df7dc7..fa07207 100644 --- a/chrome/browser/image_descriptions/android/java/src/org/chromium/chrome/browser/image_descriptions/ImageDescriptionsDialogTest.java +++ b/chrome/browser/image_descriptions/android/java/src/org/chromium/chrome/browser/image_descriptions/ImageDescriptionsDialogTest.java
@@ -45,6 +45,7 @@ import org.chromium.chrome.browser.preferences.SharedPreferencesManager; import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; +import org.chromium.chrome.test.DummyUiChromeActivityTestCase; import org.chromium.components.browser_ui.modaldialog.AppModalPresenter; import org.chromium.components.browser_ui.widget.RadioButtonWithDescription; import org.chromium.components.prefs.PrefService; @@ -54,14 +55,13 @@ import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.net.ConnectionType; import org.chromium.ui.modaldialog.ModalDialogManager; -import org.chromium.ui.test.util.DummyUiActivityTestCase; /** * Unit tests for {@link ImageDescriptionsDialog} */ @RunWith(ChromeJUnit4ClassRunner.class) @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) -public class ImageDescriptionsDialogTest extends DummyUiActivityTestCase { +public class ImageDescriptionsDialogTest extends DummyUiChromeActivityTestCase { @Rule public JniMocker mJniMocker = new JniMocker();
diff --git a/chrome/browser/lens/java/src/org/chromium/chrome/browser/lens/LensFeature.java b/chrome/browser/lens/java/src/org/chromium/chrome/browser/lens/LensFeature.java index 25602c7..91236b1 100644 --- a/chrome/browser/lens/java/src/org/chromium/chrome/browser/lens/LensFeature.java +++ b/chrome/browser/lens/java/src/org/chromium/chrome/browser/lens/LensFeature.java
@@ -47,4 +47,9 @@ ENABLE_LENS_CAMERA_ASSISTED_SEARCH_ON_TABLET = new BooleanCachedFieldTrialParameter( ChromeFeatureList.LENS_CAMERA_ASSISTED_SEARCH, ENABLE_LENS_CAMERA_ASSISTED_SEARCH_ON_TABLET_PARAM_NAME, false); + + private static final String SKIP_AGSA_VERSION_CHECK_PARAM_NAME = "skipAgsaVersionCheck"; + public static final BooleanCachedFieldTrialParameter SKIP_AGSA_VERSION_CHECK = + new BooleanCachedFieldTrialParameter(ChromeFeatureList.LENS_CAMERA_ASSISTED_SEARCH, + SKIP_AGSA_VERSION_CHECK_PARAM_NAME, false); }
diff --git a/chrome/browser/media/router/discovery/mdns/cast_media_sink_service.cc b/chrome/browser/media/router/discovery/mdns/cast_media_sink_service.cc index 1c021c0..ecd08db7 100644 --- a/chrome/browser/media/router/discovery/mdns/cast_media_sink_service.cc +++ b/chrome/browser/media/router/discovery/mdns/cast_media_sink_service.cc
@@ -28,6 +28,7 @@ dns_sd_registry_->RemoveObserver(this); dns_sd_registry_ = nullptr; } + local_state_change_registrar_.RemoveAll(); } void CastMediaSinkService::Start(
diff --git a/chrome/browser/net/stub_resolver_config_reader.cc b/chrome/browser/net/stub_resolver_config_reader.cc index afd8e4a..dfe6529 100644 --- a/chrome/browser/net/stub_resolver_config_reader.cc +++ b/chrome/browser/net/stub_resolver_config_reader.cc
@@ -238,6 +238,9 @@ } bool StubResolverConfigReader::ShouldDisableDohForParentalControls() { + if (parental_controls_testing_override_.has_value()) + return parental_controls_testing_override_.value(); + #if defined(OS_WIN) return ShouldDisableDohForWindowsParentalControls(); #else
diff --git a/chrome/browser/net/stub_resolver_config_reader.h b/chrome/browser/net/stub_resolver_config_reader.h index 67a33136..9efec29b 100644 --- a/chrome/browser/net/stub_resolver_config_reader.h +++ b/chrome/browser/net/stub_resolver_config_reader.h
@@ -74,6 +74,10 @@ bool has_device_owner); #endif + void OverrideParentalControlsForTesting(bool parental_controls_override) { + parental_controls_testing_override_ = parental_controls_override; + } + private: void OnParentalControlsDelayTimer(); @@ -94,6 +98,8 @@ // expiration of the delay timer or because of a forced check. bool parental_controls_checked_ = false; + absl::optional<bool> parental_controls_testing_override_; + // This object lives on the UI thread, but it's possible for it to be created // before BrowserMainLoop::CreateThreads() is called which would cause a // DCHECK for the UI thread to fail (as the UI thread hasn't been
diff --git a/chrome/browser/net/stub_resolver_config_reader_browsertest.cc b/chrome/browser/net/stub_resolver_config_reader_browsertest.cc index aa5d3615..0562bca 100644 --- a/chrome/browser/net/stub_resolver_config_reader_browsertest.cc +++ b/chrome/browser/net/stub_resolver_config_reader_browsertest.cc
@@ -6,6 +6,7 @@ #include <string> +#include "base/enterprise_util.h" #include "base/feature_list.h" #include "base/test/scoped_feature_list.h" #include "base/values.h" @@ -16,6 +17,11 @@ #include "chrome/common/chrome_features.h" #include "chrome/common/pref_names.h" #include "chrome/test/base/in_process_browser_test.h" +#include "components/policy/core/browser/browser_policy_connector.h" +#include "components/policy/core/common/mock_configuration_policy_provider.h" +#include "components/policy/core/common/policy_map.h" +#include "components/policy/core/common/policy_types.h" +#include "components/policy/policy_constants.h" #include "components/prefs/pref_service.h" #include "content/public/test/browser_test.h" #include "net/dns/public/secure_dns_mode.h" @@ -26,20 +32,12 @@ #include "base/win/win_util.h" #endif +// TODO(ericorth@chromium.org): Consider validating that the expected +// configuration makes it all the way to the net::HostResolverManager in the +// network service, rather than just testing StubResolverConfigReader output. + namespace { -SecureDnsConfig GetSecureDnsConfiguration( - bool force_check_parental_controls_for_automatic_mode) { - return SystemNetworkContextManager::GetStubResolverConfigReader() - ->GetSecureDnsConfiguration( - force_check_parental_controls_for_automatic_mode); -} - -bool GetInsecureStubResolverEnabled() { - return SystemNetworkContextManager::GetStubResolverConfigReader() - ->GetInsecureStubResolverEnabled(); -} - // A custom matcher to validate a DnsOverHttpsServerConfig instance. MATCHER_P2(DnsOverHttpsServerConfigMatcher, server_template, use_post, "") { return testing::ExplainMatchResult( @@ -59,42 +57,77 @@ } ~StubResolverConfigReaderBrowsertest() override = default; - void SetUpOnMainThread() override {} + void SetUpInProcessBrowserTestFixture() override { + // Normal boilerplate to setup a MockConfigurationPolicyProvider. + ON_CALL(policy_provider_, IsInitializationComplete(testing::_)) + .WillByDefault(testing::Return(true)); + ON_CALL(policy_provider_, IsFirstPolicyLoadComplete(testing::_)) + .WillByDefault(testing::Return(true)); + policy::BrowserPolicyConnector::SetPolicyProviderForTesting( + &policy_provider_); + } - private: + void SetUpOnMainThread() override { + // Set the mocked policy provider to act as if no policies are in use by + // updating to the initial still-empty `policy_map_`. + ASSERT_TRUE(policy_map_.empty()); + policy_provider_.UpdateChromePolicy(policy_map_); + + config_reader_ = SystemNetworkContextManager::GetStubResolverConfigReader(); + + // Only affects future parental controls checks, but that is all that + // matters here because these tests only deal with checking fresh config + // reads, not what has been sent to Network Service. + // + // TODO(ericorth@chromium.org): If validation of network service state is + // ever added, need to ensure the result of this override gets sent first. + config_reader_->OverrideParentalControlsForTesting( + /*parental_controls_override=*/false); + } + + protected: + void SetSecureDnsModePolicy(std::string mode_str) { + policy_map_.Set( + policy::key::kDnsOverHttpsMode, policy::POLICY_LEVEL_MANDATORY, + policy::POLICY_SCOPE_MACHINE, policy::POLICY_SOURCE_PLATFORM, + base::Value(std::move(mode_str)), + /*external_data_fetcher=*/nullptr); + policy_provider_.UpdateChromePolicy(policy_map_); + } + + void SetDohTemplatesPolicy(std::string teplates_str) { + policy_map_.Set( + policy::key::kDnsOverHttpsTemplates, policy::POLICY_LEVEL_MANDATORY, + policy::POLICY_SCOPE_MACHINE, policy::POLICY_SOURCE_PLATFORM, + base::Value(std::move(teplates_str)), + /*external_data_fetcher=*/nullptr); + policy_provider_.UpdateChromePolicy(policy_map_); + } + + void ClearPolicies() { + policy_map_.Clear(); + policy_provider_.UpdateChromePolicy(policy_map_); + } + + policy::PolicyMap policy_map_; + testing::NiceMock<policy::MockConfigurationPolicyProvider> policy_provider_; + + StubResolverConfigReader* config_reader_; + base::test::ScopedFeatureList scoped_feature_list_; }; -// TODO(https://crbug.com/1225151): flaky -#if defined(OS_WIN) -#define MAYBE_StubResolverConfig DISABLED_StubResolverConfig -#else -#define MAYBE_StubResolverConfig StubResolverConfig -#endif - -// Checks that the values returned by GetStubResolverConfigForTesting() match -// `features::kAsyncDns` (With empty DNS over HTTPS prefs). Then sets various -// DoH modes and DoH template strings and makes sure the settings are respected. -IN_PROC_BROWSER_TEST_P(StubResolverConfigReaderBrowsertest, - MAYBE_StubResolverConfig) { +// Set various DoH modes and DoH template strings and make sure the settings are +// respected. +IN_PROC_BROWSER_TEST_P(StubResolverConfigReaderBrowsertest, ConfigFromPrefs) { bool async_dns_feature_enabled = GetParam(); // Mark as not enterprise managed. #if defined(OS_WIN) base::win::ScopedDomainStateForTesting scoped_domain(false); + EXPECT_FALSE(base::IsMachineExternallyManaged()); #endif - // Check initial state. - SecureDnsConfig secure_dns_config = GetSecureDnsConfiguration( - false /* force_check_parental_controls_for_automatic_mode */); - EXPECT_EQ(async_dns_feature_enabled, GetInsecureStubResolverEnabled()); - if (base::FeatureList::IsEnabled(features::kDnsOverHttps)) { - EXPECT_EQ(net::SecureDnsMode::kAutomatic, secure_dns_config.mode()); - } else { - EXPECT_EQ(net::SecureDnsMode::kOff, secure_dns_config.mode()); - } - EXPECT_THAT(secure_dns_config.servers(), testing::IsEmpty()); - std::string good_post_template = "https://foo.test/"; std::string good_get_template = "https://bar.test/dns-query{?dns}"; std::string bad_template = "dns-query{?dns}"; @@ -107,16 +140,18 @@ local_state->SetString(prefs::kDnsOverHttpsMode, SecureDnsConfig::kModeSecure); local_state->SetString(prefs::kDnsOverHttpsTemplates, bad_template); - secure_dns_config = GetSecureDnsConfiguration( + SecureDnsConfig secure_dns_config = config_reader_->GetSecureDnsConfiguration( false /* force_check_parental_controls_for_automatic_mode */); - EXPECT_EQ(async_dns_feature_enabled, GetInsecureStubResolverEnabled()); + EXPECT_EQ(async_dns_feature_enabled, + config_reader_->GetInsecureStubResolverEnabled()); EXPECT_EQ(net::SecureDnsMode::kSecure, secure_dns_config.mode()); EXPECT_THAT(secure_dns_config.servers(), testing::IsEmpty()); local_state->SetString(prefs::kDnsOverHttpsTemplates, good_post_template); - secure_dns_config = GetSecureDnsConfiguration( + secure_dns_config = config_reader_->GetSecureDnsConfiguration( false /* force_check_parental_controls_for_automatic_mode */); - EXPECT_EQ(async_dns_feature_enabled, GetInsecureStubResolverEnabled()); + EXPECT_EQ(async_dns_feature_enabled, + config_reader_->GetInsecureStubResolverEnabled()); EXPECT_EQ(net::SecureDnsMode::kSecure, secure_dns_config.mode()); EXPECT_THAT(secure_dns_config.servers(), testing::ElementsAreArray({ @@ -126,16 +161,18 @@ local_state->SetString(prefs::kDnsOverHttpsMode, SecureDnsConfig::kModeAutomatic); local_state->SetString(prefs::kDnsOverHttpsTemplates, bad_template); - secure_dns_config = GetSecureDnsConfiguration( + secure_dns_config = config_reader_->GetSecureDnsConfiguration( false /* force_check_parental_controls_for_automatic_mode */); - EXPECT_EQ(async_dns_feature_enabled, GetInsecureStubResolverEnabled()); + EXPECT_EQ(async_dns_feature_enabled, + config_reader_->GetInsecureStubResolverEnabled()); EXPECT_EQ(net::SecureDnsMode::kAutomatic, secure_dns_config.mode()); EXPECT_THAT(secure_dns_config.servers(), testing::IsEmpty()); local_state->SetString(prefs::kDnsOverHttpsTemplates, good_then_bad_template); - secure_dns_config = GetSecureDnsConfiguration( + secure_dns_config = config_reader_->GetSecureDnsConfiguration( false /* force_check_parental_controls_for_automatic_mode */); - EXPECT_EQ(async_dns_feature_enabled, GetInsecureStubResolverEnabled()); + EXPECT_EQ(async_dns_feature_enabled, + config_reader_->GetInsecureStubResolverEnabled()); EXPECT_EQ(net::SecureDnsMode::kAutomatic, secure_dns_config.mode()); EXPECT_THAT(secure_dns_config.servers(), testing::ElementsAreArray({ @@ -143,9 +180,10 @@ })); local_state->SetString(prefs::kDnsOverHttpsTemplates, bad_then_good_template); - secure_dns_config = GetSecureDnsConfiguration( + secure_dns_config = config_reader_->GetSecureDnsConfiguration( false /* force_check_parental_controls_for_automatic_mode */); - EXPECT_EQ(async_dns_feature_enabled, GetInsecureStubResolverEnabled()); + EXPECT_EQ(async_dns_feature_enabled, + config_reader_->GetInsecureStubResolverEnabled()); EXPECT_EQ(net::SecureDnsMode::kAutomatic, secure_dns_config.mode()); EXPECT_THAT(secure_dns_config.servers(), testing::ElementsAreArray({ @@ -154,9 +192,10 @@ local_state->SetString(prefs::kDnsOverHttpsTemplates, multiple_good_templates); - secure_dns_config = GetSecureDnsConfiguration( + secure_dns_config = config_reader_->GetSecureDnsConfiguration( false /* force_check_parental_controls_for_automatic_mode */); - EXPECT_EQ(async_dns_feature_enabled, GetInsecureStubResolverEnabled()); + EXPECT_EQ(async_dns_feature_enabled, + config_reader_->GetInsecureStubResolverEnabled()); EXPECT_EQ(net::SecureDnsMode::kAutomatic, secure_dns_config.mode()); EXPECT_THAT(secure_dns_config.servers(), testing::ElementsAreArray({ @@ -166,16 +205,18 @@ local_state->SetString(prefs::kDnsOverHttpsMode, SecureDnsConfig::kModeOff); local_state->SetString(prefs::kDnsOverHttpsTemplates, good_get_template); - secure_dns_config = GetSecureDnsConfiguration( + secure_dns_config = config_reader_->GetSecureDnsConfiguration( false /* force_check_parental_controls_for_automatic_mode */); - EXPECT_EQ(async_dns_feature_enabled, GetInsecureStubResolverEnabled()); + EXPECT_EQ(async_dns_feature_enabled, + config_reader_->GetInsecureStubResolverEnabled()); EXPECT_EQ(net::SecureDnsMode::kOff, secure_dns_config.mode()); EXPECT_THAT(secure_dns_config.servers(), testing::IsEmpty()); local_state->SetString(prefs::kDnsOverHttpsMode, "no_match"); - secure_dns_config = GetSecureDnsConfiguration( + secure_dns_config = config_reader_->GetSecureDnsConfiguration( false /* force_check_parental_controls_for_automatic_mode */); - EXPECT_EQ(async_dns_feature_enabled, GetInsecureStubResolverEnabled()); + EXPECT_EQ(async_dns_feature_enabled, + config_reader_->GetInsecureStubResolverEnabled()); EXPECT_EQ(net::SecureDnsMode::kOff, secure_dns_config.mode()); EXPECT_THAT(secure_dns_config.servers(), testing::IsEmpty()); @@ -183,13 +224,124 @@ // should be unaffected. local_state->Set(prefs::kBuiltInDnsClientEnabled, base::Value(!async_dns_feature_enabled)); - secure_dns_config = GetSecureDnsConfiguration( + secure_dns_config = config_reader_->GetSecureDnsConfiguration( false /* force_check_parental_controls_for_automatic_mode */); - EXPECT_EQ(!async_dns_feature_enabled, GetInsecureStubResolverEnabled()); + EXPECT_EQ(!async_dns_feature_enabled, + config_reader_->GetInsecureStubResolverEnabled()); EXPECT_EQ(net::SecureDnsMode::kOff, secure_dns_config.mode()); EXPECT_THAT(secure_dns_config.servers(), testing::IsEmpty()); } +// Set various policies and ensure the correct prefs. +IN_PROC_BROWSER_TEST_P(StubResolverConfigReaderBrowsertest, ConfigFromPolicy) { + bool async_dns_feature_enabled = GetParam(); + +// Mark as not enterprise managed. +#if defined(OS_WIN) + base::win::ScopedDomainStateForTesting scoped_domain(false); + EXPECT_FALSE(base::IsMachineExternallyManaged()); +#endif + + // Start with default non-set policies. + SecureDnsConfig secure_dns_config = config_reader_->GetSecureDnsConfiguration( + /*force_check_parental_controls_for_automatic_mode=*/false); + EXPECT_EQ(async_dns_feature_enabled, + config_reader_->GetInsecureStubResolverEnabled()); + if (base::FeatureList::IsEnabled(features::kDnsOverHttps)) { + EXPECT_EQ(secure_dns_config.mode(), net::SecureDnsMode::kAutomatic); + } else { + EXPECT_EQ(secure_dns_config.mode(), net::SecureDnsMode::kOff); + } + EXPECT_THAT(secure_dns_config.servers(), testing::IsEmpty()); + + // ChromeOS includes its own special functionality to set default policies if + // any policies are set. This function is not declared and cannot be invoked + // in non-CrOS builds. Expect these enterprise user defaults to disable DoH. +#if defined(OS_CHROMEOS) + // Applies the special ChromeOS defaults to `policy_map_`. + policy::SetEnterpriseUsersDefaults(&policy_map_); + // Send the PolicyMap to the mock policy provider. + policy_provider_.UpdateChromePolicy(policy_map_); + secure_dns_config = config_reader_->GetSecureDnsConfiguration( + /*force_check_parental_controls_for_automatic_mode=*/false); + EXPECT_EQ(secure_dns_config.mode(), net::SecureDnsMode::kOff); + EXPECT_THAT(secure_dns_config.servers(), testing::IsEmpty()); +#endif // defined(OS_CHROMEOS) + + // Disable DoH by policy + ClearPolicies(); + SetSecureDnsModePolicy("off"); + secure_dns_config = config_reader_->GetSecureDnsConfiguration( + /*force_check_parental_controls_for_automatic_mode=*/false); + EXPECT_EQ(secure_dns_config.mode(), net::SecureDnsMode::kOff); + EXPECT_THAT(secure_dns_config.servers(), testing::IsEmpty()); + + // Automatic mode by policy + SetSecureDnsModePolicy("automatic"); + secure_dns_config = config_reader_->GetSecureDnsConfiguration( + /*force_check_parental_controls_for_automatic_mode=*/false); + EXPECT_EQ(secure_dns_config.mode(), net::SecureDnsMode::kAutomatic); + EXPECT_THAT(secure_dns_config.servers(), testing::IsEmpty()); + + // Secure mode by policy + SetSecureDnsModePolicy("secure"); + SetDohTemplatesPolicy("https://doh.test/"); + secure_dns_config = config_reader_->GetSecureDnsConfiguration( + /*force_check_parental_controls_for_automatic_mode=*/false); + EXPECT_EQ(secure_dns_config.mode(), net::SecureDnsMode::kSecure); + EXPECT_THAT(secure_dns_config.servers(), + testing::ElementsAre(DnsOverHttpsServerConfigMatcher( + "https://doh.test/", /*use_post=*/true))); + + // Invalid template policy + SetSecureDnsModePolicy("secure"); + SetDohTemplatesPolicy("invalid template"); + secure_dns_config = config_reader_->GetSecureDnsConfiguration( + /*force_check_parental_controls_for_automatic_mode=*/false); + EXPECT_EQ(secure_dns_config.mode(), net::SecureDnsMode::kSecure); + EXPECT_THAT(secure_dns_config.servers(), testing::IsEmpty()); + + // Invalid mode policy + SetSecureDnsModePolicy("invalid"); + SetDohTemplatesPolicy("https://doh.test/"); + secure_dns_config = config_reader_->GetSecureDnsConfiguration( + /*force_check_parental_controls_for_automatic_mode=*/false); + EXPECT_EQ(secure_dns_config.mode(), net::SecureDnsMode::kOff); + // Expect empty templates if mode policy is invalid. + EXPECT_THAT(secure_dns_config.servers(), testing::IsEmpty()); +} + +// Test that parental controls detection interacts correctly with prefs and +// policies. +IN_PROC_BROWSER_TEST_P(StubResolverConfigReaderBrowsertest, + ConfigFromParentalControls) { +// Mark as not enterprise managed. +#if defined(OS_WIN) + base::win::ScopedDomainStateForTesting scoped_domain(false); + EXPECT_FALSE(base::IsMachineExternallyManaged()); +#endif + + config_reader_->OverrideParentalControlsForTesting( + /*parental_controls_override=*/true); + + // Parental controls takes precedence over regular prefs. + PrefService* local_state = g_browser_process->local_state(); + local_state->SetString(prefs::kDnsOverHttpsMode, + SecureDnsConfig::kModeAutomatic); + SecureDnsConfig secure_dns_config = config_reader_->GetSecureDnsConfiguration( + /*force_check_parental_controls_for_automatic_mode=*/true); + EXPECT_EQ(secure_dns_config.mode(), net::SecureDnsMode::kOff); + EXPECT_THAT(secure_dns_config.servers(), testing::IsEmpty()); + + // Policy takes precedence over parental controls. + SetSecureDnsModePolicy("automatic"); + SetDohTemplatesPolicy(""); + secure_dns_config = config_reader_->GetSecureDnsConfiguration( + /*force_check_parental_controls_for_automatic_mode=*/true); + EXPECT_EQ(secure_dns_config.mode(), net::SecureDnsMode::kAutomatic); + EXPECT_THAT(secure_dns_config.servers(), testing::IsEmpty()); +} + INSTANTIATE_TEST_SUITE_P(All, StubResolverConfigReaderBrowsertest, ::testing::Bool());
diff --git a/chrome/browser/notifications/arc_application_notifier_controller.cc b/chrome/browser/notifications/arc_application_notifier_controller.cc index 8176c71..cf9c0b16 100644 --- a/chrome/browser/notifications/arc_application_notifier_controller.cc +++ b/chrome/browser/notifications/arc_application_notifier_controller.cc
@@ -8,36 +8,18 @@ #include "ash/public/cpp/notifier_metadata.h" #include "base/bind.h" -#include "base/strings/utf_string_conversions.h" #include "chrome/browser/apps/app_service/app_service_proxy_chromeos.h" #include "chrome/browser/apps/app_service/app_service_proxy_factory.h" +#include "chrome/browser/notifications/notifier_dataset.h" #include "chrome/browser/profiles/profile.h" -#include "chrome/browser/ui/app_list/arc/arc_app_list_prefs_factory.h" #include "chrome/browser/ui/webui/app_management/app_management.mojom.h" #include "chrome/common/chrome_features.h" -#include "components/keyed_service/content/browser_context_keyed_service_shutdown_notifier_factory.h" #include "components/services/app_service/public/cpp/app_update.h" -#include "ui/base/layout.h" -#include "ui/display/display.h" -#include "ui/display/screen.h" +#include "ui/message_center/public/cpp/message_center_constants.h" #include "ui/message_center/public/cpp/notifier_id.h" namespace arc { -namespace { - -constexpr int kArcAppIconSizeInDp = 48; - -struct NotifierDataset { - std::string app_id; - std::string app_name; - std::string package_name; - bool enabled; - bool is_system_app; -}; - -} // namespace - ArcApplicationNotifierController::ArcApplicationNotifierController( NotifierController::Observer* observer) : observer_(observer) {} @@ -65,6 +47,7 @@ const apps::AppUpdate& update) { if (update.AppType() != apps::mojom::AppType::kArc) return; + for (const auto& permission : update.Permissions()) { if (static_cast<app_management::mojom::ArcPermissionType>( permission->permission_id) != @@ -72,21 +55,21 @@ continue; } DCHECK(permission->value_type == apps::mojom::PermissionValueType::kBool); - notifier_dataset.push_back( - {update.AppId() /*app_id*/, update.Name() /*app_name*/, - update.PublisherId() /*package name*/, - !!permission->value /*enabled*/, - update.InstallSource() == - apps::mojom::InstallSource::kSystem /*is_system_app*/}); + // Do not include notifier metadata for system apps. + if (update.InstallSource() == apps::mojom::InstallSource::kSystem) { + return; + } + notifier_dataset.push_back(NotifierDataset{ + update.AppId() /*app_id*/, update.ShortName() /*app_name*/, + update.PublisherId() /*publisher_id*/, + !!permission->value /*enabled*/}); } }); std::vector<ash::NotifierMetadata> notifiers; for (auto& app_data : notifier_dataset) { - // Handle packages having multiple launcher activities. Do not include - // notifier metadata for system apps. - if (package_to_app_ids_.count(app_data.package_name) || - app_data.is_system_app) + // Handle packages having multiple launcher activities. + if (package_to_app_ids_.count(app_data.publisher_id)) continue; message_center::NotifierId notifier_id( @@ -95,8 +78,8 @@ app_data.enabled, false /* enforced */, gfx::ImageSkia()); package_to_app_ids_.insert( - std::make_pair(app_data.package_name, app_data.app_id)); - CallLoadIcon(/*allow_placeholder_icon*/ true, app_data.app_id); + std::make_pair(app_data.publisher_id, app_data.app_id)); + CallLoadIcon(app_data.app_id, /*allow_placeholder_icon*/ true); } return notifiers; } @@ -120,8 +103,9 @@ service->SetPermission(notifier_id.id, std::move(permission)); } -void ArcApplicationNotifierController::CallLoadIcon(bool allow_placeholder_icon, - std::string app_id) { +void ArcApplicationNotifierController::CallLoadIcon( + const std::string& app_id, + bool allow_placeholder_icon) { DCHECK(apps::AppServiceProxyFactory::IsAppServiceAvailableForProfile( last_used_profile_)); @@ -132,27 +116,28 @@ apps::AppServiceProxyFactory::GetForProfile(last_used_profile_) ->LoadIcon(apps::mojom::AppType::kArc, app_id, icon_type, - kArcAppIconSizeInDp, allow_placeholder_icon, + message_center::kQuickSettingIconSizeInDp, + allow_placeholder_icon, base::BindOnce(&ArcApplicationNotifierController::OnLoadIcon, weak_ptr_factory_.GetWeakPtr(), app_id)); } void ArcApplicationNotifierController::OnLoadIcon( - std::string app_id, + const std::string& app_id, apps::mojom::IconValuePtr icon_value) { - auto icon_type = + auto expected_icon_type = (base::FeatureList::IsEnabled(features::kAppServiceAdaptiveIcon)) ? apps::mojom::IconType::kStandard : apps::mojom::IconType::kUncompressed; - if (icon_value->icon_type != icon_type) + if (icon_value->icon_type != expected_icon_type) return; SetIcon(app_id, icon_value->uncompressed); if (icon_value->is_placeholder_icon) - CallLoadIcon(/*allow_placeholder_icon*/ false, app_id); + CallLoadIcon(app_id, /*allow_placeholder_icon*/ false); } -void ArcApplicationNotifierController::SetIcon(std::string app_id, +void ArcApplicationNotifierController::SetIcon(const std::string& app_id, gfx::ImageSkia image) { observer_->OnIconImageUpdated( message_center::NotifierId(message_center::NotifierType::ARC_APPLICATION, @@ -177,9 +162,8 @@ } } - if (update.IconKeyChanged()) { - CallLoadIcon(/*allow_placeholder_icon*/ true, update.AppId()); - } + if (update.IconKeyChanged()) + CallLoadIcon(update.AppId(), /*allow_placeholder_icon*/ true); } void ArcApplicationNotifierController::OnAppRegistryCacheWillBeDestroyed(
diff --git a/chrome/browser/notifications/arc_application_notifier_controller.h b/chrome/browser/notifications/arc_application_notifier_controller.h index e6cb284..5273a53 100644 --- a/chrome/browser/notifications/arc_application_notifier_controller.h +++ b/chrome/browser/notifications/arc_application_notifier_controller.h
@@ -11,7 +11,6 @@ #include "base/memory/weak_ptr.h" #include "chrome/browser/notifications/notifier_controller.h" -#include "chrome/browser/ui/app_list/arc/arc_app_icon.h" #include "components/services/app_service/public/cpp/app_registry_cache.h" class AppUpdate; @@ -39,18 +38,24 @@ bool enabled) override; private: - void SetIcon(std::string app_id, gfx::ImageSkia image); - void CallLoadIcon(bool allow_placeholder_icon, std::string app_id); - void OnLoadIcon(std::string app_id, apps::mojom::IconValuePtr icon_value); + void CallLoadIcon(const std::string& app_id, bool allow_placeholder_icon); + void OnLoadIcon(const std::string& app_id, + apps::mojom::IconValuePtr icon_value); + void SetIcon(const std::string& app_id, gfx::ImageSkia image); // apps::AppRegistryCache::Observer: void OnAppUpdate(const apps::AppUpdate& update) override; void OnAppRegistryCacheWillBeDestroyed( apps::AppRegistryCache* cache) override; + // Needed to load icons for ARC apps. Profile* last_used_profile_ = nullptr; NotifierController::Observer* observer_; + + // Used to keep track of all PWA start URLs to prevent creation of duplicate + // notifier metadata. std::map<std::string, std::string> package_to_app_ids_; + base::WeakPtrFactory<ArcApplicationNotifierController> weak_ptr_factory_{ this}; };
diff --git a/chrome/browser/notifications/chrome_ash_message_center_client.cc b/chrome/browser/notifications/chrome_ash_message_center_client.cc index 3b8e977..a6eb62e 100644 --- a/chrome/browser/notifications/chrome_ash_message_center_client.cc +++ b/chrome/browser/notifications/chrome_ash_message_center_client.cc
@@ -6,10 +6,13 @@ #include "ash/public/cpp/notifier_metadata.h" #include "ash/public/cpp/notifier_settings_observer.h" +#include "base/feature_list.h" #include "base/i18n/string_compare.h" #include "chrome/browser/ash/profiles/profile_helper.h" +#include "chrome/browser/browser_features.h" #include "chrome/browser/notifications/arc_application_notifier_controller.h" #include "chrome/browser/notifications/extension_notifier_controller.h" +#include "chrome/browser/notifications/pwa_notifier_controller.h" #include "chrome/browser/notifications/web_page_notifier_controller.h" #include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/ui/settings_window_manager_chromeos.h" @@ -107,13 +110,19 @@ DCHECK(!g_chrome_ash_message_center_client); g_chrome_ash_message_center_client = this; - sources_.insert( - std::make_pair(message_center::NotifierType::APPLICATION, - std::make_unique<ExtensionNotifierController>(this))); + if (base::FeatureList::IsEnabled(features::kQuickSettingsPWANotifications)) { + sources_.insert( + std::make_pair(message_center::NotifierType::APPLICATION, + std::make_unique<PwaNotifierController>(this))); + } else { + sources_.insert( + std::make_pair(message_center::NotifierType::APPLICATION, + std::make_unique<ExtensionNotifierController>(this))); - sources_.insert( - std::make_pair(message_center::NotifierType::WEB_PAGE, - std::make_unique<WebPageNotifierController>(this))); + sources_.insert( + std::make_pair(message_center::NotifierType::WEB_PAGE, + std::make_unique<WebPageNotifierController>(this))); + } sources_.insert(std::make_pair( message_center::NotifierType::ARC_APPLICATION,
diff --git a/chrome/browser/notifications/chrome_ash_message_center_client_browsertest.cc b/chrome/browser/notifications/chrome_ash_message_center_client_browsertest.cc new file mode 100644 index 0000000..6a73444 --- /dev/null +++ b/chrome/browser/notifications/chrome_ash_message_center_client_browsertest.cc
@@ -0,0 +1,112 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/notifications/chrome_ash_message_center_client.h" + +#include "ash/public/cpp/notifier_settings_controller.h" +#include "base/test/scoped_feature_list.h" +#include "chrome/browser/apps/app_service/app_service_proxy.h" +#include "chrome/browser/apps/app_service/app_service_proxy_factory.h" +#include "chrome/browser/browser_features.h" +#include "chrome/browser/notifications/notifier_settings_test_observer.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/web_applications/components/web_app_id.h" +#include "chrome/browser/web_applications/components/web_application_info.h" +#include "chrome/browser/web_applications/test/web_app_install_test_utils.h" +#include "chrome/test/base/in_process_browser_test.h" +#include "content/public/test/browser_test.h" + +namespace { + +const char kUrlString[] = "https://example.org"; + +} // namespace + +class ChromeAshMessageCenterClientBrowserTest : public InProcessBrowserTest { + public: + ChromeAshMessageCenterClientBrowserTest() { + feature_list_.InitWithFeatureState(features::kQuickSettingsPWANotifications, + true); + } + ChromeAshMessageCenterClientBrowserTest( + const ChromeAshMessageCenterClientBrowserTest&) = delete; + ChromeAshMessageCenterClientBrowserTest& operator=( + const ChromeAshMessageCenterClientBrowserTest&) = delete; + ~ChromeAshMessageCenterClientBrowserTest() override = default; + + void SetUpOnMainThread() override { + InProcessBrowserTest::SetUpOnMainThread(); + test_observer_ = std::make_unique<test::NotifierSettingsTestObserver>(); + ASSERT_EQ(0, GetNumberOfNotifiers()); + } + + void TearDownOnMainThread() override { + test_observer_.reset(); + InProcessBrowserTest::TearDownOnMainThread(); + } + + void RefreshNotifiers() { + ash::NotifierSettingsController::Get()->GetNotifiers(); + } + + void SetNotifierEnabled(web_app::AppId app_id, bool enabled) { + ash::NotifierSettingsController::Get()->SetNotifierEnabled( + message_center::NotifierId(message_center::NotifierType::APPLICATION, + app_id), + enabled); + apps::AppServiceProxyFactory::GetForProfile(browser()->profile()) + ->FlushMojoCallsForTesting(); + } + + int GetNumberOfNotifiers() { return test_observer_->notifiers().size(); } + + ash::NotifierMetadata GetNotifierMetadataAtIndex(int index) { + return test_observer_->notifiers()[index]; + } + + std::string InstallTestPWA() { + auto web_application_info = std::make_unique<WebApplicationInfo>(); + web_application_info->start_url = GURL(kUrlString); + web_application_info->display_mode = blink::mojom::DisplayMode::kMinimalUi; + Profile* profile = browser()->profile(); + + // Install a PWA and wait for app service to see it. + web_app::AppId app_id = + web_app::test::InstallWebApp(profile, std::move(web_application_info)); + apps::AppServiceProxy* service = + apps::AppServiceProxyFactory::GetForProfile(profile); + service->FlushMojoCallsForTesting(); + // Inform notifier controller it should begin observing |profile|'s' + // AppRegistryCache. + RefreshNotifiers(); + return app_id; + } + + private: + std::unique_ptr<test::NotifierSettingsTestObserver> test_observer_; + base::test::ScopedFeatureList feature_list_; +}; + +IN_PROC_BROWSER_TEST_F(ChromeAshMessageCenterClientBrowserTest, + PWANotifierControllerTest) { + std::string app_id = InstallTestPWA(); + + // Manually set notification permission to be true and check that notifier + // list has been updated correctly. + SetNotifierEnabled(app_id, true); + RefreshNotifiers(); + ASSERT_EQ(1, GetNumberOfNotifiers()); + ash::NotifierMetadata metadata = GetNotifierMetadataAtIndex(0); + EXPECT_EQ(app_id, metadata.notifier_id.id); + EXPECT_EQ(true, metadata.enabled); + + // Manually set notification permission to be false and check that notifier + // list has been updated correctly. + SetNotifierEnabled(app_id, false); + RefreshNotifiers(); + ASSERT_EQ(1, GetNumberOfNotifiers()); + metadata = GetNotifierMetadataAtIndex(0); + EXPECT_EQ(app_id, metadata.notifier_id.id); + EXPECT_EQ(false, metadata.enabled); +}
diff --git a/chrome/browser/notifications/notifier_dataset.cc b/chrome/browser/notifications/notifier_dataset.cc new file mode 100644 index 0000000..22052d2 --- /dev/null +++ b/chrome/browser/notifications/notifier_dataset.cc
@@ -0,0 +1,18 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/notifications/notifier_dataset.h" + +NotifierDataset::NotifierDataset(const std::string& app_id, + const std::string& app_name, + const std::string& publisher_id, + bool enabled) + : app_id(app_id), + app_name(app_name), + publisher_id(publisher_id), + enabled(enabled) {} + +NotifierDataset::NotifierDataset(NotifierDataset&& other) = default; + +NotifierDataset::~NotifierDataset() = default;
diff --git a/chrome/browser/notifications/notifier_dataset.h b/chrome/browser/notifications/notifier_dataset.h new file mode 100644 index 0000000..4f10c00 --- /dev/null +++ b/chrome/browser/notifications/notifier_dataset.h
@@ -0,0 +1,27 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_NOTIFICATIONS_NOTIFIER_DATASET_H_ +#define CHROME_BROWSER_NOTIFICATIONS_NOTIFIER_DATASET_H_ + +#include <string> + +struct NotifierDataset { + NotifierDataset(const std::string& app_id, + const std::string& app_name, + const std::string& publisher_id, + bool enabled); + NotifierDataset(const NotifierDataset&) = delete; + NotifierDataset& operator=(const NotifierDataset&) = delete; + // Move ctors are needed to push_back() into a vector. + NotifierDataset(NotifierDataset&& notifier_dataset); + ~NotifierDataset(); + + const std::string app_id; + const std::string app_name; + const std::string publisher_id; + const bool enabled; +}; + +#endif // CHROME_BROWSER_NOTIFICATIONS_NOTIFIER_DATASET_H_
diff --git a/chrome/browser/notifications/notifier_settings_test_observer.cc b/chrome/browser/notifications/notifier_settings_test_observer.cc new file mode 100644 index 0000000..fb5b529 --- /dev/null +++ b/chrome/browser/notifications/notifier_settings_test_observer.cc
@@ -0,0 +1,24 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/notifications/notifier_settings_test_observer.h" + +#include "ash/public/cpp/notifier_settings_controller.h" + +namespace test { + +NotifierSettingsTestObserver::NotifierSettingsTestObserver() { + ash::NotifierSettingsController::Get()->AddNotifierSettingsObserver(this); +} + +NotifierSettingsTestObserver::~NotifierSettingsTestObserver() { + ash::NotifierSettingsController::Get()->RemoveNotifierSettingsObserver(this); +} + +void NotifierSettingsTestObserver::OnNotifiersUpdated( + const std::vector<ash::NotifierMetadata>& notifiers) { + notifiers_ = notifiers; +} + +} // namespace test
diff --git a/chrome/browser/notifications/notifier_settings_test_observer.h b/chrome/browser/notifications/notifier_settings_test_observer.h new file mode 100644 index 0000000..7cfa1399 --- /dev/null +++ b/chrome/browser/notifications/notifier_settings_test_observer.h
@@ -0,0 +1,34 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_NOTIFICATIONS_NOTIFIER_SETTINGS_TEST_OBSERVER_H_ +#define CHROME_BROWSER_NOTIFICATIONS_NOTIFIER_SETTINGS_TEST_OBSERVER_H_ + +#include "ash/public/cpp/notifier_settings_observer.h" + +#include "ash/public/cpp/notifier_metadata.h" + +namespace test { + +class NotifierSettingsTestObserver : public ash::NotifierSettingsObserver { + public: + NotifierSettingsTestObserver(); + NotifierSettingsTestObserver(const NotifierSettingsTestObserver&) = delete; + NotifierSettingsTestObserver& operator=(const NotifierSettingsTestObserver&) = + delete; + ~NotifierSettingsTestObserver() override; + + std::vector<ash::NotifierMetadata> notifiers() const { return notifiers_; } + + // ash::NotifierSettingsObserver: + void OnNotifiersUpdated( + const std::vector<ash::NotifierMetadata>& notifiers) override; + + private: + std::vector<ash::NotifierMetadata> notifiers_; +}; + +} // namespace test + +#endif // CHROME_BROWSER_NOTIFICATIONS_NOTIFIER_SETTINGS_TEST_OBSERVER_H_
diff --git a/chrome/browser/notifications/pwa_notifier_controller.cc b/chrome/browser/notifications/pwa_notifier_controller.cc new file mode 100644 index 0000000..2d5f323f --- /dev/null +++ b/chrome/browser/notifications/pwa_notifier_controller.cc
@@ -0,0 +1,167 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/notifications/pwa_notifier_controller.h" + +#include "ash/public/cpp/notifier_metadata.h" +#include "base/bind.h" +#include "chrome/browser/apps/app_service/app_service_proxy_chromeos.h" +#include "chrome/browser/apps/app_service/app_service_proxy_factory.h" +#include "chrome/browser/notifications/notifier_dataset.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/webui/app_management/app_management.mojom.h" +#include "chrome/common/chrome_features.h" +#include "components/services/app_service/public/cpp/app_update.h" +#include "ui/message_center/public/cpp/message_center_constants.h" +#include "ui/message_center/public/cpp/notifier_id.h" + +PwaNotifierController::PwaNotifierController( + NotifierController::Observer* observer) + : observer_(observer) {} + +PwaNotifierController::~PwaNotifierController() = default; + +std::vector<ash::NotifierMetadata> PwaNotifierController::GetNotifierList( + Profile* profile) { + DCHECK( + apps::AppServiceProxyFactory::IsAppServiceAvailableForProfile(profile)); + if (observed_profile_ && !observed_profile_->IsSameOrParent(profile)) + weak_ptr_factory_.InvalidateWeakPtrs(); + observed_profile_ = profile; + apps::AppServiceProxy* service = + apps::AppServiceProxyFactory::GetForProfile(profile); + Observe(&service->AppRegistryCache()); + package_to_app_ids_.clear(); + + std::vector<NotifierDataset> notifier_dataset; + service->AppRegistryCache().ForEachApp( + [¬ifier_dataset](const apps::AppUpdate& update) { + if (update.AppType() != apps::mojom::AppType::kWeb) + return; + + for (const auto& permission : update.Permissions()) { + if (static_cast<app_management::mojom::PwaPermissionType>( + permission->permission_id) != + app_management::mojom::PwaPermissionType::NOTIFICATIONS) { + continue; + } + DCHECK(permission->value_type == + apps::mojom::PermissionValueType::kTriState); + // Do not include notifier metadata for system apps. + if (update.InstallSource() == apps::mojom::InstallSource::kSystem) { + return; + } + notifier_dataset.push_back(NotifierDataset{ + update.AppId() /*app_id*/, update.ShortName() /*app_name*/, + update.PublisherId() /*publisher_id*/, + static_cast<apps::mojom::TriState>(permission->value) == + apps::mojom::TriState::kAllow + ? true + : false /*enabled*/}); + } + }); + std::vector<ash::NotifierMetadata> notifiers; + + for (auto& app_data : notifier_dataset) { + // Handle packages having multiple launcher activities. Do not include + // notifier metadata for system apps. + if (package_to_app_ids_.count(app_data.publisher_id)) { + continue; + } + message_center::NotifierId notifier_id( + message_center::NotifierType::APPLICATION, app_data.app_id); + notifiers.emplace_back(notifier_id, base::UTF8ToUTF16(app_data.app_name), + app_data.enabled, false /* enforced */, + gfx::ImageSkia()); + package_to_app_ids_.insert( + std::make_pair(app_data.publisher_id, app_data.app_id)); + CallLoadIcon(app_data.app_id, /*allow_placeholder_icon*/ true); + } + return notifiers; +} + +void PwaNotifierController::SetNotifierEnabled( + Profile* profile, + const message_center::NotifierId& notifier_id, + bool enabled) { + DCHECK( + apps::AppServiceProxyFactory::IsAppServiceAvailableForProfile(profile)); + // We should not set permissions for a profile we are not currently observing. + DCHECK(observed_profile_->IsSameOrParent(profile)); + auto permission = apps::mojom::Permission::New(); + permission->permission_id = + static_cast<int>(app_management::mojom::PwaPermissionType::NOTIFICATIONS); + permission->value_type = apps::mojom::PermissionValueType::kTriState; + permission->value = static_cast<uint32_t>( + enabled ? apps::mojom::TriState::kAllow : apps::mojom::TriState::kBlock); + permission->is_managed = false; + apps::AppServiceProxy* service = + apps::AppServiceProxyFactory::GetForProfile(profile); + service->SetPermission(notifier_id.id, std::move(permission)); +} + +void PwaNotifierController::CallLoadIcon(const std::string& app_id, + bool allow_placeholder_icon) { + DCHECK(apps::AppServiceProxyFactory::IsAppServiceAvailableForProfile( + observed_profile_)); + + auto icon_type = + (base::FeatureList::IsEnabled(features::kAppServiceAdaptiveIcon)) + ? apps::mojom::IconType::kStandard + : apps::mojom::IconType::kUncompressed; + + apps::AppServiceProxyFactory::GetForProfile(observed_profile_) + ->LoadIcon(apps::mojom::AppType::kWeb, app_id, icon_type, + message_center::kQuickSettingIconSizeInDp, + allow_placeholder_icon, + base::BindOnce(&PwaNotifierController::OnLoadIcon, + weak_ptr_factory_.GetWeakPtr(), app_id)); +} + +void PwaNotifierController::OnLoadIcon(const std::string& app_id, + apps::mojom::IconValuePtr icon_value) { + auto expected_icon_type = + (base::FeatureList::IsEnabled(features::kAppServiceAdaptiveIcon)) + ? apps::mojom::IconType::kStandard + : apps::mojom::IconType::kUncompressed; + if (icon_value->icon_type != expected_icon_type) + return; + + SetIcon(app_id, icon_value->uncompressed); + if (icon_value->is_placeholder_icon) + CallLoadIcon(app_id, /*allow_placeholder_icon*/ false); +} + +void PwaNotifierController::SetIcon(const std::string& app_id, + gfx::ImageSkia image) { + observer_->OnIconImageUpdated( + message_center::NotifierId(message_center::NotifierType::APPLICATION, + app_id), + image); +} + +void PwaNotifierController::OnAppUpdate(const apps::AppUpdate& update) { + if (!base::Contains(package_to_app_ids_, update.PublisherId())) + return; + + if (update.PermissionsChanged()) { + for (const auto& permission : update.Permissions()) { + if (static_cast<app_management::mojom::PwaPermissionType>( + permission->permission_id) == + app_management::mojom::PwaPermissionType::NOTIFICATIONS) { + message_center::NotifierId notifier_id( + message_center::NotifierType::APPLICATION, update.AppId()); + observer_->OnNotifierEnabledChanged(notifier_id, permission->value); + } + } + } + + if (update.IconKeyChanged()) + CallLoadIcon(update.AppId(), /*allow_placeholder_icon*/ true); +} + +void PwaNotifierController::OnAppRegistryCacheWillBeDestroyed( + apps::AppRegistryCache* cache) { + Observe(nullptr); +}
diff --git a/chrome/browser/notifications/pwa_notifier_controller.h b/chrome/browser/notifications/pwa_notifier_controller.h new file mode 100644 index 0000000..e76390f --- /dev/null +++ b/chrome/browser/notifications/pwa_notifier_controller.h
@@ -0,0 +1,55 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_NOTIFICATIONS_PWA_NOTIFIER_CONTROLLER_H_ +#define CHROME_BROWSER_NOTIFICATIONS_PWA_NOTIFIER_CONTROLLER_H_ + +#include <map> +#include <memory> +#include <string> + +#include "base/memory/weak_ptr.h" +#include "chrome/browser/notifications/notifier_controller.h" +#include "components/services/app_service/public/cpp/app_registry_cache.h" + +class AppUpdate; +class Profile; + +class PwaNotifierController : public NotifierController, + public apps::AppRegistryCache::Observer { + public: + explicit PwaNotifierController(NotifierController::Observer* observer); + + PwaNotifierController(const PwaNotifierController&) = delete; + PwaNotifierController& operator=(const PwaNotifierController&) = delete; + ~PwaNotifierController() override; + + std::vector<ash::NotifierMetadata> GetNotifierList(Profile* profile) override; + void SetNotifierEnabled(Profile* profile, + const message_center::NotifierId& notifier_id, + bool enabled) override; + + private: + void CallLoadIcon(const std::string& app_id, bool allow_placeholder_icon); + void OnLoadIcon(const std::string& app_id, + apps::mojom::IconValuePtr icon_value); + void SetIcon(const std::string& app_id, gfx::ImageSkia image); + + // apps::AppRegistryCache::Observer: + void OnAppUpdate(const apps::AppUpdate& update) override; + void OnAppRegistryCacheWillBeDestroyed( + apps::AppRegistryCache* cache) override; + + // Needed to load icons for PWAs. + Profile* observed_profile_ = nullptr; + NotifierController::Observer* const observer_; + + // Used to keep track of all PWA start URLs to prevent creation of duplicate + // notifier metadat. + std::map<std::string, std::string> package_to_app_ids_; + + base::WeakPtrFactory<PwaNotifierController> weak_ptr_factory_{this}; +}; + +#endif // CHROME_BROWSER_NOTIFICATIONS_PWA_NOTIFIER_CONTROLLER_H_
diff --git a/chrome/browser/page_load_metrics/observers/core/ukm_page_load_metrics_observer.cc b/chrome/browser/page_load_metrics/observers/core/ukm_page_load_metrics_observer.cc index 9edc70e..1079749 100644 --- a/chrome/browser/page_load_metrics/observers/core/ukm_page_load_metrics_observer.cc +++ b/chrome/browser/page_load_metrics/observers/core/ukm_page_load_metrics_observer.cc
@@ -1113,9 +1113,7 @@ .SetAboveThreshold(smoothness_data.above_threshold) .SetWorstCase(smoothness_data.worst_smoothness) .SetTimingSinceFCPWorstCase( - (smoothness_data.time_max_delta.InMilliseconds() > 5000) - ? 5000 - : smoothness_data.time_max_delta.InMilliseconds()); + smoothness_data.time_max_delta.InMilliseconds()); if (smoothness_data.worst_smoothness_after1sec >= 0) builder.SetWorstCaseAfter1Sec(smoothness_data.worst_smoothness_after1sec); if (smoothness_data.worst_smoothness_after2sec >= 0) @@ -1134,9 +1132,9 @@ "Graphics.Smoothness.PerSession.MaxPercentDroppedFrames_1sWindow", smoothness_data.worst_smoothness); base::UmaHistogramCustomTimes( - "Graphics.Smoothness.PerSession.TimeMaxPrecentDroppedFrame_1sWindow", + "Graphics.Smoothness.PerSession.TimeMaxPercentDroppedFrames_1sWindow", smoothness_data.time_max_delta, base::TimeDelta::FromMilliseconds(1), - base::TimeDelta::FromSeconds(5), 50); + base::TimeDelta::FromSeconds(25), 50); } void UkmPageLoadMetricsObserver::RecordMobileFriendlinessMetrics() {
diff --git a/chrome/browser/password_edit_dialog/android/java/src/org/chromium/chrome/browser/password_edit_dialog/PasswordEditDialogViewTest.java b/chrome/browser/password_edit_dialog/android/java/src/org/chromium/chrome/browser/password_edit_dialog/PasswordEditDialogViewTest.java index c8079db6..e68f9b7 100644 --- a/chrome/browser/password_edit_dialog/android/java/src/org/chromium/chrome/browser/password_edit_dialog/PasswordEditDialogViewTest.java +++ b/chrome/browser/password_edit_dialog/android/java/src/org/chromium/chrome/browser/password_edit_dialog/PasswordEditDialogViewTest.java
@@ -18,13 +18,13 @@ import org.junit.Test; import org.junit.runner.RunWith; -import org.chromium.base.test.BaseActivityTestRule; import org.chromium.base.test.BaseJUnit4ClassRunner; import org.chromium.base.test.util.CriteriaHelper; import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.ui.modelutil.PropertyModel; import org.chromium.ui.modelutil.PropertyModelChangeProcessor; import org.chromium.ui.test.util.DummyUiActivity; +import org.chromium.ui.test.util.ThemedDummyUiActivityTestRule; import java.util.Arrays; @@ -38,8 +38,9 @@ private static final String FOOTER = "Footer"; @ClassRule - public static BaseActivityTestRule<DummyUiActivity> sActivityTestRule = - new BaseActivityTestRule<>(DummyUiActivity.class); + public static ThemedDummyUiActivityTestRule<DummyUiActivity> sActivityTestRule = + new ThemedDummyUiActivityTestRule<>( + DummyUiActivity.class, org.chromium.chrome.R.style.ColorOverlay); private static Activity sActivity;
diff --git a/chrome/browser/policy/browser_dm_token_storage_win.cc b/chrome/browser/policy/browser_dm_token_storage_win.cc index 7ff70530..65b1a69 100644 --- a/chrome/browser/policy/browser_dm_token_storage_win.cc +++ b/chrome/browser/policy/browser_dm_token_storage_win.cc
@@ -134,7 +134,6 @@ std::string BrowserDMTokenStorageWin::InitClientId() { // For the client id, use the Windows machine GUID. - // TODO(crbug.com/821977): Need a backup plan if machine GUID doesn't exist. base::win::RegKey key; LSTATUS status = key.Open(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Cryptography",
diff --git a/chrome/browser/policy/cloud/chrome_browser_cloud_management_browsertest.cc b/chrome/browser/policy/cloud/chrome_browser_cloud_management_browsertest.cc index 29d82a8..5050e2e 100644 --- a/chrome/browser/policy/cloud/chrome_browser_cloud_management_browsertest.cc +++ b/chrome/browser/policy/cloud/chrome_browser_cloud_management_browsertest.cc
@@ -6,6 +6,7 @@ #include <memory> #include <tuple> +#include <utility> #include "base/bind.h" #include "base/callback_helpers.h" @@ -23,21 +24,21 @@ #include "chrome/browser/browser_process.h" #include "chrome/browser/chrome_browser_main.h" #include "chrome/browser/chrome_browser_main_extra_parts.h" -#include "chrome/browser/device_identity/device_oauth2_token_service.h" -#include "chrome/browser/device_identity/device_oauth2_token_service_factory.h" #include "chrome/browser/net/system_network_context_manager.h" #include "chrome/browser/policy/chrome_browser_policy_connector.h" +#include "chrome/browser/policy/cloud/chrome_browser_cloud_management_browsertest_delegate.h" #include "chrome/browser/ui/browser_finder.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/chrome_result_codes.h" #include "chrome/common/chrome_switches.h" -#include "chrome/test/base/in_process_browser_test.h" +#include "chrome/test/base/chrome_test_utils.h" #include "components/enterprise/browser/controller/browser_dm_token_storage.h" #include "components/enterprise/browser/controller/chrome_browser_cloud_management_controller.h" #include "components/enterprise/browser/controller/fake_browser_dm_token_storage.h" #include "components/enterprise/browser/enterprise_switches.h" #include "components/policy/core/common/cloud/chrome_browser_cloud_management_metrics.h" #include "components/policy/core/common/cloud/cloud_policy_constants.h" +#include "components/policy/core/common/cloud/cloud_policy_util.h" #include "components/policy/core/common/cloud/device_management_service.h" #include "components/policy/core/common/cloud/dm_auth.h" #include "components/policy/core/common/cloud/machine_level_user_cloud_policy_manager.h" @@ -59,11 +60,15 @@ #include "services/network/test/test_url_loader_factory.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" -#include "ui/views/test/widget_test.h" + +#if !defined(OS_ANDROID) +#include "chrome/browser/device_identity/device_oauth2_token_service.h" +#include "chrome/browser/device_identity/device_oauth2_token_service_factory.h" +#endif // !defined(OS_ANDROID) #if defined(OS_MAC) #include "chrome/browser/policy/cloud/chrome_browser_cloud_management_browsertest_mac_util.h" -#endif +#endif // defined(OS_MAC) using testing::_; using testing::DoAll; @@ -87,15 +92,19 @@ std::unique_ptr<PolicyStorage> CreatePolicyStorage() { em::CloudPolicySettings settings; - em::BooleanPolicyProto* show_home_button = settings.mutable_showhomebutton(); - show_home_button->mutable_policy_options()->set_mode( + em::BooleanPolicyProto* saving_browser_history_disabled = + settings.mutable_savingbrowserhistorydisabled(); + saving_browser_history_disabled->mutable_policy_options()->set_mode( em::PolicyOptions::MANDATORY); - show_home_button->set_value(true); + saving_browser_history_disabled->set_value(true); auto policy_storage = std::make_unique<PolicyStorage>(); policy_storage->SetPolicyPayload( dm_protocol::kChromeMachineLevelUserCloudPolicyType, settings.SerializeAsString()); + policy_storage->SetPolicyPayload( + dm_protocol::kChromeMachineLevelUserCloudPolicyAndroidType, + settings.SerializeAsString()); policy_storage->set_robot_api_auth_code("fake_auth_code"); policy_storage->set_service_account_identity("foo@bar.com"); return policy_storage; @@ -107,6 +116,7 @@ client_info.device_token = kDMToken; client_info.allowed_policy_types.insert( {dm_protocol::kChromeMachineLevelUserCloudPolicyType, + dm_protocol::kChromeMachineLevelUserCloudPolicyAndroidType, dm_protocol::kChromeMachineLevelExtensionCloudPolicyType}); return client_info; } @@ -114,28 +124,24 @@ class ChromeBrowserCloudManagementControllerObserver : public ChromeBrowserCloudManagementController::Observer { public: + ChromeBrowserCloudManagementControllerObserver( + ChromeBrowserCloudManagementBrowserTestDelegate* delegate) + : delegate_(delegate) {} + ~ChromeBrowserCloudManagementControllerObserver() override = default; + void OnPolicyRegisterFinished(bool succeeded) override { - if (!succeeded && should_display_error_message_) { - EXPECT_EQ(0u, chrome::GetTotalBrowserCount()); -#if defined(OS_MAC) - PostAppControllerNSNotifications(); -#endif - // Close the error dialog. - ASSERT_EQ(1u, views::test::WidgetTest::GetAllWidgets().size()); - (*views::test::WidgetTest::GetAllWidgets().begin())->Close(); - } + delegate_->MaybeCheckDialogClosingAfterPolicyRegistration( + !succeeded && should_display_error_message_); EXPECT_EQ(should_succeed_, succeeded); is_finished_ = true; g_browser_process->browser_policy_connector() ->chrome_browser_cloud_management_controller() ->RemoveObserver(this); - // If enrollment fails, the manager should be marked as initialized - // immediately. Otherwise, this will be done after the policy data is - // downloaded. - EXPECT_EQ(!succeeded, g_browser_process->browser_policy_connector() - ->machine_level_user_cloud_policy_manager() - ->IsInitializationComplete( - PolicyDomain::POLICY_DOMAIN_CHROME)); + EXPECT_EQ( + delegate_->ExpectManagerImmediatelyInitialized(succeeded), + g_browser_process->browser_policy_connector() + ->machine_level_user_cloud_policy_manager() + ->IsInitializationComplete(PolicyDomain::POLICY_DOMAIN_CHROME)); } void SetShouldSucceed(bool should_succeed) { @@ -149,6 +155,8 @@ bool IsFinished() { return is_finished_; } private: + ChromeBrowserCloudManagementBrowserTestDelegate* delegate_; + bool is_finished_ = false; bool should_succeed_ = false; bool should_display_error_message_ = false; @@ -274,11 +282,11 @@ base::DoNothing(), base::DoNothing()); em::DeviceManagementRequest request; - request.mutable_register_browser_request(); - if (!machine_name.empty()) { - request.mutable_register_browser_request()->set_machine_name( - machine_name); - } + em::RegisterBrowserRequest* register_browser_request = + request.mutable_register_browser_request(); + register_browser_request->set_os_platform(GetOSPlatform()); + if (!machine_name.empty()) + register_browser_request->set_machine_name(machine_name); std::string payload; ASSERT_TRUE(request.SerializeToString(&payload)); config->SetRequestPayload(payload); @@ -345,6 +353,8 @@ token_ = response.register_response().device_management_token(); } + ChromeBrowserCloudManagementBrowserTestDelegate delegate_; + std::string token_; std::unique_ptr<DeviceManagementService> service_; network::TestURLLoaderFactory test_url_loader_factory_; @@ -368,13 +378,20 @@ IN_PROC_BROWSER_TEST_P(ChromeBrowserCloudManagementServiceIntegrationTest, RegistrationNoMachineName) { ASSERT_TRUE(token_.empty()); - PerformRegistration(kEnrollmentToken, std::string(), - /*expect_success=*/false); - EXPECT_TRUE(token_.empty()); + bool expect_success = delegate_.AcceptEmptyMachineNameOnBrowserRegistration(); + PerformRegistration(kEnrollmentToken, std::string(), expect_success); + EXPECT_NE(token_.empty(), expect_success); } +#if defined(OS_ANDROID) +// TODO(http://crbug.com/1091438): Enable this test on Android once reporting is +// implemented. +#define MAYBE_ChromeDesktopReport DISABLED_ChromeDesktopReport +#else +#define MAYBE_ChromeDesktopReport ChromeDesktopReport +#endif // defined(OS_ANDROID) IN_PROC_BROWSER_TEST_P(ChromeBrowserCloudManagementServiceIntegrationTest, - ChromeDesktopReport) { + MAYBE_ChromeDesktopReport) { em::ChromeDesktopReportRequest chrome_desktop_report; UploadChromeDesktopReport(&chrome_desktop_report); } @@ -404,7 +421,7 @@ class MachineLevelUserCloudPolicyManagerTest : public PlatformBrowserTest { protected: - bool CreateAndInitManager(const std::string& dm_token) { + int CreateAndInitManager(const std::string& dm_token) { base::ScopedAllowBlockingForTesting scope_for_testing; std::string client_id("client_id"); base::FilePath user_data_dir; @@ -437,10 +454,13 @@ manager->Shutdown(); return observer.was_called(); } + + ChromeBrowserCloudManagementBrowserTestDelegate delegate_; }; IN_PROC_BROWSER_TEST_F(MachineLevelUserCloudPolicyManagerTest, NoDmToken) { - EXPECT_FALSE(CreateAndInitManager(std::string())); + EXPECT_EQ(CreateAndInitManager(std::string()), + delegate_.ExpectOnStoreEventFired()); } IN_PROC_BROWSER_TEST_F(MachineLevelUserCloudPolicyManagerTest, WithDmToken) { @@ -451,7 +471,7 @@ : public PlatformBrowserTest, public ::testing::WithParamInterface<std::tuple<bool, bool, bool>> { public: - ChromeBrowserCloudManagementEnrollmentTest() { + ChromeBrowserCloudManagementEnrollmentTest() : observer_(&delegate_) { BrowserDMTokenStorage::SetForTesting(&storage_); storage_.SetEnrollmentToken(is_enrollment_token_valid() ? kEnrollmentToken @@ -532,6 +552,8 @@ bool storage_enabled() const { return std::get<1>(GetParam()); } bool should_display_error_message() const { return std::get<2>(GetParam()); } + ChromeBrowserCloudManagementBrowserTestDelegate delegate_; + base::HistogramTester histogram_tester_; private: @@ -554,7 +576,7 @@ // message. EXPECT_TRUE(is_enrollment_token_valid() || !should_display_error_message()); - EXPECT_EQ(1u, chrome::GetTotalBrowserCount()); + delegate_.MaybeCheckTotalBrowserCount(1u); VerifyEnrollmentResult(); #if defined(OS_MAC) @@ -566,25 +588,31 @@ #endif } +#if defined(OS_ANDROID) +// No need to run this test with |should_display_error_message| equals true on +// Android. +INSTANTIATE_TEST_SUITE_P( + ChromeBrowserCloudManagementEnrollmentTest, + ChromeBrowserCloudManagementEnrollmentTest, + ::testing::Combine( + ::testing::Bool(), + ::testing::Bool(), + /*should_display_error_message=*/::testing::Values(false))); +#else INSTANTIATE_TEST_SUITE_P(ChromeBrowserCloudManagementEnrollmentTest, ChromeBrowserCloudManagementEnrollmentTest, ::testing::Combine(::testing::Bool(), ::testing::Bool(), ::testing::Bool())); +#endif // defined(OS_ANDROID) -class MachineLevelUserCloudPolicyPolicyFetchTest - : public ChromeBrowserCloudManagementControllerObserver, - public PlatformBrowserTest, - public ::testing::WithParamInterface<std::tuple<std::string, bool>> { +class MachineLevelUserCloudPolicyPolicyFetchObserver + : public ChromeBrowserCloudManagementControllerObserver { public: - MachineLevelUserCloudPolicyPolicyFetchTest() { - BrowserDMTokenStorage::SetForTesting(&storage_); - storage_.SetEnrollmentToken(kEnrollmentToken); - storage_.SetClientId(kClientID); - storage_.EnableStorage(storage_enabled()); - if (!dm_token().empty()) - storage_.SetDMToken(dm_token()); - } + MachineLevelUserCloudPolicyPolicyFetchObserver( + ChromeBrowserCloudManagementBrowserTestDelegate* delegate) + : ChromeBrowserCloudManagementControllerObserver(delegate) {} + ~MachineLevelUserCloudPolicyPolicyFetchObserver() override = default; void QuitOnUnenroll(base::RepeatingClosure quit_closure) { quit_closure_ = std::move(quit_closure); @@ -597,16 +625,33 @@ } } + private: + base::RepeatingClosure quit_closure_; +}; + +class MachineLevelUserCloudPolicyPolicyFetchTest + : public PlatformBrowserTest, + public ::testing::WithParamInterface<std::tuple<std::string, bool>> { + public: + MachineLevelUserCloudPolicyPolicyFetchTest() : observer_(&delegate_) { + BrowserDMTokenStorage::SetForTesting(&storage_); + storage_.SetEnrollmentToken(kEnrollmentToken); + storage_.SetClientId(kClientID); + storage_.EnableStorage(storage_enabled()); + if (!dm_token().empty()) + storage_.SetDMToken(dm_token()); + } + void SetUpOnMainThread() override { g_browser_process->browser_policy_connector() ->chrome_browser_cloud_management_controller() - ->AddObserver(this); + ->AddObserver(&observer_); } void TearDownOnMainThread() override { g_browser_process->browser_policy_connector() ->chrome_browser_cloud_management_controller() - ->RemoveObserver(this); + ->RemoveObserver(&observer_); } void SetUpInProcessBrowserTestFixture() override { @@ -638,13 +683,16 @@ bool storage_enabled() const { return std::get<1>(GetParam()); } protected: + ChromeBrowserCloudManagementBrowserTestDelegate delegate_; + + MachineLevelUserCloudPolicyPolicyFetchObserver observer_; + base::HistogramTester histogram_tester_; private: std::unique_ptr<EmbeddedPolicyTestServer> test_server_; FakeBrowserDMTokenStorage storage_; base::ScopedTempDir temp_dir_; - base::RepeatingClosure quit_closure_; DISALLOW_COPY_AND_ASSIGN(MachineLevelUserCloudPolicyPolicyFetchTest); }; @@ -672,7 +720,7 @@ // |run_loop|'s QuitClosure will be called after the browser attempts to // unenroll from CBCM. This is necessary to quit the loop in the case // the storage fails since the core is not disconnected. - QuitOnUnenroll(run_loop.QuitClosure()); + observer_.QuitOnUnenroll(run_loop.QuitClosure()); } } else { store_observer = std::make_unique<PolicyFetchStoreObserver>( @@ -690,7 +738,7 @@ if (dm_token() != kInvalidDMToken) { EXPECT_EQ(1u, policy_map.size()); EXPECT_EQ(base::Value(true), - *(policy_map.Get(key::kShowHomeButton)->value())); + *(policy_map.Get(key::kSavingBrowserHistoryDisabled)->value())); // The token in storage should be valid. DMToken token = retrieve_dm_token(); @@ -730,11 +778,10 @@ ::testing::Combine(::testing::Values(kDMToken, kInvalidDMToken, ""), ::testing::Bool())); -class MachineLevelUserCloudPolicyRobotAuthTest - : public ChromeBrowserCloudManagementControllerObserver, - public PlatformBrowserTest { +#if !defined(OS_ANDROID) +class MachineLevelUserCloudPolicyRobotAuthTest : public PlatformBrowserTest { public: - MachineLevelUserCloudPolicyRobotAuthTest() { + MachineLevelUserCloudPolicyRobotAuthTest() : observer_(&delegate_) { scoped_feature_list_.InitAndEnableFeature( policy::features::kCBCMPolicyInvalidations); @@ -748,7 +795,7 @@ void SetUpOnMainThread() override { g_browser_process->browser_policy_connector() ->chrome_browser_cloud_management_controller() - ->AddObserver(this); + ->AddObserver(&observer_); test_url_loader_factory_.AddResponse( GaiaUrls::GetInstance()->oauth2_token_url().spec(), R"P({ @@ -765,7 +812,7 @@ void TearDownOnMainThread() override { g_browser_process->browser_policy_connector() ->chrome_browser_cloud_management_controller() - ->RemoveObserver(this); + ->RemoveObserver(&observer_); } void SetUpInProcessBrowserTestFixture() override { @@ -794,11 +841,13 @@ DMToken retrieve_dm_token() { return storage_.RetrieveDMToken(); } private: + ChromeBrowserCloudManagementBrowserTestDelegate delegate_; std::unique_ptr<EmbeddedPolicyTestServer> test_server_; FakeBrowserDMTokenStorage storage_; base::ScopedTempDir temp_dir_; base::test::ScopedFeatureList scoped_feature_list_; network::TestURLLoaderFactory test_url_loader_factory_; + ChromeBrowserCloudManagementControllerObserver observer_; }; // namespace policy // Flaky on linux & win: https://crbug.com/1105167 @@ -833,7 +882,7 @@ EXPECT_EQ(1u, policy_map.size()); EXPECT_EQ(base::Value(true), - *(policy_map.Get(key::kShowHomeButton)->value())); + *(policy_map.Get(key::kSavingBrowserHistoryDisabled)->value())); // The token in storage should be valid. DMToken token = retrieve_dm_token(); @@ -850,5 +899,6 @@ EXPECT_TRUE( DeviceOAuth2TokenServiceFactory::Get()->RefreshTokenIsAvailable()); } +#endif // !defined(OS_ANDROID) } // namespace policy
diff --git a/chrome/browser/policy/cloud/chrome_browser_cloud_management_browsertest_delegate.h b/chrome/browser/policy/cloud/chrome_browser_cloud_management_browsertest_delegate.h new file mode 100644 index 0000000..4322671 --- /dev/null +++ b/chrome/browser/policy/cloud/chrome_browser_cloud_management_browsertest_delegate.h
@@ -0,0 +1,40 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_POLICY_CLOUD_CHROME_BROWSER_CLOUD_MANAGEMENT_BROWSERTEST_DELEGATE_H_ +#define CHROME_BROWSER_POLICY_CLOUD_CHROME_BROWSER_CLOUD_MANAGEMENT_BROWSERTEST_DELEGATE_H_ + +#include <stddef.h> + +namespace policy { + +class ChromeBrowserCloudManagementBrowserTestDelegate { + public: + ChromeBrowserCloudManagementBrowserTestDelegate() = default; + ~ChromeBrowserCloudManagementBrowserTestDelegate() = default; + + // Check if a notification dialog has been closed if |popup_expected| on + // platforms that show an error message if policy registration fails. + void MaybeCheckDialogClosingAfterPolicyRegistration( + bool popup_expected) const; + + // Returns true on platforms in which policy manager initialization is not + // deferred. + bool ExpectManagerImmediatelyInitialized(bool enrollment_succeeded) const; + + // Returns true on platforms for which a machine name is not sent on browser + // registration. + bool AcceptEmptyMachineNameOnBrowserRegistration() const; + + // Returns true on platforms in which either OnStoreLoaded or OnStoreError + // event should be fired even if the browser is not managed by CBCM. + bool ExpectOnStoreEventFired() const; + + // Checks the number of active browsers on platforms where this is possible. + void MaybeCheckTotalBrowserCount(size_t expected_browser_count) const; +}; + +} // namespace policy + +#endif // CHROME_BROWSER_POLICY_CLOUD_CHROME_BROWSER_CLOUD_MANAGEMENT_BROWSERTEST_DELEGATE_H_
diff --git a/chrome/browser/policy/cloud/chrome_browser_cloud_management_browsertest_delegate_android.cc b/chrome/browser/policy/cloud/chrome_browser_cloud_management_browsertest_delegate_android.cc new file mode 100644 index 0000000..74e47df --- /dev/null +++ b/chrome/browser/policy/cloud/chrome_browser_cloud_management_browsertest_delegate_android.cc
@@ -0,0 +1,39 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/policy/cloud/chrome_browser_cloud_management_browsertest_delegate.h" + +namespace policy { + +void ChromeBrowserCloudManagementBrowserTestDelegate:: + MaybeCheckDialogClosingAfterPolicyRegistration(bool popup_expected) const { + // There is no popup shown on Android, no need to check. +} + +bool ChromeBrowserCloudManagementBrowserTestDelegate:: + ExpectManagerImmediatelyInitialized(bool enrollment_succeeded) const { + // Manager is always initialized immediately on Android, so it unblocks + // startup routines that wait for policy service to be available (e.g. FRE). + // + // TODO(http://crbug.com/1203435): this may no longer be needed now that we + // use ProxyPolicyProvider as an indirection to the manager. + return true; +} + +bool ChromeBrowserCloudManagementBrowserTestDelegate:: + AcceptEmptyMachineNameOnBrowserRegistration() const { + return true; +} + +bool ChromeBrowserCloudManagementBrowserTestDelegate::ExpectOnStoreEventFired() + const { + return true; +} + +void ChromeBrowserCloudManagementBrowserTestDelegate:: + MaybeCheckTotalBrowserCount(size_t expected_browser_count) const { + // No checks needed, as enrollment is never required on Android. +} + +} // namespace policy
diff --git a/chrome/browser/policy/cloud/chrome_browser_cloud_management_browsertest_delegate_desktop.cc b/chrome/browser/policy/cloud/chrome_browser_cloud_management_browsertest_delegate_desktop.cc new file mode 100644 index 0000000..91d64673 --- /dev/null +++ b/chrome/browser/policy/cloud/chrome_browser_cloud_management_browsertest_delegate_desktop.cc
@@ -0,0 +1,54 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/policy/cloud/chrome_browser_cloud_management_browsertest_delegate.h" + +#include "build/build_config.h" +#include "chrome/browser/ui/browser_finder.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "ui/views/test/widget_test.h" + +#if defined(OS_MAC) +#include "chrome/browser/policy/cloud/chrome_browser_cloud_management_browsertest_mac_util.h" +#endif // defined(OS_MAC) + +namespace policy { + +void ChromeBrowserCloudManagementBrowserTestDelegate:: + MaybeCheckDialogClosingAfterPolicyRegistration(bool popup_expected) const { + if (popup_expected) { + MaybeCheckTotalBrowserCount(0u); +#if defined(OS_MAC) + PostAppControllerNSNotifications(); +#endif + // Close the error dialog. + ASSERT_EQ(1u, views::test::WidgetTest::GetAllWidgets().size()); // IN-TEST + (*views::test::WidgetTest::GetAllWidgets().begin())->Close(); // IN-TEST + } +} + +bool ChromeBrowserCloudManagementBrowserTestDelegate:: + ExpectManagerImmediatelyInitialized(bool enrollment_succeeded) const { + // If enrollment fails, the manager should be marked as initialized + // immediately. Otherwise, this will be done after the policy data is + // downloaded. + return !enrollment_succeeded; +} + +bool ChromeBrowserCloudManagementBrowserTestDelegate:: + AcceptEmptyMachineNameOnBrowserRegistration() const { + return false; +} + +bool ChromeBrowserCloudManagementBrowserTestDelegate::ExpectOnStoreEventFired() + const { + return false; +} + +void ChromeBrowserCloudManagementBrowserTestDelegate:: + MaybeCheckTotalBrowserCount(size_t expected_browser_count) const { + EXPECT_EQ(chrome::GetTotalBrowserCount(), expected_browser_count); +} + +} // namespace policy
diff --git a/chrome/browser/predictors/predictor_database.cc b/chrome/browser/predictors/predictor_database.cc index 55ee5863..5c50126 100644 --- a/chrome/browser/predictors/predictor_database.cc +++ b/chrome/browser/predictors/predictor_database.cc
@@ -77,6 +77,8 @@ .exclusive_locking = true, .page_size = 4096, .cache_size = 500, + // TODO(pwnall): Add a meta table and remove this option. + .mmap_alt_status_discouraged = true, })), db_task_runner_(db_task_runner), autocomplete_table_( @@ -85,9 +87,6 @@ new ResourcePrefetchPredictorTables(db_task_runner_)) { db_->set_histogram_tag("Predictor"); - // This db does not use [meta] table, store mmap status data elsewhere. - db_->set_mmap_alt_status(); - is_loading_predictor_enabled_ = IsLoadingPredictorEnabled(profile); }
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc index 1027493..03f79ce6 100644 --- a/chrome/browser/prefs/browser_prefs.cc +++ b/chrome/browser/prefs/browser_prefs.cc
@@ -633,6 +633,9 @@ "signin.ProfileSwitchInterceptionDeclinedPref"; #endif +const char kSuggestionsBlocklist[] = "suggestions.blacklist"; +const char kSuggestionsData[] = "suggestions.data"; + // Register local state used only for migration (clearing or moving to a new // key). void RegisterLocalStatePrefsForMigration(PrefRegistrySimple* registry) { @@ -810,6 +813,9 @@ #if BUILDFLAG(ENABLE_DICE_SUPPORT) registry->RegisterDictionaryPref(kProfileSwitchInterceptionDeclinedPref); #endif + + registry->RegisterStringPref(kSuggestionsBlocklist, std::string()); + registry->RegisterStringPref(kSuggestionsData, std::string()); } } // namespace @@ -1591,6 +1597,9 @@ profile_prefs->ClearPref(kProfileSwitchInterceptionDeclinedPref); #endif + profile_prefs->ClearPref(kSuggestionsBlocklist); + profile_prefs->ClearPref(kSuggestionsData); + // Please don't delete the following line. It is used by PRESUBMIT.py. // END_MIGRATE_OBSOLETE_PROFILE_PREFS }
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/background_test.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/background_test.js index a0936f4..561a763c 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/background_test.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/background_test.js
@@ -3565,3 +3565,24 @@ .replay(); }); }); + +TEST_F('ChromeVoxBackgroundTest', 'NestedMenuHints', function() { + const mockFeedback = this.createMockFeedback(); + const site = ` + <div role="menu" aria-orientation="vertical"> + <div role="menu" aria-orientation="horizontal"> + <div tabindex="0" role="menuitem">hello</div> + <div tabindex="0" role="menuitem">bro</div> + </div> + </div> + `; + this.runWithLoadedTree(site, function(root) { + mockFeedback + .expectSpeech( + 'Press left or right arrow to navigate; enter to activate') + .call( + () => assertFalse(mockFeedback.utteranceInQueue( + 'Press up or down arrow to navigate; enter to activate'))) + .replay(); + }); +});
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/output/output.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/output/output.js index 1274f4a..f8e2d38d 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/output/output.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/output/output.js
@@ -2289,7 +2289,10 @@ /** @type {function(?) : boolean} */ (AutomationPredicate.table))) { ret.push({msgId: 'hint_table'}); } - if ((foundAncestor = uniqueAncestors.find( + + // This hint is not based on the role (it uses state), so we need to care + // about ordering; prefer deepest ancestor first. + if ((foundAncestor = uniqueAncestors.reverse().find( /** @type {function(?) : boolean} */ (AutomationPredicate.roles( [RoleType.MENU, RoleType.MENU_BAR]))))) { ret.push({
diff --git a/chrome/browser/resources/chromeos/accessibility/select_to_speak/options.css b/chrome/browser/resources/chromeos/accessibility/select_to_speak/options.css index c8f12aa2..86adfe2 100644 --- a/chrome/browser/resources/chromeos/accessibility/select_to_speak/options.css +++ b/chrome/browser/resources/chromeos/accessibility/select_to_speak/options.css
@@ -61,14 +61,14 @@ width: 646px; } -.option.hidden { +.option.hidden, +.option-group.hidden { display: none; } .sub-option { background-color: #fff; font-size: 13px; - margin-bottom: 16px; max-height: 60px; opacity: 1; overflow: hidden; @@ -110,7 +110,7 @@ line-height: 60px; margin: 20px 0; min-height: 20px; - padding: 0; + padding: 0 0 2px 0; } label { @@ -118,9 +118,33 @@ vertical-align: middle; } +.sub-option input[type='text'] { + background-color: #fff; + border-width: 0 0 1px 0; + height: 25px; + margin-top: 20px; + width: 300px; +} + +.tall { + margin-bottom: 16px; +} + +.short { + line-height: 40px; + vertical-align: bottom; +} + +.right { + float: right; +} + +.wide { + min-width: 200px; +} + .example { display: inline-block; - float: right; font-size: 1em; height: 60px; line-height: 60px; @@ -146,7 +170,8 @@ z-index: 10; } -.option button { +.option button, +.sub-option button { background-color: #fff; border-color: rgb(210, 227, 252); border-radius: 4px; @@ -162,11 +187,13 @@ vertical-align: middle; } -.option button:hover { +.option button:hover, +.sub-option button:hover { background-color: rgba(66, 133, 244, 0.04); } -.option button:active { +.option button:active, +.sub-option button:active { background-color: rgba(66, 133, 244, 0.15); } @@ -211,6 +238,10 @@ color: rgb(95, 99, 104); } +.subtitle a { + color: rgb(26, 115, 232); +} + #navigationControlsOption { padding: 10px 20px; }
diff --git a/chrome/browser/resources/chromeos/accessibility/select_to_speak/options.html b/chrome/browser/resources/chromeos/accessibility/select_to_speak/options.html index 09ae31a4..7dfe0cf 100644 --- a/chrome/browser/resources/chromeos/accessibility/select_to_speak/options.html +++ b/chrome/browser/resources/chromeos/accessibility/select_to_speak/options.html
@@ -15,11 +15,11 @@ <div class="container"> <h2 class="i18n" msgid="options_speech"></h2> - <div class="option-group"> + <div class="option-group" id="noNaturalVoicesOptions"> <div class="option"> <span class="i18n" msgid="options_voices_description" - id="voices_description"></span> - <select id="voice" aria-labelledby="voices_description"> + id="voicesDescription"></span> + <select id="voice" aria-labelledby="voicesDescription"> </select> </div> <hr aria-hidden="true"> @@ -31,6 +31,61 @@ </div> </div> + <div class="option-group hidden" id="naturalVoicesOptions"> + <div class="option"> + <label class="i18n" msgid="options_languages_description" + id="languagesDescription"></label> + <select class="speech-option right wide" id="language" + aria-labelledby="languagesDescription"> + <option value="0" class="i18n" + msgid="options_device_language"> + </option> + </select> + </div> + <div class="option"> + <label class="i18n" msgid="options_preferred_voice_description" + id="voicesDescription"></label> + <select class="speech-option right wide" id="localVoices" + aria-labelledby="voicesDescription"> + </select> + </div> + <div class="option" id="naturalVoicesOption"> + <input id="naturalVoices" type="checkbox" role="switch" + class="checkbox" name="naturalVoices" + aria-labelledby="naturalVoicesLabel"> + <label id="naturalVoicesLabel" class="i18n short" + msgid="options_use_natural_voices"> + </label> + <div class="subtitle"> + <span class="i18n" msgid="options_natural_voices_explanation"> + </span> + <!-- TODO(https://crbug.com/1227547): Change to correct link --> + <a href="https://support.google.com/chromebook/?p=accessibility"> + <span class="i18n" + msgid="options_natural_voices_explanation_more"> + </span> + </a> + </div> + </div> + <div class="sub-option" id="naturalVoiceSelection"> + <label class="i18n" msgid="options_natural_voice" + id="naturalVoiceDescription"></label> + <select class="speech-option right wide" id="naturalVoice" + aria-labelledby="naturalVoiceDescription"> + </select> + </div> + <div class="sub-option" id="naturalVoicePreview"> + <label class="i18n" msgid="options_natural_voice_preview"> + </label> + <button id="naturalVoicesPlay" class="i18n" + msgid="options_play_button"> + </button> + <input id="naturalVoicesExample" name="naturalVoicesExample" + type="text" class="i18n right" + msgid="options_natural_voices_example"> + </div> + </div> + <h2 class="i18n" msgid="options_highlight"></h2> <div class="option-group"> <div class="option" id="wordHighlightOption"> @@ -41,7 +96,7 @@ class="checkbox" name="wordHighlight" aria-labeledby="wordHighlightLabel"> </div> - <div class="sub-option hidden" id="highlightSubOption"> + <div class="sub-option tall hidden" id="highlightSubOption"> <span class="i18n" msgid="options_highlight_color_description" id="highlight_color_description"></span> <select id="highlightColor" @@ -62,12 +117,12 @@ msgid="options_highlight_color_pink"> </option> </select> - <div class="example dark"> + <div class="example right dark"> <span class="i18n" msgid="options_highlight_dark"></span> <div class="highlight"> </div> </div> - <div class="example light"> + <div class="example right light"> <span class="i18n" msgid="options_highlight_light"></span> <div class="highlight"> </div>
diff --git a/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_options.js b/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_options.js index 35effd1..ae47c03 100644 --- a/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_options.js +++ b/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_options.js
@@ -15,50 +15,54 @@ */ init_() { this.addTranslatedMessagesToDom_(); - this.populateVoiceList_('voice'); - window.speechSynthesis.onvoiceschanged = (function() { - this.populateVoiceList_('voice'); - }.bind(this)); - this.syncSelectControlToPref_('voice', 'voice', 'voiceName'); + // Depending on whether the enhanced TTS voices are enabled, show either the + // enhanced voices settings or the legacy settings. + const AccessibilityFeature = + chrome.accessibilityPrivate.AccessibilityFeature; + chrome.accessibilityPrivate.isFeatureEnabled( + AccessibilityFeature.ENHANCED_NETWORK_VOICES, (result) => { + const newElem = document.getElementById('naturalVoicesOptions'); + const legacyElem = document.getElementById('noNaturalVoicesOptions'); + if (!result) { + // Show UI without natural voices + this.hideElement(newElem); + this.showElement(legacyElem); + this.populateVoiceList_('voice'); + window.speechSynthesis.onvoiceschanged = (function() { + this.populateVoiceList_('voice'); + }.bind(this)); + this.syncSelectControlToPref_('voice', 'voice', 'voiceName'); + } else { + // Show UI with natural voices + this.hideElement(legacyElem); + this.showElement(newElem); + this.populateVoiceList_('localVoices'); + window.speechSynthesis.onvoiceschanged = (function() { + this.populateVoiceList_('localVoices'); + }.bind(this)); + // TODO(crbug.com/1227589): add enhanced voice settings to prefs + // and sync the controls for those settings to preferences + } + }); + this.syncCheckboxControlToPref_( 'wordHighlight', 'wordHighlight', (checked) => { const elem = document.getElementById('highlightSubOption'); const select = document.getElementById('highlightColor'); - if (checked) { - elem.classList.remove('hidden'); - elem.setAttribute('aria-hidden', false); - select.disabled = false; - } else { - elem.classList.add('hidden'); - elem.setAttribute('aria-hidden', true); - select.disabled = true; - } + this.setElementVisible(elem, checked); + select.disabled = !checked; }); this.syncCheckboxControlToPref_( 'backgroundShading', 'backgroundShading', (checked) => { const elem = document.getElementById('backgroundPreviewContainer'); - if (checked) { - elem.classList.remove('hidden'); - elem.setAttribute('aria-hidden', false); - } else { - elem.classList.add('hidden'); - elem.setAttribute('aria-hidden', true); - } + this.setElementVisible(elem, checked); }); this.syncCheckboxControlToPref_('navigationControls', 'navigationControls'); // Hide navigation control setting if feature is not enabled - const AccessibilityFeature = - chrome.accessibilityPrivate.AccessibilityFeature; chrome.accessibilityPrivate.isFeatureEnabled( AccessibilityFeature.SELECT_TO_SPEAK_NAVIGATION_CONTROL, (result) => { const elem = document.getElementById('navigationControlsOption'); - if (!result) { - elem.classList.add('hidden'); - elem.setAttribute('aria-hidden', true); - } else { - elem.classList.remove('hidden'); - elem.setAttribute('aria-hidden', false); - } + this.setElementVisible(elem, result); }); this.setUpHighlightListener_(); @@ -68,6 +72,36 @@ } /** + * Shows an element. + * @private + */ + showElement(element) { + element.classList.remove('hidden'); + element.setAttribute('aria-hidden', false); + } + + /** + * Hides an element. + * @private + */ + hideElement(element) { + element.classList.add('hidden'); + element.setAttribute('aria-hidden', true); + } + + /** + * Shows or hides an element. + * @private + */ + setElementVisible(element, isVisible) { + if (isVisible) { + this.showElement(element); + } else { + this.hideElement(element); + } + } + + /** * Processes an HTML DOM, replacing text content with translated text messages * on elements marked up for translation. Elements whose class attributes * contain the 'i18n' class name are expected to also have an msgid @@ -84,7 +118,7 @@ } var translated = chrome.i18n.getMessage('select_to_speak_' + msgid); if (elts[i].tagName === 'INPUT') { - elts[i].setAttribute('placeholder', translated); + elts[i].setAttribute('value', translated); } else { elts[i].textContent = translated; }
diff --git a/chrome/browser/resources/chromeos/accessibility/strings/select_to_speak_strings.grdp b/chrome/browser/resources/chromeos/accessibility/strings/select_to_speak_strings.grdp index 75402b20..535be6b 100644 --- a/chrome/browser/resources/chromeos/accessibility/strings/select_to_speak_strings.grdp +++ b/chrome/browser/resources/chromeos/accessibility/strings/select_to_speak_strings.grdp
@@ -15,6 +15,36 @@ <message desc="Label for the control in the Select-to-speak options dialog where the user can choose a voice from a list." name="IDS_SELECT_TO_SPEAK_OPTIONS_VOICES_DESCRIPTION"> Select a voice: </message> +<message desc="Label for the control in the Select-to-speak options dialog where the user can choose a language from a list." name="IDS_SELECT_TO_SPEAK_OPTIONS_LANGUAGES_DESCRIPTION"> + Language +</message> +<message desc="The option in the language list where the default language of the device is used as the speech language." name="IDS_SELECT_TO_SPEAK_OPTIONS_DEVICE_LANGUAGE"> + Device language +</message> +<message desc="Label for the control in the Select-to-speak options dialog where the user can choose a preferred voice for the chosen language from a list." name="IDS_SELECT_TO_SPEAK_OPTIONS_PREFERRED_VOICE_DESCRIPTION"> + Preferred voice +</message> +<message desc="Label for the control in the Select-to-speak options dialog where the user can enable support for high-quality voices streamed from the interent when the device is online." name="IDS_SELECT_TO_SPEAK_OPTIONS_USE_NATURAL_VOICES"> + Use natural voice when device is online +</message> +<message desc="Informational text related to the Select-to-speak control that enables support for high-quality voices, mentioning that enabling these voices will send text to Google for processing and generating audio." name="IDS_SELECT_TO_SPEAK_OPTIONS_NATURAL_VOICES_EXPLANATION"> + Text will be sent to Google for processing. +</message> +<message desc="Label of link to more information about high-quality voices in Select-to-speak, mentioning that enabling these voices will send text to Google for processing and generating audio." name="IDS_SELECT_TO_SPEAK_OPTIONS_NATURAL_VOICES_EXPLANATION_MORE"> + Learn more +</message> +<message desc="Label for the control in the Select-to-speak options dialog where the user can choose a high-quality voice to be streamed from the internet from a list." name="IDS_SELECT_TO_SPEAK_OPTIONS_NATURAL_VOICE"> + Natural voice +</message> +<message desc="Label for the control in the Select-to-speak options dialog where the user can listen to a preview of the selected high-quality voice." name="IDS_SELECT_TO_SPEAK_OPTIONS_NATURAL_VOICE_PREVIEW"> + Voice preview +</message> +<message desc="Example text to preview the selected high-quality voice." name="IDS_SELECT_TO_SPEAK_OPTIONS_NATURAL_VOICES_EXAMPLE"> + Hi there! I'm your text-to-speech voice. +</message> +<message desc="Label for the button in the Select-to-speak options dialog to preview the selected high-quality voice." name="IDS_SELECT_TO_SPEAK_OPTIONS_PLAY_BUTTON"> + Play +</message> <message desc="Group of options controlling highlighting." name="IDS_SELECT_TO_SPEAK_OPTIONS_HIGHLIGHT"> Highlighting </message>
diff --git a/chrome/browser/resources/chromeos/accessibility/strings/select_to_speak_strings_grdp/IDS_SELECT_TO_SPEAK_OPTIONS_DEVICE_LANGUAGE.png.sha1 b/chrome/browser/resources/chromeos/accessibility/strings/select_to_speak_strings_grdp/IDS_SELECT_TO_SPEAK_OPTIONS_DEVICE_LANGUAGE.png.sha1 new file mode 100644 index 0000000..1627cfe --- /dev/null +++ b/chrome/browser/resources/chromeos/accessibility/strings/select_to_speak_strings_grdp/IDS_SELECT_TO_SPEAK_OPTIONS_DEVICE_LANGUAGE.png.sha1
@@ -0,0 +1 @@ +d803782dbcf5890c15854c90c1d37f89ed2fcdc9 \ No newline at end of file
diff --git a/chrome/browser/resources/chromeos/accessibility/strings/select_to_speak_strings_grdp/IDS_SELECT_TO_SPEAK_OPTIONS_LANGUAGES_DESCRIPTION.png.sha1 b/chrome/browser/resources/chromeos/accessibility/strings/select_to_speak_strings_grdp/IDS_SELECT_TO_SPEAK_OPTIONS_LANGUAGES_DESCRIPTION.png.sha1 new file mode 100644 index 0000000..1627cfe --- /dev/null +++ b/chrome/browser/resources/chromeos/accessibility/strings/select_to_speak_strings_grdp/IDS_SELECT_TO_SPEAK_OPTIONS_LANGUAGES_DESCRIPTION.png.sha1
@@ -0,0 +1 @@ +d803782dbcf5890c15854c90c1d37f89ed2fcdc9 \ No newline at end of file
diff --git a/chrome/browser/resources/chromeos/accessibility/strings/select_to_speak_strings_grdp/IDS_SELECT_TO_SPEAK_OPTIONS_NATURAL_VOICE.png.sha1 b/chrome/browser/resources/chromeos/accessibility/strings/select_to_speak_strings_grdp/IDS_SELECT_TO_SPEAK_OPTIONS_NATURAL_VOICE.png.sha1 new file mode 100644 index 0000000..1627cfe --- /dev/null +++ b/chrome/browser/resources/chromeos/accessibility/strings/select_to_speak_strings_grdp/IDS_SELECT_TO_SPEAK_OPTIONS_NATURAL_VOICE.png.sha1
@@ -0,0 +1 @@ +d803782dbcf5890c15854c90c1d37f89ed2fcdc9 \ No newline at end of file
diff --git a/chrome/browser/resources/chromeos/accessibility/strings/select_to_speak_strings_grdp/IDS_SELECT_TO_SPEAK_OPTIONS_NATURAL_VOICES_EXAMPLE.png.sha1 b/chrome/browser/resources/chromeos/accessibility/strings/select_to_speak_strings_grdp/IDS_SELECT_TO_SPEAK_OPTIONS_NATURAL_VOICES_EXAMPLE.png.sha1 new file mode 100644 index 0000000..1627cfe --- /dev/null +++ b/chrome/browser/resources/chromeos/accessibility/strings/select_to_speak_strings_grdp/IDS_SELECT_TO_SPEAK_OPTIONS_NATURAL_VOICES_EXAMPLE.png.sha1
@@ -0,0 +1 @@ +d803782dbcf5890c15854c90c1d37f89ed2fcdc9 \ No newline at end of file
diff --git a/chrome/browser/resources/chromeos/accessibility/strings/select_to_speak_strings_grdp/IDS_SELECT_TO_SPEAK_OPTIONS_NATURAL_VOICES_EXPLANATION.png.sha1 b/chrome/browser/resources/chromeos/accessibility/strings/select_to_speak_strings_grdp/IDS_SELECT_TO_SPEAK_OPTIONS_NATURAL_VOICES_EXPLANATION.png.sha1 new file mode 100644 index 0000000..1627cfe --- /dev/null +++ b/chrome/browser/resources/chromeos/accessibility/strings/select_to_speak_strings_grdp/IDS_SELECT_TO_SPEAK_OPTIONS_NATURAL_VOICES_EXPLANATION.png.sha1
@@ -0,0 +1 @@ +d803782dbcf5890c15854c90c1d37f89ed2fcdc9 \ No newline at end of file
diff --git a/chrome/browser/resources/chromeos/accessibility/strings/select_to_speak_strings_grdp/IDS_SELECT_TO_SPEAK_OPTIONS_NATURAL_VOICES_EXPLANATION_MORE.png.sha1 b/chrome/browser/resources/chromeos/accessibility/strings/select_to_speak_strings_grdp/IDS_SELECT_TO_SPEAK_OPTIONS_NATURAL_VOICES_EXPLANATION_MORE.png.sha1 new file mode 100644 index 0000000..1627cfe --- /dev/null +++ b/chrome/browser/resources/chromeos/accessibility/strings/select_to_speak_strings_grdp/IDS_SELECT_TO_SPEAK_OPTIONS_NATURAL_VOICES_EXPLANATION_MORE.png.sha1
@@ -0,0 +1 @@ +d803782dbcf5890c15854c90c1d37f89ed2fcdc9 \ No newline at end of file
diff --git a/chrome/browser/resources/chromeos/accessibility/strings/select_to_speak_strings_grdp/IDS_SELECT_TO_SPEAK_OPTIONS_NATURAL_VOICE_DEFAULT.png.sha1 b/chrome/browser/resources/chromeos/accessibility/strings/select_to_speak_strings_grdp/IDS_SELECT_TO_SPEAK_OPTIONS_NATURAL_VOICE_DEFAULT.png.sha1 new file mode 100644 index 0000000..1627cfe --- /dev/null +++ b/chrome/browser/resources/chromeos/accessibility/strings/select_to_speak_strings_grdp/IDS_SELECT_TO_SPEAK_OPTIONS_NATURAL_VOICE_DEFAULT.png.sha1
@@ -0,0 +1 @@ +d803782dbcf5890c15854c90c1d37f89ed2fcdc9 \ No newline at end of file
diff --git a/chrome/browser/resources/chromeos/accessibility/strings/select_to_speak_strings_grdp/IDS_SELECT_TO_SPEAK_OPTIONS_NATURAL_VOICE_PREVIEW.png.sha1 b/chrome/browser/resources/chromeos/accessibility/strings/select_to_speak_strings_grdp/IDS_SELECT_TO_SPEAK_OPTIONS_NATURAL_VOICE_PREVIEW.png.sha1 new file mode 100644 index 0000000..1627cfe --- /dev/null +++ b/chrome/browser/resources/chromeos/accessibility/strings/select_to_speak_strings_grdp/IDS_SELECT_TO_SPEAK_OPTIONS_NATURAL_VOICE_PREVIEW.png.sha1
@@ -0,0 +1 @@ +d803782dbcf5890c15854c90c1d37f89ed2fcdc9 \ No newline at end of file
diff --git a/chrome/browser/resources/chromeos/accessibility/strings/select_to_speak_strings_grdp/IDS_SELECT_TO_SPEAK_OPTIONS_PLAY_BUTTON.png.sha1 b/chrome/browser/resources/chromeos/accessibility/strings/select_to_speak_strings_grdp/IDS_SELECT_TO_SPEAK_OPTIONS_PLAY_BUTTON.png.sha1 new file mode 100644 index 0000000..1627cfe --- /dev/null +++ b/chrome/browser/resources/chromeos/accessibility/strings/select_to_speak_strings_grdp/IDS_SELECT_TO_SPEAK_OPTIONS_PLAY_BUTTON.png.sha1
@@ -0,0 +1 @@ +d803782dbcf5890c15854c90c1d37f89ed2fcdc9 \ No newline at end of file
diff --git a/chrome/browser/resources/chromeos/accessibility/strings/select_to_speak_strings_grdp/IDS_SELECT_TO_SPEAK_OPTIONS_PREFERRED_VOICE_DESCRIPTION.png.sha1 b/chrome/browser/resources/chromeos/accessibility/strings/select_to_speak_strings_grdp/IDS_SELECT_TO_SPEAK_OPTIONS_PREFERRED_VOICE_DESCRIPTION.png.sha1 new file mode 100644 index 0000000..1627cfe --- /dev/null +++ b/chrome/browser/resources/chromeos/accessibility/strings/select_to_speak_strings_grdp/IDS_SELECT_TO_SPEAK_OPTIONS_PREFERRED_VOICE_DESCRIPTION.png.sha1
@@ -0,0 +1 @@ +d803782dbcf5890c15854c90c1d37f89ed2fcdc9 \ No newline at end of file
diff --git a/chrome/browser/resources/chromeos/accessibility/strings/select_to_speak_strings_grdp/IDS_SELECT_TO_SPEAK_OPTIONS_USE_NATURAL_VOICES.png.sha1 b/chrome/browser/resources/chromeos/accessibility/strings/select_to_speak_strings_grdp/IDS_SELECT_TO_SPEAK_OPTIONS_USE_NATURAL_VOICES.png.sha1 new file mode 100644 index 0000000..1627cfe --- /dev/null +++ b/chrome/browser/resources/chromeos/accessibility/strings/select_to_speak_strings_grdp/IDS_SELECT_TO_SPEAK_OPTIONS_USE_NATURAL_VOICES.png.sha1
@@ -0,0 +1 @@ +d803782dbcf5890c15854c90c1d37f89ed2fcdc9 \ No newline at end of file
diff --git a/chrome/browser/resources/chromeos/accessibility/strings/select_to_speak_strings_grdp/IDS_SELECT_TO_SPEAK_OPTIONS_VOICES_DESCRIPTION.png.sha1 b/chrome/browser/resources/chromeos/accessibility/strings/select_to_speak_strings_grdp/IDS_SELECT_TO_SPEAK_OPTIONS_VOICES_DESCRIPTION.png.sha1 new file mode 100644 index 0000000..1627cfe --- /dev/null +++ b/chrome/browser/resources/chromeos/accessibility/strings/select_to_speak_strings_grdp/IDS_SELECT_TO_SPEAK_OPTIONS_VOICES_DESCRIPTION.png.sha1
@@ -0,0 +1 @@ +d803782dbcf5890c15854c90c1d37f89ed2fcdc9 \ No newline at end of file
diff --git a/chrome/browser/resources/new_tab_page/modules/cart_v2/module.html b/chrome/browser/resources/new_tab_page/modules/cart_v2/module.html index 020890b..0f2e5b2d 100644 --- a/chrome/browser/resources/new_tab_page/modules/cart_v2/module.html +++ b/chrome/browser/resources/new_tab_page/modules/cart_v2/module.html
@@ -29,10 +29,6 @@ position: relative; } - :host([header-description-text]) #moduleContent { - height: 158px; - } - #cartCarousel { display: flex; flex-direction: column; @@ -43,10 +39,6 @@ z-index: 0; } - :host([header-description-text]) #cartCarousel { - padding-top: 16px; - } - #consentCard, .cart-item { margin: 0 15px 24px 15px; @@ -277,7 +269,6 @@ <div id="module"> <ntp-module-header chip-text="[[headerChipText]]" - description-text="[[headerDescriptionText]]" dismiss-text="[[i18nRecursive('', 'modulesDismissButtonText', 'modulesCartLowerThese')]]"
diff --git a/chrome/browser/resources/new_tab_page/modules/drive/module.js b/chrome/browser/resources/new_tab_page/modules/drive/module.js index 8e19f88..bebe27d12 100644 --- a/chrome/browser/resources/new_tab_page/modules/drive/module.js +++ b/chrome/browser/resources/new_tab_page/modules/drive/module.js
@@ -32,7 +32,7 @@ static get properties() { return { - /** @type {Array<!drive.mojom.File>} */ + /** @type {!Array<!drive.mojom.File>} */ files: Array, }; }
diff --git a/chrome/browser/resources/new_tab_page/modules/drive_v2/BUILD.gn b/chrome/browser/resources/new_tab_page/modules/drive_v2/BUILD.gn index a6ebcb5..f1fca89 100644 --- a/chrome/browser/resources/new_tab_page/modules/drive_v2/BUILD.gn +++ b/chrome/browser/resources/new_tab_page/modules/drive_v2/BUILD.gn
@@ -8,6 +8,7 @@ js_library("module") { deps = [ "..:module_descriptor", + "//chrome/browser/resources/new_tab_page/modules/drive:drive_module_proxy", "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", ] }
diff --git a/chrome/browser/resources/new_tab_page/modules/drive_v2/module.html b/chrome/browser/resources/new_tab_page/modules/drive_v2/module.html index e69de29..e401943 100644 --- a/chrome/browser/resources/new_tab_page/modules/drive_v2/module.html +++ b/chrome/browser/resources/new_tab_page/modules/drive_v2/module.html
@@ -0,0 +1,31 @@ +<style> + :host { + display: block; + height: 100%; + width: 100%; + } + + #files { + display: flex; + flex-direction: column; + } + + .file-title { + size: 13px; + } + + .file-description { + color: var(--cr-secondary-text-color); + size: 12px; + } +</style> +<div id="files"> + <template id="fileRepeat" is="dom-repeat" items="[[files]]"> + <a class="file"> + <div class="file-info"> + <div class="file-title">[[item.title]]</div> + <div class="file-description">[[item.justificationText]]</div> + </div> + </a> + </template> +</div>
diff --git a/chrome/browser/resources/new_tab_page/modules/drive_v2/module.js b/chrome/browser/resources/new_tab_page/modules/drive_v2/module.js index d38ad93..3f3f6c2c 100644 --- a/chrome/browser/resources/new_tab_page/modules/drive_v2/module.js +++ b/chrome/browser/resources/new_tab_page/modules/drive_v2/module.js
@@ -5,6 +5,7 @@ import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {loadTimeData} from '../../i18n_setup.js'; +import {DriveProxy} from '../drive/drive_module_proxy.js'; import {ModuleDescriptor} from '../module_descriptor.js'; class DriveModuleElement extends PolymerElement { @@ -15,13 +16,25 @@ static get template() { return html`{__html_template__}`; } + + static get properties() { + return { + /** @type {!Array<!drive.mojom.File>} */ + files: Array, + }; + } } customElements.define(DriveModuleElement.is, DriveModuleElement); -/** @return {!Promise<!DriveModuleElement>} */ +/** @return {!Promise<DriveModuleElement>} */ async function createDriveElement() { + const {files} = await DriveProxy.getInstance().handler.getFiles(); + if (files.length === 0) { + return null; + } const element = new DriveModuleElement(); + element.files = files; return element; }
diff --git a/chrome/browser/resources/read_later/side_panel/bookmark_folder.html b/chrome/browser/resources/read_later/side_panel/bookmark_folder.html index 9101f986..0800c8e 100644 --- a/chrome/browser/resources/read_later/side_panel/bookmark_folder.html +++ b/chrome/browser/resources/read_later/side_panel/bookmark_folder.html
@@ -104,7 +104,8 @@ <template is="dom-if" if="[[item.url]]" restamp> <a role="treeitem" href="[[item.url]]" class="bookmark row" - on-click="onBookmarkClick_"> + on-click="onBookmarkClick_" + on-contextmenu="onBookmarkContextMenu_"> <div class="icon" style="background-image: [[getBookmarkIcon_(item.url)]]">
diff --git a/chrome/browser/resources/read_later/side_panel/bookmark_folder.ts b/chrome/browser/resources/read_later/side_panel/bookmark_folder.ts index b4091e68..0130584 100644 --- a/chrome/browser/resources/read_later/side_panel/bookmark_folder.ts +++ b/chrome/browser/resources/read_later/side_panel/bookmark_folder.ts
@@ -13,7 +13,9 @@ import {BookmarksApiProxy} from './bookmarks_api_proxy.js'; /** Event interface for dom-repeat. */ -interface RepeaterEvent extends CustomEvent { +interface RepeaterMouseEvent extends CustomEvent { + clientX: number; + clientY: number; model: { item: chrome.bookmarks.BookmarkTreeNode, }; @@ -71,11 +73,17 @@ openFolders: string[]; private bookmarksApi_: BookmarksApiProxy = BookmarksApiProxy.getInstance(); - private onBookmarkClick_(event: RepeaterEvent) { + private onBookmarkClick_(event: RepeaterMouseEvent) { event.preventDefault(); this.bookmarksApi_.openBookmark(event.model.item.url!); } + private onBookmarkContextMenu_(event: RepeaterMouseEvent) { + event.preventDefault(); + this.bookmarksApi_.showContextMenu( + event.model.item.id, event.clientX, event.clientY); + } + private getBookmarkIcon_(url: string): string { return getFaviconForPageURL(url, false); }
diff --git a/chrome/browser/resources/read_later/side_panel/bookmarks_api_proxy.ts b/chrome/browser/resources/read_later/side_panel/bookmarks_api_proxy.ts index 15cc1e7..79e29d5 100644 --- a/chrome/browser/resources/read_later/side_panel/bookmarks_api_proxy.ts +++ b/chrome/browser/resources/read_later/side_panel/bookmarks_api_proxy.ts
@@ -45,6 +45,10 @@ this.handler.openBookmark({url}); } + showContextMenu(id: string, x: number, y: number) { + this.handler.showContextMenu(id, {x, y}); + } + static getInstance() { return instance || (instance = new BookmarksApiProxy()); }
diff --git a/chrome/browser/resources/settings/chromeos/internet_page/internet_detail_page.html b/chrome/browser/resources/settings/chromeos/internet_page/internet_detail_page.html index 8408f13..3d6c528d 100644 --- a/chrome/browser/resources/settings/chromeos/internet_page/internet_detail_page.html +++ b/chrome/browser/resources/settings/chromeos/internet_page/internet_detail_page.html
@@ -422,12 +422,10 @@ </template> </template> </template> -<template is="dom-if" if="[[showConfigurableSections_]]" restamp> - <template is="dom-if" if="[[isTether_(managedProperties_)]]" restamp> - <tether-connection-dialog id="tetherDialog" - managed-properties="[[managedProperties_]]" - on-tether-connect="onTetherConnect_" - out-of-range="[[outOfRange_]]"> - </tether-connection-dialog> - </template> +<template is="dom-if" if="[[isTether_(managedProperties_)]]" restamp> + <tether-connection-dialog id="tetherDialog" + managed-properties="[[managedProperties_]]" + on-tether-connect="onTetherConnect_" + out-of-range="[[outOfRange_]]"> + </tether-connection-dialog> </template>
diff --git a/chrome/browser/resources/settings/chromeos/os_a11y_page/manage_a11y_page.html b/chrome/browser/resources/settings/chromeos/os_a11y_page/manage_a11y_page.html index 57f64b9..0504ae29 100644 --- a/chrome/browser/resources/settings/chromeos/os_a11y_page/manage_a11y_page.html +++ b/chrome/browser/resources/settings/chromeos/os_a11y_page/manage_a11y_page.html
@@ -220,6 +220,26 @@ sub-label="[[dictationSubtitle_]]" deep-link-focus-id$="[[Setting.kDictation]]"> </settings-toggle-button> + <template is="dom-if" if="[[areDictationLocalePrefsAllowed_]]"> + <template is="dom-if" if="[[prefs.settings.a11y.dictation.value]]"> + <div class="settings-box continuation indented"> + <div class="flex start settings-box-text" id="labelWrapper"> + <div class="label" aria-hidden="true"> + $i18n{dictationLocaleMenuLabel} + </div> + <div class="secondary label"> + [[dictationLocaleMenuSubtitle_]] + </div> + </div> + <settings-dropdown-menu label="$i18n{dictationLocaleMenuLabel}" + pref="{{prefs.settings.a11y.dictation_locale}}" + menu-options="[[dictationLocaleOptions_]]" + disabled="[[!prefs.settings.a11y.dictation.value]]" + on-settings-control-change="onDictationLocalesChanged_"> + </settings-dropdown-menu> + </div> + </template> + </template> <settings-toggle-button class="hr" pref="{{prefs.settings.a11y.focus_highlight}}"
diff --git a/chrome/browser/resources/settings/chromeos/os_a11y_page/manage_a11y_page.js b/chrome/browser/resources/settings/chromeos/os_a11y_page/manage_a11y_page.js index 6ba2d914..7ff0d9c 100644 --- a/chrome/browser/resources/settings/chromeos/os_a11y_page/manage_a11y_page.js +++ b/chrome/browser/resources/settings/chromeos/os_a11y_page/manage_a11y_page.js
@@ -230,6 +230,35 @@ value: loadTimeData.getString('dictationDescription'), }, + /** @private */ + dictationLocaleMenuSubtitle_: { + type: String, + value: '', + }, + + /** @private */ + areDictationLocalePrefsAllowed_: { + type: String, + readOnly: true, + value: loadTimeData.getBoolean('areDictationLocalePrefsAllowed'), + }, + + /** @private */ + dictationLocaleOptions_: { + type: Array, + value() { + return []; + } + }, + + /** @private */ + dictationLocalesList_: { + type: Array, + value() { + return []; + } + }, + /** * |hasKeyboard_|, |hasMouse_|, |hasPointingStick_|, and |hasTouchpad_| * start undefined so observers don't trigger until they have been @@ -349,6 +378,8 @@ this.addWebUIListener( 'dictation-setting-subtitle-changed', this.onDictationSettingSubtitleChanged_.bind(this)); + this.addWebUIListener( + 'dictation-locales-set', this.onDictationLocalesSet_.bind(this)); this.manageBrowserProxy_.manageA11yPageReady(); const r = settings.routes; @@ -583,7 +614,8 @@ onManageAllyPageReady_(startup_sound_enabled) { this.$.startupSoundEnabled.checked = startup_sound_enabled; }, - /* + + /** * Whether additional features link should be shown. * @param {boolean} isKiosk * @param {boolean} isGuest @@ -601,4 +633,67 @@ onDictationSettingSubtitleChanged_(subtitle) { this.dictationSubtitle_ = subtitle; }, + + + /** + * Saves a list of locales and updates the UI to reflect the list. + * @param {!Array<!Array<string>>} locales + * @private + */ + onDictationLocalesSet_(locales) { + this.dictationLocalesList_ = locales; + this.onDictationLocalesChanged_(); + }, + + /** + * Converts an array of locales and their human-readable equivalents to + * an array of menu options. + * TODO(crbug.com/1195916): Use 'offline' to indicate to the user which + * locales work offline with an icon in the select options. + * @private + */ + onDictationLocalesChanged_() { + const currentLocale = + this.get('prefs.settings.a11y.dictation_locale.value'); + this.dictationLocaleOptions_ = + this.dictationLocalesList_ + .map((localeInfo) => { + return { + name: localeInfo.name, + value: localeInfo.value, + offline: localeInfo.offline, + recommended: localeInfo.recommended || + localeInfo.value === currentLocale, + }; + }) + .sort((first, second) => { + // All recommended locales go first. + // TODO(crbug.com/1195916): Display recommended languages at the + // top of the select options with a horizontal divider before all + // languages. + if (first.recommended !== second.recommended) { + return first.recommended ? -1 : 1; + } + return first.name.localeCompare(second.name); + }); + this.updateDictationLocaleSubtitle_(); + }, + + /** + * Updates the Dictation locale subtitle. + * @private + */ + updateDictationLocaleSubtitle_() { + const currentLocale = + this.get('prefs.settings.a11y.dictation_locale.value'); + const locale = this.dictationLocaleOptions_.find( + (element) => element.value === currentLocale); + if (!locale) { + return ''; + } + this.dictationLocaleMenuSubtitle_ = this.i18n( + locale.offline ? 'dictationLocaleSubLabelOffline' : + 'dictationLocaleSubLabelNetwork', + locale.name); + } });
diff --git a/chrome/browser/safe_browsing/BUILD.gn b/chrome/browser/safe_browsing/BUILD.gn index ec5865b..144db98 100644 --- a/chrome/browser/safe_browsing/BUILD.gn +++ b/chrome/browser/safe_browsing/BUILD.gn
@@ -112,6 +112,10 @@ "client_side_detection_service_factory.h", "delayed_warning_navigation_throttle.cc", "delayed_warning_navigation_throttle.h", + "network_context_service.cc", + "network_context_service.h", + "network_context_service_factory.cc", + "network_context_service_factory.h", "safe_browsing_blocking_page.cc", "safe_browsing_blocking_page.h", "safe_browsing_blocking_page_factory.h",
diff --git a/chrome/browser/safe_browsing/cloud_content_scanning/file_analysis_request.cc b/chrome/browser/safe_browsing/cloud_content_scanning/file_analysis_request.cc index 7568132d..8d65d60 100644 --- a/chrome/browser/safe_browsing/cloud_content_scanning/file_analysis_request.cc +++ b/chrome/browser/safe_browsing/cloud_content_scanning/file_analysis_request.cc
@@ -17,6 +17,8 @@ #include "chrome/services/file_util/public/cpp/sandboxed_rar_analyzer.h" #include "chrome/services/file_util/public/cpp/sandboxed_zip_analyzer.h" #include "components/safe_browsing/core/common/features.h" +#include "content/public/browser/browser_task_traits.h" +#include "content/public/browser/browser_thread.h" #include "crypto/secure_hash.h" #include "crypto/sha2.h" #include "net/base/filename_util.h" @@ -124,12 +126,14 @@ base::FilePath path, base::FilePath file_name, std::string mime_type, + bool delay_opening_file, BinaryUploadService::ContentAnalysisCallback callback) : Request(std::move(callback), analysis_settings.analysis_url), has_cached_result_(false), block_unsupported_types_(analysis_settings.block_unsupported_file_types), path_(std::move(path)), - file_name_(std::move(file_name)) { + file_name_(std::move(file_name)), + delay_opening_file_(delay_opening_file) { set_filename(file_name_.AsUTF8Unsafe()); cached_data_.mime_type = std::move(mime_type); } @@ -137,17 +141,37 @@ FileAnalysisRequest::~FileAnalysisRequest() = default; void FileAnalysisRequest::GetRequestData(DataCallback callback) { + data_callback_ = std::move(callback); + if (has_cached_result_) { - std::move(callback).Run(cached_result_, cached_data_); + RunCallback(); return; } - base::ThreadPool::PostTaskAndReplyWithResult( - FROM_HERE, {base::TaskPriority::USER_VISIBLE, base::MayBlock()}, - base::BindOnce(&GetFileDataBlocking, path_, - cached_data_.mime_type.empty()), + if (!delay_opening_file_) { + base::ThreadPool::PostTaskAndReplyWithResult( + FROM_HERE, {base::TaskPriority::USER_VISIBLE, base::MayBlock()}, + base::BindOnce(&GetFileDataBlocking, path_, + cached_data_.mime_type.empty()), + base::BindOnce(&FileAnalysisRequest::OnGotFileData, + weakptr_factory_.GetWeakPtr())); + } +} + +void FileAnalysisRequest::OpenFile() { + DCHECK(!data_callback_.is_null()); + + // Opening the file synchronously here is OK since OpenFile should be called + // on a base::MayBlock() thread. + std::pair<BinaryUploadService::Result, Data> file_data = + GetFileDataBlocking(path_, cached_data_.mime_type.empty()); + + // The result of opening the file is passed back to the UI thread since + // |data_callback_| calls functions that must run there. + content::GetUIThreadTaskRunner({})->PostTask( + FROM_HERE, base::BindOnce(&FileAnalysisRequest::OnGotFileData, - weakptr_factory_.GetWeakPtr(), std::move(callback))); + weakptr_factory_.GetWeakPtr(), std::move(file_data))); } bool FileAnalysisRequest::FileSupportedByDlp( @@ -178,7 +202,6 @@ } void FileAnalysisRequest::OnGotFileData( - DataCallback callback, std::pair<BinaryUploadService::Result, Data> result_and_data) { set_digest(result_and_data.second.hash); set_content_type(result_and_data.second.mime_type); @@ -186,7 +209,7 @@ if (result_and_data.first != BinaryUploadService::Result::SUCCESS) { CacheResultAndData(result_and_data.first, std::move(result_and_data.second)); - std::move(callback).Run(cached_result_, cached_data_); + RunCallback(); return; } @@ -201,7 +224,7 @@ CacheResultAndData( BinaryUploadService::Result::DLP_SCAN_UNSUPPORTED_FILE_TYPE, std::move(result_and_data.second)); - std::move(callback).Run(cached_result_, cached_data_); + RunCallback(); return; } else { clear_dlp_scan_request(); @@ -214,7 +237,7 @@ auto analyzer = base::MakeRefCounted<SandboxedZipAnalyzer>( path_, base::BindOnce(&FileAnalysisRequest::OnCheckedForEncryption, - weakptr_factory_.GetWeakPtr(), std::move(callback), + weakptr_factory_.GetWeakPtr(), std::move(result_and_data.second)), LaunchFileUtilService()); analyzer->Start(); @@ -222,19 +245,18 @@ auto analyzer = base::MakeRefCounted<SandboxedRarAnalyzer>( path_, base::BindOnce(&FileAnalysisRequest::OnCheckedForEncryption, - weakptr_factory_.GetWeakPtr(), std::move(callback), + weakptr_factory_.GetWeakPtr(), std::move(result_and_data.second)), LaunchFileUtilService()); analyzer->Start(); } else { CacheResultAndData(BinaryUploadService::Result::SUCCESS, std::move(result_and_data.second)); - std::move(callback).Run(cached_result_, cached_data_); + RunCallback(); } } void FileAnalysisRequest::OnCheckedForEncryption( - DataCallback callback, Data data, const ArchiveAnalyzerResults& analyzer_result) { bool encrypted = @@ -246,7 +268,7 @@ encrypted ? BinaryUploadService::Result::FILE_ENCRYPTED : BinaryUploadService::Result::SUCCESS; CacheResultAndData(result, std::move(data)); - std::move(callback).Run(cached_result_, cached_data_); + RunCallback(); } void FileAnalysisRequest::CacheResultAndData(BinaryUploadService::Result result, @@ -261,4 +283,10 @@ cached_data_ = std::move(data); } +void FileAnalysisRequest::RunCallback() { + if (!data_callback_.is_null()) { + std::move(data_callback_).Run(cached_result_, cached_data_); + } +} + } // namespace safe_browsing
diff --git a/chrome/browser/safe_browsing/cloud_content_scanning/file_analysis_request.h b/chrome/browser/safe_browsing/cloud_content_scanning/file_analysis_request.h index c465ee3..05bc32c 100644 --- a/chrome/browser/safe_browsing/cloud_content_scanning/file_analysis_request.h +++ b/chrome/browser/safe_browsing/cloud_content_scanning/file_analysis_request.h
@@ -22,21 +22,27 @@ base::FilePath path, base::FilePath file_name, std::string mime_type, + bool delay_opening_file, BinaryUploadService::ContentAnalysisCallback callback); FileAnalysisRequest(const FileAnalysisRequest&) = delete; FileAnalysisRequest& operator=(const FileAnalysisRequest&) = delete; ~FileAnalysisRequest() override; - // BinaryUploadService::Request implementation. + // BinaryUploadService::Request implementation. If |delay_opening_file_| is + // false, OnGotFileData is called by posting after GetFileDataBlocking runs + // a base::MayBlock() thread, otherwise the callback will be stored and run + // later when OpenFile is called. void GetRequestData(DataCallback callback) override; + // Opens the file, reads it, and then calls OnGotFileData on the UI thread. + // This should be called on a thread with base::MayBlock(). + void OpenFile(); + private: void OnGotFileData( - DataCallback callback, std::pair<BinaryUploadService::Result, Data> result_and_data); - void OnCheckedForEncryption(DataCallback callback, - Data data, + void OnCheckedForEncryption(Data data, const ArchiveAnalyzerResults& analyzer_result); // Helper functions to access the request proto. @@ -45,6 +51,9 @@ void CacheResultAndData(BinaryUploadService::Result result, Data data); + // Runs |data_callback_|. + void RunCallback(); + bool has_cached_result_; BinaryUploadService::Result cached_result_; Data cached_data_; @@ -57,6 +66,14 @@ // File name excluding the path. base::FilePath file_name_; + DataCallback data_callback_; + + // The file being opened can be delayed so that an external class can have + // more control on parallelism when multiple files are being opened. If + // |delay_opening_file_| is false, a task to open the file is posted in the + // GetRequestData call. + bool delay_opening_file_; + base::WeakPtrFactory<FileAnalysisRequest> weakptr_factory_{this}; };
diff --git a/chrome/browser/safe_browsing/cloud_content_scanning/file_analysis_request_unittest.cc b/chrome/browser/safe_browsing/cloud_content_scanning/file_analysis_request_unittest.cc index 363e62b..ebb8abd 100644 --- a/chrome/browser/safe_browsing/cloud_content_scanning/file_analysis_request_unittest.cc +++ b/chrome/browser/safe_browsing/cloud_content_scanning/file_analysis_request_unittest.cc
@@ -51,11 +51,6 @@ return set.count(mime_type); } -// const std::set<std::string>* TextMimeTypes() { -// static std::set<std::string> set = {"text/plain"}; -// return &set; -//} - } // namespace class FileAnalysisRequestTest : public testing::Test { @@ -64,10 +59,11 @@ std::unique_ptr<FileAnalysisRequest> MakeRequest(bool block_unsupported_types, base::FilePath path, - base::FilePath file_name) { + base::FilePath file_name, + bool delay_opening_file) { return std::make_unique<FileAnalysisRequest>( settings(block_unsupported_types), path, file_name, - /*mime_type*/ "", DoNothingConnector()); + /*mime_type*/ "", delay_opening_file, DoNothingConnector()); } void GetResultsForFileContents(const std::string& file_contents, @@ -78,8 +74,9 @@ base::FilePath file_path = temp_dir.GetPath().AppendASCII("normal.doc"); base::WriteFile(file_path, file_contents.data(), file_contents.size()); - auto request = MakeRequest(/*block_unsupported_types=*/false, file_path, - file_path.BaseName()); + auto request = + MakeRequest(/*block_unsupported_types=*/false, file_path, + file_path.BaseName(), /*delay_opening_file*/ false); bool called = false; base::RunLoop run_loop; @@ -110,8 +107,8 @@ { // Non-existent files should return UNKNOWN and have no information set. base::FilePath path = temp_dir.GetPath().AppendASCII("not_a_real.doc"); - auto request = - MakeRequest(/*block_unsupported_types=*/false, path, path.BaseName()); + auto request = MakeRequest(/*block_unsupported_types=*/false, path, + path.BaseName(), /*delay_opening_file*/ false); bool called = false; base::RunLoop run_loop; @@ -136,8 +133,8 @@ // Directories should not be used as paths passed to GetFileSHA256Blocking, // so they should return UNKNOWN and have no information set. base::FilePath path = temp_dir.GetPath(); - auto request = - MakeRequest(/*block_unsupported_types=*/false, path, path.BaseName()); + auto request = MakeRequest(/*block_unsupported_types=*/false, path, + path.BaseName(), /*delay_opening_file*/ false); bool called = false; base::RunLoop run_loop; @@ -162,8 +159,8 @@ // Empty files should return SUCCESS as they have no content to scan. base::FilePath path = temp_dir.GetPath().AppendASCII("empty.doc"); base::File file(path, base::File::FLAG_CREATE | base::File::FLAG_WRITE); - auto request = - MakeRequest(/*block_unsupported_types=*/false, path, path.BaseName()); + auto request = MakeRequest(/*block_unsupported_types=*/false, path, + path.BaseName(), /*delay_opening_file*/ false); bool called = false; base::RunLoop run_loop; @@ -259,8 +256,9 @@ base::File file(file_path, base::File::FLAG_CREATE | base::File::FLAG_WRITE); file.WriteAtCurrentPos(file_contents.data(), file_contents.size()); - auto request = MakeRequest(/*block_unsupported_types=*/false, file_path, - file_path.BaseName()); + auto request = + MakeRequest(/*block_unsupported_types=*/false, file_path, + file_path.BaseName(), /*delay_opening_file*/ false); base::RunLoop run_loop; request->GetRequestData(base::BindLambdaForTesting( @@ -286,8 +284,9 @@ base::File file(file_path, base::File::FLAG_CREATE | base::File::FLAG_WRITE); file.WriteAtCurrentPos(file_contents.data(), file_contents.size()); - auto request = MakeRequest(/*block_unsupported_types=*/false, file_path, - file_path.BaseName()); + auto request = + MakeRequest(/*block_unsupported_types=*/false, file_path, + file_path.BaseName(), /*delay_opening_file*/ false); base::RunLoop run_loop; request->GetRequestData(base::BindLambdaForTesting( @@ -312,8 +311,9 @@ BinaryUploadService::Result async_result; BinaryUploadService::Request::Data async_data; - auto request = MakeRequest(/*block_unsupported_types=*/false, file_path, - file_path.BaseName()); + auto request = + MakeRequest(/*block_unsupported_types=*/false, file_path, + file_path.BaseName(), /*delay_opening_file*/ false); bool called = false; base::RunLoop run_loop; @@ -349,6 +349,50 @@ EXPECT_EQ(sync_data.mime_type, async_data.mime_type); } +TEST_F(FileAnalysisRequestTest, DelayedFileOpening) { + content::BrowserTaskEnvironment browser_task_environment; + + // base::test::TaskEnvironment task_environment; + std::string file_contents = "Normal file contents"; + base::ScopedTempDir temp_dir; + ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); + base::FilePath file_path = temp_dir.GetPath().AppendASCII("foo.doc"); + + // Create the file. + base::File file(file_path, base::File::FLAG_CREATE | base::File::FLAG_WRITE); + file.WriteAtCurrentPos(file_contents.data(), file_contents.size()); + + auto request = MakeRequest(/*block_unsupported_types=*/false, file_path, + file_path.BaseName(), /*delay_opening_file*/ true); + + base::RunLoop run_loop; + request->GetRequestData(base::BindLambdaForTesting( + [&run_loop, &file_contents]( + BinaryUploadService::Result result, + const BinaryUploadService::Request::Data& data) { + run_loop.Quit(); + + EXPECT_EQ(result, BinaryUploadService::Result::SUCCESS); + EXPECT_EQ(data.size, file_contents.size()); + EXPECT_TRUE(data.contents.empty()); + // printf "Normal file contents" | sha256sum |\ + // tr '[:lower:]' '[:upper:]' + EXPECT_EQ( + data.hash, + "29644C10BD036866FCFD2BDACFF340DB5DE47A90002D6AB0C42DE6A22C26158B"); + EXPECT_TRUE(IsDocMimeType(data.mime_type)) + << data.mime_type << " is not an expected mimetype"; + })); + + base::RunLoop().RunUntilIdle(); + EXPECT_FALSE(run_loop.AnyQuitCalled()); + + request->OpenFile(); + run_loop.Run(); + + EXPECT_TRUE(run_loop.AnyQuitCalled()); +} + // Class used to validate that an archive file is correctly detected and checked // for encryption, even without a .zip/.rar extension. class FileAnalysisRequestZipTest @@ -376,7 +420,7 @@ .AppendASCII(file_name()); auto request = MakeRequest(/*block_unsupported_types=*/false, test_zip, - test_zip.BaseName()); + test_zip.BaseName(), /*delay_opening_file*/ false); bool called = false; base::RunLoop run_loop; @@ -419,8 +463,9 @@ base::FilePath file_path = temp_dir.GetPath().AppendASCII("normal.png"); base::WriteFile(file_path, normal_contents.data(), normal_contents.size()); - auto request = MakeRequest(/*block_unsupported_types=*/true, file_path, - file_path.BaseName()); + auto request = + MakeRequest(/*block_unsupported_types=*/true, file_path, + file_path.BaseName(), /*delay_opening_file*/ false); request->add_tag("dlp"); request->add_tag("malware"); @@ -463,8 +508,9 @@ base::FilePath file_path = temp_dir.GetPath().AppendASCII("normal.png"); base::WriteFile(file_path, normal_contents.data(), normal_contents.size()); - auto request = MakeRequest(/*block_unsupported_types=*/false, file_path, - file_path.BaseName()); + auto request = + MakeRequest(/*block_unsupported_types=*/false, file_path, + file_path.BaseName(), /*delay_opening_file*/ false); request->add_tag("dlp"); request->add_tag("malware");
diff --git a/chrome/browser/safe_browsing/download_protection/deep_scanning_request.cc b/chrome/browser/safe_browsing/download_protection/deep_scanning_request.cc index 5311765b..5e6fc6c 100644 --- a/chrome/browser/safe_browsing/download_protection/deep_scanning_request.cc +++ b/chrome/browser/safe_browsing/download_protection/deep_scanning_request.cc
@@ -216,6 +216,7 @@ auto request = std::make_unique<FileAnalysisRequest>( analysis_settings_, item_->GetFullPath(), item_->GetTargetFilePath().BaseName(), item_->GetMimeType(), + /* delay_opening_file */ false, base::BindOnce(&DeepScanningRequest::OnScanComplete, weak_ptr_factory_.GetWeakPtr())); request->set_filename(item_->GetTargetFilePath().BaseName().AsUTF8Unsafe());
diff --git a/chrome/browser/safe_browsing/network_context_service.cc b/chrome/browser/safe_browsing/network_context_service.cc new file mode 100644 index 0000000..3dcea28 --- /dev/null +++ b/chrome/browser/safe_browsing/network_context_service.cc
@@ -0,0 +1,45 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/safe_browsing/network_context_service.h" + +#include "chrome/browser/net/system_network_context_manager.h" +#include "chrome/browser/profiles/profile.h" + +namespace safe_browsing { + +NetworkContextService::NetworkContextService(Profile* profile) { + network_context_ = std::make_unique<SafeBrowsingNetworkContext>( + profile->GetPath(), + base::BindRepeating(&NetworkContextService::CreateNetworkContextParams, + // This is safe because `this` owns + // `network_context_`. + base::Unretained(this))); + proxy_config_monitor_ = std::make_unique<ProxyConfigMonitor>(profile); +} + +NetworkContextService::~NetworkContextService() = default; + +void NetworkContextService::Shutdown() { + network_context_->ServiceShuttingDown(); +} + +network::mojom::NetworkContext* NetworkContextService::GetNetworkContext() { + return network_context_->GetNetworkContext(); +} + +scoped_refptr<network::SharedURLLoaderFactory> +NetworkContextService::GetURLLoaderFactory() { + return network_context_->GetURLLoaderFactory(); +} + +network::mojom::NetworkContextParamsPtr +NetworkContextService::CreateNetworkContextParams() { + auto params = SystemNetworkContextManager::GetInstance() + ->CreateDefaultNetworkContextParams(); + proxy_config_monitor_->AddToNetworkContextParams(params.get()); + return params; +} + +} // namespace safe_browsing
diff --git a/chrome/browser/safe_browsing/network_context_service.h b/chrome/browser/safe_browsing/network_context_service.h new file mode 100644 index 0000000..b960f9b --- /dev/null +++ b/chrome/browser/safe_browsing/network_context_service.h
@@ -0,0 +1,46 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_SAFE_BROWSING_NETWORK_CONTEXT_SERVICE_H_ +#define CHROME_BROWSER_SAFE_BROWSING_NETWORK_CONTEXT_SERVICE_H_ + +#include <memory> + +#include "chrome/browser/net/proxy_config_monitor.h" +#include "components/keyed_service/core/keyed_service.h" +#include "components/safe_browsing/content/browser/safe_browsing_network_context.h" +#include "services/network/public/mojom/network_context.mojom.h" + +class Profile; + +namespace safe_browsing { + +// This class manages a network context for Safe Browsing communications. The +// primary reason for the use of a separate network context is to ensure that +// cookies are not shared between Safe Browsing functionality and regular +// browsing. +class NetworkContextService : public KeyedService { + public: + explicit NetworkContextService(Profile* profile); + ~NetworkContextService() override; + + // KeyedService implementation: + void Shutdown() override; + + // Get the NetworkContext associated to this profile + network::mojom::NetworkContext* GetNetworkContext(); + + // Get the URLLoaderFactory associated to this profile + scoped_refptr<network::SharedURLLoaderFactory> GetURLLoaderFactory(); + + private: + network::mojom::NetworkContextParamsPtr CreateNetworkContextParams(); + + std::unique_ptr<SafeBrowsingNetworkContext> network_context_; + std::unique_ptr<ProxyConfigMonitor> proxy_config_monitor_; +}; + +} // namespace safe_browsing + +#endif // CHROME_BROWSER_SAFE_BROWSING_NETWORK_CONTEXT_SERVICE_H_
diff --git a/chrome/browser/safe_browsing/network_context_service_factory.cc b/chrome/browser/safe_browsing/network_context_service_factory.cc new file mode 100644 index 0000000..a9c1615 --- /dev/null +++ b/chrome/browser/safe_browsing/network_context_service_factory.cc
@@ -0,0 +1,44 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/safe_browsing/network_context_service_factory.h" + +#include "chrome/browser/profiles/incognito_helpers.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/safe_browsing/network_context_service.h" +#include "components/keyed_service/content/browser_context_dependency_manager.h" + +namespace safe_browsing { + +// static +NetworkContextServiceFactory* NetworkContextServiceFactory::GetInstance() { + return base::Singleton<NetworkContextServiceFactory>::get(); +} + +// static +NetworkContextService* NetworkContextServiceFactory::GetForBrowserContext( + content::BrowserContext* context) { + return static_cast<NetworkContextService*>( + GetInstance()->GetServiceForBrowserContext(context, /*create=*/true)); +} + +NetworkContextServiceFactory::NetworkContextServiceFactory() + : BrowserContextKeyedServiceFactory( + "SafeBrowsingNetworkContextService", + BrowserContextDependencyManager::GetInstance()) {} + +NetworkContextServiceFactory::~NetworkContextServiceFactory() = default; + +KeyedService* NetworkContextServiceFactory::BuildServiceInstanceFor( + content::BrowserContext* context) const { + Profile* profile = Profile::FromBrowserContext(context); + return new NetworkContextService(profile); +} + +content::BrowserContext* NetworkContextServiceFactory::GetBrowserContextToUse( + content::BrowserContext* context) const { + return chrome::GetBrowserContextRedirectedInIncognito(context); +} + +} // namespace safe_browsing
diff --git a/chrome/browser/safe_browsing/network_context_service_factory.h b/chrome/browser/safe_browsing/network_context_service_factory.h new file mode 100644 index 0000000..57d563a --- /dev/null +++ b/chrome/browser/safe_browsing/network_context_service_factory.h
@@ -0,0 +1,44 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_SAFE_BROWSING_NETWORK_CONTEXT_SERVICE_FACTORY_H_ +#define CHROME_BROWSER_SAFE_BROWSING_NETWORK_CONTEXT_SERVICE_FACTORY_H_ + +#include "base/memory/singleton.h" +#include "components/keyed_service/content/browser_context_keyed_service_factory.h" + +namespace content { +class BrowserContext; +} + +namespace safe_browsing { + +class NetworkContextService; + +// Factory for creating the KeyedService NetworkContextService. Incognito +// profiles will return the same NetworkContextService as the original profile. +// Features using this network context are expected to behave correctly while +// incognito. +class NetworkContextServiceFactory : public BrowserContextKeyedServiceFactory { + public: + static NetworkContextServiceFactory* GetInstance(); + static NetworkContextService* GetForBrowserContext( + content::BrowserContext* context); + + private: + friend struct base::DefaultSingletonTraits<NetworkContextServiceFactory>; + + NetworkContextServiceFactory(); + ~NetworkContextServiceFactory() override; + + // BrowserContextKeyedServiceFactory overrides: + KeyedService* BuildServiceInstanceFor( + content::BrowserContext* context) const override; + content::BrowserContext* GetBrowserContextToUse( + content::BrowserContext* context) const override; +}; + +} // namespace safe_browsing + +#endif // CHROME_BROWSER_SAFE_BROWSING_NETWORK_CONTEXT_SERVICE_FACTORY_H_
diff --git a/chrome/browser/safe_browsing/safe_browsing_service.cc b/chrome/browser/safe_browsing/safe_browsing_service.cc index 77aaccf..6f33df4 100644 --- a/chrome/browser/safe_browsing/safe_browsing_service.cc +++ b/chrome/browser/safe_browsing/safe_browsing_service.cc
@@ -29,6 +29,8 @@ #include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/safe_browsing/chrome_password_protection_service.h" #include "chrome/browser/safe_browsing/chrome_password_protection_service_factory.h" +#include "chrome/browser/safe_browsing/network_context_service.h" +#include "chrome/browser/safe_browsing/network_context_service_factory.h" #include "chrome/browser/safe_browsing/safe_browsing_metrics_collector_factory.h" #include "chrome/browser/safe_browsing/safe_browsing_navigation_observer_manager_factory.h" #include "chrome/browser/safe_browsing/services_delegate.h" @@ -183,10 +185,12 @@ if (!base::FeatureList::IsEnabled(kSafeBrowsingSeparateNetworkContexts)) return GetNetworkContext(); - return services_delegate_ - ->GetSafeBrowsingNetworkContext( - Profile::FromBrowserContext(browser_context)) - ->GetNetworkContext(); + NetworkContextService* service = + NetworkContextServiceFactory::GetForBrowserContext(browser_context); + if (!service) + return nullptr; + + return service->GetNetworkContext(); } scoped_refptr<network::SharedURLLoaderFactory> @@ -195,14 +199,12 @@ if (!base::FeatureList::IsEnabled(kSafeBrowsingSeparateNetworkContexts)) return GetURLLoaderFactory(); - safe_browsing::SafeBrowsingNetworkContext* network_context = - services_delegate_->GetSafeBrowsingNetworkContext(profile); - - // |network_context| may be null in tests - if (!network_context) + NetworkContextService* service = + NetworkContextServiceFactory::GetForBrowserContext(profile); + if (!service) return nullptr; - return network_context->GetURLLoaderFactory(); + return service->GetURLLoaderFactory(); } void SafeBrowsingService::FlushNetworkInterfaceForTesting() { @@ -404,7 +406,6 @@ void SafeBrowsingService::OnProfileWillBeDestroyed(Profile* profile) { observed_profiles_.RemoveObservation(profile); services_delegate_->RemoveTelemetryService(profile); - services_delegate_->RemoveSafeBrowsingNetworkContext(profile); PrefService* pref_service = profile->GetPrefs(); DCHECK(pref_service); @@ -412,7 +413,6 @@ } void SafeBrowsingService::CreateServicesForProfile(Profile* profile) { - services_delegate_->CreateSafeBrowsingNetworkContext(profile); services_delegate_->CreateTelemetryService(profile); observed_profiles_.AddObservation(profile); }
diff --git a/chrome/browser/safe_browsing/services_delegate.cc b/chrome/browser/safe_browsing/services_delegate.cc index fc20c32..8161ac3 100644 --- a/chrome/browser/safe_browsing/services_delegate.cc +++ b/chrome/browser/safe_browsing/services_delegate.cc
@@ -42,65 +42,6 @@ } void ServicesDelegate::ShutdownServices() { - // Delete the NetworkContexts and associated ProxyConfigMonitors - network_context_map_.clear(); - proxy_config_monitor_map_.clear(); -} - -void ServicesDelegate::CreateSafeBrowsingNetworkContext(Profile* profile) { - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - DCHECK(profile); - - if (!base::FeatureList::IsEnabled(kSafeBrowsingSeparateNetworkContexts)) - return; - - auto it = network_context_map_.find(profile); - DCHECK(it == network_context_map_.end()); - network_context_map_[profile] = std::make_unique<SafeBrowsingNetworkContext>( - profile->GetPath(), - base::BindRepeating(&ServicesDelegate::CreateNetworkContextParams, - base::Unretained(this), profile)); - proxy_config_monitor_map_[profile] = - std::make_unique<ProxyConfigMonitor>(profile); -} - -void ServicesDelegate::RemoveSafeBrowsingNetworkContext(Profile* profile) { - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - DCHECK(profile); - - if (!base::FeatureList::IsEnabled(kSafeBrowsingSeparateNetworkContexts)) - return; - - auto it = network_context_map_.find(profile); - if (it != network_context_map_.end()) { - it->second->ServiceShuttingDown(); - network_context_map_.erase(it); - } - - auto proxy_it = proxy_config_monitor_map_.find(profile); - if (proxy_it != proxy_config_monitor_map_.end()) - proxy_config_monitor_map_.erase(proxy_it); -} - -SafeBrowsingNetworkContext* ServicesDelegate::GetSafeBrowsingNetworkContext( - Profile* profile) const { - DCHECK(profile); - DCHECK(base::FeatureList::IsEnabled(kSafeBrowsingSeparateNetworkContexts)); - // In tests, we may not have been notified of Profile creation. - auto it = network_context_map_.find(profile); - if (it == network_context_map_.end()) - return nullptr; - return it->second.get(); -} - -network::mojom::NetworkContextParamsPtr -ServicesDelegate::CreateNetworkContextParams(Profile* profile) { - auto params = SystemNetworkContextManager::GetInstance() - ->CreateDefaultNetworkContextParams(); - auto it = proxy_config_monitor_map_.find(profile); - DCHECK(it != proxy_config_monitor_map_.end()); - it->second->AddToNetworkContextParams(params.get()); - return params; } } // namespace safe_browsing
diff --git a/chrome/browser/safe_browsing/services_delegate.h b/chrome/browser/safe_browsing/services_delegate.h index 69292fd..b52a802 100644 --- a/chrome/browser/safe_browsing/services_delegate.h +++ b/chrome/browser/safe_browsing/services_delegate.h
@@ -10,10 +10,8 @@ #include "base/memory/ref_counted.h" #include "build/build_config.h" #include "chrome/browser/safe_browsing/incident_reporting/delayed_analysis_callback.h" -#include "services/network/public/mojom/network_context.mojom.h" class Profile; -class ProxyConfigMonitor; namespace content { class DownloadManager; @@ -38,7 +36,6 @@ class SafeBrowsingService; class SafeBrowsingDatabaseManager; struct V4ProtocolConfig; -class SafeBrowsingNetworkContext; // Abstraction to help organize code for mobile vs full safe browsing modes. // This helper class should be owned by a SafeBrowsingService, and it handles @@ -121,29 +118,12 @@ virtual void CreateTelemetryService(Profile* profile) {} virtual void RemoveTelemetryService(Profile* profile) {} - virtual void CreateSafeBrowsingNetworkContext(Profile* profile); - virtual void RemoveSafeBrowsingNetworkContext(Profile* profile); - virtual SafeBrowsingNetworkContext* GetSafeBrowsingNetworkContext( - Profile* profile) const; - protected: - network::mojom::NetworkContextParamsPtr CreateNetworkContextParams( - Profile* profile); - // Unowned pointer SafeBrowsingService* const safe_browsing_service_; // Unowned pointer ServicesCreator* const services_creator_; - - std::unique_ptr<ProxyConfigMonitor> proxy_config_monitor_; - - // Tracks existing Profiles, and their corresponding - // SafeBrowsingNetworkContexts. Accessed on UI thread. - base::flat_map<Profile*, std::unique_ptr<SafeBrowsingNetworkContext>> - network_context_map_; - base::flat_map<Profile*, std::unique_ptr<ProxyConfigMonitor>> - proxy_config_monitor_map_; }; } // namespace safe_browsing
diff --git a/chrome/browser/safe_browsing/url_lookup_service_factory.cc b/chrome/browser/safe_browsing/url_lookup_service_factory.cc index d4279355..30a1de2b 100644 --- a/chrome/browser/safe_browsing/url_lookup_service_factory.cc +++ b/chrome/browser/safe_browsing/url_lookup_service_factory.cc
@@ -10,6 +10,7 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/safe_browsing/advanced_protection_status_manager.h" #include "chrome/browser/safe_browsing/advanced_protection_status_manager_factory.h" +#include "chrome/browser/safe_browsing/network_context_service_factory.h" #include "chrome/browser/safe_browsing/safe_browsing_navigation_observer_manager_factory.h" #include "chrome/browser/safe_browsing/safe_browsing_service.h" #include "chrome/browser/safe_browsing/user_population.h" @@ -53,6 +54,7 @@ #if BUILDFLAG(FULL_SAFE_BROWSING) DependsOn(AdvancedProtectionStatusManagerFactory::GetInstance()); #endif + DependsOn(NetworkContextServiceFactory::GetInstance()); } KeyedService* RealTimeUrlLookupServiceFactory::BuildServiceInstanceFor(
diff --git a/chrome/browser/settings/BUILD.gn b/chrome/browser/settings/BUILD.gn index bc94f4d..e4f6410 100644 --- a/chrome/browser/settings/BUILD.gn +++ b/chrome/browser/settings/BUILD.gn
@@ -43,6 +43,7 @@ "//third_party/androidx:androidx_test_runner_java", "//third_party/hamcrest:hamcrest_java", "//third_party/junit", + "//ui/android:ui_java_test_support", ] }
diff --git a/chrome/browser/settings/android/java/src/org/chromium/chrome/browser/settings/ChromeImageViewPreferenceTest.java b/chrome/browser/settings/android/java/src/org/chromium/chrome/browser/settings/ChromeImageViewPreferenceTest.java index dc3438b..3149772 100644 --- a/chrome/browser/settings/android/java/src/org/chromium/chrome/browser/settings/ChromeImageViewPreferenceTest.java +++ b/chrome/browser/settings/android/java/src/org/chromium/chrome/browser/settings/ChromeImageViewPreferenceTest.java
@@ -28,9 +28,9 @@ import org.junit.runner.RunWith; import org.chromium.base.test.BaseActivityTestRule; +import org.chromium.chrome.R; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.components.browser_ui.settings.ChromeImageViewPreference; -import org.chromium.components.browser_ui.settings.R; import org.chromium.components.browser_ui.settings.SettingsLauncher; /**
diff --git a/chrome/browser/share/BUILD.gn b/chrome/browser/share/BUILD.gn index 027a2bf..9b820e2 100644 --- a/chrome/browser/share/BUILD.gn +++ b/chrome/browser/share/BUILD.gn
@@ -9,6 +9,8 @@ source_set("share") { sources = [ "bitmap_download_request.cc", + "default_ranking.cc", + "default_ranking.h", "editor_screenshot_task.cc", "link_to_text_bridge.cc", "qr_code_generation_request.cc", @@ -18,6 +20,11 @@ "share_ranking.cc", "share_ranking.h", ] + + if (is_android) { + sources += [ "default_ranking_android.cc" ] + } + deps = [ ":jni_headers", "//base",
diff --git a/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/qrcode/QrCodeDialog.java b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/qrcode/QrCodeDialog.java index 93a5fd8c..38b1540b 100644 --- a/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/qrcode/QrCodeDialog.java +++ b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/qrcode/QrCodeDialog.java
@@ -85,6 +85,9 @@ */ public void setAndroidPermissionDelegate(AndroidPermissionDelegate windowAndroid) { mWindowAndroid = windowAndroid; + if (mTabLayoutPageListener != null) { + mTabLayoutPageListener.updatePermissions(windowAndroid); + } } private View getDialogView() {
diff --git a/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/qrcode/QrCodeDialogTab.java b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/qrcode/QrCodeDialogTab.java index 8a99e03..4054c58a 100644 --- a/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/qrcode/QrCodeDialogTab.java +++ b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/qrcode/QrCodeDialogTab.java
@@ -6,6 +6,8 @@ import android.view.View; +import org.chromium.ui.base.AndroidPermissionDelegate; + /** * Common interface for all the tab components in QrCodeDialog. */ @@ -27,4 +29,9 @@ * dialog. */ public void onDestroy(); + + /** + * Called when the permissions delegate is reset. + */ + public void updatePermissions(AndroidPermissionDelegate windowAndroid); } \ No newline at end of file
diff --git a/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/qrcode/TabLayoutPageListener.java b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/qrcode/TabLayoutPageListener.java index 5a9be15..84fcf0e 100644 --- a/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/qrcode/TabLayoutPageListener.java +++ b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/qrcode/TabLayoutPageListener.java
@@ -6,6 +6,8 @@ import com.google.android.material.tabs.TabLayout; +import org.chromium.ui.base.AndroidPermissionDelegate; + import java.util.ArrayList; /** @@ -56,6 +58,17 @@ } /** + * Called when the fragment's underlying AndroidPermissionDelegate is updated. + * Propagates the given AndroidPermissionDelegate to all of the tabs. + * @param windowAndroid The updated AndroidPermissionDelegate. + */ + public void updatePermissions(AndroidPermissionDelegate windowAndroid) { + for (QrCodeDialogTab tab : mTabs) { + tab.updatePermissions(windowAndroid); + } + } + + /** * Pause all the tabs. Note that we don't update the visible tab since * the dialog will continue to display that when the resumes the dialog. */
diff --git a/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/qrcode/scan_tab/QrCodeScanCoordinator.java b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/qrcode/scan_tab/QrCodeScanCoordinator.java index cb25058..acbde8e45 100644 --- a/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/qrcode/scan_tab/QrCodeScanCoordinator.java +++ b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/qrcode/scan_tab/QrCodeScanCoordinator.java
@@ -9,6 +9,7 @@ import org.chromium.base.metrics.RecordUserAction; import org.chromium.chrome.browser.share.qrcode.QrCodeDialogTab; +import org.chromium.ui.base.AndroidPermissionDelegate; import org.chromium.ui.modelutil.PropertyModel; import org.chromium.ui.modelutil.PropertyModelChangeProcessor; @@ -54,4 +55,6 @@ public void onDestroy() { mScanView.stopCamera(); } + @Override + public void updatePermissions(AndroidPermissionDelegate windowAndroid) {} }
diff --git a/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/qrcode/share_tab/QrCodeShareCoordinator.java b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/qrcode/share_tab/QrCodeShareCoordinator.java index a59d476..e97a2d69 100644 --- a/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/qrcode/share_tab/QrCodeShareCoordinator.java +++ b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/qrcode/share_tab/QrCodeShareCoordinator.java
@@ -49,4 +49,9 @@ @Override public void onDestroy() {} + + @Override + public void updatePermissions(AndroidPermissionDelegate windowAndroid) { + mMediator.updatePermissions(windowAndroid); + } }
diff --git a/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/qrcode/share_tab/QrCodeShareMediator.java b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/qrcode/share_tab/QrCodeShareMediator.java index cc7c792..6640260 100644 --- a/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/qrcode/share_tab/QrCodeShareMediator.java +++ b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/qrcode/share_tab/QrCodeShareMediator.java
@@ -34,7 +34,7 @@ private final Context mContext; private final PropertyModel mPropertyModel; - private final AndroidPermissionDelegate mPermissionDelegate; + private AndroidPermissionDelegate mPermissionDelegate; // The number of times the user has attempted to download the QR code in this dialog. private int mNumDownloads; @@ -140,6 +140,10 @@ QrCodeShareViewProperties.HAS_STORAGE_PERMISSION, hasStoragePermission()); } + public void updatePermissions(AndroidPermissionDelegate windowAndroid) { + mPermissionDelegate = windowAndroid; + updatePermissionSettings(); + } /** * Sets whether QrCode UI is on foreground. *
diff --git a/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/long_screenshots/LongScreenshotsMediatorTest.java b/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/long_screenshots/LongScreenshotsMediatorTest.java index f584610..8c63a2f 100644 --- a/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/long_screenshots/LongScreenshotsMediatorTest.java +++ b/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/long_screenshots/LongScreenshotsMediatorTest.java
@@ -19,14 +19,15 @@ import org.mockito.Mock; import org.mockito.MockitoAnnotations; -import org.chromium.base.test.BaseActivityTestRule; import org.chromium.base.test.util.CommandLineFlags; +import org.chromium.chrome.R; import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.flags.ChromeSwitches; import org.chromium.chrome.browser.share.long_screenshots.bitmap_generation.EntryManager; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.chrome.test.util.browser.Features; import org.chromium.ui.test.util.DummyUiActivity; +import org.chromium.ui.test.util.ThemedDummyUiActivityTestRule; /** Tests for the LongScreenshotsMediator. */ @RunWith(ChromeJUnit4ClassRunner.class) @@ -38,8 +39,8 @@ private LongScreenshotsMediator mMediator; @Rule - public BaseActivityTestRule<DummyUiActivity> mActivityTestRule = - new BaseActivityTestRule<>(DummyUiActivity.class); + public ThemedDummyUiActivityTestRule<DummyUiActivity> mActivityTestRule = + new ThemedDummyUiActivityTestRule<>(DummyUiActivity.class, R.style.ColorOverlay); @Mock private View mView;
diff --git a/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/screenshot/ScreenshotShareSheetSaveDelegateTest.java b/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/screenshot/ScreenshotShareSheetSaveDelegateTest.java index 27c8736..22deae3 100644 --- a/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/screenshot/ScreenshotShareSheetSaveDelegateTest.java +++ b/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/screenshot/ScreenshotShareSheetSaveDelegateTest.java
@@ -22,8 +22,8 @@ import org.mockito.Mockito; import org.mockito.MockitoAnnotations; -import org.chromium.base.test.BaseActivityTestRule; import org.chromium.base.test.UiThreadTest; +import org.chromium.chrome.R; import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.chrome.test.util.browser.Features; @@ -31,6 +31,7 @@ import org.chromium.ui.base.PermissionCallback; import org.chromium.ui.modelutil.PropertyModel; import org.chromium.ui.test.util.DummyUiActivity; +import org.chromium.ui.test.util.ThemedDummyUiActivityTestRule; /** * Tests for the {@link ScreenshotShareSheetView}. @@ -41,8 +42,8 @@ private ScreenshotShareSheetSaveDelegate mScreenshotShareSheetSaveDelegate; @Rule - public BaseActivityTestRule<DummyUiActivity> mActivityTestRule = - new BaseActivityTestRule<>(DummyUiActivity.class); + public ThemedDummyUiActivityTestRule<DummyUiActivity> mActivityTestRule = + new ThemedDummyUiActivityTestRule<>(DummyUiActivity.class, R.style.ColorOverlay); @Mock private PropertyModel mModel;
diff --git a/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/screenshot/ScreenshotShareSheetViewTest.java b/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/screenshot/ScreenshotShareSheetViewTest.java index 54f095548..eafc8bc 100644 --- a/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/screenshot/ScreenshotShareSheetViewTest.java +++ b/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/screenshot/ScreenshotShareSheetViewTest.java
@@ -20,13 +20,13 @@ import org.chromium.base.test.UiThreadTest; import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; +import org.chromium.chrome.test.DummyUiChromeActivityTestCase; import org.chromium.chrome.test.R; import org.chromium.chrome.test.util.browser.Features; import org.chromium.components.browser_ui.widget.selectable_list.SelectionDelegate; import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.ui.modelutil.PropertyModel; import org.chromium.ui.modelutil.PropertyModelChangeProcessor; -import org.chromium.ui.test.util.DummyUiActivityTestCase; import java.util.concurrent.atomic.AtomicBoolean; @@ -35,7 +35,7 @@ */ @RunWith(ChromeJUnit4ClassRunner.class) @Features.EnableFeatures(ChromeFeatureList.CHROME_SHARE_SCREENSHOT) -public class ScreenshotShareSheetViewTest extends DummyUiActivityTestCase { +public class ScreenshotShareSheetViewTest extends DummyUiChromeActivityTestCase { private ScreenshotShareSheetView mScreenshotView; private PropertyModel mScreenshotModel; private PropertyModelChangeProcessor mScreenshotMCP;
diff --git a/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/share_sheet/ChromeProvidedSharingOptionsProviderTest.java b/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/share_sheet/ChromeProvidedSharingOptionsProviderTest.java index 3032fe0..f5659e86 100644 --- a/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/share_sheet/ChromeProvidedSharingOptionsProviderTest.java +++ b/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/share_sheet/ChromeProvidedSharingOptionsProviderTest.java
@@ -32,7 +32,6 @@ import org.chromium.base.metrics.RecordHistogram; import org.chromium.base.supplier.Supplier; -import org.chromium.base.test.BaseActivityTestRule; import org.chromium.base.test.util.ApplicationTestUtils; import org.chromium.base.test.util.JniMocker; import org.chromium.base.test.util.UserActionTester; @@ -55,6 +54,7 @@ import org.chromium.content_public.browser.WebContents; import org.chromium.ui.modelutil.PropertyModel; import org.chromium.ui.test.util.DummyUiActivity; +import org.chromium.ui.test.util.ThemedDummyUiActivityTestRule; import org.chromium.url.GURL; import java.util.List; @@ -68,8 +68,8 @@ public final ChromeBrowserTestRule mBrowserTestRule = new ChromeBrowserTestRule(); @Rule - public BaseActivityTestRule<DummyUiActivity> mActivityTestRule = - new BaseActivityTestRule<>(DummyUiActivity.class); + public ThemedDummyUiActivityTestRule<DummyUiActivity> mActivityTestRule = + new ThemedDummyUiActivityTestRule<>(DummyUiActivity.class, R.style.ColorOverlay); @Rule public TestRule mFeatureProcessor = new Features.JUnitProcessor();
diff --git a/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetBottomSheetContentTest.java b/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetBottomSheetContentTest.java index ebedfd93..746fd78 100644 --- a/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetBottomSheetContentTest.java +++ b/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetBottomSheetContentTest.java
@@ -25,7 +25,6 @@ import org.junit.Test; import org.junit.runner.RunWith; -import org.chromium.base.test.BaseActivityTestRule; import org.chromium.chrome.R; import org.chromium.chrome.browser.share.share_sheet.ShareSheetPropertyModelBuilder.ContentType; import org.chromium.chrome.test.ChromeBrowserTestRule; @@ -35,6 +34,7 @@ import org.chromium.components.favicon.LargeIconBridge; import org.chromium.components.url_formatter.UrlFormatter; import org.chromium.ui.test.util.DummyUiActivity; +import org.chromium.ui.test.util.ThemedDummyUiActivityTestRule; import org.chromium.url.GURL; import java.util.ArrayList; @@ -48,8 +48,8 @@ public final ChromeBrowserTestRule mBrowserTestRule = new ChromeBrowserTestRule(); @Rule - public BaseActivityTestRule<DummyUiActivity> mActivityTestRule = - new BaseActivityTestRule<>(DummyUiActivity.class); + public ThemedDummyUiActivityTestRule<DummyUiActivity> mActivityTestRule = + new ThemedDummyUiActivityTestRule<>(DummyUiActivity.class, R.style.ColorOverlay); private static final Bitmap.Config sConfig = Bitmap.Config.ALPHA_8; private static final Uri sImageUri = Uri.parse("content://testImage.png");
diff --git a/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetCoordinatorTest.java b/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetCoordinatorTest.java index b008c49..386742af 100644 --- a/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetCoordinatorTest.java +++ b/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetCoordinatorTest.java
@@ -45,7 +45,6 @@ import org.chromium.ui.base.WindowAndroid; import org.chromium.ui.modelutil.PropertyModel; import org.chromium.url.JUnitTestGURLs; - import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.Arrays;
diff --git a/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetPropertyModelBuilderTest.java b/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetPropertyModelBuilderTest.java index 6ba5b6b..656ecfca 100644 --- a/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetPropertyModelBuilderTest.java +++ b/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetPropertyModelBuilderTest.java
@@ -30,8 +30,8 @@ import org.mockito.Mock; import org.mockito.MockitoAnnotations; -import org.chromium.base.test.BaseActivityTestRule; import org.chromium.base.test.util.CommandLineFlags; +import org.chromium.chrome.R; import org.chromium.chrome.browser.flags.ChromeSwitches; import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.share.ChromeShareExtras; @@ -43,6 +43,7 @@ import org.chromium.components.browser_ui.share.ShareParams; import org.chromium.ui.modelutil.PropertyModel; import org.chromium.ui.test.util.DummyUiActivity; +import org.chromium.ui.test.util.ThemedDummyUiActivityTestRule; import java.util.ArrayList; import java.util.List; @@ -57,8 +58,8 @@ public final ChromeBrowserTestRule mBrowserTestRule = new ChromeBrowserTestRule(); @Rule - public BaseActivityTestRule<DummyUiActivity> mActivityTestRule = - new BaseActivityTestRule<>(DummyUiActivity.class); + public ThemedDummyUiActivityTestRule<DummyUiActivity> mActivityTestRule = + new ThemedDummyUiActivityTestRule<>(DummyUiActivity.class, R.style.ColorOverlay); @Rule public TestRule mFeatureProcessor = new Features.JUnitProcessor();
diff --git a/chrome/browser/share/default_ranking.cc b/chrome/browser/share/default_ranking.cc new file mode 100644 index 0000000..3da5479 --- /dev/null +++ b/chrome/browser/share/default_ranking.cc
@@ -0,0 +1,18 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/share/default_ranking.h" +#include "build/build_config.h" + +namespace sharing { + +#if !defined(OS_ANDROID) +std::vector<std::string> DefaultRankingForLocaleAndType( + const std::string& locale, + const std::string& type) { + return {}; +} +#endif // OS_ANDROID + +} // namespace sharing
diff --git a/chrome/browser/share/default_ranking.h b/chrome/browser/share/default_ranking.h new file mode 100644 index 0000000..8e1d216bf --- /dev/null +++ b/chrome/browser/share/default_ranking.h
@@ -0,0 +1,19 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_SHARE_DEFAULT_RANKING_H_ +#define CHROME_BROWSER_SHARE_DEFAULT_RANKING_H_ + +#include <string> +#include <vector> + +namespace sharing { + +std::vector<std::string> DefaultRankingForLocaleAndType( + const std::string& locale, + const std::string& type); + +} // namespace sharing + +#endif // CHROME_BROWSER_SHARE_DEFAULT_RANKING_H_
diff --git a/chrome/browser/share/default_ranking_android.cc b/chrome/browser/share/default_ranking_android.cc new file mode 100644 index 0000000..890cb83 --- /dev/null +++ b/chrome/browser/share/default_ranking_android.cc
@@ -0,0 +1,216 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/share/default_ranking.h" + +#include "base/strings/string_util.h" + +namespace sharing { + +namespace { + +// All four of these rankings are sourced from a combination of public app usage +// data sets and Chrome-side metrics about common share targets; the exact +// details of that process are described in go/sh-plus. +// +// These are lists of activities rather than packages, so that multiple share +// targets from the same app can appear in different places in the ranking. This +// is a bit brittle; see https://crbug.com/1222156#c4 for why. Regrettably, the +// mapping from human-readable (app name, action) pairs to activities was done +// by hand; see go/sh-3p-activities for that. +// +// These lists are used to rank which share targets are shown for users with no +// share history. In all cases, only apps actually present on the device are +// shown; these lists control the relative ordering when many of these apps are +// all present at once. Once the user has any share history, ShareRanking will +// use that history rather than these default lists. +// +// You'll notice that this data is split up by "EnUs" and "World"; this is +// because the popularity of apps around the world in general is pretty similar, +// *except* for en-US users, who have pretty major differences. If other locales +// diverge more from the main world list we will need to add more cases here for +// them. + +std::vector<std::string> DefaultEnUsImageRanking() { + return { + "com.whatsapp.ContactPicker", + "com.google.android.apps.messaging.ui.conversationlist." + "ShareIntentActivity", + "com.google.android.gm.ComposeActivityGmailExternal", + "com.facebook.messenger.intents.ShareIntentHandler", + "com.facebook.composer.shareintent." + "ImplicitShareIntentHandlerDefaultAlias", + // TODO(https://crbug.com/1228281): Files + "com.google.android.apps.photos.uploadtoalbum.UploadContentActivity", + "com.snap.mushroom.MainActivity", "org.telegram.ui.LaunchActivity", + "com.instagram.share.handleractivity.StoryShareHandlerActivity", + "com.instagram.share.handleractivity.ShareHandlerActivity", + "com.discord.app.AppActivity$AppAction", + "com.instagram.direct.share.handler." + "DirectExternalMediaShareActivityPhoto", + "com.google.android.apps.hangouts.phone.ShareIntentActivity", + "com.google.android.keep.activities.ShareReceiverActivity", + "com.google.android.apps.docs.common.shareitem.UploadMenuActivity", + "com.verizon.mms.ui.LaunchConversationActivity", + "org.thoughtcrime.securesms.sharing.ShareActivity", + "com.twitter.composer.ComposerActivity", + "com.pinterest.activity.create.PinItActivity", + "com.twitter.app.dm.DMActivity", + "com.google.android.apps.dynamite.activity.main.MainActivity", + "com.microsoft.office.outlook.compose.ComposeLauncherActivity", + "com.yahoo.mail.flux.ui.MailComposeActivity", + "com.linkedin.android.publishing.sharing.SharingDeepLinkActivity", + // TODO(https://crbug.com/1228281): Samsung email + "com.reddit.sharing.ShareActivity", + "com.linecorp.line.share.common.view.FullPickerLaunchActivity", + "com.tencent.mm.ui.tools.ShareImgUI", + // TODO(https://crbug.com/1228281): Groupme + }; +} + +std::vector<std::string> DefaultEnUsTextRanking() { + return { + "com.whatsapp.ContactPicker", + "com.google.android.apps.messaging.ui.conversationlist." + "ShareIntentActivity", + "com.google.android.gm.ComposeActivityGmailExternal", + "com.facebook.messenger.intents.ShareIntentHandler", + "com.facebook.composer.shareintent." + "ImplicitShareIntentHandlerDefaultAlias", + "com.snap.mushroom.MainActivity", "org.telegram.ui.LaunchActivity", + "com.discord.app.AppActivity$AppAction", + "com.instagram.direct.share.handler." + "DirectExternalMediaShareActivityPhoto", + "com.google.android.apps.hangouts.phone.ShareIntentActivity", + "com.google.android.keep.activities.ShareReceiverActivity", + "com.verizon.mms.ui.LaunchConversationActivity", + "org.thoughtcrime.securesms.sharing.ShareActivity", + "com.twitter.composer.ComposerActivity", + "com.pinterest.activity.create.PinItActivity", + "com.twitter.app.dm.DMActivity", + "com.ideashower.readitlater.activity.AddActivity", + "com.google.android.apps.dynamite.activity.main.MainActivity", + "com.google.android.apps.docs.common.shareitem.UploadMenuActivity", + "com.microsoft.office.outlook.compose.ComposeLauncherActivity", + "com.yahoo.mail.flux.ui.MailComposeActivity", + "com.linkedin.android.publishing.sharing.SharingDeepLinkActivity", + // TODO(https://crbug.com/1228281): Samsung email + "com.reddit.sharing.ShareActivity", + "com.linecorp.line.share.common.view.FullPickerLaunchActivity", + "com.tencent.mm.ui.tools.ShareImgUI", + // TODO(https://crbug.com/1228281): Groupme + }; +} + +std::vector<std::string> DefaultWorldImageRanking() { + return { + "com.whatsapp.ContactPicker", + "com.google.android.apps.messaging.ui.conversationlist." + "ShareIntentActivity", + "com.facebook.messenger.intents.ShareIntentHandler", + "com.google.android.gm.ComposeActivityGmailExternal", + "com.instagram.share.handleractivity.ShareHandlerActivity", + "com.instagram.share.handleractivity.StoryShareHandlerActivity", + "org.telegram.ui.LaunchActivity", + "com.facebook.composer.shareintent." + "ImplicitShareIntentHandlerDefaultAlias", + "com.linecorp.line.share.common.view.FullPickerLaunchActivity", + "com.google.android.apps.hangouts.phone.ShareIntentActivity", + "com.google.android.apps.photos.uploadtoalbum.UploadContentActivity", + // TODO(https://crbug.com/1228281): Files + "com.google.android.apps.docs.common.shareitem.UploadMenuActivity", + "com.instagram.direct.share.handler." + "DirectExternalMediaShareActivityPhoto", + "com.google.android.keep.activities.ShareReceiverActivity", + "com.snap.mushroom.MainActivity", + "com.discord.app.AppActivity$AppAction", + "com.twitter.composer.ComposerActivity", + // TODO(https://crbug.com/1227749): Whatsapp Business + "com.pinterest.activity.create.PinItActivity", + "com.linkedin.android.publishing.sharing.SharingDeepLinkActivity", + "com.facebook.mlite.share.view.ShareActivity", + "org.thoughtcrime.securesms.sharing.ShareActivity", + "com.twitter.app.dm.DMActivity", + "com.facebook.lite.stories.activities.ShareToFbStoriesAlias", + "com.microsoft.office.outlook.compose.ComposeLauncherActivity", + "com.yahoo.mail.flux.ui.MailComposeActivity", + "com.viber.voip.WelcomeShareActivity", + "com.imo.android.imoim.globalshare.SharingActivity2", + // TODO(https://crbug.com/1228281): Samsung email + "com.tencent.mm.ui.tools.ShareImgUI", + "com.verizon.mms.ui.LaunchConversationActivity", + "com.google.android.apps.dynamite.activity.main.MainActivity", + }; +} + +std::vector<std::string> DefaultWorldTextRanking() { + return { + "com.whatsapp.ContactPicker", + "com.google.android.apps.messaging.ui.conversationlist." + "ShareIntentActivity", + "com.facebook.messenger.intents.ShareIntentHandler", + "com.google.android.gm.ComposeActivityGmailExternal", + "org.telegram.ui.LaunchActivity", + "com.facebook.composer.shareintent." + "ImplicitShareIntentHandlerDefaultAlias", + "com.google.android.apps.hangouts.phone.ShareIntentActivity", + // TODO(https://crbug.com/1228281): Instagram Chat + "com.linecorp.line.share.common.view.FullPickerLaunchActivity", + "com.google.android.keep.activities.ShareReceiverActivity", + "com.snap.mushroom.MainActivity", + "com.twitter.composer.ComposerActivity", + "com.discord.app.AppActivity$AppAction", + // TODO(https://crbug.com/1227749): Whatsapp Business + "com.ideashower.readitlater.activity.AddActivity", + "com.google.android.apps.docs.common.shareitem.UploadMenuActivity", + "com.pinterest.activity.create.PinItActivity", + "com.linkedin.android.publishing.sharing.SharingDeepLinkActivity", + "com.facebook.mlite.share.view.ShareActivity", + "org.thoughtcrime.securesms.sharing.ShareActivity", + "com.twitter.app.dm.DMActivity", + "com.facebook.lite.stories.activities.ShareToFbStoriesAlias", + "com.microsoft.office.outlook.compose.ComposeLauncherActivity", + "com.yahoo.mail.flux.ui.MailComposeActivity", + "com.viber.voip.WelcomeShareActivity", + "com.imo.android.imoim.globalshare.SharingActivity2", + "com.reddit.sharing.ShareActivity", + // TODO(https://crbug.com/1228281): Samsung email + "com.tencent.mm.ui.tools.ShareImgUI", + "com.verizon.mms.ui.LaunchConversationActivity", + "com.google.android.apps.dynamite.activity.main.MainActivity", + }; +} + +bool IsImageType(const std::string& type) { + // TODO(ellyjones): The type string here comes from the Android side, which is + // where the decision about image vs other is made - should we use a constant + // for this, or an enum of ints instead? + return type == "image"; +} + +bool IsEnUsLocale(const std::string& locale) { + // TODO(ellyjones): This seems very unprincipled. + return base::StartsWith(locale, "en_US"); +} + +} // namespace + +std::vector<std::string> DefaultRankingForLocaleAndType( + const std::string& locale, + const std::string& type) { + if (IsEnUsLocale(locale)) { + if (IsImageType(type)) + return DefaultEnUsImageRanking(); + else + return DefaultEnUsTextRanking(); + } else { + if (IsImageType(type)) + return DefaultWorldImageRanking(); + else + return DefaultWorldTextRanking(); + } + return {}; +} + +} // namespace sharing
diff --git a/chrome/browser/share/share_ranking.cc b/chrome/browser/share/share_ranking.cc index ef489e5b..5e3a8bf8 100644 --- a/chrome/browser/share/share_ranking.cc +++ b/chrome/browser/share/share_ranking.cc
@@ -8,9 +8,11 @@ #include "base/task/task_traits.h" #include "base/task/thread_pool.h" #include "chrome/browser/profiles/profile.h" +#include "chrome/browser/share/default_ranking.h" #include "chrome/browser/share/share_history.h" #include "components/leveldb_proto/public/proto_database_provider.h" #include "content/public/browser/storage_partition.h" +#include "ui/base/l10n/l10n_util.h" namespace sharing { @@ -385,7 +387,7 @@ std::unique_ptr<PendingRankCall> pending, absl::optional<Ranking> ranking) { if (!ranking) - ranking = GetDefaultInitialRanking(); + ranking = GetDefaultInitialRankingForType(pending->type); Ranking display, persisted; ComputeRanking(BuildHistoryMap(pending->all_history), @@ -399,10 +401,13 @@ std::move(pending->callback).Run(display); } -ShareRanking::Ranking ShareRanking::GetDefaultInitialRanking() { +ShareRanking::Ranking ShareRanking::GetDefaultInitialRankingForType( + const std::string& type) { // TODO(https://crbug.com/1222156): Use default per-locale ranking values // rather than an empty list. - return initial_ranking_for_test_.value_or(Ranking{}); + std::string locale = l10n_util::GetApplicationLocale("", false); + return initial_ranking_for_test_.value_or( + DefaultRankingForLocaleAndType(locale, type)); } } // namespace sharing
diff --git a/chrome/browser/share/share_ranking.h b/chrome/browser/share/share_ranking.h index 9f2deb4..1646756 100644 --- a/chrome/browser/share/share_ranking.h +++ b/chrome/browser/share/share_ranking.h
@@ -118,8 +118,8 @@ void OnRankGetOldRankingDone(std::unique_ptr<PendingRankCall> pending, absl::optional<Ranking> ranking); - // Return the default initial ranking, which depends on the locale. - Ranking GetDefaultInitialRanking(); + // Return the default initial ranking, which depends on the current locale. + Ranking GetDefaultInitialRankingForType(const std::string& type); bool init_finished_ = false; leveldb_proto::Enums::InitStatus db_init_status_;
diff --git a/chrome/browser/signin/services/android/java/src/org/chromium/chrome/browser/signin/services/ProfileDataCacheRenderTest.java b/chrome/browser/signin/services/android/java/src/org/chromium/chrome/browser/signin/services/ProfileDataCacheRenderTest.java index 8a91d3c..ef0333c 100644 --- a/chrome/browser/signin/services/android/java/src/org/chromium/chrome/browser/signin/services/ProfileDataCacheRenderTest.java +++ b/chrome/browser/signin/services/android/java/src/org/chromium/chrome/browser/signin/services/ProfileDataCacheRenderTest.java
@@ -48,6 +48,7 @@ import org.chromium.base.test.util.JniMocker; import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.test.ChromeJUnit4RunnerDelegate; +import org.chromium.chrome.test.DummyUiChromeActivityTestCase; import org.chromium.chrome.test.util.ChromeRenderTestRule; import org.chromium.chrome.test.util.browser.Features; import org.chromium.chrome.test.util.browser.Features.DisableFeatures; @@ -62,7 +63,6 @@ import org.chromium.components.signin.identitymanager.IdentityManagerJni; import org.chromium.components.signin.test.util.FakeProfileDataSource; import org.chromium.content_public.browser.test.util.TestThreadUtils; -import org.chromium.ui.test.util.DummyUiActivityTestCase; import org.chromium.ui.widget.ChromeImageView; import java.io.IOException; @@ -76,7 +76,7 @@ @UseRunnerDelegate(ChromeJUnit4RunnerDelegate.class) @DisableFeatures({ChromeFeatureList.DEPRECATE_MENAGERIE_API}) @Batch(ProfileDataCacheRenderTest.PROFILE_DATA_BATCH_NAME) -public class ProfileDataCacheRenderTest extends DummyUiActivityTestCase { +public class ProfileDataCacheRenderTest extends DummyUiChromeActivityTestCase { public static final String PROFILE_DATA_BATCH_NAME = "profile_data"; public static final String ACCOUNT_EMAIL = "test@gmail.com"; private static final long NATIVE_IDENTITY_MANAGER = 10002L;
diff --git a/chrome/browser/signin/services/android/java/src/org/chromium/chrome/browser/signin/services/ProfileDataCacheWithBadgeRenderTest.java b/chrome/browser/signin/services/android/java/src/org/chromium/chrome/browser/signin/services/ProfileDataCacheWithBadgeRenderTest.java index 022dbe73..13a6f24a 100644 --- a/chrome/browser/signin/services/android/java/src/org/chromium/chrome/browser/signin/services/ProfileDataCacheWithBadgeRenderTest.java +++ b/chrome/browser/signin/services/android/java/src/org/chromium/chrome/browser/signin/services/ProfileDataCacheWithBadgeRenderTest.java
@@ -32,12 +32,12 @@ import org.chromium.chrome.R; import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; +import org.chromium.chrome.test.DummyUiChromeActivityTestCase; import org.chromium.chrome.test.util.ChromeRenderTestRule; import org.chromium.chrome.test.util.browser.Features; import org.chromium.chrome.test.util.browser.signin.AccountManagerTestRule; import org.chromium.components.signin.test.util.FakeAccountInfoService; import org.chromium.content_public.browser.test.util.TestThreadUtils; -import org.chromium.ui.test.util.DummyUiActivityTestCase; import org.chromium.ui.widget.ChromeImageView; import java.io.IOException; @@ -49,7 +49,7 @@ @RunWith(ChromeJUnit4ClassRunner.class) @Batch(ProfileDataCacheRenderTest.PROFILE_DATA_BATCH_NAME) @Features.EnableFeatures({ChromeFeatureList.DEPRECATE_MENAGERIE_API}) -public class ProfileDataCacheWithBadgeRenderTest extends DummyUiActivityTestCase { +public class ProfileDataCacheWithBadgeRenderTest extends DummyUiChromeActivityTestCase { private static final String TEST_ACCOUNT_NAME = "test@example.com"; @Rule
diff --git a/chrome/browser/signin/ui/android/java/src/org/chromium/chrome/browser/signin/ui/ConfirmImportSyncDataDialogTest.java b/chrome/browser/signin/ui/android/java/src/org/chromium/chrome/browser/signin/ui/ConfirmImportSyncDataDialogTest.java index 5fc1199e..837edcd 100644 --- a/chrome/browser/signin/ui/android/java/src/org/chromium/chrome/browser/signin/ui/ConfirmImportSyncDataDialogTest.java +++ b/chrome/browser/signin/ui/android/java/src/org/chromium/chrome/browser/signin/ui/ConfirmImportSyncDataDialogTest.java
@@ -40,9 +40,9 @@ import org.mockito.junit.MockitoRule; import org.mockito.quality.Strictness; -import org.chromium.base.test.BaseActivityTestRule; import org.chromium.base.test.util.Batch; import org.chromium.base.test.util.CommandLineFlags; +import org.chromium.chrome.R; import org.chromium.chrome.browser.flags.ChromeSwitches; import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.signin.services.IdentityServicesProvider; @@ -54,6 +54,7 @@ import org.chromium.ui.modaldialog.ModalDialogManager.ModalDialogType; import org.chromium.ui.test.util.DisableAnimationsTestRule; import org.chromium.ui.test.util.DummyUiActivity; +import org.chromium.ui.test.util.ThemedDummyUiActivityTestRule; /** * Instrumentation tests for {@link ConfirmImportSyncDataDialogCoordinator}. @@ -93,8 +94,8 @@ new DisableAnimationsTestRule(); @ClassRule - public static final BaseActivityTestRule<DummyUiActivity> sActivityTestRule = - new BaseActivityTestRule<>(DummyUiActivity.class); + public static final ThemedDummyUiActivityTestRule<DummyUiActivity> sActivityTestRule = + new ThemedDummyUiActivityTestRule<>(DummyUiActivity.class, R.style.ColorOverlay); @Mock private ConfirmImportSyncDataDialogCoordinator.Listener mListenerMock;
diff --git a/chrome/browser/signin/ui/android/java/src/org/chromium/chrome/browser/signin/ui/ConfirmManagedSyncDataDialogIntegrationTest.java b/chrome/browser/signin/ui/android/java/src/org/chromium/chrome/browser/signin/ui/ConfirmManagedSyncDataDialogIntegrationTest.java index bebe344..4cbb5e9 100644 --- a/chrome/browser/signin/ui/android/java/src/org/chromium/chrome/browser/signin/ui/ConfirmManagedSyncDataDialogIntegrationTest.java +++ b/chrome/browser/signin/ui/android/java/src/org/chromium/chrome/browser/signin/ui/ConfirmManagedSyncDataDialogIntegrationTest.java
@@ -22,8 +22,8 @@ import org.chromium.base.test.util.CommandLineFlags; import org.chromium.chrome.browser.flags.ChromeSwitches; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; +import org.chromium.chrome.test.DummyUiChromeActivityTestCase; import org.chromium.ui.test.util.DummyUiActivity; -import org.chromium.ui.test.util.DummyUiActivityTestCase; /** * Test for {@link ConfirmManagedSyncDataDialog} @@ -31,7 +31,7 @@ @RunWith(ChromeJUnit4ClassRunner.class) @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) @Batch(ConfirmSyncDataIntegrationTest.CONFIRM_SYNC_DATA_BATCH_NAME) -public class ConfirmManagedSyncDataDialogIntegrationTest extends DummyUiActivityTestCase { +public class ConfirmManagedSyncDataDialogIntegrationTest extends DummyUiChromeActivityTestCase { private static final String TEST_DOMAIN = "test.domain.example.com"; @Rule
diff --git a/chrome/browser/signin/ui/android/java/src/org/chromium/chrome/browser/signin/ui/ConfirmSyncDataIntegrationTest.java b/chrome/browser/signin/ui/android/java/src/org/chromium/chrome/browser/signin/ui/ConfirmSyncDataIntegrationTest.java index 321bd04..06b1d4d 100644 --- a/chrome/browser/signin/ui/android/java/src/org/chromium/chrome/browser/signin/ui/ConfirmSyncDataIntegrationTest.java +++ b/chrome/browser/signin/ui/android/java/src/org/chromium/chrome/browser/signin/ui/ConfirmSyncDataIntegrationTest.java
@@ -40,11 +40,11 @@ import org.chromium.chrome.browser.signin.services.IdentityServicesProvider; import org.chromium.chrome.browser.signin.services.SigninManager; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; +import org.chromium.chrome.test.DummyUiChromeActivityTestCase; import org.chromium.components.browser_ui.modaldialog.AppModalPresenter; import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.ui.modaldialog.ModalDialogManager; import org.chromium.ui.modaldialog.ModalDialogManager.ModalDialogType; -import org.chromium.ui.test.util.DummyUiActivityTestCase; /** * This class regroups the integration tests for {@link ConfirmSyncDataStateMachine}. @@ -59,7 +59,7 @@ @RunWith(ChromeJUnit4ClassRunner.class) @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) @Batch(ConfirmSyncDataIntegrationTest.CONFIRM_SYNC_DATA_BATCH_NAME) -public class ConfirmSyncDataIntegrationTest extends DummyUiActivityTestCase { +public class ConfirmSyncDataIntegrationTest extends DummyUiChromeActivityTestCase { public static final String CONFIRM_SYNC_DATA_BATCH_NAME = "confirm_sync_data"; private static final String OLD_ACCOUNT_NAME = "test.account.old@gmail.com";
diff --git a/chrome/browser/signin/ui/android/java/src/org/chromium/chrome/browser/signin/ui/SignOutDialogRenderTest.java b/chrome/browser/signin/ui/android/java/src/org/chromium/chrome/browser/signin/ui/SignOutDialogRenderTest.java index 9ea277c..af2f80e 100644 --- a/chrome/browser/signin/ui/android/java/src/org/chromium/chrome/browser/signin/ui/SignOutDialogRenderTest.java +++ b/chrome/browser/signin/ui/android/java/src/org/chromium/chrome/browser/signin/ui/SignOutDialogRenderTest.java
@@ -34,11 +34,11 @@ import org.chromium.chrome.browser.signin.services.SigninMetricsUtils; import org.chromium.chrome.browser.signin.services.SigninMetricsUtilsJni; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; +import org.chromium.chrome.test.DummyUiChromeActivityTestCase; import org.chromium.chrome.test.util.ChromeRenderTestRule; import org.chromium.components.signin.GAIAServiceType; import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.ui.test.util.DisableAnimationsTestRule; -import org.chromium.ui.test.util.DummyUiActivityTestCase; /** * Render tests for {@link SignOutDialogFragment} @@ -46,7 +46,7 @@ @RunWith(ChromeJUnit4ClassRunner.class) @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) @Batch(Batch.PER_CLASS) -public class SignOutDialogRenderTest extends DummyUiActivityTestCase { +public class SignOutDialogRenderTest extends DummyUiChromeActivityTestCase { private static final String TEST_DOMAIN = "test.domain.example.com"; @Rule
diff --git a/chrome/browser/signin/ui/android/java/src/org/chromium/chrome/browser/signin/ui/account_picker/AccountPickerDialogTest.java b/chrome/browser/signin/ui/android/java/src/org/chromium/chrome/browser/signin/ui/account_picker/AccountPickerDialogTest.java index b3988b2..f67c848 100644 --- a/chrome/browser/signin/ui/android/java/src/org/chromium/chrome/browser/signin/ui/account_picker/AccountPickerDialogTest.java +++ b/chrome/browser/signin/ui/android/java/src/org/chromium/chrome/browser/signin/ui/account_picker/AccountPickerDialogTest.java
@@ -34,6 +34,7 @@ import org.chromium.chrome.browser.flags.ChromeSwitches; import org.chromium.chrome.browser.signin.ui.R; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; +import org.chromium.chrome.test.DummyUiChromeActivityTestCase; import org.chromium.chrome.test.util.ChromeRenderTestRule; import org.chromium.chrome.test.util.browser.Features; import org.chromium.chrome.test.util.browser.signin.AccountManagerTestRule; @@ -42,7 +43,6 @@ import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.ui.modaldialog.ModalDialogManager; import org.chromium.ui.modaldialog.ModalDialogManager.ModalDialogType; -import org.chromium.ui.test.util.DummyUiActivityTestCase; import java.io.IOException; @@ -53,7 +53,7 @@ @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) @Features.EnableFeatures(ChromeFeatureList.DEPRECATE_MENAGERIE_API) @Batch(Batch.PER_CLASS) -public class AccountPickerDialogTest extends DummyUiActivityTestCase { +public class AccountPickerDialogTest extends DummyUiChromeActivityTestCase { @Rule public final Features.JUnitProcessor mProcessor = new Features.JUnitProcessor();
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index 24c6734..d2c7adaf 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -49,6 +49,10 @@ "autofill/chrome_autofill_client.h", "autofill/payments/autofill_dialog_models.cc", "autofill/payments/autofill_dialog_models.h", + "autofill/payments/autofill_error_dialog_controller.h", + "autofill/payments/autofill_error_dialog_controller_impl.cc", + "autofill/payments/autofill_error_dialog_controller_impl.h", + "autofill/payments/autofill_error_dialog_view.h", "autofill/payments/create_card_unmask_prompt_view.h", "autofill/payments/credit_card_scanner_controller.cc", "autofill/payments/credit_card_scanner_controller.h", @@ -763,10 +767,6 @@ "android/webid/account_selection_view_android.cc", "android/webid/account_selection_view_android.h", "android/webid/webid_dialog_android.cc", - "autofill/payments/autofill_error_dialog_controller.h", - "autofill/payments/autofill_error_dialog_controller_impl.cc", - "autofill/payments/autofill_error_dialog_controller_impl.h", - "autofill/payments/autofill_error_dialog_view.h", "autofill/payments/autofill_snackbar_controller.h", "autofill/payments/autofill_snackbar_controller_impl.cc", "autofill/payments/autofill_snackbar_controller_impl.h", @@ -3687,6 +3687,8 @@ "views/autofill/autofill_popup_view_utils.h", "views/autofill/edit_address_profile_view.cc", "views/autofill/edit_address_profile_view.h", + "views/autofill/payments/autofill_error_dialog_view_native_views.cc", + "views/autofill/payments/autofill_error_dialog_view_native_views.h", "views/autofill/payments/card_unmask_prompt_views.cc", "views/autofill/payments/card_unmask_prompt_views.h", "views/autofill/payments/dialog_view_ids.h",
diff --git a/chrome/browser/ui/android/appmenu/internal/java/src/org/chromium/chrome/browser/ui/appmenu/AppMenuAdapterRenderTest.java b/chrome/browser/ui/android/appmenu/internal/java/src/org/chromium/chrome/browser/ui/appmenu/AppMenuAdapterRenderTest.java index f5f2e6dd..168818f 100644 --- a/chrome/browser/ui/android/appmenu/internal/java/src/org/chromium/chrome/browser/ui/appmenu/AppMenuAdapterRenderTest.java +++ b/chrome/browser/ui/android/appmenu/internal/java/src/org/chromium/chrome/browser/ui/appmenu/AppMenuAdapterRenderTest.java
@@ -33,9 +33,9 @@ import org.chromium.base.test.util.Feature; import org.chromium.chrome.browser.ui.appmenu.test.R; import org.chromium.chrome.test.ChromeJUnit4RunnerDelegate; +import org.chromium.chrome.test.DummyUiChromeActivityTestCase; import org.chromium.chrome.test.util.ChromeRenderTestRule; import org.chromium.content_public.browser.test.util.TestThreadUtils; -import org.chromium.ui.test.util.DummyUiActivityTestCase; import java.io.IOException; import java.util.ArrayList; @@ -47,7 +47,7 @@ */ @RunWith(ParameterizedRunner.class) @ParameterAnnotations.UseRunnerDelegate(ChromeJUnit4RunnerDelegate.class) -public class AppMenuAdapterRenderTest extends DummyUiActivityTestCase { +public class AppMenuAdapterRenderTest extends DummyUiChromeActivityTestCase { // TODO(twellington): Add night mode variant after NightModeTestUtils methods are modularized // in https://crbug.com/1002287.
diff --git a/chrome/browser/ui/android/appmenu/internal/java/src/org/chromium/chrome/browser/ui/appmenu/AppMenuAdapterTest.java b/chrome/browser/ui/android/appmenu/internal/java/src/org/chromium/chrome/browser/ui/appmenu/AppMenuAdapterTest.java index 3635567..a69203c 100644 --- a/chrome/browser/ui/android/appmenu/internal/java/src/org/chromium/chrome/browser/ui/appmenu/AppMenuAdapterTest.java +++ b/chrome/browser/ui/android/appmenu/internal/java/src/org/chromium/chrome/browser/ui/appmenu/AppMenuAdapterTest.java
@@ -26,9 +26,9 @@ import org.chromium.base.test.util.CallbackHelper; import org.chromium.chrome.browser.ui.appmenu.test.R; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; +import org.chromium.chrome.test.DummyUiChromeActivityTestCase; import org.chromium.components.browser_ui.widget.text.TextViewWithCompoundDrawables; import org.chromium.content_public.browser.test.util.TestThreadUtils; -import org.chromium.ui.test.util.DummyUiActivityTestCase; import org.chromium.ui.widget.ChromeImageView; import java.util.ArrayList; @@ -41,7 +41,7 @@ * Tests for {@link AppMenuAdapter}. */ @RunWith(ChromeJUnit4ClassRunner.class) -public class AppMenuAdapterTest extends DummyUiActivityTestCase { +public class AppMenuAdapterTest extends DummyUiChromeActivityTestCase { static class TestClickHandler implements AppMenuClickHandler { public CallbackHelper onClickCallback = new CallbackHelper(); public MenuItem lastClickedItem;
diff --git a/chrome/browser/ui/android/appmenu/internal/java/src/org/chromium/chrome/browser/ui/appmenu/AppMenuTest.java b/chrome/browser/ui/android/appmenu/internal/java/src/org/chromium/chrome/browser/ui/appmenu/AppMenuTest.java index 44bc47d..b9b3651 100644 --- a/chrome/browser/ui/android/appmenu/internal/java/src/org/chromium/chrome/browser/ui/appmenu/AppMenuTest.java +++ b/chrome/browser/ui/android/appmenu/internal/java/src/org/chromium/chrome/browser/ui/appmenu/AppMenuTest.java
@@ -41,10 +41,10 @@ import org.chromium.chrome.browser.lifecycle.LifecycleObserver; import org.chromium.chrome.browser.ui.appmenu.test.R; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; +import org.chromium.chrome.test.DummyUiChromeActivityTestCase; import org.chromium.components.browser_ui.widget.highlight.ViewHighlighterTestUtils; import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.ui.test.util.DummyUiActivity; -import org.chromium.ui.test.util.DummyUiActivityTestCase; import org.chromium.ui.test.util.UiDisableIf; import org.chromium.ui.widget.ChipView; @@ -60,7 +60,7 @@ @RunWith(ChromeJUnit4ClassRunner.class) @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) @Batch(Batch.PER_CLASS) -public class AppMenuTest extends DummyUiActivityTestCase { +public class AppMenuTest extends DummyUiChromeActivityTestCase { private AppMenuCoordinatorImpl mAppMenuCoordinator; private AppMenuHandlerImpl mAppMenuHandler; private TestAppMenuPropertiesDelegate mPropertiesDelegate;
diff --git a/chrome/browser/ui/android/autofill/autofill_error_dialog_view_android.cc b/chrome/browser/ui/android/autofill/autofill_error_dialog_view_android.cc index fe85723d..e1bedf8 100644 --- a/chrome/browser/ui/android/autofill/autofill_error_dialog_view_android.cc +++ b/chrome/browser/ui/android/autofill/autofill_error_dialog_view_android.cc
@@ -30,9 +30,27 @@ AutofillErrorDialogViewAndroid::~AutofillErrorDialogViewAndroid() = default; // static -std::unique_ptr<AutofillErrorDialogView> AutofillErrorDialogView::Create( +AutofillErrorDialogView* AutofillErrorDialogView::CreateAndShow( AutofillErrorDialogController* controller) { - return std::make_unique<AutofillErrorDialogViewAndroid>(controller); + AutofillErrorDialogViewAndroid* dialog_view = + new AutofillErrorDialogViewAndroid(controller); + dialog_view->Show(); + return dialog_view; +} + +void AutofillErrorDialogViewAndroid::Dismiss() { + JNIEnv* env = base::android::AttachCurrentThread(); + if (!java_object_.is_null()) { + Java_AutofillErrorDialogBridge_dismiss(env, java_object_); + } else { + OnDismissed(env); + } +} + +void AutofillErrorDialogViewAndroid::OnDismissed(JNIEnv* env) { + controller_->OnDismissed(); + controller_ = nullptr; + delete this; } void AutofillErrorDialogViewAndroid::Show() { @@ -55,17 +73,4 @@ IDR_AUTOFILL_GOOGLE_PAY_WITH_DIVIDER)); } -void AutofillErrorDialogViewAndroid::Dismiss() { - JNIEnv* env = base::android::AttachCurrentThread(); - if (!java_object_.is_null()) { - Java_AutofillErrorDialogBridge_dismiss(env, java_object_); - } else { - OnDismissed(env); - } -} - -void AutofillErrorDialogViewAndroid::OnDismissed(JNIEnv* env) { - controller_->OnDismissed(); -} - } // namespace autofill
diff --git a/chrome/browser/ui/android/autofill/autofill_error_dialog_view_android.h b/chrome/browser/ui/android/autofill/autofill_error_dialog_view_android.h index f16b635..d2afebb 100644 --- a/chrome/browser/ui/android/autofill/autofill_error_dialog_view_android.h +++ b/chrome/browser/ui/android/autofill/autofill_error_dialog_view_android.h
@@ -24,12 +24,14 @@ ~AutofillErrorDialogViewAndroid() override; // AutofillErrorDialogView. - void Show() override; void Dismiss() override; // Called by the Java code when the error dialog is dismissed. void OnDismissed(JNIEnv* env); + // Show the dialog view. + void Show(); + private: AutofillErrorDialogController* controller_; // The corresponding java object.
diff --git a/chrome/browser/ui/android/night_mode/java/src/org/chromium/chrome/browser/night_mode/settings/ThemeSettingsFragmentTest.java b/chrome/browser/ui/android/night_mode/java/src/org/chromium/chrome/browser/night_mode/settings/ThemeSettingsFragmentTest.java index 3a50669..afbb84a5 100644 --- a/chrome/browser/ui/android/night_mode/java/src/org/chromium/chrome/browser/night_mode/settings/ThemeSettingsFragmentTest.java +++ b/chrome/browser/ui/android/night_mode/java/src/org/chromium/chrome/browser/night_mode/settings/ThemeSettingsFragmentTest.java
@@ -26,18 +26,18 @@ import org.chromium.chrome.browser.preferences.SharedPreferencesManager; import org.chromium.chrome.browser.settings.SettingsActivityTestRule; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; +import org.chromium.chrome.test.DummyUiChromeActivityTestCase; import org.chromium.chrome.test.util.browser.Features; import org.chromium.components.browser_ui.widget.RadioButtonWithDescription; import org.chromium.components.browser_ui.widget.RadioButtonWithDescriptionLayout; import org.chromium.content_public.browser.test.util.TestThreadUtils; -import org.chromium.ui.test.util.DummyUiActivityTestCase; /** * Tests for ThemeSettingsFragment. */ // clang-format off @RunWith(ChromeJUnit4ClassRunner.class) -public class ThemeSettingsFragmentTest extends DummyUiActivityTestCase { +public class ThemeSettingsFragmentTest extends DummyUiChromeActivityTestCase { // clang-format on @Rule public SettingsActivityTestRule<ThemeSettingsFragment> mSettingsActivityTestRule =
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/SpannableAutocompleteEditTextModel.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/SpannableAutocompleteEditTextModel.java index 16c9643..2ee179108 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/SpannableAutocompleteEditTextModel.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/SpannableAutocompleteEditTextModel.java
@@ -343,7 +343,12 @@ @Override public void setAutocompleteText(CharSequence userText, CharSequence inlineAutocompleteText) { + // Note: this is invoked when the Autocomplete text is supplied by the Autocomplete + // subsystem. These changes should be ignored for Autocomplete, specifically should not + // be sent back to the Autocomplete subsystem to trigger suggestions fetch. + setIgnoreTextChangeFromAutocomplete(true); setAutocompleteTextInternal(userText.toString(), inlineAutocompleteText.toString()); + setIgnoreTextChangeFromAutocomplete(false); } private void setAutocompleteTextInternal(String userText, String autocompleteText) {
diff --git a/chrome/browser/ui/android/quickactionsearchwidget/BUILD.gn b/chrome/browser/ui/android/quickactionsearchwidget/BUILD.gn index 7ac1cb17..1c3ccc7 100644 --- a/chrome/browser/ui/android/quickactionsearchwidget/BUILD.gn +++ b/chrome/browser/ui/android/quickactionsearchwidget/BUILD.gn
@@ -13,6 +13,7 @@ ":java_resources", "//base:base_java", "//chrome/android:chrome_app_java_resources", + "//chrome/browser/ui/android/searchactivityutils:java", "//components/embedder_support/android:util_java", "//third_party/android_deps:com_android_support_support_annotations_java", "//third_party/androidx:androidx_core_core_java", @@ -32,10 +33,13 @@ deps = [ ":java", ":java_resources", + "//base:base_java", "//base:base_java_test_support", + "//chrome/android:chrome_app_java_resources", "//chrome/android:chrome_java", "//chrome/browser/flags:java", "//chrome/browser/tab:java", + "//chrome/browser/ui/android/searchactivityutils:java", "//chrome/test/android:chrome_java_test_support", "//components/embedder_support/android:util_java", "//content/public/test/android:content_java_test_support",
diff --git a/chrome/browser/ui/android/quickactionsearchwidget/java/src/org/chromium/chrome/browser/ui/quickactionsearchwidget/QuickActionSearchWidgetProviderDelegate.java b/chrome/browser/ui/android/quickactionsearchwidget/java/src/org/chromium/chrome/browser/ui/quickactionsearchwidget/QuickActionSearchWidgetProviderDelegate.java index 67e004a..658f72c 100644 --- a/chrome/browser/ui/android/quickactionsearchwidget/java/src/org/chromium/chrome/browser/ui/quickactionsearchwidget/QuickActionSearchWidgetProviderDelegate.java +++ b/chrome/browser/ui/android/quickactionsearchwidget/java/src/org/chromium/chrome/browser/ui/quickactionsearchwidget/QuickActionSearchWidgetProviderDelegate.java
@@ -90,25 +90,41 @@ context.getPackageName(), R.layout.quick_action_search_widget_layout); // Search Bar Intent - Intent textSearchIntent = createTrustedIntentForAction( - QuickActionSearchWidgetReceiverDelegate.ACTION_START_TEXT_QUERY); - remoteViews.setOnClickPendingIntent(R.id.quick_action_search_widget_search_bar_container, - PendingIntent.getBroadcast(context, /*requestCode=*/0, textSearchIntent, - PendingIntent.FLAG_UPDATE_CURRENT - | IntentUtils.getPendingIntentMutabilityFlag(false))); + PendingIntent textSearchPendingIntent = createPendingIntentForAction( + QuickActionSearchWidgetReceiverDelegate.ACTION_START_TEXT_QUERY, context); + remoteViews.setOnClickPendingIntent( + R.id.quick_action_search_widget_search_bar_container, textSearchPendingIntent); + + // Voice Search Intent + PendingIntent voiceSearchPendingIntent = createPendingIntentForAction( + QuickActionSearchWidgetReceiverDelegate.ACTION_START_VOICE_QUERY, context); + remoteViews.setOnClickPendingIntent( + R.id.voice_search_quick_action_button, voiceSearchPendingIntent); // Dino Game intent - Intent dinoGameIntent = createTrustedIntentForAction( - QuickActionSearchWidgetReceiverDelegate.ACTION_START_DINO_GAME); - remoteViews.setOnClickPendingIntent(R.id.dino_quick_action_button, - PendingIntent.getBroadcast(context, /*requestCode=*/0, dinoGameIntent, - PendingIntent.FLAG_UPDATE_CURRENT - | IntentUtils.getPendingIntentMutabilityFlag(false))); + PendingIntent dinoGamePendingIntent = createPendingIntentForAction( + QuickActionSearchWidgetReceiverDelegate.ACTION_START_DINO_GAME, context); + remoteViews.setOnClickPendingIntent(R.id.dino_quick_action_button, dinoGamePendingIntent); return remoteViews; } /** + * Creates a {@link PendingIntent} that will broadcast a trusted intent for a specified action. + * + * @param context The Context from which the PendingIntent will perform the broadcast. + * @param action A String specifying the action for the intent. + * @return A {@link PendingIntent} that will broadcast a trusted intent for the specified + * action. + */ + private PendingIntent createPendingIntentForAction(final String action, final Context context) { + Intent intent = createTrustedIntentForAction(action); + return PendingIntent.getBroadcast(context, /*requestCode=*/0, intent, + PendingIntent.FLAG_UPDATE_CURRENT + | IntentUtils.getPendingIntentMutabilityFlag(false)); + } + + /** * Creates a trusted intent corresponding to a specified action. * * @param action a String specifying the action for the trusted intent.
diff --git a/chrome/browser/ui/android/quickactionsearchwidget/java/src/org/chromium/chrome/browser/ui/quickactionsearchwidget/QuickActionSearchWidgetProviderDelegateTest.java b/chrome/browser/ui/android/quickactionsearchwidget/java/src/org/chromium/chrome/browser/ui/quickactionsearchwidget/QuickActionSearchWidgetProviderDelegateTest.java index 449f8010..374f485 100644 --- a/chrome/browser/ui/android/quickactionsearchwidget/java/src/org/chromium/chrome/browser/ui/quickactionsearchwidget/QuickActionSearchWidgetProviderDelegateTest.java +++ b/chrome/browser/ui/android/quickactionsearchwidget/java/src/org/chromium/chrome/browser/ui/quickactionsearchwidget/QuickActionSearchWidgetProviderDelegateTest.java
@@ -94,7 +94,21 @@ // clang-format off QuickActionSearchWidgetTestUtils.assertSearchActivityLaunchedAfterAction( () -> QuickActionSearchWidgetTestUtils.clickOnView( - view, R.id.quick_action_search_widget_search_bar_container)); + view, R.id.quick_action_search_widget_search_bar_container), + /*shouldActivityLaunchVoiceMode=*/false); + // clang-format on + } + } + + @Test + @SmallTest + public void testVoiceButtonClick() { + for (View view : mWidgetViews) { + // clang-format off + QuickActionSearchWidgetTestUtils.assertSearchActivityLaunchedAfterAction( + () -> QuickActionSearchWidgetTestUtils.clickOnView( + view, R.id.voice_search_quick_action_button), + /*shouldActivityLaunchVoiceMode=*/true); // clang-format on } } @@ -107,7 +121,7 @@ // clang-format off QuickActionSearchWidgetTestUtils.assertDinoGameLaunchedAfterAction( () -> QuickActionSearchWidgetTestUtils.clickOnView( - view, R.id.dino_quick_action_button)); + view, R.id.dino_quick_action_button)); // clang-format on } }
diff --git a/chrome/browser/ui/android/quickactionsearchwidget/java/src/org/chromium/chrome/browser/ui/quickactionsearchwidget/QuickActionSearchWidgetReceiverDelegate.java b/chrome/browser/ui/android/quickactionsearchwidget/java/src/org/chromium/chrome/browser/ui/quickactionsearchwidget/QuickActionSearchWidgetReceiverDelegate.java index c79dacc..c1d724d 100644 --- a/chrome/browser/ui/android/quickactionsearchwidget/java/src/org/chromium/chrome/browser/ui/quickactionsearchwidget/QuickActionSearchWidgetReceiverDelegate.java +++ b/chrome/browser/ui/android/quickactionsearchwidget/java/src/org/chromium/chrome/browser/ui/quickactionsearchwidget/QuickActionSearchWidgetReceiverDelegate.java
@@ -13,11 +13,12 @@ import androidx.core.app.ActivityOptionsCompat; import org.chromium.base.IntentUtils; +import org.chromium.chrome.browser.ui.searchactivityutils.SearchActivityConstants; import org.chromium.components.embedder_support.util.UrlConstants; /** - * This class serves as the delegate for the {@link QuickActionSearchWidgetReceiver}. This - * class contains as much of the business logic for the Quick Action Search Widget as possible. + * This class serves as the delegate for the {@link QuickActionSearchWidgetReceiver}. This class + * contains as much of the business logic for the Quick Action Search Widget as possible. */ public class QuickActionSearchWidgetReceiverDelegate { private final ComponentName mSearchComponent; @@ -28,6 +29,8 @@ // AndroidManifest. static final String ACTION_START_TEXT_QUERY = "org.chromium.chrome.browser.ui.quickactionsearchwidget.START_TEXT_QUERY"; + static final String ACTION_START_VOICE_QUERY = + "org.chromium.chrome.browser.ui.quickactionsearchwidget.START_VOICE_QUERY"; static final String ACTION_START_DINO_GAME = "org.chromium.chrome.browser.ui.quickactionsearchwidget.START_DINO_GAME"; @@ -55,7 +58,9 @@ public void handleAction(final Context context, final Intent intent) { String action = intent.getAction(); if (ACTION_START_TEXT_QUERY.equals(action)) { - startSearchActivity(context); + startSearchActivity(context, /*shouldStartVoiceSearch=*/false); + } else if (ACTION_START_VOICE_QUERY.equals(action)) { + startSearchActivity(context, /*shouldStartVoiceSearch=*/true); } else if (ACTION_START_DINO_GAME.equals(action)) { startDinoGame(context); } else { @@ -67,14 +72,18 @@ * Starts the component specified by mSearchComponent. Generally this component is {@link * SearchActivity}. * - * @param context the {@link Context} in which we will launch the activity. + * @param context The {@link Context} in which we will launch the activity. + * @param shouldStartVoiceSearch If the activity should be launched in voice search mode. */ - private void startSearchActivity(final Context context) { + private void startSearchActivity(final Context context, boolean shouldStartVoiceSearch) { Intent searchIntent = new Intent(); searchIntent.setComponent(mSearchComponent); searchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); searchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT); + searchIntent.putExtra( + SearchActivityConstants.EXTRA_SHOULD_START_VOICE_SEARCH, shouldStartVoiceSearch); + Bundle optionsBundle = ActivityOptionsCompat.makeCustomAnimation(context, R.anim.activity_open_enter, 0) .toBundle();
diff --git a/chrome/browser/ui/android/quickactionsearchwidget/java/src/org/chromium/chrome/browser/ui/quickactionsearchwidget/QuickActionSearchWidgetReceiverDelegateTest.java b/chrome/browser/ui/android/quickactionsearchwidget/java/src/org/chromium/chrome/browser/ui/quickactionsearchwidget/QuickActionSearchWidgetReceiverDelegateTest.java index c30f922..2f6ade6 100644 --- a/chrome/browser/ui/android/quickactionsearchwidget/java/src/org/chromium/chrome/browser/ui/quickactionsearchwidget/QuickActionSearchWidgetReceiverDelegateTest.java +++ b/chrome/browser/ui/android/quickactionsearchwidget/java/src/org/chromium/chrome/browser/ui/quickactionsearchwidget/QuickActionSearchWidgetReceiverDelegateTest.java
@@ -69,8 +69,20 @@ Intent startTextQueryIntent = new Intent(QuickActionSearchWidgetReceiverDelegate.ACTION_START_TEXT_QUERY); - QuickActionSearchWidgetTestUtils.assertSearchActivityLaunchedAfterAction( - () -> mDelegate.handleAction(mContext, startTextQueryIntent)); + QuickActionSearchWidgetTestUtils.assertSearchActivityLaunchedAfterAction(() -> { + mDelegate.handleAction(mContext, startTextQueryIntent); + }, /*shouldActivityLaunchVoiceMode=*/false); + } + + @Test + @SmallTest + public void testHandleStartVoiceQueryAction() { + Intent startVoiceQueryIntent = + new Intent(QuickActionSearchWidgetReceiverDelegate.ACTION_START_VOICE_QUERY); + + QuickActionSearchWidgetTestUtils.assertSearchActivityLaunchedAfterAction(() -> { + mDelegate.handleAction(mContext, startVoiceQueryIntent); + }, /*shouldActivityLaunchVoiceMode=*/true); } @Test
diff --git a/chrome/browser/ui/android/quickactionsearchwidget/java/src/org/chromium/chrome/browser/ui/quickactionsearchwidget/QuickActionSearchWidgetTestUtils.java b/chrome/browser/ui/android/quickactionsearchwidget/java/src/org/chromium/chrome/browser/ui/quickactionsearchwidget/QuickActionSearchWidgetTestUtils.java index 3a9066b..a27d210 100644 --- a/chrome/browser/ui/android/quickactionsearchwidget/java/src/org/chromium/chrome/browser/ui/quickactionsearchwidget/QuickActionSearchWidgetTestUtils.java +++ b/chrome/browser/ui/android/quickactionsearchwidget/java/src/org/chromium/chrome/browser/ui/quickactionsearchwidget/QuickActionSearchWidgetTestUtils.java
@@ -5,17 +5,20 @@ package org.chromium.chrome.browser.ui.quickactionsearchwidget; import android.app.Activity; +import android.content.Intent; import android.support.test.InstrumentationRegistry; import android.view.View; import org.junit.Assert; +import org.chromium.base.IntentUtils; import org.chromium.base.test.util.Criteria; import org.chromium.base.test.util.CriteriaHelper; import org.chromium.base.test.util.Matchers; import org.chromium.chrome.browser.ChromeTabbedActivity; import org.chromium.chrome.browser.searchwidget.SearchActivity; import org.chromium.chrome.browser.tab.Tab; +import org.chromium.chrome.browser.ui.searchactivityutils.SearchActivityConstants; import org.chromium.chrome.test.util.ActivityTestUtils; import org.chromium.components.embedder_support.util.UrlConstants; import org.chromium.content_public.browser.test.util.TestThreadUtils; @@ -25,15 +28,21 @@ */ class QuickActionSearchWidgetTestUtils { /** - * Asserts that {@link SearchActivity} is launched after a given {@link Runnable} is ran. + * Asserts that {@link SearchActivity} is launched in the correct mode after a given {@link + * Runnable} is ran. * - * @param action the runnable such that after running {@link SearchActivity} is expected to be - * launched. + * @param action The runnable such that after it is ran, {@link SearchActivity} is expected to + * be launched. + * @param shouldActivityLaunchVoiceMode Whether the search activity is expected to launched in + * voice mode or not. */ - static void assertSearchActivityLaunchedAfterAction(Runnable action) { + static void assertSearchActivityLaunchedAfterAction( + final Runnable action, final boolean shouldActivityLaunchVoiceMode) { Activity activity = ActivityTestUtils.waitForActivity( InstrumentationRegistry.getInstrumentation(), SearchActivity.class, action); + Assert.assertNotNull(activity); + assertSearchActivityLaunchedWithCorrectVoiceExtras(activity, shouldActivityLaunchVoiceMode); } /** @@ -68,4 +77,12 @@ TestThreadUtils.runOnUiThreadBlocking( () -> { view.findViewById(clickTarget).performClick(); }); } + + private static void assertSearchActivityLaunchedWithCorrectVoiceExtras( + final Activity activity, final boolean shouldActivityLaunchVoiceMode) { + Intent intent = activity.getIntent(); + boolean isVoiceMode = IntentUtils.safeGetBooleanExtra( + intent, SearchActivityConstants.EXTRA_SHOULD_START_VOICE_SEARCH, false); + Assert.assertEquals(shouldActivityLaunchVoiceMode, isVoiceMode); + } }
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ToolbarProgressBarTest.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ToolbarProgressBarTest.java index 0070bf58..692bb267 100644 --- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ToolbarProgressBarTest.java +++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ToolbarProgressBarTest.java
@@ -26,9 +26,9 @@ import org.chromium.base.test.util.Feature; import org.chromium.base.test.util.Restriction; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; +import org.chromium.chrome.test.DummyUiChromeActivityTestCase; import org.chromium.components.browser_ui.widget.ClipDrawableProgressBar.ProgressBarObserver; import org.chromium.content_public.browser.test.util.TestThreadUtils; -import org.chromium.ui.test.util.DummyUiActivityTestCase; import org.chromium.ui.test.util.UiRestriction; import java.util.concurrent.TimeoutException; @@ -38,7 +38,7 @@ */ @RunWith(ChromeJUnit4ClassRunner.class) @Restriction(UiRestriction.RESTRICTION_TYPE_PHONE) -public class ToolbarProgressBarTest extends DummyUiActivityTestCase { +public class ToolbarProgressBarTest extends DummyUiChromeActivityTestCase { private final CallbackHelper mProgressUpdateHelper = new CallbackHelper(); private final CallbackHelper mProgressVisibilityHelper = new CallbackHelper(); private ToolbarProgressBar mProgressBar;
diff --git a/chrome/browser/ui/android/webid/internal/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionViewTest.java b/chrome/browser/ui/android/webid/internal/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionViewTest.java index e819b9d..ec81838 100644 --- a/chrome/browser/ui/android/webid/internal/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionViewTest.java +++ b/chrome/browser/ui/android/webid/internal/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionViewTest.java
@@ -30,10 +30,10 @@ import org.mockito.MockitoAnnotations; import org.chromium.base.Callback; -import org.chromium.base.test.BaseActivityTestRule; import org.chromium.base.test.util.Batch; import org.chromium.base.test.util.CriteriaHelper; import org.chromium.base.test.util.ScalableTimeout; +import org.chromium.chrome.R; import org.chromium.chrome.browser.ui.android.webid.AccountSelectionProperties.AccountProperties; import org.chromium.chrome.browser.ui.android.webid.AccountSelectionProperties.ContinueButtonProperties; import org.chromium.chrome.browser.ui.android.webid.AccountSelectionProperties.HeaderProperties; @@ -45,6 +45,7 @@ import org.chromium.ui.modelutil.MVCListAdapter.ModelList; import org.chromium.ui.modelutil.PropertyModel; import org.chromium.ui.test.util.DummyUiActivity; +import org.chromium.ui.test.util.ThemedDummyUiActivityTestRule; import org.chromium.url.GURL; import org.chromium.url.JUnitTestGURLs; @@ -73,8 +74,8 @@ private ModelList mSheetItems; private View mContentView; @Rule - public BaseActivityTestRule<DummyUiActivity> mActivityTestRule = - new BaseActivityTestRule<>(DummyUiActivity.class); + public ThemedDummyUiActivityTestRule<DummyUiActivity> mActivityTestRule = + new ThemedDummyUiActivityTestRule<>(DummyUiActivity.class, R.style.ColorOverlay); @Before public void setUp() throws Exception {
diff --git a/chrome/browser/ui/app_list/app_service/app_service_app_model_builder.cc b/chrome/browser/ui/app_list/app_service/app_service_app_model_builder.cc index e2e950d..05468b2a 100644 --- a/chrome/browser/ui/app_list/app_service/app_service_app_model_builder.cc +++ b/chrome/browser/ui/app_list/app_service/app_service_app_model_builder.cc
@@ -106,6 +106,7 @@ // call UpdateItem unconditionally? apps::mojom::AppType app_type = update.AppType(); if ((app_type == apps::mojom::AppType::kExtension) || + (app_type == apps::mojom::AppType::kSystemWeb) || (app_type == apps::mojom::AppType::kWeb)) { app_list::AppListSyncableService* serv = service(); if (serv) {
diff --git a/chrome/browser/ui/ash/shelf/app_service/app_service_instance_registry_helper.cc b/chrome/browser/ui/ash/shelf/app_service/app_service_instance_registry_helper.cc index be8ef80e..fc0e4812 100644 --- a/chrome/browser/ui/ash/shelf/app_service/app_service_instance_registry_helper.cc +++ b/chrome/browser/ui/ash/shelf/app_service/app_service_instance_registry_helper.cc
@@ -410,6 +410,7 @@ continue; if (app_type != apps::mojom::AppType::kExtension && + app_type != apps::mojom::AppType::kSystemWeb && app_type != apps::mojom::AppType::kWeb) { return false; }
diff --git a/chrome/browser/ui/autofill/chrome_autofill_client.cc b/chrome/browser/ui/autofill/chrome_autofill_client.cc index 4a87798..07a25e3 100644 --- a/chrome/browser/ui/autofill/chrome_autofill_client.cc +++ b/chrome/browser/ui/autofill/chrome_autofill_client.cc
@@ -113,12 +113,11 @@ namespace autofill { -using AutoselectFirstSuggestion = - AutofillClient::PopupOpenArgs::AutoselectFirstSuggestion; -#if defined(OS_ANDROID) using AutofillErrorDialogType = AutofillErrorDialogController::AutofillErrorDialogType; -#endif // OS_ANDROID + +using AutoselectFirstSuggestion = + AutofillClient::PopupOpenArgs::AutoselectFirstSuggestion; ChromeAutofillClient::~ChromeAutofillClient() { // NOTE: It is too late to clean up the autofill popup; that cleanup process @@ -300,19 +299,19 @@ card, reason, delegate); } +// TODO(crbug.com/1220990): Refactor this for both CVC and Biometrics flows. void ChromeAutofillClient::OnUnmaskVerificationResult( PaymentsRpcResult result) { unmask_controller_.OnVerificationResult(result); #if defined(OS_ANDROID) // For VCN related errors, on Android we show a new error dialog instead of // updating the CVC unmask prompt with the error message. - absl::optional<AutofillErrorDialogType> error_dialog_type; switch (result) { case AutofillClient::VCN_RETRIEVAL_PERMANENT_FAILURE: - error_dialog_type = AutofillErrorDialogType::VIRTUAL_CARD_PERMANENT_ERROR; + ShowVirtualCardErrorDialog(/*is_permanent_error=*/true); break; case AutofillClient::VCN_RETRIEVAL_TRY_AGAIN_FAILURE: - error_dialog_type = AutofillErrorDialogType::VIRTUAL_CARD_TEMPORARY_ERROR; + ShowVirtualCardErrorDialog(/*is_permanent_error=*/false); break; case AutofillClient::SUCCESS: case AutofillClient::TRY_AGAIN_FAILURE: @@ -324,11 +323,6 @@ NOTREACHED(); return; } - if (error_dialog_type) { - autofill_error_dialog_controller_.Show( - AutofillErrorDialogView::Create(&autofill_error_dialog_controller_), - error_dialog_type.value()); - } #endif // OS_ANDROID } @@ -716,14 +710,12 @@ #endif } -void ChromeAutofillClient::OnVirtualCardFetched(CreditCardFetchResult result, - const CreditCard* credit_card, - const std::u16string& cvc, - const gfx::Image& card_image) { - if (result != CreditCardFetchResult::kSuccess) { - // TODO(crbug.com/1196021): Shows the error dialog. - return; - } +void ChromeAutofillClient::OnVirtualCardDataAvailable( + const CreditCard* credit_card, + const std::u16string& cvc, + const gfx::Image& card_image) { + DCHECK(credit_card); + DCHECK(!cvc.empty()); GetFormDataImporter()->CacheFetchedVirtualCard(credit_card->LastFourDigits()); #if defined(OS_ANDROID) @@ -738,6 +730,14 @@ #endif } +void ChromeAutofillClient::ShowVirtualCardErrorDialog(bool is_permanent_error) { + AutofillErrorDialogType error_dialog_type = + is_permanent_error + ? AutofillErrorDialogType::VIRTUAL_CARD_PERMANENT_ERROR + : AutofillErrorDialogType::VIRTUAL_CARD_TEMPORARY_ERROR; + autofill_error_dialog_controller_.Show(error_dialog_type); +} + bool ChromeAutofillClient::IsAutofillAssistantShowing() { auto* assistant_runtime_manager = autofill_assistant::RuntimeManager::GetForWebContents(web_contents()); @@ -858,11 +858,9 @@ payments_client_.get(), GetPersonalDataManager(), GetPersonalDataManager()->app_locale())), -#if defined(OS_ANDROID) - autofill_error_dialog_controller_(web_contents), -#endif // OS_ANDROID unmask_controller_( - user_prefs::UserPrefs::Get(web_contents->GetBrowserContext())) { + user_prefs::UserPrefs::Get(web_contents->GetBrowserContext())), + autofill_error_dialog_controller_(web_contents) { // TODO(crbug.com/928595): Replace the closure with a callback to the // renderer that indicates if log messages should be sent from the // renderer.
diff --git a/chrome/browser/ui/autofill/chrome_autofill_client.h b/chrome/browser/ui/autofill/chrome_autofill_client.h index 02239568..72a90c2 100644 --- a/chrome/browser/ui/autofill/chrome_autofill_client.h +++ b/chrome/browser/ui/autofill/chrome_autofill_client.h
@@ -17,6 +17,7 @@ #include "build/build_config.h" #include "chrome/browser/autofill/autofill_gstatic_reader.h" #include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/autofill/payments/autofill_error_dialog_controller_impl.h" #include "components/autofill/core/browser/autofill_client.h" #include "components/autofill/core/browser/logging/log_manager.h" #include "components/autofill/core/browser/payments/legal_message_line.h" @@ -27,7 +28,6 @@ #if defined(OS_ANDROID) #include "chrome/browser/autofill/android/save_update_address_profile_flow_manager.h" -#include "chrome/browser/ui/autofill/payments/autofill_error_dialog_controller_impl.h" #include "components/autofill/core/browser/ui/payments/card_expiration_date_fix_flow_controller_impl.h" #include "components/autofill/core/browser/ui/payments/card_name_fix_flow_controller_impl.h" #else // !OS_ANDROID @@ -150,10 +150,10 @@ void HideAutofillPopup(PopupHidingReason reason) override; void ShowOfferNotificationIfApplicable( const AutofillOfferData* offer) override; - void OnVirtualCardFetched(CreditCardFetchResult result, - const CreditCard* credit_card, - const std::u16string& cvc, - const gfx::Image& card_image) override; + void OnVirtualCardDataAvailable(const CreditCard* credit_card, + const std::u16string& cvc, + const gfx::Image& card_image) override; + void ShowVirtualCardErrorDialog(bool is_permanent_error) override; bool IsAutofillAssistantShowing() override; bool IsAutocompleteEnabled() override; void PropagateAutofillPredictions( @@ -207,9 +207,9 @@ card_expiration_date_fix_flow_controller_; CardNameFixFlowControllerImpl card_name_fix_flow_controller_; SaveUpdateAddressProfileFlowManager save_update_address_profile_flow_manager_; - AutofillErrorDialogControllerImpl autofill_error_dialog_controller_; #endif CardUnmaskPromptControllerImpl unmask_controller_; + AutofillErrorDialogControllerImpl autofill_error_dialog_controller_; WEB_CONTENTS_USER_DATA_KEY_DECL();
diff --git a/chrome/browser/ui/autofill/payments/autofill_error_dialog_controller_impl.cc b/chrome/browser/ui/autofill/payments/autofill_error_dialog_controller_impl.cc index 803e21e..d30bd378 100644 --- a/chrome/browser/ui/autofill/payments/autofill_error_dialog_controller_impl.cc +++ b/chrome/browser/ui/autofill/payments/autofill_error_dialog_controller_impl.cc
@@ -19,22 +19,20 @@ } void AutofillErrorDialogControllerImpl::Show( - std::unique_ptr<AutofillErrorDialogView> autofill_error_dialog_view, AutofillErrorDialogController::AutofillErrorDialogType error_dialog_type) { if (autofill_error_dialog_view_) Dismiss(); DCHECK(autofill_error_dialog_view_ == nullptr); - autofill_error_dialog_view_ = std::move(autofill_error_dialog_view); error_dialog_type_ = error_dialog_type; - autofill_error_dialog_view_->Show(); + autofill_error_dialog_view_ = AutofillErrorDialogView::CreateAndShow(this); base::UmaHistogramEnumeration("Autofill.ErrorDialogShown", error_dialog_type); } void AutofillErrorDialogControllerImpl::OnDismissed() { // TODO(crbug.com/1196021): Log the dismiss action along with the type of the // error dialog. - autofill_error_dialog_view_.reset(); + autofill_error_dialog_view_ = nullptr; } const std::u16string AutofillErrorDialogControllerImpl::GetTitle() {
diff --git a/chrome/browser/ui/autofill/payments/autofill_error_dialog_controller_impl.h b/chrome/browser/ui/autofill/payments/autofill_error_dialog_controller_impl.h index b0a8128..94afec4e 100644 --- a/chrome/browser/ui/autofill/payments/autofill_error_dialog_controller_impl.h +++ b/chrome/browser/ui/autofill/payments/autofill_error_dialog_controller_impl.h
@@ -29,7 +29,6 @@ // Show the error dialog for the given `AutofillErrorDialogType` void Show( - std::unique_ptr<AutofillErrorDialogView> view, AutofillErrorDialogController::AutofillErrorDialogType error_dialog_type); // AutofillErrorDialogController. @@ -39,6 +38,10 @@ const std::u16string GetButtonLabel() override; content::WebContents* GetWebContents() override; + AutofillErrorDialogView* autofill_error_dialog_view() { + return autofill_error_dialog_view_; + } + private: // Dismiss the error dialog if showing. void Dismiss(); @@ -47,7 +50,7 @@ // The type of the error dialog that is being displayed. AutofillErrorDialogController::AutofillErrorDialogType error_dialog_type_; // View that displays the error dialog. - std::unique_ptr<AutofillErrorDialogView> autofill_error_dialog_view_; + AutofillErrorDialogView* autofill_error_dialog_view_ = nullptr; }; } // namespace autofill
diff --git a/chrome/browser/ui/autofill/payments/autofill_error_dialog_controller_impl_unittest.cc b/chrome/browser/ui/autofill/payments/autofill_error_dialog_controller_impl_unittest.cc index 5d1be6c..f752c55 100644 --- a/chrome/browser/ui/autofill/payments/autofill_error_dialog_controller_impl_unittest.cc +++ b/chrome/browser/ui/autofill/payments/autofill_error_dialog_controller_impl_unittest.cc
@@ -13,13 +13,6 @@ namespace autofill { -class MockAutofillErrorDialogView : public AutofillErrorDialogView { - public: - MockAutofillErrorDialogView() = default; - void Show() override {} - void Dismiss() override {} -}; - class AutofillErrorDialogControllerImplTest : public ChromeRenderViewHostTestHarness { public: @@ -38,7 +31,6 @@ TEST_F(AutofillErrorDialogControllerImplTest, MetricsTest) { base::HistogramTester histogram_tester; controller()->Show( - std::make_unique<MockAutofillErrorDialogView>(), AutofillErrorDialogController::VIRTUAL_CARD_TEMPORARY_ERROR); // Verify that the metric for shown is incremented.
diff --git a/chrome/browser/ui/autofill/payments/autofill_error_dialog_view.h b/chrome/browser/ui/autofill/payments/autofill_error_dialog_view.h index f99f7c00..ecf3b1e 100644 --- a/chrome/browser/ui/autofill/payments/autofill_error_dialog_view.h +++ b/chrome/browser/ui/autofill/payments/autofill_error_dialog_view.h
@@ -7,6 +7,8 @@ namespace autofill { +class AutofillErrorDialogController; + // The cross-platform view interface which helps show an error dialog for // autofill flows. // @@ -15,11 +17,10 @@ public: virtual ~AutofillErrorDialogView() = default; - virtual void Show() = 0; virtual void Dismiss() = 0; - // Factory function for creating the view. - static std::unique_ptr<AutofillErrorDialogView> Create( + // Factory function for creating and showing the view. + static AutofillErrorDialogView* CreateAndShow( AutofillErrorDialogController* controller); };
diff --git a/chrome/browser/ui/browser_navigator.cc b/chrome/browser/ui/browser_navigator.cc index df2bdd2..a5a1c68 100644 --- a/chrome/browser/ui/browser_navigator.cc +++ b/chrome/browser/ui/browser_navigator.cc
@@ -751,8 +751,7 @@ base::StringPiece host = url.host_piece(); if (scheme == chrome::kChromeSearchScheme) { return host != chrome::kChromeUIThumbnailHost && - host != chrome::kChromeUIThumbnailHost2 && - host != chrome::kChromeUISuggestionsHost; + host != chrome::kChromeUIThumbnailHost2; } if (scheme != content::kChromeUIScheme) @@ -785,7 +784,6 @@ host != chrome::kChromeUIBookmarksHost && host != chrome::kChromeUIThumbnailHost && host != chrome::kChromeUIThumbnailHost2 && - host != chrome::kChromeUISuggestionsHost && host != chrome::kChromeUIDevicesHost && host != chrome::kChromeUINewTabPageHost && host != chrome::kChromeUINewTabPageThirdPartyHost;
diff --git a/chrome/browser/ui/messages/android/java/src/org/chromium/chrome/browser/ui/messages/snackbar/SnackbarTest.java b/chrome/browser/ui/messages/android/java/src/org/chromium/chrome/browser/ui/messages/snackbar/SnackbarTest.java index ada05fb..db15a39 100644 --- a/chrome/browser/ui/messages/android/java/src/org/chromium/chrome/browser/ui/messages/snackbar/SnackbarTest.java +++ b/chrome/browser/ui/messages/android/java/src/org/chromium/chrome/browser/ui/messages/snackbar/SnackbarTest.java
@@ -16,8 +16,8 @@ import org.chromium.base.test.util.CriteriaHelper; import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager.SnackbarController; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; +import org.chromium.chrome.test.DummyUiChromeActivityTestCase; import org.chromium.content_public.browser.UiThreadTaskTraits; -import org.chromium.ui.test.util.DummyUiActivityTestCase; import java.util.concurrent.TimeUnit; @@ -25,7 +25,7 @@ * Tests for {@link SnackbarManager}. */ @RunWith(ChromeJUnit4ClassRunner.class) -public class SnackbarTest extends DummyUiActivityTestCase { +public class SnackbarTest extends DummyUiChromeActivityTestCase { private SnackbarManager mManager; private SnackbarController mDefaultController = new SnackbarController() { @Override
diff --git a/chrome/browser/ui/views/autofill/payments/autofill_error_dialog_view_native_views.cc b/chrome/browser/ui/views/autofill/payments/autofill_error_dialog_view_native_views.cc new file mode 100644 index 0000000..a8a06d7 --- /dev/null +++ b/chrome/browser/ui/views/autofill/payments/autofill_error_dialog_view_native_views.cc
@@ -0,0 +1,91 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/views/autofill/payments/autofill_error_dialog_view_native_views.h" + +#include "chrome/browser/ui/autofill/payments/autofill_error_dialog_controller.h" +#include "chrome/browser/ui/views/autofill/payments/payments_view_util.h" +#include "chrome/browser/ui/views/chrome_layout_provider.h" +#include "chrome/browser/ui/views/chrome_typography.h" +#include "components/constrained_window/constrained_window_views.h" +#include "components/vector_icons/vector_icons.h" +#include "ui/gfx/vector_icon_utils.h" +#include "ui/views/bubble/bubble_frame_view.h" +#include "ui/views/controls/color_tracking_icon_view.h" +#include "ui/views/layout/box_layout.h" + +namespace autofill { + +AutofillErrorDialogViewNativeViews::AutofillErrorDialogViewNativeViews( + AutofillErrorDialogController* controller) + : controller_(controller) { + SetButtons(ui::DIALOG_BUTTON_CANCEL); + SetButtonLabel(ui::DIALOG_BUTTON_CANCEL, controller_->GetButtonLabel()); + SetModalType(ui::MODAL_TYPE_CHILD); + set_fixed_width(views::LayoutProvider::Get()->GetDistanceMetric( + views::DISTANCE_MODAL_DIALOG_PREFERRED_WIDTH)); + SetShowCloseButton(false); + set_margins(ChromeLayoutProvider::Get()->GetDialogInsetsForContentType( + views::DialogContentType::kControl, views::DialogContentType::kControl)); +} + +AutofillErrorDialogViewNativeViews::~AutofillErrorDialogViewNativeViews() { + if (controller_) { + controller_->OnDismissed(); + controller_ = nullptr; + } +} + +// static +AutofillErrorDialogView* AutofillErrorDialogView::CreateAndShow( + AutofillErrorDialogController* controller) { + AutofillErrorDialogViewNativeViews* dialog_view = + new AutofillErrorDialogViewNativeViews(controller); + constrained_window::ShowWebModalDialogViews(dialog_view, + controller->GetWebContents()); + return dialog_view; +} + +void AutofillErrorDialogViewNativeViews::Dismiss() { + if (controller_) { + controller_->OnDismissed(); + controller_ = nullptr; + } + GetWidget()->CloseWithReason(views::Widget::ClosedReason::kUnspecified); +} + +views::View* AutofillErrorDialogViewNativeViews::GetContentsView() { + if (!children().empty()) + return this; + + auto* layout = SetLayoutManager(std::make_unique<views::BoxLayout>( + views::BoxLayout::Orientation::kHorizontal, gfx::Insets(), + ChromeLayoutProvider::Get()->GetDistanceMetric( + DISTANCE_RELATED_CONTROL_HORIZONTAL_SMALL))); + layout->set_cross_axis_alignment( + views::BoxLayout::CrossAxisAlignment::kCenter); + + AddChildView(std::make_unique<views::ColorTrackingIconView>( + vector_icons::kErrorIcon, + gfx::GetDefaultSizeOfVectorIcon(vector_icons::kErrorIcon), + ui::NativeTheme::kColorId_AlertSeverityHigh)); + + auto* label = AddChildView(std::make_unique<views::Label>( + controller_->GetDescription(), + ChromeTextContext::CONTEXT_DIALOG_BODY_TEXT_SMALL, STYLE_RED)); + label->SetHorizontalAlignment(gfx::ALIGN_LEFT); + label->SetMultiLine(true); + return this; +} + +void AutofillErrorDialogViewNativeViews::AddedToWidget() { + GetBubbleFrameView()->SetTitleView( + std::make_unique<TitleWithIconAndSeparatorView>(GetWindowTitle())); +} + +std::u16string AutofillErrorDialogViewNativeViews::GetWindowTitle() const { + return controller_->GetTitle(); +} + +} // namespace autofill
diff --git a/chrome/browser/ui/views/autofill/payments/autofill_error_dialog_view_native_views.h b/chrome/browser/ui/views/autofill/payments/autofill_error_dialog_view_native_views.h new file mode 100644 index 0000000..2ab1132e --- /dev/null +++ b/chrome/browser/ui/views/autofill/payments/autofill_error_dialog_view_native_views.h
@@ -0,0 +1,39 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_VIEWS_AUTOFILL_PAYMENTS_AUTOFILL_ERROR_DIALOG_VIEW_NATIVE_VIEWS_H_ +#define CHROME_BROWSER_UI_VIEWS_AUTOFILL_PAYMENTS_AUTOFILL_ERROR_DIALOG_VIEW_NATIVE_VIEWS_H_ + +#include "chrome/browser/ui/autofill/payments/autofill_error_dialog_view.h" +#include "ui/views/window/dialog_delegate.h" + +namespace autofill { + +// The native views for AutofillErrorDialogView. +class AutofillErrorDialogViewNativeViews : public AutofillErrorDialogView, + public views::DialogDelegateView { + public: + explicit AutofillErrorDialogViewNativeViews( + AutofillErrorDialogController* controller); + ~AutofillErrorDialogViewNativeViews() override; + AutofillErrorDialogViewNativeViews( + const AutofillErrorDialogViewNativeViews&) = delete; + AutofillErrorDialogViewNativeViews& operator=( + const AutofillErrorDialogViewNativeViews&) = delete; + + // AutofillErrorDialogView: + void Dismiss() override; + + // DialogDelegate: + views::View* GetContentsView() override; + void AddedToWidget() override; + std::u16string GetWindowTitle() const override; + + private: + AutofillErrorDialogController* controller_; +}; + +} // namespace autofill + +#endif // CHROME_BROWSER_UI_VIEWS_AUTOFILL_PAYMENTS_AUTOFILL_ERROR_DIALOG_VIEW_NATIVE_VIEWS_H_
diff --git a/chrome/browser/ui/views/autofill/payments/autofill_error_dialog_view_native_views_browsertest.cc b/chrome/browser/ui/views/autofill/payments/autofill_error_dialog_view_native_views_browsertest.cc new file mode 100644 index 0000000..925bb93b --- /dev/null +++ b/chrome/browser/ui/views/autofill/payments/autofill_error_dialog_view_native_views_browsertest.cc
@@ -0,0 +1,110 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/run_loop.h" +#include "chrome/browser/ui/autofill/payments/autofill_error_dialog_controller_impl.h" +#include "chrome/browser/ui/autofill/payments/autofill_error_dialog_view.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_window.h" +#include "chrome/browser/ui/test/test_browser_dialog.h" +#include "chrome/browser/ui/views/autofill/payments/autofill_error_dialog_view_native_views.h" +#include "content/public/test/browser_test.h" + +namespace autofill { + +class AutofillErrorDialogViewNativeViewsBrowserTest : public DialogBrowserTest { + public: + AutofillErrorDialogViewNativeViewsBrowserTest() = default; + ~AutofillErrorDialogViewNativeViewsBrowserTest() override = default; + AutofillErrorDialogViewNativeViewsBrowserTest( + const AutofillErrorDialogViewNativeViewsBrowserTest&) = delete; + AutofillErrorDialogViewNativeViewsBrowserTest& operator=( + const AutofillErrorDialogViewNativeViewsBrowserTest&) = delete; + + // DialogBrowserTest: + void SetUpOnMainThread() override { + controller_ = std::make_unique<AutofillErrorDialogControllerImpl>( + browser()->tab_strip_model()->GetActiveWebContents()); + } + + void ShowUi(const std::string& name) override { + AutofillErrorDialogController::AutofillErrorDialogType dialog_type; + if (name == "temporary") { + dialog_type = AutofillErrorDialogController::AutofillErrorDialogType:: + VIRTUAL_CARD_TEMPORARY_ERROR; + } else if (name == "permanent") { + dialog_type = AutofillErrorDialogController::AutofillErrorDialogType:: + VIRTUAL_CARD_PERMANENT_ERROR; + } else if (name == "eligibility") { + dialog_type = AutofillErrorDialogController::AutofillErrorDialogType:: + VIRTUAL_CARD_NOT_ELIGIBLE_ERROR; + } else { + NOTREACHED(); + return; + } + + controller()->Show(dialog_type); + } + + AutofillErrorDialogViewNativeViews* GetDialogViews() { + if (!controller()) + return nullptr; + + AutofillErrorDialogView* dialog_view = + controller()->autofill_error_dialog_view(); + if (!dialog_view) + return nullptr; + + return static_cast<AutofillErrorDialogViewNativeViews*>(dialog_view); + } + + AutofillErrorDialogControllerImpl* controller() { return controller_.get(); } + + private: + std::unique_ptr<AutofillErrorDialogControllerImpl> controller_; +}; + +IN_PROC_BROWSER_TEST_F(AutofillErrorDialogViewNativeViewsBrowserTest, + InvokeUi_temporary) { + ShowAndVerifyUi(); +} + +IN_PROC_BROWSER_TEST_F(AutofillErrorDialogViewNativeViewsBrowserTest, + InvokeUi_permanent) { + ShowAndVerifyUi(); +} + +IN_PROC_BROWSER_TEST_F(AutofillErrorDialogViewNativeViewsBrowserTest, + InvokeUi_eligibility) { + ShowAndVerifyUi(); +} + +// Ensures closing current tab while dialog being visible is correctly handled. +IN_PROC_BROWSER_TEST_F(AutofillErrorDialogViewNativeViewsBrowserTest, + CloseTabWhileDialogShowing) { + ShowUi("temporary"); + VerifyUi(); + browser()->tab_strip_model()->GetActiveWebContents()->Close(); + base::RunLoop().RunUntilIdle(); +} + +// Ensures closing browser while dialog being visible is correctly handled. +IN_PROC_BROWSER_TEST_F(AutofillErrorDialogViewNativeViewsBrowserTest, + CanCloseBrowserWhileDialogShowing) { + ShowUi("temporary"); + VerifyUi(); + browser()->window()->Close(); + base::RunLoop().RunUntilIdle(); +} + +// Ensures clicking on the cancel button is correctly handled. +IN_PROC_BROWSER_TEST_F(AutofillErrorDialogViewNativeViewsBrowserTest, + ClickCancelButton) { + ShowUi("temporary"); + VerifyUi(); + GetDialogViews()->CancelDialog(); + base::RunLoop().RunUntilIdle(); +} + +} // namespace autofill
diff --git a/chrome/browser/ui/views/autofill/payments/card_unmask_prompt_views.cc b/chrome/browser/ui/views/autofill/payments/card_unmask_prompt_views.cc index 7dc37750..f10be8a 100644 --- a/chrome/browser/ui/views/autofill/payments/card_unmask_prompt_views.cc +++ b/chrome/browser/ui/views/autofill/payments/card_unmask_prompt_views.cc
@@ -18,6 +18,7 @@ #include "components/autofill/core/browser/ui/payments/card_unmask_prompt_controller.h" #include "components/constrained_window/constrained_window_views.h" #include "components/strings/grit/components_strings.h" +#include "components/vector_icons/vector_icons.h" #include "components/web_modal/web_contents_modal_dialog_host.h" #include "components/web_modal/web_contents_modal_dialog_manager.h" #include "components/web_modal/web_contents_modal_dialog_manager_delegate.h" @@ -27,10 +28,12 @@ #include "ui/base/resource/resource_bundle.h" #include "ui/gfx/geometry/insets.h" #include "ui/gfx/paint_vector_icon.h" +#include "ui/gfx/vector_icon_utils.h" #include "ui/native_theme/native_theme.h" #include "ui/views/background.h" #include "ui/views/border.h" #include "ui/views/bubble/bubble_frame_view.h" +#include "ui/views/controls/color_tracking_icon_view.h" #include "ui/views/controls/combobox/combobox.h" #include "ui/views/controls/image_view.h" #include "ui/views/controls/label.h" @@ -47,22 +50,6 @@ namespace { -class ErrorIconView : public views::ImageView { - public: - METADATA_HEADER(ErrorIconView); - - // views::ImageView: - void OnThemeChanged() override { - ImageView::OnThemeChanged(); - const SkColor warning_text_color = views::style::GetColor( - *this, ChromeTextContext::CONTEXT_DIALOG_BODY_TEXT_SMALL, STYLE_RED); - SetImage(gfx::CreateVectorIcon(kBrowserToolsErrorIcon, warning_text_color)); - } -}; - -BEGIN_METADATA(ErrorIconView, views::ImageView) -END_METADATA - static views::GridLayout* ResetOverlayLayout(views::View* overlay) { views::GridLayout* overlay_layout = overlay->SetLayoutManager(std::make_unique<views::GridLayout>()); @@ -402,7 +389,10 @@ views::BoxLayout::CrossAxisAlignment::kCenter); temporary_error->SetVisible(false); - temporary_error->AddChildView(std::make_unique<ErrorIconView>()); + temporary_error->AddChildView(std::make_unique<views::ColorTrackingIconView>( + vector_icons::kErrorIcon, + gfx::GetDefaultSizeOfVectorIcon(vector_icons::kErrorIcon), + ui::NativeTheme::kColorId_AlertSeverityHigh)); auto error_label = std::make_unique<views::Label>( std::u16string(), ChromeTextContext::CONTEXT_DIALOG_BODY_TEXT_SMALL,
diff --git a/chrome/browser/ui/views/frame/glass_browser_frame_view.cc b/chrome/browser/ui/views/frame/glass_browser_frame_view.cc index c4a1531a..490a8370 100644 --- a/chrome/browser/ui/views/frame/glass_browser_frame_view.cc +++ b/chrome/browser/ui/views/frame/glass_browser_frame_view.cc
@@ -236,6 +236,17 @@ return caption_button_container_->GetTabSearchBubbleHost(); } +void GlassBrowserFrameView::PaintAsActiveChanged() { + BrowserNonClientFrameView::PaintAsActiveChanged(); + + // When window controls overlay is enabled, the caption button container is + // painted to a layer and is not repainted by + // BrowserNonClientFrameView::PaintAsActiveChanged. Schedule a re-paint here + // to update the caption button colors. + if (caption_button_container_ && caption_button_container_->layer()) + caption_button_container_->SchedulePaint(); +} + /////////////////////////////////////////////////////////////////////////////// // GlassBrowserFrameView, views::NonClientFrameView implementation:
diff --git a/chrome/browser/ui/views/frame/glass_browser_frame_view.h b/chrome/browser/ui/views/frame/glass_browser_frame_view.h index e5464ec..601c755 100644 --- a/chrome/browser/ui/views/frame/glass_browser_frame_view.h +++ b/chrome/browser/ui/views/frame/glass_browser_frame_view.h
@@ -76,6 +76,9 @@ const views::Label* window_title_for_testing() const { return window_title_; } protected: + // BrowserNonClientFrameView: + void PaintAsActiveChanged() override; + // views::View: void OnPaint(gfx::Canvas* canvas) override; void Layout() override;
diff --git a/chrome/browser/ui/views/permission_bubble/file_handling_permission_request_dialog.cc b/chrome/browser/ui/views/permission_bubble/file_handling_permission_request_dialog.cc index ebe73f0..769d552 100644 --- a/chrome/browser/ui/views/permission_bubble/file_handling_permission_request_dialog.cc +++ b/chrome/browser/ui/views/permission_bubble/file_handling_permission_request_dialog.cc
@@ -12,13 +12,20 @@ #include "chrome/browser/ui/browser_dialogs.h" #include "chrome/browser/ui/views/chrome_layout_provider.h" #include "chrome/browser/web_applications/components/web_app_utils.h" +#include "chrome/grit/generated_resources.h" #include "components/permissions/permission_uma_util.h" +#include "components/strings/grit/components_strings.h" #include "components/url_formatter/elide_url.h" +#include "components/vector_icons/vector_icons.h" #include "content/public/browser/web_contents.h" +#include "ui/base/l10n/l10n_util.h" #include "ui/base/metadata/metadata_impl_macros.h" +#include "ui/gfx/text_elider.h" #include "ui/views/controls/button/checkbox.h" +#include "ui/views/controls/color_tracking_icon_view.h" #include "ui/views/controls/label.h" #include "ui/views/layout/box_layout.h" +#include "ui/views/layout/flex_layout.h" #include "url/gurl.h" FileHandlingPermissionRequestDialog* g_instance_for_testing = nullptr; @@ -34,15 +41,101 @@ set_fixed_width(views::LayoutProvider::Get()->GetDistanceMetric( views::DISTANCE_MODAL_DIALOG_PREFERRED_WIDTH)); - // TODO(estade): this UI is preliminary. Update when mocks are finalized. - // TODO(estade): localize strings. + const bool plural = file_paths.size() > 1; + SetTitle(l10n_util::GetStringUTF16( + plural ? IDS_WEB_APP_FILE_HANDLING_PERMISSION_TITLE_MULTIPLE + : IDS_WEB_APP_FILE_HANDLING_PERMISSION_TITLE)); + + ChromeLayoutProvider* layout_provider = ChromeLayoutProvider::Get(); + auto* box_layout = SetLayoutManager(std::make_unique<views::BoxLayout>( + views::BoxLayout::Orientation::kVertical, + layout_provider->GetDialogInsetsForContentType( + views::DialogContentType::kText, views::DialogContentType::kControl), + layout_provider->GetDistanceMetric( + views::DISTANCE_UNRELATED_CONTROL_VERTICAL))); + + // Description of permission. // TODO(estade): use GetLastCommittedOrigin(). See crbug.com/698985 const GURL app_url = web_contents->GetMainFrame()->GetLastCommittedURL(); - SetTitle(url_formatter::FormatUrlForSecurityDisplay( - app_url, url_formatter::SchemeDisplay::OMIT_CRYPTOGRAPHIC) + - u" wants to"); - SetButtonLabel(ui::DIALOG_BUTTON_OK, u"Allow"); - SetButtonLabel(ui::DIALOG_BUTTON_CANCEL, u"Don't allow"); + auto* description_label = + AddChildView(std::make_unique<views::Label>(l10n_util::GetStringFUTF16( + plural ? IDS_WEB_APP_FILE_HANDLING_PERMISSION_DESCRIPTION_MULTIPLE + : IDS_WEB_APP_FILE_HANDLING_PERMISSION_DESCRIPTION, + url_formatter::FormatUrlForSecurityDisplay( + app_url, url_formatter::SchemeDisplay::OMIT_CRYPTOGRAPHIC)))); + description_label->SetMultiLine(true); + description_label->SetHorizontalAlignment(gfx::ALIGN_LEFT); + + // File icon and name list. + auto* files_view = AddChildView(std::make_unique<views::View>()); + files_view->SetLayoutManager(std::make_unique<views::FlexLayout>()) + ->SetOrientation(views::LayoutOrientation::kHorizontal) + .SetCrossAxisAlignment(views::LayoutAlignment::kStart); + + // File icon. + auto checkbox = std::make_unique<views::Checkbox>(); + auto* icon = + files_view->AddChildView(std::make_unique<views::ColorTrackingIconView>( + vector_icons::kDescriptionIcon, + checkbox->GetImage(views::Button::STATE_NORMAL).width())); + const int icon_margin = views::LayoutProvider::Get()->GetDistanceMetric( + views::DISTANCE_RELATED_LABEL_HORIZONTAL); + icon->SetProperty(views::kMarginsKey, gfx::Insets(0, 0, 0, icon_margin)); + + // File name list. + std::vector<std::u16string> file_names; + // Display at most a dozen files. After that, elide. + size_t displayed_file_name_count = + std::min(file_paths.size(), static_cast<size_t>(12)); + file_names.reserve(displayed_file_name_count + 1); + + // Additionally, elide very long file names (the max width is the width + // available for the label). + const int available_width = fixed_width() - + box_layout->inside_border_insets().width() - + icon->GetPreferredSize().width() - icon_margin; + std::transform(file_paths.begin(), + file_paths.begin() + displayed_file_name_count, + std::back_inserter(file_names), + [available_width](const base::FilePath& file_path) { + // Use slightly less than the available width since some + // space is needed for the separator. + return gfx::ElideFilename(file_path.BaseName(), + views::Label::GetDefaultFontList(), + 0.95 * available_width); + }); + if (file_paths.size() > displayed_file_name_count) + file_names.emplace_back(std::u16string(gfx::kEllipsisUTF16)); + + auto* files_label = + files_view->AddChildView(std::make_unique<views::Label>(base::JoinString( + file_names, l10n_util::GetStringUTF16( + IDS_WEB_APP_FILE_HANDLING_LIST_SEPARATOR)))); + files_label->SetMultiLine(true); + files_label->SetMaximumWidth(available_width); + files_label->SetHorizontalAlignment(gfx::HorizontalAlignment::ALIGN_LEFT); + + // Permanency checkbox. + bool multiple_associations = false; + std::u16string associations = + web_app::GetFileTypeAssociationsHandledByWebAppsForDisplay( + Profile::FromBrowserContext(web_contents->GetBrowserContext()), + app_url, &multiple_associations); + checkbox->SetText(l10n_util::GetStringFUTF16( + multiple_associations + ? IDS_WEB_APP_FILE_HANDLING_PERMISSION_STICKY_CHOICE_MULTIPLE + : IDS_WEB_APP_FILE_HANDLING_PERMISSION_STICKY_CHOICE, + associations)); + checkbox->SetMultiLine(true); + checkbox_ = AddChildView(std::move(checkbox)); + + // Dialog buttons. + SetButtonLabel(ui::DIALOG_BUTTON_OK, + l10n_util::GetStringUTF16(IDS_PERMISSION_ALLOW)); + SetButtonLabel(ui::DIALOG_BUTTON_CANCEL, + l10n_util::GetStringUTF16( + IDS_WEB_APP_FILE_HANDLING_PERMISSION_DONT_ALLOW)); + SetDefaultButton(ui::DIALOG_BUTTON_NONE); SetAcceptCallback( base::BindOnce(&FileHandlingPermissionRequestDialog::OnDialogAccepted, base::Unretained(this))); @@ -50,36 +143,6 @@ base::BindOnce(&FileHandlingPermissionRequestDialog::OnDialogCanceled, base::Unretained(this))); - ChromeLayoutProvider* layout_provider = ChromeLayoutProvider::Get(); - SetLayoutManager(std::make_unique<views::BoxLayout>( - views::BoxLayout::Orientation::kVertical, - layout_provider->GetDialogInsetsForContentType( - views::DialogContentType::kControl, - views::DialogContentType::kControl), - layout_provider->GetDistanceMetric( - views::DISTANCE_RELATED_CONTROL_VERTICAL))); - - std::vector<std::u16string> file_names; - file_names.reserve(file_paths.size()); - std::transform(file_paths.begin(), file_paths.end(), - std::back_inserter(file_names), - [](const base::FilePath& file_path) { - return file_path.LossyDisplayName(); - }); - AddChildView(std::make_unique<views::Label>( - u"<image> Open " + base::JoinString(file_names, u", "))) - ->SetHorizontalAlignment(gfx::ALIGN_LEFT); - - std::u16string checkbox_label = - u"Don't ask again when opening these file formats in this app: " + - web_app::GetFileTypeAssociationsHandledByWebAppsForDisplay( - Profile::FromBrowserContext(web_contents->GetBrowserContext()), - app_url); - - checkbox_ = AddChildView(std::make_unique<views::Checkbox>(checkbox_label)); - checkbox_->SetChecked(true); - checkbox_->SetMultiLine(true); - chrome::RecordDialogCreation( chrome::DialogIdentifier::FILE_HANDLING_PERMISSION_REQUEST); }
diff --git a/chrome/browser/ui/views/send_tab_to_self/send_tab_to_self_toolbar_bubble_view.cc b/chrome/browser/ui/views/send_tab_to_self/send_tab_to_self_toolbar_bubble_view.cc index 112983bbd..c848ebb4 100644 --- a/chrome/browser/ui/views/send_tab_to_self/send_tab_to_self_toolbar_bubble_view.cc +++ b/chrome/browser/ui/views/send_tab_to_self/send_tab_to_self_toolbar_bubble_view.cc
@@ -58,7 +58,7 @@ base::Unretained(this))); set_fixed_width(views::LayoutProvider::Get()->GetDistanceMetric( views::DISTANCE_BUBBLE_PREFERRED_WIDTH)); - set_close_on_deactivate(true); + set_close_on_deactivate(false); SetLayoutManager(std::make_unique<views::FlexLayout>()) ->SetOrientation(views::LayoutOrientation::kVertical)
diff --git a/chrome/browser/ui/web_applications/web_app_browser_controller.cc b/chrome/browser/ui/web_applications/web_app_browser_controller.cc index 9f5e92d3..93bd9717 100644 --- a/chrome/browser/ui/web_applications/web_app_browser_controller.cc +++ b/chrome/browser/ui/web_applications/web_app_browser_controller.cc
@@ -66,9 +66,6 @@ } bool WebAppBrowserController::AppUsesWindowControlsOverlay() const { - if (!base::FeatureList::IsEnabled(features::kWebAppWindowControlsOverlay)) - return false; - DisplayMode display = registrar().GetAppEffectiveDisplayMode(GetAppId()); return display == DisplayMode::kWindowControlsOverlay; }
diff --git a/chrome/browser/ui/web_applications/web_app_file_handling_browsertest.cc b/chrome/browser/ui/web_applications/web_app_file_handling_browsertest.cc index 3c0a158..4004798 100644 --- a/chrome/browser/ui/web_applications/web_app_file_handling_browsertest.cc +++ b/chrome/browser/ui/web_applications/web_app_file_handling_browsertest.cc
@@ -558,6 +558,12 @@ EXPECT_EQ(CONTENT_SETTING_ALLOW, map->GetContentSetting(origin, origin, ContentSettingsType::FILE_HANDLING)); + // Tangentially: make sure the outparam for + // `GetFileTypeAssociationsHandledByWebAppsForDisplay` is properly set. + bool plural = false; + GetFileTypeAssociationsHandledByWebAppsForDisplay(profile(), + GetSecureAppURL(), &plural); + EXPECT_TRUE(plural); // Install a second app, which is on the same origin and asks to handle more // file types. The permission should have been set back to ASK. @@ -583,6 +589,12 @@ EXPECT_EQ(CONTENT_SETTING_ASK, map->GetContentSetting(third_app_origin, third_app_origin, ContentSettingsType::FILE_HANDLING)); + // Tangentially: make sure the outparam for + // `GetFileTypeAssociationsHandledByWebAppsForDisplay` is properly set. + GetFileTypeAssociationsHandledByWebAppsForDisplay(profile(), third_app_url, + &plural); + EXPECT_FALSE(plural); + // Install a fourth app, which is on the same origin but asks for a subset of // the file types of the first two. This should have no effect on the // permission.
diff --git a/chrome/browser/ui/webui/ntp/new_tab_ui.cc b/chrome/browser/ui/webui/ntp/new_tab_ui.cc index 3644800..e2027c0 100644 --- a/chrome/browser/ui/webui/ntp/new_tab_ui.cc +++ b/chrome/browser/ui/webui/ntp/new_tab_ui.cc
@@ -164,11 +164,16 @@ return; } + // Sometimes the |profile_| is the parent (non-incognito) version of the user + // so we check the |web_contents| if it is provided. content::WebContents* web_contents = wc_getter.Run(); - content::RenderProcessHost* render_host = - web_contents ? web_contents->GetMainFrame()->GetProcess() : nullptr; + Profile* profile_for_window_type = + web_contents + ? Profile::FromBrowserContext(web_contents->GetBrowserContext()) + : profile_; + NTPResourceCache::WindowType win_type = - NTPResourceCache::GetWindowType(profile_, render_host); + NTPResourceCache::GetWindowType(profile_for_window_type); scoped_refptr<base::RefCountedMemory> html_bytes( NTPResourceCacheFactory::GetForProfile(profile_)->GetNewTabHTML( win_type));
diff --git a/chrome/browser/ui/webui/ntp/ntp_resource_cache.cc b/chrome/browser/ui/webui/ntp/ntp_resource_cache.cc index 555e636..8e1752d0 100644 --- a/chrome/browser/ui/webui/ntp/ntp_resource_cache.cc +++ b/chrome/browser/ui/webui/ntp/ntp_resource_cache.cc
@@ -153,17 +153,9 @@ NTPResourceCache::~NTPResourceCache() = default; -NTPResourceCache::WindowType NTPResourceCache::GetWindowType( - Profile* profile, - content::RenderProcessHost* render_host) { +NTPResourceCache::WindowType NTPResourceCache::GetWindowType(Profile* profile) { if (profile->IsGuestSession()) return GUEST; - - // Sometimes the |profile| is the parent (non-incognito) version of the user - // so we check the |render_host| if it is provided. - if (render_host && render_host->GetBrowserContext()->IsOffTheRecord()) - profile = Profile::FromBrowserContext(render_host->GetBrowserContext()); - if (profile->IsIncognitoProfile()) return INCOGNITO; if (profile->IsOffTheRecord())
diff --git a/chrome/browser/ui/webui/ntp/ntp_resource_cache.h b/chrome/browser/ui/webui/ntp/ntp_resource_cache.h index e98ab91..56592f2d 100644 --- a/chrome/browser/ui/webui/ntp/ntp_resource_cache.h +++ b/chrome/browser/ui/webui/ntp/ntp_resource_cache.h
@@ -27,10 +27,6 @@ class Value; } // namespace base -namespace content { -class RenderProcessHost; -} - namespace policy { class PolicyChangeRegistrar; } @@ -75,8 +71,7 @@ // ThemeServiceObserver: void OnThemeChanged() override; - static WindowType GetWindowType(Profile* profile, - content::RenderProcessHost* render_host); + static WindowType GetWindowType(Profile* profile); private: // KeyedService:
diff --git a/chrome/browser/ui/webui/read_later/read_later_ui.cc b/chrome/browser/ui/webui/read_later/read_later_ui.cc index 2e6f5b6..80abc39c 100644 --- a/chrome/browser/ui/webui/read_later/read_later_ui.cc +++ b/chrome/browser/ui/webui/read_later/read_later_ui.cc
@@ -109,5 +109,5 @@ void ReadLaterUI::CreateBookmarksPageHandler( mojo::PendingReceiver<side_panel::mojom::BookmarksPageHandler> receiver) { bookmarks_page_handler_ = - std::make_unique<BookmarksPageHandler>(std::move(receiver)); + std::make_unique<BookmarksPageHandler>(std::move(receiver), this); }
diff --git a/chrome/browser/ui/webui/read_later/side_panel/BUILD.gn b/chrome/browser/ui/webui/read_later/side_panel/BUILD.gn index d08630c..e1195ee 100644 --- a/chrome/browser/ui/webui/read_later/side_panel/BUILD.gn +++ b/chrome/browser/ui/webui/read_later/side_panel/BUILD.gn
@@ -9,6 +9,7 @@ webui_module_path = "/" public_deps = [ "//mojo/public/mojom/base", + "//ui/gfx/geometry/mojom", "//url/mojom:url_mojom_gurl", ] }
diff --git a/chrome/browser/ui/webui/read_later/side_panel/bookmarks.mojom b/chrome/browser/ui/webui/read_later/side_panel/bookmarks.mojom index 38c0262..9dcf7a7 100644 --- a/chrome/browser/ui/webui/read_later/side_panel/bookmarks.mojom +++ b/chrome/browser/ui/webui/read_later/side_panel/bookmarks.mojom
@@ -4,6 +4,7 @@ module side_panel.mojom; +import "ui/gfx/geometry/mojom/geometry.mojom"; import "url/mojom/url.mojom"; // Used by the Read Later WebUI page (for the side panel) to bootstrap @@ -17,4 +18,9 @@ interface BookmarksPageHandler { // Opens a bookmark by URL. OpenBookmark(url.mojom.Url url); + + // Opens a context menu for a bookmark node. The id parameter is internally + // an int64 but gets passed as a string from the chrome.bookmarks Extension + // API. + ShowContextMenu(string id, gfx.mojom.Point point); };
diff --git a/chrome/browser/ui/webui/read_later/side_panel/bookmarks_page_handler.cc b/chrome/browser/ui/webui/read_later/side_panel/bookmarks_page_handler.cc index cde023e..a8b60ab8 100644 --- a/chrome/browser/ui/webui/read_later/side_panel/bookmarks_page_handler.cc +++ b/chrome/browser/ui/webui/read_later/side_panel/bookmarks_page_handler.cc
@@ -4,13 +4,138 @@ #include "chrome/browser/ui/webui/read_later/side_panel/bookmarks_page_handler.h" +#include "chrome/app/chrome_command_ids.h" +#include "chrome/browser/bookmarks/bookmark_model_factory.h" +#include "chrome/browser/prefs/incognito_mode_prefs.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/bookmarks/bookmark_editor.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_finder.h" +#include "chrome/browser/ui/browser_navigator.h" +#include "chrome/browser/ui/browser_window.h" +#include "chrome/browser/ui/chrome_pages.h" #include "chrome/browser/ui/webui/read_later/read_later_ui.h" +#include "chrome/grit/generated_resources.h" +#include "components/bookmarks/browser/bookmark_model.h" +#include "components/bookmarks/browser/bookmark_node.h" +#include "components/bookmarks/browser/bookmark_utils.h" +#include "components/bookmarks/common/bookmark_pref_names.h" +#include "components/strings/grit/components_strings.h" +#include "ui/base/models/simple_menu_model.h" + +namespace { + +class BookmarkContextMenu : public ui::SimpleMenuModel, + public ui::SimpleMenuModel::Delegate { + public: + explicit BookmarkContextMenu(Browser* browser, + bookmarks::BookmarkModel* bookmark_model, + const bookmarks::BookmarkNode* bookmark) + : ui::SimpleMenuModel(this), + browser_(browser), + bookmark_model_(bookmark_model), + bookmark_(bookmark) { + AddItemWithStringId(IDC_CONTENT_CONTEXT_OPENLINKNEWTAB, + IDS_BOOKMARK_BAR_OPEN_IN_NEW_TAB); + AddItemWithStringId(IDC_CONTENT_CONTEXT_OPENLINKNEWWINDOW, + IDS_BOOKMARK_BAR_OPEN_IN_NEW_WINDOW); + AddItemWithStringId(IDC_CONTENT_CONTEXT_OPENLINKOFFTHERECORD, + IDS_BOOKMARK_BAR_OPEN_INCOGNITO); + AddSeparator(ui::NORMAL_SEPARATOR); + + AddItemWithStringId(IDC_BOOKMARK_BAR_EDIT, IDS_BOOKMARK_BAR_EDIT); + AddItemWithStringId(IDC_BOOKMARK_BAR_REMOVE, IDS_BOOKMARK_BAR_REMOVE); + AddSeparator(ui::NORMAL_SEPARATOR); + + AddItemWithStringId(IDC_BOOKMARK_MANAGER, IDS_BOOKMARK_MANAGER); + } + ~BookmarkContextMenu() override = default; + + void ExecuteCommand(int command_id, int event_flags) override { + switch (command_id) { + case IDC_CONTENT_CONTEXT_OPENLINKNEWTAB: { + content::OpenURLParams params(bookmark_->url(), content::Referrer(), + WindowOpenDisposition::NEW_FOREGROUND_TAB, + ui::PAGE_TRANSITION_AUTO_BOOKMARK, false); + browser_->OpenURL(params); + break; + } + + case IDC_CONTENT_CONTEXT_OPENLINKNEWWINDOW: { + content::OpenURLParams params(bookmark_->url(), content::Referrer(), + WindowOpenDisposition::NEW_WINDOW, + ui::PAGE_TRANSITION_AUTO_BOOKMARK, false); + browser_->OpenURL(params); + break; + } + + case IDC_CONTENT_CONTEXT_OPENLINKOFFTHERECORD: { + content::OpenURLParams params(bookmark_->url(), content::Referrer(), + WindowOpenDisposition::OFF_THE_RECORD, + ui::PAGE_TRANSITION_AUTO_BOOKMARK, false); + browser_->OpenURL(params); + break; + } + + case IDC_BOOKMARK_BAR_EDIT: + BookmarkEditor::Show(browser_->window()->GetNativeWindow(), + browser_->profile(), + BookmarkEditor::EditDetails::EditNode(bookmark_), + BookmarkEditor::SHOW_TREE); + break; + + case IDC_BOOKMARK_BAR_REMOVE: + bookmark_model_->Remove(bookmark_); + break; + + case IDC_BOOKMARK_MANAGER: + if (bookmark_->parent()) { + chrome::ShowBookmarkManagerForNode(browser_, + bookmark_->parent()->id()); + } else { + chrome::ShowBookmarkManager(browser_); + } + break; + + default: + NOTREACHED(); + break; + } + } + + bool IsCommandIdEnabled(int command_id) const override { + PrefService* prefs = browser_->profile()->GetPrefs(); + switch (command_id) { + case IDC_CONTENT_CONTEXT_OPENLINKOFFTHERECORD: { + IncognitoModePrefs::Availability incognito_pref = + IncognitoModePrefs::GetAvailability(prefs); + return !browser_->profile()->IsOffTheRecord() && + incognito_pref != IncognitoModePrefs::DISABLED && + IsURLAllowedInIncognito(bookmark_->url(), browser_->profile()); + } + + case IDC_BOOKMARK_BAR_EDIT: + case IDC_BOOKMARK_BAR_REMOVE: { + return prefs->GetBoolean(bookmarks::prefs::kEditBookmarksEnabled) && + bookmark_model_->client()->CanBeEditedByUser(bookmark_); + } + } + + return true; + } + + private: + Browser* const browser_; + bookmarks::BookmarkModel* bookmark_model_; + const bookmarks::BookmarkNode* bookmark_; +}; + +} // namespace BookmarksPageHandler::BookmarksPageHandler( - mojo::PendingReceiver<side_panel::mojom::BookmarksPageHandler> receiver) - : receiver_(this, std::move(receiver)) {} + mojo::PendingReceiver<side_panel::mojom::BookmarksPageHandler> receiver, + ReadLaterUI* read_later_ui) + : receiver_(this, std::move(receiver)), read_later_ui_(read_later_ui) {} BookmarksPageHandler::~BookmarksPageHandler() = default; @@ -24,3 +149,26 @@ ui::PAGE_TRANSITION_AUTO_BOOKMARK, false); browser->OpenURL(params); } + +void BookmarksPageHandler::ShowContextMenu(const std::string& id_string, + const gfx::Point& point) { + int64_t id; + if (!base::StringToInt64(id_string, &id)) + return; + + Browser* browser = chrome::FindLastActive(); + if (!browser) + return; + + bookmarks::BookmarkModel* bookmark_model = + BookmarkModelFactory::GetForBrowserContext(browser->profile()); + const bookmarks::BookmarkNode* bookmark = + bookmarks::GetBookmarkNodeByID(bookmark_model, id); + if (!bookmark) + return; + auto embedder = read_later_ui_->embedder(); + if (embedder) { + embedder->ShowContextMenu(point, std::make_unique<BookmarkContextMenu>( + browser, bookmark_model, bookmark)); + } +}
diff --git a/chrome/browser/ui/webui/read_later/side_panel/bookmarks_page_handler.h b/chrome/browser/ui/webui/read_later/side_panel/bookmarks_page_handler.h index 7760595..b0b6731 100644 --- a/chrome/browser/ui/webui/read_later/side_panel/bookmarks_page_handler.h +++ b/chrome/browser/ui/webui/read_later/side_panel/bookmarks_page_handler.h
@@ -10,20 +10,24 @@ #include "mojo/public/cpp/bindings/receiver.h" class GURL; +class ReadLaterUI; class BookmarksPageHandler : public side_panel::mojom::BookmarksPageHandler { public: explicit BookmarksPageHandler( - mojo::PendingReceiver<side_panel::mojom::BookmarksPageHandler> receiver); + mojo::PendingReceiver<side_panel::mojom::BookmarksPageHandler> receiver, + ReadLaterUI* read_later_ui); BookmarksPageHandler(const BookmarksPageHandler&) = delete; BookmarksPageHandler& operator=(const BookmarksPageHandler&) = delete; ~BookmarksPageHandler() override; // side_panel::mojom::BookmarksPageHandler: void OpenBookmark(const GURL& url) override; + void ShowContextMenu(const std::string& id, const gfx::Point& point) override; private: mojo::Receiver<side_panel::mojom::BookmarksPageHandler> receiver_; + ReadLaterUI* const read_later_ui_; }; #endif // CHROME_BROWSER_UI_WEBUI_READ_LATER_SIDE_PANEL_BOOKMARKS_PAGE_HANDLER_H_
diff --git a/chrome/browser/ui/webui/settings/chromeos/accessibility_handler.cc b/chrome/browser/ui/webui/settings/chromeos/accessibility_handler.cc index 007bd04d..0b9418c 100644 --- a/chrome/browser/ui/webui/settings/chromeos/accessibility_handler.cc +++ b/chrome/browser/ui/webui/settings/chromeos/accessibility_handler.cc
@@ -4,20 +4,29 @@ #include "chrome/browser/ui/webui/settings/chromeos/accessibility_handler.h" +#include <set> + #include "base/bind.h" #include "base/callback_helpers.h" +#include "base/containers/flat_map.h" #include "base/metrics/histogram_functions.h" #include "chrome/browser/ash/accessibility/accessibility_manager.h" +#include "chrome/browser/ash/accessibility/dictation.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/extensions/extension_tab_util.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser_finder.h" #include "chrome/common/extensions/extension_constants.h" #include "chrome/grit/generated_resources.h" +#include "components/language/core/browser/pref_names.h" +#include "components/language/core/common/locale_util.h" +#include "components/prefs/pref_service.h" #include "content/public/browser/web_ui.h" #include "extensions/browser/extension_registry.h" #include "extensions/common/constants.h" #include "ui/accessibility/accessibility_features.h" +#include "ui/base/ime/chromeos/input_method_manager.h" +#include "ui/base/ime/chromeos/input_method_util.h" #include "ui/base/l10n/l10n_util.h" namespace chromeos { @@ -115,6 +124,7 @@ base::Value(AccessibilityManager::Get()->GetStartupSoundEnabled())); MaybeAddSodaInstallerObserver(); + MaybeAddDictationLocales(); } void AccessibilityHandler::HandleShowChromeVoxTutorial( @@ -134,6 +144,8 @@ } void AccessibilityHandler::MaybeAddSodaInstallerObserver() { + // TODO(crbug.com/1195916): Don't display SODA status if the Dictation + // language is not a downloaded or available SODA language. if (features::IsExperimentalAccessibilityDictationOfflineEnabled()) { if (speech::SodaInstaller::GetInstance()->IsSodaInstalled()) OnSodaInstalled(); @@ -166,5 +178,65 @@ IDS_SETTINGS_ACCESSIBILITY_DICTATION_SUBTITLE_SODA_DOWNLOAD_ERROR))); } +void AccessibilityHandler::MaybeAddDictationLocales() { + if (!features::IsExperimentalAccessibilityDictationOfflineEnabled()) + return; + + base::flat_map<std::string, bool> locales = + ash::Dictation::GetAllSupportedLocales(); + + // Get application locale. + std::string application_locale = g_browser_process->GetApplicationLocale(); + std::pair<base::StringPiece, base::StringPiece> application_lang_and_locale = + language::SplitIntoMainAndTail(application_locale); + + // Get IME locales + input_method::InputMethodManager* ime_manager = + input_method::InputMethodManager::Get(); + std::vector<std::string> input_method_ids = + ime_manager->GetActiveIMEState()->GetActiveInputMethodIds(); + std::vector<std::string> ime_languages; + ime_manager->GetInputMethodUtil()->GetLanguageCodesFromInputMethodIds( + input_method_ids, &ime_languages); + + // Get enabled preferred UI languages. + std::string preferred_languages = + profile_->GetPrefs()->GetString(language::prefs::kPreferredLanguages); + std::vector<base::StringPiece> enabled_languages = + base::SplitStringPiece(preferred_languages, ",", base::TRIM_WHITESPACE, + base::SPLIT_WANT_NONEMPTY); + + // Combine these into one set for recommending Dication languages. + std::set<base::StringPiece> ui_languages; + ui_languages.insert(application_lang_and_locale.first); + for (auto& ime_language : ime_languages) { + ui_languages.insert(language::SplitIntoMainAndTail(ime_language).first); + } + for (auto& enabled_language : enabled_languages) { + ui_languages.insert(language::SplitIntoMainAndTail(enabled_language).first); + } + + base::Value locales_list(base::Value::Type::LIST); + for (auto& locale : locales) { + base::Value option(base::Value::Type::DICTIONARY); + option.SetKey("value", base::Value(locale.first)); + option.SetKey("name", + base::Value(l10n_util::GetDisplayNameForLocale( + locale.first, application_locale, /*is_for_ui=*/true))); + option.SetKey("offline", base::Value(locale.second)); + + // We can recommend languages that match the current application + // locale, IME languages or enabled preferred languages. + std::pair<base::StringPiece, base::StringPiece> lang_and_locale = + language::SplitIntoMainAndTail(locale.first); + bool is_recommended = base::Contains(ui_languages, lang_and_locale.first); + + option.SetKey("recommended", base::Value(is_recommended)); + locales_list.Append(std::move(option)); + } + + FireWebUIListener("dictation-locales-set", locales_list); +} + } // namespace settings } // namespace chromeos
diff --git a/chrome/browser/ui/webui/settings/chromeos/accessibility_handler.h b/chrome/browser/ui/webui/settings/chromeos/accessibility_handler.h index f778cfe3..39294c72 100644 --- a/chrome/browser/ui/webui/settings/chromeos/accessibility_handler.h +++ b/chrome/browser/ui/webui/settings/chromeos/accessibility_handler.h
@@ -60,6 +60,8 @@ void OnSodaError() override; void OnSodaLanguagePackError(speech::LanguageCode language_code) override {} + void MaybeAddDictationLocales(); + Profile* profile_; // Weak pointer. // Timer to record user changed value for the accessibility setting to turn
diff --git a/chrome/browser/ui/webui/settings/chromeos/accessibility_handler_browsertest.cc b/chrome/browser/ui/webui/settings/chromeos/accessibility_handler_browsertest.cc index d149b98..eb8043f 100644 --- a/chrome/browser/ui/webui/settings/chromeos/accessibility_handler_browsertest.cc +++ b/chrome/browser/ui/webui/settings/chromeos/accessibility_handler_browsertest.cc
@@ -5,13 +5,27 @@ #include "chrome/browser/ui/webui/settings/chromeos/accessibility_handler.h" #include <memory> +#include <set> +#include "chrome/browser/browser_process.h" +#include "chrome/browser/chromeos/input_method/mock_input_method_engine.h" +#include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/ui/browser.h" #include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/testing_profile.h" +#include "components/language/core/browser/pref_names.h" +#include "components/language/core/common/locale_util.h" +#include "components/prefs/pref_service.h" #include "content/public/test/browser_test.h" #include "content/public/test/test_web_ui.h" +#include "testing/gmock/include/gmock/gmock.h" #include "ui/accessibility/accessibility_features.h" +#include "ui/base/ime/chromeos/input_method_descriptor.h" +#include "ui/base/ime/chromeos/input_method_manager.h" +#include "ui/base/ime/chromeos/input_method_util.h" + +using ::testing::Contains; +using ::testing::Not; namespace chromeos { namespace settings { @@ -25,7 +39,8 @@ class AccessibilityHandlerTest : public InProcessBrowserTest { public: - AccessibilityHandlerTest() = default; + AccessibilityHandlerTest() + : mock_ime_engine_handler_(std::make_unique<MockInputMethodEngine>()) {} AccessibilityHandlerTest(const AccessibilityHandlerTest&) = delete; AccessibilityHandlerTest& operator=(const AccessibilityHandlerTest&) = delete; ~AccessibilityHandlerTest() override = default; @@ -74,6 +89,24 @@ return false; } + bool GetWebUIListenerArgumentListValue(const std::string& expected_listener, + const base::ListValue** argument) { + for (auto it = web_ui_.call_data().rbegin(); + it != web_ui_.call_data().rend(); ++it) { + const content::TestWebUI::CallData* data = it->get(); + std::string listener; + data->arg1()->GetAsString(&listener); + if (data->function_name() == "cr.webUIListenerCallback" && + listener == expected_listener) { + if (!data->arg2()->GetAsList(argument)) + return false; + return true; + } + } + + return false; + } + void AddSodaInstallerObserver() { handler_->MaybeAddSodaInstallerObserver(); } void OnSodaInstalled() { handler_->OnSodaInstalled(); } @@ -82,6 +115,10 @@ void OnSodaError() { handler_->OnSodaError(); } + void MaybeAddDictationLocales() { handler_->MaybeAddDictationLocales(); } + + std::unique_ptr<MockInputMethodEngine> mock_ime_engine_handler_; + private: std::unique_ptr<TestingProfile> profile_; std::unique_ptr<TestAccessibilityHandler> handler_; @@ -133,5 +170,77 @@ "dictation-setting-subtitle-changed", "Speech files downloaded")); } +IN_PROC_BROWSER_TEST_F(AccessibilityHandlerTest, DictationLocalesCalculation) { + input_method::InputMethodManager* ime_manager = + input_method::InputMethodManager::Get(); + + struct { + std::string application_locale; + std::vector<std::string> ime_locales; + std::string preferred_languages; + std::set<base::StringPiece> expected_recommended_prefixes; + } kTestCases[] = { + {"en-US", {}, "", {"en"}}, + {"en", {}, "", {"en"}}, + {"fr", {}, "", {"fr"}}, + {"en", {"en", "en-US"}, "", {"en"}}, + {"en", {"en", "en-US"}, "en", {"en"}}, + {"en", {"en", "es"}, "", {"en", "es"}}, + {"en", {"fr", "es", "fr-FR"}, "", {"en", "es", "fr"}}, + {"it-IT", {"ar", "is-IS", "uk"}, "", {"it", "ar", "is", "uk"}}, + {"en", {"fr", "es", "fr-FR"}, "en-US,it-IT", {"en", "es", "fr", "it"}}, + {"en", {}, "en-US,it-IT,uk", {"en", "it", "uk"}}, + }; + for (const auto& testcase : kTestCases) { + // Set application locale. + g_browser_process->SetApplicationLocale(testcase.application_locale); + + // Set up fake IMEs. + auto state = + ime_manager->CreateNewState(ProfileManager::GetActiveUserProfile()); + ime_manager->SetState(state); + input_method::InputMethodDescriptors imes; + for (auto& locale : testcase.ime_locales) { + std::string id = "fake-ime-extension-" + locale; + input_method::InputMethodDescriptor descriptor(id, locale, std::string(), + std::string(), {locale}, + false, GURL(), GURL()); + imes.push_back(descriptor); + } + ime_manager->GetInputMethodUtil()->ResetInputMethods(imes); + + for (auto& descriptor : imes) { + state->AddInputMethodExtension(descriptor.id(), {descriptor}, + mock_ime_engine_handler_.get()); + ASSERT_TRUE(state->EnableInputMethod(descriptor.id())); + } + + // Set up fake preferred languages. + browser()->profile()->GetPrefs()->SetString( + language::prefs::kPreferredLanguages, testcase.preferred_languages); + + MaybeAddDictationLocales(); + + const base::ListValue* argument; + ASSERT_TRUE( + GetWebUIListenerArgumentListValue("dictation-locales-set", &argument)); + for (auto& it : argument->GetList()) { + const base::DictionaryValue* dict = &base::Value::AsDictionaryValue(it); + base::StringPiece language_code = + language::SplitIntoMainAndTail(*(dict->FindStringPath("value"))) + .first; + // Only expect some locales to be recommended based on application and + // IME languages. + if (*(dict->FindBoolPath("recommended"))) { + EXPECT_THAT(testcase.expected_recommended_prefixes, + Contains(language_code)); + } else { + EXPECT_THAT(testcase.expected_recommended_prefixes, + Not(Contains(language_code))); + } + } + } +} + } // namespace settings } // namespace chromeos
diff --git a/chrome/browser/ui/webui/settings/chromeos/accessibility_section.cc b/chrome/browser/ui/webui/settings/chromeos/accessibility_section.cc index d9a8a83..0529101d 100644 --- a/chrome/browser/ui/webui/settings/chromeos/accessibility_section.cc +++ b/chrome/browser/ui/webui/settings/chromeos/accessibility_section.cc
@@ -360,6 +360,10 @@ ash::TabletMode::IsBoardTypeMarkedAsTabletCapable(); } +bool AreDictationLocalePrefsAllowed() { + return ::features::IsExperimentalAccessibilityDictationOfflineEnabled(); +} + } // namespace AccessibilitySection::AccessibilitySection( @@ -498,6 +502,12 @@ {"dictationDescription", IDS_SETTINGS_ACCESSIBILITY_DICTATION_DESCRIPTION}, {"dictationLabel", IDS_SETTINGS_ACCESSIBILITY_DICTATION_LABEL}, + {"dictationLocaleMenuLabel", + IDS_SETTINGS_ACCESSIBILITY_DICTATION_LOCALE_MENU_LABEL}, + {"dictationLocaleSubLabelOffline", + IDS_SETTINGS_ACCESSIBILITY_DICTATION_LOCALE_SUB_LABEL_OFFLINE}, + {"dictationLocaleSubLabelNetwork", + IDS_SETTINGS_ACCESSIBILITY_DICTATION_LOCALE_SUB_LABEL_NETWORK}, {"onScreenKeyboardLabel", IDS_SETTINGS_ON_SCREEN_KEYBOARD_LABEL}, {"monoAudioLabel", IDS_SETTINGS_MONO_AUDIO_LABEL}, {"startupSoundLabel", IDS_SETTINGS_STARTUP_SOUND_LABEL}, @@ -757,6 +767,9 @@ "isMagnifierContinuousMouseFollowingModeSettingEnabled", IsMagnifierContinuousMouseFollowingModeSettingEnabled()); + html_source->AddBoolean("areDictationLocalePrefsAllowed", + AreDictationLocalePrefsAllowed()); + ::settings::AddCaptionSubpageStrings(html_source); }
diff --git a/chrome/browser/ui/webui/theme_source.cc b/chrome/browser/ui/webui/theme_source.cc index 3715fd43..4872b19 100644 --- a/chrome/browser/ui/webui/theme_source.cc +++ b/chrome/browser/ui/webui/theme_source.cc
@@ -91,7 +91,7 @@ if (IsNewTabCssPath(parsed_path)) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); NTPResourceCache::WindowType type = - NTPResourceCache::GetWindowType(profile_, /*render_host=*/nullptr); + NTPResourceCache::GetWindowType(profile_); NTPResourceCache* cache = NTPResourceCacheFactory::GetForProfile(profile_); std::move(callback).Run(cache->GetNewTabCSS(type, wc_getter)); return;
diff --git a/chrome/browser/video_tutorials/internal/android/java/src/org/chromium/chrome/browser/video_tutorials/iph/VideoIPHTest.java b/chrome/browser/video_tutorials/internal/android/java/src/org/chromium/chrome/browser/video_tutorials/iph/VideoIPHTest.java index 172b38e..018df84 100644 --- a/chrome/browser/video_tutorials/internal/android/java/src/org/chromium/chrome/browser/video_tutorials/iph/VideoIPHTest.java +++ b/chrome/browser/video_tutorials/internal/android/java/src/org/chromium/chrome/browser/video_tutorials/iph/VideoIPHTest.java
@@ -28,7 +28,6 @@ import org.mockito.MockitoAnnotations; import org.chromium.base.Callback; -import org.chromium.base.test.BaseActivityTestRule; import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.video_tutorials.FeatureType; import org.chromium.chrome.browser.video_tutorials.R; @@ -37,6 +36,7 @@ import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.ui.test.util.DummyUiActivity; +import org.chromium.ui.test.util.ThemedDummyUiActivityTestRule; import java.util.HashMap; @@ -46,8 +46,8 @@ @RunWith(ChromeJUnit4ClassRunner.class) public class VideoIPHTest { @Rule - public BaseActivityTestRule<DummyUiActivity> mActivityTestRule = - new BaseActivityTestRule<>(DummyUiActivity.class); + public ThemedDummyUiActivityTestRule<DummyUiActivity> mActivityTestRule = + new ThemedDummyUiActivityTestRule<>(DummyUiActivity.class, R.style.ColorOverlay); private Activity mActivity; private VideoIPHCoordinator mCoordinator;
diff --git a/chrome/browser/video_tutorials/internal/android/java/src/org/chromium/chrome/browser/video_tutorials/languages/LanguagePickerTest.java b/chrome/browser/video_tutorials/internal/android/java/src/org/chromium/chrome/browser/video_tutorials/languages/LanguagePickerTest.java index e818d80..65f77e3a 100644 --- a/chrome/browser/video_tutorials/internal/android/java/src/org/chromium/chrome/browser/video_tutorials/languages/LanguagePickerTest.java +++ b/chrome/browser/video_tutorials/internal/android/java/src/org/chromium/chrome/browser/video_tutorials/languages/LanguagePickerTest.java
@@ -25,7 +25,6 @@ import org.mockito.Mockito; import org.mockito.MockitoAnnotations; -import org.chromium.base.test.BaseActivityTestRule; import org.chromium.chrome.browser.video_tutorials.FeatureType; import org.chromium.chrome.browser.video_tutorials.LanguageInfoProvider; import org.chromium.chrome.browser.video_tutorials.R; @@ -34,6 +33,7 @@ import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.ui.test.util.DummyUiActivity; +import org.chromium.ui.test.util.ThemedDummyUiActivityTestRule; /** * Tests for {@link LanguagePickerCoordinator}. @@ -41,8 +41,8 @@ @RunWith(ChromeJUnit4ClassRunner.class) public class LanguagePickerTest { @Rule - public BaseActivityTestRule<DummyUiActivity> mActivityTestRule = - new BaseActivityTestRule<>(DummyUiActivity.class); + public ThemedDummyUiActivityTestRule<DummyUiActivity> mActivityTestRule = + new ThemedDummyUiActivityTestRule<>(DummyUiActivity.class, R.style.ColorOverlay); private Activity mActivity; private View mContentView;
diff --git a/chrome/browser/video_tutorials/internal/android/java/src/org/chromium/chrome/browser/video_tutorials/list/TutorialListCoordinatorTest.java b/chrome/browser/video_tutorials/internal/android/java/src/org/chromium/chrome/browser/video_tutorials/list/TutorialListCoordinatorTest.java index 61d563fd..e42ed7d 100644 --- a/chrome/browser/video_tutorials/internal/android/java/src/org/chromium/chrome/browser/video_tutorials/list/TutorialListCoordinatorTest.java +++ b/chrome/browser/video_tutorials/internal/android/java/src/org/chromium/chrome/browser/video_tutorials/list/TutorialListCoordinatorTest.java
@@ -28,7 +28,6 @@ import org.mockito.MockitoAnnotations; import org.chromium.base.Callback; -import org.chromium.base.test.BaseActivityTestRule; import org.chromium.chrome.browser.video_tutorials.R; import org.chromium.chrome.browser.video_tutorials.Tutorial; import org.chromium.chrome.browser.video_tutorials.VideoTutorialUtils; @@ -37,6 +36,7 @@ import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.ui.test.util.DummyUiActivity; +import org.chromium.ui.test.util.ThemedDummyUiActivityTestRule; /** * Tests for {@link TutorialListCoordinator}. @@ -44,8 +44,8 @@ @RunWith(ChromeJUnit4ClassRunner.class) public class TutorialListCoordinatorTest { @Rule - public BaseActivityTestRule<DummyUiActivity> mActivityTestRule = - new BaseActivityTestRule<>(DummyUiActivity.class); + public ThemedDummyUiActivityTestRule<DummyUiActivity> mActivityTestRule = + new ThemedDummyUiActivityTestRule<>(DummyUiActivity.class, R.style.ColorOverlay); private Activity mActivity; private View mContentView;
diff --git a/chrome/browser/video_tutorials/internal/android/java/src/org/chromium/chrome/browser/video_tutorials/player/VideoPlayerViewBinderTest.java b/chrome/browser/video_tutorials/internal/android/java/src/org/chromium/chrome/browser/video_tutorials/player/VideoPlayerViewBinderTest.java index b70019dc..2ecdcbe 100644 --- a/chrome/browser/video_tutorials/internal/android/java/src/org/chromium/chrome/browser/video_tutorials/player/VideoPlayerViewBinderTest.java +++ b/chrome/browser/video_tutorials/internal/android/java/src/org/chromium/chrome/browser/video_tutorials/player/VideoPlayerViewBinderTest.java
@@ -25,7 +25,6 @@ import org.mockito.Mockito; import org.mockito.MockitoAnnotations; -import org.chromium.base.test.BaseActivityTestRule; import org.chromium.base.test.UiThreadTest; import org.chromium.base.test.util.ApplicationTestUtils; import org.chromium.chrome.browser.video_tutorials.PlaybackStateObserver.WatchStateInfo.State; @@ -36,6 +35,7 @@ import org.chromium.ui.modelutil.PropertyModel; import org.chromium.ui.modelutil.PropertyModelChangeProcessor; import org.chromium.ui.test.util.DummyUiActivity; +import org.chromium.ui.test.util.ThemedDummyUiActivityTestRule; import java.util.concurrent.atomic.AtomicBoolean; @@ -45,8 +45,8 @@ @RunWith(ChromeJUnit4ClassRunner.class) public class VideoPlayerViewBinderTest { @Rule - public BaseActivityTestRule<DummyUiActivity> mActivityTestRule = - new BaseActivityTestRule<>(DummyUiActivity.class); + public ThemedDummyUiActivityTestRule<DummyUiActivity> mActivityTestRule = + new ThemedDummyUiActivityTestRule<>(DummyUiActivity.class, R.style.ColorOverlay); private Activity mActivity; private VideoPlayerView mVideoPlayerView;
diff --git a/chrome/browser/web_applications/components/web_app_constants.cc b/chrome/browser/web_applications/components/web_app_constants.cc index f19d22ef..126ebc0 100644 --- a/chrome/browser/web_applications/components/web_app_constants.cc +++ b/chrome/browser/web_applications/components/web_app_constants.cc
@@ -32,10 +32,7 @@ case DisplayMode::kFullscreen: return DisplayMode::kStandalone; case DisplayMode::kWindowControlsOverlay: - if (base::FeatureList::IsEnabled(features::kWebAppWindowControlsOverlay)) return DisplayMode::kWindowControlsOverlay; - else - return DisplayMode::kStandalone; case DisplayMode::kTabbed: if (base::FeatureList::IsEnabled(features::kDesktopPWAsTabStrip)) return DisplayMode::kTabbed;
diff --git a/chrome/browser/web_applications/components/web_app_utils.h b/chrome/browser/web_applications/components/web_app_utils.h index 7d63b10..86b64df 100644 --- a/chrome/browser/web_applications/components/web_app_utils.h +++ b/chrome/browser/web_applications/components/web_app_utils.h
@@ -99,10 +99,13 @@ // associated via MIME types, this will return MIME types like "text/plain, // image/png". On all other platforms, where files are associated via file // extensions, this will return capitalized file extensions with the period -// truncated, like "TXT, PNG". +// truncated, like "TXT, PNG". `found_multiple`, when non-null, will be set to +// indicate whether the returned string is a list (false indicates it's a single +// object). std::u16string GetFileTypeAssociationsHandledByWebAppsForDisplay( Profile* profile, - const GURL& url); + const GURL& url, + bool* found_multiple = nullptr); } // namespace web_app
diff --git a/chrome/browser/web_applications/web_app_utils.cc b/chrome/browser/web_applications/web_app_utils.cc index 30a40643..54d9154 100644 --- a/chrome/browser/web_applications/web_app_utils.cc +++ b/chrome/browser/web_applications/web_app_utils.cc
@@ -206,7 +206,8 @@ std::u16string GetFileTypeAssociationsHandledByWebAppsForDisplay( Profile* profile, - const GURL& url) { + const GURL& url, + bool* found_multiple) { const apps::FileHandlers file_handlers = GetFileHandlersForAllWebAppsWithOrigin(profile, url); std::vector<std::string> associations; @@ -229,9 +230,12 @@ }); #endif // defined(OS_LINUX) + if (found_multiple) + *found_multiple = associations.size() > 1; + return base::UTF8ToUTF16(base::JoinString( - associations, l10n_util::GetStringUTF8( - IDS_WEB_APP_FILE_HANDLING_EXTENSION_LIST_SEPARATOR))); + associations, + l10n_util::GetStringUTF8(IDS_WEB_APP_FILE_HANDLING_LIST_SEPARATOR))); } } // namespace web_app
diff --git a/chrome/common/webui_url_constants.cc b/chrome/common/webui_url_constants.cc index a1f125da..cb975c2 100644 --- a/chrome/common/webui_url_constants.cc +++ b/chrome/common/webui_url_constants.cc
@@ -165,8 +165,6 @@ const char kChromeUISiteDetailsPrefixURL[] = "chrome://settings/content/siteDetails?site="; const char kChromeUISiteEngagementHost[] = "site-engagement"; -const char kChromeUISuggestionsHost[] = "suggestions"; -const char kChromeUISuggestionsURL[] = "chrome://suggestions/"; const char kChromeUISupervisedUserPassphrasePageHost[] = "managed-user-passphrase"; const char kChromeUISyncConfirmationHost[] = "sync-confirmation"; @@ -530,7 +528,6 @@ kChromeUISiteEngagementHost, kChromeUINTPTilesInternalsHost, safe_browsing::kChromeUISafeBrowsingHost, - kChromeUISuggestionsHost, kChromeUISyncInternalsHost, #if !defined(OS_ANDROID) kChromeUITermsHost,
diff --git a/chrome/common/webui_url_constants.h b/chrome/common/webui_url_constants.h index 91fb3ac5..74673240 100644 --- a/chrome/common/webui_url_constants.h +++ b/chrome/common/webui_url_constants.h
@@ -162,8 +162,6 @@ extern const char kChromeUISigninReauthURL[]; extern const char kChromeUISiteDetailsPrefixURL[]; extern const char kChromeUISiteEngagementHost[]; -extern const char kChromeUISuggestionsHost[]; -extern const char kChromeUISuggestionsURL[]; extern const char kChromeUISupervisedUserPassphrasePageHost[]; extern const char kChromeUISyncConfirmationHost[]; extern const char kChromeUISyncConfirmationLoadingPath[];
diff --git a/chrome/renderer/BUILD.gn b/chrome/renderer/BUILD.gn index 931e8b4..02cdf42 100644 --- a/chrome/renderer/BUILD.gn +++ b/chrome/renderer/BUILD.gn
@@ -366,8 +366,10 @@ } if (enable_pdf) { sources += [ - "chrome_pdf_view_web_plugin_print_client.cc", - "chrome_pdf_view_web_plugin_print_client.h", + "pdf/chrome_pdf_internal_plugin_delegate.cc", + "pdf/chrome_pdf_internal_plugin_delegate.h", + "pdf/chrome_pdf_view_web_plugin_print_client.cc", + "pdf/chrome_pdf_view_web_plugin_print_client.h", ] } }
diff --git a/chrome/renderer/chrome_content_renderer_client.cc b/chrome/renderer/chrome_content_renderer_client.cc index 468b9382..0246587 100644 --- a/chrome/renderer/chrome_content_renderer_client.cc +++ b/chrome/renderer/chrome_content_renderer_client.cc
@@ -207,16 +207,9 @@ #endif #if BUILDFLAG(ENABLE_PDF) +#include "chrome/renderer/pdf/chrome_pdf_internal_plugin_delegate.h" #include "components/pdf/common/internal_plugin_helpers.h" #include "components/pdf/renderer/internal_plugin_renderer_helpers.h" - -// TODO(crbug.com/1218971): Refactor this; only needed for -// `chrome_pdf::PdfViewWebPlugin::PrintClient`. -#include "pdf/pdf_view_web_plugin.h" -#if BUILDFLAG(ENABLE_PRINTING) -#include "chrome/renderer/chrome_pdf_view_web_plugin_print_client.h" -#endif // BUILDFLAG(ENABLE_PRINTING) - #endif // BUILDFLAG(ENABLE_PDF) #if BUILDFLAG(ENABLE_PLUGINS) @@ -1044,14 +1037,10 @@ #if BUILDFLAG(ENABLE_PDF) if (info.name == ASCIIToUTF16(ChromeContentClient::kPDFInternalPluginName)) { - std::unique_ptr<chrome_pdf::PdfViewWebPlugin::PrintClient> - print_client; -#if BUILDFLAG(ENABLE_PRINTING) - print_client = - std::make_unique<ChromePdfViewWebPluginPrintClient>(render_frame); -#endif // BUILDFLAG(ENABLE_PRINTING) WebPlugin* internal_pdf_plugin = pdf::MaybeCreateInternalPlugin( - render_frame, std::move(print_client), params); + render_frame, + std::make_unique<ChromePdfInternalPluginDelegate>(render_frame), + params); if (internal_pdf_plugin) return internal_pdf_plugin; }
diff --git a/chrome/renderer/chrome_render_frame_observer.cc b/chrome/renderer/chrome_render_frame_observer.cc index 08621dd..2269138 100644 --- a/chrome/renderer/chrome_render_frame_observer.cc +++ b/chrome/renderer/chrome_render_frame_observer.cc
@@ -281,11 +281,7 @@ } void ChromeRenderFrameObserver::DraggableRegionsChanged() { - // The DraggableRegion interface is bound browser side when - // kWebAppWindowControlsOverlay feature is turned on. - if (!base::FeatureList::IsEnabled(features::kWebAppWindowControlsOverlay)) - return; - +#if defined(OS_WIN) || defined(OS_MAC) || defined(OS_LINUX) // Only the main frame is allowed to control draggable regions, to avoid other // frames manipulate the regions in the browser process. if (!render_frame()->IsMainFrame()) @@ -307,6 +303,7 @@ render_frame()->GetBrowserInterfaceBroker()->GetInterface( remote.BindNewPipeAndPassReceiver()); remote->UpdateDraggableRegions(std::move(regions)); +#endif } void ChromeRenderFrameObserver::SetWindowFeatures(
diff --git a/chrome/renderer/pdf/DIR_METADATA b/chrome/renderer/pdf/DIR_METADATA new file mode 100644 index 0000000..11b8e5a --- /dev/null +++ b/chrome/renderer/pdf/DIR_METADATA
@@ -0,0 +1,3 @@ +monorail: { + component: "Internals>Plugins>PDF" +}
diff --git a/chrome/renderer/pdf/OWNERS b/chrome/renderer/pdf/OWNERS new file mode 100644 index 0000000..59c3f69 --- /dev/null +++ b/chrome/renderer/pdf/OWNERS
@@ -0,0 +1 @@ +file://pdf/OWNERS
diff --git a/chrome/renderer/pdf/chrome_pdf_internal_plugin_delegate.cc b/chrome/renderer/pdf/chrome_pdf_internal_plugin_delegate.cc new file mode 100644 index 0000000..cfb2077 --- /dev/null +++ b/chrome/renderer/pdf/chrome_pdf_internal_plugin_delegate.cc
@@ -0,0 +1,32 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/renderer/pdf/chrome_pdf_internal_plugin_delegate.h" + +#include <memory> + +#include "base/check.h" +#include "pdf/pdf_view_web_plugin.h" +#include "printing/buildflags/buildflags.h" + +#if BUILDFLAG(ENABLE_PRINTING) +#include "chrome/renderer/pdf/chrome_pdf_view_web_plugin_print_client.h" +#endif // BUILDFLAG(ENABLE_PRINTING) + +ChromePdfInternalPluginDelegate::ChromePdfInternalPluginDelegate( + content::RenderFrame* render_frame) + : render_frame_(render_frame) { + DCHECK(render_frame_); +} + +ChromePdfInternalPluginDelegate::~ChromePdfInternalPluginDelegate() = default; + +std::unique_ptr<chrome_pdf::PdfViewWebPlugin::PrintClient> +ChromePdfInternalPluginDelegate::CreatePrintClient() { +#if BUILDFLAG(ENABLE_PRINTING) + return std::make_unique<ChromePdfViewWebPluginPrintClient>(render_frame_); +#else // !BUILDFLAG(ENABLE_PRINTING) + return nullptr; +#endif // BUILDFLAG(ENABLE_PRINTING) +}
diff --git a/chrome/renderer/pdf/chrome_pdf_internal_plugin_delegate.h b/chrome/renderer/pdf/chrome_pdf_internal_plugin_delegate.h new file mode 100644 index 0000000..ee5a310 --- /dev/null +++ b/chrome/renderer/pdf/chrome_pdf_internal_plugin_delegate.h
@@ -0,0 +1,32 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_RENDERER_PDF_CHROME_PDF_INTERNAL_PLUGIN_DELEGATE_H_ +#define CHROME_RENDERER_PDF_CHROME_PDF_INTERNAL_PLUGIN_DELEGATE_H_ + +#include "components/pdf/renderer/pdf_internal_plugin_delegate.h" + +namespace content { +class RenderFrame; +} // namespace content + +class ChromePdfInternalPluginDelegate final + : public pdf::PdfInternalPluginDelegate { + public: + explicit ChromePdfInternalPluginDelegate(content::RenderFrame* render_frame); + ChromePdfInternalPluginDelegate(const ChromePdfInternalPluginDelegate&) = + delete; + ChromePdfInternalPluginDelegate& operator=( + const ChromePdfInternalPluginDelegate&) = delete; + ~ChromePdfInternalPluginDelegate() override; + + // `pdf::PdfInternalPluginDelegate`: + std::unique_ptr<chrome_pdf::PdfViewWebPlugin::PrintClient> CreatePrintClient() + override; + + private: + content::RenderFrame* render_frame_; +}; + +#endif // CHROME_RENDERER_PDF_CHROME_PDF_INTERNAL_PLUGIN_DELEGATE_H_
diff --git a/chrome/renderer/chrome_pdf_view_web_plugin_print_client.cc b/chrome/renderer/pdf/chrome_pdf_view_web_plugin_print_client.cc similarity index 90% rename from chrome/renderer/chrome_pdf_view_web_plugin_print_client.cc rename to chrome/renderer/pdf/chrome_pdf_view_web_plugin_print_client.cc index ab6c1b95..f2124d0 100644 --- a/chrome/renderer/chrome_pdf_view_web_plugin_print_client.cc +++ b/chrome/renderer/pdf/chrome_pdf_view_web_plugin_print_client.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/renderer/chrome_pdf_view_web_plugin_print_client.h" +#include "chrome/renderer/pdf/chrome_pdf_view_web_plugin_print_client.h" #include "base/check.h" #include "components/printing/renderer/print_render_frame_helper.h"
diff --git a/chrome/renderer/chrome_pdf_view_web_plugin_print_client.h b/chrome/renderer/pdf/chrome_pdf_view_web_plugin_print_client.h similarity index 80% rename from chrome/renderer/chrome_pdf_view_web_plugin_print_client.h rename to chrome/renderer/pdf/chrome_pdf_view_web_plugin_print_client.h index e4fd93b..42d3c69 100644 --- a/chrome/renderer/chrome_pdf_view_web_plugin_print_client.h +++ b/chrome/renderer/pdf/chrome_pdf_view_web_plugin_print_client.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_RENDERER_CHROME_PDF_VIEW_WEB_PLUGIN_PRINT_CLIENT_H_ -#define CHROME_RENDERER_CHROME_PDF_VIEW_WEB_PLUGIN_PRINT_CLIENT_H_ +#ifndef CHROME_RENDERER_PDF_CHROME_PDF_VIEW_WEB_PLUGIN_PRINT_CLIENT_H_ +#define CHROME_RENDERER_PDF_CHROME_PDF_VIEW_WEB_PLUGIN_PRINT_CLIENT_H_ #include "pdf/pdf_view_web_plugin.h" @@ -33,4 +33,4 @@ content::RenderFrame* const render_frame_; }; -#endif // CHROME_RENDERER_CHROME_PDF_VIEW_WEB_PLUGIN_PRINT_CLIENT_H_ +#endif // CHROME_RENDERER_PDF_CHROME_PDF_VIEW_WEB_PLUGIN_PRINT_CLIENT_H_
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index 1498a29b..6a2527ac 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -732,6 +732,9 @@ "../browser/metrics/ukm_browsertest.cc", "../browser/net/cert_verify_proc_browsertest.cc", "../browser/page_load_metrics/observers/ad_metrics/ad_density_intervention_android_browsertest.cc", + "../browser/policy/cloud/chrome_browser_cloud_management_browsertest.cc", + "../browser/policy/cloud/chrome_browser_cloud_management_browsertest_delegate.h", + "../browser/policy/cloud/chrome_browser_cloud_management_browsertest_delegate_android.cc", "../browser/policy/policy_prefs_browsertest.cc", "../browser/profiles/profile_browsertest_android.cc", "../browser/safe_browsing/test_safe_browsing_database_helper.cc", @@ -753,8 +756,10 @@ deps += [ "//components/autofill/content/renderer:test_support", + "//components/enterprise:enterprise", "//components/enterprise:test_support", "//components/policy/core/browser:test_support", + "//components/policy/test_support:test_support", "//components/safe_browsing/content/renderer/phishing_classifier:phishing_classifier", "//components/safe_browsing/core/common/fbs:client_model", "//components/safe_browsing/core/common/proto:client_model_proto", @@ -1650,6 +1655,8 @@ "../browser/plugins/pdf_iframe_navigation_throttle_browsertest.cc", "../browser/plugins/plugin_response_interceptor_url_loader_throttle_browsertest.cc", "../browser/policy/cloud/chrome_browser_cloud_management_browsertest.cc", + "../browser/policy/cloud/chrome_browser_cloud_management_browsertest_delegate.h", + "../browser/policy/cloud/chrome_browser_cloud_management_browsertest_delegate_desktop.cc", "../browser/policy/cloud/cloud_policy_browsertest.cc", "../browser/policy/cloud/cloud_policy_manager_browsertest.cc", "../browser/policy/cloud/cloud_policy_test_utils.cc", @@ -2839,6 +2846,7 @@ "../browser/ui/global_error/global_error_service_browsertest.cc", "../browser/ui/media_router/presentation_receiver_window_controller_browsertest.cc", "../browser/ui/views/autofill/autofill_popup_base_view_browsertest.cc", + "../browser/ui/views/autofill/payments/autofill_error_dialog_view_native_views_browsertest.cc", "../browser/ui/views/autofill/payments/card_unmask_prompt_view_tester_views.cc", "../browser/ui/views/autofill/payments/card_unmask_prompt_view_tester_views.h", "../browser/ui/views/autofill/payments/credit_card_access_manager_browsertest.cc", @@ -3377,7 +3385,10 @@ "../browser/metrics/family_user_metrics_provider_browsertest.cc", "../browser/metrics/majority_age_user_metrics_provider_browsertest.cc", "../browser/metrics/usertype_by_devicetype_metrics_provider_browsertest.cc", + "../browser/notifications/chrome_ash_message_center_client_browsertest.cc", "../browser/notifications/notification_platform_bridge_chromeos_browsertest.cc", + "../browser/notifications/notifier_settings_test_observer.cc", + "../browser/notifications/notifier_settings_test_observer.h", "../browser/process_singleton_browsertest.cc", "../browser/resources/chromeos/zip_archiver/test/zip_archiver_jstest.cc", "../browser/sessions/session_restore_browsertest_chromeos.cc",
diff --git a/chrome/test/android/BUILD.gn b/chrome/test/android/BUILD.gn index 74e81789..8dba1d9dc 100644 --- a/chrome/test/android/BUILD.gn +++ b/chrome/test/android/BUILD.gn
@@ -203,6 +203,7 @@ "javatests/src/org/chromium/chrome/test/ChromeJUnit4ClassRunner.java", "javatests/src/org/chromium/chrome/test/ChromeJUnit4RunnerDelegate.java", "javatests/src/org/chromium/chrome/test/ChromeTabbedActivityTestRule.java", + "javatests/src/org/chromium/chrome/test/DummyUiChromeActivityTestCase.java", "javatests/src/org/chromium/chrome/test/MultiActivityTestRule.java", "javatests/src/org/chromium/chrome/test/ReducedModeNativeTestRule.java", "javatests/src/org/chromium/chrome/test/TestContentProvider.java",
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/DummyUiChromeActivityTestCase.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/DummyUiChromeActivityTestCase.java new file mode 100644 index 0000000..494248e3 --- /dev/null +++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/DummyUiChromeActivityTestCase.java
@@ -0,0 +1,18 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.test; + +import org.chromium.chrome.R; +import org.chromium.ui.test.util.DummyUiActivity; +import org.chromium.ui.test.util.DummyUiActivityTestCase; +import org.chromium.ui.test.util.ThemedDummyUiActivityTestRule; + +/** Wrapper around {@link DummyUiActivityTestCase} with Chrome color overlay. */ +public class DummyUiChromeActivityTestCase extends DummyUiActivityTestCase { + /** Default constructor. */ + public DummyUiChromeActivityTestCase() { + super(new ThemedDummyUiActivityTestRule<>(DummyUiActivity.class, R.style.ColorOverlay)); + } +}
diff --git a/chrome/test/data/policy/policy_test_cases.json b/chrome/test/data/policy/policy_test_cases.json index b6a542bb..0c00bf2 100644 --- a/chrome/test/data/policy/policy_test_cases.json +++ b/chrome/test/data/policy/policy_test_cases.json
@@ -5586,6 +5586,10 @@ "reason_for_missing_test": "Maps into CrosSettings" }, + "ReportDeviceAudioStatus": { + "reason_for_missing_test": "Maps into CrosSettings" + }, + "ReportDeviceBootMode": { "reason_for_missing_test": "Maps into CrosSettings" },
diff --git a/chrome/test/data/webui/new_tab_page/modules/cart_v2/module_test.js b/chrome/test/data/webui/new_tab_page/modules/cart_v2/module_test.js index 44df982..4bb0049 100644 --- a/chrome/test/data/webui/new_tab_page/modules/cart_v2/module_test.js +++ b/chrome/test/data/webui/new_tab_page/modules/cart_v2/module_test.js
@@ -95,7 +95,7 @@ // Assert. const cartItems = moduleElement.shadowRoot.querySelectorAll('.cart-item'); assertEquals(4, cartItems.length); - assertEquals(220, moduleElement.offsetHeight); + assertEquals(446, moduleElement.offsetHeight); assertEquals(1, metrics.count('NewTabPage.Carts.CartCount', 4)); assertEquals('https://amazon.com/', cartItems[0].href); @@ -144,7 +144,8 @@ assertEquals(null, cartItems[1].querySelector('.thumbnail-fallback')); }); - test('shows welcome surface in cart module', async () => { + // TODO: Add warm welcome and enable test. + test.skip('shows welcome surface in cart module', async () => { const carts = [ { merchant: 'Foo', @@ -409,7 +410,8 @@ 1, metrics.count('NewTabPage.Carts.RestoreLastCartRestoresModule')); }); - test('scroll with full width module', async () => { + // TODO(crbug.com/1227093): Fix cart module carousel and enable test. + test.skip('scroll with full width module', async () => { // Arrange. const dummyMerchant = { merchant: 'Dummy', @@ -506,7 +508,8 @@ cartCarousel.removeEventListener('scroll', onScroll); }); - test('scroll with cutted width module', async () => { + // TODO(crbug.com/1227093): Fix cart module carousel and enable test. + test.skip('scroll with cutted width module', async () => { // Arrange. const dummyMerchant = { merchant: 'Dummy', @@ -579,59 +582,62 @@ cartCarousel.removeEventListener('scroll', onScroll); }); - test('scroll button visibility changes with module width', async () => { - // Arrange. - const dummyMerchant = { - merchant: 'Dummy', - cartUrl: {url: 'https://dummy.com'}, - productImageUrls: [], - }; - const carts = Array.from({length: 4}, () => dummyMerchant); - testProxy.handler.setResultFor( - 'getMerchantCarts', Promise.resolve({carts})); + // TODO(crbug.com/1227093): Fix cart module carousel and enable test. + test.skip( + 'scroll button visibility changes with module width', async () => { + // Arrange. + const dummyMerchant = { + merchant: 'Dummy', + cartUrl: {url: 'https://dummy.com'}, + productImageUrls: [], + }; + const carts = Array.from({length: 4}, () => dummyMerchant); + testProxy.handler.setResultFor( + 'getMerchantCarts', Promise.resolve({carts})); - // Arrange. - const moduleElement = await chromeCartV2Descriptor.initialize(); - document.body.append(moduleElement); - moduleElement.$.cartItemRepeat.render(); + // Arrange. + const moduleElement = await chromeCartV2Descriptor.initialize(); + document.body.append(moduleElement); + moduleElement.$.cartItemRepeat.render(); - // Assert. - const cartItems = moduleElement.shadowRoot.querySelectorAll('.cart-item'); - assertEquals(4, cartItems.length); + // Assert. + const cartItems = + moduleElement.shadowRoot.querySelectorAll('.cart-item'); + assertEquals(4, cartItems.length); - // Act. - let waitForLeftScrollVisibilityChange = - eventToPromise('left-scroll-hide', moduleElement); - let waitForRightScrollVisibilityChange = - eventToPromise('right-scroll-hide', moduleElement); - moduleElement.style.width = '560px'; - await waitForLeftScrollVisibilityChange; - await waitForRightScrollVisibilityChange; + // Act. + let waitForLeftScrollVisibilityChange = + eventToPromise('left-scroll-hide', moduleElement); + let waitForRightScrollVisibilityChange = + eventToPromise('right-scroll-hide', moduleElement); + moduleElement.style.width = '560px'; + await waitForLeftScrollVisibilityChange; + await waitForRightScrollVisibilityChange; - // Assert. - checkScrollButtonVisibility(moduleElement, false, false); - checkVisibleRange(moduleElement, 0, 3); + // Assert. + checkScrollButtonVisibility(moduleElement, false, false); + checkVisibleRange(moduleElement, 0, 3); - // Act. - waitForRightScrollVisibilityChange = - eventToPromise('right-scroll-show', moduleElement); - moduleElement.style.width = '480px'; - await waitForRightScrollVisibilityChange; + // Act. + waitForRightScrollVisibilityChange = + eventToPromise('right-scroll-show', moduleElement); + moduleElement.style.width = '480px'; + await waitForRightScrollVisibilityChange; - // Assert. - checkScrollButtonVisibility(moduleElement, false, true); - checkVisibleRange(moduleElement, 0, 2); + // Assert. + checkScrollButtonVisibility(moduleElement, false, true); + checkVisibleRange(moduleElement, 0, 2); - // Act. - waitForRightScrollVisibilityChange = - eventToPromise('right-scroll-hide', moduleElement); - moduleElement.style.width = '560px'; - await waitForRightScrollVisibilityChange; + // Act. + waitForRightScrollVisibilityChange = + eventToPromise('right-scroll-hide', moduleElement); + moduleElement.style.width = '560px'; + await waitForRightScrollVisibilityChange; - // Assert. - checkScrollButtonVisibility(moduleElement, false, false); - checkVisibleRange(moduleElement, 0, 3); - }); + // Assert. + checkScrollButtonVisibility(moduleElement, false, false); + checkVisibleRange(moduleElement, 0, 3); + }); test('shows discount chip', async () => { const carts = [ @@ -761,7 +767,8 @@ assertEquals(false, isVisible(consentCard)); }); - test('scroll with consent card', async () => { + // TODO(crbug.com/1227093): Fix cart module carousel and enable test. + test.skip('scroll with consent card', async () => { // Arrange. const dummyMerchant = { merchant: 'Dummy', @@ -873,7 +880,7 @@ // Act. cartItems[3].querySelector('.cart-title').click(); cartItems[0].click(); - cartItems[2].querySelector('.favicon-image').click(); + cartItems[2].querySelector('.icon-more-vert').click(); cartItems[1].querySelector('.thumbnail-container').click(); // Assert. @@ -982,8 +989,7 @@ await testRBDCartClick( cartItems[0], 'https://amazon.com', 0, 2, moduleElement); await testRBDCartClick( - cartItems[2].querySelector('.favicon-image'), 'https://bestbuy.com', - 2, 3, moduleElement); + cartItems[2], 'https://bestbuy.com', 2, 3, moduleElement); await testRBDCartClick( cartItems[1].querySelector('.thumbnail-container'), 'https://ebay.com', 1, 4, moduleElement);
diff --git a/chrome/test/data/webui/new_tab_page/modules/drive_v2/module_test.js b/chrome/test/data/webui/new_tab_page/modules/drive_v2/module_test.js index 188f604..260c6ff83 100644 --- a/chrome/test/data/webui/new_tab_page/modules/drive_v2/module_test.js +++ b/chrome/test/data/webui/new_tab_page/modules/drive_v2/module_test.js
@@ -2,17 +2,69 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import {driveV2Descriptor} from 'chrome://new-tab-page/new_tab_page.js'; +import {DriveProxy, driveV2Descriptor} from 'chrome://new-tab-page/new_tab_page.js'; +import {TestBrowserProxy} from 'chrome://test/test_browser_proxy.m.js'; +import {isVisible} from 'chrome://test/test_util.m.js'; suite('NewTabPageModulesDriveModuleTest', () => { + let testProxy; + setup(() => { PolymerTest.clearBody(); + testProxy = TestBrowserProxy.fromClass(DriveProxy); + testProxy.handler = + TestBrowserProxy.fromClass(drive.mojom.DriveHandlerRemote); + DriveProxy.setInstance(testProxy); }); test('module appears on render', async () => { + const data = { + files: [ + { + justificationText: 'Edited last week', + title: 'Foo', + id: '123', + mimeType: 'application/vnd.google-apps.spreadsheet', + itemUrl: {url: 'https://foo.com'}, + }, + { + justificationText: 'Edited yesterday', + title: 'Bar', + id: '234', + mimeType: 'application/vnd.google-apps.document', + itemUrl: {url: 'https://bar.com'}, + }, + { + justificationText: 'Created today', + title: 'Caz', + id: '345', + mimeType: 'application/vnd.google-apps.presentation', + itemUrl: {url: 'https://caz.com'}, + } + ] + }; + testProxy.handler.setResultFor('getFiles', Promise.resolve(data)); + const module = await driveV2Descriptor.initialize(); document.body.append(module); + await testProxy.handler.whenCalled('getFiles'); + module.$.fileRepeat.render(); + const items = Array.from(module.shadowRoot.querySelectorAll('.file')); + assertTrue(isVisible(module.$.files)); assertTrue(!!module); + assertEquals(3, items.length); + assertEquals('Bar', items[1].querySelector('.file-title').textContent); + assertEquals( + 'Edited yesterday', + items[1].querySelector('.file-description').textContent); + }); + + test('documents do not show without data', async () => { + testProxy.handler.setResultFor('getFiles', Promise.resolve({files: []})); + + const module = await driveV2Descriptor.initialize(); + await testProxy.handler.whenCalled('getFiles'); + assertTrue(!module); }); });
diff --git a/chrome/test/data/webui/new_tab_page/new_tab_page_browsertest.js b/chrome/test/data/webui/new_tab_page/new_tab_page_browsertest.js index 11dffeb..4c2227b7 100644 --- a/chrome/test/data/webui/new_tab_page/new_tab_page_browsertest.js +++ b/chrome/test/data/webui/new_tab_page/new_tab_page_browsertest.js
@@ -308,3 +308,16 @@ TEST_F('NewTabPageModulesChromeCartModuleTest', 'All', function() { mocha.run(); }); + +// eslint-disable-next-line no-var +var NewTabPageModulesChromeCartV2ModuleTest = + class extends NewTabPageBrowserTest { + /** @override */ + get browsePreload() { + return 'chrome://new-tab-page/test_loader.html?module=new_tab_page/modules/cart_v2/module_test.js'; + } +}; + +TEST_F('NewTabPageModulesChromeCartV2ModuleTest', 'All', function() { + mocha.run(); +});
diff --git a/chrome/test/data/webui/settings/chromeos/internet_detail_page_tests.js b/chrome/test/data/webui/settings/chromeos/internet_detail_page_tests.js index 090ca551..862e30d 100644 --- a/chrome/test/data/webui/settings/chromeos/internet_detail_page_tests.js +++ b/chrome/test/data/webui/settings/chromeos/internet_detail_page_tests.js
@@ -1034,20 +1034,33 @@ init(); }); - test('Tether1', function() { - init(); - const mojom = chromeos.networkConfig.mojom; - mojoApi_.setNetworkTypeEnabledState(mojom.NetworkType.kTether, true); - setNetworksForTest([ - OncMojo.getDefaultNetworkState(mojom.NetworkType.kTether, 'tether1'), - ]); + test( + 'Create tether network, first connection attempt shows tether dialog', + async () => { + init(); + const mojom = chromeos.networkConfig.mojom; + mojoApi_.setNetworkTypeEnabledState(mojom.NetworkType.kTether, true); + setNetworksForTest([ + OncMojo.getDefaultNetworkState( + mojom.NetworkType.kTether, 'tether1'), + ]); - internetDetailPage.init('tether1_guid', 'Tether', 'tether1'); - assertEquals('tether1_guid', internetDetailPage.guid); - return flushAsync().then(() => { - return mojoApi_.whenCalled('getManagedProperties'); - }); - }); + internetDetailPage.init('tether1_guid', 'Tether', 'tether1'); + assertEquals('tether1_guid', internetDetailPage.guid); + await flushAsync(); + await mojoApi_.whenCalled('getManagedProperties'); + + const connect = internetDetailPage.$$('#connectDisconnect'); + assertTrue(!!connect); + + const tetherDialog = internetDetailPage.$$('#tetherDialog'); + assertTrue(!!tetherDialog); + assertFalse(tetherDialog.$.dialog.open); + + connect.click(); + await flushAsync(); + assertTrue(tetherDialog.$.dialog.open); + }); test('Deep link to disconnect tether network', async () => { init();
diff --git a/chromecast/media/audio/cast_audio_output_stream.cc b/chromecast/media/audio/cast_audio_output_stream.cc index 455fa45..d1c6723 100644 --- a/chromecast/media/audio/cast_audio_output_stream.cc +++ b/chromecast/media/audio/cast_audio_output_stream.cc
@@ -109,7 +109,8 @@ // mixer_service::OutputStreamConnection::Delegate implementation: void FillNextBuffer(void* buffer, int frames, - int64_t playout_timestamp) override; + int64_t delay_timestamp, + int64_t delay) override; // We don't push an EOS buffer. void OnEosPlayed() override { NOTREACHED(); } @@ -249,7 +250,8 @@ void CastAudioOutputStream::MixerServiceWrapper::FillNextBuffer( void* buffer, int frames, - int64_t playout_timestamp) { + int64_t delay_timestamp, + int64_t delay) { DCHECK_CALLED_ON_VALID_THREAD(io_thread_checker_); // Round down to closest multiple of 4 to ensure correct channel alignment. @@ -264,6 +266,8 @@ if (!running_) return; + int64_t playout_timestamp = + (delay_timestamp == INT64_MIN ? INT64_MIN : delay_timestamp + delay); if (playout_timestamp < 0) { // Assume any negative timestamp is invalid. playout_timestamp = 0; @@ -279,13 +283,13 @@ } audio_bus_->set_frames(frames); - base::TimeDelta delay = ::media::AudioTimestampHelper::FramesToTime( + base::TimeDelta reported_delay = ::media::AudioTimestampHelper::FramesToTime( max_buffered_frames_, audio_params_.sample_rate()); - base::TimeTicks delay_timestamp = + base::TimeTicks reported_delay_timestamp = base::TimeTicks() + base::TimeDelta::FromMicroseconds(playout_timestamp); - int frames_filled = - source_callback_->OnMoreData(delay, delay_timestamp, 0, audio_bus_.get()); + int frames_filled = source_callback_->OnMoreData( + reported_delay, reported_delay_timestamp, 0, audio_bus_.get()); DCHECK_EQ(frames_filled, frames); mixer_connection_->SendNextBuffer(frames); }
diff --git a/chromecast/media/audio/mixer_service/mixer_service.proto b/chromecast/media/audio/mixer_service/mixer_service.proto index 83e2af1e..f0383b5 100644 --- a/chromecast/media/audio/mixer_service/mixer_service.proto +++ b/chromecast/media/audio/mixer_service/mixer_service.proto
@@ -143,7 +143,8 @@ // and the next audio data that is pushed to the mixer will start playing at // |next_playback_timestamp|. message BufferPushResult { - optional fixed64 next_playback_timestamp = 1; + optional fixed64 delay_timestamp = 1; + optional int64 delay = 2; } // Indicates that EOS for an audio output stream has been played out.
diff --git a/chromecast/media/audio/mixer_service/output_stream_connection.cc b/chromecast/media/audio/mixer_service/output_stream_connection.cc index 502e731..bde5362 100644 --- a/chromecast/media/audio/mixer_service/output_stream_connection.cc +++ b/chromecast/media/audio/mixer_service/output_stream_connection.cc
@@ -199,7 +199,7 @@ socket_->SendProto(kInitial, message); delegate_->FillNextBuffer( audio_buffer_->data() + MixerSocket::kAudioMessageHeaderSize, - fill_size_frames_, std::numeric_limits<int64_t>::min()); + fill_size_frames_, std::numeric_limits<int64_t>::min(), 0); } void OutputStreamConnection::OnConnectionError() { @@ -220,7 +220,8 @@ if (message.has_push_result() && !sent_eos_) { delegate_->FillNextBuffer( audio_buffer_->data() + MixerSocket::kAudioMessageHeaderSize, - fill_size_frames_, message.push_result().next_playback_timestamp()); + fill_size_frames_, message.push_result().delay_timestamp(), + message.push_result().delay()); } if (message.has_ready_for_playback()) {
diff --git a/chromecast/media/audio/mixer_service/output_stream_connection.h b/chromecast/media/audio/mixer_service/output_stream_connection.h index f042e52..0174cb4d 100644 --- a/chromecast/media/audio/mixer_service/output_stream_connection.h +++ b/chromecast/media/audio/mixer_service/output_stream_connection.h
@@ -45,7 +45,8 @@ // data is expected to play out. virtual void FillNextBuffer(void* buffer, int frames, - int64_t playout_timestamp) = 0; + int64_t delay_timestamp, + int64_t delay) = 0; // Called when audio is ready to begin playing out, ie the start threshold // has been reached. |mixer_delay| is the delay before the first buffered
diff --git a/chromecast/media/audio/mixer_service/receiver/receiver_cma.cc b/chromecast/media/audio/mixer_service/receiver/receiver_cma.cc index 30b190b2..5e47f2c7 100644 --- a/chromecast/media/audio/mixer_service/receiver/receiver_cma.cc +++ b/chromecast/media/audio/mixer_service/receiver/receiver_cma.cc
@@ -135,17 +135,9 @@ // CmaBackendShim::Delegate implementation: void OnBufferPushed(CmaBackendShim::RenderingDelay rendering_delay) override { if (!pushed_eos_) { - int64_t next_playout_timestamp; - if (rendering_delay.timestamp_microseconds == - std::numeric_limits<int64_t>::min()) { - next_playout_timestamp = std::numeric_limits<int64_t>::min(); - } else { - next_playout_timestamp = rendering_delay.timestamp_microseconds + - rendering_delay.delay_microseconds; - } - mixer_service::BufferPushResult message; - message.set_next_playback_timestamp(next_playout_timestamp); + message.set_delay_timestamp(rendering_delay.timestamp_microseconds); + message.set_delay(rendering_delay.delay_microseconds); mixer_service::Generic generic; *(generic.mutable_push_result()) = message; socket_->SendProto(kPushResult, generic);
diff --git a/chromecast/media/cma/backend/audio_decoder_for_mixer.cc b/chromecast/media/cma/backend/audio_decoder_for_mixer.cc index dc4f886..919b7cc3 100644 --- a/chromecast/media/cma/backend/audio_decoder_for_mixer.cc +++ b/chromecast/media/cma/backend/audio_decoder_for_mixer.cc
@@ -563,10 +563,11 @@ void AudioDecoderForMixer::FillNextBuffer(void* buffer, int frames, - int64_t playout_timestamp) { + int64_t delay_timestamp, + int64_t delay) { DCHECK(task_runner_->BelongsToCurrentThread()); pending_output_frames_ = kNoPendingOutput; - next_buffer_delay_ = RenderingDelay(0, playout_timestamp); + next_buffer_delay_ = RenderingDelay(delay, delay_timestamp); CheckBufferComplete(); }
diff --git a/chromecast/media/cma/backend/audio_decoder_for_mixer.h b/chromecast/media/cma/backend/audio_decoder_for_mixer.h index e19acce..3aafdb41 100644 --- a/chromecast/media/cma/backend/audio_decoder_for_mixer.h +++ b/chromecast/media/cma/backend/audio_decoder_for_mixer.h
@@ -70,7 +70,8 @@ // mixer_service::OutputStreamConnection::Delegate implementation: void FillNextBuffer(void* buffer, int frames, - int64_t playout_timestamp) override; + int64_t delay_timestamp, + int64_t delay) override; void OnAudioReadyForPlayback(int64_t mixer_delay) override; void OnEosPlayed() override; void OnMixerError() override;
diff --git a/chromecast/media/cma/backend/mixer/mixer_input_connection.cc b/chromecast/media/cma/backend/mixer/mixer_input_connection.cc index 3840ad2c..4cedbec 100644 --- a/chromecast/media/cma/backend/mixer/mixer_input_connection.cc +++ b/chromecast/media/cma/backend/mixer/mixer_input_connection.cc
@@ -15,6 +15,7 @@ #include "base/command_line.h" #include "base/location.h" #include "base/logging.h" +#include "base/numerics/ranges.h" #include "base/sequenced_task_runner.h" #include "base/threading/thread_task_runner_handle.h" #include "base/time/time.h" @@ -49,6 +50,8 @@ base::TimeDelta::FromMilliseconds(5); constexpr base::TimeDelta kInactivityTimeout = base::TimeDelta::FromSeconds(5); constexpr int64_t kDefaultMaxTimestampError = 2000; +// Max absolute value for timestamp errors, to avoid overflow/underflow. +constexpr int64_t kTimestampErrorLimit = 1000000; constexpr int kAudioMessageHeaderSize = mixer_service::MixerSocket::kAudioMessageHeaderSize; @@ -794,7 +797,7 @@ void MixerInputConnection::WritePcm(scoped_refptr<net::IOBuffer> data) { DCHECK(io_task_runner_->RunsTasksInCurrentSequence()); - int64_t next_playback_timestamp; + RenderingDelay rendering_delay; bool queued; { base::AutoLock lock(lock_); @@ -810,20 +813,22 @@ pending_data_ = std::move(data); queued = false; } else { - next_playback_timestamp = QueueData(std::move(data)); + rendering_delay = QueueData(std::move(data)); queued = true; } } if (queued) { mixer_service::Generic message; - message.mutable_push_result()->set_next_playback_timestamp( - next_playback_timestamp); + auto* push_result = message.mutable_push_result(); + push_result->set_delay_timestamp(rendering_delay.timestamp_microseconds); + push_result->set_delay(rendering_delay.delay_microseconds); socket_->SendProto(kPushResult, message); } } -int64_t MixerInputConnection::QueueData(scoped_refptr<net::IOBuffer> data) { +MixerInputConnection::RenderingDelay MixerInputConnection::QueueData( + scoped_refptr<net::IOBuffer> data) { int frames = GetFrameCount(data.get()); if (frames == 0) { AUDIO_LOG(INFO) << "End of stream for " << this; @@ -847,13 +852,13 @@ if (!started_ || paused_ || mixer_rendering_delay_.timestamp_microseconds == INT64_MIN) { - return INT64_MIN; + return RenderingDelay(); } - int64_t mixer_timestamp = mixer_rendering_delay_.timestamp_microseconds + - mixer_rendering_delay_.delay_microseconds; - return mixer_timestamp + - SamplesToMicroseconds(ExtraDelayFrames(), input_samples_per_second_); + RenderingDelay delay = mixer_rendering_delay_; + delay.delay_microseconds += + SamplesToMicroseconds(ExtraDelayFrames(), input_samples_per_second_); + return delay; } double MixerInputConnection::ExtraDelayFrames() { @@ -892,7 +897,7 @@ } if (pending_data_ && queued_frames_ < max_queued_frames_) { - next_playback_timestamp_ = QueueData(std::move(pending_data_)); + next_delay_ = QueueData(std::move(pending_data_)); queued_data = true; } } @@ -1061,11 +1066,11 @@ // See if we can accept more data into the queue. if (pending_data_ && queued_frames_ < max_queued_frames_) { - next_playback_timestamp_ = QueueData(std::move(pending_data_)); + next_delay_ = QueueData(std::move(pending_data_)); post_pcm_completion = true; } else if (pts_is_timestamp_) { - next_playback_timestamp_ = - playback_absolute_timestamp + + next_delay_ = rendering_delay; + next_delay_.delay_microseconds += SamplesToMicroseconds(ExtraDelayFrames(), input_samples_per_second_); } @@ -1153,6 +1158,10 @@ int64_t expected_playout_time, float* const* channels, bool after_silence) { + if (expected_playout_time < 0) { + // Invalid playout time. + return 0; + } int filled = 0; while (filled < num_frames && !queue_.empty()) { net::IOBuffer* buffer = queue_.front().get(); @@ -1167,7 +1176,9 @@ SamplesToMicroseconds(current_buffer_offset_ / playback_rate_, input_samples_per_second_); - const int64_t error = playout_time - desired_playout_time; + const int64_t error = + base::ClampToRange(playout_time - desired_playout_time, + -kTimestampErrorLimit, kTimestampErrorLimit); if (error < -max_timestamp_error_ || (after_silence && error < -1e6 / (input_samples_per_second_ * playback_rate_))) { @@ -1270,7 +1281,8 @@ auto* push_result = message.mutable_push_result(); { base::AutoLock lock(lock_); - push_result->set_next_playback_timestamp(next_playback_timestamp_); + push_result->set_delay_timestamp(next_delay_.timestamp_microseconds); + push_result->set_delay(next_delay_.delay_microseconds); } socket_->SendProto(kPushResult, message); }
diff --git a/chromecast/media/cma/backend/mixer/mixer_input_connection.h b/chromecast/media/cma/backend/mixer/mixer_input_connection.h index 310b6ee..26b225c 100644 --- a/chromecast/media/cma/backend/mixer/mixer_input_connection.h +++ b/chromecast/media/cma/backend/mixer/mixer_input_connection.h
@@ -134,7 +134,7 @@ void LogUnderrun(int num_frames, int filled) EXCLUSIVE_LOCKS_REQUIRED(lock_); void WritePcm(scoped_refptr<net::IOBuffer> data); - int64_t QueueData(scoped_refptr<net::IOBuffer> data) + RenderingDelay QueueData(scoped_refptr<net::IOBuffer> data) EXCLUSIVE_LOCKS_REQUIRED(lock_); double ExtraDelayFrames() EXCLUSIVE_LOCKS_REQUIRED(lock_); @@ -192,7 +192,7 @@ base::circular_deque<scoped_refptr<net::IOBuffer>> queue_ GUARDED_BY(lock_); int queued_frames_ GUARDED_BY(lock_) = 0; RenderingDelay mixer_rendering_delay_ GUARDED_BY(lock_); - int64_t next_playback_timestamp_ GUARDED_BY(lock_) = INT64_MIN; + RenderingDelay next_delay_ GUARDED_BY(lock_); int mixer_read_size_ GUARDED_BY(lock_) = 0; int current_buffer_offset_ GUARDED_BY(lock_) = 0; std::unique_ptr<RateAdjuster> rate_adjuster_ GUARDED_BY(lock_);
diff --git a/chromeos/CHROMEOS_LKGM b/chromeos/CHROMEOS_LKGM index 36f9457..702f871a 100644 --- a/chromeos/CHROMEOS_LKGM +++ b/chromeos/CHROMEOS_LKGM
@@ -1 +1 @@ -14087.0.0 \ No newline at end of file +14088.0.0 \ No newline at end of file
diff --git a/chromeos/chromeos_strings.grd b/chromeos/chromeos_strings.grd index f4c8ca1..0685f818 100644 --- a/chromeos/chromeos_strings.grd +++ b/chromeos/chromeos_strings.grd
@@ -693,6 +693,18 @@ <message name="IDS_SCANNING_APP_ACTION_TOOLBAR_PAGE_COUNT_TEXT" desc="The text in the action toolbar that shows the current page number and the total number of pages scanned."> <ph name="CURRENT_PAGE">$1<ex>2</ex></ph> of <ph name="TOTAL_PAGES">$2<ex>4</ex></ph> </message> + <message name="IDS_SCANNING_APP_REMOVE_PAGE_BUTTON_LABEL" desc="The label for the button that lets the user delete a page from their scan job."> + {PAGE_NUMBER, plural, + =0 {Remove page} + =1 {Remove page {PAGE_NUMBER}} + other {Remove page {PAGE_NUMBER}}} + </message> + <message name="IDS_SCANNING_APP_RESCAN_PAGE_BUTTON_LABEL" desc="The label for the button that lets the user replace a page from their scan job by scanning a new page from their scanner."> + {PAGE_NUMBER, plural, + =0 {Rescan page} + =1 {Rescan page {PAGE_NUMBER}} + other {Rescan page {PAGE_NUMBER}}} + </message> <!-- Diagnostics App --> <message name="IDS_DIAGNOSTICS_TITLE" desc="The title of the diagnostics app.">
diff --git a/chromeos/chromeos_strings_grd/IDS_SCANNING_APP_REMOVE_PAGE_BUTTON_LABEL.png.sha1 b/chromeos/chromeos_strings_grd/IDS_SCANNING_APP_REMOVE_PAGE_BUTTON_LABEL.png.sha1 new file mode 100644 index 0000000..8a57a6e6 --- /dev/null +++ b/chromeos/chromeos_strings_grd/IDS_SCANNING_APP_REMOVE_PAGE_BUTTON_LABEL.png.sha1
@@ -0,0 +1 @@ +3ff02f4253132750f2d78845b10d0971d0aa4a85 \ No newline at end of file
diff --git a/chromeos/chromeos_strings_grd/IDS_SCANNING_APP_RESCAN_PAGE_BUTTON_LABEL.png.sha1 b/chromeos/chromeos_strings_grd/IDS_SCANNING_APP_RESCAN_PAGE_BUTTON_LABEL.png.sha1 new file mode 100644 index 0000000..9239c1c --- /dev/null +++ b/chromeos/chromeos_strings_grd/IDS_SCANNING_APP_RESCAN_PAGE_BUTTON_LABEL.png.sha1
@@ -0,0 +1 @@ +0e61c26ae237d8a0cb4513c6174a08a245c8a0a8 \ No newline at end of file
diff --git a/chromeos/crosapi/mojom/app_service.mojom b/chromeos/crosapi/mojom/app_service.mojom index 804c926..1a59b7a4 100644 --- a/chromeos/crosapi/mojom/app_service.mojom +++ b/chromeos/crosapi/mojom/app_service.mojom
@@ -9,15 +9,17 @@ import "chromeos/crosapi/mojom/app_service_types.mojom"; // Interacts with the app service. Implemented in ash-chrome. +// This is a generic app-publisher interface that is used by the implementation +// for both Web Apps and Chrome Apps in Lacros. [Stable, Uuid="238dd8e0-480e-49f4-a3a0-28e610ef7119"] interface AppPublisher { - // Publish a stream of web apps from lacros-chrome. + // Publish a stream of apps from lacros-chrome. // |deltas| holds a sparse data structure that includes the update App data // from the existing app state in app service. OnApps@0(array<App> deltas); // Lacros exposes an AppController interface to Ash. This allows Ash to - // launch, or otherwise interact with Web Apps that run in Lacros. + // launch, or otherwise interact with Apps that run in Lacros. [MinVersion=1] RegisterAppController@1(pending_remote<AppController> controller);
diff --git a/chromeos/crosapi/mojom/crosapi.mojom b/chromeos/crosapi/mojom/crosapi.mojom index 64223823..36ab7c4b 100644 --- a/chromeos/crosapi/mojom/crosapi.mojom +++ b/chromeos/crosapi/mojom/crosapi.mojom
@@ -66,8 +66,8 @@ // please note the milestone when you added it, to help us reason about // compatibility between the client applications and older ash-chrome binaries. // -// Next version: 38 -// Next method id: 43 +// Next version: 39 +// Next method id: 44 [Stable, Uuid="8b79c34f-2bf8-4499-979a-b17cac522c1e", RenamedFrom="crosapi.mojom.AshChromeService"] interface Crosapi { @@ -103,6 +103,12 @@ // Added in M89. [MinVersion=7] BindCertDatabase@12(pending_receiver<CertDatabase> receiver); + // Binds the chrome app publisher service, which allows Lacros to connect its + // Chrome apps to the app service. + // Added in M93. + [MinVersion=38] + BindChromeAppPublisher@43(pending_receiver<AppPublisher> receiver); + // Bind the clipboard interface to allow lacros-chrome to interact with the // system clipboard. [MinVersion=10] BindClipboard@15(pending_receiver<Clipboard> receiver); @@ -271,11 +277,11 @@ [MinVersion=34] BindWebPageInfoFactory@39(pending_receiver<WebPageInfoFactory> receiver); - // Binds the app publisher service to allow web app publishing from + // Binds the web app publisher service to allow web app publishing from // lacros-chrome. // Added in M92. [MinVersion=22] - BindAppPublisher@27(pending_receiver<AppPublisher> receiver); + BindWebAppPublisher@27(pending_receiver<AppPublisher> receiver); // Passes generic browser information such as version, etc into ash in // |browser_info| during startup.
diff --git a/chromeos/dbus/pciguard/pciguard_client.cc b/chromeos/dbus/pciguard/pciguard_client.cc index f46e6d8..6480740 100644 --- a/chromeos/dbus/pciguard/pciguard_client.cc +++ b/chromeos/dbus/pciguard/pciguard_client.cc
@@ -85,7 +85,10 @@ if (!success) { LOG(ERROR) << "Pciguard: Failed to connect to signal " << signal_name << "."; + return; } + VLOG(1) << "Pciguard: Successfully connected to signal " << signal_name + << "."; } void PciguardClientImpl::SendExternalPciDevicesPermissionState(bool permitted) {
diff --git a/chromeos/dbus/typecd/typecd_client.cc b/chromeos/dbus/typecd/typecd_client.cc index f722788d..2e0c09e 100644 --- a/chromeos/dbus/typecd/typecd_client.cc +++ b/chromeos/dbus/typecd/typecd_client.cc
@@ -80,8 +80,11 @@ void TypecdClientImpl::OnSignalConnected(const std::string& interface_name, const std::string& signal_name, bool success) { - if (!success) + if (!success) { LOG(ERROR) << "Typecd: Failed to connect to signal " << signal_name << "."; + return; + } + VLOG(1) << "Typecd: Successfully connected to signal " << signal_name << "."; } // TypecdClient
diff --git a/chromeos/lacros/lacros_chrome_service_impl.cc b/chromeos/lacros/lacros_chrome_service_impl.cc index 88efb3b4..d1db4e4ff 100644 --- a/chromeos/lacros/lacros_chrome_service_impl.cc +++ b/chromeos/lacros/lacros_chrome_service_impl.cc
@@ -187,8 +187,6 @@ weak_sequenced_state_)); // Note: sorted by the Bind method names in the lexicographical order. - ConstructRemote<crosapi::mojom::AppPublisher, &Crosapi::BindAppPublisher, - Crosapi::MethodMinVersions::kBindAppPublisherMinVersion>(); ConstructRemote< crosapi::mojom::AutomationFactory, &Crosapi::BindAutomationFactory, Crosapi::MethodMinVersions::kBindAutomationFactoryMinVersion>(); @@ -272,6 +270,8 @@ ConstructRemote<crosapi::mojom::UrlHandler, &crosapi::mojom::Crosapi::BindUrlHandler, Crosapi::MethodMinVersions::kBindUrlHandlerMinVersion>(); + ConstructRemote<crosapi::mojom::AppPublisher, &Crosapi::BindWebAppPublisher, + Crosapi::MethodMinVersions::kBindWebAppPublisherMinVersion>(); ConstructRemote< crosapi::mojom::WebPageInfoFactory, &crosapi::mojom::Crosapi::BindWebPageInfoFactory,
diff --git a/chromeos/profiles/bigcore.afdo.newest.txt b/chromeos/profiles/bigcore.afdo.newest.txt index 0d0a1d0..6b959206e 100644 --- a/chromeos/profiles/bigcore.afdo.newest.txt +++ b/chromeos/profiles/bigcore.afdo.newest.txt
@@ -1 +1 @@ -chromeos-chrome-amd64-bigcore-93-4554.0-1626087514-benchmark-93.0.4573.0-r1-redacted.afdo.xz +chromeos-chrome-amd64-bigcore-93-4554.0-1626087514-benchmark-93.0.4574.0-r1-redacted.afdo.xz
diff --git a/chromeos/settings/cros_settings_names.cc b/chromeos/settings/cros_settings_names.cc index 566a89f..45eeefa 100644 --- a/chromeos/settings/cros_settings_names.cc +++ b/chromeos/settings/cros_settings_names.cc
@@ -102,6 +102,11 @@ const char kReportDeviceActivityTimes[] = "cros.device_status.report_activity_times"; +// A boolean pref that indicates whether device sound volume should be recorded +// and reported along with device policy requests. +const char kReportDeviceAudioStatus[] = + "cros.device_status.report_audio_status"; + // A boolean pref that determines whether the board status should be // included in status reports to the device management server. const char kReportDeviceBoardStatus[] =
diff --git a/chromeos/settings/cros_settings_names.h b/chromeos/settings/cros_settings_names.h index 425e772a..6dd5089 100644 --- a/chromeos/settings/cros_settings_names.h +++ b/chromeos/settings/cros_settings_names.h
@@ -86,6 +86,8 @@ COMPONENT_EXPORT(CHROMEOS_SETTINGS) extern const char kReportDeviceActivityTimes[]; COMPONENT_EXPORT(CHROMEOS_SETTINGS) +extern const char kReportDeviceAudioStatus[]; +COMPONENT_EXPORT(CHROMEOS_SETTINGS) extern const char kReportDeviceBoardStatus[]; COMPONENT_EXPORT(CHROMEOS_SETTINGS) extern const char kReportDeviceBootMode[]; COMPONENT_EXPORT(CHROMEOS_SETTINGS) extern const char kReportDeviceCpuInfo[]; @@ -382,6 +384,7 @@ using ::chromeos::kReleaseLtsTag; using ::chromeos::kReportDeviceActivityTimes; using ::chromeos::kReportDeviceAppInfo; +using ::chromeos::kReportDeviceAudioStatus; using ::chromeos::kReportDeviceBacklightInfo; using ::chromeos::kReportDeviceBluetoothInfo; using ::chromeos::kReportDeviceBoardStatus;
diff --git a/components/BUILD.gn b/components/BUILD.gn index 776cbf0d..0b5e715 100644 --- a/components/BUILD.gn +++ b/components/BUILD.gn
@@ -162,7 +162,6 @@ "//components/subresource_filter/core/browser:unit_tests", "//components/subresource_filter/core/common:unit_tests", "//components/subresource_filter/tools:unit_tests", - "//components/suggestions:unit_tests", "//components/sync:unit_tests", "//components/sync_bookmarks:unit_tests", "//components/sync_preferences:unit_tests", @@ -735,6 +734,7 @@ deps += [ "//components/pdf/browser", "//components/pdf/renderer", + "//pdf:accessibility_structs", "//pdf:features", ] }
diff --git a/components/autofill/core/browser/autofill_client.cc b/components/autofill/core/browser/autofill_client.cc index 61f51fb..e27e0b6f 100644 --- a/components/autofill/core/browser/autofill_client.cc +++ b/components/autofill/core/browser/autofill_client.cc
@@ -66,10 +66,14 @@ // ChromeAutofillClient (Chrome Desktop and Clank) implements this. } -void AutofillClient::OnVirtualCardFetched(CreditCardFetchResult result, - const CreditCard* credit_card, - const std::u16string& cvc, - const gfx::Image& card_image) { +void AutofillClient::OnVirtualCardDataAvailable(const CreditCard* credit_card, + const std::u16string& cvc, + const gfx::Image& card_image) { + // This is overridden by platform subclasses. Currently only + // ChromeAutofillClient (Chrome Desktop & Android) implements this. +} + +void AutofillClient::ShowVirtualCardErrorDialog(bool is_permanent_error) { // This is overridden by platform subclasses. Currently only // ChromeAutofillClient (Chrome Desktop & Android) implements this. }
diff --git a/components/autofill/core/browser/autofill_client.h b/components/autofill/core/browser/autofill_client.h index 069a5103..9127731 100644 --- a/components/autofill/core/browser/autofill_client.h +++ b/components/autofill/core/browser/autofill_client.h
@@ -563,16 +563,19 @@ virtual void ShowOfferNotificationIfApplicable( const AutofillOfferData* offer); - // Called when the result of fetching a virtual card from the server returns. - // |result| indicates whether the fetching was successful. |credit_card| and - // |cvc| include the information that allow the user to manually fill payment - // form. |card_image| is used for manual fallback bubble. - virtual void OnVirtualCardFetched( - CreditCardFetchResult result, - const CreditCard* credit_card = nullptr, - const std::u16string& cvc = std::u16string(), + // Called when the virtual card has been fetched successfully. + // |credit_card| and |cvc| include the information that allow the user to + // manually fill payment form. |card_image| is used for manual fallback + // bubble. + virtual void OnVirtualCardDataAvailable( + const CreditCard* credit_card, + const std::u16string& cvc, const gfx::Image& card_image = gfx::Image()); + // Called when some virtual card retrieval errors happened. Will show the + // error dialog with virtual card related messages. + virtual void ShowVirtualCardErrorDialog(bool is_permanent_error); + // Returns true if the Autofill Assistant UI is currently being shown. virtual bool IsAutofillAssistantShowing();
diff --git a/components/autofill/core/browser/browser_autofill_manager.cc b/components/autofill/core/browser/browser_autofill_manager.cc index f224c6d..e3121c1 100644 --- a/components/autofill/core/browser/browser_autofill_manager.cc +++ b/components/autofill/core/browser/browser_autofill_manager.cc
@@ -1460,9 +1460,6 @@ const CreditCard* credit_card, const std::u16string& cvc) { if (result != CreditCardFetchResult::kSuccess) { - if (credit_card && credit_card->record_type() == CreditCard::VIRTUAL_CARD) - client()->OnVirtualCardFetched(result); - driver()->RendererShouldClearPreviewedForm(); return; } @@ -1488,8 +1485,8 @@ // show the UI to help user to manually fill the form, if needed. if (credit_card->record_type() == CreditCard::VIRTUAL_CARD) { // TODO(crbug.com/1196021): Pass in real card image. - client()->OnVirtualCardFetched(CreditCardFetchResult::kSuccess, credit_card, - cvc, /*card_image=*/gfx::Image()); + client()->OnVirtualCardDataAvailable(credit_card, cvc, + /*card_image=*/gfx::Image()); } FillCreditCardForm(credit_card_query_id_, credit_card_form_,
diff --git a/components/autofill/core/browser/metrics/credit_card_form_event_logger.cc b/components/autofill/core/browser/metrics/credit_card_form_event_logger.cc index 1e668c6..7bad8d8 100644 --- a/components/autofill/core/browser/metrics/credit_card_form_event_logger.cc +++ b/components/autofill/core/browser/metrics/credit_card_form_event_logger.cc
@@ -69,6 +69,7 @@ card_selected_has_offer_); } + latest_selected_card_was_virtual_card_ = false; switch (credit_card.record_type()) { case CreditCard::LOCAL_CARD: case CreditCard::FULL_SERVER_CARD: @@ -83,6 +84,7 @@ } break; case CreditCard::VIRTUAL_CARD: + latest_selected_card_was_virtual_card_ = true; Log(FORM_EVENT_VIRTUAL_CARD_SUGGESTION_SELECTED, form); if (!has_logged_virtual_card_suggestion_selected_) { has_logged_virtual_card_suggestion_selected_ = true; @@ -203,11 +205,9 @@ } else if (logged_suggestion_filled_was_virtual_card_) { Log(FORM_EVENT_VIRTUAL_CARD_SUGGESTION_SUBMITTED_ONCE, form); - // TODO(crbug/1196021): Log BetterAuth.FlowEvents here as well. Virtual - // cards are still unmasked similarly to masked cards, they just return - // a different result. However, until virtual cards are wired up to be - // unmasked properly, certain flow variables will be missing and tests - // will be unhappy. + // Log BetterAuth.FlowEvents. + RecordCardUnmaskFlowEvent(current_authentication_flow_, + UnmaskAuthFlowEvent::kFormSubmitted); } else if (logged_suggestion_filled_was_server_data_) { Log(FORM_EVENT_SERVER_SUGGESTION_SUBMITTED_ONCE, form); } else { @@ -287,28 +287,33 @@ void CreditCardFormEventLogger::RecordCardUnmaskFlowEvent( UnmaskAuthFlowType flow, UnmaskAuthFlowEvent event) { - std::string suffix; + std::string flow_type_suffix; switch (flow) { case UnmaskAuthFlowType::kCvc: - suffix = ".Cvc"; + flow_type_suffix = ".Cvc"; break; case UnmaskAuthFlowType::kFido: - suffix = ".Fido"; + flow_type_suffix = ".Fido"; break; case UnmaskAuthFlowType::kCvcThenFido: - suffix = ".CvcThenFido"; + flow_type_suffix = ".CvcThenFido"; break; case UnmaskAuthFlowType::kCvcFallbackFromFido: - suffix = ".CvcFallbackFromFido"; + flow_type_suffix = ".CvcFallbackFromFido"; break; case UnmaskAuthFlowType::kNone: NOTREACHED(); - suffix = ""; + flow_type_suffix = ""; break; } + std::string card_type_suffix = + latest_selected_card_was_virtual_card_ ? ".VirtualCard" : ".ServerCard"; - base::UmaHistogramEnumeration("Autofill.BetterAuth.FlowEvents" + suffix, - event); + base::UmaHistogramEnumeration( + "Autofill.BetterAuth.FlowEvents" + flow_type_suffix, event); + base::UmaHistogramEnumeration( + "Autofill.BetterAuth.FlowEvents" + flow_type_suffix + card_type_suffix, + event); } bool CreditCardFormEventLogger::DoesCardHaveOffer(
diff --git a/components/autofill/core/browser/metrics/credit_card_form_event_logger.h b/components/autofill/core/browser/metrics/credit_card_form_event_logger.h index e4a3e94..84514f9 100644 --- a/components/autofill/core/browser/metrics/credit_card_form_event_logger.h +++ b/components/autofill/core/browser/metrics/credit_card_form_event_logger.h
@@ -71,6 +71,14 @@ // Logging when an authentication prompt is completed. void LogCardUnmaskAuthenticationPromptCompleted(UnmaskAuthFlowType flow); + // Allows mocking that a virtual card was selected, for unit tests that don't + // run the actual Autofill suggestions dropdown UI. + void set_latest_selected_card_was_virtual_card_for_testing( + bool latest_selected_card_was_virtual_card) { + latest_selected_card_was_virtual_card_ = + latest_selected_card_was_virtual_card; + } + protected: // FormEventLoggerBase pure-virtual overrides. void RecordPollSuggestions() override; @@ -104,6 +112,9 @@ bool has_logged_virtual_card_suggestion_selected_ = false; bool logged_suggestion_filled_was_masked_server_card_ = false; bool logged_suggestion_filled_was_virtual_card_ = false; + // If true, the most recent card to be selected as an Autofill suggestion was + // a virtual card. False for all other card types. + bool latest_selected_card_was_virtual_card_ = false; std::vector<Suggestion> suggestions_; bool has_eligible_offer_ = false; bool card_selected_has_offer_ = false;
diff --git a/components/autofill/core/browser/payments/credit_card_access_manager.cc b/components/autofill/core/browser/payments/credit_card_access_manager.cc index e48a523..5533b74 100644 --- a/components/autofill/core/browser/payments/credit_card_access_manager.cc +++ b/components/autofill/core/browser/payments/credit_card_access_manager.cc
@@ -651,11 +651,15 @@ ? CreditCardFetchResult::kTransientError : CreditCardFetchResult::kPermanentError; // If it is an virtual card retrieval error, we don't want to invoke the CVC - // authentication afterwards. Instead reset all states and notify accessor. + // authentication afterwards. Instead reset all states, notify accessor and + // invoke the error dialog. is_authentication_in_progress_ = false; unmask_auth_flow_type_ = UnmaskAuthFlowType::kNone; can_fetch_unmask_details_.Signal(); - accessor_->OnCreditCardFetched(result, card_.get()); + client_->ShowVirtualCardErrorDialog( + response.failure_type == + payments::FullCardRequest::VIRTUAL_CARD_RETRIEVAL_PERMANENT_FAILURE); + accessor_->OnCreditCardFetched(result); } else { // If it is an authentication error, start the CVC authentication process. unmask_auth_flow_type_ = UnmaskAuthFlowType::kCvcFallbackFromFido;
diff --git a/components/autofill/core/browser/payments/credit_card_access_manager.h b/components/autofill/core/browser/payments/credit_card_access_manager.h index 7b0b1fc..66a5e13 100644 --- a/components/autofill/core/browser/payments/credit_card_access_manager.h +++ b/components/autofill/core/browser/payments/credit_card_access_manager.h
@@ -162,6 +162,8 @@ NavigateFromPage_UnmaskedCardCacheResets); FRIEND_TEST_ALL_PREFIXES(CreditCardAccessManagerTest, PreflightCallRateLimited); + FRIEND_TEST_ALL_PREFIXES(CreditCardAccessManagerTest, + UnmaskAuthFlowEvent_AlsoLogsVirtualCardSubhistogram); friend class AutofillAssistantTest; friend class BrowserAutofillManagerTest; friend class AutofillMetricsTest; @@ -174,6 +176,16 @@ } #endif +#if defined(UNIT_TEST) + // Mocks that a virtual card was selected, so unit tests that don't run the + // actual Autofill suggestions dropdown UI can still follow their remaining + // steps under the guise of doing it for a virtual card. + void set_virtual_card_suggestion_selected_on_form_event_logger_for_testing() { + form_event_logger_->set_latest_selected_card_was_virtual_card_for_testing( + /*latest_selected_card_was_virtual_card=*/true); + } +#endif + // Returns whether or not unmasked card cache is empty. Exposed for testing. bool UnmaskedCardCacheIsEmpty();
diff --git a/components/autofill/core/browser/payments/credit_card_access_manager_unittest.cc b/components/autofill/core/browser/payments/credit_card_access_manager_unittest.cc index b9728b6..a75d304 100644 --- a/components/autofill/core/browser/payments/credit_card_access_manager_unittest.cc +++ b/components/autofill/core/browser/payments/credit_card_access_manager_unittest.cc
@@ -962,6 +962,7 @@ EXPECT_EQ(accessor_->result(), CreditCardFetchResult::kPermanentError); EXPECT_EQ(CreditCardFIDOAuthenticator::Flow::NONE_FLOW, GetFIDOAuthenticator()->current_flow()); + EXPECT_TRUE(autofill_client_.virtual_card_error_dialog_shown()); histogram_tester.ExpectUniqueSample( "Autofill.BetterAuth.WebauthnResult.ImmediateAuthentication", @@ -1223,6 +1224,67 @@ EXPECT_EQ(kTestCvc16, accessor_->cvc()); } +// Ensures that UnmaskAuthFlowEvents also log to a ".ServerCard" subhistogram +// when a masked server card is selected. +TEST_F(CreditCardAccessManagerTest, + UnmaskAuthFlowEvent_AlsoLogsServerCardSubhistogram) { + CreateServerCard(kTestGUID, kTestNumber); + CreditCard* card = credit_card_access_manager_->GetCreditCard(kTestGUID); + base::HistogramTester histogram_tester; + std::string flow_events_histogram_name = + "Autofill.BetterAuth.FlowEvents.Cvc.ServerCard"; + + credit_card_access_manager_->PrepareToFetchCreditCard(); + WaitForCallbacks(); + + credit_card_access_manager_->FetchCreditCard(card, accessor_->GetWeakPtr()); + histogram_tester.ExpectUniqueSample( + flow_events_histogram_name, + CreditCardFormEventLogger::UnmaskAuthFlowEvent::kPromptShown, 1); + + EXPECT_TRUE(GetRealPanForCVCAuth(AutofillClient::SUCCESS, kTestNumber)); + EXPECT_EQ(accessor_->result(), CreditCardFetchResult::kSuccess); + + histogram_tester.ExpectBucketCount( + flow_events_histogram_name, + CreditCardFormEventLogger::UnmaskAuthFlowEvent::kPromptCompleted, 1); +} + +// Ensures that UnmaskAuthFlowEvents also log to a ".VirtualCard" subhistogram +// when a virtual card is selected. +TEST_F(CreditCardAccessManagerTest, + UnmaskAuthFlowEvent_AlsoLogsVirtualCardSubhistogram) { + CreateServerCard(kTestGUID, kTestNumber); + CreditCard* card = credit_card_access_manager_->GetCreditCard(kTestGUID); + // This doesn't mock virtual card unmasking as well as + // BrowserAutofillManager::FillVirtualCardInformation(~) does, but all we + // really care about is that CreditCardFormEventLogger knows a VIRTUAL_CARD + // was selected first before server-based unmasking steps occur. + card->set_record_type(CreditCard::VIRTUAL_CARD); + credit_card_access_manager_ + ->set_virtual_card_suggestion_selected_on_form_event_logger_for_testing(); + base::HistogramTester histogram_tester; + std::string flow_events_histogram_name = + "Autofill.BetterAuth.FlowEvents.Cvc.VirtualCard"; + + credit_card_access_manager_->PrepareToFetchCreditCard(); + WaitForCallbacks(); + + credit_card_access_manager_->FetchCreditCard(card, accessor_->GetWeakPtr()); + histogram_tester.ExpectUniqueSample( + flow_events_histogram_name, + CreditCardFormEventLogger::UnmaskAuthFlowEvent::kPromptShown, 1); + + EXPECT_TRUE(GetRealPanForCVCAuth( + AutofillClient::SUCCESS, kTestNumber, /*fido_opt_in=*/false, + /*follow_with_fido_auth=*/false, /*is_virtual_card=*/true)); + EXPECT_EQ(accessor_->result(), CreditCardFetchResult::kSuccess); + + histogram_tester.ExpectBucketCount( + flow_events_histogram_name, + CreditCardFormEventLogger::UnmaskAuthFlowEvent::kPromptCompleted, 1); +} + #if defined(OS_ANDROID) // Ensures that the WebAuthn verification prompt is invoked after user opts in // on unmask card checkbox.
diff --git a/components/autofill/core/browser/test_autofill_client.cc b/components/autofill/core/browser/test_autofill_client.cc index dce60f78..1edcba9f6 100644 --- a/components/autofill/core/browser/test_autofill_client.cc +++ b/components/autofill/core/browser/test_autofill_client.cc
@@ -254,6 +254,10 @@ void TestAutofillClient::HideAutofillPopup(PopupHidingReason reason) {} +void TestAutofillClient::ShowVirtualCardErrorDialog(bool is_permanent_error) { + virtual_card_error_dialog_shown_ = true; +} + bool TestAutofillClient::IsAutocompleteEnabled() { return true; }
diff --git a/components/autofill/core/browser/test_autofill_client.h b/components/autofill/core/browser/test_autofill_client.h index 5124be7..26363fc 100644 --- a/components/autofill/core/browser/test_autofill_client.h +++ b/components/autofill/core/browser/test_autofill_client.h
@@ -141,6 +141,7 @@ void UpdatePopup(const std::vector<Suggestion>& suggestions, PopupType popup_type) override; void HideAutofillPopup(PopupHidingReason reason) override; + void ShowVirtualCardErrorDialog(bool is_permanent_error) override; bool IsAutocompleteEnabled() override; void PropagateAutofillPredictions( content::RenderFrameHost* rfh, @@ -221,6 +222,10 @@ return offer_to_save_credit_card_bubble_was_shown_.value(); } + bool virtual_card_error_dialog_shown() { + return virtual_card_error_dialog_shown_; + } + SaveCreditCardOptions get_save_credit_card_options() { return save_credit_card_options_.value(); } @@ -273,6 +278,8 @@ bool confirm_save_credit_card_locally_called_ = false; + bool virtual_card_error_dialog_shown_ = false; + // Populated if save was offered. True if bubble was shown, false otherwise. absl::optional<bool> offer_to_save_credit_card_bubble_was_shown_;
diff --git a/components/browser_ui/bottomsheet/android/internal/java/src/org/chromium/components/browser_ui/bottomsheet/BottomSheet.java b/components/browser_ui/bottomsheet/android/internal/java/src/org/chromium/components/browser_ui/bottomsheet/BottomSheet.java index 52aaaa43..c703e4b1 100644 --- a/components/browser_ui/bottomsheet/android/internal/java/src/org/chromium/components/browser_ui/bottomsheet/BottomSheet.java +++ b/components/browser_ui/bottomsheet/android/internal/java/src/org/chromium/components/browser_ui/bottomsheet/BottomSheet.java
@@ -33,6 +33,7 @@ import org.chromium.components.browser_ui.bottomsheet.BottomSheetController.StateChangeReason; import org.chromium.components.browser_ui.bottomsheet.internal.R; import org.chromium.ui.KeyboardVisibilityDelegate; +import org.chromium.ui.base.LocalizationUtils; import org.chromium.ui.util.AccessibilityUtil; /** @@ -182,7 +183,7 @@ super(context, atts); mShadowLength = context.getResources().getDimensionPixelSize( R.dimen.bottom_sheet_shadow_length); - setTranslationX(-mShadowLength); + setTranslationX((LocalizationUtils.isLayoutRtl() ? 1 : -1) * mShadowLength); setTranslationY(-mShadowLength); } @@ -1072,7 +1073,8 @@ private void sizeAndPositionSheetInParent() { int maxSheetWidth = getMaxSheetWidth(); getLayoutParams().width = maxSheetWidth; - setTranslationX((mContainerWidth - maxSheetWidth) / 2f); + setTranslationX((LocalizationUtils.isLayoutRtl() ? -1 : 1) + * (mContainerWidth - maxSheetWidth) / 2f); requestLayout(); }
diff --git a/components/download/internal/common/download_item_impl_unittest.cc b/components/download/internal/common/download_item_impl_unittest.cc index dbea485..c3dacd0 100644 --- a/components/download/internal/common/download_item_impl_unittest.cc +++ b/components/download/internal/common/download_item_impl_unittest.cc
@@ -2846,6 +2846,7 @@ ASSERT_FALSE(callback.is_null()); ASSERT_NE(nullptr, item->GetRenameHandler()); + ASSERT_FALSE(item->GetRerouteInfo().IsInitialized()); TestDownloadItemObserver observer(item); @@ -2854,10 +2855,12 @@ base::FilePath file_name(FILE_PATH_LITERAL("foo.txt")); DownloadItemRerouteInfo reroute_info; reroute_info.set_service_provider(RerouteProvider::GOOGLE_DRIVE); + reroute_info.mutable_box()->set_file_id("12345"); update_callback.Run(ProgressUpdate{file_name, reroute_info}); EXPECT_EQ(item->GetFileNameToReportUser(), file_name); EXPECT_EQ(DownloadItem::IN_PROGRESS, item->GetState()); + // Check that reroute info got updated. ASSERT_TRUE(item->GetRerouteInfo().IsInitialized()); EXPECT_EQ(reroute_info.SerializeAsString(), item->GetRerouteInfo().SerializeAsString()); @@ -2869,6 +2872,10 @@ task_environment_.RunUntilIdle(); EXPECT_EQ(item->GetTargetFilePath(), file_name); EXPECT_EQ(DownloadItem::COMPLETE, item->GetState()); + // Check that reroute info is intact. + ASSERT_TRUE(item->GetRerouteInfo().IsInitialized()); + EXPECT_EQ(reroute_info.SerializeAsString(), + item->GetRerouteInfo().SerializeAsString()); // Check that observers are updated. ASSERT_TRUE(observer.CheckAndResetDownloadUpdated());
diff --git a/components/enterprise/common/proto/download_item_reroute_info.proto b/components/enterprise/common/proto/download_item_reroute_info.proto index 27b8ea5..fb004127 100644 --- a/components/enterprise/common/proto/download_item_reroute_info.proto +++ b/components/enterprise/common/proto/download_item_reroute_info.proto
@@ -33,7 +33,7 @@ // provider. message DownloadItemRerouteInfo { // Each DownloadItem should only be rerouted to one of the providers. - optional FileSystemServiceProvider service_provider = 1; + required FileSystemServiceProvider service_provider = 1; oneof upload { BoxInfo box = 100;
diff --git a/components/error_page/content/browser/net_error_auto_reloader.cc b/components/error_page/content/browser/net_error_auto_reloader.cc index 5c1372d2..2a14b5f 100644 --- a/components/error_page/content/browser/net_error_auto_reloader.cc +++ b/components/error_page/content/browser/net_error_auto_reloader.cc
@@ -58,10 +58,12 @@ } base::TimeDelta GetNextReloadDelay(size_t reload_count) { - static const int kDelaysMs[] = {1000, 5000, 30000, 60000, - 300000, 600000, 1800000}; - return base::TimeDelta::FromMilliseconds( - kDelaysMs[std::min(reload_count, base::size(kDelaysMs) - 1)]); + static constexpr base::TimeDelta kDelays[] = { + base::TimeDelta::FromSeconds(1), base::TimeDelta::FromSeconds(5), + base::TimeDelta::FromSeconds(30), base::TimeDelta::FromMinutes(1), + base::TimeDelta::FromMinutes(5), base::TimeDelta::FromMinutes(10), + base::TimeDelta::FromMinutes(30)}; + return kDelays[std::min(reload_count, base::size(kDelays) - 1)]; } // Helper to block a navigation that would result in re-committing the same
diff --git a/components/exo/client_controlled_shell_surface_unittest.cc b/components/exo/client_controlled_shell_surface_unittest.cc index 09ceeee..e2c4361 100644 --- a/components/exo/client_controlled_shell_surface_unittest.cc +++ b/components/exo/client_controlled_shell_surface_unittest.cc
@@ -17,6 +17,7 @@ #include "ash/system/unified/unified_system_tray.h" #include "ash/test/test_widget_builder.h" #include "ash/wm/drag_window_resizer.h" +#include "ash/wm/full_restore/full_restore_controller.h" #include "ash/wm/overview/overview_controller.h" #include "ash/wm/pip/pip_positioner.h" #include "ash/wm/splitview/split_view_controller.h" @@ -49,8 +50,10 @@ #include "components/exo/test/exo_test_base.h" #include "components/exo/test/exo_test_helper.h" #include "components/exo/wm_helper.h" +#include "components/full_restore/full_restore_utils.h" #include "third_party/skia/include/utils/SkNoDrawCanvas.h" #include "ui/aura/client/aura_constants.h" +#include "ui/aura/client/window_parenting_client.h" #include "ui/aura/env.h" #include "ui/aura/window.h" #include "ui/aura/window_event_dispatcher.h" @@ -1784,6 +1787,54 @@ EXPECT_EQ(surface->window(), target); } +// Tests that a WideFrameView is created for an unparented ARC task and that the +// WideFrameView follows its respective surface when it is eventually parented. +// See crbug.com/1223135. +TEST_F(ClientControlledShellSurfaceTest, WideframeForUnparentedTasks) { + std::unique_ptr<Surface> surface(new Surface); + auto shell_surface = + exo_test_helper()->CreateClientControlledShellSurface(surface.get()); + + // Create a non-wide frame shell surface. + std::unique_ptr<Buffer> desktop_buffer( + new Buffer(exo_test_helper()->CreateGpuMemoryBuffer(gfx::Size(64, 64)))); + surface->Attach(desktop_buffer.get()); + surface->SetInputRegion(gfx::Rect(0, 0, 64, 64)); + shell_surface->SetGeometry(gfx::Rect(100, 0, 64, 64)); + surface->SetFrame(SurfaceFrameType::NORMAL); + surface->Commit(); + auto* wide_frame = shell_surface->wide_frame_for_test(); + ASSERT_FALSE(wide_frame); + + // Set the |full_restore::kParentToHiddenContainerKey| for the surface and + // reparent it, simulating the Full Restore process for an unparented ARC + // task. + aura::Window* window = shell_surface->GetWidget()->GetNativeWindow(); + window->SetProperty(full_restore::kParentToHiddenContainerKey, true); + aura::client::ParentWindowWithContext(window, + /*context=*/window->GetRootWindow(), + window->GetBoundsInScreen()); + + // Maximize the surface. The WideFrameView should be created and a crash + // should not occur. + shell_surface->SetMaximized(); + surface->Commit(); + const auto* hidden_container_parent = window->parent(); + wide_frame = shell_surface->wide_frame_for_test(); + EXPECT_TRUE(wide_frame); + EXPECT_EQ(hidden_container_parent, + wide_frame->GetWidget()->GetNativeWindow()->parent()); + + // Call the FullRestoreController, simulating the ARC task becoming ready. The + // surface should be reparented and the WideFrameView should follow it. + ash::FullRestoreController::Get()->OnARCTaskReadyForUnparentedWindow(window); + EXPECT_NE(hidden_container_parent, window->parent()); + wide_frame = shell_surface->wide_frame_for_test(); + EXPECT_TRUE(wide_frame); + EXPECT_EQ(window->parent(), + wide_frame->GetWidget()->GetNativeWindow()->parent()); +} + TEST_F(ClientControlledShellSurfaceTest, NoFrameOnModalContainer) { std::unique_ptr<Surface> surface(new Surface); auto shell_surface =
diff --git a/components/history/core/browser/expire_history_backend.cc b/components/history/core/browser/expire_history_backend.cc index e5ffda1..e6079be04 100644 --- a/components/history/core/browser/expire_history_backend.cc +++ b/components/history/core/browser/expire_history_backend.cc
@@ -474,6 +474,8 @@ // Delete content & context annotations associated with visit. main_db_->DeleteAnnotationsForVisit(visit.visit_id); + + notifier_->NotifyVisitDeleted(visit); } }
diff --git a/components/history/core/browser/expire_history_backend_unittest.cc b/components/history/core/browser/expire_history_backend_unittest.cc index 484c986..b3ea47c 100644 --- a/components/history/core/browser/expire_history_backend_unittest.cc +++ b/components/history/core/browser/expire_history_backend_unittest.cc
@@ -211,6 +211,7 @@ void NotifyURLsDeleted(DeletionInfo deletion_info) override { urls_deleted_notifications_.push_back(std::move(deletion_info)); } + void NotifyVisitDeleted(const VisitRow& visit) override {} }; // The example data consists of 4 visits. The middle two visits are to the
diff --git a/components/history/core/browser/history_backend.cc b/components/history/core/browser/history_backend.cc index 6f86309..9017009 100644 --- a/components/history/core/browser/history_backend.cc +++ b/components/history/core/browser/history_backend.cc
@@ -2407,6 +2407,10 @@ delegate_->NotifyURLsDeleted(std::move(deletion_info)); } +void HistoryBackend::NotifyVisitDeleted(const VisitRow& visit) { + tracker_.RemoveVisitById(visit.visit_id); +} + // Deleting -------------------------------------------------------------------- void HistoryBackend::DeleteAllHistory() { @@ -2458,6 +2462,8 @@ db_->GetStartDate(&first_recorded_time_); + tracker_.Clear(); + // Send out the notification that history is cleared. The in-memory database // will pick this up and clear itself. NotifyURLsDeleted(DeletionInfo::ForAllHistory());
diff --git a/components/history/core/browser/history_backend.h b/components/history/core/browser/history_backend.h index 49bfede7..f1bdf6c 100644 --- a/components/history/core/browser/history_backend.h +++ b/components/history/core/browser/history_backend.h
@@ -718,6 +718,7 @@ void NotifyURLsModified(const URLRows& changed_urls, bool is_from_expiration) override; void NotifyURLsDeleted(DeletionInfo deletion_info) override; + void NotifyVisitDeleted(const VisitRow& visit) override; // Deleting all history ------------------------------------------------------
diff --git a/components/history/core/browser/history_backend_notifier.h b/components/history/core/browser/history_backend_notifier.h index 8e9edd10e..df67e02 100644 --- a/components/history/core/browser/history_backend_notifier.h +++ b/components/history/core/browser/history_backend_notifier.h
@@ -14,8 +14,9 @@ namespace history { -// The HistoryBackendNotifier forwards notifications from the HistoryBackend's -// client to all the interested observers (in both history and main thread). +// The HistoryBackendNotifier (mostly) forwards notifications from the +// HistoryBackend's client to all the interested observers (in both history +// and main thread). class HistoryBackendNotifier { public: HistoryBackendNotifier() {} @@ -44,6 +45,9 @@ // deleted. // `deletion_info` describes the urls that have been removed from history. virtual void NotifyURLsDeleted(DeletionInfo deletion_info) = 0; + + // Called after a visit has been deleted. + virtual void NotifyVisitDeleted(const VisitRow& visit) = 0; }; } // namespace history
diff --git a/components/history/core/browser/history_backend_unittest.cc b/components/history/core/browser/history_backend_unittest.cc index c03932a..ddd0594 100644 --- a/components/history/core/browser/history_backend_unittest.cc +++ b/components/history/core/browser/history_backend_unittest.cc
@@ -170,6 +170,8 @@ using HistoryBackend::favicon_backend_; using HistoryBackend::recent_redirects_; + VisitTracker& visit_tracker() { return tracker_; } + private: ~TestHistoryBackend() override = default; }; @@ -3339,4 +3341,31 @@ } } +TEST_F(HistoryBackendTest, ExpireVisitDeletes) { + ASSERT_TRUE(backend_); + + GURL url("http://www.google.com/"); + const ContextID context_id = reinterpret_cast<ContextID>(0x1); + const int navigation_entry_id = 2; + HistoryAddPageArgs request( + url, base::Time::Now(), context_id, navigation_entry_id, GURL(), {}, + ui::PAGE_TRANSITION_TYPED, false, SOURCE_BROWSED, false, true, false); + backend_->AddPage(request); + URLRow url_row; + ASSERT_TRUE(backend_->GetURL(url, &url_row)); + + VisitVector visits; + ASSERT_TRUE(backend_->GetVisitsForURL( + backend_->db_->GetRowForURL(url, nullptr), &visits)); + ASSERT_EQ(1u, visits.size()); + + const VisitID visit_id = visits[0].visit_id; + EXPECT_EQ(visit_id, backend_->visit_tracker().GetLastVisit( + context_id, navigation_entry_id, url)); + + backend_->RemoveVisits(visits); + EXPECT_EQ(0, backend_->visit_tracker().GetLastVisit( + context_id, navigation_entry_id, url)); +} + } // namespace history
diff --git a/components/history/core/browser/history_types.h b/components/history/core/browser/history_types.h index 935382b..135abf0 100644 --- a/components/history/core/browser/history_types.h +++ b/components/history/core/browser/history_types.h
@@ -71,6 +71,11 @@ bool floc_allowed); ~VisitRow(); + // Compares two visits based on dates, for sorting. + bool operator<(const VisitRow& other) const { + return visit_time < other.visit_time; + } + // ID of this row (visit ID, used a a referrer for other visits). VisitID visit_id = 0; @@ -99,11 +104,6 @@ // Records whether the visit incremented the omnibox typed score. bool incremented_omnibox_typed_score = false; - // Compares two visits based on dates, for sorting. - bool operator<(const VisitRow& other) const { - return visit_time < other.visit_time; - } - // We allow the implicit copy constructor and operator=. };
diff --git a/components/history/core/browser/visit_tracker.cc b/components/history/core/browser/visit_tracker.cc index d96c6bc0..e04eb353 100644 --- a/components/history/core/browser/visit_tracker.cc +++ b/components/history/core/browser/visit_tracker.cc
@@ -6,6 +6,7 @@ #include <stddef.h> +#include <algorithm> namespace history { @@ -70,6 +71,24 @@ int nav_entry_id, const GURL& url, VisitID visit_id) { + if (IsEmpty()) { + // First visit, reset `visit_id_range_if_sorted_` to indicate visit ids are + // sorted. + visit_id_range_if_sorted_ = {visit_id, visit_id}; + } else if (are_transition_lists_sorted() && + visit_id > visit_id_range_if_sorted_->max_id) { + // Common case, visit ids increase. + visit_id_range_if_sorted_->max_id = visit_id; + } else { + // A visit was added with an id in the existing range. This generally + // happens in two scenarios: + // . Recent history was deleted. + // . The ids wrapped. + // These two scenarios are uncommon. Mark `visit_id_range_if_sorted_` as + // invalid so this fallsback to brute force. + visit_id_range_if_sorted_.reset(); + } + TransitionList& transitions = contexts_[context_id]; Transition t; @@ -79,19 +98,82 @@ transitions.push_back(t); CleanupTransitionList(&transitions); + +#if DCHECK_IS_ON() + // If are_transition_lists_sorted() is true, the ids should be sorted. + DCHECK(!are_transition_lists_sorted() || + std::is_sorted(transitions.begin(), transitions.end(), + TransitionVisitIdComparator())); +#endif +} + +void VisitTracker::RemoveVisitById(VisitID visit_id) { + if (IsEmpty()) + return; + + if (visit_id_range_if_sorted_ && + (visit_id < visit_id_range_if_sorted_->min_id || + visit_id > visit_id_range_if_sorted_->max_id)) { + return; + } + + const Transition transition_for_search = {{}, 0, visit_id}; + for (auto& id_and_list_pair : contexts_) { + TransitionList& transitions = id_and_list_pair.second; + auto iter = + FindTransitionListIteratorByVisitId(transitions, transition_for_search); + if (iter != transitions.end()) { + transitions.erase(iter); + if (transitions.empty()) + contexts_.erase(id_and_list_pair.first); + // visit-ids are unique. Once a match is found, stop. + // See description of `visit_id_range_if_sorted_` for details on why it + // is not recalculated here. + return; + } + } +} + +void VisitTracker::Clear() { + contexts_.clear(); } void VisitTracker::ClearCachedDataForContextID(ContextID context_id) { contexts_.erase(context_id); + if (contexts_.empty()) + visit_id_range_if_sorted_.reset(); } - void VisitTracker::CleanupTransitionList(TransitionList* transitions) { if (transitions->size() <= kMaxItemsInTransitionList) return; // Nothing to do. transitions->erase(transitions->begin(), transitions->begin() + kResizeBigTransitionListTo); + // See description of `visit_id_range_if_sorted_` for details on why it is not + // recalculated here. +} + +VisitTracker::TransitionList::const_iterator +VisitTracker::FindTransitionListIteratorByVisitId( + const TransitionList& transitions, + const Transition& transition_for_search) { + if (!are_transition_lists_sorted()) { + // If `transitions` are not sorted, then we can't use a binary search. This + // is uncommon enough, that we fallback to brute force. + for (auto iter = transitions.begin(); iter != transitions.end(); ++iter) { + if (iter->visit_id == transition_for_search.visit_id) + return iter; + } + return transitions.end(); + } + auto iter = + std::lower_bound(transitions.begin(), transitions.end(), + transition_for_search, TransitionVisitIdComparator()); + return iter != transitions.end() && + iter->visit_id == transition_for_search.visit_id + ? iter + : transitions.end(); } } // namespace history
diff --git a/components/history/core/browser/visit_tracker.h b/components/history/core/browser/visit_tracker.h index df3fba9..0462d64 100644 --- a/components/history/core/browser/visit_tracker.h +++ b/components/history/core/browser/visit_tracker.h
@@ -8,8 +8,8 @@ #include <map> #include <vector> -#include "base/macros.h" #include "components/history/core/browser/history_types.h" +#include "third_party/abseil-cpp/absl/types/optional.h" namespace history { @@ -21,24 +21,29 @@ class VisitTracker { public: VisitTracker(); + VisitTracker(const VisitTracker&) = delete; + VisitTracker& operator=(const VisitTracker&) = delete; ~VisitTracker(); - // Notifications ------------------------------------------------------------- - void AddVisit(ContextID context_id, int nav_entry_id, const GURL& url, VisitID visit_id); - // When a RenderProcessHost is destroyed, we want to clear out our saved - // transitions/visit IDs for it. + void RemoveVisitById(VisitID visit_id); + + // Removes all visits. + void Clear(); + + bool IsEmpty() const { return contexts_.empty(); } + + // Removes all visits added with the specified ContextID. void ClearCachedDataForContextID(ContextID context_id); // Querying ------------------------------------------------------------------ - // Returns the visit ID for the transition given information about the visit - // supplied by the renderer. We will return 0 if there is no appropriate - // referring visit. + // Returns the VisitID last supplied to AddVisit() matching the supplied + // parameters. Returns 0 if there is no matching visit. VisitID GetLastVisit(ContextID context_id, int nav_entry_id, const GURL& url); @@ -49,17 +54,49 @@ int nav_entry_id; // ID of the navigation entry. VisitID visit_id; // Visit ID generated by history. }; - typedef std::vector<Transition> TransitionList; + + // Compares Transition objects by visit_id. + struct TransitionVisitIdComparator { + bool operator()(const Transition& a, const Transition& b) { + return a.visit_id < b.visit_id; + } + }; + + struct VisitIdRange { + VisitID min_id; + VisitID max_id; + }; + + using TransitionList = std::vector<Transition>; // Expires oldish items in the given transition list. This keeps the list // size small by removing items that are unlikely to be needed, which is // important for GetReferrer which does brute-force searches of this list. void CleanupTransitionList(TransitionList* transitions); + // Returns true if AddVisit() was called with increasing visit-ids. In other + // words, if this is true then TransitionList are sorted by visit-id. The + // return value is undefined if IsEmpty() is true. + bool are_transition_lists_sorted() const { + return visit_id_range_if_sorted_.has_value(); + } + + TransitionList::const_iterator FindTransitionListIteratorByVisitId( + const TransitionList& transitions, + const Transition& transition_for_search); + // Maps render view hosts to lists of recent transitions. std::map<ContextID, TransitionList> contexts_; - DISALLOW_COPY_AND_ASSIGN(VisitTracker); + // Represents the range of visit ids encountered. This has a value if + // AddVisit() was called with increasing ids, which is generally the case. If + // this does not have a value, then AddVisit() was not called with + // increasing ids and each TransitionList is not sorted. + // + // This is not recalculated during removal as it would be expensive and is + // generally unnecessary (because AddVisit() is typically called with + // increasing visit-ids). + absl::optional<VisitIdRange> visit_id_range_if_sorted_; }; } // namespace history
diff --git a/components/history/core/browser/visit_tracker_unittest.cc b/components/history/core/browser/visit_tracker_unittest.cc index 9353781..d493387d 100644 --- a/components/history/core/browser/visit_tracker_unittest.cc +++ b/components/history/core/browser/visit_tracker_unittest.cc
@@ -26,21 +26,24 @@ VisitID referring_visit_id; }; +void AddVisitToTracker(const VisitToTest& test_data, VisitTracker* tracker) { + // Our host pointer is actually just an int, convert it (it will not get + // dereferenced). + ContextID context_id = reinterpret_cast<ContextID>(test_data.context_id_int); + + // Check the referrer for this visit. + VisitID ref_visit = tracker->GetLastVisit(context_id, test_data.nav_entry_id, + GURL(test_data.referrer)); + EXPECT_EQ(test_data.referring_visit_id, ref_visit); + + // Now add this visit. + tracker->AddVisit(context_id, test_data.nav_entry_id, GURL(test_data.url), + test_data.visit_id); +} + void RunTest(VisitTracker* tracker, VisitToTest* test, int test_count) { - for (int i = 0; i < test_count; i++) { - // Our host pointer is actually just an int, convert it (it will not get - // dereferenced). - ContextID context_id = reinterpret_cast<ContextID>(test[i].context_id_int); - - // Check the referrer for this visit. - VisitID ref_visit = tracker->GetLastVisit(context_id, test[i].nav_entry_id, - GURL(test[i].referrer)); - EXPECT_EQ(test[i].referring_visit_id, ref_visit); - - // Now add this visit. - tracker->AddVisit( - context_id, test[i].nav_entry_id, GURL(test[i].url), test[i].visit_id); - } + for (int i = 0; i < test_count; i++) + AddVisitToTracker(test[i], tracker); } } // namespace @@ -127,4 +130,68 @@ RunTest(&tracker, part2, base::size(part2)); } +TEST(VisitTracker, RemoveVisitById) { + VisitToTest test_simple[] = { + {1, 1, "http://www.google.com/", 2, "", 0}, + {1, 2, "http://www.google2.com/", 3, "", 0}, + {1, 3, "http://www.google3.com/", 4, "", 0}, + }; + + VisitTracker tracker; + RunTest(&tracker, test_simple, base::size(test_simple)); + + // Remove the first visit. + const VisitToTest& removed = test_simple[0]; + tracker.RemoveVisitById(removed.visit_id); + + // The first visit should no longer be in the tracker. + EXPECT_EQ(0, tracker.GetLastVisit( + reinterpret_cast<ContextID>(removed.context_id_int), + removed.nav_entry_id, GURL(removed.url))); + // The second and third should still be present. + EXPECT_EQ(test_simple[1].visit_id, + tracker.GetLastVisit( + reinterpret_cast<ContextID>(test_simple[1].context_id_int), + test_simple[1].nav_entry_id, GURL(test_simple[1].url))); + EXPECT_EQ(test_simple[2].visit_id, + tracker.GetLastVisit( + reinterpret_cast<ContextID>(test_simple[2].context_id_int), + test_simple[2].nav_entry_id, GURL(test_simple[2].url))); + + // Add back the first one, reusing the id and verify it is present. + AddVisitToTracker(removed, &tracker); + EXPECT_EQ( + removed.visit_id, + tracker.GetLastVisit(reinterpret_cast<ContextID>(removed.context_id_int), + removed.nav_entry_id, GURL(removed.url))); + + // Remove the first one again, and verify state. + tracker.RemoveVisitById(removed.visit_id); + EXPECT_EQ(0, tracker.GetLastVisit( + reinterpret_cast<ContextID>(removed.context_id_int), + removed.nav_entry_id, GURL(removed.url))); + EXPECT_EQ(test_simple[1].visit_id, + tracker.GetLastVisit( + reinterpret_cast<ContextID>(test_simple[1].context_id_int), + test_simple[1].nav_entry_id, GURL(test_simple[1].url))); + EXPECT_EQ(test_simple[2].visit_id, + tracker.GetLastVisit( + reinterpret_cast<ContextID>(test_simple[2].context_id_int), + test_simple[2].nav_entry_id, GURL(test_simple[2].url))); +} + +TEST(VisitTracker, Clear) { + VisitToTest test_simple[] = { + {1, 1, "http://www.google.com/", 2, "", 0}, + {1, 2, "http://www.google2.com/", 3, "", 0}, + {1, 3, "http://www.google3.com/", 4, "", 0}, + }; + + VisitTracker tracker; + RunTest(&tracker, test_simple, base::size(test_simple)); + EXPECT_FALSE(tracker.IsEmpty()); + tracker.Clear(); + EXPECT_TRUE(tracker.IsEmpty()); +} + } // namespace history
diff --git a/components/metrics/serialization/serialization_utils.cc b/components/metrics/serialization/serialization_utils.cc index 4ab151b..5091a7a 100644 --- a/components/metrics/serialization/serialization_utils.cc +++ b/components/metrics/serialization/serialization_utils.cc
@@ -15,6 +15,7 @@ #include "base/files/file_util.h" #include "base/files/scoped_file.h" #include "base/logging.h" +#include "base/metrics/histogram_functions.h" #include "base/numerics/safe_math.h" #include "base/strings/string_split.h" #include "base/strings/string_util.h" @@ -26,6 +27,25 @@ namespace metrics { namespace { +// Record number of reads on successful reads. Errors (file can't be opened, +// file can't be flock'ed) do not generate a sample. (If the file is found to +// be corrupt partway through, the number of successfully read entries is +// recorded.) +void RecordNumberOfReadsMetric(int num_reads) { + // 100,000 to match kMaxMessagesPerRead. + base::UmaHistogramCounts100000("UMA.ReadAndTruncateMetricsFromFile.ReadCount", + num_reads); +} + +// Record number of elements discarded because the file is too large. Errors +// (file can't be opened, file can't be flock'ed) do not generate a sample. +// (If the file is found to be corrupt partway through, the number of +// successfully read entries is recorded.) +void RecordNumberOfDiscardsMetric(int num_discards) { + base::UmaHistogramCounts1M( + "UMA.ReadAndTruncateMetricsFromFile.DiscardedCount", num_discards); +} + // Reads the next message from |file_descriptor| into |message|. // // |message| will be set to the empty string if no message could be read (EOF) @@ -89,6 +109,8 @@ } // namespace +const int SerializationUtils::kMaxMessagesPerRead = 100000; + std::unique_ptr<MetricSample> SerializationUtils::ParseSample( const std::string& sample) { if (sample.empty()) @@ -129,14 +151,20 @@ result = stat(filename.c_str(), &stat_buf); if (result < 0) { - if (errno != ENOENT) + if (errno == ENOENT) { + // File doesn't exist, nothing to collect. This isn't an error, it just + // means nothing on the ChromeOS side has written to the file yet. + RecordNumberOfReadsMetric(0); + RecordNumberOfDiscardsMetric(0); + } else { DPLOG(ERROR) << "bad metrics file stat: " << filename; - - // Nothing to collect---try later. + } return; } if (stat_buf.st_size == 0) { // Also nothing to collect. + RecordNumberOfReadsMetric(0); + RecordNumberOfDiscardsMetric(0); return; } base::ScopedFD fd(open(filename.c_str(), O_RDWR)); @@ -151,18 +179,37 @@ } // This processes all messages in the log. When all messages are - // read and processed, or an error occurs, truncate the file to zero size. - for (;;) { + // read and processed, or an error occurs, or we've read so many that the + // buffer is at risk of overflowing, truncate the file to zero size. + bool read_complete = false; + while (metrics->size() < kMaxMessagesPerRead) { std::string message; - if (!ReadMessage(fd.get(), &message)) + if (!ReadMessage(fd.get(), &message)) { + read_complete = true; break; + } std::unique_ptr<MetricSample> sample = ParseSample(message); if (sample) metrics->push_back(std::move(sample)); } + // If we hit kMaxMessagesPerRead, count the number of discarded messages for + // the discard metric, but don't add them to the vector to avoid memory + // overflow. + int num_discards = 0; + while (!read_complete) { + std::string message; + if (!ReadMessage(fd.get(), &message)) { + read_complete = true; + } else { + ++num_discards; + } + } + RecordNumberOfDiscardsMetric(num_discards); + RecordNumberOfReadsMetric(metrics->size()); + result = ftruncate(fd.get(), 0); if (result < 0) DPLOG(ERROR) << "truncate metrics log: " << filename;
diff --git a/components/metrics/serialization/serialization_utils.h b/components/metrics/serialization/serialization_utils.h index 9dca8f8b..8e0b1951 100644 --- a/components/metrics/serialization/serialization_utils.h +++ b/components/metrics/serialization/serialization_utils.h
@@ -17,6 +17,10 @@ // ChromeOS. namespace SerializationUtils { +// If there are more than 100,000 messages in the file, discard the remaining +// messages to avoid running out of memory. +extern const int kMaxMessagesPerRead; + // Deserializes a sample passed as a string and return a sample. // The return value will either be a scoped_ptr to a Metric sample (if the // deserialization was successful) or a nullptr scoped_ptr.
diff --git a/components/metrics/serialization/serialization_utils_unittest.cc b/components/metrics/serialization/serialization_utils_unittest.cc index 0c0545d..868e1e17 100644 --- a/components/metrics/serialization/serialization_utils_unittest.cc +++ b/components/metrics/serialization/serialization_utils_unittest.cc
@@ -8,15 +8,20 @@ #include <stdint.h> #include "base/check.h" +#include "base/files/file.h" #include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h" #include "base/strings/stringprintf.h" +#include "base/test/metrics/histogram_tester.h" #include "components/metrics/serialization/metric_sample.h" +#include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" namespace metrics { namespace { +using ::testing::IsEmpty; + class SerializationUtilsTest : public testing::Test { protected: SerializationUtilsTest() { @@ -186,6 +191,7 @@ } TEST_F(SerializationUtilsTest, WriteReadTest) { + base::HistogramTester histogram_tester; std::unique_ptr<MetricSample> hist = MetricSample::HistogramSample("myhist", 1, 2, 3, 4); std::unique_ptr<MetricSample> crash = MetricSample::CrashSample("mycrash"); @@ -216,6 +222,73 @@ int64_t size = 0; ASSERT_TRUE(base::GetFileSize(filepath(), &size)); ASSERT_EQ(0, size); + + histogram_tester.ExpectUniqueSample( + "UMA.ReadAndTruncateMetricsFromFile.ReadCount", 5, 1); + histogram_tester.ExpectUniqueSample( + "UMA.ReadAndTruncateMetricsFromFile.DiscardedCount", 0, 1); +} + +TEST_F(SerializationUtilsTest, TooManyMessagesTest) { + base::HistogramTester histogram_tester; + std::unique_ptr<MetricSample> hist = + MetricSample::HistogramSample("myhist", 1, 2, 3, 4); + + constexpr int kDiscardedSamples = 50000; + for (int i = 0; + i < SerializationUtils::kMaxMessagesPerRead + kDiscardedSamples; i++) { + SerializationUtils::WriteMetricToFile(*hist.get(), filename()); + } + + std::vector<std::unique_ptr<MetricSample>> vect; + SerializationUtils::ReadAndTruncateMetricsFromFile(filename(), &vect); + ASSERT_EQ(SerializationUtils::kMaxMessagesPerRead, + static_cast<int>(vect.size())); + for (auto& sample : vect) { + ASSERT_NE(nullptr, sample.get()); + EXPECT_TRUE(hist->IsEqual(*sample)); + } + + int64_t size = 0; + ASSERT_TRUE(base::GetFileSize(filepath(), &size)); + ASSERT_EQ(0, size); + histogram_tester.ExpectUniqueSample( + "UMA.ReadAndTruncateMetricsFromFile.ReadCount", + SerializationUtils::kMaxMessagesPerRead, 1); + histogram_tester.ExpectUniqueSample( + "UMA.ReadAndTruncateMetricsFromFile.DiscardedCount", kDiscardedSamples, + 1); +} + +TEST_F(SerializationUtilsTest, ReadEmptyFile) { + base::HistogramTester histogram_tester; + + { + // Create a zero-length file and then close file descriptor. + base::File file(filepath(), + base::File::FLAG_CREATE | base::File::FLAG_WRITE); + ASSERT_TRUE(file.IsValid()); + } + + std::vector<std::unique_ptr<MetricSample>> vect; + SerializationUtils::ReadAndTruncateMetricsFromFile(filename(), &vect); + EXPECT_THAT(vect, IsEmpty()); + histogram_tester.ExpectUniqueSample( + "UMA.ReadAndTruncateMetricsFromFile.ReadCount", 0, 1); + histogram_tester.ExpectUniqueSample( + "UMA.ReadAndTruncateMetricsFromFile.DiscardedCount", 0, 1); +} + +TEST_F(SerializationUtilsTest, ReadNonExistentFile) { + base::DeleteFile(filepath()); // Ensure non-existance. + base::HistogramTester histogram_tester; + std::vector<std::unique_ptr<MetricSample>> vect; + SerializationUtils::ReadAndTruncateMetricsFromFile(filename(), &vect); + EXPECT_THAT(vect, IsEmpty()); + histogram_tester.ExpectUniqueSample( + "UMA.ReadAndTruncateMetricsFromFile.ReadCount", 0, 1); + histogram_tester.ExpectUniqueSample( + "UMA.ReadAndTruncateMetricsFromFile.DiscardedCount", 0, 1); } } // namespace
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 e6eb5f9..205e51c8 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
@@ -258,7 +258,9 @@ if (PageInfoFeatures.PAGE_INFO_HISTORY.isEnabled()) { mHistoryController = mDelegate.createHistoryController( this, mView.getHistoryRowView(), mFullUrl.getHost()); - setupForgetSiteButton(mView.getForgetSiteButton()); + // TODO(crbug.com/1173154): Setup forget this site button after history delete is + // implemented. + // setupForgetSiteButton(mView.getForgetSiteButton()); } mPermissionParamsListBuilder = new PermissionParamsListBuilder(mContext, mWindowAndroid);
diff --git a/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoView.java b/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoView.java index b8a48a6..d8a4bc4 100644 --- a/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoView.java +++ b/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoView.java
@@ -76,6 +76,7 @@ private void initHistory() { mHistoryRow = findViewById(R.id.page_info_history_row); mForgetSiteButton = findViewById(R.id.page_info_forget_site_button); + initializePageInfoViewChild(mForgetSiteButton, false, null); } private void initHttpsImageCompression(Params params) {
diff --git a/components/password_manager/core/browser/password_reuse_detector.cc b/components/password_manager/core/browser/password_reuse_detector.cc index facd6d8..66124d0a 100644 --- a/components/password_manager/core/browser/password_reuse_detector.cc +++ b/components/password_manager/core/browser/password_reuse_detector.cc
@@ -89,22 +89,6 @@ PasswordReuseDetector::~PasswordReuseDetector() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - if (profile_store_) - profile_store_->RemoveObserver(this); - if (account_store_) - account_store_->RemoveObserver(this); -} - -void PasswordReuseDetector::Init( - scoped_refptr<PasswordStoreInterface> profile_store, - scoped_refptr<PasswordStoreInterface> account_store) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - DCHECK(profile_store); - profile_store_ = std::move(profile_store); - profile_store_->AddObserver(this); - account_store_ = std::move(account_store); - if (account_store_) - account_store_->AddObserver(this); } void PasswordReuseDetector::OnGetPasswordStoreResults( @@ -114,6 +98,18 @@ AddPassword(*form); } +void PasswordReuseDetector::OnLoginsChanged( + const password_manager::PasswordStoreChangeList& changes) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + for (const auto& change : changes) { + if (change.type() == PasswordStoreChange::ADD || + change.type() == PasswordStoreChange::UPDATE) + AddPassword(change.form()); + if (change.type() == PasswordStoreChange::REMOVE) + RemovePassword(change.form()); + } +} + void PasswordReuseDetector::ClearCachedAccountStorePasswords() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); for (auto& key_value : passwords_with_matching_reused_credentials_) { @@ -326,23 +322,6 @@ }); } -void PasswordReuseDetector::OnLoginsChanged( - password_manager::PasswordStoreInterface* store, - const password_manager::PasswordStoreChangeList& changes) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - for (const auto& change : changes) { - if (change.type() == PasswordStoreChange::ADD || - change.type() == PasswordStoreChange::UPDATE) - AddPassword(change.form()); - if (change.type() == PasswordStoreChange::REMOVE) - RemovePassword(change.form()); - } -} - -void PasswordReuseDetector::OnLoginsRetained( - PasswordStoreInterface* store, - const std::vector<PasswordForm>& retained_passwords) {} - void PasswordReuseDetector::AddPassword(const PasswordForm& form) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (form.password_value.size() < kMinPasswordLengthToCheck)
diff --git a/components/password_manager/core/browser/password_reuse_detector.h b/components/password_manager/core/browser/password_reuse_detector.h index de088014..7161aba 100644 --- a/components/password_manager/core/browser/password_reuse_detector.h +++ b/components/password_manager/core/browser/password_reuse_detector.h
@@ -16,7 +16,6 @@ #include "components/password_manager/core/browser/hash_password_manager.h" #include "components/password_manager/core/browser/password_form.h" #include "components/password_manager/core/browser/password_store_change.h" -#include "components/password_manager/core/browser/password_store_interface.h" #include "third_party/abseil-cpp/absl/types/optional.h" namespace password_manager { @@ -45,13 +44,10 @@ // It receives saved passwords through PasswordStoreConsumer interface. // It stores passwords in memory and CheckReuse() can be used for finding // a password reuse. -class PasswordReuseDetector : public PasswordStoreInterface::Observer { +class PasswordReuseDetector { public: PasswordReuseDetector(); - ~PasswordReuseDetector() override; - - void Init(scoped_refptr<PasswordStoreInterface> profile_store, - scoped_refptr<PasswordStoreInterface> account_store = nullptr); + ~PasswordReuseDetector(); PasswordReuseDetector(const PasswordReuseDetector&) = delete; PasswordReuseDetector& operator=(const PasswordReuseDetector&) = delete; @@ -59,6 +55,9 @@ void OnGetPasswordStoreResults( std::vector<std::unique_ptr<PasswordForm>> results); + void OnLoginsChanged( + const password_manager::PasswordStoreChangeList& changes); + // Clears all the cached passwords which are stored on the account store. void ClearCachedAccountStorePasswords(); @@ -101,14 +100,6 @@ using passwords_iterator = PasswordsReusedCredentialsMap::const_iterator; - // PasswordStoreInterface::Observer - void OnLoginsChanged( - password_manager::PasswordStoreInterface* store, - const password_manager::PasswordStoreChangeList& changes) override; - void OnLoginsRetained( - PasswordStoreInterface* store, - const std::vector<PasswordForm>& retained_passwords) override; - // Add password from |form| to |passwords_| and // |passwords_with_matching_reused_credentials_|. void AddPassword(const PasswordForm& form); @@ -162,12 +153,6 @@ // sequence. SEQUENCE_CHECKER(sequence_checker_); - scoped_refptr<PasswordStoreInterface> profile_store_ - GUARDED_BY_CONTEXT(sequence_checker_); - - scoped_refptr<PasswordStoreInterface> account_store_ - GUARDED_BY_CONTEXT(sequence_checker_); - // Contains all passwords. // A key is a password. // A value is a set of pairs of signon_realms and username on which the
diff --git a/components/password_manager/core/browser/password_reuse_detector_unittest.cc b/components/password_manager/core/browser/password_reuse_detector_unittest.cc index 2bc5e48..38ff3bd0 100644 --- a/components/password_manager/core/browser/password_reuse_detector_unittest.cc +++ b/components/password_manager/core/browser/password_reuse_detector_unittest.cc
@@ -221,8 +221,7 @@ PasswordReuseDetector reuse_detector; PasswordStoreChangeList changes = GetChangeList(type, GetForms(GetTestDomainsPasswords())); - static_cast<PasswordStoreInterface::Observer*>(&reuse_detector) - ->OnLoginsChanged(nullptr, changes); + reuse_detector.OnLoginsChanged(changes); MockPasswordReuseDetectorConsumer mockConsumer; if (type == PasswordStoreChange::REMOVE) { @@ -248,8 +247,7 @@ // Add the test domain passwords into the saved passwords map. PasswordStoreChangeList add_changes = GetChangeList(PasswordStoreChange::ADD, login_credentials); - static_cast<PasswordStoreInterface::Observer*>(&reuse_detector) - ->OnLoginsChanged(nullptr, add_changes); + reuse_detector.OnLoginsChanged(add_changes); const std::vector<MatchingReusedCredential> expected_matching_reused_credentials = { @@ -276,8 +274,7 @@ // Remove the test domain passwords from the saved passwords map. PasswordStoreChangeList remove_changes = GetChangeList(PasswordStoreChange::REMOVE, login_credentials); - static_cast<PasswordStoreInterface::Observer*>(&reuse_detector) - ->OnLoginsChanged(nullptr, remove_changes); + reuse_detector.OnLoginsChanged(remove_changes); EXPECT_CALL(mockConsumer, OnReuseCheckDone(/*is_reuse_found=*/false, _, _, _, _)); // The stored credentials were removed so no reuse should be found. @@ -298,8 +295,7 @@ // Add the test domain passwords into the saved passwords map. PasswordStoreChangeList add_changes = GetChangeList(PasswordStoreChange::ADD, login_credentials); - static_cast<PasswordStoreInterface::Observer*>(&reuse_detector) - ->OnLoginsChanged(nullptr, add_changes); + reuse_detector.OnLoginsChanged(add_changes); std::vector<MatchingReusedCredential> expected_matching_reused_credentials = { {"https://example1.com", u"example1Username", @@ -326,8 +322,7 @@ PasswordStoreChangeList remove_changes = GetChangeList( PasswordStoreChange::REMOVE, GetForms({{"https://example1.com", "example1Username", "secretword"}})); - static_cast<PasswordStoreInterface::Observer*>(&reuse_detector) - ->OnLoginsChanged(nullptr, remove_changes); + reuse_detector.OnLoginsChanged(remove_changes); expected_matching_reused_credentials = {{"https://example2.com", u"example2Username", PasswordForm::Store::kProfileStore}}; @@ -347,8 +342,7 @@ remove_changes = GetChangeList( PasswordStoreChange::REMOVE, GetForms({{"https://example2.com", "example2Username", "secretword"}})); - static_cast<PasswordStoreInterface::Observer*>(&reuse_detector) - ->OnLoginsChanged(nullptr, remove_changes); + reuse_detector.OnLoginsChanged(remove_changes); EXPECT_CALL(mockConsumer, OnReuseCheckDone( /*is_reuse_found=*/false, _, _, _, _)); reuse_detector.CheckReuse(u"123secretword", "https://evil.com", @@ -756,8 +750,7 @@ PasswordStoreChangeList remove_changes; remove_changes.push_back( PasswordStoreChange(PasswordStoreChange::REMOVE, account_store_form)); - static_cast<PasswordStoreInterface::Observer*>(&reuse_detector) - ->OnLoginsChanged(nullptr, remove_changes); + reuse_detector.OnLoginsChanged(remove_changes); EXPECT_CALL( mockConsumer,
diff --git a/components/password_manager/core/browser/password_reuse_manager.h b/components/password_manager/core/browser/password_reuse_manager.h index a944697..c65bdcc 100644 --- a/components/password_manager/core/browser/password_reuse_manager.h +++ b/components/password_manager/core/browser/password_reuse_manager.h
@@ -17,6 +17,7 @@ namespace password_manager { +class PasswordStoreInterface; class PasswordStoreSigninNotifier; using PasswordHashDataList = absl::optional<std::vector<PasswordHashData>>;
diff --git a/components/password_manager/core/browser/password_reuse_manager_impl.cc b/components/password_manager/core/browser/password_reuse_manager_impl.cc index 03b11e9..abcc40238 100644 --- a/components/password_manager/core/browser/password_reuse_manager_impl.cc +++ b/components/password_manager/core/browser/password_reuse_manager_impl.cc
@@ -77,6 +77,15 @@ PasswordReuseManagerImpl::~PasswordReuseManagerImpl() = default; void PasswordReuseManagerImpl::Shutdown() { + if (profile_store_) { + profile_store_->RemoveObserver(this); + profile_store_.reset(); + } + if (account_store_) { + account_store_->RemoveObserver(this); + profile_store_.reset(); + } + if (notifier_) notifier_->UnsubscribeFromSigninEvents(); @@ -103,13 +112,14 @@ DCHECK(profile_store); reuse_detector_ = new PasswordReuseDetector(); - ScheduleTask(base::BindOnce( - &PasswordReuseDetector::Init, base::Unretained(reuse_detector_), - base::RetainedRef(profile_store), base::RetainedRef(account_store))); - profile_store->GetAutofillableLogins(/*consumer=*/this); + + profile_store_ = profile_store; + profile_store_->AddObserver(this); + profile_store_->GetAutofillableLogins(/*consumer=*/this); if (account_store) { - account_store->GetAutofillableLogins(/*consumer=*/this); account_store_ = account_store; + account_store_->AddObserver(this); + account_store_->GetAutofillableLogins(/*consumer=*/this); } } @@ -334,6 +344,17 @@ std::move(results))); } +void PasswordReuseManagerImpl::OnLoginsChanged( + password_manager::PasswordStoreInterface* store, + const password_manager::PasswordStoreChangeList& changes) { + ScheduleTask(base::BindOnce(&PasswordReuseDetector::OnLoginsChanged, + base::Unretained(reuse_detector_), changes)); +} + +void PasswordReuseManagerImpl::OnLoginsRetained( + PasswordStoreInterface* store, + const std::vector<PasswordForm>& retained_passwords) {} + bool PasswordReuseManagerImpl::ScheduleTask(base::OnceClosure task) { return background_task_runner_ && background_task_runner_->PostTask(FROM_HERE, std::move(task));
diff --git a/components/password_manager/core/browser/password_reuse_manager_impl.h b/components/password_manager/core/browser/password_reuse_manager_impl.h index 99c79ef..ebcf8e4 100644 --- a/components/password_manager/core/browser/password_reuse_manager_impl.h +++ b/components/password_manager/core/browser/password_reuse_manager_impl.h
@@ -10,11 +10,13 @@ #include "base/sequenced_task_runner.h" #include "components/password_manager/core/browser/password_reuse_manager.h" #include "components/password_manager/core/browser/password_store_consumer.h" +#include "components/password_manager/core/browser/password_store_interface.h" namespace password_manager { class PasswordReuseManagerImpl : public PasswordReuseManager, - public PasswordStoreConsumer { + public PasswordStoreConsumer, + public PasswordStoreInterface::Observer { public: PasswordReuseManagerImpl(); ~PasswordReuseManagerImpl() override; @@ -61,6 +63,14 @@ void OnGetPasswordStoreResults( std::vector<std::unique_ptr<PasswordForm>> results) override; + // Implements PasswordStoreInterface::Observer + void OnLoginsChanged( + password_manager::PasswordStoreInterface* store, + const password_manager::PasswordStoreChangeList& changes) override; + void OnLoginsRetained( + PasswordStoreInterface* store, + const std::vector<PasswordForm>& retained_passwords) override; + // Saves |username| and a hash of |password| for password reuse checking. // |is_gaia_password| indicates if it is a Gaia account. |event| is used for // metric logging. |is_primary_account| is whether account belong to the @@ -82,6 +92,8 @@ PrefService* prefs_ = nullptr; + scoped_refptr<PasswordStoreInterface> profile_store_; + scoped_refptr<PasswordStoreInterface> account_store_; // The 'reuse_detector_', owned by this PasswordReuseManager instance, but
diff --git a/components/password_manager/core/browser/password_store.cc b/components/password_manager/core/browser/password_store.cc index 4ee2bce..3de21af3 100644 --- a/components/password_manager/core/browser/password_store.cc +++ b/components/password_manager/core/browser/password_store.cc
@@ -70,8 +70,7 @@ } // namespace -PasswordStore::PasswordStore() - : observers_(new base::ObserverListThreadSafe<Observer>()) {} +PasswordStore::PasswordStore() = default; bool PasswordStore::Init(PrefService* prefs, base::RepeatingClosure sync_enabled_or_disabled_cb) { @@ -324,11 +323,11 @@ } void PasswordStore::AddObserver(Observer* observer) { - observers_->AddObserver(observer); + observers_.AddObserver(observer); } void PasswordStore::RemoveObserver(Observer* observer) { - observers_->RemoveObserver(observer); + observers_.RemoveObserver(observer); } bool PasswordStore::ScheduleTask(base::OnceClosure task) { @@ -405,8 +404,10 @@ const PasswordStoreChangeList& changes) { DCHECK(background_task_runner_->RunsTasksInCurrentSequence()); if (!changes.empty()) { - observers_->Notify(FROM_HERE, &Observer::OnLoginsChanged, - base::RetainedRef(this), changes); + main_task_runner_->PostTask( + FROM_HERE, + base::BindOnce(&PasswordStore::NotifyLoginsChangedOnMainSequence, this, + changes)); } } @@ -425,6 +426,18 @@ "passwords", "PasswordStore::InitOnBackgroundSequence", this); } +void PasswordStore::NotifyLoginsChangedOnMainSequence( + const PasswordStoreChangeList& changes) { + DCHECK(main_task_runner_->RunsTasksInCurrentSequence()); + + if (changes.empty()) + return; + + for (auto& observer : observers_) { + observer.OnLoginsChanged(this, changes); + } +} + void PasswordStore::PostLoginsTaskAndReplyToConsumerWithResult( PasswordStoreConsumer* consumer, LoginsTask task) {
diff --git a/components/password_manager/core/browser/password_store.h b/components/password_manager/core/browser/password_store.h index dfec5c7..c8bc56c6 100644 --- a/components/password_manager/core/browser/password_store.h +++ b/components/password_manager/core/browser/password_store.h
@@ -17,7 +17,7 @@ #include "base/gtest_prod_util.h" #include "base/macros.h" #include "base/memory/scoped_refptr.h" -#include "base/observer_list_threadsafe.h" +#include "base/observer_list.h" #include "base/sequenced_task_runner.h" #include "base/time/time.h" #include "base/types/strong_alias.h" @@ -313,8 +313,7 @@ GetSyncControllerDelegateOnBackgroundSequence() = 0; // Called by *Internal() methods once the underlying data-modifying operation - // has been performed. Notifies observers that password store data may have - // been changed. + // has been performed. void NotifyLoginsChanged(const PasswordStoreChangeList& changes) override; // Invokes callback and notifies observers if there was a change to the list @@ -347,6 +346,10 @@ // |init_status_|. void OnInitCompleted(bool success); + // Notifies observers that password store data may have been changed. + void NotifyLoginsChangedOnMainSequence( + const PasswordStoreChangeList& changes); + // Schedules the given |task| to be run on the PasswordStore's TaskRunner. // Invokes |consumer|->OnGetPasswordStoreResults() on the caller's thread with // the result. @@ -481,7 +484,7 @@ scoped_refptr<base::SequencedTaskRunner> background_task_runner_; // The observers. - scoped_refptr<base::ObserverListThreadSafe<Observer>> observers_; + base::ObserverList<Observer, /*check_empty=*/true> observers_; std::unique_ptr<AffiliatedMatchHelper> affiliated_match_helper_;
diff --git a/components/password_manager/core/browser/password_store_interface.h b/components/password_manager/core/browser/password_store_interface.h index d0e8808..f04a1ed 100644 --- a/components/password_manager/core/browser/password_store_interface.h +++ b/components/password_manager/core/browser/password_store_interface.h
@@ -7,6 +7,7 @@ #include <vector> +#include "base/observer_list_types.h" #include "components/keyed_service/core/refcounted_keyed_service.h" #include "components/password_manager/core/browser/password_form_digest.h" #include "components/password_manager/core/browser/password_store_change.h" @@ -30,7 +31,7 @@ // An interface used to notify clients (observers) of this object that data in // the password store has changed. Register the observer via // `PasswordStore::AddObserver`. - class Observer { + class Observer : public base::CheckedObserver { public: // Notifies the observer that password data changed (e.g. added or changed). // Don't rely on `changes` containing REMOVED entries. Certain stores don't @@ -48,9 +49,6 @@ virtual void OnLoginsRetained( PasswordStoreInterface* store, const std::vector<PasswordForm>& retained_passwords) = 0; - - protected: - virtual ~Observer() = default; }; // Returns true iff initialization was successful.
diff --git a/components/password_manager/core/browser/password_store_unittest.cc b/components/password_manager/core/browser/password_store_unittest.cc index c6038c8..b27d6dbc 100644 --- a/components/password_manager/core/browser/password_store_unittest.cc +++ b/components/password_manager/core/browser/password_store_unittest.cc
@@ -509,6 +509,7 @@ store->AddInsecureCredential(insecure_credential); WaitForPasswordStore(); + store->RemoveObserver(&mock_observer); store->ShutdownOnUIThread(); } @@ -552,6 +553,7 @@ RemoveInsecureCredentialsReason::kRemove); WaitForPasswordStore(); + store->RemoveObserver(&mock_observer); store->ShutdownOnUIThread(); } @@ -1163,6 +1165,8 @@ UnorderedPasswordFormElementsAre(&all_credentials))); store->GetAllLogins(&mock_consumer); WaitForPasswordStore(); + + store->RemoveObserver(&mock_observer); store->ShutdownOnUIThread(); }
diff --git a/components/pdf/renderer/BUILD.gn b/components/pdf/renderer/BUILD.gn index 4b05f22eb..29cce46 100644 --- a/components/pdf/renderer/BUILD.gn +++ b/components/pdf/renderer/BUILD.gn
@@ -13,6 +13,7 @@ "internal_plugin_renderer_helpers.h", "pdf_accessibility_tree.h", "pdf_ax_action_target.h", + "pdf_internal_plugin_delegate.h", "pepper_pdf_host.h", ] @@ -20,6 +21,7 @@ "internal_plugin_renderer_helpers.cc", "pdf_accessibility_tree.cc", "pdf_ax_action_target.cc", + "pdf_internal_plugin_delegate.cc", "pepper_pdf_host.cc", ] @@ -31,6 +33,7 @@ "//content/public/common", "//gin", "//ipc", + "//pdf:accessibility_structs", "//pdf:buildflags", "//pdf:features", "//pdf:pdf_view_web_plugin",
diff --git a/components/pdf/renderer/DEPS b/components/pdf/renderer/DEPS index a9ba6f8..2c04718 100644 --- a/components/pdf/renderer/DEPS +++ b/components/pdf/renderer/DEPS
@@ -3,6 +3,7 @@ "+content/public/test", "+components/strings/grit/components_strings.h", "+mojo/public/cpp/bindings", + "+pdf/accessibility_structs.h", "+pdf/buildflags.h", "+pdf/mojom/pdf.mojom.h", "+pdf/pdf_features.h",
diff --git a/components/pdf/renderer/internal_plugin_renderer_helpers.cc b/components/pdf/renderer/internal_plugin_renderer_helpers.cc index 75d5cee6..ebef02d 100644 --- a/components/pdf/renderer/internal_plugin_renderer_helpers.cc +++ b/components/pdf/renderer/internal_plugin_renderer_helpers.cc
@@ -8,6 +8,7 @@ #include <utility> #include "base/feature_list.h" +#include "components/pdf/renderer/pdf_internal_plugin_delegate.h" #include "content/public/renderer/render_frame.h" #include "mojo/public/cpp/bindings/associated_remote.h" #include "pdf/buildflags.h" @@ -23,7 +24,7 @@ blink::WebPlugin* MaybeCreateInternalPlugin( content::RenderFrame* render_frame, - std::unique_ptr<chrome_pdf::PdfViewWebPlugin::PrintClient> print_client, + std::unique_ptr<PdfInternalPluginDelegate> delegate, blink::WebPluginParams& params) { // For a PDF plugin, `params.url` holds the plugin's stream URL. If `params` // contains an 'original-url' attribute, reset `params.url` with its original @@ -47,8 +48,8 @@ mojo::AssociatedRemote<pdf::mojom::PdfService> pdf_service_remote; render_frame->GetRemoteAssociatedInterfaces()->GetInterface( pdf_service_remote.BindNewEndpointAndPassReceiver()); - return new chrome_pdf::PdfViewWebPlugin(std::move(pdf_service_remote), - std::move(print_client), params); + return new chrome_pdf::PdfViewWebPlugin( + std::move(pdf_service_remote), delegate->CreatePrintClient(), params); #else // !BUILDFLAG(ENABLE_PDF_UNSEASONED) return nullptr; #endif // BUILDFLAG(ENABLE_PDF_UNSEASONED)
diff --git a/components/pdf/renderer/internal_plugin_renderer_helpers.h b/components/pdf/renderer/internal_plugin_renderer_helpers.h index 93cedf3..6e50140 100644 --- a/components/pdf/renderer/internal_plugin_renderer_helpers.h +++ b/components/pdf/renderer/internal_plugin_renderer_helpers.h
@@ -7,8 +7,6 @@ #include <memory> -#include "pdf/pdf_view_web_plugin.h" - namespace blink { class WebPlugin; struct WebPluginParams; @@ -20,16 +18,16 @@ namespace pdf { +class PdfInternalPluginDelegate; + // Tries to create an instance of the internal PDF plugin, returning `nullptr` // if the caller should create a Pepper plugin instance instead. // -// `print_client` is optional, and may be `nullptr`. -// // Note that `blink::WebPlugin` has a special life cycle, so it's returned as a // raw pointer here. blink::WebPlugin* MaybeCreateInternalPlugin( content::RenderFrame* render_frame, - std::unique_ptr<chrome_pdf::PdfViewWebPlugin::PrintClient> print_client, + std::unique_ptr<PdfInternalPluginDelegate> delegate, blink::WebPluginParams& params); } // namespace pdf
diff --git a/components/pdf/renderer/pdf_accessibility_tree.cc b/components/pdf/renderer/pdf_accessibility_tree.cc index 60225873..8eb64107 100644 --- a/components/pdf/renderer/pdf_accessibility_tree.cc +++ b/components/pdf/renderer/pdf_accessibility_tree.cc
@@ -19,11 +19,13 @@ #include "content/public/renderer/render_thread.h" #include "content/public/renderer/render_view.h" #include "content/public/renderer/renderer_ppapi_host.h" +#include "pdf/accessibility_structs.h" #include "pdf/pdf_features.h" #include "third_party/blink/public/strings/grit/blink_strings.h" #include "ui/accessibility/ax_enums.mojom.h" #include "ui/accessibility/null_ax_action_target.h" #include "ui/base/l10n/l10n_util.h" +#include "ui/gfx/geometry/point_f.h" #include "ui/gfx/geometry/rect_conversions.h" #include "ui/gfx/transform.h" @@ -55,10 +57,6 @@ return gfx::RectF(r.point.x, r.point.y, r.size.width, r.size.height); } -gfx::Vector2dF PpPointToVector2dF(const PP_Point& p) { - return gfx::Vector2dF(p.x, p.y); -} - // This class is used as part of our heuristic to determine which text runs live // on the same "line". As we process runs, we keep a weighted average of the // top and bottom coordinates of the line, and if a new run falls within that @@ -1273,13 +1271,13 @@ } void PdfAccessibilityTree::SetAccessibilityViewportInfo( - const PP_PrivateAccessibilityViewportInfo& viewport_info) { + const chrome_pdf::AccessibilityViewportInfo& viewport_info) { zoom_ = viewport_info.zoom; scale_ = viewport_info.scale; CHECK_GT(zoom_, 0); CHECK_GT(scale_, 0); - scroll_ = PpPointToVector2dF(viewport_info.scroll); - offset_ = PpPointToVector2dF(viewport_info.offset); + scroll_ = gfx::PointF(viewport_info.scroll).OffsetFromOrigin(); + offset_ = gfx::PointF(viewport_info.offset).OffsetFromOrigin(); selection_start_page_index_ = viewport_info.selection_start_page_index; selection_start_char_index_ = viewport_info.selection_start_char_index;
diff --git a/components/pdf/renderer/pdf_accessibility_tree.h b/components/pdf/renderer/pdf_accessibility_tree.h index 710f243..1fb780d 100644 --- a/components/pdf/renderer/pdf_accessibility_tree.h +++ b/components/pdf/renderer/pdf_accessibility_tree.h
@@ -26,6 +26,10 @@ class RendererPpapiHost; } +namespace chrome_pdf { +struct AccessibilityViewportInfo; +} // namespace chrome_pdf + namespace gfx { class Transform; } @@ -54,7 +58,7 @@ }; void SetAccessibilityViewportInfo( - const PP_PrivateAccessibilityViewportInfo& viewport_info); + const chrome_pdf::AccessibilityViewportInfo& viewport_info); void SetAccessibilityDocInfo( const PP_PrivateAccessibilityDocInfo& doc_info); void SetAccessibilityPageInfo(
diff --git a/components/pdf/renderer/pdf_accessibility_tree_browsertest.cc b/components/pdf/renderer/pdf_accessibility_tree_browsertest.cc index df05f2a..afdfbc1 100644 --- a/components/pdf/renderer/pdf_accessibility_tree_browsertest.cc +++ b/components/pdf/renderer/pdf_accessibility_tree_browsertest.cc
@@ -14,6 +14,7 @@ #include "content/public/renderer/renderer_ppapi_host.h" #include "content/public/test/fake_pepper_plugin_instance.h" #include "content/public/test/render_view_test.h" +#include "pdf/accessibility_structs.h" #include "pdf/pdf_features.h" #include "third_party/blink/public/strings/grit/blink_strings.h" #include "third_party/blink/public/web/web_local_frame.h" @@ -23,6 +24,7 @@ #include "ui/accessibility/ax_enums.mojom.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/resource/resource_bundle.h" +#include "ui/gfx/geometry/point.h" namespace pdf { @@ -174,8 +176,8 @@ viewport_info_.zoom = 1.0; viewport_info_.scale = 1.0; - viewport_info_.scroll = {0, 0}; - viewport_info_.offset = {0, 0}; + viewport_info_.scroll = gfx::Point(0, 0); + viewport_info_.offset = gfx::Point(0, 0); viewport_info_.selection_start_page_index = 0; viewport_info_.selection_start_char_index = 0; viewport_info_.selection_end_page_index = 0; @@ -188,7 +190,7 @@ } protected: - PP_PrivateAccessibilityViewportInfo viewport_info_; + chrome_pdf::AccessibilityViewportInfo viewport_info_; PP_PrivateAccessibilityDocInfo doc_info_; PP_PrivateAccessibilityPageInfo page_info_; std::vector<ppapi::PdfAccessibilityTextRunInfo> text_runs_; @@ -2005,8 +2007,8 @@ viewport_info_.zoom = 1.0; viewport_info_.scale = 1.0; - viewport_info_.scroll = {0, -56}; - viewport_info_.offset = {57, 0}; + viewport_info_.scroll = gfx::Point(0, -56); + viewport_info_.offset = gfx::Point(57, 0); pdf_accessibility_tree.SetAccessibilityViewportInfo(viewport_info_); ui::AXNode* root_node = pdf_accessibility_tree.GetRoot();
diff --git a/components/pdf/renderer/pdf_internal_plugin_delegate.cc b/components/pdf/renderer/pdf_internal_plugin_delegate.cc new file mode 100644 index 0000000..fd3a7cb --- /dev/null +++ b/components/pdf/renderer/pdf_internal_plugin_delegate.cc
@@ -0,0 +1,21 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/pdf/renderer/pdf_internal_plugin_delegate.h" + +#include <memory> + +#include "pdf/pdf_view_web_plugin.h" + +namespace pdf { + +PdfInternalPluginDelegate::PdfInternalPluginDelegate() = default; +PdfInternalPluginDelegate::~PdfInternalPluginDelegate() = default; + +std::unique_ptr<chrome_pdf::PdfViewWebPlugin::PrintClient> +PdfInternalPluginDelegate::CreatePrintClient() { + return nullptr; +} + +} // namespace pdf
diff --git a/components/pdf/renderer/pdf_internal_plugin_delegate.h b/components/pdf/renderer/pdf_internal_plugin_delegate.h new file mode 100644 index 0000000..6741744 --- /dev/null +++ b/components/pdf/renderer/pdf_internal_plugin_delegate.h
@@ -0,0 +1,30 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_PDF_RENDERER_PDF_INTERNAL_PLUGIN_DELEGATE_H_ +#define COMPONENTS_PDF_RENDERER_PDF_INTERNAL_PLUGIN_DELEGATE_H_ + +#include <memory> + +// TODO(crbug.com/1218971): Refactor this; only needed for +// `chrome_pdf::PdfViewWebPlugin::PrintClient` declaration. +#include "pdf/pdf_view_web_plugin.h" + +namespace pdf { + +// Interface for embedder-provided operations required to create an instance of +// the internal PDF plugin. +class PdfInternalPluginDelegate { + public: + PdfInternalPluginDelegate(); + virtual ~PdfInternalPluginDelegate(); + + // Creates the print client, or `nullptr` if printing is not supported. + virtual std::unique_ptr<chrome_pdf::PdfViewWebPlugin::PrintClient> + CreatePrintClient(); +}; + +} // namespace pdf + +#endif // COMPONENTS_PDF_RENDERER_PDF_INTERNAL_PLUGIN_DELEGATE_H_
diff --git a/components/pdf/renderer/pepper_pdf_host.cc b/components/pdf/renderer/pepper_pdf_host.cc index 1d19f04..9056e327 100644 --- a/components/pdf/renderer/pepper_pdf_host.cc +++ b/components/pdf/renderer/pepper_pdf_host.cc
@@ -12,6 +12,7 @@ #include "content/public/renderer/render_frame.h" #include "content/public/renderer/render_thread.h" #include "content/public/renderer/renderer_ppapi_host.h" +#include "pdf/accessibility_structs.h" #include "ppapi/host/dispatch_host_message.h" #include "ppapi/host/host_message_context.h" #include "ppapi/host/ppapi_host.h" @@ -27,6 +28,7 @@ #include "third_party/blink/public/web/web_document.h" #include "third_party/blink/public/web/web_local_frame.h" #include "third_party/blink/public/web/web_plugin_container.h" +#include "ui/gfx/geometry/point.h" namespace pdf { @@ -246,10 +248,23 @@ int32_t PepperPDFHost::OnHostMsgSetAccessibilityViewportInfo( ppapi::host::HostMessageContext* context, - const PP_PrivateAccessibilityViewportInfo& viewport_info) { + const PP_PrivateAccessibilityViewportInfo& pp_viewport_info) { if (!host_->GetPluginInstance(pp_instance())) return PP_ERROR_FAILED; CreatePdfAccessibilityTreeIfNeeded(); + chrome_pdf::AccessibilityViewportInfo viewport_info = { + pp_viewport_info.zoom, + pp_viewport_info.scale, + gfx::Point(pp_viewport_info.scroll.x, pp_viewport_info.scroll.y), + gfx::Point(pp_viewport_info.offset.x, pp_viewport_info.offset.y), + pp_viewport_info.selection_start_page_index, + pp_viewport_info.selection_start_char_index, + pp_viewport_info.selection_end_page_index, + pp_viewport_info.selection_end_char_index, + {static_cast<chrome_pdf::FocusObjectType>( + pp_viewport_info.focus_info.focused_object_type), + pp_viewport_info.focus_info.focused_object_page_index, + pp_viewport_info.focus_info.focused_annotation_index_in_page}}; pdf_accessibility_tree_->SetAccessibilityViewportInfo(viewport_info); return PP_OK; }
diff --git a/components/pdf/renderer/pepper_pdf_host.h b/components/pdf/renderer/pepper_pdf_host.h index 92ab8433..8f5345f 100644 --- a/components/pdf/renderer/pepper_pdf_host.h +++ b/components/pdf/renderer/pepper_pdf_host.h
@@ -115,7 +115,7 @@ const std::string& url); int32_t OnHostMsgSetAccessibilityViewportInfo( ppapi::host::HostMessageContext* context, - const PP_PrivateAccessibilityViewportInfo& viewport_info); + const PP_PrivateAccessibilityViewportInfo& pp_viewport_info); int32_t OnHostMsgSetAccessibilityDocInfo( ppapi::host::HostMessageContext* context, const PP_PrivateAccessibilityDocInfo& doc_info);
diff --git a/components/plugins/renderer/webview_plugin.cc b/components/plugins/renderer/webview_plugin.cc index 486b3d6f..5f874227 100644 --- a/components/plugins/renderer/webview_plugin.cc +++ b/components/plugins/renderer/webview_plugin.cc
@@ -269,6 +269,7 @@ web_view_ = WebView::Create(/*client=*/this, /*is_hidden=*/false, + /*is_prerendering=*/false, /*is_inside_portal=*/false, /*compositing_enabled=*/false, /*widgets_never_composited=*/false,
diff --git a/components/policy/proto/chrome_device_policy.proto b/components/policy/proto/chrome_device_policy.proto index eddb0c2..cb4ec2454 100644 --- a/components/policy/proto/chrome_device_policy.proto +++ b/components/policy/proto/chrome_device_policy.proto
@@ -143,6 +143,7 @@ optional bool report_system_info = 25 [default = false]; optional bool report_print_jobs = 26 [default = false]; optional bool report_login_logout = 27 [default = false]; + optional bool report_audio_status = 28 [default = true]; // Frequency to report device status, default to 3 hours. // If changed, the default value has to be updated in
diff --git a/components/policy/resources/policy_templates.json b/components/policy/resources/policy_templates.json index 5527550..e6cad59e 100644 --- a/components/policy/resources/policy_templates.json +++ b/components/policy/resources/policy_templates.json
@@ -911,6 +911,7 @@ 'ReportDeviceBootMode', 'ReportDeviceUsers', 'ReportDeviceActivityTimes', + 'ReportDeviceAudioStatus', 'ReportDeviceLocation', 'ReportDeviceNetworkInterfaces', 'ReportDeviceHardwareStatus', @@ -9526,6 +9527,37 @@ 'arc_support': 'This policy has no effect on the logging done by Android.', }, { + 'name': 'ReportDeviceAudioStatus', + 'owners': ['cros-reporting-team@google.com', 'tylergarrett@google.com'], + 'type': 'main', + 'schema': { 'type': 'boolean' }, + 'future_on': ['chrome_os'], + 'supported_chrome_os_management': ['google_cloud'], + 'device_only': True, + 'features': { + 'dynamic_refresh': True, + }, + 'items': [ + { + 'value': True, + 'caption': 'Report audio status', + }, + { + 'value': False, + 'caption': 'Do not report audio status', + }, + ], + 'example_value': False, + 'default': True, + 'id': 873, + 'caption': '''Report device audio status''', + 'tags': ['admin-sharing'], + 'desc': '''Setting the policy to enabled or leaving it unset has enrolled devices report device audio volume. + + Setting the policy to Disabled means enrolled devices don't record or report audio status.''', + 'arc_support': 'This policy has no effect on the logging done by Android.', + }, + { 'name': 'ReportDeviceBootMode', 'owners': ['cros-reporting-team@google.com', 'lbaraz@chromium.org'], 'type': 'main', @@ -20057,7 +20089,7 @@ }, { 'name': 'CoalesceH2ConnectionsWithClientCertificatesForHosts', - 'owners': ['nharper@chromium.org', 'rsleevi@chromium.org'], + 'owners': ['rsleevi@chromium.org'], 'type': 'list', 'schema': { 'type': 'array', @@ -22929,7 +22961,7 @@ }, { 'name': 'HSTSPolicyBypassList', - 'owners': ['nharper@chromium.org', 'rsleevi@chromium.org'], + 'owners': ['asymmetric@chromium.org', 'rsleevi@chromium.org'], 'type': 'list', 'schema': { 'type': 'array', @@ -26813,6 +26845,7 @@ 'SystemTimezone': 'system_timezone.timezone', 'SystemTimezoneAutomaticDetection': 'system_timezone.timezone_detection_type', 'ReportDeviceActivityTimes': 'device_reporting.report_activity_times', + 'ReportDeviceAudioStatus': 'device_reporting.report_audio_status', 'ReportDeviceBootMode': 'device_reporting.report_boot_mode', 'ReportDeviceLocation': 'device_reporting.report_location', 'ReportDeviceNetworkInterfaces': 'device_reporting.report_network_interfaces', @@ -27272,6 +27305,7 @@ 'ReportDeviceBootMode', 'ReportDeviceUsers', 'ReportDeviceActivityTimes', + 'ReportDeviceAudioStatus', 'ReportDeviceLocation', 'ReportDeviceNetworkInterfaces', 'ReportDeviceHardwareStatus', @@ -27384,6 +27418,6 @@ 'placeholders': [], 'deleted_policy_ids': [114, 115, 204, 205, 206, 412, 476, 544, 546, 562, 569, 578, 583, 585, 586, 587, 588, 589, 590, 591, 600, 668, 669], 'deleted_atomic_policy_group_ids': [19], - 'highest_id_currently_used': 872, + 'highest_id_currently_used': 873, 'highest_atomic_group_id_currently_used': 40 }
diff --git a/components/policy/test_support/policy_testserver.py b/components/policy/test_support/policy_testserver.py index 385db38..c43b440 100644 --- a/components/policy/test_support/policy_testserver.py +++ b/components/policy/test_support/policy_testserver.py
@@ -111,8 +111,6 @@ # pyopenssl is only reliably available on Chrome OS builds. # This is currently OK because policy_testserver.py's support for certificate # provisioning is only used in Tast test for now. -# TODO(https://bugs.chromium.org/p/chromium/issues/detail?id=1101729): Switch -# to issuing certificates in the test.. try: from OpenSSL import crypto except ImportError: @@ -524,7 +522,6 @@ except (IOError): return(400, 'Invalid request') - # TODO(drcrash): Check the certificate itself. if req.certificate_type != dm.CertificateBasedDeviceRegistrationData.\ ENTERPRISE_ENROLLMENT_CERTIFICATE: return(403, 'Invalid certificate type for registration') @@ -582,7 +579,6 @@ Returns: CertificateBasedDeviceRegistrationData """ - # TODO(drcrash): Verify signature. rdata = dm.CertificateBasedDeviceRegistrationData() rdata.ParseFromString(msg.data[:len(msg.data) - msg.extra_data_bytes]) return rdata @@ -1258,8 +1254,6 @@ response.new_public_key = signing_key['public_key'] # Set the verification signature appropriate for the policy domain. - # TODO(atwilson): Use the enrollment domain for public accounts when - # we add key validation for ChromeOS (http://crbug.com/328038). if 'signatures' in signing_key: verification_sig = self.GetSignatureForDomain( signing_key['signatures'], policy_data.username)
diff --git a/components/policy/test_support/request_handler_for_policy.cc b/components/policy/test_support/request_handler_for_policy.cc index 4c68cc0..41a05a4f 100644 --- a/components/policy/test_support/request_handler_for_policy.cc +++ b/components/policy/test_support/request_handler_for_policy.cc
@@ -4,6 +4,7 @@ #include "components/policy/test_support/request_handler_for_policy.h" +#include "base/strings/stringprintf.h" #include "base/time/time.h" #include "components/policy/core/common/cloud/cloud_policy_constants.h" #include "components/policy/test_support/policy_storage.h" @@ -35,6 +36,7 @@ const HttpRequest& request) { const std::set<std::string> kCloudPolicyTypes{ dm_protocol::kChromeMachineLevelUserCloudPolicyType, + dm_protocol::kChromeMachineLevelUserCloudPolicyAndroidType, dm_protocol::kChromeMachineLevelExtensionCloudPolicyType, }; @@ -54,15 +56,18 @@ em::DeviceManagementResponse device_management_response; for (const auto& fetch_request : device_management_request.policy_request().requests()) { + const std::string& policy_type = fetch_request.policy_type(); // TODO(crbug.com/1221328): Add other policy types as needed. if (kCloudPolicyTypes.find(fetch_request.policy_type()) == kCloudPolicyTypes.end()) { - return CreateHttpResponse(net::HTTP_BAD_REQUEST, "Invalid policy_type"); + return CreateHttpResponse( + net::HTTP_BAD_REQUEST, + base::StringPrintf("Invalid policy_type: %s", policy_type.c_str())); } std::string error_msg; if (!ProcessCloudPolicy( - fetch_request.policy_type(), *client_info, + policy_type, *client_info, device_management_response.mutable_policy_response() ->add_responses(), &error_msg)) {
diff --git a/components/policy/test_support/request_handler_for_register_browser.cc b/components/policy/test_support/request_handler_for_register_browser.cc index db1b531c..04426d7a 100644 --- a/components/policy/test_support/request_handler_for_register_browser.cc +++ b/components/policy/test_support/request_handler_for_register_browser.cc
@@ -46,11 +46,13 @@ const em::RegisterBrowserRequest& register_browser_request = device_management_request.register_browser_request(); - if (register_browser_request.machine_name().empty() && - register_browser_request.device_model().empty()) { - return CreateHttpResponse( - net::HTTP_BAD_REQUEST, - "Either machine name or device model must be non-empty."); + // Machine name is empty on mobile. + if (register_browser_request.os_platform() != "Android" && + register_browser_request.os_platform() != "iOS" && + register_browser_request.machine_name().empty()) { + LOG(ERROR) << "OS platform: " << register_browser_request.os_platform(); + return CreateHttpResponse(net::HTTP_BAD_REQUEST, + "Machine name must be non-empty on Desktop."); } if (enrollment_token == kInvalidEnrollmentToken) { @@ -70,6 +72,7 @@ client_info.machine_name = register_browser_request.machine_name(); client_info.allowed_policy_types.insert( {dm_protocol::kChromeMachineLevelUserCloudPolicyType, + dm_protocol::kChromeMachineLevelUserCloudPolicyAndroidType, dm_protocol::kChromeMachineLevelExtensionCloudPolicyType}); client_storage()->RegisterClient(std::move(client_info));
diff --git a/components/policy/test_support/request_handler_for_register_browser_unittest.cc b/components/policy/test_support/request_handler_for_register_browser_unittest.cc index ea5a0e3c..c5404dd 100644 --- a/components/policy/test_support/request_handler_for_register_browser_unittest.cc +++ b/components/policy/test_support/request_handler_for_register_browser_unittest.cc
@@ -49,7 +49,11 @@ } TEST_F(RequestHandlerForRegisterBrowserTest, - HandleRequest_NoDeviceInformation) { + HandleRequest_NoDeviceInformation_Desktop) { + em::DeviceManagementRequest device_management_request; + device_management_request.mutable_register_browser_request()->set_os_platform( + "Windows"); + SetEnrollmentTokenHeader(kEnrollmentToken); SetPayload(em::DeviceManagementRequest()); @@ -63,8 +67,10 @@ TEST_F(RequestHandlerForRegisterBrowserTest, HandleRequest_InvalidEnrollmentToken) { em::DeviceManagementRequest device_management_request; - device_management_request.mutable_register_browser_request() - ->set_machine_name(kMachineName); + em::RegisterBrowserRequest* register_browser_request = + device_management_request.mutable_register_browser_request(); + register_browser_request->set_os_platform("Windows"); + register_browser_request->set_machine_name(kMachineName); SetEnrollmentTokenHeader(kInvalidEnrollmentToken); SetPayload(device_management_request); @@ -78,8 +84,10 @@ TEST_F(RequestHandlerForRegisterBrowserTest, HandleRequest_Success) { em::DeviceManagementRequest device_management_request; - device_management_request.mutable_register_browser_request() - ->set_machine_name(kMachineName); + em::RegisterBrowserRequest* register_browser_request = + device_management_request.mutable_register_browser_request(); + register_browser_request->set_os_platform("Windows"); + register_browser_request->set_machine_name(kMachineName); SetEnrollmentTokenHeader(kEnrollmentToken); SetPayload(device_management_request); @@ -104,4 +112,33 @@ EXPECT_EQ(client_info->machine_name, kMachineName); } +TEST_F(RequestHandlerForRegisterBrowserTest, + HandleRequest_Success_NoDeviceInformation_Mobile) { + em::DeviceManagementRequest device_management_request; + device_management_request.mutable_register_browser_request()->set_os_platform( + "Android"); + + SetEnrollmentTokenHeader(kEnrollmentToken); + SetPayload(device_management_request); + + StartRequestAndWait(); + + EXPECT_EQ(GetResponseCode(), net::HTTP_OK); + + ASSERT_TRUE(HasResponseBody()); + em::DeviceManagementResponse device_management_response = + GetDeviceManagementResponse(); + EXPECT_EQ( + device_management_response.register_response().device_management_token(), + kFakeDeviceToken); + + ASSERT_EQ(client_storage()->GetNumberOfRegisteredClients(), 1u); + const ClientStorage::ClientInfo* client_info = + client_storage()->GetClientOrNull(kDeviceId); + ASSERT_NE(client_info, nullptr); + EXPECT_EQ(client_info->device_id, kDeviceId); + EXPECT_EQ(client_info->device_token, kFakeDeviceToken); + EXPECT_TRUE(client_info->machine_name.empty()); +} + } // namespace policy
diff --git a/components/printing/renderer/print_render_frame_helper.cc b/components/printing/renderer/print_render_frame_helper.cc index 23bb125..8d4a55c 100644 --- a/components/printing/renderer/print_render_frame_helper.cc +++ b/components/printing/renderer/print_render_frame_helper.cc
@@ -702,7 +702,8 @@ blink::WebView* web_view = blink::WebView::Create( /*client=*/nullptr, - /*is_hidden=*/false, /*is_inside_portal=*/false, + /*is_hidden=*/false, /*is_prerendering=*/false, + /*is_inside_portal=*/false, /*compositing_enabled=*/false, /*widgets_never_composited=*/false, /*opener=*/nullptr, mojo::NullAssociatedReceiver(), *source_frame.GetAgentGroupScheduler(), @@ -981,6 +982,7 @@ blink::WebView* web_view = blink::WebView::Create( /*client=*/this, /*is_hidden=*/false, + /*is_prerendering=*/false, /*is_inside_portal=*/false, /*compositing_enabled=*/false, /*widgets_never_composited=*/false,
diff --git a/components/query_tiles/internal/tile_manager.cc b/components/query_tiles/internal/tile_manager.cc index b64b6c0..46a5f45 100644 --- a/components/query_tiles/internal/tile_manager.cc +++ b/components/query_tiles/internal/tile_manager.cc
@@ -302,7 +302,7 @@ if (!tile_group_) return; std::vector<std::string> tiles_to_remove = - trending_tile_handler_.GetInactiveTrendingTiles(); + trending_tile_handler_.GetTrendingTilesToRemove(); if (tiles_to_remove.empty()) return; tile_group_->RemoveTiles(tiles_to_remove);
diff --git a/components/query_tiles/internal/tile_manager_unittest.cc b/components/query_tiles/internal/tile_manager_unittest.cc index ca7a77a02..df1e332 100644 --- a/components/query_tiles/internal/tile_manager_unittest.cc +++ b/components/query_tiles/internal/tile_manager_unittest.cc
@@ -427,10 +427,8 @@ } // Check that trending tiles get removed after inactivity. -TEST_F(TileManagerTest, TrendingTopTilesRemovedAfterInactivity) { +TEST_F(TileManagerTest, TrendingTopTilesRemovedAfterShown) { base::test::ScopedFeatureList feature_list; - feature_list.InitAndEnableFeature( - features::kQueryTilesRemoveTrendingTilesAfterInactivity); EXPECT_CALL(*tile_store(), Update(_, _, _)) .WillOnce(Invoke([](const std::string& id, const TileGroup& group, MockTileStore::UpdateCallback callback) { @@ -454,9 +452,8 @@ OnTileClicked("trending_2"); GetTiles(expected); - // The first tile will be removed due to inactivity and the third tile - // will be returned. - expected.erase(expected.begin()); + // Both the first and the second tile will be removed. + expected.erase(expected.begin(), expected.begin() + 2); expected.emplace_back(std::move(trending_3)); EXPECT_CALL(*tile_store(), Update(_, _, _)) .WillOnce(Invoke([](const std::string& id, const TileGroup& group, @@ -464,8 +461,9 @@ std::move(callback).Run(true); })); GetTiles(expected); + GetTiles(expected); - // The 2nd tile will be removed due to inactivity. + // The 3rd tile will be removed due to max impression threshold. expected.erase(expected.begin()); EXPECT_CALL(*tile_store(), Update(_, _, _)) .WillOnce(Invoke([](const std::string& id, const TileGroup& group, @@ -478,8 +476,6 @@ // Check that trending subtiles will not be removed if they are not displayed. TEST_F(TileManagerTest, UnshownTrendingSubTilesNotRemoved) { base::test::ScopedFeatureList feature_list; - feature_list.InitAndEnableFeature( - features::kQueryTilesRemoveTrendingTilesAfterInactivity); EXPECT_CALL(*tile_store(), Update(_, _, _)) .WillOnce(Invoke([](const std::string& id, const TileGroup& group, MockTileStore::UpdateCallback callback) { @@ -516,8 +512,6 @@ // correctly counted. TEST_F(TileManagerTest, GetSingleTileAfterOnTileClicked) { base::test::ScopedFeatureList feature_list; - feature_list.InitAndEnableFeature( - features::kQueryTilesRemoveTrendingTilesAfterInactivity); EXPECT_CALL(*tile_store(), Update(_, _, _)) .WillOnce(Invoke([](const std::string& id, const TileGroup& group, MockTileStore::UpdateCallback callback) { @@ -553,11 +547,12 @@ OnTileClicked("parent"); GetSingleTile("parent", get_single_tile_expected); - // Click a trending tile to reset its impression. + // Click a trending tile will not reset its impression. OnTileClicked("trending_1"); - // The 2nd tile will get removed. - expected[0].sub_tiles.erase(expected[0].sub_tiles.begin() + 1); + // The first two tiles will get removed. + expected[0].sub_tiles.erase(expected[0].sub_tiles.begin(), + expected[0].sub_tiles.begin() + 2); EXPECT_CALL(*tile_store(), Update(_, _, _)) .WillOnce(Invoke([](const std::string& id, const TileGroup& group, MockTileStore::UpdateCallback callback) { @@ -565,7 +560,7 @@ })); GetTiles(expected); - get_single_tile_expected->sub_tiles.pop_back(); + get_single_tile_expected->sub_tiles.clear(); get_single_tile_expected->sub_tiles.emplace_back( std::make_unique<Tile>(std::move(trending_3))); OnTileClicked("parent");
diff --git a/components/query_tiles/internal/trending_tile_handler.cc b/components/query_tiles/internal/trending_tile_handler.cc index 764275b9..9145e0d6 100644 --- a/components/query_tiles/internal/trending_tile_handler.cc +++ b/components/query_tiles/internal/trending_tile_handler.cc
@@ -36,17 +36,12 @@ } void TrendingTileHandler::OnTileClicked(const std::string& tile_id) { - tile_impressions_.erase(tile_id); if (IsTrendingTile(tile_id)) stats::RecordTrendingTileEvent(stats::TrendingTileEvent::kClicked); } -std::vector<std::string> TrendingTileHandler::GetInactiveTrendingTiles() { +std::vector<std::string> TrendingTileHandler::GetTrendingTilesToRemove() { std::vector<std::string> tile_ids; - if (!base::FeatureList::IsEnabled( - features::kQueryTilesRemoveTrendingTilesAfterInactivity)) { - return tile_ids; - } ImpressionMap::iterator it = tile_impressions_.begin(); while (it != tile_impressions_.end()) { if (it->second >= TileConfig::GetMaxTrendingTileImpressions()) {
diff --git a/components/query_tiles/internal/trending_tile_handler.h b/components/query_tiles/internal/trending_tile_handler.h index a1b335c..802e53fc 100644 --- a/components/query_tiles/internal/trending_tile_handler.h +++ b/components/query_tiles/internal/trending_tile_handler.h
@@ -39,8 +39,8 @@ // Called when a tile is clicked. void OnTileClicked(const std::string& tile_id); - // Returns a list of inactive trending tile Ids. - std::vector<std::string> GetInactiveTrendingTiles(); + // Returns a list of trending tile Ids to remove. + std::vector<std::string> GetTrendingTilesToRemove(); private: // Record the impression for a tile with the give id.
diff --git a/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager.cc b/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager.cc index 11b7033..e8878cc 100644 --- a/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager.cc +++ b/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager.cc
@@ -83,11 +83,62 @@ } // namespace +RenderFrameReceiverSet::RenderFrameReceiverSet( + content::WebContents* web_contents, + ContentSubresourceFilterThrottleManager* throttle_manager) + : content::WebContentsObserver(web_contents), + throttle_manager_(throttle_manager) {} + +RenderFrameReceiverSet::~RenderFrameReceiverSet() = default; + +void RenderFrameReceiverSet::Bind( + content::RenderFrameHost* frame_host, + mojo::PendingAssociatedReceiver<mojom::SubresourceFilterHost> + pending_receiver) { + mojo::ReceiverId id = + receiver_.Add(throttle_manager_, std::move(pending_receiver), frame_host); + bool newly_inserted = + frame_to_receivers_map_ + .insert(std::pair<content::RenderFrameHost*, mojo::ReceiverId>( + frame_host, id)) + .second; + + // We should only ever have one binding per RenderFrame. + CHECK(newly_inserted); +} + +void RenderFrameReceiverSet::RenderFrameDeleted( + content::RenderFrameHost* frame_host) { + auto it = frame_to_receivers_map_.find(frame_host); + if (it != frame_to_receivers_map_.end()) { + receiver_.Remove(it->second); + frame_to_receivers_map_.erase(it); + } +} + +content::RenderFrameHost* RenderFrameReceiverSet::GetCurrentTargetFrame() { + return receiver_.current_context(); +} + const char ContentSubresourceFilterThrottleManager:: kContentSubresourceFilterThrottleManagerWebContentsUserDataKey[] = "content_subresource_filter_throttle_manager"; // static +void ContentSubresourceFilterThrottleManager::BindReceiver( + mojo::PendingAssociatedReceiver<mojom::SubresourceFilterHost> + pending_receiver, + content::RenderFrameHost* render_frame_host) { + auto* manager = ContentSubresourceFilterThrottleManager::FromWebContents( + content::WebContents::FromRenderFrameHost(render_frame_host)); + + if (!manager) + return; + + manager->receiver_.Bind(render_frame_host, std::move(pending_receiver)); +} + +// static void ContentSubresourceFilterThrottleManager::CreateForWebContents( content::WebContents* web_contents, SubresourceFilterProfileContext* profile_context, @@ -122,9 +173,7 @@ VerifiedRulesetDealer::Handle* dealer_handle, content::WebContents* web_contents) : content::WebContentsObserver(web_contents), - receiver_(web_contents, - this, - content::WebContentsFrameReceiverSetPassKey()), + receiver_(web_contents, this), dealer_handle_(dealer_handle), database_manager_(std::move(database_manager)), profile_interaction_manager_(
diff --git a/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager.h b/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager.h index 24d2151..ec9774d 100644 --- a/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager.h +++ b/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager.h
@@ -37,6 +37,7 @@ class AsyncDocumentSubresourceFilter; class ActivationStateComputingNavigationThrottle; +class ContentSubresourceFilterThrottleManager; class PageLoadStatistics; class ProfileInteractionManager; class SubresourceFilterProfileContext; @@ -69,6 +70,45 @@ kMaxValue = kForcedActivationEnabled }; +// Wraps an AssociatedReceiverSet to provide automatic cleanup when a +// RenderFrameHost is removed. +// TODO(bokan, csharrison): Expose this functionality to others if it is +// broadly desirable. +class RenderFrameReceiverSet : public content::WebContentsObserver { + public: + RenderFrameReceiverSet( + content::WebContents* web_contents, + ContentSubresourceFilterThrottleManager* throttle_manager); + ~RenderFrameReceiverSet() override; + + RenderFrameReceiverSet(const RenderFrameReceiverSet&) = delete; + RenderFrameReceiverSet& operator=(const RenderFrameReceiverSet&) = delete; + + void Bind(content::RenderFrameHost* frame_host, + mojo::PendingAssociatedReceiver<mojom::SubresourceFilterHost> + pending_receiver); + + content::RenderFrameHost* GetCurrentTargetFrame(); + + // content::WebContentsObserver: + void RenderFrameDeleted(content::RenderFrameHost* frame_host) override; + + private: + // Receiver set for each frame in the page. Note, bindings are reused across + // navigations that are same-site since the RenderFrameHost is reused in that + // case. + mojo::AssociatedReceiverSet<mojom::SubresourceFilterHost, + content::RenderFrameHost*> + receiver_; + + // Track which RenderFrameHosts are in the |receiver_| set so that we can + // remove them when a RenderFrameHost is removed. + std::map<content::RenderFrameHost*, mojo::ReceiverId> frame_to_receivers_map_; + + // Must outlive this class. + ContentSubresourceFilterThrottleManager* throttle_manager_; +}; + // The ContentSubresourceFilterThrottleManager manages NavigationThrottles in // order to calculate frame activation states and subframe navigation filtering, // within a given WebContents. It contains a mapping of all activated @@ -85,6 +125,12 @@ static const char kContentSubresourceFilterThrottleManagerWebContentsUserDataKey[]; + // Binds a remote in the given RenderFrame to the correct + // ContentSubresourceFilterThrottleManager in the browser. + static void BindReceiver(mojo::PendingAssociatedReceiver< + mojom::SubresourceFilterHost> pending_receiver, + content::RenderFrameHost* render_frame_host); + // Creates a ThrottleManager instance from the given parameters and attaches // it as user data of |web_contents|. // NOTE: Short-circuits out if the kSafeBrowsingSubresourceFilter feature is @@ -315,7 +361,8 @@ // has not had a navigation evaluated by the filter list. std::map<int, LoadPolicy> navigation_load_policies_; - content::WebContentsFrameReceiverSet<mojom::SubresourceFilterHost> receiver_; + // Receiver set for all RenderFrames in the WebContents. + RenderFrameReceiverSet receiver_; base::ScopedObservation<SubresourceFilterObserverManager, SubresourceFilterObserver>
diff --git a/components/suggestions/BUILD.gn b/components/suggestions/BUILD.gn deleted file mode 100644 index f3b54188..0000000 --- a/components/suggestions/BUILD.gn +++ /dev/null
@@ -1,60 +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. - -static_library("suggestions") { - sources = [ - "blocklist_store.cc", - "blocklist_store.h", - "suggestions_pref_names.cc", - "suggestions_pref_names.h", - "suggestions_service.h", - "suggestions_service_impl.cc", - "suggestions_service_impl.h", - "suggestions_store.cc", - "suggestions_store.h", - "webui/suggestions_source.cc", - "webui/suggestions_source.h", - ] - - public_deps = [ - "//base", - "//components/prefs", - "//components/suggestions/proto", - "//net", - "//ui/base", - "//ui/gfx", - "//url", - ] - deps = [ - "//components/google/core/common", - "//components/keyed_service/core", - "//components/pref_registry", - "//components/signin/public/identity_manager", - "//components/sync", - "//components/variations", - "//components/variations/net", - "//google_apis", - ] -} - -source_set("unit_tests") { - testonly = true - sources = [ - "blocklist_store_unittest.cc", - "suggestions_service_impl_unittest.cc", - "suggestions_store_unittest.cc", - ] - deps = [ - ":suggestions", - "//base/test:test_support", - "//components/signin/public/identity_manager:test_support", - "//components/sync:test_support", - "//components/sync_preferences:test_support", - "//components/variations:test_support", - "//net:test_support", - "//services/network:test_support", - "//testing/gmock", - "//testing/gtest", - ] -}
diff --git a/components/suggestions/DEPS b/components/suggestions/DEPS deleted file mode 100644 index d04256d..0000000 --- a/components/suggestions/DEPS +++ /dev/null
@@ -1,16 +0,0 @@ -include_rules = [ - "+components/google/core", - "+components/keyed_service/core", - "+components/pref_registry", - "+components/prefs", - "+components/signin/public", - "+components/sync/driver", - "+components/sync_preferences", - "+components/variations", - "+google_apis", - "+net", - "+services/network/public", - "+services/network/test", - "+ui", - "+url", -]
diff --git a/components/suggestions/DIR_METADATA b/components/suggestions/DIR_METADATA deleted file mode 100644 index 1ee6aef..0000000 --- a/components/suggestions/DIR_METADATA +++ /dev/null
@@ -1,5 +0,0 @@ -monorail { - component: "UI>Browser>NewTabPage" -} - -team_email: "ntp-dev@chromium.org"
diff --git a/components/suggestions/OWNERS b/components/suggestions/OWNERS deleted file mode 100644 index 2bbc81a..0000000 --- a/components/suggestions/OWNERS +++ /dev/null
@@ -1,3 +0,0 @@ -mahmadi@chromium.org -tiborg@chromium.org -treib@chromium.org
diff --git a/components/suggestions/blocklist_store.cc b/components/suggestions/blocklist_store.cc deleted file mode 100644 index c24e0a6..0000000 --- a/components/suggestions/blocklist_store.cc +++ /dev/null
@@ -1,258 +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. - -#include "components/suggestions/blocklist_store.h" - -#include <stddef.h> - -#include <algorithm> -#include <set> -#include <string> - -#include "base/base64.h" -#include "base/logging.h" -#include "components/pref_registry/pref_registry_syncable.h" -#include "components/prefs/pref_service.h" -#include "components/suggestions/suggestions_pref_names.h" - -using base::TimeDelta; -using base::TimeTicks; - -namespace suggestions { -namespace { - -void PopulateBlocklistSet(const SuggestionsBlocklist& blocklist_proto, - std::set<std::string>* blocklist_set) { - blocklist_set->clear(); - for (int i = 0; i < blocklist_proto.urls_size(); ++i) { - blocklist_set->insert(blocklist_proto.urls(i)); - } -} - -void PopulateBlocklistProto(const std::set<std::string>& blocklist_set, - SuggestionsBlocklist* blocklist_proto) { - blocklist_proto->Clear(); - for (auto& url : blocklist_set) { - blocklist_proto->add_urls(url); - } -} - -} // namespace - -BlocklistStore::BlocklistStore(PrefService* profile_prefs, - const base::TimeDelta& upload_delay) - : pref_service_(profile_prefs), upload_delay_(upload_delay) { - DCHECK(pref_service_); -} - -BlocklistStore::~BlocklistStore() = default; - -bool BlocklistStore::BlocklistUrl(const GURL& url) { - if (!url.is_valid()) - return false; - - SuggestionsBlocklist blocklist_proto; - LoadBlocklist(&blocklist_proto); - std::set<std::string> blocklist_set; - PopulateBlocklistSet(blocklist_proto, &blocklist_set); - - bool success = false; - if (blocklist_set.insert(url.spec()).second) { - PopulateBlocklistProto(blocklist_set, &blocklist_proto); - success = StoreBlocklist(blocklist_proto); - } else { - // |url| was already in the blocklist. - success = true; - } - - if (success) { - // Update the blocklist time. - blocklist_times_[url.spec()] = TimeTicks::Now(); - } - - return success; -} - -bool BlocklistStore::GetTimeUntilReadyForUpload(TimeDelta* delta) { - SuggestionsBlocklist blocklist; - LoadBlocklist(&blocklist); - if (!blocklist.urls_size()) - return false; - - // Note: the size is non-negative. - if (blocklist_times_.size() < static_cast<size_t>(blocklist.urls_size())) { - // A url is not in the timestamp map: it's candidate for upload. This can - // happen after a restart. Another (undesired) case when this could happen - // is if more than one instance were created. - *delta = TimeDelta::FromSeconds(0); - return true; - } - - // Find the minimum blocklist time. Note: blocklist_times_ is NOT empty since - // blocklist is non-empty and blocklist_times_ contains as many items. - TimeDelta min_delay = TimeDelta::Max(); - for (const auto& kv : blocklist_times_) { - min_delay = - std::min(upload_delay_ - (TimeTicks::Now() - kv.second), min_delay); - } - DCHECK(min_delay != TimeDelta::Max()); - *delta = std::max(min_delay, TimeDelta::FromSeconds(0)); - - return true; -} - -bool BlocklistStore::GetTimeUntilURLReadyForUpload(const GURL& url, - TimeDelta* delta) { - auto it = blocklist_times_.find(url.spec()); - if (it != blocklist_times_.end()) { - // The url is in the timestamps map. - *delta = std::max(upload_delay_ - (TimeTicks::Now() - it->second), - TimeDelta::FromSeconds(0)); - return true; - } - - // The url still might be in the blocklist. - SuggestionsBlocklist blocklist; - LoadBlocklist(&blocklist); - for (int i = 0; i < blocklist.urls_size(); ++i) { - if (blocklist.urls(i) == url.spec()) { - *delta = TimeDelta::FromSeconds(0); - return true; - } - } - - return false; -} - -bool BlocklistStore::GetCandidateForUpload(GURL* url) { - SuggestionsBlocklist blocklist; - LoadBlocklist(&blocklist); - - for (int i = 0; i < blocklist.urls_size(); ++i) { - bool is_candidate = true; - auto it = blocklist_times_.find(blocklist.urls(i)); - if (it != blocklist_times_.end() && - TimeTicks::Now() < it->second + upload_delay_) { - // URL was added too recently. - is_candidate = false; - } - if (is_candidate) { - GURL blocklisted(blocklist.urls(i)); - url->Swap(&blocklisted); - return true; - } - } - - return false; -} - -bool BlocklistStore::RemoveUrl(const GURL& url) { - if (!url.is_valid()) - return false; - const std::string removal_candidate = url.spec(); - - SuggestionsBlocklist blocklist; - LoadBlocklist(&blocklist); - - bool removed = false; - SuggestionsBlocklist updated_blocklist; - for (int i = 0; i < blocklist.urls_size(); ++i) { - if (blocklist.urls(i) == removal_candidate) { - removed = true; - } else { - updated_blocklist.add_urls(blocklist.urls(i)); - } - } - - if (removed && StoreBlocklist(updated_blocklist)) { - blocklist_times_.erase(url.spec()); - return true; - } - - return false; -} - -void BlocklistStore::FilterSuggestions(SuggestionsProfile* profile) { - if (!profile->suggestions_size()) - return; // Empty profile, nothing to filter. - - SuggestionsBlocklist blocklist_proto; - if (!LoadBlocklist(&blocklist_proto)) { - // There was an error loading the blocklist. The blocklist was cleared and - // there's nothing to be done about it. - return; - } - if (!blocklist_proto.urls_size()) - return; // Empty blocklist, nothing to filter. - - std::set<std::string> blocklist_set; - PopulateBlocklistSet(blocklist_proto, &blocklist_set); - - // Populate the filtered suggestions. - SuggestionsProfile filtered_profile; - filtered_profile.set_timestamp(profile->timestamp()); - for (int i = 0; i < profile->suggestions_size(); ++i) { - if (blocklist_set.find(profile->suggestions(i).url()) == - blocklist_set.end()) { - // This suggestion is not blocklisted. - ChromeSuggestion* suggestion = filtered_profile.add_suggestions(); - // Note: swapping! - suggestion->Swap(profile->mutable_suggestions(i)); - } - } - - // Swap |profile| and |filtered_profile|. - profile->Swap(&filtered_profile); -} - -// static -void BlocklistStore::RegisterProfilePrefs( - user_prefs::PrefRegistrySyncable* registry) { - registry->RegisterStringPref(prefs::kSuggestionsBlocklist, std::string()); -} - -// Test seam. For simplicity of mock creation. -BlocklistStore::BlocklistStore() = default; - -bool BlocklistStore::LoadBlocklist(SuggestionsBlocklist* blocklist) { - DCHECK(blocklist); - - const std::string base64_blocklist_data = - pref_service_->GetString(prefs::kSuggestionsBlocklist); - if (base64_blocklist_data.empty()) { - blocklist->Clear(); - return false; - } - - // If the decode process fails, assume the pref value is corrupt and clear it. - std::string blocklist_data; - if (!base::Base64Decode(base64_blocklist_data, &blocklist_data) || - !blocklist->ParseFromString(blocklist_data)) { - VLOG(1) << "Suggestions blocklist data in profile pref is corrupt, " - << " clearing it."; - blocklist->Clear(); - ClearBlocklist(); - return false; - } - - return true; -} - -bool BlocklistStore::StoreBlocklist(const SuggestionsBlocklist& blocklist) { - std::string blocklist_data; - if (!blocklist.SerializeToString(&blocklist_data)) - return false; - - std::string base64_blocklist_data; - base::Base64Encode(blocklist_data, &base64_blocklist_data); - - pref_service_->SetString(prefs::kSuggestionsBlocklist, base64_blocklist_data); - return true; -} - -void BlocklistStore::ClearBlocklist() { - pref_service_->ClearPref(prefs::kSuggestionsBlocklist); -} - -} // namespace suggestions
diff --git a/components/suggestions/blocklist_store.h b/components/suggestions/blocklist_store.h deleted file mode 100644 index 0176fda..0000000 --- a/components/suggestions/blocklist_store.h +++ /dev/null
@@ -1,100 +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. - -#ifndef COMPONENTS_SUGGESTIONS_BLOCKLIST_STORE_H_ -#define COMPONENTS_SUGGESTIONS_BLOCKLIST_STORE_H_ - -#include <map> -#include <string> - -#include "base/macros.h" -#include "base/time/time.h" -#include "components/suggestions/proto/suggestions.pb.h" -#include "url/gurl.h" - -class PrefService; - -namespace user_prefs { -class PrefRegistrySyncable; -} // namespace user_prefs - -namespace suggestions { - -// A helper class for reading, writing, modifying and applying a small URL -// blocklist, pending upload to the server. The class has a concept of time -// duration before which a blocklisted URL becomes candidate for upload to the -// server. Keep in mind most of the operations involve interaction with the disk -// (the profile's preferences). Note that the class should be used as a -// singleton for the upload candidacy to work properly. -class BlocklistStore { - public: - explicit BlocklistStore( - PrefService* profile_prefs, - const base::TimeDelta& upload_delay = base::TimeDelta::FromSeconds(15)); - virtual ~BlocklistStore(); - - // Returns true if successful or |url| was already in the blocklist. If |url| - // was already in the blocklist, its blocklisting timestamp gets updated. - virtual bool BlocklistUrl(const GURL& url); - - // Clears any blocklist data from the profile's preferences. - virtual void ClearBlocklist(); - - // Gets the time until any URL is ready for upload. Returns false if the - // blocklist is empty. - virtual bool GetTimeUntilReadyForUpload(base::TimeDelta* delta); - - // Gets the time until |url| is ready for upload. Returns false if |url| is - // not part of the blocklist. - virtual bool GetTimeUntilURLReadyForUpload(const GURL& url, - base::TimeDelta* delta); - - // Sets |url| to a URL from the blocklist that is candidate for upload. - // Returns false if there is no candidate for upload. - virtual bool GetCandidateForUpload(GURL* url); - - // Removes |url| from the stored blocklist. Returns true if successful, false - // on failure or if |url| was not in the blocklist. Note that this function - // does not enforce a minimum time since blocklist before removal. - virtual bool RemoveUrl(const GURL& url); - - // Applies the blocklist to |suggestions|. - virtual void FilterSuggestions(SuggestionsProfile* suggestions); - - // Register BlocklistStore related prefs in the Profile prefs. - static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry); - - protected: - // Test seam. For simplicity of mock creation. - BlocklistStore(); - - // Loads the blocklist data from the Profile preferences into - // |blocklist|. If there is a problem with loading, the pref value is - // cleared, false is returned and |blocklist| is cleared. If successful, - // |blocklist| will contain the loaded data and true is returned. - bool LoadBlocklist(SuggestionsBlocklist* blocklist); - - // Stores the provided |blocklist| to the Profile preferences, using - // a base64 encoding of its protobuf serialization. - bool StoreBlocklist(const SuggestionsBlocklist& blocklist); - - private: - // The pref service used to persist the suggestions blocklist. - PrefService* pref_service_; - - // Delay after which a URL becomes candidate for upload, measured from the - // last time the URL was added. - base::TimeDelta upload_delay_; - - // The times at which URLs were blocklisted. Used to determine when a URL is - // valid for server upload. Guaranteed to contain URLs that are not ready for - // upload. Might not contain URLs that are ready for upload. - std::map<std::string, base::TimeTicks> blocklist_times_; - - DISALLOW_COPY_AND_ASSIGN(BlocklistStore); -}; - -} // namespace suggestions - -#endif // COMPONENTS_SUGGESTIONS_BLOCKLIST_STORE_H_
diff --git a/components/suggestions/blocklist_store_unittest.cc b/components/suggestions/blocklist_store_unittest.cc deleted file mode 100644 index 7fb8538..0000000 --- a/components/suggestions/blocklist_store_unittest.cc +++ /dev/null
@@ -1,173 +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. - -#include "components/suggestions/blocklist_store.h" - -#include <memory> -#include <set> -#include <string> - -#include "base/macros.h" -#include "components/suggestions/proto/suggestions.pb.h" -#include "components/sync_preferences/testing_pref_service_syncable.h" -#include "testing/gtest/include/gtest/gtest.h" - -using sync_preferences::TestingPrefServiceSyncable; - -namespace suggestions { - -namespace { - -const char kTestUrlA[] = "http://aaa.com/"; -const char kTestUrlB[] = "http://bbb.com/"; -const char kTestUrlC[] = "http://ccc.com/"; -const char kTestUrlD[] = "http://ddd.com/"; - -SuggestionsProfile CreateSuggestions(std::set<std::string> urls) { - SuggestionsProfile suggestions; - for (auto& url : urls) { - ChromeSuggestion* suggestion = suggestions.add_suggestions(); - suggestion->set_url(url); - } - suggestions.set_timestamp(123); - return suggestions; -} - -void ValidateSuggestions(const SuggestionsProfile& expected, - const SuggestionsProfile& actual) { - ASSERT_EQ(expected.suggestions_size(), actual.suggestions_size()); - for (int i = 0; i < expected.suggestions_size(); ++i) { - EXPECT_EQ(expected.suggestions(i).url(), actual.suggestions(i).url()); - EXPECT_EQ(expected.suggestions(i).title(), actual.suggestions(i).title()); - EXPECT_EQ(expected.suggestions(i).favicon_url(), - actual.suggestions(i).favicon_url()); - } -} - -} // namespace - -class BlocklistStoreTest : public testing::Test { - public: - BlocklistStoreTest() - : pref_service_(new sync_preferences::TestingPrefServiceSyncable) {} - - void SetUp() override { - BlocklistStore::RegisterProfilePrefs(pref_service()->registry()); - } - - sync_preferences::TestingPrefServiceSyncable* pref_service() { - return pref_service_.get(); - } - - private: - std::unique_ptr<sync_preferences::TestingPrefServiceSyncable> pref_service_; - - DISALLOW_COPY_AND_ASSIGN(BlocklistStoreTest); -}; - -// Tests adding, removing to the blocklist and filtering. -TEST_F(BlocklistStoreTest, BasicInteractions) { - BlocklistStore blocklist_store(pref_service()); - - // Create suggestions with A, B and C. C and D will be added to the blocklist. - std::set<std::string> suggested_urls; - suggested_urls.insert(kTestUrlA); - suggested_urls.insert(kTestUrlB); - const SuggestionsProfile suggestions_filtered = - CreateSuggestions(suggested_urls); - suggested_urls.insert(kTestUrlC); - const SuggestionsProfile original_suggestions = - CreateSuggestions(suggested_urls); - SuggestionsProfile suggestions; - - // Filter with an empty blocklist. - suggestions.CopyFrom(original_suggestions); - blocklist_store.FilterSuggestions(&suggestions); - ValidateSuggestions(original_suggestions, suggestions); - - // Add C and D to the blocklist and filter. - suggestions.CopyFrom(original_suggestions); - EXPECT_TRUE(blocklist_store.BlocklistUrl(GURL(kTestUrlC))); - EXPECT_TRUE(blocklist_store.BlocklistUrl(GURL(kTestUrlD))); - blocklist_store.FilterSuggestions(&suggestions); - ValidateSuggestions(suggestions_filtered, suggestions); - - // Remove C from the blocklist and filter. - suggestions.CopyFrom(original_suggestions); - EXPECT_TRUE(blocklist_store.RemoveUrl(GURL(kTestUrlC))); - blocklist_store.FilterSuggestions(&suggestions); - ValidateSuggestions(original_suggestions, suggestions); -} - -TEST_F(BlocklistStoreTest, BlocklistTwiceSuceeds) { - BlocklistStore blocklist_store(pref_service()); - EXPECT_TRUE(blocklist_store.BlocklistUrl(GURL(kTestUrlA))); - EXPECT_TRUE(blocklist_store.BlocklistUrl(GURL(kTestUrlA))); -} - -TEST_F(BlocklistStoreTest, RemoveUnknownUrlFails) { - BlocklistStore blocklist_store(pref_service()); - EXPECT_FALSE(blocklist_store.RemoveUrl(GURL(kTestUrlA))); -} - -TEST_F(BlocklistStoreTest, TestGetTimeUntilReadyForUpload) { - // Tests assumes completion within 1 hour. - base::TimeDelta upload_delay = base::TimeDelta::FromHours(1); - base::TimeDelta no_delay = base::TimeDelta::FromHours(0); - std::unique_ptr<BlocklistStore> blocklist_store( - new BlocklistStore(pref_service(), upload_delay)); - base::TimeDelta candidate_delta; - - // Blocklist is empty. - EXPECT_FALSE(blocklist_store->GetTimeUntilReadyForUpload(&candidate_delta)); - EXPECT_FALSE(blocklist_store->GetTimeUntilURLReadyForUpload( - GURL(kTestUrlA), &candidate_delta)); - - // Blocklist contains kTestUrlA. - EXPECT_TRUE(blocklist_store->BlocklistUrl(GURL(kTestUrlA))); - candidate_delta = upload_delay + base::TimeDelta::FromDays(1); - EXPECT_TRUE(blocklist_store->GetTimeUntilReadyForUpload(&candidate_delta)); - EXPECT_LE(candidate_delta, upload_delay); - EXPECT_GE(candidate_delta, no_delay); - candidate_delta = upload_delay + base::TimeDelta::FromDays(1); - EXPECT_TRUE(blocklist_store->GetTimeUntilURLReadyForUpload(GURL(kTestUrlA), - &candidate_delta)); - EXPECT_LE(candidate_delta, upload_delay); - EXPECT_GE(candidate_delta, no_delay); - EXPECT_FALSE(blocklist_store->GetTimeUntilURLReadyForUpload( - GURL(kTestUrlB), &candidate_delta)); - - // There should be no candidate for upload since the upload delay is 1 day. - // Note: this is a test that relies on timing. - GURL retrieved; - EXPECT_FALSE(blocklist_store->GetCandidateForUpload(&retrieved)); - - // Same, but with an upload delay of 0. - blocklist_store = std::make_unique<BlocklistStore>(pref_service(), no_delay); - EXPECT_TRUE(blocklist_store->BlocklistUrl(GURL(kTestUrlA))); - candidate_delta = no_delay + base::TimeDelta::FromDays(1); - EXPECT_TRUE(blocklist_store->GetTimeUntilReadyForUpload(&candidate_delta)); - EXPECT_EQ(candidate_delta, no_delay); - candidate_delta = no_delay + base::TimeDelta::FromDays(1); - EXPECT_TRUE(blocklist_store->GetTimeUntilURLReadyForUpload(GURL(kTestUrlA), - &candidate_delta)); - EXPECT_EQ(candidate_delta, no_delay); -} - -TEST_F(BlocklistStoreTest, GetCandidateForUpload) { - BlocklistStore blocklist_store(pref_service(), base::TimeDelta::FromDays(0)); - // Empty blocklist. - GURL retrieved; - EXPECT_FALSE(blocklist_store.GetCandidateForUpload(&retrieved)); - - // Blocklist A and B. Expect to retrieve A or B. - EXPECT_TRUE(blocklist_store.BlocklistUrl(GURL(kTestUrlA))); - EXPECT_TRUE(blocklist_store.BlocklistUrl(GURL(kTestUrlB))); - EXPECT_TRUE(blocklist_store.GetCandidateForUpload(&retrieved)); - std::string retrieved_string = retrieved.spec(); - EXPECT_TRUE(retrieved_string == std::string(kTestUrlA) || - retrieved_string == std::string(kTestUrlB)); -} - -} // namespace suggestions
diff --git a/components/suggestions/proto/BUILD.gn b/components/suggestions/proto/BUILD.gn deleted file mode 100644 index 1a6018b..0000000 --- a/components/suggestions/proto/BUILD.gn +++ /dev/null
@@ -1,9 +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. - -import("//third_party/protobuf/proto_library.gni") - -proto_library("proto") { - sources = [ "suggestions.proto" ] -}
diff --git a/components/suggestions/proto/suggestions.proto b/components/suggestions/proto/suggestions.proto deleted file mode 100644 index ff0a4c6d..0000000 --- a/components/suggestions/proto/suggestions.proto +++ /dev/null
@@ -1,81 +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. - -syntax = "proto2"; - -option optimize_for = LITE_RUNTIME; - -package suggestions; - -// Providers are identified with an ID. -enum ProviderId { - SERVER0 = 0; - // SERVER1 through 8 were never used. - SERVER8 = 8; - SERVER9 = 9; - SERVER10 = 10; - SERVER11 = 11; -} - -// The SuggestionsProfile is a protobuf response from the server that contains -// the list of suggestions to be presented to the user. -// -// Notice that the tags on this proto must match the ones on the server side. -// -// Next tag: 17 -message SuggestionsProfile { - repeated ChromeSuggestion suggestions = 1; - - reserved 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15; - - // Timestamp when the profile was generated (usec). - optional int64 timestamp = 16; -} - -// An individual suggestion. -// -// Notice that the tags on this proto must match the ones on the server side. -// -// Next tag: 15 -message ChromeSuggestion { - // The URL of the suggestion. - optional string url = 1; - - // Title of the suggestion. - optional string title = 2; - - // The URL of the favicon associated with this page. - optional string favicon_url = 3; - - reserved 4; - - // The provider(s) responsible for this suggestion. - repeated ProviderId providers = 5; - - reserved 6; - - // The timestamp (usec) at which this suggestion ceases to be valid. - optional int64 expiry_ts = 7; - - reserved 8, 9, 10, 11, 12, 13, 14; -} - -// A list of URLs that should be filtered from the SuggestionsProfile. -// -// Next tag: 2 -message SuggestionsBlocklist { - // URLs that make up the blocklist. - repeated string urls = 1; -} - -// ImageData contains the data to represent a website image (e.g. thumbnail). -// -// Next tag: 3 -message ImageData { - // The URL of the website represented by this image. - optional string url = 1; - - // Bitmap bytes, encoded as JPEG. - optional bytes data = 2; -}
diff --git a/components/suggestions/suggestions_pref_names.cc b/components/suggestions/suggestions_pref_names.cc deleted file mode 100644 index 3648e3795..0000000 --- a/components/suggestions/suggestions_pref_names.cc +++ /dev/null
@@ -1,19 +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. - -#include "components/suggestions/suggestions_pref_names.h" - -namespace suggestions { -namespace prefs { - -// A cache of a suggestions blocklist, represented as a serialized -// SuggestionsBlocklist protobuf. -const char kSuggestionsBlocklist[] = "suggestions.blacklist"; - -// A cache of suggestions represented as a serialized SuggestionsProfile -// protobuf. -const char kSuggestionsData[] = "suggestions.data"; - -} // namespace prefs -} // namespace suggestions
diff --git a/components/suggestions/suggestions_pref_names.h b/components/suggestions/suggestions_pref_names.h deleted file mode 100644 index 9d37cd34..0000000 --- a/components/suggestions/suggestions_pref_names.h +++ /dev/null
@@ -1,19 +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. - -#ifndef COMPONENTS_SUGGESTIONS_SUGGESTIONS_PREF_NAMES_H_ -#define COMPONENTS_SUGGESTIONS_SUGGESTIONS_PREF_NAMES_H_ - -namespace suggestions { -namespace prefs { - -// Alphabetical list of preference names specific to the Suggestions -// component. Keep alphabetized, and document each in the .cc file. -extern const char kSuggestionsBlocklist[]; -extern const char kSuggestionsData[]; - -} // namespace prefs -} // namespace suggestions - -#endif // COMPONENTS_SUGGESTIONS_SUGGESTIONS_PREF_NAMES_H_
diff --git a/components/suggestions/suggestions_service.h b/components/suggestions/suggestions_service.h deleted file mode 100644 index 43daf37..0000000 --- a/components/suggestions/suggestions_service.h +++ /dev/null
@@ -1,54 +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. - -#ifndef COMPONENTS_SUGGESTIONS_SUGGESTIONS_SERVICE_H_ -#define COMPONENTS_SUGGESTIONS_SUGGESTIONS_SERVICE_H_ - -#include "base/callback.h" -#include "base/callback_list.h" -#include "base/macros.h" -#include "components/keyed_service/core/keyed_service.h" -#include "components/suggestions/proto/suggestions.pb.h" -#include "third_party/abseil-cpp/absl/types/optional.h" -#include "url/gurl.h" - -namespace suggestions { - -// An interface to fetch server suggestions asynchronously. -class SuggestionsService : public KeyedService { - public: - using ResponseCallback = - base::RepeatingCallback<void(const SuggestionsProfile&)>; - - using ResponseCallbackList = - base::RepeatingCallbackList<void(const SuggestionsProfile&)>; - - // Initiates a network request for suggestions if sync state allows and there - // is no pending request. Returns true iff sync state allowed for a request, - // whether a new request was actually sent or not. - virtual bool FetchSuggestionsData() = 0; - - // Returns the current set of suggestions from the cache. - virtual absl::optional<SuggestionsProfile> GetSuggestionsDataFromCache() - const = 0; - - // Adds a callback that is called when the suggestions are updated. - virtual base::CallbackListSubscription AddCallback( - const ResponseCallback& callback) WARN_UNUSED_RESULT = 0; - - // Adds a URL to the blocklist cache, returning true on success or false on - // failure. The URL will eventually be uploaded to the server. - virtual bool BlocklistURL(const GURL& candidate_url) = 0; - - // Removes a URL from the local blocklist, returning true on success or false - // on failure. - virtual bool UndoBlocklistURL(const GURL& url) = 0; - - // Removes all URLs from the blocklist. - virtual void ClearBlocklist() = 0; -}; - -} // namespace suggestions - -#endif // COMPONENTS_SUGGESTIONS_SUGGESTIONS_SERVICE_H_
diff --git a/components/suggestions/suggestions_service_impl.cc b/components/suggestions/suggestions_service_impl.cc deleted file mode 100644 index 7dd92fe..0000000 --- a/components/suggestions/suggestions_service_impl.cc +++ /dev/null
@@ -1,556 +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. - -#include "components/suggestions/suggestions_service_impl.h" - -#include <memory> -#include <utility> - -#include "base/bind.h" -#include "base/feature_list.h" -#include "base/location.h" -#include "base/metrics/field_trial_params.h" -#include "base/metrics/histogram_functions.h" -#include "base/metrics/histogram_macros.h" -#include "base/strings/strcat.h" -#include "base/strings/string_number_conversions.h" -#include "base/strings/string_util.h" -#include "base/strings/stringprintf.h" -#include "build/build_config.h" -#include "components/google/core/common/google_util.h" -#include "components/pref_registry/pref_registry_syncable.h" -#include "components/signin/public/identity_manager/identity_manager.h" -#include "components/signin/public/identity_manager/primary_account_access_token_fetcher.h" -#include "components/signin/public/identity_manager/scope_set.h" -#include "components/suggestions/blocklist_store.h" -#include "components/suggestions/suggestions_store.h" -#include "components/variations/net/variations_http_headers.h" -#include "google_apis/gaia/gaia_constants.h" -#include "net/base/escape.h" -#include "net/base/load_flags.h" -#include "net/base/net_errors.h" -#include "net/base/url_util.h" -#include "net/http/http_response_headers.h" -#include "net/http/http_status_code.h" -#include "net/http/http_util.h" -#include "net/traffic_annotation/network_traffic_annotation.h" -#include "services/network/public/cpp/resource_request.h" -#include "services/network/public/cpp/shared_url_loader_factory.h" -#include "services/network/public/cpp/simple_url_loader.h" - -using base::TimeDelta; - -namespace suggestions { - -namespace { - -// Used to UMA log the state of the last response from the server. -enum SuggestionsResponseState { - RESPONSE_EMPTY, - RESPONSE_INVALID, - RESPONSE_VALID, - RESPONSE_STATE_SIZE -}; - -// Will log the supplied response |state|. -void LogResponseState(SuggestionsResponseState state) { - UMA_HISTOGRAM_ENUMERATION("Suggestions.ResponseState", state, - RESPONSE_STATE_SIZE); -} - -const net::BackoffEntry::Policy kBlocklistBackoffPolicy = { - /*num_errors_to_ignore=*/0, - /*initial_delay_ms=*/1000, - /*multiply_factor=*/2.0, - /*jitter_factor=*/0.0, - /*maximum_backoff_ms=*/2 * 60 * 60 * 1000, - /*entry_lifetime_ms=*/-1, - /*always_use_initial_delay=*/true}; - -const char kDefaultGoogleBaseURL[] = "https://www.google.com/"; - -GURL GetGoogleBaseURL() { - GURL url(google_util::CommandLineGoogleBaseURL()); - if (url.is_valid()) - return url; - return GURL(kDefaultGoogleBaseURL); -} - -// Format strings for the various suggestions URLs. They all have two string -// params: The Google base URL and the device type. -// TODO(mathp): Put this in TemplateURL. -const char kSuggestionsURLFormat[] = "%schromesuggestions?%s"; -const char kSuggestionsBlocklistURLPrefixFormat[] = - "%schromesuggestions/blacklist?t=%s&url="; -const char kSuggestionsBlocklistClearURLFormat[] = - "%schromesuggestions/blacklist/clear?t=%s"; - -const char kSuggestionsBlocklistURLParam[] = "url"; -const char kSuggestionsDeviceParam[] = "t=%s"; - -#if defined(OS_ANDROID) || defined(OS_IOS) -const char kDeviceType[] = "2"; -#else -const char kDeviceType[] = "1"; -#endif - -const char kFaviconURL[] = - "https://s2.googleusercontent.com/s2/favicons?domain_url=%s&alt=s&sz=32"; - -// The default expiry timeout is 168 hours. -const int64_t kDefaultExpiryUsec = 168 * base::Time::kMicrosecondsPerHour; - -} // namespace - -SuggestionsServiceImpl::SuggestionsServiceImpl( - signin::IdentityManager* identity_manager, - syncer::SyncService* sync_service, - scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, - std::unique_ptr<SuggestionsStore> suggestions_store, - std::unique_ptr<BlocklistStore> blocklist_store, - const base::TickClock* tick_clock) - : identity_manager_(identity_manager), - sync_service_(sync_service), - history_sync_state_(syncer::UploadState::INITIALIZING), - url_loader_factory_(url_loader_factory), - suggestions_store_(std::move(suggestions_store)), - blocklist_store_(std::move(blocklist_store)), - tick_clock_(tick_clock), - blocklist_upload_backoff_(&kBlocklistBackoffPolicy, tick_clock_), - blocklist_upload_timer_(tick_clock_) { - // |sync_service_| is null if switches::kDisableSync is set (tests use that). - if (sync_service_) - sync_service_observation_.Observe(sync_service_); - // Immediately get the current sync state, so we'll flush the cache if - // necessary. - OnStateChanged(sync_service_); - // This makes sure the initial delay is actually respected. - blocklist_upload_backoff_.InformOfRequest(/*succeeded=*/true); -} - -SuggestionsServiceImpl::~SuggestionsServiceImpl() = default; - -bool SuggestionsServiceImpl::FetchSuggestionsData() { - DCHECK(thread_checker_.CalledOnValidThread()); - // If sync state allows, issue a network request to refresh the suggestions. - if (history_sync_state_ != syncer::UploadState::ACTIVE) - return false; - IssueRequestIfNoneOngoing(BuildSuggestionsURL()); - return true; -} - -absl::optional<SuggestionsProfile> -SuggestionsServiceImpl::GetSuggestionsDataFromCache() const { - SuggestionsProfile suggestions; - // In case of empty cache or error, return empty. - if (!suggestions_store_->LoadSuggestions(&suggestions)) - return absl::nullopt; - blocklist_store_->FilterSuggestions(&suggestions); - return suggestions; -} - -base::CallbackListSubscription SuggestionsServiceImpl::AddCallback( - const ResponseCallback& callback) { - return callback_list_.Add(callback); -} - -bool SuggestionsServiceImpl::BlocklistURL(const GURL& candidate_url) { - DCHECK(thread_checker_.CalledOnValidThread()); - - // TODO(treib): Do we need to check |history_sync_state_| here? - - if (!blocklist_store_->BlocklistUrl(candidate_url)) - return false; - - callback_list_.Notify( - GetSuggestionsDataFromCache().value_or(SuggestionsProfile())); - - // Blocklist uploads are scheduled on any request completion, so only schedule - // an upload if there is no ongoing request. - if (!pending_request_) - ScheduleBlocklistUpload(); - - return true; -} - -bool SuggestionsServiceImpl::UndoBlocklistURL(const GURL& url) { - DCHECK(thread_checker_.CalledOnValidThread()); - - // TODO(treib): Do we need to check |history_sync_state_| here? - - TimeDelta time_delta; - if (blocklist_store_->GetTimeUntilURLReadyForUpload(url, &time_delta) && - time_delta > TimeDelta::FromSeconds(0) && - blocklist_store_->RemoveUrl(url)) { - // The URL was not yet candidate for upload to the server and could be - // removed from the blocklist. - callback_list_.Notify( - GetSuggestionsDataFromCache().value_or(SuggestionsProfile())); - return true; - } - return false; -} - -void SuggestionsServiceImpl::ClearBlocklist() { - DCHECK(thread_checker_.CalledOnValidThread()); - - // TODO(treib): Do we need to check |history_sync_state_| here? - - blocklist_store_->ClearBlocklist(); - callback_list_.Notify( - GetSuggestionsDataFromCache().value_or(SuggestionsProfile())); - IssueRequestIfNoneOngoing(BuildSuggestionsBlocklistClearURL()); -} - -base::TimeDelta SuggestionsServiceImpl::BlocklistDelayForTesting() const { - return blocklist_upload_backoff_.GetTimeUntilRelease(); -} - -bool SuggestionsServiceImpl::HasPendingRequestForTesting() const { - return !!pending_request_; -} - -// static -bool SuggestionsServiceImpl::GetBlocklistedUrl(const GURL& original_url, - GURL* blocklisted_url) { - bool is_blocklist_request = base::StartsWith( - original_url.spec(), BuildSuggestionsBlocklistURLPrefix(), - base::CompareCase::SENSITIVE); - if (!is_blocklist_request) - return false; - - // Extract the blocklisted URL from the blocklist request. - std::string blocklisted; - if (!net::GetValueForKeyInQuery(original_url, kSuggestionsBlocklistURLParam, - &blocklisted)) { - return false; - } - - *blocklisted_url = GURL(blocklisted); - return true; -} - -// static -void SuggestionsServiceImpl::RegisterProfilePrefs( - user_prefs::PrefRegistrySyncable* registry) { - SuggestionsStore::RegisterProfilePrefs(registry); - BlocklistStore::RegisterProfilePrefs(registry); -} - -// static -GURL SuggestionsServiceImpl::BuildSuggestionsURL() { - std::string query = base::StringPrintf(kSuggestionsDeviceParam, kDeviceType); - return GURL(base::StringPrintf( - kSuggestionsURLFormat, GetGoogleBaseURL().spec().c_str(), query.c_str())); -} - -// static -std::string SuggestionsServiceImpl::BuildSuggestionsBlocklistURLPrefix() { - return base::StringPrintf(kSuggestionsBlocklistURLPrefixFormat, - GetGoogleBaseURL().spec().c_str(), kDeviceType); -} - -// static -GURL SuggestionsServiceImpl::BuildSuggestionsBlocklistURL( - const GURL& candidate_url) { - return GURL(BuildSuggestionsBlocklistURLPrefix() + - net::EscapeQueryParamValue(candidate_url.spec(), true)); -} - -// static -GURL SuggestionsServiceImpl::BuildSuggestionsBlocklistClearURL() { - return GURL(base::StringPrintf(kSuggestionsBlocklistClearURLFormat, - GetGoogleBaseURL().spec().c_str(), - kDeviceType)); -} - -SuggestionsServiceImpl::RefreshAction -SuggestionsServiceImpl::RefreshHistorySyncState() { - syncer::UploadState new_sync_state = syncer::GetUploadToGoogleState( - sync_service_, syncer::HISTORY_DELETE_DIRECTIVES); - if (history_sync_state_ == new_sync_state) - return NO_ACTION; - - syncer::UploadState old_sync_state = history_sync_state_; - history_sync_state_ = new_sync_state; - - switch (new_sync_state) { - case syncer::UploadState::INITIALIZING: - // In this state, we do not issue server requests, but we will serve from - // cache if available -> no action required. - return NO_ACTION; - case syncer::UploadState::ACTIVE: - // If history sync was just enabled, immediately fetch suggestions, so - // that hopefully the next NTP will already get them. - if (old_sync_state == syncer::UploadState::NOT_ACTIVE) - return FETCH_SUGGESTIONS; - // Otherwise, this just means sync initialization finished. - return NO_ACTION; - case syncer::UploadState::NOT_ACTIVE: - // If the user signed out (or disabled history sync), we have to clear - // everything. - return CLEAR_SUGGESTIONS; - } - NOTREACHED(); - return NO_ACTION; -} - -void SuggestionsServiceImpl::OnStateChanged(syncer::SyncService* sync) { - DCHECK(sync_service_ == sync); - - switch (RefreshHistorySyncState()) { - case NO_ACTION: - break; - case CLEAR_SUGGESTIONS: - // Cancel any ongoing request, to stop interacting with the server. - pending_request_.reset(nullptr); - suggestions_store_->ClearSuggestions(); - callback_list_.Notify(SuggestionsProfile()); - break; - case FETCH_SUGGESTIONS: - IssueRequestIfNoneOngoing(BuildSuggestionsURL()); - break; - } -} - -void SuggestionsServiceImpl::SetDefaultExpiryTimestamp( - SuggestionsProfile* suggestions, - int64_t default_timestamp_usec) { - for (ChromeSuggestion& suggestion : *suggestions->mutable_suggestions()) { - // Do not set expiry if the server has already provided a more specific - // expiry time for this suggestion. - if (!suggestion.has_expiry_ts()) - suggestion.set_expiry_ts(default_timestamp_usec); - } -} - -void SuggestionsServiceImpl::IssueRequestIfNoneOngoing(const GURL& url) { - // If there is an ongoing request, let it complete. - // This will silently swallow blocklist and clearblocklist requests if a - // request happens to be ongoing. - // TODO(treib): Queue such requests and send them after the current one - // completes. - if (pending_request_) - return; - // If there is an ongoing token request, also wait for that. - if (token_fetcher_) - return; - - signin::ScopeSet scopes{GaiaConstants::kChromeSyncOAuth2Scope}; - token_fetcher_ = std::make_unique<signin::PrimaryAccountAccessTokenFetcher>( - "suggestions_service", identity_manager_, scopes, - base::BindOnce(&SuggestionsServiceImpl::AccessTokenAvailable, - base::Unretained(this), url), - signin::PrimaryAccountAccessTokenFetcher::Mode::kWaitUntilAvailable); -} - -void SuggestionsServiceImpl::AccessTokenAvailable( - const GURL& url, - GoogleServiceAuthError error, - signin::AccessTokenInfo access_token_info) { - DCHECK(token_fetcher_); - token_fetcher_.reset(); - - if (error.state() != GoogleServiceAuthError::NONE) { - blocklist_upload_backoff_.InformOfRequest(/*succeeded=*/false); - ScheduleBlocklistUpload(); - return; - } - - DCHECK(!access_token_info.token.empty()); - - IssueSuggestionsRequest(url, access_token_info.token); -} - -void SuggestionsServiceImpl::IssueSuggestionsRequest( - const GURL& url, - const std::string& access_token) { - DCHECK(!access_token.empty()); - pending_request_ = CreateSuggestionsRequest(url, access_token); - // Unretained is safe because the SimpleURLLoader in |pending_request_| will - // not call the callback after it is deleted. - auto callback = base::BindOnce(&SuggestionsServiceImpl::OnURLFetchComplete, - base::Unretained(this), url); - pending_request_->DownloadToStringOfUnboundedSizeUntilCrashAndDie( - url_loader_factory_.get(), std::move(callback)); - last_request_started_time_ = tick_clock_->NowTicks(); -} - -std::unique_ptr<network::SimpleURLLoader> -SuggestionsServiceImpl::CreateSuggestionsRequest( - const GURL& url, - const std::string& access_token) { - net::NetworkTrafficAnnotationTag traffic_annotation = - net::DefineNetworkTrafficAnnotation("suggestions_service", R"( - semantics { - sender: "Suggestions Service" - description: - "For signed-in users with History Sync enabled, the Suggestions " - "Service fetches website suggestions, based on the user's browsing " - "history, for display on the New Tab page." - trigger: "Opening a New Tab page." - data: "The user's OAuth2 credentials." - destination: GOOGLE_OWNED_SERVICE - } - policy { - cookies_allowed: NO - setting: - "Users can disable this feature by signing out of Chromium, or " - "disabling Sync or History Sync in Chromium settings under " - "Advanced sync settings. The feature is enabled by default." - chrome_policy { - SyncDisabled { - policy_options {mode: MANDATORY} - SyncDisabled: true - } - } - chrome_policy { - SigninAllowed { - policy_options {mode: MANDATORY} - SigninAllowed: false - } - } - })"); - auto resource_request = std::make_unique<network::ResourceRequest>(); - resource_request->url = url; - resource_request->method = "GET"; - resource_request->load_flags = net::LOAD_DISABLE_CACHE; - resource_request->credentials_mode = network::mojom::CredentialsMode::kOmit; - // Add Chrome experiment state to the request headers. - // TODO: We should call AppendVariationHeaders with explicit - // variations::SignedIn::kNo If the access_token is empty - variations::AppendVariationsHeaderUnknownSignedIn( - url, variations::InIncognito::kNo, resource_request.get()); - if (!access_token.empty()) { - resource_request->headers.SetHeader( - "Authorization", base::StrCat({"Bearer ", access_token})); - } - - auto loader = network::SimpleURLLoader::Create(std::move(resource_request), - traffic_annotation); - - // We use non-200 error codes as a signal to clear the cache in - // OnURLFetchComplete. - loader->SetAllowHttpErrorResults(true); - return loader; -} - -void SuggestionsServiceImpl::OnURLFetchComplete( - const GURL& original_url, - std::unique_ptr<std::string> suggestions_data) { - DCHECK(thread_checker_.CalledOnValidThread()); - - // The SimpleURLLoader will be deleted when the request is handled. - std::unique_ptr<const network::SimpleURLLoader> request = - std::move(pending_request_); - DCHECK(request); - - bool valid_request = suggestions_data && request->NetError() == net::OK; - if (!valid_request) { - // This represents network errors (i.e. the server did not provide a - // response). - base::UmaHistogramSparse("Suggestions.FailedRequestErrorCode", - -request->NetError()); - DVLOG(1) << "Suggestions server request failed with error: " - << request->NetError() << ": " - << net::ErrorToString(request->NetError()); - blocklist_upload_backoff_.InformOfRequest(/*succeeded=*/false); - ScheduleBlocklistUpload(); - return; - } - - int response_code = 0; - if (request->ResponseInfo() && request->ResponseInfo()->headers) - response_code = request->ResponseInfo()->headers->response_code(); - base::UmaHistogramSparse("Suggestions.FetchResponseCode", response_code); - - if (response_code != net::HTTP_OK) { - // A non-200 response code means that server has no (longer) suggestions for - // this user. Aggressively clear the cache. - suggestions_store_->ClearSuggestions(); - blocklist_upload_backoff_.InformOfRequest(/*succeeded=*/false); - ScheduleBlocklistUpload(); - return; - } - - const TimeDelta latency = - tick_clock_->NowTicks() - last_request_started_time_; - UMA_HISTOGRAM_MEDIUM_TIMES("Suggestions.FetchSuccessLatency", latency); - - // Handle a successful blocklisting. - GURL blocklisted_url; - if (GetBlocklistedUrl(original_url, &blocklisted_url)) - blocklist_store_->RemoveUrl(blocklisted_url); - - // Parse the received suggestions and update the cache, or take proper action - // in the case of invalid response. - SuggestionsProfile suggestions; - if (suggestions_data->empty()) { - LogResponseState(RESPONSE_EMPTY); - suggestions_store_->ClearSuggestions(); - } else if (suggestions.ParseFromString(*suggestions_data)) { - LogResponseState(RESPONSE_VALID); - int64_t now_usec = - (base::Time::NowFromSystemTime() - base::Time::UnixEpoch()) - .ToInternalValue(); - SetDefaultExpiryTimestamp(&suggestions, now_usec + kDefaultExpiryUsec); - PopulateExtraData(&suggestions); - suggestions_store_->StoreSuggestions(suggestions); - } else { - LogResponseState(RESPONSE_INVALID); - } - - callback_list_.Notify( - GetSuggestionsDataFromCache().value_or(SuggestionsProfile())); - - blocklist_upload_backoff_.InformOfRequest(/*succeeded=*/true); - ScheduleBlocklistUpload(); -} - -void SuggestionsServiceImpl::PopulateExtraData( - SuggestionsProfile* suggestions) { - for (ChromeSuggestion& suggestion : *suggestions->mutable_suggestions()) { - if (!suggestion.has_favicon_url() || suggestion.favicon_url().empty()) { - suggestion.set_favicon_url( - base::StringPrintf(kFaviconURL, suggestion.url().c_str())); - } - } -} - -void SuggestionsServiceImpl::Shutdown() { - // Cancel pending request. - pending_request_.reset(nullptr); - - sync_service_observation_.Reset(); -} - -void SuggestionsServiceImpl::ScheduleBlocklistUpload() { - DCHECK(thread_checker_.CalledOnValidThread()); - TimeDelta time_delta; - if (blocklist_store_->GetTimeUntilReadyForUpload(&time_delta)) { - // Blocklist cache is not empty: schedule. - blocklist_upload_timer_.Start( - FROM_HERE, time_delta + blocklist_upload_backoff_.GetTimeUntilRelease(), - base::BindOnce(&SuggestionsServiceImpl::UploadOneFromBlocklist, - weak_ptr_factory_.GetWeakPtr())); - } -} - -void SuggestionsServiceImpl::UploadOneFromBlocklist() { - DCHECK(thread_checker_.CalledOnValidThread()); - - GURL blocklisted_url; - if (blocklist_store_->GetCandidateForUpload(&blocklisted_url)) { - // Issue a blocklisting request. Even if this request ends up not being sent - // because of an ongoing request, a blocklist request is later scheduled. - IssueRequestIfNoneOngoing(BuildSuggestionsBlocklistURL(blocklisted_url)); - return; - } - - // Even though there's no candidate for upload, the blocklist might not be - // empty. - ScheduleBlocklistUpload(); -} - -} // namespace suggestions
diff --git a/components/suggestions/suggestions_service_impl.h b/components/suggestions/suggestions_service_impl.h deleted file mode 100644 index eaa210d2..0000000 --- a/components/suggestions/suggestions_service_impl.h +++ /dev/null
@@ -1,221 +0,0 @@ -// Copyright 2016 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_SUGGESTIONS_SUGGESTIONS_SERVICE_IMPL_H_ -#define COMPONENTS_SUGGESTIONS_SUGGESTIONS_SERVICE_IMPL_H_ - -#include <stdint.h> - -#include <memory> -#include <string> - -#include "base/callback.h" -#include "base/callback_list.h" -#include "base/compiler_specific.h" -#include "base/macros.h" -#include "base/memory/weak_ptr.h" -#include "base/scoped_observation.h" -#include "base/threading/thread_checker.h" -#include "base/time/tick_clock.h" -#include "base/time/time.h" -#include "base/timer/timer.h" -#include "components/signin/public/identity_manager/access_token_info.h" -#include "components/suggestions/proto/suggestions.pb.h" -#include "components/suggestions/suggestions_service.h" -#include "components/sync/driver/sync_service.h" -#include "components/sync/driver/sync_service_observer.h" -#include "components/sync/driver/sync_service_utils.h" -#include "google_apis/gaia/google_service_auth_error.h" -#include "net/base/backoff_entry.h" -#include "net/url_request/url_fetcher_delegate.h" -#include "third_party/abseil-cpp/absl/types/optional.h" -#include "url/gurl.h" - -namespace signin { -class IdentityManager; -class PrimaryAccountAccessTokenFetcher; -} // namespace signin - -namespace network { -class SharedURLLoaderFactory; -class SimpleURLLoader; -} // namespace network - -namespace user_prefs { -class PrefRegistrySyncable; -} // namespace user_prefs - -namespace suggestions { - -class BlocklistStore; -class SuggestionsStore; - -// Actual (non-test) implementation of the SuggestionsService interface. -class SuggestionsServiceImpl : public SuggestionsService, - public syncer::SyncServiceObserver { - public: - SuggestionsServiceImpl( - signin::IdentityManager* identity_manager, - syncer::SyncService* sync_service, - scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, - std::unique_ptr<SuggestionsStore> suggestions_store, - std::unique_ptr<BlocklistStore> blocklist_store, - const base::TickClock* tick_clock); - ~SuggestionsServiceImpl() override; - - // SuggestionsService implementation. - bool FetchSuggestionsData() override; - absl::optional<SuggestionsProfile> GetSuggestionsDataFromCache() - const override; - base::CallbackListSubscription AddCallback( - const ResponseCallback& callback) override WARN_UNUSED_RESULT; - bool BlocklistURL(const GURL& candidate_url) override; - bool UndoBlocklistURL(const GURL& url) override; - void ClearBlocklist() override; - - base::TimeDelta BlocklistDelayForTesting() const; - bool HasPendingRequestForTesting() const; - - // Determines which URL a blocklist request URL was for. Returns whether if - // |original_url| is a blocklist request, and puts the URL to be blocklisted - // in |blocklisted_url|, which must not be |nullptr|. - static bool GetBlocklistedUrl(const GURL& original_url, - GURL* blocklisted_url); - - // Register SuggestionsService related prefs in the Profile prefs. - static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry); - - private: - friend class SuggestionsServiceTest; - - // Establishes the different sync states that matter to SuggestionsService. - enum SyncState { - // State: Sync service is not initialized, yet not disabled. History sync - // state is unknown (since not initialized). - // Behavior: Do not issue server requests, but serve from cache if - // available. - NOT_INITIALIZED_ENABLED, - - // State: Sync service is initialized, sync is enabled and history sync is - // enabled. - // Behavior: Update suggestions from the server on FetchSuggestionsData(). - INITIALIZED_ENABLED_HISTORY, - - // State: Sync service is disabled or history sync is disabled. - // Behavior: Do not issue server requests. Clear the cache. Serve empty - // suggestions. - SYNC_OR_HISTORY_SYNC_DISABLED, - }; - - // The action that should be taken as the result of a RefreshHistorySyncState - // call. - enum RefreshAction { NO_ACTION, FETCH_SUGGESTIONS, CLEAR_SUGGESTIONS }; - - // Helpers to build the various suggestions URLs. These are static members - // rather than local functions in the .cc file to make them accessible to - // tests. - static GURL BuildSuggestionsURL(); - static std::string BuildSuggestionsBlocklistURLPrefix(); - static GURL BuildSuggestionsBlocklistURL(const GURL& candidate_url); - static GURL BuildSuggestionsBlocklistClearURL(); - - // Re-computes |history_sync_state_| from the sync service. Returns the action - // that should be taken in response. - RefreshAction RefreshHistorySyncState() WARN_UNUSED_RESULT; - - // syncer::SyncServiceObserver implementation. - void OnStateChanged(syncer::SyncService* sync) override; - - // Sets default timestamp for suggestions which do not have expiry timestamp. - void SetDefaultExpiryTimestamp(SuggestionsProfile* suggestions, - int64_t timestamp_usec); - - // Issues a network request if there isn't already one happening. - void IssueRequestIfNoneOngoing(const GURL& url); - - // Called when an access token request completes (successfully or not). - void AccessTokenAvailable(const GURL& url, - GoogleServiceAuthError error, - signin::AccessTokenInfo access_token_info); - - // Issues a network request for suggestions (fetch, blocklist, or clear - // blocklist, depending on |url|). - void IssueSuggestionsRequest(const GURL& url, - const std::string& access_token); - - // Creates a request to the suggestions service, properly setting headers. - // If OAuth2 authentication is enabled, |access_token| should be a valid - // OAuth2 access token, and will be written into an auth header. - std::unique_ptr<network::SimpleURLLoader> CreateSuggestionsRequest( - const GURL& url, - const std::string& access_token); - - // Called when fetch request completes. Parses the received suggestions data, - // and dispatches them to callbacks stored in queue. - void OnURLFetchComplete(const GURL& original_url, - std::unique_ptr<std::string> suggestions_data); - - // KeyedService implementation. - void Shutdown() override; - - // Schedules a blocklisting request if the local blocklist isn't empty. - void ScheduleBlocklistUpload(); - - // If the local blocklist isn't empty, picks a URL from it and issues a - // blocklist request for it. - void UploadOneFromBlocklist(); - - // Adds extra data to suggestions profile. - void PopulateExtraData(SuggestionsProfile* suggestions); - - base::ThreadChecker thread_checker_; - - signin::IdentityManager* identity_manager_; - - syncer::SyncService* sync_service_; - base::ScopedObservation<syncer::SyncService, syncer::SyncServiceObserver> - sync_service_observation_{this}; - - // The state of history sync, i.e. are we uploading history data to Google? - syncer::UploadState history_sync_state_; - - const scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_; - - // The cache for the suggestions. - std::unique_ptr<SuggestionsStore> suggestions_store_; - - // The local cache for temporary blocklist, until uploaded to the server. - std::unique_ptr<BlocklistStore> blocklist_store_; - - const base::TickClock* tick_clock_; - - // Backoff for scheduling blocklist upload tasks. - net::BackoffEntry blocklist_upload_backoff_; - - base::OneShotTimer blocklist_upload_timer_; - - // Helper for fetching OAuth2 access tokens. This is non-null iff an access - // token request is currently in progress. - std::unique_ptr<signin::PrimaryAccountAccessTokenFetcher> token_fetcher_; - - // Contains the current suggestions fetch request. Will only have a value - // while a request is pending, and will be reset by |OnURLFetchComplete| or - // if cancelled. - std::unique_ptr<network::SimpleURLLoader> pending_request_; - - // The start time of the previous suggestions request. This is used to measure - // the latency of requests. Initially zero. - base::TimeTicks last_request_started_time_; - - ResponseCallbackList callback_list_; - - // For callbacks may be run after destruction. - base::WeakPtrFactory<SuggestionsServiceImpl> weak_ptr_factory_{this}; - - DISALLOW_COPY_AND_ASSIGN(SuggestionsServiceImpl); -}; - -} // namespace suggestions - -#endif // COMPONENTS_SUGGESTIONS_SUGGESTIONS_SERVICE_IMPL_H_
diff --git a/components/suggestions/suggestions_service_impl_unittest.cc b/components/suggestions/suggestions_service_impl_unittest.cc deleted file mode 100644 index ef53581..0000000 --- a/components/suggestions/suggestions_service_impl_unittest.cc +++ /dev/null
@@ -1,686 +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. - -#include "components/suggestions/suggestions_service_impl.h" - -#include <stdint.h> - -#include <memory> -#include <utility> -#include <vector> - -#include "base/bind.h" -#include "base/macros.h" -#include "base/memory/ptr_util.h" -#include "base/test/mock_callback.h" -#include "base/test/task_environment.h" -#include "components/signin/public/identity_manager/identity_test_environment.h" -#include "components/suggestions/blocklist_store.h" -#include "components/suggestions/proto/suggestions.pb.h" -#include "components/suggestions/suggestions_store.h" -#include "components/sync/driver/sync_service.h" -#include "components/sync/driver/test_sync_service.h" -#include "components/variations/scoped_variations_ids_provider.h" -#include "net/base/url_util.h" -#include "net/http/http_response_headers.h" -#include "net/http/http_status_code.h" -#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h" -#include "services/network/public/mojom/url_response_head.mojom.h" -#include "services/network/test/test_url_loader_factory.h" -#include "services/network/test/test_utils.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "ui/gfx/image/image.h" - -using syncer::SyncServiceObserver; -using testing::_; -using testing::AnyNumber; -using testing::DoAll; -using testing::Mock; -using testing::Return; -using testing::SetArgPointee; -using testing::StrictMock; - -namespace { - -const char kEmail[] = "foo_email@gmail.com"; -const char kSuggestionsUrlPath[] = "/chromesuggestions"; -const char kBlocklistUrlPath[] = "/chromesuggestions/blacklist"; -const char kBlocklistClearUrlPath[] = "/chromesuggestions/blacklist/clear"; -const char kTestTitle[] = "a title"; -const char kTestUrl[] = "http://go.com"; -const char kTestFaviconUrl[] = - "https://s2.googleusercontent.com/s2/favicons?domain_url=" - "http://go.com&alt=s&sz=32"; -const char kBlocklistedUrl[] = "http://blocklist.com"; -const int64_t kTestSetExpiry = 12121212; // This timestamp lies in the past. - -// GMock matcher for protobuf equality. -MATCHER_P(EqualsProto, message, "") { - // This implementation assumes protobuf serialization is deterministic, which - // is true in practice but technically not something that code is supposed - // to rely on. However, it vastly simplifies the implementation. - std::string expected_serialized, actual_serialized; - message.SerializeToString(&expected_serialized); - arg.SerializeToString(&actual_serialized); - return expected_serialized == actual_serialized; -} - -} // namespace - -namespace suggestions { - -SuggestionsProfile CreateSuggestionsProfile() { - SuggestionsProfile profile; - profile.set_timestamp(123); - ChromeSuggestion* suggestion = profile.add_suggestions(); - suggestion->set_title(kTestTitle); - suggestion->set_url(kTestUrl); - return profile; -} - -class TestSuggestionsStore : public suggestions::SuggestionsStore { - public: - TestSuggestionsStore() { cached_suggestions = CreateSuggestionsProfile(); } - bool LoadSuggestions(SuggestionsProfile* suggestions) override { - suggestions->CopyFrom(cached_suggestions); - return cached_suggestions.suggestions_size(); - } - bool StoreSuggestions(const SuggestionsProfile& suggestions) override { - cached_suggestions.CopyFrom(suggestions); - return true; - } - void ClearSuggestions() override { - cached_suggestions = SuggestionsProfile(); - } - - SuggestionsProfile cached_suggestions; -}; - -class MockBlocklistStore : public suggestions::BlocklistStore { - public: - MOCK_METHOD1(BlocklistUrl, bool(const GURL&)); - MOCK_METHOD0(ClearBlocklist, void()); - MOCK_METHOD1(GetTimeUntilReadyForUpload, bool(base::TimeDelta*)); - MOCK_METHOD2(GetTimeUntilURLReadyForUpload, - bool(const GURL&, base::TimeDelta*)); - MOCK_METHOD1(GetCandidateForUpload, bool(GURL*)); - MOCK_METHOD1(RemoveUrl, bool(const GURL&)); - MOCK_METHOD1(FilterSuggestions, void(SuggestionsProfile*)); -}; - -class SuggestionsServiceTest : public testing::Test { - protected: - SuggestionsServiceTest() { - identity_test_env_.MakePrimaryAccountAvailable(kEmail, - signin::ConsentLevel::kSync); - identity_test_env_.SetAutomaticIssueOfAccessTokens(true); - } - - ~SuggestionsServiceTest() override {} - - void SetUp() override { - sync_service()->SetPreferredDataTypes({syncer::HISTORY_DELETE_DIRECTIVES}); - sync_service()->SetActiveDataTypes({syncer::HISTORY_DELETE_DIRECTIVES}); - - // These objects are owned by the SuggestionsService, but we keep the - // pointers around for testing. - test_suggestions_store_ = new TestSuggestionsStore(); - mock_blocklist_store_ = new StrictMock<MockBlocklistStore>(); - suggestions_service_ = std::make_unique<SuggestionsServiceImpl>( - identity_test_env_.identity_manager(), sync_service(), - base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>( - url_loader_factory()), - base::WrapUnique(test_suggestions_store_), - base::WrapUnique(mock_blocklist_store_), - task_environment_.GetMockTickClock()); - } - - GURL GetCurrentlyQueriedUrl() { - if (url_loader_factory()->NumPending() == 0) - return GURL(); - - return url_loader_factory()->pending_requests()->front().request.url; - } - - bool RespondToSuggestionsFetch(const std::string& response_body, - net::HttpStatusCode response_code, - int net_error = net::OK) { - return RespondToFetch(SuggestionsServiceImpl::BuildSuggestionsURL(), - response_body, response_code, net_error); - } - - bool RespondToBlocklistFetch(const std::string& response_body, - net::HttpStatusCode response_code, - int net_error = net::OK) { - return RespondToFetch(SuggestionsServiceImpl::BuildSuggestionsBlocklistURL( - GURL(kBlocklistedUrl)), - response_body, response_code, net_error); - } - - bool RespondToFetchWithProfile(const SuggestionsProfile& suggestions) { - return RespondToFetch(SuggestionsServiceImpl::BuildSuggestionsURL(), - suggestions.SerializeAsString(), net::HTTP_OK); - } - - bool RespondToFetch(const GURL& url, - const std::string& response_body, - net::HttpStatusCode response_code, - int net_error = net::OK) { - bool rv = url_loader_factory()->SimulateResponseForPendingRequest( - url, network::URLLoaderCompletionStatus(net_error), - network::CreateURLResponseHead(response_code), response_body); - task_environment_.RunUntilIdle(); - return rv; - } - - syncer::TestSyncService* sync_service() { return &test_sync_service_; } - - MockBlocklistStore* blocklist_store() { return mock_blocklist_store_; } - - TestSuggestionsStore* suggestions_store() { return test_suggestions_store_; } - - SuggestionsServiceImpl* suggestions_service() { - return suggestions_service_.get(); - } - - signin::IdentityTestEnvironment* identity_test_env() { - return &identity_test_env_; - } - - network::TestURLLoaderFactory* url_loader_factory() { - return &url_loader_factory_; - } - - base::test::TaskEnvironment task_environment_{ - base::test::TaskEnvironment::TimeSource::MOCK_TIME}; - - private: - variations::ScopedVariationsIdsProvider scoped_variations_ids_provider_{ - variations::VariationsIdsProvider::Mode::kUseSignedInState}; - signin::IdentityTestEnvironment identity_test_env_; - syncer::TestSyncService test_sync_service_; - network::TestURLLoaderFactory url_loader_factory_; - - // Owned by the SuggestionsService. - MockBlocklistStore* mock_blocklist_store_ = nullptr; - TestSuggestionsStore* test_suggestions_store_ = nullptr; - - std::unique_ptr<SuggestionsServiceImpl> suggestions_service_; - - DISALLOW_COPY_AND_ASSIGN(SuggestionsServiceTest); -}; - -TEST_F(SuggestionsServiceTest, FetchSuggestionsData) { - base::MockCallback<SuggestionsService::ResponseCallback> callback; - auto subscription = suggestions_service()->AddCallback(callback.Get()); - - EXPECT_CALL(*blocklist_store(), FilterSuggestions(_)); - EXPECT_CALL(*blocklist_store(), GetTimeUntilReadyForUpload(_)) - .WillOnce(Return(false)); - - // Send the request. The data should be returned to the callback. - suggestions_service()->FetchSuggestionsData(); - - EXPECT_CALL(callback, Run(_)); - - // Wait for the eventual network request. - task_environment_.RunUntilIdle(); - ASSERT_TRUE(GetCurrentlyQueriedUrl().is_valid()); - EXPECT_EQ(GetCurrentlyQueriedUrl().path(), kSuggestionsUrlPath); - ASSERT_TRUE(RespondToFetchWithProfile(CreateSuggestionsProfile())); - - SuggestionsProfile suggestions; - suggestions_store()->LoadSuggestions(&suggestions); - ASSERT_EQ(1, suggestions.suggestions_size()); - EXPECT_EQ(kTestTitle, suggestions.suggestions(0).title()); - EXPECT_EQ(kTestUrl, suggestions.suggestions(0).url()); - EXPECT_EQ(kTestFaviconUrl, suggestions.suggestions(0).favicon_url()); -} - -TEST_F(SuggestionsServiceTest, IgnoresNoopSyncChange) { - base::MockCallback<SuggestionsService::ResponseCallback> callback; - EXPECT_CALL(callback, Run(_)).Times(0); - auto subscription = suggestions_service()->AddCallback(callback.Get()); - - // An no-op change should not result in a suggestions refresh. - static_cast<SyncServiceObserver*>(suggestions_service()) - ->OnStateChanged(sync_service()); - - // Wait for eventual (but unexpected) network requests. - task_environment_.RunUntilIdle(); - EXPECT_FALSE(suggestions_service()->HasPendingRequestForTesting()); -} - -TEST_F(SuggestionsServiceTest, PersistentAuthErrorState) { - // Put some suggestions in. - suggestions_store()->StoreSuggestions(CreateSuggestionsProfile()); - - GoogleServiceAuthError error = - GoogleServiceAuthError(GoogleServiceAuthError::SERVICE_ERROR); - sync_service()->SetAuthError(std::move(error)); - // An no-op change should not result in a suggestions refresh. - static_cast<SyncServiceObserver*>(suggestions_service()) - ->OnStateChanged(sync_service()); - - // Wait for eventual (but unexpected) network requests. - task_environment_.RunUntilIdle(); - EXPECT_FALSE(suggestions_service()->HasPendingRequestForTesting()); - - SuggestionsProfile empty_suggestions; - EXPECT_FALSE(suggestions_store()->LoadSuggestions(&empty_suggestions)); -} - -TEST_F(SuggestionsServiceTest, IgnoresUninterestingSyncChange) { - base::MockCallback<SuggestionsService::ResponseCallback> callback; - EXPECT_CALL(callback, Run(_)).Times(0); - auto subscription = suggestions_service()->AddCallback(callback.Get()); - - // An uninteresting change should not result in a network request (the - // SyncState is INITIALIZED_ENABLED_HISTORY before and after). - sync_service()->SetActiveDataTypes( - {syncer::HISTORY_DELETE_DIRECTIVES, syncer::BOOKMARKS}); - static_cast<SyncServiceObserver*>(suggestions_service()) - ->OnStateChanged(sync_service()); - - // Wait for eventual (but unexpected) network requests. - task_environment_.RunUntilIdle(); - EXPECT_FALSE(suggestions_service()->HasPendingRequestForTesting()); -} - -// During startup, the state changes from NOT_INITIALIZED_ENABLED to -// INITIALIZED_ENABLED_HISTORY (for a signed-in user with history sync enabled). -// This should *not* result in an automatic fetch. -TEST_F(SuggestionsServiceTest, DoesNotFetchOnStartup) { - // The sync service starts out inactive. - sync_service()->SetTransportState( - syncer::SyncService::TransportState::INITIALIZING); - static_cast<SyncServiceObserver*>(suggestions_service()) - ->OnStateChanged(sync_service()); - - task_environment_.RunUntilIdle(); - ASSERT_FALSE(suggestions_service()->HasPendingRequestForTesting()); - - // Sync getting enabled should not result in a fetch. - sync_service()->SetTransportState( - syncer::SyncService::TransportState::ACTIVE); - static_cast<SyncServiceObserver*>(suggestions_service()) - ->OnStateChanged(sync_service()); - - // Wait for eventual (but unexpected) network requests. - task_environment_.RunUntilIdle(); - EXPECT_FALSE(suggestions_service()->HasPendingRequestForTesting()); -} - -TEST_F(SuggestionsServiceTest, FetchSuggestionsDataSyncNotInitializedEnabled) { - sync_service()->SetTransportState( - syncer::SyncService::TransportState::INITIALIZING); - static_cast<SyncServiceObserver*>(suggestions_service()) - ->OnStateChanged(sync_service()); - - base::MockCallback<SuggestionsService::ResponseCallback> callback; - EXPECT_CALL(callback, Run(_)).Times(0); - auto subscription = suggestions_service()->AddCallback(callback.Get()); - - // Try to fetch suggestions. Since sync is not active, no network request - // should be sent. - suggestions_service()->FetchSuggestionsData(); - - // Wait for eventual (but unexpected) network requests. - task_environment_.RunUntilIdle(); - EXPECT_FALSE(suggestions_service()->HasPendingRequestForTesting()); - - // |suggestions_store()| should still contain the default values. - SuggestionsProfile suggestions; - suggestions_store()->LoadSuggestions(&suggestions); - EXPECT_THAT(suggestions, EqualsProto(CreateSuggestionsProfile())); -} - -TEST_F(SuggestionsServiceTest, FetchSuggestionsDataSyncDisabled) { - sync_service()->SetDisableReasons( - syncer::SyncService::DISABLE_REASON_USER_CHOICE); - sync_service()->SetTransportState( - syncer::SyncService::TransportState::DISABLED); - - base::MockCallback<SuggestionsService::ResponseCallback> callback; - auto subscription = suggestions_service()->AddCallback(callback.Get()); - - // Tell SuggestionsService that the sync state changed. The cache should be - // cleared and empty data returned to the callback. - EXPECT_CALL(callback, Run(EqualsProto(SuggestionsProfile()))); - static_cast<SyncServiceObserver*>(suggestions_service()) - ->OnStateChanged(sync_service()); - - // Try to fetch suggestions. Since sync is not active, no network request - // should be sent. - suggestions_service()->FetchSuggestionsData(); - - // Wait for eventual (but unexpected) network requests. - task_environment_.RunUntilIdle(); - EXPECT_FALSE(suggestions_service()->HasPendingRequestForTesting()); -} - -TEST_F(SuggestionsServiceTest, FetchSuggestionsDataNoAccessToken) { - identity_test_env()->SetAutomaticIssueOfAccessTokens(false); - - base::MockCallback<SuggestionsService::ResponseCallback> callback; - EXPECT_CALL(callback, Run(_)).Times(0); - auto subscription = suggestions_service()->AddCallback(callback.Get()); - - EXPECT_CALL(*blocklist_store(), GetTimeUntilReadyForUpload(_)) - .WillOnce(Return(false)); - - suggestions_service()->FetchSuggestionsData(); - - identity_test_env()->WaitForAccessTokenRequestIfNecessaryAndRespondWithError( - GoogleServiceAuthError( - GoogleServiceAuthError::State::INVALID_GAIA_CREDENTIALS)); - - // Wait for eventual (but unexpected) network requests. - task_environment_.RunUntilIdle(); - EXPECT_FALSE(suggestions_service()->HasPendingRequestForTesting()); -} - -TEST_F(SuggestionsServiceTest, FetchingSuggestionsIgnoresRequestFailure) { - EXPECT_CALL(*blocklist_store(), GetTimeUntilReadyForUpload(_)) - .WillOnce(Return(false)); - - suggestions_service()->FetchSuggestionsData(); - - // Wait for the eventual network request. - task_environment_.RunUntilIdle(); - ASSERT_TRUE(RespondToSuggestionsFetch("irrelevant", net::HTTP_OK, - net::ERR_INVALID_RESPONSE)); -} - -TEST_F(SuggestionsServiceTest, FetchingSuggestionsClearsStoreIfResponseNotOK) { - suggestions_store()->StoreSuggestions(CreateSuggestionsProfile()); - - // Expect that an upload to the blocklist is scheduled. - EXPECT_CALL(*blocklist_store(), GetTimeUntilReadyForUpload(_)) - .WillOnce(Return(false)); - - // Send the request. Empty data will be returned to the callback. - suggestions_service()->FetchSuggestionsData(); - - // Wait for the eventual network request. - task_environment_.RunUntilIdle(); - ASSERT_TRUE(RespondToSuggestionsFetch("irrelevant", net::HTTP_BAD_REQUEST)); - - SuggestionsProfile empty_suggestions; - EXPECT_FALSE(suggestions_store()->LoadSuggestions(&empty_suggestions)); -} - -TEST_F(SuggestionsServiceTest, BlocklistURL) { - const base::TimeDelta no_delay = base::TimeDelta::FromSeconds(0); - - base::MockCallback<SuggestionsService::ResponseCallback> callback; - auto subscription = suggestions_service()->AddCallback(callback.Get()); - - EXPECT_CALL(*blocklist_store(), BlocklistUrl(GURL(kBlocklistedUrl))) - .WillOnce(Return(true)); - EXPECT_CALL(*blocklist_store(), FilterSuggestions(_)).Times(2); - EXPECT_CALL(*blocklist_store(), GetTimeUntilReadyForUpload(_)) - .WillOnce(DoAll(SetArgPointee<0>(no_delay), Return(true))) - .WillOnce(Return(false)); - EXPECT_CALL(*blocklist_store(), GetCandidateForUpload(_)) - .WillOnce(DoAll(SetArgPointee<0>(GURL(kBlocklistedUrl)), Return(true))); - EXPECT_CALL(*blocklist_store(), RemoveUrl(GURL(kBlocklistedUrl))) - .WillOnce(Return(true)); - - EXPECT_CALL(callback, Run(_)).Times(2); - - EXPECT_TRUE(suggestions_service()->BlocklistURL(GURL(kBlocklistedUrl))); - - // Wait on the upload task, the blocklist request and the next blocklist - // scheduling task. - task_environment_.FastForwardUntilNoTasksRemain(); - - EXPECT_EQ(GetCurrentlyQueriedUrl().path(), kBlocklistUrlPath); - // The blocklist fetch needs to contain a valid profile or the favicon will - // not be set. - ASSERT_TRUE(RespondToBlocklistFetch( - CreateSuggestionsProfile().SerializeAsString(), net::HTTP_OK)); - task_environment_.RunUntilIdle(); - - SuggestionsProfile suggestions; - suggestions_store()->LoadSuggestions(&suggestions); - ASSERT_EQ(1, suggestions.suggestions_size()); - EXPECT_EQ(kTestTitle, suggestions.suggestions(0).title()); - EXPECT_EQ(kTestUrl, suggestions.suggestions(0).url()); - EXPECT_EQ(kTestFaviconUrl, suggestions.suggestions(0).favicon_url()); -} - -TEST_F(SuggestionsServiceTest, BlocklistURLFails) { - base::MockCallback<SuggestionsService::ResponseCallback> callback; - EXPECT_CALL(callback, Run(_)).Times(0); - auto subscription = suggestions_service()->AddCallback(callback.Get()); - - EXPECT_CALL(*blocklist_store(), BlocklistUrl(GURL(kBlocklistedUrl))) - .WillOnce(Return(false)); - - EXPECT_FALSE(suggestions_service()->BlocklistURL(GURL(kBlocklistedUrl))); -} - -TEST_F(SuggestionsServiceTest, RetryBlocklistURLRequestAfterFailure) { - const base::TimeDelta no_delay = base::TimeDelta::FromSeconds(0); - - base::MockCallback<SuggestionsService::ResponseCallback> callback; - auto subscription = suggestions_service()->AddCallback(callback.Get()); - - // Set expectations for first, failing request. - EXPECT_CALL(*blocklist_store(), GetTimeUntilReadyForUpload(_)) - .Times(AnyNumber()) - .WillRepeatedly(DoAll(SetArgPointee<0>(no_delay), Return(true))); - EXPECT_CALL(*blocklist_store(), FilterSuggestions(_)); - EXPECT_CALL(*blocklist_store(), BlocklistUrl(GURL(kBlocklistedUrl))) - .WillOnce(Return(true)); - EXPECT_CALL(*blocklist_store(), GetCandidateForUpload(_)) - .WillOnce(DoAll(SetArgPointee<0>(GURL(kBlocklistedUrl)), Return(true))); - - EXPECT_CALL(callback, Run(_)).Times(2); - - // Blocklist call, first request attempt. - EXPECT_TRUE(suggestions_service()->BlocklistURL(GURL(kBlocklistedUrl))); - - // Wait for the first scheduling receiving a failing response. - task_environment_.FastForwardUntilNoTasksRemain(); - ASSERT_TRUE(GetCurrentlyQueriedUrl().is_valid()); - EXPECT_EQ(GetCurrentlyQueriedUrl().path(), kBlocklistUrlPath); - ASSERT_TRUE(RespondToBlocklistFetch("irrelevant", net::HTTP_OK, - net::ERR_INVALID_RESPONSE)); - - // Assert that the failure was processed as expected. - Mock::VerifyAndClearExpectations(blocklist_store()); - - // Now expect the retried request to succeed. - EXPECT_CALL(*blocklist_store(), GetTimeUntilReadyForUpload(_)) - .Times(AnyNumber()) - .WillRepeatedly(DoAll(SetArgPointee<0>(no_delay), Return(true))); - EXPECT_CALL(*blocklist_store(), FilterSuggestions(_)); - EXPECT_CALL(*blocklist_store(), GetCandidateForUpload(_)) - .WillOnce(DoAll(SetArgPointee<0>(GURL(kBlocklistedUrl)), Return(true))); - EXPECT_CALL(*blocklist_store(), RemoveUrl(GURL(kBlocklistedUrl))) - .WillOnce(Return(true)); - - // Wait for the second scheduling followed by a successful response. - task_environment_.FastForwardUntilNoTasksRemain(); - ASSERT_TRUE(suggestions_service()->HasPendingRequestForTesting()); - ASSERT_TRUE(GetCurrentlyQueriedUrl().is_valid()); - EXPECT_EQ(GetCurrentlyQueriedUrl().path(), kBlocklistUrlPath); - ASSERT_TRUE(RespondToBlocklistFetch( - CreateSuggestionsProfile().SerializeAsString(), net::HTTP_OK)); - - SuggestionsProfile suggestions; - suggestions_store()->LoadSuggestions(&suggestions); - ASSERT_EQ(1, suggestions.suggestions_size()); - EXPECT_EQ(kTestTitle, suggestions.suggestions(0).title()); - EXPECT_EQ(kTestUrl, suggestions.suggestions(0).url()); - EXPECT_EQ(kTestFaviconUrl, suggestions.suggestions(0).favicon_url()); -} - -TEST_F(SuggestionsServiceTest, UndoBlocklistURL) { - // Ensure scheduling the request doesn't happen before undo. - const base::TimeDelta delay = base::TimeDelta::FromHours(1); - - base::MockCallback<SuggestionsService::ResponseCallback> callback; - auto subscription = suggestions_service()->AddCallback(callback.Get()); - - // Blocklist expectations. - EXPECT_CALL(*blocklist_store(), BlocklistUrl(GURL(kBlocklistedUrl))) - .WillOnce(Return(true)); - EXPECT_CALL(*blocklist_store(), FilterSuggestions(_)).Times(AnyNumber()); - EXPECT_CALL(*blocklist_store(), GetTimeUntilReadyForUpload(_)) - .WillOnce(DoAll(SetArgPointee<0>(delay), Return(true))); - // Undo expectations. - EXPECT_CALL(*blocklist_store(), - GetTimeUntilURLReadyForUpload(GURL(kBlocklistedUrl), _)) - .WillOnce(DoAll(SetArgPointee<1>(delay), Return(true))); - EXPECT_CALL(*blocklist_store(), RemoveUrl(GURL(kBlocklistedUrl))) - .WillOnce(Return(true)); - - EXPECT_CALL(callback, Run(_)).Times(2); - EXPECT_TRUE(suggestions_service()->BlocklistURL(GURL(kBlocklistedUrl))); - EXPECT_TRUE(suggestions_service()->UndoBlocklistURL(GURL(kBlocklistedUrl))); -} - -TEST_F(SuggestionsServiceTest, ClearBlocklist) { - const base::TimeDelta delay = base::TimeDelta::FromHours(1); - - base::MockCallback<SuggestionsService::ResponseCallback> callback; - auto subscription = suggestions_service()->AddCallback(callback.Get()); - - // Blocklist expectations. - EXPECT_CALL(*blocklist_store(), BlocklistUrl(GURL(kBlocklistedUrl))) - .WillOnce(Return(true)); - EXPECT_CALL(*blocklist_store(), FilterSuggestions(_)).Times(AnyNumber()); - EXPECT_CALL(*blocklist_store(), GetTimeUntilReadyForUpload(_)) - .WillOnce(DoAll(SetArgPointee<0>(delay), Return(true))); - EXPECT_CALL(*blocklist_store(), ClearBlocklist()); - - EXPECT_CALL(callback, Run(_)).Times(2); - EXPECT_TRUE(suggestions_service()->BlocklistURL(GURL(kBlocklistedUrl))); - suggestions_service()->ClearBlocklist(); - - // Wait for the eventual network request. - task_environment_.RunUntilIdle(); - ASSERT_TRUE(suggestions_service()->HasPendingRequestForTesting()); - EXPECT_EQ(GetCurrentlyQueriedUrl().path(), kBlocklistClearUrlPath); -} - -TEST_F(SuggestionsServiceTest, UndoBlocklistURLFailsIfNotInBlocklist) { - // Ensure scheduling the request doesn't happen before undo. - const base::TimeDelta delay = base::TimeDelta::FromHours(1); - - base::MockCallback<SuggestionsService::ResponseCallback> callback; - auto subscription = suggestions_service()->AddCallback(callback.Get()); - - // Blocklist expectations. - EXPECT_CALL(*blocklist_store(), BlocklistUrl(GURL(kBlocklistedUrl))) - .WillOnce(Return(true)); - EXPECT_CALL(*blocklist_store(), FilterSuggestions(_)); - EXPECT_CALL(*blocklist_store(), GetTimeUntilReadyForUpload(_)) - .WillOnce(DoAll(SetArgPointee<0>(delay), Return(true))); - // Undo expectations. - // URL is not in local blocklist. - EXPECT_CALL(*blocklist_store(), - GetTimeUntilURLReadyForUpload(GURL(kBlocklistedUrl), _)) - .WillOnce(Return(false)); - - EXPECT_CALL(callback, Run(_)); - - EXPECT_TRUE(suggestions_service()->BlocklistURL(GURL(kBlocklistedUrl))); - EXPECT_FALSE(suggestions_service()->UndoBlocklistURL(GURL(kBlocklistedUrl))); -} - -TEST_F(SuggestionsServiceTest, UndoBlocklistURLFailsIfAlreadyCandidate) { - // Ensure scheduling the request doesn't happen before undo. - const base::TimeDelta delay = base::TimeDelta::FromHours(1); - - base::MockCallback<SuggestionsService::ResponseCallback> callback; - auto subscription = suggestions_service()->AddCallback(callback.Get()); - - // Blocklist expectations. - EXPECT_CALL(*blocklist_store(), BlocklistUrl(GURL(kBlocklistedUrl))) - .WillOnce(Return(true)); - EXPECT_CALL(*blocklist_store(), FilterSuggestions(_)); - EXPECT_CALL(*blocklist_store(), GetTimeUntilReadyForUpload(_)) - .WillOnce(DoAll(SetArgPointee<0>(delay), Return(true))); - - // URL is not yet candidate for upload. - const base::TimeDelta negative_delay = base::TimeDelta::FromHours(-1); - EXPECT_CALL(*blocklist_store(), - GetTimeUntilURLReadyForUpload(GURL(kBlocklistedUrl), _)) - .WillOnce(DoAll(SetArgPointee<1>(negative_delay), Return(true))); - - EXPECT_CALL(callback, Run(_)); - - EXPECT_TRUE(suggestions_service()->BlocklistURL(GURL(kBlocklistedUrl))); - EXPECT_FALSE(suggestions_service()->UndoBlocklistURL(GURL(kBlocklistedUrl))); -} - -TEST_F(SuggestionsServiceTest, TemporarilyIncreasesBlocklistDelayOnFailure) { - EXPECT_CALL(*blocklist_store(), FilterSuggestions(_)).Times(AnyNumber()); - EXPECT_CALL(*blocklist_store(), GetTimeUntilReadyForUpload(_)) - .Times(AnyNumber()) - .WillRepeatedly(Return(false)); - const base::TimeDelta initial_delay = - suggestions_service()->BlocklistDelayForTesting(); - - // Delay unchanged on success. - suggestions_service()->FetchSuggestionsData(); - task_environment_.RunUntilIdle(); - ASSERT_TRUE(RespondToFetchWithProfile(CreateSuggestionsProfile())); - EXPECT_EQ(initial_delay, suggestions_service()->BlocklistDelayForTesting()); - - // Delay increases on failure. - suggestions_service()->FetchSuggestionsData(); - task_environment_.RunUntilIdle(); - ASSERT_TRUE(RespondToSuggestionsFetch("irrelevant", net::HTTP_BAD_REQUEST)); - base::TimeDelta delay_after_fail = - suggestions_service()->BlocklistDelayForTesting(); - EXPECT_GT(delay_after_fail, initial_delay); - - // Success resets future delays, but the current horizon remains. Since no - // time has passed, the actual current delay stays the same. - suggestions_service()->FetchSuggestionsData(); - task_environment_.RunUntilIdle(); - ASSERT_TRUE(RespondToFetchWithProfile(CreateSuggestionsProfile())); - EXPECT_EQ(delay_after_fail, - suggestions_service()->BlocklistDelayForTesting()); - - // After the current horizon has passed, we're back at the initial delay. - task_environment_.FastForwardBy(delay_after_fail); - suggestions_service()->FetchSuggestionsData(); - task_environment_.RunUntilIdle(); - ASSERT_TRUE(RespondToFetchWithProfile(CreateSuggestionsProfile())); - EXPECT_EQ(initial_delay, suggestions_service()->BlocklistDelayForTesting()); -} - -TEST_F(SuggestionsServiceTest, DoesNotOverrideDefaultExpiryTime) { - EXPECT_CALL(*blocklist_store(), FilterSuggestions(_)); - EXPECT_CALL(*blocklist_store(), GetTimeUntilReadyForUpload(_)) - .WillOnce(Return(false)); - - suggestions_service()->FetchSuggestionsData(); - - task_environment_.RunUntilIdle(); - // Creates one suggestion without timestamp and adds a second with timestamp. - SuggestionsProfile profile = CreateSuggestionsProfile(); - ChromeSuggestion* suggestion = profile.add_suggestions(); - suggestion->set_title(kTestTitle); - suggestion->set_url(kTestUrl); - suggestion->set_expiry_ts(kTestSetExpiry); - ASSERT_TRUE(RespondToFetchWithProfile(profile)); - - SuggestionsProfile suggestions; - suggestions_store()->LoadSuggestions(&suggestions); - ASSERT_EQ(2, suggestions.suggestions_size()); - // Suggestion[0] had no time stamp and should be ahead of the old suggestion. - EXPECT_LT(kTestSetExpiry, suggestions.suggestions(0).expiry_ts()); - // Suggestion[1] had a very old time stamp but should not be updated. - EXPECT_EQ(kTestSetExpiry, suggestions.suggestions(1).expiry_ts()); -} - -} // namespace suggestions
diff --git a/components/suggestions/suggestions_store.cc b/components/suggestions/suggestions_store.cc deleted file mode 100644 index cc360b3..0000000 --- a/components/suggestions/suggestions_store.cc +++ /dev/null
@@ -1,111 +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. - -#include "components/suggestions/suggestions_store.h" - -#include <stdint.h> - -#include <memory> -#include <string> -#include <utility> - -#include "base/base64.h" -#include "base/logging.h" -#include "base/time/default_clock.h" -#include "base/time/time.h" -#include "components/pref_registry/pref_registry_syncable.h" -#include "components/prefs/pref_service.h" -#include "components/suggestions/suggestions_pref_names.h" - -namespace suggestions { - -SuggestionsStore::SuggestionsStore(PrefService* profile_prefs) - : pref_service_(profile_prefs), clock_(base::DefaultClock::GetInstance()) { - DCHECK(profile_prefs); -} - -SuggestionsStore::SuggestionsStore() { -} - -SuggestionsStore::~SuggestionsStore() {} - -void SuggestionsStore::SetClockForTesting(base::Clock* test_clock) { - this->clock_ = test_clock; -} - -bool SuggestionsStore::LoadSuggestions(SuggestionsProfile* suggestions) { - DCHECK(suggestions); - - const std::string base64_suggestions_data = - pref_service_->GetString(prefs::kSuggestionsData); - if (base64_suggestions_data.empty()) { - suggestions->Clear(); - return false; - } - - // If the decode process fails, assume the pref value is corrupt and clear it. - std::string suggestions_data; - if (!base::Base64Decode(base64_suggestions_data, &suggestions_data) || - !suggestions->ParseFromString(suggestions_data)) { - VLOG(1) << "Suggestions data in profile pref is corrupt, clearing it."; - suggestions->Clear(); - ClearSuggestions(); - return false; - } - - // Filter expired suggestions and update the stored suggestions if at least - // one was filtered. Return false if all suggestions are filtered. - int unfiltered_size = suggestions->suggestions_size(); - FilterExpiredSuggestions(suggestions); - if (suggestions->suggestions_size() != unfiltered_size) { - if (!suggestions->suggestions_size()) { - suggestions->Clear(); - ClearSuggestions(); - return false; - } else { - StoreSuggestions(*suggestions); - } - } - - return true; -} - -void SuggestionsStore::FilterExpiredSuggestions( - SuggestionsProfile* suggestions) { - SuggestionsProfile filtered_suggestions; - int64_t now_usec = - (this->clock_->Now() - base::Time::UnixEpoch()).ToInternalValue(); - filtered_suggestions.set_timestamp(suggestions->timestamp()); - - for (int i = 0; i < suggestions->suggestions_size(); ++i) { - ChromeSuggestion* suggestion = suggestions->mutable_suggestions(i); - if (!suggestion->has_expiry_ts() || suggestion->expiry_ts() > now_usec) { - filtered_suggestions.add_suggestions()->Swap(suggestion); - } - } - suggestions->Swap(&filtered_suggestions); -} - -bool SuggestionsStore::StoreSuggestions(const SuggestionsProfile& suggestions) { - std::string suggestions_data; - if (!suggestions.SerializeToString(&suggestions_data)) return false; - - std::string base64_suggestions_data; - base::Base64Encode(suggestions_data, &base64_suggestions_data); - - pref_service_->SetString(prefs::kSuggestionsData, base64_suggestions_data); - return true; -} - -void SuggestionsStore::ClearSuggestions() { - pref_service_->ClearPref(prefs::kSuggestionsData); -} - -// static -void SuggestionsStore::RegisterProfilePrefs( - user_prefs::PrefRegistrySyncable* registry) { - registry->RegisterStringPref(prefs::kSuggestionsData, std::string()); -} - -} // namespace suggestions
diff --git a/components/suggestions/suggestions_store.h b/components/suggestions/suggestions_store.h deleted file mode 100644 index eb25c57..0000000 --- a/components/suggestions/suggestions_store.h +++ /dev/null
@@ -1,63 +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. - -#ifndef COMPONENTS_SUGGESTIONS_SUGGESTIONS_STORE_H_ -#define COMPONENTS_SUGGESTIONS_SUGGESTIONS_STORE_H_ - -#include "base/macros.h" -#include "base/time/clock.h" -#include "components/suggestions/proto/suggestions.pb.h" - -class PrefService; - -namespace user_prefs { -class PrefRegistrySyncable; -} // namespace user_prefs - -namespace suggestions { - -// A helper class for reading and writing the suggestions to the profile's -// preference file. -class SuggestionsStore { - public: - explicit SuggestionsStore(PrefService* profile_prefs); - virtual ~SuggestionsStore(); - - // Loads the suggestion data from the profile's preferences into - // |suggestions|. If there is a problem with loading, the pref value is - // cleared, false is returned and |suggestions| is cleared. If successful, - // |suggestions| will contain the loaded data and true is returned. - virtual bool LoadSuggestions(SuggestionsProfile* suggestions); - - // Stores the provided |suggestions| to the profile's preferences, using - // a base64 encoding of its protobuf serialization. - virtual bool StoreSuggestions(const SuggestionsProfile& suggestions); - - // Clears any suggestion data from the profile's preferences. - virtual void ClearSuggestions(); - - // Register SuggestionsStore related prefs in the Profile prefs. - static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry); - - void SetClockForTesting(base::Clock* clock); - - protected: - // Test seam. For simplicity of mock creation. - SuggestionsStore(); - - private: - // The pref service used to persist the suggestions data. - PrefService* pref_service_; - // Can be overridden for testing. - base::Clock* clock_; - - DISALLOW_COPY_AND_ASSIGN(SuggestionsStore); - - // Filters expired suggestions. - void FilterExpiredSuggestions(SuggestionsProfile* suggestions); -}; - -} // namespace suggestions - -#endif // COMPONENTS_SUGGESTIONS_SUGGESTIONS_STORE_H_
diff --git a/components/suggestions/suggestions_store_unittest.cc b/components/suggestions/suggestions_store_unittest.cc deleted file mode 100644 index 5f91e0c2..0000000 --- a/components/suggestions/suggestions_store_unittest.cc +++ /dev/null
@@ -1,165 +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. - -#include "components/suggestions/suggestions_store.h" - -#include <stdint.h> - -#include <memory> - -#include "base/macros.h" -#include "base/test/simple_test_clock.h" -#include "base/time/time.h" -#include "components/suggestions/proto/suggestions.pb.h" -#include "components/sync_preferences/testing_pref_service_syncable.h" -#include "components/variations/scoped_variations_ids_provider.h" -#include "testing/gtest/include/gtest/gtest.h" - -using sync_preferences::TestingPrefServiceSyncable; - -namespace suggestions { - -namespace { - -const char kTestTitle[] = "Foo site"; -const char kTestUrl[] = "http://foo.com/"; - -void AddSuggestion(SuggestionsProfile* suggestions, - const char* title, - const char* url, - int64_t expiry_ts) { - ChromeSuggestion* suggestion = suggestions->add_suggestions(); - suggestion->set_url(title); - suggestion->set_title(url); - suggestion->set_expiry_ts(expiry_ts); -} - -SuggestionsProfile CreateTestSuggestions() { - SuggestionsProfile suggestions; - suggestions.set_timestamp(123); - ChromeSuggestion* suggestion = suggestions.add_suggestions(); - suggestion->set_url(kTestTitle); - suggestion->set_title(kTestUrl); - return suggestions; -} - -SuggestionsProfile CreateTestSuggestionsProfileWithExpiry( - base::Time current_time, - int expired_count, - int valid_count) { - int64_t current_time_usec = - (current_time - base::Time::UnixEpoch()).ToInternalValue(); - int64_t offset_usec = 5 * base::Time::kMicrosecondsPerMinute; - - SuggestionsProfile suggestions; - for (int i = 1; i <= valid_count; i++) - AddSuggestion(&suggestions, kTestTitle, kTestUrl, - current_time_usec + offset_usec * i); - for (int i = 1; i <= expired_count; i++) - AddSuggestion(&suggestions, kTestTitle, kTestUrl, - current_time_usec - offset_usec * i); - - return suggestions; -} - -void ValidateSuggestions(const SuggestionsProfile& expected, - const SuggestionsProfile& actual) { - EXPECT_EQ(expected.suggestions_size(), actual.suggestions_size()); - for (int i = 0; i < expected.suggestions_size(); ++i) { - EXPECT_EQ(expected.suggestions(i).url(), actual.suggestions(i).url()); - EXPECT_EQ(expected.suggestions(i).title(), actual.suggestions(i).title()); - EXPECT_EQ(expected.suggestions(i).expiry_ts(), - actual.suggestions(i).expiry_ts()); - EXPECT_EQ(expected.suggestions(i).favicon_url(), - actual.suggestions(i).favicon_url()); - } -} - -} // namespace - -class SuggestionsStoreTest : public testing::Test { - public: - SuggestionsStoreTest() - : pref_service_(new sync_preferences::TestingPrefServiceSyncable) {} - - void SetUp() override { - SuggestionsStore::RegisterProfilePrefs(pref_service_->registry()); - suggestions_store_ = - std::make_unique<SuggestionsStore>(pref_service_.get()); - - test_clock_.SetNow(base::Time::FromInternalValue(13063394337546738)); - suggestions_store_->SetClockForTesting(&test_clock_); - } - - protected: - variations::ScopedVariationsIdsProvider scoped_variations_ids_provider_{ - variations::VariationsIdsProvider::Mode::kUseSignedInState}; - std::unique_ptr<sync_preferences::TestingPrefServiceSyncable> pref_service_; - std::unique_ptr<SuggestionsStore> suggestions_store_; - base::SimpleTestClock test_clock_; - - DISALLOW_COPY_AND_ASSIGN(SuggestionsStoreTest); -}; - -// Tests LoadSuggestions function to filter expired suggestions. -TEST_F(SuggestionsStoreTest, LoadAllExpired) { - SuggestionsProfile suggestions = - CreateTestSuggestionsProfileWithExpiry(test_clock_.Now(), 5, 0); - SuggestionsProfile filtered_suggestions; - - // Store and load. Expired suggestions should not be loaded. - EXPECT_TRUE(suggestions_store_->StoreSuggestions(suggestions)); - EXPECT_FALSE(suggestions_store_->LoadSuggestions(&filtered_suggestions)); - EXPECT_EQ(0, filtered_suggestions.suggestions_size()); -} - -// Tests LoadSuggestions function to filter expired suggestions. -TEST_F(SuggestionsStoreTest, LoadValidAndExpired) { - SuggestionsProfile suggestions = - CreateTestSuggestionsProfileWithExpiry(test_clock_.Now(), 5, 3); - SuggestionsProfile filtered_suggestions; - - // Store and load. Expired suggestions should not be loaded. - EXPECT_TRUE(suggestions_store_->StoreSuggestions(suggestions)); - EXPECT_TRUE(suggestions_store_->LoadSuggestions(&filtered_suggestions)); - EXPECT_EQ(3, filtered_suggestions.suggestions_size()); -} - -// Tests LoadSuggestions function to filter expired suggestions. -TEST_F(SuggestionsStoreTest, CheckStoreAfterLoadExpired) { - SuggestionsProfile suggestions = - CreateTestSuggestionsProfileWithExpiry(test_clock_.Now(), 5, 3); - SuggestionsProfile filtered_suggestions; - - // Store and load. Expired suggestions should not be loaded. - EXPECT_TRUE(suggestions_store_->StoreSuggestions(suggestions)); - EXPECT_TRUE(suggestions_store_->LoadSuggestions(&filtered_suggestions)); - - SuggestionsProfile loaded_suggestions; - EXPECT_TRUE(suggestions_store_->LoadSuggestions(&loaded_suggestions)); - EXPECT_EQ(3, loaded_suggestions.suggestions_size()); - ValidateSuggestions(filtered_suggestions, loaded_suggestions); -} - -TEST_F(SuggestionsStoreTest, LoadStoreClear) { - const SuggestionsProfile suggestions = CreateTestSuggestions(); - const SuggestionsProfile empty_suggestions; - SuggestionsProfile recovered_suggestions; - - // Attempt to load when prefs are empty. - EXPECT_FALSE(suggestions_store_->LoadSuggestions(&recovered_suggestions)); - ValidateSuggestions(empty_suggestions, recovered_suggestions); - - // Store then reload. - EXPECT_TRUE(suggestions_store_->StoreSuggestions(suggestions)); - EXPECT_TRUE(suggestions_store_->LoadSuggestions(&recovered_suggestions)); - ValidateSuggestions(suggestions, recovered_suggestions); - - // Clear. - suggestions_store_->ClearSuggestions(); - EXPECT_FALSE(suggestions_store_->LoadSuggestions(&recovered_suggestions)); - ValidateSuggestions(empty_suggestions, recovered_suggestions); -} - -} // namespace suggestions
diff --git a/components/suggestions/webui/suggestions_source.cc b/components/suggestions/webui/suggestions_source.cc deleted file mode 100644 index c08ab66..0000000 --- a/components/suggestions/webui/suggestions_source.cc +++ /dev/null
@@ -1,134 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "components/suggestions/webui/suggestions_source.h" - -#include <string> - -#include "base/barrier_closure.h" -#include "base/base64.h" -#include "base/bind.h" -#include "base/strings/strcat.h" -#include "base/strings/string_number_conversions.h" -#include "base/strings/string_piece.h" -#include "base/strings/string_util.h" -#include "base/strings/utf_string_conversions.h" -#include "base/time/time.h" -#include "components/suggestions/proto/suggestions.pb.h" -#include "net/base/escape.h" -#include "ui/base/l10n/time_format.h" -#include "ui/gfx/codec/png_codec.h" -#include "ui/gfx/image/image_skia.h" - -namespace suggestions { - -namespace { - -const char kHtmlHeader[] = - "<!DOCTYPE html>\n<html>\n<head>\n<title>Suggestions</title>\n" - "<meta charset=\"utf-8\">\n" - "<style type=\"text/css\">\nli {white-space: nowrap;}\n</style>\n"; -const char kHtmlBody[] = "</head>\n<body>\n"; -const char kHtmlFooter[] = "</body>\n</html>\n"; - -const char kRefreshPath[] = "refresh"; - -std::string GetRefreshHtml(const std::string& base_url, bool is_refresh) { - if (is_refresh) - return "<p>Refreshing in the background, reload to see new data.</p>\n"; - return std::string("<p><a href=\"") + base_url + kRefreshPath + - "\">Refresh</a></p>\n"; -} -// Returns the HTML needed to display the suggestions. -std::string RenderOutputHtml(const std::string& base_url, - bool is_refresh, - const SuggestionsProfile& profile) { - std::vector<std::string> out; - out.push_back(kHtmlHeader); - out.push_back(kHtmlBody); - out.push_back("<h1>Suggestions</h1>\n"); - out.push_back(GetRefreshHtml(base_url, is_refresh)); - out.push_back("<ul>"); - int64_t now = (base::Time::NowFromSystemTime() - base::Time::UnixEpoch()) - .ToInternalValue(); - size_t size = profile.suggestions_size(); - for (size_t i = 0; i < size; ++i) { - const ChromeSuggestion& suggestion = profile.suggestions(i); - base::TimeDelta remaining_time = - base::TimeDelta::FromMicroseconds(suggestion.expiry_ts() - now); - std::u16string remaining_time_formatted = ui::TimeFormat::Detailed( - ui::TimeFormat::Format::FORMAT_DURATION, - ui::TimeFormat::Length::LENGTH_LONG, -1, remaining_time); - std::string line; - line += "<li><a href=\""; - line += net::EscapeForHTML(suggestion.url()); - line += "\" target=\"_blank\">"; - line += net::EscapeForHTML(suggestion.title()); - line += "</a> Expires in "; - line += base::UTF16ToUTF8(remaining_time_formatted); - std::vector<std::string> providers; - for (int p = 0; p < suggestion.providers_size(); ++p) - providers.push_back(base::NumberToString(suggestion.providers(p))); - line += ". Provider IDs: " + base::JoinString(providers, ", "); - line += "</li>\n"; - out.push_back(line); - } - out.push_back("</ul>"); - out.push_back(kHtmlFooter); - return base::StrCat(out); -} - -// Returns the HTML needed to display that no suggestions are available. -std::string RenderOutputHtmlNoSuggestions(const std::string& base_url, - bool is_refresh) { - std::vector<std::string> out; - out.push_back(kHtmlHeader); - out.push_back(kHtmlBody); - out.push_back("<h1>Suggestions</h1>\n"); - out.push_back("<p>You have no suggestions.</p>\n"); - out.push_back(GetRefreshHtml(base_url, is_refresh)); - out.push_back(kHtmlFooter); - return base::StrCat(out); -} - -} // namespace - -SuggestionsSource::SuggestionsSource(SuggestionsService* suggestions_service, - const std::string& base_url) - : suggestions_service_(suggestions_service), base_url_(base_url) {} - -SuggestionsSource::~SuggestionsSource() {} - -void SuggestionsSource::StartDataRequest(const std::string& path, - GotDataCallback callback) { - // If this was called as "chrome://suggestions/refresh", we also trigger an - // async update of the suggestions. - bool is_refresh = (path == kRefreshPath); - - // |suggestions_service| is null for guest profiles. - if (!suggestions_service_) { - std::string output = RenderOutputHtmlNoSuggestions(base_url_, is_refresh); - std::move(callback).Run(base::RefCountedString::TakeString(&output)); - return; - } - - if (is_refresh) - suggestions_service_->FetchSuggestionsData(); - - SuggestionsProfile suggestions_profile = - suggestions_service_->GetSuggestionsDataFromCache().value_or( - SuggestionsProfile()); - size_t size = suggestions_profile.suggestions_size(); - - std::string output = - !size ? RenderOutputHtmlNoSuggestions(base_url_, is_refresh) - : RenderOutputHtml(base_url_, is_refresh, suggestions_profile); - std::move(callback).Run(base::RefCountedString::TakeString(&output)); -} - -std::string SuggestionsSource::GetMimeType(const std::string& path) const { - return "text/html"; -} - -} // namespace suggestions
diff --git a/components/suggestions/webui/suggestions_source.h b/components/suggestions/webui/suggestions_source.h deleted file mode 100644 index 6d7317f..0000000 --- a/components/suggestions/webui/suggestions_source.h +++ /dev/null
@@ -1,49 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef COMPONENTS_SUGGESTIONS_WEBUI_SUGGESTIONS_SOURCE_H_ -#define COMPONENTS_SUGGESTIONS_WEBUI_SUGGESTIONS_SOURCE_H_ - -#include <map> -#include <string> - -#include "base/callback.h" -#include "base/macros.h" -#include "base/memory/ref_counted_memory.h" -#include "base/memory/weak_ptr.h" -#include "components/suggestions/suggestions_service.h" -#include "url/gurl.h" - -namespace suggestions { - -// SuggestionsSource renders a webpage to list SuggestionsService data. -class SuggestionsSource { - public: - SuggestionsSource(SuggestionsService* suggestions_service, - const std::string& base_url); - ~SuggestionsSource(); - - using GotDataCallback = - base::OnceCallback<void(scoped_refptr<base::RefCountedMemory>)>; - - void StartDataRequest(const std::string& path, GotDataCallback callback); - std::string GetMimeType(const std::string& path) const; - - private: - // Only used when servicing requests on the UI thread. - SuggestionsService* suggestions_service_; - - // The base URL at which which the Suggestions WebUI lives in the context of - // the embedder. - const std::string base_url_; - - // For callbacks may be run after destruction. - base::WeakPtrFactory<SuggestionsSource> weak_ptr_factory_{this}; - - DISALLOW_COPY_AND_ASSIGN(SuggestionsSource); -}; - -} // namespace suggestions - -#endif // COMPONENTS_SUGGESTIONS_WEBUI_SUGGESTIONS_SOURCE_H_
diff --git a/components/webapps/browser/installable/installable_manager.cc b/components/webapps/browser/installable/installable_manager.cc index 393180e..223f44cc 100644 --- a/components/webapps/browser/installable/installable_manager.cc +++ b/components/webapps/browser/installable/installable_manager.cc
@@ -182,8 +182,7 @@ display_mode == blink::mojom::DisplayMode::kStandalone || display_mode == blink::mojom::DisplayMode::kFullscreen || display_mode == blink::mojom::DisplayMode::kMinimalUi || - (display_mode == blink::mojom::DisplayMode::kWindowControlsOverlay && - base::FeatureList::IsEnabled(features::kWebAppWindowControlsOverlay)) || + (display_mode == blink::mojom::DisplayMode::kWindowControlsOverlay) || (display_mode == blink::mojom::DisplayMode::kTabbed && base::FeatureList::IsEnabled(features::kDesktopPWAsTabStrip))); }
diff --git a/components/webapps/browser/installable/installable_manager_unittest.cc b/components/webapps/browser/installable/installable_manager_unittest.cc index 5ade544..990f789 100644 --- a/components/webapps/browser/installable/installable_manager_unittest.cc +++ b/components/webapps/browser/installable/installable_manager_unittest.cc
@@ -280,8 +280,8 @@ manifest.display = blink::mojom::DisplayMode::kWindowControlsOverlay; EXPECT_TRUE( IsManifestValid(manifest, false /* check_webapp_manifest_display */)); - EXPECT_FALSE(IsManifestValid(manifest)); - EXPECT_EQ(MANIFEST_DISPLAY_NOT_SUPPORTED, GetErrorCode()); + EXPECT_TRUE(IsManifestValid(manifest)); + EXPECT_EQ(NO_ERROR_DETECTED, GetErrorCode()); manifest.display = blink::mojom::DisplayMode::kTabbed; EXPECT_TRUE( @@ -323,8 +323,8 @@ blink::mojom::DisplayMode::kWindowControlsOverlay); EXPECT_TRUE( IsManifestValid(manifest, false /* check_webapp_manifest_display */)); - EXPECT_FALSE(IsManifestValid(manifest)); - EXPECT_EQ(MANIFEST_DISPLAY_OVERRIDE_NOT_SUPPORTED, GetErrorCode()); + EXPECT_TRUE(IsManifestValid(manifest)); + EXPECT_EQ(NO_ERROR_DETECTED, GetErrorCode()); manifest.display_override.insert(manifest.display_override.begin(), blink::mojom::DisplayMode::kTabbed);
diff --git a/content/app_shim_remote_cocoa/web_contents_ns_view_bridge.mm b/content/app_shim_remote_cocoa/web_contents_ns_view_bridge.mm index c77eaba..113c4f4 100644 --- a/content/app_shim_remote_cocoa/web_contents_ns_view_bridge.mm +++ b/content/app_shim_remote_cocoa/web_contents_ns_view_bridge.mm
@@ -18,6 +18,7 @@ ns_view_.reset( [[WebContentsViewCocoa alloc] initWithViewsHostableView:nullptr]); [ns_view_ setHost:host_.get()]; + [ns_view_ enableDroppedScreenShotCopier]; view_id_ = std::make_unique<remote_cocoa::ScopedNSViewIdMapping>( view_id, ns_view_.get()); }
diff --git a/content/app_shim_remote_cocoa/web_contents_view_cocoa.h b/content/app_shim_remote_cocoa/web_contents_view_cocoa.h index 05c0368..eb42756 100644 --- a/content/app_shim_remote_cocoa/web_contents_view_cocoa.h +++ b/content/app_shim_remote_cocoa/web_contents_view_cocoa.h
@@ -15,6 +15,7 @@ } // namespace content namespace remote_cocoa { +class DroppedScreenShotCopierMac; namespace mojom { class WebContentsNSViewHost; } // namespace mojom @@ -35,6 +36,13 @@ base::scoped_nsobject<WebDragSource> _dragSource; BOOL _mouseDownCanMoveWindow; + + // Utility to copy screenshots to a usable directory for PWAs. This utility + // will maintain a temporary directory for such screenshot files until this + // WebContents is destroyed. + // https://crbug.com/1148078 + std::unique_ptr<remote_cocoa::DroppedScreenShotCopierMac> + _droppedScreenShotCopier; } // Set or un-set the mojo interface through which to communicate with the @@ -43,6 +51,10 @@ - (void)setMouseDownCanMoveWindow:(BOOL)canMove; +// Enable the workaround for https://crbug.com/1148078. This is called by +// in-PWA-process instances, to limit the workaround's effect to just PWAs. +- (void)enableDroppedScreenShotCopier; + // Returns the available drag operations. This is a required method for // NSDraggingSource. It is supposedly deprecated, but the non-deprecated API // -[NSWindow dragImage:...] still relies on it.
diff --git a/content/app_shim_remote_cocoa/web_contents_view_cocoa.mm b/content/app_shim_remote_cocoa/web_contents_view_cocoa.mm index 94cba51d..9b088eb 100644 --- a/content/app_shim_remote_cocoa/web_contents_view_cocoa.mm +++ b/content/app_shim_remote_cocoa/web_contents_view_cocoa.mm
@@ -4,6 +4,8 @@ #import "content/app_shim_remote_cocoa/web_contents_view_cocoa.h" +#import "content/browser/web_contents/web_contents_view_mac.h" + #import "base/mac/mac_util.h" #import "content/app_shim_remote_cocoa/web_drag_source_mac.h" #import "content/browser/web_contents/web_drag_dest_mac.h" @@ -15,11 +17,71 @@ #include "ui/base/dragdrop/cocoa_dnd_util.h" #include "ui/base/dragdrop/drag_drop_types.h" +#include "base/files/file_util.h" +#include "base/files/scoped_temp_dir.h" + using remote_cocoa::mojom::DraggingInfo; using remote_cocoa::mojom::SelectionDirection; using remote_cocoa::mojom::Visibility; using content::DropData; +namespace remote_cocoa { + +// DroppedScreenShotCopierMac is a utility to copy screenshots to a usable +// directory for PWAs. When screenshots are taken and dragged directly on to an +// application, the resulting file can only be opened by the application that it +// is passed to. For PWAs, this means that the file dragged to the PWA is not +// accessible by the browser, resulting in a failure to open the file. This +// class works around that problem by copying such screenshot files. +// https://crbug.com/1148078 +class DroppedScreenShotCopierMac { + public: + DroppedScreenShotCopierMac() = default; + ~DroppedScreenShotCopierMac() { + if (temp_dir_) { + base::ScopedAllowBlocking allow_io; + temp_dir_.reset(); + } + } + + // Examine all entries in `drop_data.filenames`. If any of them look like a + // screenshot file, copy the file to a temporary directory. This temporary + // directory (and its contents) will be kept alive until `this` is destroyed. + void CopyScreenShotsInDropData(content::DropData& drop_data) { + for (auto& file_info : drop_data.filenames) { + if (IsPathScreenShot(file_info.path)) { + base::ScopedAllowBlocking allow_io; + if (!temp_dir_) { + auto new_temp_dir = std::make_unique<base::ScopedTempDir>(); + if (!new_temp_dir->CreateUniqueTempDir()) + return; + temp_dir_ = std::move(new_temp_dir); + } + base::FilePath copy_path = + temp_dir_->GetPath().Append(file_info.path.BaseName()); + if (base::CopyFile(file_info.path, copy_path)) + file_info.path = copy_path; + } + } + } + + private: + bool IsPathScreenShot(const base::FilePath& path) const { + const std::string& value = path.value(); + size_t found_var = value.find("/var"); + if (found_var != 0) + return false; + size_t found_screencaptureui = value.find("screencaptureui"); + if (found_screencaptureui == std::string::npos) + return false; + return true; + } + + std::unique_ptr<base::ScopedTempDir> temp_dir_; +}; + +} // namespace remote_cocoa + // Ensure that the ui::DragDropTypes::DragOperation enum values stay in sync // with NSDragOperation constants, since the code below uses // NSDragOperationToDragOperation to filter invalid values. @@ -62,6 +124,12 @@ [super dealloc]; } +- (void)enableDroppedScreenShotCopier { + DCHECK(!_droppedScreenShotCopier); + _droppedScreenShotCopier = + std::make_unique<remote_cocoa::DroppedScreenShotCopierMac>(); +} + - (void)populateDraggingInfo:(DraggingInfo*)info fromNSDraggingInfo:(id<NSDraggingInfo>)nsInfo { NSPoint windowPoint = [nsInfo draggingLocation]; @@ -197,6 +265,12 @@ DropData dropData; content::PopulateDropDataFromPasteboard(&dropData, [sender draggingPasteboard]); + + // Work around screen shot drag-drop permission bugs. + // https://crbug.com/1148078 + if (_droppedScreenShotCopier) + _droppedScreenShotCopier->CopyScreenShotsInDropData(dropData); + _host->SetDropData(dropData); auto draggingInfo = DraggingInfo::New();
diff --git a/content/browser/accessibility/browser_accessibility_state_impl.cc b/content/browser/accessibility/browser_accessibility_state_impl.cc index 5bf9e522..046da54 100644 --- a/content/browser/accessibility/browser_accessibility_state_impl.cc +++ b/content/browser/accessibility/browser_accessibility_state_impl.cc
@@ -321,6 +321,12 @@ return; } + // Adding an accessibility mode flag is generally the result of an + // accessibility API call, so we should also reset the auto-disable + // accessibility code. The only exception is in tests or when a user manually + // toggles accessibility flags in chrome://accessibility. + OnAccessibilityApiUsage(); + ui::AXMode previous_mode = accessibility_mode_; accessibility_mode_ |= mode; if (accessibility_mode_ == previous_mode)
diff --git a/content/browser/accessibility/browser_accessibility_state_impl_unittest.cc b/content/browser/accessibility/browser_accessibility_state_impl_unittest.cc index 48a5b162..677038a 100644 --- a/content/browser/accessibility/browser_accessibility_state_impl_unittest.cc +++ b/content/browser/accessibility/browser_accessibility_state_impl_unittest.cc
@@ -105,4 +105,25 @@ EXPECT_FALSE(state_->IsAccessibleBrowser()); } +TEST_F(BrowserAccessibilityStateImplTest, + AddAccessibilityModeFlagsPreventsAutoDisableAccessibility) { + // Initially, accessibility should be disabled. + EXPECT_FALSE(state_->IsAccessibleBrowser()); + + // Enable accessibility. + state_->OnScreenReaderDetected(); + EXPECT_TRUE(state_->IsAccessibleBrowser()); + + // Send user input, wait 31 seconds, then send another user input event - + // but add a new accessibility mode flag. + state_->OnUserInputEvent(); + state_->OnUserInputEvent(); + clock_.Advance(base::TimeDelta::FromSeconds(31)); + state_->AddAccessibilityModeFlags(ui::kAXModeComplete); + state_->OnUserInputEvent(); + + // Accessibility should still be enabled. + EXPECT_TRUE(state_->IsAccessibleBrowser()); +} + } // namespace content
diff --git a/content/browser/file_system_access/file_system_access_handle_base.cc b/content/browser/file_system_access/file_system_access_handle_base.cc index 3ed2a0e3..029409c 100644 --- a/content/browser/file_system_access/file_system_access_handle_base.cc +++ b/content/browser/file_system_access/file_system_access_handle_base.cc
@@ -198,4 +198,8 @@ url, recurse); } +WebContentsImpl* FileSystemAccessHandleBase::web_contents() const { + return static_cast<WebContentsImpl*>(WebContentsObserver::web_contents()); +} + } // namespace content
diff --git a/content/browser/file_system_access/file_system_access_handle_base.h b/content/browser/file_system_access/file_system_access_handle_base.h index 2975098e..0844de7 100644 --- a/content/browser/file_system_access/file_system_access_handle_base.h +++ b/content/browser/file_system_access/file_system_access_handle_base.h
@@ -5,15 +5,12 @@ #ifndef CONTENT_BROWSER_FILE_SYSTEM_ACCESS_FILE_SYSTEM_ACCESS_HANDLE_BASE_H_ #define CONTENT_BROWSER_FILE_SYSTEM_ACCESS_FILE_SYSTEM_ACCESS_HANDLE_BASE_H_ -#include <vector> - #include "base/bind_post_task.h" #include "base/callback_helpers.h" #include "base/memory/weak_ptr.h" #include "base/sequence_checker.h" #include "base/threading/sequence_bound.h" #include "content/browser/file_system_access/file_system_access_manager_impl.h" -#include "content/browser/web_contents/web_contents_impl.h" #include "content/common/content_export.h" #include "content/public/browser/web_contents_observer.h" #include "storage/browser/file_system/file_system_operation_runner.h" @@ -29,6 +26,8 @@ namespace content { +class WebContentsImpl; + // Base class for File and Directory handle implementations. Holds data that is // common to both and (will) deal with functionality that is common as well, // such as permission requests. Instances of this class should be owned by the @@ -98,9 +97,7 @@ return manager()->context(); } - WebContentsImpl* web_contents() const { - return static_cast<WebContentsImpl*>(WebContentsObserver::web_contents()); - } + WebContentsImpl* web_contents() const; virtual base::WeakPtr<FileSystemAccessHandleBase> AsWeakPtr() = 0;
diff --git a/content/browser/file_system_access/file_system_access_manager_impl.cc b/content/browser/file_system_access/file_system_access_manager_impl.cc index af27b1d..e317b66 100644 --- a/content/browser/file_system_access/file_system_access_manager_impl.cc +++ b/content/browser/file_system_access/file_system_access_manager_impl.cc
@@ -11,6 +11,7 @@ #include "base/bind_post_task.h" #include "base/callback_helpers.h" #include "base/check_op.h" +#include "base/command_line.h" #include "base/files/file.h" #include "base/files/file_path.h" #include "base/metrics/histogram_functions.h"
diff --git a/content/browser/interest_group/interest_group_browsertest.cc b/content/browser/interest_group/interest_group_browsertest.cc index 59c37f9..6062ea18 100644 --- a/content/browser/interest_group/interest_group_browsertest.cc +++ b/content/browser/interest_group/interest_group_browsertest.cc
@@ -231,7 +231,7 @@ return interest_groups; } - int GetJoinCount(url::Origin owner, std::string name) { + int GetJoinCount(const url::Origin& owner, const std::string& name) { for (const auto& interest_group : GetInterestGroupsForOwner(owner)) { if (interest_group->group->name == name) { return interest_group->signals->join_count; @@ -240,8 +240,9 @@ return 0; } - bool JoinInterestGroupAndWaitInJs(url::Origin owner, - std::string name) WARN_UNUSED_RESULT { + bool JoinInterestGroupAndWaitInJs(const url::Origin& owner, + const std::string& name) + WARN_UNUSED_RESULT { int initial_count = GetJoinCount(owner, name); if (!JoinInterestGroupInJS(owner, name)) { return false; @@ -267,7 +268,8 @@ return true; } - bool LeaveInterestGroupAndWait(url::Origin owner, std::string name) { + bool LeaveInterestGroupAndWait(const url::Origin& owner, + const std::string& name) { if (!LeaveInterestGroupInJS(owner, name)) { return false; } @@ -352,41 +354,41 @@ // This join should fail and throw an exception since a.test is not the same // origin as the bidding_url, bid.a.test. EXPECT_FALSE(JoinInterestGroupInJS(blink::mojom::InterestGroup::New( - /* expiry */ base::Time(), - /* owner= */ test_origin_a, - /* name = */ "bicycles", - /* bidding_url = */ GURL("https://bid.a.test"), - /* update_url = */ absl::nullopt, - /* trusted_bidding_signals_url = */ absl::nullopt, - /* trusted_bidding_signals_keys = */ absl::nullopt, - /* user_bidding_signals = */ absl::nullopt, - /* ads = */ absl::nullopt))); + /*expiry=*/base::Time(), + /*owner=*/test_origin_a, + /*name=*/"bicycles", + /*bidding_url=*/GURL("https://bid.a.test"), + /*update_url=*/absl::nullopt, + /*trusted_bidding_signals_url=*/absl::nullopt, + /*trusted_bidding_signals_keys=*/absl::nullopt, + /*user_bidding_signals=*/absl::nullopt, + /*ads=*/absl::nullopt))); // This join should fail and throw an exception since a.test is not the same // origin as the update_url, update.a.test. EXPECT_FALSE(JoinInterestGroupInJS(blink::mojom::InterestGroup::New( - /* expiry */ base::Time(), - /* owner= */ test_origin_a, - /* name = */ "tricycles", - /* bidding_url = */ absl::nullopt, - /* update_url = */ GURL("https://update.a.test"), - /* trusted_bidding_signals_url = */ absl::nullopt, - /* trusted_bidding_signals_keys = */ absl::nullopt, - /* user_bidding_signals = */ absl::nullopt, - /* ads = */ absl::nullopt))); + /*expiry=*/base::Time(), + /*owner=*/test_origin_a, + /*name=*/"tricycles", + /*bidding_url=*/absl::nullopt, + /*update_url=*/GURL("https://update.a.test"), + /*trusted_bidding_signals_url=*/absl::nullopt, + /*trusted_bidding_signals_keys=*/absl::nullopt, + /*user_bidding_signals=*/absl::nullopt, + /*ads=*/absl::nullopt))); // This join should fail and throw an exception since a.test is not the same // origin as the trusted_bidding_signals_url, signals.a.test. EXPECT_FALSE(JoinInterestGroupInJS(blink::mojom::InterestGroup::New( - /* expiry */ base::Time(), - /* owner= */ test_origin_a, - /* name = */ "four-wheelers", - /* bidding_url = */ absl::nullopt, - /* update_url = */ absl::nullopt, - /* trusted_bidding_signals_url = */ GURL("https://signals.a.test"), - /* trusted_bidding_signals_keys = */ absl::nullopt, - /* user_bidding_signals = */ absl::nullopt, - /* ads = */ absl::nullopt))); + /*expiry=*/base::Time(), + /*owner=*/test_origin_a, + /*name=*/"four-wheelers", + /*bidding_url=*/absl::nullopt, + /*update_url=*/absl::nullopt, + /*trusted_bidding_signals_url=*/GURL("https://signals.a.test"), + /*trusted_bidding_signals_keys=*/absl::nullopt, + /*user_bidding_signals=*/absl::nullopt, + /*ads=*/absl::nullopt))); // This join should silently fail since d.test is not allowlisted for the API, // and allowlist checks only happen in the browser process, so don't throw an @@ -417,15 +419,15 @@ // Inject an interest group into the DB for that for that site so we can try // to remove it. manager_->JoinInterestGroup(blink::mojom::InterestGroup::New( - /* expiry */ base::Time::Now() + base::TimeDelta::FromSeconds(300), - /* owner= */ test_origin_d, - /* name = */ "candy", - /* bidding_url = */ absl::nullopt, - /* update_url = */ absl::nullopt, - /* trusted_bidding_signals_url = */ absl::nullopt, - /* trusted_bidding_signals_keys = */ absl::nullopt, - /* user_bidding_signals = */ absl::nullopt, - /* ads = */ absl::nullopt)); + /*expiry=*/base::Time::Now() + base::TimeDelta::FromSeconds(300), + /*owner=*/test_origin_d, + /*name=*/"candy", + /*bidding_url=*/absl::nullopt, + /*update_url=*/absl::nullopt, + /*trusted_bidding_signals_url=*/absl::nullopt, + /*trusted_bidding_signals_keys=*/absl::nullopt, + /*user_bidding_signals=*/absl::nullopt, + /*ads=*/absl::nullopt)); ASSERT_TRUE(NavigateToURL(shell(), test_url_d)); // This leave should do nothing because origin_d is not allowed by privacy @@ -521,20 +523,23 @@ IN_PROC_BROWSER_TEST_F(InterestGroupBrowserTest, JoinInterestGroupInvalidBiddingLogicUrl) { - ASSERT_TRUE(NavigateToURL(shell(), embedded_test_server()->GetURL("/echo"))); + GURL url = https_server_->GetURL("a.test", "/echo"); + std::string origin_string = url::Origin::Create(url).Serialize(); + ASSERT_TRUE(NavigateToURL(shell(), url)); EXPECT_EQ( - "TypeError: Failed to execute 'joinAdInterestGroup' on 'Navigator': " - "biddingLogicUrl 'https://invalid^&' for AuctionAdInterestGroup with " - "owner 'https://test.com' and name 'cars' cannot be resolved to a valid " - "URL.", - EvalJs(shell(), R"( + base::StringPrintf( + "TypeError: Failed to execute 'joinAdInterestGroup' on 'Navigator': " + "biddingLogicUrl 'https://invalid^&' for AuctionAdInterestGroup with " + "owner '%s' and name 'cars' cannot be resolved to a valid URL.", + origin_string.c_str()), + EvalJs(shell(), JsReplace(R"( (function() { try { navigator.joinAdInterestGroup( { name: 'cars', - owner: 'https://test.com', + owner: $1, biddingLogicUrl: 'https://invalid^&', }, /*joinDurationSec=*/1); @@ -542,25 +547,29 @@ return e.toString(); } return 'done'; -})())")); +})())", + origin_string.c_str()))); } IN_PROC_BROWSER_TEST_F(InterestGroupBrowserTest, JoinInterestGroupInvalidDailyUpdateUrl) { - ASSERT_TRUE(NavigateToURL(shell(), embedded_test_server()->GetURL("/echo"))); + GURL url = https_server_->GetURL("a.test", "/echo"); + std::string origin_string = url::Origin::Create(url).Serialize(); + ASSERT_TRUE(NavigateToURL(shell(), url)); EXPECT_EQ( - "TypeError: Failed to execute 'joinAdInterestGroup' on 'Navigator': " - "dailyUpdateUrl 'https://invalid^&' for AuctionAdInterestGroup with " - "owner 'https://test.com' and name 'cars' cannot be resolved to a valid " - "URL.", - EvalJs(shell(), R"( + base::StringPrintf( + "TypeError: Failed to execute 'joinAdInterestGroup' on 'Navigator': " + "dailyUpdateUrl 'https://invalid^&' for AuctionAdInterestGroup with " + "owner '%s' and name 'cars' cannot be resolved to a valid URL.", + origin_string.c_str()), + EvalJs(shell(), JsReplace(R"( (function() { try { navigator.joinAdInterestGroup( { name: 'cars', - owner: 'https://test.com', + owner: $1, dailyUpdateUrl: 'https://invalid^&', }, /*joinDurationSec=*/1); @@ -568,25 +577,29 @@ return e.toString(); } return 'done'; -})())")); +})())", + origin_string.c_str()))); } IN_PROC_BROWSER_TEST_F(InterestGroupBrowserTest, JoinInterestGroupInvalidTrustedBiddingSignalsUrl) { - ASSERT_TRUE(NavigateToURL(shell(), embedded_test_server()->GetURL("/echo"))); + GURL url = https_server_->GetURL("a.test", "/echo"); + std::string origin_string = url::Origin::Create(url).Serialize(); + ASSERT_TRUE(NavigateToURL(shell(), url)); - EXPECT_EQ( - "TypeError: Failed to execute 'joinAdInterestGroup' on 'Navigator': " - "trustedBiddingSignalsUrl 'https://invalid^&' for " - "AuctionAdInterestGroup with owner 'https://test.com' and name 'cars' " - "cannot be resolved to a valid URL.", - EvalJs(shell(), R"( + EXPECT_EQ(base::StringPrintf( + "TypeError: Failed to execute 'joinAdInterestGroup' on " + "'Navigator': trustedBiddingSignalsUrl 'https://invalid^&' for " + "AuctionAdInterestGroup with owner '%s' and name 'cars' cannot " + "be resolved to a valid URL.", + origin_string.c_str()), + EvalJs(shell(), JsReplace(R"( (function() { try { navigator.joinAdInterestGroup( { name: 'cars', - owner: 'https://test.com', + owner: $1, trustedBiddingSignalsUrl: 'https://invalid^&', }, /*joinDurationSec=*/1); @@ -594,24 +607,29 @@ return e.toString(); } return 'done'; -})())")); +})())", + origin_string.c_str()))); } IN_PROC_BROWSER_TEST_F(InterestGroupBrowserTest, JoinInterestGroupInvalidUserBiddingSignals) { - ASSERT_TRUE(NavigateToURL(shell(), embedded_test_server()->GetURL("/echo"))); + GURL url = https_server_->GetURL("a.test", "/echo"); + std::string origin_string = url::Origin::Create(url).Serialize(); + ASSERT_TRUE(NavigateToURL(shell(), url)); EXPECT_EQ( - "TypeError: Failed to execute 'joinAdInterestGroup' on 'Navigator': " - "userBiddingSignals for AuctionAdInterestGroup with owner " - "'https://test.com' and name 'cars' must be a JSON-serializable object.", - EvalJs(shell(), R"( + base::StringPrintf( + "TypeError: Failed to execute 'joinAdInterestGroup' on 'Navigator': " + "userBiddingSignals for AuctionAdInterestGroup with owner '%s' and " + "name 'cars' must be a JSON-serializable object.", + origin_string.c_str()), + EvalJs(shell(), JsReplace(R"( (function() { try { navigator.joinAdInterestGroup( { name: 'cars', - owner: 'https://test.com', + owner: $1, userBiddingSignals: function() {}, }, /*joinDurationSec=*/1); @@ -619,24 +637,29 @@ return e.toString(); } return 'done'; -})())")); +})())", + origin_string.c_str()))); } IN_PROC_BROWSER_TEST_F(InterestGroupBrowserTest, JoinInterestGroupInvalidAdUrl) { - ASSERT_TRUE(NavigateToURL(shell(), embedded_test_server()->GetURL("/echo"))); + GURL url = https_server_->GetURL("a.test", "/echo"); + std::string origin_string = url::Origin::Create(url).Serialize(); + ASSERT_TRUE(NavigateToURL(shell(), url)); EXPECT_EQ( - "TypeError: Failed to execute 'joinAdInterestGroup' on 'Navigator': " - "ad renderUrl 'https://invalid^&' for AuctionAdInterestGroup with owner " - "'https://test.com' and name 'cars' cannot be resolved to a valid URL.", - EvalJs(shell(), R"( + base::StringPrintf( + "TypeError: Failed to execute 'joinAdInterestGroup' on 'Navigator': " + "ad renderUrl 'https://invalid^&' for AuctionAdInterestGroup with " + "owner '%s' and name 'cars' cannot be resolved to a valid URL.", + origin_string.c_str()), + EvalJs(shell(), JsReplace(R"( (function() { try { navigator.joinAdInterestGroup( { name: 'cars', - owner: 'https://test.com', + owner: $1, ads: [{renderUrl:"https://invalid^&"}], }, /*joinDurationSec=*/1); @@ -644,18 +667,23 @@ return e.toString(); } return 'done'; -})())")); +})())", + origin_string.c_str()))); } IN_PROC_BROWSER_TEST_F(InterestGroupBrowserTest, JoinInterestGroupInvalidAdMetadata) { - ASSERT_TRUE(NavigateToURL(shell(), embedded_test_server()->GetURL("/echo"))); + GURL url = https_server_->GetURL("a.test", "/echo"); + std::string origin_string = url::Origin::Create(url).Serialize(); + ASSERT_TRUE(NavigateToURL(shell(), url)); EXPECT_EQ( - "TypeError: Failed to execute 'joinAdInterestGroup' on 'Navigator': ad " - "metadata for AuctionAdInterestGroup with owner 'https://test.com' and " - "name 'cars' must be a JSON-serializable object.", - EvalJs(shell(), R"( + base::StringPrintf( + "TypeError: Failed to execute 'joinAdInterestGroup' on " + "'Navigator': ad metadata for AuctionAdInterestGroup with " + "owner '%s' and name 'cars' must be a JSON-serializable object.", + origin_string.c_str()), + EvalJs(shell(), JsReplace(R"( (function() { let x = {}; let y = {}; @@ -665,7 +693,7 @@ navigator.joinAdInterestGroup( { name: 'cars', - owner: 'https://test.com', + owner: $1, ads: [{renderUrl:"https://test.com", metadata:x}], }, /*joinDurationSec=*/1); @@ -673,7 +701,8 @@ return e.toString(); } return 'done'; -})())")); +})())", + origin_string.c_str()))); } IN_PROC_BROWSER_TEST_F(InterestGroupBrowserTest, @@ -748,16 +777,16 @@ "metadata : {ad:'metadata', here : [ 1, 2 ]}}]"; EXPECT_TRUE(JoinInterestGroupAndWaitInJs( blink::mojom::InterestGroup::New( - /* expiry */ base::Time(), - /* owner= */ url::Origin::Create(test_url.GetOrigin()), - /* name = */ "cars", - /* bidding_url = */ + /*expiry=*/base::Time(), + /*owner=*/url::Origin::Create(test_url.GetOrigin()), + /*name=*/"cars", + /*bidding_url=*/ https_server_->GetURL("a.test", "/interest_group/bidding_logic.js"), - /* update_url = */ absl::nullopt, - /* trusted_bidding_signals_url = */ absl::nullopt, - /* trusted_bidding_signals_keys = */ absl::nullopt, - /* user_bidding_signals = */ "{some: 'json', data: {here: [1, 2]}}", - /* ads = */ absl::nullopt), + /*update_url=*/absl::nullopt, + /*trusted_bidding_signals_url=*/absl::nullopt, + /*trusted_bidding_signals_keys=*/absl::nullopt, + /*user_bidding_signals=*/"{some: 'json', data: {here: [1, 2]}}", + /*ads=*/absl::nullopt), ads)); EXPECT_EQ( @@ -880,16 +909,16 @@ "metadata : {ad:'metadata', here : [ 1, 2 ]}}]"; EXPECT_TRUE(JoinInterestGroupAndWaitInJs( blink::mojom::InterestGroup::New( - /* expiry */ base::Time(), - /* owner= */ url::Origin::Create(test_url.GetOrigin()), - /* name = */ "cars", - /* bidding_url = */ + /*expiry=*/base::Time(), + /*owner=*/url::Origin::Create(test_url.GetOrigin()), + /*name=*/"cars", + /*bidding_url=*/ https_server_->GetURL("a.test", "/interest_group/bidding_logic.js"), - /* update_url = */ absl::nullopt, - /* trusted_bidding_signals_url = */ absl::nullopt, - /* trusted_bidding_signals_keys = */ absl::nullopt, - /* user_bidding_signals = */ "{some: 'json', data: {here: [1, 2]}}", - /* ads = */ absl::nullopt), + /*update_url=*/absl::nullopt, + /*trusted_bidding_signals_url=*/absl::nullopt, + /*trusted_bidding_signals_keys=*/absl::nullopt, + /*user_bidding_signals=*/"{some: 'json', data: {here: [1, 2]}}", + /*ads=*/absl::nullopt), ads)); EXPECT_EQ( @@ -949,18 +978,18 @@ "metadata : {ad:'metadata', here : [ 1, 2 ]}}]"; EXPECT_TRUE(JoinInterestGroupAndWaitInJs( blink::mojom::InterestGroup::New( - /* expiry */ base::Time(), - /* owner= */ url::Origin::Create(test_url_a), - /* name = */ "cars", - /* bidding_url = */ + /*expiry=*/base::Time(), + /*owner=*/url::Origin::Create(test_url_a), + /*name=*/"cars", + /*bidding_url=*/ https_server_->GetURL("a.test", "/interest_group/bidding_logic.js"), - /* update_url = */ absl::nullopt, - /* trusted_bidding_signals_url = */ + /*update_url=*/absl::nullopt, + /*trusted_bidding_signals_url=*/ https_server_->GetURL("a.test", "/interest_group/trusted_bidding_signals.json"), - /* trusted_bidding_signals_keys = */ absl::nullopt, - /* user_bidding_signals = */ "{some: 'json', data: {here: [1, 2]}}", - /* ads = */ absl::nullopt), + /*trusted_bidding_signals_keys=*/absl::nullopt, + /*user_bidding_signals=*/"{some: 'json', data: {here: [1, 2]}}", + /*ads=*/absl::nullopt), ads, "['key1']")); GURL test_url_d = https_server_->GetURL("d.test", "/echo"); @@ -1023,19 +1052,19 @@ "metadata : {ad:'metadata', here : [ 1, 2 ]}}]"; EXPECT_TRUE(JoinInterestGroupAndWaitInJs( blink::mojom::InterestGroup::New( - /* expiry */ base::Time(), - /* owner= */ url::Origin::Create(test_url.GetOrigin()), - /* name = */ "cars", - /* bidding_url = */ + /*expiry=*/base::Time(), + /*owner=*/url::Origin::Create(test_url.GetOrigin()), + /*name=*/"cars", + /*bidding_url=*/ https_server_->GetURL(test_url.host(), "/interest_group/bidding_logic.js"), - /* update_url = */ absl::nullopt, - /* trusted_bidding_signals_url = */ + /*update_url=*/absl::nullopt, + /*trusted_bidding_signals_url=*/ https_server_->GetURL(test_url.host(), "/interest_group/trusted_bidding_signals.json"), - /* trusted_bidding_signals_keys = */ absl::nullopt, - /* user_bidding_signals = */ "{some: 'json', data: {here: [1, 2]}}", - /* ads = */ absl::nullopt), + /*trusted_bidding_signals_keys=*/absl::nullopt, + /*user_bidding_signals=*/"{some: 'json', data: {here: [1, 2]}}", + /*ads=*/absl::nullopt), ads, "['key1']")); EXPECT_EQ("https://example.com/render", @@ -1071,18 +1100,18 @@ "metadata : {ad:'metadata', here : [ 1, 2 ]}}]"; EXPECT_TRUE(JoinInterestGroupAndWaitInJs( blink::mojom::InterestGroup::New( - /* expiry */ base::Time(), - /* owner= */ url::Origin::Create(test_url.GetOrigin()), - /* name = */ "cars", - /* bidding_url = */ + /*expiry=*/base::Time(), + /*owner=*/url::Origin::Create(test_url.GetOrigin()), + /*name=*/"cars", + /*bidding_url=*/ https_server_->GetURL("a.test", "/interest_group/bidding_logic.js"), - /* update_url = */ absl::nullopt, - /* trusted_bidding_signals_url = */ + /*update_url=*/absl::nullopt, + /*trusted_bidding_signals_url=*/ https_server_->GetURL("a.test", "/interest_group/trusted_bidding_signals.json"), - /* trusted_bidding_signals_keys = */ absl::nullopt, - /* user_bidding_signals = */ "{some: 'json', data: {here: [1, 2]}}", - /* ads = */ absl::nullopt), + /*trusted_bidding_signals_keys=*/absl::nullopt, + /*user_bidding_signals=*/"{some: 'json', data: {here: [1, 2]}}", + /*ads=*/absl::nullopt), ads, "['key1']")); EXPECT_EQ( @@ -1209,18 +1238,18 @@ "metadata : {ad:'metadata', here : [ 1, 2 ]}}]"; EXPECT_TRUE(JoinInterestGroupAndWaitInJs( blink::mojom::InterestGroup::New( - /* expiry */ base::Time(), - /* owner= */ url::Origin::Create(bidder_url.GetOrigin()), - /* name = */ "cars", - /* bidding_url = */ + /*expiry=*/base::Time(), + /*owner=*/url::Origin::Create(bidder_url.GetOrigin()), + /*name=*/"cars", + /*bidding_url=*/ https_server_->GetURL(kBidder, "/interest_group/bidding_logic.js"), - /* update_url = */ absl::nullopt, - /* trusted_bidding_signals_url = */ + /*update_url=*/absl::nullopt, + /*trusted_bidding_signals_url=*/ https_server_->GetURL(kBidder, "/interest_group/trusted_bidding_signals.json"), - /* trusted_bidding_signals_keys = */ absl::nullopt, - /* user_bidding_signals = */ "{some: 'json', data: {here: [1, 2]}}", - /* ads = */ absl::nullopt), + /*trusted_bidding_signals_keys=*/absl::nullopt, + /*user_bidding_signals=*/"{some: 'json', data: {here: [1, 2]}}", + /*ads=*/absl::nullopt), ads, "['key1']")); // Navigate to publisher. @@ -1284,18 +1313,18 @@ ASSERT_TRUE(NavigateToURL(shell(), other_url)); EXPECT_TRUE(JoinInterestGroupAndWaitInJs( blink::mojom::InterestGroup::New( - /* expiry */ base::Time(), - /* owner= */ other_origin, - /* name = */ "cars", - /* bidding_url = */ + /*expiry=*/base::Time(), + /*owner=*/other_origin, + /*name=*/"cars", + /*bidding_url=*/ https_server_->GetURL( kOtherHost, "/interest_group/bidding_logic_expect_top_frame_a_test.js"), - /* update_url = */ absl::nullopt, - /* trusted_bidding_signals_url = */ absl::nullopt, - /* trusted_bidding_signals_keys = */ absl::nullopt, - /* user_bidding_signals = */ absl::nullopt, - /* ads = */ absl::nullopt), + /*update_url=*/absl::nullopt, + /*trusted_bidding_signals_url=*/absl::nullopt, + /*trusted_bidding_signals_keys=*/absl::nullopt, + /*user_bidding_signals=*/absl::nullopt, + /*ads=*/absl::nullopt), "[{renderUrl : 'https://example.com/render'}]")); const struct { @@ -1366,46 +1395,46 @@ EXPECT_TRUE(JoinInterestGroupAndWaitInJs( blink::mojom::InterestGroup::New( - /* expiry */ base::Time(), - /* owner= */ url::Origin::Create(test_url.GetOrigin()), - /* name = */ "cars", - /* bidding_url = */ + /*expiry=*/base::Time(), + /*owner=*/url::Origin::Create(test_url.GetOrigin()), + /*name=*/"cars", + /*bidding_url=*/ https_server_->GetURL( "a.test", "/interest_group/bidding_logic_stop_bidding_after_win.js"), - /* update_url = */ absl::nullopt, - /* trusted_bidding_signals_url = */ absl::nullopt, - /* trusted_bidding_signals_keys = */ absl::nullopt, - /* user_bidding_signals = */ "{some: 'json', data: {here: [1, 2]}}", - /* ads = */ absl::nullopt), + /*update_url=*/absl::nullopt, + /*trusted_bidding_signals_url=*/absl::nullopt, + /*trusted_bidding_signals_keys=*/absl::nullopt, + /*user_bidding_signals=*/"{some: 'json', data: {here: [1, 2]}}", + /*ads=*/absl::nullopt), "[{renderUrl : 'https://stop_bidding_after_win.com/render'}]")); EXPECT_TRUE(JoinInterestGroupAndWaitInJs( blink::mojom::InterestGroup::New( - /* expiry */ base::Time(), - /* owner= */ url::Origin::Create(test_url.GetOrigin()), - /* name = */ "bikes", - /* bidding_url = */ + /*expiry=*/base::Time(), + /*owner=*/url::Origin::Create(test_url.GetOrigin()), + /*name=*/"bikes", + /*bidding_url=*/ https_server_->GetURL("a.test", "/interest_group/bidding_logic.js"), - /* update_url = */ absl::nullopt, - /* trusted_bidding_signals_url = */ + /*update_url=*/absl::nullopt, + /*trusted_bidding_signals_url=*/ https_server_->GetURL("a.test", "/interest_group/trusted_bidding_signals.json"), - /* trusted_bidding_signals_keys = */ absl::nullopt, - /* user_bidding_signals = */ "{some: 'json', data: {here: [1, 2]}}", - /* ads = */ absl::nullopt), + /*trusted_bidding_signals_keys=*/absl::nullopt, + /*user_bidding_signals=*/"{some: 'json', data: {here: [1, 2]}}", + /*ads=*/absl::nullopt), "[{renderUrl : 'https://example.com/render'}]", "['key1']")); EXPECT_TRUE(JoinInterestGroupAndWaitInJs( blink::mojom::InterestGroup::New( - /* expiry */ base::Time(), - /* owner= */ url::Origin::Create(test_url.GetOrigin()), - /* name = */ "shoes", - /* bidding_url = */ + /*expiry=*/base::Time(), + /*owner=*/url::Origin::Create(test_url.GetOrigin()), + /*name=*/"shoes", + /*bidding_url=*/ https_server_->GetURL("a.test", "/interest_group/bidding_logic.js"), - /* update_url = */ absl::nullopt, - /* trusted_bidding_signals_url = */ absl::nullopt, - /* trusted_bidding_signals_keys = */ absl::nullopt, - /* user_bidding_signals = */ "{some: 'json', data: {here: [1, 2]}}", - /* ads = */ absl::nullopt), + /*update_url=*/absl::nullopt, + /*trusted_bidding_signals_url=*/absl::nullopt, + /*trusted_bidding_signals_keys=*/absl::nullopt, + /*user_bidding_signals=*/"{some: 'json', data: {here: [1, 2]}}", + /*ads=*/absl::nullopt), "[{renderUrl : 'https://example.com/render2'}]")); EXPECT_EQ( @@ -1439,18 +1468,18 @@ // This group will win if it has never won an auction. EXPECT_TRUE(JoinInterestGroupAndWaitInJs( blink::mojom::InterestGroup::New( - /* expiry */ base::Time(), - /* owner= */ url::Origin::Create(test_url.GetOrigin()), - /* name = */ "cars", - /* bidding_url = */ + /*expiry=*/base::Time(), + /*owner=*/url::Origin::Create(test_url.GetOrigin()), + /*name=*/"cars", + /*bidding_url=*/ https_server_->GetURL( "a.test", "/interest_group/bidding_logic_stop_bidding_after_win.js"), - /* update_url = */ absl::nullopt, - /* trusted_bidding_signals_url = */ absl::nullopt, - /* trusted_bidding_signals_keys = */ absl::nullopt, - /* user_bidding_signals = */ "{some: 'json', data: {here: [1, 2]}}", - /* ads = */ absl::nullopt), + /*update_url=*/absl::nullopt, + /*trusted_bidding_signals_url=*/absl::nullopt, + /*trusted_bidding_signals_keys=*/absl::nullopt, + /*user_bidding_signals=*/"{some: 'json', data: {here: [1, 2]}}", + /*ads=*/absl::nullopt), ads)); GURL test_url2 = https_server_->GetURL("b.test", "/echo"); @@ -1458,16 +1487,16 @@ // This group will win if the other interest group has won an auction. EXPECT_TRUE(JoinInterestGroupAndWaitInJs( blink::mojom::InterestGroup::New( - /* expiry */ base::Time(), - /* owner= */ url::Origin::Create(test_url2.GetOrigin()), - /* name = */ "shoes", - /* bidding_url = */ + /*expiry=*/base::Time(), + /*owner=*/url::Origin::Create(test_url2.GetOrigin()), + /*name=*/"shoes", + /*bidding_url=*/ https_server_->GetURL("b.test", "/interest_group/bidding_logic.js"), - /* update_url = */ absl::nullopt, - /* trusted_bidding_signals_url = */ absl::nullopt, - /* trusted_bidding_signals_keys = */ absl::nullopt, - /* user_bidding_signals = */ "{some: 'json', data: {here: [1, 2]}}", - /* ads = */ absl::nullopt), + /*update_url=*/absl::nullopt, + /*trusted_bidding_signals_url=*/absl::nullopt, + /*trusted_bidding_signals_keys=*/absl::nullopt, + /*user_bidding_signals=*/"{some: 'json', data: {here: [1, 2]}}", + /*ads=*/absl::nullopt), "[{renderUrl : 'https://example.com/render'}]")); // Both owners have one interest group in storage, and both interest groups @@ -1558,17 +1587,17 @@ "metadata : {ad:'metadata', here : [ 1, 2 ]}}]"; EXPECT_TRUE(JoinInterestGroupAndWaitInJs( blink::mojom::InterestGroup::New( - /* expiry */ base::Time(), - /* owner= */ url::Origin::Create(test_url.GetOrigin()), - /* name = */ "cars", - /* bidding_url = */ + /*expiry=*/base::Time(), + /*owner=*/url::Origin::Create(test_url.GetOrigin()), + /*name=*/"cars", + /*bidding_url=*/ https_server_->GetURL( "a.test", "/interest_group/bidding_logic_invalid_ad_url.js"), - /* update_url = */ absl::nullopt, - /* trusted_bidding_signals_url = */ absl::nullopt, - /* trusted_bidding_signals_keys = */ absl::nullopt, - /* user_bidding_signals = */ "{some: 'json', data: {here: [1, 2]}}", - /* ads = */ absl::nullopt), + /*update_url=*/absl::nullopt, + /*trusted_bidding_signals_url=*/absl::nullopt, + /*trusted_bidding_signals_keys=*/absl::nullopt, + /*user_bidding_signals=*/"{some: 'json', data: {here: [1, 2]}}", + /*ads=*/absl::nullopt), ads)); EXPECT_EQ( @@ -1803,16 +1832,15 @@ "metadata : {ad:'metadata', here : [ 1, 2 ]}}]"; EXPECT_TRUE(JoinInterestGroupAndWaitInJs( blink::mojom::InterestGroup::New( - /* expiry */ base::Time(), - /* owner= */ url::Origin::Create(hanging_url.GetOrigin()), - /* name = */ "cars", - /* bidding_url = */ - hanging_url, - /* update_url = */ absl::nullopt, - /* trusted_bidding_signals_url = */ absl::nullopt, - /* trusted_bidding_signals_keys = */ absl::nullopt, - /* user_bidding_signals = */ "{some: 'json', data: {here: [1, 2]}}", - /* ads = */ absl::nullopt), + /*expiry=*/base::Time(), + /*owner=*/url::Origin::Create(hanging_url.GetOrigin()), + /*name=*/"cars", + /*bidding_url=*/hanging_url, + /*update_url=*/absl::nullopt, + /*trusted_bidding_signals_url=*/absl::nullopt, + /*trusted_bidding_signals_keys=*/absl::nullopt, + /*user_bidding_signals=*/"{some: 'json', data: {here: [1, 2]}}", + /*ads=*/absl::nullopt), ads, "['key1']")); ExecuteScriptAsync(
diff --git a/content/browser/prerender/prerender_browsertest.cc b/content/browser/prerender/prerender_browsertest.cc index e487f69..ba73655 100644 --- a/content/browser/prerender/prerender_browsertest.cc +++ b/content/browser/prerender/prerender_browsertest.cc
@@ -270,6 +270,14 @@ EXPECT_EQ(rfhi->lifecycle_state(), RenderFrameHostImpl::LifecycleStateImpl::kActive); EXPECT_FALSE(rfhi->frame_tree()->is_prerendering()); + + // Check that each document can use a deferred Mojo interface. Choose + // WebLocks API as the feature is enabled by default and does not require + // permission. + const std::string kMojoScript = R"( + navigator.locks.request('hi', {mode:'shared'}, () => {}); + )"; + EXPECT_TRUE(ExecJs(rfhi, kMojoScript)); } } @@ -1278,8 +1286,7 @@ // Blank <iframe> is a special case. Tests that the blank iframe knows the // prerendering state as well. -// TODO(https://crbug.com/1185965): This test is disabled for flakiness. -IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, DISABLED_PrerenderBlankIframe) { +IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderBlankIframe) { TestHostPrerenderingState(GetUrl("/page_with_blank_iframe.html")); } @@ -2591,11 +2598,8 @@ // Ensures WebContents::OpenURL with a cross-origin URL targeting a frame in a // prerendered host will successfully navigate that frame, though it should be // deferred until activation. -// TODO(bokan): This test exposes a race condition between the iframe -// navigation and the prerenderingchange event being dispatched. -// https://crbug.com/1213454. IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, - DISABLED_OpenURLCrossOriginInPrerenderingFrame) { + OpenURLCrossOriginInPrerenderingFrame) { const GURL kInitialUrl = GetUrl("/empty.html"); const GURL kPrerenderingUrl = GetUrl("/page_with_blank_iframe.html"); const GURL kNewIframeUrl = GetCrossOriginUrl("/simple_page.html"); @@ -2673,9 +2677,8 @@ auto* prerender_ftn = prerendered_rfh->frame_tree_node(); EXPECT_FALSE(prerender_ftn->HasNavigation()); - // Now navigate the primary page to the prerendered URL so that we activate - // the prerender. Use a CommitDeferringCondition to pause activation - // before it completes. + // Start an activation navigation for the prerender. Use a + // CommitDeferringCondition to pause activation before it completes. TestNavigationManager activation_observer(shell()->web_contents(), kPrerenderingUrl); MockCommitDeferringConditionWrapper condition(/*is_ready_to_commit=*/false); @@ -2686,6 +2689,9 @@ // Wait for the condition to pause the activation. condition.WaitUntilInvoked(); + NavigationRequest* request = + web_contents_impl()->GetFrameTree()->root()->navigation_request(); + EXPECT_TRUE(request->IsCommitDeferringConditionDeferredForTesting()); EXPECT_EQ(web_contents()->GetURL(), kInitialUrl); } @@ -2719,10 +2725,88 @@ EXPECT_EQ(shell()->web_contents()->GetURL(), kPrerenderingUrl); } -// Ensures WebContents::OpenURL to a frame in a currently activating (i.e. -// "reserved") prerendering host navigates the frame. +// Tests that cross-origin subframe navigations in a prerendered page are +// deferred even if they start after the a navigation starts that will +// attempt to activate the prerendered page. +// +// Regression test for https://crbug.com/1190262. IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, - OpenURLInReservedPrerenderingFrame) { + CrossOriginSubframeNavigationDuringActivation) { + const GURL kInitialUrl = GetUrl("/empty.html"); + const GURL kPrerenderingUrl = GetUrl("/page_with_blank_iframe.html"); + const GURL kCrossOriginUrl = GetCrossOriginUrl("/simple_page.html"); + + // Navigate to an initial page. + ASSERT_TRUE(NavigateToURL(shell(), kInitialUrl)); + ASSERT_EQ(shell()->web_contents()->GetURL(), kInitialUrl); + + // Start prerendering `kPrerenderingUrl`. + int prerender_host_id = RenderFrameHost::kNoFrameTreeNodeId; + RenderFrameHost* prerender_main_frame = nullptr; + { + prerender_host_id = AddPrerender(kPrerenderingUrl); + ASSERT_NE(prerender_host_id, RenderFrameHost::kNoFrameTreeNodeId); + + prerender_main_frame = GetPrerenderedMainFrameHost(prerender_host_id); + RenderFrameHost* child_frame = ChildFrameAt(prerender_main_frame, 0); + ASSERT_TRUE(child_frame); + } + + // Start an activation navigation for the prerender. Use a + // CommitDeferringCondition to pause activation before it completes. + test::PrerenderHostObserver prerender_observer(*web_contents(), + kPrerenderingUrl); + TestNavigationManager activation_observer(shell()->web_contents(), + kPrerenderingUrl); + MockCommitDeferringConditionWrapper condition(/*is_ready_to_commit=*/false); + { + MockCommitDeferringConditionInstaller installer(condition.PassToDelegate()); + ASSERT_TRUE(ExecJs(web_contents()->GetMainFrame(), + JsReplace("location = $1", kPrerenderingUrl))); + + // Wait for the condition to pause the activation. + condition.WaitUntilInvoked(); + NavigationRequest* request = + web_contents_impl()->GetFrameTree()->root()->navigation_request(); + EXPECT_TRUE(request->IsCommitDeferringConditionDeferredForTesting()); + EXPECT_EQ(web_contents()->GetURL(), kInitialUrl); + } + + // Start a cross-origin subframe navigation in the prerendered page. It + // should be deferred. + std::string kNavigateScript = R"( + document.querySelector('iframe').src = $1; + )"; + TestNavigationManager iframe_nav_observer(shell()->web_contents(), + kCrossOriginUrl); + ASSERT_TRUE(ExecJs(prerender_main_frame, + JsReplace(kNavigateScript, kCrossOriginUrl))); + + iframe_nav_observer.WaitForFirstYieldAfterDidStartNavigation(); + + // The PrerenderSubframeNavigationThrottle should defer it until activation. + auto* child_ftn = + FrameTreeNode::GloballyFindByID(prerender_host_id)->child_at(0); + auto* child_navigation = child_ftn->navigation_request(); + ASSERT_NE(child_navigation, nullptr); + EXPECT_TRUE(child_navigation->IsDeferredForTesting()); + + // Allow the activation navigation to complete. + condition.CallResumeClosure(); + activation_observer.WaitForNavigationFinished(); + EXPECT_TRUE(activation_observer.was_prerendered_page_activation()); + + // The iframe navigation should finish. + iframe_nav_observer.WaitForNavigationFinished(); + EXPECT_EQ(ChildFrameAt(prerender_main_frame, 0)->GetLastCommittedURL(), + kCrossOriginUrl); +} + +// Tests WebContents::OpenURL to a frame in a prerendered page when a +// navigation that will attempt to activate the page has already started. The +// subframe navigation should succeed. +IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, + OpenURLInSubframeDuringActivation) { const GURL kInitialUrl = GetUrl("/empty.html"); const GURL kPrerenderingUrl = GetUrl("/page_with_blank_iframe.html"); const GURL kNewIframeUrl = GetUrl("/simple_page.html"); @@ -2746,8 +2830,8 @@ ASSERT_TRUE(child_frame); } - // Now navigate the primary page to the prerendered URL so that we activate - // the prerender. + // Start an activation navigation for the prerender. Use a + // CommitDeferringCondition to pause activation before it completes. test::PrerenderHostObserver prerender_observer(*web_contents(), kPrerenderingUrl); TestNavigationManager activation_observer(shell()->web_contents(), @@ -2760,11 +2844,14 @@ // Wait for the condition to pause the activation. condition.WaitUntilInvoked(); + NavigationRequest* request = + web_contents_impl()->GetFrameTree()->root()->navigation_request(); + EXPECT_TRUE(request->IsCommitDeferringConditionDeferredForTesting()); EXPECT_EQ(web_contents()->GetURL(), kInitialUrl); } - // Use the OpenURL API to navigate the iframe in the reserved prerendering - // frame tree. This navigation should succeed. + // Use the OpenURL API to navigate the iframe in the prerendering frame tree. + // This navigation should succeed. { TestNavigationManager iframe_observer(shell()->web_contents(), kNewIframeUrl); @@ -2776,12 +2863,10 @@ EXPECT_EQ(child_frame->GetLastCommittedURL(), kNewIframeUrl); } - // Allow the navigation to complete to activation, the iframe navigation - // should be able to finish. Ensure the navigation completes in the iframe. - { - condition.CallResumeClosure(); - prerender_observer.WaitForActivation(); - } + // Allow the activation navigation to complete. + condition.CallResumeClosure(); + activation_observer.WaitForNavigationFinished(); + EXPECT_TRUE(activation_observer.was_prerendered_page_activation()); } class ScopedDataSaverTestContentBrowserClient
diff --git a/content/browser/prerender/prerender_host_unittest.cc b/content/browser/prerender/prerender_host_unittest.cc index f52dfe7..8469c270 100644 --- a/content/browser/prerender/prerender_host_unittest.cc +++ b/content/browser/prerender/prerender_host_unittest.cc
@@ -244,73 +244,6 @@ kPrerenderingUrl); } -// Tests that cross-origin subframe navigations in a prerendered page are -// deferred even if they start after the prerendered page has been reserved for -// activation. -// -// Regression test for https://crbug.com/1190262. -TEST_F(PrerenderHostTest, SubframeNavigationForReservedHost) { - const GURL kOriginUrl("https://example.com/"); - std::unique_ptr<TestWebContents> web_contents = CreateWebContents(kOriginUrl); - RenderFrameHostImpl* initiator_rfh = web_contents->GetMainFrame(); - PrerenderHostRegistry* registry = web_contents->GetPrerenderHostRegistry(); - - // Start prerendering a page. - const GURL kPrerenderingUrl("https://example.com/next"); - RenderFrameHostImpl* prerender_rfh = - web_contents->AddPrerenderAndCommitNavigation(kPrerenderingUrl); - const int prerender_ftn_id = prerender_rfh->GetFrameTreeNodeId(); - PrerenderHost* prerender_host = - registry->FindNonReservedHostById(prerender_ftn_id); - - ActivationObserver activation_observer; - prerender_host->AddObserver(&activation_observer); - - // Now navigate the primary page to the prerendered URL so that we activate - // the prerender. Use a CommitDeferringCondition to pause activation - // before it completes. - std::unique_ptr<NavigationSimulatorImpl> navigation; - MockCommitDeferringConditionWrapper condition(/*is_ready_to_commit=*/false); - { - MockCommitDeferringConditionInstaller installer(condition.PassToDelegate()); - - // Start trying to activate the prerendered page. - navigation = NavigationSimulatorImpl::CreateRendererInitiated( - kPrerenderingUrl, initiator_rfh); - navigation->Start(); - - // Wait for the condition to pause the activation. - condition.WaitUntilInvoked(); - } - - // The primary page should still be the original page. - EXPECT_EQ(web_contents->GetURL(), kOriginUrl); - - // Start a cross-origin subframe navigation in the prerendered page. It - // should be deferred. - RenderFrameHost* subframe = - RenderFrameHostTester::For(prerender_rfh)->AppendChild("subframe"); - std::unique_ptr<NavigationSimulatorImpl> subframe_nav_sim = - NavigationSimulatorImpl::CreateRendererInitiated( - GURL("https://example2.test/"), subframe); - subframe_nav_sim->SetAutoAdvance(false); - subframe_nav_sim->Start(); - EXPECT_TRUE(subframe_nav_sim->IsDeferred()); - - // Resume the activation. - condition.CallResumeClosure(); - activation_observer.WaitUntilHostDestroyed(); - EXPECT_TRUE(activation_observer.was_activated()); - EXPECT_EQ(registry->FindHostByUrlForTesting(kPrerenderingUrl), nullptr); - ExpectFinalStatus(PrerenderHost::FinalStatus::kActivated); - EXPECT_EQ(web_contents->GetMainFrame()->GetLastCommittedURL(), - kPrerenderingUrl); - - // The subframe navigation should no longer be deferred. - subframe_nav_sim->Wait(); - EXPECT_FALSE(subframe_nav_sim->IsDeferred()); -} - // Tests that an activation can successfully commit after the prerendering page // has updated its PageState. TEST_F(PrerenderHostTest, ActivationAfterPageStateUpdate) {
diff --git a/content/browser/prerender/prerender_subframe_navigation_throttle.cc b/content/browser/prerender/prerender_subframe_navigation_throttle.cc index eae9185..fd5f7e35 100644 --- a/content/browser/prerender/prerender_subframe_navigation_throttle.cc +++ b/content/browser/prerender/prerender_subframe_navigation_throttle.cc
@@ -34,8 +34,13 @@ } PrerenderSubframeNavigationThrottle::PrerenderSubframeNavigationThrottle( - NavigationHandle* navigation_handle) - : NavigationThrottle(navigation_handle) {} + NavigationHandle* nav_handle) + : NavigationThrottle(nav_handle), + prerender_root_ftn_id_(NavigationRequest::From(nav_handle) + ->frame_tree_node() + ->frame_tree() + ->root() + ->frame_tree_node_id()) {} PrerenderSubframeNavigationThrottle::~PrerenderSubframeNavigationThrottle() = default; @@ -79,11 +84,46 @@ ->frame_tree_node() ->frame_tree() ->is_prerendering()); - if (is_deferred_) { - is_deferred_ = false; - // May delete `this`. - Resume(); - } + // OnActivated() is called right before activation navigation commit which is + // a little early. We want to resume the subframe navigation after the + // PageBroadcast ActivatePrerenderedPage IPC is sent, to + // guarantee that the new document starts in the non-prerendered state and + // does not get a prerenderingchange event. + // + // Listen to the WebContents to wait for the activation navigation to finish + // before resuming the subframe navigation. + Observe(navigation_handle()->GetWebContents()); +} + +// Use DidFinishNavigation() rather than PrimaryPageChanged() in order to +// Resume() after the PageBroadcast Activate IPC is sent, which happens a +// little after PrimaryPageChanged() and before DidFinishNavigation(). This +// guarantees the new document starts in non-prerendered state. +void PrerenderSubframeNavigationThrottle::DidFinishNavigation( + NavigationHandle* nav_handle) { + // Ignore finished navigations that are not the activation navigation for the + // prerendering frame tree that this subframe navigation started in. + auto* finished_navigation = NavigationRequest::From(nav_handle); + if (finished_navigation->prerender_frame_tree_node_id() != + prerender_root_ftn_id_) + return; + + // If the finished navigation did not commit, do not Resume(). We expect that + // the prerendered page and therefore the subframe navigation will eventually + // be cancelled. + if (!finished_navigation->HasCommitted()) + return; + + // The activation is finished. There is no need to listen to the WebContents + // anymore. + Observe(nullptr); + + // Resume the subframe navigation. + if (!is_deferred_) + return; + is_deferred_ = false; + Resume(); + // Resume() may have deleted `this`. } void PrerenderSubframeNavigationThrottle::OnHostDestroyed() { @@ -114,12 +154,12 @@ PrerenderHostRegistry* registry = frame_tree_node->current_frame_host() ->delegate() ->GetPrerenderHostRegistry(); - int id = frame_tree_node->frame_tree()->GetMainFrame()->GetFrameTreeNodeId(); - PrerenderHost* prerender_host = registry->FindNonReservedHostById(id); + PrerenderHost* prerender_host = + registry->FindNonReservedHostById(prerender_root_ftn_id_); if (!prerender_host) { // The host might be reserved already for activation. In either case, we // defer until activation for simplicity. - prerender_host = registry->FindReservedHostById(id); + prerender_host = registry->FindReservedHostById(prerender_root_ftn_id_); } DCHECK(prerender_host);
diff --git a/content/browser/prerender/prerender_subframe_navigation_throttle.h b/content/browser/prerender/prerender_subframe_navigation_throttle.h index 4eed6d7..a507ab5 100644 --- a/content/browser/prerender/prerender_subframe_navigation_throttle.h +++ b/content/browser/prerender/prerender_subframe_navigation_throttle.h
@@ -14,7 +14,8 @@ // PrerenderSubframeNavigationThrottle defers cross-origin subframe loading // during the main frame is in a prerendered state. class PrerenderSubframeNavigationThrottle : public NavigationThrottle, - public PrerenderHost::Observer { + public PrerenderHost::Observer, + public WebContentsObserver { public: ~PrerenderSubframeNavigationThrottle() override; @@ -35,9 +36,13 @@ void OnActivated() override; void OnHostDestroyed() override; + // WebContentsObserver: + void DidFinishNavigation(NavigationHandle* nav_handle) override; + ThrottleCheckResult WillStartOrRedirectRequest(); bool is_deferred_ = false; + const int prerender_root_ftn_id_; base::ScopedObservation<PrerenderHost, PrerenderHost::Observer> observation_{ this}; };
diff --git a/content/browser/renderer_host/input/touch_selection_controller_client_aura_browsertest.cc b/content/browser/renderer_host/input/touch_selection_controller_client_aura_browsertest.cc index cb22853..4c6b0c47 100644 --- a/content/browser/renderer_host/input/touch_selection_controller_client_aura_browsertest.cc +++ b/content/browser/renderer_host/input/touch_selection_controller_client_aura_browsertest.cc
@@ -391,9 +391,8 @@ TouchSelectionControllerClientAuraSiteIsolationTest, testing::Bool()); -// TODO(crbug.com/1225345): Re-enable this test. IN_PROC_BROWSER_TEST_P(TouchSelectionControllerClientAuraSiteIsolationTest, - DISABLED_BasicSelectionIsolatedIframe) { + BasicSelectionIsolatedIframe) { GURL test_url(embedded_test_server()->GetURL( "a.com", "/cross_site_iframe_factory.html?a(a)")); EXPECT_TRUE(NavigateToURL(shell(), test_url));
diff --git a/content/browser/renderer_host/navigation_controller_impl.cc b/content/browser/renderer_host/navigation_controller_impl.cc index e04121dc..abaecb5 100644 --- a/content/browser/renderer_host/navigation_controller_impl.cc +++ b/content/browser/renderer_host/navigation_controller_impl.cc
@@ -3518,7 +3518,6 @@ std::string(), /* data_url_as_string */ #endif !params.is_renderer_initiated, /* is_browser_initiated */ - node->frame_tree()->is_prerendering() /* is_prerendering */, GURL() /* web_bundle_physical_url */, GURL() /* base_url_override_for_web_bundle */, ukm::kInvalidSourceId /* document_ukm_source_id */,
diff --git a/content/browser/renderer_host/navigation_controller_impl_unittest.cc b/content/browser/renderer_host/navigation_controller_impl_unittest.cc index 8d6b4fb..2587268 100644 --- a/content/browser/renderer_host/navigation_controller_impl_unittest.cc +++ b/content/browser/renderer_host/navigation_controller_impl_unittest.cc
@@ -107,6 +107,7 @@ SetPageLifecycleStateCallback callback), (override)); MOCK_METHOD(void, AudioStateChanged, (bool is_audio_playing), (override)); + MOCK_METHOD(void, ActivatePrerenderedPage, (), (override)); MOCK_METHOD(void, SetInsidePortal, (bool is_inside_portal), (override)); MOCK_METHOD(void, UpdateWebPreferences,
diff --git a/content/browser/renderer_host/navigation_entry_impl.cc b/content/browser/renderer_host/navigation_entry_impl.cc index 2085d77..8bd384f 100644 --- a/content/browser/renderer_host/navigation_entry_impl.cc +++ b/content/browser/renderer_host/navigation_entry_impl.cc
@@ -872,7 +872,7 @@ #if defined(OS_ANDROID) std::string(), #endif - false /* is_browser_initiated */, false /* is_prerendering */, + false /* is_browser_initiated */, GURL() /* web_bundle_physical_url */, GURL() /* base_url_override_for_web_bundle */, ukm::kInvalidSourceId /* document_ukm_source_id */, frame_policy,
diff --git a/content/browser/renderer_host/navigation_request.cc b/content/browser/renderer_host/navigation_request.cc index 4656725d..1ac8ecb 100644 --- a/content/browser/renderer_host/navigation_request.cc +++ b/content/browser/renderer_host/navigation_request.cc
@@ -1009,7 +1009,6 @@ /*data_url_as_string=*/std::string(), #endif /*is_browser_initiated=*/false, - frame_tree_node->frame_tree()->is_prerendering(), /*web_bundle_physical_url=*/GURL(), /*base_url_override_for_web_bundle=*/GURL(), /*document_ukm_source_id=*/ukm::kInvalidSourceId, @@ -1132,7 +1131,6 @@ std::string() /* data_url_as_string */, #endif false /* is_browser_initiated */, - frame_tree_node->frame_tree()->is_prerendering(), GURL() /* web_bundle_physical_url */, GURL() /* base_url_override_for_web_bundle */, ukm::kInvalidSourceId /* document_ukm_source_id */, @@ -3965,16 +3963,6 @@ redirect_chain_.clear(); redirect_chain_.push_back(GetURL()); - // Set `is_prerendering` here so it's accurate before sending it to the - // renderer, as it may be out of sync with the source of truth which is the - // frame tree state. The frame tree may have changed if activation happened - // while this navigation is occurring in an iframe. - // TODO(crbug.com/1189481): With MPArch, the NavigationRequest should be - // notified when it transfers frame trees, and commit_params should be updated - // then. - commit_params_->is_prerendering = - frame_tree_node_->frame_tree()->is_prerendering(); - ReadyToCommitNavigation(true /* is_error */); // Use a separate cache shard, and no cookies, for error pages. @@ -4145,16 +4133,6 @@ } } - // Set `is_prerendering` here so it's accurate before sending it to the - // renderer, as it may be out of sync with the source of truth which is the - // frame tree state. The frame tree may have changed if activation happened - // while this navigation is occurring in an iframe. - // TODO(crbug.com/1189481): With MPArch, the NavigationRequest should be - // notified when it transfers frame trees, and commit_params should be updated - // then. - commit_params_->is_prerendering = - frame_tree_node_->frame_tree()->is_prerendering(); - if (!IsSameDocument()) GetNavigationController()->PopulateAppHistoryEntryVectors(this);
diff --git a/content/browser/renderer_host/render_frame_host_manager.cc b/content/browser/renderer_host/render_frame_host_manager.cc index 64ff190d..c456305 100644 --- a/content/browser/renderer_host/render_frame_host_manager.cc +++ b/content/browser/renderer_host/render_frame_host_manager.cc
@@ -3292,6 +3292,9 @@ } else { DCHECK_EQ(prev_state, RenderFrameHostImpl::LifecycleStateImpl::kPrerendering); + for (RenderViewHostImpl* rvh : render_view_hosts_to_restore) { + rvh->ActivatePrerenderedPage(); + } current_frame_host()->ActivateForPrerendering(); } }
diff --git a/content/browser/renderer_host/render_view_host_impl.cc b/content/browser/renderer_host/render_view_host_impl.cc index 454a3f15..ce54ce5 100644 --- a/content/browser/renderer_host/render_view_host_impl.cc +++ b/content/browser/renderer_host/render_view_host_impl.cc
@@ -429,6 +429,8 @@ params->replication_state = frame_tree_node->current_replication_state().Clone(); params->devtools_main_frame_token = frame_tree_node->devtools_frame_token(); + DCHECK_EQ(frame_tree_node->frame_tree(), frame_tree_); + params->is_prerendering = frame_tree_->is_prerendering(); if (main_rfh) { auto local_frame_params = mojom::CreateLocalMainFrameParams::New(); @@ -558,6 +560,15 @@ is_in_back_forward_cache_, std::move(page_restore_params)); } +void RenderViewHostImpl::ActivatePrerenderedPage() { + // Null in some unit tests that use TestRenderViewHost. + // TODO(falken): Bind this in tests. + if (!page_broadcast_) + return; + + page_broadcast_->ActivatePrerenderedPage(); +} + void RenderViewHostImpl::SetFrameTreeVisibility( blink::mojom::PageVisibilityState visibility) { page_lifecycle_state_manager_->SetFrameTreeVisibility(visibility);
diff --git a/content/browser/renderer_host/render_view_host_impl.h b/content/browser/renderer_host/render_view_host_impl.h index fc0290b..43fb371 100644 --- a/content/browser/renderer_host/render_view_host_impl.h +++ b/content/browser/renderer_host/render_view_host_impl.h
@@ -240,6 +240,8 @@ bool is_in_back_forward_cache() const { return is_in_back_forward_cache_; } + void ActivatePrerenderedPage(); + void SetFrameTreeVisibility(blink::mojom::PageVisibilityState visibility); void SetIsFrozen(bool frozen);
diff --git a/content/browser/webauth/authenticator_impl_unittest.cc b/content/browser/webauth/authenticator_impl_unittest.cc index 715bc1f..48e5096 100644 --- a/content/browser/webauth/authenticator_impl_unittest.cc +++ b/content/browser/webauth/authenticator_impl_unittest.cc
@@ -5154,6 +5154,62 @@ AuthenticatorStatus::CREDENTIAL_EXCLUDED); } +TEST_F(PINAuthenticatorImplTest, RemoveSecondAuthenticator) { + // Create two PIN-capable devices. Touch one of them to trigger a prompt for + // a PIN. Remove the other. Don't crash. + base::RepeatingCallback<void(bool)> disconnect_1, disconnect_2; + + device::test::MultipleVirtualFidoDeviceFactory::DeviceDetails device_1; + device_1.state->pin = kTestPIN; + device_1.config.pin_support = true; + std::tie(disconnect_1, device_1.disconnect_events) = + device::FidoDeviceDiscovery::EventStream<bool>::New(); + + device::test::MultipleVirtualFidoDeviceFactory::DeviceDetails device_2; + device_2.state->pin = kTestPIN; + device_2.config.pin_support = true; + std::tie(disconnect_2, device_2.disconnect_events) = + device::FidoDeviceDiscovery::EventStream<bool>::New(); + + int callbacks = 0; + auto touch_callback = [&](int device_num) -> bool { + callbacks++; + if (callbacks == 1) { + // Wait for the other authenticator to be triggered. + return false; + } else if (callbacks == 2) { + // Touch authenticator to collect a PIN. + return true; + } else { + CHECK_EQ(callbacks, 3); + + // Disconnect other authenticator then complete with a touch. + if (device_num == 1) { + disconnect_2.Run(false); + } else { + disconnect_1.Run(false); + } + return true; + } + }; + + device_1.state->simulate_press_callback = base::BindLambdaForTesting( + [&](VirtualFidoDevice* _) -> bool { return touch_callback(1); }); + device_2.state->simulate_press_callback = base::BindLambdaForTesting( + [&](VirtualFidoDevice* _) -> bool { return touch_callback(2); }); + + auto discovery = + std::make_unique<device::test::MultipleVirtualFidoDeviceFactory>(); + discovery->AddDevice(std::move(device_1)); + discovery->AddDevice(std::move(device_2)); + AuthenticatorEnvironmentImpl::GetInstance() + ->ReplaceDefaultDiscoveryFactoryForTesting(std::move(discovery)); + + test_client_.expected = { + {PINReason::kChallenge, kTestPIN16, device::kMaxPinRetries}}; + EXPECT_EQ(AuthenticatorMakeCredential().status, AuthenticatorStatus::SUCCESS); +} + class InternalUVAuthenticatorImplTest : public UVAuthenticatorImplTest { public: struct TestCase {
diff --git a/content/common/content_switches_internal.cc b/content/common/content_switches_internal.cc index 7cd1e042..eb544f2 100644 --- a/content/common/content_switches_internal.cc +++ b/content/common/content_switches_internal.cc
@@ -32,6 +32,8 @@ #if defined(OS_WIN) #include "base/win/windows_version.h" + +#include <windows.h> #endif namespace content {
diff --git a/content/common/frame.mojom b/content/common/frame.mojom index be6f44b6..192a508 100644 --- a/content/common/frame.mojom +++ b/content/common/frame.mojom
@@ -109,6 +109,9 @@ // Whether the RenderView should initially be hidden. bool hidden; + // Prerender2: Whether the RenderView is for a prerendered page. + bool is_prerendering; + // When true, all RenderWidgets under this RenderView will never be shown to // the user, and thus never composited, and will not need to produce pixels // for display. This allows the renderer to optimize and avoid resources used
diff --git a/content/public/android/java/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityImpl.java b/content/public/android/java/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityImpl.java index a6abeed..4da7e35d 100644 --- a/content/public/android/java/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityImpl.java +++ b/content/public/android/java/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityImpl.java
@@ -1254,7 +1254,6 @@ // The container view is indicated by a virtualViewId of NO_ID; post these events directly // since there's no web-specific information to attach. if (virtualViewId == View.NO_ID) { - if (mTracker != null) mTracker.addEvent(AccessibilityEvent.obtain(eventType)); mView.sendAccessibilityEvent(eventType); return; }
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityTest.java b/content/public/android/javatests/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityTest.java index ee62384c..4428f37 100644 --- a/content/public/android/javatests/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityTest.java +++ b/content/public/android/javatests/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityTest.java
@@ -100,7 +100,7 @@ "Conversion of event masks to event types not correct."; // Constant values for unit tests - private static final int UNSUPPRESSED_EXPECTED_COUNT = 25; + private static final int UNSUPPRESSED_EXPECTED_COUNT = 15; private AccessibilityNodeInfo mNodeInfo; private AccessibilityContentShellTestData mTestData; @@ -343,7 +343,6 @@ * Ensure we throttle TYPE_WINDOW_CONTENT_CHANGED events for large tree updates. */ @Test - @FlakyTest(message = "https://crbug.com/1161533") @SmallTest public void testMaxContentChangedEventsFired_default() throws Throwable { // Build a simple web page with complex visibility change. @@ -358,16 +357,15 @@ // Signal end of test mActivityTestRule.sendEndOfTestSignal(); - // Verify number of events processed + // Verify number of events processed, allow for multiple atomic updates. int eventCount = mTestData.getTypeWindowContentChangedCount(); - Assert.assertTrue(thresholdError(eventCount, maxEvents), eventCount <= maxEvents); + Assert.assertTrue(thresholdError(eventCount, maxEvents), eventCount <= (maxEvents * 3)); } /** * Ensure we need to throttle TYPE_WINDOW_CONTENT_CHANGED events for some large tree updates. */ @Test - @FlakyTest(message = "https://crbug.com/1161533") @SmallTest public void testMaxContentChangedEventsFired_largeLimit() throws Throwable { // Build a simple web page with complex visibility change.
diff --git a/content/public/browser/web_contents_receiver_set.h b/content/public/browser/web_contents_receiver_set.h index c373078..8b2ded14 100644 --- a/content/public/browser/web_contents_receiver_set.h +++ b/content/public/browser/web_contents_receiver_set.h
@@ -55,9 +55,6 @@ namespace subresource_redirect { class SubresourceRedirectObserver; } -namespace subresource_filter { -class ContentSubresourceFilterThrottleManager; -} namespace content { @@ -142,7 +139,6 @@ friend class ::pdf::PDFWebContentsHelper; friend class ::printing::PrintManager; friend class ::security_interstitials::SecurityInterstitialTabHelper; - friend class ::subresource_filter::ContentSubresourceFilterThrottleManager; friend class ::subresource_redirect::SubresourceRedirectObserver; friend class ConversionHost; friend class DisplayCutoutHostImpl;
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc index 50973ec..21a03f22 100644 --- a/content/renderer/render_frame_impl.cc +++ b/content/renderer/render_frame_impl.cc
@@ -1017,7 +1017,6 @@ common_params.text_fragment_token; navigation_params->is_browser_initiated = commit_params.is_browser_initiated; - navigation_params->is_prerendering = commit_params.is_prerendering; navigation_params->is_cross_site_cross_browsing_context_group = commit_params.is_cross_site_cross_browsing_context_group;
diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc index 95ab5d2..d372704 100644 --- a/content/renderer/render_thread_impl.cc +++ b/content/renderer/render_thread_impl.cc
@@ -100,6 +100,7 @@ #include "gpu/command_buffer/client/gles2_interface.h" #include "gpu/command_buffer/client/raster_interface.h" #include "gpu/command_buffer/client/shared_memory_limits.h" +#include "gpu/config/gpu_driver_bug_workarounds.h" #include "gpu/config/gpu_finch_features.h" #include "gpu/config/gpu_switches.h" #include "gpu/ipc/client/command_buffer_proxy_impl.h" @@ -1173,6 +1174,8 @@ gpu_channel_host->gpu_feature_info() .status_values[gpu::GPU_FEATURE_TYPE_OOP_RASTERIZATION] == gpu::kGpuFeatureStatusEnabled && + !gpu_channel_host->gpu_feature_info().IsWorkaroundEnabled( + gpu::DISABLE_CANVAS_OOP_RASTERIZATION) && base::FeatureList::IsEnabled(features::kCanvasOopRasterization); bool support_gles2_interface = false; bool support_grcontext = !support_oop_rasterization;
diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc index 47c22b0..30882aa 100644 --- a/content/renderer/render_view_impl.cc +++ b/content/renderer/render_view_impl.cc
@@ -115,7 +115,7 @@ // The newly created webview_ is owned by this instance. webview_ = WebView::Create( - this, params->hidden, + this, params->hidden, params->is_prerendering, params->type == mojom::ViewWidgetType::kPortal ? true : false, /*compositing_enabled=*/true, params->never_composited, opener_frame ? opener_frame->View() : nullptr,
diff --git a/content/renderer/renderer_blink_platform_impl.cc b/content/renderer/renderer_blink_platform_impl.cc index cb70283b..2ca27e1 100644 --- a/content/renderer/renderer_blink_platform_impl.cc +++ b/content/renderer/renderer_blink_platform_impl.cc
@@ -58,6 +58,7 @@ #include "content/renderer/worker/worker_thread_registry.h" #include "device/gamepad/public/cpp/gamepads.h" #include "gpu/command_buffer/client/gles2_interface.h" +#include "gpu/config/gpu_driver_bug_workarounds.h" #include "gpu/config/gpu_finch_features.h" #include "gpu/config/gpu_info.h" #include "gpu/ipc/client/gpu_channel_host.h" @@ -812,6 +813,8 @@ gpu_channel_host->gpu_feature_info() .status_values[gpu::GPU_FEATURE_TYPE_OOP_RASTERIZATION] == gpu::kGpuFeatureStatusEnabled && + !gpu_channel_host->gpu_feature_info().IsWorkaroundEnabled( + gpu::DISABLE_CANVAS_OOP_RASTERIZATION) && base::FeatureList::IsEnabled(features::kCanvasOopRasterization); attributes.enable_gles2_interface = !attributes.enable_oop_rasterization;
diff --git a/content/shell/browser/shell_devtools_bindings.cc b/content/shell/browser/shell_devtools_bindings.cc index 8ab931c..c08ee7e05 100644 --- a/content/shell/browser/shell_devtools_bindings.cc +++ b/content/shell/browser/shell_devtools_bindings.cc
@@ -264,35 +264,39 @@ void ShellDevToolsBindings::HandleMessageFromDevToolsFrontend( base::Value message) { - std::string method; - base::ListValue* params = nullptr; - base::DictionaryValue* dict = nullptr; - if (!message.GetAsDictionary(&dict) || !dict->GetString("method", &method)) { + if (!message.is_dict()) return; - } - int request_id = 0; - dict->GetInteger("id", &request_id); - dict->GetList("params", ¶ms); + const std::string* method = message.FindStringKey("method"); + if (!method) + return; - if (method == "dispatchProtocolMessage" && params && params->GetSize() == 1) { - std::string protocol_message; - if (!agent_host_ || !params->GetString(0, &protocol_message)) + int request_id = message.FindIntKey("id").value_or(0); + base::Value* params_value = message.FindListKey("params"); + + // Since we've received message by value, we can take the list. + base::Value::ListStorage params; + if (params_value) { + params = std::move(*params_value).TakeList(); + } + + if (*method == "dispatchProtocolMessage" && params.size() == 1) { + const std::string* protocol_message = params[0].GetIfString(); + if (!agent_host_ || !protocol_message) return; agent_host_->DispatchProtocolMessage( - this, base::as_bytes(base::make_span(protocol_message))); - } else if (method == "loadCompleted") { + this, base::as_bytes(base::make_span(*protocol_message))); + } else if (*method == "loadCompleted") { CallClientFunction("DevToolsAPI", "setUseSoftMenu", base::Value(true)); - } else if (method == "loadNetworkResource" && params->GetSize() == 3) { + } else if (*method == "loadNetworkResource" && params.size() == 3) { // TODO(pfeldman): handle some of the embedder messages in content. - std::string url; - std::string headers; - int stream_id; - if (!params->GetString(0, &url) || !params->GetString(1, &headers) || - !params->GetInteger(2, &stream_id)) { + const std::string* url = params[0].GetIfString(); + const std::string* headers = params[1].GetIfString(); + absl::optional<const int> stream_id = params[2].GetIfInt(); + if (!url || !headers || !stream_id.has_value()) { return; } - GURL gurl(url); + GURL gurl(*url); if (!gurl.is_valid()) { base::DictionaryValue response; response.SetInteger("statusCode", 404); @@ -332,7 +336,7 @@ // TODO(caseq): this preserves behavior of URLFetcher-based implementation. // We really need to pass proper first party origin from the front-end. resource_request->site_for_cookies = net::SiteForCookies::FromUrl(gurl); - resource_request->headers.AddHeadersFromString(headers); + resource_request->headers.AddHeadersFromString(*headers); auto* partition = web_contents()->GetBrowserContext()->GetStoragePartitionForUrl(gurl); @@ -341,39 +345,45 @@ auto simple_url_loader = network::SimpleURLLoader::Create( std::move(resource_request), traffic_annotation); auto resource_loader = std::make_unique<NetworkResourceLoader>( - stream_id, request_id, this, std::move(simple_url_loader), + *stream_id, request_id, this, std::move(simple_url_loader), factory.get()); loaders_.insert(std::move(resource_loader)); return; - } else if (method == "getPreferences") { + } else if (*method == "getPreferences") { SendMessageAck(request_id, std::move(preferences_)); return; - } else if (method == "setPreference") { - std::string name; - std::string value; - if (!params->GetString(0, &name) || !params->GetString(1, &value)) { + } else if (*method == "setPreference") { + if (params.size() < 2) return; - } - preferences_.SetKey(name, base::Value(value)); - } else if (method == "removePreference") { - std::string name; - if (!params->GetString(0, &name)) + const std::string* name = params[0].GetIfString(); + + // We're just setting params[1] as a value anyways, so just make sure it's + // the type we want, but don't worry about getting it. + if (!name || !params[1].is_string()) return; - preferences_.RemoveKey(name); - } else if (method == "requestFileSystems") { + + preferences_.SetKey(*name, std::move(params[1])); + } else if (*method == "removePreference") { + const std::string* name = params[0].GetIfString(); + if (!name) + return; + preferences_.RemoveKey(*name); + } else if (*method == "requestFileSystems") { CallClientFunction("DevToolsAPI", "fileSystemsLoaded", base::Value(base::Value::Type::LIST)); - } else if (method == "reattach") { + } else if (*method == "reattach") { if (!agent_host_) return; agent_host_->DetachClient(this); agent_host_->AttachClient(this); - } else if (method == "registerExtensionsAPI") { - std::string origin; - std::string script; - if (!params->GetString(0, &origin) || !params->GetString(1, &script)) + } else if (*method == "registerExtensionsAPI") { + if (params.size() < 2) return; - extensions_api_[origin + "/"] = script; + const std::string* origin = params[0].GetIfString(); + const std::string* script = params[1].GetIfString(); + if (!origin || !script) + return; + extensions_api_[*origin + "/"] = *script; } else { return; }
diff --git a/content/test/data/gpu/webcodecs/encode.html b/content/test/data/gpu/webcodecs/encode.html index 56c6701..98de7635 100644 --- a/content/test/data/gpu/webcodecs/encode.html +++ b/content/test/data/gpu/webcodecs/encode.html
@@ -13,6 +13,8 @@ <script type="text/javascript"> 'use strict'; async function main(arg) { + // Use 16x16 aligned resolution since some platforms require that. + // See https://crbug.com/1084702. const width = 640; const height = 480; const frames_in_one_pass = 15; @@ -66,9 +68,10 @@ TEST.log('First pass completed'); - // Reconfigure on-the-fly - encoder_config.width += 100; - encoder_config.height += 100; + // Reconfigure on-the-fly. Use 16x16 aligned resolution since some + // platforms require that. See https://crbug.com/1084702. + encoder_config.width += 128; + encoder_config.height += 128; encoder_config.bitrate += encoder_config.bitrate / 2; encoder.configure(encoder_config); @@ -98,4 +101,4 @@ <body> </body> -</html> \ No newline at end of file +</html>
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 4a06ed9..b93d7e87 100644 --- a/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt +++ b/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt
@@ -351,6 +351,9 @@ crbug.com/1170369 [ linux skia-renderer-dawn ] Pixel_WebGLPreservedAfterTabSwitch [ Failure ] crbug.com/1170369 [ win skia-renderer-dawn ] Pixel_WebGLPreservedAfterTabSwitch [ Failure ] +# Failure of dawn_pixel_skia_gold_test on win dawn +crbug.com/1228694 [ win skia-renderer-dawn ] Pixel_CSS3DBlueBox [ Failure ] + # Flakes on Linux SkiaRenderer Dawn. crbug.com/1200898 [ linux skia-renderer-dawn ] Pixel_BackgroundImage [ RetryOnFailure ]
diff --git a/content/test/mock_commit_deferring_condition.cc b/content/test/mock_commit_deferring_condition.cc index cfae5f1c..6297469 100644 --- a/content/test/mock_commit_deferring_condition.cc +++ b/content/test/mock_commit_deferring_condition.cc
@@ -54,8 +54,10 @@ base::OnceClosure resume_closure) { did_call_will_commit_navigation_ = true; resume_closure_ = std::move(resume_closure); - if (invoked_closure_) - std::move(invoked_closure_).Run(); + if (invoked_closure_) { + base::SequencedTaskRunnerHandle::Get()->PostTask( + FROM_HERE, std::move(invoked_closure_)); + } } MockCommitDeferringCondition::MockCommitDeferringCondition(
diff --git a/device/fido/fido_request_handler_base.cc b/device/fido/fido_request_handler_base.cc index 9cdcf33..8046667e 100644 --- a/device/fido/fido_request_handler_base.cc +++ b/device/fido/fido_request_handler_base.cc
@@ -248,9 +248,6 @@ // CancelOngoingTasks(). auto authenticator_it = active_authenticators_.find(authenticator->GetId()); if (authenticator_it == active_authenticators_.end()) { - NOTREACHED(); - FIDO_LOG(ERROR) << "AuthenticatorRemoved() for unknown authenticator " - << authenticator->GetId(); return; } DCHECK_EQ(authenticator_it->second, authenticator);
diff --git a/device/fido/multiple_virtual_fido_device_factory.cc b/device/fido/multiple_virtual_fido_device_factory.cc index 75e5915..afa723b0 100644 --- a/device/fido/multiple_virtual_fido_device_factory.cc +++ b/device/fido/multiple_virtual_fido_device_factory.cc
@@ -32,7 +32,8 @@ continue; } discoveries.push_back(std::make_unique<VirtualFidoDeviceDiscovery>( - device.transport, device.state, device.protocol, device.config)); + device.transport, device.state, device.protocol, device.config, + std::move(device.disconnect_events))); } return discoveries; }
diff --git a/device/fido/multiple_virtual_fido_device_factory.h b/device/fido/multiple_virtual_fido_device_factory.h index dfb8a67..4a995511 100644 --- a/device/fido/multiple_virtual_fido_device_factory.h +++ b/device/fido/multiple_virtual_fido_device_factory.h
@@ -36,6 +36,11 @@ VirtualCtap2Device::Config config; scoped_refptr<VirtualFidoDevice::State> state = base::MakeRefCounted<VirtualFidoDevice::State>(); + // disconnect_events can be emplaced in order to cause the device to be + // disconnected. It is not expected that one would want to disconnect it + // multiple times but that is possible to simulate with this interface. + // The |bool| argument is ignored (void is not a valid template argument). + std::unique_ptr<FidoDeviceDiscovery::EventStream<bool>> disconnect_events; }; MultipleVirtualFidoDeviceFactory();
diff --git a/device/fido/virtual_fido_device_discovery.cc b/device/fido/virtual_fido_device_discovery.cc index 5e99483..a3bd983 100644 --- a/device/fido/virtual_fido_device_discovery.cc +++ b/device/fido/virtual_fido_device_discovery.cc
@@ -18,11 +18,13 @@ FidoTransportProtocol transport, scoped_refptr<VirtualFidoDevice::State> state, ProtocolVersion supported_protocol, - const VirtualCtap2Device::Config& ctap2_config) + const VirtualCtap2Device::Config& ctap2_config, + std::unique_ptr<FidoDeviceDiscovery::EventStream<bool>> disconnect_events) : FidoDeviceDiscovery(transport), state_(std::move(state)), supported_protocol_(supported_protocol), - ctap2_config_(ctap2_config) {} + ctap2_config_(ctap2_config), + disconnect_events_(std::move(disconnect_events)) {} VirtualFidoDeviceDiscovery::~VirtualFidoDeviceDiscovery() = default; void VirtualFidoDeviceDiscovery::StartInternal() { @@ -33,11 +35,25 @@ device = std::make_unique<VirtualU2fDevice>(state_); } + id_ = device->GetId(); AddDevice(std::move(device)); base::SequencedTaskRunnerHandle::Get()->PostTask( FROM_HERE, base::BindOnce(&VirtualFidoDeviceDiscovery::NotifyDiscoveryStarted, AsWeakPtr(), true /* success */)); + + if (disconnect_events_) { + // |disconnect_events_| is owned by this object therefore, when this object + // is destroyed, no more events can be received. Therefore |Unretained| + // works here. + disconnect_events_->Connect(base::BindRepeating( + &VirtualFidoDeviceDiscovery::Disconnect, base::Unretained(this))); + } +} + +void VirtualFidoDeviceDiscovery::Disconnect(bool _) { + CHECK(!id_.empty()); + RemoveDevice(id_); } } // namespace test
diff --git a/device/fido/virtual_fido_device_discovery.h b/device/fido/virtual_fido_device_discovery.h index 782be67..bf46e180 100644 --- a/device/fido/virtual_fido_device_discovery.h +++ b/device/fido/virtual_fido_device_discovery.h
@@ -18,10 +18,12 @@ : public FidoDeviceDiscovery, public base::SupportsWeakPtr<VirtualFidoDeviceDiscovery> { public: - VirtualFidoDeviceDiscovery(FidoTransportProtocol transport, - scoped_refptr<VirtualFidoDevice::State> state, - ProtocolVersion supported_protocol, - const VirtualCtap2Device::Config& ctap2_config); + VirtualFidoDeviceDiscovery( + FidoTransportProtocol transport, + scoped_refptr<VirtualFidoDevice::State> state, + ProtocolVersion supported_protocol, + const VirtualCtap2Device::Config& ctap2_config, + std::unique_ptr<EventStream<bool>> disconnect_events); ~VirtualFidoDeviceDiscovery() override; VirtualFidoDeviceDiscovery(const VirtualFidoDeviceDiscovery& other) = delete; VirtualFidoDeviceDiscovery& operator=( @@ -31,9 +33,13 @@ void StartInternal() override; private: + void Disconnect(bool _); + scoped_refptr<VirtualFidoDevice::State> state_; const ProtocolVersion supported_protocol_; const VirtualCtap2Device::Config ctap2_config_; + std::unique_ptr<EventStream<bool>> disconnect_events_; + std::string id_; }; } // namespace test
diff --git a/device/fido/virtual_fido_device_factory.cc b/device/fido/virtual_fido_device_factory.cc index bc6d3c0..2c903840 100644 --- a/device/fido/virtual_fido_device_factory.cc +++ b/device/fido/virtual_fido_device_factory.cc
@@ -38,7 +38,8 @@ return {}; } return SingleDiscovery(std::make_unique<VirtualFidoDeviceDiscovery>( - transport_, state_, supported_protocol_, ctap2_config_)); + transport_, state_, supported_protocol_, ctap2_config_, + /*disconnect_events=*/nullptr)); } bool VirtualFidoDeviceFactory::IsTestOverride() {
diff --git a/docs/cl_respect.md b/docs/cl_respect.md index 97af2d82..225af940 100644 --- a/docs/cl_respect.md +++ b/docs/cl_respect.md
@@ -52,7 +52,7 @@ #### Provide context Change descriptions are the first impression your change makes, both on -reviewers and on code archeologists from the future. A [good description](https://www.chromium.org/developers/contributing-code#TOC-Writing-change-list-descriptions) +reviewers and on code archeologists from the future. A [good description](https://chromium.googlesource.com/chromium/src/+/refs/heads/main/docs/contributing.md#Uploading-a-change-for-review) aims to do two things. First, it conveys at a glance the high level view. Second, it provides references to all the relevant information for a deep dive: design docs, bugs, testing instructions. The bug\# is a useful reference, but
diff --git a/docs/vscode.md b/docs/vscode.md index 6c7be97..6ba039d 100644 --- a/docs/vscode.md +++ b/docs/vscode.md
@@ -44,7 +44,7 @@ subject to changes. This doc is checked into the Chromium git repo, so if you make changes, read the [documentation guidelines](https://chromium.googlesource.com/chromium/src/+/main/docs/documentation_guidelines.md) -and [submit a change list](https://www.chromium.org/developers/contributing-code). +and [submit a change list](https://chromium.googlesource.com/chromium/src/+/refs/heads/main/docs/contributing.md). All file paths and commands have been tested on Linux. Windows and Mac might require a slightly different setup (e.g. `Ctrl` -> `Cmd`). Please update this
diff --git a/extensions/browser/content_script_tracker.cc b/extensions/browser/content_script_tracker.cc index 260e78e..33b422cc 100644 --- a/extensions/browser/content_script_tracker.cc +++ b/extensions/browser/content_script_tracker.cc
@@ -44,44 +44,69 @@ // by ReadyToCommit races associated with RenderDocumentHostUserData. // For more information see: // https://docs.google.com/document/d/1MFprp2ss2r9RNamJ7Jxva1bvRZvec3rzGceDGoJ6vW0/edit# -class ContentScriptsSet : public base::SupportsUserData::Data { +class RenderProcessHostUserData : public base::SupportsUserData::Data { public: - static const ExtensionIdSet* Get(const content::RenderProcessHost& process) { + static const RenderProcessHostUserData* Get( + const content::RenderProcessHost& process) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - auto* self = - static_cast<ContentScriptsSet*>(process.GetUserData(kUserDataKey)); - return self ? &self->content_scripts_ : nullptr; + return static_cast<RenderProcessHostUserData*>( + process.GetUserData(kUserDataKey)); } - static ExtensionIdSet& GetOrCreate(content::RenderProcessHost& process) { + static RenderProcessHostUserData& GetOrCreate( + content::RenderProcessHost& process) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - auto* self = - static_cast<ContentScriptsSet*>(process.GetUserData(kUserDataKey)); + auto* self = static_cast<RenderProcessHostUserData*>( + process.GetUserData(kUserDataKey)); if (!self) { - // Create a new ContentScriptsSet if needed. The ownership is passed to - // the `process` (i.e. the new ContentScriptsSet will be destroyed at the - // same time as the `process` - this is why we don't need to purge or - // destroy the set from within ContentScriptTracker). - auto owned_self = base::WrapUnique(new ContentScriptsSet); + // Create a new RenderProcessHostUserData if needed. The ownership is + // passed to the `process` (i.e. the new RenderProcessHostUserData will be + // destroyed at the same time as the `process` - this is why we don't need + // to purge or destroy the set from within ContentScriptTracker). + auto owned_self = base::WrapUnique(new RenderProcessHostUserData); self = owned_self.get(); process.SetUserData(kUserDataKey, std::move(owned_self)); } - return self->content_scripts_; + DCHECK(self); + return *self; } // base::SupportsUserData::Data override: - ~ContentScriptsSet() override = default; + ~RenderProcessHostUserData() override = default; + + bool HasContentScript(const ExtensionId& extension_id) const { + return base::Contains(content_scripts_, extension_id); + } + + void AddContentScript(const ExtensionId& extension_id) { + content_scripts_.insert(extension_id); + } + + void AddFrame(content::RenderFrameHost* frame) { frames_.insert(frame); } + void RemoveFrame(content::RenderFrameHost* frame) { frames_.erase(frame); } + const std::set<content::RenderFrameHost*>& frames() const { return frames_; } private: - ContentScriptsSet() = default; + RenderProcessHostUserData() = default; static const char* kUserDataKey; + + // Set of extensions ids that have *ever* injected a content script into this + // particular renderer process. This is the core data maintained by the + // ContentScriptTracker. ExtensionIdSet content_scripts_; + + // Set of frames that are *currently* hosted in this particular renderer + // process. This is mostly used just to get GetLastCommittedURL of these + // frames so that when a new extension is loaded, then ContentScriptTracker + // can know where content scripts may be injected. + std::set<content::RenderFrameHost*> frames_; }; -const char* ContentScriptsSet::kUserDataKey = "ContentScriptTracker's data"; +const char* RenderProcessHostUserData::kUserDataKey = + "ContentScriptTracker's data"; class RenderFrameHostAdapter : public ContentScriptInjectionUrlGetter::FrameAdapter { @@ -192,15 +217,15 @@ const Extension& extension) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - // Store `extension.id()` in `content_scripts_for_process`. - // ContentScriptTracker never removes entries from this set - once a renderer - // process gains an ability to talk on behalf of a content script, it retains - // this ability forever. Note that the set will be destroyed together with - // the RenderProcessHost (see also a comment inside - // ContentScriptsSet::GetOrCreate). - ExtensionIdSet& content_scripts_for_process = - ContentScriptsSet::GetOrCreate(*frame->GetProcess()); - content_scripts_for_process.insert(extension.id()); + // Store `extension.id()` in `process_data`. ContentScriptTracker never + // removes entries from this set - once a renderer process gains an ability to + // talk on behalf of a content script, it retains this ability forever. Note + // that the `process_data` will be destroyed together with the + // RenderProcessHost (see also a comment inside + // RenderProcessHostUserData::GetOrCreate). + auto& process_data = + RenderProcessHostUserData::GetOrCreate(*frame->GetProcess()); + process_data.AddContentScript(extension.id()); URLLoaderFactoryManager::WillProgrammaticallyInjectContentScript( pass_key, frame, extension); @@ -266,6 +291,28 @@ return extensions_injecting_content_scripts; } +const Extension* FindExtensionByHostId(content::BrowserContext* browser_context, + const mojom::HostID& host_id) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + + switch (host_id.type) { + case mojom::HostID::HostType::kWebUi: + // ContentScriptTracker only tracks extensions. + return nullptr; + case mojom::HostID::HostType::kExtensions: + break; + } + + const ExtensionRegistry* registry = ExtensionRegistry::Get(browser_context); + DCHECK(registry); // WillExecuteCode and WillUpdateContentScriptsInRenderer + // shouldn't happen during shutdown. + + const Extension* extension = + registry->enabled_extensions().GetByID(host_id.id); + + return extension; +} + } // namespace // static @@ -277,11 +324,11 @@ // Check if we've been notified about the content script injection via // ReadyToCommitNavigation or WillExecuteCode methods. - const ExtensionIdSet* extension_id_set = ContentScriptsSet::Get(process); - if (!extension_id_set) + const auto* process_data = RenderProcessHostUserData::Get(process); + if (!process_data) return false; - return base::Contains(*extension_id_set, extension_id); + return process_data->HasContentScript(extension_id); } // static @@ -291,17 +338,18 @@ DCHECK_CURRENTLY_ON(content::BrowserThread::UI); // Store `extensions_injecting_content_scripts` in - // `content_scripts_for_process`. ContentScriptTracker never removes entries + // `process_data`. ContentScriptTracker never removes entries // from this set - once a renderer process gains an ability to talk on behalf - // of a content script, it retains this ability forever. Note that the set + // of a content script, it retains this ability forever. Note that the + // `process_data` // will be destroyed together with the RenderProcessHost (see also a comment - // inside ContentScriptsSet::GetOrCreate). + // inside RenderProcessHostUserData::GetOrCreate). std::vector<const Extension*> extensions_injecting_content_scripts = GetExtensionsInjectingContentScripts(navigation); - ExtensionIdSet& content_scripts_for_process = ContentScriptsSet::GetOrCreate( + auto& process_data = RenderProcessHostUserData::GetOrCreate( *navigation->GetRenderFrameHost()->GetProcess()); for (const Extension* extension : extensions_injecting_content_scripts) - content_scripts_for_process.insert(extension->id()); + process_data.AddContentScript(extension->id()); URLLoaderFactoryManager::WillInjectContentScriptsWhenNavigationCommits( base::PassKey<ContentScriptTracker>(), navigation, @@ -309,6 +357,24 @@ } // static +void ContentScriptTracker::RenderFrameCreated( + base::PassKey<ExtensionWebContentsObserver> pass_key, + content::RenderFrameHost* frame) { + auto& process_data = + RenderProcessHostUserData::GetOrCreate(*frame->GetProcess()); + process_data.AddFrame(frame); +} + +// static +void ContentScriptTracker::RenderFrameDeleted( + base::PassKey<ExtensionWebContentsObserver> pass_key, + content::RenderFrameHost* frame) { + auto& process_data = + RenderProcessHostUserData::GetOrCreate(*frame->GetProcess()); + process_data.RemoveFrame(frame); +} + +// static void ContentScriptTracker::ReadyToCommitNavigationWithGuestViewContentScripts( base::PassKey<WebViewGuest> pass_key, content::WebContents* outer_web_contents, @@ -335,9 +401,8 @@ // navigation. content::RenderProcessHost* inner_process = navigation->GetRenderFrameHost()->GetProcess(); - ExtensionIdSet& content_scripts_for_process = - ContentScriptsSet::GetOrCreate(*inner_process); - content_scripts_for_process.insert(app_id); + auto& process_data = RenderProcessHostUserData::GetOrCreate(*inner_process); + process_data.AddContentScript(app_id); } // static @@ -347,20 +412,10 @@ const mojom::HostID& host_id) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - switch (host_id.type) { - case mojom::HostID::HostType::kWebUi: - // This class only tracks extensions. - return; - case mojom::HostID::HostType::kExtensions: - break; - } - - const ExtensionRegistry* registry = - ExtensionRegistry::Get(frame->GetProcess()->GetBrowserContext()); - DCHECK(registry); // WillExecuteCode shouldn't happen during shutdown. const Extension* extension = - registry->enabled_extensions().GetByID(host_id.id); - DCHECK(extension); // Guaranteed by the caller - see the doc comment. + FindExtensionByHostId(frame->GetProcess()->GetBrowserContext(), host_id); + if (!extension) + return; HandleProgrammaticContentScriptInjection(PassKey(), frame, *extension); } @@ -374,6 +429,29 @@ } // static +void ContentScriptTracker::WillUpdateContentScriptsInRenderer( + base::PassKey<UserScriptLoader> pass_key, + const mojom::HostID& host_id, + content::RenderProcessHost& process) { + const Extension* extension = + FindExtensionByHostId(process.GetBrowserContext(), host_id); + if (!extension) + return; + + auto& process_data = RenderProcessHostUserData::GetOrCreate(process); + const std::set<content::RenderFrameHost*>& frames_in_process = + process_data.frames(); + bool any_frame_matches_content_scripts = + std::any_of(frames_in_process.begin(), frames_in_process.end(), + [extension](content::RenderFrameHost* frame) { + return DoContentScriptsMatch(*extension, frame, + frame->GetLastCommittedURL()); + }); + if (any_frame_matches_content_scripts) + process_data.AddContentScript(extension->id()); +} + +// static bool ContentScriptTracker::DoContentScriptsMatchForTesting( const Extension& extension, content::RenderFrameHost* frame,
diff --git a/extensions/browser/content_script_tracker.h b/extensions/browser/content_script_tracker.h index ef792fb..bf2aa717 100644 --- a/extensions/browser/content_script_tracker.h +++ b/extensions/browser/content_script_tracker.h
@@ -23,6 +23,7 @@ class Extension; class ExtensionWebContentsObserver; +class UserScriptLoader; class RequestContentScript; class ScriptExecutor; class WebViewGuest; @@ -55,12 +56,18 @@ const content::RenderProcessHost& process, const ExtensionId& extension_id); - // Called before a navigation commits. This method will inspect all enabled - // extensions and consult their manifests to check if they might inject - // content scripts into the target of the `navigation`. + // The few methods below are called by ExtensionWebContentsObserver to notify + // ContentScriptTracker about various events. The methods correspond directly + // to methods of content::WebContentsObserver with the same names. static void ReadyToCommitNavigation( base::PassKey<ExtensionWebContentsObserver> pass_key, content::NavigationHandle* navigation); + static void RenderFrameCreated( + base::PassKey<ExtensionWebContentsObserver> pass_key, + content::RenderFrameHost* frame); + static void RenderFrameDeleted( + base::PassKey<ExtensionWebContentsObserver> pass_key, + content::RenderFrameHost* frame); // Called before a navigation commits in a GuestView with a non-empty set of // content scripts to inject into the guest. @@ -83,7 +90,14 @@ // action of the `chrome.declarativeContent` API). static void WillExecuteCode(base::PassKey<RequestContentScript> pass_key, content::RenderFrameHost* frame, - const Extension& extension_id); + const Extension& extension); + + // Called before the given renderer `process` is notified about new content + // scripts. + static void WillUpdateContentScriptsInRenderer( + base::PassKey<UserScriptLoader> pass_key, + const mojom::HostID& host_id, + content::RenderProcessHost& process); private: using PassKey = base::PassKey<ContentScriptTracker>;
diff --git a/extensions/browser/extension_message_filter.cc b/extensions/browser/extension_message_filter.cc index c9aa439..0623261c 100644 --- a/extensions/browser/extension_message_filter.cc +++ b/extensions/browser/extension_message_filter.cc
@@ -101,9 +101,14 @@ return true; case MessagingEndpoint::Type::kTab: - // TODO(https://crbug.com/1212918: Re-enable the enforcement after - // investigating and fixing the root cause of bad message reports coming - // from the end users. + if (source_endpoint.extension_id.has_value() && + !ContentScriptTracker::DidProcessRunContentScriptFromExtension( + process, source_endpoint.extension_id.value())) { + // TODO(https://crbug.com/1212918: Re-enable the enforcement after + // investigating and fixing the root cause of bad message reports coming + // from the end users. + LOG(ERROR) << "EMF_INVALID_EXTENSION_ID_FOR_CONTENT_SCRIPT"; + } return true; } }
diff --git a/extensions/browser/extension_web_contents_observer.cc b/extensions/browser/extension_web_contents_observer.cc index c5ea7a0..a0846eb 100644 --- a/extensions/browser/extension_web_contents_observer.cc +++ b/extensions/browser/extension_web_contents_observer.cc
@@ -5,7 +5,6 @@ #include "extensions/browser/extension_web_contents_observer.h" #include "base/check.h" -#include "base/types/pass_key.h" #include "content/public/browser/child_process_security_policy.h" #include "content/public/browser/navigation_handle.h" #include "content/public/browser/render_frame_host.h" @@ -119,6 +118,7 @@ content::RenderFrameHost* render_frame_host) { DCHECK(initialized_); InitializeRenderFrame(render_frame_host); + ContentScriptTracker::RenderFrameCreated(PassKey(), render_frame_host); const Extension* extension = GetExtensionFromFrame(render_frame_host, false); if (!extension) @@ -166,12 +166,12 @@ ProcessManager::Get(browser_context_) ->UnregisterRenderFrameHost(render_frame_host); ExtensionApiFrameIdMap::Get()->OnRenderFrameDeleted(render_frame_host); + ContentScriptTracker::RenderFrameDeleted(PassKey(), render_frame_host); } void ExtensionWebContentsObserver::ReadyToCommitNavigation( content::NavigationHandle* navigation_handle) { - ContentScriptTracker::ReadyToCommitNavigation( - base::PassKey<ExtensionWebContentsObserver>(), navigation_handle); + ContentScriptTracker::ReadyToCommitNavigation(PassKey(), navigation_handle); const ExtensionRegistry* const registry = ExtensionRegistry::Get(browser_context_);
diff --git a/extensions/browser/extension_web_contents_observer.h b/extensions/browser/extension_web_contents_observer.h index f11dcaa..8e36f04 100644 --- a/extensions/browser/extension_web_contents_observer.h +++ b/extensions/browser/extension_web_contents_observer.h
@@ -10,6 +10,7 @@ #include "base/compiler_specific.h" #include "base/macros.h" +#include "base/types/pass_key.h" #include "content/public/browser/web_contents_observer.h" #include "extensions/browser/extension_function_dispatcher.h" #include "extensions/common/mojom/frame.mojom.h" @@ -119,6 +120,8 @@ content::RenderFrameHost* render_frame_host) const; private: + using PassKey = base::PassKey<ExtensionWebContentsObserver>; + friend class ExtensionFrameHostBrowserTest; // The BrowserContext associated with the WebContents being observed. content::BrowserContext* browser_context_;
diff --git a/extensions/browser/user_script_loader.cc b/extensions/browser/user_script_loader.cc index 1e82e58..522d49ed 100644 --- a/extensions/browser/user_script_loader.cc +++ b/extensions/browser/user_script_loader.cc
@@ -14,11 +14,13 @@ #include "base/containers/cxx20_erase.h" #include "base/memory/writable_shared_memory_region.h" #include "base/strings/string_util.h" +#include "base/types/pass_key.h" #include "base/version.h" #include "build/build_config.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/render_process_host.h" +#include "extensions/browser/content_script_tracker.h" #include "extensions/browser/extension_registry.h" #include "extensions/browser/extensions_browser_client.h" #include "extensions/browser/guest_view/web_view/web_view_renderer_state.h" @@ -435,7 +437,6 @@ void UserScriptLoader::SendUpdate( content::RenderProcessHost* process, const base::ReadOnlySharedMemoryRegion& shared_memory) { - // Make sure we only send user scripts to processes in our browser_context. if (!ExtensionsBrowserClient::Get()->IsSameContext( browser_context_, process->GetBrowserContext())) @@ -470,6 +471,9 @@ return; } + ContentScriptTracker::WillUpdateContentScriptsInRenderer( + base::PassKey<UserScriptLoader>(), host_id_, *process); + mojom::Renderer* renderer = RendererStartupHelperFactory::GetForBrowserContext(browser_context()) ->GetRenderer(process);
diff --git a/extensions/renderer/scoped_web_frame.cc b/extensions/renderer/scoped_web_frame.cc index 56f155e..f64a6dd 100644 --- a/extensions/renderer/scoped_web_frame.cc +++ b/extensions/renderer/scoped_web_frame.cc
@@ -21,6 +21,7 @@ view_(blink::WebView::Create( /*client=*/nullptr, /*is_hidden=*/false, + /*is_prerendering=*/false, /*is_inside_portal=*/false, /*compositing_enabled=*/false, /*widgets_never_composited=*/false,
diff --git a/fuchsia/engine/BUILD.gn b/fuchsia/engine/BUILD.gn index 58962c9..7a2519c 100644 --- a/fuchsia/engine/BUILD.gn +++ b/fuchsia/engine/BUILD.gn
@@ -411,6 +411,7 @@ "//net:test_support", "//testing/gtest", "//third_party/fuchsia-sdk/sdk/fidl/fuchsia.web", + "//third_party/fuchsia-sdk/sdk/pkg/scenic_cpp", "//ui/ozone", ] visibility = [ @@ -576,14 +577,17 @@ "web_engine_integration_test.cc", "web_engine_integration_test_base.cc", "web_engine_integration_test_base.h", + "web_instance_host_integration_test.cc", ] data = [ "test/data" ] deps = [ + ":browsertest_core", "//base", "//base:test_log_listener_safe", "//fuchsia/base", "//fuchsia/base:run_all_integration_tests", "//fuchsia/base/test:test_support", + "//fuchsia/engine/web_instance_host", "//media", "//media/fuchsia/audio:test_support", "//media/fuchsia/camera:test_support", @@ -600,7 +604,11 @@ "//build/config/fuchsia/test/read_debug_data.test-cmx", "//build/config/fuchsia/test/vulkan_capabilities.test-cmx", "//build/config/fuchsia/test/web_engine_required_capabilities.test-cmx", + "//build/config/fuchsia/test/web_instance_host_capabilities.test-cmx", ] + + # Required by web_instance_host. + additional_manifests = [ "//fuchsia/engine/web_instance.cmx" ] } cr_fuchsia_package("web_engine_shell_pkg") {
diff --git a/fuchsia/engine/browser/context_impl.cc b/fuchsia/engine/browser/context_impl.cc index 9c5aef2..cd9ff5f 100644 --- a/fuchsia/engine/browser/context_impl.cc +++ b/fuchsia/engine/browser/context_impl.cc
@@ -35,12 +35,9 @@ base::Unretained(this))) { DCHECK(browser_context_); DCHECK(devtools_controller_); - devtools_controller_->OnContextCreated(); } -ContextImpl::~ContextImpl() { - devtools_controller_->OnContextDestroyed(); -} +ContextImpl::~ContextImpl() = default; void ContextImpl::DestroyFrame(FrameImpl* frame) { auto iter = frames_.find(frame);
diff --git a/fuchsia/engine/browser/web_engine_devtools_controller.cc b/fuchsia/engine/browser/web_engine_devtools_controller.cc index e609cf9..4a36a722 100644 --- a/fuchsia/engine/browser/web_engine_devtools_controller.cc +++ b/fuchsia/engine/browser/web_engine_devtools_controller.cc
@@ -89,8 +89,6 @@ NoopController& operator=(const NoopController&) = delete; // WebEngineDevToolsController implementation: - void OnContextCreated() override {} - void OnContextDestroyed() override {} bool OnFrameCreated(content::WebContents* contents, bool user_debugging) override { return !user_debugging; @@ -106,23 +104,22 @@ }; // "User-mode" makes DevTools accessible to remote devices for Frames specified -// by the Context owner. The controller, which starts DevTools when the first -// Frame is created, and shuts it down when no debuggable Frames remain. +// by the web_instance owner. The controller, which starts DevTools when the +// first Frame is created, and shuts it down when no debuggable Frames remain. class UserModeController : public WebEngineDevToolsController { public: explicit UserModeController(uint16_t server_port) : ip_endpoint_(net::IPAddress::IPv6AllZeros(), server_port) {} - ~UserModeController() override { DCHECK(!is_remote_debugging_started_); } + ~UserModeController() override { + if (is_remote_debugging_started_) { + content::DevToolsAgentHost::StopRemoteDebuggingServer(); + } + } UserModeController(const UserModeController&) = delete; UserModeController& operator=(const UserModeController&) = delete; // WebEngineDevToolsController implementation: - void OnContextCreated() override {} - void OnContextDestroyed() override { - if (is_remote_debugging_started_) - content::DevToolsAgentHost::StopRemoteDebuggingServer(); - } bool OnFrameCreated(content::WebContents* contents, bool user_debugging) override { if (user_debugging) { @@ -207,21 +204,14 @@ DebugModeController() : DebugModeController( net::IPEndPoint(net::IPAddress::IPv4Localhost(), 0)) {} - ~DebugModeController() override = default; + ~DebugModeController() override { + content::DevToolsAgentHost::StopRemoteDebuggingServer(); + } DebugModeController(const DebugModeController&) = delete; DebugModeController& operator=(const DebugModeController&) = delete; // DevToolsController implementation: - void OnContextCreated() override { - StartRemoteDebuggingServer( - base::BindOnce(&DebugModeController::OnDevToolsPortChanged, - base::Unretained(this)), - ip_endpoint_); - } - void OnContextDestroyed() override { - content::DevToolsAgentHost::StopRemoteDebuggingServer(); - } bool OnFrameCreated(content::WebContents* contents, bool user_debugging) override { return !user_debugging; @@ -242,7 +232,13 @@ explicit DebugModeController(net::IPEndPoint ip_endpoint) : ip_endpoint_(std::move(ip_endpoint)), connector_binding_(base::ComponentContextForProcess()->outgoing().get(), - this) {} + this) { + // Immediately start the service. + StartRemoteDebuggingServer( + base::BindOnce(&DebugModeController::OnDevToolsPortChanged, + base::Unretained(this)), + ip_endpoint_); + } virtual void OnDevToolsPortChanged(uint16_t port) { devtools_port_ = port; @@ -290,8 +286,7 @@ }; // "Mixed-mode" is used when both user and debug remote debugging are active at -// the same time. The service lifespan is tied to the Context and all Frames are -// available for remote debugging. +// the same time. The service is enabled for the lifespan of the web_instance. class MixedModeController : public DebugModeController { public: explicit MixedModeController(uint16_t server_port)
diff --git a/fuchsia/engine/browser/web_engine_devtools_controller.h b/fuchsia/engine/browser/web_engine_devtools_controller.h index 66856f5..df7fad8 100644 --- a/fuchsia/engine/browser/web_engine_devtools_controller.h +++ b/fuchsia/engine/browser/web_engine_devtools_controller.h
@@ -25,12 +25,6 @@ static std::unique_ptr<WebEngineDevToolsController> CreateFromCommandLine( const base::CommandLine& command_line); - // Called by the Context to signal its creation. - virtual void OnContextCreated() = 0; - - // Called by the Context to signal its destruction. - virtual void OnContextDestroyed() = 0; - // Called by the Context to signal a new Frame was created. |user_debugging| // should be set to true when debugging was requested from the user API. // Returns false if |contents| is not user-debuggable despite |user_debugging|
diff --git a/fuchsia/engine/web_instance_host_integration_test.cc b/fuchsia/engine/web_instance_host_integration_test.cc new file mode 100644 index 0000000..12df9e4 --- /dev/null +++ b/fuchsia/engine/web_instance_host_integration_test.cc
@@ -0,0 +1,166 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <fuchsia/io/cpp/fidl.h> +#include <fuchsia/web/cpp/fidl.h> +#include <lib/fdio/directory.h> +#include <lib/fidl/cpp/binding.h> +#include <lib/sys/cpp/component_context.h> + +#include "base/command_line.h" +#include "base/files/file_enumerator.h" +#include "base/fuchsia/filtered_service_directory.h" +#include "base/fuchsia/fuchsia_logging.h" +#include "base/fuchsia/process_context.h" +#include "base/strings/string_piece_forward.h" +#include "base/test/task_environment.h" +#include "fuchsia/base/test/fit_adapter.h" +#include "fuchsia/base/test/frame_test_util.h" +#include "fuchsia/base/test/result_receiver.h" +#include "fuchsia/base/test/test_devtools_list_fetcher.h" +#include "fuchsia/base/test/test_navigation_listener.h" +#include "fuchsia/engine/test/frame_for_test.h" +#include "fuchsia/engine/web_instance_host/web_instance_host.h" +#include "net/test/embedded_test_server/default_handlers.h" +#include "net/test/embedded_test_server/embedded_test_server.h" +#include "testing/gtest/include/gtest/gtest.h" + +class WebInstanceHostIntegrationTest : public testing::Test { + public: + WebInstanceHostIntegrationTest() + : task_environment_(base::test::TaskEnvironment::MainThreadType::IO), + filtered_service_directory_( + base::ComponentContextForProcess()->svc().get()) { + // Push all services from /svc to the filtered service directory. + base::FileEnumerator file_enum(base::FilePath("/svc"), false, + base::FileEnumerator::FILES); + for (auto file = file_enum.Next(); !file.empty(); file = file_enum.Next()) { + zx_status_t status = filtered_service_directory_.AddService( + file_enum.GetInfo().GetName().value().c_str()); + ZX_CHECK(status == ZX_OK, status) + << "FilteredServiceDirectory::AddService"; + } + } + + ~WebInstanceHostIntegrationTest() override = default; + WebInstanceHostIntegrationTest(const WebInstanceHostIntegrationTest&) = + delete; + WebInstanceHostIntegrationTest& operator=( + const WebInstanceHostIntegrationTest&) = delete; + + void SetUp() override { + // Override command line. This is necessary to get WebEngine logs. + base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); + command_line->AppendSwitchASCII("enable-logging", "stderr"); + + embedded_test_server_.ServeFilesFromSourceDirectory( + "fuchsia/engine/test/data"); + net::test_server::RegisterDefaultHandlers(&embedded_test_server_); + CHECK(embedded_test_server_.Start()); + } + + protected: + fuchsia::web::CreateContextParams TestContextParams() { + fuchsia::web::CreateContextParams create_params; + zx_status_t status = filtered_service_directory_.ConnectClient( + create_params.mutable_service_directory()->NewRequest()); + ZX_CHECK(status == ZX_OK, status) + << "FilteredServiceDirectory::ConnectClient"; + return create_params; + } + + void CreateContext(fuchsia::web::CreateContextParams context_params) { + CHECK(!context_); + + fuchsia::io::DirectoryHandle web_instance_services; + web_instance_host_.CreateInstanceForContext( + std::move(context_params), web_instance_services.NewRequest()); + web_instance_services_ = std::make_unique<sys::ServiceDirectory>( + std::move(web_instance_services)); + + zx_status_t result = web_instance_services_->Connect(context_.NewRequest()); + ZX_CHECK(result == ZX_OK, result) << "fdio_service_connect_at"; + context_.set_error_handler([](zx_status_t status) { ADD_FAILURE(); }); + } + + void ConnectFrameHost() { + zx_status_t result = + web_instance_services_->Connect(frame_host_.NewRequest()); + ZX_CHECK(result == ZX_OK, result) << "fdio_service_connect_at"; + frame_host_.set_error_handler([](zx_status_t status) { ADD_FAILURE(); }); + } + + const base::test::TaskEnvironment task_environment_; + + fidl::InterfaceHandle<fuchsia::sys::ComponentController> + web_engine_controller_; + + cr_fuchsia::WebInstanceHost web_instance_host_; + std::unique_ptr<sys::ServiceDirectory> web_instance_services_; + fuchsia::web::ContextPtr context_; + fuchsia::web::FrameHostPtr frame_host_; + + net::EmbeddedTestServer embedded_test_server_; + + base::FilteredServiceDirectory filtered_service_directory_; +}; + +// Check that connecting and disconnecting to the FrameHost service does not +// trigger shutdown of the devtools service. +TEST_F(WebInstanceHostIntegrationTest, FrameHostDebugging) { + fuchsia::web::CreateContextParams create_params = TestContextParams(); + create_params.set_remote_debugging_port(0); + CreateContext(std::move(create_params)); + + fuchsia::web::CreateFrameParams create_frame_params; + create_frame_params.set_enable_remote_debugging(true); + auto frame = cr_fuchsia::FrameForTest::Create(context_, + std::move(create_frame_params)); + + // Expect to receive a notification of the selected DevTools port. + base::RunLoop run_loop; + cr_fuchsia::ResultReceiver< + fuchsia::web::Context_GetRemoteDebuggingPort_Result> + port_receiver(run_loop.QuitClosure()); + context_->GetRemoteDebuggingPort( + cr_fuchsia::CallbackToFitFunction(port_receiver.GetReceiveCallback())); + run_loop.Run(); + ASSERT_TRUE(port_receiver->is_response()); + uint16_t remote_debugging_port = port_receiver->response().port; + ASSERT_TRUE(remote_debugging_port != 0); + + // Navigate to a URL, the devtools service should be active and report a + // single page. + GURL url = embedded_test_server_.GetURL("/defaultresponse"); + ASSERT_TRUE(cr_fuchsia::LoadUrlAndExpectResponse( + frame.GetNavigationController(), fuchsia::web::LoadUrlParams(), + url.spec())); + frame.navigation_listener().RunUntilUrlEquals(url); + base::Value devtools_list = + cr_fuchsia::GetDevToolsListFromPort(remote_debugging_port); + ASSERT_TRUE(devtools_list.is_list()); + EXPECT_EQ(devtools_list.GetList().size(), 1u); + base::Value* devtools_url = devtools_list.GetList()[0].FindPath("url"); + ASSERT_TRUE(devtools_url->is_string()); + EXPECT_EQ(devtools_url->GetString(), url); + + // Connect to the FrameHost and immediately disconnect it. + ConnectFrameHost(); + frame_host_.Unbind(); + + // Navigate to a different page. The devtools service should still be active + // and report the new page. + GURL url2 = embedded_test_server_.GetURL("/title1.html"); + ASSERT_TRUE(cr_fuchsia::LoadUrlAndExpectResponse( + frame.GetNavigationController(), fuchsia::web::LoadUrlParams(), + url2.spec())); + frame.navigation_listener().RunUntilUrlEquals(url2); + + devtools_list = cr_fuchsia::GetDevToolsListFromPort(remote_debugging_port); + ASSERT_TRUE(devtools_list.is_list()); + EXPECT_EQ(devtools_list.GetList().size(), 1u); + devtools_url = devtools_list.GetList()[0].FindPath("url"); + ASSERT_TRUE(devtools_url->is_string()); + EXPECT_EQ(devtools_url->GetString(), url2); +}
diff --git a/gpu/command_buffer/service/shared_image_factory.cc b/gpu/command_buffer/service/shared_image_factory.cc index c6c87a98..dd5759ea 100644 --- a/gpu/command_buffer/service/shared_image_factory.cc +++ b/gpu/command_buffer/service/shared_image_factory.cc
@@ -132,24 +132,26 @@ gr_context_type_ == GrContextType::kMetal); #endif + if (enable_wrapped_sk_image && context_state) { + auto wrapped_sk_image_factory = + std::make_unique<raster::WrappedSkImageFactory>(context_state); + factories_.push_back(std::move(wrapped_sk_image_factory)); + } + bool use_gl = gl::GetGLImplementation() != gl::kGLImplementationNone; if (use_gl) { - gl_texture_backing_factory_ = + auto gl_texture_backing_factory = std::make_unique<SharedImageBackingFactoryGLTexture>( gpu_preferences, workarounds, gpu_feature_info, shared_context_state_ ? shared_context_state_->progress_reporter() : nullptr); - - gl_image_backing_factory_ = - std::make_unique<SharedImageBackingFactoryGLImage>( - gpu_preferences, workarounds, gpu_feature_info, image_factory, - shared_context_state_ ? shared_context_state_->progress_reporter() - : nullptr); + factories_.push_back(std::move(gl_texture_backing_factory)); #if defined(OS_ANDROID) - egl_backing_factory_ = std::make_unique<SharedImageBackingFactoryEGL>( + auto egl_backing_factory = std::make_unique<SharedImageBackingFactoryEGL>( gpu_preferences, workarounds, gpu_feature_info, shared_image_manager->batch_access_manager()); + factories_.push_back(std::move(egl_backing_factory)); #endif } @@ -161,32 +163,37 @@ !BUILDFLAG(IS_CHROMEOS_LACROS) && !BUILDFLAG(IS_CHROMECAST) // Desktop Linux, not ChromeOS. if (ShouldUseExternalVulkanImageFactory()) { - interop_backing_factory_ = + auto external_vk_image_factory = std::make_unique<ExternalVkImageFactory>(context_state); + factories_.push_back(std::move(external_vk_image_factory)); } else { LOG(ERROR) << "ERROR: gr_context_type_ is GrContextType::kVulkan and " "interop_backing_factory_ is not set"; } #elif defined(OS_FUCHSIA) || defined(OS_WIN) - interop_backing_factory_ = + auto external_vk_image_factory = std::make_unique<ExternalVkImageFactory>(context_state); + factories_.push_back(std::move(external_vk_image_factory)); #elif defined(OS_ANDROID) - // For Android - external_vk_image_factory_ = - std::make_unique<ExternalVkImageFactory>(context_state); const auto& enabled_extensions = context_state->vk_context_provider() ->GetDeviceQueue() ->enabled_extensions(); if (gfx::HasExtension( enabled_extensions, VK_ANDROID_EXTERNAL_MEMORY_ANDROID_HARDWARE_BUFFER_EXTENSION_NAME)) { - interop_backing_factory_ = std::make_unique<SharedImageBackingFactoryAHB>( + auto ahb_factory = std::make_unique<SharedImageBackingFactoryAHB>( workarounds, gpu_feature_info); + factories_.push_back(std::move(ahb_factory)); } + // For Android + auto external_vk_image_factory = + std::make_unique<ExternalVkImageFactory>(context_state); + factories_.push_back(std::move(external_vk_image_factory)); #endif #elif BUILDFLAG(IS_CHROMEOS_ASH) - interop_backing_factory_ = + auto ozone_factory = std::make_unique<SharedImageBackingFactoryOzone>(context_state); + factories_.push_back(std::move(ozone_factory)); #else // Others LOG(ERROR) << "ERROR: gr_context_type_ is GrContextType::kVulkan and " @@ -196,15 +203,12 @@ // gr_context_type_ != GrContextType::kVulkan #if defined(OS_ANDROID) && BUILDFLAG(ENABLE_VULKAN) if (base::AndroidHardwareBufferCompat::IsSupportAvailable()) { - interop_backing_factory_ = std::make_unique<SharedImageBackingFactoryAHB>( + auto ahb_factory = std::make_unique<SharedImageBackingFactoryAHB>( workarounds, gpu_feature_info); + factories_.push_back(std::move(ahb_factory)); } #endif } - if (enable_wrapped_sk_image && context_state) { - wrapped_sk_image_factory_ = - std::make_unique<raster::WrappedSkImageFactory>(context_state); - } #if defined(OS_WIN) // For Windows @@ -212,10 +216,21 @@ gles2::PassthroughCommandDecoderSupported(); if (use_passthrough && gr_context_type_ == GrContextType::kGL) { // Only supported for passthrough command decoder. - interop_backing_factory_ = std::make_unique<SharedImageBackingFactoryD3D>(); + auto d3d_factory = std::make_unique<SharedImageBackingFactoryD3D>(); + d3d_backing_factory_ = d3d_factory.get(); + factories_.push_back(std::move(d3d_factory)); } #endif // OS_WIN + if (use_gl) { + auto gl_image_backing_factory = + std::make_unique<SharedImageBackingFactoryGLImage>( + gpu_preferences, workarounds, gpu_feature_info, image_factory, + shared_context_state_ ? shared_context_state_->progress_reporter() + : nullptr); + factories_.push_back(std::move(gl_image_backing_factory)); + } + #if defined(OS_FUCHSIA) vulkan_context_provider_ = context_state->vk_context_provider(); #endif // OS_FUCHSIA @@ -355,11 +370,8 @@ if (!SharedImageBackingFactoryD3D::IsSwapChainSupported()) return false; - SharedImageBackingFactoryD3D* d3d_backing_factory = - static_cast<SharedImageBackingFactoryD3D*>( - interop_backing_factory_.get()); bool allow_legacy_mailbox = true; - auto backings = d3d_backing_factory->CreateSwapChain( + auto backings = d3d_backing_factory_->CreateSwapChain( front_buffer_mailbox, back_buffer_mailbox, format, size, color_space, surface_origin, alpha_type, usage); return RegisterBacking(std::move(backings.front_buffer), @@ -443,10 +455,10 @@ gfx::BufferFormat format, const gfx::Size& size, uint32_t usage) { - if (!interop_backing_factory_) + if (!d3d_backing_factory_) return false; - auto backings = interop_backing_factory_->CreateSharedImageVideoPlanes( + auto backings = d3d_backing_factory_->CreateSharedImageVideoPlanes( mailboxes, std::move(handle), format, size, usage); if (backings.size() != gfx::NumberOfPlanesForLinearBufferFormat(format)) @@ -514,52 +526,12 @@ return backing_factory_for_testing_; bool share_between_threads = IsSharedBetweenThreads(usage); - - if (wrapped_sk_image_factory_ && - wrapped_sk_image_factory_->IsSupported( - usage, format, share_between_threads, gmb_type, gr_context_type_, - allow_legacy_mailbox, is_pixel_used)) { - return wrapped_sk_image_factory_.get(); - } - - if (gl_texture_backing_factory_ && - gl_texture_backing_factory_->IsSupported( - usage, format, share_between_threads, gmb_type, gr_context_type_, - allow_legacy_mailbox, is_pixel_used)) { - return gl_texture_backing_factory_.get(); - } - -#if defined(OS_ANDROID) - if (egl_backing_factory_ && - egl_backing_factory_->IsSupported(usage, format, share_between_threads, - gmb_type, gr_context_type_, - allow_legacy_mailbox, is_pixel_used)) { - return egl_backing_factory_.get(); - } -#endif // !defined(OS_ANDROID) - - if (interop_backing_factory_ && - interop_backing_factory_->IsSupported( - usage, format, share_between_threads, gmb_type, gr_context_type_, - allow_legacy_mailbox, is_pixel_used)) { - return interop_backing_factory_.get(); - } - -#if defined(OS_ANDROID) - // On android, we sometime choose VkImage based backing factory as an - // interop if the format is not supported by the AHB backing factory. - if (external_vk_image_factory_ && - external_vk_image_factory_->IsSupported( - usage, format, share_between_threads, gmb_type, gr_context_type_, - allow_legacy_mailbox, is_pixel_used)) - return external_vk_image_factory_.get(); -#endif // !defined(OS_ANDROID) - - if (gl_image_backing_factory_ && - gl_image_backing_factory_->IsSupported( - usage, format, share_between_threads, gmb_type, gr_context_type_, - allow_legacy_mailbox, is_pixel_used)) { - return gl_image_backing_factory_.get(); + for (auto& factory : factories_) { + if (factory->IsSupported(usage, format, share_between_threads, gmb_type, + gr_context_type_, allow_legacy_mailbox, + is_pixel_used)) { + return factory.get(); + } } LOG(ERROR) << "Could not find SharedImageBackingFactory with params: usage: "
diff --git a/gpu/command_buffer/service/shared_image_factory.h b/gpu/command_buffer/service/shared_image_factory.h index bca02c6e..4b0983d 100644 --- a/gpu/command_buffer/service/shared_image_factory.h +++ b/gpu/command_buffer/service/shared_image_factory.h
@@ -6,6 +6,7 @@ #define GPU_COMMAND_BUFFER_SERVICE_SHARED_IMAGE_FACTORY_H_ #include <memory> +#include <vector> #include "base/containers/flat_set.h" #include "base/memory/scoped_refptr.h" @@ -26,16 +27,13 @@ } // namespace viz namespace gpu { -class ExternalVkImageFactory; class GpuDriverBugWorkarounds; class ImageFactory; class MailboxManager; class MemoryTracker; class SharedContextState; class SharedImageBackingFactory; -class SharedImageBackingFactoryEGL; -class SharedImageBackingFactoryGLImage; -class SharedImageBackingFactoryGLTexture; +class SharedImageBackingFactoryD3D; struct GpuFeatureInfo; struct GpuPreferences; @@ -43,10 +41,6 @@ class SysmemBufferCollection; #endif // OS_FUCHSIA -namespace raster { -class WrappedSkImageFactory; -} // namespace raster - // TODO(ericrk): Make this a very thin wrapper around SharedImageManager like // SharedImageRepresentationFactory. class GPU_GLES2_EXPORT SharedImageFactory { @@ -173,30 +167,15 @@ base::flat_set<std::unique_ptr<SharedImageRepresentationFactoryRef>> shared_images_; - // Used for creating shared image using GLTexture backing - std::unique_ptr<SharedImageBackingFactoryGLTexture> - gl_texture_backing_factory_; + // Array of all the backing factories to choose from for creating shared + // images. + std::vector<std::unique_ptr<SharedImageBackingFactory>> factories_; - // Used for creating shared image using GLImage backing - std::unique_ptr<SharedImageBackingFactoryGLImage> gl_image_backing_factory_; - - // Used for creating shared image which can be shared between GL, Vulkan and - // D3D12. - std::unique_ptr<SharedImageBackingFactory> interop_backing_factory_; - -#if defined(OS_ANDROID) - // Used for creating shared image using EGL Backing - std::unique_ptr<SharedImageBackingFactoryEGL> egl_backing_factory_; - - // On android we have two interop factory which is |interop_backing_factory_| - // and |external_vk_image_factory_| and we choose one of those - // based on the format it supports. - std::unique_ptr<ExternalVkImageFactory> external_vk_image_factory_; +#if defined(OS_WIN) + // Used for creating swap chains + SharedImageBackingFactoryD3D* d3d_backing_factory_ = nullptr; #endif - // Non-null if compositing with SkiaRenderer. - std::unique_ptr<raster::WrappedSkImageFactory> wrapped_sk_image_factory_; - #if defined(OS_FUCHSIA) viz::VulkanContextProvider* vulkan_context_provider_; base::flat_map<gfx::SysmemBufferCollectionId,
diff --git a/gpu/config/gpu_driver_bug_list.json b/gpu/config/gpu_driver_bug_list.json index 87e2506..6757cfd 100644 --- a/gpu/config/gpu_driver_bug_list.json +++ b/gpu/config/gpu_driver_bug_list.json
@@ -3746,6 +3746,18 @@ "features": [ "disable_media_foundation_hardware_security" ] + }, + { + "id": 378, + "cr_bugs": [1227033], + "description": "Don't use the OOPR Canvas feature on Macs with NVIDIA GPUs", + "os": { + "type" : "macosx" + }, + "vendor_id": "0x10de", + "features": [ + "disable_canvas_oop_rasterization" + ] } ] }
diff --git a/gpu/config/gpu_workaround_list.txt b/gpu/config/gpu_workaround_list.txt index b7e265f..ff63e95 100644 --- a/gpu/config/gpu_workaround_list.txt +++ b/gpu/config/gpu_workaround_list.txt
@@ -22,6 +22,7 @@ disable_async_readpixels disable_av_sample_buffer_display_layer disable_blend_equation_advanced +disable_canvas_oop_rasterization disable_chromium_framebuffer_multisample disable_d3d11 disable_d3d11_video_decoder
diff --git a/headless/BUILD.gn b/headless/BUILD.gn index f9e3e8b..541cf9e 100644 --- a/headless/BUILD.gn +++ b/headless/BUILD.gn
@@ -260,12 +260,12 @@ ] } -# Code needed in both processes. Only exposed through |headless| and -# |headless_non_renderer| components. +# Code needed in both processes. Only exposed through the |headless_renderer| +# target and the |headless_non_renderer| component. source_set("headless_shared_sources") { visibility = [ - ":headless", ":headless_non_renderer", + ":headless_renderer", ] defines = [] @@ -322,11 +322,6 @@ configs += [ ":headless_defines_config" ] } -# Code that is needed in a renderer process. -component("headless") { - deps = [ ":headless_shared_sources" ] -} - # Code that is not needed in a renderer process. component("headless_non_renderer") { sources = [ @@ -617,7 +612,7 @@ } deps = [ - ":headless", + ":headless_shared_sources", "//build:chromeos_buildflags", "//components/crash/core/common", "//components/security_state/content",
diff --git a/infra/inclusive_language_presubmit_exempt_dirs.txt b/infra/inclusive_language_presubmit_exempt_dirs.txt index 0c44460..449988e 100644 --- a/infra/inclusive_language_presubmit_exempt_dirs.txt +++ b/infra/inclusive_language_presubmit_exempt_dirs.txt
@@ -77,7 +77,6 @@ components/safe_browsing/core/common/proto 3 1 components/security_interstitials/content 1 1 components/strictmode/android/java/src/org/chromium/components/strictmode 4 3 -components/suggestions 5 3 components/sync 1 1 components/sync/protocol 5 2 components/test/data/autofill/heuristics/input 4 1
diff --git a/ios/chrome/app/BUILD.gn b/ios/chrome/app/BUILD.gn index fcdbc3d..35ccb83 100644 --- a/ios/chrome/app/BUILD.gn +++ b/ios/chrome/app/BUILD.gn
@@ -295,7 +295,6 @@ "//components/prefs/ios", "//components/previous_session_info", "//components/proxy_config", - "//components/suggestions", "//components/sync", "//components/web_resource", "//ios/chrome/app/application_delegate", @@ -340,7 +339,6 @@ "//ios/chrome/browser/share_extension", "//ios/chrome/browser/signin", "//ios/chrome/browser/snapshots", - "//ios/chrome/browser/suggestions", "//ios/chrome/browser/sync", "//ios/chrome/browser/ui:feature_flags", "//ios/chrome/browser/ui/appearance",
diff --git a/ios/chrome/app/spotlight/BUILD.gn b/ios/chrome/app/spotlight/BUILD.gn index 0cca2a642..9cd4c86 100644 --- a/ios/chrome/app/spotlight/BUILD.gn +++ b/ios/chrome/app/spotlight/BUILD.gn
@@ -25,14 +25,12 @@ "//components/favicon/core", "//components/favicon_base", "//components/history/core/browser", - "//components/suggestions", "//ios/chrome/app", "//ios/chrome/app/strings", "//ios/chrome/browser", "//ios/chrome/browser/bookmarks", "//ios/chrome/browser/favicon", "//ios/chrome/browser/history", - "//ios/chrome/browser/suggestions", "//ios/chrome/browser/sync", "//ios/chrome/browser/ui/content_suggestions", "//ios/chrome/common/app_group",
diff --git a/ios/chrome/app/spotlight/topsites_spotlight_manager.mm b/ios/chrome/app/spotlight/topsites_spotlight_manager.mm index 6e504feb..6f18daf 100644 --- a/ios/chrome/app/spotlight/topsites_spotlight_manager.mm +++ b/ios/chrome/app/spotlight/topsites_spotlight_manager.mm
@@ -13,12 +13,10 @@ #include "components/history/core/browser/history_types.h" #include "components/history/core/browser/top_sites.h" #include "components/history/core/browser/top_sites_observer.h" -#include "components/suggestions/suggestions_service.h" #include "components/sync/driver/sync_service.h" #include "ios/chrome/browser/bookmarks/bookmark_model_factory.h" #include "ios/chrome/browser/favicon/ios_chrome_large_icon_service_factory.h" #include "ios/chrome/browser/history/top_sites_factory.h" -#include "ios/chrome/browser/suggestions/suggestions_service_factory.h" #include "ios/chrome/browser/sync/sync_observer_bridge.h" #include "ios/chrome/browser/sync/sync_service_factory.h" #import "ios/chrome/browser/ui/content_suggestions/content_suggestions_mediator.h" @@ -29,7 +27,6 @@ class SpotlightTopSitesBridge; class SpotlightTopSitesCallbackBridge; -class SpotlightSuggestionsBridge; @interface TopSitesSpotlightManager ()<SyncObserverModelBridge> { // Bridge to register for top sites changes. It's important that this instance @@ -39,18 +36,9 @@ // Bridge to register for top sites callbacks. std::unique_ptr<SpotlightTopSitesCallbackBridge> _topSitesCallbackBridge; - // Bridge to register for sync changes. - std::unique_ptr<SyncObserverBridge> _syncObserverBridge; - - // Bridge to register for suggestion changes. - std::unique_ptr<SpotlightSuggestionsBridge> _suggestionsBridge; - bookmarks::BookmarkModel* _bookmarkModel; // weak - suggestions::SuggestionsService* _suggestionService; // weak - syncer::SyncService* _syncService; // weak scoped_refptr<history::TopSites> _topSites; - base::CallbackListSubscription _suggestionsServiceResponseSubscription; // Indicates if a reindex is pending. Reindexes made by calling the external // reindexTopSites method are executed at most every second. @@ -61,10 +49,7 @@ - (instancetype) initWithLargeIconService:(favicon::LargeIconService*)largeIconService topSites:(scoped_refptr<history::TopSites>)topSites - bookmarkModel:(bookmarks::BookmarkModel*)bookmarkModel - syncService:(syncer::SyncService*)syncService - suggestionsService: - (suggestions::SuggestionsService*)suggestionsService; + bookmarkModel:(bookmarks::BookmarkModel*)bookmarkModel; // Updates all indexed top sites from appropriate source, within limit of number // of sites shown on NTP. @@ -77,13 +62,8 @@ - (void)addAllLocalTopSitesItems; // Adds all top sites from Suggestions source (server-based), within limit of // number of sites shown on NTP. -- (void)addAllSuggestionsTopSitesItems; -// Callback for topsites mostvisited, adds sites to spotlight. - (void)onMostVisitedURLsAvailable: (const history::MostVisitedURLList&)top_sites; -// Callback for suggestions, adds sites to spotlight. -- (void)onSuggestionsProfileAvailable: - (const suggestions::SuggestionsProfile&)suggestions_profile; @end @@ -128,23 +108,6 @@ history::TopSites* top_sites_; }; -class SpotlightSuggestionsBridge - : public base::SupportsWeakPtr<SpotlightSuggestionsBridge> { - public: - explicit SpotlightSuggestionsBridge(TopSitesSpotlightManager* owner) - : owner_(owner) {} - - ~SpotlightSuggestionsBridge() {} - - void OnSuggestionsProfileAvailable( - const suggestions::SuggestionsProfile& suggestions_profile) { - [owner_ onSuggestionsProfileAvailable:suggestions_profile]; - } - - private: - __weak TopSitesSpotlightManager* owner_; -}; - @implementation TopSitesSpotlightManager @synthesize topSites = _topSites; @@ -156,42 +119,23 @@ topSites:ios::TopSitesFactory::GetForBrowserState( browserState) bookmarkModel:ios::BookmarkModelFactory::GetForBrowserState( - browserState) - syncService:SyncServiceFactory::GetForBrowserState( - browserState) - suggestionsService:suggestions::SuggestionsServiceFactory:: - GetForBrowserState(browserState)]; + browserState)]; } - (instancetype) initWithLargeIconService:(favicon::LargeIconService*)largeIconService topSites:(scoped_refptr<history::TopSites>)topSites - bookmarkModel:(bookmarks::BookmarkModel*)bookmarkModel - syncService:(syncer::SyncService*)syncService - suggestionsService: - (suggestions::SuggestionsService*)suggestionsService { + bookmarkModel:(bookmarks::BookmarkModel*)bookmarkModel { self = [super initWithLargeIconService:largeIconService domain:spotlight::DOMAIN_TOPSITES]; if (self) { DCHECK(topSites); DCHECK(bookmarkModel); - DCHECK(syncService); - DCHECK(suggestionsService); _topSites = topSites; _topSitesBridge.reset(new SpotlightTopSitesBridge(self, _topSites.get())); _topSitesCallbackBridge.reset(new SpotlightTopSitesCallbackBridge(self)); _bookmarkModel = bookmarkModel; _isReindexPending = false; - if (syncService && suggestionsService) { - _suggestionsBridge.reset(new SpotlightSuggestionsBridge(self)); - _syncService = syncService; - _suggestionService = suggestionsService; - _suggestionsServiceResponseSubscription = - _suggestionService->AddCallback(base::BindRepeating( - &SpotlightSuggestionsBridge::OnSuggestionsProfileAvailable, - _suggestionsBridge->AsWeakPtr())); - _syncObserverBridge.reset(new SyncObserverBridge(self, syncService)); - } } return self; } @@ -209,11 +153,7 @@ if (!_topSites) return; - if (_suggestionService) { - [self addAllSuggestionsTopSitesItems]; - } else { - [self addAllLocalTopSitesItems]; - } + [self addAllLocalTopSitesItems]; } - (void)addAllLocalTopSitesItems { @@ -222,12 +162,6 @@ _topSitesCallbackBridge->AsWeakPtr())); } -- (void)addAllSuggestionsTopSitesItems { - if (!_suggestionService->FetchSuggestionsData()) { - [self addAllLocalTopSitesItems]; - } -} - - (BOOL)isURLBookmarked:(const GURL&)URL { if (!_bookmarkModel->loaded()) return NO; @@ -254,29 +188,6 @@ } } -- (void)onSuggestionsProfileAvailable: - (const suggestions::SuggestionsProfile&)suggestionsProfile { - size_t size = suggestionsProfile.suggestions_size(); - if (size) { - NSUInteger sitesToIndex = - MIN(size, [ContentSuggestionsMediator maxSitesShown]); - for (size_t i = 0; i < sitesToIndex; i++) { - const suggestions::ChromeSuggestion& suggestion = - suggestionsProfile.suggestions(i); - GURL URL = GURL(suggestion.url()); - // Check if the item is bookmarked, in which case it is already indexed. - if ([self isURLBookmarked:URL]) { - continue; - } - - std::string title = suggestion.title(); - [self refreshItemsWithURL:URL title:base::SysUTF8ToNSString(title)]; - } - } else { - [self addAllLocalTopSitesItems]; - } -} - - (void)reindexTopSites { if (_isReindexPending) { return; @@ -298,13 +209,9 @@ - (void)shutdown { _topSitesBridge.reset(); _topSitesCallbackBridge.reset(); - _syncObserverBridge.reset(); - _suggestionsBridge.reset(); _topSites = nullptr; _bookmarkModel = nullptr; - _syncService = nullptr; - _suggestionService = nullptr; [super shutdown]; }
diff --git a/ios/chrome/browser/browser_state/BUILD.gn b/ios/chrome/browser/browser_state/BUILD.gn index 363c6e6..69b1192 100644 --- a/ios/chrome/browser/browser_state/BUILD.gn +++ b/ios/chrome/browser/browser_state/BUILD.gn
@@ -128,7 +128,6 @@ "//ios/chrome/browser/sessions", "//ios/chrome/browser/signin", "//ios/chrome/browser/snapshots", - "//ios/chrome/browser/suggestions", "//ios/chrome/browser/sync", "//ios/chrome/browser/sync/glue", "//ios/chrome/browser/translate",
diff --git a/ios/chrome/browser/browser_state/browser_state_keyed_service_factories.mm b/ios/chrome/browser/browser_state/browser_state_keyed_service_factories.mm index 426a51f..f9b0a9f 100644 --- a/ios/chrome/browser/browser_state/browser_state_keyed_service_factories.mm +++ b/ios/chrome/browser/browser_state/browser_state_keyed_service_factories.mm
@@ -55,7 +55,6 @@ #include "ios/chrome/browser/signin/signin_browser_state_info_updater_factory.h" #include "ios/chrome/browser/signin/signin_client_factory.h" #include "ios/chrome/browser/signin/signin_error_controller_factory.h" -#include "ios/chrome/browser/suggestions/suggestions_service_factory.h" #include "ios/chrome/browser/sync/consent_auditor_factory.h" #include "ios/chrome/browser/sync/ios_user_event_service_factory.h" #include "ios/chrome/browser/sync/model_type_store_service_factory.h" @@ -111,7 +110,6 @@ ios::WebDataServiceFactory::GetInstance(); ios::WebHistoryServiceFactory::GetInstance(); translate::TranslateRankerFactory::GetInstance(); - suggestions::SuggestionsServiceFactory::GetInstance(); AuthenticationServiceFactory::GetInstance(); BreadcrumbManagerKeyedServiceFactory::GetInstance(); BrowserDownloadServiceFactory::GetInstance();
diff --git a/ios/chrome/browser/chrome_url_constants.cc b/ios/chrome/browser/chrome_url_constants.cc index db9d645..3e6680dd 100644 --- a/ios/chrome/browser/chrome_url_constants.cc +++ b/ios/chrome/browser/chrome_url_constants.cc
@@ -22,7 +22,6 @@ const char kChromeUIOfflineURL[] = "chrome://offline/"; const char kChromeUIPolicyURL[] = "chrome://policy/"; const char kChromeUISettingsURL[] = "chrome://settings/"; -const char kChromeUISuggestionsURL[] = "chrome://suggestions/"; const char kChromeUITermsURL[] = "chrome://terms/"; const char kChromeUIVersionURL[] = "chrome://version/"; @@ -51,7 +50,6 @@ const char kChromeUIPolicyHost[] = "policy"; const char kChromeUIPrefsInternalsHost[] = "prefs-internals"; const char kChromeUISignInInternalsHost[] = "signin-internals"; -const char kChromeUISuggestionsHost[] = "suggestions"; const char kChromeUITermsHost[] = "terms"; const char kChromeUITranslateInternalsHost[] = "translate-internals"; const char kChromeUIURLKeyedMetricsHost[] = "ukm"; @@ -73,7 +71,6 @@ kChromeUINTPTilesInternalsHost, kChromeUIPasswordManagerInternalsHost, kChromeUISignInInternalsHost, - kChromeUISuggestionsHost, kChromeUISyncInternalsHost, kChromeUITermsHost, kChromeUIUserActionsHost,
diff --git a/ios/chrome/browser/chrome_url_constants.h b/ios/chrome/browser/chrome_url_constants.h index 081dd352..60052efb 100644 --- a/ios/chrome/browser/chrome_url_constants.h +++ b/ios/chrome/browser/chrome_url_constants.h
@@ -25,7 +25,6 @@ extern const char kChromeUIPolicyURL[]; extern const char kChromeUIPopularSitesInternalsURL[]; extern const char kChromeUISettingsURL[]; -extern const char kChromeUISuggestionsURL[]; extern const char kChromeUITermsURL[]; extern const char kChromeUIVersionURL[]; @@ -55,7 +54,6 @@ extern const char kChromeUIPopularSitesInternalsHost[]; extern const char kChromeUIPrefsInternalsHost[]; extern const char kChromeUISignInInternalsHost[]; -extern const char kChromeUISuggestionsHost[]; extern const char kChromeUITermsHost[]; extern const char kChromeUITranslateInternalsHost[]; extern const char kChromeUIURLKeyedMetricsHost[];
diff --git a/ios/chrome/browser/discover_feed/BUILD.gn b/ios/chrome/browser/discover_feed/BUILD.gn index 3b31524..89fd0117 100644 --- a/ios/chrome/browser/discover_feed/BUILD.gn +++ b/ios/chrome/browser/discover_feed/BUILD.gn
@@ -18,7 +18,6 @@ "//components/signin/public/identity_manager", "//ios/chrome/browser/browser_state", "//ios/chrome/browser/signin", - "//ios/chrome/browser/ui/content_suggestions:feature_flags", "//ios/chrome/browser/ui/content_suggestions:metrics", "//ios/public/provider/chrome/browser", "//ios/public/provider/chrome/browser/discover_feed",
diff --git a/ios/chrome/browser/discover_feed/discover_feed_service.h b/ios/chrome/browser/discover_feed/discover_feed_service.h index f801c36..f8ad395 100644 --- a/ios/chrome/browser/discover_feed/discover_feed_service.h +++ b/ios/chrome/browser/discover_feed/discover_feed_service.h
@@ -10,7 +10,6 @@ #include "components/signin/public/identity_manager/identity_manager.h" class AuthenticationService; -@class ContentSuggestionsMetricsRecorder; @class DiscoverFeedMetricsRecorder; class PrefService; @@ -25,15 +24,10 @@ signin::IdentityManager* identity_manager); ~DiscoverFeedService() override; - // Returns the DiscoverFeedMetricsRecorder to be used by the Discover Feed, a - // single instance needs to be used per BrowserState. + // Returns the FeedMetricsRecorder to be used by the Feed, a single instance + // of DiscoverFeedMetricsRecorder needs to be used per BrowserState. DiscoverFeedMetricsRecorder* GetDiscoverFeedMetricsRecorder(); - // Returns the ContentSuggestionsMetricsRecorder to be used by the Zine Feed, - // a single instance needs to be used per BrowserState. - // TODO(crbug.com/1200303): Remove this when we launch the Discover feed. - ContentSuggestionsMetricsRecorder* GetContentSuggestionsMetricsRecorder(); - // KeyedService: void Shutdown() override; @@ -50,10 +44,6 @@ // Metrics recorder for the DiscoverFeed. __strong DiscoverFeedMetricsRecorder* discover_feed_metrics_recorder_ = nil; - // Metrics recorder for the Zine feed. - __strong ContentSuggestionsMetricsRecorder* - content_suggestions_metrics_recorder_ = nil; - DISALLOW_COPY_AND_ASSIGN(DiscoverFeedService); };
diff --git a/ios/chrome/browser/discover_feed/discover_feed_service.mm b/ios/chrome/browser/discover_feed/discover_feed_service.mm index 45dba54b..db3f30d 100644 --- a/ios/chrome/browser/discover_feed/discover_feed_service.mm +++ b/ios/chrome/browser/discover_feed/discover_feed_service.mm
@@ -5,8 +5,6 @@ #include "ios/chrome/browser/discover_feed/discover_feed_service.h" #include "ios/chrome/browser/browser_state/chrome_browser_state.h" -#import "ios/chrome/browser/ui/content_suggestions/content_suggestions_feature.h" -#import "ios/chrome/browser/ui/content_suggestions/content_suggestions_metrics_recorder.h" #import "ios/chrome/browser/ui/content_suggestions/discover_feed_metrics_recorder.h" #import "ios/public/provider/chrome/browser/chrome_browser_provider.h" #import "ios/public/provider/chrome/browser/discover_feed/discover_feed_configuration.h" @@ -23,12 +21,6 @@ if (identity_manager) identity_manager_observation_.Observe(identity_manager); - if (!IsDiscoverFeedEnabled()) { - content_suggestions_metrics_recorder_ = - [[ContentSuggestionsMetricsRecorder alloc] init]; - return; - } - discover_feed_metrics_recorder_ = [[DiscoverFeedMetricsRecorder alloc] init]; DiscoverFeedConfiguration* discover_config = @@ -47,11 +39,6 @@ return discover_feed_metrics_recorder_; } -ContentSuggestionsMetricsRecorder* -DiscoverFeedService::GetContentSuggestionsMetricsRecorder() { - return content_suggestions_metrics_recorder_; -} - void DiscoverFeedService::Shutdown() { identity_manager_observation_.Reset(); @@ -59,7 +46,6 @@ ios::GetChromeBrowserProvider().GetDiscoverFeedProvider()->StopFeed(); discover_feed_metrics_recorder_ = nil; - content_suggestions_metrics_recorder_ = nil; } void DiscoverFeedService::OnPrimaryAccountChanged(
diff --git a/ios/chrome/browser/ntp_tiles/BUILD.gn b/ios/chrome/browser/ntp_tiles/BUILD.gn index 4a05e76c..f3c9aa1 100644 --- a/ios/chrome/browser/ntp_tiles/BUILD.gn +++ b/ios/chrome/browser/ntp_tiles/BUILD.gn
@@ -25,7 +25,6 @@ "//ios/chrome/browser/history", "//ios/chrome/browser/json_parser", "//ios/chrome/browser/search_engines", - "//ios/chrome/browser/suggestions", "//ios/web", "//services/network/public/cpp", ]
diff --git a/ios/chrome/browser/omaha/omaha_service.mm b/ios/chrome/browser/omaha/omaha_service.mm index 3152e20..713a24f 100644 --- a/ios/chrome/browser/omaha/omaha_service.mm +++ b/ios/chrome/browser/omaha/omaha_service.mm
@@ -410,10 +410,6 @@ number_of_tries_ = [defaults integerForKey:kNumberTriesKey]; last_sent_time_ = base::Time::FromCFAbsoluteTime([defaults doubleForKey:kLastSentTimeKey]); - last_server_date_ = [defaults integerForKey:kLastServerDateKey]; - if (last_server_date_ == 0) { - last_server_date_ = -2; // -2 indicates "unknown" to the Omaha Server. - } NSString* lastSentVersion = [defaults stringForKey:kLastSentVersionKey]; if (lastSentVersion) { last_sent_version_ = @@ -421,6 +417,19 @@ } else { last_sent_version_ = base::Version(kDefaultLastSentVersion); } + last_server_date_ = [defaults integerForKey:kLastServerDateKey]; + if (last_server_date_ == 0) { + if (lastSentVersion) { + // If there is a record of the last sent version but no record of the + // last server date, this client has upgraded from a version of Chrome + // that did not support saving the last server date. Send -2 ("unknown"). + last_server_date_ = -2; + } else { + // If there is neither a last server date nor last sent version, this is + // a fresh install. Send -1 ("first active"). + last_server_date_ = -1; + } + } application_install_date_ = GetApplicationContext()->GetLocalState()->GetInt64( @@ -586,16 +595,17 @@ // Set up <updatecheck/> xml_wrapper.StartElement("updatecheck"); xml_wrapper.EndElement(); - - // Set up <ping active=1/> - std::string last_server_date = base::StringPrintf("%d", last_server_date_); - xml_wrapper.StartElement("ping"); - xml_wrapper.WriteAttribute("active", "1"); - xml_wrapper.WriteAttribute("ad", last_server_date.c_str()); - xml_wrapper.WriteAttribute("rd", last_server_date.c_str()); - xml_wrapper.EndElement(); } + // Set up <ping ... /> + const std::string last_server_date = + base::StringPrintf("%d", last_server_date_); + xml_wrapper.StartElement("ping"); + xml_wrapper.WriteAttribute("active", "1"); + xml_wrapper.WriteAttribute("ad", last_server_date.c_str()); + xml_wrapper.WriteAttribute("rd", last_server_date.c_str()); + xml_wrapper.EndElement(); + // End app. xml_wrapper.EndElement(); // End request.
diff --git a/ios/chrome/browser/omaha/omaha_service_unittest.mm b/ios/chrome/browser/omaha/omaha_service_unittest.mm index 97e5cdb..aa33681 100644 --- a/ios/chrome/browser/omaha/omaha_service_unittest.mm +++ b/ios/chrome/browser/omaha/omaha_service_unittest.mm
@@ -142,7 +142,7 @@ " brand=\"[A-Z][A-Z][A-Z][A-Z]\" client=\"\" appid=\"{[^}]*}\"" " installage=\"0\">" "<updatecheck/>" - "<ping active=\"1\" ad=\"-2\" rd=\"-2\"/></app></request>"; + "<ping active=\"1\" ad=\"-1\" rd=\"-1\"/></app></request>"; OmahaService service(false); service.StartInternal(); @@ -170,7 +170,7 @@ "<app version=\"[^\"]*\" nextversion=\"\" ap=\"[^\"]*\" lang=\"[^\"]*\"" " brand=\"[A-Z][A-Z][A-Z][A-Z]\" client=\"\" appid=\"{[^}]*}\">" "<updatecheck/>" - "<ping active=\"1\" ad=\"-2\" rd=\"-2\"/></app></request>"; + "<ping active=\"1\" ad=\"-1\" rd=\"-1\"/></app></request>"; OmahaService service(false); service.StartInternal(); @@ -201,6 +201,7 @@ " brand=\"[A-Z][A-Z][A-Z][A-Z]\" client=\"\" appid=\"{[^}]*}\"" " installage=\"%d\">" "<event eventtype=\"%d\" eventresult=\"1\"/>" + "<ping active=\"1\" ad=\"-1\" rd=\"-1\"/>" "</app></request>"; // First install. @@ -758,6 +759,7 @@ test_application_id() + "\" status=\"ok\">" "<event status=\"ok\"/>" + "<ping status=\"ok\"/>" "</app></response>"; auto* pending_request = test_url_loader_factory_.GetPendingRequest(0); test_url_loader_factory_.SimulateResponseForPendingRequest(
diff --git a/ios/chrome/browser/pref_names.cc b/ios/chrome/browser/pref_names.cc index fe39cfd..b0be1c5 100644 --- a/ios/chrome/browser/pref_names.cc +++ b/ios/chrome/browser/pref_names.cc
@@ -132,6 +132,11 @@ const char kSigninShouldPromptForSigninAgain[] = "ios.signin.should_prompt_for_signin_again"; +// Number of times the user dismissed the web sign-in dialog. This value is +// reset to zero when the user signs in (using the web sign-in dialog). +const char kSigninWebSignDismissalCount[] = + "ios.signin.web_signin_dismissal_count"; + // Integer to count the number of times the MICE web sign-in is displayed. const char kSigninBottomSheetShownCount[] = "ios.signin.bottom_sheet_shown_count";
diff --git a/ios/chrome/browser/pref_names.h b/ios/chrome/browser/pref_names.h index 73b3cea..849253d 100644 --- a/ios/chrome/browser/pref_names.h +++ b/ios/chrome/browser/pref_names.h
@@ -42,6 +42,7 @@ extern const char kSigninLastAccounts[]; extern const char kSigninLastAccountsMigrated[]; extern const char kSigninShouldPromptForSigninAgain[]; +extern const char kSigninWebSignDismissalCount[]; extern const char kSigninBottomSheetShownCount[]; extern const char kIosUserZoomMultipliers[];
diff --git a/ios/chrome/browser/suggestions/BUILD.gn b/ios/chrome/browser/suggestions/BUILD.gn deleted file mode 100644 index 5ec806bdf..0000000 --- a/ios/chrome/browser/suggestions/BUILD.gn +++ /dev/null
@@ -1,23 +0,0 @@ -# Copyright 2016 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -source_set("suggestions") { - configs += [ "//build/config/compiler:enable_arc" ] - sources = [ - "suggestions_service_factory.h", - "suggestions_service_factory.mm", - ] - deps = [ - "//base", - "//components/browser_sync", - "//components/keyed_service/ios", - "//components/signin/public/identity_manager", - "//components/suggestions", - "//ios/chrome/browser/browser_state", - "//ios/chrome/browser/signin", - "//ios/chrome/browser/sync", - "//ios/web", - "//net", - ] -}
diff --git a/ios/chrome/browser/suggestions/DIR_METADATA b/ios/chrome/browser/suggestions/DIR_METADATA deleted file mode 100644 index e3fa31a..0000000 --- a/ios/chrome/browser/suggestions/DIR_METADATA +++ /dev/null
@@ -1,12 +0,0 @@ -# Metadata information for this directory. -# -# For more information on DIR_METADATA files, see: -# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/README.md -# -# For the schema of this file, see Metadata message: -# https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/proto/dir_metadata.proto - -monorail { - component: "UI>Browser>NewTabPage" -} -team_email: "ntp-dev@chromium.org" \ No newline at end of file
diff --git a/ios/chrome/browser/suggestions/OWNERS b/ios/chrome/browser/suggestions/OWNERS deleted file mode 100644 index 8fde2a2..0000000 --- a/ios/chrome/browser/suggestions/OWNERS +++ /dev/null
@@ -1,3 +0,0 @@ -justincohen@chromium.org -mathp@chromium.org -rohitrao@chromium.org
diff --git a/ios/chrome/browser/suggestions/suggestions_service_factory.h b/ios/chrome/browser/suggestions/suggestions_service_factory.h deleted file mode 100644 index 3264585..0000000 --- a/ios/chrome/browser/suggestions/suggestions_service_factory.h +++ /dev/null
@@ -1,47 +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. - -#ifndef IOS_CHROME_BROWSER_SUGGESTIONS_SUGGESTIONS_SERVICE_FACTORY_H_ -#define IOS_CHROME_BROWSER_SUGGESTIONS_SUGGESTIONS_SERVICE_FACTORY_H_ - -#include <memory> - -#include "base/macros.h" -#include "base/no_destructor.h" -#include "components/keyed_service/ios/browser_state_keyed_service_factory.h" - -class ChromeBrowserState; - -namespace suggestions { - -class SuggestionsService; - -// Singleton that owns all SuggestionsServices and associates them with -// web::BrowserState. -class SuggestionsServiceFactory : public BrowserStateKeyedServiceFactory { - public: - static SuggestionsServiceFactory* GetInstance(); - - // Returns the SuggestionsService for |browser_state|. - static SuggestionsService* GetForBrowserState( - ChromeBrowserState* browser_state); - - private: - friend class base::NoDestructor<SuggestionsServiceFactory>; - - SuggestionsServiceFactory(); - ~SuggestionsServiceFactory() override; - - // BrowserStateKeyedServiceFactory implementation. - std::unique_ptr<KeyedService> BuildServiceInstanceFor( - web::BrowserState* context) const override; - void RegisterBrowserStatePrefs( - user_prefs::PrefRegistrySyncable* registry) override; - - DISALLOW_COPY_AND_ASSIGN(SuggestionsServiceFactory); -}; - -} // namespace suggestions - -#endif // IOS_CHROME_BROWSER_SUGGESTIONS_SUGGESTIONS_SERVICE_FACTORY_H_
diff --git a/ios/chrome/browser/suggestions/suggestions_service_factory.mm b/ios/chrome/browser/suggestions/suggestions_service_factory.mm deleted file mode 100644 index dc4f48eb..0000000 --- a/ios/chrome/browser/suggestions/suggestions_service_factory.mm +++ /dev/null
@@ -1,83 +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. - -#include "ios/chrome/browser/suggestions/suggestions_service_factory.h" - -#include <memory> -#include <utility> - -#include "base/files/file_path.h" -#include "base/no_destructor.h" -#include "base/task/post_task.h" -#include "base/time/default_tick_clock.h" -#include "components/keyed_service/ios/browser_state_dependency_manager.h" -#include "components/signin/public/identity_manager/identity_manager.h" -#include "components/suggestions/blocklist_store.h" -#include "components/suggestions/suggestions_service_impl.h" -#include "components/suggestions/suggestions_store.h" -#include "components/sync/driver/sync_service.h" -#include "ios/chrome/browser/browser_state/chrome_browser_state.h" -#include "ios/chrome/browser/signin/identity_manager_factory.h" -#include "ios/chrome/browser/sync/sync_service_factory.h" -#include "ios/web/public/browser_state.h" -#include "ios/web/public/thread/web_thread.h" -#include "services/network/public/cpp/shared_url_loader_factory.h" - -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - -namespace suggestions { - -// static -SuggestionsServiceFactory* SuggestionsServiceFactory::GetInstance() { - static base::NoDestructor<SuggestionsServiceFactory> instance; - return instance.get(); -} - -// static -SuggestionsService* SuggestionsServiceFactory::GetForBrowserState( - ChromeBrowserState* browser_state) { - return static_cast<SuggestionsService*>( - GetInstance()->GetServiceForBrowserState(browser_state, true)); -} - -SuggestionsServiceFactory::SuggestionsServiceFactory() - : BrowserStateKeyedServiceFactory( - "SuggestionsService", - BrowserStateDependencyManager::GetInstance()) { - DependsOn(IdentityManagerFactory::GetInstance()); - DependsOn(SyncServiceFactory::GetInstance()); -} - -SuggestionsServiceFactory::~SuggestionsServiceFactory() { -} - -std::unique_ptr<KeyedService> -SuggestionsServiceFactory::BuildServiceInstanceFor( - web::BrowserState* context) const { - ChromeBrowserState* browser_state = - ChromeBrowserState::FromBrowserState(context); - signin::IdentityManager* identity_manager = - IdentityManagerFactory::GetForBrowserState(browser_state); - syncer::SyncService* sync_service = - SyncServiceFactory::GetForBrowserState(browser_state); - - std::unique_ptr<SuggestionsStore> suggestions_store( - new SuggestionsStore(browser_state->GetPrefs())); - std::unique_ptr<BlocklistStore> blocked_suggestions( - new BlocklistStore(browser_state->GetPrefs())); - - return std::make_unique<SuggestionsServiceImpl>( - identity_manager, sync_service, - browser_state->GetSharedURLLoaderFactory(), std::move(suggestions_store), - std::move(blocked_suggestions), base::DefaultTickClock::GetInstance()); -} - -void SuggestionsServiceFactory::RegisterBrowserStatePrefs( - user_prefs::PrefRegistrySyncable* registry) { - SuggestionsServiceImpl::RegisterProfilePrefs(registry); -} - -} // namespace suggestions
diff --git a/ios/chrome/browser/ui/authentication/signin/consistency_promo_signin/consistency_promo_signin_coordinator.mm b/ios/chrome/browser/ui/authentication/signin/consistency_promo_signin/consistency_promo_signin_coordinator.mm index 0d21370..fecf0bf 100644 --- a/ios/chrome/browser/ui/authentication/signin/consistency_promo_signin/consistency_promo_signin_coordinator.mm +++ b/ios/chrome/browser/ui/authentication/signin/consistency_promo_signin/consistency_promo_signin_coordinator.mm
@@ -406,6 +406,11 @@ - (void)consistencyDefaultAccountCoordinatorSkip: (ConsistencyDefaultAccountCoordinator*)coordinator { + ChromeBrowserState* browserState = self.browser->GetBrowserState(); + PrefService* userPrefService = browserState->GetPrefs(); + const int skipCounter = + userPrefService->GetInteger(prefs::kSigninWebSignDismissalCount) + 1; + userPrefService->SetInteger(prefs::kSigninWebSignDismissalCount, skipCounter); [self dismissNavigationViewController]; }
diff --git a/ios/chrome/browser/ui/authentication/signin/signin_coordinator.mm b/ios/chrome/browser/ui/authentication/signin/signin_coordinator.mm index ff1520b5..59a877c5 100644 --- a/ios/chrome/browser/ui/authentication/signin/signin_coordinator.mm +++ b/ios/chrome/browser/ui/authentication/signin/signin_coordinator.mm
@@ -6,6 +6,8 @@ #include "base/notreached.h" #import "components/pref_registry/pref_registry_syncable.h" +#import "components/prefs/pref_service.h" +#import "components/signin/public/base/account_consistency_method.h" #include "ios/chrome/browser/browser_state/chrome_browser_state.h" #import "ios/chrome/browser/main/browser.h" #import "ios/chrome/browser/pref_names.h" @@ -30,11 +32,23 @@ using signin_metrics::AccessPoint; using signin_metrics::PromoAction; +namespace { + +// Parameter for web signin dismissal count. +// This parameter is releated to kMICEWebSignIn feature. +const char* kConsecutiveActiveDismissalLimitParam = + "consecutive_active_dismissal_limit"; +// Default web sign-in dismissal count. +constexpr int kDefaultSignInWebSignInDismissalCount = 3; + +} // namespace + @implementation SigninCoordinator + (void)registerBrowserStatePrefs:(user_prefs::PrefRegistrySyncable*)registry { // ConsistencyPromoSigninCoordinator. registry->RegisterIntegerPref(prefs::kSigninBottomSheetShownCount, 0); + registry->RegisterIntegerPref(prefs::kSigninWebSignDismissalCount, 0); } + (instancetype) @@ -165,6 +179,16 @@ SUPPRESSED_SIGNIN_NOT_ALLOWED); return nil; } + const int maxDismissalCount = base::GetFieldTrialParamByFeatureAsInt( + signin::kMICEWebSignIn, kConsecutiveActiveDismissalLimitParam, + kDefaultSignInWebSignInDismissalCount); + if (userPrefService->GetInteger(prefs::kSigninWebSignDismissalCount) > + maxDismissalCount) { + RecordConsistencyPromoUserAction( + signin_metrics::AccountConsistencyPromoAction:: + SUPPRESSED_CONSECUTIVE_DISMISSALS); + return nil; + } return [[ConsistencyPromoSigninCoordinator alloc] initWithBaseViewController:viewController browser:browser];
diff --git a/ios/chrome/browser/ui/content_suggestions/BUILD.gn b/ios/chrome/browser/ui/content_suggestions/BUILD.gn index faabc32..4a257bc 100644 --- a/ios/chrome/browser/ui/content_suggestions/BUILD.gn +++ b/ios/chrome/browser/ui/content_suggestions/BUILD.gn
@@ -7,6 +7,8 @@ "content_suggestions_action_handler.h", "content_suggestions_alert_factory.h", "content_suggestions_alert_factory.mm", + "content_suggestions_category_wrapper.h", + "content_suggestions_category_wrapper.mm", "content_suggestions_consumer.h", "content_suggestions_coordinator.h", "content_suggestions_coordinator.mm", @@ -16,6 +18,8 @@ "content_suggestions_header_view_controller.mm", "content_suggestions_mediator.h", "content_suggestions_mediator.mm", + "content_suggestions_metrics_recorder.h", + "content_suggestions_metrics_recorder.mm", "content_suggestions_service_bridge_observer.h", "content_suggestions_service_bridge_observer.mm", "discover_feed_delegate.h", @@ -29,7 +33,6 @@ ] deps = [ ":constants", - ":content_suggestions_util", ":feature_flags", ":metrics", "//base", @@ -112,18 +115,6 @@ configs += [ "//build/config/compiler:enable_arc" ] } -source_set("content_suggestions_util") { - sources = [ - "content_suggestions_category_wrapper.h", - "content_suggestions_category_wrapper.mm", - ] - deps = [ - "//base", - "//components/ntp_snippets", - ] - configs += [ "//build/config/compiler:enable_arc" ] -} - source_set("constants") { sources = [ "content_suggestions_constants.h", @@ -155,6 +146,7 @@ "content_suggestions_layout.h", "content_suggestions_layout.mm", "content_suggestions_menu_provider.h", + "content_suggestions_metrics_recording.h", "content_suggestions_view_controller.h", "content_suggestions_view_controller.mm", "content_suggestions_view_controller_audience.h", @@ -210,22 +202,13 @@ source_set("metrics") { sources = [ - "content_suggestions_metrics_recorder.h", - "content_suggestions_metrics_recorder.mm", - "content_suggestions_metrics_recording.h", "discover_feed_metrics_recorder.h", "discover_feed_metrics_recorder.mm", ] deps = [ - ":content_suggestions_util", ":feature_flags", "//base", "//components/feed/core/v2/public:common", - "//components/ntp_snippets", - "//ios/chrome/browser/ui/content_suggestions/cells", - "//ios/chrome/browser/ui/content_suggestions/cells:cells_ui", - "//ios/chrome/browser/ui/content_suggestions/identifier", - "//ui/base", ] configs += [ "//build/config/compiler:enable_arc" ] } @@ -282,7 +265,6 @@ ":content_suggestions", ":content_suggestions_ui", ":content_suggestions_ui_util", - ":content_suggestions_util", "//base", "//base/test:test_support", "//components/ntp_snippets",
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_coordinator.h b/ios/chrome/browser/ui/content_suggestions/content_suggestions_coordinator.h index 7988127c..b5175e4 100644 --- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_coordinator.h +++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_coordinator.h
@@ -13,7 +13,6 @@ @class BubblePresenter; @class ContentSuggestionsHeaderViewController; -@class ContentSuggestionsMetricsRecorder; @class DiscoverFeedMetricsRecorder; @protocol NewTabPageCommands; @protocol NewTabPageControllerDelegate; @@ -66,10 +65,6 @@ @property(nonatomic, strong) DiscoverFeedMetricsRecorder* discoverFeedMetricsRecorder; -// Metrics recorder for the Zine feed events related to ContentSuggestions. -@property(nonatomic, strong) - ContentSuggestionsMetricsRecorder* contentSuggestionsMetricsRecorder; - // Dismisses all modals owned by the NTP mediator. - (void)dismissModals;
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_coordinator.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_coordinator.mm index 41a6b30..0a0df66 100644 --- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_coordinator.mm +++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_coordinator.mm
@@ -118,6 +118,7 @@ ContentSuggestionsMediator* contentSuggestionsMediator; @property(nonatomic, strong) ContentSuggestionsHeaderSynchronizer* headerCollectionInteractionHandler; +@property(nonatomic, strong) ContentSuggestionsMetricsRecorder* metricsRecorder; @property(nonatomic, strong) UIViewController* discoverFeedViewController; @property(nonatomic, strong) UIView* discoverFeedHeaderMenuButton; @property(nonatomic, strong) URLDragDropHandler* dragDropHandler; @@ -254,8 +255,9 @@ self.headerController.promoCanShow = [self.contentSuggestionsMediator notificationPromo]->CanShow(); - self.contentSuggestionsMetricsRecorder.delegate = - self.contentSuggestionsMediator; + self.metricsRecorder = [[ContentSuggestionsMetricsRecorder alloc] init]; + self.metricsRecorder.delegate = self.contentSuggestionsMediator; + // Offset to maintain Discover feed scroll position. CGFloat offset = 0; @@ -282,8 +284,7 @@ self.suggestionsViewController.audience = self; self.suggestionsViewController.overscrollDelegate = self; self.suggestionsViewController.themeChangeDelegate = self; - self.suggestionsViewController.metricsRecorder = - self.contentSuggestionsMetricsRecorder; + self.suggestionsViewController.metricsRecorder = self.metricsRecorder; id<SnackbarCommands> dispatcher = static_cast<id<SnackbarCommands>>(self.browser->GetCommandDispatcher()); self.suggestionsViewController.dispatcher = dispatcher; @@ -316,7 +317,7 @@ self.ntpMediator.NTPMetrics = [[NTPHomeMetrics alloc] initWithBrowserState:self.browser->GetBrowserState() webState:self.webState]; - self.ntpMediator.metricsRecorder = self.contentSuggestionsMetricsRecorder; + self.ntpMediator.metricsRecorder = self.metricsRecorder; self.ntpMediator.suggestionsViewController = self.suggestionsViewController; self.ntpMediator.suggestionsMediator = self.contentSuggestionsMediator; self.ntpMediator.suggestionsService = contentSuggestionsService;
diff --git a/ios/chrome/browser/ui/infobars/BUILD.gn b/ios/chrome/browser/ui/infobars/BUILD.gn index bcde93a..21fee48 100644 --- a/ios/chrome/browser/ui/infobars/BUILD.gn +++ b/ios/chrome/browser/ui/infobars/BUILD.gn
@@ -63,8 +63,6 @@ source_set("infobars_ui") { configs += [ "//build/config/compiler:enable_arc" ] sources = [ - "confirm_infobar_view.h", - "confirm_infobar_view.mm", "infobar_badge_ui_delegate.h", "infobar_container_consumer.h", "infobar_ui_delegate.h", @@ -118,10 +116,7 @@ source_set("unit_tests") { configs += [ "//build/config/compiler:enable_arc" ] testonly = true - sources = [ - "confirm_infobar_view_unittest.mm", - "infobar_container_coordinator_unittest.mm", - ] + sources = [ "infobar_container_coordinator_unittest.mm" ] deps = [ ":feature_flags", ":infobars",
diff --git a/ios/chrome/browser/ui/infobars/confirm_infobar_view.h b/ios/chrome/browser/ui/infobars/confirm_infobar_view.h deleted file mode 100644 index 96a128b53..0000000 --- a/ios/chrome/browser/ui/infobars/confirm_infobar_view.h +++ /dev/null
@@ -1,67 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef IOS_CHROME_BROWSER_UI_INFOBARS_CONFIRM_INFOBAR_VIEW_H_ -#define IOS_CHROME_BROWSER_UI_INFOBARS_CONFIRM_INFOBAR_VIEW_H_ - -#import <UIKit/UIKit.h> - -#import "ios/chrome/browser/ui/fancy_ui/bidi_container_view.h" - -// An infobar with an optional message, icon, two action buttons, and a switch. -@interface ConfirmInfoBarView : BidiContainerView - -// Label text with links initialized with |stringAsLink:|. -@property(nonatomic, strong, readonly) NSString* markedLabel; - -// TODO(crbug.com/302582): rename methods from add* to set*. -// Adds a dismiss button subview. -- (void)addCloseButtonWithTag:(NSInteger)tag - target:(id)target - action:(SEL)action; - -// Adds icon subview. This image will be rendered as a template image. -- (void)addLeftIcon:(UIImage*)image; - -// Creates a new string from |string| that is interpreted as a link by -// |addLabel:|. |tag| must not be 0. -+ (NSString*)stringAsLink:(NSString*)string tag:(NSUInteger)tag; - -// Adds a message to the infobar that optionaly contains links initialized with -// |stringAsLink:|. -- (void)addLabel:(NSString*)label; - -// Adds a message to the infobar that optionaly contains links initialized with -// |stringAsLink:|. |action| is called when a link is clicked, with the tag -// associated with the link passed as a parameter.. -- (void)addLabel:(NSString*)label action:(void (^)(NSUInteger))action; - -// Adds two buttons to the infobar. Button1 is the primary action of the infobar -// and in Material Design mode is shown with bold colors to reflect this role. -- (void)addButton1:(NSString*)title1 - tag1:(NSInteger)tag1 - button2:(NSString*)title2 - tag2:(NSInteger)tag2 - target:(id)target - action:(SEL)action; - -// Adds a button to the infobar. -- (void)addButton:(NSString*)title - tag:(NSInteger)tag - target:(id)target - action:(SEL)action; - -// Adds to the infobar a switch and an adjacent label. -- (void)addSwitchWithLabel:(NSString*)label - isOn:(BOOL)isOn - tag:(NSInteger)tag - target:(id)target - action:(SEL)action; - -// Adds to the infobar a footer label below the title. -- (void)addFooterLabel:(NSString*)label; - -@end - -#endif // IOS_CHROME_BROWSER_UI_INFOBARS_CONFIRM_INFOBAR_VIEW_H_
diff --git a/ios/chrome/browser/ui/infobars/confirm_infobar_view.mm b/ios/chrome/browser/ui/infobars/confirm_infobar_view.mm deleted file mode 100644 index 819e7235..0000000 --- a/ios/chrome/browser/ui/infobars/confirm_infobar_view.mm +++ /dev/null
@@ -1,1110 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import "ios/chrome/browser/ui/infobars/confirm_infobar_view.h" - -#import <CoreGraphics/CoreGraphics.h> -#import <QuartzCore/QuartzCore.h> - -#import <MaterialComponents/MaterialButtons.h> - -#include "base/check_op.h" -#include "base/format_macros.h" -#include "base/i18n/rtl.h" -#include "base/mac/foundation_util.h" -#include "base/notreached.h" -#include "base/strings/sys_string_conversions.h" -#include "components/strings/grit/components_strings.h" -#import "ios/chrome/browser/ui/colors/MDCPalette+CrAdditions.h" -#import "ios/chrome/browser/ui/infobars/infobar_constants.h" -#import "ios/chrome/browser/ui/toolbar/public/toolbar_constants.h" -#import "ios/chrome/browser/ui/util/label_link_controller.h" -#import "ios/chrome/browser/ui/util/named_guide.h" -#import "ios/chrome/browser/ui/util/uikit_ui_util.h" -#import "ios/chrome/common/ui/colors/semantic_color_names.h" -#import "ios/chrome/common/ui/util/pointer_interaction_util.h" -#include "ios/chrome/grit/ios_theme_resources.h" -#include "ui/base/l10n/l10n_util.h" -#include "ui/base/resource/resource_bundle.h" -#import "ui/gfx/ios/NSString+CrStringDrawing.h" -#import "ui/gfx/ios/uikit_util.h" -#include "url/gurl.h" - -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - -namespace { - -const char kChromeInfobarURL[] = "chromeinternal://infobar/"; - -// UX configuration metrics for the layout of items. -struct LayoutMetrics { - CGFloat left_margin_on_first_line_when_icon_absent; - CGFloat minimum_space_between_right_and_left_aligned_widgets; - CGFloat right_margin; - CGFloat space_between_widgets; - CGFloat close_button_inner_padding; - CGFloat button_height; - CGFloat button_margin; - CGFloat extra_button_margin_on_single_line; - CGFloat button_spacing; - CGFloat button_width_units; - CGFloat buttons_margin_top; - CGFloat close_button_margin_left; - CGFloat label_line_spacing; - CGFloat label_margin_bottom; - CGFloat extra_margin_between_label_and_button; - CGFloat label_margin_top; - CGFloat minimum_infobar_height; - CGFloat horizontal_space_between_icon_and_text; -}; - -const LayoutMetrics kLayoutMetrics = { - 20.0, // left_margin_on_first_line_when_icon_absent - 30.0, // minimum_space_between_right_and_left_aligned_widgets - 10.0, // right_margin - 10.0, // space_between_widgets - 8.0, // close_button_inner_padding - 36.0, // button_height - 16.0, // button_margin - 8.0, // extra_button_margin_on_single_line - 8.0, // button_spacing - 8.0, // button_width_units - 16.0, // buttons_margin_top - 16.0, // close_button_margin_left - 5.0, // label_line_spacing - 22.0, // label_margin_bottom - 0.0, // extra_margin_between_label_and_button - 21.0, // label_margin_top - 68.0, // minimum_infobar_height - 16.0 // horizontal_space_between_icon_and_text -}; - -// Corner radius for action buttons. -const CGFloat kButtonCornerRadius = 8.0; - -enum InfoBarButtonPosition { ON_FIRST_LINE, CENTER, LEFT, RIGHT }; - -// Returns the font for the Infobar's main body text. -UIFont* InfoBarLabelFont() { - // Due to https://crbug.com/989761, disable dynamic type. Once migration to - // Messages is complete, this class will be deleted. - if (@available(iOS 13, *)) { - return [UIFont systemFontOfSize:17]; - } else { - return [UIFont preferredFontForTextStyle:UIFontTextStyleBody]; - } -} - -// Returns the font for the Infobar's toggle switch's (if one exists) body text. -UIFont* InfoBarSwitchLabelFont() { - // Due to https://crbug.com/989761, disable dynamic type. Once migration to - // Messages is complete, this class will be deleted. - if (@available(iOS 13, *)) { - return [UIFont systemFontOfSize:17]; - } else { - return [UIFont preferredFontForTextStyle:UIFontTextStyleBody]; - } -} - -// Returns the font for the label on Infobar's action buttons. -UIFont* InfoBarButtonLabelFont() { - // Due to https://crbug.com/989761, disable dynamic type. Once migration to - // Messages is complete, this class will be deleted. - if (@available(iOS 13, *)) { - return [UIFont systemFontOfSize:17 weight:UIFontWeightSemibold]; - } else { - return [UIFont preferredFontForTextStyle:UIFontTextStyleHeadline]; - } -} - -UIImage* InfoBarCloseImage() { - ui::ResourceBundle& resourceBundle = ui::ResourceBundle::GetSharedInstance(); - return resourceBundle.GetNativeImageNamed(IDR_IOS_INFOBAR_CLOSE).ToUIImage(); -} - -} // namespace - -// UIView containing a label. -@interface InfobarFooterView : BidiContainerView - -@property(nonatomic, readonly) UILabel* label; -@property(nonatomic) CGFloat preferredLabelWidth; - -// Initialize the view's label with |labelText|. -- (instancetype)initWithText:(NSString*)labelText NS_DESIGNATED_INITIALIZER; - -- (instancetype)initWithFrame:(CGRect)frame NS_UNAVAILABLE; -- (instancetype)initWithCoder:(NSCoder*)aDecoder NS_UNAVAILABLE; - -// Returns the height taken by the view constrained by a width of |width|. -// If |layout| is yes, it sets the frame of the view to fit |width|. -- (CGFloat)heightRequiredForFooterWithWidth:(CGFloat)width layout:(BOOL)layout; - -// Returns the preferred width. A smaller width requires eliding the text. -- (CGFloat)preferredWidth; -@end - -@implementation InfobarFooterView - -- (instancetype)initWithText:(NSString*)labelText { - // Creates label. - UILabel* label = [[UILabel alloc] initWithFrame:CGRectZero]; - label.textAlignment = NSTextAlignmentNatural; - label.font = InfoBarSwitchLabelFont(); - label.text = labelText; - label.textColor = [UIColor colorNamed:kTextSecondaryColor]; - label.backgroundColor = UIColor.clearColor; - label.lineBreakMode = NSLineBreakByWordWrapping; - label.numberOfLines = 0; - label.adjustsFontSizeToFitWidth = NO; - [label sizeToFit]; - - self = [super initWithFrame:label.frame]; - if (!self) - return nil; - _label = label; - _preferredLabelWidth = CGRectGetMaxX(_label.frame); - [self addSubview:_label]; - return self; -} - -- (CGFloat)heightRequiredForFooterWithWidth:(CGFloat)width layout:(BOOL)layout { - CGFloat widthLeftForLabel = width; - CGSize maxSize = CGSizeMake(widthLeftForLabel, CGFLOAT_MAX); - CGSize labelSize = - [[self.label text] cr_boundingSizeWithSize:maxSize - font:[self.label font]]; - CGFloat viewHeight = labelSize.height; - if (layout) { - // Lays out the label and the switch to fit in {width, viewHeight}. - CGRect newLabelFrame = CGRectMake(0, 0, labelSize.width, labelSize.height); - newLabelFrame = AlignRectOriginAndSizeToPixels(newLabelFrame); - [self.label setFrame:newLabelFrame]; - } - return viewHeight; -} - -- (CGFloat)preferredWidth { - return self.preferredLabelWidth; -} - -@end - -// UIView containing a switch and a label. -@interface SwitchView : InfobarFooterView - -// Initialize the view's label with |labelText|. -- (instancetype)initWithText:(NSString*)labelText - isOn:(BOOL)isOn NS_DESIGNATED_INITIALIZER; -- (instancetype)initWithText:(NSString*)labelText NS_UNAVAILABLE; - -// Specifies the object, action, and tag used when the switch is toggled. -- (void)setTag:(NSInteger)tag target:(id)target action:(SEL)action; - -// Returns the height taken by the view constrained by a width of |width|. -// If |layout| is yes, it sets the frame of the label and the switch to fit -// |width|. -- (CGFloat)heightRequiredForFooterWithWidth:(CGFloat)width layout:(BOOL)layout; - -// Returns the preferred width. A smaller width requires eliding the text. -- (CGFloat)preferredWidth; - -@end - -@implementation SwitchView { - UISwitch* _switch; - CGFloat _preferredTotalWidth; - // Layout metrics for calculating item placement. - const LayoutMetrics* _metrics; -} - -- (instancetype)initWithText:(NSString*)labelText isOn:(BOOL)isOn { - _metrics = &kLayoutMetrics; - - self = [super initWithText:labelText]; - if (!self) - return nil; - - self.label.textColor = [UIColor colorNamed:kTextPrimaryColor]; - _switch = [[UISwitch alloc] initWithFrame:CGRectZero]; - _switch.exclusiveTouch = YES; - _switch.accessibilityLabel = labelText; - _switch.onTintColor = [UIColor colorNamed:kBlueColor]; - _switch.on = isOn; - - // Computes the size and initializes the view. - CGSize labelSize = self.label.frame.size; - CGSize switchSize = _switch.frame.size; - CGRect frameRect = CGRectMake( - 0, 0, - labelSize.width + _metrics->space_between_widgets + switchSize.width, - std::max(labelSize.height, switchSize.height)); - [self setFrame:frameRect]; - - // Sets the position of the label and the switch. The label is left aligned - // and the switch is right aligned. Both are vertically centered. - CGRect labelFrame = - CGRectMake(0, (self.frame.size.height - labelSize.height) / 2, - labelSize.width, labelSize.height); - CGRect switchFrame = - CGRectMake(self.frame.size.width - switchSize.width, - (self.frame.size.height - switchSize.height) / 2, - switchSize.width, switchSize.height); - - labelFrame = AlignRectOriginAndSizeToPixels(labelFrame); - switchFrame = AlignRectOriginAndSizeToPixels(switchFrame); - - [self.label setFrame:labelFrame]; - [_switch setFrame:switchFrame]; - _preferredTotalWidth = CGRectGetMaxX(switchFrame); - self.preferredLabelWidth = CGRectGetMaxX(labelFrame); - - [self addSubview:self.label]; - [self addSubview:_switch]; - return self; -} - -- (void)setTag:(NSInteger)tag target:(id)target action:(SEL)action { - [_switch setTag:tag]; - [_switch addTarget:target - action:action - forControlEvents:UIControlEventValueChanged]; -} - -- (CGFloat)heightRequiredForFooterWithWidth:(CGFloat)width layout:(BOOL)layout { - CGFloat widthLeftForLabel = - width - [_switch frame].size.width - _metrics->space_between_widgets; - CGSize maxSize = CGSizeMake(widthLeftForLabel, CGFLOAT_MAX); - CGSize labelSize = - [[self.label text] cr_boundingSizeWithSize:maxSize - font:[self.label font]]; - CGFloat viewHeight = std::max(labelSize.height, [_switch frame].size.height); - if (layout) { - // Lays out the label and the switch to fit in {width, viewHeight}. - CGRect newLabelFrame; - newLabelFrame.origin.x = 0; - newLabelFrame.origin.y = (viewHeight - labelSize.height) / 2; - newLabelFrame.size = labelSize; - newLabelFrame = AlignRectOriginAndSizeToPixels(newLabelFrame); - [self.label setFrame:newLabelFrame]; - CGRect newSwitchFrame; - newSwitchFrame.origin.x = - CGRectGetMaxX(newLabelFrame) + _metrics->space_between_widgets; - newSwitchFrame.origin.y = (viewHeight - [_switch frame].size.height) / 2; - newSwitchFrame.size = [_switch frame].size; - newSwitchFrame = AlignRectOriginAndSizeToPixels(newSwitchFrame); - [_switch setFrame:newSwitchFrame]; - } - return viewHeight; -} - -- (CGFloat)preferredWidth { - return _preferredTotalWidth; -} - -@end - -@interface ConfirmInfoBarView (Testing) -// Returns the buttons' height. -- (CGFloat)buttonsHeight; -// Returns the button margin applied in some views. -- (CGFloat)buttonMargin; -// Returns the height of the infobar, and lays out the subviews if |layout| is -// YES. -- (CGFloat)computeRequiredHeightAndLayoutSubviews:(BOOL)layout; -// Returns the height of the laid out buttons when not on the first line. -// Either the buttons are narrow enough and they are on a single line next to -// each other, or they are supperposed on top of each other. -// Also lays out the buttons when |layout| is YES, in which case it uses -// |heightOfFirstLine| to compute their vertical position. -- (CGFloat)heightThatFitsButtonsUnderOtherWidgets:(CGFloat)heightOfFirstLine - layout:(BOOL)layout; -// The |button| is positioned with the right edge at the specified y-axis -// position |rightEdge| and the top row at |y|. -// Returns the left edge of the newly-positioned button. -- (CGFloat)layoutWideButtonAlignRight:(UIButton*)button - rightEdge:(CGFloat)rightEdge - y:(CGFloat)y; -// Returns the minimum height of infobars. -- (CGFloat)minimumInfobarHeight; -// Returns |string| stripped of the markers specifying the links and fills -// |linkRanges_| with the ranges of the enclosed links. -- (NSString*)stripMarkersFromString:(NSString*)string; -// Returns the ranges of the links and the associated tags. -- (const std::vector<std::pair<NSUInteger, NSRange>>&)linkRanges; -@end - -@interface ConfirmInfoBarView () - -// Returns the marker delimiting the start of a link. -+ (NSString*)openingMarkerForLink; -// Returns the marker delimiting the end of a link. -+ (NSString*)closingMarkerForLink; - -// How much of the infobar (in points) is visible (e.g., during showing/hiding -// animation). -@property(nonatomic, assign) CGFloat visibleHeight; - -// Separator above the view separating it from the web content. -@property(nonatomic, strong) UIView* separator; - -@end - -@implementation ConfirmInfoBarView { - // The height of this infobar when fully visible. - CGFloat _targetHeight; - // View containing the icon. - UIImageView* _imageView; - // Close button. - UIButton* _closeButton; - // View containing the label and maybe switch. - InfobarFooterView* _InfobarFooterView; - // We are using a LabelLinkController with an UILabel to be able to have - // parts of the label underlined and clickable. This label_ may be nil if - // the delegate returns an empty string for GetMessageText(). - LabelLinkController* _labelLinkController; - UILabel* _label; - // Array of range information. The first element of the pair is the tag of - // the action and the second element is the range defining the link. - std::vector<std::pair<NSUInteger, NSRange>> _linkRanges; - // Text for the label with link markers included. - NSString* _markedLabel; - // Buttons. - // button1_ is tagged with ConfirmInfoBarDelegate::BUTTON_OK . - // button2_ is tagged with ConfirmInfoBarDelegate::BUTTON_CANCEL . - UIButton* _button1; - UIButton* _button2; - // Drop shadow. - UIImageView* _shadow; - // Layout metrics for calculating item placement. - const LayoutMetrics* _metrics; -} - -@synthesize visibleHeight = _visibleHeight; - -- (instancetype)initWithFrame:(CGRect)frame { - self = [super initWithFrame:frame]; - if (self) { - _metrics = &kLayoutMetrics; - [self setAccessibilityViewIsModal:YES]; - - // Add a separator above the view separating it from the web content. - _separator = [[UIView alloc] init]; - _separator.translatesAutoresizingMaskIntoConstraints = NO; - _separator.backgroundColor = [UIColor colorNamed:kToolbarShadowColor]; - } - return self; -} - -- (NSString*)markedLabel { - return _markedLabel; -} - -// Returns the width reserved for the icon. -- (CGFloat)leftMarginOnFirstLine { - CGFloat leftMargin = 0; - if (_imageView) { - leftMargin += CGRectGetMaxX([self frameOfIcon]); - leftMargin += _metrics->horizontal_space_between_icon_and_text; - } else { - leftMargin += _metrics->left_margin_on_first_line_when_icon_absent; - leftMargin += self.safeAreaInsets.left; - } - return leftMargin; -} - -// Returns the width reserved for the close button. -- (CGFloat)rightMarginOnFirstLine { - return [_closeButton imageView].image.size.width + - _metrics->close_button_inner_padding * 2 + self.safeAreaInsets.right; -} - -// Returns the horizontal space available between the icon and the close -// button. -- (CGFloat)horizontalSpaceAvailableOnFirstLine { - return [self frame].size.width - [self leftMarginOnFirstLine] - - [self rightMarginOnFirstLine]; -} - -// Returns the height taken by a label constrained by a width of |width|. -- (CGFloat)heightRequiredForLabelWithWidth:(CGFloat)width { - return [_label sizeThatFits:CGSizeMake(width, CGFLOAT_MAX)].height; -} - -// Returns the width required by a label if it was displayed on a single line. -- (CGFloat)widthOfLabelOnASingleLine { - // |label_| can be nil when delegate returns "" for GetMessageText(). - if (!_label) - return 0.0; - CGSize rect = [[_label text] cr_pixelAlignedSizeWithFont:[_label font]]; - return rect.width; -} - -// Returns the minimum size required by |button| to be properly displayed. -- (CGFloat)narrowestWidthOfButton:(UIButton*)button { - if (!button) - return 0; - // The button itself is queried for the size. The width is rounded up to be a - // multiple of 8 to fit Material grid spacing requirements. - CGFloat labelWidth = - [button sizeThatFits:CGSizeMake(CGFLOAT_MAX, CGFLOAT_MAX)].width; - return ceil(labelWidth / _metrics->button_width_units) * - _metrics->button_width_units; -} - -// Returns the width of the buttons if they are laid out on the first line. -- (CGFloat)widthOfButtonsOnFirstLine { - CGFloat width = [self narrowestWidthOfButton:_button1] + - [self narrowestWidthOfButton:_button2]; - if (_button1 && _button2) { - width += _metrics->space_between_widgets; - } - return width; -} - -// Returns the width needed for the switch. -- (CGFloat)preferredWidthOfSwitch { - return [_InfobarFooterView preferredWidth]; -} - -// Returns the space required to separate the left aligned widgets (label) from -// the right aligned widgets (switch, buttons), assuming they fit on one line. -- (CGFloat)widthToSeparateRightAndLeftWidgets { - BOOL leftWidgetsArePresent = (_label != nil); - BOOL rightWidgetsArePresent = _button1 || _button2 || _InfobarFooterView; - if (!leftWidgetsArePresent || !rightWidgetsArePresent) - return 0; - return _metrics->minimum_space_between_right_and_left_aligned_widgets; -} - -// Returns the space required to separate the switch and the buttons. -- (CGFloat)widthToSeparateSwitchAndButtons { - BOOL buttonsArePresent = _button1 || _button2; - BOOL switchIsPresent = (_InfobarFooterView != nil); - if (!buttonsArePresent || !switchIsPresent) - return 0; - return _metrics->space_between_widgets; -} - -// Lays out |button| at the height |y| and in the position |position|. -// Must only be used for wide buttons, i.e. buttons not on the first line. -- (void)layoutWideButton:(UIButton*)button - y:(CGFloat)y - position:(InfoBarButtonPosition)position { - CGFloat screenWidth = [self frame].size.width; - CGFloat startPercentage = 0.0; - CGFloat endPercentage = 0.0; - switch (position) { - case LEFT: - startPercentage = 0.0; - endPercentage = 0.5; - break; - case RIGHT: - startPercentage = 0.5; - endPercentage = 1.0; - break; - case CENTER: - startPercentage = 0.0; - endPercentage = 1.0; - break; - case ON_FIRST_LINE: - NOTREACHED(); - } - DCHECK(startPercentage >= 0.0 && startPercentage <= 1.0); - DCHECK(endPercentage >= 0.0 && endPercentage <= 1.0); - DCHECK(startPercentage < endPercentage); - // In Material the button is not stretched to fit the available space. It is - // placed centrally in the allotted space. - CGFloat minX = screenWidth * startPercentage; - CGFloat maxX = screenWidth * endPercentage; - CGFloat midpoint = (minX + maxX) / 2; - CGFloat minWidth = - std::min([self narrowestWidthOfButton:button], maxX - minX); - CGFloat left = midpoint - minWidth / 2; - CGRect frame = CGRectMake(left, y, minWidth, _metrics->button_height); - frame = AlignRectOriginAndSizeToPixels(frame); - [button setFrame:frame]; -} - -- (CGFloat)layoutWideButtonAlignRight:(UIButton*)button - rightEdge:(CGFloat)rightEdge - y:(CGFloat)y { - CGFloat width = [self narrowestWidthOfButton:button]; - CGFloat leftEdge = rightEdge - width; - CGRect frame = CGRectMake(leftEdge, y, width, _metrics->button_height); - frame = AlignRectOriginAndSizeToPixels(frame); - [button setFrame:frame]; - return leftEdge; -} - -- (CGFloat)heightThatFitsButtonsUnderOtherWidgets:(CGFloat)heightOfFirstLine - layout:(BOOL)layout { - if (_button1 && _button2) { - CGFloat halfWidthOfScreen = [self frame].size.width / 2.0; - if ([self narrowestWidthOfButton:_button1] <= halfWidthOfScreen && - [self narrowestWidthOfButton:_button2] <= halfWidthOfScreen) { - // Each button can fit in half the screen's width. - if (layout) { - // When there are two buttons on one line, they are positioned aligned - // right in the available space, spaced apart by - // metrics_->button_spacing. - CGFloat leftOfRightmostButton = - [self layoutWideButtonAlignRight:_button1 - rightEdge:CGRectGetWidth(self.bounds) - - _metrics->button_margin - - self.safeAreaInsets.right - y:heightOfFirstLine]; - [self layoutWideButtonAlignRight:_button2 - rightEdge:leftOfRightmostButton - - _metrics->button_spacing - y:heightOfFirstLine]; - } - return _metrics->button_height; - } else { - // At least one of the two buttons is larger than half the screen's width, - // so |button2_| is placed underneath |button1_|. - if (layout) { - [self layoutWideButton:_button1 y:heightOfFirstLine position:CENTER]; - [self layoutWideButton:_button2 - y:heightOfFirstLine + _metrics->button_height - position:CENTER]; - } - return 2 * _metrics->button_height; - } - } - // There is at most 1 button to layout. - UIButton* button = _button1 ? _button1 : _button2; - if (button) { - if (layout) { - // Where is there is just one button it is positioned aligned right in the - // available space. - [self layoutWideButtonAlignRight:button - rightEdge:CGRectGetWidth(self.bounds) - - _metrics->button_margin - - self.safeAreaInsets.right - y:heightOfFirstLine]; - } - return _metrics->button_height; - } - return 0; -} - -- (CGFloat)computeRequiredHeightAndLayoutSubviews:(BOOL)layout { - CGFloat requiredHeight = 0; - CGFloat widthOfLabel = [self widthOfLabelOnASingleLine] + - [self widthToSeparateRightAndLeftWidgets]; - CGFloat widthOfButtons = [self widthOfButtonsOnFirstLine]; - CGFloat preferredWidthOfSwitch = [self preferredWidthOfSwitch]; - CGFloat widthOfScreen = [self frame].size.width; - CGFloat rightMarginOnFirstLine = [self rightMarginOnFirstLine]; - CGFloat spaceAvailableOnFirstLine = - [self horizontalSpaceAvailableOnFirstLine]; - CGFloat widthOfButtonAndSwitch = widthOfButtons + - [self widthToSeparateSwitchAndButtons] + - preferredWidthOfSwitch; - // Tests if the label, switch, and buttons can fit on a single line. - if (widthOfLabel + widthOfButtonAndSwitch < spaceAvailableOnFirstLine) { - // The label, switch, and buttons can fit on a single line. - requiredHeight = _metrics->minimum_infobar_height; - if (layout) { - // Lays out the close button. - CGRect buttonFrame = [self frameOfCloseButton:YES]; - [_closeButton setFrame:buttonFrame]; - // Lays out the label. - CGFloat labelHeight = [self heightRequiredForLabelWithWidth:widthOfLabel]; - CGRect frame = - CGRectMake([self leftMarginOnFirstLine], - (_metrics->minimum_infobar_height - labelHeight) / 2, - [self widthOfLabelOnASingleLine], labelHeight); - frame = AlignRectOriginAndSizeToPixels(frame); - [_label setFrame:frame]; - // Layouts the buttons. - CGFloat buttonMargin = - rightMarginOnFirstLine + _metrics->extra_button_margin_on_single_line; - if (_button1) { - CGFloat width = [self narrowestWidthOfButton:_button1]; - CGFloat offset = width; - frame = CGRectMake( - widthOfScreen - buttonMargin - offset, - (_metrics->minimum_infobar_height - _metrics->button_height) / 2, - width, _metrics->button_height); - frame = AlignRectOriginAndSizeToPixels(frame); - [_button1 setFrame:frame]; - } - if (_button2) { - CGFloat width = [self narrowestWidthOfButton:_button2]; - CGFloat offset = widthOfButtons; - frame = CGRectMake( - widthOfScreen - buttonMargin - offset, - (_metrics->minimum_infobar_height - _metrics->button_height) / 2, - width, frame.size.height = _metrics->button_height); - frame = AlignRectOriginAndSizeToPixels(frame); - [_button2 setFrame:frame]; - } - // Lays out the switch view to the left of the buttons. - if (_InfobarFooterView) { - frame = CGRectMake( - widthOfScreen - buttonMargin - widthOfButtonAndSwitch, - (_metrics->minimum_infobar_height - - [_InfobarFooterView frame].size.height) / - 2.0, - preferredWidthOfSwitch, [_InfobarFooterView frame].size.height); - frame = AlignRectOriginAndSizeToPixels(frame); - [_InfobarFooterView setFrame:frame]; - } - } - } else { - // The widgets (label, switch, buttons) can't fit on a single line. Attempts - // to lay out the label and switch on the first line, and the buttons - // underneath. - CGFloat heightOfLabelAndSwitch = 0; - - if (layout) { - // Lays out the close button. - CGRect buttonFrame = [self frameOfCloseButton:NO]; - [_closeButton setFrame:buttonFrame]; - } - if (widthOfLabel + preferredWidthOfSwitch < spaceAvailableOnFirstLine) { - // The label and switch can fit on the first line. - heightOfLabelAndSwitch = _metrics->minimum_infobar_height; - if (layout) { - CGFloat labelHeight = - [self heightRequiredForLabelWithWidth:widthOfLabel]; - CGRect labelFrame = - CGRectMake([self leftMarginOnFirstLine], - (heightOfLabelAndSwitch - labelHeight) / 2, - [self widthOfLabelOnASingleLine], labelHeight); - labelFrame = AlignRectOriginAndSizeToPixels(labelFrame); - [_label setFrame:labelFrame]; - if (_InfobarFooterView) { - CGRect switchRect = CGRectMake( - widthOfScreen - rightMarginOnFirstLine - preferredWidthOfSwitch, - (heightOfLabelAndSwitch - - [_InfobarFooterView frame].size.height) / - 2, - preferredWidthOfSwitch, [_InfobarFooterView frame].size.height); - switchRect = AlignRectOriginAndSizeToPixels(switchRect); - [_InfobarFooterView setFrame:switchRect]; - } - } - } else { - // The label and switch can't fit on the first line, so lay them out on - // different lines. - // Computes the height of the label, and optionally lays it out. - CGFloat labelMarginBottom = _metrics->label_margin_bottom; - if (_button1 || _button2) { - // Material features more padding between the label and the button than - // the label and the bottom of the dialog when there is no button. - labelMarginBottom += _metrics->extra_margin_between_label_and_button; - } - CGFloat heightOfLabelWithPadding = - [self heightRequiredForLabelWithWidth:spaceAvailableOnFirstLine] + - _metrics->label_margin_top + labelMarginBottom; - if (layout) { - CGRect labelFrame = - CGRectMake([self leftMarginOnFirstLine], _metrics->label_margin_top, - spaceAvailableOnFirstLine, - heightOfLabelWithPadding - _metrics->label_margin_top - - labelMarginBottom); - labelFrame = AlignRectOriginAndSizeToPixels(labelFrame); - [_label setFrame:labelFrame]; - } - // Computes the height of the switch view (if any), and optionally lays it - // out. - CGFloat heightOfSwitchWithPadding = 0; - if (_InfobarFooterView != nil) { - // The switch view is aligned with the first line's label, hence the - // call to |leftMarginOnFirstLine|. - CGFloat widthAvailableForSwitchView = [self frame].size.width - - [self leftMarginOnFirstLine] - - _metrics->right_margin; - CGFloat heightOfSwitch = [_InfobarFooterView - heightRequiredForFooterWithWidth:widthAvailableForSwitchView - layout:layout]; - // If there are buttons underneath the switch, add padding. - if (_button1 || _button2) { - heightOfSwitchWithPadding = - heightOfSwitch + _metrics->space_between_widgets + - _metrics->extra_margin_between_label_and_button; - } else { - heightOfSwitchWithPadding = heightOfSwitch; - } - if (layout) { - CGRect switchRect = - CGRectMake([self leftMarginOnFirstLine], heightOfLabelWithPadding, - widthAvailableForSwitchView, heightOfSwitch); - switchRect = AlignRectOriginAndSizeToPixels(switchRect); - [_InfobarFooterView setFrame:switchRect]; - } - } - heightOfLabelAndSwitch = - std::max(heightOfLabelWithPadding + heightOfSwitchWithPadding, - _metrics->minimum_infobar_height); - } - // Lays out the button(s) under the label and switch. - CGFloat heightOfButtons = - [self heightThatFitsButtonsUnderOtherWidgets:heightOfLabelAndSwitch - layout:layout]; - requiredHeight = heightOfLabelAndSwitch; - if (heightOfButtons > 0) - requiredHeight += heightOfButtons + _metrics->button_margin; - } - // Take into account the bottom safe area. - // The top safe area is ignored because at rest (i.e. not during animations) - // the infobar is aligned to the bottom of the screen, and thus should not - // have its top intersect with any safe area. - CGFloat bottomSafeAreaInset = self.safeAreaInsets.bottom; - requiredHeight += bottomSafeAreaInset; - - UILayoutGuide* guide = - [NamedGuide guideWithName:kSecondaryToolbarGuide view:self]; - UILayoutGuide* guideNoFullscreen = - [NamedGuide guideWithName:kSecondaryToolbarNoFullscreenGuide view:self]; - if (guide && guideNoFullscreen) { - CGFloat toolbarHeightCurrent = guide.layoutFrame.size.height; - CGFloat toolbarHeightMax = guideNoFullscreen.layoutFrame.size.height; - if (toolbarHeightMax > 0) { - CGFloat fullscreenProgress = toolbarHeightCurrent / toolbarHeightMax; - CGFloat toolbarHeightInSafeArea = toolbarHeightMax - bottomSafeAreaInset; - requiredHeight += fullscreenProgress * toolbarHeightInSafeArea; - } - } - - return requiredHeight; -} - -- (CGSize)sizeThatFits:(CGSize)size { - CGFloat requiredHeight = [self computeRequiredHeightAndLayoutSubviews:NO]; - return CGSizeMake([self frame].size.width, requiredHeight); -} - -- (void)layoutSubviews { - // Add the separator if it's not already added. - if (self.separator.superview != self) { - [self addSubview:self.separator]; - CGFloat separatorHeight = - ui::AlignValueToUpperPixel(kToolbarSeparatorHeight); - [NSLayoutConstraint activateConstraints:@[ - [self.separator.heightAnchor constraintEqualToConstant:separatorHeight], - [self.leadingAnchor constraintEqualToAnchor:self.separator.leadingAnchor], - [self.trailingAnchor - constraintEqualToAnchor:self.separator.trailingAnchor], - [self.topAnchor constraintEqualToAnchor:self.separator.bottomAnchor], - ]]; - } - - // Lays out the position of the icon. - [_imageView setFrame:[self frameOfIcon]]; - self.visibleHeight = [self computeRequiredHeightAndLayoutSubviews:YES]; - [self resetBackground]; - - // Asks the BidiContainerView to reposition of all the subviews. - for (UIView* view in [self subviews]) - [self setSubviewNeedsAdjustmentForRTL:view]; - [super layoutSubviews]; -} - -- (void)resetBackground { - self.backgroundColor = [UIColor colorNamed:kBackgroundColor]; - CGFloat shadowY = 0; - shadowY = -[_shadow image].size.height; // Shadow above the infobar. - [_shadow setFrame:CGRectMake(0, shadowY, self.bounds.size.width, - [_shadow image].size.height)]; - [_shadow setAutoresizingMask:UIViewAutoresizingFlexibleWidth]; -} - -- (void)addCloseButtonWithTag:(NSInteger)tag - target:(id)target - action:(SEL)action { - DCHECK(!_closeButton); - UIImage* image = InfoBarCloseImage(); - _closeButton = [UIButton buttonWithType:UIButtonTypeSystem]; - [_closeButton setExclusiveTouch:YES]; - [_closeButton setImage:image forState:UIControlStateNormal]; - [_closeButton addTarget:target - action:action - forControlEvents:UIControlEventTouchUpInside]; - [_closeButton setTag:tag]; - [_closeButton setAccessibilityLabel:l10n_util::GetNSString(IDS_CLOSE)]; - _closeButton.tintColor = [UIColor colorNamed:kToolbarButtonColor]; - - if (@available(iOS 13.4, *)) { - _closeButton.pointerInteractionEnabled = YES; - } - [self addSubview:_closeButton]; -} - -- (void)addSwitchWithLabel:(NSString*)label - isOn:(BOOL)isOn - tag:(NSInteger)tag - target:(id)target - action:(SEL)action { - SwitchView* switchView = [[SwitchView alloc] initWithText:label isOn:isOn]; - [switchView setTag:tag target:target action:action]; - _InfobarFooterView = switchView; - [self addSubview:_InfobarFooterView]; -} - -- (void)addFooterLabel:(NSString*)label { - _InfobarFooterView = [[InfobarFooterView alloc] initWithText:label]; - [self addSubview:_InfobarFooterView]; -} - -- (void)addLeftIcon:(UIImage*)image { - if (_imageView) { - [_imageView removeFromSuperview]; - } - UIImage* templateImage = - [image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; - _imageView = [[UIImageView alloc] initWithImage:templateImage]; - [self addSubview:_imageView]; -} - -- (NSString*)stripMarkersFromString:(NSString*)string { - _linkRanges.clear(); - for (;;) { - // Find the opening marker, followed by the tag between parentheses. - NSRange startingRange = - [string rangeOfString:[[ConfirmInfoBarView openingMarkerForLink] - stringByAppendingString:@"("]]; - if (!startingRange.length) - return [string copy]; - // Read the tag. - NSUInteger beginTag = NSMaxRange(startingRange); - NSRange closingParenthesis = [string - rangeOfString:@")" - options:NSLiteralSearch - range:NSMakeRange(beginTag, [string length] - beginTag)]; - if (closingParenthesis.location == NSNotFound) - return [string copy]; - NSInteger tag = [[string - substringWithRange:NSMakeRange(beginTag, closingParenthesis.location - - beginTag)] integerValue]; - // If the parsing fails, |tag| is 0. Negative values are not allowed. - if (tag <= 0) - return [string copy]; - // Find the closing marker. - startingRange.length = - closingParenthesis.location - startingRange.location + 1; - NSRange endingRange = - [string rangeOfString:[ConfirmInfoBarView closingMarkerForLink]]; - DCHECK(endingRange.length); - // Compute range of link in stripped string and add it to the array. - NSRange rangeOfLinkInStrippedString = - NSMakeRange(startingRange.location, - endingRange.location - NSMaxRange(startingRange)); - _linkRanges.push_back(std::make_pair(tag, rangeOfLinkInStrippedString)); - // Creates a new string without the markers. - NSString* beforeLink = [string substringToIndex:startingRange.location]; - NSRange rangeOfLink = - NSMakeRange(NSMaxRange(startingRange), - endingRange.location - NSMaxRange(startingRange)); - NSString* link = [string substringWithRange:rangeOfLink]; - NSString* afterLink = [string substringFromIndex:NSMaxRange(endingRange)]; - string = [NSString stringWithFormat:@"%@%@%@", beforeLink, link, afterLink]; - } -} - -- (void)addLabel:(NSString*)label { - [self addLabel:label action:nil]; -} - -- (void)addLabel:(NSString*)text action:(void (^)(NSUInteger))action { - _markedLabel = [text copy]; - if (action) - text = [self stripMarkersFromString:text]; - if ([_label superview]) { - [_label removeFromSuperview]; - } - - _label = [[UILabel alloc] initWithFrame:CGRectZero]; - _label.textColor = [UIColor colorNamed:kTextPrimaryColor]; - - NSMutableParagraphStyle* paragraphStyle = - [[NSMutableParagraphStyle alloc] init]; - paragraphStyle.lineBreakMode = NSLineBreakByWordWrapping; - paragraphStyle.lineSpacing = _metrics->label_line_spacing; - NSDictionary* attributes = @{ - NSParagraphStyleAttributeName : paragraphStyle, - NSFontAttributeName : InfoBarLabelFont(), - }; - [_label setNumberOfLines:0]; - - [_label - setAttributedText:[[NSAttributedString alloc] initWithString:text - attributes:attributes]]; - - [self addSubview:_label]; - - if (_linkRanges.empty()) - return; - - _labelLinkController = [[LabelLinkController alloc] - initWithLabel:_label - action:^(const GURL& gurl) { - if (action) { - NSUInteger actionTag = [base::SysUTF8ToNSString( - gurl.ExtractFileName()) integerValue]; - action(actionTag); - } - }]; - - [_labelLinkController setLinkUnderlineStyle:NSUnderlineStyleSingle]; - [_labelLinkController setLinkColor:[UIColor colorNamed:kTextPrimaryColor]]; - - std::vector<std::pair<NSUInteger, NSRange>>::const_iterator it; - for (it = _linkRanges.begin(); it != _linkRanges.end(); ++it) { - // The last part of the URL contains the tag, so it can be retrieved in the - // callback. This tag is generally a command ID. - std::string url = std::string(kChromeInfobarURL) + - std::string(std::to_string((int)it->first)); - [_labelLinkController addLinkWithRange:it->second url:GURL(url)]; - } -} - -- (void)addButton1:(NSString*)title1 - tag1:(NSInteger)tag1 - button2:(NSString*)title2 - tag2:(NSInteger)tag2 - target:(id)target - action:(SEL)action { - _button1 = [self infoBarButton:title1 - backgroundColor:[UIColor colorNamed:kBlueColor] - customTitleColor:[UIColor colorNamed:kSolidButtonTextColor] - tag:tag1 - target:target - action:action]; - [_button1 - setAccessibilityIdentifier:kConfirmInfobarButton1AccessibilityIdentifier]; - [self addSubview:_button1]; - - _button2 = [self infoBarButton:title2 - backgroundColor:nil - customTitleColor:[UIColor colorNamed:kBlueColor] - tag:tag2 - target:target - action:action]; - [_button2 - setAccessibilityIdentifier:kConfirmInfobarButton2AccessibilityIdentifier]; - [self addSubview:_button2]; -} - -- (void)addButton:(NSString*)title - tag:(NSInteger)tag - target:(id)target - action:(SEL)action { - if (![title length]) - return; - _button1 = [self infoBarButton:title - backgroundColor:[UIColor colorNamed:kBlueColor] - customTitleColor:[UIColor colorNamed:kSolidButtonTextColor] - tag:tag - target:target - action:action]; - [self addSubview:_button1]; -} - -// Initializes and returns a button for the infobar, with the specified -// |message| and colors. -- (UIButton*)infoBarButton:(NSString*)message - backgroundColor:(UIColor*)backgroundColor - customTitleColor:(UIColor*)customTitleColor - tag:(NSInteger)tag - target:(id)target - action:(SEL)action { - MDCFlatButton* button = [[MDCFlatButton alloc] init]; - button.uppercaseTitle = NO; - button.layer.cornerRadius = kButtonCornerRadius; - [button setTitleFont:InfoBarButtonLabelFont() forState:UIControlStateNormal]; - button.inkColor = [UIColor colorNamed:kMDCInkColor]; - [button setBackgroundColor:backgroundColor forState:UIControlStateNormal]; - [button setBackgroundColor:[UIColor colorNamed:kDisabledTintColor] - forState:UIControlStateDisabled]; - if (backgroundColor) - button.hasOpaqueBackground = YES; - if (customTitleColor) { - button.tintAdjustmentMode = UIViewTintAdjustmentModeNormal; - [button setTitleColor:customTitleColor forState:UIControlStateNormal]; - } - button.titleLabel.adjustsFontSizeToFitWidth = YES; - button.titleLabel.minimumScaleFactor = 0.6f; - [button setTitle:message forState:UIControlStateNormal]; - [button setTag:tag]; - [button addTarget:target - action:action - forControlEvents:UIControlEventTouchUpInside]; - - if (@available(iOS 13.4, *)) { - button.pointerInteractionEnabled = YES; - button.pointerStyleProvider = CreateOpaqueButtonPointerStyleProvider(); - } - // Without the call to layoutIfNeeded, |button| returns an incorrect - // titleLabel the first time it is accessed in |narrowestWidthOfButton|. - [button layoutIfNeeded]; - return button; -} - -- (CGRect)frameOfCloseButton:(BOOL)singleLineMode { - DCHECK(_closeButton); - // Add padding to increase the touchable area. - CGSize closeButtonSize = [_closeButton imageView].image.size; - closeButtonSize.width += _metrics->close_button_inner_padding * 2; - closeButtonSize.height += _metrics->close_button_inner_padding * 2; - CGFloat x = CGRectGetMaxX(self.frame) - closeButtonSize.width - - self.safeAreaInsets.right; - // Aligns the close button at the top (height includes touch padding). - CGFloat y = 0; - if (singleLineMode) { - // On single-line mode the button is centered vertically. - y = ui::AlignValueToUpperPixel( - (_metrics->minimum_infobar_height - closeButtonSize.height) * 0.5); - } - return CGRectMake(x, y, closeButtonSize.width, closeButtonSize.height); -} - -- (CGRect)frameOfIcon { - CGSize iconSize = [_imageView image].size; - CGFloat y = _metrics->buttons_margin_top; - CGFloat x = _metrics->close_button_margin_left + self.safeAreaInsets.left; - return CGRectMake(AlignValueToPixel(x), AlignValueToPixel(y), iconSize.width, - iconSize.height); -} - -+ (NSString*)openingMarkerForLink { - return @"$LINK_START"; -} - -+ (NSString*)closingMarkerForLink { - return @"$LINK_END"; -} - -+ (NSString*)stringAsLink:(NSString*)string tag:(NSUInteger)tag { - DCHECK_NE(0u, tag); - return [NSString stringWithFormat:@"%@(%" PRIuNS ")%@%@", - [ConfirmInfoBarView openingMarkerForLink], - tag, string, - [ConfirmInfoBarView closingMarkerForLink]]; -} - -#pragma mark - Testing - -- (CGFloat)minimumInfobarHeight { - return _metrics->minimum_infobar_height; -} - -- (CGFloat)buttonsHeight { - return _metrics->button_height; -} - -- (CGFloat)buttonMargin { - return _metrics->button_margin; -} - -- (const std::vector<std::pair<NSUInteger, NSRange>>&)linkRanges { - return _linkRanges; -} - -@end
diff --git a/ios/chrome/browser/ui/infobars/confirm_infobar_view_unittest.mm b/ios/chrome/browser/ui/infobars/confirm_infobar_view_unittest.mm deleted file mode 100644 index 953fd8b1..0000000 --- a/ios/chrome/browser/ui/infobars/confirm_infobar_view_unittest.mm +++ /dev/null
@@ -1,193 +0,0 @@ -// Copyright 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. - -#import "ios/chrome/browser/ui/infobars/confirm_infobar_view.h" - -#include "testing/gtest/include/gtest/gtest.h" -#include "testing/gtest_mac.h" -#include "testing/platform_test.h" - -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - -@interface ConfirmInfoBarView (Testing) -- (CGFloat)buttonsHeight; -- (CGFloat)buttonMargin; -- (CGFloat)computeRequiredHeightAndLayoutSubviews:(BOOL)layout; -- (CGFloat)heightThatFitsButtonsUnderOtherWidgets:(CGFloat)heightOfFirstLine - layout:(BOOL)layout; -- (CGFloat)minimumInfobarHeight; -- (NSString*)stripMarkersFromString:(NSString*)string; -- (const std::vector<std::pair<NSUInteger, NSRange>>&)linkRanges; -@end - -namespace { - -const int kShortStringLength = 4; -const int kLongStringLength = 1000; - -class ConfirmInfoBarViewTest : public PlatformTest { - protected: - void SetUp() override { - PlatformTest::SetUp(); - CGFloat screenWidth = [UIScreen mainScreen].bounds.size.width; - confirmInfobarView_ = [[ConfirmInfoBarView alloc] - initWithFrame:CGRectMake(0, 0, screenWidth, 0)]; - [confirmInfobarView_ addCloseButtonWithTag:0 target:nil action:nil]; - } - - NSString* RandomString(int numberOfCharacters) { - NSMutableString* string = [NSMutableString string]; - NSString* letters = @"abcde "; - for (int i = 0; i < numberOfCharacters; i++) { - [string - appendFormat:@"%C", [letters characterAtIndex:arc4random_uniform( - [letters length])]]; - } - return string; - } - - NSString* ShortRandomString() { return RandomString(kShortStringLength); } - - NSString* LongRandomString() { return RandomString(kLongStringLength); } - - CGFloat InfobarHeight() { - return [confirmInfobarView_ computeRequiredHeightAndLayoutSubviews:NO]; - } - - CGFloat MinimumInfobarHeight() { - return [confirmInfobarView_ minimumInfobarHeight]; - } - - CGFloat ButtonsHeight() { return [confirmInfobarView_ buttonsHeight]; } - - CGFloat ButtonMargin() { return [confirmInfobarView_ buttonMargin]; } - - void TestLinkDetectionHelper( - NSString* input, - NSString* expectedOutput, - const std::vector<std::pair<NSUInteger, NSRange>>& expectedRanges) { - NSString* output = [confirmInfobarView_ stripMarkersFromString:input]; - EXPECT_NSEQ(expectedOutput, output); - const std::vector<std::pair<NSUInteger, NSRange>>& ranges = - [confirmInfobarView_ linkRanges]; - EXPECT_EQ(expectedRanges.size(), ranges.size()); - for (unsigned int i = 0; i < expectedRanges.size(); ++i) { - EXPECT_EQ(expectedRanges[i].first, ranges[i].first); - EXPECT_TRUE(NSEqualRanges(expectedRanges[i].second, ranges[i].second)); - } - } - - ConfirmInfoBarView* confirmInfobarView_; -}; - -TEST_F(ConfirmInfoBarViewTest, TestLayoutWithNoLabel) { - // Do not call -addLabel: to test the case when there is no label. - EXPECT_EQ(MinimumInfobarHeight(), InfobarHeight()); -} - -TEST_F(ConfirmInfoBarViewTest, TestLayoutWithShortLabel) { - [confirmInfobarView_ addLabel:ShortRandomString()]; - EXPECT_EQ(MinimumInfobarHeight(), InfobarHeight()); -} - -TEST_F(ConfirmInfoBarViewTest, TestLayoutWithLongLabel) { - [confirmInfobarView_ addLabel:LongRandomString()]; - EXPECT_LT(MinimumInfobarHeight(), InfobarHeight()); - EXPECT_EQ(0, [confirmInfobarView_ heightThatFitsButtonsUnderOtherWidgets:0 - layout:NO]); -} - -TEST_F(ConfirmInfoBarViewTest, TestLayoutWithShortButtons) { - [confirmInfobarView_ addLabel:ShortRandomString()]; - [confirmInfobarView_ addButton1:ShortRandomString() - tag1:0 - button2:ShortRandomString() - tag2:0 - target:nil - action:nil]; - EXPECT_EQ(MinimumInfobarHeight(), InfobarHeight()); - EXPECT_EQ( - ButtonsHeight(), - [confirmInfobarView_ heightThatFitsButtonsUnderOtherWidgets:0 layout:NO]); -} - -TEST_F(ConfirmInfoBarViewTest, TestLayoutWithOneLongButtonAndOneShortButton) { - [confirmInfobarView_ addLabel:ShortRandomString()]; - [confirmInfobarView_ addButton1:LongRandomString() - tag1:0 - button2:ShortRandomString() - tag2:0 - target:nil - action:nil]; - EXPECT_EQ(MinimumInfobarHeight() + ButtonsHeight() * 2 + ButtonMargin(), - InfobarHeight()); - EXPECT_EQ( - ButtonsHeight() * 2, - [confirmInfobarView_ heightThatFitsButtonsUnderOtherWidgets:0 layout:NO]); -} - -TEST_F(ConfirmInfoBarViewTest, TestLayoutWithShortLabelAndShortButton) { - [confirmInfobarView_ addLabel:ShortRandomString()]; - [confirmInfobarView_ addButton:ShortRandomString() - tag:0 - target:nil - action:nil]; - EXPECT_EQ(MinimumInfobarHeight(), InfobarHeight()); -} - -TEST_F(ConfirmInfoBarViewTest, TestLayoutWithShortLabelAndLongButton) { - [confirmInfobarView_ addLabel:ShortRandomString()]; - [confirmInfobarView_ addButton:LongRandomString() - tag:0 - target:nil - action:nil]; - EXPECT_EQ(MinimumInfobarHeight() + ButtonsHeight() + ButtonMargin(), - InfobarHeight()); -} - -TEST_F(ConfirmInfoBarViewTest, TestLayoutWithLongLabelAndLongButtons) { - [confirmInfobarView_ addLabel:LongRandomString()]; - [confirmInfobarView_ addButton1:ShortRandomString() - tag1:0 - button2:LongRandomString() - tag2:0 - target:nil - action:nil]; - EXPECT_LT(MinimumInfobarHeight() + ButtonsHeight() * 2, InfobarHeight()); -} - -TEST_F(ConfirmInfoBarViewTest, TestLinkDetection) { - [confirmInfobarView_ addLabel:ShortRandomString()]; - NSString* linkFoo = [ConfirmInfoBarView stringAsLink:@"foo" tag:1]; - NSString* linkBar = [ConfirmInfoBarView stringAsLink:@"bar" tag:2]; - std::vector<std::pair<NSUInteger, NSRange>> ranges; - // No link. - TestLinkDetectionHelper(@"", @"", ranges); - TestLinkDetectionHelper(@"foo", @"foo", ranges); - // One link. - ranges.push_back(std::make_pair(1, NSMakeRange(0, 3))); - TestLinkDetectionHelper(linkFoo, @"foo", ranges); - NSString* link1 = [NSString stringWithFormat:@"baz%@qux", linkFoo]; - // Link in the middle. - ranges.clear(); - ranges.push_back(std::make_pair(1, NSMakeRange(3, 3))); - TestLinkDetectionHelper(link1, @"bazfooqux", ranges); - // Multiple links. - NSString* link2 = [NSString stringWithFormat:@"%@%@", linkFoo, linkBar]; - ranges.clear(); - ranges.push_back(std::make_pair(1, NSMakeRange(0, 3))); - ranges.push_back(std::make_pair(2, NSMakeRange(3, 3))); - TestLinkDetectionHelper(link2, @"foobar", ranges); - // Multiple links and text. - NSString* link3 = - [NSString stringWithFormat:@"baz%@qux%@tot", linkFoo, linkBar]; - ranges.clear(); - ranges.push_back(std::make_pair(1, NSMakeRange(3, 3))); - ranges.push_back(std::make_pair(2, NSMakeRange(9, 3))); - TestLinkDetectionHelper(link3, @"bazfooquxbartot", ranges); -} - -} // namespace
diff --git a/ios/chrome/browser/ui/main/scene_controller.mm b/ios/chrome/browser/ui/main/scene_controller.mm index b6303664..a53935a 100644 --- a/ios/chrome/browser/ui/main/scene_controller.mm +++ b/ios/chrome/browser/ui/main/scene_controller.mm
@@ -1289,7 +1289,9 @@ return; } self.sceneState.appState.signinUpgradePromoPresentedOnce = YES; - DCHECK(!self.signinCoordinator); + DCHECK(!self.signinCoordinator) << "self.signinCoordinator class: " + << base::SysNSStringToUTF8(NSStringFromClass( + self.signinCoordinator.class)); Browser* browser = self.mainInterface.browser; self.signinCoordinator = [SigninCoordinator upgradeSigninPromoCoordinatorWithBaseViewController:self.mainInterface @@ -1394,7 +1396,9 @@ // TODO(crbug.com/779791) : Remove showing settings from MainController. - (void)showAutofillSettingsFromViewController: (UIViewController*)baseViewController { - DCHECK(!self.signinCoordinator); + DCHECK(!self.signinCoordinator) << "self.signinCoordinator class: " + << base::SysNSStringToUTF8(NSStringFromClass( + self.signinCoordinator.class)); if (self.settingsNavigationController) return; @@ -1425,7 +1429,8 @@ // This dispatch is necessary to give enough time for the tools menu to // disappear before taking a screenshot. dispatch_async(dispatch_get_main_queue(), ^{ - DCHECK(!self.signinCoordinator); + DCHECK(!self.signinCoordinator) << base::SysNSStringToUTF8( + NSStringFromClass(self.signinCoordinator.class)); if (self.settingsNavigationController) return; Browser* browser = self.mainInterface.browser; @@ -1475,7 +1480,9 @@ // TODO(crbug.com/779791) : Do not pass |baseViewController| through dispatcher. - (void)showSignin:(ShowSigninCommand*)command baseViewController:(UIViewController*)baseViewController { - DCHECK(!self.signinCoordinator); + DCHECK(!self.signinCoordinator) << "self.signinCoordinator class: " + << base::SysNSStringToUTF8(NSStringFromClass( + self.signinCoordinator.class)); Browser* mainBrowser = self.mainInterface.browser; switch (command.operation) { @@ -1507,7 +1514,9 @@ - (void)showAdvancedSigninSettingsFromViewController: (UIViewController*)baseViewController { - DCHECK(!self.signinCoordinator); + DCHECK(!self.signinCoordinator) << "self.signinCoordinator class: " + << base::SysNSStringToUTF8(NSStringFromClass( + self.signinCoordinator.class)); Browser* mainBrowser = self.mainInterface.browser; self.signinCoordinator = [SigninCoordinator advancedSettingsSigninCoordinatorWithBaseViewController:baseViewController @@ -1617,7 +1626,9 @@ } - (void)showSettingsFromViewController:(UIViewController*)baseViewController { - DCHECK(!self.signinCoordinator); + DCHECK(!self.signinCoordinator) << "self.signinCoordinator class: " + << base::SysNSStringToUTF8(NSStringFromClass( + self.signinCoordinator.class)); if (self.settingsNavigationController) return; [[DeferredInitializationRunner sharedInstance] @@ -1662,7 +1673,9 @@ // TODO(crbug.com/779791) : Remove show settings from MainController. - (void)showAccountsSettingsFromViewController: (UIViewController*)baseViewController { - DCHECK(!self.signinCoordinator); + DCHECK(!self.signinCoordinator) << "self.signinCoordinator class: " + << base::SysNSStringToUTF8(NSStringFromClass( + self.signinCoordinator.class)); if (!baseViewController) { DCHECK_EQ(self.currentInterface.viewController, self.mainCoordinator.activeViewController); @@ -1691,7 +1704,9 @@ // TODO(crbug.com/779791) : Remove Google services settings from MainController. - (void)showGoogleServicesSettingsFromViewController: (UIViewController*)baseViewController { - DCHECK(!self.signinCoordinator); + DCHECK(!self.signinCoordinator) << "self.signinCoordinator class: " + << base::SysNSStringToUTF8(NSStringFromClass( + self.signinCoordinator.class)); if (!baseViewController) { DCHECK_EQ(self.currentInterface.viewController, self.mainCoordinator.activeViewController); @@ -1719,7 +1734,9 @@ // TODO(crbug.com/779791) : Remove show settings commands from MainController. - (void)showSyncSettingsFromViewController: (UIViewController*)baseViewController { - DCHECK(!self.signinCoordinator); + DCHECK(!self.signinCoordinator) << "self.signinCoordinator class: " + << base::SysNSStringToUTF8(NSStringFromClass( + self.signinCoordinator.class)); if (self.settingsNavigationController) { [self.settingsNavigationController showSyncSettingsFromViewController:baseViewController]; @@ -1738,7 +1755,9 @@ // TODO(crbug.com/779791) : Remove show settings commands from MainController. - (void)showSyncPassphraseSettingsFromViewController: (UIViewController*)baseViewController { - DCHECK(!self.signinCoordinator); + DCHECK(!self.signinCoordinator) << "self.signinCoordinator class: " + << base::SysNSStringToUTF8(NSStringFromClass( + self.signinCoordinator.class)); if (self.settingsNavigationController) { [self.settingsNavigationController showSyncPassphraseSettingsFromViewController:baseViewController]; @@ -1762,7 +1781,9 @@ // dispatched command. baseViewController = self.currentInterface.viewController; } - DCHECK(!self.signinCoordinator); + DCHECK(!self.signinCoordinator) << "self.signinCoordinator class: " + << base::SysNSStringToUTF8(NSStringFromClass( + self.signinCoordinator.class)); if (self.settingsNavigationController) { [self.settingsNavigationController showSavedPasswordsSettingsFromViewController:baseViewController]; @@ -1780,7 +1801,9 @@ - (void)showSavedPasswordsSettingsAndStartPasswordCheckFromViewController: (UIViewController*)baseViewController { - DCHECK(!self.signinCoordinator); + DCHECK(!self.signinCoordinator) << "self.signinCoordinator class: " + << base::SysNSStringToUTF8(NSStringFromClass( + self.signinCoordinator.class)); [self dismissModalDialogs]; if (self.settingsNavigationController) { [self.settingsNavigationController @@ -1801,7 +1824,9 @@ // TODO(crbug.com/779791) : Remove show settings commands from MainController. - (void)showProfileSettingsFromViewController: (UIViewController*)baseViewController { - DCHECK(!self.signinCoordinator); + DCHECK(!self.signinCoordinator) << "self.signinCoordinator class: " + << base::SysNSStringToUTF8(NSStringFromClass( + self.signinCoordinator.class)); if (self.settingsNavigationController) { [self.settingsNavigationController showProfileSettingsFromViewController:baseViewController]; @@ -1820,7 +1845,9 @@ // TODO(crbug.com/779791) : Remove show settings commands from MainController. - (void)showCreditCardSettingsFromViewController: (UIViewController*)baseViewController { - DCHECK(!self.signinCoordinator); + DCHECK(!self.signinCoordinator) << "self.signinCoordinator class: " + << base::SysNSStringToUTF8(NSStringFromClass( + self.signinCoordinator.class)); if (self.settingsNavigationController) { [self.settingsNavigationController showCreditCardSettingsFromViewController:baseViewController]; @@ -2290,7 +2317,8 @@ ProceduralBlock completionWithBVC = ^{ DCHECK(self.currentInterface.viewController); DCHECK(!self.mainCoordinator.isTabGridActive); - DCHECK(!self.signinCoordinator); + DCHECK(!self.signinCoordinator) << base::SysNSStringToUTF8( + NSStringFromClass(self.signinCoordinator.class)); // This will dismiss the SSO view controller. [self.interfaceProvider.currentInterface clearPresentedStateWithCompletion:completion @@ -2300,7 +2328,8 @@ // |self.currentInterface.bvc| may exist but tab switcher should be // active. DCHECK(self.mainCoordinator.isTabGridActive); - DCHECK(!self.signinCoordinator); + DCHECK(!self.signinCoordinator) << base::SysNSStringToUTF8( + NSStringFromClass(self.signinCoordinator.class)); // History coordinator can be started on top of the tab grid. // This is not true of the other tab switchers. DCHECK(self.mainCoordinator); @@ -2615,7 +2644,9 @@ (syncer:: TrustedVaultUserActionTriggerForUMA) trigger { - DCHECK(!self.signinCoordinator); + DCHECK(!self.signinCoordinator) << "self.signinCoordinator class: " + << base::SysNSStringToUTF8(NSStringFromClass( + self.signinCoordinator.class)); Browser* mainBrowser = self.mainInterface.browser; self.signinCoordinator = [SigninCoordinator trustedVaultReAuthenticationCoordinatorWithBaseViewController:
diff --git a/ios/chrome/browser/ui/ntp/BUILD.gn b/ios/chrome/browser/ui/ntp/BUILD.gn index 67b4d4c..a67505b 100644 --- a/ios/chrome/browser/ui/ntp/BUILD.gn +++ b/ios/chrome/browser/ui/ntp/BUILD.gn
@@ -126,8 +126,8 @@ "//components/keyed_service/core", "//components/metrics", "//components/ntp_tiles", + "//components/prefs", "//components/strings", - "//components/suggestions", "//ios/chrome/app/strings", "//ios/chrome/browser", "//ios/chrome/browser/browser_state", @@ -138,7 +138,6 @@ "//ios/chrome/browser/ntp_tiles", "//ios/chrome/browser/reading_list", "//ios/chrome/browser/search_engines", - "//ios/chrome/browser/suggestions", "//ios/chrome/browser/tabs", "//ios/chrome/browser/ui:feature_flags", "//ios/chrome/browser/ui/bookmarks",
diff --git a/ios/chrome/browser/ui/ntp/new_tab_page_coordinator.mm b/ios/chrome/browser/ui/ntp/new_tab_page_coordinator.mm index dbcdf0ca..ee66e877 100644 --- a/ios/chrome/browser/ui/ntp/new_tab_page_coordinator.mm +++ b/ios/chrome/browser/ui/ntp/new_tab_page_coordinator.mm
@@ -31,7 +31,6 @@ #import "ios/chrome/browser/ui/content_suggestions/content_suggestions_feature.h" #import "ios/chrome/browser/ui/content_suggestions/content_suggestions_header_synchronizer.h" #import "ios/chrome/browser/ui/content_suggestions/content_suggestions_header_view_controller.h" -#import "ios/chrome/browser/ui/content_suggestions/content_suggestions_metrics_recorder.h" #import "ios/chrome/browser/ui/content_suggestions/discover_feed_metrics_recorder.h" #import "ios/chrome/browser/ui/content_suggestions/ntp_home_mediator.h" #import "ios/chrome/browser/ui/main/scene_state.h" @@ -224,23 +223,16 @@ self.contentSuggestionsCoordinator.bubblePresenter = self.bubblePresenter; DiscoverFeedMetricsRecorder* discoverFeedMetricsRecorder; - ContentSuggestionsMetricsRecorder* contentSuggestionsMetricsRecorder; - - DiscoverFeedService* discoverFeedService = - DiscoverFeedServiceFactory::GetForBrowserState( - self.browser->GetBrowserState()); if (IsDiscoverFeedEnabled()) { + // Creating the DiscoverFeedService will start the DiscoverFeed. + DiscoverFeedService* discoverFeedService = + DiscoverFeedServiceFactory::GetForBrowserState( + self.browser->GetBrowserState()); discoverFeedMetricsRecorder = discoverFeedService->GetDiscoverFeedMetricsRecorder(); self.contentSuggestionsCoordinator.discoverFeedMetricsRecorder = discoverFeedMetricsRecorder; - } else { - // TODO(crbug.com/1200303): Remove this when we launch the Discover feed. - contentSuggestionsMetricsRecorder = - discoverFeedService->GetContentSuggestionsMetricsRecorder(); - self.contentSuggestionsCoordinator.contentSuggestionsMetricsRecorder = - contentSuggestionsMetricsRecorder; } // Requests a Discover feed here if the correct flags and prefs are enabled.
diff --git a/ios/chrome/browser/ui/toolbar/toolbar_mediator.mm b/ios/chrome/browser/ui/toolbar/toolbar_mediator.mm index 9adf62ef0..2febf6b 100644 --- a/ios/chrome/browser/ui/toolbar/toolbar_mediator.mm +++ b/ios/chrome/browser/ui/toolbar/toolbar_mediator.mm
@@ -41,9 +41,6 @@ // The current web state associated with the toolbar. @property(nonatomic, assign) web::WebState* webState; -// Whether the associated toolbar is in dark mode. -@property(nonatomic, assign) BOOL toolbarDarkMode; - // Whether an overlay is currently presented over the web content area. @property(nonatomic, assign, getter=isWebContentAreaShowingOverlay) BOOL webContentAreaShowingOverlay;
diff --git a/ios/chrome/browser/ui/webui/BUILD.gn b/ios/chrome/browser/ui/webui/BUILD.gn index b4793618..62b5f32 100644 --- a/ios/chrome/browser/ui/webui/BUILD.gn +++ b/ios/chrome/browser/ui/webui/BUILD.gn
@@ -25,8 +25,6 @@ "ntp_tiles_internals_ui.h", "prefs_internals_ui.cc", "prefs_internals_ui.h", - "suggestions_ui.cc", - "suggestions_ui.h", "terms_ui.h", "terms_ui.mm", "ukm_internals_ui.cc", @@ -55,7 +53,6 @@ "//components/prefs", "//components/resources", "//components/strings", - "//components/suggestions", "//components/ukm", "//components/ukm/debug:util", "//components/version_info", @@ -74,7 +71,6 @@ "//ios/chrome/browser/ntp_tiles", "//ios/chrome/browser/passwords", "//ios/chrome/browser/policy", - "//ios/chrome/browser/suggestions", "//ios/chrome/browser/ui/util", "//ios/chrome/browser/ui/util:terms_util", "//ios/chrome/browser/web/java_script_console",
diff --git a/ios/chrome/browser/ui/webui/chrome_web_ui_ios_controller_factory.mm b/ios/chrome/browser/ui/webui/chrome_web_ui_ios_controller_factory.mm index cef07d6e..5b4b86c 100644 --- a/ios/chrome/browser/ui/webui/chrome_web_ui_ios_controller_factory.mm +++ b/ios/chrome/browser/ui/webui/chrome_web_ui_ios_controller_factory.mm
@@ -26,7 +26,6 @@ #include "ios/chrome/browser/ui/webui/policy/policy_ui.h" #include "ios/chrome/browser/ui/webui/prefs_internals_ui.h" #include "ios/chrome/browser/ui/webui/signin_internals_ui_ios.h" -#include "ios/chrome/browser/ui/webui/suggestions_ui.h" #include "ios/chrome/browser/ui/webui/terms_ui.h" #include "ios/chrome/browser/ui/webui/translate_internals/translate_internals_ui.h" #include "ios/chrome/browser/ui/webui/ukm_internals_ui.h" @@ -97,8 +96,6 @@ return &NewWebUIIOS<PrefsInternalsUI>; if (url_host == kChromeUISignInInternalsHost) return &NewWebUIIOS<SignInInternalsUIIOS>; - if (url.host_piece() == kChromeUISuggestionsHost) - return &NewWebUIIOS<suggestions::SuggestionsUI>; if (url.host_piece() == kChromeUITranslateInternalsHost) return &NewWebUIIOS<TranslateInternalsUI>; if (url_host == kChromeUIURLKeyedMetricsHost)
diff --git a/ios/chrome/browser/ui/webui/prefs_internals_ui.cc b/ios/chrome/browser/ui/webui/prefs_internals_ui.cc index db85d402..02fae48 100644 --- a/ios/chrome/browser/ui/webui/prefs_internals_ui.cc +++ b/ios/chrome/browser/ui/webui/prefs_internals_ui.cc
@@ -12,7 +12,6 @@ #include "components/prefs/pref_service.h" #include "ios/chrome/browser/browser_state/chrome_browser_state.h" #include "ios/chrome/browser/chrome_url_constants.h" -#include "ios/chrome/browser/suggestions/suggestions_service_factory.h" #include "ios/web/public/thread/web_thread.h" #include "ios/web/public/webui/url_data_source_ios.h"
diff --git a/ios/chrome/browser/ui/webui/suggestions_ui.cc b/ios/chrome/browser/ui/webui/suggestions_ui.cc deleted file mode 100644 index 6952319..0000000 --- a/ios/chrome/browser/ui/webui/suggestions_ui.cc +++ /dev/null
@@ -1,74 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "ios/chrome/browser/ui/webui/suggestions_ui.h" - -#include <map> -#include <string> - -#include "components/suggestions/webui/suggestions_source.h" -#include "ios/chrome/browser/browser_state/chrome_browser_state.h" -#include "ios/chrome/browser/chrome_url_constants.h" -#include "ios/chrome/browser/suggestions/suggestions_service_factory.h" -#include "ios/web/public/webui/url_data_source_ios.h" - -namespace suggestions { - -namespace { - -// Glues a SuggestionsSource instance to //ios/chrome. -class SuggestionsSourceWrapper : public web::URLDataSourceIOS { - public: - explicit SuggestionsSourceWrapper(SuggestionsService* suggestions_service); - - // web::URLDataSourceIOS implementation. - std::string GetSource() const override; - void StartDataRequest( - const std::string& path, - web::URLDataSourceIOS::GotDataCallback callback) override; - std::string GetMimeType(const std::string& path) const override; - - private: - ~SuggestionsSourceWrapper() override; - - SuggestionsSource suggestions_source_; - - DISALLOW_COPY_AND_ASSIGN(SuggestionsSourceWrapper); -}; - -SuggestionsSourceWrapper::SuggestionsSourceWrapper( - SuggestionsService* suggestions_service) - : suggestions_source_(suggestions_service, kChromeUISuggestionsURL) {} - -SuggestionsSourceWrapper::~SuggestionsSourceWrapper() {} - -std::string SuggestionsSourceWrapper::GetSource() const { - return kChromeUISuggestionsHost; -} - -void SuggestionsSourceWrapper::StartDataRequest( - const std::string& path, - web::URLDataSourceIOS::GotDataCallback callback) { - suggestions_source_.StartDataRequest(path, std::move(callback)); -} - -std::string SuggestionsSourceWrapper::GetMimeType( - const std::string& path) const { - return "text/html"; -} - -} // namespace - -SuggestionsUI::SuggestionsUI(web::WebUIIOS* web_ui, const std::string& host) - : web::WebUIIOSController(web_ui, host) { - ChromeBrowserState* browser_state = ChromeBrowserState::FromWebUIIOS(web_ui); - web::URLDataSourceIOS::Add( - browser_state, - new SuggestionsSourceWrapper( - SuggestionsServiceFactory::GetForBrowserState(browser_state))); -} - -SuggestionsUI::~SuggestionsUI() {} - -} // namespace suggestions
diff --git a/ios/chrome/browser/ui/webui/suggestions_ui.h b/ios/chrome/browser/ui/webui/suggestions_ui.h deleted file mode 100644 index ff7571ad..0000000 --- a/ios/chrome/browser/ui/webui/suggestions_ui.h +++ /dev/null
@@ -1,32 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef IOS_CHROME_BROWSER_UI_WEBUI_SUGGESTIONS_UI_H_ -#define IOS_CHROME_BROWSER_UI_WEBUI_SUGGESTIONS_UI_H_ - -#include <string> - -#include "base/macros.h" -#include "ios/web/public/webui/web_ui_ios_controller.h" - -namespace web { -class WebUIIOS; -} - -namespace suggestions { - -// The WebUIController for chrome://suggestions. Renders a webpage to list -// SuggestionsService data. -class SuggestionsUI : public web::WebUIIOSController { - public: - explicit SuggestionsUI(web::WebUIIOS* web_ui, const std::string& host); - ~SuggestionsUI() override; - - private: - DISALLOW_COPY_AND_ASSIGN(SuggestionsUI); -}; - -} // namespace suggestions - -#endif // IOS_CHROME_BROWSER_UI_WEBUI_SUGGESTIONS_UI_H_
diff --git a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.arm64.zip.sha1 b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.arm64.zip.sha1 index ccd4e94..24ecfa7 100644 --- a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.arm64.zip.sha1 +++ b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.arm64.zip.sha1
@@ -1 +1 @@ -cc337f31543e49f86e0b9803217347bf947cf5ce \ No newline at end of file +4b4485e3d74b5a8af01dbc33c1ed6da7f07404c7 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.x64.zip.sha1 b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.x64.zip.sha1 index d22e806..8f90f87 100644 --- a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.x64.zip.sha1 +++ b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.x64.zip.sha1
@@ -1 +1 @@ -6aea8a4ab0d2a24fe2790dcce1e114b9bcff778a \ No newline at end of file +529e0089d65b21f1b19532bc680c7821ff27fcd2 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.arm64.zip.sha1 b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.arm64.zip.sha1 index 1a128b2..0889c174 100644 --- a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.arm64.zip.sha1 +++ b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.arm64.zip.sha1
@@ -1 +1 @@ -33c9c77b9f0c0a63872fa71c50e9cc33e2d5ef64 \ No newline at end of file +9bfacae858389bd7009457f5a8ca74002e6b1227 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.x64.zip.sha1 b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.x64.zip.sha1 index ce06451..d0d2cf33 100644 --- a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.x64.zip.sha1 +++ b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.x64.zip.sha1
@@ -1 +1 @@ -2911969fa4caab0e99dcbd96dfb812506e36d83a \ No newline at end of file +4da6a9474dc4ed9af94d4142c3ac5c3da98cc94c \ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.arm64.zip.sha1 b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.arm64.zip.sha1 index e63f13c4..08fef2d 100644 --- a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.arm64.zip.sha1 +++ b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.arm64.zip.sha1
@@ -1 +1 @@ -45a69bc363b4ee87bcb22bab3de9eadf7c88297e \ No newline at end of file +1b902493ccb1ab67e5c9237c34c7f3e27c8d655a \ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.x64.zip.sha1 b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.x64.zip.sha1 index e77be76..a51441ad 100644 --- a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.x64.zip.sha1 +++ b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.x64.zip.sha1
@@ -1 +1 @@ -09b02270405a1ece9dfab6e7d44de09e74ccd85b \ No newline at end of file +841b1c90796fd4e244e2e010b002a979d580f7ca \ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.arm64.zip.sha1 b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.arm64.zip.sha1 index 1d06a7b..ad754fe 100644 --- a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.arm64.zip.sha1 +++ b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.arm64.zip.sha1
@@ -1 +1 @@ -be2a67431c1677711a36dc219ae2cbd0590d35b9 \ No newline at end of file +26ba4bdfa9eb7c7bb260d0b325ffb276e4355fe4 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.x64.zip.sha1 b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.x64.zip.sha1 index c1d28573..3e5492f 100644 --- a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.x64.zip.sha1 +++ b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.x64.zip.sha1
@@ -1 +1 @@ -7f4cdf5ab5b693a7cd8131f6716827bbb0416a9e \ No newline at end of file +fc0fb9ff949d6b577227abf201b93364455946c0 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.arm64.zip.sha1 b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.arm64.zip.sha1 index 0671098..540c256 100644 --- a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.arm64.zip.sha1 +++ b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.arm64.zip.sha1
@@ -1 +1 @@ -dfebc194fd798a663b728a332641001bdb87a625 \ No newline at end of file +76987345e9cf6cab7c4ce1236dae56589a549bdd \ No newline at end of file
diff --git a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.x64.zip.sha1 b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.x64.zip.sha1 index 3733ece..c95e3190 100644 --- a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.x64.zip.sha1 +++ b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.x64.zip.sha1
@@ -1 +1 @@ -ad24f9c131870e905413436971bdcf80c7fcae6e \ No newline at end of file +1073c90b71d44a033218244080b6465ddd7f5033 \ No newline at end of file
diff --git a/media/cdm/cdm_type_conversion.cc b/media/cdm/cdm_type_conversion.cc index c938623..726aa52 100644 --- a/media/cdm/cdm_type_conversion.cc +++ b/media/cdm/cdm_type_conversion.cc
@@ -588,7 +588,7 @@ const DecryptConfig* decrypt_config = encrypted_buffer.decrypt_config(); if (!decrypt_config) { - DVLOG(2) << __func__ << ": Clear buffer."; + DVLOG(3) << __func__ << ": Clear buffer."; return; }
diff --git a/media/cdm/win/media_foundation_cdm_factory.cc b/media/cdm/win/media_foundation_cdm_factory.cc index 4aa3972..ebac525e 100644 --- a/media/cdm/win/media_foundation_cdm_factory.cc +++ b/media/cdm/win/media_foundation_cdm_factory.cc
@@ -158,12 +158,17 @@ base::UTF8ToWide(content_type).c_str()); } +crash_reporter::CrashKeyString<256> g_origin_crash_key("cdm-origin"); + } // namespace MediaFoundationCdmFactory::MediaFoundationCdmFactory( std::unique_ptr<CdmAuxiliaryHelper> helper, const base::FilePath& user_data_dir) - : helper_(std::move(helper)), user_data_dir_(user_data_dir) {} + : helper_(std::move(helper)), + user_data_dir_(user_data_dir), + cdm_origin_crash_key_(&g_origin_crash_key, + helper_->GetCdmOrigin().Serialize()) {} MediaFoundationCdmFactory::~MediaFoundationCdmFactory() = default;
diff --git a/media/cdm/win/media_foundation_cdm_factory.h b/media/cdm/win/media_foundation_cdm_factory.h index 574d2386..1810e351 100644 --- a/media/cdm/win/media_foundation_cdm_factory.h +++ b/media/cdm/win/media_foundation_cdm_factory.h
@@ -17,6 +17,7 @@ #include "base/memory/weak_ptr.h" #include "base/unguessable_token.h" #include "base/win/scoped_com_initializer.h" +#include "components/crash/core/common/crash_key.h" #include "media/base/cdm_factory.h" #include "media/base/media_export.h" #include "media/cdm/cdm_auxiliary_helper.h" @@ -88,6 +89,9 @@ std::unique_ptr<CdmAuxiliaryHelper> helper_; base::FilePath user_data_dir_; + // CDM origin crash key used in crash reporting. + crash_reporter::ScopedCrashKeyString cdm_origin_crash_key_; + // IMFContentDecryptionModule implementations typically require MTA to run. base::win::ScopedCOMInitializer com_initializer_{ base::win::ScopedCOMInitializer::kMTA};
diff --git a/media/fuchsia/cdm/service/BUILD.gn b/media/fuchsia/cdm/service/BUILD.gn index 7cd4ac5..b87b99f 100644 --- a/media/fuchsia/cdm/service/BUILD.gn +++ b/media/fuchsia/cdm/service/BUILD.gn
@@ -20,7 +20,6 @@ deps = [ "//fuchsia/base", "//media/fuchsia/mojom", - "//third_party/fuchsia-sdk/sdk/pkg/fit-promise", "//url", ] } @@ -36,7 +35,6 @@ "//media", "//testing/gmock", "//testing/gtest", - "//third_party/fuchsia-sdk/sdk/pkg/fit-promise", "//url", ]
diff --git a/media/gpu/android/android_video_encode_accelerator.cc b/media/gpu/android/android_video_encode_accelerator.cc index 51c4175..248982f5 100644 --- a/media/gpu/android/android_video_encode_accelerator.cc +++ b/media/gpu/android/android_video_encode_accelerator.cc
@@ -175,6 +175,15 @@ return false; } + // Non 16x16 aligned resolutions don't work with MediaCodec unfortunately, see + // https://crbug.com/1084702 for details. + if (config.input_visible_size.width() % 16 != 0 || + config.input_visible_size.height() % 16 != 0) { + DLOG(ERROR) << "MediaCodec is only tested with resolutions " + "that are 16x16 aligned."; + return false; + } + frame_size_ = config.input_visible_size; last_set_bitrate_ = config.bitrate.target();
diff --git a/native_client_sdk/OWNERS b/native_client_sdk/OWNERS index 2de7111..3e3c6d73 100644 --- a/native_client_sdk/OWNERS +++ b/native_client_sdk/OWNERS
@@ -1,4 +1,2 @@ set noparent -binji@chromium.org -bradnelson@chromium.org sbc@chromium.org
diff --git a/native_client_sdk/src/README b/native_client_sdk/src/README index 3c35cb22..1b90c96 100644 --- a/native_client_sdk/src/README +++ b/native_client_sdk/src/README
@@ -18,7 +18,7 @@ If you want to contribute to the Native Client SDK itself, please read the online documentation on contributing code to Chromium here: - http://www.chromium.org/developers/contributing-code + https://chromium.googlesource.com/chromium/src/+/refs/heads/main/docs/contributing.md Known Issues ------------
diff --git a/net/dns/host_resolver_manager.cc b/net/dns/host_resolver_manager.cc index 2e15b86..2dff5aae 100644 --- a/net/dns/host_resolver_manager.cc +++ b/net/dns/host_resolver_manager.cc
@@ -81,6 +81,7 @@ #include "net/dns/dns_response_result_extractor.h" #include "net/dns/dns_transaction.h" #include "net/dns/dns_util.h" +#include "net/dns/host_cache.h" #include "net/dns/host_resolver_mdns_listener_impl.h" #include "net/dns/host_resolver_mdns_task.h" #include "net/dns/host_resolver_proc.h" @@ -2881,15 +2882,14 @@ HostCache::Entry::SOURCE_UNKNOWN); } - absl::optional<HostCache::Entry> resolved = - ResolveAsIP(job_key.query_type, resolve_canonname, ip_address); - if (resolved) - return resolved.value(); + if (ip_address.IsValid()) + return ResolveAsIP(job_key.query_type, resolve_canonname, ip_address); // Special-case localhost names, as per the recommendations in // https://tools.ietf.org/html/draft-west-let-localhost-be-localhost. - resolved = ServeLocalhost(GetHostname(job_key.host), job_key.query_type, - default_family_due_to_no_ipv6); + absl::optional<HostCache::Entry> resolved = + ServeLocalhost(GetHostname(job_key.host), job_key.query_type, + default_family_due_to_no_ipv6); if (resolved) return resolved.value(); @@ -2959,17 +2959,17 @@ } } -absl::optional<HostCache::Entry> HostResolverManager::ResolveAsIP( - DnsQueryType query_type, - bool resolve_canonname, - const IPAddress& ip_address) { - if (!ip_address.IsValid() || !IsAddressType(query_type)) - return absl::nullopt; +HostCache::Entry HostResolverManager::ResolveAsIP(DnsQueryType query_type, + bool resolve_canonname, + const IPAddress& ip_address) { + DCHECK(ip_address.IsValid()); + // IP literals cannot resolve unless the query type is an address query that + // allows addresses with the same address family as the literal. E.g., don't + // return IPv6 addresses for IPv4 queries or anything for a non-address query. AddressFamily family = GetAddressFamily(ip_address); if (query_type != DnsQueryType::UNSPECIFIED && query_type != AddressFamilyToDnsQueryType(family)) { - // Don't return IPv6 addresses for IPv4 queries, and vice versa. return HostCache::Entry(ERR_NAME_NOT_RESOLVED, HostCache::Entry::SOURCE_UNKNOWN); }
diff --git a/net/dns/host_resolver_manager.h b/net/dns/host_resolver_manager.h index d44b51b..ac4e6827 100644 --- a/net/dns/host_resolver_manager.h +++ b/net/dns/host_resolver_manager.h
@@ -301,11 +301,10 @@ std::deque<TaskType> tasks, RequestImpl* request); - // Tries to resolve |key| and its possible IP address representation, - // |ip_address|. Returns a results entry iff the input can be resolved. - absl::optional<HostCache::Entry> ResolveAsIP(DnsQueryType query_type, - bool resolve_canonname, - const IPAddress& ip_address); + // Resolves the IP literal hostname represented by `ip_address`. + HostCache::Entry ResolveAsIP(DnsQueryType query_type, + bool resolve_canonname, + const IPAddress& ip_address); // Returns the result iff |cache_usage| permits cache lookups and a positive // match is found for |key| in |cache|. |out_stale_info| must be non-null, and
diff --git a/net/dns/host_resolver_manager_unittest.cc b/net/dns/host_resolver_manager_unittest.cc index 1d5f655..fdb8276 100644 --- a/net/dns/host_resolver_manager_unittest.cc +++ b/net/dns/host_resolver_manager_unittest.cc
@@ -8252,6 +8252,32 @@ bar_records.begin(), bar_records.end())); } +TEST_F(HostResolverManagerDnsTest, TxtQueryRejectsIpLiteral) { + MockDnsClientRuleList rules; + + // Entry that would resolve if DNS is mistakenly queried to ensure that does + // not happen. + rules.emplace_back("8.8.8.8", dns_protocol::kTypeTXT, /*secure=*/false, + MockDnsClientRule::Result( + BuildTestDnsTextResponse("8.8.8.8", {{"text"}})), + /*delay=*/false); + + CreateResolver(); + UseMockDnsClient(CreateValidDnsConfig(), std::move(rules)); + + HostResolver::ResolveHostParameters parameters; + parameters.dns_query_type = DnsQueryType::TXT; + + ResolveHostResponseHelper response(resolver_->CreateRequest( + HostPortPair("8.8.8.8", 108), NetworkIsolationKey(), NetLogWithSource(), + parameters, resolve_context_.get(), resolve_context_->host_cache())); + EXPECT_THAT(response.result_error(), IsError(ERR_NAME_NOT_RESOLVED)); + EXPECT_FALSE(response.request()->GetAddressResults()); + EXPECT_FALSE(response.request()->GetTextResults()); + EXPECT_FALSE(response.request()->GetHostnameResults()); + EXPECT_FALSE(response.request()->GetExperimentalResultsForTesting()); +} + // Test that TXT records can be extracted from a response that also contains // unrecognized record types. TEST_F(HostResolverManagerDnsTest, TxtQuery_MixedWithUnrecognizedType) { @@ -8644,12 +8670,15 @@ HostPortPair("foo.com", 108), HostPortPair("bar.com", 108)))); } -TEST_F(HostResolverManagerDnsTest, PtrQuery_Ip) { +TEST_F(HostResolverManagerDnsTest, PtrQueryRejectsIpLiteral) { MockDnsClientRuleList rules; - rules.emplace_back("8.8.8.8", dns_protocol::kTypePTR, false /* secure */, + + // Entry that would resolve if DNS is mistakenly queried to ensure that does + // not happen. + rules.emplace_back("8.8.8.8", dns_protocol::kTypePTR, /*secure=*/false, MockDnsClientRule::Result(BuildTestDnsPointerResponse( "8.8.8.8", {"foo.com", "bar.com"})), - false /* delay */); + /*delay=*/false); CreateResolver(); UseMockDnsClient(CreateValidDnsConfig(), std::move(rules)); @@ -8660,6 +8689,31 @@ ResolveHostResponseHelper response(resolver_->CreateRequest( HostPortPair("8.8.8.8", 108), NetworkIsolationKey(), NetLogWithSource(), parameters, resolve_context_.get(), resolve_context_->host_cache())); + EXPECT_THAT(response.result_error(), IsError(ERR_NAME_NOT_RESOLVED)); + EXPECT_FALSE(response.request()->GetAddressResults()); + EXPECT_FALSE(response.request()->GetTextResults()); + EXPECT_FALSE(response.request()->GetHostnameResults()); + EXPECT_FALSE(response.request()->GetExperimentalResultsForTesting()); +} + +TEST_F(HostResolverManagerDnsTest, PtrQueryHandlesReverseIpLookup) { + const char kHostname[] = "8.8.8.8.in-addr.arpa"; + + MockDnsClientRuleList rules; + rules.emplace_back(kHostname, dns_protocol::kTypePTR, /*secure=*/false, + MockDnsClientRule::Result(BuildTestDnsPointerResponse( + kHostname, {"dns.google.test", "foo.test"})), + /*delay=*/false); + + CreateResolver(); + UseMockDnsClient(CreateValidDnsConfig(), std::move(rules)); + + HostResolver::ResolveHostParameters parameters; + parameters.dns_query_type = DnsQueryType::PTR; + + ResolveHostResponseHelper response(resolver_->CreateRequest( + HostPortPair(kHostname, 108), NetworkIsolationKey(), NetLogWithSource(), + parameters, resolve_context_.get(), resolve_context_->host_cache())); EXPECT_THAT(response.result_error(), IsOk()); EXPECT_FALSE(response.request()->GetAddressResults()); EXPECT_FALSE(response.request()->GetTextResults()); @@ -8668,7 +8722,8 @@ // Order between separate records is undefined. EXPECT_THAT(response.request()->GetHostnameResults(), testing::Optional(testing::UnorderedElementsAre( - HostPortPair("foo.com", 108), HostPortPair("bar.com", 108)))); + HostPortPair("dns.google.test", 108), + HostPortPair("foo.test", 108)))); } TEST_F(HostResolverManagerDnsTest, PtrQuery_NonexistentDomain) { @@ -8960,6 +9015,33 @@ HostPortPair("google.com", 5))); } +TEST_F(HostResolverManagerDnsTest, SrvQueryRejectsIpLiteral) { + MockDnsClientRuleList rules; + + // Entry that would resolve if DNS is mistakenly queried to ensure that does + // not happen. + rules.emplace_back("8.8.8.8", dns_protocol::kTypeSRV, /*secure=*/false, + MockDnsClientRule::Result(BuildTestDnsServiceResponse( + "8.8.8.8", {{/*priority=*/4, /*weight=*/0, /*port=*/90, + /*target=*/"google.test"}})), + /*delay=*/false); + + CreateResolver(); + UseMockDnsClient(CreateValidDnsConfig(), std::move(rules)); + + HostResolver::ResolveHostParameters parameters; + parameters.dns_query_type = DnsQueryType::SRV; + + ResolveHostResponseHelper response(resolver_->CreateRequest( + HostPortPair("8.8.8.8", 108), NetworkIsolationKey(), NetLogWithSource(), + parameters, resolve_context_.get(), resolve_context_->host_cache())); + EXPECT_THAT(response.result_error(), IsError(ERR_NAME_NOT_RESOLVED)); + EXPECT_FALSE(response.request()->GetAddressResults()); + EXPECT_FALSE(response.request()->GetTextResults()); + EXPECT_FALSE(response.request()->GetHostnameResults()); + EXPECT_FALSE(response.request()->GetExperimentalResultsForTesting()); +} + // 0-weight services are allowed. Ensure that we can handle such records, // especially the case where all entries have weight 0. TEST_F(HostResolverManagerDnsTest, SrvQuery_ZeroWeight) { @@ -9282,6 +9364,34 @@ EXPECT_FALSE(response.request()->GetExperimentalResultsForTesting()); } +TEST_F(HostResolverManagerDnsTest, HttpsQueryRejectsIpLiteral) { + MockDnsClientRuleList rules; + + // Entry that would resolve if DNS is mistakenly queried to ensure that does + // not happen. + rules.emplace_back("8.8.8.8", dns_protocol::kTypeHttps, /*secure=*/false, + MockDnsClientRule::Result(BuildTestDnsResponse( + "8.8.8.8", dns_protocol::kTypeHttps, + {BuildTestHttpsAliasRecord("8.8.8.8", "alias.test")})), + /*delay=*/false); + + CreateResolver(); + UseMockDnsClient(CreateValidDnsConfig(), std::move(rules)); + + HostResolver::ResolveHostParameters parameters; + parameters.dns_query_type = DnsQueryType::HTTPS; + + ResolveHostResponseHelper response(resolver_->CreateRequest( + url::SchemeHostPort(url::kHttpsScheme, "8.8.8.8", 443), + NetworkIsolationKey(), NetLogWithSource(), parameters, + resolve_context_.get(), resolve_context_->host_cache())); + EXPECT_THAT(response.result_error(), IsError(ERR_NAME_NOT_RESOLVED)); + EXPECT_FALSE(response.request()->GetAddressResults()); + EXPECT_FALSE(response.request()->GetTextResults()); + EXPECT_FALSE(response.request()->GetHostnameResults()); + EXPECT_FALSE(response.request()->GetExperimentalResultsForTesting()); +} + TEST_F(HostResolverManagerDnsTest, HttpsInsecureQueryDisallowedWhenAdditionalTypesDisallowed) { const std::string kName = "https.test";
diff --git a/net/quic/quic_transport_client.cc b/net/quic/quic_transport_client.cc index c1dbbecc..11dc85a6 100644 --- a/net/quic/quic_transport_client.cc +++ b/net/quic/quic_transport_client.cc
@@ -17,6 +17,7 @@ #include "net/third_party/quiche/src/quic/core/quic_connection.h" #include "net/third_party/quiche/src/quic/core/quic_utils.h" #include "net/url_request/url_request_context.h" +#include "url/scheme_host_port.h" namespace net { @@ -213,7 +214,7 @@ next_connect_state_ = CONNECT_STATE_RESOLVE_HOST_COMPLETE; HostResolver::ResolveHostParameters parameters; resolve_host_request_ = context_->host_resolver()->CreateRequest( - HostPortPair::FromURL(url_), isolation_key_, net_log_, absl::nullopt); + url::SchemeHostPort(url_), isolation_key_, net_log_, absl::nullopt); return resolve_host_request_->Start( base::BindOnce(&QuicTransportClient::DoLoop, base::Unretained(this))); }
diff --git a/pdf/BUILD.gn b/pdf/BUILD.gn index fd0b12dab..5460550 100644 --- a/pdf/BUILD.gn +++ b/pdf/BUILD.gn
@@ -242,7 +242,11 @@ } source_set("accessibility_structs") { - visibility = [ ":*" ] + visibility = [ + ":*", + "//components:components_browsertests", + "//components/pdf/renderer", + ] sources = [ "accessibility_helper.cc",
diff --git a/services/metrics/public/cpp/ukm_source.cc b/services/metrics/public/cpp/ukm_source.cc index 0e7d69cf..ab4e3dc 100644 --- a/services/metrics/public/cpp/ukm_source.cc +++ b/services/metrics/public/cpp/ukm_source.cc
@@ -27,9 +27,11 @@ // changed to an Atomic32 (make CustomTabState derive from int32_t) and accessed // with no-barrier loads and stores. UkmSource::CustomTabState g_custom_tab_state = UkmSource::kCustomTabUnset; +// TODO(crbug/1228735): This will be replacing g_custom_tab_state above. +int32_t g_android_activity_type_state = -1; // Returns a URL that is under the length limit, by returning a constant -// string when the URl is too long. +// string when the URL is too long. std::string GetShortenedURL(const GURL& url) { if (url.spec().length() > kMaxURLLength) return kMaxUrlLengthMessage; @@ -60,6 +62,25 @@ return SourceType::DEFAULT; } } + +AndroidActivityType ToProtobufActivityType(int32_t type) { + switch (type) { + case 0: + return AndroidActivityType::TABBED; + case 1: + return AndroidActivityType::CUSTOM_TAB; + case 2: + return AndroidActivityType::TRUSTED_WEB_ACTIVITY; + case 3: + return AndroidActivityType::WEB_APP; + case 4: + return AndroidActivityType::WEB_APK; + default: + NOTREACHED(); + return AndroidActivityType::TABBED; + } +} + } // namespace // static @@ -67,6 +88,11 @@ g_custom_tab_state = visible ? kCustomTabTrue : kCustomTabFalse; } +// static +void UkmSource::SetAndroidActivityTypeState(int32_t activity_type) { + g_android_activity_type_state = activity_type; +} + UkmSource::NavigationData::NavigationData() = default; UkmSource::NavigationData::~NavigationData() = default; @@ -100,6 +126,7 @@ : id_(id), type_(GetSourceIdType(id_)), custom_tab_state_(g_custom_tab_state), + android_activity_type_state_(g_android_activity_type_state), creation_time_(base::TimeTicks::Now()) { navigation_data_.urls = {url}; DCHECK(!url.is_empty()); @@ -110,6 +137,7 @@ type_(GetSourceIdType(id_)), navigation_data_(navigation_data), custom_tab_state_(g_custom_tab_state), + android_activity_type_state_(g_android_activity_type_state), creation_time_(base::TimeTicks::Now()) { DCHECK(type_ == SourceIdType::NAVIGATION_ID); DCHECK(!navigation_data.urls.empty()); @@ -141,6 +169,12 @@ if (custom_tab_state_ != kCustomTabUnset) proto_source->set_is_custom_tab(custom_tab_state_ == kCustomTabTrue); + // -1 corresponds to the unset state. Android activity type values start at 0. + // See chrome/browser/flags/ActivityType.java + if (android_activity_type_state_ != -1) + proto_source->set_android_activity_type( + ToProtobufActivityType(android_activity_type_state_)); + if (navigation_data_.previous_source_id != kInvalidSourceId) proto_source->set_previous_source_id(navigation_data_.previous_source_id);
diff --git a/services/metrics/public/cpp/ukm_source.h b/services/metrics/public/cpp/ukm_source.h index 0609d484..e78bf492 100644 --- a/services/metrics/public/cpp/ukm_source.h +++ b/services/metrics/public/cpp/ukm_source.h
@@ -132,6 +132,9 @@ // Sets the current "custom tab" state. This can be called from any thread. static void SetCustomTabVisible(bool visible); + // Sets the current "android_activity_type" state, this will replace the + // "custom tab" state. + static void SetAndroidActivityTypeState(int32_t android_activity_type); private: const ukm::SourceId id_; @@ -142,7 +145,9 @@ // A flag indicating if metric was collected in a custom tab. This is set // automatically when the object is created and so represents the state when // the metric was created. + // TODO(crbug/1228735): To be replaced by |android_activity_type_state_|. const CustomTabState custom_tab_state_; + const int32_t android_activity_type_state_ = -1; // When this object was created. const base::TimeTicks creation_time_;
diff --git a/services/network/trust_tokens/trust_token_database_owner.cc b/services/network/trust_tokens/trust_token_database_owner.cc index 6b02af7..5abab4d 100644 --- a/services/network/trust_tokens/trust_token_database_owner.cc +++ b/services/network/trust_tokens/trust_token_database_owner.cc
@@ -87,6 +87,8 @@ .exclusive_locking = true, .page_size = 4096, .cache_size = 500, + // TODO(pwnall): Add a meta table and remove this option. + .mmap_alt_status_discouraged = true, })), issuer_table_( std::make_unique<sqlite_proto::KeyValueTable<TrustTokenIssuerConfig>>( @@ -119,8 +121,6 @@ flush_delay_for_writes)) { // These two lines are boilerplate copied from predictor_database.cc. backing_database_->set_histogram_tag("TrustTokens"); - // We have to call this because the database doesn't have a "meta" table. - backing_database_->set_mmap_alt_status(); // Because TrustTokenDatabaseOwners are only constructed through an // asynchronous factory method, they are impossible to delete prior to their
diff --git a/skia/OWNERS b/skia/OWNERS index 7fec08d..efd493e 100644 --- a/skia/OWNERS +++ b/skia/OWNERS
@@ -8,7 +8,6 @@ fmalita@chromium.org jvanverth@google.com michaelludwig@google.com -mtklein@google.com reed@google.com rmistry@google.com robertphillips@google.com
diff --git a/sql/database.cc b/sql/database.cc index f0f3156..bb1c729 100644 --- a/sql/database.cc +++ b/sql/database.cc
@@ -645,9 +645,9 @@ // Progress information is tracked in the [meta] table for databases which use // sql::MetaTable, otherwise it is tracked in a special view. - // TODO(shess): Move all cases to the view implementation. + // TODO(pwnall): Migrate all databases to using a meta table. int64_t mmap_ofs = 0; - if (mmap_alt_status_) { + if (options_.mmap_alt_status_discouraged) { if (!GetMmapAltStatus(&mmap_ofs)) return 0; } else { @@ -725,7 +725,7 @@ DCHECK(mmap_ofs > 0 || mmap_ofs == MetaTable::kMmapFailure); } - if (mmap_alt_status_) { + if (options_.mmap_alt_status_discouraged) { if (!SetMmapAltStatus(mmap_ofs)) return 0; } else {
diff --git a/sql/database.h b/sql/database.h index eea1380..7c49ba5 100644 --- a/sql/database.h +++ b/sql/database.h
@@ -131,6 +131,16 @@ // TODO(pwnall): Replace the default with an invalid value after all // sql::Database users explicitly initialize page_size. int cache_size = 0; + + // Stores mmap failures in the SQL schema, instead of the meta table. + // + // This option is strongly discouraged for new databases, and will eventually + // be removed. + // + // If this option is true, the mmap status is stored in the database schema. + // Like any other schema change, changing the mmap status invalidates all + // pre-compiled SQL statements. + bool mmap_alt_status_discouraged = false; }; // Handle to an open SQLite database. @@ -181,11 +191,6 @@ // Returns whether a database will be opened in WAL mode. bool UseWALMode() const; - // Call to use alternative status-tracking for mmap. Usually this is tracked - // in the meta table, but some databases have no meta table. - // TODO(shess): Maybe just have all databases use the alt option? - void set_mmap_alt_status() { mmap_alt_status_ = true; } - // Opt out of memory-mapped file I/O. void set_mmap_disabled() { mmap_disabled_ = true; } @@ -761,9 +766,6 @@ // databases. bool poisoned_ = false; - // |true| to use alternate storage for tracking mmap status. - bool mmap_alt_status_ = false; - // |true| if SQLite memory-mapped I/O is not desired for this database. bool mmap_disabled_;
diff --git a/sql/database_unittest.cc b/sql/database_unittest.cc index fa785bb..bbfb075 100644 --- a/sql/database_unittest.cc +++ b/sql/database_unittest.cc
@@ -1257,7 +1257,10 @@ // Re-open fresh database with alt-status flag set. db_->Close(); Database::Delete(db_path_); - db_->set_mmap_alt_status(); + + DatabaseOptions options = GetDBOptions(); + options.mmap_alt_status_discouraged = true; + db_ = std::make_unique<Database>(options); ASSERT_TRUE(db_->Open(db_path_)); { @@ -1339,7 +1342,11 @@ ASSERT_FALSE(db_->DoesViewExist("MmapStatus")); // Using alt status, everything should be mapped, with state in the view. - db_->set_mmap_alt_status(); + DatabaseOptions options = GetDBOptions(); + options.mmap_alt_status_discouraged = true; + db_ = std::make_unique<Database>(options); + ASSERT_TRUE(db_->Open(db_path_)); + ASSERT_GT(db_->GetAppropriateMmapSize(), kMmapAlot); ASSERT_FALSE(db_->DoesTableExist("meta")); ASSERT_TRUE(db_->DoesViewExist("MmapStatus"));
diff --git a/testing/buildbot/chromium.android.fyi.json b/testing/buildbot/chromium.android.fyi.json index 47ab03e4..e05c488 100644 --- a/testing/buildbot/chromium.android.fyi.json +++ b/testing/buildbot/chromium.android.fyi.json
@@ -4829,18 +4829,18 @@ ], "named_caches": [ { - "name": "avd_generic_androidS", + "name": "avd_generic_android_s", "path": ".android" }, { - "name": "system_images_android_S_google_apis_x64", + "name": "system_images_android_s_google_apis_x64", "path": ".emulator_sdk" } ], "optional_dimensions": { "60": [ { - "caches": "avd_generic_androidS" + "caches": "avd_generic_android_s" } ] }, @@ -4898,18 +4898,18 @@ ], "named_caches": [ { - "name": "avd_generic_androidS", + "name": "avd_generic_android_s", "path": ".android" }, { - "name": "system_images_android_S_google_apis_x64", + "name": "system_images_android_s_google_apis_x64", "path": ".emulator_sdk" } ], "optional_dimensions": { "60": [ { - "caches": "avd_generic_androidS" + "caches": "avd_generic_android_s" } ] }, @@ -4968,18 +4968,18 @@ ], "named_caches": [ { - "name": "avd_generic_androidS", + "name": "avd_generic_android_s", "path": ".android" }, { - "name": "system_images_android_S_google_apis_x64", + "name": "system_images_android_s_google_apis_x64", "path": ".emulator_sdk" } ], "optional_dimensions": { "60": [ { - "caches": "avd_generic_androidS" + "caches": "avd_generic_android_s" } ] }, @@ -5037,18 +5037,18 @@ ], "named_caches": [ { - "name": "avd_generic_androidS", + "name": "avd_generic_android_s", "path": ".android" }, { - "name": "system_images_android_S_google_apis_x64", + "name": "system_images_android_s_google_apis_x64", "path": ".emulator_sdk" } ], "optional_dimensions": { "60": [ { - "caches": "avd_generic_androidS" + "caches": "avd_generic_android_s" } ] }, @@ -5101,18 +5101,18 @@ ], "named_caches": [ { - "name": "avd_generic_androidS", + "name": "avd_generic_android_s", "path": ".android" }, { - "name": "system_images_android_S_google_apis_x64", + "name": "system_images_android_s_google_apis_x64", "path": ".emulator_sdk" } ], "optional_dimensions": { "60": [ { - "caches": "avd_generic_androidS" + "caches": "avd_generic_android_s" } ] }, @@ -5161,18 +5161,18 @@ ], "named_caches": [ { - "name": "avd_generic_androidS", + "name": "avd_generic_android_s", "path": ".android" }, { - "name": "system_images_android_S_google_apis_x64", + "name": "system_images_android_s_google_apis_x64", "path": ".emulator_sdk" } ], "optional_dimensions": { "60": [ { - "caches": "avd_generic_androidS" + "caches": "avd_generic_android_s" } ] }, @@ -5230,18 +5230,18 @@ ], "named_caches": [ { - "name": "avd_generic_androidS", + "name": "avd_generic_android_s", "path": ".android" }, { - "name": "system_images_android_S_google_apis_x64", + "name": "system_images_android_s_google_apis_x64", "path": ".emulator_sdk" } ], "optional_dimensions": { "60": [ { - "caches": "avd_generic_androidS" + "caches": "avd_generic_android_s" } ] }, @@ -5299,18 +5299,18 @@ ], "named_caches": [ { - "name": "avd_generic_androidS", + "name": "avd_generic_android_s", "path": ".android" }, { - "name": "system_images_android_S_google_apis_x64", + "name": "system_images_android_s_google_apis_x64", "path": ".emulator_sdk" } ], "optional_dimensions": { "60": [ { - "caches": "avd_generic_androidS" + "caches": "avd_generic_android_s" } ] }, @@ -5368,18 +5368,18 @@ ], "named_caches": [ { - "name": "avd_generic_androidS", + "name": "avd_generic_android_s", "path": ".android" }, { - "name": "system_images_android_S_google_apis_x64", + "name": "system_images_android_s_google_apis_x64", "path": ".emulator_sdk" } ], "optional_dimensions": { "60": [ { - "caches": "avd_generic_androidS" + "caches": "avd_generic_android_s" } ] }, @@ -5437,18 +5437,18 @@ ], "named_caches": [ { - "name": "avd_generic_androidS", + "name": "avd_generic_android_s", "path": ".android" }, { - "name": "system_images_android_S_google_apis_x64", + "name": "system_images_android_s_google_apis_x64", "path": ".emulator_sdk" } ], "optional_dimensions": { "60": [ { - "caches": "avd_generic_androidS" + "caches": "avd_generic_android_s" } ] }, @@ -5507,18 +5507,18 @@ ], "named_caches": [ { - "name": "avd_generic_androidS", + "name": "avd_generic_android_s", "path": ".android" }, { - "name": "system_images_android_S_google_apis_x64", + "name": "system_images_android_s_google_apis_x64", "path": ".emulator_sdk" } ], "optional_dimensions": { "60": [ { - "caches": "avd_generic_androidS" + "caches": "avd_generic_android_s" } ] }, @@ -5577,18 +5577,18 @@ ], "named_caches": [ { - "name": "avd_generic_androidS", + "name": "avd_generic_android_s", "path": ".android" }, { - "name": "system_images_android_S_google_apis_x64", + "name": "system_images_android_s_google_apis_x64", "path": ".emulator_sdk" } ], "optional_dimensions": { "60": [ { - "caches": "avd_generic_androidS" + "caches": "avd_generic_android_s" } ] }, @@ -5646,18 +5646,18 @@ ], "named_caches": [ { - "name": "avd_generic_androidS", + "name": "avd_generic_android_s", "path": ".android" }, { - "name": "system_images_android_S_google_apis_x64", + "name": "system_images_android_s_google_apis_x64", "path": ".emulator_sdk" } ], "optional_dimensions": { "60": [ { - "caches": "avd_generic_androidS" + "caches": "avd_generic_android_s" } ] }, @@ -5715,18 +5715,18 @@ ], "named_caches": [ { - "name": "avd_generic_androidS", + "name": "avd_generic_android_s", "path": ".android" }, { - "name": "system_images_android_S_google_apis_x64", + "name": "system_images_android_s_google_apis_x64", "path": ".emulator_sdk" } ], "optional_dimensions": { "60": [ { - "caches": "avd_generic_androidS" + "caches": "avd_generic_android_s" } ] }, @@ -5785,18 +5785,18 @@ ], "named_caches": [ { - "name": "avd_generic_androidS", + "name": "avd_generic_android_s", "path": ".android" }, { - "name": "system_images_android_S_google_apis_x64", + "name": "system_images_android_s_google_apis_x64", "path": ".emulator_sdk" } ], "optional_dimensions": { "60": [ { - "caches": "avd_generic_androidS" + "caches": "avd_generic_android_s" } ] }, @@ -5854,18 +5854,18 @@ ], "named_caches": [ { - "name": "avd_generic_androidS", + "name": "avd_generic_android_s", "path": ".android" }, { - "name": "system_images_android_S_google_apis_x64", + "name": "system_images_android_s_google_apis_x64", "path": ".emulator_sdk" } ], "optional_dimensions": { "60": [ { - "caches": "avd_generic_androidS" + "caches": "avd_generic_android_s" } ] }, @@ -5923,18 +5923,18 @@ ], "named_caches": [ { - "name": "avd_generic_androidS", + "name": "avd_generic_android_s", "path": ".android" }, { - "name": "system_images_android_S_google_apis_x64", + "name": "system_images_android_s_google_apis_x64", "path": ".emulator_sdk" } ], "optional_dimensions": { "60": [ { - "caches": "avd_generic_androidS" + "caches": "avd_generic_android_s" } ] }, @@ -5992,18 +5992,18 @@ ], "named_caches": [ { - "name": "avd_generic_androidS", + "name": "avd_generic_android_s", "path": ".android" }, { - "name": "system_images_android_S_google_apis_x64", + "name": "system_images_android_s_google_apis_x64", "path": ".emulator_sdk" } ], "optional_dimensions": { "60": [ { - "caches": "avd_generic_androidS" + "caches": "avd_generic_android_s" } ] }, @@ -6067,18 +6067,18 @@ ], "named_caches": [ { - "name": "avd_generic_androidS", + "name": "avd_generic_android_s", "path": ".android" }, { - "name": "system_images_android_S_google_apis_x64", + "name": "system_images_android_s_google_apis_x64", "path": ".emulator_sdk" } ], "optional_dimensions": { "60": [ { - "caches": "avd_generic_androidS" + "caches": "avd_generic_android_s" } ] }, @@ -6137,18 +6137,18 @@ ], "named_caches": [ { - "name": "avd_generic_androidS", + "name": "avd_generic_android_s", "path": ".android" }, { - "name": "system_images_android_S_google_apis_x64", + "name": "system_images_android_s_google_apis_x64", "path": ".emulator_sdk" } ], "optional_dimensions": { "60": [ { - "caches": "avd_generic_androidS" + "caches": "avd_generic_android_s" } ] }, @@ -6206,18 +6206,18 @@ ], "named_caches": [ { - "name": "avd_generic_androidS", + "name": "avd_generic_android_s", "path": ".android" }, { - "name": "system_images_android_S_google_apis_x64", + "name": "system_images_android_s_google_apis_x64", "path": ".emulator_sdk" } ], "optional_dimensions": { "60": [ { - "caches": "avd_generic_androidS" + "caches": "avd_generic_android_s" } ] }, @@ -6276,18 +6276,18 @@ ], "named_caches": [ { - "name": "avd_generic_androidS", + "name": "avd_generic_android_s", "path": ".android" }, { - "name": "system_images_android_S_google_apis_x64", + "name": "system_images_android_s_google_apis_x64", "path": ".emulator_sdk" } ], "optional_dimensions": { "60": [ { - "caches": "avd_generic_androidS" + "caches": "avd_generic_android_s" } ] }, @@ -6346,18 +6346,18 @@ ], "named_caches": [ { - "name": "avd_generic_androidS", + "name": "avd_generic_android_s", "path": ".android" }, { - "name": "system_images_android_S_google_apis_x64", + "name": "system_images_android_s_google_apis_x64", "path": ".emulator_sdk" } ], "optional_dimensions": { "60": [ { - "caches": "avd_generic_androidS" + "caches": "avd_generic_android_s" } ] }, @@ -6416,18 +6416,18 @@ ], "named_caches": [ { - "name": "avd_generic_androidS", + "name": "avd_generic_android_s", "path": ".android" }, { - "name": "system_images_android_S_google_apis_x64", + "name": "system_images_android_s_google_apis_x64", "path": ".emulator_sdk" } ], "optional_dimensions": { "60": [ { - "caches": "avd_generic_androidS" + "caches": "avd_generic_android_s" } ] }, @@ -6486,18 +6486,18 @@ ], "named_caches": [ { - "name": "avd_generic_androidS", + "name": "avd_generic_android_s", "path": ".android" }, { - "name": "system_images_android_S_google_apis_x64", + "name": "system_images_android_s_google_apis_x64", "path": ".emulator_sdk" } ], "optional_dimensions": { "60": [ { - "caches": "avd_generic_androidS" + "caches": "avd_generic_android_s" } ] }, @@ -6555,18 +6555,18 @@ ], "named_caches": [ { - "name": "avd_generic_androidS", + "name": "avd_generic_android_s", "path": ".android" }, { - "name": "system_images_android_S_google_apis_x64", + "name": "system_images_android_s_google_apis_x64", "path": ".emulator_sdk" } ], "optional_dimensions": { "60": [ { - "caches": "avd_generic_androidS" + "caches": "avd_generic_android_s" } ] }, @@ -6624,18 +6624,18 @@ ], "named_caches": [ { - "name": "avd_generic_androidS", + "name": "avd_generic_android_s", "path": ".android" }, { - "name": "system_images_android_S_google_apis_x64", + "name": "system_images_android_s_google_apis_x64", "path": ".emulator_sdk" } ], "optional_dimensions": { "60": [ { - "caches": "avd_generic_androidS" + "caches": "avd_generic_android_s" } ] }, @@ -6693,18 +6693,18 @@ ], "named_caches": [ { - "name": "avd_generic_androidS", + "name": "avd_generic_android_s", "path": ".android" }, { - "name": "system_images_android_S_google_apis_x64", + "name": "system_images_android_s_google_apis_x64", "path": ".emulator_sdk" } ], "optional_dimensions": { "60": [ { - "caches": "avd_generic_androidS" + "caches": "avd_generic_android_s" } ] }, @@ -6762,18 +6762,18 @@ ], "named_caches": [ { - "name": "avd_generic_androidS", + "name": "avd_generic_android_s", "path": ".android" }, { - "name": "system_images_android_S_google_apis_x64", + "name": "system_images_android_s_google_apis_x64", "path": ".emulator_sdk" } ], "optional_dimensions": { "60": [ { - "caches": "avd_generic_androidS" + "caches": "avd_generic_android_s" } ] }, @@ -6831,18 +6831,18 @@ ], "named_caches": [ { - "name": "avd_generic_androidS", + "name": "avd_generic_android_s", "path": ".android" }, { - "name": "system_images_android_S_google_apis_x64", + "name": "system_images_android_s_google_apis_x64", "path": ".emulator_sdk" } ], "optional_dimensions": { "60": [ { - "caches": "avd_generic_androidS" + "caches": "avd_generic_android_s" } ] }, @@ -6900,18 +6900,18 @@ ], "named_caches": [ { - "name": "avd_generic_androidS", + "name": "avd_generic_android_s", "path": ".android" }, { - "name": "system_images_android_S_google_apis_x64", + "name": "system_images_android_s_google_apis_x64", "path": ".emulator_sdk" } ], "optional_dimensions": { "60": [ { - "caches": "avd_generic_androidS" + "caches": "avd_generic_android_s" } ] }, @@ -6969,18 +6969,18 @@ ], "named_caches": [ { - "name": "avd_generic_androidS", + "name": "avd_generic_android_s", "path": ".android" }, { - "name": "system_images_android_S_google_apis_x64", + "name": "system_images_android_s_google_apis_x64", "path": ".emulator_sdk" } ], "optional_dimensions": { "60": [ { - "caches": "avd_generic_androidS" + "caches": "avd_generic_android_s" } ] }, @@ -7040,18 +7040,18 @@ ], "named_caches": [ { - "name": "avd_generic_androidS", + "name": "avd_generic_android_s", "path": ".android" }, { - "name": "system_images_android_S_google_apis_x64", + "name": "system_images_android_s_google_apis_x64", "path": ".emulator_sdk" } ], "optional_dimensions": { "60": [ { - "caches": "avd_generic_androidS" + "caches": "avd_generic_android_s" } ] }, @@ -7109,18 +7109,18 @@ ], "named_caches": [ { - "name": "avd_generic_androidS", + "name": "avd_generic_android_s", "path": ".android" }, { - "name": "system_images_android_S_google_apis_x64", + "name": "system_images_android_s_google_apis_x64", "path": ".emulator_sdk" } ], "optional_dimensions": { "60": [ { - "caches": "avd_generic_androidS" + "caches": "avd_generic_android_s" } ] }, @@ -7178,18 +7178,18 @@ ], "named_caches": [ { - "name": "avd_generic_androidS", + "name": "avd_generic_android_s", "path": ".android" }, { - "name": "system_images_android_S_google_apis_x64", + "name": "system_images_android_s_google_apis_x64", "path": ".emulator_sdk" } ], "optional_dimensions": { "60": [ { - "caches": "avd_generic_androidS" + "caches": "avd_generic_android_s" } ] }, @@ -7247,18 +7247,18 @@ ], "named_caches": [ { - "name": "avd_generic_androidS", + "name": "avd_generic_android_s", "path": ".android" }, { - "name": "system_images_android_S_google_apis_x64", + "name": "system_images_android_s_google_apis_x64", "path": ".emulator_sdk" } ], "optional_dimensions": { "60": [ { - "caches": "avd_generic_androidS" + "caches": "avd_generic_android_s" } ] }, @@ -7316,18 +7316,18 @@ ], "named_caches": [ { - "name": "avd_generic_androidS", + "name": "avd_generic_android_s", "path": ".android" }, { - "name": "system_images_android_S_google_apis_x64", + "name": "system_images_android_s_google_apis_x64", "path": ".emulator_sdk" } ], "optional_dimensions": { "60": [ { - "caches": "avd_generic_androidS" + "caches": "avd_generic_android_s" } ] }, @@ -7385,18 +7385,18 @@ ], "named_caches": [ { - "name": "avd_generic_androidS", + "name": "avd_generic_android_s", "path": ".android" }, { - "name": "system_images_android_S_google_apis_x64", + "name": "system_images_android_s_google_apis_x64", "path": ".emulator_sdk" } ], "optional_dimensions": { "60": [ { - "caches": "avd_generic_androidS" + "caches": "avd_generic_android_s" } ] }, @@ -7454,18 +7454,18 @@ ], "named_caches": [ { - "name": "avd_generic_androidS", + "name": "avd_generic_android_s", "path": ".android" }, { - "name": "system_images_android_S_google_apis_x64", + "name": "system_images_android_s_google_apis_x64", "path": ".emulator_sdk" } ], "optional_dimensions": { "60": [ { - "caches": "avd_generic_androidS" + "caches": "avd_generic_android_s" } ] }, @@ -7523,18 +7523,18 @@ ], "named_caches": [ { - "name": "avd_generic_androidS", + "name": "avd_generic_android_s", "path": ".android" }, { - "name": "system_images_android_S_google_apis_x64", + "name": "system_images_android_s_google_apis_x64", "path": ".emulator_sdk" } ], "optional_dimensions": { "60": [ { - "caches": "avd_generic_androidS" + "caches": "avd_generic_android_s" } ] }, @@ -7592,18 +7592,18 @@ ], "named_caches": [ { - "name": "avd_generic_androidS", + "name": "avd_generic_android_s", "path": ".android" }, { - "name": "system_images_android_S_google_apis_x64", + "name": "system_images_android_s_google_apis_x64", "path": ".emulator_sdk" } ], "optional_dimensions": { "60": [ { - "caches": "avd_generic_androidS" + "caches": "avd_generic_android_s" } ] }, @@ -7661,18 +7661,18 @@ ], "named_caches": [ { - "name": "avd_generic_androidS", + "name": "avd_generic_android_s", "path": ".android" }, { - "name": "system_images_android_S_google_apis_x64", + "name": "system_images_android_s_google_apis_x64", "path": ".emulator_sdk" } ], "optional_dimensions": { "60": [ { - "caches": "avd_generic_androidS" + "caches": "avd_generic_android_s" } ] }, @@ -7730,18 +7730,18 @@ ], "named_caches": [ { - "name": "avd_generic_androidS", + "name": "avd_generic_android_s", "path": ".android" }, { - "name": "system_images_android_S_google_apis_x64", + "name": "system_images_android_s_google_apis_x64", "path": ".emulator_sdk" } ], "optional_dimensions": { "60": [ { - "caches": "avd_generic_androidS" + "caches": "avd_generic_android_s" } ] }, @@ -7799,18 +7799,18 @@ ], "named_caches": [ { - "name": "avd_generic_androidS", + "name": "avd_generic_android_s", "path": ".android" }, { - "name": "system_images_android_S_google_apis_x64", + "name": "system_images_android_s_google_apis_x64", "path": ".emulator_sdk" } ], "optional_dimensions": { "60": [ { - "caches": "avd_generic_androidS" + "caches": "avd_generic_android_s" } ] }, @@ -7868,18 +7868,18 @@ ], "named_caches": [ { - "name": "avd_generic_androidS", + "name": "avd_generic_android_s", "path": ".android" }, { - "name": "system_images_android_S_google_apis_x64", + "name": "system_images_android_s_google_apis_x64", "path": ".emulator_sdk" } ], "optional_dimensions": { "60": [ { - "caches": "avd_generic_androidS" + "caches": "avd_generic_android_s" } ] }, @@ -7937,18 +7937,18 @@ ], "named_caches": [ { - "name": "avd_generic_androidS", + "name": "avd_generic_android_s", "path": ".android" }, { - "name": "system_images_android_S_google_apis_x64", + "name": "system_images_android_s_google_apis_x64", "path": ".emulator_sdk" } ], "optional_dimensions": { "60": [ { - "caches": "avd_generic_androidS" + "caches": "avd_generic_android_s" } ] }, @@ -8006,18 +8006,18 @@ ], "named_caches": [ { - "name": "avd_generic_androidS", + "name": "avd_generic_android_s", "path": ".android" }, { - "name": "system_images_android_S_google_apis_x64", + "name": "system_images_android_s_google_apis_x64", "path": ".emulator_sdk" } ], "optional_dimensions": { "60": [ { - "caches": "avd_generic_androidS" + "caches": "avd_generic_android_s" } ] }, @@ -8075,18 +8075,18 @@ ], "named_caches": [ { - "name": "avd_generic_androidS", + "name": "avd_generic_android_s", "path": ".android" }, { - "name": "system_images_android_S_google_apis_x64", + "name": "system_images_android_s_google_apis_x64", "path": ".emulator_sdk" } ], "optional_dimensions": { "60": [ { - "caches": "avd_generic_androidS" + "caches": "avd_generic_android_s" } ] }, @@ -8144,18 +8144,18 @@ ], "named_caches": [ { - "name": "avd_generic_androidS", + "name": "avd_generic_android_s", "path": ".android" }, { - "name": "system_images_android_S_google_apis_x64", + "name": "system_images_android_s_google_apis_x64", "path": ".emulator_sdk" } ], "optional_dimensions": { "60": [ { - "caches": "avd_generic_androidS" + "caches": "avd_generic_android_s" } ] }, @@ -8213,18 +8213,18 @@ ], "named_caches": [ { - "name": "avd_generic_androidS", + "name": "avd_generic_android_s", "path": ".android" }, { - "name": "system_images_android_S_google_apis_x64", + "name": "system_images_android_s_google_apis_x64", "path": ".emulator_sdk" } ], "optional_dimensions": { "60": [ { - "caches": "avd_generic_androidS" + "caches": "avd_generic_android_s" } ] }, @@ -8283,18 +8283,18 @@ ], "named_caches": [ { - "name": "avd_generic_androidS", + "name": "avd_generic_android_s", "path": ".android" }, { - "name": "system_images_android_S_google_apis_x64", + "name": "system_images_android_s_google_apis_x64", "path": ".emulator_sdk" } ], "optional_dimensions": { "60": [ { - "caches": "avd_generic_androidS" + "caches": "avd_generic_android_s" } ] }, @@ -8352,18 +8352,18 @@ ], "named_caches": [ { - "name": "avd_generic_androidS", + "name": "avd_generic_android_s", "path": ".android" }, { - "name": "system_images_android_S_google_apis_x64", + "name": "system_images_android_s_google_apis_x64", "path": ".emulator_sdk" } ], "optional_dimensions": { "60": [ { - "caches": "avd_generic_androidS" + "caches": "avd_generic_android_s" } ] }, @@ -8421,18 +8421,18 @@ ], "named_caches": [ { - "name": "avd_generic_androidS", + "name": "avd_generic_android_s", "path": ".android" }, { - "name": "system_images_android_S_google_apis_x64", + "name": "system_images_android_s_google_apis_x64", "path": ".emulator_sdk" } ], "optional_dimensions": { "60": [ { - "caches": "avd_generic_androidS" + "caches": "avd_generic_android_s" } ] }, @@ -8490,18 +8490,18 @@ ], "named_caches": [ { - "name": "avd_generic_androidS", + "name": "avd_generic_android_s", "path": ".android" }, { - "name": "system_images_android_S_google_apis_x64", + "name": "system_images_android_s_google_apis_x64", "path": ".emulator_sdk" } ], "optional_dimensions": { "60": [ { - "caches": "avd_generic_androidS" + "caches": "avd_generic_android_s" } ] }, @@ -8559,18 +8559,18 @@ ], "named_caches": [ { - "name": "avd_generic_androidS", + "name": "avd_generic_android_s", "path": ".android" }, { - "name": "system_images_android_S_google_apis_x64", + "name": "system_images_android_s_google_apis_x64", "path": ".emulator_sdk" } ], "optional_dimensions": { "60": [ { - "caches": "avd_generic_androidS" + "caches": "avd_generic_android_s" } ] }, @@ -8628,18 +8628,18 @@ ], "named_caches": [ { - "name": "avd_generic_androidS", + "name": "avd_generic_android_s", "path": ".android" }, { - "name": "system_images_android_S_google_apis_x64", + "name": "system_images_android_s_google_apis_x64", "path": ".emulator_sdk" } ], "optional_dimensions": { "60": [ { - "caches": "avd_generic_androidS" + "caches": "avd_generic_android_s" } ] }, @@ -8697,18 +8697,18 @@ ], "named_caches": [ { - "name": "avd_generic_androidS", + "name": "avd_generic_android_s", "path": ".android" }, { - "name": "system_images_android_S_google_apis_x64", + "name": "system_images_android_s_google_apis_x64", "path": ".emulator_sdk" } ], "optional_dimensions": { "60": [ { - "caches": "avd_generic_androidS" + "caches": "avd_generic_android_s" } ] }, @@ -8766,18 +8766,18 @@ ], "named_caches": [ { - "name": "avd_generic_androidS", + "name": "avd_generic_android_s", "path": ".android" }, { - "name": "system_images_android_S_google_apis_x64", + "name": "system_images_android_s_google_apis_x64", "path": ".emulator_sdk" } ], "optional_dimensions": { "60": [ { - "caches": "avd_generic_androidS" + "caches": "avd_generic_android_s" } ] }, @@ -8835,18 +8835,18 @@ ], "named_caches": [ { - "name": "avd_generic_androidS", + "name": "avd_generic_android_s", "path": ".android" }, { - "name": "system_images_android_S_google_apis_x64", + "name": "system_images_android_s_google_apis_x64", "path": ".emulator_sdk" } ], "optional_dimensions": { "60": [ { - "caches": "avd_generic_androidS" + "caches": "avd_generic_android_s" } ] }, @@ -8904,18 +8904,18 @@ ], "named_caches": [ { - "name": "avd_generic_androidS", + "name": "avd_generic_android_s", "path": ".android" }, { - "name": "system_images_android_S_google_apis_x64", + "name": "system_images_android_s_google_apis_x64", "path": ".emulator_sdk" } ], "optional_dimensions": { "60": [ { - "caches": "avd_generic_androidS" + "caches": "avd_generic_android_s" } ] }, @@ -8973,18 +8973,18 @@ ], "named_caches": [ { - "name": "avd_generic_androidS", + "name": "avd_generic_android_s", "path": ".android" }, { - "name": "system_images_android_S_google_apis_x64", + "name": "system_images_android_s_google_apis_x64", "path": ".emulator_sdk" } ], "optional_dimensions": { "60": [ { - "caches": "avd_generic_androidS" + "caches": "avd_generic_android_s" } ] }, @@ -9042,18 +9042,18 @@ ], "named_caches": [ { - "name": "avd_generic_androidS", + "name": "avd_generic_android_s", "path": ".android" }, { - "name": "system_images_android_S_google_apis_x64", + "name": "system_images_android_s_google_apis_x64", "path": ".emulator_sdk" } ], "optional_dimensions": { "60": [ { - "caches": "avd_generic_androidS" + "caches": "avd_generic_android_s" } ] }, @@ -9112,18 +9112,18 @@ ], "named_caches": [ { - "name": "avd_generic_androidS", + "name": "avd_generic_android_s", "path": ".android" }, { - "name": "system_images_android_S_google_apis_x64", + "name": "system_images_android_s_google_apis_x64", "path": ".emulator_sdk" } ], "optional_dimensions": { "60": [ { - "caches": "avd_generic_androidS" + "caches": "avd_generic_android_s" } ] }, @@ -9181,18 +9181,18 @@ ], "named_caches": [ { - "name": "avd_generic_androidS", + "name": "avd_generic_android_s", "path": ".android" }, { - "name": "system_images_android_S_google_apis_x64", + "name": "system_images_android_s_google_apis_x64", "path": ".emulator_sdk" } ], "optional_dimensions": { "60": [ { - "caches": "avd_generic_androidS" + "caches": "avd_generic_android_s" } ] }, @@ -9250,18 +9250,18 @@ ], "named_caches": [ { - "name": "avd_generic_androidS", + "name": "avd_generic_android_s", "path": ".android" }, { - "name": "system_images_android_S_google_apis_x64", + "name": "system_images_android_s_google_apis_x64", "path": ".emulator_sdk" } ], "optional_dimensions": { "60": [ { - "caches": "avd_generic_androidS" + "caches": "avd_generic_android_s" } ] }, @@ -9319,18 +9319,18 @@ ], "named_caches": [ { - "name": "avd_generic_androidS", + "name": "avd_generic_android_s", "path": ".android" }, { - "name": "system_images_android_S_google_apis_x64", + "name": "system_images_android_s_google_apis_x64", "path": ".emulator_sdk" } ], "optional_dimensions": { "60": [ { - "caches": "avd_generic_androidS" + "caches": "avd_generic_android_s" } ] }, @@ -9388,18 +9388,18 @@ ], "named_caches": [ { - "name": "avd_generic_androidS", + "name": "avd_generic_android_s", "path": ".android" }, { - "name": "system_images_android_S_google_apis_x64", + "name": "system_images_android_s_google_apis_x64", "path": ".emulator_sdk" } ], "optional_dimensions": { "60": [ { - "caches": "avd_generic_androidS" + "caches": "avd_generic_android_s" } ] }, @@ -9457,18 +9457,18 @@ ], "named_caches": [ { - "name": "avd_generic_androidS", + "name": "avd_generic_android_s", "path": ".android" }, { - "name": "system_images_android_S_google_apis_x64", + "name": "system_images_android_s_google_apis_x64", "path": ".emulator_sdk" } ], "optional_dimensions": { "60": [ { - "caches": "avd_generic_androidS" + "caches": "avd_generic_android_s" } ] }, @@ -9526,18 +9526,18 @@ ], "named_caches": [ { - "name": "avd_generic_androidS", + "name": "avd_generic_android_s", "path": ".android" }, { - "name": "system_images_android_S_google_apis_x64", + "name": "system_images_android_s_google_apis_x64", "path": ".emulator_sdk" } ], "optional_dimensions": { "60": [ { - "caches": "avd_generic_androidS" + "caches": "avd_generic_android_s" } ] }, @@ -9600,18 +9600,18 @@ ], "named_caches": [ { - "name": "avd_generic_androidS", + "name": "avd_generic_android_s", "path": ".android" }, { - "name": "system_images_android_S_google_apis_x64", + "name": "system_images_android_s_google_apis_x64", "path": ".emulator_sdk" } ], "optional_dimensions": { "60": [ { - "caches": "avd_generic_androidS" + "caches": "avd_generic_android_s" } ] }, @@ -9670,18 +9670,18 @@ ], "named_caches": [ { - "name": "avd_generic_androidS", + "name": "avd_generic_android_s", "path": ".android" }, { - "name": "system_images_android_S_google_apis_x64", + "name": "system_images_android_s_google_apis_x64", "path": ".emulator_sdk" } ], "optional_dimensions": { "60": [ { - "caches": "avd_generic_androidS" + "caches": "avd_generic_android_s" } ] }, @@ -9740,18 +9740,18 @@ ], "named_caches": [ { - "name": "avd_generic_androidS", + "name": "avd_generic_android_s", "path": ".android" }, { - "name": "system_images_android_S_google_apis_x64", + "name": "system_images_android_s_google_apis_x64", "path": ".emulator_sdk" } ], "optional_dimensions": { "60": [ { - "caches": "avd_generic_androidS" + "caches": "avd_generic_android_s" } ] }, @@ -9809,18 +9809,18 @@ ], "named_caches": [ { - "name": "avd_generic_androidS", + "name": "avd_generic_android_s", "path": ".android" }, { - "name": "system_images_android_S_google_apis_x64", + "name": "system_images_android_s_google_apis_x64", "path": ".emulator_sdk" } ], "optional_dimensions": { "60": [ { - "caches": "avd_generic_androidS" + "caches": "avd_generic_android_s" } ] }, @@ -9878,18 +9878,18 @@ ], "named_caches": [ { - "name": "avd_generic_androidS", + "name": "avd_generic_android_s", "path": ".android" }, { - "name": "system_images_android_S_google_apis_x64", + "name": "system_images_android_s_google_apis_x64", "path": ".emulator_sdk" } ], "optional_dimensions": { "60": [ { - "caches": "avd_generic_androidS" + "caches": "avd_generic_android_s" } ] },
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json index 479fd38..20106b8 100644 --- a/testing/buildbot/chromium.fyi.json +++ b/testing/buildbot/chromium.fyi.json
@@ -88040,20 +88040,20 @@ "gtest_tests": [ { "args": [ - "--ash-chrome-path-override=../../lacros_version_skew_tests_M92/chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v93.0.4570.0/test_ash_chrome" ], "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" }, - "name": "lacros_chrome_browsertests_Lacros version skew testing ash 92.0.4499.0", + "name": "lacros_chrome_browsertests_Lacros version skew testing ash 93.0.4570.0", "swarming": { "can_use_on_swarming_builders": true, "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_M92", - "revision": "version:92.0.4499.0" + "location": "lacros_version_skew_tests_v93.0.4570.0", + "revision": "version:93.0.4570.0" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -88063,20 +88063,66 @@ }, { "args": [ - "--ash-chrome-path-override=../../lacros_version_skew_tests_M92/chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v93.0.4573.0/test_ash_chrome" ], "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" }, - "name": "lacros_chrome_browsertests_run_in_series_Lacros version skew testing ash 92.0.4499.0", + "name": "lacros_chrome_browsertests_Lacros version skew testing ash 93.0.4573.0", "swarming": { "can_use_on_swarming_builders": true, "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_M92", - "revision": "version:92.0.4499.0" + "location": "lacros_version_skew_tests_v93.0.4573.0", + "revision": "version:93.0.4573.0" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "lacros_chrome_browsertests", + "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests/" + }, + { + "args": [ + "--ash-chrome-path-override=../../lacros_version_skew_tests_v93.0.4570.0/test_ash_chrome" + ], + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "name": "lacros_chrome_browsertests_run_in_series_Lacros version skew testing ash 93.0.4570.0", + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", + "location": "lacros_version_skew_tests_v93.0.4570.0", + "revision": "version:93.0.4570.0" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "lacros_chrome_browsertests_run_in_series", + "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests_run_in_series/" + }, + { + "args": [ + "--ash-chrome-path-override=../../lacros_version_skew_tests_v93.0.4573.0/test_ash_chrome" + ], + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "name": "lacros_chrome_browsertests_run_in_series_Lacros version skew testing ash 93.0.4573.0", + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", + "location": "lacros_version_skew_tests_v93.0.4573.0", + "revision": "version:93.0.4573.0" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
diff --git a/testing/buildbot/chromium.linux.json b/testing/buildbot/chromium.linux.json index 2a051cd..c534d272 100644 --- a/testing/buildbot/chromium.linux.json +++ b/testing/buildbot/chromium.linux.json
@@ -13364,7 +13364,7 @@ } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 25 + "shards": 30 }, "test_id_prefix": "ninja://:blink_web_tests/" },
diff --git a/testing/buildbot/mixins.pyl b/testing/buildbot/mixins.pyl index eaf81a1..3e2a105 100644 --- a/testing/buildbot/mixins.pyl +++ b/testing/buildbot/mixins.pyl
@@ -180,7 +180,9 @@ ] }, }, - # TODO(crbug.com/1225851): Update "S" to the right value once S is released. + # TODO(crbug.com/1225851): Update "S" and "_s" to the right value once S is + # released. Using "_s" in stead of "S" in swarming as it does not accept + # uppercase character. '12-x64-emulator': { '$mixin_append': { 'args': [ @@ -192,17 +194,17 @@ 'optional_dimensions': { '60': [ { - 'caches': 'avd_generic_androidS', + 'caches': 'avd_generic_android_s', } ], }, 'named_caches': [ { - 'name': 'avd_generic_androidS', + 'name': 'avd_generic_android_s', 'path': '.android', }, { - 'name': 'system_images_android_S_google_apis_x64', + 'name': 'system_images_android_s_google_apis_x64', 'path': '.emulator_sdk', }, ]
diff --git a/testing/buildbot/test_suite_exceptions.pyl b/testing/buildbot/test_suite_exceptions.pyl index 3c8f996c..1a4c01a 100644 --- a/testing/buildbot/test_suite_exceptions.pyl +++ b/testing/buildbot/test_suite_exceptions.pyl
@@ -241,7 +241,7 @@ '--debug', ], 'swarming': { - 'shards': 25, + 'shards': 30, }, }, 'Mac10.11 Tests': {
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl index 1649e20..3e2a161 100644 --- a/testing/buildbot/test_suites.pyl +++ b/testing/buildbot/test_suites.pyl
@@ -7303,6 +7303,7 @@ 'linux_lacros_chrome_browsertests_version_skew': { 'variants': [ 'LACROS_VERSION_SKEW_CANARY', + 'LACROS_VERSION_SKEW_DEV', ] }, },
diff --git a/testing/buildbot/variants.pyl b/testing/buildbot/variants.pyl index e0fa3b1..f6870dd 100644 --- a/testing/buildbot/variants.pyl +++ b/testing/buildbot/variants.pyl
@@ -46,15 +46,30 @@ }, 'LACROS_VERSION_SKEW_CANARY': { 'args': [ - '--ash-chrome-path-override=../../lacros_version_skew_tests_M92/chrome', + '--ash-chrome-path-override=../../lacros_version_skew_tests_v93.0.4573.0/test_ash_chrome', ], - 'identifier': 'Lacros version skew testing ash 92.0.4499.0', + 'identifier': 'Lacros version skew testing ash 93.0.4573.0', 'swarming': { 'cipd_packages': [ { 'cipd_package': 'chromium/testing/linux-ash-chromium/x86_64/ash.zip', - 'location': 'lacros_version_skew_tests_M92', - 'revision': 'version:92.0.4499.0', + 'location': 'lacros_version_skew_tests_v93.0.4573.0', + 'revision': 'version:93.0.4573.0', + }, + ], + }, + }, + 'LACROS_VERSION_SKEW_DEV': { + 'args': [ + '--ash-chrome-path-override=../../lacros_version_skew_tests_v93.0.4570.0/test_ash_chrome', + ], + 'identifier': 'Lacros version skew testing ash 93.0.4570.0', + 'swarming': { + 'cipd_packages': [ + { + 'cipd_package': 'chromium/testing/linux-ash-chromium/x86_64/ash.zip', + 'location': 'lacros_version_skew_tests_v93.0.4570.0', + 'revision': 'version:93.0.4570.0', }, ], },
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index 7fd1b1b..36c8cfc 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -5911,6 +5911,20 @@ "OmniboxAssistantVoiceSearch", "VoiceSearchAudioCapturePolicy" ] + }, + { + "name": "AssistantIntegration_MultiUser_20210708", + "params": { + "colorful_mic": "false", + "enable_multi_account_check": "false", + "experiment_id": "47732038", + "min_agsa_version": "12.26" + }, + "enable_features": [ + "AssistantIntentExperimentId", + "OmniboxAssistantVoiceSearch", + "VoiceSearchAudioCapturePolicy" + ] } ] }
diff --git a/third_party/android_deps/buildSrc/src/main/groovy/ChromiumDepGraph.groovy b/third_party/android_deps/buildSrc/src/main/groovy/ChromiumDepGraph.groovy index 3b8a75f5..d91336f5 100644 --- a/third_party/android_deps/buildSrc/src/main/groovy/ChromiumDepGraph.groovy +++ b/third_party/android_deps/buildSrc/src/main/groovy/ChromiumDepGraph.groovy
@@ -212,7 +212,8 @@ licenseName: 'Apache 2.0'), org_eclipse_jgit_org_eclipse_jgit: new PropertyOverride( url: 'https://www.eclipse.org/jgit/', - licenseUrl: 'https://raw.githubusercontent.com/eclipse/jgit/master/LICENSE', + licenseUrl: 'https://www.eclipse.org/org/documents/edl-v10.html', + licensePath: 'licenses/Eclipse_EDL.txt', licenseName: 'BSD 3-Clause'), com_google_protobuf_protobuf_java: new PropertyOverride( url: 'https://github.com/protocolbuffers/protobuf/blob/master/java/README.md',
diff --git a/third_party/android_deps/libs/org_eclipse_jgit_org_eclipse_jgit/LICENSE b/third_party/android_deps/libs/org_eclipse_jgit_org_eclipse_jgit/LICENSE index 1b85c646..bdd082c0 100644 --- a/third_party/android_deps/libs/org_eclipse_jgit_org_eclipse_jgit/LICENSE +++ b/third_party/android_deps/libs/org_eclipse_jgit_org_eclipse_jgit/LICENSE
@@ -1,37 +1,11 @@ -This program and the accompanying materials are made available -under the terms of the Eclipse Distribution License v1.0 which -accompanies this distribution, is reproduced below, and is -available at http://www.eclipse.org/org/documents/edl-v10.php - +Eclipse Distribution License - v 1.0 +Copyright (c) 2007, Eclipse Foundation, Inc. and its licensors. All rights reserved. -Redistribution and use in source and binary forms, with or -without modification, are permitted provided that the following -conditions are met: +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: -- Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. +* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +* Neither the name of the Eclipse Foundation, Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. -- Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials provided - with the distribution. - -- Neither the name of the Eclipse Foundation, Inc. nor the - names of its contributors may be used to endorse or promote - products derived from this software without specific prior - written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND -CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, -INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/third_party/android_deps/licenses/Eclipse_EDL.txt b/third_party/android_deps/licenses/Eclipse_EDL.txt new file mode 100644 index 0000000..bdd082c0 --- /dev/null +++ b/third_party/android_deps/licenses/Eclipse_EDL.txt
@@ -0,0 +1,11 @@ +Eclipse Distribution License - v 1.0 +Copyright (c) 2007, Eclipse Foundation, Inc. and its licensors. +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +* Neither the name of the Eclipse Foundation, Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/third_party/blink/public/mojom/navigation/navigation_params.mojom b/third_party/blink/public/mojom/navigation/navigation_params.mojom index 6aa764b..5857fab 100644 --- a/third_party/blink/public/mojom/navigation/navigation_params.mojom +++ b/third_party/blink/public/mojom/navigation/navigation_params.mojom
@@ -410,15 +410,6 @@ // Whether this navigation was browser initiated. bool is_browser_initiated = false; - // Whether this navigation is happening in a prerendering frame tree. - // Should not be referred to in the browser process, as it is only guaranteed - // to be accurate just before sending it to the renderer process. The browser - // process should use the frame tree's `is_prerendering` state instead. - // TODO(crbug.com/1189481): With MPArch, the NavigationRequest should be - // notified when it transfers frame trees, and commit_params should be updated - // then. - bool is_prerendering = false; - // The physical URL of Web Bundle from which the document is loaded. // Used as an additional identifier for MemoryCache. url.mojom.Url web_bundle_physical_url;
diff --git a/third_party/blink/public/mojom/page/page.mojom b/third_party/blink/public/mojom/page/page.mojom index a428fe7..8521520 100644 --- a/third_party/blink/public/mojom/page/page.mojom +++ b/third_party/blink/public/mojom/page/page.mojom
@@ -62,6 +62,9 @@ // Notifies the renderer when audio is started or stopped. AudioStateChanged(bool is_audio_playing); + // Notifies renderers when a prerendered page is activated. + ActivatePrerenderedPage(); + // Notifies renderers when a portal web contents is activated or if a // web contents is adopted as a portal. SetInsidePortal(bool is_inside_portal);
diff --git a/third_party/blink/public/web/web_navigation_params.h b/third_party/blink/public/web/web_navigation_params.h index faab413..2300fff3 100644 --- a/third_party/blink/public/web/web_navigation_params.h +++ b/third_party/blink/public/web/web_navigation_params.h
@@ -344,8 +344,6 @@ bool has_text_fragment_token = false; // Whether this navigation was browser initiated. bool is_browser_initiated = false; - // Whether this navigation was for prerendering. - bool is_prerendering = false; // Whether the document should be able to access local file:// resources. bool grant_load_local_resources = false; // The previews state which should be used for this navigation.
diff --git a/third_party/blink/public/web/web_view.h b/third_party/blink/public/web/web_view.h index 04906f28..f54b993e 100644 --- a/third_party/blink/public/web/web_view.h +++ b/third_party/blink/public/web/web_view.h
@@ -98,6 +98,8 @@ // // clients may be null, but should both be null or not together. // |is_hidden| defines the initial visibility of the page. + // |is_prerendering| defines whether the page is being prerendered by the + // Prerender2 feature (see content/browser/prerender/README.md). // [is_inside_portal] defines whether the page is inside_portal. // |compositing_enabled| dictates whether accelerated compositing should be // enabled for the page. It must be false if no clients are provided, or if a @@ -121,6 +123,7 @@ BLINK_EXPORT static WebView* Create( WebViewClient*, bool is_hidden, + bool is_prerendering, bool is_inside_portal, bool compositing_enabled, bool widgets_never_composited,
diff --git a/third_party/blink/renderer/bindings/core/v8/v8_metrics.cc b/third_party/blink/renderer/bindings/core/v8/v8_metrics.cc index c8d5fb0..69711164 100644 --- a/third_party/blink/renderer/bindings/core/v8/v8_metrics.cc +++ b/third_party/blink/renderer/bindings/core/v8/v8_metrics.cc
@@ -276,6 +276,15 @@ } void V8MetricsRecorder::AddMainThreadEvent( + const v8::metrics::GarbageCollectionFullMainThreadBatchedIncrementalMark& + batched_events, + ContextId context_id) { + for (auto event : batched_events.events) { + AddMainThreadEvent(event, context_id); + } +} + +void V8MetricsRecorder::AddMainThreadEvent( const v8::metrics::GarbageCollectionFullMainThreadIncrementalSweep& event, ContextId context_id) { if (event.cpp_wall_clock_duration_in_us != -1) { @@ -287,6 +296,15 @@ } } +void V8MetricsRecorder::AddMainThreadEvent( + const v8::metrics::GarbageCollectionFullMainThreadBatchedIncrementalSweep& + batched_events, + ContextId context_id) { + for (auto event : batched_events.events) { + AddMainThreadEvent(event, context_id); + } +} + void V8MetricsRecorder::NotifyIsolateDisposal() { v8::metrics::Recorder::NotifyIsolateDisposal(); isolate_ = nullptr;
diff --git a/third_party/blink/renderer/bindings/core/v8/v8_metrics.h b/third_party/blink/renderer/bindings/core/v8/v8_metrics.h index 0c59555..687b1c1 100644 --- a/third_party/blink/renderer/bindings/core/v8/v8_metrics.h +++ b/third_party/blink/renderer/bindings/core/v8/v8_metrics.h
@@ -39,8 +39,16 @@ const v8::metrics::GarbageCollectionFullMainThreadIncrementalMark& event, ContextId context_id) override; void AddMainThreadEvent( + const v8::metrics::GarbageCollectionFullMainThreadBatchedIncrementalMark& + event, + ContextId context_id) override; + void AddMainThreadEvent( const v8::metrics::GarbageCollectionFullMainThreadIncrementalSweep& event, ContextId context_id) override; + void AddMainThreadEvent( + const v8::metrics::GarbageCollectionFullMainThreadBatchedIncrementalSweep& + event, + ContextId context_id) override; void NotifyIsolateDisposal() override;
diff --git a/third_party/blink/renderer/bindings/generated_in_modules.gni b/third_party/blink/renderer/bindings/generated_in_modules.gni index 0d57134..0212490b 100644 --- a/third_party/blink/renderer/bindings/generated_in_modules.gni +++ b/third_party/blink/renderer/bindings/generated_in_modules.gni
@@ -707,8 +707,6 @@ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_picture_in_picture_event_init.h", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_picture_in_picture_options.cc", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_picture_in_picture_options.h", - "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_plane_init.cc", - "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_plane_init.h", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_plane_layout.cc", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_plane_layout.h", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_point_2d.cc", @@ -915,10 +913,6 @@ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_video_frame_init.h", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_video_frame_metadata.cc", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_video_frame_metadata.h", - "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_video_frame_plane_init.cc", - "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_video_frame_plane_init.h", - "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_video_frame_rect.cc", - "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_video_frame_rect.h", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_watch_advertisements_options.cc", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_watch_advertisements_options.h", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_wave_shaper_options.cc", @@ -2043,8 +2037,6 @@ "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_picture_in_picture_event.h", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_picture_in_picture_window.cc", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_picture_in_picture_window.h", - "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_plane.cc", - "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_plane.h", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_plugin.cc", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_plugin.h", "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_plugin_array.cc",
diff --git a/third_party/blink/renderer/bindings/idl_in_core.gni b/third_party/blink/renderer/bindings/idl_in_core.gni index 3b502081..6bca4f4 100644 --- a/third_party/blink/renderer/bindings/idl_in_core.gni +++ b/third_party/blink/renderer/bindings/idl_in_core.gni
@@ -738,6 +738,7 @@ "//third_party/blink/renderer/core/testing/origin_trials_test.idl", "//third_party/blink/renderer/core/testing/origin_trials_test_dictionary.idl", "//third_party/blink/renderer/core/testing/origin_trials_test_partial.idl", + "//third_party/blink/renderer/core/testing/origin_trials_test_window.idl", "//third_party/blink/renderer/core/testing/record_test.idl", "//third_party/blink/renderer/core/testing/sequence_test.idl", "//third_party/blink/renderer/core/testing/static_selection.idl",
diff --git a/third_party/blink/renderer/bindings/idl_in_modules.gni b/third_party/blink/renderer/bindings/idl_in_modules.gni index 3d39deb..eea90bf 100644 --- a/third_party/blink/renderer/bindings/idl_in_modules.gni +++ b/third_party/blink/renderer/bindings/idl_in_modules.gni
@@ -821,8 +821,6 @@ "//third_party/blink/renderer/modules/webcodecs/image_track.idl", "//third_party/blink/renderer/modules/webcodecs/image_track_list.idl", "//third_party/blink/renderer/modules/webcodecs/latency_mode.idl", - "//third_party/blink/renderer/modules/webcodecs/plane.idl", - "//third_party/blink/renderer/modules/webcodecs/plane_init.idl", "//third_party/blink/renderer/modules/webcodecs/plane_layout.idl", "//third_party/blink/renderer/modules/webcodecs/video_color_primaries.idl", "//third_party/blink/renderer/modules/webcodecs/video_color_space.idl", @@ -841,8 +839,6 @@ "//third_party/blink/renderer/modules/webcodecs/video_frame_copy_to_options.idl", "//third_party/blink/renderer/modules/webcodecs/video_frame_init.idl", "//third_party/blink/renderer/modules/webcodecs/video_frame_output_callback.idl", - "//third_party/blink/renderer/modules/webcodecs/video_frame_plane_init.idl", - "//third_party/blink/renderer/modules/webcodecs/video_frame_rect.idl", "//third_party/blink/renderer/modules/webcodecs/video_matrix_coefficients.idl", "//third_party/blink/renderer/modules/webcodecs/video_pixel_format.idl", "//third_party/blink/renderer/modules/webcodecs/video_transfer_characteristics.idl",
diff --git a/third_party/blink/renderer/core/BUILD.gn b/third_party/blink/renderer/core/BUILD.gn index d7c3833f..50e944a 100644 --- a/third_party/blink/renderer/core/BUILD.gn +++ b/third_party/blink/renderer/core/BUILD.gn
@@ -430,6 +430,7 @@ "testing/null_execution_context.h", "testing/origin_trials_test.cc", "testing/origin_trials_test.h", + "testing/origin_trials_test_global.h", "testing/origin_trials_test_partial.h", "testing/record_test.cc", "testing/record_test.h",
diff --git a/third_party/blink/renderer/core/css/css_properties.json5 b/third_party/blink/renderer/core/css/css_properties.json5 index bb31ab5..ce8e89b6 100644 --- a/third_party/blink/renderer/core/css/css_properties.json5 +++ b/third_party/blink/renderer/core/css/css_properties.json5
@@ -2657,7 +2657,6 @@ "simp-chinese-informal", "trad-chinese-formal", "trad-chinese-informal", "hiragana", "katakana", "hiragana-iroha", "katakana-iroha", "none" ], - computed_style_custom_functions: ["getter"], style_builder_custom_functions: ["initial", "inherit", "value"], tree_scoped_value: true, },
diff --git a/third_party/blink/renderer/core/css/properties/longhands/longhands_custom.cc b/third_party/blink/renderer/core/css/properties/longhands/longhands_custom.cc index 600d0f5..c600ea3 100644 --- a/third_party/blink/renderer/core/css/properties/longhands/longhands_custom.cc +++ b/third_party/blink/renderer/core/css/properties/longhands/longhands_custom.cc
@@ -4328,15 +4328,15 @@ const ComputedStyle& style, const LayoutObject*, bool allow_visited_style) const { - if (!style.GetListStyleType()) + if (!style.ListStyleType()) return CSSIdentifierValue::Create(CSSValueID::kNone); - if (style.GetListStyleType()->IsString()) { + if (style.ListStyleType()->IsString()) { return MakeGarbageCollected<CSSStringValue>( - style.GetListStyleType()->GetStringValue()); + style.ListStyleType()->GetStringValue()); } // TODO(crbug.com/687225): Return a scoped CSSValue? return MakeGarbageCollected<CSSCustomIdentValue>( - style.GetListStyleType()->GetCounterStyleName()); + style.ListStyleType()->GetCounterStyleName()); } void ListStyleType::ApplyInitial(StyleResolverState& state) const { @@ -4345,7 +4345,7 @@ } void ListStyleType::ApplyInherit(StyleResolverState& state) const { - state.Style()->SetListStyleType(state.ParentStyle()->GetListStyleType()); + state.Style()->SetListStyleType(state.ParentStyle()->ListStyleType()); } void ListStyleType::ApplyValue(StyleResolverState& state,
diff --git a/third_party/blink/renderer/core/dom/document.cc b/third_party/blink/renderer/core/dom/document.cc index 570b3b3..8fe4614 100644 --- a/third_party/blink/renderer/core/dom/document.cc +++ b/third_party/blink/renderer/core/dom/document.cc
@@ -8180,13 +8180,6 @@ void Document::ActivateForPrerendering(base::TimeTicks activation_start) { DCHECK(features::IsPrerender2Enabled()); - // For subframes, this can be called before the navigation commit, and this - // document may be the initial empty one with `is_prerendering_` being false. - if (is_initial_empty_document_) { - DCHECK(!is_prerendering_); - return; - } - // TODO(bokan): Portals will change this assumption since they mean an active // document can be "adopted" into a portal. DCHECK(is_prerendering_);
diff --git a/third_party/blink/renderer/core/dom/events/event_target.cc b/third_party/blink/renderer/core/dom/events/event_target.cc index 5d34599..b9c9dd9 100644 --- a/third_party/blink/renderer/core/dom/events/event_target.cc +++ b/third_party/blink/renderer/core/dom/events/event_target.cc
@@ -209,12 +209,6 @@ } } -void RegisterWithScheduler(ExecutionContext* execution_context, - const AtomicString& event_type) { - if (!execution_context || !execution_context->GetScheduler()) - return; -} - } // namespace EventTargetData::EventTargetData() = default; @@ -536,8 +530,6 @@ } } - RegisterWithScheduler(GetExecutionContext(), event_type); - if (event_util::IsDOMMutationEventType(event_type)) { if (ExecutionContext* context = GetExecutionContext()) { String message_text = String::Format(
diff --git a/third_party/blink/renderer/core/dom/pseudo_element.cc b/third_party/blink/renderer/core/dom/pseudo_element.cc index bf76fac..0560cea 100644 --- a/third_party/blink/renderer/core/dom/pseudo_element.cc +++ b/third_party/blink/renderer/core/dom/pseudo_element.cc
@@ -280,7 +280,7 @@ return !pseudo_style->ContentPreventsBoxGeneration(); const ComputedStyle* parent_style = originating_element->GetComputedStyle(); - return parent_style && (parent_style->GetListStyleType() || + return parent_style && (parent_style->ListStyleType() || parent_style->GeneratesMarkerImage()); } default:
diff --git a/third_party/blink/renderer/core/exported/web_plugin_container_impl.cc b/third_party/blink/renderer/core/exported/web_plugin_container_impl.cc index b21bc31..d13f05e 100644 --- a/third_party/blink/renderer/core/exported/web_plugin_container_impl.cc +++ b/third_party/blink/renderer/core/exported/web_plugin_container_impl.cc
@@ -95,6 +95,7 @@ #include "third_party/blink/renderer/core/script/classic_script.h" #include "third_party/blink/renderer/core/scroll/scroll_animator_base.h" #include "third_party/blink/renderer/core/scroll/scrollbar_theme.h" +#include "third_party/blink/renderer/platform/bindings/script_forbidden_scope.h" #include "third_party/blink/renderer/platform/exported/wrapped_resource_response.h" #include "third_party/blink/renderer/platform/geometry/layout_rect.h" #include "third_party/blink/renderer/platform/graphics/graphics_context.h" @@ -786,6 +787,8 @@ } if (web_plugin_) { + // Plugins may execute script on being detached during the lifecycle update. + ScriptForbiddenScope::AllowUserAgentScript allow_script; CHECK(web_plugin_->Container() == this); web_plugin_->Destroy(); web_plugin_ = nullptr;
diff --git a/third_party/blink/renderer/core/exported/web_view_impl.cc b/third_party/blink/renderer/core/exported/web_view_impl.cc index e4bf32d..2f9022d 100644 --- a/third_party/blink/renderer/core/exported/web_view_impl.cc +++ b/third_party/blink/renderer/core/exported/web_view_impl.cc
@@ -446,6 +446,7 @@ WebView* WebView::Create( WebViewClient* client, bool is_hidden, + bool is_prerendering, bool is_inside_portal, bool compositing_enabled, bool widgets_never_composited, @@ -459,14 +460,16 @@ client, is_hidden ? mojom::blink::PageVisibilityState::kHidden : mojom::blink::PageVisibilityState::kVisible, - is_inside_portal, compositing_enabled, widgets_never_composited, - To<WebViewImpl>(opener), std::move(page_handle), agent_group_scheduler, - session_storage_namespace_id, std::move(page_base_background_color)); + is_prerendering, is_inside_portal, compositing_enabled, + widgets_never_composited, To<WebViewImpl>(opener), std::move(page_handle), + agent_group_scheduler, session_storage_namespace_id, + std::move(page_base_background_color)); } WebViewImpl* WebViewImpl::Create( WebViewClient* client, mojom::blink::PageVisibilityState visibility, + bool is_prerendering, bool is_inside_portal, bool compositing_enabled, bool widgets_never_composited, @@ -477,11 +480,11 @@ absl::optional<SkColor> page_base_background_color) { // Take a self-reference for WebViewImpl that is released by calling Close(), // then return a raw pointer to the caller. - auto web_view = base::AdoptRef( - new WebViewImpl(client, visibility, is_inside_portal, compositing_enabled, - widgets_never_composited, opener, std::move(page_handle), - agent_group_scheduler, session_storage_namespace_id, - std::move(page_base_background_color))); + auto web_view = base::AdoptRef(new WebViewImpl( + client, visibility, is_prerendering, is_inside_portal, + compositing_enabled, widgets_never_composited, opener, + std::move(page_handle), agent_group_scheduler, + session_storage_namespace_id, std::move(page_base_background_color))); web_view->AddRef(); return web_view.get(); } @@ -539,6 +542,7 @@ WebViewImpl::WebViewImpl( WebViewClient* client, mojom::blink::PageVisibilityState visibility, + bool is_prerendering, bool is_inside_portal, bool does_composite, bool widgets_never_composited, @@ -569,6 +573,7 @@ *page_, session_storage_namespace_id_); SetVisibilityState(visibility, /*is_initial_state=*/true); + page_->SetIsPrerendering(is_prerendering); // We pass this state to Page, but it's only used by the main frame in the // page. @@ -3139,6 +3144,10 @@ #endif // !defined(OS_MAC) } +void WebViewImpl::ActivatePrerenderedPage() { + GetPage()->SetIsPrerendering(false); +} + void WebViewImpl::SetInsidePortal(bool inside_portal) { GetPage()->SetInsidePortal(inside_portal);
diff --git a/third_party/blink/renderer/core/exported/web_view_impl.h b/third_party/blink/renderer/core/exported/web_view_impl.h index bbf91bd..97e3d30 100644 --- a/third_party/blink/renderer/core/exported/web_view_impl.h +++ b/third_party/blink/renderer/core/exported/web_view_impl.h
@@ -114,6 +114,7 @@ static WebViewImpl* Create( WebViewClient*, mojom::blink::PageVisibilityState visibility, + bool is_prerendering, bool is_inside_portal, bool compositing_enabled, bool widgets_never_composited, @@ -278,6 +279,7 @@ mojom::blink::PageRestoreParamsPtr page_restore_params, SetPageLifecycleStateCallback callback) override; void AudioStateChanged(bool is_audio_playing) override; + void ActivatePrerenderedPage() override; void SetInsidePortal(bool is_inside_portal) override; void UpdateWebPreferences( const blink::web_pref::WebPreferences& preferences) override; @@ -638,6 +640,7 @@ WebViewImpl( WebViewClient*, mojom::blink::PageVisibilityState visibility, + bool is_prerendering, bool is_inside_portal, bool does_composite, bool widgets_never_composite,
diff --git a/third_party/blink/renderer/core/exported/web_view_test.cc b/third_party/blink/renderer/core/exported/web_view_test.cc index daa86f9d..46b81c4 100644 --- a/third_party/blink/renderer/core/exported/web_view_test.cc +++ b/third_party/blink/renderer/core/exported/web_view_test.cc
@@ -488,6 +488,7 @@ WebViewImpl* web_view = To<WebViewImpl>( WebView::Create(&web_view_client, /*is_hidden=*/false, + /*is_prerendering=*/false, /*is_inside_portal=*/false, /*compositing_enabled=*/true, /*widgets_never_composited=*/false, @@ -2736,7 +2737,8 @@ // Note: this test doesn't use WebViewHelper since WebViewHelper creates an // internal WebViewClient on demand if the supplied WebViewClient is null. WebViewImpl* web_view = To<WebViewImpl>(WebView::Create( - /*client=*/nullptr, /*is_hidden=*/false, /*is_inside_portal=*/false, + /*client=*/nullptr, /*is_hidden=*/false, /*is_prerendering=*/false, + /*is_inside_portal=*/false, /*compositing_enabled=*/false, /*widgets_never_composited=*/false, /*opener=*/nullptr, mojo::NullAssociatedReceiver(),
diff --git a/third_party/blink/renderer/core/frame/frame_test_helpers.cc b/third_party/blink/renderer/core/frame/frame_test_helpers.cc index 790ce74..cbb7547f 100644 --- a/third_party/blink/renderer/core/frame/frame_test_helpers.cc +++ b/third_party/blink/renderer/core/frame/frame_test_helpers.cc
@@ -619,6 +619,7 @@ web_view_ = To<WebViewImpl>( WebView::Create(test_web_view_client_, /*is_hidden=*/false, + /*is_prerendering=*/false, /*is_inside_portal=*/false, /*compositing_enabled=*/true, /*widgets_never_composited=*/false,
diff --git a/third_party/blink/renderer/core/frame/local_frame.cc b/third_party/blink/renderer/core/frame/local_frame.cc index 2b96901..696be9a 100644 --- a/third_party/blink/renderer/core/frame/local_frame.cc +++ b/third_party/blink/renderer/core/frame/local_frame.cc
@@ -2327,16 +2327,18 @@ scoped_refptr<const SharedBuffer> data) { CHECK(GetDocument()->IsInitialEmptyDocument()); DCHECK(!Client()->IsLocalFrameClientImpl()); + DCHECK(GetPage()); // Any Document requires Shutdown() before detach, even the initial empty // document. GetDocument()->Shutdown(); DomWindow()->ClearForReuse(); - Document* document = - DomWindow()->InstallNewDocument(DocumentInit::Create() - .WithWindow(DomWindow(), nullptr) - .WithTypeFrom(mime_type)); + Document* document = DomWindow()->InstallNewDocument( + DocumentInit::Create() + .WithWindow(DomWindow(), nullptr) + .WithTypeFrom(mime_type) + .ForPrerendering(GetPage()->IsPrerendering())); DocumentParser* parser = document->OpenForNavigation( kForceSynchronousParsing, mime_type, AtomicString("UTF-8")); for (const auto& segment : *data) @@ -2934,8 +2936,10 @@ void LocalFrame::UpdateWindowControlsOverlay( const gfx::Rect& bounding_rect_in_dips) { - if (!RuntimeEnabledFeatures::WebAppWindowControlsOverlayEnabled(nullptr)) + if (!RuntimeEnabledFeatures::WebAppWindowControlsOverlayEnabled( + GetDocument()->GetExecutionContext())) { return; + } // The rect passed to us from content is in DIP screen space, relative to the // main frame, and needs to move to CSS space. This doesn't take the page's
diff --git a/third_party/blink/renderer/core/frame/local_frame_view.cc b/third_party/blink/renderer/core/frame/local_frame_view.cc index e4d8388..b4ff8c6 100644 --- a/third_party/blink/renderer/core/frame/local_frame_view.cc +++ b/third_party/blink/renderer/core/frame/local_frame_view.cc
@@ -2372,6 +2372,7 @@ void LocalFrameView::UpdateLifecyclePhasesInternal( DocumentLifecycle::LifecycleState target_state) { + ScriptForbiddenScope forbid_script; // RunScrollTimelineSteps must not run more than once. bool should_run_scroll_timeline_steps = true; @@ -2473,6 +2474,10 @@ continue; } + // At this point in time, script is allowed to run as we will repeat the + // lifecycle update if anything is invalidated. + ScriptForbiddenScope::AllowUserAgentScript allow_script; + // ResizeObserver and post-layout IntersectionObserver observation // deliveries may dirty style and layout. RunResizeObserverSteps will return // true if any observer ran that may have dirtied style or layout; @@ -2724,6 +2729,7 @@ } void LocalFrameView::RunPaintLifecyclePhase(PaintBenchmarkMode benchmark_mode) { + DCHECK(ScriptForbiddenScope::IsScriptForbidden()); DCHECK(LocalFrameTreeAllowsThrottling()); TRACE_EVENT0("blink,benchmark", "LocalFrameView::RunPaintLifecyclePhase"); // While printing or capturing a paint preview of a document, the paint walk @@ -2763,15 +2769,9 @@ area->UpdateCompositorScrollAnimations(); } Document& document = frame_view.GetLayoutView()->GetDocument(); - { - // Updating animations can notify ready promises which could mutate - // the DOM. We should delay these until we have finished the lifecycle - // update. https://crbug.com/1196781 - ScriptForbiddenScope forbid_script; - document.GetDocumentAnimations().UpdateAnimations( - DocumentLifecycle::kPaintClean, paint_artifact_compositor_.get(), - needed_update); - } + document.GetDocumentAnimations().UpdateAnimations( + DocumentLifecycle::kPaintClean, paint_artifact_compositor_.get(), + needed_update); total_animations_count += document.GetDocumentAnimations().GetAnimationsCount(); }); @@ -4422,6 +4422,7 @@ // so painting the tree should just clear the previous painted output. DCHECK(!IsUpdatingLifecycle()); AllowThrottlingScope allow_throtting(*this); + ScriptForbiddenScope forbid_script; RunPaintLifecyclePhase(PaintBenchmarkMode::kNormal); } @@ -4950,6 +4951,7 @@ // quantization when the time is very small. base::LapTimer timer(kWarmupRuns, kTimeLimit, kTimeCheckInterval); do { + ScriptForbiddenScope forbid_script; // Force a paint with everything cached before a small invalidation // test to better simulate real-world scenarios. if (mode == PaintBenchmarkMode::kSmallInvalidation)
diff --git a/third_party/blink/renderer/core/frame/web_frame_test.cc b/third_party/blink/renderer/core/frame/web_frame_test.cc index 42638913..f1bf945 100644 --- a/third_party/blink/renderer/core/frame/web_frame_test.cc +++ b/third_party/blink/renderer/core/frame/web_frame_test.cc
@@ -14086,35 +14086,4 @@ EXPECT_EQ(remote_frame->GetCompositingScaleFactor(), 5.0f); } -TEST_F(WebFrameTest, IsPrerendering) { - frame_test_helpers::WebViewHelper web_view_helper; - web_view_helper.Initialize(); - auto params = std::make_unique<WebNavigationParams>(); - params->url = KURL("about:blank"); - params->is_prerendering = false; - web_view_helper.LocalMainFrame()->CommitNavigation(std::move(params), - nullptr); - WebViewImpl* web_view = web_view_helper.GetWebView(); - - EXPECT_FALSE(web_view->MainFrameImpl() - ->GetFrame() - ->GetDocument() - ->Fetcher() - ->Context() - .IsPrerendering()); - - params = std::make_unique<WebNavigationParams>(); - params->url = KURL("about:blank"); - params->is_prerendering = true; - web_view_helper.LocalMainFrame()->CommitNavigation(std::move(params), - nullptr); - - EXPECT_TRUE(web_view->MainFrameImpl() - ->GetFrame() - ->GetDocument() - ->Fetcher() - ->Context() - .IsPrerendering()); -} - } // namespace blink
diff --git a/third_party/blink/renderer/core/html/canvas/canvas_resource_tracker_test.cc b/third_party/blink/renderer/core/html/canvas/canvas_resource_tracker_test.cc index 155d24e..cc0069c1 100644 --- a/third_party/blink/renderer/core/html/canvas/canvas_resource_tracker_test.cc +++ b/third_party/blink/renderer/core/html/canvas/canvas_resource_tracker_test.cc
@@ -20,11 +20,13 @@ SetBodyInnerHTML("<canvas id='canvas'></canvas>"); auto* canvas = To<HTMLCanvasElement>(GetDocument().getElementById("canvas")); auto* context = GetDocument().GetExecutionContext(); - for (auto entry : - CanvasResourceTracker::For(context->GetIsolate())->GetResourceMap()) { - EXPECT_EQ(canvas, entry.key); - EXPECT_EQ(context, entry.value); - } + const auto& resource_map = + CanvasResourceTracker::For(context->GetIsolate())->GetResourceMap(); + // The map may hold more than a single entry as CanvasResourceTracker is + // instantiated per v8::Isolate which is reused across tests. + const auto it = resource_map.find(canvas); + EXPECT_NE(resource_map.end(), it); + EXPECT_EQ(context, it->value); } } // namespace blink
diff --git a/third_party/blink/renderer/core/layout/layout_list_item.cc b/third_party/blink/renderer/core/layout/layout_list_item.cc index 8350fd56..5a9056847 100644 --- a/third_party/blink/renderer/core/layout/layout_list_item.cc +++ b/third_party/blink/renderer/core/layout/layout_list_item.cc
@@ -61,7 +61,7 @@ LayoutBlockFlow::StyleDidChange(diff, old_style); StyleImage* current_image = StyleRef().ListStyleImage(); - if (StyleRef().GetListStyleType() || + if (StyleRef().ListStyleType() || (current_image && !current_image->ErrorOccurred())) { NotifyOfSubtreeChange(); } @@ -80,10 +80,8 @@ list_marker->UpdateMarkerContentIfNeeded(*marker); if (old_style) { - const ListStyleTypeData* old_list_style_type = - old_style->GetListStyleType(); - const ListStyleTypeData* new_list_style_type = - StyleRef().GetListStyleType(); + const ListStyleTypeData* old_list_style_type = old_style->ListStyleType(); + const ListStyleTypeData* new_list_style_type = StyleRef().ListStyleType(); if (old_list_style_type != new_list_style_type && (!old_list_style_type || !new_list_style_type || *old_list_style_type != *new_list_style_type)) { @@ -98,9 +96,8 @@ void LayoutListItem::UpdateCounterStyle() { NOT_DESTROYED(); - if (!StyleRef().GetListStyleType() || - StyleRef().GetListStyleType()->IsCounterStyleReferenceValid( - GetDocument())) { + if (!StyleRef().ListStyleType() || + StyleRef().ListStyleType()->IsCounterStyleReferenceValid(GetDocument())) { return; }
diff --git a/third_party/blink/renderer/core/layout/layout_list_marker.cc b/third_party/blink/renderer/core/layout/layout_list_marker.cc index e43e7e01..5384103e0 100644 --- a/third_party/blink/renderer/core/layout/layout_list_marker.cc +++ b/third_party/blink/renderer/core/layout/layout_list_marker.cc
@@ -323,7 +323,7 @@ const CounterStyle& LayoutListMarker::GetCounterStyle() const { NOT_DESTROYED(); - const ListStyleTypeData* list_style_data = StyleRef().GetListStyleType(); + const ListStyleTypeData* list_style_data = StyleRef().ListStyleType(); DCHECK(list_style_data); DCHECK(list_style_data->IsCounterStyle()); return list_style_data->GetCounterStyle(GetDocument());
diff --git a/third_party/blink/renderer/core/layout/layout_object.cc b/third_party/blink/renderer/core/layout/layout_object.cc index f6bfc7c1..06fb9971 100644 --- a/third_party/blink/renderer/core/layout/layout_object.cc +++ b/third_party/blink/renderer/core/layout/layout_object.cc
@@ -714,7 +714,7 @@ ListMarker::ListStyleCategory::kSymbol) return false; const AtomicString& name = - StyleRef().GetListStyleType()->GetCounterStyleName(); + StyleRef().ListStyleType()->GetCounterStyleName(); return name == "disclosure-open" || name == "disclosure-closed"; } return false;
diff --git a/third_party/blink/renderer/core/layout/list_marker.cc b/third_party/blink/renderer/core/layout/list_marker.cc index 10bd25c8..a74135e 100644 --- a/third_party/blink/renderer/core/layout/list_marker.cc +++ b/third_party/blink/renderer/core/layout/list_marker.cc
@@ -271,7 +271,7 @@ return; } - if (!style.GetListStyleType()) { + if (!style.ListStyleType()) { marker_text_type_ = kNotText; return; } @@ -314,7 +314,7 @@ DCHECK(font_data); if (!font_data) return LayoutUnit(); - const AtomicString& name = style.GetListStyleType()->GetCounterStyleName(); + const AtomicString& name = style.ListStyleType()->GetCounterStyleName(); if (name == "disclosure-open" || name == "disclosure-closed") return DisclosureSymbolSize(style); return LayoutUnit((font_data->GetFontMetrics().Ascent() * 2 / 3 + 1) / 2 + 2); @@ -331,7 +331,7 @@ switch (GetListStyleCategory(document, list_item_style)) { case ListStyleCategory::kSymbol: { const AtomicString& name = - list_item_style.GetListStyleType()->GetCounterStyleName(); + list_item_style.ListStyleType()->GetCounterStyleName(); if (name == "disclosure-open" || name == "disclosure-closed") { return {LayoutUnit(), LayoutUnit(kClosureMarkerMarginEm * marker_style.SpecifiedFontSize())}; @@ -368,7 +368,7 @@ return {}; const FontMetrics& font_metrics = font_data->GetFontMetrics(); const AtomicString& name = - list_item_style.GetListStyleType()->GetCounterStyleName(); + list_item_style.ListStyleType()->GetCounterStyleName(); LayoutUnit offset = (name == "disclosure-open" || name == "disclosure-closed") ? DisclosureSymbolSize(marker_style) @@ -397,7 +397,7 @@ // http://crbug.com/543193 const FontMetrics& font_metrics = font_data->GetFontMetrics(); const int ascent = font_metrics.Ascent(); - const AtomicString& name = style.GetListStyleType()->GetCounterStyleName(); + const AtomicString& name = style.ListStyleType()->GetCounterStyleName(); if (name == "disclosure-open" || name == "disclosure-closed") { LayoutUnit marker_size = DisclosureSymbolSize(style); relative_rect = LayoutRect(LayoutUnit(), ascent - marker_size, marker_size, @@ -416,15 +416,15 @@ const CounterStyle& ListMarker::GetCounterStyle(Document& document, const ComputedStyle& style) { - DCHECK(style.GetListStyleType()); - DCHECK(style.GetListStyleType()->IsCounterStyle()); - return style.GetListStyleType()->GetCounterStyle(document); + DCHECK(style.ListStyleType()); + DCHECK(style.ListStyleType()->IsCounterStyle()); + return style.ListStyleType()->GetCounterStyle(document); } ListMarker::ListStyleCategory ListMarker::GetListStyleCategory( Document& document, const ComputedStyle& style) { - const ListStyleTypeData* list_style = style.GetListStyleType(); + const ListStyleTypeData* list_style = style.ListStyleType(); if (!list_style) return ListStyleCategory::kNone; if (list_style->IsString())
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_items_builder.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_items_builder.cc index 94757a3..5a9cd8f 100644 --- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_items_builder.cc +++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_items_builder.cc
@@ -1217,7 +1217,7 @@ kPopDirectionalFormattingCharacter); } - if (style->Display() == EDisplay::kListItem && style->GetListStyleType()) { + if (style->Display() == EDisplay::kListItem && style->ListStyleType()) { is_empty_inline_ = false; is_block_level_ = false; }
diff --git a/third_party/blink/renderer/core/layout/ng/list/layout_ng_list_item.cc b/third_party/blink/renderer/core/layout/ng/list/layout_ng_list_item.cc index 6bda3aad..9b42dfe2 100644 --- a/third_party/blink/renderer/core/layout/ng/list/layout_ng_list_item.cc +++ b/third_party/blink/renderer/core/layout/ng/list/layout_ng_list_item.cc
@@ -54,10 +54,8 @@ list_marker->UpdateMarkerContentIfNeeded(*marker); if (old_style) { - const ListStyleTypeData* old_list_style_type = - old_style->GetListStyleType(); - const ListStyleTypeData* new_list_style_type = - StyleRef().GetListStyleType(); + const ListStyleTypeData* old_list_style_type = old_style->ListStyleType(); + const ListStyleTypeData* new_list_style_type = StyleRef().ListStyleType(); if (old_list_style_type != new_list_style_type && (!old_list_style_type || !new_list_style_type || *old_list_style_type != *new_list_style_type)) @@ -66,9 +64,8 @@ } void LayoutNGListItem::UpdateCounterStyle() { - if (!StyleRef().GetListStyleType() || - StyleRef().GetListStyleType()->IsCounterStyleReferenceValid( - GetDocument())) { + if (!StyleRef().ListStyleType() || + StyleRef().ListStyleType()->IsCounterStyleReferenceValid(GetDocument())) { return; }
diff --git a/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.cc index d30a8cf1..8f3eed6 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.cc
@@ -2599,20 +2599,27 @@ if (ConstraintSpace().IsTableCell()) { builder.SetIsTableCellChild(true); - // Some scrollable percentage-sized children of table-cells (in the - // "measure" phase) use their min-size (instead of sizing normally). + // Only apply the restricted block-size behaviour if we are in the + // measuring phase, or we are in the layout phase and the %-block-size is + // indefinite. + const bool is_measuring_or_indefinite = + !ConstraintSpace().IsFixedBlockSize() || + (ConstraintSpace().IsFixedBlockSize() && + child_percentage_size_.block_size == kIndefiniteSize); + + // Some scrollable percentage-sized children of table-cells use their + // min-size (instead of sizing normally). // // We only apply this rule if the block size of the containing table cell - // is considered to be "restricted", though. Otherwise, especially if this - // is the only child of the cell, and that is the only cell in the row, - // we'd end up with zero block size. + // is considered to be "restricted". Otherwise, especially if this is the + // only child of the cell, and that is the only cell in the row, we'd end + // up with zero block size. if (ConstraintSpace().IsRestrictedBlockSizeTableCell() && - !ConstraintSpace().IsFixedBlockSize() && - !child.ShouldBeConsideredAsReplaced() && + is_measuring_or_indefinite && !child.ShouldBeConsideredAsReplaced() && child_style.LogicalHeight().IsPercentOrCalc() && (child_style.OverflowBlockDirection() == EOverflow::kAuto || child_style.OverflowBlockDirection() == EOverflow::kScroll)) - builder.SetIsMeasuringRestrictedBlockSizeTableCellChild(); + builder.SetIsRestrictedBlockSizeTableCellChild(); } bool has_bfc_block_offset = container_builder_.BfcBlockOffset().has_value();
diff --git a/third_party/blink/renderer/core/layout/ng/ng_constraint_space.h b/third_party/blink/renderer/core/layout/ng/ng_constraint_space.h index e3f67d9..2121ecc 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_constraint_space.h +++ b/third_party/blink/renderer/core/layout/ng/ng_constraint_space.h
@@ -494,11 +494,10 @@ // If this is a child of a table-cell. bool IsTableCellChild() const { return bitfields_.is_table_cell_child; } - // If we should apply the restricted block-size measuring behavior. See where - // this is set within |NGBlockLayoutAlgorithm| for the conditions when this - // applies. - bool IsMeasuringRestrictedBlockSizeTableCellChild() const { - return bitfields_.is_measuring_restricted_block_size_table_cell_child; + // If we should apply the restricted block-size behavior. See where this is + // set within |NGBlockLayoutAlgorithm| for the conditions when this applies. + bool IsRestrictedBlockSizeTableCellChild() const { + return bitfields_.is_restricted_block_size_table_cell_child; } bool IsPaintedAtomically() const { return bitfields_.is_painted_atomically; } @@ -1344,7 +1343,7 @@ is_fixed_block_size(false), is_fixed_block_size_indefinite(false), is_table_cell_child(false), - is_measuring_restricted_block_size_table_cell_child(false), + is_restricted_block_size_table_cell_child(false), percentage_inline_storage(kSameAsAvailable), percentage_block_storage(kSameAsAvailable), replaced_percentage_block_storage(kSameAsAvailable) {} @@ -1375,8 +1374,8 @@ is_fixed_block_size_indefinite == other.is_fixed_block_size_indefinite && is_table_cell_child == other.is_table_cell_child && - is_measuring_restricted_block_size_table_cell_child == - other.is_measuring_restricted_block_size_table_cell_child; + is_restricted_block_size_table_cell_child == + other.is_restricted_block_size_table_cell_child; } unsigned has_rare_data : 1; @@ -1405,7 +1404,7 @@ unsigned is_fixed_block_size : 1; unsigned is_fixed_block_size_indefinite : 1; unsigned is_table_cell_child : 1; - unsigned is_measuring_restricted_block_size_table_cell_child : 1; + unsigned is_restricted_block_size_table_cell_child : 1; unsigned percentage_inline_storage : 2; // NGPercentageStorage unsigned percentage_block_storage : 2; // NGPercentageStorage
diff --git a/third_party/blink/renderer/core/layout/ng/ng_constraint_space_builder.h b/third_party/blink/renderer/core/layout/ng/ng_constraint_space_builder.h index 0779995..97f34030 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_constraint_space_builder.h +++ b/third_party/blink/renderer/core/layout/ng/ng_constraint_space_builder.h
@@ -370,9 +370,8 @@ space_.bitfields_.is_table_cell_child = b; } - void SetIsMeasuringRestrictedBlockSizeTableCellChild() { - space_.bitfields_.is_measuring_restricted_block_size_table_cell_child = - true; + void SetIsRestrictedBlockSizeTableCellChild() { + space_.bitfields_.is_restricted_block_size_table_cell_child = true; } void SetExclusionSpace(const NGExclusionSpace& exclusion_space) {
diff --git a/third_party/blink/renderer/core/layout/ng/ng_layout_utils.cc b/third_party/blink/renderer/core/layout/ng/ng_layout_utils.cc index e081cb3..5cf9964f 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_layout_utils.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_layout_utils.cc
@@ -80,8 +80,8 @@ old_space.IsFixedBlockSizeIndefinite()); DCHECK_EQ(new_space.BlockAutoBehavior(), old_space.BlockAutoBehavior()); DCHECK_EQ(new_space.IsTableCellChild(), old_space.IsTableCellChild()); - DCHECK_EQ(new_space.IsMeasuringRestrictedBlockSizeTableCellChild(), - old_space.IsMeasuringRestrictedBlockSizeTableCellChild()); + DCHECK_EQ(new_space.IsRestrictedBlockSizeTableCellChild(), + old_space.IsRestrictedBlockSizeTableCellChild()); if (node.IsQuirkyAndFillsViewport()) return true;
diff --git a/third_party/blink/renderer/core/layout/ng/ng_length_utils.cc b/third_party/blink/renderer/core/layout/ng/ng_length_utils.cc index eefa57ad..cbbd3a50 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_length_utils.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_length_utils.cc
@@ -669,10 +669,10 @@ space, style, border_padding, available_block_size_adjustment, opt_percentage_resolution_block_size_for_min_max); - // Scrollable percentage-sized children of table cells, in the table - // "measure" phase contribute nothing to the row height measurement. + // Scrollable percentage-sized children of table cells (sometimes) are sized + // to their min-size. // See: https://drafts.csswg.org/css-tables-3/#row-layout - if (space.IsMeasuringRestrictedBlockSizeTableCellChild()) + if (space.IsRestrictedBlockSizeTableCellChild()) return min_max.min_size; const bool has_aspect_ratio = !style.AspectRatio().IsAuto();
diff --git a/third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm_utils.cc b/third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm_utils.cc index e4ec95c..dc44852 100644 --- a/third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm_utils.cc +++ b/third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm_utils.cc
@@ -497,7 +497,7 @@ builder.SetTableCellAlignmentBaseline(alignment_baseline); builder.SetTableCellColumnIndex(column_index); builder.SetIsRestrictedBlockSizeTableCell( - is_table_block_size_specified || !cell_style.LogicalHeight().IsAuto()); + is_table_block_size_specified || cell_style.LogicalHeight().IsFixed()); builder.SetIsTableCellHiddenForPaint(is_hidden_for_paint); builder.SetIsTableCellWithCollapsedBorders(has_collapsed_borders); builder.SetHideTableCellIfEmpty( @@ -572,7 +572,7 @@ void NGTableAlgorithmUtils::ComputeSectionMinimumRowBlockSizes( const NGBlockNode& section, const LayoutUnit cell_percentage_inline_size, - const bool is_table_block_size_restricted, + const bool is_table_block_size_specified, const NGTableTypes::ColumnLocations& column_locations, const NGTableBorders& table_borders, const LayoutUnit block_border_spacing, @@ -594,7 +594,7 @@ row = To<NGBlockNode>(row.NextSibling())) { colspan_cell_tabulator.StartRow(); NGTableTypes::Row row_constraint = ComputeMinimumRowBlockSize( - row, cell_percentage_inline_size, is_table_block_size_restricted, + row, cell_percentage_inline_size, is_table_block_size_specified, column_locations, table_borders, current_row++, section_index, /* is_section_collapsed */ section.Style().Visibility() == EVisibility::kCollapse,
diff --git a/third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm_utils.h b/third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm_utils.h index 8e5c8ba..4a76b54 100644 --- a/third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm_utils.h +++ b/third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm_utils.h
@@ -61,7 +61,7 @@ static void ComputeSectionMinimumRowBlockSizes( const NGBlockNode& section, const LayoutUnit cell_percentage_resolution_inline_size, - const bool is_restricted_block_size_table, + const bool is_table_block_size_specified, const NGTableTypes::ColumnLocations& column_locations, const NGTableBorders& table_borders, const LayoutUnit block_border_spacing,
diff --git a/third_party/blink/renderer/core/loader/document_loader.cc b/third_party/blink/renderer/core/loader/document_loader.cc index 8404d319..90f1b553 100644 --- a/third_party/blink/renderer/core/loader/document_loader.cc +++ b/third_party/blink/renderer/core/loader/document_loader.cc
@@ -401,7 +401,6 @@ params_->had_transient_user_activation), had_sticky_activation_(params_->is_user_activated), is_browser_initiated_(params_->is_browser_initiated), - is_prerendering_(params_->is_prerendering), was_discarded_(params_->was_discarded), loading_srcdoc_(url_.IsAboutSrcdocURL()), loading_url_as_empty_document_(!params_->is_static_data && @@ -526,7 +525,6 @@ params->had_transient_user_activation = last_navigation_had_transient_user_activation_; params->is_browser_initiated = is_browser_initiated_; - params->is_prerendering = is_prerendering_; params->was_discarded = was_discarded_; params->web_bundle_physical_url = web_bundle_physical_url_; params->web_bundle_claimed_url = web_bundle_claimed_url_; @@ -2255,6 +2253,7 @@ WillCommitNavigation(); + is_prerendering_ = frame_->GetPage()->IsPrerendering(); Document* document = frame_->DomWindow()->InstallNewDocument( DocumentInit::Create() .WithWindow(frame_->DomWindow(), owner_document)
diff --git a/third_party/blink/renderer/core/loader/document_loader.h b/third_party/blink/renderer/core/loader/document_loader.h index 8d1973cf5..4f320d6a 100644 --- a/third_party/blink/renderer/core/loader/document_loader.h +++ b/third_party/blink/renderer/core/loader/document_loader.h
@@ -581,7 +581,8 @@ // Whether this load request was initiated by the browser. const bool is_browser_initiated_ = false; - // Whether this loader is working for a prerendering document. + // Whether this loader committed a document in a prerendered page that has not + // yet been activated. This is only set after commit. bool is_prerendering_ = false; // If true, the navigation loading this document should allow a text fragment
diff --git a/third_party/blink/renderer/core/page/page.h b/third_party/blink/renderer/core/page/page.h index 2889d7d..72e214c 100644 --- a/third_party/blink/renderer/core/page/page.h +++ b/third_party/blink/renderer/core/page/page.h
@@ -330,6 +330,11 @@ void SetInsidePortal(bool inside_portal); bool InsidePortal() const; + void SetIsPrerendering(bool is_prerendering) { + is_prerendering_ = is_prerendering; + } + bool IsPrerendering() const { return is_prerendering_; } + void SetTextAutosizerPageInfo( const mojom::blink::TextAutosizerPageInfo& page_info) { web_text_autosizer_page_info_ = page_info; @@ -493,6 +498,14 @@ // Accessed by frames to determine whether to expose the PortalHost object. bool inside_portal_ = false; + // Whether the page is being prerendered by the Prerender2 + // feature. See content/browser/prerender/README.md. + // + // This is ordinarily initialized by WebViewImpl immediately after creating + // this Page. Once initialized, it can only transition from true to false on + // prerender activation; it does not go from false to true. + bool is_prerendering_ = false; + mojom::blink::TextAutosizerPageInfo web_text_autosizer_page_info_; WebScopedVirtualTimePauser history_navigation_virtual_time_pauser_;
diff --git a/third_party/blink/renderer/core/paint/inline_text_box_painter_test.cc b/third_party/blink/renderer/core/paint/inline_text_box_painter_test.cc index 1b505e57..7e194b63 100644 --- a/third_party/blink/renderer/core/paint/inline_text_box_painter_test.cc +++ b/third_party/blink/renderer/core/paint/inline_text_box_painter_test.cc
@@ -7,6 +7,7 @@ #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/renderer/core/editing/testing/selection_sample.h" +#include "third_party/blink/renderer/core/page/focus_controller.h" #include "third_party/blink/renderer/core/paint/paint_controller_paint_test.h" using testing::ElementsAre; @@ -41,8 +42,10 @@ return; SetBodyInnerHTML("<span>A<br>B<br>C</span>"); - GetDocument().GetFrame()->Selection().SetHandleVisibleForTesting(); - GetDocument().GetFrame()->Selection().SelectAll(); + LocalFrame* local_frame = GetDocument().GetFrame(); + local_frame->Selection().SetHandleVisibleForTesting(); + local_frame->GetPage()->GetFocusController().SetFocusedFrame(local_frame); + local_frame->Selection().SelectAll(); UpdateAllLifecyclePhasesForTest(); auto chunks = ContentPaintChunks(); @@ -65,11 +68,13 @@ if (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) return; - GetDocument().GetFrame()->Selection().SetSelectionAndEndTyping( + LocalFrame* local_frame = GetDocument().GetFrame(); + local_frame->Selection().SetSelectionAndEndTyping( SelectionSample::SetSelectionText( GetDocument().body(), "<div style='white-space:pre'>f^oo\nbar\nb|az</div>")); - GetDocument().GetFrame()->Selection().SetHandleVisibleForTesting(); + local_frame->Selection().SetHandleVisibleForTesting(); + local_frame->GetPage()->GetFocusController().SetFocusedFrame(local_frame); UpdateAllLifecyclePhasesForTest(); auto chunks = ContentPaintChunks();
diff --git a/third_party/blink/renderer/core/paint/list_marker_painter.cc b/third_party/blink/renderer/core/paint/list_marker_painter.cc index 93cb979..b269733 100644 --- a/third_party/blink/renderer/core/paint/list_marker_painter.cc +++ b/third_party/blink/renderer/core/paint/list_marker_painter.cc
@@ -86,8 +86,8 @@ const ComputedStyle& style, const LayoutRect& marker) { DCHECK(object); - DCHECK(style.GetListStyleType()); - DCHECK(style.GetListStyleType()->IsCounterStyle()); + DCHECK(style.ListStyleType()); + DCHECK(style.ListStyleType()->IsCounterStyle()); GraphicsContext& context = paint_info.context; ScopedDarkModeElementRoleOverride list_symbol( &context, DarkModeFilter::ElementRole::kListSymbol); @@ -101,7 +101,7 @@ context.SetStrokeStyle(kSolidStroke); context.SetStrokeThickness(1.0f); IntRect snapped_rect = PixelSnappedIntRect(marker); - const AtomicString& type = style.GetListStyleType()->GetCounterStyleName(); + const AtomicString& type = style.ListStyleType()->GetCounterStyleName(); if (type == "disc") { context.FillEllipse(FloatRect(snapped_rect)); } else if (type == "circle") {
diff --git a/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter_test.cc b/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter_test.cc index 4ad80e2..9d9bfd8 100644 --- a/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter_test.cc +++ b/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter_test.cc
@@ -200,4 +200,26 @@ auto record = builder.EndRecording(); } +TEST_P(NGBoxFragmentPainterTest, ClippedText) { + SetBodyInnerHTML(R"HTML( + <div id="target" style="overflow: hidden; position: relative; + width: 100px; height: 100px"> + A<br>B<br>C<br>D + </div> + )HTML"); + // Initially all the texts are painted. + auto num_all_display_items = ContentDisplayItems().size(); + auto* target = GetDocument().getElementById("target"); + + target->SetInlineStyleProperty(CSSPropertyID::kHeight, "0px"); + UpdateAllLifecyclePhasesForTest(); + // None of the texts should be painted. + EXPECT_EQ(num_all_display_items - 4, ContentDisplayItems().size()); + + target->SetInlineStyleProperty(CSSPropertyID::kHeight, "1px"); + UpdateAllLifecyclePhasesForTest(); + // Only "A" should be painted. + EXPECT_EQ(num_all_display_items - 3, ContentDisplayItems().size()); +} + } // namespace blink
diff --git a/third_party/blink/renderer/core/paint/scoped_paint_state.cc b/third_party/blink/renderer/core/paint/scoped_paint_state.cc index 3e302b1..db29fae 100644 --- a/third_party/blink/renderer/core/paint/scoped_paint_state.cc +++ b/third_party/blink/renderer/core/paint/scoped_paint_state.cc
@@ -55,25 +55,25 @@ fragment_to_paint_->ContentsProperties(), box, input_paint_info_.DisplayItemTypeForClipping()); - // Then adjust paint offset and cull rect for scroll translation. const auto* properties = fragment_to_paint_->PaintProperties(); - if (!properties) - return; - const auto* scroll_translation = properties->ScrollTranslation(); - if (!scroll_translation) - return; + const auto* scroll_translation = + properties ? properties->ScrollTranslation() : nullptr; // See comments for ScrollTranslation in object_paint_properties.h // for the reason of adding ScrollOrigin(). The paint offset will // be used only for the scrolling contents that are not painted through // descendant objects' Paint() method, e.g. inline boxes. - paint_offset_ += PhysicalOffset(box.ScrollOrigin()); + if (scroll_translation) + paint_offset_ += PhysicalOffset(box.ScrollOrigin()); if (RuntimeEnabledFeatures::CullRectUpdateEnabled()) { + // We calculated cull rects for PaintLayers only. + if (!box.HasLayer()) + return; adjusted_paint_info_.emplace(input_paint_info_); adjusted_paint_info_->SetCullRect( fragment_to_paint_->GetContentsCullRect()); - if (box.HasLayer() && box.Layer()->PreviousPaintResult() == kFullyPainted) { + if (box.Layer()->PreviousPaintResult() == kFullyPainted) { PhysicalRect contents_visual_rect = box.PhysicalContentsVisualOverflowRect(); contents_visual_rect.Move(fragment_to_paint_->PaintOffset()); @@ -94,8 +94,10 @@ if (IsA<LayoutView>(box) && input_paint_info_.GetCullRect().IsInfinite()) return; - adjusted_paint_info_.emplace(input_paint_info_); - adjusted_paint_info_->TransformCullRect(*scroll_translation); + if (scroll_translation) { + adjusted_paint_info_.emplace(input_paint_info_); + adjusted_paint_info_->TransformCullRect(*scroll_translation); + } } } // namespace blink
diff --git a/third_party/blink/renderer/core/paint/selection_bounds_recorder.cc b/third_party/blink/renderer/core/paint/selection_bounds_recorder.cc index 411f20eb..f9266ca8 100644 --- a/third_party/blink/renderer/core/paint/selection_bounds_recorder.cc +++ b/third_party/blink/renderer/core/paint/selection_bounds_recorder.cc
@@ -10,6 +10,8 @@ #include "third_party/blink/renderer/core/layout/api/selection_state.h" #include "third_party/blink/renderer/core/layout/geometry/physical_rect.h" #include "third_party/blink/renderer/core/layout/layout_box.h" +#include "third_party/blink/renderer/core/page/focus_controller.h" +#include "third_party/blink/renderer/core/page/page.h" #include "third_party/blink/renderer/platform/graphics/paint/paint_controller.h" namespace blink { @@ -165,6 +167,16 @@ if (!frame_selection.IsHandleVisible() || frame_selection.IsHidden()) return false; + // If the currently focused frame is not the one in which selection + // lives, don't paint the selection bounds. Note this is subtly different + // from whether the frame has focus (i.e. `FrameSelection::SelectionHasFocus`) + // which is false if the hosting window is not focused. + LocalFrame* local_frame = frame_selection.GetFrame(); + LocalFrame* focused_frame = + local_frame->GetPage()->GetFocusController().FocusedFrame(); + if (local_frame != focused_frame) + return false; + if (state == SelectionState::kInside || state == SelectionState::kNone) return false;
diff --git a/third_party/blink/renderer/core/style/computed_style.cc b/third_party/blink/renderer/core/style/computed_style.cc index 04f33532..0bce899 100644 --- a/third_party/blink/renderer/core/style/computed_style.cc +++ b/third_party/blink/renderer/core/style/computed_style.cc
@@ -2517,14 +2517,10 @@ curr_child->ClearImage(); } -ListStyleTypeData* ComputedStyle::GetListStyleType() const { - return ListStyleTypeInternal(); -} - const AtomicString& ComputedStyle::ListStyleStringValue() const { - if (!GetListStyleType() || !GetListStyleType()->IsString()) + if (!ListStyleType() || !ListStyleType()->IsString()) return g_null_atom; - return GetListStyleType()->GetStringValue(); + return ListStyleType()->GetStringValue(); } absl::optional<Color> ComputedStyle::AccentColorResolved() const {
diff --git a/third_party/blink/renderer/core/style/computed_style.h b/third_party/blink/renderer/core/style/computed_style.h index 4103f1c..d88bed13 100644 --- a/third_party/blink/renderer/core/style/computed_style.h +++ b/third_party/blink/renderer/core/style/computed_style.h
@@ -963,11 +963,8 @@ // list-style-type const AtomicString& ListStyleStringValue() const; - // TODO(crbug.com/687225): Make this function auto-generated. - CORE_EXPORT ListStyleTypeData* GetListStyleType() const; bool ListStyleTypeDataEquivalent(const ComputedStyle& other) const { - return DataEquivalent(ListStyleTypeInternal(), - other.ListStyleTypeInternal()); + return DataEquivalent(ListStyleType(), other.ListStyleType()); } // quotes
diff --git a/third_party/blink/renderer/core/testing/origin_trials_test_global.h b/third_party/blink/renderer/core/testing/origin_trials_test_global.h new file mode 100644 index 0000000..2cbb03c --- /dev/null +++ b/third_party/blink/renderer/core/testing/origin_trials_test_global.h
@@ -0,0 +1,25 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_TESTING_ORIGIN_TRIALS_TEST_GLOBAL_H_ +#define THIRD_PARTY_BLINK_RENDERER_CORE_TESTING_ORIGIN_TRIALS_TEST_GLOBAL_H_ + +#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" + +namespace blink { + +class LocalDOMWindow; + +// This is used for testing that the Window interface can be extended with +// origin trial-enabled IDL members at run-time. +class OriginTrialsTestGlobal final { + STATIC_ONLY(OriginTrialsTestGlobal); + + public: + static bool testOriginTrialGlobalAttribute(LocalDOMWindow&) { return true; } +}; + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_CORE_TESTING_ORIGIN_TRIALS_TEST_GLOBAL_H_
diff --git a/third_party/blink/renderer/core/testing/origin_trials_test_window.idl b/third_party/blink/renderer/core/testing/origin_trials_test_window.idl new file mode 100644 index 0000000..1c4adb6 --- /dev/null +++ b/third_party/blink/renderer/core/testing/origin_trials_test_window.idl
@@ -0,0 +1,10 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +[ + ImplementedAs=OriginTrialsTestGlobal, + RuntimeEnabled=OriginTrialsSampleAPI +] partial interface Window { + readonly attribute boolean testOriginTrialGlobalAttribute; +};
diff --git a/third_party/blink/renderer/modules/accessibility/ax_layout_object.cc b/third_party/blink/renderer/modules/accessibility/ax_layout_object.cc index 37ec5f8..6886bbe 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_layout_object.cc +++ b/third_party/blink/renderer/modules/accessibility/ax_layout_object.cc
@@ -622,7 +622,7 @@ return ax::mojom::blink::ListStyle::kNone; case ListMarker::ListStyleCategory::kSymbol: { const AtomicString& counter_style_name = - computed_style->GetListStyleType()->GetCounterStyleName(); + computed_style->ListStyleType()->GetCounterStyleName(); if (counter_style_name == "disc") return ax::mojom::blink::ListStyle::kDisc; if (counter_style_name == "circle") @@ -633,7 +633,7 @@ } case ListMarker::ListStyleCategory::kLanguage: { const AtomicString& counter_style_name = - computed_style->GetListStyleType()->GetCounterStyleName(); + computed_style->ListStyleType()->GetCounterStyleName(); if (counter_style_name == "decimal") return ax::mojom::blink::ListStyle::kNumeric; if (counter_style_name == "decimal-leading-zero") {
diff --git a/third_party/blink/renderer/modules/csspaint/paint_worklet.cc b/third_party/blink/renderer/modules/csspaint/paint_worklet.cc index e6e0c5b..618e08f 100644 --- a/third_party/blink/renderer/modules/csspaint/paint_worklet.cc +++ b/third_party/blink/renderer/modules/csspaint/paint_worklet.cc
@@ -17,6 +17,7 @@ #include "third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope.h" #include "third_party/blink/renderer/modules/csspaint/paint_worklet_id_generator.h" #include "third_party/blink/renderer/modules/csspaint/paint_worklet_messaging_proxy.h" +#include "third_party/blink/renderer/platform/bindings/script_forbidden_scope.h" #include "third_party/blink/renderer/platform/graphics/paint_generated_image.h" namespace blink { @@ -126,6 +127,10 @@ layout_object.GetDocument(), layout_object.StyleRef(), paint_definition->NativeInvalidationProperties(), paint_definition->CustomInvalidationProperties()); + // The PaintWorkletGlobalScope is sufficiently isolated that it is safe to + // run during the lifecycle update without concern for it causing + // invalidations to the lifecycle. + ScriptForbiddenScope::AllowUserAgentScript allow_script; sk_sp<PaintRecord> paint_record = paint_definition->Paint( container_size, zoom, style_map, data, device_scale_factor); if (!paint_record)
diff --git a/third_party/blink/renderer/modules/file_system_access/file_system_access_file_delegate.h b/third_party/blink/renderer/modules/file_system_access/file_system_access_file_delegate.h index c884478..9ae8bc4 100644 --- a/third_party/blink/renderer/modules/file_system_access/file_system_access_file_delegate.h +++ b/third_party/blink/renderer/modules/file_system_access/file_system_access_file_delegate.h
@@ -5,12 +5,17 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_FILE_SYSTEM_ACCESS_FILE_SYSTEM_ACCESS_FILE_DELEGATE_H_ #define THIRD_PARTY_BLINK_RENDERER_MODULES_FILE_SYSTEM_ACCESS_FILE_SYSTEM_ACCESS_FILE_DELEGATE_H_ +#include "base/files/file.h" #include "mojo/public/cpp/bindings/pending_remote.h" #include "third_party/blink/public/mojom/file_system_access/file_system_access_file_handle.mojom-blink.h" #include "third_party/blink/renderer/core/execution_context/execution_context.h" #include "third_party/blink/renderer/platform/heap/handle.h" namespace blink { +// File object providing a common interface for file operations for an +// AccessHandle. These methods closely map to base::File equivalents. The +// implementation of the FileDelegate will depend on whether the renderer is in +// incognito. All methods are synchronous. class FileSystemAccessFileDelegate : public GarbageCollected<FileSystemAccessFileDelegate> { public: @@ -22,10 +27,42 @@ mojo::PendingRemote<mojom::blink::FileSystemAccessFileDelegateHost> incognito_file_remote); - // TODO(crbug.com/1225653): Add file operation methods here. + // Reads the given number of bytes (or until EOF is reached) into the span + // starting with the given offset. Returns the number of bytes read, or -1 on + // error. + virtual int Read(int64_t offset, base::span<uint8_t> data) = 0; + // Writes the span into the file at the given offset, overwriting any data + // that was previously there. Returns the number of bytes written, or -1 on + // error. + virtual int Write(int64_t offset, const base::span<uint8_t> data) = 0; + + // Returns the current size of this file, or a negative number on failure. + virtual int64_t GetLength() = 0; + + // Truncates the file to the given length. If |length| is greater than the + // current size of the file, the file is extended with zeros. If the file + // doesn't exist, |false| is returned. + virtual bool SetLength(int64_t length) = 0; + + // Instructs the filesystem to flush the file to disk. + virtual bool Flush() = 0; + + // Close the file. Destroying this object will close the file automatically. + virtual void Close() = 0; + + // Returns |true| if the file handle wrapped by this object is valid. virtual bool IsValid() const = 0; + // TODO(crbug.com/1228745): Move FileErrorOr to //base and use as a return + // type for the methods above. Then remove this method. + // + // Returns the error for the last operation on this file and converts it to + // the closest base::File::Error equivalent. Unlike the base::File equivalent, + // this method returns a cached error value which is guaranteed to be from the + // last operation on this file. + virtual base::File::Error GetLastFileError() = 0; + // GarbageCollected virtual void Trace(Visitor* visitor) const {} };
diff --git a/third_party/blink/renderer/modules/file_system_access/file_system_access_incognito_file_delegate.cc b/third_party/blink/renderer/modules/file_system_access/file_system_access_incognito_file_delegate.cc index c17df70..f73dcae 100644 --- a/third_party/blink/renderer/modules/file_system_access/file_system_access_incognito_file_delegate.cc +++ b/third_party/blink/renderer/modules/file_system_access/file_system_access_incognito_file_delegate.cc
@@ -4,6 +4,8 @@ #include "third_party/blink/renderer/modules/file_system_access/file_system_access_incognito_file_delegate.h" +#include "base/files/file.h" +#include "base/notreached.h" #include "mojo/public/cpp/bindings/pending_remote.h" #include "third_party/blink/renderer/core/execution_context/execution_context.h" #include "third_party/blink/renderer/modules/file_system_access/file_system_access_file_delegate.h" @@ -36,4 +38,48 @@ FileSystemAccessFileDelegate::Trace(visitor); } +int FileSystemAccessIncognitoFileDelegate::Read(int64_t offset, + base::span<uint8_t> data) { + // TODO(crbug.com/1225653): Implement this method. + NOTIMPLEMENTED(); + return 0; +} + +int FileSystemAccessIncognitoFileDelegate::Write( + int64_t offset, + const base::span<uint8_t> data) { + // TODO(crbug.com/1225653): Implement this method. + NOTIMPLEMENTED(); + return 0; +} + +int64_t FileSystemAccessIncognitoFileDelegate::GetLength() { + // TODO(crbug.com/1225653): Implement this method. + NOTIMPLEMENTED(); + return 0; +} + +bool FileSystemAccessIncognitoFileDelegate::SetLength(int64_t length) { + // TODO(crbug.com/1225653): Implement this method. + NOTIMPLEMENTED(); + return false; +} + +bool FileSystemAccessIncognitoFileDelegate::Flush() { + // TODO(crbug.com/1225653): Implement this method. + NOTIMPLEMENTED(); + return false; +} + +void FileSystemAccessIncognitoFileDelegate::Close() { + // TODO(crbug.com/1225653): Implement this method. + NOTIMPLEMENTED(); +} + +base::File::Error FileSystemAccessIncognitoFileDelegate::GetLastFileError() { + // TODO(crbug.com/1225653): Implement this method. + NOTIMPLEMENTED(); + return base::File::Error::FILE_OK; +} + } // namespace blink
diff --git a/third_party/blink/renderer/modules/file_system_access/file_system_access_incognito_file_delegate.h b/third_party/blink/renderer/modules/file_system_access/file_system_access_incognito_file_delegate.h index 958478a..e2bf801a 100644 --- a/third_party/blink/renderer/modules/file_system_access/file_system_access_incognito_file_delegate.h +++ b/third_party/blink/renderer/modules/file_system_access/file_system_access_incognito_file_delegate.h
@@ -5,6 +5,7 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_FILE_SYSTEM_ACCESS_FILE_SYSTEM_ACCESS_INCOGNITO_FILE_DELEGATE_H_ #define THIRD_PARTY_BLINK_RENDERER_MODULES_FILE_SYSTEM_ACCESS_FILE_SYSTEM_ACCESS_INCOGNITO_FILE_DELEGATE_H_ +#include "base/files/file.h" #include "mojo/public/cpp/bindings/pending_remote.h" #include "third_party/blink/public/mojom/file_system_access/file_system_access_file_handle.mojom-blink.h" #include "third_party/blink/renderer/core/execution_context/execution_context.h" @@ -14,6 +15,8 @@ namespace blink { +// Incognito implementation of the FileSystemAccessFileDelegate. All file +// operations are routed to the browser to be written to in-memory files. class FileSystemAccessIncognitoFileDelegate final : public FileSystemAccessFileDelegate { public: @@ -30,8 +33,19 @@ FileSystemAccessIncognitoFileDelegate& operator=( const FileSystemAccessIncognitoFileDelegate&) = delete; + int Read(int64_t offset, base::span<uint8_t> data) override; + int Write(int64_t offset, const base::span<uint8_t> data) override; + + int64_t GetLength() override; + bool SetLength(int64_t length) override; + + bool Flush() override; + void Close() override; + bool IsValid() const override { return mojo_ptr_.is_bound(); } + base::File::Error GetLastFileError() override; + void Trace(Visitor*) const override; private:
diff --git a/third_party/blink/renderer/modules/file_system_access/file_system_access_regular_file_delegate.cc b/third_party/blink/renderer/modules/file_system_access/file_system_access_regular_file_delegate.cc index b4ea7f2..37e41b04 100644 --- a/third_party/blink/renderer/modules/file_system_access/file_system_access_regular_file_delegate.cc +++ b/third_party/blink/renderer/modules/file_system_access/file_system_access_regular_file_delegate.cc
@@ -4,6 +4,7 @@ #include "third_party/blink/renderer/modules/file_system_access/file_system_access_regular_file_delegate.h" +#include "base/notreached.h" #include "mojo/public/cpp/bindings/pending_remote.h" #include "third_party/blink/renderer/platform/heap/handle.h" @@ -20,4 +21,47 @@ base::PassKey<FileSystemAccessFileDelegate>) : backing_file_(std::move(backing_file)) {} +int FileSystemAccessRegularFileDelegate::Read(int64_t offset, + base::span<uint8_t> data) { + // TODO(crbug.com/1218431): Implement this method. + NOTIMPLEMENTED(); + return 0; +} + +int FileSystemAccessRegularFileDelegate::Write(int64_t offset, + const base::span<uint8_t> data) { + // TODO(crbug.com/1218431): Implement this method. + NOTIMPLEMENTED(); + return 0; +} + +int64_t FileSystemAccessRegularFileDelegate::GetLength() { + // TODO(crbug.com/1218431): Implement this method. + NOTIMPLEMENTED(); + return 0; +} + +bool FileSystemAccessRegularFileDelegate::SetLength(int64_t length) { + // TODO(crbug.com/1218431): Implement this method. + NOTIMPLEMENTED(); + return false; +} + +bool FileSystemAccessRegularFileDelegate::Flush() { + // TODO(crbug.com/1218431): Implement this method. + NOTIMPLEMENTED(); + return false; +} + +void FileSystemAccessRegularFileDelegate::Close() { + // TODO(crbug.com/1218431): Implement this method. + NOTIMPLEMENTED(); +} + +base::File::Error FileSystemAccessRegularFileDelegate::GetLastFileError() { + // TODO(crbug.com/1218431): Implement this method. + NOTIMPLEMENTED(); + return base::File::Error::FILE_OK; +} + } // namespace blink
diff --git a/third_party/blink/renderer/modules/file_system_access/file_system_access_regular_file_delegate.h b/third_party/blink/renderer/modules/file_system_access/file_system_access_regular_file_delegate.h index e3664d3..991f813 100644 --- a/third_party/blink/renderer/modules/file_system_access/file_system_access_regular_file_delegate.h +++ b/third_party/blink/renderer/modules/file_system_access/file_system_access_regular_file_delegate.h
@@ -5,6 +5,7 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_FILE_SYSTEM_ACCESS_FILE_SYSTEM_ACCESS_REGULAR_FILE_DELEGATE_H_ #define THIRD_PARTY_BLINK_RENDERER_MODULES_FILE_SYSTEM_ACCESS_FILE_SYSTEM_ACCESS_REGULAR_FILE_DELEGATE_H_ +#include "base/files/file.h" #include "base/types/pass_key.h" #include "mojo/public/cpp/bindings/pending_remote.h" #include "third_party/blink/public/mojom/file_system_access/file_system_access_file_handle.mojom-blink.h" @@ -13,6 +14,8 @@ namespace blink { +// Non-incognito implementation of the FileSystemAccessFileDelegate. This class +// is a thin wrapper around an OS-level file descriptor. class FileSystemAccessRegularFileDelegate final : public FileSystemAccessFileDelegate { public: @@ -27,8 +30,19 @@ FileSystemAccessRegularFileDelegate& operator=( const FileSystemAccessRegularFileDelegate&) = delete; + int Read(int64_t offset, base::span<uint8_t> data) override; + int Write(int64_t offset, const base::span<uint8_t> data) override; + + int64_t GetLength() override; + bool SetLength(int64_t length) override; + + bool Flush() override; + void Close() override; + bool IsValid() const override { return backing_file_.IsValid(); } + base::File::Error GetLastFileError() override; + private: // The file on disk backing the parent FileSystemFileHandle. base::File backing_file_;
diff --git a/third_party/blink/renderer/modules/manifest/manifest_parser_unittest.cc b/third_party/blink/renderer/modules/manifest/manifest_parser_unittest.cc index c82b1be..3eb707b 100644 --- a/third_party/blink/renderer/modules/manifest/manifest_parser_unittest.cc +++ b/third_party/blink/renderer/modules/manifest/manifest_parser_unittest.cc
@@ -625,6 +625,7 @@ // Parsing fails for 'window-controls-overlay' when WCO flag is disabled. { + ScopedWebAppWindowControlsOverlayForTest window_controls_overlay(false); auto& manifest = ParseManifest("{ \"display\": \"window-controls-overlay\" }"); EXPECT_EQ(manifest->display, blink::mojom::DisplayMode::kUndefined); @@ -790,6 +791,7 @@ // Reject 'window-controls-overlay' when WCO flag is disabled. { + ScopedWebAppWindowControlsOverlayForTest window_controls_overlay(false); auto& manifest = ParseManifest( "{ \"display_override\": [ \"window-controls-overlay\" ] }"); EXPECT_TRUE(manifest->display_override.IsEmpty());
diff --git a/third_party/blink/renderer/modules/peerconnection/webrtc_audio_renderer_test.cc b/third_party/blink/renderer/modules/peerconnection/webrtc_audio_renderer_test.cc index 1af78b3..bfbf19c 100644 --- a/third_party/blink/renderer/modules/peerconnection/webrtc_audio_renderer_test.cc +++ b/third_party/blink/renderer/modules/peerconnection/webrtc_audio_renderer_test.cc
@@ -142,6 +142,7 @@ web_view_(blink::WebView::Create( /*client=*/nullptr, /*is_hidden=*/false, + /*is_prerendering=*/false, /*is_inside_portal=*/false, /*compositing_enabled=*/false, /*widgets_never_composited=*/false,
diff --git a/third_party/blink/renderer/modules/webcodecs/BUILD.gn b/third_party/blink/renderer/modules/webcodecs/BUILD.gn index 5bc0d8f..3e92645 100644 --- a/third_party/blink/renderer/modules/webcodecs/BUILD.gn +++ b/third_party/blink/renderer/modules/webcodecs/BUILD.gn
@@ -52,8 +52,6 @@ "image_track_list.h", "parsed_copy_to_options.cc", "parsed_copy_to_options.h", - "plane.cc", - "plane.h", "video_color_space.cc", "video_color_space.h", "video_decoder.cc",
diff --git a/third_party/blink/renderer/modules/webcodecs/parsed_copy_to_options.cc b/third_party/blink/renderer/modules/webcodecs/parsed_copy_to_options.cc index bc4f2bf80..7351ae21 100644 --- a/third_party/blink/renderer/modules/webcodecs/parsed_copy_to_options.cc +++ b/third_party/blink/renderer/modules/webcodecs/parsed_copy_to_options.cc
@@ -9,7 +9,6 @@ #include "base/numerics/checked_math.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_plane_layout.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_video_frame_copy_to_options.h" -#include "third_party/blink/renderer/bindings/modules/v8/v8_video_frame_rect.h" #include "third_party/blink/renderer/modules/webcodecs/dom_rect_util.h" #include "third_party/blink/renderer/platform/bindings/exception_state.h"
diff --git a/third_party/blink/renderer/modules/webcodecs/plane.cc b/third_party/blink/renderer/modules/webcodecs/plane.cc deleted file mode 100644 index aa4b37e8..0000000 --- a/third_party/blink/renderer/modules/webcodecs/plane.cc +++ /dev/null
@@ -1,121 +0,0 @@ -// Copyright 2020 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "third_party/blink/renderer/modules/webcodecs/plane.h" - -#include <string.h> - -#include "third_party/blink/renderer/platform/bindings/exception_code.h" -#include "third_party/blink/renderer/platform/bindings/exception_state.h" -#include "ui/gfx/gpu_memory_buffer.h" - -namespace blink { - -namespace { - -void CopyPlane(const uint8_t* plane, - size_t copy_size, - size_t trailing_zeros_size, - uint8_t* dest) { - // Copy plane bytes. - memcpy(dest, plane, copy_size); - - // Zero trailing padding bytes. - memset(dest + copy_size, 0, trailing_zeros_size); -} - -} // namespace - -Plane::Plane(scoped_refptr<VideoFrameHandle> handle, size_t plane) - : handle_(std::move(handle)), plane_(plane) { -#if DCHECK_IS_ON() - // Validate the plane index, but only if the handle is valid. - auto local_frame = handle_->frame(); - if (local_frame) { - DCHECK(local_frame->IsMappable() || local_frame->HasGpuMemoryBuffer()); - DCHECK_LT(plane, local_frame->layout().num_planes()); - } -#endif // DCHECK_IS_ON() -} - -uint32_t Plane::stride() const { - auto local_frame = handle_->frame(); - if (!local_frame) - return 0; - // TODO(sandersd): Consider returning row_bytes() instead. This would imply - // removing padding bytes in copyInto(). - return local_frame->stride(plane_); -} - -uint32_t Plane::rows() const { - auto local_frame = handle_->frame(); - if (!local_frame) - return 0; - return local_frame->rows(plane_); -} - -uint32_t Plane::length() const { - auto local_frame = handle_->frame(); - if (!local_frame) - return 0; - - // Note: this could be slightly larger than the actual data size. readInto() - // will pad with zeros. - return local_frame->rows(plane_) * local_frame->stride(plane_); -} - -void Plane::readInto(MaybeShared<DOMArrayBufferView> dst, - ExceptionState& exception_state) { - auto local_frame = handle_->frame(); - if (!local_frame) { - exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError, - "Cannot read from closed VideoFrame."); - return; - } - - // Note: these methods all return int. - size_t rows = local_frame->rows(plane_); - size_t row_bytes = local_frame->row_bytes(plane_); - size_t stride = local_frame->stride(plane_); - - DCHECK_GT(rows, 0u); // should fail VideoFrame::IsValidConfig() - DCHECK_GT(row_bytes, 0u); // should fail VideoFrame::IsValidConfig() - DCHECK_GE(stride, row_bytes); - - size_t total_size = rows * stride; - size_t trailing_zeros_size = stride - row_bytes; - size_t copy_size = total_size - trailing_zeros_size; - - // Note: byteLength is zero if the buffer is detached. - uint8_t* base = static_cast<uint8_t*>(dst->BaseAddressMaybeShared()); - if (!base) { - exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError, - "Destination buffer is not valid."); - return; - } - if (total_size > dst->byteLength()) { - exception_state.ThrowDOMException( - DOMExceptionCode::kInvalidStateError, - "Destination buffer is not large enough."); - return; - } - - if (local_frame->IsMappable()) { - CopyPlane(local_frame->data(plane_), copy_size, trailing_zeros_size, base); - return; - } - - DCHECK(local_frame->HasGpuMemoryBuffer()); - auto* gmb = local_frame->GetGpuMemoryBuffer(); - if (!gmb->Map()) { - exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError, - "Could not map video frame into memory."); - return; - } - CopyPlane(static_cast<const uint8_t*>(gmb->memory(plane_)), copy_size, - trailing_zeros_size, base); - gmb->Unmap(); -} - -} // namespace blink
diff --git a/third_party/blink/renderer/modules/webcodecs/plane.h b/third_party/blink/renderer/modules/webcodecs/plane.h deleted file mode 100644 index c271016..0000000 --- a/third_party/blink/renderer/modules/webcodecs/plane.h +++ /dev/null
@@ -1,49 +0,0 @@ -// Copyright 2020 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_WEBCODECS_PLANE_H_ -#define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBCODECS_PLANE_H_ - -#include <stdint.h> - -#include "base/memory/scoped_refptr.h" -#include "third_party/blink/renderer/core/typed_arrays/array_buffer_view_helpers.h" -#include "third_party/blink/renderer/core/typed_arrays/dom_typed_array.h" -#include "third_party/blink/renderer/modules/modules_export.h" -#include "third_party/blink/renderer/modules/webcodecs/video_frame_handle.h" -#include "third_party/blink/renderer/platform/bindings/script_wrappable.h" - -namespace blink { - -class ExceptionState; - -class MODULES_EXPORT Plane final : public ScriptWrappable { - DEFINE_WRAPPERTYPEINFO(); - - public: - // Construct a Plane given a |handle| and a plane index. - // It is legal for |handle| to be invalid, the resulting Plane will also be - // invalid. - Plane(scoped_refptr<VideoFrameHandle> handle, size_t plane); - ~Plane() override = default; - - // TODO(sandersd): Review return types. There is some implicit casting going - // on here. - // TODO(sandersd): Consider throwing if |handle_| is invalidated. Currently - // everything returns 0, which is not a bad API either. - uint32_t stride() const; - uint32_t rows() const; - uint32_t length() const; - - // Throws InvalidStateError if |handle_| has been invalidated. - void readInto(MaybeShared<DOMArrayBufferView> dst, ExceptionState&); - - private: - scoped_refptr<VideoFrameHandle> handle_; - size_t plane_; -}; - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_WEBCODECS_PLANE_H_
diff --git a/third_party/blink/renderer/modules/webcodecs/plane.idl b/third_party/blink/renderer/modules/webcodecs/plane.idl deleted file mode 100644 index 637721a..0000000 --- a/third_party/blink/renderer/modules/webcodecs/plane.idl +++ /dev/null
@@ -1,16 +0,0 @@ -// Copyright 2020 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// https://github.com/WICG/web-codecs - -[ - Exposed=(Window,DedicatedWorker), - RuntimeEnabled=WebCodecs -] interface Plane { - readonly attribute unsigned long stride; - readonly attribute unsigned long rows; - readonly attribute unsigned long length; - - [RaisesException] void readInto([AllowShared] ArrayBufferView dst); -};
diff --git a/third_party/blink/renderer/modules/webcodecs/plane_init.idl b/third_party/blink/renderer/modules/webcodecs/plane_init.idl deleted file mode 100644 index f9b111e..0000000 --- a/third_party/blink/renderer/modules/webcodecs/plane_init.idl +++ /dev/null
@@ -1,15 +0,0 @@ -// Copyright 2020 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// https://github.com/WICG/web-codecs - -dictionary PlaneInit { - // TODO(sandersd): Mark as required when |src| is removed. - BufferSource data; - [EnforceRange] unsigned long offset; - required [EnforceRange] unsigned long stride; - - // DEPRECATED: Use |data|. - BufferSource src; -};
diff --git a/third_party/blink/renderer/modules/webcodecs/video_decoder.cc b/third_party/blink/renderer/modules/webcodecs/video_decoder.cc index 7e9e2ca..189fa42e 100644 --- a/third_party/blink/renderer/modules/webcodecs/video_decoder.cc +++ b/third_party/blink/renderer/modules/webcodecs/video_decoder.cc
@@ -27,7 +27,6 @@ #include "third_party/blink/renderer/bindings/modules/v8/v8_video_color_space_init.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_video_decoder_config.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_video_decoder_support.h" -#include "third_party/blink/renderer/bindings/modules/v8/v8_video_frame_rect.h" #include "third_party/blink/renderer/core/dom/dom_exception.h" #include "third_party/blink/renderer/modules/webcodecs/codec_config_eval.h" #include "third_party/blink/renderer/modules/webcodecs/encoded_video_chunk.h"
diff --git a/third_party/blink/renderer/modules/webcodecs/video_frame.cc b/third_party/blink/renderer/modules/webcodecs/video_frame.cc index 61eeddb..1e960317 100644 --- a/third_party/blink/renderer/modules/webcodecs/video_frame.cc +++ b/third_party/blink/renderer/modules/webcodecs/video_frame.cc
@@ -19,15 +19,12 @@ #include "media/base/video_util.h" #include "third_party/blink/public/platform/platform.h" #include "third_party/blink/public/platform/web_graphics_context_3d_provider.h" -#include "third_party/blink/renderer/bindings/modules/v8/v8_plane_init.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_plane_layout.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_union_cssimagevalue_htmlcanvaselement_htmlimageelement_htmlvideoelement_imagebitmap_offscreencanvas_svgimageelement_videoframe.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_video_color_space_init.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_video_frame_buffer_init.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_video_frame_copy_to_options.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_video_frame_init.h" -#include "third_party/blink/renderer/bindings/modules/v8/v8_video_frame_plane_init.h" -#include "third_party/blink/renderer/bindings/modules/v8/v8_video_frame_rect.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_video_pixel_format.h" #include "third_party/blink/renderer/core/geometry/dom_rect_read_only.h" #include "third_party/blink/renderer/core/html/canvas/canvas_image_source.h" @@ -39,7 +36,6 @@ #include "third_party/blink/renderer/modules/webcodecs/dom_rect_util.h" #include "third_party/blink/renderer/modules/webcodecs/parsed_copy_to_options.h" #include "third_party/blink/renderer/modules/webcodecs/video_color_space.h" -#include "third_party/blink/renderer/modules/webcodecs/webcodecs_logger.h" #include "third_party/blink/renderer/platform/graphics/image.h" #include "third_party/blink/renderer/platform/graphics/skia/skia_utils.h" #include "third_party/blink/renderer/platform/graphics/unaccelerated_static_bitmap_image.h" @@ -432,235 +428,6 @@ ExecutionContext::From(script_state))); } -// TODO(crbug.com/1198324): Merge shared logic with VideoDecoderConfig. -// static -VideoFrame* VideoFrame::Create(ScriptState* script_state, - const HeapVector<Member<PlaneInit>>& planes, - const VideoFramePlaneInit* init, - ExceptionState& exception_state) { - ExecutionContext* execution_context = ExecutionContext::From(script_state); - WebCodecsLogger::From(*execution_context).LogPlanarConstructionDeprecation(); - - // Handle format; the string was validated by the V8 binding. - auto typed_fmt = V8VideoPixelFormat::Create(init->format()); - auto media_fmt = ToMediaPixelFormat(typed_fmt->AsEnum()); - - // Validate coded size. - uint32_t coded_width = init->codedWidth(); - uint32_t coded_height = init->codedHeight(); - if (coded_width == 0 || coded_width > media::limits::kMaxDimension || - coded_height == 0 || coded_height > media::limits::kMaxDimension || - coded_width * coded_height > media::limits::kMaxCanvas) { - exception_state.ThrowTypeError(String::Format( - "Invalid coded size (%u, %u).", coded_width, coded_height)); - return nullptr; - } - - const gfx::Size coded_size(coded_width, coded_height); - - // Validate visible rect. - uint32_t visible_left = 0; - uint32_t visible_top = 0; - uint32_t visible_width = coded_width; - uint32_t visible_height = coded_height; - if (init->hasVisibleRect()) { - gfx::Rect rect = - ToGfxRect(init->visibleRect(), "visibleRect", exception_state); - if (exception_state.HadException()) - return nullptr; - visible_left = rect.x(); - visible_top = rect.y(); - visible_width = rect.width(); - visible_height = rect.height(); - } else if (init->hasVisibleRegion()) { - WebCodecsLogger::From(*execution_context).LogVisibleRegionDeprecation(); - visible_left = init->visibleRegion()->left(); - visible_top = init->visibleRegion()->top(); - visible_width = init->visibleRegion()->width(); - visible_height = init->visibleRegion()->height(); - } else { - if (init->hasCropLeft()) { - WebCodecsLogger::From(*execution_context).LogCropDeprecation(); - visible_left = init->cropLeft(); - if (visible_left >= coded_width) { - exception_state.ThrowTypeError( - String::Format("Invalid cropLeft %u for codedWidth %u.", - visible_left, coded_width)); - return nullptr; - } - visible_width = coded_width - visible_left; - } - if (init->hasCropTop()) { - WebCodecsLogger::From(*execution_context).LogCropDeprecation(); - visible_top = init->cropTop(); - if (visible_top >= coded_height) { - exception_state.ThrowTypeError( - String::Format("Invalid cropTop %u for codedHeight %u.", - visible_top, coded_height)); - return nullptr; - } - visible_height = coded_height - visible_top; - } - if (init->hasCropWidth()) { - WebCodecsLogger::From(*execution_context).LogCropDeprecation(); - visible_width = init->cropWidth(); - } - if (init->hasCropHeight()) { - WebCodecsLogger::From(*execution_context).LogCropDeprecation(); - visible_height = init->cropHeight(); - } - } - if (visible_left >= coded_width || visible_top >= coded_height || - visible_width == 0 || visible_width > media::limits::kMaxDimension || - visible_height == 0 || visible_height > media::limits::kMaxDimension || - visible_left + visible_width > coded_width || - visible_top + visible_height > coded_height) { - exception_state.ThrowTypeError( - String::Format("Invalid visibleRect {x: %u, y: %u, width: %u, " - "height: %u} for coded size (%u, %u).", - visible_left, visible_top, visible_width, visible_height, - coded_width, coded_height)); - return nullptr; - } - - const gfx::Rect visible_rect(visible_left, visible_top, visible_width, - visible_height); - - // Validate natural size. - uint32_t natural_width = visible_width; - uint32_t natural_height = visible_height; - if (init->hasDisplayWidth() || init->hasDisplayHeight()) { - if (!init->hasDisplayWidth()) { - exception_state.ThrowTypeError( - String::Format("Invalid display size, displayHeight specified " - "without displayWidth.")); - return nullptr; - } - if (!init->hasDisplayHeight()) { - exception_state.ThrowTypeError( - String::Format("Invalid display size, displayWidth specified " - "without displayHeight.")); - return nullptr; - } - - natural_width = init->displayWidth(); - natural_height = init->displayHeight(); - if (natural_width == 0 || natural_width > media::limits::kMaxDimension || - natural_height == 0 || natural_height > media::limits::kMaxDimension) { - exception_state.ThrowTypeError(String::Format( - "Invalid display size (%u, %u).", natural_width, natural_height)); - return nullptr; - } - } - - const gfx::Size natural_size(natural_width, natural_height); - - // Validate planes. - if (media::VideoFrame::NumPlanes(media_fmt) != planes.size()) { - exception_state.ThrowTypeError( - String::Format("Invalid number of planes for format %s; expected %zu, " - "received %u.", - IDLEnumAsString(init->format()).Ascii().c_str(), - media::VideoFrame::NumPlanes(media_fmt), planes.size())); - return nullptr; - } - - for (wtf_size_t i = 0; i < planes.size(); ++i) { - if (!planes[i]->hasData()) { - if (planes[i]->hasSrc()) { - WebCodecsLogger::From(*execution_context).LogPlaneInitSrcDeprecation(); - } else { - // TODO(sandersd): Make |data| an actual required member. - exception_state.ThrowTypeError(String::Format( - "Required member 'data' is missing for plane %u.", i)); - return nullptr; - } - } - } - - for (wtf_size_t i = 0; i < planes.size(); ++i) { - DOMArrayPiece buffer(planes[i]->hasData() ? planes[i]->data() - : planes[i]->src()); - - size_t offset = 0; - if (planes[i]->hasOffset()) - offset = planes[i]->offset(); - - const size_t stride = planes[i]->stride(); - - const gfx::Size plane_size = - media::VideoFrame::PlaneSize(media_fmt, i, coded_size); - const size_t minimum_stride = plane_size.width(); - const size_t rows = plane_size.height(); - if (stride < minimum_stride) { - exception_state.ThrowTypeError(String::Format( - "The stride of plane %u is too small for the given coded size " - "(%u, %u); expected at least %zu, received %zu", - i, coded_width, coded_height, minimum_stride, stride)); - return nullptr; - } - - // Note: This check requires the full stride to be provided for every row, - // including the last. - const auto end = base::CheckedNumeric<size_t>(stride) * rows + offset; - if (!end.IsValid() || end.ValueOrDie() > buffer.ByteLength()) { - exception_state.ThrowTypeError(String::Format( - "Plane %u with %zu rows of stride %zu bytes does not fit at " - "offset %zu in src buffer with length %zu.", - i, rows, stride, offset, buffer.ByteLength())); - return nullptr; - } - } - - // Create a frame. - const auto timestamp = base::TimeDelta::FromMicroseconds(init->timestamp()); - auto& frame_pool = CachedVideoFramePool::From(*execution_context); - auto frame = frame_pool.CreateFrame(media_fmt, coded_size, visible_rect, - natural_size, timestamp); - if (!frame) { - exception_state.ThrowDOMException( - DOMExceptionCode::kOperationError, - String::Format( - "Failed to create a video frame with configuration {format: %s, " - "coded_size: %s, visible_rect: %s, display_size: %s}", - VideoPixelFormatToString(media_fmt).c_str(), - coded_size.ToString().c_str(), visible_rect.ToString().c_str(), - natural_size.ToString().c_str())); - return nullptr; - } - - if (init->hasDuration()) { - frame->metadata().frame_duration = - base::TimeDelta::FromMicroseconds(init->duration()); - } - - // Copy data. - for (wtf_size_t i = 0; i < planes.size(); ++i) { - DOMArrayPiece buffer(planes[i]->hasData() ? planes[i]->data() - : planes[i]->src()); - size_t offset = 0; - if (planes[i]->hasOffset()) - offset = planes[i]->offset(); - const size_t stride = planes[i]->stride(); - - const gfx::Size plane_size = - media::VideoFrame::PlaneSize(media_fmt, i, coded_size); - const size_t minimum_stride = plane_size.width(); - const size_t rows = plane_size.height(); - - uint8_t* src_ptr = reinterpret_cast<uint8_t*>(buffer.Data()) + offset; - uint8_t* dst_ptr = frame->data(i); - for (size_t row = 0; row < rows; ++row) { - memcpy(dst_ptr, src_ptr, minimum_stride); - src_ptr += stride; - dst_ptr += frame->stride(i); - } - } - - return MakeGarbageCollected<VideoFrame>(std::move(frame), - ExecutionContext::From(script_state)); -} - VideoFrame* VideoFrame::Create(ScriptState* script_state, const V8BufferSource* data, const VideoFrameBufferInit* init, @@ -837,26 +604,6 @@ } } -absl::optional<HeapVector<Member<Plane>>> VideoFrame::planes( - ExecutionContext* execution_context) { - WebCodecsLogger::From(*execution_context).LogPlanesDeprecation(); - // Verify that |this| has not been invalidated, and that the format is - // supported. - auto local_frame = handle_->frame(); - if (!local_frame || !IsSupportedPlanarFormat(*local_frame)) - return absl::nullopt; - - // Create a Plane for each VideoFrame plane, but only the first time. - if (planes_.IsEmpty()) { - for (size_t i = 0; i < local_frame->layout().num_planes(); i++) { - // Note: |handle_| may have been invalidated since |local_frame| was read. - planes_.push_back(MakeGarbageCollected<Plane>(handle_, i)); - } - } - - return planes_; -} - uint32_t VideoFrame::codedWidth() const { auto local_frame = handle_->frame(); if (!local_frame) @@ -871,23 +618,6 @@ return local_frame->coded_size().height(); } -VideoFrameRect* VideoFrame::codedRegion( - ExecutionContext* execution_context) const { - WebCodecsLogger::From(*execution_context).LogCodedRegionDeprecation(); - auto local_frame = handle_->frame(); - auto* rect = MakeGarbageCollected<VideoFrameRect>(); - rect->setLeft(0); - rect->setTop(0); - if (local_frame) { - rect->setWidth(local_frame->coded_size().width()); - rect->setHeight(local_frame->coded_size().height()); - } else { - rect->setWidth(0); - rect->setHeight(0); - } - return rect; -} - absl::optional<DOMRectReadOnly*> VideoFrame::codedRect() { auto local_frame = handle_->frame(); if (!local_frame) @@ -901,25 +631,6 @@ return coded_rect_; } -VideoFrameRect* VideoFrame::visibleRegion( - ExecutionContext* execution_context) const { - WebCodecsLogger::From(*execution_context).LogVisibleRegionDeprecation(); - auto local_frame = handle_->frame(); - auto* rect = MakeGarbageCollected<VideoFrameRect>(); - if (local_frame) { - rect->setLeft(local_frame->visible_rect().x()); - rect->setTop(local_frame->visible_rect().y()); - rect->setWidth(local_frame->visible_rect().width()); - rect->setHeight(local_frame->visible_rect().height()); - } else { - rect->setLeft(0); - rect->setTop(0); - rect->setWidth(0); - rect->setHeight(0); - } - return rect; -} - absl::optional<DOMRectReadOnly*> VideoFrame::visibleRect() { auto local_frame = handle_->frame(); if (!local_frame) @@ -934,38 +645,6 @@ return visible_rect_; } -uint32_t VideoFrame::cropLeft(ExecutionContext* execution_context) const { - WebCodecsLogger::From(*execution_context).LogCropDeprecation(); - auto local_frame = handle_->frame(); - if (!local_frame) - return 0; - return local_frame->visible_rect().x(); -} - -uint32_t VideoFrame::cropTop(ExecutionContext* execution_context) const { - WebCodecsLogger::From(*execution_context).LogCropDeprecation(); - auto local_frame = handle_->frame(); - if (!local_frame) - return 0; - return local_frame->visible_rect().y(); -} - -uint32_t VideoFrame::cropWidth(ExecutionContext* execution_context) const { - WebCodecsLogger::From(*execution_context).LogCropDeprecation(); - auto local_frame = handle_->frame(); - if (!local_frame) - return 0; - return local_frame->visible_rect().width(); -} - -uint32_t VideoFrame::cropHeight(ExecutionContext* execution_context) const { - WebCodecsLogger::From(*execution_context).LogCropDeprecation(); - auto local_frame = handle_->frame(); - if (!local_frame) - return 0; - return local_frame->visible_rect().height(); -} - uint32_t VideoFrame::displayWidth() const { auto local_frame = handle_->frame(); if (!local_frame) @@ -1258,7 +937,6 @@ } void VideoFrame::Trace(Visitor* visitor) const { - visitor->Trace(planes_); visitor->Trace(coded_rect_); visitor->Trace(visible_rect_); visitor->Trace(color_space_);
diff --git a/third_party/blink/renderer/modules/webcodecs/video_frame.h b/third_party/blink/renderer/modules/webcodecs/video_frame.h index cf3ebdc..0144320 100644 --- a/third_party/blink/renderer/modules/webcodecs/video_frame.h +++ b/third_party/blink/renderer/modules/webcodecs/video_frame.h
@@ -10,13 +10,11 @@ #include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/blink/renderer/bindings/core/v8/v8_typedefs.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_typedefs.h" -#include "third_party/blink/renderer/bindings/modules/v8/v8_video_frame_rect.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_video_pixel_format.h" #include "third_party/blink/renderer/core/html/canvas/canvas_image_source.h" #include "third_party/blink/renderer/core/imagebitmap/image_bitmap_source.h" #include "third_party/blink/renderer/modules/canvas/canvas2d/canvas_image_source_util.h" #include "third_party/blink/renderer/modules/modules_export.h" -#include "third_party/blink/renderer/modules/webcodecs/plane.h" #include "third_party/blink/renderer/modules/webcodecs/video_frame_handle.h" #include "third_party/blink/renderer/platform/bindings/script_wrappable.h" #include "third_party/blink/renderer/platform/heap/heap_allocator.h" @@ -36,14 +34,12 @@ class DOMRectReadOnly; class ExceptionState; class ExecutionContext; -class PlaneInit; class ScriptPromise; class ScriptState; class VideoColorSpace; class VideoFrameBufferInit; class VideoFrameCopyToOptions; class VideoFrameInit; -class VideoFramePlaneInit; class MODULES_EXPORT VideoFrame final : public ScriptWrappable, public CanvasImageSource, @@ -65,10 +61,6 @@ const VideoFrameInit* init, ExceptionState& exception_state); static VideoFrame* Create(ScriptState*, - const HeapVector<Member<PlaneInit>>&, - const VideoFramePlaneInit*, - ExceptionState&); - static VideoFrame* Create(ScriptState*, const V8BufferSource*, const VideoFrameBufferInit*, ExceptionState&); @@ -78,25 +70,12 @@ absl::optional<int64_t> timestamp() const; absl::optional<uint64_t> duration() const; - // DEPRECATED. - absl::optional<HeapVector<Member<Plane>>> planes(ExecutionContext*); - uint32_t codedWidth() const; uint32_t codedHeight() const; absl::optional<DOMRectReadOnly*> codedRect(); absl::optional<DOMRectReadOnly*> visibleRect(); - // DEPRECATED. - VideoFrameRect* codedRegion(ExecutionContext*) const; - VideoFrameRect* visibleRegion(ExecutionContext*) const; - - // DEPRECATED. - uint32_t cropLeft(ExecutionContext*) const; - uint32_t cropTop(ExecutionContext*) const; - uint32_t cropWidth(ExecutionContext*) const; - uint32_t cropHeight(ExecutionContext*) const; - uint32_t displayWidth() const; uint32_t displayHeight() const; @@ -150,7 +129,6 @@ scoped_refptr<VideoFrameHandle> handle_; // Caches - HeapVector<Member<Plane>> planes_; Member<DOMRectReadOnly> coded_rect_; Member<DOMRectReadOnly> visible_rect_; Member<VideoColorSpace> color_space_;
diff --git a/third_party/blink/renderer/modules/webcodecs/video_frame.idl b/third_party/blink/renderer/modules/webcodecs/video_frame.idl index 59c4853..3290ca54 100644 --- a/third_party/blink/renderer/modules/webcodecs/video_frame.idl +++ b/third_party/blink/renderer/modules/webcodecs/video_frame.idl
@@ -13,10 +13,6 @@ constructor(CanvasImageSource source, optional VideoFrameInit init = {}); [CallWith=ScriptState, RaisesException] - constructor(sequence<PlaneInit> planes, - VideoFramePlaneInit init); - - [CallWith=ScriptState, RaisesException] constructor([AllowShared] BufferSource data, VideoFrameBufferInit init); readonly attribute VideoPixelFormat? format; @@ -60,17 +56,4 @@ [RaisesException] VideoFrame clone(); void close(); - - // DEPRECATED: Use copyTo(). - [CallWith=ExecutionContext] readonly attribute FrozenArray<Plane>? planes; - - // DEPRECATED: Use visibleRect. - [CallWith=ExecutionContext] readonly attribute unsigned long cropLeft; - [CallWith=ExecutionContext] readonly attribute unsigned long cropTop; - [CallWith=ExecutionContext] readonly attribute unsigned long cropWidth; - [CallWith=ExecutionContext] readonly attribute unsigned long cropHeight; - - // DEPRECATED: Use codedRect/visibleRect. - [CallWith=ExecutionContext] readonly attribute VideoFrameRect codedRegion; - [CallWith=ExecutionContext] readonly attribute VideoFrameRect visibleRegion; };
diff --git a/third_party/blink/renderer/modules/webcodecs/video_frame_plane_init.idl b/third_party/blink/renderer/modules/webcodecs/video_frame_plane_init.idl deleted file mode 100644 index f4c7806..0000000 --- a/third_party/blink/renderer/modules/webcodecs/video_frame_plane_init.idl +++ /dev/null
@@ -1,29 +0,0 @@ -// Copyright 2020 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// https://github.com/WICG/web-codecs - -dictionary VideoFramePlaneInit { - required VideoPixelFormat format; - - required [EnforceRange] long long timestamp; // microseconds - [EnforceRange] unsigned long long duration; // microseconds - - required [EnforceRange] unsigned long codedWidth; - required [EnforceRange] unsigned long codedHeight; - - DOMRectInit visibleRect; - - [EnforceRange] unsigned long displayWidth; - [EnforceRange] unsigned long displayHeight; - - // DEPRECATED: Use visibleRect. - [EnforceRange] unsigned long cropLeft; - [EnforceRange] unsigned long cropTop; - [EnforceRange] unsigned long cropWidth; - [EnforceRange] unsigned long cropHeight; - - // DEPRECATED: Use visibleRect. - VideoFrameRect visibleRegion; -};
diff --git a/third_party/blink/renderer/modules/webcodecs/video_frame_rect.idl b/third_party/blink/renderer/modules/webcodecs/video_frame_rect.idl deleted file mode 100644 index d2ad4fe..0000000 --- a/third_party/blink/renderer/modules/webcodecs/video_frame_rect.idl +++ /dev/null
@@ -1,14 +0,0 @@ -// Copyright 2021 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// https://github.com/WICG/web-codecs - -// Specifies a rectangular region of a VideoFrame. Valid rects have positive -// area and are contained within the frame's coded size. -dictionary VideoFrameRect { - required [EnforceRange] unsigned long left; - required [EnforceRange] unsigned long top; - required [EnforceRange] unsigned long width; - required [EnforceRange] unsigned long height; -};
diff --git a/third_party/blink/renderer/modules/webcodecs/webcodecs_logger.cc b/third_party/blink/renderer/modules/webcodecs/webcodecs_logger.cc index 52241d0..e70ad64 100644 --- a/third_party/blink/renderer/modules/webcodecs/webcodecs_logger.cc +++ b/third_party/blink/renderer/modules/webcodecs/webcodecs_logger.cc
@@ -56,42 +56,6 @@ return close_auditor_; } -void WebCodecsLogger::LogCropDeprecation() { - LogDeprecation( - Deprecation::kCrop, - "cropTop, cropLeft, cropWidth, and cropHeight are deprecated; please " - "use visibleRect."); -} - -void WebCodecsLogger::LogPlaneInitSrcDeprecation() { - LogDeprecation(Deprecation::kPlaneInitSrc, - "PlaneInit.src is deprecated, please use PlaneInit.data."); -} - -void WebCodecsLogger::LogPlanesDeprecation() { - LogDeprecation(Deprecation::kPlaneInitSrc, - "VideoFrame.planes is deprecated, please use " - "VideoFrame.copyTo()."); -} - -void WebCodecsLogger::LogCodedRegionDeprecation() { - LogDeprecation( - Deprecation::kCodedRegion, - "VideoFrame.codedRegion is deprecated; please use VideoFrame.codedRect."); -} - -void WebCodecsLogger::LogVisibleRegionDeprecation() { - LogDeprecation(Deprecation::kVisibleRegion, - "visibleRegion is deprecated; please use visibleRect."); -} - -void WebCodecsLogger::LogPlanarConstructionDeprecation() { - LogDeprecation(Deprecation::kPlanarConstruction, - "new VideoFrame(sequence<PlaneInit>, VideoFramePlaneInit) is " - "deprecated; please use new VideoFrame(BufferSource, " - "VideoFrameBufferInit)."); -} - void WebCodecsLogger::LogCloseErrors(TimerBase*) { // If it's been a while since this class was used and there are not other // references to |leak_status_|, stop the timer. @@ -116,16 +80,6 @@ close_auditor_->Clear(); } -void WebCodecsLogger::LogDeprecation(Deprecation id, const String& message) { - uint32_t id_bits = static_cast<uint32_t>(id); - if (logged_deprecations_ & id_bits) - return; - logged_deprecations_ |= id_bits; - GetSupplementable()->AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>( - mojom::blink::ConsoleMessageSource::kDeprecation, - mojom::blink::ConsoleMessageLevel::kWarning, message)); -} - void WebCodecsLogger::Trace(Visitor* visitor) const { visitor->Trace(timer_); Supplement<ExecutionContext>::Trace(visitor);
diff --git a/third_party/blink/renderer/modules/webcodecs/webcodecs_logger.h b/third_party/blink/renderer/modules/webcodecs/webcodecs_logger.h index be889700..8d5eb5d 100644 --- a/third_party/blink/renderer/modules/webcodecs/webcodecs_logger.h +++ b/third_party/blink/renderer/modules/webcodecs/webcodecs_logger.h
@@ -62,33 +62,14 @@ // Returns |close_auditor_| and starts |timer_| if needed. scoped_refptr<VideoFrameCloseAuditor> GetCloseAuditor(); - void LogCropDeprecation(); - void LogPlaneInitSrcDeprecation(); - void LogPlanesDeprecation(); - void LogCodedRegionDeprecation(); - void LogVisibleRegionDeprecation(); - void LogPlanarConstructionDeprecation(); - void Trace(Visitor*) const override; private: - enum class Deprecation : uint32_t { - kCrop = 1, - kPlaneInitSrc = 2, - kPlanes = 4, - kCodedRegion = 8, - kVisibleRegion = 16, - kPlanarConstruction = 32, - }; - void LogCloseErrors(TimerBase*); - void LogDeprecation(Deprecation, const String& message); base::TimeTicks last_auditor_access_; scoped_refptr<VideoFrameCloseAuditor> close_auditor_; HeapTaskRunnerTimer<WebCodecsLogger> timer_; - - uint32_t logged_deprecations_ = 0; }; } // namespace blink
diff --git a/third_party/blink/renderer/platform/media/web_media_player_impl_unittest.cc b/third_party/blink/renderer/platform/media/web_media_player_impl_unittest.cc index a6312fe..2944ac2 100644 --- a/third_party/blink/renderer/platform/media/web_media_player_impl_unittest.cc +++ b/third_party/blink/renderer/platform/media/web_media_player_impl_unittest.cc
@@ -327,6 +327,7 @@ web_view_(WebView::Create( /*client=*/nullptr, /*is_hidden=*/false, + /*is_prerendering=*/false, /*is_inside_portal=*/false, /*compositing_enabled=*/false, /*widgets_never_composited=*/false,
diff --git a/third_party/blink/renderer/platform/peerconnection/rtc_video_encoder.cc b/third_party/blink/renderer/platform/peerconnection/rtc_video_encoder.cc index b82a567b..d574bb51 100644 --- a/third_party/blink/renderer/platform/peerconnection/rtc_video_encoder.cc +++ b/third_party/blink/renderer/platform/peerconnection/rtc_video_encoder.cc
@@ -578,9 +578,17 @@ DETACH_FROM_SEQUENCE(sequence_checker_); // The default values of EncoderInfo. + // TODO(crbug.com/1228804): These settings should be set at the time + // RTCVideoEncoder is constructed instead of done here. encoder_info_.scaling_settings = webrtc::VideoEncoder::ScalingSettings::kOff; +#if defined(OS_ANDROID) + // MediaCodec requires 16x16 alignment, see https://crbug.com/1084702. + encoder_info_.requested_resolution_alignment = 16; + encoder_info_.apply_alignment_to_all_simulcast_layers = true; +#else encoder_info_.requested_resolution_alignment = 1; encoder_info_.apply_alignment_to_all_simulcast_layers = false; +#endif encoder_info_.supports_native_handle = true; encoder_info_.implementation_name = "ExternalEncoder"; encoder_info_.has_trusted_rate_controller = true; @@ -1567,9 +1575,16 @@ webrtc::VideoEncoder::EncoderInfo RTCVideoEncoder::GetEncoderInfo() const { webrtc::VideoEncoder::EncoderInfo info; +#if defined(OS_ANDROID) + // MediaCodec requires 16x16 alignment, see https://crbug.com/1084702. We + // normally override this in |impl_|, but sometimes this method is called + // before |impl_| is created, so we need to override it here too. + info.requested_resolution_alignment = 16; + info.apply_alignment_to_all_simulcast_layers = true; +#endif + if (impl_) info = impl_->GetEncoderInfo(); - return info; }
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5 index f31e0df..bc5dcde 100644 --- a/third_party/blink/renderer/platform/runtime_enabled_features.json5 +++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -2300,6 +2300,7 @@ name: "WebAppWindowControlsOverlay", origin_trial_feature_name: "WebAppWindowControlsOverlay", origin_trial_os: ["win", "mac", "linux"], + status: "experimental", }, { name: "WebAssemblyCSP",
diff --git a/third_party/blink/web_tests/FlagExpectations/disable-layout-ng b/third_party/blink/web_tests/FlagExpectations/disable-layout-ng index a4d6e36..a4702154 100644 --- a/third_party/blink/web_tests/FlagExpectations/disable-layout-ng +++ b/third_party/blink/web_tests/FlagExpectations/disable-layout-ng
@@ -273,7 +273,7 @@ crbug.com/1157740 external/wpt/css/css-sizing/aspect-ratio/flex-aspect-ratio-004.html [ Pass ] crbug.com/1157740 external/wpt/css/css-sizing/aspect-ratio/flex-aspect-ratio-024.html [ Failure ] crbug.com/1157740 external/wpt/css/css-sizing/aspect-ratio/flex-aspect-ratio-025.html [ Pass ] -crbug.com/1203090 external/wpt/css/css-sizing/aspect-ratio/grid-aspect-ratio-018.html [ Pass ] +crbug.com/1203090 external/wpt/css/css-sizing/aspect-ratio/grid-aspect-ratio-018.html [ Failure Pass ] crbug.com/1203090 external/wpt/css/css-sizing/aspect-ratio/grid-aspect-ratio-019.html [ Pass ] crbug.com/591099 external/wpt/css/css-sizing/clone-nowrap-intrinsic-size-bidi.html [ Failure ] crbug.com/591099 external/wpt/css/css-sizing/intrinsic-percent-non-replaced-004.html [ Failure ] @@ -1254,3 +1254,7 @@ # unblock wpt-importer crbug.com/591099 external/wpt/css/css-lists/list-style-type-decimal-vertical-lr.html [ Failure ] crbug.com/591099 external/wpt/css/css-lists/list-style-type-decimal-vertical-rl.html [ Failure ] + +# unblock wpt-importer +crbug.com/591099 external/wpt/css/css-lists/list-style-image-gradients.html [ Failure ] +crbug.com/591099 external/wpt/editing/other/insert-text-in-void-element.tentative.html [ Failure ]
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index e6a3edb..c93abe28 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -3098,6 +3098,7 @@ crbug.com/626703 external/wpt/css/css-ruby/ruby-intrinsic-isize-003.html [ Failure ] crbug.com/626703 [ Mac10.13 ] external/wpt/selection/contenteditable/modifying-selection-with-primary-mouse-button.tentative.html [ Crash Failure ] crbug.com/626703 [ Mac10.15 ] external/wpt/streams/readable-streams/tee.any.html [ Crash Failure ] +crbug.com/626703 [ Mac10.15 ] external/wpt/streams/readable-streams/tee.any.worker.html [ Failure ] crbug.com/626703 [ Mac10.15 ] external/wpt/url/url-origin.any.worker.html [ Crash Failure ] crbug.com/1191547 external/wpt/html/semantics/forms/the-label-element/proxy-modifier-click-to-associated-element.tentative.html [ Timeout ] crbug.com/626703 external/wpt/websockets/cookies/001.html?wss&wpt_flags=https [ Failure ] @@ -4719,262 +4720,262 @@ crbug.com/831796 fast/events/autoscroll-in-textfield.html [ Failure Pass ] # DevTools underscore migration -crbug.com/1207342 http/tests/devtools/sources/debugger/debugger-scripts.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger/worker-debugging.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger/debugger-minified-variables-evalution.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger/async-callstack-network-initiator.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger/pause-in-removed-frame.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger/debugger-suspend-active-dom-objects.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger/debugger-disable-enable.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger/debugger-scope-resolve-this.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger/skip-pause-during-navigation.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger/mutation-observer-suspend-while-paused.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger/debugger-reload-on-pause.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger/debugger-scripts-reload.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger/source-frame-breakpoint-decorations.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger/debugger-scope-minified-variables.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger/debugger-autocontinue-on-syntax-error.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger/dynamic-script-tag.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger/live-edit.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger/debugger-compile-and-run.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger/debugger-completions-on-call-frame.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger/debugger-prototype-property.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger/worker-debugging-script-mapping.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger/debugger-es6-harmony-scopes.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger/script-failed-to-parse.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger/live-edit-original-content.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger/sources-panel-content-scripts.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger/source-map-http-header.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger/debugger-scope-resolve-identifiers.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger/debugger-return-value.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger/async-callstack-fetch.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger/rethrow-error-from-bindings-crash.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger/script-collected.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger/source-frame-inline-breakpoint-decorations.js [ Pass Failure Timeout ] -crbug.com/1207342 http/tests/devtools/sources/debugger/dynamic-scripts.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger/debugger-cyclic-reference.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/dont-diverge-script-evaluated-twice.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-ui/reveal-not-skipped.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-ui/script-snippet-model.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-ui/script-formatter-breakpoints-2.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-ui/call-stack-show-more.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-ui/debugger-save-to-temp-var.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-ui/async-call-stack-async-function.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-ui/monitor-console-command.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-ui/break-on-set-timeout-with-syntax-error.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-ui/watch-expressions-panel-switch.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-ui/source-url-comment.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-ui/source-frame.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-ui/async-call-stack-url.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-ui/script-formatter-search.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-ui/function-generator-details.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-ui/popover-for-spread-operator.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-ui/debugger-expand-scope.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-ui/script-formatter-breakpoints-3.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-ui/scripts-sorting.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-ui/switch-file.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-ui/watch-expressions-preserve-expansion.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-ui/copy-stack-trace.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-ui/custom-element-lifecycle-events.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-ui/scripts-panel.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-ui/break-on-empty-event-listener.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-ui/callstack-placards-discarded.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-ui/selected-call-frame-after-formatting-source.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-ui/async-call-stack-worker.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-ui/function-details.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-ui/last-execution-context.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-breakpoints/breakpoint-with-sourcemap.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-breakpoints/no-pause-on-disabled-breakpoint.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-breakpoints/inline-breakpoint-with-sourcemap.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-breakpoints/debugger-disable-add-breakpoint.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-breakpoints/breakpoint-one-target-with-source-map.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-breakpoints/dom-breakpoints-reload.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-breakpoints/event-listener-breakpoints-script-first-stmt.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-breakpoints/xhr-breakpoints.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-breakpoints/provisional-breakpoints.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-breakpoints/set-logpoint.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-breakpoints/set-breakpoint-while-blocking-main-thread.js [ Pass Failure Timeout ] -crbug.com/1207342 http/tests/devtools/sources/debugger-breakpoints/breakpoint-manager-listeners-count.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-breakpoints/event-listener-breakpoints-xhr.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-breakpoints/event-listener-breakpoints.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-breakpoints/breakpoints-in-anonymous-script-with-two-targets.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-breakpoints/nodejs-set-breakpoint.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-breakpoints/event-listener-breakpoints-after-suspension.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-breakpoints/event-listener-breakpoints-webaudio.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-breakpoints/debugger-reload-breakpoints-with-source-maps.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-breakpoints/debugger-breakpoints-not-activated-on-reload.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-breakpoints/set-conditional-breakpoint.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-breakpoints/picture-in-picture-event-listener-breakpoints.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-breakpoints/possible-breakpoints.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-breakpoints/debugger-set-breakpoint-regex.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-async/async-callstack-post-message.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-async/async-callstack-web-sql.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-async/async-callstack-reload-no-crash.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-async/async-await/async-callstack-async-await1.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-async/async-await/async-callstack-async-await2.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-async/async-await/async-callstack-async-await3.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-async/async-await/async-pause-on-exception.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-async/async-callstack-mutation-observer.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-async/async-callstack-scripted-scroll.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-async/async-callstack-xhrs.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-async/async-callstack-get-as-string.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-async/async-callstack-in-console.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-async/async-callstack-promises.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-async/async-callstack-middle-run.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-async/async-callstack.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-async/async-callstack-indexed-db.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-async/async-callstack-set-interval.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-async/async-callstack-events.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/inline-script-with-source-map.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-step/debugger-step-into-event-listener.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-step/debugger-step-out-across-timeouts.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-step/debugger-step-through-promises.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-step/debugger-step-over-document-write.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-step/debugger-step-out.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-step/debugger-step-over-inlined-scripts.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-step/debugger-step-out-custom-element-callbacks.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-step/debugger-step-in.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-step/debugger-step-out-event-listener.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-step/debugger-step-into-inlined-scripts.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-step/debugger-step-over-across-timeouts.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-step/debugger-step-in-ignore-injected-script.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-step/debugger-step-into-custom-element-callbacks.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-step/step-through-event-listeners.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-step/debugger-step-into-document-write.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-step/debugger-step-over.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-step/debugger-step-into-across-timeouts.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-console/step-into-async-fetch.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-console/debug-console-command.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/sources-panel-extension-names.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-pause/debugger-pause-on-debugger-statement.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-pause/debugger-pause-on-failed-assertion.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-pause/debugger-pause-on-exception.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-pause/debugger-eval-while-paused-throws.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-pause/debugger-mute-exception.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-pause/debugger-change-variable.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-pause/debugger-resume-button-in-overlay.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-pause/pause-on-elements-panel.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-pause/set-return-value.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-pause/skip-pauses-until-reload.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-pause/function-name-in-callstack.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-pause/debugger-pause-on-promise-rejection.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-pause/debugger-eval-while-paused.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-pause/pause-in-internal-script.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-pause/eval-on-pause-blocked.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-pause/debugger-eval-on-call-frame-inside-iframe.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-pause/debugger-no-nested-pause.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-pause/pause-in-inline-script.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-pause/debugger-pause-in-internal.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-pause/debugger-pause-in-eval-script.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-pause/debugger-pause-with-overrides.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-pause/debugger-eval-on-call-frame.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/event-listener-breakpoints-script-fst-stmt-for-module.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-frameworks/frameworks-jquery.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-frameworks/frameworks-ignore-list-by-source-code.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-frameworks/frameworks-with-worker.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-frameworks/frameworks-dom-xhr-event-breakpoints.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-frameworks/frameworks-skip-step-in.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-frameworks/frameworks-with-async-callstack.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-frameworks/frameworks-skip-exceptions.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-frameworks/frameworks-steppings.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-frameworks/frameworks-skip-break-program.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/sources/debugger-frameworks/frameworks-step-into-skips-setTimeout.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/console/console-api-on-call-frame.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/console/worker-eval-contains-stack.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/console/nested-worker-eval-contains-stack.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/console/console-error-on-call-frame.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/indexeddb/live-update-indexeddb-content.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/compiler-source-mapping-debug.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/network/parse-form-data.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/network/network-choose-preview-view.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/network/network-update-calculator-for-all-requests.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/network/network-filter-updated-requests.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/network/request-name-path.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/network/json-preview.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/network/from-disk-cache-timing.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/service-workers/service-worker-pause.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/a11y-axe-core/sources/threads-a11y-test.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/a11y-axe-core/sources/scope-pane-a11y-test.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/cache-storage/cache-entry-deletion.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/cache-storage/cache-names.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/cache-storage/cache-deletion.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/cache-storage/cache-data.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/cache-storage/cache-live-update-list.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/cache-storage/cache-live-update-cache-content.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/cache-storage/cache-track-valid-origin.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/oopif/oopif-elements-nesting-error-page.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/oopif/oopif-elements-nesting.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/oopif/oopif-elements-navigate-out.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/tracing/timeline-network/timeline-network-resource-navigation.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/tracing/timeline-network/timeline-network-resource-navigation-sgx.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/tracing/user-timing.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/runtime/evaluate-without-side-effects.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/runtime/evaluate-timeout.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/resource-har-conversion.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/debugger/fetch-breakpoints.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/bindings/ignore-listed-sourcemap-detach.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/domdebugger/domdebugger-getEventListeners.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/modify-cross-domain-rule.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/search/search-in-script.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/resource-har-headers.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/profiler/cpu-profiler-calculate-time.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/resource-tree/resource-request-content-while-loading.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/resource-tree/resource-tree-events.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/resource-tree/resource-tree-crafted-frame-add.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/persistence/persistence-do-not-overwrite-css.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/elements/styles-4/styles-rerequest-sourcemap-on-watchdog.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/elements/styles-1/css-live-edit.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/elements/styles-2/nested-pseudo-elements.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/elements/iframe-load-event.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/elements/event-listener-sidebar-jquery2.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/elements/elements-js-path.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/elements/elements-hide-html-comments.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/elements/elements-panel-limited-children.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/elements/event-listener-sidebar-jquery1.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/elements/elements-css-path.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/elements/insert-node.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/elements/attribute-modified-ns.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/elements/expand-recursively.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/elements/user-properties.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/elements/elements-panel-correct-case.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/elements/inspect-limited-children.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/elements/elements-iframe-base-url.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/elements/event-listener-sidebar-remove.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/elements/styles/original-content-provider.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/elements/styles/xsl-transformed.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/elements/modify-chardata.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/elements/elements-panel-structure.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/elements/event-listeners-about-blank.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/elements/event-listener-sidebar.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/elements/shadow/shadow-host-display-modes.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/elements/shadow/create-shadow-root.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/elements/shadow/update-shadowdom.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/elements/shadow/shadow-distribution.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/elements/shadow/shadow-root.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/elements/move-node.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/elements/elements-child-node-count-mismatch.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/elements/edit/edit-dom-actions-4.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/elements/edit/set-attribute.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/elements/edit/remove-node.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/elements/edit/undo-dom-edits.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/elements/edit/edit-dom-actions-1.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/elements/edit/edit-dom-actions-3.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/elements/edit/edit-dom-actions-shadow-1.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/elements/edit/shadow-dom-modify-chardata.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/elements/edit/delete-from-document.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/elements/edit/undo-dom-edits-2.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/elements/edit/edit-dom-actions-shadow-2.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/elements/edit/perform-undo-undo.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/elements/edit/edit-dom-actions-2.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/elements/edit/insert-node-collapsed.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/elements/bidi-dom-tree.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/elements/elements-panel-rewrite-href.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/elements/event-listeners-framework-with-service-worker.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/elements/node-xpath.js [ Pass Failure ] -crbug.com/1207342 http/tests/inspector-protocol/cpu-profiler/record-cpu-profile-with-cpu-throttling.js [ Pass Failure ] -crbug.com/1207342 http/tests/inspector-protocol/page/frameScheduledNavigation.js [ Pass Failure ] -crbug.com/1207342 http/tests/devtools/persistence/persistence-external-change-breakpoints.js [ Pass Failure ] -crbug.com/1207342 crbug.com/1135652 http/tests/devtools/sources/debugger-pause/debugger-pause-infinite-loop.js [ Pass Failure Timeout ] +crbug.com/1207342 http/tests/devtools/sources/debugger/debugger-scripts.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger/worker-debugging.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger/debugger-minified-variables-evalution.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger/async-callstack-network-initiator.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger/pause-in-removed-frame.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger/debugger-suspend-active-dom-objects.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger/debugger-disable-enable.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger/debugger-scope-resolve-this.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger/skip-pause-during-navigation.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger/mutation-observer-suspend-while-paused.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger/debugger-reload-on-pause.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger/debugger-scripts-reload.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger/source-frame-breakpoint-decorations.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger/debugger-scope-minified-variables.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger/debugger-autocontinue-on-syntax-error.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger/dynamic-script-tag.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger/live-edit.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger/debugger-compile-and-run.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger/debugger-completions-on-call-frame.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger/debugger-prototype-property.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger/worker-debugging-script-mapping.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger/debugger-es6-harmony-scopes.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger/script-failed-to-parse.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger/live-edit-original-content.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger/sources-panel-content-scripts.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger/source-map-http-header.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger/debugger-scope-resolve-identifiers.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger/debugger-return-value.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger/async-callstack-fetch.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger/rethrow-error-from-bindings-crash.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger/script-collected.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger/source-frame-inline-breakpoint-decorations.js [ Failure Pass Timeout ] +crbug.com/1207342 http/tests/devtools/sources/debugger/dynamic-scripts.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger/debugger-cyclic-reference.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/dont-diverge-script-evaluated-twice.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-ui/reveal-not-skipped.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-ui/script-snippet-model.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-ui/script-formatter-breakpoints-2.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-ui/call-stack-show-more.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-ui/debugger-save-to-temp-var.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-ui/async-call-stack-async-function.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-ui/monitor-console-command.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-ui/break-on-set-timeout-with-syntax-error.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-ui/watch-expressions-panel-switch.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-ui/source-url-comment.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-ui/source-frame.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-ui/async-call-stack-url.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-ui/script-formatter-search.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-ui/function-generator-details.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-ui/popover-for-spread-operator.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-ui/debugger-expand-scope.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-ui/script-formatter-breakpoints-3.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-ui/scripts-sorting.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-ui/switch-file.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-ui/watch-expressions-preserve-expansion.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-ui/copy-stack-trace.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-ui/custom-element-lifecycle-events.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-ui/scripts-panel.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-ui/break-on-empty-event-listener.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-ui/callstack-placards-discarded.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-ui/selected-call-frame-after-formatting-source.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-ui/async-call-stack-worker.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-ui/function-details.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-ui/last-execution-context.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-breakpoints/breakpoint-with-sourcemap.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-breakpoints/no-pause-on-disabled-breakpoint.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-breakpoints/inline-breakpoint-with-sourcemap.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-breakpoints/debugger-disable-add-breakpoint.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-breakpoints/breakpoint-one-target-with-source-map.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-breakpoints/dom-breakpoints-reload.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-breakpoints/event-listener-breakpoints-script-first-stmt.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-breakpoints/xhr-breakpoints.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-breakpoints/provisional-breakpoints.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-breakpoints/set-logpoint.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-breakpoints/set-breakpoint-while-blocking-main-thread.js [ Failure Pass Timeout ] +crbug.com/1207342 http/tests/devtools/sources/debugger-breakpoints/breakpoint-manager-listeners-count.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-breakpoints/event-listener-breakpoints-xhr.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-breakpoints/event-listener-breakpoints.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-breakpoints/breakpoints-in-anonymous-script-with-two-targets.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-breakpoints/nodejs-set-breakpoint.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-breakpoints/event-listener-breakpoints-after-suspension.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-breakpoints/event-listener-breakpoints-webaudio.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-breakpoints/debugger-reload-breakpoints-with-source-maps.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-breakpoints/debugger-breakpoints-not-activated-on-reload.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-breakpoints/set-conditional-breakpoint.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-breakpoints/picture-in-picture-event-listener-breakpoints.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-breakpoints/possible-breakpoints.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-breakpoints/debugger-set-breakpoint-regex.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-async/async-callstack-post-message.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-async/async-callstack-web-sql.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-async/async-callstack-reload-no-crash.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-async/async-await/async-callstack-async-await1.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-async/async-await/async-callstack-async-await2.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-async/async-await/async-callstack-async-await3.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-async/async-await/async-pause-on-exception.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-async/async-callstack-mutation-observer.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-async/async-callstack-scripted-scroll.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-async/async-callstack-xhrs.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-async/async-callstack-get-as-string.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-async/async-callstack-in-console.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-async/async-callstack-promises.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-async/async-callstack-middle-run.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-async/async-callstack.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-async/async-callstack-indexed-db.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-async/async-callstack-set-interval.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-async/async-callstack-events.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/inline-script-with-source-map.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-step/debugger-step-into-event-listener.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-step/debugger-step-out-across-timeouts.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-step/debugger-step-through-promises.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-step/debugger-step-over-document-write.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-step/debugger-step-out.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-step/debugger-step-over-inlined-scripts.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-step/debugger-step-out-custom-element-callbacks.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-step/debugger-step-in.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-step/debugger-step-out-event-listener.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-step/debugger-step-into-inlined-scripts.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-step/debugger-step-over-across-timeouts.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-step/debugger-step-in-ignore-injected-script.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-step/debugger-step-into-custom-element-callbacks.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-step/step-through-event-listeners.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-step/debugger-step-into-document-write.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-step/debugger-step-over.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-step/debugger-step-into-across-timeouts.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-console/step-into-async-fetch.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-console/debug-console-command.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/sources-panel-extension-names.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-pause/debugger-pause-on-debugger-statement.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-pause/debugger-pause-on-failed-assertion.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-pause/debugger-pause-on-exception.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-pause/debugger-eval-while-paused-throws.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-pause/debugger-mute-exception.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-pause/debugger-change-variable.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-pause/debugger-resume-button-in-overlay.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-pause/pause-on-elements-panel.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-pause/set-return-value.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-pause/skip-pauses-until-reload.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-pause/function-name-in-callstack.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-pause/debugger-pause-on-promise-rejection.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-pause/debugger-eval-while-paused.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-pause/pause-in-internal-script.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-pause/eval-on-pause-blocked.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-pause/debugger-eval-on-call-frame-inside-iframe.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-pause/debugger-no-nested-pause.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-pause/pause-in-inline-script.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-pause/debugger-pause-in-internal.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-pause/debugger-pause-in-eval-script.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-pause/debugger-pause-with-overrides.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-pause/debugger-eval-on-call-frame.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/event-listener-breakpoints-script-fst-stmt-for-module.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-frameworks/frameworks-jquery.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-frameworks/frameworks-ignore-list-by-source-code.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-frameworks/frameworks-with-worker.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-frameworks/frameworks-dom-xhr-event-breakpoints.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-frameworks/frameworks-skip-step-in.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-frameworks/frameworks-with-async-callstack.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-frameworks/frameworks-skip-exceptions.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-frameworks/frameworks-steppings.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-frameworks/frameworks-skip-break-program.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/sources/debugger-frameworks/frameworks-step-into-skips-setTimeout.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/console/console-api-on-call-frame.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/console/worker-eval-contains-stack.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/console/nested-worker-eval-contains-stack.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/console/console-error-on-call-frame.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/indexeddb/live-update-indexeddb-content.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/compiler-source-mapping-debug.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/network/parse-form-data.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/network/network-choose-preview-view.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/network/network-update-calculator-for-all-requests.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/network/network-filter-updated-requests.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/network/request-name-path.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/network/json-preview.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/network/from-disk-cache-timing.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/service-workers/service-worker-pause.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/a11y-axe-core/sources/threads-a11y-test.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/a11y-axe-core/sources/scope-pane-a11y-test.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/cache-storage/cache-entry-deletion.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/cache-storage/cache-names.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/cache-storage/cache-deletion.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/cache-storage/cache-data.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/cache-storage/cache-live-update-list.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/cache-storage/cache-live-update-cache-content.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/cache-storage/cache-track-valid-origin.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/oopif/oopif-elements-nesting-error-page.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/oopif/oopif-elements-nesting.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/oopif/oopif-elements-navigate-out.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/tracing/timeline-network/timeline-network-resource-navigation.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/tracing/timeline-network/timeline-network-resource-navigation-sgx.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/tracing/user-timing.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/runtime/evaluate-without-side-effects.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/runtime/evaluate-timeout.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/resource-har-conversion.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/debugger/fetch-breakpoints.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/bindings/ignore-listed-sourcemap-detach.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/domdebugger/domdebugger-getEventListeners.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/modify-cross-domain-rule.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/search/search-in-script.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/resource-har-headers.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/profiler/cpu-profiler-calculate-time.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/resource-tree/resource-request-content-while-loading.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/resource-tree/resource-tree-events.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/resource-tree/resource-tree-crafted-frame-add.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/persistence/persistence-do-not-overwrite-css.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/elements/styles-4/styles-rerequest-sourcemap-on-watchdog.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/elements/styles-1/css-live-edit.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/elements/styles-2/nested-pseudo-elements.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/elements/iframe-load-event.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/elements/event-listener-sidebar-jquery2.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/elements/elements-js-path.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/elements/elements-hide-html-comments.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/elements/elements-panel-limited-children.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/elements/event-listener-sidebar-jquery1.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/elements/elements-css-path.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/elements/insert-node.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/elements/attribute-modified-ns.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/elements/expand-recursively.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/elements/user-properties.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/elements/elements-panel-correct-case.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/elements/inspect-limited-children.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/elements/elements-iframe-base-url.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/elements/event-listener-sidebar-remove.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/elements/styles/original-content-provider.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/elements/styles/xsl-transformed.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/elements/modify-chardata.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/elements/elements-panel-structure.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/elements/event-listeners-about-blank.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/elements/event-listener-sidebar.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/elements/shadow/shadow-host-display-modes.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/elements/shadow/create-shadow-root.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/elements/shadow/update-shadowdom.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/elements/shadow/shadow-distribution.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/elements/shadow/shadow-root.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/elements/move-node.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/elements/elements-child-node-count-mismatch.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/elements/edit/edit-dom-actions-4.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/elements/edit/set-attribute.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/elements/edit/remove-node.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/elements/edit/undo-dom-edits.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/elements/edit/edit-dom-actions-1.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/elements/edit/edit-dom-actions-3.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/elements/edit/edit-dom-actions-shadow-1.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/elements/edit/shadow-dom-modify-chardata.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/elements/edit/delete-from-document.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/elements/edit/undo-dom-edits-2.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/elements/edit/edit-dom-actions-shadow-2.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/elements/edit/perform-undo-undo.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/elements/edit/edit-dom-actions-2.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/elements/edit/insert-node-collapsed.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/elements/bidi-dom-tree.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/elements/elements-panel-rewrite-href.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/elements/event-listeners-framework-with-service-worker.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/elements/node-xpath.js [ Failure Pass ] +crbug.com/1207342 http/tests/inspector-protocol/cpu-profiler/record-cpu-profile-with-cpu-throttling.js [ Failure Pass ] +crbug.com/1207342 http/tests/inspector-protocol/page/frameScheduledNavigation.js [ Failure Pass ] +crbug.com/1207342 http/tests/devtools/persistence/persistence-external-change-breakpoints.js [ Failure Pass ] +crbug.com/1207342 crbug.com/1135652 http/tests/devtools/sources/debugger-pause/debugger-pause-infinite-loop.js [ Failure Pass Timeout ] # Sheriff 2018-04-13 crbug.com/833655 [ Linux ] media/controls/closed-captions-dynamic-update.html [ Skip ] @@ -7222,12 +7223,12 @@ crbug.com/1222097 virtual/synchronous_html_parser/external/wpt/html/semantics/embedded-content/media-elements/track/track-element/track-cues-sorted-before-dispatch.html [ Failure Pass ] # Temporarily disable to unblock a WebRTC roll -crbug.com/webrtc/8199 [ Win ] external/wpt/webrtc-stats/supported-stats.html [ Pass Failure ] -crbug.com/webrtc/8199 [ Linux ] external/wpt/webrtc-stats/supported-stats.html [ Pass Failure ] -crbug.com/webrtc/8199 [ Mac10.15 ] external/wpt/webrtc-stats/supported-stats.html [ Pass Failure ] -crbug.com/webrtc/8199 [ Mac10.14 ] external/wpt/webrtc-stats/supported-stats.html [ Pass Failure ] -crbug.com/webrtc/8199 [ Mac10.13 ] external/wpt/webrtc-stats/supported-stats.html [ Pass Failure ] -crbug.com/webrtc/8199 [ Mac10.12 ] external/wpt/webrtc-stats/supported-stats.html [ Pass Failure ] +crbug.com/webrtc/8199 [ Win ] external/wpt/webrtc-stats/supported-stats.html [ Failure Pass ] +crbug.com/webrtc/8199 [ Linux ] external/wpt/webrtc-stats/supported-stats.html [ Failure Pass ] +crbug.com/webrtc/8199 [ Mac10.15 ] external/wpt/webrtc-stats/supported-stats.html [ Failure Pass ] +crbug.com/webrtc/8199 [ Mac10.14 ] external/wpt/webrtc-stats/supported-stats.html [ Failure Pass ] +crbug.com/webrtc/8199 [ Mac10.13 ] external/wpt/webrtc-stats/supported-stats.html [ Failure Pass ] +crbug.com/webrtc/8199 [ Mac10.12 ] external/wpt/webrtc-stats/supported-stats.html [ Failure Pass ] # Sheriff crbug.com/1223276 external/wpt/layout-instability/input-timestamp.html [ Skip ] @@ -7297,30 +7298,33 @@ # Sheriff 2021-07-13 crbug.com/1220114 [ Linux ] external/wpt/webrtc-encoded-transform/RTCPeerConnection-insertable-streams-simulcast.https.html [ Failure Pass ] +crbug.com/1228788 [ Linux ] external/wpt/webrtc-encoded-transform/RTCPeerConnection-insertable-streams-audio.https.html [ Failure Pass ] +crbug.com/1228772 [ Linux ] external/wpt/webrtc/simulcast/h264.https.html [ Crash Pass Failure ] +crbug.com/1228772 [ Linux ] virtual/webrtc-wpt-plan-b/external/wpt/webrtc/RTCPeerConnection-mandatory-getStats.https.html [ Failure Pass ] # PlzServiceWorker failing tests crbug.com/996511 virtual/plz-service-worker/http/tests/inspector-protocol/service-worker/service-worker-fetch-async-stacks.js [ Timeout ] crbug.com/996511 virtual/plz-service-worker/http/tests/inspector-protocol/service-worker/offline-service-worker.js [ Timeout ] # A number of http/tests/inspector-protocol/network tests are flaky. -crbug.com/1228246 http/tests/inspector-protocol/network/disable-interception-midway.js [ Timeout Crash Pass Failure Skip ] -crbug.com/1228246 http/tests/inspector-protocol/network/request-interception-frame-id.js [ Timeout Crash Pass Failure Skip ] -crbug.com/1228246 http/tests/inspector-protocol/network/request-interception-patterns.js [ Timeout Crash Pass Failure Skip ] -crbug.com/1228246 http/tests/inspector-protocol/network/request-response-interception-disable-between.js [ Timeout Crash Pass Failure Skip ] -crbug.com/1228246 http/tests/inspector-protocol/network/same-site-issue-warn-cookie-lax-subresource-context-downgrade.js [ Timeout Crash Pass Failure Skip ] -crbug.com/1228246 http/tests/inspector-protocol/network/same-site-issue-warn-cookie-strict-subresource-context-downgrade.js [ Timeout Crash Pass Failure Skip ] -crbug.com/1228246 http/tests/inspector-protocol/network/webbundle.js [ Timeout Crash Pass Failure Skip ] +crbug.com/1228246 http/tests/inspector-protocol/network/disable-interception-midway.js [ Crash Failure Pass Skip Timeout ] +crbug.com/1228246 http/tests/inspector-protocol/network/request-interception-frame-id.js [ Crash Failure Pass Skip Timeout ] +crbug.com/1228246 http/tests/inspector-protocol/network/request-interception-patterns.js [ Crash Failure Pass Skip Timeout ] +crbug.com/1228246 http/tests/inspector-protocol/network/request-response-interception-disable-between.js [ Crash Failure Pass Skip Timeout ] +crbug.com/1228246 http/tests/inspector-protocol/network/same-site-issue-warn-cookie-lax-subresource-context-downgrade.js [ Crash Failure Pass Skip Timeout ] +crbug.com/1228246 http/tests/inspector-protocol/network/same-site-issue-warn-cookie-strict-subresource-context-downgrade.js [ Crash Failure Pass Skip Timeout ] +crbug.com/1228246 http/tests/inspector-protocol/network/webbundle.js [ Crash Failure Pass Skip Timeout ] # Other devtools flaky tests outside of http/tests/inspector-protocol/network. -crbug.com/1228261 http/tests/devtools/console/console-context-selector.js [ Timeout Crash Pass Failure Skip ] -crbug.com/1228261 http/tests/inspector-protocol/browser-grant-permissions.js [ Timeout Crash Pass Failure Skip ] -crbug.com/1228261 http/tests/inspector-protocol/network-fetch-content-with-error-status-code.js [ Timeout Crash Pass Failure Skip ] -crbug.com/1228261 http/tests/inspector-protocol/fetch/request-paused-network-id-cors.js [ Timeout Crash Pass Failure Skip ] -crbug.com/1228261 http/tests/inspector-protocol/service-worker/network-extrainfo-subresource.js [ Timeout Crash Pass Failure Skip ] -crbug.com/1228261 http/tests/inspector-protocol/service-worker/network-get-request-body-blob.js [ Timeout Crash Pass Failure Skip ] +crbug.com/1228261 http/tests/devtools/console/console-context-selector.js [ Crash Failure Pass Skip Timeout ] +crbug.com/1228261 http/tests/inspector-protocol/browser-grant-permissions.js [ Crash Failure Pass Skip Timeout ] +crbug.com/1228261 http/tests/inspector-protocol/network-fetch-content-with-error-status-code.js [ Crash Failure Pass Skip Timeout ] +crbug.com/1228261 http/tests/inspector-protocol/fetch/request-paused-network-id-cors.js [ Crash Failure Pass Skip Timeout ] +crbug.com/1228261 http/tests/inspector-protocol/service-worker/network-extrainfo-subresource.js [ Crash Failure Pass Skip Timeout ] +crbug.com/1228261 http/tests/inspector-protocol/service-worker/network-get-request-body-blob.js [ Crash Failure Pass Skip Timeout ] # Flakes that might be caused or aggravated by PlzServiceWorker -crbug.com/996511 virtual/plz-service-worker/external/wpt/service-workers/cache-storage/frame/cache-abort.https.html [ Timeout Crash Pass Failure Skip ] -crbug.com/996511 virtual/plz-service-worker/external/wpt/service-workers/cache-storage/window/cache-abort.https.html [ Timeout Crash Pass Failure Skip ] -crbug.com/996511 virtual/plz-service-worker/external/wpt/service-workers/service-worker/getregistrations.https.html [ Timeout Crash Pass Failure Skip ] -crbug.com/996511 virtual/plz-service-worker/http/tests/inspector-protocol/fetch/fetch-cors-preflight-sw.js [ Timeout Crash Pass Failure Skip ] +crbug.com/996511 virtual/plz-service-worker/external/wpt/service-workers/cache-storage/frame/cache-abort.https.html [ Crash Failure Pass Skip Timeout ] +crbug.com/996511 virtual/plz-service-worker/external/wpt/service-workers/cache-storage/window/cache-abort.https.html [ Crash Failure Pass Skip Timeout ] +crbug.com/996511 virtual/plz-service-worker/external/wpt/service-workers/service-worker/getregistrations.https.html [ Crash Failure Pass Skip Timeout ] +crbug.com/996511 virtual/plz-service-worker/http/tests/inspector-protocol/fetch/fetch-cors-preflight-sw.js [ Crash Failure Pass Skip Timeout ]
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 354683da..425b828c 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
@@ -66,6 +66,13 @@ {} ] ], + "move-owned-inside-another-owned.html": [ + "babe8dcd1dc77cd8da462d029db7f2d270d4b00a", + [ + null, + {} + ] + ], "slot-assignment-lockup.html": [ "85b6c9294a5eaa86c445607b552ece296c509614", [ @@ -1027,6 +1034,20 @@ }, "css-transforms": { "crashtests": { + "preserve3d-containing-block-inline-001.html": [ + "3be0af34cfa60f9d90a019a4ef7bb4a1bb536d2e", + [ + null, + {} + ] + ], + "preserve3d-containing-block-inline-002.html": [ + "163e977a917fbebf44ed9557e0ffaeaa6985bffd", + [ + null, + {} + ] + ], "preserve3d-scene-001.html": [ "1bb1091acf2bd15776c4b4da079f057d8956482a", [ @@ -1040,6 +1061,13 @@ null, {} ] + ], + "transform-marquee-resize-div-image-001.html": [ + "8bdbb984f3a1cb8a500a93faa4efa4a633b81826", + [ + null, + {} + ] ] }, "large-matrix-crash.html": [ @@ -9211,7 +9239,7 @@ {} ] ], - "local_FileSystemFileHandle-create-sync-access-handle-dedicated-worker-manual.https.html": [ + "local_FileSystemFileHandle-create-sync-access-handle-dedicated-worker-manual.https.tentative.html": [ "2b9c4445df4b642953de5f5d1882a077a98392c0", [ null, @@ -77503,6 +77531,32 @@ {} ] ], + "out-of-flow-in-multicolumn-064.html": [ + "19afe87f8853478e088426f0f68956663571d08a", + [ + null, + [ + [ + "/css/reference/ref-filled-green-100px-square.xht", + "==" + ] + ], + {} + ] + ], + "out-of-flow-in-multicolumn-065.html": [ + "13a1bdbafb792a9f2f765b59e72164865bd119cc", + [ + null, + [ + [ + "/css/reference/ref-filled-green-100px-square.xht", + "==" + ] + ], + {} + ] + ], "overflow-clip-000.html": [ "72b10f5cdd3092a042f1f90bff04e9428d61608e", [ @@ -87198,6 +87252,45 @@ ] ] }, + "counter-style-access-from-shadow-dom.html": [ + "a99bbcc82207f593a59be3cf5e786b09faa39b07", + [ + null, + [ + [ + "/css/css-counter-styles/counter-style-access-from-shadow-dom-ref.html", + "==" + ] + ], + {} + ] + ], + "counter-style-fallbacks-in-shadow-dom.html": [ + "39fb5f87fa3349106bd5c34d1fe4a342d49b27c7", + [ + null, + [ + [ + "/css/css-counter-styles/counter-style-fallbacks-in-shadow-dom-ref.html", + "==" + ] + ], + {} + ] + ], + "counter-styles-override-in-shadow-dom.html": [ + "908cafa80cefb9bdc37680eef7f004b930aeeaf1", + [ + null, + [ + [ + "/css/css-counter-styles/counter-styles-override-in-shadow-dom-ref.html", + "==" + ] + ], + {} + ] + ], "cssom": { "cssom-additive-symbols-setter-invalid.html": [ "fd382553df86d6b093d5d580f97b6791dab8b77b", @@ -90306,162 +90399,6 @@ {} ] ], - "flex-abspos-staticpos-align-content-001.html": [ - "da5968a1bd9ba745e55c79f1642ddb025cdc6c96", - [ - null, - [ - [ - "/css/css-flexbox/abspos/flex-abspos-staticpos-align-content-001-ref.html", - "==" - ] - ], - {} - ] - ], - "flex-abspos-staticpos-align-content-002.html": [ - "20a6d2089fa34a0bd44b5277d8154c6e0a7c6e60", - [ - null, - [ - [ - "/css/css-flexbox/abspos/flex-abspos-staticpos-align-content-002-ref.html", - "==" - ] - ], - {} - ] - ], - "flex-abspos-staticpos-align-content-003.html": [ - "9503187de85b6bde62f9570d08bf4aa568420553", - [ - null, - [ - [ - "/css/css-flexbox/abspos/flex-abspos-staticpos-align-content-003-ref.html", - "==" - ] - ], - {} - ] - ], - "flex-abspos-staticpos-align-content-004.html": [ - "121921c6c39602cdd847a12efb350f56b3f179e2", - [ - null, - [ - [ - "/css/css-flexbox/abspos/flex-abspos-staticpos-align-content-004-ref.html", - "==" - ] - ], - {} - ] - ], - "flex-abspos-staticpos-align-content-005.html": [ - "5fe76de0aed644e5353b0c766746f840fca71a20", - [ - null, - [ - [ - "/css/css-flexbox/abspos/flex-abspos-staticpos-align-content-005-ref.html", - "==" - ] - ], - {} - ] - ], - "flex-abspos-staticpos-align-content-006.html": [ - "c6ad204f0955169c57873ef8f1116afcc20511d6", - [ - null, - [ - [ - "/css/css-flexbox/abspos/flex-abspos-staticpos-align-content-006-ref.html", - "==" - ] - ], - {} - ] - ], - "flex-abspos-staticpos-align-content-007.html": [ - "1af6c30d3951400853f2d39cefa26ae3a64fe9a5", - [ - null, - [ - [ - "/css/css-flexbox/abspos/flex-abspos-staticpos-align-content-007-ref.html", - "==" - ] - ], - {} - ] - ], - "flex-abspos-staticpos-align-content-008.html": [ - "83381ca85f4417c8cca9d40ef92bc0e4f2431621", - [ - null, - [ - [ - "/css/css-flexbox/abspos/flex-abspos-staticpos-align-content-008-ref.html", - "==" - ] - ], - {} - ] - ], - "flex-abspos-staticpos-align-content-rtl-001.html": [ - "592a62e46501e413656082f28eea80585847929d", - [ - null, - [ - [ - "/css/css-flexbox/abspos/flex-abspos-staticpos-align-content-rtl-001-ref.html", - "==" - ] - ], - {} - ] - ], - "flex-abspos-staticpos-align-content-rtl-002.html": [ - "2d5ec17f605cb3a62610b1f502da94e6d370bdd9", - [ - null, - [ - [ - "/css/css-flexbox/abspos/flex-abspos-staticpos-align-content-rtl-002-ref.html", - "==" - ] - ], - {} - ] - ], - "flex-abspos-staticpos-align-content-vertWM-001.html": [ - "58cc640df96e202d01fbdfa2a57f1e7f3e6860b5", - [ - null, - [ - [ - "/css/css-flexbox/abspos/flex-abspos-staticpos-align-content-vertWM-001-ref.html", - "==" - ] - ], - {} - ] - ], - "flex-abspos-staticpos-align-content-vertWM-002.html": [ - "87d44d1231e5d5e132b1fd665abeadf9da7b8af4", - [ - null, - [ - [ - "/css/css-flexbox/abspos/flex-abspos-staticpos-align-content-vertWM-002-ref.html", - "==" - ] - ], - {} - ] - ], "flex-abspos-staticpos-align-self-safe-001.html": [ "b7302cb962dbff9bfc99592ac7a2d2f2aae52b21", [ @@ -90475,58 +90412,6 @@ {} ] ], - "flex-abspos-staticpos-align-self-vertWM-001.html": [ - "bb5bee014ae5163a826e31e7140c013fad877217", - [ - null, - [ - [ - "/css/css-flexbox/abspos/flex-abspos-staticpos-align-self-vertWM-001-ref.html", - "==" - ] - ], - {} - ] - ], - "flex-abspos-staticpos-align-self-vertWM-002.html": [ - "5e11c5b0fcc0e4f2c09aa1672dd32e2647400b3e", - [ - null, - [ - [ - "/css/css-flexbox/abspos/flex-abspos-staticpos-align-self-vertWM-002-ref.html", - "==" - ] - ], - {} - ] - ], - "flex-abspos-staticpos-align-self-vertWM-003.html": [ - "b285ad4ff3ad13f4dc7ccf3f44e2504e1250c9a4", - [ - null, - [ - [ - "/css/css-flexbox/abspos/flex-abspos-staticpos-align-self-vertWM-003-ref.html", - "==" - ] - ], - {} - ] - ], - "flex-abspos-staticpos-align-self-vertWM-004.html": [ - "b7566887b4a0ecea60d79f26f524010c713574a1", - [ - null, - [ - [ - "/css/css-flexbox/abspos/flex-abspos-staticpos-align-self-vertWM-004-ref.html", - "==" - ] - ], - {} - ] - ], "flex-abspos-staticpos-fallback-align-content-001.html": [ "80dd2f68f9510ce7535b97f80655ce8b483886f4", [ @@ -101567,7 +101452,7 @@ ] ], "font-size-adjust-009.html": [ - "108e15e4b220363282dca6645b9f4db54179798b", + "765447b22f040b8015789d0a6df532e801e67459", [ null, [ @@ -101580,7 +101465,7 @@ ] ], "font-size-adjust-010.html": [ - "d3d385985c2acbe2b15d71d068eb0cda5ebcf77b", + "6ee3ab7d8742b8f5d6bd3f16319ef57911183e67", [ null, [ @@ -101593,7 +101478,7 @@ ] ], "font-size-adjust-011.html": [ - "5e5c1a71a2138067319c20114384f8741375e88c", + "f4ac39c257471a81114f5f32019c65fc24187595", [ null, [ @@ -123848,6 +123733,19 @@ {} ] ], + "multicol-scroll-content.html": [ + "9fdaf1a8806ee534e7814be1aa6261ae2f3d2c84", + [ + null, + [ + [ + "/css/css-multicol/multicol-scroll-content-ref.html", + "==" + ] + ], + {} + ] + ], "multicol-shorthand-001.xht": [ "650a324a80433b4f06ae61ac251d579c2d677e99", [ @@ -128827,6 +128725,84 @@ {} ] ], + "position-relative-008.html": [ + "e2c7c02bbdf803fa73745b08b21db250b49c088b", + [ + null, + [ + [ + "/css/reference/ref-filled-green-100px-square-only.html", + "==" + ] + ], + {} + ] + ], + "position-relative-009.html": [ + "5f4093d75a6fd53da63db5d3f4f1a4416fb7183b", + [ + null, + [ + [ + "/css/reference/ref-filled-green-100px-square-only.html", + "==" + ] + ], + {} + ] + ], + "position-relative-010.html": [ + "40697357991e5d7f49f51e45dc2fe357982a2625", + [ + null, + [ + [ + "/css/reference/ref-filled-green-100px-square-only.html", + "==" + ] + ], + {} + ] + ], + "position-relative-011.html": [ + "aaf7492a8b6e776a947dee6cc49b5ea04879766a", + [ + null, + [ + [ + "/css/reference/ref-filled-green-100px-square-only.html", + "==" + ] + ], + {} + ] + ], + "position-relative-012.html": [ + "c2debe1af986647e6e411f5e40aa382c55e5912c", + [ + null, + [ + [ + "/css/reference/ref-filled-green-100px-square-only.html", + "==" + ] + ], + {} + ] + ], + "position-relative-013.html": [ + "94888b158f66145b5b3bcecd2131f48c0214c959", + [ + null, + [ + [ + "/css/reference/ref-filled-green-100px-square-only.html", + "==" + ] + ], + {} + ] + ], "position-relative-table-tbody-left-absolute-child.html": [ "98e759a8c0a83817b3d691503e807ed5ed549936", [ @@ -137730,19 +137706,6 @@ {} ] ], - "grid-aspect-ratio-013.html": [ - "e52db16721a1a082bd86b24d87bfa4709838669c", - [ - null, - [ - [ - "/css/reference/ref-filled-green-100px-square.xht", - "==" - ] - ], - {} - ] - ], "grid-aspect-ratio-014.html": [ "1bec95ea5392588f99107361448686d11295c3f7", [ @@ -137796,7 +137759,7 @@ ] ], "grid-aspect-ratio-018.html": [ - "76fd6d96944a20c7a49f9e18e1524169f4e40a71", + "d0b496e2503529847bbf91ff8b0d49565abc1892", [ null, [ @@ -137809,7 +137772,7 @@ ] ], "grid-aspect-ratio-019.html": [ - "465b39949fb26ef95f6e7117f7d599b8f82ffa68", + "bf9c353866f73d21e50aca50ed59debceebffc50", [ null, [ @@ -161061,6 +161024,19 @@ {} ] ], + "preserve-3d-flat-grouping-properties-containing-block-inline.tentative.html": [ + "c5666aa358079fae47ca48d64824258fe2ed5c57", + [ + null, + [ + [ + "/css/css-transforms/preserve-3d-flat-grouping-properties-containing-block-inline-ref.html", + "==" + ] + ], + {} + ] + ], "preserve3d-and-filter-no-perspective.html": [ "0145b0dbfd24326e23a32e85064913f9f9393491", [ @@ -213757,7 +213733,7 @@ [] ], "cookie-test.js": [ - "9a965060ea97e4fefb544188712f15785d14752f", + "8096ffc5da86737f6a30ce2f85816015f73b96f1", [] ], "cookie.py": [ @@ -223962,6 +223938,10 @@ "85a391d5a2cdaf43b62819f20d9879ed1dead584", [] ], + "webkit-focus-ring-color.tentative-expected.txt": [ + "1297e17e027a7c12ce37aa398afc8d7cea678c57", + [] + ], "whitesquare-ref.html": [ "ea7103759ba65a30434c7f996e9957c5519b11fd", [] @@ -225094,10 +225074,22 @@ [] ] }, + "counter-style-access-from-shadow-dom-ref.html": [ + "ee40f94bda4b400be543eb79eff155269a6f4056", + [] + ], + "counter-style-fallbacks-in-shadow-dom-ref.html": [ + "53e467bb391884ec9751edfcffe85f03c8502e08", + [] + ], "counter-style-name-syntax-expected.txt": [ "ec612be1d7ed5a88ce935416379316ff6059a8bb", [] ], + "counter-styles-override-in-shadow-dom-ref.html": [ + "aa398f73a7f206a196e35b8a5538200a93353040", + [] + ], "cssom": { "cssom-additive-symbols-setter-ref.html": [ "a09788e369a58a35dd92370cc1f25ef2561c1814", @@ -225979,52 +225971,52 @@ [] ], "abspos": { - "flex-abspos-staticpos-align-content-001-ref.html": [ - "98b4bd95823d4a14a52bbcf176f3dfbbbc211d54", + "flex-abspos-staticpos-align-content-001-expected.txt": [ + "a4b03b6e3f4885d42439c900b421a77d8fc1410f", [] ], - "flex-abspos-staticpos-align-content-002-ref.html": [ - "b9bde37740edd87ab94a6fffbf115a9f7c74bd89", + "flex-abspos-staticpos-align-content-002-expected.txt": [ + "9e6e0c3a899b4403b7378a542adcdac436c92cd3", [] ], - "flex-abspos-staticpos-align-content-003-ref.html": [ - "3d4867f617c4bdf092f4848808b53e42c0611b79", + "flex-abspos-staticpos-align-content-003-expected.txt": [ + "948ea5f3155be0cab86bb7d1504eb8cd3bb83d28", [] ], - "flex-abspos-staticpos-align-content-004-ref.html": [ - "82399e3accfaf678467501436c265aa4375cb4d6", + "flex-abspos-staticpos-align-content-004-expected.txt": [ + "ce0ac474aae469c6f47f477dfccfa58a9793aa7d", [] ], - "flex-abspos-staticpos-align-content-005-ref.html": [ - "8d853a84df64f822d03ae2456a66b13b68e71064", + "flex-abspos-staticpos-align-content-005-expected.txt": [ + "9f23cb4b247444b0a298a61231f7a7bfc7a3cda6", [] ], - "flex-abspos-staticpos-align-content-006-ref.html": [ - "f4880c4d68de1344fab11e38909eff015235aef0", + "flex-abspos-staticpos-align-content-006-expected.txt": [ + "4a15c232d40f4b6e79b495c379e2a5fff4dfa083", [] ], - "flex-abspos-staticpos-align-content-007-ref.html": [ - "55a390da0cdb87c04c6480bd4596f110f32bd47b", + "flex-abspos-staticpos-align-content-007-expected.txt": [ + "a2c75990a98b11c4d59f78634a41d53576bc361f", [] ], - "flex-abspos-staticpos-align-content-008-ref.html": [ - "f8b40d27e858f2e10dc76880a79f6cc3139813c7", + "flex-abspos-staticpos-align-content-008-expected.txt": [ + "f588fc5834665ac5e224f43a62ed5c36111c91f4", [] ], - "flex-abspos-staticpos-align-content-rtl-001-ref.html": [ - "3d4867f617c4bdf092f4848808b53e42c0611b79", + "flex-abspos-staticpos-align-content-rtl-001-expected.txt": [ + "948ea5f3155be0cab86bb7d1504eb8cd3bb83d28", [] ], - "flex-abspos-staticpos-align-content-rtl-002-ref.html": [ - "989d6ac13d5e2ec7055dd349bc086d5c09fa26f0", + "flex-abspos-staticpos-align-content-rtl-002-expected.txt": [ + "1c849f427108b9800f9fe28008c6edea4688d6aa", [] ], - "flex-abspos-staticpos-align-content-vertWM-001-ref.html": [ - "989d6ac13d5e2ec7055dd349bc086d5c09fa26f0", + "flex-abspos-staticpos-align-content-vertWM-001-expected.txt": [ + "1c849f427108b9800f9fe28008c6edea4688d6aa", [] ], - "flex-abspos-staticpos-align-content-vertWM-002-ref.html": [ - "3d4867f617c4bdf092f4848808b53e42c0611b79", + "flex-abspos-staticpos-align-content-vertWM-002-expected.txt": [ + "948ea5f3155be0cab86bb7d1504eb8cd3bb83d28", [] ], "flex-abspos-staticpos-align-self-001-expected.txt": [ @@ -226079,20 +226071,20 @@ "fb1fb93ea997b1107efa595f17ae5b9c38419a92", [] ], - "flex-abspos-staticpos-align-self-vertWM-001-ref.html": [ - "e9b697062418aa434d33e65f9295839ca9ff1175", + "flex-abspos-staticpos-align-self-vertWM-001-expected.txt": [ + "5ea1d55939802079738adee91a9d1bc292395e66", [] ], - "flex-abspos-staticpos-align-self-vertWM-002-ref.html": [ - "4459c1a03c89349066235ead8a4e5ea24a2ac75f", + "flex-abspos-staticpos-align-self-vertWM-002-expected.txt": [ + "5ea1d55939802079738adee91a9d1bc292395e66", [] ], - "flex-abspos-staticpos-align-self-vertWM-003-ref.html": [ - "75a998e34121bd8067a6694f523b32c0e928689a", + "flex-abspos-staticpos-align-self-vertWM-003-expected.txt": [ + "000202121b549fd35e56d9eb575d11f11facb15a", [] ], - "flex-abspos-staticpos-align-self-vertWM-004-ref.html": [ - "a4be517ce0669defc631689e5208c3e7fa8abc4e", + "flex-abspos-staticpos-align-self-vertWM-004-expected.txt": [ + "000202121b549fd35e56d9eb575d11f11facb15a", [] ], "flex-abspos-staticpos-fallback-align-content-001-ref.html": [ @@ -228316,7 +228308,7 @@ ], "animations": { "font-size-adjust-interpolation-expected.txt": [ - "3dd91183e8044b0477ae8d47fb26a49a5c955e2c", + "05d041d5fcc95aafb4cc8efb23f98619692b3f58", [] ], "font-stretch-interpolation-expected.txt": [ @@ -228938,11 +228930,11 @@ [] ], "font-size-adjust-computed-expected.txt": [ - "cf6646f2555cbb36421e3a254136fe978e33e2bd", + "c824213e0a9e82e61b31deac83c0dcdaecc30276", [] ], "font-size-adjust-valid-expected.txt": [ - "5139a3280fed530d12437a20375abef39d183269", + "0b5e69fcd46d662db7cdb3b98bf6b743778148a1", [] ], "font-style-computed-expected.txt": [ @@ -239284,6 +239276,10 @@ "b1ad88eb3bb1f7bb7417c06d4b89e8c24d443f1d", [] ], + "multicol-scroll-content-ref.html": [ + "320e425dbd16a5736e6a1ca9ae93bfb06bfbcaac", + [] + ], "multicol-span-000-ref.xht": [ "7c076f4e30127d15f0966e3845771aeb8cc5ad19", [] @@ -247658,6 +247654,10 @@ "bea389ab47fc6b9eecde572a252149dc294f63e1", [] ], + "preserve-3d-flat-grouping-properties-containing-block-inline-ref.html": [ + "7ca006cc5de2b459aa5133af11618f7b6cb8195e", + [] + ], "preserve3d-and-filter-no-perspective-ref.html": [ "d84ea9a19cb31d28010876009e984083e8493a7c", [] @@ -257658,6 +257658,10 @@ "6a59f713223e2451fbf6fad78fb6375a434e7803", [] ], + "insert-text-in-void-element.tentative-expected.txt": [ + "9cbdf9306c899d491bcb49768185a0999329c34c", + [] + ], "restoration-expected.txt": [ "a8d74b3eb1e0a59f0c5b5989c60349720487a00b", [] @@ -266666,7 +266670,7 @@ [] ], "path-objects.yaml": [ - "0e40e8bb88308a0078fde58f90a6cb3b69898fab", + "52256004b2f979264203d1abb7c232f42a44b746", [] ], "pixel-manipulation.yaml": [ @@ -266744,7 +266748,7 @@ [] ], "path-objects.yaml": [ - "c10b9d3053a3abb9ceb11eba46f5586cc1ead834", + "ea97135854b2a8b1c62c1fb242611b7e5dd5057b", [] ], "pixel-manipulation.yaml": [ @@ -266839,7 +266843,7 @@ [] ], "common.js": [ - "68f8782b3942ed5eff4bb17fe926a42dbe5bf451", + "a5afd3625ac15232eaf0cbd56fe87e240a2d56e3", [] ], "dispatcher.js": [ @@ -266861,6 +266865,10 @@ "iframeTest.js": [ "501a864d4677e1c7e5ddc0b4c4868ac8712e4723", [] + ], + "sw_executor.js": [ + "0b47d66b65f066fbbf6052c0d3adcdf26706a52c", + [] ] }, "shared-worker.tentative.https-expected.txt": [ @@ -267194,6 +267202,10 @@ "1822ba4e3b05a17b48ad7165c565f84caadb3a40", [] ], + "coop-navigate-same-origin-csp-sandbox-expected.txt": [ + "428a7a9662721c297d5433c3c67be9462df7bea5", + [] + ], "coop-navigated-popup.https.html.headers": [ "d83ed86fb9b5d159b9f380424887402edc96cb75", [] @@ -280038,15 +280050,15 @@ [] ], "frac-invalid-2-ref.html": [ - "5b1960db59238590ac93af5c123ab2bff1066716", + "d57c20901bb3f39e6faa91a6ca192e5c60917965", [] ], "frac-invalid-3-ref.html": [ - "7cb95acaf09c82060e2cd5a2b3ee9ef7e05b55b0", + "703e4aeca06180b25178a97c1e1f39ea01a9e244", [] ], "frac-invalid-ref.html": [ - "e1c44fea37edbafc3f8df11f2b18fa190fe8bd8c", + "beb302473256ebeb5872df39c37c1dff1c97eb4b", [] ], "frac-legacy-bevelled-attribute.tentative-ref.html": [ @@ -280057,10 +280069,6 @@ "d4be8ea03bfc29506af0e26a3d94d5eeafaaf472", [] ], - "frac-linethickness-002-expected.txt": [ - "a3382b5d34ad3aa5d2102d96a8b417a3f35c129d", - [] - ], "frac-linethickness-003-notref.html": [ "934d66633397313175e98c4bda871bb0a95e5db0", [] @@ -280121,6 +280129,10 @@ "2f823ba9550d1c5a2cac2fe5b4b3bc5867a1be75", [] ], + "inferred-mrow-stretchy-expected.txt": [ + "dbcd828d9975219d0a06173869c2fa01f9dcaa5b", + [] + ], "legacy-mfenced-element-001-ref.html": [ "00c781b6e4fc8f51e98583a35f76d61a3d104440", [] @@ -280129,10 +280141,6 @@ "0c26780c10f06cde8f7815a84f5fe22217907dfd", [] ], - "merror-001-expected.txt": [ - "1848d63bb7670f1f05a53ff02051cf22572ad479", - [] - ], "mrow-painting-order-ref.html": [ "72694959a86f1917cbd3db13b7f1a8b71714b711", [] @@ -280147,6 +280155,10 @@ "d73ecc2d8c49891fe65f9a5ae30db30d62faaedd", [] ], + "mo-axis-height-1-expected.txt": [ + "2ed92752e4badbeb5d07f302b441e0436278b8f1", + [] + ], "mo-font-relative-lengths-001-expected.txt": [ "c38addf525a1324d9f30ce5aebfd9e01a0e99e36", [] @@ -280341,10 +280353,6 @@ }, "relations": { "css-styling": { - "attribute-mapping-001-expected.txt": [ - "751e02b0c9a246f233693d6a045692c6a5e4f349", - [] - ], "attribute-mapping-002-expected.txt": [ "e947f70455890f895827a40ddd2c48ff16ff3388", [] @@ -280385,10 +280393,6 @@ "1bffae30b78bbb160e98de85f5629e594612bd50", [] ], - "default-properties-on-the-math-root-expected.txt": [ - "d0fae2e56ed9d66417a278ddd2814c72e6ea13e4", - [] - ], "display-1-ref.html": [ "ce65aba18c9483274765cde6f62bdf5fdeea001e", [] @@ -280558,10 +280562,6 @@ [] ], "padding-border-margin": { - "border-002-expected.txt": [ - "862589b72b58a4edd43530ee9a8e47bbe16ee4a7", - [] - ], "padding-border-margin-001-ref.html": [ "150a650bc28434f1811d3d40747d074146ec4a30", [] @@ -286265,7 +286265,7 @@ [] ], "webusb-test.js": [ - "5775c071b2299c8eb62c6ffff53b05358448172d", + "10140a54fabf01d52d9674ec72c46fc812bfb95d", [] ], "webusb-test.js.headers": [ @@ -290169,6 +290169,22 @@ "bad-buffers-and-views.any.worker-expected.txt": [ "7824e1ec8b0f947893f4e9038c1000e8ef5492ab", [] + ], + "tee.any-expected.txt": [ + "1f96021cb3f9619067f5916419832422555b5d8c", + [] + ], + "tee.any.serviceworker-expected.txt": [ + "1f96021cb3f9619067f5916419832422555b5d8c", + [] + ], + "tee.any.sharedworker-expected.txt": [ + "1f96021cb3f9619067f5916419832422555b5d8c", + [] + ], + "tee.any.worker-expected.txt": [ + "1f96021cb3f9619067f5916419832422555b5d8c", + [] ] }, "readable-streams": { @@ -290221,29 +290237,29 @@ [] ], "tee.any-expected.txt": [ - "bebedc3cd64215dea5fcc13e70a9e847dd85f77c", + "1c3ffa7490074d2df9fcf02fccf448e94992e9b4", [] ], "tee.any.serviceworker-expected.txt": [ - "bebedc3cd64215dea5fcc13e70a9e847dd85f77c", + "1c3ffa7490074d2df9fcf02fccf448e94992e9b4", [] ], "tee.any.sharedworker-expected.txt": [ - "bebedc3cd64215dea5fcc13e70a9e847dd85f77c", + "1c3ffa7490074d2df9fcf02fccf448e94992e9b4", [] ], "tee.any.worker-expected.txt": [ - "bebedc3cd64215dea5fcc13e70a9e847dd85f77c", + "1c3ffa7490074d2df9fcf02fccf448e94992e9b4", [] ] }, "resources": { "recording-streams.js": [ - "34d02a143dccdb459a87d261be7b724ed75bb832", + "661fe512f516c6c331025b74e6bf936e130f32c7", [] ], "rs-test-templates.js": [ - "700bd9c3ca9f9e92c86512bf38f903944be9bdce", + "400907a9db2908fdfba78ee29862b84196cc0e7f", [] ], "rs-utils.js": [ @@ -292393,11 +292409,11 @@ ], "resources": { "a-element-origin.js": [ - "3b8cb1cbbe7c75a7d64442b59f2ad4888cef2f68", + "cb7d4a895c40c456c3f4c0ade050115319ad410c", [] ], "a-element.js": [ - "f64531bc8bd5285ae9f2c35cd38f8a739ee39e72", + "553855a870c55917877d0ce9d1e5900bb744425a", [] ], "percent-encoding.json": [ @@ -292417,7 +292433,7 @@ [] ], "urltestdata.json": [ - "a56b30caf98cb10745bfddbf38734f0f88e9e45d", + "34cc2e5a9e356c405b1162ada7e43b7afd248871", [] ] }, @@ -299557,14 +299573,6 @@ "dd0047734a25a218aab70b7f807bf2c3f776594a", [] ], - "json.any-expected.txt": [ - "d9a840da176d064a5b60c3009cf3da5fc63b212e", - [] - ], - "json.any.worker-expected.txt": [ - "d9a840da176d064a5b60c3009cf3da5fc63b212e", - [] - ], "no-utf16-json-expected.txt": [ "9a74f1dc20910787d318edcc27461722a323e86f", [] @@ -316646,7 +316654,7 @@ ] }, "cross-origin-iframe.sub.https.html": [ - "f3fc924ea708ab72ad0d9625ecb82137045c6252", + "c64888512715ca688a06eae7d203c56075ef4d03", [ null, { @@ -328219,6 +328227,26 @@ ] ] }, + "size": { + "attributes.www.sub.html": [ + "3004007ec8e053ef01acf56226c5c1e7e439c8a2", + [ + null, + { + "timeout": "long" + } + ] + ], + "name-and-value.html": [ + "2122c0d461a07d3b67eb0438a143b19e871b626c", + [ + null, + { + "timeout": "long" + } + ] + ] + }, "value": { "value-ctl.html": [ "71c10c214159a72294152ef9d9d7ec4f841347aa", @@ -331788,6 +331816,13 @@ null, {} ] + ], + "webkit-focus-ring-color.tentative.html": [ + "b79e16dbe66082b61916b44e4bf5c516099d37dd", + [ + null, + {} + ] ] }, "css-color-adjust": { @@ -332519,6 +332554,90 @@ {} ] ], + "flex-abspos-staticpos-align-content-001.html": [ + "b1c22ba74f7d10a29a47b1006352dd38a63ccb5f", + [ + null, + {} + ] + ], + "flex-abspos-staticpos-align-content-002.html": [ + "409f7923f3f3bcb3ea0ad71dcd27520a42bff0d4", + [ + null, + {} + ] + ], + "flex-abspos-staticpos-align-content-003.html": [ + "f0f163cf838c6cfb90d4eaf5aca40353d738e006", + [ + null, + {} + ] + ], + "flex-abspos-staticpos-align-content-004.html": [ + "fe07b8d0f53ac75cecb2632c97605f715e0e7bcd", + [ + null, + {} + ] + ], + "flex-abspos-staticpos-align-content-005.html": [ + "ac48584bf8526b0f5b841420d66bd4293b717958", + [ + null, + {} + ] + ], + "flex-abspos-staticpos-align-content-006.html": [ + "aacfe85660c3311a0d5fdb307902c26b01bc9185", + [ + null, + {} + ] + ], + "flex-abspos-staticpos-align-content-007.html": [ + "0b6f8123c32d604853e1050731f61cc0f3187a54", + [ + null, + {} + ] + ], + "flex-abspos-staticpos-align-content-008.html": [ + "66bc6be0880b348250998ffeef1ec8fc4fcc5f3f", + [ + null, + {} + ] + ], + "flex-abspos-staticpos-align-content-rtl-001.html": [ + "214c2670cfa3a92873e2405ac94d99e7339d488f", + [ + null, + {} + ] + ], + "flex-abspos-staticpos-align-content-rtl-002.html": [ + "2dfc20a9a18ecad7f21c225d484727bf239a6b12", + [ + null, + {} + ] + ], + "flex-abspos-staticpos-align-content-vertWM-001.html": [ + "d983b501f2923be8c8f378b48f1553091f3ced51", + [ + null, + {} + ] + ], + "flex-abspos-staticpos-align-content-vertWM-002.html": [ + "a24247185f84a74437e3c99f6a01bdf782b03711", + [ + null, + {} + ] + ], "flex-abspos-staticpos-align-self-001.html": [ "7fb82d4f9259b6e628629fbe59ae84eae64474d4", [ @@ -332603,6 +332722,34 @@ {} ] ], + "flex-abspos-staticpos-align-self-vertWM-001.html": [ + "42aeb01907d3ac941a4f0fb05b0d5c60bece8e68", + [ + null, + {} + ] + ], + "flex-abspos-staticpos-align-self-vertWM-002.html": [ + "bb5b1f57a7f688ffe9cd907284ae4923ffcdcb77", + [ + null, + {} + ] + ], + "flex-abspos-staticpos-align-self-vertWM-003.html": [ + "6d877c6280bc1da016aeecb422f26bffb16951d6", + [ + null, + {} + ] + ], + "flex-abspos-staticpos-align-self-vertWM-004.html": [ + "3248871fe50cec8d9e5f95f7c336fccaaf2be0bb", + [ + null, + {} + ] + ], "flex-abspos-staticpos-justify-content-001.html": [ "afcecaafd24465bab13b1f45c879886e52c48409", [ @@ -334389,7 +334536,7 @@ "css-fonts": { "animations": { "font-size-adjust-interpolation.html": [ - "dbb246ba658f8a1b9c20ac36fa081cc8486e36bf", + "a138d7fee5a39bc925a7a4cc5224dcc3db5cc387", [ null, {} @@ -334717,21 +334864,21 @@ ] ], "font-size-adjust-computed.html": [ - "ec6afcb2beeae32209d2909768f51308c590bc1e", + "a4c8212b980a4461ab05a26a9401c6c4e62a5143", [ null, {} ] ], "font-size-adjust-invalid.html": [ - "f36a7ad2a917431e514b621ec7bd3418616ae9a8", + "8f1dfb15822ad1eccbfaa6667874fe2974950df9", [ null, {} ] ], "font-size-adjust-valid.html": [ - "676eb0265c5364d5190849fd960b3a1f2ed61b55", + "bb46daf4be57b3f6a1bfb9b8c24230ced0f8d8dd", [ null, {} @@ -344967,7 +345114,7 @@ ] ], "colspan-redistribution.html": [ - "bf744da8228c49dbc95cc8d47a67710a236e3db4", + "3c4d57c142bae329031beb8f325f1d49a1f6f640", [ null, {} @@ -361402,6 +361549,15 @@ {} ] ], + "insert-text-in-void-element.tentative.html": [ + "a67f061bc42775ceaba4e5693184523049a5d2ea", + [ + null, + { + "timeout": "long" + } + ] + ], "move-inserted-node-from-DOMNodeInserted-during-exec-command-insertHTML.html": [ "41e012a62e9617f372f85d0a0cedefe8ad42fbd6", [ @@ -386566,10 +386722,10 @@ } ] ], - "sandboxed_FileSystemFileHandle-create-sync-access-handle-dedicated-worker.https.window.js": [ + "sandboxed_FileSystemFileHandle-create-sync-access-handle-dedicated-worker.https.tentative.window.js": [ "f0d938b045c906a4eb6e7902e39fdc95ad15a2a0", [ - "file-system-access/sandboxed_FileSystemFileHandle-create-sync-access-handle-dedicated-worker.https.window.html", + "file-system-access/sandboxed_FileSystemFileHandle-create-sync-access-handle-dedicated-worker.https.tentative.window.html", { "script_metadata": [ [ @@ -396232,6 +396388,13 @@ {} ] ], + "2d.path.roundrect.1.radius.dompointinit.html": [ + "1926bccfdac65af7401467cb19d909c6068052f5", + [ + null, + {} + ] + ], "2d.path.roundrect.1.radius.double.html": [ "0703e9f10b3e8ae30afe5380218b47f6401331cf", [ @@ -396246,6 +396409,13 @@ {} ] ], + "2d.path.roundrect.2.radii.1.dompointinit.html": [ + "37eb89dcf76428bbc6242f29dfe33b700211bc9d", + [ + null, + {} + ] + ], "2d.path.roundrect.2.radii.1.double.html": [ "f35ec3246dc6df32ea637ab9d80fb605078c47a6", [ @@ -396260,6 +396430,13 @@ {} ] ], + "2d.path.roundrect.2.radii.2.dompointinit.html": [ + "7f672555008d90c636fc62a05e612301dc93a3b0", + [ + null, + {} + ] + ], "2d.path.roundrect.2.radii.2.double.html": [ "9ae82104c98ba88c5976fa25a006bd180ef6f862", [ @@ -396274,6 +396451,13 @@ {} ] ], + "2d.path.roundrect.3.radii.1.dompointinit.html": [ + "11709a1df8907b628c9ea0d59dd986a3d2a0bb4c", + [ + null, + {} + ] + ], "2d.path.roundrect.3.radii.1.double.html": [ "197a8add86a75db42d10ab6c6053fa7768382847", [ @@ -396288,6 +396472,13 @@ {} ] ], + "2d.path.roundrect.3.radii.2.dompointinit.html": [ + "72e753305999132a9636da41783ed0a84296877a", + [ + null, + {} + ] + ], "2d.path.roundrect.3.radii.2.double.html": [ "74df39e99170e23d0771ea723f1524b66b37a245", [ @@ -396302,6 +396493,13 @@ {} ] ], + "2d.path.roundrect.3.radii.3.dompointinit.html": [ + "eec602ea453ac0544436967146c190eca117e3c5", + [ + null, + {} + ] + ], "2d.path.roundrect.3.radii.3.double.html": [ "af7d760faba33bcdf26ff7e1e2dad91f46d3967c", [ @@ -396316,6 +396514,13 @@ {} ] ], + "2d.path.roundrect.4.radii.1.dompointinit.html": [ + "72b9ecc7b5136891e6dfdd3c9525168840d4d43d", + [ + null, + {} + ] + ], "2d.path.roundrect.4.radii.1.double.html": [ "059f49f0c1b91070dc493a00dfea95c28ec73149", [ @@ -396330,6 +396535,13 @@ {} ] ], + "2d.path.roundrect.4.radii.2.dompointinit.html": [ + "a58a8461c51338376796b8ab01b66286410e9e39", + [ + null, + {} + ] + ], "2d.path.roundrect.4.radii.2.double.html": [ "0ffbbfe2b0458ca6c190c551168d1d9709a50edf", [ @@ -396344,6 +396556,13 @@ {} ] ], + "2d.path.roundrect.4.radii.3.dompointinit.html": [ + "f58de8e49bed2a2215ccdf3a5a2727931cc5c89b", + [ + null, + {} + ] + ], "2d.path.roundrect.4.radii.3.double.html": [ "3d6225289d2c0e55b53ecb1fc86d4eab75bd161e", [ @@ -396358,6 +396577,13 @@ {} ] ], + "2d.path.roundrect.4.radii.4.dompointinit.html": [ + "59291121aa79c47c3d223af3ae61ed23378a4277", + [ + null, + {} + ] + ], "2d.path.roundrect.4.radii.4.double.html": [ "7e2addf116d80c2b7f45b7e0d9aaecfca1bd45c0", [ @@ -396436,21 +396662,21 @@ ] ], "2d.path.roundrect.radius.negative.html": [ - "01ad92ea5c0a5b2730981f38f7708a955e5f1996", + "37489d27d92bbca7c55fb7154bae2100d0610540", [ null, {} ] ], "2d.path.roundrect.radius.none.html": [ - "b55d1eca654065329ff34622d270f938aa2e7214", + "16a03c1fdc5d5b77557b5ba574a233007511f63e", [ null, {} ] ], "2d.path.roundrect.radius.toomany.html": [ - "aaa7756f65f3ce7f57450772343323ca978e57f3", + "c6a960b0590d1b67d4e18d437c170dd0957baf51", [ null, {} @@ -406062,6 +406288,20 @@ {} ] ], + "2d.path.roundrect.1.radius.dompointinit.html": [ + "0bf33703b434caaacd5709fe4501278fa5888882", + [ + null, + {} + ] + ], + "2d.path.roundrect.1.radius.dompointinit.worker.js": [ + "ec0580b84af31b9464cc69f672d16c0e746e7d9f", + [ + "html/canvas/offscreen/path-objects/2d.path.roundrect.1.radius.dompointinit.worker.html", + {} + ] + ], "2d.path.roundrect.1.radius.double.html": [ "bfc15e7a5d9f1398aa4a93e5791efed73fa673f4", [ @@ -406090,6 +406330,20 @@ {} ] ], + "2d.path.roundrect.2.radii.1.dompointinit.html": [ + "dbaac00b7dbb21894c7f594c032067f32dfb0e5b", + [ + null, + {} + ] + ], + "2d.path.roundrect.2.radii.1.dompointinit.worker.js": [ + "f9d11df747a80f3986a2cef94da375159e60c8bc", + [ + "html/canvas/offscreen/path-objects/2d.path.roundrect.2.radii.1.dompointinit.worker.html", + {} + ] + ], "2d.path.roundrect.2.radii.1.double.html": [ "f359b3d8a4284f583e755d1074f754c2b1673d63", [ @@ -406118,6 +406372,20 @@ {} ] ], + "2d.path.roundrect.2.radii.2.dompointinit.html": [ + "eb782c136aeb28cf3d26ac3f703b86e872573b27", + [ + null, + {} + ] + ], + "2d.path.roundrect.2.radii.2.dompointinit.worker.js": [ + "528596833bc825f843478689ae138107defa4a61", + [ + "html/canvas/offscreen/path-objects/2d.path.roundrect.2.radii.2.dompointinit.worker.html", + {} + ] + ], "2d.path.roundrect.2.radii.2.double.html": [ "50cf0c61c3204d08fdabd8e3e4f25a326879c29e", [ @@ -406146,6 +406414,20 @@ {} ] ], + "2d.path.roundrect.3.radii.1.dompointinit.html": [ + "a4196795893f7cc6df421a86ac2dbe243c492c7b", + [ + null, + {} + ] + ], + "2d.path.roundrect.3.radii.1.dompointinit.worker.js": [ + "8ef16a44e66f5a78f242a71c2cb23a0612a65c3b", + [ + "html/canvas/offscreen/path-objects/2d.path.roundrect.3.radii.1.dompointinit.worker.html", + {} + ] + ], "2d.path.roundrect.3.radii.1.double.html": [ "324eb8cd0aefec4733719dabd89a6b00a9a1d677", [ @@ -406174,6 +406456,20 @@ {} ] ], + "2d.path.roundrect.3.radii.2.dompointinit.html": [ + "07c4eec330d2af8c97646b55c1fdbe1355619e3a", + [ + null, + {} + ] + ], + "2d.path.roundrect.3.radii.2.dompointinit.worker.js": [ + "557762505e207eff5512ba9d916adda507a16e80", + [ + "html/canvas/offscreen/path-objects/2d.path.roundrect.3.radii.2.dompointinit.worker.html", + {} + ] + ], "2d.path.roundrect.3.radii.2.double.html": [ "7da57484c0502bb3c90b08aafd9245062e9c2712", [ @@ -406202,6 +406498,20 @@ {} ] ], + "2d.path.roundrect.3.radii.3.dompointinit.html": [ + "9e4677636538b8ae842b9a2197adc1aae73c1ac0", + [ + null, + {} + ] + ], + "2d.path.roundrect.3.radii.3.dompointinit.worker.js": [ + "5bc8e6fd1fb01ae4a45283ec0c0d5a08f90b84f4", + [ + "html/canvas/offscreen/path-objects/2d.path.roundrect.3.radii.3.dompointinit.worker.html", + {} + ] + ], "2d.path.roundrect.3.radii.3.double.html": [ "d2f7a03ba0401ef2d5ed424ba864855d68b4b17c", [ @@ -406230,6 +406540,20 @@ {} ] ], + "2d.path.roundrect.4.radii.1.dompointinit.html": [ + "81900a270c62d352b997149d5d1f0f98c38ced83", + [ + null, + {} + ] + ], + "2d.path.roundrect.4.radii.1.dompointinit.worker.js": [ + "dad5edf954b3817fd60a9d955400bb472b42b698", + [ + "html/canvas/offscreen/path-objects/2d.path.roundrect.4.radii.1.dompointinit.worker.html", + {} + ] + ], "2d.path.roundrect.4.radii.1.double.html": [ "24160a11405e136ab5be8b589354a0cccebb26f1", [ @@ -406258,6 +406582,20 @@ {} ] ], + "2d.path.roundrect.4.radii.2.dompointinit.html": [ + "1386928a3adfb0b5122d4ba5a48bd656dc326029", + [ + null, + {} + ] + ], + "2d.path.roundrect.4.radii.2.dompointinit.worker.js": [ + "d0dd9bab083e7df4d1316351ec680af159f465b7", + [ + "html/canvas/offscreen/path-objects/2d.path.roundrect.4.radii.2.dompointinit.worker.html", + {} + ] + ], "2d.path.roundrect.4.radii.2.double.html": [ "97ecb398fb57a88a1df0fb94c46ca68e0332543e", [ @@ -406286,6 +406624,20 @@ {} ] ], + "2d.path.roundrect.4.radii.3.dompointinit.html": [ + "66e2b7ea207a229b87a63f7451878e60571d83f5", + [ + null, + {} + ] + ], + "2d.path.roundrect.4.radii.3.dompointinit.worker.js": [ + "5242cbb5c56ec81a6f03cd2ad01547633532e03d", + [ + "html/canvas/offscreen/path-objects/2d.path.roundrect.4.radii.3.dompointinit.worker.html", + {} + ] + ], "2d.path.roundrect.4.radii.3.double.html": [ "08554c09e498d4b7e8ca89437fcf6ff2deaf00ee", [ @@ -406314,6 +406666,20 @@ {} ] ], + "2d.path.roundrect.4.radii.4.dompointinit.html": [ + "2cd39301417cb262e541aefe5809f166d6038d4e", + [ + null, + {} + ] + ], + "2d.path.roundrect.4.radii.4.dompointinit.worker.js": [ + "50cd0edca15ce7b1f0bf1c025ada77e141071f7d", + [ + "html/canvas/offscreen/path-objects/2d.path.roundrect.4.radii.4.dompointinit.worker.html", + {} + ] + ], "2d.path.roundrect.4.radii.4.double.html": [ "32959f718eee247b4debb3c794c64d9c851a15ea", [ @@ -406469,42 +406835,42 @@ ] ], "2d.path.roundrect.radius.negative.html": [ - "4c973738583f00755a45c218292633e38c0715b2", + "afedca2ef92871327d2358680f8fda38904f88a1", [ null, {} ] ], "2d.path.roundrect.radius.negative.worker.js": [ - "b941725dd30356e0ec46a7ea69cce4fc79a3c21f", + "9fc4e8f78d7a09073df96228a630f325b06493fd", [ "html/canvas/offscreen/path-objects/2d.path.roundrect.radius.negative.worker.html", {} ] ], "2d.path.roundrect.radius.none.html": [ - "6defab24e32e0e5ab095ff78c1251454ac1d5085", + "85d9b80d645ae82768f7cab6bec379c828738910", [ null, {} ] ], "2d.path.roundrect.radius.none.worker.js": [ - "9acbf0d84d9aaede8beedc2a82df18ff8834650f", + "e1623b9f29aab9965ceb45f62b0cd0c16f77970e", [ "html/canvas/offscreen/path-objects/2d.path.roundrect.radius.none.worker.html", {} ] ], "2d.path.roundrect.radius.toomany.html": [ - "fe75bc2dc2c00f952fa7d286f950f21564c24e42", + "c615b0e8b6ef8156a50978d1ea1ebaac860dad76", [ null, {} ] ], "2d.path.roundrect.radius.toomany.worker.js": [ - "294ae6bc3c5271962be162566e9ec07b6afd33ad", + "2b35cb51038106d1035951715ac41f0e5f239425", [ "html/canvas/offscreen/path-objects/2d.path.roundrect.radius.toomany.worker.html", {} @@ -410797,6 +411163,20 @@ {} ] ], + "service-worker-coep-credentialless-proxy.tentative.https.html": [ + "fe12ec8d263b9a552c80e799ca3d7c945cb43db5", + [ + null, + {} + ] + ], + "service-worker-coep-none-proxy.tentative.https.html": [ + "599623bc54ddbd5e1c9d162214267ad1c6f5782e", + [ + null, + {} + ] + ], "service-worker.tentative.https.html": [ "377bcceb8be4756b67e7308b2a42fdb51070a802", [ @@ -410937,7 +411317,7 @@ ] ], "reporting-navigation.https.html": [ - "ab274be3295284210440afa89ae93329d7eeffe6", + "dea89478183870fa3db4ff6fef1d97a2a4ced516", [ null, { @@ -410946,7 +411326,7 @@ ] ], "reporting-subresource-corp.https.html": [ - "9bcf37b0cdfe32f9676ca4260a477875a69414b8", + "e56124a4a085d962874714b3c23b091378d9ff6b", [ null, { @@ -411139,6 +411519,13 @@ {} ] ], + "coop-navigate-same-origin-csp-sandbox.html": [ + "e6ed947172276b9d5cfbb661eb539459f4149898", + [ + null, + {} + ] + ], "coop-navigated-history-popup.https.html": [ "a061be992c1aa05ba8b0c1290f3562ab9a88904e", [ @@ -421944,7 +422331,7 @@ ] ], "dialog-form-submission.html": [ - "344f5f1d831f68e2f6dc4e764227c5462224b9de", + "5934485087a267f917d9b47d5414a36c1065da6f", [ null, { @@ -432203,7 +432590,7 @@ }, "js-self-profiling": { "idlharness.https.html": [ - "716667e7e17ae30264f40c4dd0a868bc11797f03", + "3807a6e4fa384479fc50d826f81f53556132f4f2", [ null, {} @@ -433970,6 +434357,13 @@ {} ] ], + "subsup-6.html": [ + "9666c80f9f60bd2cfd10437d9273777f11c3e2cb", + [ + null, + {} + ] + ], "subsup-parameters-1.html": [ "3f49b1d53b7866cac95bc56878312514d42a46c1", [ @@ -458540,7 +458934,7 @@ ] ], "sanitizer-sanitize.https.tentative.html": [ - "a577a1e36b7a316cafd21f07c88d7970209d206f", + "34615f6383b8f6db0330f5b8181e3ef157b7dbf8", [ null, {} @@ -468497,6 +468891,145 @@ ] } ] + ], + "tee.any.js": [ + "3ea5f6bb9cb5e0e93984479e748265dec534a01c", + [ + null, + { + "jsshell": true, + "script_metadata": [ + [ + "global", + "window,worker,jsshell" + ], + [ + "script", + "../resources/rs-utils.js" + ], + [ + "script", + "../resources/test-utils.js" + ], + [ + "script", + "../resources/recording-streams.js" + ], + [ + "script", + "../resources/rs-test-templates.js" + ] + ] + } + ], + [ + "streams/readable-byte-streams/tee.any.html", + { + "script_metadata": [ + [ + "global", + "window,worker,jsshell" + ], + [ + "script", + "../resources/rs-utils.js" + ], + [ + "script", + "../resources/test-utils.js" + ], + [ + "script", + "../resources/recording-streams.js" + ], + [ + "script", + "../resources/rs-test-templates.js" + ] + ] + } + ], + [ + "streams/readable-byte-streams/tee.any.serviceworker.html", + { + "script_metadata": [ + [ + "global", + "window,worker,jsshell" + ], + [ + "script", + "../resources/rs-utils.js" + ], + [ + "script", + "../resources/test-utils.js" + ], + [ + "script", + "../resources/recording-streams.js" + ], + [ + "script", + "../resources/rs-test-templates.js" + ] + ] + } + ], + [ + "streams/readable-byte-streams/tee.any.sharedworker.html", + { + "script_metadata": [ + [ + "global", + "window,worker,jsshell" + ], + [ + "script", + "../resources/rs-utils.js" + ], + [ + "script", + "../resources/test-utils.js" + ], + [ + "script", + "../resources/recording-streams.js" + ], + [ + "script", + "../resources/rs-test-templates.js" + ] + ] + } + ], + [ + "streams/readable-byte-streams/tee.any.worker.html", + { + "script_metadata": [ + [ + "global", + "window,worker,jsshell" + ], + [ + "script", + "../resources/rs-utils.js" + ], + [ + "script", + "../resources/test-utils.js" + ], + [ + "script", + "../resources/recording-streams.js" + ], + [ + "script", + "../resources/rs-test-templates.js" + ] + ] + } + ] ] }, "readable-streams": { @@ -469449,7 +469982,7 @@ ] ], "tee.any.js": [ - "761f6e9c3599c19f78d7635eeca5cbe3bef2a4b7", + "14c447be7296eaec984b7cfd45b58d2a5ae9a57a", [ null, { @@ -469470,6 +470003,10 @@ [ "script", "../resources/recording-streams.js" + ], + [ + "script", + "../resources/rs-test-templates.js" ] ] } @@ -469493,6 +470030,10 @@ [ "script", "../resources/recording-streams.js" + ], + [ + "script", + "../resources/rs-test-templates.js" ] ] } @@ -469516,6 +470057,10 @@ [ "script", "../resources/recording-streams.js" + ], + [ + "script", + "../resources/rs-test-templates.js" ] ] } @@ -469539,6 +470084,10 @@ [ "script", "../resources/recording-streams.js" + ], + [ + "script", + "../resources/rs-test-templates.js" ] ] } @@ -469562,6 +470111,10 @@ [ "script", "../resources/recording-streams.js" + ], + [ + "script", + "../resources/rs-test-templates.js" ] ] } @@ -475302,7 +475855,7 @@ ] ], "require-trusted-types-for.tentative.html": [ - "bf3dedd978c3810e24e61454086977dfbbca1237", + "2a3820a89b8ad36c324139bf75fab8d72d7087a4", [ null, {} @@ -477979,7 +478532,7 @@ ] ], "url-constructor.any.js": [ - "3f4af56d2a9654f323f912c5a6e64686c415da42", + "dfa98092fa64758ce6927f9770818b334e33e6c1", [ "url/url-constructor.any.html", { @@ -478006,7 +478559,7 @@ ] ], "url-origin.any.js": [ - "d9ef64c73b8bcc7fe37d94e6b77a5b8d967a0f0f", + "9c1f97ed2e59493d807c5d3694ae48c6b6975f5a", [ "url/url-origin.any.html", {} @@ -486664,7 +487217,7 @@ }, "webcodecs": { "audio-data-serialization.any.js": [ - "3d42aec8edf16a428c94cd0f06185af3df98d22a", + "0af59e9e40146943583e1dbece43102eb15fecbe", [ "webcodecs/audio-data-serialization.any.html", { @@ -486686,7 +487239,7 @@ ] ], "audio-data.any.js": [ - "e196cb8d8e896dbe7c8fa00b1945b2f7dbddfdcf", + "02d4f8fdfb0e7c04d2c4a6dae93fc5a4dfc93d74", [ "webcodecs/audio-data.any.html", { @@ -486774,7 +487327,7 @@ ] ], "audio-encoder.any.js": [ - "da120a3ddea6f5d18aa115ad4108dd6f5ae3b959", + "c8d924faf305231de173d4966432c77024bcc031", [ "webcodecs/audio-encoder.any.html", { @@ -487517,7 +488070,7 @@ ] ], "videoDecoder-codec-specific.any.js": [ - "233e292226d86a265ddd29d28b7357236849e1cc", + "16a35e3c98b68ae74a2ba7d79b822684e4078f2b", [ "webcodecs/videoDecoder-codec-specific.any.html?av1", { @@ -487862,7 +488415,7 @@ ] ], "videoFrame-copyTo.any.js": [ - "9365085afc6839b7e9758c2e6621bdb434690b8d", + "0a5f6fd2086bc830955d4db7fe9ddfb3f589acce", [ "webcodecs/videoFrame-copyTo.any.html", { @@ -487994,7 +488547,7 @@ ] ], "videoFrame.any.js": [ - "6cc9814c692ef3faf7aa3ea8e09beb4b7376489e", + "a67a1b260d1cc34c1c89544a054eca983204c794", [ "webcodecs/videoFrame.any.html", {
diff --git a/third_party/blink/web_tests/external/wpt/css/css-color/webkit-focus-ring-color.tentative-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-color/webkit-focus-ring-color.tentative-expected.txt new file mode 100644 index 0000000..1297e17e --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-color/webkit-focus-ring-color.tentative-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL -webkit-focus-ring-color is supported for compat assert_true: expected true got false +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/css/css-color/webkit-focus-ring-color.tentative.html b/third_party/blink/web_tests/external/wpt/css/css-color/webkit-focus-ring-color.tentative.html new file mode 100644 index 0000000..b79e16db --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-color/webkit-focus-ring-color.tentative.html
@@ -0,0 +1,10 @@ +<!doctype html> +<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1718934"> +<title>-webkit-focus-ring-color is supported for compat</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> +test(function() { + assert_true(CSS.supports("color", "-webkit-focus-ring-color")); +}); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-fonts/animations/font-size-adjust-interpolation-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-fonts/animations/font-size-adjust-interpolation-expected.txt index 3dd91183..05d041d5 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-fonts/animations/font-size-adjust-interpolation-expected.txt +++ b/third_party/blink/web_tests/external/wpt/css/css-fonts/animations/font-size-adjust-interpolation-expected.txt
@@ -56,34 +56,34 @@ PASS Web Animations: property <font-size-adjust> from [initial] to [2] at (0.6) should be [2] PASS Web Animations: property <font-size-adjust> from [initial] to [2] at (1) should be [2] PASS Web Animations: property <font-size-adjust> from [initial] to [2] at (1.5) should be [2] -FAIL CSS Transitions: property <font-size-adjust> from [initial] to [cap 2] at (-0.3) should be [cap 2] assert_true: 'to' value should be supported expected true got false -FAIL CSS Transitions: property <font-size-adjust> from [initial] to [cap 2] at (0) should be [cap 2] assert_true: 'to' value should be supported expected true got false -FAIL CSS Transitions: property <font-size-adjust> from [initial] to [cap 2] at (0.3) should be [cap 2] assert_true: 'to' value should be supported expected true got false -FAIL CSS Transitions: property <font-size-adjust> from [initial] to [cap 2] at (0.5) should be [cap 2] assert_true: 'to' value should be supported expected true got false -FAIL CSS Transitions: property <font-size-adjust> from [initial] to [cap 2] at (0.6) should be [cap 2] assert_true: 'to' value should be supported expected true got false -FAIL CSS Transitions: property <font-size-adjust> from [initial] to [cap 2] at (1) should be [cap 2] assert_true: 'to' value should be supported expected true got false -FAIL CSS Transitions: property <font-size-adjust> from [initial] to [cap 2] at (1.5) should be [cap 2] assert_true: 'to' value should be supported expected true got false -FAIL CSS Transitions with transition: all: property <font-size-adjust> from [initial] to [cap 2] at (-0.3) should be [cap 2] assert_true: 'to' value should be supported expected true got false -FAIL CSS Transitions with transition: all: property <font-size-adjust> from [initial] to [cap 2] at (0) should be [cap 2] assert_true: 'to' value should be supported expected true got false -FAIL CSS Transitions with transition: all: property <font-size-adjust> from [initial] to [cap 2] at (0.3) should be [cap 2] assert_true: 'to' value should be supported expected true got false -FAIL CSS Transitions with transition: all: property <font-size-adjust> from [initial] to [cap 2] at (0.5) should be [cap 2] assert_true: 'to' value should be supported expected true got false -FAIL CSS Transitions with transition: all: property <font-size-adjust> from [initial] to [cap 2] at (0.6) should be [cap 2] assert_true: 'to' value should be supported expected true got false -FAIL CSS Transitions with transition: all: property <font-size-adjust> from [initial] to [cap 2] at (1) should be [cap 2] assert_true: 'to' value should be supported expected true got false -FAIL CSS Transitions with transition: all: property <font-size-adjust> from [initial] to [cap 2] at (1.5) should be [cap 2] assert_true: 'to' value should be supported expected true got false -FAIL CSS Animations: property <font-size-adjust> from [initial] to [cap 2] at (-0.3) should be [initial] assert_true: 'to' value should be supported expected true got false -FAIL CSS Animations: property <font-size-adjust> from [initial] to [cap 2] at (0) should be [initial] assert_true: 'to' value should be supported expected true got false -FAIL CSS Animations: property <font-size-adjust> from [initial] to [cap 2] at (0.3) should be [initial] assert_true: 'to' value should be supported expected true got false -FAIL CSS Animations: property <font-size-adjust> from [initial] to [cap 2] at (0.5) should be [cap 2] assert_true: 'to' value should be supported expected true got false -FAIL CSS Animations: property <font-size-adjust> from [initial] to [cap 2] at (0.6) should be [cap 2] assert_true: 'to' value should be supported expected true got false -FAIL CSS Animations: property <font-size-adjust> from [initial] to [cap 2] at (1) should be [cap 2] assert_true: 'to' value should be supported expected true got false -FAIL CSS Animations: property <font-size-adjust> from [initial] to [cap 2] at (1.5) should be [cap 2] assert_true: 'to' value should be supported expected true got false -FAIL Web Animations: property <font-size-adjust> from [initial] to [cap 2] at (-0.3) should be [initial] assert_true: 'to' value should be supported expected true got false -FAIL Web Animations: property <font-size-adjust> from [initial] to [cap 2] at (0) should be [initial] assert_true: 'to' value should be supported expected true got false -FAIL Web Animations: property <font-size-adjust> from [initial] to [cap 2] at (0.3) should be [initial] assert_true: 'to' value should be supported expected true got false -FAIL Web Animations: property <font-size-adjust> from [initial] to [cap 2] at (0.5) should be [cap 2] assert_true: 'to' value should be supported expected true got false -FAIL Web Animations: property <font-size-adjust> from [initial] to [cap 2] at (0.6) should be [cap 2] assert_true: 'to' value should be supported expected true got false -FAIL Web Animations: property <font-size-adjust> from [initial] to [cap 2] at (1) should be [cap 2] assert_true: 'to' value should be supported expected true got false -FAIL Web Animations: property <font-size-adjust> from [initial] to [cap 2] at (1.5) should be [cap 2] assert_true: 'to' value should be supported expected true got false +FAIL CSS Transitions: property <font-size-adjust> from [initial] to [cap-height 2] at (-0.3) should be [cap-height 2] assert_true: 'to' value should be supported expected true got false +FAIL CSS Transitions: property <font-size-adjust> from [initial] to [cap-height 2] at (0) should be [cap-height 2] assert_true: 'to' value should be supported expected true got false +FAIL CSS Transitions: property <font-size-adjust> from [initial] to [cap-height 2] at (0.3) should be [cap-height 2] assert_true: 'to' value should be supported expected true got false +FAIL CSS Transitions: property <font-size-adjust> from [initial] to [cap-height 2] at (0.5) should be [cap-height 2] assert_true: 'to' value should be supported expected true got false +FAIL CSS Transitions: property <font-size-adjust> from [initial] to [cap-height 2] at (0.6) should be [cap-height 2] assert_true: 'to' value should be supported expected true got false +FAIL CSS Transitions: property <font-size-adjust> from [initial] to [cap-height 2] at (1) should be [cap-height 2] assert_true: 'to' value should be supported expected true got false +FAIL CSS Transitions: property <font-size-adjust> from [initial] to [cap-height 2] at (1.5) should be [cap-height 2] assert_true: 'to' value should be supported expected true got false +FAIL CSS Transitions with transition: all: property <font-size-adjust> from [initial] to [cap-height 2] at (-0.3) should be [cap-height 2] assert_true: 'to' value should be supported expected true got false +FAIL CSS Transitions with transition: all: property <font-size-adjust> from [initial] to [cap-height 2] at (0) should be [cap-height 2] assert_true: 'to' value should be supported expected true got false +FAIL CSS Transitions with transition: all: property <font-size-adjust> from [initial] to [cap-height 2] at (0.3) should be [cap-height 2] assert_true: 'to' value should be supported expected true got false +FAIL CSS Transitions with transition: all: property <font-size-adjust> from [initial] to [cap-height 2] at (0.5) should be [cap-height 2] assert_true: 'to' value should be supported expected true got false +FAIL CSS Transitions with transition: all: property <font-size-adjust> from [initial] to [cap-height 2] at (0.6) should be [cap-height 2] assert_true: 'to' value should be supported expected true got false +FAIL CSS Transitions with transition: all: property <font-size-adjust> from [initial] to [cap-height 2] at (1) should be [cap-height 2] assert_true: 'to' value should be supported expected true got false +FAIL CSS Transitions with transition: all: property <font-size-adjust> from [initial] to [cap-height 2] at (1.5) should be [cap-height 2] assert_true: 'to' value should be supported expected true got false +FAIL CSS Animations: property <font-size-adjust> from [initial] to [cap-height 2] at (-0.3) should be [initial] assert_true: 'to' value should be supported expected true got false +FAIL CSS Animations: property <font-size-adjust> from [initial] to [cap-height 2] at (0) should be [initial] assert_true: 'to' value should be supported expected true got false +FAIL CSS Animations: property <font-size-adjust> from [initial] to [cap-height 2] at (0.3) should be [initial] assert_true: 'to' value should be supported expected true got false +FAIL CSS Animations: property <font-size-adjust> from [initial] to [cap-height 2] at (0.5) should be [cap-height 2] assert_true: 'to' value should be supported expected true got false +FAIL CSS Animations: property <font-size-adjust> from [initial] to [cap-height 2] at (0.6) should be [cap-height 2] assert_true: 'to' value should be supported expected true got false +FAIL CSS Animations: property <font-size-adjust> from [initial] to [cap-height 2] at (1) should be [cap-height 2] assert_true: 'to' value should be supported expected true got false +FAIL CSS Animations: property <font-size-adjust> from [initial] to [cap-height 2] at (1.5) should be [cap-height 2] assert_true: 'to' value should be supported expected true got false +FAIL Web Animations: property <font-size-adjust> from [initial] to [cap-height 2] at (-0.3) should be [initial] assert_true: 'to' value should be supported expected true got false +FAIL Web Animations: property <font-size-adjust> from [initial] to [cap-height 2] at (0) should be [initial] assert_true: 'to' value should be supported expected true got false +FAIL Web Animations: property <font-size-adjust> from [initial] to [cap-height 2] at (0.3) should be [initial] assert_true: 'to' value should be supported expected true got false +FAIL Web Animations: property <font-size-adjust> from [initial] to [cap-height 2] at (0.5) should be [cap-height 2] assert_true: 'to' value should be supported expected true got false +FAIL Web Animations: property <font-size-adjust> from [initial] to [cap-height 2] at (0.6) should be [cap-height 2] assert_true: 'to' value should be supported expected true got false +FAIL Web Animations: property <font-size-adjust> from [initial] to [cap-height 2] at (1) should be [cap-height 2] assert_true: 'to' value should be supported expected true got false +FAIL Web Animations: property <font-size-adjust> from [initial] to [cap-height 2] at (1.5) should be [cap-height 2] assert_true: 'to' value should be supported expected true got false PASS CSS Transitions: property <font-size-adjust> from [inherit] to [2] at (-2) should be [5] PASS CSS Transitions: property <font-size-adjust> from [inherit] to [2] at (-0.3) should be [3.3] PASS CSS Transitions: property <font-size-adjust> from [inherit] to [2] at (0) should be [3] @@ -168,34 +168,34 @@ PASS Web Animations: property <font-size-adjust> from [0] to [1.2] at (0.6) should be [0.72] PASS Web Animations: property <font-size-adjust> from [0] to [1.2] at (1) should be [1.2] PASS Web Animations: property <font-size-adjust> from [0] to [1.2] at (1.5) should be [1.8] -FAIL CSS Transitions: property <font-size-adjust> from [cap 0] to [cap 1.2] at (-2) should be [cap 0] assert_true: 'from' value should be supported expected true got false -FAIL CSS Transitions: property <font-size-adjust> from [cap 0] to [cap 1.2] at (-0.3) should be [cap 0] assert_true: 'from' value should be supported expected true got false -FAIL CSS Transitions: property <font-size-adjust> from [cap 0] to [cap 1.2] at (0) should be [cap 0] assert_true: 'from' value should be supported expected true got false -FAIL CSS Transitions: property <font-size-adjust> from [cap 0] to [cap 1.2] at (0.3) should be [cap 0.36] assert_true: 'from' value should be supported expected true got false -FAIL CSS Transitions: property <font-size-adjust> from [cap 0] to [cap 1.2] at (0.6) should be [cap 0.72] assert_true: 'from' value should be supported expected true got false -FAIL CSS Transitions: property <font-size-adjust> from [cap 0] to [cap 1.2] at (1) should be [cap 1.2] assert_true: 'from' value should be supported expected true got false -FAIL CSS Transitions: property <font-size-adjust> from [cap 0] to [cap 1.2] at (1.5) should be [cap 1.8] assert_true: 'from' value should be supported expected true got false -FAIL CSS Transitions with transition: all: property <font-size-adjust> from [cap 0] to [cap 1.2] at (-2) should be [cap 0] assert_true: 'from' value should be supported expected true got false -FAIL CSS Transitions with transition: all: property <font-size-adjust> from [cap 0] to [cap 1.2] at (-0.3) should be [cap 0] assert_true: 'from' value should be supported expected true got false -FAIL CSS Transitions with transition: all: property <font-size-adjust> from [cap 0] to [cap 1.2] at (0) should be [cap 0] assert_true: 'from' value should be supported expected true got false -FAIL CSS Transitions with transition: all: property <font-size-adjust> from [cap 0] to [cap 1.2] at (0.3) should be [cap 0.36] assert_true: 'from' value should be supported expected true got false -FAIL CSS Transitions with transition: all: property <font-size-adjust> from [cap 0] to [cap 1.2] at (0.6) should be [cap 0.72] assert_true: 'from' value should be supported expected true got false -FAIL CSS Transitions with transition: all: property <font-size-adjust> from [cap 0] to [cap 1.2] at (1) should be [cap 1.2] assert_true: 'from' value should be supported expected true got false -FAIL CSS Transitions with transition: all: property <font-size-adjust> from [cap 0] to [cap 1.2] at (1.5) should be [cap 1.8] assert_true: 'from' value should be supported expected true got false -FAIL CSS Animations: property <font-size-adjust> from [cap 0] to [cap 1.2] at (-2) should be [cap 0] assert_true: 'from' value should be supported expected true got false -FAIL CSS Animations: property <font-size-adjust> from [cap 0] to [cap 1.2] at (-0.3) should be [cap 0] assert_true: 'from' value should be supported expected true got false -FAIL CSS Animations: property <font-size-adjust> from [cap 0] to [cap 1.2] at (0) should be [cap 0] assert_true: 'from' value should be supported expected true got false -FAIL CSS Animations: property <font-size-adjust> from [cap 0] to [cap 1.2] at (0.3) should be [cap 0.36] assert_true: 'from' value should be supported expected true got false -FAIL CSS Animations: property <font-size-adjust> from [cap 0] to [cap 1.2] at (0.6) should be [cap 0.72] assert_true: 'from' value should be supported expected true got false -FAIL CSS Animations: property <font-size-adjust> from [cap 0] to [cap 1.2] at (1) should be [cap 1.2] assert_true: 'from' value should be supported expected true got false -FAIL CSS Animations: property <font-size-adjust> from [cap 0] to [cap 1.2] at (1.5) should be [cap 1.8] assert_true: 'from' value should be supported expected true got false -FAIL Web Animations: property <font-size-adjust> from [cap 0] to [cap 1.2] at (-2) should be [cap 0] assert_true: 'from' value should be supported expected true got false -FAIL Web Animations: property <font-size-adjust> from [cap 0] to [cap 1.2] at (-0.3) should be [cap 0] assert_true: 'from' value should be supported expected true got false -FAIL Web Animations: property <font-size-adjust> from [cap 0] to [cap 1.2] at (0) should be [cap 0] assert_true: 'from' value should be supported expected true got false -FAIL Web Animations: property <font-size-adjust> from [cap 0] to [cap 1.2] at (0.3) should be [cap 0.36] assert_true: 'from' value should be supported expected true got false -FAIL Web Animations: property <font-size-adjust> from [cap 0] to [cap 1.2] at (0.6) should be [cap 0.72] assert_true: 'from' value should be supported expected true got false -FAIL Web Animations: property <font-size-adjust> from [cap 0] to [cap 1.2] at (1) should be [cap 1.2] assert_true: 'from' value should be supported expected true got false -FAIL Web Animations: property <font-size-adjust> from [cap 0] to [cap 1.2] at (1.5) should be [cap 1.8] assert_true: 'from' value should be supported expected true got false +FAIL CSS Transitions: property <font-size-adjust> from [cap-height 0] to [cap-height 1.2] at (-2) should be [cap-height 0] assert_true: 'from' value should be supported expected true got false +FAIL CSS Transitions: property <font-size-adjust> from [cap-height 0] to [cap-height 1.2] at (-0.3) should be [cap-height 0] assert_true: 'from' value should be supported expected true got false +FAIL CSS Transitions: property <font-size-adjust> from [cap-height 0] to [cap-height 1.2] at (0) should be [cap-height 0] assert_true: 'from' value should be supported expected true got false +FAIL CSS Transitions: property <font-size-adjust> from [cap-height 0] to [cap-height 1.2] at (0.3) should be [cap-height 0.36] assert_true: 'from' value should be supported expected true got false +FAIL CSS Transitions: property <font-size-adjust> from [cap-height 0] to [cap-height 1.2] at (0.6) should be [cap-height 0.72] assert_true: 'from' value should be supported expected true got false +FAIL CSS Transitions: property <font-size-adjust> from [cap-height 0] to [cap-height 1.2] at (1) should be [cap-height 1.2] assert_true: 'from' value should be supported expected true got false +FAIL CSS Transitions: property <font-size-adjust> from [cap-height 0] to [cap-height 1.2] at (1.5) should be [cap-height 1.8] assert_true: 'from' value should be supported expected true got false +FAIL CSS Transitions with transition: all: property <font-size-adjust> from [cap-height 0] to [cap-height 1.2] at (-2) should be [cap-height 0] assert_true: 'from' value should be supported expected true got false +FAIL CSS Transitions with transition: all: property <font-size-adjust> from [cap-height 0] to [cap-height 1.2] at (-0.3) should be [cap-height 0] assert_true: 'from' value should be supported expected true got false +FAIL CSS Transitions with transition: all: property <font-size-adjust> from [cap-height 0] to [cap-height 1.2] at (0) should be [cap-height 0] assert_true: 'from' value should be supported expected true got false +FAIL CSS Transitions with transition: all: property <font-size-adjust> from [cap-height 0] to [cap-height 1.2] at (0.3) should be [cap-height 0.36] assert_true: 'from' value should be supported expected true got false +FAIL CSS Transitions with transition: all: property <font-size-adjust> from [cap-height 0] to [cap-height 1.2] at (0.6) should be [cap-height 0.72] assert_true: 'from' value should be supported expected true got false +FAIL CSS Transitions with transition: all: property <font-size-adjust> from [cap-height 0] to [cap-height 1.2] at (1) should be [cap-height 1.2] assert_true: 'from' value should be supported expected true got false +FAIL CSS Transitions with transition: all: property <font-size-adjust> from [cap-height 0] to [cap-height 1.2] at (1.5) should be [cap-height 1.8] assert_true: 'from' value should be supported expected true got false +FAIL CSS Animations: property <font-size-adjust> from [cap-height 0] to [cap-height 1.2] at (-2) should be [cap-height 0] assert_true: 'from' value should be supported expected true got false +FAIL CSS Animations: property <font-size-adjust> from [cap-height 0] to [cap-height 1.2] at (-0.3) should be [cap-height 0] assert_true: 'from' value should be supported expected true got false +FAIL CSS Animations: property <font-size-adjust> from [cap-height 0] to [cap-height 1.2] at (0) should be [cap-height 0] assert_true: 'from' value should be supported expected true got false +FAIL CSS Animations: property <font-size-adjust> from [cap-height 0] to [cap-height 1.2] at (0.3) should be [cap-height 0.36] assert_true: 'from' value should be supported expected true got false +FAIL CSS Animations: property <font-size-adjust> from [cap-height 0] to [cap-height 1.2] at (0.6) should be [cap-height 0.72] assert_true: 'from' value should be supported expected true got false +FAIL CSS Animations: property <font-size-adjust> from [cap-height 0] to [cap-height 1.2] at (1) should be [cap-height 1.2] assert_true: 'from' value should be supported expected true got false +FAIL CSS Animations: property <font-size-adjust> from [cap-height 0] to [cap-height 1.2] at (1.5) should be [cap-height 1.8] assert_true: 'from' value should be supported expected true got false +FAIL Web Animations: property <font-size-adjust> from [cap-height 0] to [cap-height 1.2] at (-2) should be [cap-height 0] assert_true: 'from' value should be supported expected true got false +FAIL Web Animations: property <font-size-adjust> from [cap-height 0] to [cap-height 1.2] at (-0.3) should be [cap-height 0] assert_true: 'from' value should be supported expected true got false +FAIL Web Animations: property <font-size-adjust> from [cap-height 0] to [cap-height 1.2] at (0) should be [cap-height 0] assert_true: 'from' value should be supported expected true got false +FAIL Web Animations: property <font-size-adjust> from [cap-height 0] to [cap-height 1.2] at (0.3) should be [cap-height 0.36] assert_true: 'from' value should be supported expected true got false +FAIL Web Animations: property <font-size-adjust> from [cap-height 0] to [cap-height 1.2] at (0.6) should be [cap-height 0.72] assert_true: 'from' value should be supported expected true got false +FAIL Web Animations: property <font-size-adjust> from [cap-height 0] to [cap-height 1.2] at (1) should be [cap-height 1.2] assert_true: 'from' value should be supported expected true got false +FAIL Web Animations: property <font-size-adjust> from [cap-height 0] to [cap-height 1.2] at (1.5) should be [cap-height 1.8] assert_true: 'from' value should be supported expected true got false PASS CSS Transitions: property <font-size-adjust> from [none] to [1.2] at (-0.3) should be [1.2] PASS CSS Transitions: property <font-size-adjust> from [none] to [1.2] at (0) should be [1.2] PASS CSS Transitions: property <font-size-adjust> from [none] to [1.2] at (0.3) should be [1.2] @@ -224,34 +224,34 @@ PASS Web Animations: property <font-size-adjust> from [none] to [1.2] at (0.6) should be [1.2] PASS Web Animations: property <font-size-adjust> from [none] to [1.2] at (1) should be [1.2] PASS Web Animations: property <font-size-adjust> from [none] to [1.2] at (1.5) should be [1.2] -FAIL CSS Transitions: property <font-size-adjust> from [none] to [cap 1.2] at (-0.3) should be [cap 1.2] assert_true: 'to' value should be supported expected true got false -FAIL CSS Transitions: property <font-size-adjust> from [none] to [cap 1.2] at (0) should be [cap 1.2] assert_true: 'to' value should be supported expected true got false -FAIL CSS Transitions: property <font-size-adjust> from [none] to [cap 1.2] at (0.3) should be [cap 1.2] assert_true: 'to' value should be supported expected true got false -FAIL CSS Transitions: property <font-size-adjust> from [none] to [cap 1.2] at (0.5) should be [cap 1.2] assert_true: 'to' value should be supported expected true got false -FAIL CSS Transitions: property <font-size-adjust> from [none] to [cap 1.2] at (0.6) should be [cap 1.2] assert_true: 'to' value should be supported expected true got false -FAIL CSS Transitions: property <font-size-adjust> from [none] to [cap 1.2] at (1) should be [cap 1.2] assert_true: 'to' value should be supported expected true got false -FAIL CSS Transitions: property <font-size-adjust> from [none] to [cap 1.2] at (1.5) should be [cap 1.2] assert_true: 'to' value should be supported expected true got false -FAIL CSS Transitions with transition: all: property <font-size-adjust> from [none] to [cap 1.2] at (-0.3) should be [cap 1.2] assert_true: 'to' value should be supported expected true got false -FAIL CSS Transitions with transition: all: property <font-size-adjust> from [none] to [cap 1.2] at (0) should be [cap 1.2] assert_true: 'to' value should be supported expected true got false -FAIL CSS Transitions with transition: all: property <font-size-adjust> from [none] to [cap 1.2] at (0.3) should be [cap 1.2] assert_true: 'to' value should be supported expected true got false -FAIL CSS Transitions with transition: all: property <font-size-adjust> from [none] to [cap 1.2] at (0.5) should be [cap 1.2] assert_true: 'to' value should be supported expected true got false -FAIL CSS Transitions with transition: all: property <font-size-adjust> from [none] to [cap 1.2] at (0.6) should be [cap 1.2] assert_true: 'to' value should be supported expected true got false -FAIL CSS Transitions with transition: all: property <font-size-adjust> from [none] to [cap 1.2] at (1) should be [cap 1.2] assert_true: 'to' value should be supported expected true got false -FAIL CSS Transitions with transition: all: property <font-size-adjust> from [none] to [cap 1.2] at (1.5) should be [cap 1.2] assert_true: 'to' value should be supported expected true got false -FAIL CSS Animations: property <font-size-adjust> from [none] to [cap 1.2] at (-0.3) should be [none] assert_true: 'to' value should be supported expected true got false -FAIL CSS Animations: property <font-size-adjust> from [none] to [cap 1.2] at (0) should be [none] assert_true: 'to' value should be supported expected true got false -FAIL CSS Animations: property <font-size-adjust> from [none] to [cap 1.2] at (0.3) should be [none] assert_true: 'to' value should be supported expected true got false -FAIL CSS Animations: property <font-size-adjust> from [none] to [cap 1.2] at (0.5) should be [cap 1.2] assert_true: 'to' value should be supported expected true got false -FAIL CSS Animations: property <font-size-adjust> from [none] to [cap 1.2] at (0.6) should be [cap 1.2] assert_true: 'to' value should be supported expected true got false -FAIL CSS Animations: property <font-size-adjust> from [none] to [cap 1.2] at (1) should be [cap 1.2] assert_true: 'to' value should be supported expected true got false -FAIL CSS Animations: property <font-size-adjust> from [none] to [cap 1.2] at (1.5) should be [cap 1.2] assert_true: 'to' value should be supported expected true got false -FAIL Web Animations: property <font-size-adjust> from [none] to [cap 1.2] at (-0.3) should be [none] assert_true: 'to' value should be supported expected true got false -FAIL Web Animations: property <font-size-adjust> from [none] to [cap 1.2] at (0) should be [none] assert_true: 'to' value should be supported expected true got false -FAIL Web Animations: property <font-size-adjust> from [none] to [cap 1.2] at (0.3) should be [none] assert_true: 'to' value should be supported expected true got false -FAIL Web Animations: property <font-size-adjust> from [none] to [cap 1.2] at (0.5) should be [cap 1.2] assert_true: 'to' value should be supported expected true got false -FAIL Web Animations: property <font-size-adjust> from [none] to [cap 1.2] at (0.6) should be [cap 1.2] assert_true: 'to' value should be supported expected true got false -FAIL Web Animations: property <font-size-adjust> from [none] to [cap 1.2] at (1) should be [cap 1.2] assert_true: 'to' value should be supported expected true got false -FAIL Web Animations: property <font-size-adjust> from [none] to [cap 1.2] at (1.5) should be [cap 1.2] assert_true: 'to' value should be supported expected true got false +FAIL CSS Transitions: property <font-size-adjust> from [none] to [cap-height 1.2] at (-0.3) should be [cap-height 1.2] assert_true: 'to' value should be supported expected true got false +FAIL CSS Transitions: property <font-size-adjust> from [none] to [cap-height 1.2] at (0) should be [cap-height 1.2] assert_true: 'to' value should be supported expected true got false +FAIL CSS Transitions: property <font-size-adjust> from [none] to [cap-height 1.2] at (0.3) should be [cap-height 1.2] assert_true: 'to' value should be supported expected true got false +FAIL CSS Transitions: property <font-size-adjust> from [none] to [cap-height 1.2] at (0.5) should be [cap-height 1.2] assert_true: 'to' value should be supported expected true got false +FAIL CSS Transitions: property <font-size-adjust> from [none] to [cap-height 1.2] at (0.6) should be [cap-height 1.2] assert_true: 'to' value should be supported expected true got false +FAIL CSS Transitions: property <font-size-adjust> from [none] to [cap-height 1.2] at (1) should be [cap-height 1.2] assert_true: 'to' value should be supported expected true got false +FAIL CSS Transitions: property <font-size-adjust> from [none] to [cap-height 1.2] at (1.5) should be [cap-height 1.2] assert_true: 'to' value should be supported expected true got false +FAIL CSS Transitions with transition: all: property <font-size-adjust> from [none] to [cap-height 1.2] at (-0.3) should be [cap-height 1.2] assert_true: 'to' value should be supported expected true got false +FAIL CSS Transitions with transition: all: property <font-size-adjust> from [none] to [cap-height 1.2] at (0) should be [cap-height 1.2] assert_true: 'to' value should be supported expected true got false +FAIL CSS Transitions with transition: all: property <font-size-adjust> from [none] to [cap-height 1.2] at (0.3) should be [cap-height 1.2] assert_true: 'to' value should be supported expected true got false +FAIL CSS Transitions with transition: all: property <font-size-adjust> from [none] to [cap-height 1.2] at (0.5) should be [cap-height 1.2] assert_true: 'to' value should be supported expected true got false +FAIL CSS Transitions with transition: all: property <font-size-adjust> from [none] to [cap-height 1.2] at (0.6) should be [cap-height 1.2] assert_true: 'to' value should be supported expected true got false +FAIL CSS Transitions with transition: all: property <font-size-adjust> from [none] to [cap-height 1.2] at (1) should be [cap-height 1.2] assert_true: 'to' value should be supported expected true got false +FAIL CSS Transitions with transition: all: property <font-size-adjust> from [none] to [cap-height 1.2] at (1.5) should be [cap-height 1.2] assert_true: 'to' value should be supported expected true got false +FAIL CSS Animations: property <font-size-adjust> from [none] to [cap-height 1.2] at (-0.3) should be [none] assert_true: 'to' value should be supported expected true got false +FAIL CSS Animations: property <font-size-adjust> from [none] to [cap-height 1.2] at (0) should be [none] assert_true: 'to' value should be supported expected true got false +FAIL CSS Animations: property <font-size-adjust> from [none] to [cap-height 1.2] at (0.3) should be [none] assert_true: 'to' value should be supported expected true got false +FAIL CSS Animations: property <font-size-adjust> from [none] to [cap-height 1.2] at (0.5) should be [cap-height 1.2] assert_true: 'to' value should be supported expected true got false +FAIL CSS Animations: property <font-size-adjust> from [none] to [cap-height 1.2] at (0.6) should be [cap-height 1.2] assert_true: 'to' value should be supported expected true got false +FAIL CSS Animations: property <font-size-adjust> from [none] to [cap-height 1.2] at (1) should be [cap-height 1.2] assert_true: 'to' value should be supported expected true got false +FAIL CSS Animations: property <font-size-adjust> from [none] to [cap-height 1.2] at (1.5) should be [cap-height 1.2] assert_true: 'to' value should be supported expected true got false +FAIL Web Animations: property <font-size-adjust> from [none] to [cap-height 1.2] at (-0.3) should be [none] assert_true: 'to' value should be supported expected true got false +FAIL Web Animations: property <font-size-adjust> from [none] to [cap-height 1.2] at (0) should be [none] assert_true: 'to' value should be supported expected true got false +FAIL Web Animations: property <font-size-adjust> from [none] to [cap-height 1.2] at (0.3) should be [none] assert_true: 'to' value should be supported expected true got false +FAIL Web Animations: property <font-size-adjust> from [none] to [cap-height 1.2] at (0.5) should be [cap-height 1.2] assert_true: 'to' value should be supported expected true got false +FAIL Web Animations: property <font-size-adjust> from [none] to [cap-height 1.2] at (0.6) should be [cap-height 1.2] assert_true: 'to' value should be supported expected true got false +FAIL Web Animations: property <font-size-adjust> from [none] to [cap-height 1.2] at (1) should be [cap-height 1.2] assert_true: 'to' value should be supported expected true got false +FAIL Web Animations: property <font-size-adjust> from [none] to [cap-height 1.2] at (1.5) should be [cap-height 1.2] assert_true: 'to' value should be supported expected true got false PASS CSS Transitions: property <font-size-adjust> from [0.2] to [1.2] at (-2) should be [0] PASS CSS Transitions: property <font-size-adjust> from [0.2] to [1.2] at (-0.3) should be [0] PASS CSS Transitions: property <font-size-adjust> from [0.2] to [1.2] at (0) should be [0.2] @@ -280,61 +280,61 @@ PASS Web Animations: property <font-size-adjust> from [0.2] to [1.2] at (0.6) should be [0.8] PASS Web Animations: property <font-size-adjust> from [0.2] to [1.2] at (1) should be [1.2] PASS Web Animations: property <font-size-adjust> from [0.2] to [1.2] at (1.5) should be [1.7] -FAIL CSS Transitions: property <font-size-adjust> from [ch 0.2] to [ch 1.2] at (-2) should be [ch 0] assert_true: 'from' value should be supported expected true got false -FAIL CSS Transitions: property <font-size-adjust> from [ch 0.2] to [ch 1.2] at (-0.3) should be [ch 0] assert_true: 'from' value should be supported expected true got false -FAIL CSS Transitions: property <font-size-adjust> from [ch 0.2] to [ch 1.2] at (0) should be [ch 0.2] assert_true: 'from' value should be supported expected true got false -FAIL CSS Transitions: property <font-size-adjust> from [ch 0.2] to [ch 1.2] at (0.3) should be [ch 0.5] assert_true: 'from' value should be supported expected true got false -FAIL CSS Transitions: property <font-size-adjust> from [ch 0.2] to [ch 1.2] at (0.6) should be [ch 0.8] assert_true: 'from' value should be supported expected true got false -FAIL CSS Transitions: property <font-size-adjust> from [ch 0.2] to [ch 1.2] at (1) should be [ch 1.2] assert_true: 'from' value should be supported expected true got false -FAIL CSS Transitions: property <font-size-adjust> from [ch 0.2] to [ch 1.2] at (1.5) should be [ch 1.7] assert_true: 'from' value should be supported expected true got false -FAIL CSS Transitions with transition: all: property <font-size-adjust> from [ch 0.2] to [ch 1.2] at (-2) should be [ch 0] assert_true: 'from' value should be supported expected true got false -FAIL CSS Transitions with transition: all: property <font-size-adjust> from [ch 0.2] to [ch 1.2] at (-0.3) should be [ch 0] assert_true: 'from' value should be supported expected true got false -FAIL CSS Transitions with transition: all: property <font-size-adjust> from [ch 0.2] to [ch 1.2] at (0) should be [ch 0.2] assert_true: 'from' value should be supported expected true got false -FAIL CSS Transitions with transition: all: property <font-size-adjust> from [ch 0.2] to [ch 1.2] at (0.3) should be [ch 0.5] assert_true: 'from' value should be supported expected true got false -FAIL CSS Transitions with transition: all: property <font-size-adjust> from [ch 0.2] to [ch 1.2] at (0.6) should be [ch 0.8] assert_true: 'from' value should be supported expected true got false -FAIL CSS Transitions with transition: all: property <font-size-adjust> from [ch 0.2] to [ch 1.2] at (1) should be [ch 1.2] assert_true: 'from' value should be supported expected true got false -FAIL CSS Transitions with transition: all: property <font-size-adjust> from [ch 0.2] to [ch 1.2] at (1.5) should be [ch 1.7] assert_true: 'from' value should be supported expected true got false -FAIL CSS Animations: property <font-size-adjust> from [ch 0.2] to [ch 1.2] at (-2) should be [ch 0] assert_true: 'from' value should be supported expected true got false -FAIL CSS Animations: property <font-size-adjust> from [ch 0.2] to [ch 1.2] at (-0.3) should be [ch 0] assert_true: 'from' value should be supported expected true got false -FAIL CSS Animations: property <font-size-adjust> from [ch 0.2] to [ch 1.2] at (0) should be [ch 0.2] assert_true: 'from' value should be supported expected true got false -FAIL CSS Animations: property <font-size-adjust> from [ch 0.2] to [ch 1.2] at (0.3) should be [ch 0.5] assert_true: 'from' value should be supported expected true got false -FAIL CSS Animations: property <font-size-adjust> from [ch 0.2] to [ch 1.2] at (0.6) should be [ch 0.8] assert_true: 'from' value should be supported expected true got false -FAIL CSS Animations: property <font-size-adjust> from [ch 0.2] to [ch 1.2] at (1) should be [ch 1.2] assert_true: 'from' value should be supported expected true got false -FAIL CSS Animations: property <font-size-adjust> from [ch 0.2] to [ch 1.2] at (1.5) should be [ch 1.7] assert_true: 'from' value should be supported expected true got false -FAIL Web Animations: property <font-size-adjust> from [ch 0.2] to [ch 1.2] at (-2) should be [ch 0] assert_true: 'from' value should be supported expected true got false -FAIL Web Animations: property <font-size-adjust> from [ch 0.2] to [ch 1.2] at (-0.3) should be [ch 0] assert_true: 'from' value should be supported expected true got false -FAIL Web Animations: property <font-size-adjust> from [ch 0.2] to [ch 1.2] at (0) should be [ch 0.2] assert_true: 'from' value should be supported expected true got false -FAIL Web Animations: property <font-size-adjust> from [ch 0.2] to [ch 1.2] at (0.3) should be [ch 0.5] assert_true: 'from' value should be supported expected true got false -FAIL Web Animations: property <font-size-adjust> from [ch 0.2] to [ch 1.2] at (0.6) should be [ch 0.8] assert_true: 'from' value should be supported expected true got false -FAIL Web Animations: property <font-size-adjust> from [ch 0.2] to [ch 1.2] at (1) should be [ch 1.2] assert_true: 'from' value should be supported expected true got false -FAIL Web Animations: property <font-size-adjust> from [ch 0.2] to [ch 1.2] at (1.5) should be [ch 1.7] assert_true: 'from' value should be supported expected true got false -FAIL CSS Transitions: property <font-size-adjust> from [ex 0.2] to [ch 1.2] at (-0.3) should be [ch 1.2] assert_true: 'from' value should be supported expected true got false -FAIL CSS Transitions: property <font-size-adjust> from [ex 0.2] to [ch 1.2] at (0) should be [ch 1.2] assert_true: 'from' value should be supported expected true got false -FAIL CSS Transitions: property <font-size-adjust> from [ex 0.2] to [ch 1.2] at (0.3) should be [ch 1.2] assert_true: 'from' value should be supported expected true got false -FAIL CSS Transitions: property <font-size-adjust> from [ex 0.2] to [ch 1.2] at (0.5) should be [ch 1.2] assert_true: 'from' value should be supported expected true got false -FAIL CSS Transitions: property <font-size-adjust> from [ex 0.2] to [ch 1.2] at (0.6) should be [ch 1.2] assert_true: 'from' value should be supported expected true got false -FAIL CSS Transitions: property <font-size-adjust> from [ex 0.2] to [ch 1.2] at (1) should be [ch 1.2] assert_true: 'from' value should be supported expected true got false -FAIL CSS Transitions: property <font-size-adjust> from [ex 0.2] to [ch 1.2] at (1.5) should be [ch 1.2] assert_true: 'from' value should be supported expected true got false -FAIL CSS Transitions with transition: all: property <font-size-adjust> from [ex 0.2] to [ch 1.2] at (-0.3) should be [ch 1.2] assert_true: 'from' value should be supported expected true got false -FAIL CSS Transitions with transition: all: property <font-size-adjust> from [ex 0.2] to [ch 1.2] at (0) should be [ch 1.2] assert_true: 'from' value should be supported expected true got false -FAIL CSS Transitions with transition: all: property <font-size-adjust> from [ex 0.2] to [ch 1.2] at (0.3) should be [ch 1.2] assert_true: 'from' value should be supported expected true got false -FAIL CSS Transitions with transition: all: property <font-size-adjust> from [ex 0.2] to [ch 1.2] at (0.5) should be [ch 1.2] assert_true: 'from' value should be supported expected true got false -FAIL CSS Transitions with transition: all: property <font-size-adjust> from [ex 0.2] to [ch 1.2] at (0.6) should be [ch 1.2] assert_true: 'from' value should be supported expected true got false -FAIL CSS Transitions with transition: all: property <font-size-adjust> from [ex 0.2] to [ch 1.2] at (1) should be [ch 1.2] assert_true: 'from' value should be supported expected true got false -FAIL CSS Transitions with transition: all: property <font-size-adjust> from [ex 0.2] to [ch 1.2] at (1.5) should be [ch 1.2] assert_true: 'from' value should be supported expected true got false -FAIL CSS Animations: property <font-size-adjust> from [ex 0.2] to [ch 1.2] at (-0.3) should be [ex 0.2] assert_true: 'from' value should be supported expected true got false -FAIL CSS Animations: property <font-size-adjust> from [ex 0.2] to [ch 1.2] at (0) should be [ex 0.2] assert_true: 'from' value should be supported expected true got false -FAIL CSS Animations: property <font-size-adjust> from [ex 0.2] to [ch 1.2] at (0.3) should be [ex 0.2] assert_true: 'from' value should be supported expected true got false -FAIL CSS Animations: property <font-size-adjust> from [ex 0.2] to [ch 1.2] at (0.5) should be [ch 1.2] assert_true: 'from' value should be supported expected true got false -FAIL CSS Animations: property <font-size-adjust> from [ex 0.2] to [ch 1.2] at (0.6) should be [ch 1.2] assert_true: 'from' value should be supported expected true got false -FAIL CSS Animations: property <font-size-adjust> from [ex 0.2] to [ch 1.2] at (1) should be [ch 1.2] assert_true: 'from' value should be supported expected true got false -FAIL CSS Animations: property <font-size-adjust> from [ex 0.2] to [ch 1.2] at (1.5) should be [ch 1.2] assert_true: 'from' value should be supported expected true got false -FAIL Web Animations: property <font-size-adjust> from [ex 0.2] to [ch 1.2] at (-0.3) should be [ex 0.2] assert_true: 'from' value should be supported expected true got false -FAIL Web Animations: property <font-size-adjust> from [ex 0.2] to [ch 1.2] at (0) should be [ex 0.2] assert_true: 'from' value should be supported expected true got false -FAIL Web Animations: property <font-size-adjust> from [ex 0.2] to [ch 1.2] at (0.3) should be [ex 0.2] assert_true: 'from' value should be supported expected true got false -FAIL Web Animations: property <font-size-adjust> from [ex 0.2] to [ch 1.2] at (0.5) should be [ch 1.2] assert_true: 'from' value should be supported expected true got false -FAIL Web Animations: property <font-size-adjust> from [ex 0.2] to [ch 1.2] at (0.6) should be [ch 1.2] assert_true: 'from' value should be supported expected true got false -FAIL Web Animations: property <font-size-adjust> from [ex 0.2] to [ch 1.2] at (1) should be [ch 1.2] assert_true: 'from' value should be supported expected true got false -FAIL Web Animations: property <font-size-adjust> from [ex 0.2] to [ch 1.2] at (1.5) should be [ch 1.2] assert_true: 'from' value should be supported expected true got false +FAIL CSS Transitions: property <font-size-adjust> from [ch-width 0.2] to [ch-width 1.2] at (-2) should be [ch-width 0] assert_true: 'from' value should be supported expected true got false +FAIL CSS Transitions: property <font-size-adjust> from [ch-width 0.2] to [ch-width 1.2] at (-0.3) should be [ch-width 0] assert_true: 'from' value should be supported expected true got false +FAIL CSS Transitions: property <font-size-adjust> from [ch-width 0.2] to [ch-width 1.2] at (0) should be [ch-width 0.2] assert_true: 'from' value should be supported expected true got false +FAIL CSS Transitions: property <font-size-adjust> from [ch-width 0.2] to [ch-width 1.2] at (0.3) should be [ch-width 0.5] assert_true: 'from' value should be supported expected true got false +FAIL CSS Transitions: property <font-size-adjust> from [ch-width 0.2] to [ch-width 1.2] at (0.6) should be [ch-width 0.8] assert_true: 'from' value should be supported expected true got false +FAIL CSS Transitions: property <font-size-adjust> from [ch-width 0.2] to [ch-width 1.2] at (1) should be [ch-width 1.2] assert_true: 'from' value should be supported expected true got false +FAIL CSS Transitions: property <font-size-adjust> from [ch-width 0.2] to [ch-width 1.2] at (1.5) should be [ch-width 1.7] assert_true: 'from' value should be supported expected true got false +FAIL CSS Transitions with transition: all: property <font-size-adjust> from [ch-width 0.2] to [ch-width 1.2] at (-2) should be [ch-width 0] assert_true: 'from' value should be supported expected true got false +FAIL CSS Transitions with transition: all: property <font-size-adjust> from [ch-width 0.2] to [ch-width 1.2] at (-0.3) should be [ch-width 0] assert_true: 'from' value should be supported expected true got false +FAIL CSS Transitions with transition: all: property <font-size-adjust> from [ch-width 0.2] to [ch-width 1.2] at (0) should be [ch-width 0.2] assert_true: 'from' value should be supported expected true got false +FAIL CSS Transitions with transition: all: property <font-size-adjust> from [ch-width 0.2] to [ch-width 1.2] at (0.3) should be [ch-width 0.5] assert_true: 'from' value should be supported expected true got false +FAIL CSS Transitions with transition: all: property <font-size-adjust> from [ch-width 0.2] to [ch-width 1.2] at (0.6) should be [ch-width 0.8] assert_true: 'from' value should be supported expected true got false +FAIL CSS Transitions with transition: all: property <font-size-adjust> from [ch-width 0.2] to [ch-width 1.2] at (1) should be [ch-width 1.2] assert_true: 'from' value should be supported expected true got false +FAIL CSS Transitions with transition: all: property <font-size-adjust> from [ch-width 0.2] to [ch-width 1.2] at (1.5) should be [ch-width 1.7] assert_true: 'from' value should be supported expected true got false +FAIL CSS Animations: property <font-size-adjust> from [ch-width 0.2] to [ch-width 1.2] at (-2) should be [ch-width 0] assert_true: 'from' value should be supported expected true got false +FAIL CSS Animations: property <font-size-adjust> from [ch-width 0.2] to [ch-width 1.2] at (-0.3) should be [ch-width 0] assert_true: 'from' value should be supported expected true got false +FAIL CSS Animations: property <font-size-adjust> from [ch-width 0.2] to [ch-width 1.2] at (0) should be [ch-width 0.2] assert_true: 'from' value should be supported expected true got false +FAIL CSS Animations: property <font-size-adjust> from [ch-width 0.2] to [ch-width 1.2] at (0.3) should be [ch-width 0.5] assert_true: 'from' value should be supported expected true got false +FAIL CSS Animations: property <font-size-adjust> from [ch-width 0.2] to [ch-width 1.2] at (0.6) should be [ch-width 0.8] assert_true: 'from' value should be supported expected true got false +FAIL CSS Animations: property <font-size-adjust> from [ch-width 0.2] to [ch-width 1.2] at (1) should be [ch-width 1.2] assert_true: 'from' value should be supported expected true got false +FAIL CSS Animations: property <font-size-adjust> from [ch-width 0.2] to [ch-width 1.2] at (1.5) should be [ch-width 1.7] assert_true: 'from' value should be supported expected true got false +FAIL Web Animations: property <font-size-adjust> from [ch-width 0.2] to [ch-width 1.2] at (-2) should be [ch-width 0] assert_true: 'from' value should be supported expected true got false +FAIL Web Animations: property <font-size-adjust> from [ch-width 0.2] to [ch-width 1.2] at (-0.3) should be [ch-width 0] assert_true: 'from' value should be supported expected true got false +FAIL Web Animations: property <font-size-adjust> from [ch-width 0.2] to [ch-width 1.2] at (0) should be [ch-width 0.2] assert_true: 'from' value should be supported expected true got false +FAIL Web Animations: property <font-size-adjust> from [ch-width 0.2] to [ch-width 1.2] at (0.3) should be [ch-width 0.5] assert_true: 'from' value should be supported expected true got false +FAIL Web Animations: property <font-size-adjust> from [ch-width 0.2] to [ch-width 1.2] at (0.6) should be [ch-width 0.8] assert_true: 'from' value should be supported expected true got false +FAIL Web Animations: property <font-size-adjust> from [ch-width 0.2] to [ch-width 1.2] at (1) should be [ch-width 1.2] assert_true: 'from' value should be supported expected true got false +FAIL Web Animations: property <font-size-adjust> from [ch-width 0.2] to [ch-width 1.2] at (1.5) should be [ch-width 1.7] assert_true: 'from' value should be supported expected true got false +FAIL CSS Transitions: property <font-size-adjust> from [ex-height 0.2] to [cap-height 1.2] at (-0.3) should be [cap-height 1.2] assert_true: 'from' value should be supported expected true got false +FAIL CSS Transitions: property <font-size-adjust> from [ex-height 0.2] to [cap-height 1.2] at (0) should be [cap-height 1.2] assert_true: 'from' value should be supported expected true got false +FAIL CSS Transitions: property <font-size-adjust> from [ex-height 0.2] to [cap-height 1.2] at (0.3) should be [cap-height 1.2] assert_true: 'from' value should be supported expected true got false +FAIL CSS Transitions: property <font-size-adjust> from [ex-height 0.2] to [cap-height 1.2] at (0.5) should be [cap-height 1.2] assert_true: 'from' value should be supported expected true got false +FAIL CSS Transitions: property <font-size-adjust> from [ex-height 0.2] to [cap-height 1.2] at (0.6) should be [cap-height 1.2] assert_true: 'from' value should be supported expected true got false +FAIL CSS Transitions: property <font-size-adjust> from [ex-height 0.2] to [cap-height 1.2] at (1) should be [cap-height 1.2] assert_true: 'from' value should be supported expected true got false +FAIL CSS Transitions: property <font-size-adjust> from [ex-height 0.2] to [cap-height 1.2] at (1.5) should be [cap-height 1.2] assert_true: 'from' value should be supported expected true got false +FAIL CSS Transitions with transition: all: property <font-size-adjust> from [ex-height 0.2] to [cap-height 1.2] at (-0.3) should be [cap-height 1.2] assert_true: 'from' value should be supported expected true got false +FAIL CSS Transitions with transition: all: property <font-size-adjust> from [ex-height 0.2] to [cap-height 1.2] at (0) should be [cap-height 1.2] assert_true: 'from' value should be supported expected true got false +FAIL CSS Transitions with transition: all: property <font-size-adjust> from [ex-height 0.2] to [cap-height 1.2] at (0.3) should be [cap-height 1.2] assert_true: 'from' value should be supported expected true got false +FAIL CSS Transitions with transition: all: property <font-size-adjust> from [ex-height 0.2] to [cap-height 1.2] at (0.5) should be [cap-height 1.2] assert_true: 'from' value should be supported expected true got false +FAIL CSS Transitions with transition: all: property <font-size-adjust> from [ex-height 0.2] to [cap-height 1.2] at (0.6) should be [cap-height 1.2] assert_true: 'from' value should be supported expected true got false +FAIL CSS Transitions with transition: all: property <font-size-adjust> from [ex-height 0.2] to [cap-height 1.2] at (1) should be [cap-height 1.2] assert_true: 'from' value should be supported expected true got false +FAIL CSS Transitions with transition: all: property <font-size-adjust> from [ex-height 0.2] to [cap-height 1.2] at (1.5) should be [cap-height 1.2] assert_true: 'from' value should be supported expected true got false +FAIL CSS Animations: property <font-size-adjust> from [ex-height 0.2] to [cap-height 1.2] at (-0.3) should be [ex-height 0.2] assert_true: 'from' value should be supported expected true got false +FAIL CSS Animations: property <font-size-adjust> from [ex-height 0.2] to [cap-height 1.2] at (0) should be [ex-height 0.2] assert_true: 'from' value should be supported expected true got false +FAIL CSS Animations: property <font-size-adjust> from [ex-height 0.2] to [cap-height 1.2] at (0.3) should be [ex-height 0.2] assert_true: 'from' value should be supported expected true got false +FAIL CSS Animations: property <font-size-adjust> from [ex-height 0.2] to [cap-height 1.2] at (0.5) should be [cap-height 1.2] assert_true: 'from' value should be supported expected true got false +FAIL CSS Animations: property <font-size-adjust> from [ex-height 0.2] to [cap-height 1.2] at (0.6) should be [cap-height 1.2] assert_true: 'from' value should be supported expected true got false +FAIL CSS Animations: property <font-size-adjust> from [ex-height 0.2] to [cap-height 1.2] at (1) should be [cap-height 1.2] assert_true: 'from' value should be supported expected true got false +FAIL CSS Animations: property <font-size-adjust> from [ex-height 0.2] to [cap-height 1.2] at (1.5) should be [cap-height 1.2] assert_true: 'from' value should be supported expected true got false +FAIL Web Animations: property <font-size-adjust> from [ex-height 0.2] to [cap-height 1.2] at (-0.3) should be [ex-height 0.2] assert_true: 'from' value should be supported expected true got false +FAIL Web Animations: property <font-size-adjust> from [ex-height 0.2] to [cap-height 1.2] at (0) should be [ex-height 0.2] assert_true: 'from' value should be supported expected true got false +FAIL Web Animations: property <font-size-adjust> from [ex-height 0.2] to [cap-height 1.2] at (0.3) should be [ex-height 0.2] assert_true: 'from' value should be supported expected true got false +FAIL Web Animations: property <font-size-adjust> from [ex-height 0.2] to [cap-height 1.2] at (0.5) should be [cap-height 1.2] assert_true: 'from' value should be supported expected true got false +FAIL Web Animations: property <font-size-adjust> from [ex-height 0.2] to [cap-height 1.2] at (0.6) should be [cap-height 1.2] assert_true: 'from' value should be supported expected true got false +FAIL Web Animations: property <font-size-adjust> from [ex-height 0.2] to [cap-height 1.2] at (1) should be [cap-height 1.2] assert_true: 'from' value should be supported expected true got false +FAIL Web Animations: property <font-size-adjust> from [ex-height 0.2] to [cap-height 1.2] at (1.5) should be [cap-height 1.2] assert_true: 'from' value should be supported expected true got false Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/external/wpt/css/css-fonts/animations/font-size-adjust-interpolation.html b/third_party/blink/web_tests/external/wpt/css/css-fonts/animations/font-size-adjust-interpolation.html index dbb246b..a138d7f 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-fonts/animations/font-size-adjust-interpolation.html +++ b/third_party/blink/web_tests/external/wpt/css/css-fonts/animations/font-size-adjust-interpolation.html
@@ -61,7 +61,7 @@ test_no_interpolation({ property: 'font-size-adjust', from: 'initial', - to: 'cap 2', + to: 'cap-height 2', }); test_interpolation({ @@ -109,16 +109,16 @@ test_interpolation({ property: 'font-size-adjust', - from: 'cap 0', - to: 'cap 1.2' + from: 'cap-height 0', + to: 'cap-height 1.2' }, [ - {at: -2, expect: 'cap 0'}, - {at: -0.3, expect: 'cap 0'}, - {at: 0, expect: 'cap 0'}, - {at: 0.3, expect: 'cap 0.36'}, - {at: 0.6, expect: 'cap 0.72'}, - {at: 1, expect: 'cap 1.2'}, - {at: 1.5, expect: 'cap 1.8'}, + {at: -2, expect: 'cap-height 0'}, + {at: -0.3, expect: 'cap-height 0'}, + {at: 0, expect: 'cap-height 0'}, + {at: 0.3, expect: 'cap-height 0.36'}, + {at: 0.6, expect: 'cap-height 0.72'}, + {at: 1, expect: 'cap-height 1.2'}, + {at: 1.5, expect: 'cap-height 1.8'}, ]); test_no_interpolation({ @@ -130,7 +130,7 @@ test_no_interpolation({ property: 'font-size-adjust', from: 'none', - to: 'cap 1.2' + to: 'cap-height 1.2' }); test_interpolation({ @@ -149,21 +149,21 @@ test_interpolation({ property: 'font-size-adjust', - from: 'ch 0.2', - to: 'ch 1.2' + from: 'ch-width 0.2', + to: 'ch-width 1.2' }, [ - {at: -2, expect: 'ch 0'}, // CSS font-size-adjust can't be negative. - {at: -0.3, expect: 'ch 0'}, - {at: 0, expect: 'ch 0.2'}, - {at: 0.3, expect: 'ch 0.5'}, - {at: 0.6, expect: 'ch 0.8'}, - {at: 1, expect: 'ch 1.2'}, - {at: 1.5, expect: 'ch 1.7'}, + {at: -2, expect: 'ch-width 0'}, // CSS font-size-adjust can't be negative. + {at: -0.3, expect: 'ch-width 0'}, + {at: 0, expect: 'ch-width 0.2'}, + {at: 0.3, expect: 'ch-width 0.5'}, + {at: 0.6, expect: 'ch-width 0.8'}, + {at: 1, expect: 'ch-width 1.2'}, + {at: 1.5, expect: 'ch-width 1.7'}, ]); test_no_interpolation({ // can't interpolate between different adjustment basis property: 'font-size-adjust', - from: 'ex 0.2', - to: 'ch 1.2' + from: 'ex-height 0.2', + to: 'cap-height 1.2' }); </script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-fonts/font-size-adjust-009.html b/third_party/blink/web_tests/external/wpt/css/css-fonts/font-size-adjust-009.html index 108e15e..765447b2 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-fonts/font-size-adjust-009.html +++ b/third_party/blink/web_tests/external/wpt/css/css-fonts/font-size-adjust-009.html
@@ -1,12 +1,12 @@ <!DOCTYPE html> <meta charset="utf-8"> -<title>CSS Fonts Test: font-size-adjust - two-value syntax - using 'cap' as the basis for adjustment</title> +<title>CSS Fonts Test: font-size-adjust - two-value syntax - using 'cap-height' as the basis for adjustment</title> <link rel="author" title="Jonathan Kew" href="mailto:jkew@mozilla.com"> <link rel="help" title="2.6 Relative sizing: the font-size-adjust property" href="https://drafts.csswg.org/css-fonts-4/#font-size-adjust-prop"> <link rel="help" title="extend font-size-adjust to take a pair of values: <metric> <number>" href="https://github.com/w3c/csswg-drafts/issues/6160"> -<meta name="assert" content="Test checks that font-size-adjust with the 'cap' metric works as expected"> +<meta name="assert" content="Test checks that font-size-adjust with the 'cap-height' metric works as expected"> <link rel="match" href="font-size-adjust-009-ref.html"> <style> @font-face { @@ -24,17 +24,17 @@ #test1 { color: green; background: green; - font-size-adjust: cap calc(1462 / 2048); /* should cause no change */ + font-size-adjust: cap-height calc(1462 / 2048); /* should cause no change */ } #test2 { color: blue; background: blue; - font-size-adjust: cap calc(1.5 * 1462 / 2048); /* should be 1.5 times larger */ + font-size-adjust: cap-height calc(1.5 * 1462 / 2048); /* should be 1.5 times larger */ } #test3 { color: magenta; background: magenta; - font-size-adjust: cap calc(0.75 * 1462 / 2048); /* should be 0.75 times larger */ + font-size-adjust: cap-height calc(0.75 * 1462 / 2048); /* should be 0.75 times larger */ } </style> <body>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-fonts/font-size-adjust-010.html b/third_party/blink/web_tests/external/wpt/css/css-fonts/font-size-adjust-010.html index d3d3859..6ee3ab7 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-fonts/font-size-adjust-010.html +++ b/third_party/blink/web_tests/external/wpt/css/css-fonts/font-size-adjust-010.html
@@ -1,12 +1,12 @@ <!DOCTYPE html> <meta charset="utf-8"> -<title>CSS Fonts Test: font-size-adjust - two-value syntax - using 'ch' as the basis for adjustment</title> +<title>CSS Fonts Test: font-size-adjust - two-value syntax - using 'ch-width' as the basis for adjustment</title> <link rel="author" title="Jonathan Kew" href="mailto:jkew@mozilla.com"> <link rel="help" title="2.6 Relative sizing: the font-size-adjust property" href="https://drafts.csswg.org/css-fonts-4/#font-size-adjust-prop"> <link rel="help" title="extend font-size-adjust to take a pair of values: <metric> <number>" href="https://github.com/w3c/csswg-drafts/issues/6160"> -<meta name="assert" content="Test checks that font-size-adjust with the 'ch' metric works as expected"> +<meta name="assert" content="Test checks that font-size-adjust with the 'ch-width' metric works as expected"> <link rel="match" href="font-size-adjust-009-ref.html"> <style> @font-face { @@ -24,17 +24,17 @@ #test1 { color: green; background: green; - font-size-adjust: ch calc(1128 / 2048); /* should cause no change */ + font-size-adjust: ch-width calc(1128 / 2048); /* should cause no change */ } #test2 { color: blue; background: blue; - font-size-adjust: ch calc(1.5 * 1128 / 2048); /* should be 1.5 times larger */ + font-size-adjust: ch-width calc(1.5 * 1128 / 2048); /* should be 1.5 times larger */ } #test3 { color: magenta; background: magenta; - font-size-adjust: ch calc(0.75 * 1128 / 2048); /* should be 0.75 times larger */ + font-size-adjust: ch-width calc(0.75 * 1128 / 2048); /* should be 0.75 times larger */ } </style> <body>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-fonts/font-size-adjust-011.html b/third_party/blink/web_tests/external/wpt/css/css-fonts/font-size-adjust-011.html index 5e5c1a71..f4ac39c2 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-fonts/font-size-adjust-011.html +++ b/third_party/blink/web_tests/external/wpt/css/css-fonts/font-size-adjust-011.html
@@ -1,12 +1,12 @@ <!DOCTYPE html> <meta charset="utf-8"> -<title>CSS Fonts Test: font-size-adjust - two-value syntax - using 'ic' as the basis for adjustment</title> +<title>CSS Fonts Test: font-size-adjust - two-value syntax - using 'ic-width' as the basis for adjustment</title> <link rel="author" title="Jonathan Kew" href="mailto:jkew@mozilla.com"> <link rel="help" title="2.6 Relative sizing: the font-size-adjust property" href="https://drafts.csswg.org/css-fonts-4/#font-size-adjust-prop"> <link rel="help" title="extend font-size-adjust to take a pair of values: <metric> <number>" href="https://github.com/w3c/csswg-drafts/issues/6160"> -<meta name="assert" content="Test checks that font-size-adjust with the 'ic' metric works as expected"> +<meta name="assert" content="Test checks that font-size-adjust with the 'ic-width' metric works as expected"> <link rel="match" href="font-size-adjust-009-ref.html"> <style> @font-face { @@ -24,17 +24,17 @@ #test1 { color: green; background: green; - font-size-adjust: ic 1.0; /* should cause no change */ + font-size-adjust: ic-width 1.0; /* should cause no change */ } #test2 { color: blue; background: blue; - font-size-adjust: ic 1.5; /* should be 1.5 times larger */ + font-size-adjust: ic-width 1.5; /* should be 1.5 times larger */ } #test3 { color: magenta; background: magenta; - font-size-adjust: ic 0.75; /* should be 0.75 times larger */ + font-size-adjust: ic-width 0.75; /* should be 0.75 times larger */ } </style> <body>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-fonts/parsing/font-size-adjust-computed-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-fonts/parsing/font-size-adjust-computed-expected.txt index cf6646f..c824213 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-fonts/parsing/font-size-adjust-computed-expected.txt +++ b/third_party/blink/web_tests/external/wpt/css/css-fonts/parsing/font-size-adjust-computed-expected.txt
@@ -1,9 +1,10 @@ This is a testharness.js-based test. PASS Property font-size-adjust value 'none' PASS Property font-size-adjust value '0.5' -FAIL Property font-size-adjust value 'ex 0.5' assert_true: 'ex 0.5' is a supported value for font-size-adjust. expected true got false -FAIL Property font-size-adjust value 'cap 0.8' assert_true: 'cap 0.8' is a supported value for font-size-adjust. expected true got false -FAIL Property font-size-adjust value 'ch 0.4' assert_true: 'ch 0.4' is a supported value for font-size-adjust. expected true got false -FAIL Property font-size-adjust value 'ic 0.9' assert_true: 'ic 0.9' is a supported value for font-size-adjust. expected true got false +FAIL Property font-size-adjust value 'ex-height 0.5' assert_true: 'ex-height 0.5' is a supported value for font-size-adjust. expected true got false +FAIL Property font-size-adjust value 'cap-height 0.8' assert_true: 'cap-height 0.8' is a supported value for font-size-adjust. expected true got false +FAIL Property font-size-adjust value 'ch-width 0.4' assert_true: 'ch-width 0.4' is a supported value for font-size-adjust. expected true got false +FAIL Property font-size-adjust value 'ic-width 0.9' assert_true: 'ic-width 0.9' is a supported value for font-size-adjust. expected true got false +FAIL Property font-size-adjust value 'ic-height 1.1' assert_true: 'ic-height 1.1' is a supported value for font-size-adjust. expected true got false Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/external/wpt/css/css-fonts/parsing/font-size-adjust-computed.html b/third_party/blink/web_tests/external/wpt/css/css-fonts/parsing/font-size-adjust-computed.html index ec6afcb..a4c8212b 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-fonts/parsing/font-size-adjust-computed.html +++ b/third_party/blink/web_tests/external/wpt/css/css-fonts/parsing/font-size-adjust-computed.html
@@ -14,10 +14,11 @@ <script> test_computed_value('font-size-adjust', 'none'); test_computed_value('font-size-adjust', '0.5'); -test_computed_value('font-size-adjust', 'ex 0.5', '0.5'); // default basis 'ex' omitted from serialization -test_computed_value('font-size-adjust', 'cap 0.8'); -test_computed_value('font-size-adjust', 'ch 0.4'); -test_computed_value('font-size-adjust', 'ic 0.9'); +test_computed_value('font-size-adjust', 'ex-height 0.5', '0.5'); // default basis 'ex-height' omitted from serialization +test_computed_value('font-size-adjust', 'cap-height 0.8'); +test_computed_value('font-size-adjust', 'ch-width 0.4'); +test_computed_value('font-size-adjust', 'ic-width 0.9'); +test_computed_value('font-size-adjust', 'ic-height 1.1'); </script> </body> </html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-fonts/parsing/font-size-adjust-invalid.html b/third_party/blink/web_tests/external/wpt/css/css-fonts/parsing/font-size-adjust-invalid.html index f36a7ad2..8f1dfb1 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-fonts/parsing/font-size-adjust-invalid.html +++ b/third_party/blink/web_tests/external/wpt/css/css-fonts/parsing/font-size-adjust-invalid.html
@@ -13,8 +13,10 @@ <script> test_invalid_value('font-size-adjust', 'auto'); test_invalid_value('font-size-adjust', '-10'); -test_invalid_value('font-size-adjust', '0.5 ex'); +test_invalid_value('font-size-adjust', '0.5 ex-height'); test_invalid_value('font-size-adjust', 'em 1.0'); +test_invalid_value('font-size-adjust', 'ch 0.5'); // it's 'ch-width', not 'ch' +test_invalid_value('font-size-adjust', 'ic 1.0'); // it's 'ic-width' or 'ic-height', not 'ic' </script> </body> </html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-fonts/parsing/font-size-adjust-valid-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-fonts/parsing/font-size-adjust-valid-expected.txt index 5139a32..0b5e69f 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-fonts/parsing/font-size-adjust-valid-expected.txt +++ b/third_party/blink/web_tests/external/wpt/css/css-fonts/parsing/font-size-adjust-valid-expected.txt
@@ -1,9 +1,10 @@ This is a testharness.js-based test. PASS e.style['font-size-adjust'] = "none" should set the property value PASS e.style['font-size-adjust'] = "0.5" should set the property value -FAIL e.style['font-size-adjust'] = "ex 0.5" should set the property value assert_not_equals: property should be set got disallowed value "" -FAIL e.style['font-size-adjust'] = "cap 0.8" should set the property value assert_not_equals: property should be set got disallowed value "" -FAIL e.style['font-size-adjust'] = "ch 0.4" should set the property value assert_not_equals: property should be set got disallowed value "" -FAIL e.style['font-size-adjust'] = "ic 0.9" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['font-size-adjust'] = "ex-height 0.5" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['font-size-adjust'] = "cap-height 0.8" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['font-size-adjust'] = "ch-width 0.4" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['font-size-adjust'] = "ic-width 0.9" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['font-size-adjust'] = "ic-height 0.9" should set the property value assert_not_equals: property should be set got disallowed value "" Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/external/wpt/css/css-fonts/parsing/font-size-adjust-valid.html b/third_party/blink/web_tests/external/wpt/css/css-fonts/parsing/font-size-adjust-valid.html index 676eb026..bb46daf4 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-fonts/parsing/font-size-adjust-valid.html +++ b/third_party/blink/web_tests/external/wpt/css/css-fonts/parsing/font-size-adjust-valid.html
@@ -13,10 +13,11 @@ <script> test_valid_value('font-size-adjust', 'none'); test_valid_value('font-size-adjust', '0.5'); -test_valid_value('font-size-adjust', 'ex 0.5', '0.5'); // default basis 'ex' omitted from serialization -test_valid_value('font-size-adjust', 'cap 0.8'); -test_valid_value('font-size-adjust', 'ch 0.4'); -test_valid_value('font-size-adjust', 'ic 0.9'); +test_valid_value('font-size-adjust', 'ex-height 0.5', '0.5'); // default basis 'ex' omitted from serialization +test_valid_value('font-size-adjust', 'cap-height 0.8'); +test_valid_value('font-size-adjust', 'ch-width 0.4'); +test_valid_value('font-size-adjust', 'ic-width 0.9'); +test_valid_value('font-size-adjust', 'ic-height 0.9'); </script> </body> </html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-sizing/aspect-ratio/grid-aspect-ratio-018.html b/third_party/blink/web_tests/external/wpt/css/css-sizing/aspect-ratio/grid-aspect-ratio-018.html index 76fd6d9..d0b496e 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-sizing/aspect-ratio/grid-aspect-ratio-018.html +++ b/third_party/blink/web_tests/external/wpt/css/css-sizing/aspect-ratio/grid-aspect-ratio-018.html
@@ -17,6 +17,9 @@ <p>Test passes if there is a filled green square and <strong>no red</strong>.</p> <div id="reference-overlapped-red"></div> -<div style="display: grid; grid-template-columns: 100px; grid-template-rows: 100px;"> - <div style="height: 100px; aspect-ratio: 1/2; justify-self: stretch; background: green;"></div> +<div style="display: grid; grid-template-columns: 100px; grid-template-rows: 50px;"> + <div style="height: 50px; aspect-ratio: 1/2; justify-self: stretch; background: green;"></div> +</div> +<div style="display: grid; grid-template-columns: 100px; grid-template-rows: 50px;justify-items: stretch"> + <div style="height: 50px; aspect-ratio: 1/2; justify-self: auto; background: green;"></div> </div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-sizing/aspect-ratio/grid-aspect-ratio-019.html b/third_party/blink/web_tests/external/wpt/css/css-sizing/aspect-ratio/grid-aspect-ratio-019.html index 465b399..bf9c353 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-sizing/aspect-ratio/grid-aspect-ratio-019.html +++ b/third_party/blink/web_tests/external/wpt/css/css-sizing/aspect-ratio/grid-aspect-ratio-019.html
@@ -17,6 +17,9 @@ <p>Test passes if there is a filled green square and <strong>no red</strong>.</p> <div id="reference-overlapped-red"></div> -<div style="display: grid; grid-template-columns: 100px; grid-template-rows: 100px;"> +<div style="display: grid; grid-template-columns: 100px; grid-template-rows: 50px;"> <div style="width: 100px; aspect-ratio: 2/1; align-self: stretch; background: green;"></div> </div> +<div style="display: grid; grid-template-columns: 100px; grid-template-rows: 50px; align-items: stretch"> + <div style="width: 100px; aspect-ratio: 2/1; align-self: auto; background: green;"></div> +</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-tables/height-distribution/percentage-sizing-of-table-cell-007-ref.html b/third_party/blink/web_tests/external/wpt/css/css-tables/height-distribution/percentage-sizing-of-table-cell-007-ref.html new file mode 100644 index 0000000..cdd6e7c --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-tables/height-distribution/percentage-sizing-of-table-cell-007-ref.html
@@ -0,0 +1,8 @@ +<!DOCTYPE html> +<table> + <td> + <div style="width: 100px; height: 100px; overflow-y: scroll;"> + <div style="height: 200px; background: green;"></div> + </div> + </td> +</table>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-tables/height-distribution/percentage-sizing-of-table-cell-007.html b/third_party/blink/web_tests/external/wpt/css/css-tables/height-distribution/percentage-sizing-of-table-cell-007.html new file mode 100644 index 0000000..371333a2 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-tables/height-distribution/percentage-sizing-of-table-cell-007.html
@@ -0,0 +1,10 @@ +<!DOCTYPE html> +<link rel="help" href="https://bugs.chromium.org/p/chromium/issues/detail?id=1227868"> +<link rel="match" href="percentage-sizing-of-table-cell-007-ref.html"> +<table style="height: 100%;"> + <td> + <div style="width: 100px; min-height: 100px; height: 100%; overflow-y: scroll;"> + <div style="height: 200px; background: green;"></div> + </div> + </td> +</table>
diff --git a/third_party/blink/web_tests/external/wpt/editing/other/insert-text-in-void-element.tentative-expected.txt b/third_party/blink/web_tests/external/wpt/editing/other/insert-text-in-void-element.tentative-expected.txt new file mode 100644 index 0000000..9cbdf93 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/editing/other/insert-text-in-void-element.tentative-expected.txt
@@ -0,0 +1,45 @@ +This is a testharness.js-based test. +PASS Inserting text when selection is collapsed in <br> which is only child +PASS Inserting text when selection is collapsed in <br> which follows a text node +PASS Inserting text when selection is collapsed in <br> which is followed by a text node +PASS Inserting text when selection is collapsed in <br> which follows an empty <span> element +PASS Inserting text when selection is collapsed in <br> which follows a text node and an empty <span> element +PASS Inserting text when selection is collapsed in <br> which follows a non-empty <span> element +PASS Inserting text when selection is collapsed in <br> which follows a text node, an empty <span> element and white-space only text node +FAIL Inserting text when selection is collapsed in <embed> which is only child assert_in_array: The text should be inserted before the <embed> element value "<div><embed></div>" not in array ["<div>abc<embed></div>", "<div>abc<embed><br></div>"] +PASS Inserting text when selection is collapsed in <embed> which follows a text node +FAIL Inserting text when selection is collapsed in <embed> which is followed by a text node assert_in_array: The text should be inserted before the <embed> element value "<div><embed>abcdef</div>" not in array ["<div>abc<embed>def</div>", "<div>abc<embed>def<br></div>"] +FAIL Inserting text when selection is collapsed in <embed> which follows an empty <span> element assert_in_array: The text should be inserted before the previous empty inline element of <embed> value "<div><span></span><embed></div>" not in array ["<div>abc<span></span><embed></div>", "<div>abc<span></span><embed><br></div>"] +PASS Inserting text when selection is collapsed in <embed> which follows a text node and an empty <span> element +PASS Inserting text when selection is collapsed in <embed> which follows a non-empty <span> element +FAIL Inserting text when selection is collapsed in <embed> which follows a text node, an empty <span> element and white-space only text node assert_in_array: The text should be inserted before the previous empty inline element value "<div>abcdef<span></span><embed></div>" not in array ["<div>abcdef<span></span> <embed></div>", "<div>abcdef<span></span> <embed><br></div>"] +PASS Inserting text when selection is collapsed in <hr> which is only child +PASS Inserting text when selection is collapsed in <hr> which follows a text node +PASS Inserting text when selection is collapsed in <hr> which is followed by a text node +PASS Inserting text when selection is collapsed in <hr> which follows an empty <span> element +PASS Inserting text when selection is collapsed in <hr> which follows a text node and an empty <span> element +PASS Inserting text when selection is collapsed in <hr> which follows a non-empty <span> element +FAIL Inserting text when selection is collapsed in <hr> which follows a text node, an empty <span> element and white-space only text node assert_in_array: The text should be inserted after the previous empty inline element value "<div>abc<span></span>\ndef<hr></div>" not in array ["<div>abc<span></span>def<hr></div>", "<div>abc<span></span>def<br><hr></div>"] +PASS Inserting text when selection is collapsed in <img> which is only child +PASS Inserting text when selection is collapsed in <img> which follows a text node +PASS Inserting text when selection is collapsed in <img> which is followed by a text node +PASS Inserting text when selection is collapsed in <img> which follows an empty <span> element +PASS Inserting text when selection is collapsed in <img> which follows a text node and an empty <span> element +PASS Inserting text when selection is collapsed in <img> which follows a non-empty <span> element +PASS Inserting text when selection is collapsed in <img> which follows a text node, an empty <span> element and white-space only text node +PASS Inserting text when selection is collapsed in <input> which is only child +PASS Inserting text when selection is collapsed in <input> which follows a text node +PASS Inserting text when selection is collapsed in <input> which is followed by a text node +PASS Inserting text when selection is collapsed in <input> which follows an empty <span> element +PASS Inserting text when selection is collapsed in <input> which follows a text node and an empty <span> element +PASS Inserting text when selection is collapsed in <input> which follows a non-empty <span> element +PASS Inserting text when selection is collapsed in <input> which follows a text node, an empty <span> element and white-space only text node +PASS Inserting text when selection is collapsed in <wbr> which is only child +PASS Inserting text when selection is collapsed in <wbr> which follows a text node +FAIL Inserting text when selection is collapsed in <wbr> which is followed by a text node assert_in_array: The text should be inserted before the <wbr> element value "<div><wbr>abcdef</div>" not in array ["<div>abc<wbr>def</div>", "<div>abc<wbr>def<br></div>"] +PASS Inserting text when selection is collapsed in <wbr> which follows an empty <span> element +PASS Inserting text when selection is collapsed in <wbr> which follows a text node and an empty <span> element +PASS Inserting text when selection is collapsed in <wbr> which follows a non-empty <span> element +FAIL Inserting text when selection is collapsed in <wbr> which follows a text node, an empty <span> element and white-space only text node assert_in_array: The text should be inserted before the previous empty inline element value "<div>abcdef<span></span><wbr></div>" not in array ["<div>abcdef<span></span> <wbr></div>", "<div>abcdef<span></span> <wbr><br></div>"] +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/editing/other/insert-text-in-void-element.tentative.html b/third_party/blink/web_tests/external/wpt/editing/other/insert-text-in-void-element.tentative.html new file mode 100644 index 0000000..a67f061b --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/editing/other/insert-text-in-void-element.tentative.html
@@ -0,0 +1,292 @@ +<!doctype html> +<meta charset=utf-8> +<title>Test insertText when selection collapsed in void element</title> +<meta name="timeout" content="long"> +<script src=/resources/testharness.js></script> +<script src=/resources/testharnessreport.js></script> +<div contenteditable></div> +<script> +"use strict"; + +const voidElements = [ + "br", + "embed", + "hr", + "img", + "input", + "wbr", +]; + +// This test tests whether the inserted text is inserted into, when selection +// is collapsed in the void element. The expected results are based on Blink, +// but the results of <embed> and <wbr> elements are not consistent with the +// other elements'. Therefore, Blink also does not pass some of the following +// tests. +// FYI: This cannot be tested by editing/run because there is no way to collapse +// selection into a void element with the framework. + +const editor = document.querySelector("div[contenteditable]"); +for (const tag of voidElements) { + test(() => { + editor.innerHTML = `<div></div>`; + const element = document.createElement(tag); + editor.firstChild.appendChild(element); + editor.focus(); + const selection = getSelection(); + selection.collapse(element, 0); + document.execCommand("insertText", false, "abc"); + if (tag == "br") { + assert_in_array( + editor.innerHTML, + [ + "<div>abc</div>", + "<div>abc<br></div>", + ], + `The text should be inserted before the <br> element` + ); + } else { + assert_in_array( + editor.innerHTML, + [ + `<div>abc<${tag}></div>`, + `<div>abc<${tag}><br></div>`, + ], + `The text should be inserted before the <${tag}> element` + ); + } + }, `Inserting text when selection is collapsed in <${tag}> which is only child`); + + test(() => { + editor.innerHTML = `<div>abc</div>`; + const element = document.createElement(tag); + editor.firstChild.appendChild(element); + editor.focus(); + const selection = getSelection(); + selection.collapse(element, 0); + document.execCommand("insertText", false, "def"); + if (tag == "br") { + assert_in_array( + editor.innerHTML, + [ + "<div>abcdef</div>", + "<div>abcdef<br></div>", + ], + `The text should be inserted before the <br> element` + ); + } else { + assert_in_array( + editor.innerHTML, + [ + `<div>abcdef<${tag}></div>`, + `<div>abcdef<${tag}><br></div>`, + ], + `The text should be inserted before the <${tag}> element` + ); + } + }, `Inserting text when selection is collapsed in <${tag}> which follows a text node`); + + test(() => { + editor.innerHTML = `<div>def</div>`; + const element = document.createElement(tag); + editor.firstChild.insertBefore(element, editor.firstChild.firstChild); + editor.focus(); + const selection = getSelection(); + selection.collapse(element, 0); + document.execCommand("insertText", false, "abc"); + if (tag == "br") { + assert_in_array( + editor.innerHTML, + [ + "<div>abc<br>def</div>", + "<div>abc<br>def<br></div>", + ], + `The text should be inserted before the <br> element` + ); + } else { + assert_in_array( + editor.innerHTML, + [ + `<div>abc<${tag}>def</div>`, + `<div>abc<${tag}>def<br></div>`, + ], + `The text should be inserted before the <${tag}> element` + ); + } + }, `Inserting text when selection is collapsed in <${tag}> which is followed by a text node`); + + test(() => { + editor.innerHTML = `<div><span></span></div>`; + const element = document.createElement(tag); + editor.firstChild.appendChild(element); + editor.focus(); + const selection = getSelection(); + selection.collapse(element, 0); + document.execCommand("insertText", false, "abc"); + if (tag == "br") { + assert_in_array( + editor.innerHTML, + [ + "<div><span></span>abc</div>", + "<div><span></span>abc<br></div>", + ], + `The text should be inserted after the previous empty inline element of <br>` + ); + } else if (tag == "input") { // visible inline? + assert_in_array( + editor.innerHTML, + [ + `<div><span></span>abc<${tag}></div>`, + `<div><span></span>abc<${tag}><br></div>`, + ], + `The text should be inserted after the previous empty inline element of <${tag}>` + ); + } else if (tag == "hr") { // block + assert_in_array( + editor.innerHTML, + [ + `<div><span></span>abc<${tag}></div>`, + `<div><span></span>abc<br><${tag}></div>`, + ], + `The text should be inserted after the previous empty inline element of <${tag}>` + ); + } else { + assert_in_array( + editor.innerHTML, + [ + `<div>abc<span></span><${tag}></div>`, + `<div>abc<span></span><${tag}><br></div>`, + ], + `The text should be inserted before the previous empty inline element of <${tag}>` + ); + } + }, `Inserting text when selection is collapsed in <${tag}> which follows an empty <span> element`); + + test(() => { + editor.innerHTML = `<div>abc<span></span></div>`; + const element = document.createElement(tag); + editor.firstChild.appendChild(element); + editor.focus(); + const selection = getSelection(); + selection.collapse(element, 0); + document.execCommand("insertText", false, "def"); + if (tag == "br") { + assert_in_array( + editor.innerHTML, + [ + "<div>abcdef<span></span></div>", + "<div>abcdef<span></span><br></div>", + ], + `The text should be inserted at end of the first text node before empty <span> and <br>` + ); + } else if (tag == "hr") { // block + assert_in_array( + editor.innerHTML, + [ + `<div>abc<span></span>def<${tag}></div>`, + `<div>abc<span></span>def<br><${tag}></div>`, + ], + `The text should be inserted after the previous empty inline element of <${tag}> even if the empty element follows a text node` + ); + } else { + assert_in_array( + editor.innerHTML, + [ + `<div>abcdef<span></span><${tag}></div>`, + `<div>abcdef<span></span><${tag}><br></div>`, + ], + `The text should be inserted before the previous empty inline element of <${tag}>` + ); + } + }, `Inserting text when selection is collapsed in <${tag}> which follows a text node and an empty <span> element`); + + test(() => { + editor.innerHTML = `<div><span>abc</span></div>`; + const element = document.createElement(tag); + editor.firstChild.appendChild(element); + editor.focus(); + const selection = getSelection(); + selection.collapse(element, 0); + document.execCommand("insertText", false, "def"); + if (tag == "br") { + assert_in_array( + editor.innerHTML, + [ + "<div><span>abcdef</span></div>", + "<div><span>abcdef</span><br></div>", + ], + `The text should be inserted at end of the text node in <span>` + ); + } else if (tag == "hr") { // block + assert_in_array( + editor.innerHTML, + [ + `<div><span>abc</span>def<${tag}></div>`, + `<div><span>abc</span>def<br><${tag}></div>`, + ], + `The text should be inserted at after the span and before <${tag}>` + ); + } else { + assert_in_array( + editor.innerHTML, + [ + `<div><span>abcdef</span><${tag}></div>`, + `<div><span>abcdef</span><${tag}><br></div>`, + ], + `The text should be inserted at end of the text node in <span> before <${tag}>` + ); + } + }, `Inserting text when selection is collapsed in <${tag}> which follows a non-empty <span> element`); + + test(() => { + editor.innerHTML = `<div>abc<span></span>\n</div>`; + const element = document.createElement(tag); + editor.firstChild.appendChild(element); + editor.focus(); + const selection = getSelection(); + selection.collapse(element, 0); + document.execCommand("insertText", false, "def"); + if (tag == "br") { + assert_in_array( + editor.innerHTML.replace(/\n/g, " "), + [ + "<div>abcdef<span></span></div>", + "<div>abcdef<span></span><br></div>", + "<div>abcdef<span></span> </div>", + "<div>abcdef<span></span> <br></div>", + ], + `The text should be inserted at end of the first text node with ignoring the empty <span> and invisible text node before <br>` + ); + } else if (tag == "img" || tag == "input") { // visible inline + assert_in_array( + editor.innerHTML.replace(/\n/g, " "), + [ + `<div>abc<span></span> def<${tag}></div>`, + `<div>abc<span></span> def<${tag}><br></div>`, + `<div>abc<span></span> def<${tag}></div>`, + `<div>abc<span></span> def<${tag}><br></div>`, + ], + `The text should be inserted at end of the last visible text node` + ); + } else if (tag == "hr") { // block + assert_in_array( + editor.innerHTML, + [ + `<div>abc<span></span>def<${tag}></div>`, + `<div>abc<span></span>def<br><${tag}></div>`, + ], + `The text should be inserted after the previous empty inline element` + ); + } else { + assert_in_array( + editor.innerHTML.replace(/\n/g, " "), + [ + `<div>abcdef<span></span> <${tag}></div>`, + `<div>abcdef<span></span> <${tag}><br></div>`, + ], + `The text should be inserted before the previous empty inline element` + ); + } + }, `Inserting text when selection is collapsed in <${tag}> which follows a text node, an empty <span> element and white-space only text node`); +} + +</script> \ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-dialog-element/dialog-form-submission.html b/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-dialog-element/dialog-form-submission.html index 344f5f1..5934485 100644 --- a/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-dialog-element/dialog-form-submission.html +++ b/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-dialog-element/dialog-form-submission.html
@@ -99,5 +99,33 @@ assert_equals(dialog.returnValue, "", "dialog's returnValue remains the same"); }, "closing the dialog while submitting should stop the submission"); +promise_test(async () => { + const dialog = document.querySelector('dialog'); + dialog.returnValue = undefined; + dialog.showModal(); + + let submitEvent = false; + const dialogForm = document.getElementById('dialogForm'); + dialogForm.onsubmit = function() { + submitEvent = true; + assert_false(dialog.open, "dialog should be closed"); + assert_equals(dialog.returnValue, "", "dialog's returnValue remains the same"); + }; + + const button = document.querySelector('button'); + button.value = "sushi"; + button.onclick = function() { + dialogForm.submit(); + assert_false(dialog.open, "dialog should be closed now"); + // The returnValue should be "" because there is no submitter + assert_equals(dialog.returnValue, "", "returnValue shouldn be empty string"); + }; + + button.click(); + assert_true(submitEvent, "Should have submit event"); + assert_false(dialog.open, "dialog should be closed"); + assert_equals(dialog.returnValue, "", "dialog's returnValue remains the same"); +}, "calling form.submit() in click handler of submit button should start the submission synchronously"); + </script> </body>
diff --git a/third_party/blink/web_tests/external/wpt/js-self-profiling/__dir__.headers b/third_party/blink/web_tests/external/wpt/js-self-profiling/__dir__.headers index 35b10bd2..93537b4 100644 --- a/third_party/blink/web_tests/external/wpt/js-self-profiling/__dir__.headers +++ b/third_party/blink/web_tests/external/wpt/js-self-profiling/__dir__.headers
@@ -1,3 +1 @@ -Cross-Origin-Opener-Policy: same-origin -Cross-Origin-Embedder-Policy: require-corp Document-Policy: js-profiling
diff --git a/third_party/blink/web_tests/wpt_internal/js-self-profiling/concurrent-profilers.https.html b/third_party/blink/web_tests/external/wpt/js-self-profiling/concurrent-profilers.https.html similarity index 100% rename from third_party/blink/web_tests/wpt_internal/js-self-profiling/concurrent-profilers.https.html rename to third_party/blink/web_tests/external/wpt/js-self-profiling/concurrent-profilers.https.html
diff --git a/third_party/blink/web_tests/wpt_internal/js-self-profiling/external-script.https.html b/third_party/blink/web_tests/external/wpt/js-self-profiling/external-script.https.html similarity index 100% rename from third_party/blink/web_tests/wpt_internal/js-self-profiling/external-script.https.html rename to third_party/blink/web_tests/external/wpt/js-self-profiling/external-script.https.html
diff --git a/third_party/blink/web_tests/wpt_internal/js-self-profiling/function-names.https.html b/third_party/blink/web_tests/external/wpt/js-self-profiling/function-names.https.html similarity index 100% rename from third_party/blink/web_tests/wpt_internal/js-self-profiling/function-names.https.html rename to third_party/blink/web_tests/external/wpt/js-self-profiling/function-names.https.html
diff --git a/third_party/blink/web_tests/wpt_internal/js-self-profiling/iframe-context-filtration.https.html b/third_party/blink/web_tests/external/wpt/js-self-profiling/iframe-context-filtration.https.html similarity index 100% rename from third_party/blink/web_tests/wpt_internal/js-self-profiling/iframe-context-filtration.https.html rename to third_party/blink/web_tests/external/wpt/js-self-profiling/iframe-context-filtration.https.html
diff --git a/third_party/blink/web_tests/wpt_internal/js-self-profiling/inline-script.https.html b/third_party/blink/web_tests/external/wpt/js-self-profiling/inline-script.html similarity index 100% rename from third_party/blink/web_tests/wpt_internal/js-self-profiling/inline-script.https.html rename to third_party/blink/web_tests/external/wpt/js-self-profiling/inline-script.html
diff --git a/third_party/blink/web_tests/wpt_internal/js-self-profiling/max-buffer-size.https.html b/third_party/blink/web_tests/external/wpt/js-self-profiling/max-buffer-size.https.html similarity index 89% rename from third_party/blink/web_tests/wpt_internal/js-self-profiling/max-buffer-size.https.html rename to third_party/blink/web_tests/external/wpt/js-self-profiling/max-buffer-size.https.html index 655b1e9c..399b804 100644 --- a/third_party/blink/web_tests/wpt_internal/js-self-profiling/max-buffer-size.https.html +++ b/third_party/blink/web_tests/external/wpt/js-self-profiling/max-buffer-size.https.html
@@ -20,8 +20,8 @@ maxBufferSize: 2, }); - // Force 10 samples with a max buffer size of 2. - for (let i = 0; i < 10; i++) { + // Force 3 samples with a max buffer size of 2. + for (let i = 0; i < 3; i++) { ProfileUtils.forceSample(); } @@ -39,13 +39,12 @@ assert_unreached("samplebufferfull invoked on wrong profiler"); }); pf[1].addEventListener("samplebufferfull", async ()=>{ - console.log("samplebufferfull"); pf[0].stop(); pf[1].stop(); assertTrue(true); }); - for (let i = 0; i < 10; i++) { + for (let i = 0; i < 2; i++) { ProfileUtils.forceSample(); }
diff --git a/third_party/blink/web_tests/wpt_internal/js-self-profiling/resources/__dir__.headers b/third_party/blink/web_tests/external/wpt/js-self-profiling/resources/__dir__.headers similarity index 100% rename from third_party/blink/web_tests/wpt_internal/js-self-profiling/resources/__dir__.headers rename to third_party/blink/web_tests/external/wpt/js-self-profiling/resources/__dir__.headers
diff --git a/third_party/blink/web_tests/wpt_internal/js-self-profiling/resources/child-frame.html b/third_party/blink/web_tests/external/wpt/js-self-profiling/resources/child-frame.html similarity index 100% rename from third_party/blink/web_tests/wpt_internal/js-self-profiling/resources/child-frame.html rename to third_party/blink/web_tests/external/wpt/js-self-profiling/resources/child-frame.html
diff --git a/third_party/blink/web_tests/wpt_internal/js-self-profiling/resources/external-script.js b/third_party/blink/web_tests/external/wpt/js-self-profiling/resources/external-script.js similarity index 100% rename from third_party/blink/web_tests/wpt_internal/js-self-profiling/resources/external-script.js rename to third_party/blink/web_tests/external/wpt/js-self-profiling/resources/external-script.js
diff --git a/third_party/blink/web_tests/wpt_internal/js-self-profiling/resources/external-script.js.headers b/third_party/blink/web_tests/external/wpt/js-self-profiling/resources/external-script.js.headers similarity index 100% rename from third_party/blink/web_tests/wpt_internal/js-self-profiling/resources/external-script.js.headers rename to third_party/blink/web_tests/external/wpt/js-self-profiling/resources/external-script.js.headers
diff --git a/third_party/blink/web_tests/wpt_internal/js-self-profiling/resources/profile-utils.js b/third_party/blink/web_tests/external/wpt/js-self-profiling/resources/profile-utils.js similarity index 88% rename from third_party/blink/web_tests/wpt_internal/js-self-profiling/resources/profile-utils.js rename to third_party/blink/web_tests/external/wpt/js-self-profiling/resources/profile-utils.js index 6b4f6e27..33338a6 100644 --- a/third_party/blink/web_tests/wpt_internal/js-self-profiling/resources/profile-utils.js +++ b/third_party/blink/web_tests/external/wpt/js-self-profiling/resources/profile-utils.js
@@ -2,7 +2,13 @@ const TEST_SAMPLE_INTERVAL = 10; function forceSample() { - window.internals.collectSample(); + // Spin for |TEST_SAMPLE_INTERVAL + 500|ms to ensure that a sample occurs + // before this function returns. As periodic sampling is enforced by a + // SHOULD clause, it is indeed testable. + // + // More reliable sampling will be handled in a future testdriver RFC + // (https://github.com/web-platform-tests/rfcs/pull/81). + for (const deadline = performance.now() + TEST_SAMPLE_INTERVAL + 500; performance.now() < deadline;); } // Creates a new profile that captures the execution of when the given
diff --git a/third_party/blink/web_tests/wpt_internal/js-self-profiling/time-domain.window.js b/third_party/blink/web_tests/external/wpt/js-self-profiling/time-domain.window.js similarity index 100% rename from third_party/blink/web_tests/wpt_internal/js-self-profiling/time-domain.window.js rename to third_party/blink/web_tests/external/wpt/js-self-profiling/time-domain.window.js
diff --git a/third_party/blink/web_tests/wpt_internal/js-self-profiling/without-document-policy/disabled.https.html b/third_party/blink/web_tests/external/wpt/js-self-profiling/without-document-policy/disabled.https.html similarity index 100% rename from third_party/blink/web_tests/wpt_internal/js-self-profiling/without-document-policy/disabled.https.html rename to third_party/blink/web_tests/external/wpt/js-self-profiling/without-document-policy/disabled.https.html
diff --git a/third_party/blink/web_tests/external/wpt/streams/readable-byte-streams/tee.any-expected.txt b/third_party/blink/web_tests/external/wpt/streams/readable-byte-streams/tee.any-expected.txt new file mode 100644 index 0000000..1f96021 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/streams/readable-byte-streams/tee.any-expected.txt
@@ -0,0 +1,39 @@ +This is a testharness.js-based test. +PASS ReadableStream teeing with byte source: rs.tee() returns an array of two ReadableStreams +FAIL ReadableStream teeing with byte source: should be able to read one branch to the end without affecting the other promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'getReader' on 'ReadableStream': Cannot use a BYOB reader with a non-byte stream" +FAIL ReadableStream teeing with byte source: chunks should be cloned for each branch assert_not_equals: chunks should have different buffers got disallowed value object "[object ArrayBuffer]" +FAIL ReadableStream teeing with byte source: chunks for BYOB requests from branch 1 should be cloned to branch 2 promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'getReader' on 'ReadableStream': Cannot use a BYOB reader with a non-byte stream" +FAIL ReadableStream teeing with byte source: errors in the source should propagate to both branches promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'getReader' on 'ReadableStream': Cannot use a BYOB reader with a non-byte stream" +PASS ReadableStream teeing with byte source: canceling branch1 should not impact branch2 +PASS ReadableStream teeing with byte source: canceling branch2 should not impact branch1 +PASS Running templatedRSTeeCancel with ReadableStream teeing with byte source +PASS ReadableStream teeing with byte source: canceling both branches should aggregate the cancel reasons into an array +PASS ReadableStream teeing with byte source: canceling both branches in reverse order should aggregate the cancel reasons into an array +PASS ReadableStream teeing with byte source: failing to cancel the original stream should cause cancel() to reject on branches +PASS ReadableStream teeing with byte source: erroring a teed stream should properly handle canceled branches +FAIL ReadableStream teeing with byte source: closing the original should close the branches promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'getReader' on 'ReadableStream': Cannot use a BYOB reader with a non-byte stream" +FAIL ReadableStream teeing with byte source: erroring the original should immediately error the branches promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'getReader' on 'ReadableStream': Cannot use a BYOB reader with a non-byte stream" +PASS ReadableStream teeing with byte source: erroring the original should error pending reads from default reader +FAIL ReadableStream teeing with byte source: erroring the original should error pending reads from BYOB reader promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'getReader' on 'ReadableStream': Cannot use a BYOB reader with a non-byte stream" +FAIL ReadableStream teeing with byte source: canceling branch1 should finish when branch2 reads until end of stream promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'getReader' on 'ReadableStream': Cannot use a BYOB reader with a non-byte stream" +FAIL ReadableStream teeing with byte source: canceling branch1 should finish when original stream errors promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'getReader' on 'ReadableStream': Cannot use a BYOB reader with a non-byte stream" +FAIL ReadableStream teeing with byte source: should not pull any chunks if no branches are reading assert_array_equals: pull should not be called lengths differ, expected array [] length 0, got ["pull", "pull"] length 2 +FAIL ReadableStream teeing with byte source: should only pull enough to fill the emptiest queue promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'getReader' on 'ReadableStream': Cannot use a BYOB reader with a non-byte stream" +FAIL ReadableStream teeing with byte source: should not pull when original is already errored promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'getReader' on 'ReadableStream': Cannot use a BYOB reader with a non-byte stream" +FAIL ReadableStream teeing with byte source: stops pulling when original stream errors while branch 1 is reading promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'getReader' on 'ReadableStream': Cannot use a BYOB reader with a non-byte stream" +FAIL ReadableStream teeing with byte source: stops pulling when original stream errors while branch 2 is reading promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'getReader' on 'ReadableStream': Cannot use a BYOB reader with a non-byte stream" +FAIL ReadableStream teeing with byte source: stops pulling when original stream errors while both branches are reading promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'getReader' on 'ReadableStream': Cannot use a BYOB reader with a non-byte stream" +FAIL ReadableStream teeing with byte source: canceling both branches in sequence with delay promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'getReader' on 'ReadableStream': Cannot use a BYOB reader with a non-byte stream" +FAIL ReadableStream teeing with byte source: failing to cancel when canceling both branches in sequence with delay promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'getReader' on 'ReadableStream': Cannot use a BYOB reader with a non-byte stream" +FAIL ReadableStream teeing with byte source: read from branch1 and branch2, cancel branch1, cancel branch2 promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'getReader' on 'ReadableStream': Cannot use a BYOB reader with a non-byte stream" +FAIL ReadableStream teeing with byte source: read from branch1 and branch2, cancel branch2, cancel branch1 promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'getReader' on 'ReadableStream': Cannot use a BYOB reader with a non-byte stream" +FAIL ReadableStream teeing with byte source: read from branch1 and branch2, cancel branch2, enqueue to branch1 promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'getReader' on 'ReadableStream': Cannot use a BYOB reader with a non-byte stream" +FAIL ReadableStream teeing with byte source: read from branch1 and branch2, cancel branch1, respond to branch2 promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'getReader' on 'ReadableStream': Cannot use a BYOB reader with a non-byte stream" +FAIL ReadableStream teeing with byte source: pull with BYOB reader, then pull with default reader promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'getReader' on 'ReadableStream': Cannot use a BYOB reader with a non-byte stream" +FAIL ReadableStream teeing with byte source: pull with default reader, then pull with BYOB reader assert_equals: pull() should be called once expected 1 but got 2 +FAIL ReadableStream teeing with byte source: read from branch2, then read from branch1 promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'getReader' on 'ReadableStream': Cannot use a BYOB reader with a non-byte stream" +FAIL ReadableStream teeing with byte source: read from branch1 with default reader, then close while branch2 has pending BYOB read promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'getReader' on 'ReadableStream': Cannot use a BYOB reader with a non-byte stream" +FAIL ReadableStream teeing with byte source: read from branch2 with default reader, then close while branch1 has pending BYOB read promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'getReader' on 'ReadableStream': Cannot use a BYOB reader with a non-byte stream" +FAIL ReadableStream teeing with byte source: close when both branches have pending BYOB reads promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'getReader' on 'ReadableStream': Cannot use a BYOB reader with a non-byte stream" +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/streams/readable-byte-streams/tee.any.js b/third_party/blink/web_tests/external/wpt/streams/readable-byte-streams/tee.any.js new file mode 100644 index 0000000..3ea5f6b --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/streams/readable-byte-streams/tee.any.js
@@ -0,0 +1,894 @@ +// META: global=window,worker,jsshell +// META: script=../resources/rs-utils.js +// META: script=../resources/test-utils.js +// META: script=../resources/recording-streams.js +// META: script=../resources/rs-test-templates.js +'use strict'; + +function assert_typed_array_equals(actual, expected, message) { + const prefix = message === undefined ? '' : `${message} `; + assert_equals(typeof actual, 'object', `${prefix}type is object`); + assert_equals(actual.constructor, expected.constructor, `${prefix}constructor`); + assert_equals(actual.byteOffset, expected.byteOffset, `${prefix}byteOffset`); + assert_equals(actual.byteLength, expected.byteLength, `${prefix}byteLength`); + assert_equals(actual.buffer.byteLength, expected.buffer.byteLength, `${prefix}buffer.byteLength`); + assert_array_equals([...actual], [...expected], `${prefix}contents`); + assert_array_equals([...new Uint8Array(actual.buffer)], [...new Uint8Array(expected.buffer)], `${prefix}buffer contents`); +} + +test(() => { + + const rs = new ReadableStream({ type: 'bytes' }); + const result = rs.tee(); + + assert_true(Array.isArray(result), 'return value should be an array'); + assert_equals(result.length, 2, 'array should have length 2'); + assert_equals(result[0].constructor, ReadableStream, '0th element should be a ReadableStream'); + assert_equals(result[1].constructor, ReadableStream, '1st element should be a ReadableStream'); + +}, 'ReadableStream teeing with byte source: rs.tee() returns an array of two ReadableStreams'); + +promise_test(async t => { + + const rs = new ReadableStream({ + type: 'bytes', + start(c) { + c.enqueue(new Uint8Array([0x01])); + c.enqueue(new Uint8Array([0x02])); + c.close(); + } + }); + + const [branch1, branch2] = rs.tee(); + const reader1 = branch1.getReader({ mode: 'byob' }); + const reader2 = branch2.getReader({ mode: 'byob' }); + + reader2.closed.then(t.unreached_func('branch2 should not be closed')); + + { + const result = await reader1.read(new Uint8Array(1)); + assert_equals(result.done, false, 'done'); + assert_typed_array_equals(result.value, new Uint8Array([0x01]), 'value'); + } + + { + const result = await reader1.read(new Uint8Array(1)); + assert_equals(result.done, false, 'done'); + assert_typed_array_equals(result.value, new Uint8Array([0x02]), 'value'); + } + + { + const result = await reader1.read(new Uint8Array(1)); + assert_equals(result.done, true, 'done'); + assert_typed_array_equals(result.value, new Uint8Array([0]).subarray(0, 0), 'value'); + } + + { + const result = await reader2.read(new Uint8Array(1)); + assert_equals(result.done, false, 'done'); + assert_typed_array_equals(result.value, new Uint8Array([0x01]), 'value'); + } + + await reader1.closed; + +}, 'ReadableStream teeing with byte source: should be able to read one branch to the end without affecting the other'); + +promise_test(async () => { + + let pullCount = 0; + const enqueuedChunk = new Uint8Array([0x01]); + const rs = new ReadableStream({ + type: 'bytes', + pull(c) { + ++pullCount; + if (pullCount === 1) { + c.enqueue(enqueuedChunk); + } + } + }); + + const [branch1, branch2] = rs.tee(); + const reader1 = branch1.getReader(); + const reader2 = branch2.getReader(); + + const [result1, result2] = await Promise.all([reader1.read(), reader2.read()]); + assert_equals(result1.done, false, 'reader1 done'); + assert_equals(result2.done, false, 'reader2 done'); + + const view1 = result1.value; + const view2 = result2.value; + assert_typed_array_equals(view1, new Uint8Array([0x01]), 'reader1 value'); + assert_typed_array_equals(view2, new Uint8Array([0x01]), 'reader2 value'); + + assert_not_equals(view1.buffer, view2.buffer, 'chunks should have different buffers'); + assert_not_equals(enqueuedChunk.buffer, view1.buffer, 'enqueued chunk and branch1\'s chunk should have different buffers'); + assert_not_equals(enqueuedChunk.buffer, view2.buffer, 'enqueued chunk and branch2\'s chunk should have different buffers'); + +}, 'ReadableStream teeing with byte source: chunks should be cloned for each branch'); + +promise_test(async () => { + + let pullCount = 0; + const rs = new ReadableStream({ + type: 'bytes', + pull(c) { + ++pullCount; + if (pullCount === 1) { + c.byobRequest.view[0] = 0x01; + c.byobRequest.respond(1); + } + } + }); + + const [branch1, branch2] = rs.tee(); + const reader1 = branch1.getReader({ mode: 'byob' }); + const reader2 = branch2.getReader(); + const buffer = new Uint8Array([42, 42, 42]).buffer; + + { + const result = await reader1.read(new Uint8Array(buffer, 0, 1)); + assert_equals(result.done, false, 'done'); + assert_typed_array_equals(result.value, new Uint8Array([0x01, 42, 42]).subarray(0, 1), 'value'); + } + + { + const result = await reader2.read(); + assert_equals(result.done, false, 'done'); + assert_typed_array_equals(result.value, new Uint8Array([0x01]), 'value'); + } + +}, 'ReadableStream teeing with byte source: chunks for BYOB requests from branch 1 should be cloned to branch 2'); + +promise_test(async t => { + + const theError = { name: 'boo!' }; + const rs = new ReadableStream({ + type: 'bytes', + start(c) { + c.enqueue(new Uint8Array([0x01])); + c.enqueue(new Uint8Array([0x02])); + }, + pull() { + throw theError; + } + }); + + const [branch1, branch2] = rs.tee(); + const reader1 = branch1.getReader({ mode: 'byob' }); + const reader2 = branch2.getReader({ mode: 'byob' }); + + { + const result = await reader1.read(new Uint8Array(1)); + assert_equals(result.done, false, 'first read from branch1 should not be done'); + assert_typed_array_equals(result.value, new Uint8Array([0x01]), 'first read from branch1'); + } + + { + const result = await reader1.read(new Uint8Array(1)); + assert_equals(result.done, false, 'second read from branch1 should not be done'); + assert_typed_array_equals(result.value, new Uint8Array([0x02]), 'second read from branch1'); + } + + await promise_rejects_exactly(t, theError, reader1.read(new Uint8Array(1))); + await promise_rejects_exactly(t, theError, reader2.read(new Uint8Array(1))); + + await Promise.all([ + promise_rejects_exactly(t, theError, reader1.closed), + promise_rejects_exactly(t, theError, reader2.closed) + ]); + +}, 'ReadableStream teeing with byte source: errors in the source should propagate to both branches'); + +promise_test(async () => { + + const rs = new ReadableStream({ + type: 'bytes', + start(c) { + c.enqueue(new Uint8Array([0x01])); + c.enqueue(new Uint8Array([0x02])); + c.close(); + } + }); + + const [branch1, branch2] = rs.tee(); + branch1.cancel(); + + const [chunks1, chunks2] = await Promise.all([readableStreamToArray(branch1), readableStreamToArray(branch2)]); + assert_array_equals(chunks1, [], 'branch1 should have no chunks'); + assert_equals(chunks2.length, 2, 'branch2 should have two chunks'); + assert_typed_array_equals(chunks2[0], new Uint8Array([0x01]), 'first chunk from branch2'); + assert_typed_array_equals(chunks2[1], new Uint8Array([0x02]), 'second chunk from branch2'); + +}, 'ReadableStream teeing with byte source: canceling branch1 should not impact branch2'); + +promise_test(async () => { + + const rs = new ReadableStream({ + type: 'bytes', + start(c) { + c.enqueue(new Uint8Array([0x01])); + c.enqueue(new Uint8Array([0x02])); + c.close(); + } + }); + + const [branch1, branch2] = rs.tee(); + branch2.cancel(); + + const [chunks1, chunks2] = await Promise.all([readableStreamToArray(branch1), readableStreamToArray(branch2)]); + assert_equals(chunks1.length, 2, 'branch1 should have two chunks'); + assert_typed_array_equals(chunks1[0], new Uint8Array([0x01]), 'first chunk from branch1'); + assert_typed_array_equals(chunks1[1], new Uint8Array([0x02]), 'second chunk from branch1'); + assert_array_equals(chunks2, [], 'branch2 should have no chunks'); + +}, 'ReadableStream teeing with byte source: canceling branch2 should not impact branch1'); + +templatedRSTeeCancel('ReadableStream teeing with byte source', (extras) => { + return new ReadableStream({ type: 'bytes', ...extras }); +}); + +promise_test(async () => { + + let controller; + const rs = new ReadableStream({ + type: 'bytes', + start(c) { + controller = c; + } + }); + + const [branch1, branch2] = rs.tee(); + const reader1 = branch1.getReader({ mode: 'byob' }); + const reader2 = branch2.getReader({ mode: 'byob' }); + + const promise = Promise.all([reader1.closed, reader2.closed]); + + controller.close(); + + // The branches are created with HWM 0, so we need to read from at least one of them + // to observe the stream becoming closed. + const read1 = await reader1.read(new Uint8Array(1)); + assert_equals(read1.done, true, 'first read from branch1 should be done'); + + await promise; + +}, 'ReadableStream teeing with byte source: closing the original should close the branches'); + +promise_test(async t => { + + let controller; + const rs = new ReadableStream({ + type: 'bytes', + start(c) { + controller = c; + } + }); + + const [branch1, branch2] = rs.tee(); + const reader1 = branch1.getReader({ mode: 'byob' }); + const reader2 = branch2.getReader({ mode: 'byob' }); + + const theError = { name: 'boo!' }; + const promise = Promise.all([ + promise_rejects_exactly(t, theError, reader1.closed), + promise_rejects_exactly(t, theError, reader2.closed) + ]); + + controller.error(theError); + await promise; + +}, 'ReadableStream teeing with byte source: erroring the original should immediately error the branches'); + +promise_test(async t => { + + let controller; + const rs = new ReadableStream({ + type: 'bytes', + start(c) { + controller = c; + } + }); + + const [branch1, branch2] = rs.tee(); + const reader1 = branch1.getReader(); + const reader2 = branch2.getReader(); + + const theError = { name: 'boo!' }; + const promise = Promise.all([ + promise_rejects_exactly(t, theError, reader1.read()), + promise_rejects_exactly(t, theError, reader2.read()) + ]); + + controller.error(theError); + await promise; + +}, 'ReadableStream teeing with byte source: erroring the original should error pending reads from default reader'); + +promise_test(async t => { + + let controller; + const rs = new ReadableStream({ + type: 'bytes', + start(c) { + controller = c; + } + }); + + const [branch1, branch2] = rs.tee(); + const reader1 = branch1.getReader({ mode: 'byob' }); + const reader2 = branch2.getReader({ mode: 'byob' }); + + const theError = { name: 'boo!' }; + const promise = Promise.all([ + promise_rejects_exactly(t, theError, reader1.read(new Uint8Array(1))), + promise_rejects_exactly(t, theError, reader2.read(new Uint8Array(1))) + ]); + + controller.error(theError); + await promise; + +}, 'ReadableStream teeing with byte source: erroring the original should error pending reads from BYOB reader'); + +promise_test(async () => { + + let controller; + const rs = new ReadableStream({ + type: 'bytes', + start(c) { + controller = c; + } + }); + + const [branch1, branch2] = rs.tee(); + const reader1 = branch1.getReader({ mode: 'byob' }); + const reader2 = branch2.getReader({ mode: 'byob' }); + const cancelPromise = reader2.cancel(); + + controller.enqueue(new Uint8Array([0x01])); + + const read1 = await reader1.read(new Uint8Array(1)); + assert_equals(read1.done, false, 'first read() from branch1 should not be done'); + assert_typed_array_equals(read1.value, new Uint8Array([0x01]), 'first read() from branch1'); + + controller.close(); + + const read2 = await reader1.read(new Uint8Array(1)); + assert_equals(read2.done, true, 'second read() from branch1 should be done'); + + await Promise.all([ + reader1.closed, + cancelPromise + ]); + +}, 'ReadableStream teeing with byte source: canceling branch1 should finish when branch2 reads until end of stream'); + +promise_test(async t => { + + let controller; + const theError = { name: 'boo!' }; + const rs = new ReadableStream({ + type: 'bytes', + start(c) { + controller = c; + } + }); + + const [branch1, branch2] = rs.tee(); + const reader1 = branch1.getReader({ mode: 'byob' }); + const reader2 = branch2.getReader({ mode: 'byob' }); + const cancelPromise = reader2.cancel(); + + controller.error(theError); + + await Promise.all([ + promise_rejects_exactly(t, theError, reader1.read(new Uint8Array(1))), + cancelPromise + ]); + +}, 'ReadableStream teeing with byte source: canceling branch1 should finish when original stream errors'); + +promise_test(async () => { + + const rs = recordingReadableStream({ type: 'bytes' }); + + // Create two branches, each with a HWM of 0. This should result in no chunks being pulled. + rs.tee(); + + await flushAsyncEvents(); + assert_array_equals(rs.events, [], 'pull should not be called'); + +}, 'ReadableStream teeing with byte source: should not pull any chunks if no branches are reading'); + +promise_test(async () => { + + const rs = recordingReadableStream({ + type: 'bytes', + pull(controller) { + controller.enqueue(new Uint8Array([0x01])); + } + }); + + const [reader1, reader2] = rs.tee().map(branch => branch.getReader({ mode: 'byob' })); + await Promise.all([ + reader1.read(new Uint8Array(1)), + reader2.read(new Uint8Array(1)) + ]); + assert_array_equals(rs.events, ['pull'], 'pull should be called once'); + +}, 'ReadableStream teeing with byte source: should only pull enough to fill the emptiest queue'); + +promise_test(async t => { + + const rs = recordingReadableStream({ type: 'bytes' }); + const theError = { name: 'boo!' }; + + rs.controller.error(theError); + + const [reader1, reader2] = rs.tee().map(branch => branch.getReader({ mode: 'byob' })); + + await flushAsyncEvents(); + assert_array_equals(rs.events, [], 'pull should not be called'); + + await Promise.all([ + promise_rejects_exactly(t, theError, reader1.closed), + promise_rejects_exactly(t, theError, reader2.closed) + ]); + +}, 'ReadableStream teeing with byte source: should not pull when original is already errored'); + +for (const branch of [1, 2]) { + promise_test(async t => { + + const rs = recordingReadableStream({ type: 'bytes' }); + const theError = { name: 'boo!' }; + + const [reader1, reader2] = rs.tee().map(branch => branch.getReader({ mode: 'byob' })); + + await flushAsyncEvents(); + assert_array_equals(rs.events, [], 'pull should not be called'); + + const reader = (branch === 1) ? reader1 : reader2; + const read1 = reader.read(new Uint8Array(1)); + + await flushAsyncEvents(); + assert_array_equals(rs.events, ['pull'], 'pull should be called once'); + + rs.controller.error(theError); + + await Promise.all([ + promise_rejects_exactly(t, theError, read1), + promise_rejects_exactly(t, theError, reader1.closed), + promise_rejects_exactly(t, theError, reader2.closed) + ]); + + await flushAsyncEvents(); + assert_array_equals(rs.events, ['pull'], 'pull should be called once'); + + }, `ReadableStream teeing with byte source: stops pulling when original stream errors while branch ${branch} is reading`); +} + +promise_test(async t => { + + const rs = recordingReadableStream({ type: 'bytes' }); + const theError = { name: 'boo!' }; + + const [reader1, reader2] = rs.tee().map(branch => branch.getReader({ mode: 'byob' })); + + await flushAsyncEvents(); + assert_array_equals(rs.events, [], 'pull should not be called'); + + const read1 = reader1.read(new Uint8Array(1)); + const read2 = reader2.read(new Uint8Array(1)); + + await flushAsyncEvents(); + assert_array_equals(rs.events, ['pull'], 'pull should be called once'); + + rs.controller.error(theError); + + await Promise.all([ + promise_rejects_exactly(t, theError, read1), + promise_rejects_exactly(t, theError, read2), + promise_rejects_exactly(t, theError, reader1.closed), + promise_rejects_exactly(t, theError, reader2.closed) + ]); + + await flushAsyncEvents(); + assert_array_equals(rs.events, ['pull'], 'pull should be called once'); + +}, 'ReadableStream teeing with byte source: stops pulling when original stream errors while both branches are reading'); + +promise_test(async () => { + + const rs = recordingReadableStream({ type: 'bytes' }); + + const [reader1, reader2] = rs.tee().map(branch => branch.getReader({ mode: 'byob' })); + + const read1 = reader1.read(new Uint8Array([0x11])); + const read2 = reader2.read(new Uint8Array([0x22])); + + const cancel1 = reader1.cancel(); + await flushAsyncEvents(); + const cancel2 = reader2.cancel(); + + const result1 = await read1; + assert_object_equals(result1, { value: undefined, done: true }); + const result2 = await read2; + assert_object_equals(result2, { value: undefined, done: true }); + + await Promise.all([cancel1, cancel2]); + +}, 'ReadableStream teeing with byte source: canceling both branches in sequence with delay'); + +promise_test(async t => { + + const theError = { name: 'boo!' }; + const rs = new ReadableStream({ + type: 'bytes', + cancel() { + throw theError; + } + }); + + const [reader1, reader2] = rs.tee().map(branch => branch.getReader({ mode: 'byob' })); + + const read1 = reader1.read(new Uint8Array([0x11])); + const read2 = reader2.read(new Uint8Array([0x22])); + + const cancel1 = reader1.cancel(); + await flushAsyncEvents(); + const cancel2 = reader2.cancel(); + + const result1 = await read1; + assert_object_equals(result1, { value: undefined, done: true }); + const result2 = await read2; + assert_object_equals(result2, { value: undefined, done: true }); + + await Promise.all([ + promise_rejects_exactly(t, theError, cancel1), + promise_rejects_exactly(t, theError, cancel2) + ]); + +}, 'ReadableStream teeing with byte source: failing to cancel when canceling both branches in sequence with delay'); + +promise_test(async () => { + + let cancelResolve; + const cancelCalled = new Promise((resolve) => { + cancelResolve = resolve; + }); + const rs = recordingReadableStream({ + type: 'bytes', + cancel() { + cancelResolve(); + } + }); + + const [reader1, reader2] = rs.tee().map(branch => branch.getReader({ mode: 'byob' })); + + const read1 = reader1.read(new Uint8Array([0x11])); + await flushAsyncEvents(); + const read2 = reader2.read(new Uint8Array([0x22])); + await flushAsyncEvents(); + + // We are reading into branch1's buffer. + const byobRequest1 = rs.controller.byobRequest; + assert_not_equals(byobRequest1, null); + assert_typed_array_equals(byobRequest1.view, new Uint8Array([0x11]), 'byobRequest1.view'); + + // Cancelling branch1 should not affect the BYOB request. + const cancel1 = reader1.cancel(); + const result1 = await read1; + assert_equals(result1.done, true); + assert_equals(result1.value, undefined); + await flushAsyncEvents(); + const byobRequest2 = rs.controller.byobRequest; + assert_typed_array_equals(byobRequest2.view, new Uint8Array([0x11]), 'byobRequest2.view'); + + // Cancelling branch1 should invalidate the BYOB request. + const cancel2 = reader2.cancel(); + await cancelCalled; + const byobRequest3 = rs.controller.byobRequest; + assert_equals(byobRequest3, null); + const result2 = await read2; + assert_equals(result2.done, true); + assert_equals(result2.value, undefined); + + await Promise.all([cancel1, cancel2]); + +}, 'ReadableStream teeing with byte source: read from branch1 and branch2, cancel branch1, cancel branch2'); + +promise_test(async () => { + + let cancelResolve; + const cancelCalled = new Promise((resolve) => { + cancelResolve = resolve; + }); + const rs = recordingReadableStream({ + type: 'bytes', + cancel() { + cancelResolve(); + } + }); + + const [reader1, reader2] = rs.tee().map(branch => branch.getReader({ mode: 'byob' })); + + const read1 = reader1.read(new Uint8Array([0x11])); + await flushAsyncEvents(); + const read2 = reader2.read(new Uint8Array([0x22])); + await flushAsyncEvents(); + + // We are reading into branch1's buffer. + const byobRequest1 = rs.controller.byobRequest; + assert_not_equals(byobRequest1, null); + assert_typed_array_equals(byobRequest1.view, new Uint8Array([0x11]), 'byobRequest1.view'); + + // Cancelling branch2 should not affect the BYOB request. + const cancel2 = reader2.cancel(); + const result2 = await read2; + assert_equals(result2.done, true); + assert_equals(result2.value, undefined); + await flushAsyncEvents(); + const byobRequest2 = rs.controller.byobRequest; + assert_typed_array_equals(byobRequest2.view, new Uint8Array([0x11]), 'byobRequest2.view'); + + // Cancelling branch1 should invalidate the BYOB request. + const cancel1 = reader1.cancel(); + await cancelCalled; + const byobRequest3 = rs.controller.byobRequest; + assert_equals(byobRequest3, null); + const result1 = await read1; + assert_equals(result1.done, true); + assert_equals(result1.value, undefined); + + await Promise.all([cancel1, cancel2]); + +}, 'ReadableStream teeing with byte source: read from branch1 and branch2, cancel branch2, cancel branch1'); + +promise_test(async () => { + + const rs = recordingReadableStream({ type: 'bytes' }); + + const [reader1, reader2] = rs.tee().map(branch => branch.getReader({ mode: 'byob' })); + + const read1 = reader1.read(new Uint8Array([0x11])); + await flushAsyncEvents(); + const read2 = reader2.read(new Uint8Array([0x22])); + await flushAsyncEvents(); + + // We are reading into branch1's buffer. + assert_typed_array_equals(rs.controller.byobRequest.view, new Uint8Array([0x11]), 'first byobRequest.view'); + + // Cancelling branch2 should not affect the BYOB request. + reader2.cancel(); + const result2 = await read2; + assert_equals(result2.done, true); + assert_equals(result2.value, undefined); + await flushAsyncEvents(); + assert_typed_array_equals(rs.controller.byobRequest.view, new Uint8Array([0x11]), 'second byobRequest.view'); + + // Respond to the BYOB request. + rs.controller.byobRequest.view[0] = 0x33; + rs.controller.byobRequest.respond(1); + + // branch1 should receive the read chunk. + const result1 = await read1; + assert_equals(result1.done, false); + assert_typed_array_equals(result1.value, new Uint8Array([0x33]), 'first read() from branch1'); + +}, 'ReadableStream teeing with byte source: read from branch1 and branch2, cancel branch2, enqueue to branch1'); + +promise_test(async () => { + + const rs = recordingReadableStream({ type: 'bytes' }); + + const [reader1, reader2] = rs.tee().map(branch => branch.getReader({ mode: 'byob' })); + + const read1 = reader1.read(new Uint8Array([0x11])); + await flushAsyncEvents(); + const read2 = reader2.read(new Uint8Array([0x22])); + await flushAsyncEvents(); + + // We are reading into branch1's buffer. + assert_typed_array_equals(rs.controller.byobRequest.view, new Uint8Array([0x11]), 'first byobRequest.view'); + + // Cancelling branch1 should not affect the BYOB request. + reader1.cancel(); + const result1 = await read1; + assert_equals(result1.done, true); + assert_equals(result1.value, undefined); + await flushAsyncEvents(); + assert_typed_array_equals(rs.controller.byobRequest.view, new Uint8Array([0x11]), 'second byobRequest.view'); + + // Respond to the BYOB request. + rs.controller.byobRequest.view[0] = 0x33; + rs.controller.byobRequest.respond(1); + + // branch2 should receive the read chunk. + const result2 = await read2; + assert_equals(result2.done, false); + assert_typed_array_equals(result2.value, new Uint8Array([0x33]), 'first read() from branch2'); + +}, 'ReadableStream teeing with byte source: read from branch1 and branch2, cancel branch1, respond to branch2'); + +promise_test(async () => { + + let pullCount = 0; + const byobRequestDefined = []; + const rs = new ReadableStream({ + type: 'bytes', + pull(c) { + ++pullCount; + byobRequestDefined.push(c.byobRequest !== null); + c.enqueue(new Uint8Array([pullCount])); + } + }); + + const [branch1, _] = rs.tee(); + const reader1 = branch1.getReader({ mode: 'byob' }); + + const result1 = await reader1.read(new Uint8Array([0x11])); + assert_equals(result1.done, false, 'first read should not be done'); + assert_typed_array_equals(result1.value, new Uint8Array([0x1]), 'first read'); + assert_equals(pullCount, 1, 'pull() should be called once'); + assert_equals(byobRequestDefined[0], true, 'should have created a BYOB request for first read'); + + reader1.releaseLock(); + const reader2 = branch1.getReader(); + + const result2 = await reader2.read(); + assert_equals(result2.done, false, 'second read should not be done'); + assert_typed_array_equals(result2.value, new Uint8Array([0x2]), 'second read'); + assert_equals(pullCount, 2, 'pull() should be called twice'); + assert_equals(byobRequestDefined[1], false, 'should not have created a BYOB request for second read'); + +}, 'ReadableStream teeing with byte source: pull with BYOB reader, then pull with default reader'); + +promise_test(async () => { + + let pullCount = 0; + const byobRequestDefined = []; + const rs = new ReadableStream({ + type: 'bytes', + pull(c) { + ++pullCount; + byobRequestDefined.push(c.byobRequest !== null); + c.enqueue(new Uint8Array([pullCount])); + } + }); + + const [branch1, _] = rs.tee(); + const reader1 = branch1.getReader(); + + const result1 = await reader1.read(); + assert_equals(result1.done, false, 'first read should not be done'); + assert_typed_array_equals(result1.value, new Uint8Array([0x1]), 'first read'); + assert_equals(pullCount, 1, 'pull() should be called once'); + assert_equals(byobRequestDefined[0], false, 'should not have created a BYOB request for first read'); + + reader1.releaseLock(); + const reader2 = branch1.getReader({ mode: 'byob' }); + + const result2 = await reader2.read(new Uint8Array([0x22])); + assert_equals(result2.done, false, 'second read should not be done'); + assert_typed_array_equals(result2.value, new Uint8Array([0x2]), 'second read'); + assert_equals(pullCount, 2, 'pull() should be called twice'); + assert_equals(byobRequestDefined[1], true, 'should have created a BYOB request for second read'); + +}, 'ReadableStream teeing with byte source: pull with default reader, then pull with BYOB reader'); + +promise_test(async () => { + + const rs = recordingReadableStream({ + type: 'bytes' + }); + const [reader1, reader2] = rs.tee().map(branch => branch.getReader({ mode: 'byob' })); + + // Wait for each branch's start() promise to resolve. + await flushAsyncEvents(); + + const read2 = reader2.read(new Uint8Array([0x22])); + const read1 = reader1.read(new Uint8Array([0x11])); + await flushAsyncEvents(); + + // branch2 should provide the BYOB request. + const byobRequest = rs.controller.byobRequest; + assert_typed_array_equals(byobRequest.view, new Uint8Array([0x22]), 'first BYOB request'); + byobRequest.view[0] = 0x01; + byobRequest.respond(1); + + const result1 = await read1; + assert_equals(result1.done, false, 'first read should not be done'); + assert_typed_array_equals(result1.value, new Uint8Array([0x1]), 'first read'); + + const result2 = await read2; + assert_equals(result2.done, false, 'second read should not be done'); + assert_typed_array_equals(result2.value, new Uint8Array([0x1]), 'second read'); + +}, 'ReadableStream teeing with byte source: read from branch2, then read from branch1'); + +promise_test(async () => { + + const rs = recordingReadableStream({ type: 'bytes' }); + const [branch1, branch2] = rs.tee(); + const reader1 = branch1.getReader(); + const reader2 = branch2.getReader({ mode: 'byob' }); + await flushAsyncEvents(); + + const read1 = reader1.read(); + const read2 = reader2.read(new Uint8Array([0x22])); + await flushAsyncEvents(); + + // There should be no BYOB request. + assert_equals(rs.controller.byobRequest, null, 'first BYOB request'); + + // Close the stream. + rs.controller.close(); + + const result1 = await read1; + assert_equals(result1.done, true, 'read from branch1 should be done'); + assert_equals(result1.value, undefined, 'read from branch1'); + + // branch2 should get its buffer back. + const result2 = await read2; + assert_equals(result2.done, true, 'read from branch2 should be done'); + assert_typed_array_equals(result2.value, new Uint8Array([0x22]).subarray(0, 0), 'read from branch2'); + +}, 'ReadableStream teeing with byte source: read from branch1 with default reader, then close while branch2 has pending BYOB read'); + +promise_test(async () => { + + const rs = recordingReadableStream({ type: 'bytes' }); + const [branch1, branch2] = rs.tee(); + const reader1 = branch1.getReader({ mode: 'byob' }); + const reader2 = branch2.getReader(); + await flushAsyncEvents(); + + const read2 = reader2.read(); + const read1 = reader1.read(new Uint8Array([0x11])); + await flushAsyncEvents(); + + // There should be no BYOB request. + assert_equals(rs.controller.byobRequest, null, 'first BYOB request'); + + // Close the stream. + rs.controller.close(); + + const result2 = await read2; + assert_equals(result2.done, true, 'read from branch2 should be done'); + assert_equals(result2.value, undefined, 'read from branch2'); + + // branch1 should get its buffer back. + const result1 = await read1; + assert_equals(result1.done, true, 'read from branch1 should be done'); + assert_typed_array_equals(result1.value, new Uint8Array([0x11]).subarray(0, 0), 'read from branch1'); + +}, 'ReadableStream teeing with byte source: read from branch2 with default reader, then close while branch1 has pending BYOB read'); + +promise_test(async () => { + + const rs = recordingReadableStream({ type: 'bytes' }); + const [reader1, reader2] = rs.tee().map(branch => branch.getReader({ mode: 'byob' })); + await flushAsyncEvents(); + + const read1 = reader1.read(new Uint8Array([0x11])); + const read2 = reader2.read(new Uint8Array([0x22])); + await flushAsyncEvents(); + + // branch1 should provide the BYOB request. + const byobRequest = rs.controller.byobRequest; + assert_typed_array_equals(byobRequest.view, new Uint8Array([0x11]), 'first BYOB request'); + + // Close the stream. + rs.controller.close(); + byobRequest.respond(0); + + // Both branches should get their buffers back. + const result1 = await read1; + assert_equals(result1.done, true, 'first read should be done'); + assert_typed_array_equals(result1.value, new Uint8Array([0x11]).subarray(0, 0), 'first read'); + + const result2 = await read2; + assert_equals(result2.done, true, 'second read should be done'); + assert_typed_array_equals(result2.value, new Uint8Array([0x22]).subarray(0, 0), 'second read'); + +}, 'ReadableStream teeing with byte source: close when both branches have pending BYOB reads');
diff --git a/third_party/blink/web_tests/external/wpt/streams/readable-byte-streams/tee.any.serviceworker-expected.txt b/third_party/blink/web_tests/external/wpt/streams/readable-byte-streams/tee.any.serviceworker-expected.txt new file mode 100644 index 0000000..1f96021 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/streams/readable-byte-streams/tee.any.serviceworker-expected.txt
@@ -0,0 +1,39 @@ +This is a testharness.js-based test. +PASS ReadableStream teeing with byte source: rs.tee() returns an array of two ReadableStreams +FAIL ReadableStream teeing with byte source: should be able to read one branch to the end without affecting the other promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'getReader' on 'ReadableStream': Cannot use a BYOB reader with a non-byte stream" +FAIL ReadableStream teeing with byte source: chunks should be cloned for each branch assert_not_equals: chunks should have different buffers got disallowed value object "[object ArrayBuffer]" +FAIL ReadableStream teeing with byte source: chunks for BYOB requests from branch 1 should be cloned to branch 2 promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'getReader' on 'ReadableStream': Cannot use a BYOB reader with a non-byte stream" +FAIL ReadableStream teeing with byte source: errors in the source should propagate to both branches promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'getReader' on 'ReadableStream': Cannot use a BYOB reader with a non-byte stream" +PASS ReadableStream teeing with byte source: canceling branch1 should not impact branch2 +PASS ReadableStream teeing with byte source: canceling branch2 should not impact branch1 +PASS Running templatedRSTeeCancel with ReadableStream teeing with byte source +PASS ReadableStream teeing with byte source: canceling both branches should aggregate the cancel reasons into an array +PASS ReadableStream teeing with byte source: canceling both branches in reverse order should aggregate the cancel reasons into an array +PASS ReadableStream teeing with byte source: failing to cancel the original stream should cause cancel() to reject on branches +PASS ReadableStream teeing with byte source: erroring a teed stream should properly handle canceled branches +FAIL ReadableStream teeing with byte source: closing the original should close the branches promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'getReader' on 'ReadableStream': Cannot use a BYOB reader with a non-byte stream" +FAIL ReadableStream teeing with byte source: erroring the original should immediately error the branches promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'getReader' on 'ReadableStream': Cannot use a BYOB reader with a non-byte stream" +PASS ReadableStream teeing with byte source: erroring the original should error pending reads from default reader +FAIL ReadableStream teeing with byte source: erroring the original should error pending reads from BYOB reader promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'getReader' on 'ReadableStream': Cannot use a BYOB reader with a non-byte stream" +FAIL ReadableStream teeing with byte source: canceling branch1 should finish when branch2 reads until end of stream promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'getReader' on 'ReadableStream': Cannot use a BYOB reader with a non-byte stream" +FAIL ReadableStream teeing with byte source: canceling branch1 should finish when original stream errors promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'getReader' on 'ReadableStream': Cannot use a BYOB reader with a non-byte stream" +FAIL ReadableStream teeing with byte source: should not pull any chunks if no branches are reading assert_array_equals: pull should not be called lengths differ, expected array [] length 0, got ["pull", "pull"] length 2 +FAIL ReadableStream teeing with byte source: should only pull enough to fill the emptiest queue promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'getReader' on 'ReadableStream': Cannot use a BYOB reader with a non-byte stream" +FAIL ReadableStream teeing with byte source: should not pull when original is already errored promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'getReader' on 'ReadableStream': Cannot use a BYOB reader with a non-byte stream" +FAIL ReadableStream teeing with byte source: stops pulling when original stream errors while branch 1 is reading promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'getReader' on 'ReadableStream': Cannot use a BYOB reader with a non-byte stream" +FAIL ReadableStream teeing with byte source: stops pulling when original stream errors while branch 2 is reading promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'getReader' on 'ReadableStream': Cannot use a BYOB reader with a non-byte stream" +FAIL ReadableStream teeing with byte source: stops pulling when original stream errors while both branches are reading promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'getReader' on 'ReadableStream': Cannot use a BYOB reader with a non-byte stream" +FAIL ReadableStream teeing with byte source: canceling both branches in sequence with delay promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'getReader' on 'ReadableStream': Cannot use a BYOB reader with a non-byte stream" +FAIL ReadableStream teeing with byte source: failing to cancel when canceling both branches in sequence with delay promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'getReader' on 'ReadableStream': Cannot use a BYOB reader with a non-byte stream" +FAIL ReadableStream teeing with byte source: read from branch1 and branch2, cancel branch1, cancel branch2 promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'getReader' on 'ReadableStream': Cannot use a BYOB reader with a non-byte stream" +FAIL ReadableStream teeing with byte source: read from branch1 and branch2, cancel branch2, cancel branch1 promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'getReader' on 'ReadableStream': Cannot use a BYOB reader with a non-byte stream" +FAIL ReadableStream teeing with byte source: read from branch1 and branch2, cancel branch2, enqueue to branch1 promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'getReader' on 'ReadableStream': Cannot use a BYOB reader with a non-byte stream" +FAIL ReadableStream teeing with byte source: read from branch1 and branch2, cancel branch1, respond to branch2 promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'getReader' on 'ReadableStream': Cannot use a BYOB reader with a non-byte stream" +FAIL ReadableStream teeing with byte source: pull with BYOB reader, then pull with default reader promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'getReader' on 'ReadableStream': Cannot use a BYOB reader with a non-byte stream" +FAIL ReadableStream teeing with byte source: pull with default reader, then pull with BYOB reader assert_equals: pull() should be called once expected 1 but got 2 +FAIL ReadableStream teeing with byte source: read from branch2, then read from branch1 promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'getReader' on 'ReadableStream': Cannot use a BYOB reader with a non-byte stream" +FAIL ReadableStream teeing with byte source: read from branch1 with default reader, then close while branch2 has pending BYOB read promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'getReader' on 'ReadableStream': Cannot use a BYOB reader with a non-byte stream" +FAIL ReadableStream teeing with byte source: read from branch2 with default reader, then close while branch1 has pending BYOB read promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'getReader' on 'ReadableStream': Cannot use a BYOB reader with a non-byte stream" +FAIL ReadableStream teeing with byte source: close when both branches have pending BYOB reads promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'getReader' on 'ReadableStream': Cannot use a BYOB reader with a non-byte stream" +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/streams/readable-byte-streams/tee.any.sharedworker-expected.txt b/third_party/blink/web_tests/external/wpt/streams/readable-byte-streams/tee.any.sharedworker-expected.txt new file mode 100644 index 0000000..1f96021 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/streams/readable-byte-streams/tee.any.sharedworker-expected.txt
@@ -0,0 +1,39 @@ +This is a testharness.js-based test. +PASS ReadableStream teeing with byte source: rs.tee() returns an array of two ReadableStreams +FAIL ReadableStream teeing with byte source: should be able to read one branch to the end without affecting the other promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'getReader' on 'ReadableStream': Cannot use a BYOB reader with a non-byte stream" +FAIL ReadableStream teeing with byte source: chunks should be cloned for each branch assert_not_equals: chunks should have different buffers got disallowed value object "[object ArrayBuffer]" +FAIL ReadableStream teeing with byte source: chunks for BYOB requests from branch 1 should be cloned to branch 2 promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'getReader' on 'ReadableStream': Cannot use a BYOB reader with a non-byte stream" +FAIL ReadableStream teeing with byte source: errors in the source should propagate to both branches promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'getReader' on 'ReadableStream': Cannot use a BYOB reader with a non-byte stream" +PASS ReadableStream teeing with byte source: canceling branch1 should not impact branch2 +PASS ReadableStream teeing with byte source: canceling branch2 should not impact branch1 +PASS Running templatedRSTeeCancel with ReadableStream teeing with byte source +PASS ReadableStream teeing with byte source: canceling both branches should aggregate the cancel reasons into an array +PASS ReadableStream teeing with byte source: canceling both branches in reverse order should aggregate the cancel reasons into an array +PASS ReadableStream teeing with byte source: failing to cancel the original stream should cause cancel() to reject on branches +PASS ReadableStream teeing with byte source: erroring a teed stream should properly handle canceled branches +FAIL ReadableStream teeing with byte source: closing the original should close the branches promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'getReader' on 'ReadableStream': Cannot use a BYOB reader with a non-byte stream" +FAIL ReadableStream teeing with byte source: erroring the original should immediately error the branches promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'getReader' on 'ReadableStream': Cannot use a BYOB reader with a non-byte stream" +PASS ReadableStream teeing with byte source: erroring the original should error pending reads from default reader +FAIL ReadableStream teeing with byte source: erroring the original should error pending reads from BYOB reader promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'getReader' on 'ReadableStream': Cannot use a BYOB reader with a non-byte stream" +FAIL ReadableStream teeing with byte source: canceling branch1 should finish when branch2 reads until end of stream promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'getReader' on 'ReadableStream': Cannot use a BYOB reader with a non-byte stream" +FAIL ReadableStream teeing with byte source: canceling branch1 should finish when original stream errors promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'getReader' on 'ReadableStream': Cannot use a BYOB reader with a non-byte stream" +FAIL ReadableStream teeing with byte source: should not pull any chunks if no branches are reading assert_array_equals: pull should not be called lengths differ, expected array [] length 0, got ["pull", "pull"] length 2 +FAIL ReadableStream teeing with byte source: should only pull enough to fill the emptiest queue promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'getReader' on 'ReadableStream': Cannot use a BYOB reader with a non-byte stream" +FAIL ReadableStream teeing with byte source: should not pull when original is already errored promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'getReader' on 'ReadableStream': Cannot use a BYOB reader with a non-byte stream" +FAIL ReadableStream teeing with byte source: stops pulling when original stream errors while branch 1 is reading promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'getReader' on 'ReadableStream': Cannot use a BYOB reader with a non-byte stream" +FAIL ReadableStream teeing with byte source: stops pulling when original stream errors while branch 2 is reading promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'getReader' on 'ReadableStream': Cannot use a BYOB reader with a non-byte stream" +FAIL ReadableStream teeing with byte source: stops pulling when original stream errors while both branches are reading promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'getReader' on 'ReadableStream': Cannot use a BYOB reader with a non-byte stream" +FAIL ReadableStream teeing with byte source: canceling both branches in sequence with delay promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'getReader' on 'ReadableStream': Cannot use a BYOB reader with a non-byte stream" +FAIL ReadableStream teeing with byte source: failing to cancel when canceling both branches in sequence with delay promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'getReader' on 'ReadableStream': Cannot use a BYOB reader with a non-byte stream" +FAIL ReadableStream teeing with byte source: read from branch1 and branch2, cancel branch1, cancel branch2 promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'getReader' on 'ReadableStream': Cannot use a BYOB reader with a non-byte stream" +FAIL ReadableStream teeing with byte source: read from branch1 and branch2, cancel branch2, cancel branch1 promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'getReader' on 'ReadableStream': Cannot use a BYOB reader with a non-byte stream" +FAIL ReadableStream teeing with byte source: read from branch1 and branch2, cancel branch2, enqueue to branch1 promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'getReader' on 'ReadableStream': Cannot use a BYOB reader with a non-byte stream" +FAIL ReadableStream teeing with byte source: read from branch1 and branch2, cancel branch1, respond to branch2 promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'getReader' on 'ReadableStream': Cannot use a BYOB reader with a non-byte stream" +FAIL ReadableStream teeing with byte source: pull with BYOB reader, then pull with default reader promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'getReader' on 'ReadableStream': Cannot use a BYOB reader with a non-byte stream" +FAIL ReadableStream teeing with byte source: pull with default reader, then pull with BYOB reader assert_equals: pull() should be called once expected 1 but got 2 +FAIL ReadableStream teeing with byte source: read from branch2, then read from branch1 promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'getReader' on 'ReadableStream': Cannot use a BYOB reader with a non-byte stream" +FAIL ReadableStream teeing with byte source: read from branch1 with default reader, then close while branch2 has pending BYOB read promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'getReader' on 'ReadableStream': Cannot use a BYOB reader with a non-byte stream" +FAIL ReadableStream teeing with byte source: read from branch2 with default reader, then close while branch1 has pending BYOB read promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'getReader' on 'ReadableStream': Cannot use a BYOB reader with a non-byte stream" +FAIL ReadableStream teeing with byte source: close when both branches have pending BYOB reads promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'getReader' on 'ReadableStream': Cannot use a BYOB reader with a non-byte stream" +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/streams/readable-byte-streams/tee.any.worker-expected.txt b/third_party/blink/web_tests/external/wpt/streams/readable-byte-streams/tee.any.worker-expected.txt new file mode 100644 index 0000000..1f96021 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/streams/readable-byte-streams/tee.any.worker-expected.txt
@@ -0,0 +1,39 @@ +This is a testharness.js-based test. +PASS ReadableStream teeing with byte source: rs.tee() returns an array of two ReadableStreams +FAIL ReadableStream teeing with byte source: should be able to read one branch to the end without affecting the other promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'getReader' on 'ReadableStream': Cannot use a BYOB reader with a non-byte stream" +FAIL ReadableStream teeing with byte source: chunks should be cloned for each branch assert_not_equals: chunks should have different buffers got disallowed value object "[object ArrayBuffer]" +FAIL ReadableStream teeing with byte source: chunks for BYOB requests from branch 1 should be cloned to branch 2 promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'getReader' on 'ReadableStream': Cannot use a BYOB reader with a non-byte stream" +FAIL ReadableStream teeing with byte source: errors in the source should propagate to both branches promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'getReader' on 'ReadableStream': Cannot use a BYOB reader with a non-byte stream" +PASS ReadableStream teeing with byte source: canceling branch1 should not impact branch2 +PASS ReadableStream teeing with byte source: canceling branch2 should not impact branch1 +PASS Running templatedRSTeeCancel with ReadableStream teeing with byte source +PASS ReadableStream teeing with byte source: canceling both branches should aggregate the cancel reasons into an array +PASS ReadableStream teeing with byte source: canceling both branches in reverse order should aggregate the cancel reasons into an array +PASS ReadableStream teeing with byte source: failing to cancel the original stream should cause cancel() to reject on branches +PASS ReadableStream teeing with byte source: erroring a teed stream should properly handle canceled branches +FAIL ReadableStream teeing with byte source: closing the original should close the branches promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'getReader' on 'ReadableStream': Cannot use a BYOB reader with a non-byte stream" +FAIL ReadableStream teeing with byte source: erroring the original should immediately error the branches promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'getReader' on 'ReadableStream': Cannot use a BYOB reader with a non-byte stream" +PASS ReadableStream teeing with byte source: erroring the original should error pending reads from default reader +FAIL ReadableStream teeing with byte source: erroring the original should error pending reads from BYOB reader promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'getReader' on 'ReadableStream': Cannot use a BYOB reader with a non-byte stream" +FAIL ReadableStream teeing with byte source: canceling branch1 should finish when branch2 reads until end of stream promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'getReader' on 'ReadableStream': Cannot use a BYOB reader with a non-byte stream" +FAIL ReadableStream teeing with byte source: canceling branch1 should finish when original stream errors promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'getReader' on 'ReadableStream': Cannot use a BYOB reader with a non-byte stream" +FAIL ReadableStream teeing with byte source: should not pull any chunks if no branches are reading assert_array_equals: pull should not be called lengths differ, expected array [] length 0, got ["pull", "pull"] length 2 +FAIL ReadableStream teeing with byte source: should only pull enough to fill the emptiest queue promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'getReader' on 'ReadableStream': Cannot use a BYOB reader with a non-byte stream" +FAIL ReadableStream teeing with byte source: should not pull when original is already errored promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'getReader' on 'ReadableStream': Cannot use a BYOB reader with a non-byte stream" +FAIL ReadableStream teeing with byte source: stops pulling when original stream errors while branch 1 is reading promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'getReader' on 'ReadableStream': Cannot use a BYOB reader with a non-byte stream" +FAIL ReadableStream teeing with byte source: stops pulling when original stream errors while branch 2 is reading promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'getReader' on 'ReadableStream': Cannot use a BYOB reader with a non-byte stream" +FAIL ReadableStream teeing with byte source: stops pulling when original stream errors while both branches are reading promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'getReader' on 'ReadableStream': Cannot use a BYOB reader with a non-byte stream" +FAIL ReadableStream teeing with byte source: canceling both branches in sequence with delay promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'getReader' on 'ReadableStream': Cannot use a BYOB reader with a non-byte stream" +FAIL ReadableStream teeing with byte source: failing to cancel when canceling both branches in sequence with delay promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'getReader' on 'ReadableStream': Cannot use a BYOB reader with a non-byte stream" +FAIL ReadableStream teeing with byte source: read from branch1 and branch2, cancel branch1, cancel branch2 promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'getReader' on 'ReadableStream': Cannot use a BYOB reader with a non-byte stream" +FAIL ReadableStream teeing with byte source: read from branch1 and branch2, cancel branch2, cancel branch1 promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'getReader' on 'ReadableStream': Cannot use a BYOB reader with a non-byte stream" +FAIL ReadableStream teeing with byte source: read from branch1 and branch2, cancel branch2, enqueue to branch1 promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'getReader' on 'ReadableStream': Cannot use a BYOB reader with a non-byte stream" +FAIL ReadableStream teeing with byte source: read from branch1 and branch2, cancel branch1, respond to branch2 promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'getReader' on 'ReadableStream': Cannot use a BYOB reader with a non-byte stream" +FAIL ReadableStream teeing with byte source: pull with BYOB reader, then pull with default reader promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'getReader' on 'ReadableStream': Cannot use a BYOB reader with a non-byte stream" +FAIL ReadableStream teeing with byte source: pull with default reader, then pull with BYOB reader assert_equals: pull() should be called once expected 1 but got 2 +FAIL ReadableStream teeing with byte source: read from branch2, then read from branch1 promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'getReader' on 'ReadableStream': Cannot use a BYOB reader with a non-byte stream" +FAIL ReadableStream teeing with byte source: read from branch1 with default reader, then close while branch2 has pending BYOB read promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'getReader' on 'ReadableStream': Cannot use a BYOB reader with a non-byte stream" +FAIL ReadableStream teeing with byte source: read from branch2 with default reader, then close while branch1 has pending BYOB read promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'getReader' on 'ReadableStream': Cannot use a BYOB reader with a non-byte stream" +FAIL ReadableStream teeing with byte source: close when both branches have pending BYOB reads promise_test: Unhandled rejection with value: object "TypeError: Failed to execute 'getReader' on 'ReadableStream': Cannot use a BYOB reader with a non-byte stream" +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/streams/readable-streams/tee.any-expected.txt b/third_party/blink/web_tests/external/wpt/streams/readable-streams/tee.any-expected.txt index bebedc3..1c3ffa74 100644 --- a/third_party/blink/web_tests/external/wpt/streams/readable-streams/tee.any-expected.txt +++ b/third_party/blink/web_tests/external/wpt/streams/readable-streams/tee.any-expected.txt
@@ -5,6 +5,7 @@ PASS ReadableStream teeing: errors in the source should propagate to both branches PASS ReadableStream teeing: canceling branch1 should not impact branch2 PASS ReadableStream teeing: canceling branch2 should not impact branch1 +PASS Running templatedRSTeeCancel with ReadableStream teeing PASS ReadableStream teeing: canceling both branches should aggregate the cancel reasons into an array PASS ReadableStream teeing: canceling both branches in reverse order should aggregate the cancel reasons into an array PASS ReadableStream teeing: failing to cancel the original stream should cause cancel() to reject on branches
diff --git a/third_party/blink/web_tests/external/wpt/streams/readable-streams/tee.any.js b/third_party/blink/web_tests/external/wpt/streams/readable-streams/tee.any.js index 761f6e9c..14c447b 100644 --- a/third_party/blink/web_tests/external/wpt/streams/readable-streams/tee.any.js +++ b/third_party/blink/web_tests/external/wpt/streams/readable-streams/tee.any.js
@@ -2,6 +2,7 @@ // META: script=../resources/rs-utils.js // META: script=../resources/test-utils.js // META: script=../resources/recording-streams.js +// META: script=../resources/rs-test-templates.js 'use strict'; test(() => { @@ -161,92 +162,9 @@ }, 'ReadableStream teeing: canceling branch2 should not impact branch1'); -promise_test(() => { - - const reason1 = new Error('We\'re wanted men.'); - const reason2 = new Error('I have the death sentence on twelve systems.'); - - let resolve; - const promise = new Promise(r => resolve = r); - const rs = new ReadableStream({ - cancel(reason) { - assert_array_equals(reason, [reason1, reason2], - 'the cancel reason should be an array containing those from the branches'); - resolve(); - } - }); - - const branch = rs.tee(); - const branch1 = branch[0]; - const branch2 = branch[1]; - branch1.cancel(reason1); - branch2.cancel(reason2); - - return promise; - -}, 'ReadableStream teeing: canceling both branches should aggregate the cancel reasons into an array'); - -promise_test(() => { - - const reason1 = new Error('This little one\'s not worth the effort.'); - const reason2 = new Error('Come, let me get you something.'); - - let resolve; - const promise = new Promise(r => resolve = r); - const rs = new ReadableStream({ - cancel(reason) { - assert_array_equals(reason, [reason1, reason2], - 'the cancel reason should be an array containing those from the branches'); - resolve(); - } - }); - - const branch = rs.tee(); - const branch1 = branch[0]; - const branch2 = branch[1]; - return Promise.all([ - branch2.cancel(reason2), - branch1.cancel(reason1), - promise - ]); - -}, 'ReadableStream teeing: canceling both branches in reverse order should aggregate the cancel reasons into an array'); - -promise_test(t => { - - const theError = { name: 'I\'ll be careful.' }; - const rs = new ReadableStream({ - cancel() { - throw theError; - } - }); - - const branch = rs.tee(); - const branch1 = branch[0]; - const branch2 = branch[1]; - - return Promise.all([ - promise_rejects_exactly(t, theError, branch1.cancel()), - promise_rejects_exactly(t, theError, branch2.cancel()) - ]); - -}, 'ReadableStream teeing: failing to cancel the original stream should cause cancel() to reject on branches'); - -promise_test(t => { - - const theError = { name: 'You just watch yourself!' }; - let controller; - const stream = new ReadableStream({ start(c) { controller = c; } }); - const [branch1, branch2] = stream.tee(); - - controller.error(theError); - - return Promise.all([ - promise_rejects_exactly(t, theError, branch1.cancel()), - promise_rejects_exactly(t, theError, branch2.cancel()) - ]); - -}, 'ReadableStream teeing: erroring a teed stream should properly handle canceled branches'); +templatedRSTeeCancel('ReadableStream teeing', (extras) => { + return new ReadableStream({ ...extras }); +}); promise_test(t => {
diff --git a/third_party/blink/web_tests/external/wpt/streams/readable-streams/tee.any.serviceworker-expected.txt b/third_party/blink/web_tests/external/wpt/streams/readable-streams/tee.any.serviceworker-expected.txt index bebedc3..1c3ffa74 100644 --- a/third_party/blink/web_tests/external/wpt/streams/readable-streams/tee.any.serviceworker-expected.txt +++ b/third_party/blink/web_tests/external/wpt/streams/readable-streams/tee.any.serviceworker-expected.txt
@@ -5,6 +5,7 @@ PASS ReadableStream teeing: errors in the source should propagate to both branches PASS ReadableStream teeing: canceling branch1 should not impact branch2 PASS ReadableStream teeing: canceling branch2 should not impact branch1 +PASS Running templatedRSTeeCancel with ReadableStream teeing PASS ReadableStream teeing: canceling both branches should aggregate the cancel reasons into an array PASS ReadableStream teeing: canceling both branches in reverse order should aggregate the cancel reasons into an array PASS ReadableStream teeing: failing to cancel the original stream should cause cancel() to reject on branches
diff --git a/third_party/blink/web_tests/external/wpt/streams/readable-streams/tee.any.sharedworker-expected.txt b/third_party/blink/web_tests/external/wpt/streams/readable-streams/tee.any.sharedworker-expected.txt index bebedc3..1c3ffa74 100644 --- a/third_party/blink/web_tests/external/wpt/streams/readable-streams/tee.any.sharedworker-expected.txt +++ b/third_party/blink/web_tests/external/wpt/streams/readable-streams/tee.any.sharedworker-expected.txt
@@ -5,6 +5,7 @@ PASS ReadableStream teeing: errors in the source should propagate to both branches PASS ReadableStream teeing: canceling branch1 should not impact branch2 PASS ReadableStream teeing: canceling branch2 should not impact branch1 +PASS Running templatedRSTeeCancel with ReadableStream teeing PASS ReadableStream teeing: canceling both branches should aggregate the cancel reasons into an array PASS ReadableStream teeing: canceling both branches in reverse order should aggregate the cancel reasons into an array PASS ReadableStream teeing: failing to cancel the original stream should cause cancel() to reject on branches
diff --git a/third_party/blink/web_tests/external/wpt/streams/readable-streams/tee.any.worker-expected.txt b/third_party/blink/web_tests/external/wpt/streams/readable-streams/tee.any.worker-expected.txt index bebedc3..1c3ffa74 100644 --- a/third_party/blink/web_tests/external/wpt/streams/readable-streams/tee.any.worker-expected.txt +++ b/third_party/blink/web_tests/external/wpt/streams/readable-streams/tee.any.worker-expected.txt
@@ -5,6 +5,7 @@ PASS ReadableStream teeing: errors in the source should propagate to both branches PASS ReadableStream teeing: canceling branch1 should not impact branch2 PASS ReadableStream teeing: canceling branch2 should not impact branch1 +PASS Running templatedRSTeeCancel with ReadableStream teeing PASS ReadableStream teeing: canceling both branches should aggregate the cancel reasons into an array PASS ReadableStream teeing: canceling both branches in reverse order should aggregate the cancel reasons into an array PASS ReadableStream teeing: failing to cancel the original stream should cause cancel() to reject on branches
diff --git a/third_party/blink/web_tests/external/wpt/streams/resources/recording-streams.js b/third_party/blink/web_tests/external/wpt/streams/resources/recording-streams.js index 34d02a1..661fe51 100644 --- a/third_party/blink/web_tests/external/wpt/streams/resources/recording-streams.js +++ b/third_party/blink/web_tests/external/wpt/streams/resources/recording-streams.js
@@ -3,6 +3,7 @@ self.recordingReadableStream = (extras = {}, strategy) => { let controllerToCopyOver; const stream = new ReadableStream({ + type: extras.type, start(controller) { controllerToCopyOver = controller;
diff --git a/third_party/blink/web_tests/external/wpt/streams/resources/rs-test-templates.js b/third_party/blink/web_tests/external/wpt/streams/resources/rs-test-templates.js index 700bd9c3..400907a 100644 --- a/third_party/blink/web_tests/external/wpt/streams/resources/rs-test-templates.js +++ b/third_party/blink/web_tests/external/wpt/streams/resources/rs-test-templates.js
@@ -636,3 +636,93 @@ }, label + ': reader\'s closed property always returns the same promise'); }; + +self.templatedRSTeeCancel = (label, factory) => { + test(() => {}, `Running templatedRSTeeCancel with ${label}`); + + promise_test(async () => { + + const reason1 = new Error('We\'re wanted men.'); + const reason2 = new Error('I have the death sentence on twelve systems.'); + + let resolve; + const promise = new Promise(r => resolve = r); + const rs = factory({ + cancel(reason) { + assert_array_equals(reason, [reason1, reason2], + 'the cancel reason should be an array containing those from the branches'); + resolve(); + } + }); + + const [branch1, branch2] = rs.tee(); + await Promise.all([ + branch1.cancel(reason1), + branch2.cancel(reason2), + promise + ]); + + }, `${label}: canceling both branches should aggregate the cancel reasons into an array`); + + promise_test(async () => { + + const reason1 = new Error('This little one\'s not worth the effort.'); + const reason2 = new Error('Come, let me get you something.'); + + let resolve; + const promise = new Promise(r => resolve = r); + const rs = factory({ + cancel(reason) { + assert_array_equals(reason, [reason1, reason2], + 'the cancel reason should be an array containing those from the branches'); + resolve(); + } + }); + + const [branch1, branch2] = rs.tee(); + await Promise.all([ + branch2.cancel(reason2), + branch1.cancel(reason1), + promise + ]); + + }, `${label}: canceling both branches in reverse order should aggregate the cancel reasons into an array`); + + promise_test(async t => { + + const theError = { name: 'I\'ll be careful.' }; + const rs = factory({ + cancel() { + throw theError; + } + }); + + const [branch1, branch2] = rs.tee(); + await Promise.all([ + promise_rejects_exactly(t, theError, branch1.cancel()), + promise_rejects_exactly(t, theError, branch2.cancel()) + ]); + + }, `${label}: failing to cancel the original stream should cause cancel() to reject on branches`); + + promise_test(async t => { + + const theError = { name: 'You just watch yourself!' }; + let controller; + const stream = factory({ + start(c) { + controller = c; + } + }); + + const [branch1, branch2] = stream.tee(); + controller.error(theError); + + await Promise.all([ + promise_rejects_exactly(t, theError, branch1.cancel()), + promise_rejects_exactly(t, theError, branch2.cancel()) + ]); + + }, `${label}: erroring a teed stream should properly handle canceled branches`); + +};
diff --git a/third_party/blink/web_tests/external/wpt/url/resources/a-element-origin.js b/third_party/blink/web_tests/external/wpt/url/resources/a-element-origin.js index 3b8cb1cb..cb7d4a8 100644 --- a/third_party/blink/web_tests/external/wpt/url/resources/a-element-origin.js +++ b/third_party/blink/web_tests/external/wpt/url/resources/a-element-origin.js
@@ -16,6 +16,8 @@ for(var i = 0, l = urltests.length; i < l; i++) { var expected = urltests[i] if (typeof expected === "string" || !("origin" in expected)) continue + // skip without base because you cannot unset the baseURL of a document + if (expected.base === null) continue; test(function() { var url = bURL(expected.input, expected.base)
diff --git a/third_party/blink/web_tests/external/wpt/url/resources/a-element.js b/third_party/blink/web_tests/external/wpt/url/resources/a-element.js index f64531b..553855a8 100644 --- a/third_party/blink/web_tests/external/wpt/url/resources/a-element.js +++ b/third_party/blink/web_tests/external/wpt/url/resources/a-element.js
@@ -16,6 +16,8 @@ for(var i = 0, l = urltests.length; i < l; i++) { var expected = urltests[i] if (typeof expected === "string") continue // skip comments + // skip without base because you cannot unset the baseURL of a document + if (expected.base === null) continue; test(function() { var url = bURL(expected.input, expected.base)
diff --git a/third_party/blink/web_tests/external/wpt/url/resources/urltestdata.json b/third_party/blink/web_tests/external/wpt/url/resources/urltestdata.json index a56b30c..34cc2e5 100644 --- a/third_party/blink/web_tests/external/wpt/url/resources/urltestdata.json +++ b/third_party/blink/web_tests/external/wpt/url/resources/urltestdata.json
@@ -3303,12 +3303,14 @@ { "input": "http:@:www.example.com", "base": "about:blank", - "failure": true + "failure": true, + "inputCanBeRelative": true }, { "input": "http:/@:www.example.com", "base": "about:blank", - "failure": true + "failure": true, + "inputCanBeRelative": true }, { "input": "http://@:www.example.com", @@ -6373,7 +6375,8 @@ { "input": "\\\\\\.\\Y:", "base": "about:blank", - "failure": true + "failure": true, + "inputCanBeRelative": true }, "# file: drive letter cases from https://crbug.com/1078698 but lowercased", { @@ -6435,7 +6438,8 @@ { "input": "\\\\\\.\\y:", "base": "about:blank", - "failure": true + "failure": true, + "inputCanBeRelative": true }, "# Additional file URL tests for (https://github.com/whatwg/url/issues/405)", { @@ -8016,5 +8020,16 @@ "protocol": "abc:", "search": "", "username": "" + }, + "Empty query and fragment with blank should throw an error", + { + "input": "#", + "base": null, + "failure": true + }, + { + "input": "?", + "base": null, + "failure": true } ]
diff --git a/third_party/blink/web_tests/external/wpt/url/url-constructor.any.js b/third_party/blink/web_tests/external/wpt/url/url-constructor.any.js index 3f4af56..dfa9809 100644 --- a/third_party/blink/web_tests/external/wpt/url/url-constructor.any.js +++ b/third_party/blink/web_tests/external/wpt/url/url-constructor.any.js
@@ -1,7 +1,7 @@ // META: timeout=long function bURL(url, base) { - return new URL(url, base || "about:blank") + return base ? new URL(url, base) : new URL(url) } function runURLTests(urltests) {
diff --git a/third_party/blink/web_tests/external/wpt/url/url-origin.any.js b/third_party/blink/web_tests/external/wpt/url/url-origin.any.js index d9ef64c7..9c1f97e 100644 --- a/third_party/blink/web_tests/external/wpt/url/url-origin.any.js +++ b/third_party/blink/web_tests/external/wpt/url/url-origin.any.js
@@ -1,7 +1,7 @@ promise_test(() => fetch("resources/urltestdata.json").then(res => res.json()).then(runURLTests), "Loading data…"); function bURL(url, base) { - return new URL(url, base || "about:blank") + return base ? new URL(url, base) : new URL(url) } function runURLTests(urltests) {
diff --git a/third_party/blink/web_tests/external/wpt/webcodecs/utils.js b/third_party/blink/web_tests/external/wpt/webcodecs/utils.js index e07d0fd..199a136 100644 --- a/third_party/blink/web_tests/external/wpt/webcodecs/utils.js +++ b/third_party/blink/web_tests/external/wpt/webcodecs/utils.js
@@ -150,22 +150,6 @@ return promise_rejects_dom(test, 'InvalidStateError', codec.flush(), 'flush'); } -// Verifies a PlaneInit structure matches the actual constructed plane. -function verifyPlane(expected, actual) { - assert_less_than_equal(expected.stride, actual.stride, 'plane strides'); - assert_equals(expected.rows, actual.rows, 'plane rows'); - assert_less_than_equal( - expected.stride * expected.rows, actual.length, 'plane size'); - - var testBuffer = new Uint8Array(actual.length); - actual.readInto(testBuffer); - for (var h = 0; h < actual.rows; ++h) { - assert_array_equals( - expected.src.slice(h * expected.stride, expected.stride), - testBuffer.slice(h * actual.stride, expected.stride), 'plane data'); - } -} - // Reference values generated by: // https://fiddle.skia.org/c/f100d4d5f085a9e09896aabcbc463868
diff --git a/third_party/blink/web_tests/external/wpt/webcodecs/videoFrame.any.js b/third_party/blink/web_tests/external/wpt/webcodecs/videoFrame.any.js index a67a1b2..82711707 100644 --- a/third_party/blink/web_tests/external/wpt/webcodecs/videoFrame.any.js +++ b/third_party/blink/web_tests/external/wpt/webcodecs/videoFrame.any.js
@@ -54,67 +54,6 @@ test(t => { let image = makeImageBitmap(32, 16); - let frame = new VideoFrame(image, {timestamp: 0}); - - // TODO(sandersd): This would be more clear as RGBA, but conversion has - // not be specified (or implemented) yet. - if (frame.format !== 'I420') { - return; - } - assert_equals(frame.planes.length, 3, 'number of planes'); - - // Validate Y plane metadata. - let yPlane = frame.planes[0]; - let yStride = yPlane.stride; - let yRows = yPlane.rows; - let yLength = yPlane.length; - - // Required minimums to contain the visible data. - assert_greater_than_equal(yRows, 16, 'Y plane rows'); - assert_greater_than_equal(yStride, 32, 'Y plane stride'); - assert_greater_than_equal(yLength, 32 * 16, 'Y plane length'); - - // Not required by spec, but sets limit at 50% padding per dimension. - assert_less_than_equal(yRows, 32, 'Y plane rows'); - assert_less_than_equal(yStride, 64, 'Y plane stride'); - assert_less_than_equal(yLength, 32 * 64, 'Y plane length'); - - // Validate Y plane data. - let buffer = new ArrayBuffer(yLength); - let view = new Uint8Array(buffer); - frame.planes[0].readInto(view); - - // TODO(sandersd): This probably needs to be fuzzy unless we can make - // guarantees about the color space. - assert_equals(view[0], 94, 'Y value at (0, 0)'); - - frame.close(); -}, 'Test we can read planar data from a VideoFrame.'); - -test(t => { - let image = makeImageBitmap(32, 16); - let frame = new VideoFrame(image, {timestamp: 0}); - - // TODO(sandersd): This would be more clear as RGBA, but conversion has - // not be specified (or implemented) yet. - if (frame.format !== 'I420') { - return; - } - - assert_equals(frame.planes.length, 3, 'number of planes'); - - // Attempt to read Y plane data, but close the frame first. - let yPlane = frame.planes[0]; - let yLength = yPlane.length; - frame.close(); - - let buffer = new ArrayBuffer(yLength); - let view = new Uint8Array(buffer); - assert_throws_dom('InvalidStateError', () => yPlane.readInto(view)); -}, 'Test we cannot read planar data from a closed VideoFrame.'); - -test(t => { - let image = makeImageBitmap(32, 16); image.close(); @@ -210,7 +149,7 @@ displayHeight: Math.pow(2, 32) }), 'invalid display height'); -}, 'Test invalid planar constructed VideoFrames'); +}, 'Test invalid buffer constructed VideoFrames'); test(t => { let fmt = 'I420'; @@ -221,15 +160,11 @@ 1, 2, // v ]); let frame = new VideoFrame(data, vfInit); - assert_equals(frame.planes.length, 3, 'plane count'); assert_equals(frame.format, fmt, 'plane format'); assert_equals(frame.colorSpace.primaries, 'bt709', 'color primaries'); assert_equals(frame.colorSpace.transfer, 'bt709', 'color transfer'); assert_equals(frame.colorSpace.matrix, 'bt709', 'color matrix'); assert_false(frame.colorSpace.fullRange, 'color range'); - verifyPlane({stride: 4, rows: 2, src: data.slice(0, 8)}, frame.planes[0]); - verifyPlane({stride: 2, rows: 1, src: data.slice(8, 10)}, frame.planes[1]); - verifyPlane({stride: 2, rows: 1, src: data.slice(10, 12)}, frame.planes[2]); frame.close(); let y = {offset: 0, stride: 4}; @@ -251,7 +186,7 @@ assert_throws_js(TypeError, () => { let frame = new VideoFrame(data.slice(0, 8), vfInit); }, 'data too small'); -}, 'Test planar constructed I420 VideoFrame'); +}, 'Test buffer constructed I420 VideoFrame'); test(t => { let fmt = 'I420'; @@ -287,16 +222,11 @@ 8, 7, 6, 5, 4, 3, 2, 1, // a ]); let frame = new VideoFrame(data, vfInit); - assert_equals(frame.planes.length, 4, 'plane count'); assert_equals(frame.format, fmt, 'plane format'); assert_equals(frame.colorSpace.primaries, 'bt709', 'color primaries'); assert_equals(frame.colorSpace.transfer, 'bt709', 'color transfer'); assert_equals(frame.colorSpace.matrix, 'bt709', 'color matrix'); assert_false(frame.colorSpace.fullRange, 'color range'); - verifyPlane({stride: 4, rows: 2, src: data.slice(0, 8)}, frame.planes[0]); - verifyPlane({stride: 2, rows: 1, src: data.slice(8, 10)}, frame.planes[1]); - verifyPlane({stride: 2, rows: 1, src: data.slice(10, 12)}, frame.planes[2]); - verifyPlane({stride: 4, rows: 2, src: data.slice(12, 20)}, frame.planes[3]); frame.close(); // Most constraints are tested as part of I420 above. @@ -313,7 +243,7 @@ assert_throws_js(TypeError, () => { let frame = new VideoFrame(data.slice(0, 12), vfInit); }, 'data too small'); -}, 'Test planar constructed I420+Alpha VideoFrame'); +}, 'Test buffer constructed I420+Alpha VideoFrame'); test(t => { let fmt = 'NV12'; @@ -323,14 +253,11 @@ 1, 2, 3, 4, // uv ]); let frame = new VideoFrame(data, vfInit); - assert_equals(frame.planes.length, 2, 'plane count'); assert_equals(frame.format, fmt, 'plane format'); assert_equals(frame.colorSpace.primaries, 'bt709', 'color primaries'); assert_equals(frame.colorSpace.transfer, 'bt709', 'color transfer'); assert_equals(frame.colorSpace.matrix, 'bt709', 'color matrix'); assert_false(frame.colorSpace.fullRange, 'color range'); - verifyPlane({stride: 4, rows: 2, src: data.slice(0, 8)}, frame.planes[0]); - verifyPlane({stride: 4, rows: 1, src: data.slice(8, 12)}, frame.planes[1]); frame.close(); let y = {offset: 0, stride: 4}; @@ -347,7 +274,7 @@ assert_throws_js(TypeError, () => { let frame = new VideoFrame(data.slice(0, 8), vfInit); }, 'data too small'); -}, 'Test planar constructed NV12 VideoFrame'); +}, 'Test buffer constructed NV12 VideoFrame'); test(t => { let vfInit = {timestamp: 1234, codedWidth: 4, codedHeight: 2}; @@ -356,47 +283,37 @@ 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, ]); let frame = new VideoFrame(data, {...vfInit, format: 'RGBA'}); - assert_equals(frame.planes.length, 1, 'plane count'); assert_equals(frame.format, 'RGBA', 'plane format'); assert_equals(frame.colorSpace.primaries, 'bt709', 'color primaries'); assert_equals(frame.colorSpace.transfer, 'iec61966-2-1', 'color transfer'); assert_equals(frame.colorSpace.matrix, 'rgb', 'color matrix'); assert_true(frame.colorSpace.fullRange, 'color range'); - verifyPlane({stride: 16, rows: 2, src: data}, frame.planes[0]); frame.close(); - // TODO(sandersd): verifyPlane() should not check alpha bytes. frame = new VideoFrame(data, {...vfInit, format: 'RGBX'}); - assert_equals(frame.planes.length, 1, 'plane count'); assert_equals(frame.format, 'RGBX', 'plane format'); assert_equals(frame.colorSpace.primaries, 'bt709', 'color primaries'); assert_equals(frame.colorSpace.transfer, 'iec61966-2-1', 'color transfer'); assert_equals(frame.colorSpace.matrix, 'rgb', 'color matrix'); assert_true(frame.colorSpace.fullRange, 'color range'); - verifyPlane({stride: 16, rows: 2, src: data}, frame.planes[0]); frame.close(); frame = new VideoFrame(data, {...vfInit, format: 'BGRA'}); - assert_equals(frame.planes.length, 1, 'plane count'); assert_equals(frame.format, 'BGRA', 'plane format'); assert_equals(frame.colorSpace.primaries, 'bt709', 'color primaries'); assert_equals(frame.colorSpace.transfer, 'iec61966-2-1', 'color transfer'); assert_equals(frame.colorSpace.matrix, 'rgb', 'color matrix'); assert_true(frame.colorSpace.fullRange, 'color range'); - verifyPlane({stride: 16, rows: 2, src: data}, frame.planes[0]); frame.close(); - // TODO(sandersd): verifyPlane() should not check alpha bytes. frame = new VideoFrame(data, {...vfInit, format: 'BGRX'}); - assert_equals(frame.planes.length, 1, 'plane count'); assert_equals(frame.format, 'BGRX', 'plane format'); assert_equals(frame.colorSpace.primaries, 'bt709', 'color primaries'); assert_equals(frame.colorSpace.transfer, 'iec61966-2-1', 'color transfer'); assert_equals(frame.colorSpace.matrix, 'rgb', 'color matrix'); assert_true(frame.colorSpace.fullRange, 'color range'); - verifyPlane({stride: 16, rows: 2, src: data}, frame.planes[0]); frame.close(); -}, 'Test planar constructed RGB VideoFrames'); +}, 'Test buffer constructed RGB VideoFrames'); test(t => { let image = makeImageBitmap(32, 16); @@ -444,16 +361,13 @@ 8, 7, 6, 5, 4, 3, 2, 1, // a ]); let frame = new VideoFrame(data, vfInit); - assert_equals(frame.planes.length, 4, 'plane count'); assert_equals(frame.format, fmt, 'plane format'); let alpha_frame_copy = new VideoFrame(frame, {alpha: 'keep'}); assert_equals(alpha_frame_copy.format, 'I420A', 'plane format'); - assert_equals(alpha_frame_copy.planes.length, 4, 'plane count'); let opaque_frame_copy = new VideoFrame(frame, {alpha: 'discard'}); assert_equals(opaque_frame_copy.format, 'I420', 'plane format'); - assert_equals(opaque_frame_copy.planes.length, 3, 'plane count'); frame.close(); alpha_frame_copy.close(); @@ -467,7 +381,6 @@ 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, ]); let frame = new VideoFrame(data, {...vfInit, format: 'RGBA'}); - assert_equals(frame.planes.length, 1, 'plane count'); assert_equals(frame.format, 'RGBA', 'plane format'); let alpha_frame_copy = new VideoFrame(frame, {alpha: 'keep'}); @@ -481,7 +394,6 @@ frame.close(); frame = new VideoFrame(data, {...vfInit, format: 'BGRA'}); - assert_equals(frame.planes.length, 1, 'plane count'); assert_equals(frame.format, 'BGRA', 'plane format'); alpha_frame_copy = new VideoFrame(frame, {alpha: 'keep'});
diff --git a/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-properties-after-frame-navigated-expected.txt b/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-properties-after-frame-navigated-expected.txt index 0e72ad5..eca34df7 100644 --- a/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-properties-after-frame-navigated-expected.txt +++ b/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-properties-after-frame-navigated-expected.txt
@@ -78,6 +78,8 @@ PASS window.cached_navigator_virtualKeyboard.boundingRect.y is 0 PASS window.cached_navigator_virtualKeyboard.ongeometrychange is null PASS window.cached_navigator_virtualKeyboard.overlaysContent is false +PASS window.cached_navigator_windowControlsOverlay.ongeometrychange is null +PASS window.cached_navigator_windowControlsOverlay.visible is false PASS window.cached_navigator_xr.ondevicechange is null PASS window.cached_performance.onresourcetimingbufferfull is null PASS window.cached_performance_navigation.redirectCount is 0
diff --git a/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-properties-after-frame-removed-and-gced-expected.txt b/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-properties-after-frame-removed-and-gced-expected.txt index a0d42a83..7cd7d4c 100644 --- a/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-properties-after-frame-removed-and-gced-expected.txt +++ b/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-properties-after-frame-removed-and-gced-expected.txt
@@ -78,6 +78,8 @@ PASS window.cached_navigator_virtualKeyboard.boundingRect.y is 0 PASS window.cached_navigator_virtualKeyboard.ongeometrychange is null PASS window.cached_navigator_virtualKeyboard.overlaysContent is false +PASS window.cached_navigator_windowControlsOverlay.ongeometrychange is null +PASS window.cached_navigator_windowControlsOverlay.visible is false PASS window.cached_navigator_xr.ondevicechange is null PASS window.cached_performance.onresourcetimingbufferfull is null PASS window.cached_performance_navigation.redirectCount is 0
diff --git a/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-properties-after-frame-removed-expected.txt b/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-properties-after-frame-removed-expected.txt index e753ccd..285a358 100644 --- a/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-properties-after-frame-removed-expected.txt +++ b/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-properties-after-frame-removed-expected.txt
@@ -78,6 +78,8 @@ PASS window.cached_navigator_virtualKeyboard.boundingRect.y is 0 PASS window.cached_navigator_virtualKeyboard.ongeometrychange is null PASS window.cached_navigator_virtualKeyboard.overlaysContent is false +PASS window.cached_navigator_windowControlsOverlay.ongeometrychange is null +PASS window.cached_navigator_windowControlsOverlay.visible is false PASS window.cached_navigator_xr.ondevicechange is null PASS window.cached_performance.onresourcetimingbufferfull is null PASS window.cached_performance_navigation.redirectCount is 0
diff --git a/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-window-after-frame-navigated-expected.txt b/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-window-after-frame-navigated-expected.txt index 019026b..2f09fc8 100644 --- a/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-window-after-frame-navigated-expected.txt +++ b/third_party/blink/web_tests/fast/dom/Window/property-access-on-cached-window-after-frame-navigated-expected.txt
@@ -88,6 +88,8 @@ PASS oldChildWindow.navigator.virtualKeyboard.ongeometrychange is newChildWindow.navigator.virtualKeyboard.ongeometrychange PASS oldChildWindow.navigator.virtualKeyboard.overlaysContent is newChildWindow.navigator.virtualKeyboard.overlaysContent PASS oldChildWindow.navigator.webdriver is newChildWindow.navigator.webdriver +PASS oldChildWindow.navigator.windowControlsOverlay.ongeometrychange is newChildWindow.navigator.windowControlsOverlay.ongeometrychange +PASS oldChildWindow.navigator.windowControlsOverlay.visible is newChildWindow.navigator.windowControlsOverlay.visible PASS oldChildWindow.navigator.xr.ondevicechange is newChildWindow.navigator.xr.ondevicechange PASS oldChildWindow.onabort is newChildWindow.onabort PASS oldChildWindow.onafterprint is newChildWindow.onafterprint
diff --git a/third_party/blink/web_tests/fast/forms/text/input-readonly-focus.html b/third_party/blink/web_tests/fast/forms/text/input-readonly-focus.html index 4f0966e..1e866c9 100644 --- a/third_party/blink/web_tests/fast/forms/text/input-readonly-focus.html +++ b/third_party/blink/web_tests/fast/forms/text/input-readonly-focus.html
@@ -2,6 +2,7 @@ <head> <script> function runTest() { + testRunner.waitUntilDone(); testRunner.dumpAsText(); var input = document.getElementById('i'); @@ -13,6 +14,8 @@ var input = document.getElementById('i'); input.onfocus = function(e) { document.body.innerHTML = 'PASS'; + if (window.testRunner) + window.testRunner.notifyDone(); } if (window.testRunner) runTest();
diff --git a/third_party/blink/web_tests/http/tests/origin_trials/resources/origintrials.js b/third_party/blink/web_tests/http/tests/origin_trials/resources/origintrials.js index 84d986b..d48ebb1d 100644 --- a/third_party/blink/web_tests/http/tests/origin_trials/resources/origintrials.js +++ b/third_party/blink/web_tests/http/tests/origin_trials/resources/origintrials.js
@@ -261,6 +261,13 @@ }); }, 'Attribute should exist on object and return value'); + test(() => { + assert_true('testOriginTrialGlobalAttribute' in self, + 'Attribute exists on global scope (window)'); + assert_true(self.testOriginTrialGlobalAttribute, + 'Atttribute on global scope (window) should return boolean value'); + }, 'Attribute should exist on global scope (window) and return value'); + fetch_tests_from_worker(new Worker('resources/enabled-worker.js')); };
diff --git a/third_party/blink/web_tests/http/tests/origin_trials/resources/window-open-helper.js b/third_party/blink/web_tests/http/tests/origin_trials/resources/window-open-helper.js new file mode 100644 index 0000000..247c75e5 --- /dev/null +++ b/third_party/blink/web_tests/http/tests/origin_trials/resources/window-open-helper.js
@@ -0,0 +1,75 @@ +// Helper functions to verify that origin trial checks work as expected in a +// document loaded via window.open(). + +const MESSAGE_DONE = 'done'; +const MESSAGE_RESULT = 'result'; + +window.isTheOpenerForOTTest = !window.opener; + +// Listens for messages from the target (opened window), to convert test results +// into asserts, and complete the test. +receiveMessageFromTarget = (event) => { + if (event.data === MESSAGE_DONE) { + done(); + return; + } + + if (MESSAGE_RESULT in event.data) { + test(function() { + assert_true(event.data.result, event.data.description); + }, 'Trial is enabled in document after window.open'); + } +} + +// Sends any message from the target to the opener. +sendToOpener = (message) => { + window.opener.postMessage(message, '*'); +} + +// Sends a test result from the target to the opener, capturing if the test +// passed, and a description. +sendTestResult = (passed, description) => { + sendToOpener({result: passed, description}); +} + +// Performs setup needed to allow a window to be opened, and collect test +// results from the target (opened window). +setupWindowOpenTest = () => { + // Only the opener needs to do any test setup. + if (!window.isTheOpenerForOTTest) { + return; + } + + // Test will signal done, once all results have been collected from the + // target window. + setup({explicit_done: true}); + + // Allow windows to be opened. + if (window.testRunner) { + testRunner.setPopupBlockingEnabled(false); + } + + // Listener to collect results from the target window. + window.addEventListener('message', receiveMessageFromTarget, false); +} + +// Runs the tests in the target (opened window). +runTestInTarget = (run_test_func, test_description) => { + if (window.isTheOpenerForOTTest) { + return; + } + + const passed = run_test_func(); + sendTestResult(passed, test_description); + + sendToOpener(MESSAGE_DONE); +} + +// Opens the current document in a new window. +openCurrentAsTarget = () => { + if (window.isTheOpenerForOTTest) { + const url = window.location.pathname; + const filename = url.substring(url.lastIndexOf('/') + 1); + window.open(filename); + } +}
diff --git a/third_party/blink/web_tests/http/tests/origin_trials/valid-token-window-open-header-enabled.php b/third_party/blink/web_tests/http/tests/origin_trials/valid-token-window-open-header-enabled.php new file mode 100644 index 0000000..8d0b77e --- /dev/null +++ b/third_party/blink/web_tests/http/tests/origin_trials/valid-token-window-open-header-enabled.php
@@ -0,0 +1,44 @@ +<?php +// TODO(iclelland): Generate this sample token during the build. The token +// below will expire in 2033, but it would be better to always have a token which +// is guaranteed to be valid when the tests are run. +// Generate this token with the command: +// generate_token.py http://127.0.0.1:8000 Frobulate -expire-timestamp=2000000000 +header("Origin-Trial: AlCoOPbezqtrGMzSzbLQC4c+oPqO6yuioemcBPjgcXajF8jtmZr4B8tJRPAARPbsX6hDeVyXCKHzEJfpBXvZgQEAAABReyJvcmlnaW4iOiAiaHR0cDovLzEyNy4wLjAuMTo4MDAwIiwgImZlYXR1cmUiOiAiRnJvYnVsYXRlIiwgImV4cGlyeSI6IDIwMDAwMDAwMDB9"); +?> +<!DOCTYPE html> +<meta charset="utf-8"> +<title>Test that trial is enabled by header when navigated by window.open</title> +<script src="../resources/testharness.js"></script> +<script src="../resources/testharnessreport.js"></script> +<script src="resources/window-open-helper.js"></script> +<script> +setupWindowOpenTest(); + +function runTest() { + runTestInTarget(() => { + return ('testOriginTrialGlobalAttribute' in self && + window.testOriginTrialGlobalAttribute); + }, + 'testOriginTrialGlobalAttribute should be defined on window and return true'); + + runTestInTarget(() => { + const testObject = internals.originTrialsTest(); + return ('normalAttribute' in testObject && testObject.normalAttribute); + }, + 'normalAttribute should be defined and return true'); +} +</script> + +<html> + +<body onload="runTest()"> + <p> + This test opens a new window. It passes, if the trial is enabled in the + opened window. + </p> + <script> + openCurrentAsTarget(); + </script> +</body> +</html>
diff --git a/third_party/blink/web_tests/http/tests/origin_trials/valid-token-window-open-meta-enabled.html b/third_party/blink/web_tests/http/tests/origin_trials/valid-token-window-open-meta-enabled.html new file mode 100644 index 0000000..97f949a --- /dev/null +++ b/third_party/blink/web_tests/http/tests/origin_trials/valid-token-window-open-meta-enabled.html
@@ -0,0 +1,43 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<!-- +// TODO(iclelland): Generate this sample token during the build. The token +// below will expire in 2033, but it would be better to always have a token which +// is guaranteed to be valid when the tests are run. +// Generate this token with the command: +// generate_token.py http://127.0.0.1:8000 StorageFoundationAPI --expire-timestamp=2000000000 +--> +<meta http-equiv="origin-trial" + content="AlCoOPbezqtrGMzSzbLQC4c+oPqO6yuioemcBPjgcXajF8jtmZr4B8tJRPAARPbsX6hDeVyXCKHzEJfpBXvZgQEAAABReyJvcmlnaW4iOiAiaHR0cDovLzEyNy4wLjAuMTo4MDAwIiwgImZlYXR1cmUiOiAiRnJvYnVsYXRlIiwgImV4cGlyeSI6IDIwMDAwMDAwMDB9" /> +<title>Test that trial is enabled by meta tag when navigated by window.open</title> +<script src="../resources/testharness.js"></script> +<script src="../resources/testharnessreport.js"></script> +<script src="resources/window-open-helper.js"></script> +<script> +setupWindowOpenTest(); + +function runTest() { + runTestInTarget(() => { + return ('testOriginTrialGlobalAttribute' in self && + window.testOriginTrialGlobalAttribute); + }, + 'testOriginTrialGlobalAttribute should be defined on window and return true'); + + runTestInTarget(() => { + const testObject = internals.originTrialsTest(); + return ('normalAttribute' in testObject && testObject.normalAttribute); + }, + 'normalAttribute should be defined and return true'); +} +</script> +<html> +<body onload="runTest()"> + <p> + This test opens a new window. It passes, if the trial is enabled in the + opened window. + </p> + <script> + openCurrentAsTarget(); + </script> +</body> +</html>
diff --git a/third_party/blink/web_tests/http/tests/origin_trials/webexposed/storage-foundation-window-open-header.php b/third_party/blink/web_tests/http/tests/origin_trials/webexposed/storage-foundation-window-open-header.php new file mode 100644 index 0000000..c7586d2f --- /dev/null +++ b/third_party/blink/web_tests/http/tests/origin_trials/webexposed/storage-foundation-window-open-header.php
@@ -0,0 +1,32 @@ +<?php +// Generate this token with the command: +// generate_token.py http://127.0.0.1:8000 StorageFoundationAPI --expire-timestamp=2000000000 +header("Origin-Trial: A3C2zYg350joPm2nXnW161G1NPsfxe5lianKdg5qM1a/qjuxGRoQDaZk0mGxl9ErHv/iXEfZ0f3lskbjeqFuFggAAABceyJvcmlnaW4iOiAiaHR0cDovLzEyNy4wLjAuMTo4MDAwIiwgImZlYXR1cmUiOiAiU3RvcmFnZUZvdW5kYXRpb25BUEkiLCAiZXhwaXJ5IjogMjAwMDAwMDAwMH0="); +?> +<!DOCTYPE html> +<meta charset="utf-8"> +<title>Test that StorageFoundationAPI trial is enabled by header when navigated by window.open</title> +<script src="../../resources/testharness.js"></script> +<script src="../../resources/testharnessreport.js"></script> +<script src="../resources/window-open-helper.js"></script> +<script> +setupWindowOpenTest(); + +function runTest() { + runTestInTarget(() => { + return (typeof storageFoundation == 'object'); + }, + 'storageFoundation should be defined in document'); +} +</script> +<html> +<body onload="runTest()"> + <p> + This test opens a new window. It passes, if the trial is enabled in the + opened window. + </p> + <script> + openCurrentAsTarget(); + </script> +</body> +</html>
diff --git a/third_party/blink/web_tests/http/tests/origin_trials/webexposed/storage-foundation-window-open-meta.html b/third_party/blink/web_tests/http/tests/origin_trials/webexposed/storage-foundation-window-open-meta.html new file mode 100644 index 0000000..4532d05 --- /dev/null +++ b/third_party/blink/web_tests/http/tests/origin_trials/webexposed/storage-foundation-window-open-meta.html
@@ -0,0 +1,33 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<!-- +// Generate this token with the command: +// generate_token.py http://127.0.0.1:8000 StorageFoundationAPI --expire-timestamp=2000000000 +--> +<meta http-equiv="origin-trial" + content="A3C2zYg350joPm2nXnW161G1NPsfxe5lianKdg5qM1a/qjuxGRoQDaZk0mGxl9ErHv/iXEfZ0f3lskbjeqFuFggAAABceyJvcmlnaW4iOiAiaHR0cDovLzEyNy4wLjAuMTo4MDAwIiwgImZlYXR1cmUiOiAiU3RvcmFnZUZvdW5kYXRpb25BUEkiLCAiZXhwaXJ5IjogMjAwMDAwMDAwMH0=" /> +<title>Test that StorageFoundationAPI trial is enabled by meta tag when navigated by window.open</title> +<script src="../../resources/testharness.js"></script> +<script src="../../resources/testharnessreport.js"></script> +<script src="../resources/window-open-helper.js"></script> +<script> + setupWindowOpenTest(); + + function runTest() { + runTestInTarget(() => { + return (typeof storageFoundation == 'object'); + }, + 'storageFoundation should be defined in document'); + } +</script> +<html> +<body onload="runTest()"> + <p> + This test opens a new window. It passes, if the trial is enabled in the + opened window. + </p> + <script> + openCurrentAsTarget(); + </script> +</body> +</html>
diff --git a/third_party/blink/web_tests/http/tests/resources/origin-trials-helper.js b/third_party/blink/web_tests/http/tests/resources/origin-trials-helper.js index 1d4aa411..fc24700 100644 --- a/third_party/blink/web_tests/http/tests/resources/origin-trials-helper.js +++ b/third_party/blink/web_tests/http/tests/resources/origin-trials-helper.js
@@ -1,5 +1,5 @@ // This file provides an OriginTrialsHelper object which can be used by -// LayoutTests that are checking members exposed to script by origin trials. +// WebTests that are checking members exposed to script by origin trials. // // The current available methods are: // check_properties_exist:
diff --git a/third_party/blink/web_tests/platform/mac-mac-arm11.0/external/wpt/css/css-fonts/animations/font-size-adjust-interpolation-expected.txt b/third_party/blink/web_tests/platform/mac-mac-arm11.0/external/wpt/css/css-fonts/animations/font-size-adjust-interpolation-expected.txt new file mode 100644 index 0000000..3dd91183 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac-arm11.0/external/wpt/css/css-fonts/animations/font-size-adjust-interpolation-expected.txt
@@ -0,0 +1,340 @@ +This is a testharness.js-based test. +Found 336 tests; 196 PASS, 140 FAIL, 0 TIMEOUT, 0 NOTRUN. +PASS CSS Transitions: property <font-size-adjust> from neutral to [2] at (-2) should be [0] +PASS CSS Transitions: property <font-size-adjust> from neutral to [2] at (-0.3) should be [0.7] +PASS CSS Transitions: property <font-size-adjust> from neutral to [2] at (0) should be [1] +PASS CSS Transitions: property <font-size-adjust> from neutral to [2] at (0.3) should be [1.3] +PASS CSS Transitions: property <font-size-adjust> from neutral to [2] at (0.6) should be [1.6] +PASS CSS Transitions: property <font-size-adjust> from neutral to [2] at (1) should be [2] +PASS CSS Transitions: property <font-size-adjust> from neutral to [2] at (1.5) should be [2.5] +PASS CSS Transitions with transition: all: property <font-size-adjust> from neutral to [2] at (-2) should be [0] +PASS CSS Transitions with transition: all: property <font-size-adjust> from neutral to [2] at (-0.3) should be [0.7] +PASS CSS Transitions with transition: all: property <font-size-adjust> from neutral to [2] at (0) should be [1] +PASS CSS Transitions with transition: all: property <font-size-adjust> from neutral to [2] at (0.3) should be [1.3] +PASS CSS Transitions with transition: all: property <font-size-adjust> from neutral to [2] at (0.6) should be [1.6] +PASS CSS Transitions with transition: all: property <font-size-adjust> from neutral to [2] at (1) should be [2] +PASS CSS Transitions with transition: all: property <font-size-adjust> from neutral to [2] at (1.5) should be [2.5] +PASS CSS Animations: property <font-size-adjust> from neutral to [2] at (-2) should be [0] +PASS CSS Animations: property <font-size-adjust> from neutral to [2] at (-0.3) should be [0.7] +PASS CSS Animations: property <font-size-adjust> from neutral to [2] at (0) should be [1] +PASS CSS Animations: property <font-size-adjust> from neutral to [2] at (0.3) should be [1.3] +PASS CSS Animations: property <font-size-adjust> from neutral to [2] at (0.6) should be [1.6] +PASS CSS Animations: property <font-size-adjust> from neutral to [2] at (1) should be [2] +PASS CSS Animations: property <font-size-adjust> from neutral to [2] at (1.5) should be [2.5] +PASS Web Animations: property <font-size-adjust> from neutral to [2] at (-2) should be [0] +PASS Web Animations: property <font-size-adjust> from neutral to [2] at (-0.3) should be [0.7] +PASS Web Animations: property <font-size-adjust> from neutral to [2] at (0) should be [1] +PASS Web Animations: property <font-size-adjust> from neutral to [2] at (0.3) should be [1.3] +PASS Web Animations: property <font-size-adjust> from neutral to [2] at (0.6) should be [1.6] +PASS Web Animations: property <font-size-adjust> from neutral to [2] at (1) should be [2] +PASS Web Animations: property <font-size-adjust> from neutral to [2] at (1.5) should be [2.5] +PASS CSS Transitions: property <font-size-adjust> from [initial] to [2] at (-0.3) should be [2] +PASS CSS Transitions: property <font-size-adjust> from [initial] to [2] at (0) should be [2] +PASS CSS Transitions: property <font-size-adjust> from [initial] to [2] at (0.3) should be [2] +PASS CSS Transitions: property <font-size-adjust> from [initial] to [2] at (0.5) should be [2] +PASS CSS Transitions: property <font-size-adjust> from [initial] to [2] at (0.6) should be [2] +PASS CSS Transitions: property <font-size-adjust> from [initial] to [2] at (1) should be [2] +PASS CSS Transitions: property <font-size-adjust> from [initial] to [2] at (1.5) should be [2] +PASS CSS Transitions with transition: all: property <font-size-adjust> from [initial] to [2] at (-0.3) should be [2] +PASS CSS Transitions with transition: all: property <font-size-adjust> from [initial] to [2] at (0) should be [2] +PASS CSS Transitions with transition: all: property <font-size-adjust> from [initial] to [2] at (0.3) should be [2] +PASS CSS Transitions with transition: all: property <font-size-adjust> from [initial] to [2] at (0.5) should be [2] +PASS CSS Transitions with transition: all: property <font-size-adjust> from [initial] to [2] at (0.6) should be [2] +PASS CSS Transitions with transition: all: property <font-size-adjust> from [initial] to [2] at (1) should be [2] +PASS CSS Transitions with transition: all: property <font-size-adjust> from [initial] to [2] at (1.5) should be [2] +PASS CSS Animations: property <font-size-adjust> from [initial] to [2] at (-0.3) should be [initial] +PASS CSS Animations: property <font-size-adjust> from [initial] to [2] at (0) should be [initial] +PASS CSS Animations: property <font-size-adjust> from [initial] to [2] at (0.3) should be [initial] +PASS CSS Animations: property <font-size-adjust> from [initial] to [2] at (0.5) should be [2] +PASS CSS Animations: property <font-size-adjust> from [initial] to [2] at (0.6) should be [2] +PASS CSS Animations: property <font-size-adjust> from [initial] to [2] at (1) should be [2] +PASS CSS Animations: property <font-size-adjust> from [initial] to [2] at (1.5) should be [2] +PASS Web Animations: property <font-size-adjust> from [initial] to [2] at (-0.3) should be [initial] +PASS Web Animations: property <font-size-adjust> from [initial] to [2] at (0) should be [initial] +PASS Web Animations: property <font-size-adjust> from [initial] to [2] at (0.3) should be [initial] +PASS Web Animations: property <font-size-adjust> from [initial] to [2] at (0.5) should be [2] +PASS Web Animations: property <font-size-adjust> from [initial] to [2] at (0.6) should be [2] +PASS Web Animations: property <font-size-adjust> from [initial] to [2] at (1) should be [2] +PASS Web Animations: property <font-size-adjust> from [initial] to [2] at (1.5) should be [2] +FAIL CSS Transitions: property <font-size-adjust> from [initial] to [cap 2] at (-0.3) should be [cap 2] assert_true: 'to' value should be supported expected true got false +FAIL CSS Transitions: property <font-size-adjust> from [initial] to [cap 2] at (0) should be [cap 2] assert_true: 'to' value should be supported expected true got false +FAIL CSS Transitions: property <font-size-adjust> from [initial] to [cap 2] at (0.3) should be [cap 2] assert_true: 'to' value should be supported expected true got false +FAIL CSS Transitions: property <font-size-adjust> from [initial] to [cap 2] at (0.5) should be [cap 2] assert_true: 'to' value should be supported expected true got false +FAIL CSS Transitions: property <font-size-adjust> from [initial] to [cap 2] at (0.6) should be [cap 2] assert_true: 'to' value should be supported expected true got false +FAIL CSS Transitions: property <font-size-adjust> from [initial] to [cap 2] at (1) should be [cap 2] assert_true: 'to' value should be supported expected true got false +FAIL CSS Transitions: property <font-size-adjust> from [initial] to [cap 2] at (1.5) should be [cap 2] assert_true: 'to' value should be supported expected true got false +FAIL CSS Transitions with transition: all: property <font-size-adjust> from [initial] to [cap 2] at (-0.3) should be [cap 2] assert_true: 'to' value should be supported expected true got false +FAIL CSS Transitions with transition: all: property <font-size-adjust> from [initial] to [cap 2] at (0) should be [cap 2] assert_true: 'to' value should be supported expected true got false +FAIL CSS Transitions with transition: all: property <font-size-adjust> from [initial] to [cap 2] at (0.3) should be [cap 2] assert_true: 'to' value should be supported expected true got false +FAIL CSS Transitions with transition: all: property <font-size-adjust> from [initial] to [cap 2] at (0.5) should be [cap 2] assert_true: 'to' value should be supported expected true got false +FAIL CSS Transitions with transition: all: property <font-size-adjust> from [initial] to [cap 2] at (0.6) should be [cap 2] assert_true: 'to' value should be supported expected true got false +FAIL CSS Transitions with transition: all: property <font-size-adjust> from [initial] to [cap 2] at (1) should be [cap 2] assert_true: 'to' value should be supported expected true got false +FAIL CSS Transitions with transition: all: property <font-size-adjust> from [initial] to [cap 2] at (1.5) should be [cap 2] assert_true: 'to' value should be supported expected true got false +FAIL CSS Animations: property <font-size-adjust> from [initial] to [cap 2] at (-0.3) should be [initial] assert_true: 'to' value should be supported expected true got false +FAIL CSS Animations: property <font-size-adjust> from [initial] to [cap 2] at (0) should be [initial] assert_true: 'to' value should be supported expected true got false +FAIL CSS Animations: property <font-size-adjust> from [initial] to [cap 2] at (0.3) should be [initial] assert_true: 'to' value should be supported expected true got false +FAIL CSS Animations: property <font-size-adjust> from [initial] to [cap 2] at (0.5) should be [cap 2] assert_true: 'to' value should be supported expected true got false +FAIL CSS Animations: property <font-size-adjust> from [initial] to [cap 2] at (0.6) should be [cap 2] assert_true: 'to' value should be supported expected true got false +FAIL CSS Animations: property <font-size-adjust> from [initial] to [cap 2] at (1) should be [cap 2] assert_true: 'to' value should be supported expected true got false +FAIL CSS Animations: property <font-size-adjust> from [initial] to [cap 2] at (1.5) should be [cap 2] assert_true: 'to' value should be supported expected true got false +FAIL Web Animations: property <font-size-adjust> from [initial] to [cap 2] at (-0.3) should be [initial] assert_true: 'to' value should be supported expected true got false +FAIL Web Animations: property <font-size-adjust> from [initial] to [cap 2] at (0) should be [initial] assert_true: 'to' value should be supported expected true got false +FAIL Web Animations: property <font-size-adjust> from [initial] to [cap 2] at (0.3) should be [initial] assert_true: 'to' value should be supported expected true got false +FAIL Web Animations: property <font-size-adjust> from [initial] to [cap 2] at (0.5) should be [cap 2] assert_true: 'to' value should be supported expected true got false +FAIL Web Animations: property <font-size-adjust> from [initial] to [cap 2] at (0.6) should be [cap 2] assert_true: 'to' value should be supported expected true got false +FAIL Web Animations: property <font-size-adjust> from [initial] to [cap 2] at (1) should be [cap 2] assert_true: 'to' value should be supported expected true got false +FAIL Web Animations: property <font-size-adjust> from [initial] to [cap 2] at (1.5) should be [cap 2] assert_true: 'to' value should be supported expected true got false +PASS CSS Transitions: property <font-size-adjust> from [inherit] to [2] at (-2) should be [5] +PASS CSS Transitions: property <font-size-adjust> from [inherit] to [2] at (-0.3) should be [3.3] +PASS CSS Transitions: property <font-size-adjust> from [inherit] to [2] at (0) should be [3] +PASS CSS Transitions: property <font-size-adjust> from [inherit] to [2] at (0.3) should be [2.7] +PASS CSS Transitions: property <font-size-adjust> from [inherit] to [2] at (0.6) should be [2.4] +PASS CSS Transitions: property <font-size-adjust> from [inherit] to [2] at (1) should be [2] +PASS CSS Transitions: property <font-size-adjust> from [inherit] to [2] at (1.5) should be [1.5] +PASS CSS Transitions with transition: all: property <font-size-adjust> from [inherit] to [2] at (-2) should be [5] +PASS CSS Transitions with transition: all: property <font-size-adjust> from [inherit] to [2] at (-0.3) should be [3.3] +PASS CSS Transitions with transition: all: property <font-size-adjust> from [inherit] to [2] at (0) should be [3] +PASS CSS Transitions with transition: all: property <font-size-adjust> from [inherit] to [2] at (0.3) should be [2.7] +PASS CSS Transitions with transition: all: property <font-size-adjust> from [inherit] to [2] at (0.6) should be [2.4] +PASS CSS Transitions with transition: all: property <font-size-adjust> from [inherit] to [2] at (1) should be [2] +PASS CSS Transitions with transition: all: property <font-size-adjust> from [inherit] to [2] at (1.5) should be [1.5] +PASS CSS Animations: property <font-size-adjust> from [inherit] to [2] at (-2) should be [5] +PASS CSS Animations: property <font-size-adjust> from [inherit] to [2] at (-0.3) should be [3.3] +PASS CSS Animations: property <font-size-adjust> from [inherit] to [2] at (0) should be [3] +PASS CSS Animations: property <font-size-adjust> from [inherit] to [2] at (0.3) should be [2.7] +PASS CSS Animations: property <font-size-adjust> from [inherit] to [2] at (0.6) should be [2.4] +PASS CSS Animations: property <font-size-adjust> from [inherit] to [2] at (1) should be [2] +PASS CSS Animations: property <font-size-adjust> from [inherit] to [2] at (1.5) should be [1.5] +PASS Web Animations: property <font-size-adjust> from [inherit] to [2] at (-2) should be [5] +PASS Web Animations: property <font-size-adjust> from [inherit] to [2] at (-0.3) should be [3.3] +PASS Web Animations: property <font-size-adjust> from [inherit] to [2] at (0) should be [3] +PASS Web Animations: property <font-size-adjust> from [inherit] to [2] at (0.3) should be [2.7] +PASS Web Animations: property <font-size-adjust> from [inherit] to [2] at (0.6) should be [2.4] +PASS Web Animations: property <font-size-adjust> from [inherit] to [2] at (1) should be [2] +PASS Web Animations: property <font-size-adjust> from [inherit] to [2] at (1.5) should be [1.5] +PASS CSS Transitions: property <font-size-adjust> from [unset] to [2] at (-2) should be [5] +PASS CSS Transitions: property <font-size-adjust> from [unset] to [2] at (-0.3) should be [3.3] +PASS CSS Transitions: property <font-size-adjust> from [unset] to [2] at (0) should be [3] +PASS CSS Transitions: property <font-size-adjust> from [unset] to [2] at (0.3) should be [2.7] +PASS CSS Transitions: property <font-size-adjust> from [unset] to [2] at (0.6) should be [2.4] +PASS CSS Transitions: property <font-size-adjust> from [unset] to [2] at (1) should be [2] +PASS CSS Transitions: property <font-size-adjust> from [unset] to [2] at (1.5) should be [1.5] +PASS CSS Transitions with transition: all: property <font-size-adjust> from [unset] to [2] at (-2) should be [5] +PASS CSS Transitions with transition: all: property <font-size-adjust> from [unset] to [2] at (-0.3) should be [3.3] +PASS CSS Transitions with transition: all: property <font-size-adjust> from [unset] to [2] at (0) should be [3] +PASS CSS Transitions with transition: all: property <font-size-adjust> from [unset] to [2] at (0.3) should be [2.7] +PASS CSS Transitions with transition: all: property <font-size-adjust> from [unset] to [2] at (0.6) should be [2.4] +PASS CSS Transitions with transition: all: property <font-size-adjust> from [unset] to [2] at (1) should be [2] +PASS CSS Transitions with transition: all: property <font-size-adjust> from [unset] to [2] at (1.5) should be [1.5] +PASS CSS Animations: property <font-size-adjust> from [unset] to [2] at (-2) should be [5] +PASS CSS Animations: property <font-size-adjust> from [unset] to [2] at (-0.3) should be [3.3] +PASS CSS Animations: property <font-size-adjust> from [unset] to [2] at (0) should be [3] +PASS CSS Animations: property <font-size-adjust> from [unset] to [2] at (0.3) should be [2.7] +PASS CSS Animations: property <font-size-adjust> from [unset] to [2] at (0.6) should be [2.4] +PASS CSS Animations: property <font-size-adjust> from [unset] to [2] at (1) should be [2] +PASS CSS Animations: property <font-size-adjust> from [unset] to [2] at (1.5) should be [1.5] +PASS Web Animations: property <font-size-adjust> from [unset] to [2] at (-2) should be [5] +PASS Web Animations: property <font-size-adjust> from [unset] to [2] at (-0.3) should be [3.3] +PASS Web Animations: property <font-size-adjust> from [unset] to [2] at (0) should be [3] +PASS Web Animations: property <font-size-adjust> from [unset] to [2] at (0.3) should be [2.7] +PASS Web Animations: property <font-size-adjust> from [unset] to [2] at (0.6) should be [2.4] +PASS Web Animations: property <font-size-adjust> from [unset] to [2] at (1) should be [2] +PASS Web Animations: property <font-size-adjust> from [unset] to [2] at (1.5) should be [1.5] +PASS CSS Transitions: property <font-size-adjust> from [0] to [1.2] at (-2) should be [0] +PASS CSS Transitions: property <font-size-adjust> from [0] to [1.2] at (-0.3) should be [0] +PASS CSS Transitions: property <font-size-adjust> from [0] to [1.2] at (0) should be [0] +PASS CSS Transitions: property <font-size-adjust> from [0] to [1.2] at (0.3) should be [0.36] +PASS CSS Transitions: property <font-size-adjust> from [0] to [1.2] at (0.6) should be [0.72] +PASS CSS Transitions: property <font-size-adjust> from [0] to [1.2] at (1) should be [1.2] +PASS CSS Transitions: property <font-size-adjust> from [0] to [1.2] at (1.5) should be [1.8] +PASS CSS Transitions with transition: all: property <font-size-adjust> from [0] to [1.2] at (-2) should be [0] +PASS CSS Transitions with transition: all: property <font-size-adjust> from [0] to [1.2] at (-0.3) should be [0] +PASS CSS Transitions with transition: all: property <font-size-adjust> from [0] to [1.2] at (0) should be [0] +PASS CSS Transitions with transition: all: property <font-size-adjust> from [0] to [1.2] at (0.3) should be [0.36] +PASS CSS Transitions with transition: all: property <font-size-adjust> from [0] to [1.2] at (0.6) should be [0.72] +PASS CSS Transitions with transition: all: property <font-size-adjust> from [0] to [1.2] at (1) should be [1.2] +PASS CSS Transitions with transition: all: property <font-size-adjust> from [0] to [1.2] at (1.5) should be [1.8] +PASS CSS Animations: property <font-size-adjust> from [0] to [1.2] at (-2) should be [0] +PASS CSS Animations: property <font-size-adjust> from [0] to [1.2] at (-0.3) should be [0] +PASS CSS Animations: property <font-size-adjust> from [0] to [1.2] at (0) should be [0] +PASS CSS Animations: property <font-size-adjust> from [0] to [1.2] at (0.3) should be [0.36] +PASS CSS Animations: property <font-size-adjust> from [0] to [1.2] at (0.6) should be [0.72] +PASS CSS Animations: property <font-size-adjust> from [0] to [1.2] at (1) should be [1.2] +PASS CSS Animations: property <font-size-adjust> from [0] to [1.2] at (1.5) should be [1.8] +PASS Web Animations: property <font-size-adjust> from [0] to [1.2] at (-2) should be [0] +PASS Web Animations: property <font-size-adjust> from [0] to [1.2] at (-0.3) should be [0] +PASS Web Animations: property <font-size-adjust> from [0] to [1.2] at (0) should be [0] +PASS Web Animations: property <font-size-adjust> from [0] to [1.2] at (0.3) should be [0.36] +PASS Web Animations: property <font-size-adjust> from [0] to [1.2] at (0.6) should be [0.72] +PASS Web Animations: property <font-size-adjust> from [0] to [1.2] at (1) should be [1.2] +PASS Web Animations: property <font-size-adjust> from [0] to [1.2] at (1.5) should be [1.8] +FAIL CSS Transitions: property <font-size-adjust> from [cap 0] to [cap 1.2] at (-2) should be [cap 0] assert_true: 'from' value should be supported expected true got false +FAIL CSS Transitions: property <font-size-adjust> from [cap 0] to [cap 1.2] at (-0.3) should be [cap 0] assert_true: 'from' value should be supported expected true got false +FAIL CSS Transitions: property <font-size-adjust> from [cap 0] to [cap 1.2] at (0) should be [cap 0] assert_true: 'from' value should be supported expected true got false +FAIL CSS Transitions: property <font-size-adjust> from [cap 0] to [cap 1.2] at (0.3) should be [cap 0.36] assert_true: 'from' value should be supported expected true got false +FAIL CSS Transitions: property <font-size-adjust> from [cap 0] to [cap 1.2] at (0.6) should be [cap 0.72] assert_true: 'from' value should be supported expected true got false +FAIL CSS Transitions: property <font-size-adjust> from [cap 0] to [cap 1.2] at (1) should be [cap 1.2] assert_true: 'from' value should be supported expected true got false +FAIL CSS Transitions: property <font-size-adjust> from [cap 0] to [cap 1.2] at (1.5) should be [cap 1.8] assert_true: 'from' value should be supported expected true got false +FAIL CSS Transitions with transition: all: property <font-size-adjust> from [cap 0] to [cap 1.2] at (-2) should be [cap 0] assert_true: 'from' value should be supported expected true got false +FAIL CSS Transitions with transition: all: property <font-size-adjust> from [cap 0] to [cap 1.2] at (-0.3) should be [cap 0] assert_true: 'from' value should be supported expected true got false +FAIL CSS Transitions with transition: all: property <font-size-adjust> from [cap 0] to [cap 1.2] at (0) should be [cap 0] assert_true: 'from' value should be supported expected true got false +FAIL CSS Transitions with transition: all: property <font-size-adjust> from [cap 0] to [cap 1.2] at (0.3) should be [cap 0.36] assert_true: 'from' value should be supported expected true got false +FAIL CSS Transitions with transition: all: property <font-size-adjust> from [cap 0] to [cap 1.2] at (0.6) should be [cap 0.72] assert_true: 'from' value should be supported expected true got false +FAIL CSS Transitions with transition: all: property <font-size-adjust> from [cap 0] to [cap 1.2] at (1) should be [cap 1.2] assert_true: 'from' value should be supported expected true got false +FAIL CSS Transitions with transition: all: property <font-size-adjust> from [cap 0] to [cap 1.2] at (1.5) should be [cap 1.8] assert_true: 'from' value should be supported expected true got false +FAIL CSS Animations: property <font-size-adjust> from [cap 0] to [cap 1.2] at (-2) should be [cap 0] assert_true: 'from' value should be supported expected true got false +FAIL CSS Animations: property <font-size-adjust> from [cap 0] to [cap 1.2] at (-0.3) should be [cap 0] assert_true: 'from' value should be supported expected true got false +FAIL CSS Animations: property <font-size-adjust> from [cap 0] to [cap 1.2] at (0) should be [cap 0] assert_true: 'from' value should be supported expected true got false +FAIL CSS Animations: property <font-size-adjust> from [cap 0] to [cap 1.2] at (0.3) should be [cap 0.36] assert_true: 'from' value should be supported expected true got false +FAIL CSS Animations: property <font-size-adjust> from [cap 0] to [cap 1.2] at (0.6) should be [cap 0.72] assert_true: 'from' value should be supported expected true got false +FAIL CSS Animations: property <font-size-adjust> from [cap 0] to [cap 1.2] at (1) should be [cap 1.2] assert_true: 'from' value should be supported expected true got false +FAIL CSS Animations: property <font-size-adjust> from [cap 0] to [cap 1.2] at (1.5) should be [cap 1.8] assert_true: 'from' value should be supported expected true got false +FAIL Web Animations: property <font-size-adjust> from [cap 0] to [cap 1.2] at (-2) should be [cap 0] assert_true: 'from' value should be supported expected true got false +FAIL Web Animations: property <font-size-adjust> from [cap 0] to [cap 1.2] at (-0.3) should be [cap 0] assert_true: 'from' value should be supported expected true got false +FAIL Web Animations: property <font-size-adjust> from [cap 0] to [cap 1.2] at (0) should be [cap 0] assert_true: 'from' value should be supported expected true got false +FAIL Web Animations: property <font-size-adjust> from [cap 0] to [cap 1.2] at (0.3) should be [cap 0.36] assert_true: 'from' value should be supported expected true got false +FAIL Web Animations: property <font-size-adjust> from [cap 0] to [cap 1.2] at (0.6) should be [cap 0.72] assert_true: 'from' value should be supported expected true got false +FAIL Web Animations: property <font-size-adjust> from [cap 0] to [cap 1.2] at (1) should be [cap 1.2] assert_true: 'from' value should be supported expected true got false +FAIL Web Animations: property <font-size-adjust> from [cap 0] to [cap 1.2] at (1.5) should be [cap 1.8] assert_true: 'from' value should be supported expected true got false +PASS CSS Transitions: property <font-size-adjust> from [none] to [1.2] at (-0.3) should be [1.2] +PASS CSS Transitions: property <font-size-adjust> from [none] to [1.2] at (0) should be [1.2] +PASS CSS Transitions: property <font-size-adjust> from [none] to [1.2] at (0.3) should be [1.2] +PASS CSS Transitions: property <font-size-adjust> from [none] to [1.2] at (0.5) should be [1.2] +PASS CSS Transitions: property <font-size-adjust> from [none] to [1.2] at (0.6) should be [1.2] +PASS CSS Transitions: property <font-size-adjust> from [none] to [1.2] at (1) should be [1.2] +PASS CSS Transitions: property <font-size-adjust> from [none] to [1.2] at (1.5) should be [1.2] +PASS CSS Transitions with transition: all: property <font-size-adjust> from [none] to [1.2] at (-0.3) should be [1.2] +PASS CSS Transitions with transition: all: property <font-size-adjust> from [none] to [1.2] at (0) should be [1.2] +PASS CSS Transitions with transition: all: property <font-size-adjust> from [none] to [1.2] at (0.3) should be [1.2] +PASS CSS Transitions with transition: all: property <font-size-adjust> from [none] to [1.2] at (0.5) should be [1.2] +PASS CSS Transitions with transition: all: property <font-size-adjust> from [none] to [1.2] at (0.6) should be [1.2] +PASS CSS Transitions with transition: all: property <font-size-adjust> from [none] to [1.2] at (1) should be [1.2] +PASS CSS Transitions with transition: all: property <font-size-adjust> from [none] to [1.2] at (1.5) should be [1.2] +PASS CSS Animations: property <font-size-adjust> from [none] to [1.2] at (-0.3) should be [none] +PASS CSS Animations: property <font-size-adjust> from [none] to [1.2] at (0) should be [none] +PASS CSS Animations: property <font-size-adjust> from [none] to [1.2] at (0.3) should be [none] +PASS CSS Animations: property <font-size-adjust> from [none] to [1.2] at (0.5) should be [1.2] +PASS CSS Animations: property <font-size-adjust> from [none] to [1.2] at (0.6) should be [1.2] +PASS CSS Animations: property <font-size-adjust> from [none] to [1.2] at (1) should be [1.2] +PASS CSS Animations: property <font-size-adjust> from [none] to [1.2] at (1.5) should be [1.2] +PASS Web Animations: property <font-size-adjust> from [none] to [1.2] at (-0.3) should be [none] +PASS Web Animations: property <font-size-adjust> from [none] to [1.2] at (0) should be [none] +PASS Web Animations: property <font-size-adjust> from [none] to [1.2] at (0.3) should be [none] +PASS Web Animations: property <font-size-adjust> from [none] to [1.2] at (0.5) should be [1.2] +PASS Web Animations: property <font-size-adjust> from [none] to [1.2] at (0.6) should be [1.2] +PASS Web Animations: property <font-size-adjust> from [none] to [1.2] at (1) should be [1.2] +PASS Web Animations: property <font-size-adjust> from [none] to [1.2] at (1.5) should be [1.2] +FAIL CSS Transitions: property <font-size-adjust> from [none] to [cap 1.2] at (-0.3) should be [cap 1.2] assert_true: 'to' value should be supported expected true got false +FAIL CSS Transitions: property <font-size-adjust> from [none] to [cap 1.2] at (0) should be [cap 1.2] assert_true: 'to' value should be supported expected true got false +FAIL CSS Transitions: property <font-size-adjust> from [none] to [cap 1.2] at (0.3) should be [cap 1.2] assert_true: 'to' value should be supported expected true got false +FAIL CSS Transitions: property <font-size-adjust> from [none] to [cap 1.2] at (0.5) should be [cap 1.2] assert_true: 'to' value should be supported expected true got false +FAIL CSS Transitions: property <font-size-adjust> from [none] to [cap 1.2] at (0.6) should be [cap 1.2] assert_true: 'to' value should be supported expected true got false +FAIL CSS Transitions: property <font-size-adjust> from [none] to [cap 1.2] at (1) should be [cap 1.2] assert_true: 'to' value should be supported expected true got false +FAIL CSS Transitions: property <font-size-adjust> from [none] to [cap 1.2] at (1.5) should be [cap 1.2] assert_true: 'to' value should be supported expected true got false +FAIL CSS Transitions with transition: all: property <font-size-adjust> from [none] to [cap 1.2] at (-0.3) should be [cap 1.2] assert_true: 'to' value should be supported expected true got false +FAIL CSS Transitions with transition: all: property <font-size-adjust> from [none] to [cap 1.2] at (0) should be [cap 1.2] assert_true: 'to' value should be supported expected true got false +FAIL CSS Transitions with transition: all: property <font-size-adjust> from [none] to [cap 1.2] at (0.3) should be [cap 1.2] assert_true: 'to' value should be supported expected true got false +FAIL CSS Transitions with transition: all: property <font-size-adjust> from [none] to [cap 1.2] at (0.5) should be [cap 1.2] assert_true: 'to' value should be supported expected true got false +FAIL CSS Transitions with transition: all: property <font-size-adjust> from [none] to [cap 1.2] at (0.6) should be [cap 1.2] assert_true: 'to' value should be supported expected true got false +FAIL CSS Transitions with transition: all: property <font-size-adjust> from [none] to [cap 1.2] at (1) should be [cap 1.2] assert_true: 'to' value should be supported expected true got false +FAIL CSS Transitions with transition: all: property <font-size-adjust> from [none] to [cap 1.2] at (1.5) should be [cap 1.2] assert_true: 'to' value should be supported expected true got false +FAIL CSS Animations: property <font-size-adjust> from [none] to [cap 1.2] at (-0.3) should be [none] assert_true: 'to' value should be supported expected true got false +FAIL CSS Animations: property <font-size-adjust> from [none] to [cap 1.2] at (0) should be [none] assert_true: 'to' value should be supported expected true got false +FAIL CSS Animations: property <font-size-adjust> from [none] to [cap 1.2] at (0.3) should be [none] assert_true: 'to' value should be supported expected true got false +FAIL CSS Animations: property <font-size-adjust> from [none] to [cap 1.2] at (0.5) should be [cap 1.2] assert_true: 'to' value should be supported expected true got false +FAIL CSS Animations: property <font-size-adjust> from [none] to [cap 1.2] at (0.6) should be [cap 1.2] assert_true: 'to' value should be supported expected true got false +FAIL CSS Animations: property <font-size-adjust> from [none] to [cap 1.2] at (1) should be [cap 1.2] assert_true: 'to' value should be supported expected true got false +FAIL CSS Animations: property <font-size-adjust> from [none] to [cap 1.2] at (1.5) should be [cap 1.2] assert_true: 'to' value should be supported expected true got false +FAIL Web Animations: property <font-size-adjust> from [none] to [cap 1.2] at (-0.3) should be [none] assert_true: 'to' value should be supported expected true got false +FAIL Web Animations: property <font-size-adjust> from [none] to [cap 1.2] at (0) should be [none] assert_true: 'to' value should be supported expected true got false +FAIL Web Animations: property <font-size-adjust> from [none] to [cap 1.2] at (0.3) should be [none] assert_true: 'to' value should be supported expected true got false +FAIL Web Animations: property <font-size-adjust> from [none] to [cap 1.2] at (0.5) should be [cap 1.2] assert_true: 'to' value should be supported expected true got false +FAIL Web Animations: property <font-size-adjust> from [none] to [cap 1.2] at (0.6) should be [cap 1.2] assert_true: 'to' value should be supported expected true got false +FAIL Web Animations: property <font-size-adjust> from [none] to [cap 1.2] at (1) should be [cap 1.2] assert_true: 'to' value should be supported expected true got false +FAIL Web Animations: property <font-size-adjust> from [none] to [cap 1.2] at (1.5) should be [cap 1.2] assert_true: 'to' value should be supported expected true got false +PASS CSS Transitions: property <font-size-adjust> from [0.2] to [1.2] at (-2) should be [0] +PASS CSS Transitions: property <font-size-adjust> from [0.2] to [1.2] at (-0.3) should be [0] +PASS CSS Transitions: property <font-size-adjust> from [0.2] to [1.2] at (0) should be [0.2] +PASS CSS Transitions: property <font-size-adjust> from [0.2] to [1.2] at (0.3) should be [0.5] +PASS CSS Transitions: property <font-size-adjust> from [0.2] to [1.2] at (0.6) should be [0.8] +PASS CSS Transitions: property <font-size-adjust> from [0.2] to [1.2] at (1) should be [1.2] +PASS CSS Transitions: property <font-size-adjust> from [0.2] to [1.2] at (1.5) should be [1.7] +PASS CSS Transitions with transition: all: property <font-size-adjust> from [0.2] to [1.2] at (-2) should be [0] +PASS CSS Transitions with transition: all: property <font-size-adjust> from [0.2] to [1.2] at (-0.3) should be [0] +PASS CSS Transitions with transition: all: property <font-size-adjust> from [0.2] to [1.2] at (0) should be [0.2] +PASS CSS Transitions with transition: all: property <font-size-adjust> from [0.2] to [1.2] at (0.3) should be [0.5] +PASS CSS Transitions with transition: all: property <font-size-adjust> from [0.2] to [1.2] at (0.6) should be [0.8] +PASS CSS Transitions with transition: all: property <font-size-adjust> from [0.2] to [1.2] at (1) should be [1.2] +PASS CSS Transitions with transition: all: property <font-size-adjust> from [0.2] to [1.2] at (1.5) should be [1.7] +PASS CSS Animations: property <font-size-adjust> from [0.2] to [1.2] at (-2) should be [0] +PASS CSS Animations: property <font-size-adjust> from [0.2] to [1.2] at (-0.3) should be [0] +PASS CSS Animations: property <font-size-adjust> from [0.2] to [1.2] at (0) should be [0.2] +PASS CSS Animations: property <font-size-adjust> from [0.2] to [1.2] at (0.3) should be [0.5] +PASS CSS Animations: property <font-size-adjust> from [0.2] to [1.2] at (0.6) should be [0.8] +PASS CSS Animations: property <font-size-adjust> from [0.2] to [1.2] at (1) should be [1.2] +PASS CSS Animations: property <font-size-adjust> from [0.2] to [1.2] at (1.5) should be [1.7] +PASS Web Animations: property <font-size-adjust> from [0.2] to [1.2] at (-2) should be [0] +PASS Web Animations: property <font-size-adjust> from [0.2] to [1.2] at (-0.3) should be [0] +PASS Web Animations: property <font-size-adjust> from [0.2] to [1.2] at (0) should be [0.2] +PASS Web Animations: property <font-size-adjust> from [0.2] to [1.2] at (0.3) should be [0.5] +PASS Web Animations: property <font-size-adjust> from [0.2] to [1.2] at (0.6) should be [0.8] +PASS Web Animations: property <font-size-adjust> from [0.2] to [1.2] at (1) should be [1.2] +PASS Web Animations: property <font-size-adjust> from [0.2] to [1.2] at (1.5) should be [1.7] +FAIL CSS Transitions: property <font-size-adjust> from [ch 0.2] to [ch 1.2] at (-2) should be [ch 0] assert_true: 'from' value should be supported expected true got false +FAIL CSS Transitions: property <font-size-adjust> from [ch 0.2] to [ch 1.2] at (-0.3) should be [ch 0] assert_true: 'from' value should be supported expected true got false +FAIL CSS Transitions: property <font-size-adjust> from [ch 0.2] to [ch 1.2] at (0) should be [ch 0.2] assert_true: 'from' value should be supported expected true got false +FAIL CSS Transitions: property <font-size-adjust> from [ch 0.2] to [ch 1.2] at (0.3) should be [ch 0.5] assert_true: 'from' value should be supported expected true got false +FAIL CSS Transitions: property <font-size-adjust> from [ch 0.2] to [ch 1.2] at (0.6) should be [ch 0.8] assert_true: 'from' value should be supported expected true got false +FAIL CSS Transitions: property <font-size-adjust> from [ch 0.2] to [ch 1.2] at (1) should be [ch 1.2] assert_true: 'from' value should be supported expected true got false +FAIL CSS Transitions: property <font-size-adjust> from [ch 0.2] to [ch 1.2] at (1.5) should be [ch 1.7] assert_true: 'from' value should be supported expected true got false +FAIL CSS Transitions with transition: all: property <font-size-adjust> from [ch 0.2] to [ch 1.2] at (-2) should be [ch 0] assert_true: 'from' value should be supported expected true got false +FAIL CSS Transitions with transition: all: property <font-size-adjust> from [ch 0.2] to [ch 1.2] at (-0.3) should be [ch 0] assert_true: 'from' value should be supported expected true got false +FAIL CSS Transitions with transition: all: property <font-size-adjust> from [ch 0.2] to [ch 1.2] at (0) should be [ch 0.2] assert_true: 'from' value should be supported expected true got false +FAIL CSS Transitions with transition: all: property <font-size-adjust> from [ch 0.2] to [ch 1.2] at (0.3) should be [ch 0.5] assert_true: 'from' value should be supported expected true got false +FAIL CSS Transitions with transition: all: property <font-size-adjust> from [ch 0.2] to [ch 1.2] at (0.6) should be [ch 0.8] assert_true: 'from' value should be supported expected true got false +FAIL CSS Transitions with transition: all: property <font-size-adjust> from [ch 0.2] to [ch 1.2] at (1) should be [ch 1.2] assert_true: 'from' value should be supported expected true got false +FAIL CSS Transitions with transition: all: property <font-size-adjust> from [ch 0.2] to [ch 1.2] at (1.5) should be [ch 1.7] assert_true: 'from' value should be supported expected true got false +FAIL CSS Animations: property <font-size-adjust> from [ch 0.2] to [ch 1.2] at (-2) should be [ch 0] assert_true: 'from' value should be supported expected true got false +FAIL CSS Animations: property <font-size-adjust> from [ch 0.2] to [ch 1.2] at (-0.3) should be [ch 0] assert_true: 'from' value should be supported expected true got false +FAIL CSS Animations: property <font-size-adjust> from [ch 0.2] to [ch 1.2] at (0) should be [ch 0.2] assert_true: 'from' value should be supported expected true got false +FAIL CSS Animations: property <font-size-adjust> from [ch 0.2] to [ch 1.2] at (0.3) should be [ch 0.5] assert_true: 'from' value should be supported expected true got false +FAIL CSS Animations: property <font-size-adjust> from [ch 0.2] to [ch 1.2] at (0.6) should be [ch 0.8] assert_true: 'from' value should be supported expected true got false +FAIL CSS Animations: property <font-size-adjust> from [ch 0.2] to [ch 1.2] at (1) should be [ch 1.2] assert_true: 'from' value should be supported expected true got false +FAIL CSS Animations: property <font-size-adjust> from [ch 0.2] to [ch 1.2] at (1.5) should be [ch 1.7] assert_true: 'from' value should be supported expected true got false +FAIL Web Animations: property <font-size-adjust> from [ch 0.2] to [ch 1.2] at (-2) should be [ch 0] assert_true: 'from' value should be supported expected true got false +FAIL Web Animations: property <font-size-adjust> from [ch 0.2] to [ch 1.2] at (-0.3) should be [ch 0] assert_true: 'from' value should be supported expected true got false +FAIL Web Animations: property <font-size-adjust> from [ch 0.2] to [ch 1.2] at (0) should be [ch 0.2] assert_true: 'from' value should be supported expected true got false +FAIL Web Animations: property <font-size-adjust> from [ch 0.2] to [ch 1.2] at (0.3) should be [ch 0.5] assert_true: 'from' value should be supported expected true got false +FAIL Web Animations: property <font-size-adjust> from [ch 0.2] to [ch 1.2] at (0.6) should be [ch 0.8] assert_true: 'from' value should be supported expected true got false +FAIL Web Animations: property <font-size-adjust> from [ch 0.2] to [ch 1.2] at (1) should be [ch 1.2] assert_true: 'from' value should be supported expected true got false +FAIL Web Animations: property <font-size-adjust> from [ch 0.2] to [ch 1.2] at (1.5) should be [ch 1.7] assert_true: 'from' value should be supported expected true got false +FAIL CSS Transitions: property <font-size-adjust> from [ex 0.2] to [ch 1.2] at (-0.3) should be [ch 1.2] assert_true: 'from' value should be supported expected true got false +FAIL CSS Transitions: property <font-size-adjust> from [ex 0.2] to [ch 1.2] at (0) should be [ch 1.2] assert_true: 'from' value should be supported expected true got false +FAIL CSS Transitions: property <font-size-adjust> from [ex 0.2] to [ch 1.2] at (0.3) should be [ch 1.2] assert_true: 'from' value should be supported expected true got false +FAIL CSS Transitions: property <font-size-adjust> from [ex 0.2] to [ch 1.2] at (0.5) should be [ch 1.2] assert_true: 'from' value should be supported expected true got false +FAIL CSS Transitions: property <font-size-adjust> from [ex 0.2] to [ch 1.2] at (0.6) should be [ch 1.2] assert_true: 'from' value should be supported expected true got false +FAIL CSS Transitions: property <font-size-adjust> from [ex 0.2] to [ch 1.2] at (1) should be [ch 1.2] assert_true: 'from' value should be supported expected true got false +FAIL CSS Transitions: property <font-size-adjust> from [ex 0.2] to [ch 1.2] at (1.5) should be [ch 1.2] assert_true: 'from' value should be supported expected true got false +FAIL CSS Transitions with transition: all: property <font-size-adjust> from [ex 0.2] to [ch 1.2] at (-0.3) should be [ch 1.2] assert_true: 'from' value should be supported expected true got false +FAIL CSS Transitions with transition: all: property <font-size-adjust> from [ex 0.2] to [ch 1.2] at (0) should be [ch 1.2] assert_true: 'from' value should be supported expected true got false +FAIL CSS Transitions with transition: all: property <font-size-adjust> from [ex 0.2] to [ch 1.2] at (0.3) should be [ch 1.2] assert_true: 'from' value should be supported expected true got false +FAIL CSS Transitions with transition: all: property <font-size-adjust> from [ex 0.2] to [ch 1.2] at (0.5) should be [ch 1.2] assert_true: 'from' value should be supported expected true got false +FAIL CSS Transitions with transition: all: property <font-size-adjust> from [ex 0.2] to [ch 1.2] at (0.6) should be [ch 1.2] assert_true: 'from' value should be supported expected true got false +FAIL CSS Transitions with transition: all: property <font-size-adjust> from [ex 0.2] to [ch 1.2] at (1) should be [ch 1.2] assert_true: 'from' value should be supported expected true got false +FAIL CSS Transitions with transition: all: property <font-size-adjust> from [ex 0.2] to [ch 1.2] at (1.5) should be [ch 1.2] assert_true: 'from' value should be supported expected true got false +FAIL CSS Animations: property <font-size-adjust> from [ex 0.2] to [ch 1.2] at (-0.3) should be [ex 0.2] assert_true: 'from' value should be supported expected true got false +FAIL CSS Animations: property <font-size-adjust> from [ex 0.2] to [ch 1.2] at (0) should be [ex 0.2] assert_true: 'from' value should be supported expected true got false +FAIL CSS Animations: property <font-size-adjust> from [ex 0.2] to [ch 1.2] at (0.3) should be [ex 0.2] assert_true: 'from' value should be supported expected true got false +FAIL CSS Animations: property <font-size-adjust> from [ex 0.2] to [ch 1.2] at (0.5) should be [ch 1.2] assert_true: 'from' value should be supported expected true got false +FAIL CSS Animations: property <font-size-adjust> from [ex 0.2] to [ch 1.2] at (0.6) should be [ch 1.2] assert_true: 'from' value should be supported expected true got false +FAIL CSS Animations: property <font-size-adjust> from [ex 0.2] to [ch 1.2] at (1) should be [ch 1.2] assert_true: 'from' value should be supported expected true got false +FAIL CSS Animations: property <font-size-adjust> from [ex 0.2] to [ch 1.2] at (1.5) should be [ch 1.2] assert_true: 'from' value should be supported expected true got false +FAIL Web Animations: property <font-size-adjust> from [ex 0.2] to [ch 1.2] at (-0.3) should be [ex 0.2] assert_true: 'from' value should be supported expected true got false +FAIL Web Animations: property <font-size-adjust> from [ex 0.2] to [ch 1.2] at (0) should be [ex 0.2] assert_true: 'from' value should be supported expected true got false +FAIL Web Animations: property <font-size-adjust> from [ex 0.2] to [ch 1.2] at (0.3) should be [ex 0.2] assert_true: 'from' value should be supported expected true got false +FAIL Web Animations: property <font-size-adjust> from [ex 0.2] to [ch 1.2] at (0.5) should be [ch 1.2] assert_true: 'from' value should be supported expected true got false +FAIL Web Animations: property <font-size-adjust> from [ex 0.2] to [ch 1.2] at (0.6) should be [ch 1.2] assert_true: 'from' value should be supported expected true got false +FAIL Web Animations: property <font-size-adjust> from [ex 0.2] to [ch 1.2] at (1) should be [ch 1.2] assert_true: 'from' value should be supported expected true got false +FAIL Web Animations: property <font-size-adjust> from [ex 0.2] to [ch 1.2] at (1.5) should be [ch 1.2] assert_true: 'from' value should be supported expected true got false +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/mac-mac-arm11.0/external/wpt/css/css-fonts/parsing/font-size-adjust-computed-expected.txt b/third_party/blink/web_tests/platform/mac-mac-arm11.0/external/wpt/css/css-fonts/parsing/font-size-adjust-computed-expected.txt new file mode 100644 index 0000000..cf6646f --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac-arm11.0/external/wpt/css/css-fonts/parsing/font-size-adjust-computed-expected.txt
@@ -0,0 +1,9 @@ +This is a testharness.js-based test. +PASS Property font-size-adjust value 'none' +PASS Property font-size-adjust value '0.5' +FAIL Property font-size-adjust value 'ex 0.5' assert_true: 'ex 0.5' is a supported value for font-size-adjust. expected true got false +FAIL Property font-size-adjust value 'cap 0.8' assert_true: 'cap 0.8' is a supported value for font-size-adjust. expected true got false +FAIL Property font-size-adjust value 'ch 0.4' assert_true: 'ch 0.4' is a supported value for font-size-adjust. expected true got false +FAIL Property font-size-adjust value 'ic 0.9' assert_true: 'ic 0.9' is a supported value for font-size-adjust. expected true got false +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/mac-mac-arm11.0/external/wpt/css/css-fonts/parsing/font-size-adjust-valid-expected.txt b/third_party/blink/web_tests/platform/mac-mac-arm11.0/external/wpt/css/css-fonts/parsing/font-size-adjust-valid-expected.txt new file mode 100644 index 0000000..5139a32 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac-arm11.0/external/wpt/css/css-fonts/parsing/font-size-adjust-valid-expected.txt
@@ -0,0 +1,9 @@ +This is a testharness.js-based test. +PASS e.style['font-size-adjust'] = "none" should set the property value +PASS e.style['font-size-adjust'] = "0.5" should set the property value +FAIL e.style['font-size-adjust'] = "ex 0.5" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['font-size-adjust'] = "cap 0.8" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['font-size-adjust'] = "ch 0.4" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['font-size-adjust'] = "ic 0.9" should set the property value assert_not_equals: property should be set got disallowed value "" +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/mac-mac10.14/external/wpt/streams/readable-streams/tee.any.worker-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.14/external/wpt/streams/readable-streams/tee.any.worker-expected.txt new file mode 100644 index 0000000..1c3ffa74 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac10.14/external/wpt/streams/readable-streams/tee.any.worker-expected.txt
@@ -0,0 +1,28 @@ +This is a testharness.js-based test. +PASS ReadableStream teeing: rs.tee() returns an array of two ReadableStreams +PASS ReadableStream teeing: should be able to read one branch to the end without affecting the other +PASS ReadableStream teeing: values should be equal across each branch +PASS ReadableStream teeing: errors in the source should propagate to both branches +PASS ReadableStream teeing: canceling branch1 should not impact branch2 +PASS ReadableStream teeing: canceling branch2 should not impact branch1 +PASS Running templatedRSTeeCancel with ReadableStream teeing +PASS ReadableStream teeing: canceling both branches should aggregate the cancel reasons into an array +PASS ReadableStream teeing: canceling both branches in reverse order should aggregate the cancel reasons into an array +PASS ReadableStream teeing: failing to cancel the original stream should cause cancel() to reject on branches +PASS ReadableStream teeing: erroring a teed stream should properly handle canceled branches +PASS ReadableStream teeing: erroring a teed stream should error both branches +PASS ReadableStream teeing: closing the original should immediately close the branches +PASS ReadableStream teeing: erroring the original should immediately error the branches +PASS ReadableStream teeing: canceling branch1 should finish when branch2 reads until end of stream +PASS ReadableStream teeing: canceling branch1 should finish when original stream errors +PASS ReadableStream teeing: canceling both branches in sequence with delay +PASS ReadableStream teeing: failing to cancel when canceling both branches in sequence with delay +PASS ReadableStreamTee should not use a modified ReadableStream constructor from the global object +FAIL ReadableStreamTee should not pull more chunks than can fit in the branch queue assert_array_equals: pull should only be called once lengths differ, expected array ["pull"] length 1, got ["pull", "pull"] length 2 +PASS ReadableStreamTee should only pull enough to fill the emptiest queue +PASS ReadableStreamTee should not pull when original is already errored +FAIL ReadableStreamTee stops pulling when original stream errors while branch 1 is reading assert_array_equals: pull should be called once lengths differ, expected array ["pull"] length 1, got ["pull", "pull"] length 2 +FAIL ReadableStreamTee stops pulling when original stream errors while branch 2 is reading assert_array_equals: pull should be called once lengths differ, expected array ["pull"] length 1, got ["pull", "pull"] length 2 +FAIL ReadableStreamTee stops pulling when original stream errors while both branches are reading assert_array_equals: pull should be called once lengths differ, expected array ["pull"] length 1, got ["pull", "pull"] length 2 +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/mac-mac10.15/external/wpt/streams/readable-streams/tee.any.worker-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.15/external/wpt/streams/readable-streams/tee.any.worker-expected.txt new file mode 100644 index 0000000..bebedc3 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac10.15/external/wpt/streams/readable-streams/tee.any.worker-expected.txt
@@ -0,0 +1,27 @@ +This is a testharness.js-based test. +PASS ReadableStream teeing: rs.tee() returns an array of two ReadableStreams +PASS ReadableStream teeing: should be able to read one branch to the end without affecting the other +PASS ReadableStream teeing: values should be equal across each branch +PASS ReadableStream teeing: errors in the source should propagate to both branches +PASS ReadableStream teeing: canceling branch1 should not impact branch2 +PASS ReadableStream teeing: canceling branch2 should not impact branch1 +PASS ReadableStream teeing: canceling both branches should aggregate the cancel reasons into an array +PASS ReadableStream teeing: canceling both branches in reverse order should aggregate the cancel reasons into an array +PASS ReadableStream teeing: failing to cancel the original stream should cause cancel() to reject on branches +PASS ReadableStream teeing: erroring a teed stream should properly handle canceled branches +PASS ReadableStream teeing: erroring a teed stream should error both branches +PASS ReadableStream teeing: closing the original should immediately close the branches +PASS ReadableStream teeing: erroring the original should immediately error the branches +PASS ReadableStream teeing: canceling branch1 should finish when branch2 reads until end of stream +PASS ReadableStream teeing: canceling branch1 should finish when original stream errors +PASS ReadableStream teeing: canceling both branches in sequence with delay +PASS ReadableStream teeing: failing to cancel when canceling both branches in sequence with delay +PASS ReadableStreamTee should not use a modified ReadableStream constructor from the global object +FAIL ReadableStreamTee should not pull more chunks than can fit in the branch queue assert_array_equals: pull should only be called once lengths differ, expected array ["pull"] length 1, got ["pull", "pull"] length 2 +PASS ReadableStreamTee should only pull enough to fill the emptiest queue +PASS ReadableStreamTee should not pull when original is already errored +FAIL ReadableStreamTee stops pulling when original stream errors while branch 1 is reading assert_array_equals: pull should be called once lengths differ, expected array ["pull"] length 1, got ["pull", "pull"] length 2 +FAIL ReadableStreamTee stops pulling when original stream errors while branch 2 is reading assert_array_equals: pull should be called once lengths differ, expected array ["pull"] length 1, got ["pull", "pull"] length 2 +FAIL ReadableStreamTee stops pulling when original stream errors while both branches are reading assert_array_equals: pull should be called once lengths differ, expected array ["pull"] length 1, got ["pull", "pull"] length 2 +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/virtual/anonymous-iframe/webexposed/global-interface-listing-expected.txt b/third_party/blink/web_tests/virtual/anonymous-iframe/webexposed/global-interface-listing-expected.txt index c3ecebc8..981a8d2f 100644 --- a/third_party/blink/web_tests/virtual/anonymous-iframe/webexposed/global-interface-listing-expected.txt +++ b/third_party/blink/web_tests/virtual/anonymous-iframe/webexposed/global-interface-listing-expected.txt
@@ -5759,6 +5759,7 @@ getter webdriver getter webkitPersistentStorage getter webkitTemporaryStorage + getter windowControlsOverlay getter xr method canShare method clearAppBadge @@ -6404,13 +6405,6 @@ getter width method constructor setter onresize -interface Plane - attribute @@toStringTag - getter length - getter rows - getter stride - method constructor - method readInto interface Plugin attribute @@toStringTag getter description @@ -9123,21 +9117,14 @@ attribute @@toStringTag getter codedHeight getter codedRect - getter codedRegion getter codedWidth getter colorSpace - getter cropHeight - getter cropLeft - getter cropTop - getter cropWidth getter displayHeight getter displayWidth getter duration getter format - getter planes getter timestamp getter visibleRect - getter visibleRegion method allocationSize method clone method close @@ -10633,6 +10620,18 @@ attribute PERSISTENT attribute TEMPORARY method constructor +interface WindowControlsOverlay : EventTarget + attribute @@toStringTag + getter ongeometrychange + getter visible + method constructor + method getBoundingClientRect + setter ongeometrychange +interface WindowControlsOverlayGeometryChangeEvent : Event + attribute @@toStringTag + getter boundingRect + getter visible + method constructor interface Worker : EventTarget attribute @@toStringTag getter onerror
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt index a6d0798..2a79ce4 100644 --- a/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt +++ b/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt
@@ -1253,13 +1253,6 @@ [Worker] method request [Worker] method requestAll [Worker] method revoke -[Worker] interface Plane -[Worker] attribute @@toStringTag -[Worker] getter length -[Worker] getter rows -[Worker] getter stride -[Worker] method constructor -[Worker] method readInto [Worker] interface ProgressEvent : Event [Worker] attribute @@toStringTag [Worker] getter lengthComputable @@ -1851,21 +1844,14 @@ [Worker] attribute @@toStringTag [Worker] getter codedHeight [Worker] getter codedRect -[Worker] getter codedRegion [Worker] getter codedWidth [Worker] getter colorSpace -[Worker] getter cropHeight -[Worker] getter cropLeft -[Worker] getter cropTop -[Worker] getter cropWidth [Worker] getter displayHeight [Worker] getter displayWidth [Worker] getter duration [Worker] getter format -[Worker] getter planes [Worker] getter timestamp [Worker] getter visibleRect -[Worker] getter visibleRegion [Worker] method allocationSize [Worker] method clone [Worker] method close
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt index 7f7fd5a..9bffdf8 100644 --- a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt +++ b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
@@ -5757,6 +5757,7 @@ getter webdriver getter webkitPersistentStorage getter webkitTemporaryStorage + getter windowControlsOverlay getter xr method canShare method clearAppBadge @@ -6402,13 +6403,6 @@ getter width method constructor setter onresize -interface Plane - attribute @@toStringTag - getter length - getter rows - getter stride - method constructor - method readInto interface Plugin attribute @@toStringTag getter description @@ -9121,21 +9115,14 @@ attribute @@toStringTag getter codedHeight getter codedRect - getter codedRegion getter codedWidth getter colorSpace - getter cropHeight - getter cropLeft - getter cropTop - getter cropWidth getter displayHeight getter displayWidth getter duration getter format - getter planes getter timestamp getter visibleRect - getter visibleRegion method allocationSize method clone method close @@ -10631,6 +10618,18 @@ attribute PERSISTENT attribute TEMPORARY method constructor +interface WindowControlsOverlay : EventTarget + attribute @@toStringTag + getter ongeometrychange + getter visible + method constructor + method getBoundingClientRect + setter ongeometrychange +interface WindowControlsOverlayGeometryChangeEvent : Event + attribute @@toStringTag + getter boundingRect + getter visible + method constructor interface Worker : EventTarget attribute @@toStringTag getter onerror
diff --git a/third_party/blink/web_tests/wpt_internal/js-self-profiling/__dir__.headers b/third_party/blink/web_tests/wpt_internal/js-self-profiling/__dir__.headers deleted file mode 100644 index 93537b4..0000000 --- a/third_party/blink/web_tests/wpt_internal/js-self-profiling/__dir__.headers +++ /dev/null
@@ -1 +0,0 @@ -Document-Policy: js-profiling
diff --git a/third_party/freetype/README.chromium b/third_party/freetype/README.chromium index 6414d4e9..098117d2 100644 --- a/third_party/freetype/README.chromium +++ b/third_party/freetype/README.chromium
@@ -1,7 +1,7 @@ Name: FreeType URL: http://www.freetype.org/ -Version: VER-2-10-4-308-gd3dc2da9b -Revision: d3dc2da9b27af5b90575d62989389cc65fe7977c +Version: VER-2-10-4-314-g59e95b014 +Revision: 59e95b014aa162393d6d569225cf713d71ffdc33 CPEPrefix: cpe:/a:freetype:freetype:2.10.4 License: Custom license "inspired by the BSD, Artistic, and IJG (Independent JPEG Group) licenses"
diff --git a/third_party/inspector_protocol/README.chromium b/third_party/inspector_protocol/README.chromium index 9f34ef87..b960c84f 100644 --- a/third_party/inspector_protocol/README.chromium +++ b/third_party/inspector_protocol/README.chromium
@@ -2,7 +2,7 @@ Short Name: inspector_protocol URL: https://chromium.googlesource.com/deps/inspector_protocol/ Version: 0 -Revision: 35e8d2d89cb017d72cf905362672de77c978e1e6 +Revision: 32cf5f2bf4dc20c73ead291e68d2e2f6b638cd57 License: BSD License File: LICENSE Security Critical: yes
diff --git a/third_party/inspector_protocol/crdtp/README.md b/third_party/inspector_protocol/crdtp/README.md index 81957e16..c75fbad 100644 --- a/third_party/inspector_protocol/crdtp/README.md +++ b/third_party/inspector_protocol/crdtp/README.md
@@ -41,7 +41,7 @@ # Building and running the tests. If you're familiar with -[Chromium's development process](https://www.chromium.org/developers/contributing-code) +[Chromium's development process](https://chromium.googlesource.com/chromium/src/+/refs/heads/main/docs/contributing.md) and have the depot_tools installed, you may use these commands to fetch the package (and dependencies) and build and run the tests:
diff --git a/third_party/inspector_protocol/lib/base_string_adapter_cc.template b/third_party/inspector_protocol/lib/base_string_adapter_cc.template index 10488f2..96a0c8e 100644 --- a/third_party/inspector_protocol/lib/base_string_adapter_cc.template +++ b/third_party/inspector_protocol/lib/base_string_adapter_cc.template
@@ -33,51 +33,32 @@ return nullptr; if (value->is_none()) return protocol::Value::null(); - if (value->is_bool()) { - bool inner; - value->GetAsBoolean(&inner); - return protocol::FundamentalValue::create(inner); - } - if (value->is_int()) { - int inner; - value->GetAsInteger(&inner); - return protocol::FundamentalValue::create(inner); - } - if (value->is_double()) { - double inner; - value->GetAsDouble(&inner); - return protocol::FundamentalValue::create(inner); - } - if (value->is_string()) { - std::string inner; - value->GetAsString(&inner); - return protocol::StringValue::create(inner); - } + if (value->is_bool()) + return protocol::FundamentalValue::create(value->GetBool()); + if (value->is_int()) + return protocol::FundamentalValue::create(value->GetInt()); + if (value->is_double()) + return protocol::FundamentalValue::create(value->GetDouble()); + if (value->is_string()) + return protocol::StringValue::create(value->GetString()); if (value->is_list()) { - const base::ListValue* list = nullptr; - value->GetAsList(&list); std::unique_ptr<protocol::ListValue> result = protocol::ListValue::create(); - for (size_t i = 0; i < list->GetSize(); i++) { - const base::Value* item = nullptr; - list->Get(i, &item); + for (const base::Value& item : value->GetList()) { std::unique_ptr<protocol::Value> converted = - toProtocolValue(item, depth - 1); + toProtocolValue(&item, depth - 1); if (converted) result->pushValue(std::move(converted)); } return result; } if (value->is_dict()) { - const base::DictionaryValue* dictionary = nullptr; - value->GetAsDictionary(&dictionary); std::unique_ptr<protocol::DictionaryValue> result = protocol::DictionaryValue::create(); - for (base::DictionaryValue::Iterator it(*dictionary); - !it.IsAtEnd(); it.Advance()) { + for (const auto& it : value->DictItems()) { std::unique_ptr<protocol::Value> converted = - toProtocolValue(&it.value(), depth - 1); + toProtocolValue(&it.second, depth - 1); if (converted) - result->setValue(it.key(), std::move(converted)); + result->setValue(it.first, std::move(converted)); } return result; } @@ -111,24 +92,26 @@ } if (value->type() == Value::TypeArray) { ListValue* list = ListValue::cast(value); - std::unique_ptr<base::ListValue> result(new base::ListValue()); + std::unique_ptr<base::Value> result(new base::Value( + base::Value::Type::LIST)); for (size_t i = 0; i < list->size(); i++) { std::unique_ptr<base::Value> converted = toBaseValue(list->at(i), depth - 1); if (converted) - result->Append(std::move(converted)); + result->Append(std::move(*converted)); } return result; } if (value->type() == Value::TypeObject) { DictionaryValue* dict = DictionaryValue::cast(value); - std::unique_ptr<base::DictionaryValue> result(new base::DictionaryValue()); + std::unique_ptr<base::Value> result(new base::Value( + base::Value::Type::DICTIONARY)); for (size_t i = 0; i < dict->size(); i++) { DictionaryValue::Entry entry = dict->at(i); std::unique_ptr<base::Value> converted = toBaseValue(entry.second, depth - 1); if (converted) - result->SetWithoutPathExpansion(entry.first, std::move(converted)); + result->SetKey(entry.first, std::move(*converted)); } return result; }
diff --git a/third_party/metrics_proto/README.chromium b/third_party/metrics_proto/README.chromium index 49dc100..fa4af9b 100644 --- a/third_party/metrics_proto/README.chromium +++ b/third_party/metrics_proto/README.chromium
@@ -1,8 +1,8 @@ Name: Metrics Protos Short Name: metrics_proto URL: This is the canonical public repository -Version: 384326864 -Date: 2021/07/12 UTC +Version: 384480155 +Date: 2021/07/13 UTC License: BSD Security Critical: Yes
diff --git a/third_party/metrics_proto/perf_data.proto b/third_party/metrics_proto/perf_data.proto index c5199f4..31586ab 100644 --- a/third_party/metrics_proto/perf_data.proto +++ b/third_party/metrics_proto/perf_data.proto
@@ -236,6 +236,18 @@ // Indicates a mispredicted branch. optional bool mispredicted = 3; + + // Indicates a predicted branch. + optional bool predicted = 4; + + // Indicates running in a hardware transaction + optional bool in_transaction = 5; + + // Indicates aborting a hardware transaction + optional bool abort = 6; + + // Cycle count to last branch + optional uint32 cycles = 7; } message SampleEvent { @@ -336,6 +348,9 @@ // Not added from original: optional LostEvent lost_event = 6; // Not added from original: optional ThrottleEvent throttle_event = 7; // Not added from original: optional ReadEvent read_event = 8; + + // Time after boot in nanoseconds corresponding to the event. + optional uint64 timestamp = 10; } message PerfEventStats {
diff --git a/third_party/metrics_proto/ukm/source.proto b/third_party/metrics_proto/ukm/source.proto index a283f0e..c58c6ba 100644 --- a/third_party/metrics_proto/ukm/source.proto +++ b/third_party/metrics_proto/ukm/source.proto
@@ -20,10 +20,21 @@ PAYMENT_APP_ID = 5; DESKTOP_WEB_APP_ID = 6; WORKER_ID = 7; + NO_URL_ID = 8; +} + +// Android Activity Type defined by +// https://source.chromium.org/chromium/chromium/src/+/main:chrome/browser/flags/android/chrome_session_state.h?q=ActivityType +enum AndroidActivityType { + TABBED = 0; + CUSTOM_TAB = 1; + TRUSTED_WEB_ACTIVITY = 2; + WEB_APP = 3; + WEB_APK = 4; } // Source contains data related to a top-level navigation. -// Next tag: 18 +// Next tag: 19 message Source { // The URL scheme, such as HTTP, HTTPS, CHROME_EXTENSION, etc. enum UrlScheme { @@ -144,8 +155,17 @@ optional string initial_url = 6; // Flag indicating if the metric was collected while inside a "custom tab". + // TODO(b/191457204): to be replaced by |android_activity_type| below. optional bool is_custom_tab = 7; + // For Android only. Denotes the Chrome activity type when the source was + // created. See + // https://source.chromium.org/chromium/chromium/src/+/main:chrome/browser/flags/android/chrome_session_state.h;l=20;drc=c14f6f4b9c44fe479a8d004576b42723b2a5feb6 + // This field should eventually replace the |is_custom_tab| above because it + // additionally distinguishes between Trusted Web Activities, WebAPKs, and + // WebApps. + optional AndroidActivityType android_activity_type = 18; + // Relative time of navigation for this Source, as seen by the client, and is // set for sources of type ukm::SourceIdType::NAVIGATION_ID. Time of events // related to this Source will generally be relative to this timestamp. The
diff --git a/third_party/zlib/OWNERS b/third_party/zlib/OWNERS index 0bfa9fb..ecffb59 100644 --- a/third_party/zlib/OWNERS +++ b/third_party/zlib/OWNERS
@@ -1,6 +1,5 @@ agl@chromium.org cavalcantii@chromium.org cblume@chromium.org -mtklein@google.com noel@chromium.org scroggo@google.com
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index 4649c32..a70ae419 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -2411,6 +2411,7 @@ <int value="0" label="HOME_FRAGMENT"/> <int value="1" label="CRASHES_LIST_FRAGMENT"/> <int value="2" label="FLAGS_FRAGMENT"/> + <int value="3" label="COMPONENTS_LIST_FRAGMENT"/> </enum> <enum name="AndroidWebViewDevUiMenu"> @@ -25876,6 +25877,7 @@ <int value="870" label="AllowHttpsOnlyMode"/> <int value="871" label="DesktopSharingHubEnabled"/> <int value="872" label="RestrictedManagedGuestSessionEnabled"/> + <int value="873" label="ReportDeviceAudioStatus"/> </enum> <enum name="EnterprisePolicyDeviceIdValidity"> @@ -49969,6 +49971,7 @@ <int value="1019623058" label="ash-enable-shelf-model-synchronization"/> <int value="1019857902" label="disable-hide-inactive-stacked-tab-close-buttons"/> + <int value="1021573543" label="QuickSettingsPWA:disabled"/> <int value="1021848000" label="SharedHighlightingUseBlocklist:disabled"/> <int value="1022424308" label="SignedExchangeSubresourcePrefetch:enabled"/> <int value="1022992701" label="enable-origin-chip-always"/> @@ -51296,6 +51299,7 @@ <int value="2087069781" label="ui-debug-tools:enabled"/> <int value="2088446947" label="enable-ephemeral-guest-profiles-on-desktop"/> <int value="2089897928" label="enable-audio-focus"/> + <int value="2089901626" label="QuickSettingsPWA:enabled"/> <int value="2091002949" label="RemoveNavigationHistory:disabled"/> <int value="2091943748" label="MigrateDefaultChromeAppToWebAppsGSuite:disabled"/>
diff --git a/tools/metrics/histograms/histograms_xml/android/histograms.xml b/tools/metrics/histograms/histograms_xml/android/histograms.xml index 3cb27f8c..fb377c8 100644 --- a/tools/metrics/histograms/histograms_xml/android/histograms.xml +++ b/tools/metrics/histograms/histograms_xml/android/histograms.xml
@@ -3333,6 +3333,20 @@ </summary> </histogram> +<histogram + name="Android.WebView.Metrics.PackagesAllowList.ResultReceivingDelay" + units="ms" expires_after="2022-07-01"> + <owner>hazems@chromium.org</owner> + <owner>src/android_webview/OWNERS</owner> + <summary> + Records the time delta between creating a AwMetricsServiceClient instance + during WebView startup and the time when the app package names allowlist is + loaded and looked up. This only records when a new version of the allowlist + is loaded successfully. i.e it's not recorded if the loading the allowlist + fails or if a cached version is used. + </summary> +</histogram> + <histogram name="Android.WebView.MixedContent.Mode" enum="WebViewMixedContentMode" expires_after="M96"> <owner>ntfschr@chromium.org</owner>
diff --git a/tools/metrics/histograms/histograms_xml/ash/histograms.xml b/tools/metrics/histograms/histograms_xml/ash/histograms.xml index 141ddb3..a6b064c 100644 --- a/tools/metrics/histograms/histograms_xml/ash/histograms.xml +++ b/tools/metrics/histograms/histograms_xml/ash/histograms.xml
@@ -1498,6 +1498,26 @@ </summary> </histogram> +<histogram name="Ash.MessageCenter.Scroll.PresentationTime" units="ms" + expires_after="2022-07-10"> + <owner>leandre@chromium.org</owner> + <owner>cros-status-area-eng@google.com</owner> + <summary> + Presentation time while scrolling through the list of notifications in + Notification Center. Emitted when Notification Center is scrolled. + </summary> +</histogram> + +<histogram name="Ash.MessageCenter.Scroll.PresentationTime.MaxLatency" + units="ms" expires_after="2022-07-10"> + <owner>leandre@chromium.org</owner> + <owner>cros-status-area-eng@google.com</owner> + <summary> + Presentation time while scrolling through the list of notifications in + Notification Center. Emitted when Notification Center is scrolled. + </summary> +</histogram> + <histogram base="true" name="Ash.NavigationWidget.AnimationSmoothness" units="%" expires_after="2022-06-02"> <!-- Name completed by histogram suffixes
diff --git a/tools/metrics/histograms/histograms_xml/autofill/histograms.xml b/tools/metrics/histograms/histograms_xml/autofill/histograms.xml index 8ca6e8f..462629d 100644 --- a/tools/metrics/histograms/histograms_xml/autofill/histograms.xml +++ b/tools/metrics/histograms/histograms_xml/autofill/histograms.xml
@@ -41,6 +41,14 @@ to be filled and assigned to the control case."/> </variants> +<variants name="Autofill.BetterAuthFlowType"> + <variant name="Cvc" summary="CVC authentication only"/> + <variant name="CvcFallbackFromFido" + summary="CVC fallback from FIDO authentication"/> + <variant name="CvcThenFido" summary="CVC followed by FIDO authentication"/> + <variant name="Fido" summary="FIDO authentication only"/> +</variants> + <variants name="Autofill.OfferNotification.Type"> <variant name="CardLinkedOffer" summary="The bubble/infobar for an offer that is linked to a credit @@ -358,6 +366,21 @@ </summary> </histogram> +<histogram + name="Autofill.BetterAuth.FlowEvents.{BetterAuthFlowType}.{CardType}" + enum="AutofillCreditCardAuthenticationEvents" expires_after="2021-12-05"> + <owner>jsaul@google.com</owner> + <owner>manasverma@google.com</owner> + <owner>autofill-auth-team@google.com</owner> + <summary> + Tracks when a user completes each step in a card unmasking flow per + authentication flow type, with an additional breakdown for if it was a + server card or virtual card. + </summary> + <token key="BetterAuthFlowType" variants="Autofill.BetterAuthFlowType"/> + <token key="CardType" variants="Autofill.PaymentsRpcCardType"/> +</histogram> + <histogram base="true" name="Autofill.BetterAuth.OptInCalled" enum="AutofillCreditCardWebauthnOptInParameters" expires_after="2021-12-05"> <owner>jsaul@google.com</owner>
diff --git a/tools/metrics/histograms/histograms_xml/download/histograms.xml b/tools/metrics/histograms/histograms_xml/download/histograms.xml index 96e1517..a0dd274e 100644 --- a/tools/metrics/histograms/histograms_xml/download/histograms.xml +++ b/tools/metrics/histograms/histograms_xml/download/histograms.xml
@@ -73,7 +73,9 @@ </histogram> <histogram name="Download.ContentType.Audio" enum="DownloadAudioType" - expires_after="2021-08-22"> + expires_after="never"> +<!-- expires-never: Monitors download system health. --> + <owner>xingliu@chromium.org</owner> <summary>Types of audio files that are downloaded.</summary> </histogram> @@ -87,7 +89,9 @@ </histogram> <histogram name="Download.ContentType.Text" enum="DownloadTextType" - expires_after="2021-09-12"> + expires_after="never"> +<!-- expires-never: Monitors download system health. --> + <owner>xingliu@chromium.org</owner> <summary>Types of text files that are downloaded.</summary> </histogram>
diff --git a/tools/metrics/histograms/histograms_xml/histogram_suffixes_list.xml b/tools/metrics/histograms/histograms_xml/histogram_suffixes_list.xml index 6f898e58..916a1aa 100644 --- a/tools/metrics/histograms/histograms_xml/histogram_suffixes_list.xml +++ b/tools/metrics/histograms/histograms_xml/histogram_suffixes_list.xml
@@ -944,6 +944,11 @@ </histogram_suffixes> <histogram_suffixes name="AndroidWebViewFragments" separator="."> + <owner>hazems@chromium.org</owner> + <owner>ntfschr@chromium.org</owner> + <owner>src/android_webview/OWNERS</owner> + <suffix name="ComponentsListFragment" + label="This is for the components list tool"/> <suffix name="CrashesListFragment" label="This is for the crash list tool."/> <suffix name="FlagsFragment" label="This is for the flag modification tool."/> <suffix name="HomeFragment" label="This is for the home (default) page."/> @@ -8319,6 +8324,14 @@ <suffix name="IPH_ReadingListEntryPoint" label="In product help to educate users to click the star icon to add a tab to reading list."/> + <suffix name="IPH_ReadLaterAppMenuBookmarks" + label="In product help for read later app menu.."/> + <suffix name="IPH_ReadLaterAppMenuBookmarkThisPage" + label="In product help for read later app menu."/> + <suffix name="IPH_ReadLaterBottomSheet" + label="In product help for read later bottom sheet entry point."/> + <suffix name="IPH_ReadLaterContextMenu" + label="In product help for read later context menu entry point."/> <suffix name="IPH_ReopenTab" label="In product help for reopening closed tabs."/> <suffix name="IPH_SharedHighlightingBuilder"
diff --git a/tools/metrics/histograms/histograms_xml/others/histograms.xml b/tools/metrics/histograms/histograms_xml/others/histograms.xml index ef225de..5e1d7e7 100644 --- a/tools/metrics/histograms/histograms_xml/others/histograms.xml +++ b/tools/metrics/histograms/histograms_xml/others/histograms.xml
@@ -7138,6 +7138,23 @@ </summary> </histogram> +<histogram + name="Graphics.Smoothness.PerSession.TimeMaxPercentDroppedFrames_1sWindow" + units="ms" expires_after="2021-11-18"> + <owner>sadrul@chromium.org</owner> + <owner>graphics-dev@chromium.org</owner> + <summary> + Tracks the time since First Contentful Paint when the sliding window with + the max percent of dropped frames occurs, up to 25 seconds. The metric is + reported once per page-load when the page closes. + + PercentDroppedFrames is measured by tracking the number of frames which were + not displayed on screen out of the total number of frames expected to be + produced and displayed. In other words, the lower this number is, the + smoother experience. + </summary> +</histogram> + <histogram name="Graphics.Smoothness.Stale" units="ms" expires_after="2022-01-02"> <owner>sadrul@chromium.org</owner>
diff --git a/tools/metrics/histograms/histograms_xml/uma/histograms.xml b/tools/metrics/histograms/histograms_xml/uma/histograms.xml index a948d4b..5c70a21 100644 --- a/tools/metrics/histograms/histograms_xml/uma/histograms.xml +++ b/tools/metrics/histograms/histograms_xml/uma/histograms.xml
@@ -495,6 +495,37 @@ </summary> </histogram> +<histogram name="UMA.ReadAndTruncateMetricsFromFile.DiscardedCount" + units="samples" expires_after="2021-12-26"> + <owner>iby@chromium.org</owner> + <owner>cros-telemetry@google.com</owner> + <summary> + Number of metric samples discarded on each read from the ChromeOS external + metrics file. This should only be greater than 0 if the file had so many + samples we couldn't fit them all in memory. Emitted each time + ReadAndTruncateMetricsFromFile() is called and successfully processes the + external metrics file. No entry is emitted if there was an unexpected error + opening the file. If the file is found to be corrupt partway through a read, + the number of entries discarded before the corruption is found is recorded. + </summary> +</histogram> + +<histogram name="UMA.ReadAndTruncateMetricsFromFile.ReadCount" units="samples" + expires_after="2021-12-26"> + <owner>iby@chromium.org</owner> + <owner>cros-telemetry@google.com</owner> + <summary> + Number of metric samples successfully read from the ChromeOS external + metrics file on each read. Samples discarded because the file is too large + are recorded in UMA.ReadAndTruncateMetricsFromFile.DiscardedCount and not in + here. Emitted each time ReadAndTruncateMetricsFromFile() is called and + successfully processes the external metrics file. No entry is emitted if + there was an unexpected error opening the file. If the file is found to be + corrupt partway through a read, the number of entries read before the + corruption is found is recorded. + </summary> +</histogram> + <histogram name="UMA.SamplingRatePerMille" units="samples per mille" expires_after="2022-01-02"> <owner>jwd@chromium.org</owner>
diff --git a/tools/perf/core/perfetto_binary_roller/binary_deps.json b/tools/perf/core/perfetto_binary_roller/binary_deps.json index 5bf0b4f6..bb329c3 100644 --- a/tools/perf/core/perfetto_binary_roller/binary_deps.json +++ b/tools/perf/core/perfetto_binary_roller/binary_deps.json
@@ -1,16 +1,16 @@ { "trace_processor_shell": { "win": { - "hash": "1e40184a08982bb78e3cce7a2c21a975eb6b6e00", - "remote_path": "perfetto_binaries/trace_processor_shell/win/aecbd80f576686b67e29bdfae8c9c03bb9ce1996/trace_processor_shell.exe" + "hash": "711c1ef1d13ae18e0dc950a11774deb2bf03fab7", + "remote_path": "perfetto_binaries/trace_processor_shell/win/1595ee00954aff328e9e335b36c9c000476fd670/trace_processor_shell.exe" }, "mac": { - "hash": "d7eb4c9af40a0bfbf9431c469c498da7f8195132", - "remote_path": "perfetto_binaries/trace_processor_shell/mac/aecbd80f576686b67e29bdfae8c9c03bb9ce1996/trace_processor_shell" + "hash": "9553d226a4780c049c31e0a71e526051f7e26bc2", + "remote_path": "perfetto_binaries/trace_processor_shell/mac/51a1443c7cb98f1fd50e1bb87c183704b4f5c81b/trace_processor_shell" }, "linux": { - "hash": "cf2335e84a4ffd5b6205005e90fdd6c05211bf4c", - "remote_path": "perfetto_binaries/trace_processor_shell/linux/aecbd80f576686b67e29bdfae8c9c03bb9ce1996/trace_processor_shell" + "hash": "8184e149b615d87ed64ce5877e86e2724d7ccbdf", + "remote_path": "perfetto_binaries/trace_processor_shell/linux/1595ee00954aff328e9e335b36c9c000476fd670/trace_processor_shell" } }, "power_profile.sql": {
diff --git a/tools/traffic_annotation/summary/annotations.xml b/tools/traffic_annotation/summary/annotations.xml index 4f0ef3fe..115321b0 100644 --- a/tools/traffic_annotation/summary/annotations.xml +++ b/tools/traffic_annotation/summary/annotations.xml
@@ -337,7 +337,7 @@ <item id="stream_message_pipe_adapter" added_in_milestone="66" hash_code="71837756" type="0" content_hash_code="66212605" os_list="linux,windows" file_path="remoting/protocol/stream_message_pipe_adapter.cc"/> <item id="stream_packet_socket" added_in_milestone="84" hash_code="38197513" type="0" content_hash_code="55116994" os_list="linux,windows" file_path="remoting/protocol/stream_packet_socket.cc"/> <item id="suggestions_image_manager" added_in_milestone="62" hash_code="13211343" type="0" deprecated="2018-11-28" content_hash_code="36271280" file_path=""/> - <item id="suggestions_service" added_in_milestone="62" hash_code="35370363" type="0" content_hash_code="66296423" os_list="linux,windows" file_path="components/suggestions/suggestions_service_impl.cc"/> + <item id="suggestions_service" added_in_milestone="62" hash_code="35370363" type="0" deprecated="2021-07-08" content_hash_code="66296423" file_path=""/> <item id="supervised_user_refresh_token_fetcher" added_in_milestone="62" hash_code="136117054" type="0" deprecated="2018-04-18" content_hash_code="101636136" file_path=""/> <item id="supervised_user_url_filter" added_in_milestone="62" hash_code="14257952" type="0" deprecated="2019-07-30" content_hash_code="30470003" file_path=""/> <item id="supervised_users_blacklist" added_in_milestone="62" hash_code="78544924" type="0" deprecated="2019-07-30" content_hash_code="10924669" file_path=""/>
diff --git a/ui/android/BUILD.gn b/ui/android/BUILD.gn index 6078cb6..d4f90e5 100644 --- a/ui/android/BUILD.gn +++ b/ui/android/BUILD.gn
@@ -411,6 +411,7 @@ "javatests/src/org/chromium/ui/test/util/DummyUiActivityTestCase.java", "javatests/src/org/chromium/ui/test/util/NightModeTestUtils.java", "javatests/src/org/chromium/ui/test/util/RenderTestRule.java", + "javatests/src/org/chromium/ui/test/util/ThemedDummyUiActivityTestRule.java", "javatests/src/org/chromium/ui/test/util/UiDisableIf.java", "javatests/src/org/chromium/ui/test/util/UiDisableIfSkipCheck.java", "javatests/src/org/chromium/ui/test/util/UiRestriction.java", @@ -423,6 +424,7 @@ ":ui_java", "//base:base_java", "//base:base_java_test_support", + "//components/browser_ui/modaldialog/android:java", "//third_party/android_deps:android_support_v7_appcompat_java", # For androidx.test.espresso.ViewInteraction
diff --git a/ui/android/DEPS b/ui/android/DEPS index c011478..a46a1565 100644 --- a/ui/android/DEPS +++ b/ui/android/DEPS
@@ -28,5 +28,8 @@ specific_include_rules = { ".*test\.(cc|h)": [ "+components/viz/test" - ] + ], + ".*DummyUiActivity\.java": [ + "+components/browser_ui/modaldialog/android/java/src/org/chromium/components/browser_ui/modaldialog", + ], }
diff --git a/ui/android/javatests/src/org/chromium/ui/test/util/DummyUiActivity.java b/ui/android/javatests/src/org/chromium/ui/test/util/DummyUiActivity.java index e32f73e..2d93f5c 100644 --- a/ui/android/javatests/src/org/chromium/ui/test/util/DummyUiActivity.java +++ b/ui/android/javatests/src/org/chromium/ui/test/util/DummyUiActivity.java
@@ -8,19 +8,25 @@ import android.view.KeyEvent; import android.view.MotionEvent; -import androidx.annotation.IdRes; import androidx.annotation.LayoutRes; +import androidx.annotation.StyleRes; import androidx.appcompat.app.AppCompatActivity; import org.chromium.base.Callback; +import org.chromium.components.browser_ui.modaldialog.AppModalPresenter; +import org.chromium.ui.modaldialog.ModalDialogManager; +import org.chromium.ui.modaldialog.ModalDialogManager.ModalDialogType; +import org.chromium.ui.modaldialog.ModalDialogManagerHolder; /** Dummy activity to test UI components without Chrome browser initialization and natives. */ -public class DummyUiActivity extends AppCompatActivity { +public class DummyUiActivity extends AppCompatActivity implements ModalDialogManagerHolder { private static int sTestTheme; private static int sTestLayout; private Callback<MotionEvent> mMotionEventCallback; private Callback<KeyEvent> mKeyEventCallback; + private ModalDialogManager mModalDialogManager = + new ModalDialogManager(new AppModalPresenter(this), ModalDialogType.APP); @Override public void onCreate(Bundle savedInstanceState) { @@ -39,7 +45,7 @@ * in test code later if you want to set theme after activity launched. * @param resid The style resource describing the theme. */ - public static void setTestTheme(@IdRes int resid) { + public static void setTestTheme(@StyleRes int resid) { sTestTheme = resid; } @@ -53,6 +59,12 @@ sTestLayout = layoutResID; } + // Implementation of ModalDialogManagerHolder + @Override + public ModalDialogManager getModalDialogManager() { + return mModalDialogManager; + } + @Override public boolean dispatchTouchEvent(MotionEvent event) { if (mMotionEventCallback != null) mMotionEventCallback.onResult(event);
diff --git a/ui/android/javatests/src/org/chromium/ui/test/util/DummyUiActivityTestCase.java b/ui/android/javatests/src/org/chromium/ui/test/util/DummyUiActivityTestCase.java index 2171462..390d1df 100644 --- a/ui/android/javatests/src/org/chromium/ui/test/util/DummyUiActivityTestCase.java +++ b/ui/android/javatests/src/org/chromium/ui/test/util/DummyUiActivityTestCase.java
@@ -24,16 +24,30 @@ public class DummyUiActivityTestCase { private DummyUiActivity mActivity; - private BaseActivityTestRule<DummyUiActivity> mActivityTestRule = - new BaseActivityTestRule<>(DummyUiActivity.class); + private final BaseActivityTestRule<? extends DummyUiActivity> mActivityTestRule; // Disable animations to reduce flakiness. @ClassRule - public static DisableAnimationsTestRule disableAnimationsRule = new DisableAnimationsTestRule(); + public static final DisableAnimationsTestRule disableAnimationsRule = + new DisableAnimationsTestRule(); @Rule - public TestRule ruleChain = RuleChain.outerRule(mActivityTestRule) - .around(new TestDriverRule()); + public final TestRule ruleChain; + + /** Default constructor that creates a {@link DummyUiActivity} as expected. */ + public DummyUiActivityTestCase() { + this(new BaseActivityTestRule<DummyUiActivity>(DummyUiActivity.class)); + } + + /** + * Constructor to allow subclasses to inject activity and rule subclasses. + * @param activityTestRule Injected rule to use for activity interactions. + */ + protected DummyUiActivityTestCase( + BaseActivityTestRule<? extends DummyUiActivity> activityTestRule) { + mActivityTestRule = activityTestRule; + ruleChain = RuleChain.outerRule(mActivityTestRule).around(new TestDriverRule()); + } /** * TestRule to setup and tear down for each test. @@ -72,8 +86,4 @@ public DummyUiActivity getActivity() { return mActivity; } - - public BaseActivityTestRule<DummyUiActivity> getActivityTestRule() { - return mActivityTestRule; - } }
diff --git a/ui/android/javatests/src/org/chromium/ui/test/util/ThemedDummyUiActivityTestRule.java b/ui/android/javatests/src/org/chromium/ui/test/util/ThemedDummyUiActivityTestRule.java new file mode 100644 index 0000000..c0fe3d9 --- /dev/null +++ b/ui/android/javatests/src/org/chromium/ui/test/util/ThemedDummyUiActivityTestRule.java
@@ -0,0 +1,49 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.ui.test.util; + +import androidx.annotation.CallSuper; +import androidx.annotation.StyleRes; + +import org.junit.runner.Description; +import org.junit.runners.model.Statement; + +import org.chromium.base.test.BaseActivityTestRule; + +/** + * A wrapper around {@link BaseActivityTestRule} that sets the {@link DummyUiActivity} theme. This + * test rule only allows setting one theme at a time. If you need to set more than one theme, at + * this time, you need to create test-only theme in resources. + * @param <T> Activity must subclass DummyUiActivity to allow setting the theme. + * */ +public class ThemedDummyUiActivityTestRule<T extends DummyUiActivity> + extends BaseActivityTestRule<T> { + private final @StyleRes int mThemeId; + + /** + * @param activityClass The class of the activity the test rule will use. + * @param themeId The theme to apply to the activity. + */ + public ThemedDummyUiActivityTestRule(Class<T> activityClass, @StyleRes int themeId) { + super(activityClass); + mThemeId = themeId; + } + + @Override + @CallSuper + public Statement apply(final Statement base, final Description desc) { + return super.apply(new Statement() { + @Override + public void evaluate() throws Throwable { + DummyUiActivity.setTestTheme(mThemeId); + try { + base.evaluate(); + } finally { + DummyUiActivity.setTestTheme(0); + } + } + }, desc); + } +}
diff --git a/ui/aura/window.cc b/ui/aura/window.cc index 824b4d6..b04cbd1 100644 --- a/ui/aura/window.cc +++ b/ui/aura/window.cc
@@ -871,7 +871,8 @@ } void* Window::GetNativeWindowProperty(const char* key) const { - return reinterpret_cast<void*>(GetPropertyInternal(key, 0)); + return reinterpret_cast<void*>(GetPropertyInternal(key, 0, + /*search_parent=*/false)); } void Window::OnDeviceScaleFactorChanged(float old_device_scale_factor,
diff --git a/ui/base/class_property.cc b/ui/base/class_property.cc index 86c0c48..78767b39 100644 --- a/ui/base/class_property.cc +++ b/ui/base/class_property.cc
@@ -7,6 +7,8 @@ #include <algorithm> #include <utility> +#include "base/notreached.h" + namespace ui { PropertyHandler::PropertyHandler() = default; @@ -28,7 +30,7 @@ PropertyDeallocator deallocator, int64_t value, int64_t default_value) { - int64_t old = GetPropertyInternal(key, default_value); + int64_t old = GetPropertyInternal(key, default_value, false); if (value == default_value) { prop_map_.erase(key); } else { @@ -53,12 +55,30 @@ prop_map_.clear(); } +PropertyHandler* PropertyHandler::GetParentHandler() const { + // If you plan on using cascading properties, you must override this method + // to return the "parent" handler. If you want to use cascading properties in + // scenarios where there isn't a notion of a parent, just override this method + // and return null. + NOTREACHED(); + return nullptr; +} + int64_t PropertyHandler::GetPropertyInternal(const void* key, - int64_t default_value) const { - auto iter = prop_map_.find(key); - if (iter == prop_map_.end()) - return default_value; - return iter->second.value; + int64_t default_value, + bool search_parent) const { + const PropertyHandler* handler = this; + while (handler) { + auto iter = handler->prop_map_.find(key); + if (iter == handler->prop_map_.end()) { + if (!search_parent) + break; + handler = handler->GetParentHandler(); + continue; + } + return iter->second.value; + } + return default_value; } std::set<const void*> PropertyHandler::GetAllPropertyKeys() const {
diff --git a/ui/base/class_property.h b/ui/base/class_property.h index 25c00e7d0..a4be5fb 100644 --- a/ui/base/class_property.h +++ b/ui/base/class_property.h
@@ -45,6 +45,18 @@ // If the properties are used outside the file where they are defined // their accessor methods should also be declared in a suitable header // using DECLARE_EXPORTED_UI_CLASS_PROPERTY_TYPE(FOO_EXPORT, MyType) +// +// Cascading properties: +// +// Use the DEFINE_CASCADING_XXX macros to create a class property type that +// will automatically search up an instance hierarchy for the first defined +// property. This only affects the GetProperty() call. SetProperty() will +// still explicitly set the value on the given instance. This is useful for +// hierarchies of instances which a single set property can effect a whole sub- +// tree of instances. +// +// In order to use this feature, you must override GetParentHandler() on the +// class that inherits PropertyHandler. namespace ui { @@ -55,6 +67,7 @@ struct ClassProperty { T default_value; const char* name; + bool cascading = false; PropertyDeallocator deallocator; }; @@ -79,7 +92,9 @@ // Sets the |value| of the given class |property|. Setting to the default // value (e.g., NULL) removes the property. The lifetime of objects set as // values of unowned properties is managed by the caller (owned properties are - // freed when they are overwritten or cleared). + // freed when they are overwritten or cleared). NOTE: This should NOT be + // for passing a raw pointer for owned properties. Prefer the std::unique_ptr + // version below. template<typename T> void SetProperty(const ClassProperty<T>* property, T value); @@ -97,8 +112,16 @@ template <typename T> void SetProperty(const ClassProperty<T*>* property, T&& value); + // Sets the |value| of the given class |property|, which must be an owned + // property and of pointer type. Use std::make_unique<> or base::WrapUnique to + // ensure proper ownership transfer. + template <typename T> + T* SetProperty(const ClassProperty<T*>* property, std::unique_ptr<T> value); + // Returns the value of the given class |property|. Returns the // property-specific default value if the property was not previously set. + // The return value is the raw pointer useful for accessing the value + // contents. template<typename T> T GetProperty(const ClassProperty<T>* property) const; @@ -115,6 +138,10 @@ virtual void AfterPropertyChange(const void* key, int64_t old_value) {} void ClearProperties(); + // Override this function when inheriting this class on a class or classes + // in which instances are arranged in a parent-child relationship and + // the intent is to use cascading properties. + virtual PropertyHandler* GetParentHandler() const; // Called by the public {Set,Get,Clear}Property functions. int64_t SetPropertyInternal(const void* key, @@ -122,7 +149,13 @@ PropertyDeallocator deallocator, int64_t value, int64_t default_value); - int64_t GetPropertyInternal(const void* key, int64_t default_value) const; + // |search_parent| is required here for the setters to be able to look up the + // current value of property only on the current instance without searching + // the parent handler. This value is sent with the AfterPropertyChange() + // notification. + int64_t GetPropertyInternal(const void* key, + int64_t default_value, + bool search_parent) const; private: // Value struct to keep the name and deallocator for this property. @@ -177,11 +210,13 @@ (*property->deallocator)(old); } } - template<typename T> + template <typename T> static T Get(const ::ui::PropertyHandler* handler, - const ::ui::ClassProperty<T>* property) { + const ::ui::ClassProperty<T>* property, + bool allow_cascade) { return ClassPropertyCaster<T>::FromInt64(handler->GetPropertyInternal( - property, ClassPropertyCaster<T>::ToInt64(property->default_value))); + property, ClassPropertyCaster<T>::ToInt64(property->default_value), + property->cascading && allow_cascade)); } template<typename T> static void Clear(::ui::PropertyHandler* handler, @@ -202,13 +237,13 @@ void PropertyHandler::SetProperty(const ClassProperty<T*>* property, const T& value) { // Prevent additional heap allocation if possible. - T* const old = GetProperty(property); + T* const old = subtle::PropertyHelper::Get<T*>(this, property, false); if (old) { T temp(*old); *old = value; AfterPropertyChange(property, reinterpret_cast<int64_t>(&temp)); } else { - SetProperty(property, new T(value)); + SetProperty(property, std::make_unique<T>(value)); } } @@ -216,16 +251,26 @@ void PropertyHandler::SetProperty(const ClassProperty<T*>* property, T&& value) { // Prevent additional heap allocation if possible. - T* const old = GetProperty(property); + T* const old = subtle::PropertyHelper::Get<T*>(this, property, false); if (old) { T temp(std::move(*old)); *old = std::forward<T>(value); AfterPropertyChange(property, reinterpret_cast<int64_t>(&temp)); } else { - SetProperty(property, new T(std::forward<T>(value))); + SetProperty(property, std::make_unique<T>(std::forward<T>(value))); } } +template <typename T> +T* PropertyHandler::SetProperty(const ClassProperty<T*>* property, + std::unique_ptr<T> value) { + // This form only works for 'owned' properties. + DCHECK(property->deallocator); + T* value_ptr = value.get(); + subtle::PropertyHelper::Set<T*>(this, property, value.release()); + return value_ptr; +} + } // namespace ui // Macros to declare the property getter/setter template functions. @@ -253,7 +298,7 @@ template <> \ EXPORT T \ PropertyHandler::GetProperty(const ClassProperty<T>* property) const { \ - return subtle::PropertyHelper::Get<T>(this, property); \ + return subtle::PropertyHelper::Get<T>(this, property, true); \ } \ template <> \ EXPORT void PropertyHandler::ClearProperty( \ @@ -267,18 +312,36 @@ #define DEFINE_UI_CLASS_PROPERTY_KEY(TYPE, NAME, DEFAULT) \ static_assert(sizeof(TYPE) <= sizeof(int64_t), "property type too large"); \ - const ::ui::ClassProperty<TYPE> NAME##_Value = {DEFAULT, #NAME, nullptr}; \ + const ::ui::ClassProperty<TYPE> NAME##_Value = {DEFAULT, #NAME, false, \ + nullptr}; \ const ::ui::ClassProperty<TYPE>* const NAME = &NAME##_Value; -#define DEFINE_OWNED_UI_CLASS_PROPERTY_KEY(TYPE, NAME, DEFAULT) \ - namespace { \ - void Deallocator##NAME(int64_t p) { \ - enum { type_must_be_complete = sizeof(TYPE) }; \ - delete ::ui::ClassPropertyCaster<TYPE*>::FromInt64(p); \ - } \ - const ::ui::ClassProperty<TYPE*> NAME##_Value = {DEFAULT, #NAME, \ - &Deallocator##NAME}; \ - } /* namespace */ \ +#define DEFINE_OWNED_UI_CLASS_PROPERTY_KEY(TYPE, NAME, DEFAULT) \ + namespace { \ + void Deallocator##NAME(int64_t p) { \ + enum { type_must_be_complete = sizeof(TYPE) }; \ + delete ::ui::ClassPropertyCaster<TYPE*>::FromInt64(p); \ + } \ + const ::ui::ClassProperty<TYPE*> NAME##_Value = {DEFAULT, #NAME, false, \ + &Deallocator##NAME}; \ + } /* namespace */ \ + const ::ui::ClassProperty<TYPE*>* const NAME = &NAME##_Value; + +#define DEFINE_CASCADING_UI_CLASS_PROPERTY_KEY(TYPE, NAME, DEFAULT) \ + static_assert(sizeof(TYPE) <= sizeof(int64_t), "property type too large"); \ + const ::ui::ClassProperty<TYPE> NAME##_Value = {DEFAULT, #NAME, true, \ + nullptr}; \ + const ::ui::ClassProperty<TYPE>* const NAME = &NAME##_Value; + +#define DEFINE_CASCADING_OWNED_UI_CLASS_PROPERTY_KEY(TYPE, NAME, DEFAULT) \ + namespace { \ + void Deallocator##NAME(int64_t p) { \ + enum { type_must_be_complete = sizeof(TYPE) }; \ + delete ::ui::ClassPropertyCaster<TYPE*>::FromInt64(p); \ + } \ + const ::ui::ClassProperty<TYPE*> NAME##_Value = {DEFAULT, #NAME, true, \ + &Deallocator##NAME}; \ + } /* namespace */ \ const ::ui::ClassProperty<TYPE*>* const NAME = &NAME##_Value; #endif // UI_BASE_CLASS_PROPERTY_H_
diff --git a/ui/base/class_property_unittest.cc b/ui/base/class_property_unittest.cc index ffc2dca..ffa0dbc 100644 --- a/ui/base/class_property_unittest.cc +++ b/ui/base/class_property_unittest.cc
@@ -22,7 +22,9 @@ class TestProperty { public: - TestProperty() {} + TestProperty() = default; + TestProperty(const TestProperty&) = delete; + TestProperty& operator=(const TestProperty&) = delete; ~TestProperty() { last_deleted_ = this; } @@ -30,7 +32,18 @@ private: static void* last_deleted_; - DISALLOW_COPY_AND_ASSIGN(TestProperty); +}; + +class TestCascadingProperty { + public: + explicit TestCascadingProperty(ui::PropertyHandler* handler) + : handler_(handler) {} + ~TestCascadingProperty() = default; + + ui::PropertyHandler* handler() { return handler_; } + + private: + ui::PropertyHandler* handler_; }; void* TestProperty::last_deleted_ = nullptr; @@ -66,11 +79,15 @@ DEFINE_OWNED_UI_CLASS_PROPERTY_KEY(AssignableTestProperty, kAssignableKey, nullptr) +DEFINE_CASCADING_OWNED_UI_CLASS_PROPERTY_KEY(TestCascadingProperty, + kCascadingOwnedKey, + nullptr) } // namespace DEFINE_UI_CLASS_PROPERTY_TYPE(TestProperty*) DEFINE_UI_CLASS_PROPERTY_TYPE(AssignableTestProperty*) +DEFINE_UI_CLASS_PROPERTY_TYPE(TestCascadingProperty*) namespace ui { namespace test { @@ -79,15 +96,20 @@ class TestPropertyHandler : public PropertyHandler { public: + TestPropertyHandler() = default; + explicit TestPropertyHandler(TestPropertyHandler* parent) : parent_(parent) {} + ~TestPropertyHandler() override = default; int num_events() const { return num_events_; } protected: void AfterPropertyChange(const void* key, int64_t old_value) override { ++num_events_; } + PropertyHandler* GetParentHandler() const override { return parent_; } private: int num_events_ = 0; + TestPropertyHandler* parent_ = nullptr; }; const int kDefaultIntValue = -2; @@ -133,24 +155,23 @@ { PropertyHandler h; - EXPECT_EQ(NULL, h.GetProperty(kOwnedKey)); + EXPECT_EQ(nullptr, h.GetProperty(kOwnedKey)); void* last_deleted = TestProperty::last_deleted(); - TestProperty* p1 = new TestProperty(); - h.SetProperty(kOwnedKey, p1); + TestProperty* p1 = + h.SetProperty(kOwnedKey, std::make_unique<TestProperty>()); EXPECT_EQ(p1, h.GetProperty(kOwnedKey)); EXPECT_EQ(last_deleted, TestProperty::last_deleted()); - TestProperty* p2 = new TestProperty(); - h.SetProperty(kOwnedKey, p2); + TestProperty* p2 = + h.SetProperty(kOwnedKey, std::make_unique<TestProperty>()); EXPECT_EQ(p2, h.GetProperty(kOwnedKey)); EXPECT_EQ(p1, TestProperty::last_deleted()); h.ClearProperty(kOwnedKey); - EXPECT_EQ(NULL, h.GetProperty(kOwnedKey)); + EXPECT_EQ(nullptr, h.GetProperty(kOwnedKey)); EXPECT_EQ(p2, TestProperty::last_deleted()); - p3 = new TestProperty(); - h.SetProperty(kOwnedKey, p3); + p3 = h.SetProperty(kOwnedKey, std::make_unique<TestProperty>()); EXPECT_EQ(p3, h.GetProperty(kOwnedKey)); EXPECT_EQ(p2, TestProperty::last_deleted()); } @@ -162,8 +183,8 @@ std::unique_ptr<PropertyHandler> src = std::make_unique<PropertyHandler>(); void* last_deleted = TestProperty::last_deleted(); EXPECT_FALSE(src->GetProperty(kOwnedKey)); - TestProperty* p1 = new TestProperty(); - src->SetProperty(kOwnedKey, p1); + TestProperty* p1 = + src->SetProperty(kOwnedKey, std::make_unique<TestProperty>()); src->SetProperty(kIntKey, INT_MAX); // dest will take ownership of the owned property. Existing properties with @@ -296,5 +317,21 @@ EXPECT_EQ(6, h.num_events()); } +TEST(PropertyTest, CascadingProperties) { + TestPropertyHandler h; + TestPropertyHandler h2(&h); + + // Set the property on the parent handler. + h.SetProperty(kCascadingOwnedKey, + std::make_unique<TestCascadingProperty>(&h)); + + // Get the property value from the child handler. + auto* value = h2.GetProperty(kCascadingOwnedKey); + + EXPECT_TRUE(value); + // The property value should have a reference to |h|. + EXPECT_EQ(&h, value->handler()); +} + } // namespace test } // namespace ui
diff --git a/ui/message_center/public/cpp/message_center_constants.h b/ui/message_center/public/cpp/message_center_constants.h index d3cf0a1..11d833f 100644 --- a/ui/message_center/public/cpp/message_center_constants.h +++ b/ui/message_center/public/cpp/message_center_constants.h
@@ -19,6 +19,7 @@ // Square image sizes in DIPs. const int kNotificationButtonIconSize = 16; const int kNotificationIconSize = 80; +const int kQuickSettingIconSizeInDp = 48; // A border is applied to images that have a non-preferred aspect ratio. const int kNotificationImageBorderSize = 10; const int kNotificationPreferredImageWidth = 360;
diff --git a/ui/ozone/platform/wayland/BUILD.gn b/ui/ozone/platform/wayland/BUILD.gn index e2f18a9..c0b0ec4 100644 --- a/ui/ozone/platform/wayland/BUILD.gn +++ b/ui/ozone/platform/wayland/BUILD.gn
@@ -391,6 +391,8 @@ "test/test_zwp_linux_buffer_params.h", "test/test_zwp_linux_explicit_synchronization.cc", "test/test_zwp_linux_explicit_synchronization.h", + "test/test_zwp_primary_selection.cc", + "test/test_zwp_primary_selection.h", "test/test_zwp_text_input_manager.cc", "test/test_zwp_text_input_manager.h", ]
diff --git a/ui/ozone/platform/wayland/host/wayland_data_drag_controller_unittest.cc b/ui/ozone/platform/wayland/host/wayland_data_drag_controller_unittest.cc index eaed1f56..779febc 100644 --- a/ui/ozone/platform/wayland/host/wayland_data_drag_controller_unittest.cc +++ b/ui/ozone/platform/wayland/host/wayland_data_drag_controller_unittest.cc
@@ -354,7 +354,8 @@ } TEST_P(WaylandDataDragControllerTest, ReceiveDrag) { - auto* data_offer = data_device_manager_->data_device()->OnDataOffer(); + auto* data_offer = + data_device_manager_->data_device()->CreateAndSendDataOffer(); data_offer->OnOffer(kMimeTypeText, ToClipboardData(std::string(kSampleTextForDragAndDrop))); @@ -393,7 +394,8 @@ } TEST_P(WaylandDataDragControllerTest, DropSeveralMimeTypes) { - auto* data_offer = data_device_manager_->data_device()->OnDataOffer(); + auto* data_offer = + data_device_manager_->data_device()->CreateAndSendDataOffer(); data_offer->OnOffer(kMimeTypeText, ToClipboardData(std::string(kSampleTextForDragAndDrop))); data_offer->OnOffer( @@ -447,7 +449,8 @@ {"/home/user/file", "/home/guest/file"}}}; for (const auto& kCase : kCases) { - auto* data_offer = data_device_manager_->data_device()->OnDataOffer(); + auto* data_offer = + data_device_manager_->data_device()->CreateAndSendDataOffer(); data_offer->OnOffer(kMimeTypeURIList, ToClipboardData(kCase.content)); EXPECT_CALL(*drop_handler_, MockOnDragEnter()).Times(1); @@ -500,7 +503,8 @@ "file:///files/are/ok", u"The policy allows that"}}; for (const auto& kCase : kCases) { - auto* data_offer = data_device_manager_->data_device()->OnDataOffer(); + auto* data_offer = + data_device_manager_->data_device()->CreateAndSendDataOffer(); data_offer->OnOffer(kMimeTypeMozillaURL, ToClipboardData(kCase.content)); EXPECT_CALL(*drop_handler_, MockOnDragEnter()).Times(1); @@ -555,7 +559,8 @@ } TEST_P(WaylandDataDragControllerTest, ForeignDragHandleAskAction) { - auto* data_offer = data_device_manager_->data_device()->OnDataOffer(); + auto* data_offer = + data_device_manager_->data_device()->CreateAndSendDataOffer(); data_offer->OnOffer(kMimeTypeText, ToClipboardData(std::string(kSampleTextForDragAndDrop))); data_offer->OnSourceActions(WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE |
diff --git a/ui/ozone/platform/wayland/test/test_data_device.cc b/ui/ozone/platform/wayland/test/test_data_device.cc index dface6c7..e2a8a8b 100644 --- a/ui/ozone/platform/wayland/test/test_data_device.cc +++ b/ui/ozone/platform/wayland/test/test_data_device.cc
@@ -13,6 +13,7 @@ #include "ui/ozone/platform/wayland/test/server_object.h" #include "ui/ozone/platform/wayland/test/test_data_offer.h" #include "ui/ozone/platform/wayland/test/test_data_source.h" +#include "ui/ozone/platform/wayland/test/test_selection_device_manager.h" namespace wl { @@ -31,34 +32,64 @@ origin_surface, serial); } -void DataDeviceSetSelection(wl_client* client, - wl_resource* resource, - wl_resource* data_source, - uint32_t serial) { - GetUserDataAs<TestDataDevice>(resource)->SetSelection( - data_source ? GetUserDataAs<TestDataSource>(data_source) : nullptr, - serial); -} - void DataDeviceRelease(wl_client* client, wl_resource* resource) { wl_resource_destroy(resource); } +struct WlDataDeviceImpl : public TestSelectionDevice::Delegate { + explicit WlDataDeviceImpl(TestDataDevice* device) : device_(device) {} + ~WlDataDeviceImpl() override = default; + + WlDataDeviceImpl(const WlDataDeviceImpl&) = delete; + WlDataDeviceImpl& operator=(const WlDataDeviceImpl&) = delete; + + TestSelectionOffer* CreateAndSendOffer() override { + wl_resource* device_resource = device_->resource(); + wl_resource* new_offer_resource = CreateResourceWithImpl<TestDataOffer>( + device_->client(), &wl_data_offer_interface, + wl_resource_get_version(device_resource), &kTestDataOfferImpl, 0); + wl_data_device_send_data_offer(device_resource, new_offer_resource); + return GetUserDataAs<TestSelectionOffer>(new_offer_resource); + } + + void HandleSetSelection(TestSelectionSource* source, + uint32_t serial) override { + device_->SetSelection(static_cast<TestDataSource*>(source), serial); + } + + void SendSelection(TestSelectionOffer* selection_offer) override { + CHECK(selection_offer); + wl_data_device_send_selection(device_->resource(), + selection_offer->resource()); + } + + void OnDestroying() override { delete this; } + + private: + TestDataDevice* const device_; +}; + } // namespace const struct wl_data_device_interface kTestDataDeviceImpl = { - &DataDeviceStartDrag, &DataDeviceSetSelection, &DataDeviceRelease}; + &DataDeviceStartDrag, &TestSelectionDevice::SetSelection, + &DataDeviceRelease}; TestDataDevice::TestDataDevice(wl_resource* resource, wl_client* client) - : ServerObject(resource), client_(client) {} + : TestSelectionDevice(resource, new WlDataDeviceImpl(this)), + client_(client) {} -TestDataDevice::~TestDataDevice() {} +TestDataDevice::~TestDataDevice() = default; void TestDataDevice::SetSelection(TestDataSource* data_source, uint32_t serial) { NOTIMPLEMENTED(); } +TestDataOffer* TestDataDevice::CreateAndSendDataOffer() { + return static_cast<TestDataOffer*>(TestSelectionDevice::OnDataOffer()); +} + void TestDataDevice::StartDrag(TestDataSource* source, MockSurface* origin, uint32_t serial) { @@ -69,16 +100,6 @@ wl_client_flush(client_); } -TestDataOffer* TestDataDevice::OnDataOffer() { - wl_resource* data_offer_resource = CreateResourceWithImpl<TestDataOffer>( - client_, &wl_data_offer_interface, wl_resource_get_version(resource()), - &kTestDataOfferImpl, 0); - data_offer_ = GetUserDataAs<TestDataOffer>(data_offer_resource); - wl_data_device_send_data_offer(resource(), data_offer_resource); - - return GetUserDataAs<TestDataOffer>(data_offer_resource); -} - void TestDataDevice::OnEnter(uint32_t serial, wl_resource* surface, wl_fixed_t x, @@ -100,8 +121,4 @@ wl_data_device_send_drop(resource()); } -void TestDataDevice::OnSelection(TestDataOffer* data_offer) { - wl_data_device_send_selection(resource(), data_offer->resource()); -} - } // namespace wl
diff --git a/ui/ozone/platform/wayland/test/test_data_device.h b/ui/ozone/platform/wayland/test/test_data_device.h index 1b8805c..41963b3 100644 --- a/ui/ozone/platform/wayland/test/test_data_device.h +++ b/ui/ozone/platform/wayland/test/test_data_device.h
@@ -11,7 +11,7 @@ #include "base/macros.h" #include "ui/ozone/platform/wayland/test/mock_surface.h" -#include "ui/ozone/platform/wayland/test/server_object.h" +#include "ui/ozone/platform/wayland/test/test_selection_device_manager.h" struct wl_client; struct wl_resource; @@ -23,7 +23,7 @@ class TestDataOffer; class TestDataSource; -class TestDataDevice : public ServerObject { +class TestDataDevice : public TestSelectionDevice { public: struct DragDelegate { virtual void StartDrag(TestDataSource* source, @@ -36,12 +36,12 @@ void set_drag_delegate(DragDelegate* delegate) { drag_delegate_ = delegate; } + TestDataOffer* CreateAndSendDataOffer(); void SetSelection(TestDataSource* data_source, uint32_t serial); void StartDrag(TestDataSource* data_source, MockSurface* origin, uint32_t serial); - TestDataOffer* OnDataOffer(); void OnEnter(uint32_t serial, wl_resource* surface, wl_fixed_t x, @@ -50,10 +50,10 @@ void OnLeave(); void OnMotion(uint32_t time, wl_fixed_t x, wl_fixed_t y); void OnDrop(); - void OnSelection(TestDataOffer* data_offer); + + wl_client* client() { return client_; } private: - TestDataOffer* data_offer_; wl_client* client_ = nullptr; DragDelegate* drag_delegate_ = nullptr;
diff --git a/ui/ozone/platform/wayland/test/test_data_device_manager.cc b/ui/ozone/platform/wayland/test/test_data_device_manager.cc index c26f4f4..e54efbf8 100644 --- a/ui/ozone/platform/wayland/test/test_data_device_manager.cc +++ b/ui/ozone/platform/wayland/test/test_data_device_manager.cc
@@ -45,6 +45,6 @@ &kTestDataDeviceManagerImpl, kDataDeviceManagerVersion) {} -TestDataDeviceManager::~TestDataDeviceManager() {} +TestDataDeviceManager::~TestDataDeviceManager() = default; } // namespace wl
diff --git a/ui/ozone/platform/wayland/test/test_data_offer.cc b/ui/ozone/platform/wayland/test/test_data_offer.cc index acedb732..fc3d268b 100644 --- a/ui/ozone/platform/wayland/test/test_data_offer.cc +++ b/ui/ozone/platform/wayland/test/test_data_offer.cc
@@ -14,6 +14,7 @@ #include "base/task/post_task.h" #include "base/task/task_traits.h" #include "base/task/thread_pool.h" +#include "ui/ozone/platform/wayland/test/test_selection_device_manager.h" namespace wl { @@ -57,6 +58,25 @@ preferred_action); } +struct WlDataOfferImpl : public TestSelectionOffer::Delegate { + explicit WlDataOfferImpl(TestDataOffer* offer) : offer_(offer) {} + ~WlDataOfferImpl() override = default; + + WlDataOfferImpl(const WlDataOfferImpl&) = delete; + WlDataOfferImpl& operator=(const WlDataOfferImpl&) = delete; + + void SendOffer(const std::string& mime_type, + ui::PlatformClipboard::Data data) override { + offer_->AddData(mime_type, data); + wl_data_offer_send_offer(offer_->resource(), mime_type.c_str()); + } + + void OnDestroying() override { delete this; } + + private: + TestDataOffer* const offer_; +}; + } // namespace const struct wl_data_offer_interface kTestDataOfferImpl = { @@ -64,12 +84,12 @@ DataOfferSetActions}; TestDataOffer::TestDataOffer(wl_resource* resource) - : ServerObject(resource), + : TestSelectionOffer(resource, new WlDataOfferImpl(this)), task_runner_( base::ThreadPool::CreateSequencedTaskRunner({base::MayBlock()})), write_data_weak_ptr_factory_(this) {} -TestDataOffer::~TestDataOffer() {} +TestDataOffer::~TestDataOffer() = default; void TestDataOffer::Receive(const std::string& mime_type, base::ScopedFD fd) { DCHECK(fd.is_valid()); @@ -79,12 +99,6 @@ data_to_offer_[mime_type])); } -void TestDataOffer::OnOffer(const std::string& mime_type, - ui::PlatformClipboard::Data data) { - data_to_offer_[mime_type] = data; - wl_data_offer_send_offer(resource(), mime_type.c_str()); -} - void TestDataOffer::SetActions(uint32_t dnd_actions, uint32_t preferred_action) { client_supported_actions_ = dnd_actions; @@ -100,4 +114,9 @@ wl_data_offer_send_action(resource(), dnd_action); } +void TestDataOffer::AddData(const std::string& mime_type, + ui::PlatformClipboard::Data data) { + data_to_offer_[mime_type] = data; +} + } // namespace wl
diff --git a/ui/ozone/platform/wayland/test/test_data_offer.h b/ui/ozone/platform/wayland/test/test_data_offer.h index 77c389c..31cda30 100644 --- a/ui/ozone/platform/wayland/test/test_data_offer.h +++ b/ui/ozone/platform/wayland/test/test_data_offer.h
@@ -14,7 +14,7 @@ #include "base/macros.h" #include "base/memory/weak_ptr.h" #include "base/threading/thread.h" -#include "ui/ozone/platform/wayland/test/server_object.h" +#include "ui/ozone/platform/wayland/test/test_selection_device_manager.h" #include "ui/ozone/public/platform_clipboard.h" struct wl_resource; @@ -27,13 +27,12 @@ extern const struct wl_data_offer_interface kTestDataOfferImpl; -class TestDataOffer : public ServerObject { +class TestDataOffer : public TestSelectionOffer { public: explicit TestDataOffer(wl_resource* resource); ~TestDataOffer() override; void Receive(const std::string& mime_type, base::ScopedFD fd); - void OnOffer(const std::string& mime_type, ui::PlatformClipboard::Data data); void SetActions(uint32_t dnd_actions, uint32_t preferred_action); void OnSourceActions(uint32_t source_actions); @@ -42,6 +41,8 @@ uint32_t supported_actions() const { return client_supported_actions_; } uint32_t preferred_action() const { return client_preferred_action_; } + void AddData(const std::string& mime_type, ui::PlatformClipboard::Data data); + private: const scoped_refptr<base::SequencedTaskRunner> task_runner_; ui::PlatformClipboard::DataMap data_to_offer_;
diff --git a/ui/ozone/platform/wayland/test/test_data_source.cc b/ui/ozone/platform/wayland/test/test_data_source.cc index 28acb1f..505f97c 100644 --- a/ui/ozone/platform/wayland/test/test_data_source.cc +++ b/ui/ozone/platform/wayland/test/test_data_source.cc
@@ -18,6 +18,7 @@ #include "base/task/task_traits.h" #include "base/task/thread_pool.h" #include "base/task_runner_util.h" +#include "ui/ozone/platform/wayland/test/test_selection_device_manager.h" namespace wl { @@ -42,12 +43,6 @@ return bytes; } -void DataSourceOffer(wl_client* client, - wl_resource* resource, - const char* mime_type) { - GetUserDataAs<TestDataSource>(resource)->Offer(mime_type); -} - void DataSourceDestroy(wl_client* client, wl_resource* resource) { wl_resource_destroy(resource); } @@ -58,13 +53,30 @@ GetUserDataAs<TestDataSource>(resource)->SetActions(dnd_actions); } +struct WlDataSourceImpl : public TestSelectionSource::Delegate { + explicit WlDataSourceImpl(TestDataSource* offer) : source_(offer) {} + ~WlDataSourceImpl() override = default; + + WlDataSourceImpl(const WlDataSourceImpl&) = delete; + WlDataSourceImpl& operator=(const WlDataSourceImpl&) = delete; + + void HandleOffer(const std::string& mime_type) override { + source_->Offer(mime_type); + } + + void OnDestroying() override { delete this; } + + private: + TestDataSource* const source_; +}; + } // namespace const struct wl_data_source_interface kTestDataSourceImpl = { - DataSourceOffer, DataSourceDestroy, DataSourceSetActions}; + TestSelectionSource::Offer, DataSourceDestroy, DataSourceSetActions}; TestDataSource::TestDataSource(wl_resource* resource) - : ServerObject(resource), + : TestSelectionSource(resource, new WlDataSourceImpl(this)), task_runner_( base::ThreadPool::CreateSequencedTaskRunner({base::MayBlock()})) {}
diff --git a/ui/ozone/platform/wayland/test/test_data_source.h b/ui/ozone/platform/wayland/test/test_data_source.h index bcf66c3..2bef4f27 100644 --- a/ui/ozone/platform/wayland/test/test_data_source.h +++ b/ui/ozone/platform/wayland/test/test_data_source.h
@@ -15,7 +15,7 @@ #include "base/callback_forward.h" #include "base/macros.h" #include "base/memory/weak_ptr.h" -#include "ui/ozone/platform/wayland/test/server_object.h" +#include "ui/ozone/platform/wayland/test/test_selection_device_manager.h" struct wl_resource; @@ -27,7 +27,7 @@ extern const struct wl_data_source_interface kTestDataSourceImpl; -class TestDataSource : public ServerObject { +class TestDataSource : public TestSelectionSource { public: explicit TestDataSource(wl_resource* resource); ~TestDataSource() override;
diff --git a/ui/ozone/platform/wayland/test/test_selection_device_manager.cc b/ui/ozone/platform/wayland/test/test_selection_device_manager.cc index e697806..92c0cb3 100644 --- a/ui/ozone/platform/wayland/test/test_selection_device_manager.cc +++ b/ui/ozone/platform/wayland/test/test_selection_device_manager.cc
@@ -12,90 +12,87 @@ namespace wl { -namespace { +// TestSelectionOffer implementation. +TestSelectionOffer::TestSelectionOffer(wl_resource* resource, + Delegate* delegate) + : ServerObject(resource), delegate_(delegate) {} -void Destroy(wl_client* client, wl_resource* resource) { - wl_resource_destroy(resource); +TestSelectionOffer::~TestSelectionOffer() { + delegate_->OnDestroying(); } -} // namespace +void TestSelectionOffer::OnOffer(const std::string& mime_type, + ui::PlatformClipboard::Data data) { + delegate_->SendOffer(mime_type, data); +} -const struct zwp_primary_selection_device_manager_v1_interface - TestSelectionDeviceManager::kTestSelectionManagerImpl = { - &CreateSource, &GetDevice, &Destroy}; - -// TODO(crbug.com/1204670): Implement primary selection offer. -struct TestSelectionOffer : public ServerObject { - explicit TestSelectionOffer(wl_resource* resource) : ServerObject(resource) {} - ~TestSelectionOffer() override = default; -}; - -TestSelectionSource::TestSelectionSource(wl_resource* resource) - : ServerObject(resource) {} +// TestSelectionSource implementation. +TestSelectionSource::TestSelectionSource(wl_resource* resource, + Delegate* delegate) + : ServerObject(resource), delegate_(delegate) {} TestSelectionSource::~TestSelectionSource() = default; -// TODO(crbug.com/1204670): Implement primary selection source. void TestSelectionSource::Offer(struct wl_client* client, struct wl_resource* resource, const char* mime_type) { - NOTIMPLEMENTED(); + CHECK(GetUserDataAs<TestSelectionSource>(resource)); + auto* self = GetUserDataAs<TestSelectionSource>(resource); + self->delegate_->HandleOffer(mime_type); } +// TestSelectionDevice implementation. TestSelectionDevice::TestSelectionDevice(wl_resource* resource, - wl_client* client) - : ServerObject(resource) {} + Delegate* delegate) + : ServerObject(resource), delegate_(delegate) {} -TestSelectionDevice::~TestSelectionDevice() = default; - -void TestSelectionDevice::SendSelectionOffer( - const ui::PlatformClipboard::DataMap& data_map) { - NOTIMPLEMENTED(); +TestSelectionDevice::~TestSelectionDevice() { + delegate_->OnDestroying(); } -// TODO(crbug.com/1204670): Implement primary selection device. +TestSelectionOffer* TestSelectionDevice::OnDataOffer() { + return delegate_->CreateAndSendOffer(); +} + +void TestSelectionDevice::OnSelection(TestSelectionOffer* offer) { + delegate_->SendSelection(offer); +} + void TestSelectionDevice::SetSelection(struct wl_client* client, struct wl_resource* resource, struct wl_resource* source, uint32_t serial) { - NOTIMPLEMENTED(); + CHECK(GetUserDataAs<TestSelectionDevice>(resource)); + auto* self = GetUserDataAs<TestSelectionDevice>(resource); + auto* src = source ? GetUserDataAs<TestSelectionSource>(source) : nullptr; + self->delegate_->HandleSetSelection(src, serial); } -TestSelectionDeviceManager::TestSelectionDeviceManager() - : GlobalObject(&zwp_primary_selection_device_manager_v1_interface, - &kTestSelectionManagerImpl, - 1) {} +TestSelectionDeviceManager::TestSelectionDeviceManager( + const InterfaceInfo& info, + Delegate* delegate) + : GlobalObject(info.interface, info.implementation, info.version), + delegate_(delegate) {} -TestSelectionDeviceManager::~TestSelectionDeviceManager() = default; +TestSelectionDeviceManager::~TestSelectionDeviceManager() { + delegate_->OnDestroying(); +} void TestSelectionDeviceManager::CreateSource(wl_client* client, wl_resource* manager_resource, uint32_t id) { - const struct zwp_primary_selection_source_v1_interface - kTestSelectionSourceImpl = {&TestSelectionSource::Offer, &Destroy}; - wl_resource* source_resource = CreateResourceWithImpl<TestSelectionSource>( - client, &zwp_primary_selection_source_v1_interface, - wl_resource_get_version(manager_resource), &kTestSelectionSourceImpl, id); - + CHECK(GetUserDataAs<TestSelectionDeviceManager>(manager_resource)); auto* manager = GetUserDataAs<TestSelectionDeviceManager>(manager_resource); - CHECK(manager); - manager->source_ = GetUserDataAs<TestSelectionSource>(source_resource); + manager->source_ = manager->delegate_->CreateSource(client, id); } void TestSelectionDeviceManager::GetDevice(wl_client* client, wl_resource* manager_resource, uint32_t id, wl_resource* seat_resource) { - const struct zwp_primary_selection_device_v1_interface - kTestSelectionDeviceImpl = {&TestSelectionDevice::SetSelection, &Destroy}; - wl_resource* resource = CreateResourceWithImpl<TestSelectionDevice>( - client, &zwp_primary_selection_device_v1_interface, - wl_resource_get_version(manager_resource), &kTestSelectionDeviceImpl, id, - client); - + CHECK(GetUserDataAs<TestSelectionDeviceManager>(manager_resource)); auto* manager = GetUserDataAs<TestSelectionDeviceManager>(manager_resource); - CHECK(manager); - manager->device_ = GetUserDataAs<TestSelectionDevice>(resource); + manager->device_ = manager->delegate_->CreateDevice(client, id); } } // namespace wl
diff --git a/ui/ozone/platform/wayland/test/test_selection_device_manager.h b/ui/ozone/platform/wayland/test/test_selection_device_manager.h index 2f84120..50d8eab 100644 --- a/ui/ozone/platform/wayland/test/test_selection_device_manager.h +++ b/ui/ozone/platform/wayland/test/test_selection_device_manager.h
@@ -5,9 +5,8 @@ #ifndef UI_OZONE_PLATFORM_WAYLAND_TEST_TEST_SELECTION_DEVICE_MANAGER_H_ #define UI_OZONE_PLATFORM_WAYLAND_TEST_TEST_SELECTION_DEVICE_MANAGER_H_ -#include <primary-selection-unstable-v1-server-protocol.h> - #include <cstdint> +#include <string> #include "ui/ozone/platform/wayland/test/global_object.h" #include "ui/ozone/platform/wayland/test/server_object.h" @@ -18,10 +17,31 @@ class TestSelectionSource; class TestSelectionDevice; -// Manage wl_data_device_manager object. +// Base classes for data device implementations. Protocol specific derived +// classes must bind request handlers and factory methods for data device and +// source instances. E.g: Standard data device (wl_data_*), as well as zwp and +// gtk primary selection protocols. + class TestSelectionDeviceManager : public GlobalObject { public: - TestSelectionDeviceManager(); + struct Delegate { + virtual TestSelectionDevice* CreateDevice(wl_client* client, + uint32_t id) = 0; + virtual TestSelectionSource* CreateSource(wl_client* client, + uint32_t id) = 0; + virtual void OnDestroying() = 0; + + protected: + virtual ~Delegate() = default; + }; + + struct InterfaceInfo { + const struct wl_interface* interface; + const void* implementation; + uint32_t version; + }; + + TestSelectionDeviceManager(const InterfaceInfo& info, Delegate* delegate); ~TestSelectionDeviceManager() override; TestSelectionDeviceManager(const TestSelectionDeviceManager&) = delete; @@ -31,7 +51,6 @@ const TestSelectionDevice* device() const { return device_; } const TestSelectionSource* source() const { return source_; } - private: // Protocol object requests: static void CreateSource(wl_client* client, wl_resource* manager_resource, @@ -41,42 +60,88 @@ uint32_t id, wl_resource* seat_resource); + private: + Delegate* const delegate_; + TestSelectionDevice* device_ = nullptr; TestSelectionSource* source_ = nullptr; +}; - static const struct zwp_primary_selection_device_manager_v1_interface - kTestSelectionManagerImpl; +class TestSelectionOffer : public ServerObject { + public: + struct Delegate { + virtual void SendOffer(const std::string& mime_type, + ui::PlatformClipboard::Data data) = 0; + virtual void OnDestroying() = 0; + + protected: + virtual ~Delegate() = default; + }; + + TestSelectionOffer(wl_resource* resource, Delegate* delegate); + ~TestSelectionOffer() override; + + TestSelectionOffer(const TestSelectionOffer&) = delete; + TestSelectionOffer& operator=(const TestSelectionOffer&) = delete; + + void OnOffer(const std::string& mime_type, ui::PlatformClipboard::Data data); + + private: + Delegate* const delegate_; }; class TestSelectionSource : public ServerObject { public: - explicit TestSelectionSource(wl_resource* resource); - ~TestSelectionSource() override; + struct Delegate { + virtual void HandleOffer(const std::string& mime_type) = 0; + virtual void OnDestroying() = 0; - private: - friend class TestSelectionDeviceManager; + protected: + virtual ~Delegate() = default; + }; + + TestSelectionSource(wl_resource* resource, Delegate* delegate); + ~TestSelectionSource() override; // Protocol object requests: static void Offer(struct wl_client* client, struct wl_resource* resource, const char* mime_type); + + private: + Delegate* const delegate_; }; class TestSelectionDevice : public ServerObject { public: - TestSelectionDevice(wl_resource* resource, wl_client* client); + struct Delegate { + virtual TestSelectionOffer* CreateAndSendOffer() = 0; + virtual void SendSelection(TestSelectionOffer* offer) = 0; + virtual void HandleSetSelection(TestSelectionSource* source, + uint32_t serial) = 0; + virtual void OnDestroying() = 0; + + protected: + virtual ~Delegate() = default; + }; + + TestSelectionDevice(wl_resource* resource, Delegate* delegate); ~TestSelectionDevice() override; - void SendSelectionOffer(const ui::PlatformClipboard::DataMap& data_map); + TestSelectionDevice(const TestSelectionDevice&) = delete; + TestSelectionDevice& operator=(const TestSelectionDevice&) = delete; - private: - friend class TestSelectionDeviceManager; + TestSelectionOffer* OnDataOffer(); + void OnSelection(TestSelectionOffer* offer); // Protocol object requests: static void SetSelection(struct wl_client* client, struct wl_resource* resource, struct wl_resource* source, uint32_t serial); + + private: + Delegate* const delegate_; }; } // namespace wl
diff --git a/ui/ozone/platform/wayland/test/test_wayland_server_thread.cc b/ui/ozone/platform/wayland/test/test_wayland_server_thread.cc index 72bd2ee1..e33858d 100644 --- a/ui/ozone/platform/wayland/test/test_wayland_server_thread.cc +++ b/ui/ozone/platform/wayland/test/test_wayland_server_thread.cc
@@ -17,6 +17,7 @@ #include "base/run_loop.h" #include "base/strings/string_number_conversions.h" #include "base/task_runner_util.h" +#include "ui/ozone/platform/wayland/test/test_zwp_primary_selection.h" namespace wl { @@ -71,7 +72,9 @@ if (!data_device_manager_.Initialize(display_.get())) return false; if (config.primary_selection_protocol != PrimarySelectionProtocol::kNone) { - if (!selection_device_manager_.Initialize(display_.get())) + // TODO(crbug.com/1204670): Support gtk primary selection. + primary_selection_device_manager_.reset(CreateTestSelectionManagerZwp()); + if (!primary_selection_device_manager_->Initialize(display_.get())) return false; } if (!seat_.Initialize(display_.get()))
diff --git a/ui/ozone/platform/wayland/test/test_wayland_server_thread.h b/ui/ozone/platform/wayland/test/test_wayland_server_thread.h index 5c6ff13..6b94e7f 100644 --- a/ui/ozone/platform/wayland/test/test_wayland_server_thread.h +++ b/ui/ozone/platform/wayland/test/test_wayland_server_thread.h
@@ -22,7 +22,6 @@ #include "ui/ozone/platform/wayland/test/test_data_device_manager.h" #include "ui/ozone/platform/wayland/test/test_output.h" #include "ui/ozone/platform/wayland/test/test_seat.h" -#include "ui/ozone/platform/wayland/test/test_selection_device_manager.h" #include "ui/ozone/platform/wayland/test/test_subcompositor.h" #include "ui/ozone/platform/wayland/test/test_viewporter.h" #include "ui/ozone/platform/wayland/test/test_zwp_linux_explicit_synchronization.h" @@ -49,6 +48,8 @@ PrimarySelectionProtocol::kNone; }; +class TestSelectionDeviceManager; + class TestWaylandServerThread : public base::Thread, base::MessagePumpLibevent::FdWatcher { public: @@ -139,7 +140,7 @@ TestZwpLinuxExplicitSynchronizationV1 zwp_linux_explicit_synchronization_v1_; MockZwpLinuxDmabufV1 zwp_linux_dmabuf_v1_; MockWpPresentation wp_presentation_; - TestSelectionDeviceManager selection_device_manager_; + std::unique_ptr<TestSelectionDeviceManager> primary_selection_device_manager_; std::vector<std::unique_ptr<GlobalObject>> globals_;
diff --git a/ui/ozone/platform/wayland/test/test_zwp_primary_selection.cc b/ui/ozone/platform/wayland/test/test_zwp_primary_selection.cc new file mode 100644 index 0000000..5c25fa50 --- /dev/null +++ b/ui/ozone/platform/wayland/test/test_zwp_primary_selection.cc
@@ -0,0 +1,103 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ui/ozone/platform/wayland/test/test_zwp_primary_selection.h" + +#include <primary-selection-unstable-v1-server-protocol.h> +#include <wayland-server-core.h> + +#include <cstdint> + +#include "base/notreached.h" +#include "ui/ozone/platform/wayland/test/test_selection_device_manager.h" + +// TODO(crbug.com/1204670): Implement zwp primary selection support. + +namespace wl { + +namespace { + +void Destroy(wl_client* client, wl_resource* resource) { + wl_resource_destroy(resource); +} + +struct ZwpPrimarySelectionOffer : public TestSelectionOffer::Delegate { + void SendOffer(const std::string& mime_type, + ui::PlatformClipboard::Data data) override { + NOTIMPLEMENTED(); + } + + void OnDestroying() override { NOTIMPLEMENTED(); } +}; + +struct ZwpPrimarySelectionDevice : public TestSelectionDevice::Delegate { + TestSelectionOffer* CreateAndSendOffer() override { + NOTIMPLEMENTED(); + return nullptr; + } + + void SendSelection(TestSelectionOffer* offer) override { NOTIMPLEMENTED(); } + + void HandleSetSelection(TestSelectionSource* source, + uint32_t serial) override { + NOTIMPLEMENTED(); + } + + void OnDestroying() override { NOTIMPLEMENTED(); } +}; + +struct ZwpPrimarySelectionSource : public TestSelectionSource::Delegate { + void HandleOffer(const std::string& mime_type) override { NOTIMPLEMENTED(); } + + void OnDestroying() override { NOTIMPLEMENTED(); } +}; + +struct ZwpPrimarySelectionDeviceManager + : public TestSelectionDeviceManager::Delegate { + explicit ZwpPrimarySelectionDeviceManager(uint32_t version) + : version_(version) {} + ~ZwpPrimarySelectionDeviceManager() override = default; + + TestSelectionDevice* CreateDevice(wl_client* client, uint32_t id) override { + const struct zwp_primary_selection_device_v1_interface + kTestSelectionDeviceImpl = {&TestSelectionDevice::SetSelection, + &Destroy}; + wl_resource* resource = CreateResourceWithImpl<TestSelectionDevice>( + client, &zwp_primary_selection_device_v1_interface, version_, + &kTestSelectionDeviceImpl, id, new ZwpPrimarySelectionDevice); + return GetUserDataAs<TestSelectionDevice>(resource); + } + + TestSelectionSource* CreateSource(wl_client* client, uint32_t id) override { + const struct zwp_primary_selection_source_v1_interface + kTestSelectionSourceImpl = {&TestSelectionSource::Offer, &Destroy}; + wl_resource* resource = CreateResourceWithImpl<TestSelectionSource>( + client, &zwp_primary_selection_source_v1_interface, version_, + &kTestSelectionSourceImpl, id, new ZwpPrimarySelectionSource); + return GetUserDataAs<TestSelectionSource>(resource); + } + + void OnDestroying() override { delete this; } + + private: + const uint32_t version_; +}; + +} // namespace + +TestSelectionDeviceManager* CreateTestSelectionManagerZwp() { + constexpr uint32_t kVersion = 1; + const struct zwp_primary_selection_device_manager_v1_interface + kTestSelectionManagerImpl = {&TestSelectionDeviceManager::CreateSource, + &TestSelectionDeviceManager::GetDevice, + &Destroy}; + const TestSelectionDeviceManager::InterfaceInfo interface_info = { + .interface = &zwp_primary_selection_device_manager_v1_interface, + .implementation = &kTestSelectionManagerImpl, + .version = kVersion}; + return new TestSelectionDeviceManager( + interface_info, new ZwpPrimarySelectionDeviceManager(kVersion)); +} + +} // namespace wl
diff --git a/ui/ozone/platform/wayland/test/test_zwp_primary_selection.h b/ui/ozone/platform/wayland/test/test_zwp_primary_selection.h new file mode 100644 index 0000000..e957552 --- /dev/null +++ b/ui/ozone/platform/wayland/test/test_zwp_primary_selection.h
@@ -0,0 +1,15 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef UI_OZONE_PLATFORM_WAYLAND_TEST_TEST_ZWP_PRIMARY_SELECTION_H_ +#define UI_OZONE_PLATFORM_WAYLAND_TEST_TEST_ZWP_PRIMARY_SELECTION_H_ + +#include "ui/ozone/platform/wayland/test/test_selection_device_manager.h" +namespace wl { + +TestSelectionDeviceManager* CreateTestSelectionManagerZwp(); + +} + +#endif // UI_OZONE_PLATFORM_WAYLAND_TEST_TEST_ZWP_PRIMARY_SELECTION_H_
diff --git a/ui/platform_window/stub/BUILD.gn b/ui/platform_window/stub/BUILD.gn index fd53cfe..f5e805e8 100644 --- a/ui/platform_window/stub/BUILD.gn +++ b/ui/platform_window/stub/BUILD.gn
@@ -7,6 +7,7 @@ deps = [ "//base", + "//ui/base", "//ui/gfx", "//ui/gfx/geometry", "//ui/platform_window",
diff --git a/ui/views/controls/color_tracking_icon_view.cc b/ui/views/controls/color_tracking_icon_view.cc index 1d08463..d7c3ded 100644 --- a/ui/views/controls/color_tracking_icon_view.cc +++ b/ui/views/controls/color_tracking_icon_view.cc
@@ -5,23 +5,25 @@ #include "ui/views/controls/color_tracking_icon_view.h" #include "ui/gfx/paint_vector_icon.h" -#include "ui/native_theme/native_theme.h" namespace views { -ColorTrackingIconView::ColorTrackingIconView(const gfx::VectorIcon& icon, - int icon_size) - : icon_(icon), icon_size_(icon_size) { - // Set the image using a placeholder color. This will allow the ImageView to - // report its preferred size before OnThemeChanged for layout purposes. - SetImage(gfx::CreateVectorIcon(icon_, icon_size_, gfx::kPlaceholderColor)); +ColorTrackingIconView::ColorTrackingIconView( + const gfx::VectorIcon& icon, + int icon_size, + ui::NativeTheme::ColorId icon_color_id) + : icon_(icon), icon_size_(icon_size), icon_color_id_(icon_color_id) { + // Set the image using the color generated from icon_color_id_. This will + // allow the ImageView to report its preferred size before OnThemeChanged for + // layout purposes. + SetImage(gfx::CreateVectorIcon( + icon_, icon_size_, GetNativeTheme()->GetSystemColor(icon_color_id_))); } void ColorTrackingIconView::OnThemeChanged() { ImageView::OnThemeChanged(); - const SkColor color = GetNativeTheme()->GetSystemColor( - ui::NativeTheme::kColorId_DefaultIconColor); - SetImage(gfx::CreateVectorIcon(icon_, icon_size_, color)); + SetImage(gfx::CreateVectorIcon( + icon_, icon_size_, GetNativeTheme()->GetSystemColor(icon_color_id_))); } } // namespace views
diff --git a/ui/views/controls/color_tracking_icon_view.h b/ui/views/controls/color_tracking_icon_view.h index 4ab7a54..40525f28 100644 --- a/ui/views/controls/color_tracking_icon_view.h +++ b/ui/views/controls/color_tracking_icon_view.h
@@ -5,6 +5,7 @@ #ifndef UI_VIEWS_CONTROLS_COLOR_TRACKING_ICON_VIEW_H_ #define UI_VIEWS_CONTROLS_COLOR_TRACKING_ICON_VIEW_H_ +#include "ui/native_theme/native_theme.h" #include "ui/views/controls/image_view.h" namespace gfx { @@ -17,7 +18,10 @@ // icon is always the correct color. class VIEWS_EXPORT ColorTrackingIconView : public ImageView { public: - ColorTrackingIconView(const gfx::VectorIcon& icon, int icon_size); + ColorTrackingIconView(const gfx::VectorIcon& icon, + int icon_size, + ui::NativeTheme::ColorId icon_color_id = + ui::NativeTheme::kColorId_DefaultIconColor); // ImageView: void OnThemeChanged() override; @@ -25,6 +29,7 @@ private: const gfx::VectorIcon& icon_; const int icon_size_; + const ui::NativeTheme::ColorId icon_color_id_; }; } // namespace views
diff --git a/weblayer/browser/content_browser_client_impl.cc b/weblayer/browser/content_browser_client_impl.cc index f33ce3c..0c76aaf6 100644 --- a/weblayer/browser/content_browser_client_impl.cc +++ b/weblayer/browser/content_browser_client_impl.cc
@@ -902,6 +902,16 @@ return true; } + if (interface_name == + subresource_filter::mojom::SubresourceFilterHost::Name_) { + subresource_filter::ContentSubresourceFilterThrottleManager::BindReceiver( + mojo::PendingAssociatedReceiver< + subresource_filter::mojom::SubresourceFilterHost>( + std::move(*handle)), + render_frame_host); + return true; + } + return false; }