diff --git a/DEPS b/DEPS index 195044b..7b0821f 100644 --- a/DEPS +++ b/DEPS
@@ -178,11 +178,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': '4e9cfe7691dda3ca829e4cf7fef49a25f0c4f3f2', + 'skia_revision': '00ddb0029da729c4cb456d5fe39f4a65c8531ca2', # 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': '13387c560ef69e6c40088f04b9397f5e765766ee', + 'v8_revision': 'd58488c28be7c9115cd4e4ed2d752102f11c952d', # 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. @@ -190,7 +190,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ANGLE # and whatever else without interference from each other. - 'angle_revision': '9823d86a5a400418277777bad7d78006a4cd2ef1', + 'angle_revision': '3d598abb3014f0e10a4565a4fb01556e4152ffef', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling SwiftShader # and whatever else without interference from each other. @@ -198,7 +198,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling PDFium # and whatever else without interference from each other. - 'pdfium_revision': '3ea38438da69868f33aac23ce7d1b3575479fb0a', + 'pdfium_revision': '2acdf79f9eef6c65ea4e2f546454c4c562d45588', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling BoringSSL # and whatever else without interference from each other. @@ -229,7 +229,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': '093f87bfe45160195ade7bd5174bbaaf50ebd6be', + 'freetype_revision': '3f70e6d20c82b28174096adcd0657b3c998b007b', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling HarfBuzz # and whatever else without interference from each other. @@ -241,7 +241,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': 'ed728376c1a8e8b8a689cd22d7fe953a634c9d5e', + 'catapult_revision': 'be5a62acfa44dd850da59380af898ffc64483a93', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # and whatever else without interference from each other. @@ -249,7 +249,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling devtools-frontend # and whatever else without interference from each other. - 'devtools_frontend_revision': '568858e7437c6cfbd54efb492a5c31685c7822c3', + 'devtools_frontend_revision': '32b1b68d990ee2c1ceb41109ae19a4a2354e4a2b', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libprotobuf-mutator # and whatever else without interference from each other. @@ -293,7 +293,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. - 'spirv_cross_revision': '7e0295abf81cc939ecb2644c88592d77407d18d3', + 'spirv_cross_revision': 'd638d2df9c8c4a862e0af829cf49cc6dcbb235a2', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. @@ -524,7 +524,7 @@ }, 'src/ios/third_party/material_components_ios/src': { - 'url': Var('chromium_git') + '/external/github.com/material-components/material-components-ios.git' + '@' + '459066d00ee638e32b6c46ed05fa7242ed524ae3', + 'url': Var('chromium_git') + '/external/github.com/material-components/material-components-ios.git' + '@' + '996ef4e29110ef6da9a34771687235a965c18072', 'condition': 'checkout_ios', }, @@ -927,7 +927,7 @@ Var('chromium_git') + '/codecs/libgav1.git' + '@' + '638ef84819f8b3cd614dcf63378fe4814aa4cb2a', 'src/third_party/glslang/src': - Var('chromium_git') + '/external/github.com/KhronosGroup/glslang.git' + '@' + '55f9d97f3b1e2b9d0a5f015a3075512f698e1efa', + Var('chromium_git') + '/external/github.com/KhronosGroup/glslang.git' + '@' + '4fa68edd68197a8c77779942b5d973f89c621752', 'src/third_party/google_toolbox_for_mac/src': { 'url': Var('chromium_git') + '/external/github.com/google/google-toolbox-for-mac.git' + '@' + Var('google_toolbox_for_mac_revision'), @@ -1220,7 +1220,7 @@ }, 'src/third_party/perfetto': - Var('android_git') + '/platform/external/perfetto.git' + '@' + '237c0fa4e1f0ff06ab4573cb9010e746fb32b1bd', + Var('android_git') + '/platform/external/perfetto.git' + '@' + 'd4e0aadfce0df20f5b006c952205e71e9cfe4dde', 'src/third_party/perl': { 'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3', @@ -1298,7 +1298,7 @@ 'packages': [ { 'package': 'fuchsia/third_party/aemu/linux-amd64', - 'version': '5LzaFiFYMxwWXcgus5JjF74yr90M5oz9IMo29pTdoLgC' + 'version': 'k9-kEftX16LlRF3TNODWTs4uqKfXXrwIK3wkb2CNnbsC' }, ], 'condition': 'host_os == "linux" and checkout_fuchsia', @@ -1453,7 +1453,7 @@ }, 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + '1c330752579e584561fc1cb88cc76d1905d22375', + Var('webrtc_git') + '/src.git' + '@' + 'b0bd0708d6542ce837d0499975fab7b22d2fad20', 'src/third_party/libgifcodec': Var('skia_git') + '/libgifcodec' + '@'+ Var('libgifcodec_revision'), @@ -1525,7 +1525,7 @@ Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'), 'src-internal': { - 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@e76c18d893de41a79c30318984af1df7deffb43f', + 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@568a908f7b188abb0a47e59e101e701df6f780df', 'condition': 'checkout_src_internal', },
diff --git a/android_webview/browser/aw_content_browser_client.cc b/android_webview/browser/aw_content_browser_client.cc index 2393b51..856b07f 100644 --- a/android_webview/browser/aw_content_browser_client.cc +++ b/android_webview/browser/aw_content_browser_client.cc
@@ -448,9 +448,11 @@ return rb.GetImageNamed(IDR_DEFAULT_FAVICON).AsImageSkia(); } -bool AwContentBrowserClient::AllowAppCache(const GURL& manifest_url, - const GURL& first_party, - content::BrowserContext* context) { +bool AwContentBrowserClient::AllowAppCache( + const GURL& manifest_url, + const GURL& site_for_cookies, + const base::Optional<url::Origin>& top_frame_origin, + content::BrowserContext* context) { // WebView doesn't have a per-site policy for locally stored data, // instead AppCache can be disabled for individual WebViews. return true;
diff --git a/android_webview/browser/aw_content_browser_client.h b/android_webview/browser/aw_content_browser_client.h index 32d5be9b..fb6dc56 100644 --- a/android_webview/browser/aw_content_browser_client.h +++ b/android_webview/browser/aw_content_browser_client.h
@@ -78,7 +78,8 @@ std::string GetAcceptLangs(content::BrowserContext* context) override; gfx::ImageSkia GetDefaultFavicon() override; bool AllowAppCache(const GURL& manifest_url, - const GURL& first_party, + const GURL& site_for_cookies, + const base::Optional<url::Origin>& top_frame_origin, content::BrowserContext* context) override; scoped_refptr<content::QuotaPermissionContext> CreateQuotaPermissionContext() override;
diff --git a/ash/public/cpp/login_types.h b/ash/public/cpp/login_types.h index b8b71255..67dda195 100644 --- a/ash/public/cpp/login_types.h +++ b/ash/public/cpp/login_types.h
@@ -273,7 +273,7 @@ // True if the display password button should be visible on the login/lock // screen for this user. - bool show_display_password_button = true; + bool show_display_password_button = false; // Contains the public account information if user type is PUBLIC_ACCOUNT. base::Optional<PublicAccountInfo> public_account_info;
diff --git a/base/BUILD.gn b/base/BUILD.gn index 3a3091a..6c36c61 100644 --- a/base/BUILD.gn +++ b/base/BUILD.gn
@@ -2972,7 +2972,8 @@ if (current_cpu == "arm") { sources += [ "profiler/chrome_unwinder_android_unittest.cc" ] } - if (current_cpu == "arm" || current_cpu == "arm64") { + if (!exclude_unwind_tables && + (current_cpu == "arm" || current_cpu == "arm64")) { sources += [ "profiler/native_unwinder_android_unittest.cc" ] include_dirs = [ "//third_party/libunwindstack/src/libunwindstack/include" ]
diff --git a/base/threading/hang_watcher_unittest.cc b/base/threading/hang_watcher_unittest.cc index 15d43763..4a6033f 100644 --- a/base/threading/hang_watcher_unittest.cc +++ b/base/threading/hang_watcher_unittest.cc
@@ -486,7 +486,8 @@ // If the HangWatcher detects it slept for longer than expected it will not // monitor. -TEST_F(HangWatcherPeriodicMonitoringTest, NoMonitorOnOverSleep) { +// TODO(crbug.com/1081654): Test flaky on ChromeOS. +TEST_F(HangWatcherPeriodicMonitoringTest, DISABLED_NoMonitorOnOverSleep) { RunLoop run_loop; // If a call to HangWatcher::Monitor() takes place the test will instantly
diff --git a/build/config/c++/libc++.natvis b/build/config/c++/libc++.natvis index 2603e2e8..9a49a29 100644 --- a/build/config/c++/libc++.natvis +++ b/build/config/c++/libc++.natvis
@@ -248,6 +248,13 @@ </Expand> </Type> + <Type Name="std::__1::priority_queue<*>"> + <DisplayString>{c}</DisplayString> + <Expand> + <ExpandedItem>c</ExpandedItem> + <Item Name="[comp]">comp</Item> + </Expand> + </Type> <Type Name="std::__1::set<*>"> <Intrinsic Name="size" Expression="*(size_type*)&__tree_.__pair3_" /> @@ -283,11 +290,81 @@ </Expand> </Type> - <Type Name="std::__1::priority_queue<*>"> - <DisplayString>{c}</DisplayString> + <Type Name="std::__1::__tuple_leaf<*,*,0>"> + <DisplayString>{__value_}</DisplayString> + </Type> + + <Type Name="std::__1::tuple<>"> + <DisplayString>()</DisplayString> + </Type> + + <Type Name="std::__1::tuple<*>"> + <DisplayString>({(std::__1::__tuple_leaf<0,$T1,0>)__base_})</DisplayString> + <Expand> + <Item Name="[0]">(std::__1::__tuple_leaf<0,$T1,0>)__base_</Item> + </Expand> + </Type> + + <Type Name="std::__1::tuple<*,*>"> + <DisplayString>({(std::__1::__tuple_leaf<0,$T1,0>)__base_}, {(std::__1::__tuple_leaf<1,$T2,0>)__base_})</DisplayString> <Expand> - <ExpandedItem>c</ExpandedItem> - <Item Name="[comp]">comp</Item> + <Item Name="[0]">(std::__1::__tuple_leaf<0,$T1,0>)__base_</Item> + <Item Name="[1]">(std::__1::__tuple_leaf<1,$T2,0>)__base_</Item> + </Expand> + </Type> + + <Type Name="std::__1::tuple<*,*,*>"> + <DisplayString>({(std::__1::__tuple_leaf<0,$T1,0>)__base_}, {(std::__1::__tuple_leaf<1,$T2,0>)__base_}, {(std::__1::__tuple_leaf<2,$T3,0>)__base_})</DisplayString> + <Expand> + <Item Name="[0]">(std::__1::__tuple_leaf<0,$T1,0>)__base_</Item> + <Item Name="[1]">(std::__1::__tuple_leaf<1,$T2,0>)__base_</Item> + <Item Name="[2]">(std::__1::__tuple_leaf<2,$T3,0>)__base_</Item> + </Expand> + </Type> + + <Type Name="std::__1::tuple<*,*,*,*>"> + <DisplayString>({(std::__1::__tuple_leaf<0,$T1,0>)__base_}, {(std::__1::__tuple_leaf<1,$T2,0>)__base_}, {(std::__1::__tuple_leaf<2,$T3,0>)__base_}, {(std::__1::__tuple_leaf<3,$T4,0>)__base_})</DisplayString> + <Expand> + <Item Name="[0]">(std::__1::__tuple_leaf<0,$T1,0>)__base_</Item> + <Item Name="[1]">(std::__1::__tuple_leaf<1,$T2,0>)__base_</Item> + <Item Name="[2]">(std::__1::__tuple_leaf<2,$T3,0>)__base_</Item> + <Item Name="[3]">(std::__1::__tuple_leaf<3,$T4,0>)__base_</Item> + </Expand> + </Type> + + <Type Name="std::__1::tuple<*,*,*,*,*>"> + <DisplayString>({(std::__1::__tuple_leaf<0,$T1,0>)__base_}, {(std::__1::__tuple_leaf<1,$T2,0>)__base_}, {(std::__1::__tuple_leaf<2,$T3,0>)__base_}, {(std::__1::__tuple_leaf<3,$T4,0>)__base_}, {(std::__1::__tuple_leaf<4,$T5,0>)__base_})</DisplayString> + <Expand> + <Item Name="[0]">(std::__1::__tuple_leaf<0,$T1,0>)__base_</Item> + <Item Name="[1]">(std::__1::__tuple_leaf<1,$T2,0>)__base_</Item> + <Item Name="[2]">(std::__1::__tuple_leaf<2,$T3,0>)__base_</Item> + <Item Name="[3]">(std::__1::__tuple_leaf<3,$T4,0>)__base_</Item> + <Item Name="[4]">(std::__1::__tuple_leaf<4,$T5,0>)__base_</Item> + </Expand> + </Type> + + <Type Name="std::__1::tuple<*,*,*,*,*,*>"> + <DisplayString>({(std::__1::__tuple_leaf<0,$T1,0>)__base_}, {(std::__1::__tuple_leaf<1,$T2,0>)__base_}, {(std::__1::__tuple_leaf<2,$T3,0>)__base_}, {(std::__1::__tuple_leaf<3,$T4,0>)__base_}, {(std::__1::__tuple_leaf<4,$T5,0>)__base_}, {(std::__1::__tuple_leaf<5,$T6,0>)__base_})</DisplayString> + <Expand> + <Item Name="[0]">(std::__1::__tuple_leaf<0,$T1,0>)__base_</Item> + <Item Name="[1]">(std::__1::__tuple_leaf<1,$T2,0>)__base_</Item> + <Item Name="[2]">(std::__1::__tuple_leaf<2,$T3,0>)__base_</Item> + <Item Name="[3]">(std::__1::__tuple_leaf<3,$T4,0>)__base_</Item> + <Item Name="[4]">(std::__1::__tuple_leaf<4,$T5,0>)__base_</Item> + <Item Name="[5]">(std::__1::__tuple_leaf<5,$T6,0>)__base_</Item> + </Expand> + </Type> + + <Type Name="std::__1::tuple<*,*,*,*,*,*,*>"> + <DisplayString>({(std::__1::__tuple_leaf<0,$T1,0>)__base_}, {(std::__1::__tuple_leaf<1,$T2,0>)__base_}, {(std::__1::__tuple_leaf<2,$T3,0>)__base_}, {(std::__1::__tuple_leaf<3,$T4,0>)__base_}, {(std::__1::__tuple_leaf<4,$T5,0>)__base_}, {(std::__1::__tuple_leaf<5,$T6,0>)__base_}, {(std::__1::__tuple_leaf<6,$T7,0>)__base_})</DisplayString> + <Expand> + <Item Name="[0]">(std::__1::__tuple_leaf<0,$T1,0>)__base_</Item> + <Item Name="[1]">(std::__1::__tuple_leaf<1,$T2,0>)__base_</Item> + <Item Name="[2]">(std::__1::__tuple_leaf<2,$T3,0>)__base_</Item> + <Item Name="[3]">(std::__1::__tuple_leaf<3,$T4,0>)__base_</Item> + <Item Name="[4]">(std::__1::__tuple_leaf<4,$T5,0>)__base_</Item> + <Item Name="[5]">(std::__1::__tuple_leaf<5,$T6,0>)__base_</Item> + <Item Name="[6]">(std::__1::__tuple_leaf<6,$T7,0>)__base_</Item> </Expand> </Type>
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1 index 63e104d..7adce85 100644 --- a/build/fuchsia/linux.sdk.sha1 +++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@ -0.20200512.0.1 \ No newline at end of file +0.20200512.1.1 \ No newline at end of file
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1 index 63e104d..7adce85 100644 --- a/build/fuchsia/mac.sdk.sha1 +++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@ -0.20200512.0.1 \ No newline at end of file +0.20200512.1.1 \ No newline at end of file
diff --git a/cc/metrics/frame_sequence_metrics.cc b/cc/metrics/frame_sequence_metrics.cc index 205d072..0cefe55 100644 --- a/cc/metrics/frame_sequence_metrics.cc +++ b/cc/metrics/frame_sequence_metrics.cc
@@ -177,7 +177,7 @@ // throughput. aggregated_throughput_.frames_expected = impl_throughput_.frames_expected; DCHECK_LE(aggregated_throughput_.frames_produced, - aggregated_throughput_.frames_produced); + aggregated_throughput_.frames_expected); } void FrameSequenceMetrics::ReportMetrics() { @@ -281,12 +281,12 @@ } // Reset the metrics that reach reporting threshold. - if (impl_throughput_.frames_expected >= kMinFramesForThroughputMetric) + if (impl_throughput_.frames_expected >= kMinFramesForThroughputMetric) { impl_throughput_ = {}; + aggregated_throughput_ = {}; + } if (main_throughput_.frames_expected >= kMinFramesForThroughputMetric) main_throughput_ = {}; - if (aggregated_throughput_percent.has_value()) - aggregated_throughput_ = {}; } base::Optional<int> FrameSequenceMetrics::ThroughputData::ReportHistogram(
diff --git a/cc/metrics/frame_sequence_metrics_unittest.cc b/cc/metrics/frame_sequence_metrics_unittest.cc index b52a810..ae43da1 100644 --- a/cc/metrics/frame_sequence_metrics_unittest.cc +++ b/cc/metrics/frame_sequence_metrics_unittest.cc
@@ -23,6 +23,18 @@ EXPECT_EQ(first.aggregated_throughput().frames_expected, 200u); } +TEST(FrameSequenceMetricsTest, AggregatedThroughputClearedAfterReport) { + FrameSequenceMetrics first(FrameSequenceTrackerType::kCompositorAnimation, + nullptr); + first.impl_throughput().frames_expected = 200u; + first.impl_throughput().frames_produced = 190u; + first.aggregated_throughput().frames_produced = 150u; + + first.ReportMetrics(); + EXPECT_EQ(first.aggregated_throughput().frames_expected, 0u); + EXPECT_EQ(first.aggregated_throughput().frames_produced, 0u); +} + TEST(FrameSequenceMetricsTest, MergeMetrics) { // Create a metric with only a small number of frames. It shouldn't report any // metrics.
diff --git a/chrome/android/chrome_java_sources.gni b/chrome/android/chrome_java_sources.gni index 16acea16..479fc65 100644 --- a/chrome/android/chrome_java_sources.gni +++ b/chrome/android/chrome_java_sources.gni
@@ -1346,6 +1346,7 @@ "java/src/org/chromium/chrome/browser/push_messaging/PushMessagingServiceObserver.java", "java/src/org/chromium/chrome/browser/query_tiles/FakeTileProvider.java", "java/src/org/chromium/chrome/browser/query_tiles/QueryTileSection.java", + "java/src/org/chromium/chrome/browser/query_tiles/QueryTileUtils.java", "java/src/org/chromium/chrome/browser/query_tiles/TileProviderFactory.java", "java/src/org/chromium/chrome/browser/rappor/RapporServiceBridge.java", "java/src/org/chromium/chrome/browser/resources/ResourceMapper.java",
diff --git a/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantAccessibilityIntegrationTest.java b/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantAccessibilityIntegrationTest.java index e2e4520..b2cfad9 100644 --- a/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantAccessibilityIntegrationTest.java +++ b/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantAccessibilityIntegrationTest.java
@@ -39,6 +39,7 @@ import org.junit.runner.RunWith; import org.chromium.base.test.util.CommandLineFlags; +import org.chromium.base.test.util.DisabledTest; import org.chromium.chrome.autofill_assistant.R; import org.chromium.chrome.browser.autofill_assistant.proto.ActionProto; import org.chromium.chrome.browser.autofill_assistant.proto.ChipProto; @@ -107,6 +108,7 @@ @Test @MediumTest + @DisabledTest(message = "crbug.com/1081604") public void testBottomSheetHasRestrictedFixedHeight() throws Exception { ArrayList<ActionProto> list = new ArrayList<>();
diff --git a/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantChromeTabIntegrationTest.java b/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantChromeTabIntegrationTest.java index 60387306..d347f3c4 100644 --- a/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantChromeTabIntegrationTest.java +++ b/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantChromeTabIntegrationTest.java
@@ -338,6 +338,7 @@ @Test @MediumTest + @DisabledTest(message = "https://crbug.com/1081608") public void interactingWithLocationBarHidesAutofillAssistant() throws Exception { ArrayList<ActionProto> list = new ArrayList<>(); list.add((ActionProto) ActionProto.newBuilder()
diff --git a/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantKeyboardIntegrationTest.java b/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantKeyboardIntegrationTest.java index dfa5887..86e32e8 100644 --- a/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantKeyboardIntegrationTest.java +++ b/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantKeyboardIntegrationTest.java
@@ -237,4 +237,61 @@ tapElement(mTestRule, "profile_name"); waitUntilKeyboardMatchesCondition(mTestRule, /* isShowing= */ true); } + + @Test + @MediumTest + public void keyboardDoesNotShowOnElementClickInIFrame() throws Exception { + ElementReferenceProto element = (ElementReferenceProto) ElementReferenceProto.newBuilder() + .addSelectors("#iframe") + .addSelectors("#name") + .build(); + + ArrayList<ActionProto> list = new ArrayList<>(); + list.add((ActionProto) ActionProto.newBuilder() + .setClick(ClickProto.newBuilder() + .setClickType(ClickType.CLICK) + .setElementToClick(element)) + .build()); + list.add((ActionProto) ActionProto.newBuilder() + .setPrompt(PromptProto.newBuilder().setMessage("Clicked").addChoices( + Choice.newBuilder().setChip( + ChipProto.newBuilder() + .setType(ChipType.HIGHLIGHTED_ACTION) + .setText("Continue")))) + .build()); + list.add( + (ActionProto) ActionProto.newBuilder() + .setFocusElement(FocusElementProto.newBuilder() + .setElement(element) + .setTouchableElementArea( + ElementAreaProto.newBuilder().addTouchable( + Rectangle.newBuilder().addElements( + element)))) + .build()); + list.add((ActionProto) ActionProto.newBuilder() + .setPrompt(PromptProto.newBuilder() + .setMessage("Highlighted") + .addChoices(Choice.newBuilder())) + .build()); + + AutofillAssistantTestScript script = new AutofillAssistantTestScript( + (SupportedScriptProto) SupportedScriptProto.newBuilder() + .setPath(TEST_PAGE) + .setPresentation(PresentationProto.newBuilder().setAutostart(true).setChip( + ChipProto.newBuilder().setText("Done"))) + .build(), + list); + + runAutofillAssistant(script); + + // Autofill Assistant clicking an <input> element does not show the keyboard. + waitUntilViewMatchesCondition(withText("Clicked"), isCompletelyDisplayed()); + assertThat(isKeyboardVisible(), is(false)); + + // A user's click on an <input> element does show the keyboard. + onView(withText("Continue")).perform(click()); + waitUntilViewMatchesCondition(withText("Highlighted"), isCompletelyDisplayed()); + tapElement(mTestRule, "iframe", "name"); + waitUntilKeyboardMatchesCondition(mTestRule, /* isShowing= */ true); + } }
diff --git a/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceTest.java b/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceTest.java index 10cc489..fce0cd8 100644 --- a/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceTest.java +++ b/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceTest.java
@@ -48,6 +48,7 @@ import org.chromium.base.test.params.ParameterSet; import org.chromium.base.test.params.ParameterizedRunner; import org.chromium.base.test.util.CommandLineFlags; +import org.chromium.base.test.util.DisabledTest; import org.chromium.base.test.util.Feature; import org.chromium.base.test.util.Restriction; import org.chromium.chrome.browser.ChromeTabbedActivity; @@ -173,6 +174,7 @@ @Test @MediumTest @Feature({"StartSurface"}) + @DisabledTest // clang-format off @CommandLineFlags.Add({BASE_PARAMS + "/omniboxonly" + "/hide_switch_when_no_incognito_tabs/true"}) @@ -225,6 +227,7 @@ @Test @MediumTest @Feature({"StartSurface"}) + @DisabledTest @CommandLineFlags.Add({BASE_PARAMS + "/twopanes"}) public void testShow_TwoPanes() { final ChromeTabbedActivity cta = mActivityTestRule.getActivity();
diff --git a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/ConditionalTabStripTest.java b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/ConditionalTabStripTest.java index 3b25bdb..ce09a7e5 100644 --- a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/ConditionalTabStripTest.java +++ b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/ConditionalTabStripTest.java
@@ -42,6 +42,7 @@ import org.junit.runner.RunWith; import org.chromium.base.test.util.CommandLineFlags; +import org.chromium.base.test.util.DisabledTest; import org.chromium.base.test.util.Restriction; import org.chromium.chrome.browser.ChromeTabbedActivity; import org.chromium.chrome.browser.TabsTest.SimulateClickOnMainThread; @@ -403,6 +404,7 @@ @Test @MediumTest + @DisabledTest(message = "crbug.com/1081697") public void testStrip_UndoDismiss() throws Exception { ChromeTabbedActivity cta = mActivityTestRule.getActivity(); for (int i = 0; i < 3; i++) {
diff --git a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/library/feedactionmanager/FeedActionManagerImpl.java b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/library/feedactionmanager/FeedActionManagerImpl.java index 6deb83d..0ae18dc 100644 --- a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/library/feedactionmanager/FeedActionManagerImpl.java +++ b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/library/feedactionmanager/FeedActionManagerImpl.java
@@ -369,6 +369,7 @@ actions.add(StreamUploadableAction.newBuilder() .setFeatureContentId(contentId) .setPayload(viewActionData.actionPayload) + .setDurationMs(viewActionData.durationMs) .setTimestampSeconds(currentTimeS) .build()); // Stop tracking this particular content as we're already uploading a view
diff --git a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/library/feedrequestmanager/UploadableActionsRequestBuilder.java b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/library/feedrequestmanager/UploadableActionsRequestBuilder.java index 74fd14c..8db0e01 100644 --- a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/library/feedrequestmanager/UploadableActionsRequestBuilder.java +++ b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/library/feedrequestmanager/UploadableActionsRequestBuilder.java
@@ -68,6 +68,7 @@ FeedAction.newBuilder().setActionPayload(payload).setClientData( FeedAction.ClientData.newBuilder() .setTimestampSeconds(action.getTimestampSeconds()) + .setDurationMs(action.getDurationMs()) .build()); if (mSemanticPropertiesMap.containsKey(contentId)) { feedAction.setSemanticProperties(
diff --git a/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/library/feedactionmanager/FeedActionManagerImplTest.java b/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/library/feedactionmanager/FeedActionManagerImplTest.java index ff02361a..78828d5 100644 --- a/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/library/feedactionmanager/FeedActionManagerImplTest.java +++ b/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/library/feedactionmanager/FeedActionManagerImplTest.java
@@ -281,7 +281,7 @@ // View covers >50% (FeedActionManagerImpl.VIEWPORT_COVERAGE_THRESHOLD) of viewport, // but <50% (FeedActionManagerImpl.VIEW_EXPOSURE_THRESHOLD) of the view is visible. new Rect(0, -1000, 100, 51), CONTENT_ID_STRING, LONG_DURATION_MS); - verifyActionUpserted(ACTION_PAYLOAD, CONTENT_ID_STRING, LONG_DURATION_S); + verifyActionUpserted(ACTION_PAYLOAD, CONTENT_ID_STRING, LONG_DURATION_S, LONG_DURATION_MS); } @Test @@ -291,7 +291,7 @@ // it covers <50% (FeedActionManagerImpl.VIEWPORT_COVERAGE_THRESHOLD) of the // viewport. new Rect(0, -48, 100, 49), CONTENT_ID_STRING, LONG_DURATION_MS); - verifyActionUpserted(ACTION_PAYLOAD, CONTENT_ID_STRING, LONG_DURATION_S); + verifyActionUpserted(ACTION_PAYLOAD, CONTENT_ID_STRING, LONG_DURATION_S, LONG_DURATION_MS); } @Test @@ -351,12 +351,14 @@ .setFeatureContentId(CONTENT_ID_STRING) .setPayload(ACTION_PAYLOAD) .setTimestampSeconds(DEFAULT_TIME_SECONDS + LONG_DURATION_S) + .setDurationMs(LONG_DURATION_MS) .build(), StreamUploadableAction.newBuilder() .setFeatureContentId(CONTENT_ID_STRING) .setPayload(ACTION_PAYLOAD) .setTimestampSeconds( DEFAULT_TIME_SECONDS + LONG_DURATION_S + 1 + LONG_DURATION_S) + .setDurationMs(LONG_DURATION_MS) .build()); } @@ -411,11 +413,13 @@ .setFeatureContentId("contentId1") .setPayload(ACTION_PAYLOAD) .setTimestampSeconds(DEFAULT_TIME_SECONDS + LONG_DURATION_S) + .setDurationMs(LONG_DURATION_MS) .build(), StreamUploadableAction.newBuilder() .setFeatureContentId("contentId3") .setPayload(ACTION_PAYLOAD) .setTimestampSeconds(DEFAULT_TIME_SECONDS + LONG_DURATION_S) + .setDurationMs(LONG_DURATION_MS) .build()); } @@ -442,7 +446,8 @@ mActionManager.onScrollEnd(); mFakeClock.advance(1000); mActionManager.onHide(); - verifyActionUpserted(ACTION_PAYLOAD, CONTENT_ID_STRING, LONG_DURATION_S + 1); + verifyActionUpserted( + ACTION_PAYLOAD, CONTENT_ID_STRING, LONG_DURATION_S + 1, LONG_DURATION_MS); } @Test @@ -471,7 +476,7 @@ mActionManager.onAnimationFinished(); mFakeClock.advance(LONG_DURATION_MS); mActionManager.onHide(); - verifyActionUpserted(ACTION_PAYLOAD, CONTENT_ID_STRING, LONG_DURATION_S); + verifyActionUpserted(ACTION_PAYLOAD, CONTENT_ID_STRING, LONG_DURATION_S, LONG_DURATION_MS); } @Test @@ -500,7 +505,8 @@ mActionManager.onLayoutChange(); mFakeClock.advance(1000); mActionManager.onHide(); - verifyActionUpserted(ACTION_PAYLOAD, CONTENT_ID_STRING, LONG_DURATION_S + 1); + verifyActionUpserted( + ACTION_PAYLOAD, CONTENT_ID_STRING, LONG_DURATION_S + 1, LONG_DURATION_MS); } @Test @@ -528,7 +534,8 @@ mActionManager.onLayoutChange(); verifyNoActionUpserted(); mActionManager.storeViewActions(() -> { - verifyActionUpserted(ACTION_PAYLOAD, CONTENT_ID_STRING, LONG_DURATION_S); + verifyActionUpserted( + ACTION_PAYLOAD, CONTENT_ID_STRING, LONG_DURATION_S, LONG_DURATION_MS); mStoreViewActionsRunnable.run(); }); verify(mStoreViewActionsRunnable).run(); @@ -543,11 +550,13 @@ verify(mStoreViewActionsRunnable, times(1)).run(); } - private void verifyActionUpserted(ActionPayload payload, String contentId, long durationS) { + private void verifyActionUpserted( + ActionPayload payload, String contentId, long elapsedTimeS, long durationMs) { verifyActionsUpserted(StreamUploadableAction.newBuilder() .setFeatureContentId(contentId) .setPayload(payload) - .setTimestampSeconds(DEFAULT_TIME_SECONDS + durationS) + .setTimestampSeconds(DEFAULT_TIME_SECONDS + elapsedTimeS) + .setDurationMs(durationMs) .build()); }
diff --git a/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/library/feedrequestmanager/UploadableActionsRequestBuilderTest.java b/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/library/feedrequestmanager/UploadableActionsRequestBuilderTest.java index fcb47b4..1e5d460 100644 --- a/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/library/feedrequestmanager/UploadableActionsRequestBuilderTest.java +++ b/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/library/feedrequestmanager/UploadableActionsRequestBuilderTest.java
@@ -37,6 +37,7 @@ public class UploadableActionsRequestBuilderTest { private static final String CONTENT_ID = "contentId"; private static final int TIME = 100; + private static final long DURATION = 20; private static final byte[] SEMANTIC_PROPERTIES_BYTES = new byte[] {0x1, 0xf}; private static final SemanticProperties SEMANTIC_PROPERTIES = SemanticProperties.newBuilder() @@ -68,6 +69,7 @@ .setFeatureContentId(CONTENT_ID) .setPayload(mPayload) .setTimestampSeconds(TIME) + .setDurationMs(DURATION) .build()); mRequestBuilder = ActionRequest.newBuilder().setRequestVersion( ActionRequest.RequestVersion.FEED_UPLOAD_ACTION); @@ -81,6 +83,7 @@ .setActionPayload(mPayload) .setClientData(FeedAction.ClientData.newBuilder() .setTimestampSeconds(TIME) + .setDurationMs(DURATION) .build()) .build(); mFeedActionRequestBuilder.addFeedAction(feedAction); @@ -111,6 +114,7 @@ .setActionPayload(mPayload) .setClientData(FeedAction.ClientData.newBuilder() .setTimestampSeconds(TIME) + .setDurationMs(DURATION) .build()) .build(); mFeedActionRequestBuilder.addFeedAction(feedAction);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/HiddenTabHolder.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/HiddenTabHolder.java index 63777e95..503d24b 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/HiddenTabHolder.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/HiddenTabHolder.java
@@ -22,7 +22,6 @@ import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tab.TabBuilder; import org.chromium.chrome.browser.tab.TabLaunchType; -import org.chromium.chrome.browser.tab.TabObserver; import org.chromium.chrome.browser.tab_activity_glue.ReparentingTask; import org.chromium.components.embedder_support.util.UrlUtilities; import org.chromium.content_public.browser.LoadUrlParams; @@ -44,24 +43,46 @@ public final CustomTabsSessionToken session; public final String url; public final Tab tab; - public final TabObserver observer; public final String referrer; - private SpeculationParams(CustomTabsSessionToken session, String url, Tab tab, - TabObserver observer, String referrer) { + private SpeculationParams( + CustomTabsSessionToken session, String url, Tab tab, String referrer) { this.session = session; this.url = url; this.tab = tab; - this.observer = observer; this.referrer = referrer; } } private class HiddenTabObserver extends EmptyTabObserver { + // This WindowAndroid is "owned" by the Tab and should be destroyed when it is no longer + // needed by the Tab or when the Tab is destroyed. + private WindowAndroid mOwnedWindowAndroid; + public HiddenTabObserver(WindowAndroid ownedWindowAndroid) { + mOwnedWindowAndroid = ownedWindowAndroid; + } + @Override public void onCrash(Tab tab) { destroyHiddenTab(null); } + + @Override + public void onDestroyed(Tab tab) { + destroyOwnedWindow(tab); + } + + @Override + public void onActivityAttachmentChanged(Tab tab, WindowAndroid window) { + destroyOwnedWindow(tab); + } + + private void destroyOwnedWindow(Tab tab) { + assert mOwnedWindowAndroid != null; + mOwnedWindowAndroid.destroy(); + mOwnedWindowAndroid = null; + tab.removeObserver(this); + } } @Nullable private SpeculationParams mSpeculation; @@ -85,7 +106,7 @@ Tab tab = buildDetachedTab(); - HiddenTabObserver observer = new HiddenTabObserver(); + HiddenTabObserver observer = new HiddenTabObserver(tab.getWindowAndroid()); tab.addObserver(observer); // Updating post message as soon as we have a valid WebContents. @@ -101,7 +122,7 @@ loadParams.setReferrer(new Referrer(referrer, ReferrerPolicy.DEFAULT)); } - mSpeculation = new SpeculationParams(session, url, tab, observer, referrer); + mSpeculation = new SpeculationParams(session, url, tab, referrer); mSpeculation.tab.loadUrl(loadParams); } @@ -151,7 +172,6 @@ String speculatedUrl = mSpeculation.url; String speculationReferrer = mSpeculation.referrer; - tab.removeObserver(mSpeculation.observer); mSpeculation = null; boolean urlsMatch = ignoreFragments
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediator.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediator.java index 02fe3dc..996e0a8 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediator.java
@@ -52,6 +52,7 @@ import org.chromium.chrome.browser.omnibox.suggestions.tiles.TileSuggestionProcessor; import org.chromium.chrome.browser.omnibox.voice.VoiceRecognitionHandler; import org.chromium.chrome.browser.profiles.Profile; +import org.chromium.chrome.browser.query_tiles.QueryTileUtils; import org.chromium.chrome.browser.search_engines.TemplateUrlServiceFactory; import org.chromium.chrome.browser.share.ShareDelegate; import org.chromium.chrome.browser.tab.Tab; @@ -666,8 +667,9 @@ /** Called when a query tile is selected by the user. */ void onQueryTileSelected(QueryTile queryTile) { - // For last level tile, start a search query. - if (queryTile.children.isEmpty()) { + // For last level tile, start a search query, unless we want to let user have a chance to + // edit the query. + if (queryTile.children.isEmpty() && !QueryTileUtils.isQueryEditingEnabled()) { String url = TemplateUrlServiceFactory.get().getUrlForSearchQuery(queryTile.queryText); mDelegate.loadUrl(url, PageTransition.LINK, mLastActionUpTimestamp); mDelegate.setKeyboardVisibility(false);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/page_info/ChromePageInfoControllerDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/page_info/ChromePageInfoControllerDelegate.java index bcc4f897..5d580f4 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/page_info/ChromePageInfoControllerDelegate.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/page_info/ChromePageInfoControllerDelegate.java
@@ -36,8 +36,11 @@ import org.chromium.components.page_info.PageInfoControllerDelegate; import org.chromium.components.page_info.PageInfoControllerDelegate.OfflinePageState; import org.chromium.components.page_info.PageInfoControllerDelegate.PreviewPageState; +import org.chromium.components.page_info.PageInfoFeatureList; +import org.chromium.components.page_info.PageInfoRowView; import org.chromium.components.page_info.PageInfoView; import org.chromium.components.page_info.PageInfoView.PageInfoViewParams; +import org.chromium.components.page_info.PageInfoViewV2; import org.chromium.components.page_info.SystemSettingsActivityRequiredListener; import org.chromium.components.security_state.ConnectionSecurityLevel; import org.chromium.components.security_state.SecurityStateModel; @@ -301,7 +304,17 @@ @Override public void updatePermissionDisplay(PageInfoView view) { assert (mPermissionParamsListBuilder != null); - view.setPermissions(mPermissionParamsListBuilder.build()); + PageInfoView.PermissionParams params = mPermissionParamsListBuilder.build(); + if (PageInfoFeatureList.isEnabled(PageInfoFeatureList.PAGE_INFO_V2)) { + PageInfoRowView.ViewParams rowParams = new PageInfoRowView.ViewParams(); + rowParams.visible = true; + rowParams.title = mContext.getString(R.string.page_info_permissions_title); + // TODO(crbug.com/1077766): Create a permissions subtitle string that represents + // the state, potentially using R.plurals. + ((PageInfoViewV2) view).getPermissionsRowView().setParams(rowParams); + } else { + view.setPermissions(params); + } } @VisibleForTesting
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/query_tiles/QueryTileSection.java b/chrome/android/java/src/org/chromium/chrome/browser/query_tiles/QueryTileSection.java index 97c1cdf..78a62c3 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/query_tiles/QueryTileSection.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/query_tiles/QueryTileSection.java
@@ -65,7 +65,7 @@ mQueryTileSectionView = queryTileSectionView; mSearchBoxCoordinator = searchBoxCoordinator; mSubmitQueryCallback = performSearchQueryCallback; - if (!isFeatureEnabled()) return; + if (!QueryTileUtils.isFeatureEnabled()) return; mTileProvider = TileProviderFactory.getForProfile(profile); TileConfig tileConfig = new TileConfig.Builder().setUmaPrefix(UMA_PREFIX).build(); @@ -83,9 +83,14 @@ private void onTileClicked(ImageTile tile) { QueryTile queryTile = (QueryTile) tile; mTileUmaLogger.recordTileClicked(queryTile); + boolean isLastLevelTile = queryTile.children.isEmpty(); if (isLastLevelTile) { - mSubmitQueryCallback.onResult(queryTile.queryText); + if (QueryTileUtils.isQueryEditingEnabled()) { + mSearchBoxCoordinator.setSearchText(queryTile.queryText); + } else { + mSubmitQueryCallback.onResult(queryTile.queryText); + } return; } @@ -158,7 +163,7 @@ * tiles section on NTP is shortened so that feed is still visible above the fold. */ public Integer getMaxRowsForMostVisitedTiles() { - if (!isFeatureEnabled()) return null; + if (!QueryTileUtils.isFeatureEnabled()) return null; DisplayAndroid display = DisplayAndroid.getNonMultiDisplay(mQueryTileSectionView.getContext());
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/query_tiles/QueryTileUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/query_tiles/QueryTileUtils.java new file mode 100644 index 0000000..0e37b2d --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/query_tiles/QueryTileUtils.java
@@ -0,0 +1,33 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.query_tiles; + +import org.chromium.chrome.browser.flags.ChromeFeatureList; + +/** + * Handles various feature utility functions for query tiles. + */ +public class QueryTileUtils { + /** + * This is the main feature flag for query tiles. All other flags are effective only when this + * flag is enabled. + * @return Whether the query tile feature is enabled. + */ + public static boolean isFeatureEnabled() { + return ChromeFeatureList.isEnabled(ChromeFeatureList.QUERY_TILES); + } + + /** + * This is one experimental variation where user will have a chance of editing the query text + * before starting a search. When a query tile is clicked, the query text will be pasted in the + * omnibox. No second level tiles will be displayed. This is meant to show only one level of + * query tiles. + * @return Whether the user should have a chance to edit the query text before starting a + * search. + */ + public static boolean isQueryEditingEnabled() { + return ChromeFeatureList.isEnabled(ChromeFeatureList.QUERY_TILES_ENABLE_QUERY_EDITING); + } +}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/page_info/PageInfoControllerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/page_info/PageInfoControllerTest.java index 2e62ce0..247c800 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/page_info/PageInfoControllerTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/page_info/PageInfoControllerTest.java
@@ -96,9 +96,9 @@ new OfflinePageUtils.TabOfflinePageLoadUrlDelegate(tab)); chromePageInfoControllerDelegate.setOfflinePageStateForTesting( ChromePageInfoControllerDelegate.OfflinePageState.NOT_OFFLINE_PAGE); - PageInfoController pageInfo = - new PageInfoController(tab.getWebContents(), ConnectionSecurityLevel.NONE, - /*publisher=*/null, chromePageInfoControllerDelegate); + PageInfoController pageInfo = new PageInfoController(tab.getWebContents(), + ConnectionSecurityLevel.NONE, + /*publisher=*/null, chromePageInfoControllerDelegate, /*isV2Enabled=*/false); PageInfoView pageInfoView = pageInfo.getPageInfoViewForTesting(); // Test that the title contains the Unicode hostname rather than strict equality, as // the test server will be bound to a random port.
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index e20a219..aa5e446 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -3031,6 +3031,7 @@ "//components/location/android:settings", "//components/module_installer/android:native", "//components/omnibox/browser", + "//components/page_info/android", "//components/page_load_metrics/browser", "//components/paint_preview/browser/android", "//components/paint_preview/player/android", @@ -3220,6 +3221,8 @@ "enterprise/connectors/connectors_prefs.h", "enterprise/connectors/enterprise_connectors_policy_handler.cc", "enterprise/connectors/enterprise_connectors_policy_handler.h", + "enterprise/connectors/service_providers.cc", + "enterprise/connectors/service_providers.h", "enterprise/reporting/browser_report_generator.cc", "enterprise/reporting/browser_report_generator.h", "enterprise/reporting/extension_info.cc",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index fde4757..cc6ceac 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -102,6 +102,7 @@ #include "components/offline_pages/core/offline_page_feature.h" #include "components/omnibox/browser/omnibox_field_trial.h" #include "components/omnibox/common/omnibox_features.h" +#include "components/page_info/android/features.h" #include "components/paint_preview/buildflags/buildflags.h" #include "components/paint_preview/features/features.h" #include "components/password_manager/core/common/password_manager_features.h" @@ -2849,6 +2850,10 @@ {"query-tiles-omnibox", flag_descriptions::kQueryTilesOmniboxName, flag_descriptions::kQueryTilesOmniboxDescription, kOsAndroid, FEATURE_VALUE_TYPE(upboarding::features::kQueryTilesInOmnibox)}, + {"query-tiles-enable-query-editing", + flag_descriptions::kQueryTilesEnableQueryEditingName, + flag_descriptions::kQueryTilesEnableQueryEditingDescription, kOsAndroid, + FEATURE_VALUE_TYPE(upboarding::features::kQueryTilesEnableQueryEditing)}, {"query-tiles-country-code", flag_descriptions::kQueryTilesCountryCode, flag_descriptions::kQueryTilesCountryCodeDescription, kOsAndroid, MULTI_VALUE_TYPE(kQueryTilesCountryChoices)}, @@ -3550,6 +3555,11 @@ flag_descriptions::kCrossOriginOpenerPolicyDescription, kOsAll, FEATURE_VALUE_TYPE(network::features::kCrossOriginOpenerPolicy)}, + {"cross-origin-opener-policy-reporting", + flag_descriptions::kCrossOriginOpenerPolicyReportingName, + flag_descriptions::kCrossOriginOpenerPolicyReportingDescription, kOsAll, + FEATURE_VALUE_TYPE(network::features::kCrossOriginOpenerPolicyReporting)}, + {"disable-keepalive-fetch", flag_descriptions::kDisableKeepaliveFetchName, flag_descriptions::kDisableKeepaliveFetchDescription, kOsAll, FEATURE_VALUE_TYPE(network::features::kDisableKeepaliveFetch)}, @@ -5389,6 +5399,12 @@ FEATURE_VALUE_TYPE(chrome::android::kPageInfoPerformanceHints)}, #endif // !defined(OS_ANDROID) +#if defined(OS_ANDROID) + {"page-info-version-2", flag_descriptions::kPageInfoV2Name, + flag_descriptions::kPageInfoV2Description, kOsAndroid, + FEATURE_VALUE_TYPE(page_info::kPageInfoV2)}, +#endif // !defined(OS_ANDROID) + #if defined(OS_CHROMEOS) {"drag-to-snap-in-clamshell-mode", flag_descriptions::kDragToSnapInClamshellModeName,
diff --git a/chrome/browser/android/autofill_assistant/ui_controller_android_utils.cc b/chrome/browser/android/autofill_assistant/ui_controller_android_utils.cc index fb0138a..751f8cb2 100644 --- a/chrome/browser/android/autofill_assistant/ui_controller_android_utils.cc +++ b/chrome/browser/android/autofill_assistant/ui_controller_android_utils.cc
@@ -122,11 +122,15 @@ env, base::android::ToJavaIntArray(env, ints.get(), proto.ints().values_size())); } - case ValueProto::kUserActions: { + case ValueProto::kCreditCards: + case ValueProto::kProfiles: + case ValueProto::kLoginOptions: + case ValueProto::kCreditCardResponse: + case ValueProto::kLoginOptionResponse: + case ValueProto::kUserActions: // Unused. NOTREACHED(); return nullptr; - } case ValueProto::kDates: { auto jlist = Java_AssistantValue_createDateTimeList(env); for (const auto& value : proto.dates().values()) {
diff --git a/chrome/browser/apps/intent_helper/apps_navigation_throttle.cc b/chrome/browser/apps/intent_helper/apps_navigation_throttle.cc index 1fe7de7..85e55d9 100644 --- a/chrome/browser/apps/intent_helper/apps_navigation_throttle.cc +++ b/chrome/browser/apps/intent_helper/apps_navigation_throttle.cc
@@ -8,7 +8,6 @@ #include <utility> #include "base/bind.h" -#include "base/metrics/histogram_macros.h" #include "base/optional.h" #include "chrome/browser/apps/app_service/app_launch_params.h" #include "chrome/browser/apps/app_service/app_service_proxy.h"
diff --git a/chrome/browser/autofill/autofill_server_browsertest.cc b/chrome/browser/autofill/autofill_server_browsertest.cc index b662a8e..6f32b1e 100644 --- a/chrome/browser/autofill/autofill_server_browsertest.cc +++ b/chrome/browser/autofill/autofill_server_browsertest.cc
@@ -75,22 +75,17 @@ } private: - // Helper to extract the value of a query param. Returns "*** not found ***" - // if the requested query param is not in the query string. - std::string GetQueryParam(const std::string& query_str, - const std::string& param_name) { - url::Component query(0, query_str.length()); - url::Component key, value; - while (url::ExtractQueryKeyValue(query_str.c_str(), &query, &key, &value)) { - std::string key_string(query_str.substr(key.begin, key.len)); - std::string param_text(query_str.substr(value.begin, value.len)); - std::string param_value; - if (key_string == param_name && - base::Base64UrlDecode(param_text, - base::Base64UrlDecodePolicy::REQUIRE_PADDING, - ¶m_value)) { - return param_value; - } + // Helper to extract the value passed to a lookup in the URL. Returns "*** not + // found ***" if the the data cannot be decoded. + std::string GetLookupContent(const std::string& query_path) { + if (query_path.find("/v1/pages/") == std::string::npos) + return "*** not found ***"; + std::string payload = query_path.substr(strlen("/v1/pages/")); + std::string decoded_payload; + if (base::Base64UrlDecode(payload, + base::Base64UrlDecodePolicy::REQUIRE_PADDING, + &decoded_payload)) { + return decoded_payload; } return "*** not found ***"; } @@ -99,7 +94,7 @@ // NOTE: This constant matches the one defined in // components/autofill/core/browser/autofill_download_manager.cc static const char kDefaultAutofillServerURL[] = - "https://clients1.google.com/tbproxy/af/"; + "https://content-autofill.googleapis.com/"; DCHECK(params); network::ResourceRequest resource_request = params->url_request; if (resource_request.url.spec().find(kDefaultAutofillServerURL) == @@ -109,7 +104,7 @@ const std::string& data = (resource_request.method == "GET") - ? GetQueryParam(resource_request.url.query(), "q") + ? GetLookupContent(resource_request.url.path()) : network::GetUploadData(resource_request); EXPECT_EQ(data, expected_upload_data_); @@ -185,15 +180,15 @@ " };" "</script>"; - AutofillQueryContents query; + AutofillPageQueryRequest query; query.set_client_version("6.1.1715.1442/en (GGLL)"); - AutofillQueryContents::Form* query_form = query.add_form(); + auto* query_form = query.add_forms(); query_form->set_signature(15916856893790176210U); - test::FillQueryField(query_form->add_field(), 2594484045U, "one", "text"); - test::FillQueryField(query_form->add_field(), 2750915947U, "two", "text"); - test::FillQueryField(query_form->add_field(), 3494787134U, "three", "text"); - test::FillQueryField(query_form->add_field(), 1236501728U, "four", "text"); + test::FillQueryField(query_form->add_fields(), 2594484045U, "one", "text"); + test::FillQueryField(query_form->add_fields(), 2750915947U, "two", "text"); + test::FillQueryField(query_form->add_fields(), 3494787134U, "three", "text"); + test::FillQueryField(query_form->add_fields(), 1236501728U, "four", "text"); std::string expected_query_string; ASSERT_TRUE(query.SerializeToString(&expected_query_string)); @@ -207,30 +202,31 @@ // Submit the form, using a simulated mouse click because form submissions not // triggered by user gestures are ignored. Expect an upload request upon form // submission, with form fields matching those from the query request. - AutofillUploadContents upload; - upload.set_submission(true); - upload.set_client_version("6.1.1715.1442/en (GGLL)"); - upload.set_form_signature(15916856893790176210U); - upload.set_autofill_used(false); - upload.set_data_present("1f7e0003780000080004"); - upload.set_action_signature(15724779818122431245U); - upload.set_form_name("test_form"); - upload.set_passwords_revealed(false); - upload.set_submission_event( + AutofillUploadRequest request; + AutofillUploadContents* upload = request.mutable_upload(); + upload->set_submission(true); + upload->set_client_version("6.1.1715.1442/en (GGLL)"); + upload->set_form_signature(15916856893790176210U); + upload->set_autofill_used(false); + upload->set_data_present("1f7e0003780000080004"); + upload->set_action_signature(15724779818122431245U); + upload->set_form_name("test_form"); + upload->set_passwords_revealed(false); + upload->set_submission_event( AutofillUploadContents_SubmissionIndicatorEvent_HTML_FORM_SUBMISSION); - upload.set_has_form_tag(true); + upload->set_has_form_tag(true); - test::FillUploadField(upload.add_field(), 2594484045U, "one", "text", nullptr, - 2U); - test::FillUploadField(upload.add_field(), 2750915947U, "two", "text", "off", - 2U); - test::FillUploadField(upload.add_field(), 3494787134U, "three", "text", + test::FillUploadField(upload->add_field(), 2594484045U, "one", "text", nullptr, 2U); - test::FillUploadField(upload.add_field(), 1236501728U, "four", "text", "off", + test::FillUploadField(upload->add_field(), 2750915947U, "two", "text", "off", + 2U); + test::FillUploadField(upload->add_field(), 3494787134U, "three", "text", + nullptr, 2U); + test::FillUploadField(upload->add_field(), 1236501728U, "four", "text", "off", 2U); std::string expected_upload_string; - ASSERT_TRUE(upload.SerializeToString(&expected_upload_string)); + ASSERT_TRUE(request.SerializeToString(&expected_upload_string)); WindowedNetworkObserver upload_network_observer(expected_upload_string); content::WebContents* web_contents = @@ -254,14 +250,14 @@ " <input type='submit'>" "</form>"; - AutofillQueryContents query; + AutofillPageQueryRequest query; query.set_client_version("6.1.1715.1442/en (GGLL)"); - AutofillQueryContents::Form* query_form = query.add_form(); + auto* query_form = query.add_forms(); query_form->set_signature(8900697631820480876U); - test::FillQueryField(query_form->add_field(), 2594484045U, "one", "text"); - test::FillQueryField(query_form->add_field(), 2750915947U, "two", "text"); - test::FillQueryField(query_form->add_field(), 116843943U, "three", + test::FillQueryField(query_form->add_fields(), 2594484045U, "one", "text"); + test::FillQueryField(query_form->add_fields(), 2750915947U, "two", "text"); + test::FillQueryField(query_form->add_fields(), 116843943U, "three", "password"); std::string expected_query_string;
diff --git a/chrome/browser/browser_switcher/browser_switcher_service.cc b/chrome/browser/browser_switcher/browser_switcher_service.cc index 22433b0..4588b30 100644 --- a/chrome/browser/browser_switcher/browser_switcher_service.cc +++ b/chrome/browser/browser_switcher/browser_switcher_service.cc
@@ -30,8 +30,10 @@ namespace { // How long to wait after |BrowserSwitcherService| is created before initiating -// the sitelist fetch. -const base::TimeDelta kFetchSitelistDelay = base::TimeDelta::FromSeconds(60); +// the sitelist fetch. Non-zero values are used for testing. +// +// TODO(nicolaso): get rid of this. +const base::TimeDelta kFetchSitelistDelay = base::TimeDelta(); // How long to wait after a fetch to re-fetch the sitelist to keep it fresh. const base::TimeDelta kRefreshSitelistDelay = base::TimeDelta::FromMinutes(30); @@ -141,6 +143,7 @@ request->url = source.url; request->load_flags = net::LOAD_BYPASS_CACHE | net::LOAD_DISABLE_CACHE; request->credentials_mode = network::mojom::CredentialsMode::kInclude; + request->priority = net::IDLE; source.url_loader = network::SimpleURLLoader::Create(std::move(request), traffic_annotation); source.url_loader->SetRetryOptions(
diff --git a/chrome/browser/browser_switcher/browser_switcher_service_browsertest.cc b/chrome/browser/browser_switcher/browser_switcher_service_browsertest.cc index 1ff0ee8..62a0c79 100644 --- a/chrome/browser/browser_switcher/browser_switcher_service_browsertest.cc +++ b/chrome/browser/browser_switcher/browser_switcher_service_browsertest.cc
@@ -102,7 +102,6 @@ EXPECT_CALL(provider_, IsInitializationComplete(testing::_)) .WillRepeatedly(testing::Return(true)); policy::BrowserPolicyConnector::SetPolicyProviderForTesting(&provider_); - BrowserSwitcherService::SetFetchDelayForTesting(base::TimeDelta()); BrowserSwitcherService::SetRefreshDelayForTesting(base::TimeDelta()); }
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc index caf1fd9..180943b 100644 --- a/chrome/browser/chrome_content_browser_client.cc +++ b/chrome/browser/chrome_content_browser_client.cc
@@ -2348,12 +2348,13 @@ bool ChromeContentBrowserClient::AllowAppCache( const GURL& manifest_url, - const GURL& first_party, + const GURL& site_for_cookies, + const base::Optional<url::Origin>& top_frame_origin, content::BrowserContext* context) { DCHECK_CURRENTLY_ON(BrowserThread::UI); return CookieSettingsFactory::GetForProfile( Profile::FromBrowserContext(context)) - ->IsCookieAccessAllowed(manifest_url, first_party); + ->IsCookieAccessAllowed(manifest_url, site_for_cookies, top_frame_origin); } content::AllowServiceWorkerResult @@ -2489,7 +2490,7 @@ base::OnceCallback<void(bool)> callback) { Profile* profile = Profile::FromBrowserContext(browser_context); auto cookie_settings = CookieSettingsFactory::GetForProfile(profile); - bool allow = cookie_settings->IsCookieAccessAllowed(url, url); + bool allow = cookie_settings->IsCookieAccessAllowed(url, url, base::nullopt); #if BUILDFLAG(ENABLE_EXTENSIONS) GuestPermissionRequestHelper(url, render_frames, std::move(callback), allow); @@ -2555,7 +2556,7 @@ Profile* profile = Profile::FromBrowserContext(browser_context); auto cookie_settings = CookieSettingsFactory::GetForProfile(profile); - bool allow = cookie_settings->IsCookieAccessAllowed(url, url); + bool allow = cookie_settings->IsCookieAccessAllowed(url, url, base::nullopt); // Record access to IndexedDB for potential display in UI. for (const auto& it : render_frames) { @@ -2572,7 +2573,7 @@ const std::vector<content::GlobalFrameRoutingId>& render_frames) { Profile* profile = Profile::FromBrowserContext(browser_context); auto cookie_settings = CookieSettingsFactory::GetForProfile(profile); - bool allow = cookie_settings->IsCookieAccessAllowed(url, url); + bool allow = cookie_settings->IsCookieAccessAllowed(url, url, base::nullopt); // Record access to CacheStorage for potential display in UI. for (const auto& it : render_frames) { @@ -2589,7 +2590,7 @@ const std::vector<content::GlobalFrameRoutingId>& render_frames) { Profile* profile = Profile::FromBrowserContext(browser_context); auto cookie_settings = CookieSettingsFactory::GetForProfile(profile); - return cookie_settings->IsCookieAccessAllowed(url, url); + return cookie_settings->IsCookieAccessAllowed(url, url, base::nullopt); } ChromeContentBrowserClient::AllowWebBluetoothResult @@ -3699,16 +3700,6 @@ ->GetPolicies(policy::PolicyNamespace(policy::POLICY_DOMAIN_CHROME, std::string())); -#if defined(OS_WIN) - const base::Value* force_network_in_process_value = - policies.GetValue(policy::key::kForceNetworkInProcess); - bool force_network_in_process = false; - if (force_network_in_process_value) - force_network_in_process_value->GetAsBoolean(&force_network_in_process); - if (force_network_in_process) - content::ForceInProcessNetworkService(true); -#endif - service_manager::EnableAudioSandbox(ShouldEnableAudioSandbox(policies)); } #endif
diff --git a/chrome/browser/chrome_content_browser_client.h b/chrome/browser/chrome_content_browser_client.h index 9bf5aae..2a6c2428 100644 --- a/chrome/browser/chrome_content_browser_client.h +++ b/chrome/browser/chrome_content_browser_client.h
@@ -220,7 +220,9 @@ content::BrowserContext* browser_context, blink::mojom::RendererPreferences* out_prefs) override; bool AllowAppCache(const GURL& manifest_url, - const GURL& first_party, + + const GURL& site_for_cookies, + const base::Optional<url::Origin>& top_frame_origin, content::BrowserContext* context) override; content::AllowServiceWorkerResult AllowServiceWorkerOnIO( const GURL& scope,
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn index c2889ac..fca1f91 100644 --- a/chrome/browser/chromeos/BUILD.gn +++ b/chrome/browser/chromeos/BUILD.gn
@@ -794,6 +794,8 @@ "cert_provisioning/cert_provisioning_common.h", "cert_provisioning/cert_provisioning_invalidator.cc", "cert_provisioning/cert_provisioning_invalidator.h", + "cert_provisioning/cert_provisioning_metrics.cc", + "cert_provisioning/cert_provisioning_metrics.h", "cert_provisioning/cert_provisioning_platform_keys_helpers.cc", "cert_provisioning/cert_provisioning_platform_keys_helpers.h", "cert_provisioning/cert_provisioning_scheduler.cc",
diff --git a/chrome/browser/chromeos/app_mode/app_session.cc b/chrome/browser/chromeos/app_mode/app_session.cc index 9f63527c..fb6b87f 100644 --- a/chrome/browser/chromeos/app_mode/app_session.cc +++ b/chrome/browser/chromeos/app_mode/app_session.cc
@@ -175,8 +175,13 @@ browser->tab_strip_model()->GetActiveWebContents(); std::string url_string = active_tab ? active_tab->GetURL().spec() : std::string(); + bool app_browser = browser->is_type_app() || browser->is_type_app_popup() || + browser->is_type_popup(); - if (KioskSettingsNavigationThrottle::IsSettingsPage(url_string)) { + // The browser has to be of type TYPE_APP, TYPE_POPUP or TYPE_APP_POPUP, + // since they do not have visible tab strip. + if (app_browser && + KioskSettingsNavigationThrottle::IsSettingsPage(url_string)) { if (app_session_->settings_browser_ && browser != app_session_->settings_browser_) { // Navigate to this page in the old browser, the current one will be
diff --git a/chrome/browser/chromeos/apps/intent_helper/chromeos_apps_navigation_throttle.cc b/chrome/browser/chromeos/apps/intent_helper/chromeos_apps_navigation_throttle.cc index 5c6b3603..4718726 100644 --- a/chrome/browser/chromeos/apps/intent_helper/chromeos_apps_navigation_throttle.cc +++ b/chrome/browser/chromeos/apps/intent_helper/chromeos_apps_navigation_throttle.cc
@@ -7,7 +7,6 @@ #include <utility> #include "base/bind.h" -#include "base/metrics/histogram_macros.h" #include "base/task/post_task.h" #include "chrome/browser/apps/intent_helper/apps_navigation_types.h" #include "chrome/browser/apps/intent_helper/intent_picker_auto_display_service.h" @@ -21,7 +20,6 @@ #include "chrome/browser/ui/browser_window.h" #include "chromeos/constants/chromeos_switches.h" #include "components/arc/intent_helper/arc_intent_helper_bridge.h" -#include "components/arc/metrics/arc_metrics_constants.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h"
diff --git a/chrome/browser/chromeos/apps/intent_helper/common_apps_navigation_throttle.cc b/chrome/browser/chromeos/apps/intent_helper/common_apps_navigation_throttle.cc index 4928b77..ececd5c 100644 --- a/chrome/browser/chromeos/apps/intent_helper/common_apps_navigation_throttle.cc +++ b/chrome/browser/chromeos/apps/intent_helper/common_apps_navigation_throttle.cc
@@ -13,6 +13,7 @@ #include "chrome/browser/apps/app_service/launch_utils.h" #include "chrome/browser/apps/intent_helper/apps_navigation_types.h" #include "chrome/browser/apps/intent_helper/intent_picker_auto_display_service.h" +#include "chrome/browser/chromeos/apps/metrics/intent_handling_metrics.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/intent_picker_tab_helper.h" #include "chrome/common/chrome_features.h" @@ -130,6 +131,14 @@ url, launch_source, display::kDefaultDisplayId); CloseOrGoBack(web_contents); } + + apps::AppsNavigationThrottle::PickerAction action = + apps::AppsNavigationThrottle::GetPickerAction(entry_type, close_reason, + should_persist); + apps::AppsNavigationThrottle::Platform platform = + apps::AppsNavigationThrottle::GetDestinationPlatform(launch_name, action); + apps::IntentHandlingMetrics::RecordIntentPickerMetrics( + apps::Source::kHttpOrHttps, should_persist, action, platform); } // static
diff --git a/chrome/browser/chromeos/cert_provisioning/cert_provisioning_common.cc b/chrome/browser/chromeos/cert_provisioning/cert_provisioning_common.cc index 337937f6..c29a375 100644 --- a/chrome/browser/chromeos/cert_provisioning/cert_provisioning_common.cc +++ b/chrome/browser/chromeos/cert_provisioning/cert_provisioning_common.cc
@@ -42,6 +42,18 @@ } } // namespace +bool IsFinalState(CertProvisioningWorkerState state) { + switch (state) { + case CertProvisioningWorkerState::kSucceeded: + case CertProvisioningWorkerState::kInconsistentDataError: + case CertProvisioningWorkerState::kFailed: + case CertProvisioningWorkerState::kCanceled: + return true; + default: + return false; + } +} + //===================== CertProfile ============================================ base::Optional<CertProfile> CertProfile::MakeFromValue(
diff --git a/chrome/browser/chromeos/cert_provisioning/cert_provisioning_common.h b/chrome/browser/chromeos/cert_provisioning/cert_provisioning_common.h index 71a996e..c2762ce 100644 --- a/chrome/browser/chromeos/cert_provisioning/cert_provisioning_common.h +++ b/chrome/browser/chromeos/cert_provisioning/cert_provisioning_common.h
@@ -37,7 +37,8 @@ // Numeric values are used in serialization and should not be remapped. enum class CertScope { kUser = 0, kDevice = 1, kMaxValue = kDevice }; -// These values are used in serialization and should be changed carefully. +// These values are used in serialization and should be changed carefully. Also +// enums.xml should be updated. enum class CertProvisioningWorkerState { kInitState = 0, kKeypairGenerated = 1, @@ -47,13 +48,17 @@ kKeypairMarked = 5, kSignCsrFinished = 6, kFinishCsrResponseReceived = 7, - kSucceed = 8, + kSucceeded = 8, kInconsistentDataError = 9, kFailed = 10, kCanceled = 11, kMaxValue = kCanceled, }; +// Returns true if the |state| is one of final states, i. e. worker should +// finish its task in one of them. +bool IsFinalState(CertProvisioningWorkerState state); + using CertProfileId = std::string; // Names of CertProfile fields in a base::Value representation. Must be in sync
diff --git a/chrome/browser/chromeos/cert_provisioning/cert_provisioning_metrics.cc b/chrome/browser/chromeos/cert_provisioning/cert_provisioning_metrics.cc new file mode 100644 index 0000000..ac1ef7b --- /dev/null +++ b/chrome/browser/chromeos/cert_provisioning/cert_provisioning_metrics.cc
@@ -0,0 +1,75 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/chromeos/cert_provisioning/cert_provisioning_metrics.h" + +#include "base/metrics/histogram_functions.h" +#include "base/notreached.h" +#include "chrome/browser/chromeos/cert_provisioning/cert_provisioning_common.h" + +namespace chromeos { +namespace cert_provisioning { + +#define CP_RESULT "ChromeOS.CertProvisioning.Result" +#define CP_EVENT "ChromeOS.CertProvisioning.Event" +#define CP_KEYPAIR_GENERATION_TIME \ + "ChromeOS.CertProvisioning.KeypairGenerationTime" +#define CP_VA_TIME "ChromeOS.CertProvisioning.VaTime" +#define CP_CSR_SIGN_TIME "ChromeOS.CertProvisioning.CsrSignTime" + +#define CP_USER ".User" +#define CP_DEVICE ".Device" + +namespace { +// "*.User" should have index 0, "*.Device" should have index 1 (same as values +// of CertScope). +const char* const kResult[] = {CP_RESULT CP_USER, CP_RESULT CP_DEVICE}; +const char* const kEvent[] = {CP_EVENT CP_USER, CP_EVENT CP_DEVICE}; +const char* const kKeypairGenerationTime[] = { + CP_KEYPAIR_GENERATION_TIME CP_USER, CP_KEYPAIR_GENERATION_TIME CP_DEVICE}; +const char* const kVaTime[] = {CP_VA_TIME CP_USER, CP_VA_TIME CP_DEVICE}; +const char* const kSignCsrTime[] = {CP_CSR_SIGN_TIME CP_USER, + CP_CSR_SIGN_TIME CP_DEVICE}; + +// CertScope has stable indexes because it is also used for serialization. +constexpr int ToIdx(CertScope scope) { + static_assert(static_cast<int>(CertScope::kMaxValue) == 1, + "CertScope was modified, update arrays with metric names"); + return static_cast<int>(scope); +} +} // namespace + +void RecordResult(CertScope scope, + CertProvisioningWorkerState final_state, + CertProvisioningWorkerState prev_state) { + base::UmaHistogramEnumeration(kResult[ToIdx(scope)], final_state); + if (final_state == CertProvisioningWorkerState::kFailed) { + base::UmaHistogramEnumeration(kResult[ToIdx(scope)], prev_state); + } +} + +void RecordEvent(CertScope scope, CertProvisioningEvent event) { + base::UmaHistogramEnumeration(kEvent[ToIdx(scope)], event); +} + +void RecordKeypairGenerationTime(CertScope scope, base::TimeDelta sample) { + base::UmaHistogramCustomTimes(kKeypairGenerationTime[ToIdx(scope)], sample, + base::TimeDelta::FromMilliseconds(1), + base::TimeDelta::FromMinutes(2), 25); +} + +void RecordVerifiedAccessTime(CertScope scope, base::TimeDelta sample) { + base::UmaHistogramCustomTimes(kVaTime[ToIdx(scope)], sample, + base::TimeDelta::FromMilliseconds(1), + base::TimeDelta::FromMinutes(2), 25); +} + +void RecordCsrSignTime(CertScope scope, base::TimeDelta sample) { + base::UmaHistogramCustomTimes(kSignCsrTime[ToIdx(scope)], sample, + base::TimeDelta::FromMilliseconds(1), + base::TimeDelta::FromMinutes(2), 25); +} + +} // namespace cert_provisioning +} // namespace chromeos
diff --git a/chrome/browser/chromeos/cert_provisioning/cert_provisioning_metrics.h b/chrome/browser/chromeos/cert_provisioning/cert_provisioning_metrics.h new file mode 100644 index 0000000..20f8cf3 --- /dev/null +++ b/chrome/browser/chromeos/cert_provisioning/cert_provisioning_metrics.h
@@ -0,0 +1,56 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_CHROMEOS_CERT_PROVISIONING_CERT_PROVISIONING_METRICS_H_ +#define CHROME_BROWSER_CHROMEOS_CERT_PROVISIONING_CERT_PROVISIONING_METRICS_H_ + +#include "base/time/time.h" +#include "chrome/browser/chromeos/cert_provisioning/cert_provisioning_common.h" + +namespace chromeos { +namespace cert_provisioning { + +// The enum is used for UMA, the values should not be renumerated. +enum class CertProvisioningEvent { + // Some worker tried to register(or reregister) for invalidation topic. + kRegisteredToInvalidationTopic = 0, + // Invalidation received. + kInvalidationReceived = 1, + // Some worker retried to continue without invalidation. + kWorkerRetryWithoutInvalidation = 2, + // Some worker retried to continue without invalidation and made some + // progress. + kWorkerRetrySucceededWithoutInvalidation = 3, + // Profile retried manually from UI. + kWorkerRetryManual = 4, + kWorkerCreated = 5, + kWorkerDeserialized = 6, + kWorkerDeserializationFailed = 7, + kMaxValue = kWorkerDeserializationFailed +}; + +// Records the |final_state| of a worker. If the worker is failed, also records +// its |prev_state| into the same histogram. It is reasonable to put both of +// them in the same histogram because the worker should never stop on an +// intermediate state and even if it does, it is the same as failure. +void RecordResult(CertScope scope, + CertProvisioningWorkerState final_state, + CertProvisioningWorkerState prev_state); + +void RecordEvent(CertScope scope, CertProvisioningEvent event); + +// Records time of generation key pair by certificate provisioning worker. +void RecordKeypairGenerationTime(CertScope scope, base::TimeDelta sample); + +// Records time of building Verified Access response by certificate provisioning +// worker. +void RecordVerifiedAccessTime(CertScope scope, base::TimeDelta sample); + +// Records time of signing a CSR by certificate provisioning worker. +void RecordCsrSignTime(CertScope scope, base::TimeDelta sample); + +} // namespace cert_provisioning +} // namespace chromeos + +#endif // CHROME_BROWSER_CHROMEOS_CERT_PROVISIONING_CERT_PROVISIONING_METRICS_H_
diff --git a/chrome/browser/chromeos/cert_provisioning/cert_provisioning_scheduler.cc b/chrome/browser/chromeos/cert_provisioning/cert_provisioning_scheduler.cc index 3c8db9b5..ccd640a 100644 --- a/chrome/browser/chromeos/cert_provisioning/cert_provisioning_scheduler.cc +++ b/chrome/browser/chromeos/cert_provisioning/cert_provisioning_scheduler.cc
@@ -15,6 +15,7 @@ #include "chrome/browser/browser_process.h" #include "chrome/browser/browser_process_platform_part.h" #include "chrome/browser/chromeos/cert_provisioning/cert_provisioning_common.h" +#include "chrome/browser/chromeos/cert_provisioning/cert_provisioning_metrics.h" #include "chrome/browser/chromeos/cert_provisioning/cert_provisioning_worker.h" #include "chrome/browser/chromeos/platform_keys/platform_keys_service.h" #include "chrome/browser/chromeos/platform_keys/platform_keys_service_factory.h" @@ -25,6 +26,7 @@ #include "chromeos/network/network_handler.h" #include "chromeos/network/network_state_handler.h" #include "components/prefs/pref_service.h" +#include "content/public/browser/browser_thread.h" namespace chromeos { namespace cert_provisioning { @@ -169,19 +171,19 @@ } CertProvisioningScheduler::~CertProvisioningScheduler() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); network_state_handler_->RemoveObserver(this, FROM_HERE); } void CertProvisioningScheduler::ScheduleInitialUpdate() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); base::SequencedTaskRunnerHandle::Get()->PostTask( FROM_HERE, base::Bind(&CertProvisioningScheduler::InitialUpdateCerts, weak_factory_.GetWeakPtr())); } void CertProvisioningScheduler::ScheduleDailyUpdate() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); base::SequencedTaskRunnerHandle::Get()->PostDelayedTask( FROM_HERE, base::Bind(&CertProvisioningScheduler::DailyUpdateCerts, @@ -190,7 +192,7 @@ } void CertProvisioningScheduler::ScheduleRetry(const CertProfile& profile) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); base::SequencedTaskRunnerHandle::Get()->PostDelayedTask( FROM_HERE, base::Bind(&CertProvisioningScheduler::ProcessProfile, @@ -199,13 +201,13 @@ } void CertProvisioningScheduler::InitialUpdateCerts() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); DeleteCertsWithoutPolicy(); } void CertProvisioningScheduler::DeleteCertsWithoutPolicy() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); std::vector<CertProfile> profiles = GetCertProfiles(); std::set<std::string> cert_profile_ids_to_keep; @@ -222,7 +224,7 @@ void CertProvisioningScheduler::OnDeleteCertsWithoutPolicyDone( const std::string& error_message) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); cert_deleter_.reset(); @@ -237,7 +239,7 @@ } void CertProvisioningScheduler::CleanVaKeysIfIdle() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); if (!workers_.empty()) { OnCleanVaKeysIfIdleDone(true); @@ -252,7 +254,7 @@ void CertProvisioningScheduler::OnCleanVaKeysIfIdleDone( base::Optional<bool> delete_result) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); if (!delete_result.has_value() || !delete_result.value()) { LOG(ERROR) << "Failed to delete keys while idle"; @@ -263,7 +265,7 @@ } void CertProvisioningScheduler::RegisterForPrefsChanges() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); pref_change_registrar_.Init(pref_service_); pref_change_registrar_.Add( @@ -272,7 +274,7 @@ } void CertProvisioningScheduler::DailyUpdateCerts() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); failed_cert_profiles_.clear(); UpdateCerts(); @@ -280,7 +282,7 @@ } void CertProvisioningScheduler::DeserializeWorkers() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); const base::Value* saved_workers = pref_service_->Get(GetPrefNameForSerialization(cert_scope_)); @@ -307,13 +309,16 @@ } void CertProvisioningScheduler::OnPrefsChange() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); UpdateCerts(); } void CertProvisioningScheduler::UpdateOneCert( const std::string& cert_profile_id) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + + RecordEvent(cert_scope_, CertProvisioningEvent::kWorkerRetryManual); + if (!CheckInternetConnection()) { return; } @@ -327,7 +332,7 @@ } void CertProvisioningScheduler::UpdateCerts() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); if (!CheckInternetConnection()) { return; @@ -351,7 +356,7 @@ std::map<std::string, scoped_refptr<net::X509Certificate>> existing_certs_with_ids, const std::string& error_message) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); certs_with_ids_getter_.reset(); @@ -362,7 +367,7 @@ std::vector<CertProfile> profiles = GetCertProfiles(); - DeleteWorkersWithoutPolicy(profiles); + CancelWorkersWithoutPolicy(profiles); for (const auto& profile : profiles) { if (base::Contains(existing_certs_with_ids, profile.profile_id) || @@ -376,17 +381,23 @@ void CertProvisioningScheduler::ProcessProfile( const CertProfile& cert_profile) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); CertProvisioningWorker* worker = FindWorker(cert_profile.profile_id); - if (!worker || (worker->GetCertProfile().policy_version != - cert_profile.policy_version)) { - EraseKey(failed_cert_profiles_, cert_profile.profile_id); - // Create new worker or replace an existing one. + if (!worker) { CreateCertProvisioningWorker(cert_profile); return; } + if ((worker->GetCertProfile().policy_version != + cert_profile.policy_version)) { + // The worker has outdated policy version. Make it stop, clean up current + // state and report back through its callback. That will trigger retry for + // its certificate profile. + worker->Stop(CertProvisioningWorkerState::kInconsistentDataError); + return; + } + if (worker->IsWaiting()) { worker->DoStep(); return; @@ -398,7 +409,7 @@ void CertProvisioningScheduler::CreateCertProvisioningWorker( CertProfile cert_profile) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); std::unique_ptr<CertProvisioningWorker> worker = CertProvisioningWorkerFactory::Get()->Create( @@ -414,7 +425,7 @@ void CertProvisioningScheduler::OnProfileFinished( const CertProfile& profile, CertProvisioningWorkerState state) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); auto worker_iter = workers_.find(profile.profile_id); if (worker_iter == workers_.end()) { @@ -424,7 +435,7 @@ } switch (state) { - case CertProvisioningWorkerState::kSucceed: + case CertProvisioningWorkerState::kSucceeded: VLOG(0) << "Successfully provisioned certificate for profile: " << profile.profile_id; break; @@ -433,6 +444,8 @@ << profile.profile_id; ScheduleRetry(profile); break; + case CertProvisioningWorkerState::kCanceled: + break; default: LOG(ERROR) << "Failed to process certificate profile: " << profile.profile_id; @@ -445,7 +458,7 @@ CertProvisioningWorker* CertProvisioningScheduler::FindWorker( CertProfileId profile_id) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); auto iter = workers_.find(profile_id); if (iter == workers_.end()) { @@ -457,7 +470,7 @@ base::Optional<CertProfile> CertProvisioningScheduler::GetOneCertProfile( const std::string& cert_profile_id) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); const base::Value* profile_list = pref_service_->Get(pref_name_); if (!profile_list) { @@ -478,7 +491,7 @@ } std::vector<CertProfile> CertProvisioningScheduler::GetCertProfiles() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); const base::Value* profile_list = pref_service_->Get(pref_name_); if (!profile_list) { @@ -501,18 +514,18 @@ } const WorkerMap& CertProvisioningScheduler::GetWorkers() const { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); return workers_; } const std::map<std::string, FailedWorkerInfo>& CertProvisioningScheduler::GetFailedCertProfileIds() const { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); return failed_cert_profiles_; } bool CertProvisioningScheduler::CheckInternetConnection() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); const NetworkState* network = network_state_handler_->DefaultNetwork(); bool is_online = network && network->IsOnline(); is_waiting_for_online_ = !is_online; @@ -521,7 +534,7 @@ void CertProvisioningScheduler::OnNetworkChange( const chromeos::NetworkState* network) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); if (is_waiting_for_online_ && network && network->IsOnline()) { UpdateCerts(); } @@ -529,19 +542,19 @@ void CertProvisioningScheduler::DefaultNetworkChanged( const chromeos::NetworkState* network) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); OnNetworkChange(network); } void CertProvisioningScheduler::NetworkConnectionStateChanged( const chromeos::NetworkState* network) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); OnNetworkChange(network); } void CertProvisioningScheduler::UpdateFailedCertProfiles( const CertProvisioningWorker& worker) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); FailedWorkerInfo info; info.state = worker.GetPreviousState(); info.public_key = worker.GetPublicKey(); @@ -549,9 +562,9 @@ failed_cert_profiles_[worker.GetCertProfile().profile_id] = std::move(info); } -void CertProvisioningScheduler::DeleteWorkersWithoutPolicy( +void CertProvisioningScheduler::CancelWorkersWithoutPolicy( const std::vector<CertProfile>& profiles) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); if (workers_.empty()) { return; @@ -562,14 +575,13 @@ cert_profile_ids.insert(profile.profile_id); } - for (auto iter = workers_.begin(); iter != workers_.end();) { - const auto& worker = iter->second; - if (cert_profile_ids.find(worker->GetCertProfile().profile_id) == + for (auto& kv : workers_) { + auto& worker_ptr = kv.second; + if (cert_profile_ids.find(worker_ptr->GetCertProfile().profile_id) == cert_profile_ids.end()) { - worker->Cancel(); - iter = workers_.erase(iter); - } else { - ++iter; + // This will trigger clean up (if any) in the worker and make it call its + // callback. + worker_ptr->Stop(CertProvisioningWorkerState::kCanceled); } } }
diff --git a/chrome/browser/chromeos/cert_provisioning/cert_provisioning_scheduler.h b/chrome/browser/chromeos/cert_provisioning/cert_provisioning_scheduler.h index e87d5d1d..4a95879f 100644 --- a/chrome/browser/chromeos/cert_provisioning/cert_provisioning_scheduler.h +++ b/chrome/browser/chromeos/cert_provisioning/cert_provisioning_scheduler.h
@@ -46,6 +46,9 @@ // This class is a part of certificate provisioning feature. It tracks updates // of |RequiredClientCertificateForUser|, |RequiredClientCertificateForDevice| // policies and creates one CertProvisioningWorker for every policy entry. +// Should work on the UI thread because it interacts with PlatformKeysService +// and some methods are called from the UI to populate certificate manager +// settings page. class CertProvisioningScheduler : public NetworkStateHandlerObserver { public: static std::unique_ptr<CertProvisioningScheduler> @@ -68,7 +71,8 @@ CertProvisioningScheduler(const CertProvisioningScheduler&) = delete; CertProvisioningScheduler& operator=(const CertProvisioningScheduler&) = delete; - + // Intended to be called when a user press a button in certificate manager UI. + // Retries provisioning of a specific certificate. void UpdateOneCert(const std::string& cert_profile_id); void UpdateCerts(); void OnProfileFinished(const CertProfile& profile, @@ -87,7 +91,7 @@ void InitialUpdateCerts(); void DeleteCertsWithoutPolicy(); void OnDeleteCertsWithoutPolicyDone(const std::string& error_message); - void DeleteWorkersWithoutPolicy(const std::vector<CertProfile>& profiles); + void CancelWorkersWithoutPolicy(const std::vector<CertProfile>& profiles); void CleanVaKeysIfIdle(); void OnCleanVaKeysIfIdleDone(base::Optional<bool> delete_result); void RegisterForPrefsChanges(); @@ -144,7 +148,6 @@ std::unique_ptr<CertProvisioningCertDeleter> cert_deleter_; std::unique_ptr<CertProvisioningInvalidatorFactory> invalidator_factory_; - SEQUENCE_CHECKER(sequence_checker_); base::WeakPtrFactory<CertProvisioningScheduler> weak_factory_{this}; };
diff --git a/chrome/browser/chromeos/cert_provisioning/cert_provisioning_scheduler_unittest.cc b/chrome/browser/chromeos/cert_provisioning/cert_provisioning_scheduler_unittest.cc index 5b3e899..912c2e4 100644 --- a/chrome/browser/chromeos/cert_provisioning/cert_provisioning_scheduler_unittest.cc +++ b/chrome/browser/chromeos/cert_provisioning/cert_provisioning_scheduler_unittest.cc
@@ -242,7 +242,7 @@ // Emulate callback from the worker. scheduler.OnProfileFinished(cert_profile, - CertProvisioningWorkerState::kSucceed); + CertProvisioningWorkerState::kSucceeded); // Finished worker should be deleted. EXPECT_EQ(scheduler.GetWorkers().size(), 0U); @@ -392,7 +392,7 @@ ASSERT_EQ(scheduler.GetWorkers().size(), 1U); // Emulate callback from the worker. - scheduler.OnProfileFinished(profile, CertProvisioningWorkerState::kSucceed); + scheduler.OnProfileFinished(profile, CertProvisioningWorkerState::kSucceeded); ASSERT_EQ(scheduler.GetWorkers().size(), 0U); EXPECT_TRUE(scheduler.GetFailedCertProfileIds().empty()); @@ -471,7 +471,7 @@ // worker0 successfully finished. Should be just deleted. scheduler.OnProfileFinished(cert_profile0, - CertProvisioningWorkerState::kSucceed); + CertProvisioningWorkerState::kSucceeded); // worker1 is waiting. Should be continued. worker1->SetExpectations(/*do_step_times=*/AtLeast(1), /*is_waiting=*/true, @@ -605,7 +605,6 @@ const char kCertProfileId[] = "cert_profile_id_1"; const char kCertProfileVersion1[] = "cert_profile_version_1"; const char kCertProfileVersion2[] = "cert_profile_version_2"; - const char kCertProfileVersion3[] = "cert_profile_version_3"; CertProvisioningScheduler scheduler( cert_scope, GetProfile(), &pref_service_, @@ -689,12 +688,6 @@ scheduler.UpdateCerts(); EXPECT_EQ(scheduler.GetWorkers().size(), 1U); - // Add a new worker to the factory. - CertProfile cert_profile_v3{kCertProfileId, kCertProfileVersion3}; - worker = mock_factory_.ExpectCreateReturnMock(cert_scope, cert_profile_v3); - worker->SetExpectations(/*do_step_times=*/AtLeast(1), /*is_waiting=*/false, - cert_profile_v3); - // On policy update if existing profile has changed its policy_version, // scheduler should recreate the worker for it. config = ParseJson( @@ -703,8 +696,20 @@ "policy_version":"cert_profile_version_3", "key_algorithm":"rsa", "renewal_period_seconds": 365000}])"); + + // On policy change scheduler should detect mismatch in policy versions and + // stop the worker. + EXPECT_CALL(*worker, + Stop(CertProvisioningWorkerState::kInconsistentDataError)); + pref_service_.Set(prefs::kRequiredClientCertificateForDevice, config); - EXPECT_EQ(scheduler.GetWorkers().size(), 1U); + // EXPECT_EQ(scheduler.GetWorkers().size(), 1U); + + // Emulate that after some time the worker reports back to scheduler. + FastForwardBy(base::TimeDelta::FromSeconds(10)); + scheduler.OnProfileFinished( + cert_profile_v1, CertProvisioningWorkerState::kInconsistentDataError); + EXPECT_EQ(scheduler.GetWorkers().size(), 0U); } TEST_F(CertProvisioningSchedulerTest, RetryAfterNoInternetConnection) { @@ -791,11 +796,16 @@ FastForwardBy(base::TimeDelta::FromSeconds(1)); EXPECT_EQ(scheduler.GetWorkers().size(), 1U); - EXPECT_CALL(*worker, Cancel); + EXPECT_CALL(*worker, Stop(CertProvisioningWorkerState::kCanceled)); config = ParseJson("[]"); pref_service_.Set(prefs::kRequiredClientCertificateForDevice, config); + FastForwardBy(base::TimeDelta::FromSeconds(1)); + // Emulate callback from the worker. + scheduler.OnProfileFinished(cert_profile, + CertProvisioningWorkerState::kCanceled); + ASSERT_EQ(scheduler.GetWorkers().size(), 0U); }
diff --git a/chrome/browser/chromeos/cert_provisioning/cert_provisioning_worker.cc b/chrome/browser/chromeos/cert_provisioning/cert_provisioning_worker.cc index 89ef6a1..58ba7df 100644 --- a/chrome/browser/chromeos/cert_provisioning/cert_provisioning_worker.cc +++ b/chrome/browser/chromeos/cert_provisioning/cert_provisioning_worker.cc
@@ -8,9 +8,11 @@ #include "base/bind.h" #include "base/bind_helpers.h" #include "base/no_destructor.h" +#include "base/time/time.h" #include "chrome/browser/chromeos/attestation/tpm_challenge_key_result.h" #include "chrome/browser/chromeos/cert_provisioning/cert_provisioning_common.h" #include "chrome/browser/chromeos/cert_provisioning/cert_provisioning_invalidator.h" +#include "chrome/browser/chromeos/cert_provisioning/cert_provisioning_metrics.h" #include "chrome/browser/chromeos/cert_provisioning/cert_provisioning_serializer.h" #include "chrome/browser/chromeos/platform_keys/platform_keys_service.h" #include "chrome/browser/chromeos/platform_keys/platform_keys_service_factory.h" @@ -94,7 +96,7 @@ case CertProvisioningWorkerState::kFinishCsrResponseReceived: res -= 1; FALLTHROUGH; - case CertProvisioningWorkerState::kSucceed: + case CertProvisioningWorkerState::kSucceeded: case CertProvisioningWorkerState::kInconsistentDataError: case CertProvisioningWorkerState::kFailed: case CertProvisioningWorkerState::kCanceled: @@ -128,6 +130,7 @@ policy::CloudPolicyClient* cloud_policy_client, std::unique_ptr<CertProvisioningInvalidator> invalidator, CertProvisioningWorkerCallback callback) { + RecordEvent(cert_scope, CertProvisioningEvent::kWorkerCreated); return std::make_unique<CertProvisioningWorkerImpl>( cert_scope, profile, pref_service, cert_profile, cloud_policy_client, std::move(invalidator), std::move(callback)); @@ -147,8 +150,11 @@ std::move(invalidator), std::move(callback)); if (!CertProvisioningSerializer::DeserializeWorker(saved_worker, worker.get())) { + RecordEvent(cert_scope, + CertProvisioningEvent::kWorkerDeserializationFailed); return {}; } + RecordEvent(cert_scope, CertProvisioningEvent::kWorkerDeserialized); return worker; } @@ -219,7 +225,7 @@ case CertProvisioningWorkerState::kFinishCsrResponseReceived: DownloadCert(); return; - case CertProvisioningWorkerState::kSucceed: + case CertProvisioningWorkerState::kSucceeded: case CertProvisioningWorkerState::kInconsistentDataError: case CertProvisioningWorkerState::kFailed: case CertProvisioningWorkerState::kCanceled: @@ -229,9 +235,12 @@ NOTREACHED() << " " << static_cast<uint>(state_); } -void CertProvisioningWorkerImpl::Cancel() { +void CertProvisioningWorkerImpl::Stop(CertProvisioningWorkerState state) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - UpdateState(CertProvisioningWorkerState::kCanceled); + DCHECK(IsFinalState(state)); + + CancelScheduledTasks(); + UpdateState(state); } void CertProvisioningWorkerImpl::UpdateState( @@ -242,10 +251,17 @@ prev_state_ = state_; state_ = new_state; + if (is_continued_without_invalidation_for_uma_) { + RecordEvent( + cert_scope_, + CertProvisioningEvent::kWorkerRetrySucceededWithoutInvalidation); + is_continued_without_invalidation_for_uma_ = false; + } + HandleSerialization(); - if (IsFinished()) { - CleanUpAndMaybeRunCallback(); + if (IsFinalState(state_)) { + CleanUpAndRunCallback(); } } @@ -259,13 +275,16 @@ GetVaKeyName(cert_scope_, cert_profile_.profile_id), profile_, GetVaKeyNameForSpkac(cert_scope_, cert_profile_.profile_id), base::BindOnce(&CertProvisioningWorkerImpl::OnGenerateKeyDone, - weak_factory_.GetWeakPtr())); + weak_factory_.GetWeakPtr(), base::TimeTicks::Now())); } void CertProvisioningWorkerImpl::OnGenerateKeyDone( + base::TimeTicks start_time, const attestation::TpmChallengeKeyResult& result) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + RecordKeypairGenerationTime(cert_scope_, base::TimeTicks::Now() - start_time); + if (result.result_code == attestation::TpmChallengeKeyResultCode::kGetCertificateFailedError) { LOG(WARNING) << "Failed to get certificate for a key"; @@ -339,13 +358,16 @@ va_challenge_, /*include_signed_public_key=*/true, base::BindOnce( &CertProvisioningWorkerImpl::OnBuildVaChallengeResponseDone, - weak_factory_.GetWeakPtr())); + weak_factory_.GetWeakPtr(), base::TimeTicks::Now())); } void CertProvisioningWorkerImpl::OnBuildVaChallengeResponseDone( + base::TimeTicks start_time, const attestation::TpmChallengeKeyResult& result) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + RecordVerifiedAccessTime(cert_scope_, base::TimeTicks::Now() - start_time); + if (!result.IsSuccess()) { LOG(ERROR) << "Failed to build challenge response: " << result.GetErrorMessage(); @@ -425,14 +447,17 @@ GetPlatformKeysTokenId(cert_scope_), csr_, public_key_, hashing_algorithm_.value(), base::BindRepeating(&CertProvisioningWorkerImpl::OnSignCsrDone, - weak_factory_.GetWeakPtr())); + weak_factory_.GetWeakPtr(), base::TimeTicks::Now())); } void CertProvisioningWorkerImpl::OnSignCsrDone( + base::TimeTicks start_time, const std::string& signature, const std::string& error_message) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + RecordCsrSignTime(cert_scope_, base::TimeTicks::Now() - start_time); + if (!error_message.empty()) { LOG(ERROR) << "Failed to sign CSR: " << error_message; UpdateState(CertProvisioningWorkerState::kFailed); @@ -521,21 +546,7 @@ return; } - UpdateState(CertProvisioningWorkerState::kSucceed); -} - -bool CertProvisioningWorkerImpl::IsFinished() const { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - - switch (state_) { - case CertProvisioningWorkerState::kSucceed: - case CertProvisioningWorkerState::kInconsistentDataError: - case CertProvisioningWorkerState::kFailed: - case CertProvisioningWorkerState::kCanceled: - return true; - default: - return false; - } + UpdateState(CertProvisioningWorkerState::kSucceeded); } bool CertProvisioningWorkerImpl::IsWaiting() const { @@ -617,19 +628,32 @@ base::SequencedTaskRunnerHandle::Get()->PostDelayedTask( FROM_HERE, base::BindOnce(&CertProvisioningWorkerImpl::OnShouldContinue, - weak_factory_.GetWeakPtr()), + weak_factory_.GetWeakPtr(), ContinueReason::kTimeout), delay); is_waiting_ = true; VLOG(0) << "Next step scheduled in " << delay; } -void CertProvisioningWorkerImpl::OnShouldContinue() { +void CertProvisioningWorkerImpl::OnShouldContinue(ContinueReason reason) { + switch (reason) { + case ContinueReason::kInvalidation: + RecordEvent(cert_scope_, CertProvisioningEvent::kInvalidationReceived); + break; + case ContinueReason::kTimeout: + RecordEvent(cert_scope_, + CertProvisioningEvent::kWorkerRetryWithoutInvalidation); + break; + } + // Worker is already doing something. if (!IsWaiting()) { return; } + is_continued_without_invalidation_for_uma_ = + (reason == ContinueReason::kTimeout); + DoStep(); } @@ -638,13 +662,13 @@ weak_factory_.InvalidateWeakPtrs(); } -void CertProvisioningWorkerImpl::CleanUpAndMaybeRunCallback() { +void CertProvisioningWorkerImpl::CleanUpAndRunCallback() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); UnregisterFromInvalidationTopic(); // Keep conditions mutually exclusive. - if (state_ == CertProvisioningWorkerState::kSucceed) { + if (state_ == CertProvisioningWorkerState::kSucceeded) { // No extra clean up is necessary. OnCleanUpDone(); return; @@ -695,15 +719,13 @@ if (!error_message.empty()) { LOG(ERROR) << "Failed to delete a key: " << error_message; } + OnCleanUpDone(); } void CertProvisioningWorkerImpl::OnCleanUpDone() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - - if (state_ == CertProvisioningWorkerState::kCanceled) { - return; - } + RecordResult(cert_scope_, state_, prev_state_); std::move(callback_).Run(cert_profile_, state_); } @@ -728,7 +750,7 @@ case CertProvisioningWorkerState::kFinishCsrResponseReceived: CertProvisioningSerializer::SerializeWorkerToPrefs(pref_service_, *this); break; - case CertProvisioningWorkerState::kSucceed: + case CertProvisioningWorkerState::kSucceeded: case CertProvisioningWorkerState::kInconsistentDataError: case CertProvisioningWorkerState::kFailed: case CertProvisioningWorkerState::kCanceled: @@ -762,7 +784,11 @@ invalidator_->Register( invalidation_topic_, base::BindRepeating(&CertProvisioningWorkerImpl::OnShouldContinue, - weak_factory_.GetWeakPtr())); + weak_factory_.GetWeakPtr(), + ContinueReason::kInvalidation)); + + RecordEvent(cert_scope_, + CertProvisioningEvent::kRegisteredToInvalidationTopic); } void CertProvisioningWorkerImpl::UnregisterFromInvalidationTopic() {
diff --git a/chrome/browser/chromeos/cert_provisioning/cert_provisioning_worker.h b/chrome/browser/chromeos/cert_provisioning/cert_provisioning_worker.h index f40499c..c1d20cf 100644 --- a/chrome/browser/chromeos/cert_provisioning/cert_provisioning_worker.h +++ b/chrome/browser/chromeos/cert_provisioning/cert_provisioning_worker.h
@@ -75,9 +75,10 @@ // Continue provisioning a certificate. virtual void DoStep() = 0; - // Stops the worker, triggers clean ups (deletes serialized state, keys, and - // so on), Canceled workers will never call the callback. - virtual void Cancel() = 0; + // Sets worker's state to one of final ones. That triggers corresponding + // clean ups (deletes serialized state, keys, and so on) and returns |state| + // via callback. + virtual void Stop(CertProvisioningWorkerState state) = 0; // Returns true, if the worker is waiting for some future event. |DoStep| can // be called to try continue right now. virtual bool IsWaiting() const = 0; @@ -106,7 +107,7 @@ // CertProvisioningWorker void DoStep() override; - void Cancel() override; + void Stop(CertProvisioningWorkerState state) override; bool IsWaiting() const override; const CertProfile& GetCertProfile() const override; const std::string& GetPublicKey() const override; @@ -117,7 +118,8 @@ friend class CertProvisioningSerializer; void GenerateKey(); - void OnGenerateKeyDone(const attestation::TpmChallengeKeyResult& result); + void OnGenerateKeyDone(base::TimeTicks start_time, + const attestation::TpmChallengeKeyResult& result); void StartCsr(); void OnStartCsrDone(policy::DeviceManagementStatus status, @@ -130,6 +132,7 @@ void BuildVaChallengeResponse(); void OnBuildVaChallengeResponseDone( + base::TimeTicks start_time, const attestation::TpmChallengeKeyResult& result); void RegisterKey(); @@ -139,7 +142,8 @@ void OnMarkKeyDone(const std::string& error_message); void SignCsr(); - void OnSignCsrDone(const std::string& signature, + void OnSignCsrDone(base::TimeTicks start_time, + const std::string& signature, const std::string& error_message); void FinishCsr(); @@ -160,7 +164,8 @@ void ScheduleNextStep(base::TimeDelta delay); void CancelScheduledTasks(); - void OnShouldContinue(); + enum class ContinueReason { kTimeout, kInvalidation }; + void OnShouldContinue(ContinueReason reason); // Registers for |invalidation_topic_| that allows to receive notification // when server side is ready to continue provisioning process. @@ -174,7 +179,6 @@ // worker can be destroyed in callback and should not use any member fields // after that. void UpdateState(CertProvisioningWorkerState state); - bool IsFinished() const; // Serializes the worker or deletes serialized state accroding to the current // state. Some states are considered unrecoverable, some can be reached again @@ -184,7 +188,7 @@ // to be called from CertProvisioningDeserializer. void InitAfterDeserialization(); - void CleanUpAndMaybeRunCallback(); + void CleanUpAndRunCallback(); void OnDeleteVaKeyDone(base::Optional<bool> delete_result); void OnRemoveKeyDone(const std::string& error_message); void OnCleanUpDone(); @@ -208,6 +212,9 @@ // on failure. CertProvisioningWorkerState prev_state_ = state_; bool is_waiting_ = false; + // Used for an UMA metric to track situation when the worker did not receive + // an invalidation for a completed server side task. + bool is_continued_without_invalidation_for_uma_ = false; // Calculates retry timeout for network related failures. net::BackoffEntry request_backoff_;
diff --git a/chrome/browser/chromeos/cert_provisioning/cert_provisioning_worker_unittest.cc b/chrome/browser/chromeos/cert_provisioning/cert_provisioning_worker_unittest.cc index 50688f2..25a324f 100644 --- a/chrome/browser/chromeos/cert_provisioning/cert_provisioning_worker_unittest.cc +++ b/chrome/browser/chromeos/cert_provisioning/cert_provisioning_worker_unittest.cc
@@ -8,11 +8,13 @@ #include "base/json/json_string_value_serializer.h" #include "base/json/json_writer.h" #include "base/test/gmock_callback_support.h" +#include "base/test/metrics/histogram_tester.h" #include "base/test/values_test_util.h" #include "base/time/time.h" #include "chrome/browser/chromeos/attestation/mock_tpm_challenge_key_subtle.h" #include "chrome/browser/chromeos/attestation/tpm_challenge_key_subtle.h" #include "chrome/browser/chromeos/cert_provisioning/cert_provisioning_common.h" +#include "chrome/browser/chromeos/cert_provisioning/cert_provisioning_metrics.h" #include "chrome/browser/chromeos/cert_provisioning/cert_provisioning_test_helpers.h" #include "chrome/browser/chromeos/cert_provisioning/mock_cert_provisioning_invalidator.h" #include "chrome/browser/chromeos/platform_keys/mock_platform_keys_service.h" @@ -378,6 +380,8 @@ // Checks that the worker makes all necessary requests to other modules during // success scenario. TEST_F(CertProvisioningWorkerTest, Success) { + base::HistogramTester histogram_tester; + CertProfile cert_profile{kCertProfileId, kCertProfileVersion}; MockTpmChallengeKeySubtle* mock_tpm_challenge_key = PrepareTpmChallengeKey(); @@ -432,11 +436,23 @@ EXPECT_CALL(*mock_invalidator, Unregister()).Times(1); EXPECT_CALL(callback_observer_, - Callback(cert_profile, CertProvisioningWorkerState::kSucceed)) + Callback(cert_profile, CertProvisioningWorkerState::kSucceeded)) .Times(1); } worker.DoStep(); + + histogram_tester.ExpectUniqueSample("ChromeOS.CertProvisioning.Result.User", + CertProvisioningWorkerState::kSucceeded, + 1); + histogram_tester.ExpectUniqueSample( + "ChromeOS.CertProvisioning.Event.User", + CertProvisioningEvent::kRegisteredToInvalidationTopic, 1); + histogram_tester.ExpectTotalCount( + "ChromeOS.CertProvisioning.KeypairGenerationTime.User", 1); + histogram_tester.ExpectTotalCount("ChromeOS.CertProvisioning.VaTime.User", 1); + histogram_tester.ExpectTotalCount( + "ChromeOS.CertProvisioning.CsrSignTime.User", 1); } // Checks that the worker makes all necessary requests to other modules during @@ -487,7 +503,7 @@ platform_keys::kTokenIdUser, /*certificate=*/_, /*callback=*/_)); EXPECT_CALL(callback_observer_, - Callback(cert_profile, CertProvisioningWorkerState::kSucceed)) + Callback(cert_profile, CertProvisioningWorkerState::kSucceeded)) .Times(1); } @@ -586,11 +602,11 @@ platform_keys::kTokenIdSystem, /*certificate=*/_, /*callback=*/_)); EXPECT_CALL(callback_observer_, - Callback(cert_profile, CertProvisioningWorkerState::kSucceed)) + Callback(cert_profile, CertProvisioningWorkerState::kSucceeded)) .Times(1); worker.DoStep(); - EXPECT_EQ(worker.GetState(), CertProvisioningWorkerState::kSucceed); + EXPECT_EQ(worker.GetState(), CertProvisioningWorkerState::kSucceeded); } } @@ -697,10 +713,10 @@ CertProvisioningWorkerState::kFinishCsrResponseReceived); EXPECT_CALL(callback_observer_, - Callback(cert_profile, CertProvisioningWorkerState::kSucceed)) + Callback(cert_profile, CertProvisioningWorkerState::kSucceeded)) .Times(1); FastForwardBy(download_cert_real_delay + small_delay); - EXPECT_EQ(worker.GetState(), CertProvisioningWorkerState::kSucceed); + EXPECT_EQ(worker.GetState(), CertProvisioningWorkerState::kSucceeded); } } @@ -746,6 +762,8 @@ // Checks that when the server returns response error, the worker will enter an // error state and stop the provisioning. Also check factory. TEST_F(CertProvisioningWorkerTest, ResponseErrorHandling) { + base::HistogramTester histogram_tester; + CertProfile cert_profile{kCertProfileId, kCertProfileVersion}; MockTpmChallengeKeySubtle* mock_tpm_challenge_key = PrepareTpmChallengeKey(); @@ -778,6 +796,13 @@ worker->DoStep(); FastForwardBy(TimeDelta::FromSeconds(1)); + + histogram_tester.ExpectBucketCount("ChromeOS.CertProvisioning.Result.User", + CertProvisioningWorkerState::kFailed, 1); + histogram_tester.ExpectBucketCount( + "ChromeOS.CertProvisioning.Result.User", + CertProvisioningWorkerState::kKeypairGenerated, 1); + histogram_tester.ExpectTotalCount("ChromeOS.CertProvisioning.Result.User", 2); } TEST_F(CertProvisioningWorkerTest, InconsistentDataErrorHandling) { @@ -879,6 +904,8 @@ // Checks that the worker removes a key when an error occurs after the key was // registered. TEST_F(CertProvisioningWorkerTest, RemoveRegisteredKey) { + base::HistogramTester histogram_tester; + CertProfile cert_profile{kCertProfileId, kCertProfileVersion}; MockTpmChallengeKeySubtle* mock_tpm_challenge_key = PrepareTpmChallengeKey(); MockCertProvisioningInvalidator* mock_invalidator = nullptr; @@ -929,6 +956,13 @@ worker.DoStep(); FastForwardBy(TimeDelta::FromSeconds(1)); + + histogram_tester.ExpectBucketCount("ChromeOS.CertProvisioning.Result.User", + CertProvisioningWorkerState::kFailed, 1); + histogram_tester.ExpectBucketCount( + "ChromeOS.CertProvisioning.Result.User", + CertProvisioningWorkerState::kKeyRegistered, 1); + histogram_tester.ExpectTotalCount("ChromeOS.CertProvisioning.Result.User", 2); } class PrefServiceObserver { @@ -1116,7 +1150,7 @@ EXPECT_CALL(*mock_invalidator, Unregister()).Times(1); EXPECT_CALL(callback_observer_, - Callback(cert_profile, CertProvisioningWorkerState::kSucceed)) + Callback(cert_profile, CertProvisioningWorkerState::kSucceeded)) .Times(1); worker->DoStep(); } @@ -1230,6 +1264,8 @@ } TEST_F(CertProvisioningWorkerTest, CancelDeviceWorker) { + base::HistogramTester histogram_tester; + CertScope cert_scope = CertScope::kDevice; CertProfile cert_profile{kCertProfileId, kCertProfileVersion}; @@ -1284,8 +1320,17 @@ pref_val = ParseJson("{}"); EXPECT_CALL(pref_observer, OnPrefValueUpdated(IsJson(pref_val))).Times(1); - worker->Cancel(); + worker->Stop(CertProvisioningWorkerState::kCanceled); + + EXPECT_CALL(callback_observer_, + Callback(cert_profile, CertProvisioningWorkerState::kCanceled)) + .Times(1); + FastForwardBy(TimeDelta::FromSeconds(1)); } + + histogram_tester.ExpectUniqueSample("ChromeOS.CertProvisioning.Result.Device", + CertProvisioningWorkerState::kCanceled, + 1); } } // namespace
diff --git a/chrome/browser/chromeos/cert_provisioning/mock_cert_provisioning_worker.h b/chrome/browser/chromeos/cert_provisioning/mock_cert_provisioning_worker.h index 95f43ea4..907291b 100644 --- a/chrome/browser/chromeos/cert_provisioning/mock_cert_provisioning_worker.h +++ b/chrome/browser/chromeos/cert_provisioning/mock_cert_provisioning_worker.h
@@ -64,7 +64,7 @@ ~MockCertProvisioningWorker() override; MOCK_METHOD(void, DoStep, (), (override)); - MOCK_METHOD(void, Cancel, (), (override)); + MOCK_METHOD(void, Stop, (CertProvisioningWorkerState), (override)); MOCK_METHOD(bool, IsWaiting, (), (const override)); MOCK_METHOD(const CertProfile&, GetCertProfile, (), (const override)); MOCK_METHOD(const std::string&, GetPublicKey, (), (const override));
diff --git a/chrome/browser/chromeos/file_manager/file_manager_jstest.cc b/chrome/browser/chromeos/file_manager/file_manager_jstest.cc index e915f9e..d1e3857e 100644 --- a/chrome/browser/chromeos/file_manager/file_manager_jstest.cc +++ b/chrome/browser/chromeos/file_manager/file_manager_jstest.cc
@@ -112,6 +112,10 @@ RunTestURL("foreground/js/task_controller_unittest_gen.html"); } +IN_PROC_BROWSER_TEST_F(FileManagerJsTest, FileManagerCommandsTest) { + RunTestURL("foreground/js/file_manager_commands_unittest_gen.html"); +} + IN_PROC_BROWSER_TEST_F(FileManagerJsTest, FileTasks) { RunTestURL("foreground/js/file_tasks_unittest_gen.html"); }
diff --git a/chrome/browser/chromeos/login/kiosk_browsertest.cc b/chrome/browser/chromeos/login/kiosk_browsertest.cc index 0cbe104..ae7c44d 100644 --- a/chrome/browser/chromeos/login/kiosk_browsertest.cc +++ b/chrome/browser/chromeos/login/kiosk_browsertest.cc
@@ -1399,6 +1399,7 @@ content::TestNavigationObserver settings_navigation_observer(web_contents, 1); NavigateParams params(profile, page2, ui::PAGE_TRANSITION_AUTO_BOOKMARK); + params.disposition = WindowOpenDisposition::NEW_POPUP; Navigate(¶ms); // Wait for browser to be handled. base::RunLoop waiter;
diff --git a/chrome/browser/chromeos/login/screens/hid_detection_screen_browsertest.cc b/chrome/browser/chromeos/login/screens/hid_detection_screen_browsertest.cc index aecd62a5..2d7037f 100644 --- a/chrome/browser/chromeos/login/screens/hid_detection_screen_browsertest.cc +++ b/chrome/browser/chromeos/login/screens/hid_detection_screen_browsertest.cc
@@ -10,6 +10,7 @@ #include "chrome/browser/chromeos/login/login_wizard.h" #include "chrome/browser/chromeos/login/screens/base_screen.h" #include "chrome/browser/chromeos/login/screens/hid_detection_screen.h" +#include "chrome/browser/chromeos/login/test/js_checker.h" #include "chrome/browser/chromeos/login/test/oobe_base_test.h" #include "chrome/browser/chromeos/login/test/oobe_screen_waiter.h" #include "chrome/browser/chromeos/login/wizard_controller.h" @@ -97,6 +98,15 @@ base::RunLoop().RunUntilIdle(); } + void ContinueToWelcomeScreen() { + // Simulate the user's click on "Continue" button. + test::OobeJS() + .CreateVisibilityWaiter(true, {"hid-detection", "hid-continue-button"}) + ->Wait(); + test::OobeJS().TapOnPath({"hid-detection", "hid-continue-button"}); + OobeScreenWaiter(WelcomeView::kScreenId).Wait(); + } + private: HIDDetectionScreen* hid_detection_screen_; std::unique_ptr<device::FakeInputServiceLinux> fake_input_service_manager_; @@ -188,9 +198,7 @@ AddDeviceToService(DeviceType::kKeyboard, device::mojom::InputDeviceType::TYPE_BLUETOOTH); - // Simulate the user's click on "Continue" button. - hid_detection_screen()->OnContinueButtonClicked(); - OobeScreenWaiter(WelcomeView::kScreenId).Wait(); + ContinueToWelcomeScreen(); // The adapter should not be powered off at this moment. EXPECT_TRUE(adapter()->IsPowered()); @@ -207,12 +215,34 @@ AddDeviceToService(DeviceType::kKeyboard, device::mojom::InputDeviceType::TYPE_USB); - // Simulate the user's click on "Continue" button. - hid_detection_screen()->OnContinueButtonClicked(); - OobeScreenWaiter(WelcomeView::kScreenId).Wait(); + ContinueToWelcomeScreen(); // The adapter should be powered off at this moment. EXPECT_FALSE(adapter()->IsPowered()); } +// Tests that the connected 'ticks' are shown when the devices are connected. +IN_PROC_BROWSER_TEST_F(HIDDetectionScreenTest, TestTicks) { + OobeScreenWaiter(HIDDetectionView::kScreenId).Wait(); + test::OobeJS() + .CreateVisibilityWaiter(false, {"hid-detection", "mouse-tick"}) + ->Wait(); + test::OobeJS() + .CreateVisibilityWaiter(false, {"hid-detection", "keyboard-tick"}) + ->Wait(); + + AddDeviceToService(DeviceType::kMouse, + device::mojom::InputDeviceType::TYPE_USB); + AddDeviceToService(DeviceType::kKeyboard, + device::mojom::InputDeviceType::TYPE_USB); + + test::OobeJS() + .CreateVisibilityWaiter(true, {"hid-detection", "mouse-tick"}) + ->Wait(); + test::OobeJS() + .CreateVisibilityWaiter(true, {"hid-detection", "keyboard-tick"}) + ->Wait(); + ContinueToWelcomeScreen(); +} + } // namespace chromeos
diff --git a/chrome/browser/chromeos/policy/device_policy_decoder_chromeos.cc b/chrome/browser/chromeos/policy/device_policy_decoder_chromeos.cc index 99c9d73..a966a40 100644 --- a/chrome/browser/chromeos/policy/device_policy_decoder_chromeos.cc +++ b/chrome/browser/chromeos/policy/device_policy_decoder_chromeos.cc
@@ -1532,15 +1532,6 @@ nullptr); } - if (policy.has_minimum_chrome_version_enforced()) { - const em::StringPolicyProto& container( - policy.minimum_chrome_version_enforced()); - if (container.has_value()) { - SetJsonDevicePolicy(key::kMinimumChromeVersionEnforced, container.value(), - policies); - } - } - if (policy.has_unaffiliated_arc_allowed()) { const em::UnaffiliatedArcAllowedProto& container( policy.unaffiliated_arc_allowed());
diff --git a/chrome/browser/chromeos/policy/minimum_version_policy_handler_browsertest.cc b/chrome/browser/chromeos/policy/minimum_version_policy_handler_browsertest.cc index ad575914..6ae0f9e 100644 --- a/chrome/browser/chromeos/policy/minimum_version_policy_handler_browsertest.cc +++ b/chrome/browser/chromeos/policy/minimum_version_policy_handler_browsertest.cc
@@ -161,7 +161,10 @@ profile->GetProfilePolicyConnector()->OverrideIsManagedForTesting(true); } -IN_PROC_BROWSER_TEST_F(MinimumVersionPolicyTest, CriticalUpdateOnLoginScreen) { +// TODO(https://crbug.com/1076072): Temporarily disable the test till branch +// date to avoid unexpected policy behaviour before it's ready to use. +IN_PROC_BROWSER_TEST_F(MinimumVersionPolicyTest, + DISABLED_CriticalUpdateOnLoginScreen) { EXPECT_EQ(ash::LoginScreenTestApi::GetUsersCount(), 1); EXPECT_FALSE(ash::LoginScreenTestApi::IsOobeDialogVisible()); @@ -185,7 +188,10 @@ EXPECT_FALSE(ash::LoginScreenTestApi::IsOobeDialogVisible()); } -IN_PROC_BROWSER_TEST_F(MinimumVersionPolicyTest, PRE_CriticalUpdateInSession) { +// TODO(https://crbug.com/1076072): Temporarily disable the test till branch +// date to avoid unexpected policy behaviour before it's ready to use. +IN_PROC_BROWSER_TEST_F(MinimumVersionPolicyTest, + DISABLED_PRE_CriticalUpdateInSession) { // Login the user into the session and mark as managed. Login(); MarkUserManaged(); @@ -207,7 +213,10 @@ EXPECT_TRUE(chrome::IsAttemptingShutdown()); } -IN_PROC_BROWSER_TEST_F(MinimumVersionPolicyTest, CriticalUpdateInSession) { +// TODO(https://crbug.com/1076072): Temporarily disable the test till branch +// date to avoid unexpected policy behaviour before it's ready to use. +IN_PROC_BROWSER_TEST_F(MinimumVersionPolicyTest, + DISABLED_CriticalUpdateInSession) { // Check login screen is shown post chrome restart due to critical update // required in session. EXPECT_EQ(session_manager::SessionManager::Get()->session_state(), @@ -219,8 +228,10 @@ EXPECT_EQ(user_manager::UserManager::Get()->GetLoggedInUsers().size(), 0u); } +// TODO(https://crbug.com/1076072): Temporarily disable the test till branch +// date to avoid unexpected policy behaviour before it's ready to use. IN_PROC_BROWSER_TEST_F(MinimumVersionPolicyTest, - CriticalUpdateInSessionUnmanagedUser) { + DISABLED_CriticalUpdateInSessionUnmanagedUser) { // Login the user into the session. Login(); @@ -244,8 +255,10 @@ chromeos::LoginManagerMixin login_manager_{&mixin_host_}; }; +// TODO(https://crbug.com/1076072): Temporarily disable the test till branch +// date to avoid unexpected policy behaviour before it's ready to use. IN_PROC_BROWSER_TEST_F(MinimumVersionNoUsersLoginTest, - CriticalUpdateOnLoginScreen) { + DISABLED_CriticalUpdateOnLoginScreen) { chromeos::OobeScreenWaiter(chromeos::GaiaView::kScreenId).Wait(); EXPECT_EQ(ash::LoginScreenTestApi::GetUsersCount(), 0); @@ -289,8 +302,10 @@ } }; +// TODO(https://crbug.com/1076072): Temporarily disable the test till branch +// date to avoid unexpected policy behaviour before it's ready to use. IN_PROC_BROWSER_TEST_F(MinimumVersionPolicyPresentTest, - DeadlineReachedNoUsers) { + DISABLED_DeadlineReachedNoUsers) { // Checks update required screen is shown at startup if there is no user in // the device. EXPECT_EQ(session_manager::SessionManager::Get()->session_state(), @@ -310,7 +325,10 @@ chromeos::LoginManagerMixin login_mixin_{&mixin_host_}; }; -IN_PROC_BROWSER_TEST_F(MinimumVersionExistingUserTest, DeadlineReached) { +// TODO(https://crbug.com/1076072): Temporarily disable the test till branch +// date to avoid unexpected policy behaviour before it's ready to use. +IN_PROC_BROWSER_TEST_F(MinimumVersionExistingUserTest, + DISABLED_DeadlineReached) { // Checks update required screen is shown at startup if user is existing in // the device. EXPECT_EQ(session_manager::SessionManager::Get()->session_state(), @@ -335,7 +353,10 @@ } }; -IN_PROC_BROWSER_TEST_F(MinimumVersionBeforeLoginHost, DeadlineReached) { +// TODO(https://crbug.com/1076072): Temporarily disable the test till branch +// date to avoid unexpected policy behaviour before it's ready to use. +IN_PROC_BROWSER_TEST_F(MinimumVersionBeforeLoginHost, + DISABLED_DeadlineReached) { // Checks update required screen is shown at startup if the policy handler is // invoked before login display host is created. EXPECT_EQ(chromeos::LoginDisplayHost::default_host(), nullptr); @@ -372,8 +393,10 @@ } }; +// TODO(https://crbug.com/1076072): Temporarily disable the test till branch +// date to avoid unexpected policy behaviour before it's ready to use. IN_PROC_BROWSER_TEST_F(MinimumVersionPublicSessionAutoLoginTest, - BlockAutoLogin) { + DISABLED_BlockAutoLogin) { // Checks public session auto login is blocked if update is required on // reboot. EXPECT_EQ(session_manager::SessionManager::Get()->session_state(),
diff --git a/chrome/browser/chromeos/settings/device_settings_provider.cc b/chrome/browser/chromeos/settings/device_settings_provider.cc index 39abb90..8c814c5 100644 --- a/chrome/browser/chromeos/settings/device_settings_provider.cc +++ b/chrome/browser/chromeos/settings/device_settings_provider.cc
@@ -762,16 +762,6 @@ policy.tpm_firmware_update_settings()))); } - if (policy.has_minimum_chrome_version_enforced()) { - const em::StringPolicyProto& container( - policy.minimum_chrome_version_enforced()); - if (container.has_value()) { - SetJsonDeviceSetting(kMinimumChromeVersionEnforced, - policy::key::kMinimumChromeVersionEnforced, - container.value(), new_values_cache); - } - } - if (policy.has_cast_receiver_name()) { const em::CastReceiverNameProto& container(policy.cast_receiver_name()); if (container.has_name()) {
diff --git a/chrome/browser/component_updater/registration.cc b/chrome/browser/component_updater/registration.cc index 3b985d0..66046f8f 100644 --- a/chrome/browser/component_updater/registration.cc +++ b/chrome/browser/component_updater/registration.cc
@@ -47,6 +47,7 @@ #if !defined(OS_ANDROID) #include "chrome/browser/component_updater/intervention_policy_database_component_installer.h" #include "chrome/browser/component_updater/soda_component_installer.h" +#include "chrome/browser/enterprise/connectors/service_providers.h" #include "chrome/browser/resource_coordinator/tab_manager.h" #endif @@ -192,6 +193,10 @@ #if defined(OS_CHROMEOS) RegisterSmartDimComponent(cus); #endif // !defined(OS_CHROMEOS) + +#if !defined(OS_ANDROID) + enterprise_connectors::RegisterServiceProvidersComponent(cus); +#endif } } // namespace component_updater
diff --git a/chrome/browser/enterprise/connectors/OWNERS b/chrome/browser/enterprise/connectors/OWNERS index 3b28b37d..10c7df8 100644 --- a/chrome/browser/enterprise/connectors/OWNERS +++ b/chrome/browser/enterprise/connectors/OWNERS
@@ -1,2 +1,5 @@ rogerta@chromium.org domfc@chromium.org + +per-file service_providers.*=file://components/component_updater/OWNERS +
diff --git a/chrome/browser/enterprise/connectors/service_providers.cc b/chrome/browser/enterprise/connectors/service_providers.cc new file mode 100644 index 0000000..76c71b4 --- /dev/null +++ b/chrome/browser/enterprise/connectors/service_providers.cc
@@ -0,0 +1,163 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/enterprise/connectors/service_providers.h" + +#include <memory> +#include <string> +#include <vector> + +#include "base/bind.h" +#include "base/callback.h" +#include "base/files/file_path.h" +#include "base/files/file_util.h" +#include "base/json/json_reader.h" +#include "base/memory/ref_counted.h" +#include "base/memory/weak_ptr.h" +#include "base/optional.h" +#include "base/task/task_traits.h" +#include "base/task/thread_pool.h" +#include "base/values.h" +#include "components/component_updater/component_installer.h" +#include "components/component_updater/component_updater_service.h" +#include "components/update_client/update_client.h" + +namespace { + +const base::FilePath::CharType kConfigFileName[] = + FILE_PATH_LITERAL("service_providers.json"); + +// The SHA256 of the SubjectPublicKeyInfo used to sign the extension. +// The extension id is: dfcoifdifjfolmglbbogapfcihdgckga +// SHA256: 352e8538595ebc6b11e60f5287362a60a4c4f0c2fb3595c43621942ffbd973b5 +const uint8_t kPublicKeySHA256[32] = { + 0x35, 0x2e, 0x85, 0x38, 0x59, 0x5e, 0xbc, 0x6b, 0x11, 0xe6, 0x0f, + 0x52, 0x87, 0x36, 0x2a, 0x60, 0xa4, 0xc4, 0xf0, 0xc2, 0xfb, 0x35, + 0x95, 0xc4, 0x36, 0x21, 0x94, 0x2f, 0xfb, 0xd9, 0x73, 0xb5}; + +base::Optional<base::Value> LoadConfigFromDisk(const base::FilePath& path) { + // TODO(crbug/1081375): replace this with a safe read function. + std::string json; + if (!base::ReadFileToString(path, &json)) { + return base::nullopt; + } + + return base::JSONReader::Read(json); +} + +} // namespace + +namespace enterprise_connectors { + +class ServiceProvidersConfigPolicy + : public component_updater::ComponentInstallerPolicy { + public: + ServiceProvidersConfigPolicy(); + ~ServiceProvidersConfigPolicy() override; + + const base::Value& GetServiceProvidersConfig() const { return config_; } + + private: + void SetConfig(base::Optional<base::Value> config); + + // component_updater::ComponentInstallerPolicy overrides: + bool VerifyInstallation(const base::DictionaryValue& manifest, + const base::FilePath& install_dir) const override; + bool SupportsGroupPolicyEnabledComponentUpdates() const override; + bool RequiresNetworkEncryption() const override; + update_client::CrxInstaller::Result OnCustomInstall( + const base::DictionaryValue& manifest, + const base::FilePath& install_dir) override; + void OnCustomUninstall() override; + void ComponentReady(const base::Version& version, + const base::FilePath& install_dir, + std::unique_ptr<base::DictionaryValue> manifest) override; + base::FilePath GetRelativeInstallDir() const override; + void GetHash(std::vector<uint8_t>* hash) const override; + std::string GetName() const override; + std::vector<std::string> GetMimeTypes() const override; + update_client::InstallerAttributes GetInstallerAttributes() const override; + + base::Value config_; + base::WeakPtrFactory<ServiceProvidersConfigPolicy> factory_{this}; +}; + +ServiceProvidersConfigPolicy::ServiceProvidersConfigPolicy() = default; +ServiceProvidersConfigPolicy::~ServiceProvidersConfigPolicy() = default; + +void ServiceProvidersConfigPolicy::SetConfig( + base::Optional<base::Value> config) { + if (!config.has_value()) + return; + + config_ = std::move(config.value()); +} + +bool ServiceProvidersConfigPolicy::VerifyInstallation( + const base::DictionaryValue& manifest, + const base::FilePath& install_dir) const { + const base::FilePath config_file = install_dir.Append(kConfigFileName); + return base::PathExists(config_file); +} + +bool ServiceProvidersConfigPolicy::SupportsGroupPolicyEnabledComponentUpdates() + const { + return false; +} + +bool ServiceProvidersConfigPolicy::RequiresNetworkEncryption() const { + return false; +} + +update_client::CrxInstaller::Result +ServiceProvidersConfigPolicy::OnCustomInstall( + const base::DictionaryValue& manifest, + const base::FilePath& install_dir) { + return update_client::CrxInstaller::Result(0); // Nothing custom here. +} + +void ServiceProvidersConfigPolicy::OnCustomUninstall() {} + +void ServiceProvidersConfigPolicy::ComponentReady( + const base::Version& version, + const base::FilePath& install_dir, + std::unique_ptr<base::DictionaryValue> manifest) { + const base::FilePath config_file = install_dir.Append(kConfigFileName); + base::ThreadPool::PostTaskAndReplyWithResult( + FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT}, + base::BindOnce(&LoadConfigFromDisk, config_file), + base::BindOnce(&ServiceProvidersConfigPolicy::SetConfig, + factory_.GetWeakPtr())); +} + +base::FilePath ServiceProvidersConfigPolicy::GetRelativeInstallDir() const { + return base::FilePath(FILE_PATH_LITERAL("ECSerivceProvidersConfig")); +} + +void ServiceProvidersConfigPolicy::GetHash(std::vector<uint8_t>* hash) const { + hash->assign(kPublicKeySHA256, + kPublicKeySHA256 + base::size(kPublicKeySHA256)); +} + +std::string ServiceProvidersConfigPolicy::GetName() const { + return "Enterprise Connectors Service Providers Configuration"; +} + +std::vector<std::string> ServiceProvidersConfigPolicy::GetMimeTypes() const { + return std::vector<std::string>(); +} + +update_client::InstallerAttributes +ServiceProvidersConfigPolicy::GetInstallerAttributes() const { + return update_client::InstallerAttributes(); +} + +void RegisterServiceProvidersComponent( + component_updater::ComponentUpdateService* cus) { + auto installer = base::MakeRefCounted<component_updater::ComponentInstaller>( + std::make_unique<ServiceProvidersConfigPolicy>()); + installer->Register(cus, base::OnceClosure()); +} + +} // namespace enterprise_connectors
diff --git a/chrome/browser/enterprise/connectors/service_providers.h b/chrome/browser/enterprise/connectors/service_providers.h new file mode 100644 index 0000000..3b11ab7 --- /dev/null +++ b/chrome/browser/enterprise/connectors/service_providers.h
@@ -0,0 +1,21 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_ENTERPRISE_CONNECTORS_SERVICE_PROVIDERS_H_ +#define CHROME_BROWSER_ENTERPRISE_CONNECTORS_SERVICE_PROVIDERS_H_ + +namespace component_updater { +class ComponentUpdateService; +} + +namespace enterprise_connectors { + +// Registers a component extension with the update service which downloads +// and verifies service provider configurations used by enterprise connectors. +void RegisterServiceProvidersComponent( + component_updater::ComponentUpdateService* cus); + +} // namespace enterprise_connectors + +#endif // CHROME_BROWSER_ENTERPRISE_CONNECTORS_SERVICE_PROVIDERS_H_
diff --git a/chrome/browser/file_util_service.cc b/chrome/browser/file_util_service.cc index e3a4d884..b4369b8 100644 --- a/chrome/browser/file_util_service.cc +++ b/chrome/browser/file_util_service.cc
@@ -13,7 +13,6 @@ content::ServiceProcessHost::Launch<chrome::mojom::FileUtilService>( remote.InitWithNewPipeAndPassReceiver(), content::ServiceProcessHost::Options() - .WithSandboxType(service_manager::SandboxType::kUtility) .WithDisplayName(IDS_UTILITY_PROCESS_FILE_UTILITY_NAME) .Pass()); return remote;
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json index af5ad49..1870aa2 100644 --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json
@@ -641,6 +641,11 @@ "expiry_milestone": 85 }, { + "name": "cross-origin-opener-policy-reporting", + "owners": [ "ahemery", "clamy", "pmeuleman" ], + "expiry_milestone": 85 + }, + { "name": "crostini-disk-resizing", "owners": [ "davidmunro", "nverne" ], "expiry_milestone": 86 @@ -3384,6 +3389,11 @@ "expiry_milestone": 88 }, { + "name": "page-info-version-2", + "owners": [ "eokoyomon", "dullweber" ], + "expiry_milestone": 88 + }, + { "name": "paint-preview-demo", "owners": [ "ckitagawa", "fredmello", "mahmoudi" ], "expiry_milestone": 88 @@ -3545,6 +3555,11 @@ "expiry_milestone": 88 }, { + "name": "query-tiles-enable-query-editing", + "owners": [ "shaktisahu"], + "expiry_milestone": 88 + }, + { "name": "query-tiles-instant-fetch", "owners": [ "xingliu"], "expiry_milestone": 88
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index 5c73b18..2ca838b 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -762,6 +762,11 @@ const char kCrossOriginOpenerPolicyDescription[] = "Enables Cross Origin Opener Policy."; +const char kCrossOriginOpenerPolicyReportingName[] = + "Cross Origin Opener Policy reporting"; +const char kCrossOriginOpenerPolicyReportingDescription[] = + "Enables Cross Origin Opener Policy reporting."; + const char kDisableKeepaliveFetchName[] = "Disable fetch with keepalive set"; const char kDisableKeepaliveFetchDescription[] = "Disable fetch with keepalive set " @@ -2597,6 +2602,10 @@ const char kPageInfoPerformanceHintsDescription[] = "Show site performance information in the page info menu."; +const char kPageInfoV2Name[] = "Page info version two"; +const char kPageInfoV2Description[] = + "Enable the second version of the page info menu."; + const char kPasswordManagerOnboardingAndroidName[] = "Password manager onboarding experience"; const char kPasswordManagerOnboardingAndroidDescription[] = @@ -2632,6 +2641,11 @@ const char kQueryTilesDescription[] = "Shows query tiles in Chrome"; const char kQueryTilesOmniboxName[] = "Show query tiles in omnibox"; const char kQueryTilesOmniboxDescription[] = "Shows query tiles in omnibox"; +const char kQueryTilesEnableQueryEditingName[] = + "Query Tiles - Enable query edit mode"; +const char kQueryTilesEnableQueryEditingDescription[] = + "When a query tile is tapped, the query text will be shown in the omnibox " + "and user will have a chance to edit the text before submitting"; const char kQueryTilesCountryCode[] = "Country code for getting tiles"; const char kQueryTilesCountryCodeDescription[] = "When query tiles are enabled, this value determines tiles for which "
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index f153e53..683ca3a 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -437,6 +437,9 @@ extern const char kCrossOriginOpenerPolicyName[]; extern const char kCrossOriginOpenerPolicyDescription[]; +extern const char kCrossOriginOpenerPolicyReportingName[]; +extern const char kCrossOriginOpenerPolicyReportingDescription[]; + extern const char kDisableKeepaliveFetchName[]; extern const char kDisableKeepaliveFetchDescription[]; @@ -1512,6 +1515,9 @@ extern const char kPageInfoPerformanceHintsName[]; extern const char kPageInfoPerformanceHintsDescription[]; +extern const char kPageInfoV2Name[]; +extern const char kPageInfoV2Description[]; + extern const char kPasswordManagerOnboardingAndroidName[]; extern const char kPasswordManagerOnboardingAndroidDescription[]; @@ -1528,6 +1534,8 @@ extern const char kQueryTilesDescription[]; extern const char kQueryTilesOmniboxName[]; extern const char kQueryTilesOmniboxDescription[]; +extern const char kQueryTilesEnableQueryEditingName[]; +extern const char kQueryTilesEnableQueryEditingDescription[]; extern const char kQueryTilesCountryCode[]; extern const char kQueryTilesCountryCodeDescription[]; extern const char kQueryTilesCountryCodeUS[];
diff --git a/chrome/browser/flags/android/chrome_feature_list.cc b/chrome/browser/flags/android/chrome_feature_list.cc index 6bc30df..3b90058 100644 --- a/chrome/browser/flags/android/chrome_feature_list.cc +++ b/chrome/browser/flags/android/chrome_feature_list.cc
@@ -257,6 +257,7 @@ &subresource_filter::kSafeBrowsingSubresourceFilter, &upboarding::features::kQueryTiles, &upboarding::features::kQueryTilesInOmnibox, + &upboarding::features::kQueryTilesEnableQueryEditing, }; const base::Feature* FindFeatureExposedToJava(const std::string& feature_name) {
diff --git a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java index 4886c47f..b336df6ed 100644 --- a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java +++ b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java
@@ -353,6 +353,7 @@ public static final String PRIORITIZE_BOOTSTRAP_TASKS = "PrioritizeBootstrapTasks"; public static final String PROBABILISTIC_CRYPTID_RENDERER = "ProbabilisticCryptidRenderer"; public static final String QUERY_TILES = "QueryTiles"; + public static final String QUERY_TILES_ENABLE_QUERY_EDITING = "QueryTilesEnableQueryEditing"; public static final String QUERY_IN_OMNIBOX = "QueryInOmnibox"; public static final String QUIET_NOTIFICATION_PROMPTS = "QuietNotificationPrompts"; public static final String REACHED_CODE_PROFILER = "ReachedCodeProfiler";
diff --git a/chrome/browser/lookalikes/lookalike_url_navigation_throttle_browsertest.cc b/chrome/browser/lookalikes/lookalike_url_navigation_throttle_browsertest.cc index 61e190a0..a8dffd6 100644 --- a/chrome/browser/lookalikes/lookalike_url_navigation_throttle_browsertest.cc +++ b/chrome/browser/lookalikes/lookalike_url_navigation_throttle_browsertest.cc
@@ -404,9 +404,10 @@ TestMetricsRecordedAndMaybeInterstitialShown( browser(), kNavigatedUrl, kExpectedSuggestedUrl, - NavigationSuggestionEvent::kMatchTopSite); + NavigationSuggestionEvent::kMatchSkeletonTop500); - CheckUkm({kNavigatedUrl}, "MatchType", LookalikeUrlMatchType::kTopSite); + CheckUkm({kNavigatedUrl}, "MatchType", + LookalikeUrlMatchType::kSkeletonMatchTop500); } // Embedding a top domain should show an interstitial when enabled. If disabled @@ -463,8 +464,10 @@ TestInterstitialNotShown(browser(), kNavigatedUrl); histograms.ExpectTotalCount(lookalikes::kHistogramName, 1); histograms.ExpectBucketCount(lookalikes::kHistogramName, - NavigationSuggestionEvent::kMatchTopSite, 1); - CheckUkm({kNavigatedUrl}, "MatchType", LookalikeUrlMatchType::kTopSite); + NavigationSuggestionEvent::kMatchSkeletonTop5k, + 1); + CheckUkm({kNavigatedUrl}, "MatchType", + LookalikeUrlMatchType::kSkeletonMatchTop5k); } // Same as Idn_TopDomain_Match, but this time the domain contains characters @@ -481,9 +484,10 @@ TestMetricsRecordedAndMaybeInterstitialShown( browser(), kNavigatedUrl, kExpectedSuggestedUrl, - NavigationSuggestionEvent::kMatchTopSite); + NavigationSuggestionEvent::kMatchSkeletonTop500); - CheckUkm({kNavigatedUrl}, "MatchType", LookalikeUrlMatchType::kTopSite); + CheckUkm({kNavigatedUrl}, "MatchType", + LookalikeUrlMatchType::kSkeletonMatchTop500); } // The navigated domain will fall back to punycode because it fails spoof checks
diff --git a/chrome/browser/media/cast_mirroring_service_host.cc b/chrome/browser/media/cast_mirroring_service_host.cc index 2ad4828..efa09c31 100644 --- a/chrome/browser/media/cast_mirroring_service_host.cc +++ b/chrome/browser/media/cast_mirroring_service_host.cc
@@ -210,7 +210,6 @@ mirroring_service_.BindNewPipeAndPassReceiver(), content::ServiceProcessHost::Options() .WithDisplayName("Mirroring Service") - .WithSandboxType(service_manager::SandboxType::kUtility) .Pass()); mojo::PendingRemote<mojom::ResourceProvider> provider; resource_provider_receiver.Bind(provider.InitWithNewPipeAndPassReceiver());
diff --git a/chrome/browser/policy/policy_browsertest.cc b/chrome/browser/policy/policy_browsertest.cc index 2a6a62d..657410c5 100644 --- a/chrome/browser/policy/policy_browsertest.cc +++ b/chrome/browser/policy/policy_browsertest.cc
@@ -3206,57 +3206,6 @@ EXPECT_EQ(JSIncrementerFetch(contents), 3); } -#if defined(OS_WIN) - -class ForceNetworkInProcessTest - : public InProcessBrowserTest, - public ::testing::WithParamInterface< - /*policy::key::kForceNetworkInProcess=*/bool> { - public: - // InProcessBrowserTest implementation: - void SetUp() override { - EXPECT_CALL(policy_provider_, IsInitializationComplete(testing::_)) - .WillRepeatedly(testing::Return(true)); - policy::PolicyMap values; - values.Set(policy::key::kForceNetworkInProcess, - policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_MACHINE, - policy::POLICY_SOURCE_CLOUD, - std::make_unique<base::Value>(GetParam()), nullptr); - policy_provider_.UpdateChromePolicy(values); - policy::BrowserPolicyConnector::SetPolicyProviderForTesting( - &policy_provider_); - - InProcessBrowserTest::SetUp(); - } - - private: - policy::MockConfigurationPolicyProvider policy_provider_; -}; - -IN_PROC_BROWSER_TEST_P(ForceNetworkInProcessTest, IsRespected) { - bool expected_in_process = GetParam(); - - // When run with --enable-features=NetworkServiceInProcess, the Network - // Service will always be in process. This configuration is used on some - // bots - see https://crbug.com/1002752. - expected_in_process |= - base::FeatureList::IsEnabled(features::kNetworkServiceInProcess); - - ASSERT_EQ(expected_in_process, content::IsInProcessNetworkService()); -} - -INSTANTIATE_TEST_SUITE_P( - Enabled, - ForceNetworkInProcessTest, - ::testing::Values(/*policy::key::kForceNetworkInProcess=*/true)); - -INSTANTIATE_TEST_SUITE_P( - Disabled, - ForceNetworkInProcessTest, - ::testing::Values(/*policy::key::kForceNetworkInProcess=*/false)); - -#endif // defined(OS_WIN) - #if !defined(OS_ANDROID) // The possibilities for a boolean policy.
diff --git a/chrome/browser/reputation/local_heuristics.cc b/chrome/browser/reputation/local_heuristics.cc index c489e03c..9ab2e23d 100644 --- a/chrome/browser/reputation/local_heuristics.cc +++ b/chrome/browser/reputation/local_heuristics.cc
@@ -64,8 +64,6 @@ *safe_url = GURL(std::string(url::kHttpScheme) + url::kStandardSchemeSeparator + matched_domain); switch (match_type) { - case LookalikeUrlMatchType::kTopSite: - return kEnableLookalikeTopSites.Get(); case LookalikeUrlMatchType::kEditDistance: return kEnableLookalikeEditDistance.Get(); case LookalikeUrlMatchType::kEditDistanceSiteEngagement: @@ -73,12 +71,15 @@ case LookalikeUrlMatchType::kTargetEmbedding: return kEnableLookalikeTargetEmbedding.Get(); case LookalikeUrlMatchType::kSiteEngagement: - // We should only ever reach this case when the - // kLookalikeUrlNavigationSuggestionsUI feature is disabled. Otherwise, an - // interstitial will already be shown on the kSiteEngagement match type. + case LookalikeUrlMatchType::kSkeletonMatchTop500: + // We should only ever reach these cases when the lookalike interstitial + // is disabled. Now that interstitial is fully launched, this only happens + // in tests. DCHECK(!base::FeatureList::IsEnabled( features::kLookalikeUrlNavigationSuggestionsUI)); return true; + case LookalikeUrlMatchType::kSkeletonMatchTop5k: + return kEnableLookalikeTopSites.Get(); case LookalikeUrlMatchType::kNone: NOTREACHED(); }
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 485516e40..f941c38c 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/background_test.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/background_test.js
@@ -2546,3 +2546,24 @@ node.focus(); }); }); + +TEST_F('ChromeVoxBackgroundTest', 'MenuItemRadio', function() { + const mockFeedback = this.createMockFeedback(); + this.runWithLoadedTree( + ` + <ul role="menu" tabindex="0" autofocus> + <li role="menuitemradio" aria-checked="true">Small</li> + <li role="menuitemradio" aria-checked="false">Medium</li> + <li role="menuitemradio" aria-checked="false">Large</li> + </ul> + `, + function(root) { + mockFeedback.expectSpeech('Menu', 'with 3 items') + .call(doCmd('nextObject')) + .expectSpeech('Small, menu item radio button selected', ' 1 of 3 ') + .call(doCmd('nextObject')) + .expectSpeech( + 'Medium, menu item radio button unselected', ' 2 of 3 ') + .replay(); + }); +});
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/output.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/output.js index b2e5c776..7efaafad 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/output.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/output.js
@@ -2511,8 +2511,8 @@ }, menuItemRadio: { speak: `$if($checked, $earcon(CHECK_ON), $earcon(CHECK_OFF)) - $if($checked, @describe_radio_selected($name), - @describe_radio_unselected($name)) $state $roleDescription + $if($checked, @describe_menu_item_radio_selected($name), + @describe_menu_item_radio_unselected($name)) $state $roleDescription $restriction $description @describe_index($posInSet, $setSize)` },
diff --git a/chrome/browser/resources/chromeos/accessibility/strings/chromevox_strings.grdp b/chrome/browser/resources/chromeos/accessibility/strings/chromevox_strings.grdp index b897a6b..75c81625 100644 --- a/chrome/browser/resources/chromeos/accessibility/strings/chromevox_strings.grdp +++ b/chrome/browser/resources/chromeos/accessibility/strings/chromevox_strings.grdp
@@ -430,6 +430,12 @@ <message desc="Describes a HTML radio button named 'name' in the unselected state." name="IDS_CHROMEVOX_DESCRIBE_RADIO_UNSELECTED"> <ph name="name">$1</ph>, radio button unselected </message> + <message desc="Describes a HTML menu item radio button named 'name' in the selected state." name="IDS_CHROMEVOX_DESCRIBE_MENU_ITEM_RADIO_SELECTED"> + <ph name="name">$1</ph>, menu item radio button selected + </message> + <message desc="Describes a HTML menu item radio button named 'name' in the unselected state." name="IDS_CHROMEVOX_DESCRIBE_MENU_ITEM_RADIO_UNSELECTED"> + <ph name="name">$1</ph>, menu item radio button unselected + </message> <message desc="Describes a window named 'name'." name="IDS_CHROMEVOX_DESCRIBE_WINDOW"> <ph name="name">$1</ph>, window </message>
diff --git a/chrome/browser/resources/chromeos/login/oobe_hid_detection.html b/chrome/browser/resources/chromeos/login/oobe_hid_detection.html index d99f9a1..c522279 100644 --- a/chrome/browser/resources/chromeos/login/oobe_hid_detection.html +++ b/chrome/browser/resources/chromeos/login/oobe_hid_detection.html
@@ -46,7 +46,7 @@ </svg> </iron-iconset-svg> -<dom-module id="oobe-hid-detection"> +<dom-module id="hid-detection"> <template> <style include="oobe-dialog-host"></style> <link rel="stylesheet" href="oobe_hid_detection.css"> @@ -89,6 +89,7 @@ <div slot="bottom-buttons" class="flex layout horizontal end-justified"> <oobe-text-button inverse on-tap="onHIDContinueTap_" text-key="hidDetectionContinue" + id="hid-continue-button" disabled="[[!continueButtonEnabled]]"></oobe-text-button> </div> </oobe-dialog>
diff --git a/chrome/browser/resources/chromeos/login/oobe_hid_detection.js b/chrome/browser/resources/chromeos/login/oobe_hid_detection.js index 242d99d..7992f5f 100644 --- a/chrome/browser/resources/chromeos/login/oobe_hid_detection.js +++ b/chrome/browser/resources/chromeos/login/oobe_hid_detection.js
@@ -20,7 +20,7 @@ }; Polymer({ - is: 'oobe-hid-detection', + is: 'hid-detection', behaviors: [OobeI18nBehavior, OobeDialogHostBehavior, LoginScreenBehavior],
diff --git a/chrome/browser/resources/chromeos/login/oobe_screens.html b/chrome/browser/resources/chromeos/login/oobe_screens.html index 10ce9e34..615287a 100644 --- a/chrome/browser/resources/chromeos/login/oobe_screens.html +++ b/chrome/browser/resources/chromeos/login/oobe_screens.html
@@ -12,9 +12,9 @@ </kiosk-enable> <include src="oobe_screen_update.html"> <include src="oobe_screen_auto_enrollment_check.html"> -<oobe-hid-detection id="hid-detection" class="step right hidden" +<hid-detection id="hid-detection" class="step right hidden" full-screen-dialog> -</oobe-hid-detection> +</hid-detection> <include src="oobe_screen_supervision_transition.html"> <include src="oobe_screen_demo_setup.html"> <include src="oobe_screen_demo_preferences.html">
diff --git a/chrome/browser/resources/settings/safety_check_page/BUILD.gn b/chrome/browser/resources/settings/safety_check_page/BUILD.gn index 60c090d0..c33108c7 100644 --- a/chrome/browser/resources/settings/safety_check_page/BUILD.gn +++ b/chrome/browser/resources/settings/safety_check_page/BUILD.gn
@@ -11,7 +11,12 @@ closure_flags = settings_closure_flags deps = [ ":safety_check_browser_proxy", + ":safety_check_child", + ":safety_check_extensions_element", ":safety_check_page", + ":safety_check_passwords_element", + ":safety_check_safe_browsing_element", + ":safety_check_updates_element", ] } @@ -19,15 +24,34 @@ deps = [ "//ui/webui/resources/js:cr.m" ] } +js_library("safety_check_child") { + deps = [ + "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", + "//ui/webui/resources/js:assert.m", + "//ui/webui/resources/js:i18n_behavior.m", + ] +} + +js_library("safety_check_extensions_element") { + deps = [ + ":safety_check_child", + "..:metrics_browser_proxy", + "..:open_window_proxy", + "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", + "//ui/webui/resources/js:assert.m", + "//ui/webui/resources/js:web_ui_listener_behavior.m", + ] +} + js_library("safety_check_page") { deps = [ ":safety_check_browser_proxy", + ":safety_check_extensions_element", + ":safety_check_passwords_element", + ":safety_check_safe_browsing_element", + ":safety_check_updates_element", "..:hats_browser_proxy", - "..:lifetime_browser_proxy.m", "..:metrics_browser_proxy", - "..:open_window_proxy", - "..:route", - "..:router.m", "../autofill_page:password_manager_proxy", "//third_party/polymer/v3_0/components-chromium/iron-a11y-announcer:iron-a11y-announcer", "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", @@ -37,6 +61,50 @@ ] } +js_library("safety_check_passwords_element") { + deps = [ + ":safety_check_child", + "..:metrics_browser_proxy", + "..:route", + "..:router.m", + "../autofill_page:password_manager_proxy", + "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", + "//ui/webui/resources/js:assert.m", + "//ui/webui/resources/js:web_ui_listener_behavior.m", + ] +} + +js_library("safety_check_safe_browsing_element") { + deps = [ + ":safety_check_child", + "..:metrics_browser_proxy", + "..:route", + "..:router.m", + "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", + "//ui/webui/resources/js:assert.m", + "//ui/webui/resources/js:i18n_behavior.m", + "//ui/webui/resources/js:web_ui_listener_behavior.m", + ] +} + +js_library("safety_check_updates_element") { + deps = [ + ":safety_check_child", + "..:lifetime_browser_proxy.m", + "..:metrics_browser_proxy", + "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", + "//ui/webui/resources/js:assert.m", + "//ui/webui/resources/js:web_ui_listener_behavior.m", + ] +} + html_to_js("web_components") { - js_files = [ "safety_check_page.js" ] + js_files = [ + "safety_check_child.js", + "safety_check_extensions_element.js", + "safety_check_page.js", + "safety_check_passwords_element.js", + "safety_check_safe_browsing_element.js", + "safety_check_updates_element.js", + ] }
diff --git a/chrome/browser/resources/settings/safety_check_page/safety_check_child.html b/chrome/browser/resources/settings/safety_check_page/safety_check_child.html new file mode 100644 index 0000000..c28ebf4 --- /dev/null +++ b/chrome/browser/resources/settings/safety_check_page/safety_check_child.html
@@ -0,0 +1,53 @@ +<style include="cr-shared-style settings-shared iron-flex"> + iron-icon { + display: flex; + flex-shrink: 0; + padding-inline-end: var(--cr-icon-button-margin-start); + width: var(--cr-link-row-icon-width, var(--cr-icon-size)); + } + + .icon-blue { + fill: var(--google-blue-600); + } + + .icon-red { + fill: var(--google-red-600); + } + + /* dark mode */ + @media (prefers-color-scheme: dark) { + .icon-blue { + fill: var(--google-blue-refresh-300); + } + + .icon-red { + fill: var(--google-red-refresh-300); + } + } +</style> +<div class="cr-row"> + <iron-icon id="statusIcon" + icon="[[getStatusIcon_(iconStatus)]]" + src="[[getStatusIconSrc_(iconStatus)]]" + class$="[[getStatusIconClass_(iconStatus)]]" + role="img" + aria-label="[[getStatusIconAriaLabel_(iconStatus)]]"> + </iron-icon> + <div class="flex cr-padded-text"> + <div id="label">[[label]]</div> + <div id="subLabel" class="secondary" no-search + inner-h-t-m-l="[[subLabel]]"> + </div> + </div> + <template is="dom-if" if="[[showButton_(buttonLabel)]]" restamp> + <div class="separator"></div> + <cr-button id="button" class$="[[buttonClass]]" on-click="onButtonClick_" + aria-label="[[buttonAriaLabel]]" no-search> + [[buttonLabel]] + </cr-button> + </template> + <template is="dom-if" if="[[showManagedIcon_(managedIcon)]]" restamp> + <iron-icon id="managedIcon" icon="[[managedIcon]]" aria-hidden="true"> + </iron-icon> + </template> +</div>
diff --git a/chrome/browser/resources/settings/safety_check_page/safety_check_child.js b/chrome/browser/resources/settings/safety_check_page/safety_check_child.js new file mode 100644 index 0000000..c4db1d2af --- /dev/null +++ b/chrome/browser/resources/settings/safety_check_page/safety_check_child.js
@@ -0,0 +1,160 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * @fileoverview + * 'settings-safety-check-element' bundles functionality safety check elements + * have in common. It is used by all safety check elements: parent, updates, + * passwors, etc. + */ +import 'chrome://resources/cr_elements/cr_button/cr_button.m.js'; +import 'chrome://resources/cr_elements/shared_style_css.m.js'; +import 'chrome://resources/cr_elements/shared_vars_css.m.js'; +import 'chrome://resources/polymer/v3_0/iron-flex-layout/iron-flex-layout-classes.js'; +import 'chrome://resources/polymer/v3_0/iron-icon/iron-icon.js'; +import '../settings_shared_css.m.js'; + +import {assertNotReached} from 'chrome://resources/js/assert.m.js'; +import {I18nBehavior} from 'chrome://resources/js/i18n_behavior.m.js'; +import {html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; + +/** + * UI states a safety check child can be in. Defines the basic UI of the child. + * @enum {number} + */ +export const SafetyCheckIconStatus = { + RUNNING: 0, + SAFE: 1, + INFO: 2, + WARNING: 3, +}; + +Polymer({ + is: 'settings-safety-check-child', + + _template: html`{__html_template__}`, + + behaviors: [I18nBehavior], + + properties: { + /** + * Status of the left hand icon. + * {!SafetyCheckParentStatus} + */ + iconStatus: { + type: Number, + value: SafetyCheckIconStatus.RUNNING, + }, + + /**Primary label of the element. */ + label: String, + + /** Secondary label of the element. */ + subLabel: String, + + /** Text of the right hand button. |null| removes it from the DOM. */ + buttonLabel: String, + + /** Aria label of the right hand button. */ + buttonAriaLabel: String, + + /** Classes of the right hand button. */ + buttonClass: String, + + /** Right hand managed icon. |null| removes it from the DOM. */ + managedIcon: String, + }, + + /** + * Returns the left hand icon for an icon status. + * @private + * @return {?string} + */ + getStatusIcon_: function() { + switch (this.iconStatus) { + case SafetyCheckIconStatus.RUNNING: + return null; + case SafetyCheckIconStatus.SAFE: + return 'cr:check'; + case SafetyCheckIconStatus.INFO: + return 'cr:info'; + case SafetyCheckIconStatus.WARNING: + return 'cr:warning'; + default: + assertNotReached(); + } + }, + + /** + * Returns the left hand icon src for an icon status. + * @private + * @return {?string} + */ + getStatusIconSrc_: function() { + if (this.iconStatus === SafetyCheckIconStatus.RUNNING) { + return 'chrome://resources/images/throbber_small.svg'; + } + return null; + }, + + /** + * Returns the left hand icon class for an icon status. + * @private + * @return {string} + */ + getStatusIconClass_: function() { + switch (this.iconStatus) { + case SafetyCheckIconStatus.RUNNING: + case SafetyCheckIconStatus.SAFE: + return 'icon-blue'; + case SafetyCheckIconStatus.WARNING: + return 'icon-red'; + default: + return ''; + } + }, + + /** + * Returns the left hand icon aria label for an icon status. + * @private + * @return {string} + */ + getStatusIconAriaLabel_: function() { + switch (this.iconStatus) { + case SafetyCheckIconStatus.RUNNING: + return this.i18n('safetyCheckIconRunningAriaLabel'); + case SafetyCheckIconStatus.SAFE: + return this.i18n('safetyCheckIconSafeAriaLabel'); + case SafetyCheckIconStatus.INFO: + return this.i18n('safetyCheckIconInfoAriaLabel'); + case SafetyCheckIconStatus.WARNING: + return this.i18n('safetyCheckIconWarningAriaLabel'); + default: + assertNotReached(); + } + }, + + /** + * If the right-hand side button should be shown. + * @private + * @return {boolean} + */ + showButton_: function() { + return !!this.buttonLabel; + }, + + /** @private */ + onButtonClick_: function() { + this.fire('button-click'); + }, + + /** + * If the right-hand side managed icon should be shown. + * @private + * @return {boolean} + */ + showManagedIcon_: function() { + return !!this.managedIcon; + }, +});
diff --git a/chrome/browser/resources/settings/safety_check_page/safety_check_extensions_element.html b/chrome/browser/resources/settings/safety_check_page/safety_check_extensions_element.html new file mode 100644 index 0000000..937aca68b --- /dev/null +++ b/chrome/browser/resources/settings/safety_check_page/safety_check_extensions_element.html
@@ -0,0 +1,11 @@ +<settings-safety-check-child + id="safetyCheckChild" + icon-status="[[getIconStatus_(status_)]]" + label="$i18n{safetyCheckExtensionsPrimaryLabel}" + sub-label="[[displayString_]]" + button-label="[[getButtonLabel_(status_)]]" + button-aria-label="$i18n{safetyCheckExtensionsButtonAriaLabel}" + button-class="[[getButtonClass_(status_)]]" + on-button-click="onButtonClick_" + managed-icon="[[getManagedIcon_(status_)]]"> +</settings-safety-check-child>
diff --git a/chrome/browser/resources/settings/safety_check_page/safety_check_extensions_element.js b/chrome/browser/resources/settings/safety_check_page/safety_check_extensions_element.js new file mode 100644 index 0000000..7d18036 --- /dev/null +++ b/chrome/browser/resources/settings/safety_check_page/safety_check_extensions_element.js
@@ -0,0 +1,149 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * @fileoverview + * 'settings-safety-extensions-element' is the settings page containing the + * safety check element showing the extension status. + */ +import {assertNotReached} from 'chrome://resources/js/assert.m.js'; +import {I18nBehavior} from 'chrome://resources/js/i18n_behavior.m.js'; +import {WebUIListenerBehavior} from 'chrome://resources/js/web_ui_listener_behavior.m.js'; +import {html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; + +import {MetricsBrowserProxy, MetricsBrowserProxyImpl, SafetyCheckInteractions} from '../metrics_browser_proxy.js'; +import {OpenWindowProxyImpl} from '../open_window_proxy.js'; + +import {SafetyCheckCallbackConstants, SafetyCheckExtensionsStatus} from './safety_check_browser_proxy.js'; +import {SafetyCheckIconStatus} from './safety_check_child.js'; + +/** + * @typedef {{ + * newState: SafetyCheckExtensionsStatus, + * displayString: string, + * }} + */ +let ExtensionssChangedEvent; + +Polymer({ + is: 'settings-safety-check-extensions-element', + + _template: html`{__html_template__}`, + + behaviors: [ + I18nBehavior, + WebUIListenerBehavior, + ], + + properties: { + /** + * Current state of the safety check extensions element. + * @private {!SafetyCheckExtensionsStatus} + */ + status_: { + type: Number, + value: SafetyCheckExtensionsStatus.CHECKING, + }, + + /** UI string to display for this child, received from the backend. */ + displayString_: String, + }, + + /** ?MetricsBrowserProxy */ + metricsBrowserProxy_: null, + + /** @override */ + attached: function() { + this.metricsBrowserProxy_ = MetricsBrowserProxyImpl.getInstance(); + + // Register for safety check status updates. + this.addWebUIListener( + SafetyCheckCallbackConstants.EXTENSIONS_CHANGED, + this.onSafetyCheckExtensionsChanged_.bind(this)); + }, + + /** + * @param {!ExtensionssChangedEvent} event + * @private + */ + onSafetyCheckExtensionsChanged_: function(event) { + this.status_ = event.newState; + this.displayString_ = event.displayString; + }, + + /** + * @return {SafetyCheckIconStatus} + * @private + */ + getIconStatus_: function() { + switch (this.status_) { + case SafetyCheckExtensionsStatus.CHECKING: + return SafetyCheckIconStatus.RUNNING; + case SafetyCheckExtensionsStatus.ERROR: + case SafetyCheckExtensionsStatus.BLOCKLISTED_REENABLED_ALL_BY_ADMIN: + return SafetyCheckIconStatus.INFO; + case SafetyCheckExtensionsStatus.NO_BLOCKLISTED_EXTENSIONS: + case SafetyCheckExtensionsStatus.BLOCKLISTED_ALL_DISABLED: + return SafetyCheckIconStatus.SAFE; + case SafetyCheckExtensionsStatus.BLOCKLISTED_REENABLED_ALL_BY_USER: + case SafetyCheckExtensionsStatus.BLOCKLISTED_REENABLED_SOME_BY_USER: + return SafetyCheckIconStatus.WARNING; + default: + assertNotReached(); + } + }, + + /** + * @private + * @return {?string} + */ + getButtonLabel_: function() { + switch (this.status_) { + case SafetyCheckExtensionsStatus.BLOCKLISTED_ALL_DISABLED: + case SafetyCheckExtensionsStatus.BLOCKLISTED_REENABLED_ALL_BY_USER: + case SafetyCheckExtensionsStatus.BLOCKLISTED_REENABLED_SOME_BY_USER: + return this.i18n('safetyCheckReview'); + default: + return null; + } + }, + + /** + * @private + * @return {string} + */ + getButtonClass_: function() { + switch (this.status_) { + case SafetyCheckExtensionsStatus.BLOCKLISTED_REENABLED_ALL_BY_USER: + case SafetyCheckExtensionsStatus.BLOCKLISTED_REENABLED_SOME_BY_USER: + return 'action-button'; + default: + return ''; + } + }, + + /** @private */ + onButtonClick_: function() { + // Log click both in action and histogram. + this.metricsBrowserProxy_.recordSafetyCheckInteractionHistogram( + SafetyCheckInteractions.SAFETY_CHECK_EXTENSIONS_REVIEW); + this.metricsBrowserProxy_.recordAction( + 'Settings.SafetyCheck.ReviewExtensions'); + + OpenWindowProxyImpl.getInstance().openURL('chrome://extensions'); + }, + + /** + * @private + * @return {?string} + */ + getManagedIcon_: function() { + switch (this.status_) { + case SafetyCheckExtensionsStatus.BLOCKLISTED_REENABLED_ALL_BY_ADMIN: + return 'cr20:domain'; + default: + return null; + } + }, +});
diff --git a/chrome/browser/resources/settings/safety_check_page/safety_check_page.html b/chrome/browser/resources/settings/safety_check_page/safety_check_page.html index 0421d26..81df827 100644 --- a/chrome/browser/resources/settings/safety_check_page/safety_check_page.html +++ b/chrome/browser/resources/settings/safety_check_page/safety_check_page.html
@@ -1,4 +1,3 @@ - <style include="cr-shared-style settings-shared iron-flex"> #safetyCheckCollapse .list-item.selected { min-height: var(--settings-row-two-line-min-height); @@ -10,25 +9,6 @@ padding-inline-end: var(--cr-icon-button-margin-start); width: var(--cr-link-row-icon-width, var(--cr-icon-size)); } - - .icon-blue { - fill: var(--google-blue-600); - } - - .icon-red { - fill: var(--google-red-600); - } - - /* dark mode */ - @media (prefers-color-scheme: dark) { - .icon-blue { - fill: var(--google-blue-refresh-300); - } - - .icon-red { - fill: var(--google-red-refresh-300); - } - } </style> <div id="safetyCheckParent" class="cr-row first two-line"> <iron-icon icon="settings20:safety-check" aria-hidden="true"> @@ -57,121 +37,12 @@ </div> <iron-collapse id="safetyCheckCollapse" opened="[[shouldShowChildren_(parentStatus_)]]"> - <div class="cr-row"> - <iron-icon icon="[[getUpdatesIcon_(updatesStatus_)]]" - id="updatesIcon" - role="img" - aria-label="[[getUpdatesIconAriaLabel_(updatesStatus_)]]" - src="[[getUpdatesIconSrc_(updatesStatus_)]]" - class$="[[getUpdatesIconClass_(updatesStatus_)]]"> - </iron-icon> - <div class="flex cr-padded-text"> - <div>$i18n{safetyCheckUpdatesPrimaryLabel}</div> - <div class="secondary" no-search - inner-h-t-m-l="[[updatesDisplayString_]]"> - </div> - </div> - <template is="dom-if" - if="[[shouldShowUpdatesButton_(updatesStatus_)]]" restamp> - <div class="separator"></div> - <cr-button id="safetyCheckUpdatesButton" class="action-button" - on-click="onSafetyCheckUpdatesButtonClick_" no-search - aria-label="$i18n{safetyCheckUpdatesButtonAriaLabel}"> - $i18n{aboutRelaunch} - </cr-button> - </template> - <template is="dom-if" - if="[[shouldShowUpdatesManagedIcon_(updatesStatus_)]]" restamp> - <iron-icon id="safetyCheckUpdatesManagedIcon" icon="cr20:domain" - aria-hidden="true"> - </iron-icon> - </template> - </div> - <div class="cr-row"> - <iron-icon icon="[[getPasswordsIcon_(passwordsStatus_)]]" - id="passwordsIcon" - src="[[getPasswordsIconSrc_(passwordsStatus_)]]" - class$="[[getPasswordsIconClass_(passwordsStatus_)]]" - role="img" - aria-label="[[getPasswordsIconAriaLabel_(passwordsStatus_)]]"> - </iron-icon> - <div class="flex cr-padded-text"> - <div>$i18n{passwords}</div> - <div class="secondary" no-search - inner-h-t-m-l="[[passwordsDisplayString_]]"> - </div> - </div> - <template is="dom-if" - if="[[shouldShowPasswordsButton_(passwordsStatus_)]]" restamp> - <div class="separator"></div> - <cr-button id="safetyCheckPasswordsButton" class="action-button" - on-click="onPasswordsButtonClick_" no-search - aria-label="$i18n{safetyCheckPasswordsButtonAriaLabel}"> - $i18n{safetyCheckReview} - </cr-button> - </template> - </div> - <div class="cr-row"> - <iron-icon icon="[[getSafeBrowsingIcon_(safeBrowsingStatus_)]]" - id="safeBrowsingIcon" - src="[[getSafeBrowsingIconSrc_(safeBrowsingStatus_)]]" - class$="[[getSafeBrowsingIconClass_(safeBrowsingStatus_)]]" - role="img" - aria-label="[[getSafeBrowsingIconAriaLabel_(safeBrowsingStatus_)]]"> - </iron-icon> - <div class="flex cr-padded-text"> - <div>$i18n{safeBrowsingSectionLabel}</div> - <div class="secondary" no-search - inner-h-t-m-l="[[safeBrowsingDisplayString_]]"> - </div> - </div> - <template is="dom-if" - if="[[shouldShowSafeBrowsingButton_(safeBrowsingStatus_)]]" restamp> - <div class="separator"></div> - <cr-button id="safetyCheckSafeBrowsingButton" class="action-button" - on-click="onSafeBrowsingButtonClick_" no-search - aria-label="$i18n{safetyCheckSafeBrowsingButtonAriaLabel}"> - $i18n{safetyCheckSafeBrowsingButton} - </cr-button> - </template> - <template is="dom-if" - if="[[shouldShowSafeBrowsingManagedIcon_(safeBrowsingStatus_)]]" - restamp> - <iron-icon id="safetyCheckSafeBrowsingManagedIcon" aria-hidden="true" - icon="[[getSafeBrowsingManagedIcon_(safeBrowsingStatus_)]]"> - </iron-icon> - </template> - </div> - <div class="cr-row"> - <iron-icon icon="[[getExtensionsIcon_(extensionsStatus_)]]" - id="extensionsIcon" - src="[[getExtensionsIconSrc_(extensionsStatus_)]]" - class$="[[getExtensionsIconClass_(extensionsStatus_)]]" - role="img" - aria-label="[[getExtensionsIconAriaLabel_(extensionsStatus_)]]"> - </iron-icon> - <div class="flex cr-padded-text"> - <div>$i18n{safetyCheckExtensionsPrimaryLabel}</div> - <div class="secondary" no-search - inner-h-t-m-l="[[extensionsDisplayString_]]"> - </div> - </div> - <template is="dom-if" - if="[[shouldShowExtensionsButton_(extensionsStatus_)]]" restamp> - <div class="separator"></div> - <cr-button id="safetyCheckExtensionsButton" - class$="[[getExtensionsButtonClass_(extensionsStatus_)]]" - on-click="onSafetyCheckExtensionsButtonClick_" no-search - aria-label="$i18n{safetyCheckExtensionsButtonAriaLabel}"> - $i18n{safetyCheckReview} - </cr-button> - </template> - <template is="dom-if" - if="[[shouldShowExtensionsManagedIcon_(extensionsStatus_)]]" - restamp> - <iron-icon id="safetyCheckExtensionsManagedIcon" icon="cr20:domain" - aria-hidden="true"> - </iron-icon> - </template> - </div> + <settings-safety-check-updates-element> + </settings-safety-check-updates-element> + <settings-safety-check-passwords-element> + </settings-safety-check-passwords-element> + <settings-safety-check-safe-browsing-element> + </settings-safety-check-safe-browsing-element> + <settings-safety-check-extensions-element> + </settings-safety-check-extensions-element> </iron-collapse>
diff --git a/chrome/browser/resources/settings/safety_check_page/safety_check_page.js b/chrome/browser/resources/settings/safety_check_page/safety_check_page.js index 4d6d1172..0266ba4 100644 --- a/chrome/browser/resources/settings/safety_check_page/safety_check_page.js +++ b/chrome/browser/resources/settings/safety_check_page/safety_check_page.js
@@ -16,6 +16,10 @@ import 'chrome://resources/polymer/v3_0/iron-flex-layout/iron-flex-layout-classes.js'; import 'chrome://resources/polymer/v3_0/iron-icon/iron-icon.js'; import '../settings_shared_css.m.js'; +import './safety_check_extensions_element.js'; +import './safety_check_passwords_element.js'; +import './safety_check_safe_browsing_element.js'; +import './safety_check_updates_element.js'; import {assertNotReached} from 'chrome://resources/js/assert.m.js'; import {I18nBehavior} from 'chrome://resources/js/i18n_behavior.m.js'; @@ -23,29 +27,11 @@ import {IronA11yAnnouncer} from 'chrome://resources/polymer/v3_0/iron-a11y-announcer/iron-a11y-announcer.js'; import {flush, html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; -import {PasswordManagerImpl, PasswordManagerProxy} from '../autofill_page/password_manager_proxy.js'; import {HatsBrowserProxyImpl} from '../hats_browser_proxy.js'; import {loadTimeData} from '../i18n_setup.js'; -import {LifetimeBrowserProxy, LifetimeBrowserProxyImpl} from '../lifetime_browser_proxy.m.js'; import {MetricsBrowserProxy, MetricsBrowserProxyImpl, SafetyCheckInteractions} from '../metrics_browser_proxy.js'; -import {OpenWindowProxyImpl} from '../open_window_proxy.js'; -import {PrefsBehavior} from '../prefs/prefs_behavior.m.js'; -import {routes} from '../route.js'; -import {Router} from '../router.m.js'; -import {SafetyCheckBrowserProxy, SafetyCheckBrowserProxyImpl, SafetyCheckCallbackConstants, SafetyCheckExtensionsStatus, SafetyCheckParentStatus, SafetyCheckPasswordsStatus, SafetyCheckSafeBrowsingStatus, SafetyCheckUpdatesStatus} from './safety_check_browser_proxy.js'; - - -/** - * UI states a safety check child can be in. Defines the basic UI of the child. - * @enum {number} - */ -const ChildUiStatus = { - RUNNING: 0, - SAFE: 1, - INFO: 2, - WARNING: 3, -}; +import {SafetyCheckBrowserProxy, SafetyCheckBrowserProxyImpl, SafetyCheckCallbackConstants, SafetyCheckParentStatus} from './safety_check_browser_proxy.js'; /** * @typedef {{ @@ -55,38 +41,6 @@ */ let ParentChangedEvent; -/** - * @typedef {{ - * newState: SafetyCheckUpdatesStatus, - * displayString: string, - * }} - */ -let UpdatesChangedEvent; - -/** - * @typedef {{ - * newState: SafetyCheckPasswordsStatus, - * displayString: string, - * }} - */ -let PasswordsChangedEvent; - -/** - * @typedef {{ - * newState: SafetyCheckSafeBrowsingStatus, - * displayString: string, - * }} - */ -let SafeBrowsingChangedEvent; - -/** - * @typedef {{ - * newState: SafetyCheckExtensionsStatus, - * displayString: string, - * }} - */ -let ExtensionsChangedEvent; - Polymer({ is: 'settings-safety-check-page', @@ -108,78 +62,15 @@ }, /** - * Current state of the safety check updates element. - * @private {!SafetyCheckUpdatesStatus} - */ - updatesStatus_: { - type: Number, - value: SafetyCheckUpdatesStatus.CHECKING, - }, - - /** - * Current state of the safety check passwords element. - * @private {!SafetyCheckPasswordsStatus} - */ - passwordsStatus_: { - type: Number, - value: SafetyCheckPasswordsStatus.CHECKING, - }, - - /** - * Current state of the safety check safe browsing element. - * @private {!SafetyCheckSafeBrowsingStatus} - */ - safeBrowsingStatus_: { - type: Number, - value: SafetyCheckSafeBrowsingStatus.CHECKING, - }, - - /** - * Current state of the safety check extensions element. - * @private {!SafetyCheckExtensionsStatus} - */ - extensionsStatus_: { - type: Number, - value: SafetyCheckExtensionsStatus.CHECKING, - }, - - /** * UI string to display for the parent status. * @private */ parentDisplayString_: String, - - /** - * UI string to display for the updates status. - * @private - */ - updatesDisplayString_: String, - - /** - * UI string to display for the passwords status. - * @private - */ - passwordsDisplayString_: String, - - /** - * UI string to display for the Safe Browsing status. - * @private - */ - safeBrowsingDisplayString_: String, - - /** - * UI string to display for the extensions status. - * @private - */ - extensionsDisplayString_: String, }, /** @private {SafetyCheckBrowserProxy} */ safetyCheckBrowserProxy_: null, - /** @private {?LifetimeBrowserProxy} */ - lifetimeBrowserProxy_: null, - /** @private {?MetricsBrowserProxy} */ metricsBrowserProxy_: null, @@ -192,25 +83,12 @@ /** @override */ attached: function() { this.safetyCheckBrowserProxy_ = SafetyCheckBrowserProxyImpl.getInstance(); - this.lifetimeBrowserProxy_ = LifetimeBrowserProxyImpl.getInstance(); this.metricsBrowserProxy_ = MetricsBrowserProxyImpl.getInstance(); // Register for safety check status updates. this.addWebUIListener( SafetyCheckCallbackConstants.PARENT_CHANGED, this.onSafetyCheckParentChanged_.bind(this)); - this.addWebUIListener( - SafetyCheckCallbackConstants.UPDATES_CHANGED, - this.onSafetyCheckUpdatesChanged_.bind(this)); - this.addWebUIListener( - SafetyCheckCallbackConstants.PASSWORDS_CHANGED, - this.onSafetyCheckPasswordsChanged_.bind(this)); - this.addWebUIListener( - SafetyCheckCallbackConstants.SAFE_BROWSING_CHANGED, - this.onSafetyCheckSafeBrowsingChanged_.bind(this)); - this.addWebUIListener( - SafetyCheckCallbackConstants.EXTENSIONS_CHANGED, - this.onSafetyCheckExtensionsChanged_.bind(this)); // Configure default UI. this.parentDisplayString_ = @@ -260,42 +138,6 @@ }, /** - * @param {!UpdatesChangedEvent} event - * @private - */ - onSafetyCheckUpdatesChanged_: function(event) { - this.updatesStatus_ = event.newState; - this.updatesDisplayString_ = event.displayString; - }, - - /** - * @param {!PasswordsChangedEvent} event - * @private - */ - onSafetyCheckPasswordsChanged_: function(event) { - this.passwordsDisplayString_ = event.displayString; - this.passwordsStatus_ = event.newState; - }, - - /** - * @param {!SafeBrowsingChangedEvent} event - * @private - */ - onSafetyCheckSafeBrowsingChanged_: function(event) { - this.safeBrowsingStatus_ = event.newState; - this.safeBrowsingDisplayString_ = event.displayString; - }, - - /** - * @param {!ExtensionsChangedEvent} event - * @private - */ - onSafetyCheckExtensionsChanged_: function(event) { - this.extensionsDisplayString_ = event.displayString; - this.extensionsStatus_ = event.newState; - }, - - /** * @private * @return {boolean} */ @@ -338,438 +180,4 @@ shouldShowChildren_: function() { return this.parentStatus_ != SafetyCheckParentStatus.BEFORE; }, - - /** - * Returns the default icon for a safety check child in the specified state. - * @private - * @param {ChildUiStatus} childUiStatus - * @return {?string} - */ - getChildUiIcon_: function(childUiStatus) { - switch (childUiStatus) { - case ChildUiStatus.RUNNING: - return null; - case ChildUiStatus.SAFE: - return 'cr:check'; - case ChildUiStatus.INFO: - return 'cr:info'; - case ChildUiStatus.WARNING: - return 'cr:warning'; - default: - assertNotReached(); - } - }, - - /** - * Returns the default icon src for animated icons for a safety check child - * in the specified state. - * @private - * @param {ChildUiStatus} childUiStatus - * @return {?string} - */ - getChildUiIconSrc_: function(childUiStatus) { - if (childUiStatus === ChildUiStatus.RUNNING) { - return 'chrome://resources/images/throbber_small.svg'; - } - return null; - }, - - /** - * Returns the default icon class for a safety check child in the specified - * state. - * @private - * @param {ChildUiStatus} childUiStatus - * @return {string} - */ - getChildUiIconClass_: function(childUiStatus) { - switch (childUiStatus) { - case ChildUiStatus.RUNNING: - case ChildUiStatus.SAFE: - return 'icon-blue'; - case ChildUiStatus.WARNING: - return 'icon-red'; - default: - return ''; - } - }, - - /** - * Returns the default icon aria label for a safety check child in the - * specified state. - * @private - * @param {ChildUiStatus} childUiStatus - * @return {string} - */ - getChildUiIconAriaLabel_: function(childUiStatus) { - switch (childUiStatus) { - case ChildUiStatus.RUNNING: - return this.i18n('safetyCheckIconRunningAriaLabel'); - case ChildUiStatus.SAFE: - return this.i18n('safetyCheckIconSafeAriaLabel'); - case ChildUiStatus.INFO: - return this.i18n('safetyCheckIconInfoAriaLabel'); - case ChildUiStatus.WARNING: - return this.i18n('safetyCheckIconWarningAriaLabel'); - default: - assertNotReached(); - } - }, - - /** - * @private - * @return {boolean} - */ - shouldShowUpdatesButton_: function() { - return this.updatesStatus_ === SafetyCheckUpdatesStatus.RELAUNCH; - }, - - /** - * @private - * @return {boolean} - */ - shouldShowUpdatesManagedIcon_: function() { - return this.updatesStatus_ === SafetyCheckUpdatesStatus.DISABLED_BY_ADMIN; - }, - - /** @private */ - onSafetyCheckUpdatesButtonClick_: function() { - // Log click both in action and histogram. - this.metricsBrowserProxy_.recordSafetyCheckInteractionHistogram( - SafetyCheckInteractions.SAFETY_CHECK_UPDATES_RELAUNCH); - this.metricsBrowserProxy_.recordAction( - 'Settings.SafetyCheck.RelaunchAfterUpdates'); - - this.lifetimeBrowserProxy_.relaunch(); - }, - - /** - * @return {ChildUiStatus} - * @private - */ - getUpdatesUiStatus_: function() { - switch (this.updatesStatus_) { - case SafetyCheckUpdatesStatus.CHECKING: - case SafetyCheckUpdatesStatus.UPDATING: - return ChildUiStatus.RUNNING; - case SafetyCheckUpdatesStatus.UPDATED: - return ChildUiStatus.SAFE; - case SafetyCheckUpdatesStatus.RELAUNCH: - case SafetyCheckUpdatesStatus.DISABLED_BY_ADMIN: - case SafetyCheckUpdatesStatus.FAILED_OFFLINE: - case SafetyCheckUpdatesStatus.UNKNOWN: - return ChildUiStatus.INFO; - case SafetyCheckUpdatesStatus.FAILED: - return ChildUiStatus.WARNING; - default: - assertNotReached(); - } - }, - - /** - * @private - * @return {?string} - */ - getUpdatesIcon_: function() { - return this.getChildUiIcon_(this.getUpdatesUiStatus_()); - }, - - /** - * @private - * @return {?string} - */ - getUpdatesIconSrc_: function() { - return this.getChildUiIconSrc_(this.getUpdatesUiStatus_()); - }, - - /** - * @private - * @return {string} - */ - getUpdatesIconClass_: function() { - return this.getChildUiIconClass_(this.getUpdatesUiStatus_()); - }, - - /** - * @private - * @return {string} - */ - getUpdatesIconAriaLabel_: function() { - return this.getChildUiIconAriaLabel_(this.getUpdatesUiStatus_()); - }, - - /** - * @private - * @return {boolean} - */ - shouldShowPasswordsButton_: function() { - return this.passwordsStatus_ === SafetyCheckPasswordsStatus.COMPROMISED; - }, - - /** - * @private - * @return {ChildUiStatus} - */ - getPasswordsUiStatus_: function() { - switch (this.passwordsStatus_) { - case SafetyCheckPasswordsStatus.CHECKING: - return ChildUiStatus.RUNNING; - case SafetyCheckPasswordsStatus.SAFE: - return ChildUiStatus.SAFE; - case SafetyCheckPasswordsStatus.COMPROMISED: - return ChildUiStatus.WARNING; - case SafetyCheckPasswordsStatus.OFFLINE: - case SafetyCheckPasswordsStatus.NO_PASSWORDS: - case SafetyCheckPasswordsStatus.SIGNED_OUT: - case SafetyCheckPasswordsStatus.QUOTA_LIMIT: - case SafetyCheckPasswordsStatus.ERROR: - return ChildUiStatus.INFO; - default: - assertNotReached(); - } - }, - - /** - * @private - * @return {?string} - */ - getPasswordsIcon_: function() { - return this.getChildUiIcon_(this.getPasswordsUiStatus_()); - }, - - /** - * @private - * @return {?string} - */ - getPasswordsIconSrc_: function() { - return this.getChildUiIconSrc_(this.getPasswordsUiStatus_()); - }, - - /** - * @private - * @return {string} - */ - getPasswordsIconClass_: function() { - return this.getChildUiIconClass_(this.getPasswordsUiStatus_()); - }, - - /** - * @private - * @return {string} - */ - getPasswordsIconAriaLabel_: function() { - return this.getChildUiIconAriaLabel_(this.getPasswordsUiStatus_()); - }, - - /** @private */ - onPasswordsButtonClick_: function() { - // Log click both in action and histogram. - this.metricsBrowserProxy_.recordSafetyCheckInteractionHistogram( - SafetyCheckInteractions.SAFETY_CHECK_PASSWORDS_MANAGE); - this.metricsBrowserProxy_.recordAction( - 'Settings.SafetyCheck.ManagePasswords'); - - Router.getInstance().navigateTo(routes.CHECK_PASSWORDS); - PasswordManagerImpl.getInstance().recordPasswordCheckReferrer( - PasswordManagerProxy.PasswordCheckReferrer.SAFETY_CHECK); - }, - - /** - * @private - * @return {boolean} - */ - shouldShowSafeBrowsingButton_: function() { - return this.safeBrowsingStatus_ === SafetyCheckSafeBrowsingStatus.DISABLED; - }, - - /** - * @private - * @return {boolean} - */ - shouldShowSafeBrowsingManagedIcon_: function() { - return this.getSafeBrowsingManagedIcon_() != null; - }, - - /** - * @private - * @return {?string} - */ - getSafeBrowsingManagedIcon_: function() { - switch (this.safeBrowsingStatus_) { - case SafetyCheckSafeBrowsingStatus.DISABLED_BY_ADMIN: - return 'cr20:domain'; - case SafetyCheckSafeBrowsingStatus.DISABLED_BY_EXTENSION: - return 'cr:extension'; - default: - return null; - } - }, - - /** - * @private - * @return {ChildUiStatus} - */ - getSafeBrowsingUiStatus_: function() { - switch (this.safeBrowsingStatus_) { - case SafetyCheckSafeBrowsingStatus.CHECKING: - return ChildUiStatus.RUNNING; - case SafetyCheckSafeBrowsingStatus.ENABLED_STANDARD: - case SafetyCheckSafeBrowsingStatus.ENABLED_ENHANCED: - return ChildUiStatus.SAFE; - case SafetyCheckSafeBrowsingStatus.ENABLED: - // ENABLED is deprecated. - assertNotReached(); - case SafetyCheckSafeBrowsingStatus.DISABLED: - case SafetyCheckSafeBrowsingStatus.DISABLED_BY_ADMIN: - case SafetyCheckSafeBrowsingStatus.DISABLED_BY_EXTENSION: - return ChildUiStatus.INFO; - default: - assertNotReached(); - } - }, - - /** - * @private - * @return {?string} - */ - getSafeBrowsingIcon_: function() { - return this.getChildUiIcon_(this.getSafeBrowsingUiStatus_()); - }, - - /** - * @private - * @return {?string} - */ - getSafeBrowsingIconSrc_: function() { - return this.getChildUiIconSrc_(this.getSafeBrowsingUiStatus_()); - }, - - /** - * @private - * @return {string} - */ - getSafeBrowsingIconClass_: function() { - return this.getChildUiIconClass_(this.getSafeBrowsingUiStatus_()); - }, - - /** - * @private - * @return {string} - */ - getSafeBrowsingIconAriaLabel_: function() { - return this.getChildUiIconAriaLabel_(this.getSafeBrowsingUiStatus_()); - }, - - /** @private */ - onSafeBrowsingButtonClick_: function() { - // Log click both in action and histogram. - this.metricsBrowserProxy_.recordSafetyCheckInteractionHistogram( - SafetyCheckInteractions.SAFETY_CHECK_SAFE_BROWSING_MANAGE); - this.metricsBrowserProxy_.recordAction( - 'Settings.SafetyCheck.ManageSafeBrowsing'); - - Router.getInstance().navigateTo(routes.SECURITY); - }, - - /** - * @private - * @return {boolean} - */ - shouldShowExtensionsButton_: function() { - switch (this.extensionsStatus_) { - case SafetyCheckExtensionsStatus.BLOCKLISTED_ALL_DISABLED: - case SafetyCheckExtensionsStatus.BLOCKLISTED_REENABLED_ALL_BY_USER: - case SafetyCheckExtensionsStatus.BLOCKLISTED_REENABLED_SOME_BY_USER: - return true; - default: - return false; - } - }, - - /** - * @private - * @return {boolean} - */ - shouldShowExtensionsManagedIcon_: function() { - return this.extensionsStatus_ === - SafetyCheckExtensionsStatus.BLOCKLISTED_REENABLED_ALL_BY_ADMIN; - }, - - /** @private */ - onSafetyCheckExtensionsButtonClick_: function() { - // Log click both in action and histogram. - this.metricsBrowserProxy_.recordSafetyCheckInteractionHistogram( - SafetyCheckInteractions.SAFETY_CHECK_EXTENSIONS_REVIEW); - this.metricsBrowserProxy_.recordAction( - 'Settings.SafetyCheck.ReviewExtensions'); - - OpenWindowProxyImpl.getInstance().openURL('chrome://extensions'); - }, - - /** - * @private - * @return {ChildUiStatus} - */ - getExtensionsUiStatus_: function() { - switch (this.extensionsStatus_) { - case SafetyCheckExtensionsStatus.CHECKING: - return ChildUiStatus.RUNNING; - case SafetyCheckExtensionsStatus.ERROR: - case SafetyCheckExtensionsStatus.BLOCKLISTED_REENABLED_ALL_BY_ADMIN: - return ChildUiStatus.INFO; - case SafetyCheckExtensionsStatus.NO_BLOCKLISTED_EXTENSIONS: - case SafetyCheckExtensionsStatus.BLOCKLISTED_ALL_DISABLED: - return ChildUiStatus.SAFE; - case SafetyCheckExtensionsStatus.BLOCKLISTED_REENABLED_ALL_BY_USER: - case SafetyCheckExtensionsStatus.BLOCKLISTED_REENABLED_SOME_BY_USER: - return ChildUiStatus.WARNING; - default: - assertNotReached(); - } - }, - - /** - * @private - * @return {?string} - */ - getExtensionsIcon_: function() { - return this.getChildUiIcon_(this.getExtensionsUiStatus_()); - }, - - /** - * @private - * @return {?string} - */ - getExtensionsIconSrc_: function() { - return this.getChildUiIconSrc_(this.getExtensionsUiStatus_()); - }, - - /** - * @private - * @return {string} - */ - getExtensionsIconClass_: function() { - return this.getChildUiIconClass_(this.getExtensionsUiStatus_()); - }, - - /** - * @private - * @return {string} - */ - getExtensionsIconAriaLabel_: function() { - return this.getChildUiIconAriaLabel_(this.getExtensionsUiStatus_()); - }, - - /** - * @private - * @return {string} - */ - getExtensionsButtonClass_: function() { - switch (this.extensionsStatus_) { - case SafetyCheckExtensionsStatus.BLOCKLISTED_REENABLED_ALL_BY_USER: - case SafetyCheckExtensionsStatus.BLOCKLISTED_REENABLED_SOME_BY_USER: - return 'action-button'; - default: - return ''; - } - }, });
diff --git a/chrome/browser/resources/settings/safety_check_page/safety_check_passwords_element.html b/chrome/browser/resources/settings/safety_check_page/safety_check_passwords_element.html new file mode 100644 index 0000000..55bbdb06 --- /dev/null +++ b/chrome/browser/resources/settings/safety_check_page/safety_check_passwords_element.html
@@ -0,0 +1,10 @@ +<settings-safety-check-child + id="safetyCheckChild" + icon-status="[[getIconStatus_(status_)]]" + label="$i18n{passwords}" + sub-label="[[displayString_]]" + button-label="[[getButtonLabel_(status_)]]" + button-aria-label="$i18n{safetyCheckPasswordsButtonAriaLabel}" + button-class="action-button" + on-button-click="onButtonClick_"> +</settings-safety-check-child>
diff --git a/chrome/browser/resources/settings/safety_check_page/safety_check_passwords_element.js b/chrome/browser/resources/settings/safety_check_page/safety_check_passwords_element.js new file mode 100644 index 0000000..790780e --- /dev/null +++ b/chrome/browser/resources/settings/safety_check_page/safety_check_passwords_element.js
@@ -0,0 +1,125 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * @fileoverview + * 'settings-safety-passwords-element' is the settings page containing the + * safety check element showing the password status. + */ +import {assertNotReached} from 'chrome://resources/js/assert.m.js'; +import {I18nBehavior} from 'chrome://resources/js/i18n_behavior.m.js'; +import {WebUIListenerBehavior} from 'chrome://resources/js/web_ui_listener_behavior.m.js'; +import {html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; + +import {PasswordManagerImpl, PasswordManagerProxy} from '../autofill_page/password_manager_proxy.js'; +import {MetricsBrowserProxy, MetricsBrowserProxyImpl, SafetyCheckInteractions} from '../metrics_browser_proxy.js'; +import {routes} from '../route.js'; +import {Router} from '../router.m.js'; + +import {SafetyCheckCallbackConstants, SafetyCheckPasswordsStatus} from './safety_check_browser_proxy.js'; +import {SafetyCheckIconStatus} from './safety_check_child.js'; + +/** + * @typedef {{ + * newState: SafetyCheckPasswordsStatus, + * displayString: string, + * }} + */ +let PasswordsChangedEvent; + +Polymer({ + is: 'settings-safety-check-passwords-element', + + _template: html`{__html_template__}`, + + behaviors: [ + I18nBehavior, + WebUIListenerBehavior, + ], + + properties: { + /** + * Current state of the safety check passwords element. + * @private {!SafetyCheckPasswordsStatus} + */ + status_: { + type: Number, + value: SafetyCheckPasswordsStatus.CHECKING, + }, + + /** UI string to display for this child, received from the backend. */ + displayString_: String, + }, + + /** ?MetricsBrowserProxy */ + metricsBrowserProxy_: null, + + /** @override */ + attached: function() { + this.metricsBrowserProxy_ = MetricsBrowserProxyImpl.getInstance(); + + // Register for safety check status updates. + this.addWebUIListener( + SafetyCheckCallbackConstants.PASSWORDS_CHANGED, + this.onSafetyCheckPasswordsChanged_.bind(this)); + }, + + /** + * @param {!PasswordsChangedEvent} event + * @private + */ + onSafetyCheckPasswordsChanged_: function(event) { + this.status_ = event.newState; + this.displayString_ = event.displayString; + }, + + /** + * @return {SafetyCheckIconStatus} + * @private + */ + getIconStatus_: function() { + switch (this.status_) { + case SafetyCheckPasswordsStatus.CHECKING: + return SafetyCheckIconStatus.RUNNING; + case SafetyCheckPasswordsStatus.SAFE: + return SafetyCheckIconStatus.SAFE; + case SafetyCheckPasswordsStatus.COMPROMISED: + return SafetyCheckIconStatus.WARNING; + case SafetyCheckPasswordsStatus.OFFLINE: + case SafetyCheckPasswordsStatus.NO_PASSWORDS: + case SafetyCheckPasswordsStatus.SIGNED_OUT: + case SafetyCheckPasswordsStatus.QUOTA_LIMIT: + case SafetyCheckPasswordsStatus.ERROR: + return SafetyCheckIconStatus.INFO; + default: + assertNotReached(); + } + }, + + /** + * @private + * @return {?string} + */ + getButtonLabel_: function() { + switch (this.status_) { + case SafetyCheckPasswordsStatus.COMPROMISED: + return this.i18n('safetyCheckReview'); + default: + return null; + } + }, + + /** @private */ + onButtonClick_: function() { + // Log click both in action and histogram. + this.metricsBrowserProxy_.recordSafetyCheckInteractionHistogram( + SafetyCheckInteractions.SAFETY_CHECK_PASSWORDS_MANAGE); + this.metricsBrowserProxy_.recordAction( + 'Settings.SafetyCheck.ManagePasswords'); + + Router.getInstance().navigateTo(routes.CHECK_PASSWORDS); + PasswordManagerImpl.getInstance().recordPasswordCheckReferrer( + PasswordManagerProxy.PasswordCheckReferrer.SAFETY_CHECK); + }, +});
diff --git a/chrome/browser/resources/settings/safety_check_page/safety_check_safe_browsing_element.html b/chrome/browser/resources/settings/safety_check_page/safety_check_safe_browsing_element.html new file mode 100644 index 0000000..9ed22b8a --- /dev/null +++ b/chrome/browser/resources/settings/safety_check_page/safety_check_safe_browsing_element.html
@@ -0,0 +1,11 @@ +<settings-safety-check-child + id="safetyCheckChild" + icon-status="[[getIconStatus_(status_)]]" + label="$i18n{safeBrowsingSectionLabel}" + sub-label="[[displayString_]]" + button-label="[[getButtonLabel_(status_)]]" + button-aria-label="$i18n{safetyCheckSafeBrowsingButtonAriaLabel}" + button-class="action-button" + on-button-click="onButtonClick_" + managed-icon="[[getManagedIcon_(status_)]]"> +</settings-safety-check-child>
diff --git a/chrome/browser/resources/settings/safety_check_page/safety_check_safe_browsing_element.js b/chrome/browser/resources/settings/safety_check_page/safety_check_safe_browsing_element.js new file mode 100644 index 0000000..73ff0c42 --- /dev/null +++ b/chrome/browser/resources/settings/safety_check_page/safety_check_safe_browsing_element.js
@@ -0,0 +1,138 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * @fileoverview + * 'settings-safety-safe-browsing-element' is the settings page containing the + * safety check element showing the Safe Browsing status. + */ +import {assertNotReached} from 'chrome://resources/js/assert.m.js'; +import {I18nBehavior} from 'chrome://resources/js/i18n_behavior.m.js'; +import {WebUIListenerBehavior} from 'chrome://resources/js/web_ui_listener_behavior.m.js'; +import {html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; + +import {MetricsBrowserProxy, MetricsBrowserProxyImpl, SafetyCheckInteractions} from '../metrics_browser_proxy.js'; +import {routes} from '../route.js'; +import {Router} from '../router.m.js'; + +import {SafetyCheckCallbackConstants, SafetyCheckSafeBrowsingStatus} from './safety_check_browser_proxy.js'; +import {SafetyCheckIconStatus} from './safety_check_child.js'; + +/** + * @typedef {{ + * newState: SafetyCheckSafeBrowsingStatus, + * displayString: string, + * }} + */ +let SafeBrowsingChangedEvent; + +Polymer({ + is: 'settings-safety-check-safe-browsing-element', + + _template: html`{__html_template__}`, + + behaviors: [ + I18nBehavior, + WebUIListenerBehavior, + ], + + properties: { + /** + * Current state of the safety check safe browsing element, received from + * the backend. + * @private {!SafetyCheckSafeBrowsingStatus} + */ + status_: { + type: Number, + value: SafetyCheckSafeBrowsingStatus.CHECKING, + }, + + /** UI string to display for this child, received from the backend. */ + displayString_: String, + }, + + /** ?MetricsBrowserProxy */ + metricsBrowserProxy_: null, + + /** @override */ + attached: function() { + this.metricsBrowserProxy_ = MetricsBrowserProxyImpl.getInstance(); + + // Register for safety check status updates. + this.addWebUIListener( + SafetyCheckCallbackConstants.SAFE_BROWSING_CHANGED, + this.onSafetyCheckSafeBrowsingChanged_.bind(this)); + }, + + /** + * @param {!SafeBrowsingChangedEvent} event + * @private + */ + onSafetyCheckSafeBrowsingChanged_: function(event) { + this.displayString_ = event.displayString; + this.status_ = event.newState; + }, + + /** + * @return {SafetyCheckIconStatus} + * @private + */ + getIconStatus_: function() { + switch (this.status_) { + case SafetyCheckSafeBrowsingStatus.CHECKING: + return SafetyCheckIconStatus.RUNNING; + case SafetyCheckSafeBrowsingStatus.ENABLED_STANDARD: + case SafetyCheckSafeBrowsingStatus.ENABLED_ENHANCED: + return SafetyCheckIconStatus.SAFE; + case SafetyCheckSafeBrowsingStatus.ENABLED: + // ENABLED is deprecated. + assertNotReached(); + case SafetyCheckSafeBrowsingStatus.DISABLED: + case SafetyCheckSafeBrowsingStatus.DISABLED_BY_ADMIN: + case SafetyCheckSafeBrowsingStatus.DISABLED_BY_EXTENSION: + return SafetyCheckIconStatus.INFO; + default: + assertNotReached(); + } + }, + + /** + * @private + * @return {?string} + */ + getButtonLabel_: function() { + switch (this.status_) { + case SafetyCheckSafeBrowsingStatus.DISABLED: + return this.i18n('safetyCheckSafeBrowsingButton'); + default: + return null; + } + }, + + /** @private */ + onButtonClick_: function() { + // Log click both in action and histogram. + this.metricsBrowserProxy_.recordSafetyCheckInteractionHistogram( + SafetyCheckInteractions.SAFETY_CHECK_SAFE_BROWSING_MANAGE); + this.metricsBrowserProxy_.recordAction( + 'Settings.SafetyCheck.ManageSafeBrowsing'); + + Router.getInstance().navigateTo(routes.SECURITY); + }, + + /** + * @private + * @return {?string} + */ + getManagedIcon_: function() { + switch (this.status_) { + case SafetyCheckSafeBrowsingStatus.DISABLED_BY_ADMIN: + return 'cr20:domain'; + case SafetyCheckSafeBrowsingStatus.DISABLED_BY_EXTENSION: + return 'cr:extension'; + default: + return null; + } + }, +});
diff --git a/chrome/browser/resources/settings/safety_check_page/safety_check_updates_element.html b/chrome/browser/resources/settings/safety_check_page/safety_check_updates_element.html new file mode 100644 index 0000000..9b247b6 --- /dev/null +++ b/chrome/browser/resources/settings/safety_check_page/safety_check_updates_element.html
@@ -0,0 +1,11 @@ +<settings-safety-check-child + id="safetyCheckChild" + icon-status="[[getIconStatus_(status_)]]" + label="$i18n{safetyCheckUpdatesPrimaryLabel}" + sub-label="[[displayString_]]" + button-label="[[getButtonLabel_(status_)]]" + button-aria-label="$i18n{safetyCheckUpdatesButtonAriaLabel}" + button-class="action-button" + on-button-click="onButtonClick_" + managed-icon="[[getManagedIcon_(status_)]]"> +</settings-safety-check-child>
diff --git a/chrome/browser/resources/settings/safety_check_page/safety_check_updates_element.js b/chrome/browser/resources/settings/safety_check_page/safety_check_updates_element.js new file mode 100644 index 0000000..9d952fc --- /dev/null +++ b/chrome/browser/resources/settings/safety_check_page/safety_check_updates_element.js
@@ -0,0 +1,138 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * @fileoverview + * 'settings-safety-updates-element' is the settings page containing the safety + * check element showing the browser's update status. + */ +import {assertNotReached} from 'chrome://resources/js/assert.m.js'; +import {I18nBehavior} from 'chrome://resources/js/i18n_behavior.m.js'; +import {WebUIListenerBehavior} from 'chrome://resources/js/web_ui_listener_behavior.m.js'; +import {html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; + +import {LifetimeBrowserProxy, LifetimeBrowserProxyImpl} from '../lifetime_browser_proxy.m.js'; +import {MetricsBrowserProxy, MetricsBrowserProxyImpl, SafetyCheckInteractions} from '../metrics_browser_proxy.js'; + +import {SafetyCheckCallbackConstants, SafetyCheckUpdatesStatus} from './safety_check_browser_proxy.js'; +import {SafetyCheckIconStatus} from './safety_check_child.js'; + +/** + * @typedef {{ + * newState: SafetyCheckUpdatesStatus, + * displayString: string, + * }} + */ +let UpdatesChangedEvent; + +Polymer({ + is: 'settings-safety-check-updates-element', + + _template: html`{__html_template__}`, + + behaviors: [ + I18nBehavior, + WebUIListenerBehavior, + ], + + properties: { + /** + * Current state of the safety check updates element. + * @private {!SafetyCheckUpdatesStatus} + */ + status_: { + type: Number, + value: SafetyCheckUpdatesStatus.CHECKING, + }, + + /** UI string to display for this child, received from the backend. */ + displayString_: String, + }, + + /** @private {?LifetimeBrowserProxy} */ + lifetimeBrowserProxy_: null, + + /** ?MetricsBrowserProxy */ + metricsBrowserProxy_: null, + + /** @override */ + attached: function() { + this.lifetimeBrowserProxy_ = LifetimeBrowserProxyImpl.getInstance(); + this.metricsBrowserProxy_ = MetricsBrowserProxyImpl.getInstance(); + + // Register for safety check status updates. + this.addWebUIListener( + SafetyCheckCallbackConstants.UPDATES_CHANGED, + this.onSafetyCheckUpdatesChanged_.bind(this)); + }, + + /** + * @param {!UpdatesChangedEvent} event + * @private + */ + onSafetyCheckUpdatesChanged_: function(event) { + this.status_ = event.newState; + this.displayString_ = event.displayString; + }, + + /** + * @return {SafetyCheckIconStatus} + * @private + */ + getIconStatus_: function() { + switch (this.status_) { + case SafetyCheckUpdatesStatus.CHECKING: + case SafetyCheckUpdatesStatus.UPDATING: + return SafetyCheckIconStatus.RUNNING; + case SafetyCheckUpdatesStatus.UPDATED: + return SafetyCheckIconStatus.SAFE; + case SafetyCheckUpdatesStatus.RELAUNCH: + case SafetyCheckUpdatesStatus.DISABLED_BY_ADMIN: + case SafetyCheckUpdatesStatus.FAILED_OFFLINE: + case SafetyCheckUpdatesStatus.UNKNOWN: + return SafetyCheckIconStatus.INFO; + case SafetyCheckUpdatesStatus.FAILED: + return SafetyCheckIconStatus.WARNING; + default: + assertNotReached(); + } + }, + + /** + * @private + * @return {?string} + */ + getButtonLabel_: function() { + switch (this.status_) { + case SafetyCheckUpdatesStatus.RELAUNCH: + return this.i18n('aboutRelaunch'); + default: + return null; + } + }, + + /** @private */ + onButtonClick_: function() { + // Log click both in action and histogram. + this.metricsBrowserProxy_.recordSafetyCheckInteractionHistogram( + SafetyCheckInteractions.SAFETY_CHECK_UPDATES_RELAUNCH); + this.metricsBrowserProxy_.recordAction( + 'Settings.SafetyCheck.RelaunchAfterUpdates'); + + this.lifetimeBrowserProxy_.relaunch(); + }, + + /** + * @private + * @return {?string} + */ + getManagedIcon_: function() { + switch (this.status_) { + case SafetyCheckUpdatesStatus.DISABLED_BY_ADMIN: + return 'cr20:domain'; + default: + return null; + } + }, +});
diff --git a/chrome/browser/resources/settings/settings.gni b/chrome/browser/resources/settings/settings.gni index f5bbb72d..48e79e5 100644 --- a/chrome/browser/resources/settings/settings.gni +++ b/chrome/browser/resources/settings/settings.gni
@@ -98,6 +98,7 @@ "settings.SafetyCheckBrowserProxy|SafetyCheckBrowserProxy", "settings.SafetyCheckCallbackConstants|SafetyCheckCallbackConstants", "settings.SafetyCheckExtensionsStatus|SafetyCheckExtensionsStatus", + "settings.SafetyCheckIconStatus|SafetyCheckIconStatus", "settings.SafetyCheckParentStatus|SafetyCheckParentStatus", "settings.SafetyCheckPasswordsStatus|SafetyCheckPasswordsStatus", "settings.SafetyCheckSafeBrowsingStatus|SafetyCheckSafeBrowsingStatus",
diff --git a/chrome/browser/resources/settings/settings.js b/chrome/browser/resources/settings/settings.js index 6d6b929..e39f075 100644 --- a/chrome/browser/resources/settings/settings.js +++ b/chrome/browser/resources/settings/settings.js
@@ -33,5 +33,6 @@ export {buildRouter, routes} from './route.js'; export {Route, Router} from './router.m.js'; export {SafetyCheckBrowserProxy, SafetyCheckBrowserProxyImpl, SafetyCheckCallbackConstants, SafetyCheckExtensionsStatus, SafetyCheckParentStatus, SafetyCheckPasswordsStatus, SafetyCheckSafeBrowsingStatus, SafetyCheckUpdatesStatus} from './safety_check_page/safety_check_browser_proxy.js'; +export {SafetyCheckIconStatus} from './safety_check_page/safety_check_child.js'; export {SearchEngine, SearchEnginesBrowserProxy, SearchEnginesBrowserProxyImpl, SearchEnginesInfo} from './search_engines_page/search_engines_browser_proxy.m.js'; export {getSearchManager, SearchRequest, setSearchManagerForTesting} from './search_settings.m.js';
diff --git a/chrome/browser/resources/settings/settings_resources_v3.grdp b/chrome/browser/resources/settings/settings_resources_v3.grdp index a920b76..4953d88 100644 --- a/chrome/browser/resources/settings/settings_resources_v3.grdp +++ b/chrome/browser/resources/settings/settings_resources_v3.grdp
@@ -547,10 +547,30 @@ <include name="IDR_SETTINGS_SAFETY_CHECK_PAGE_SAFETY_CHECK_BROWSER_PROXY_JS" file="safety_check_page/safety_check_browser_proxy.js" compress="false" type="BINDATA" /> + <include name="IDR_SETTINGS_SAFETY_CHECK_PAGE_SAFETY_CHECK_CHILD_JS" + file="${root_gen_dir}/chrome/browser/resources/settings/safety_check_page/safety_check_child.js" + use_base_dir="false" + compress="false" type="BINDATA" /> + <include name="IDR_SETTINGS_SAFETY_CHECK_PAGE_SAFETY_CHECK_EXTENSIONS_ELEMENT_JS" + file="${root_gen_dir}/chrome/browser/resources/settings/safety_check_page/safety_check_extensions_element.js" + use_base_dir="false" + compress="false" type="BINDATA" /> <include name="IDR_SETTINGS_SAFETY_CHECK_PAGE_SAFETY_CHECK_PAGE_JS" file="${root_gen_dir}/chrome/browser/resources/settings/safety_check_page/safety_check_page.js" use_base_dir="false" compress="false" type="BINDATA" /> + <include name="IDR_SETTINGS_SAFETY_CHECK_PAGE_SAFETY_CHECK_PASSWORDS_ELEMENT_JS" + file="${root_gen_dir}/chrome/browser/resources/settings/safety_check_page/safety_check_passwords_element.js" + use_base_dir="false" + compress="false" type="BINDATA" /> + <include name="IDR_SETTINGS_SAFETY_CHECK_PAGE_SAFETY_CHECK_SAFE_BROWSING_ELEMENT_JS" + file="${root_gen_dir}/chrome/browser/resources/settings/safety_check_page/safety_check_safe_browsing_element.js" + use_base_dir="false" + compress="false" type="BINDATA" /> + <include name="IDR_SETTINGS_SAFETY_CHECK_PAGE_SAFETY_CHECK_UPDATES_ELEMENT_JS" + file="${root_gen_dir}/chrome/browser/resources/settings/safety_check_page/safety_check_updates_element.js" + use_base_dir="false" + compress="false" type="BINDATA" /> <include name="IDR_SETTINGS_SEARCH_ENGINES_BROWSER_PROXY_M_JS" file="${root_gen_dir}/chrome/browser/resources/settings/search_engines_page/search_engines_browser_proxy.m.js" use_base_dir="false"
diff --git a/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_dialog_views.cc b/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_dialog_views.cc index 0f35c56..8b336eec 100644 --- a/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_dialog_views.cc +++ b/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_dialog_views.cc
@@ -223,7 +223,59 @@ } views::View* DeepScanningDialogViews::GetContentsView() { - return contents_view_.get(); + if (!contents_view_) { + contents_view_ = new views::View(); // Owned by caller. + + // Create layout + views::GridLayout* layout = + contents_view_->SetLayoutManager(std::make_unique<views::GridLayout>()); + views::ColumnSet* columns = layout->AddColumnSet(0); + columns->AddColumn( + /*h_align=*/views::GridLayout::FILL, + /*v_align=*/views::GridLayout::FILL, + /*resize_percent=*/1.0, + /*size_type=*/views::GridLayout::ColumnSize::kUsePreferred, + /*fixed_width=*/0, + /*min_width=*/0); + + // Add the top image. + layout->StartRow(views::GridLayout::kFixedSize, 0); + image_ = layout->AddView(std::make_unique<DeepScanningTopImageView>(this)); + + // Add padding to distance the top image from the icon and message. + layout->AddPaddingRow(views::GridLayout::kFixedSize, 16); + + // Add the side icon and message row. + layout->StartRow(views::GridLayout::kFixedSize, 0); + auto icon_and_message_row = std::make_unique<views::View>(); + auto* row_layout = icon_and_message_row->SetLayoutManager( + std::make_unique<views::BoxLayout>( + views::BoxLayout::Orientation::kHorizontal, + kMessageAndIconRowInsets, kSideIconBetweenChildSpacing)); + row_layout->set_main_axis_alignment( + views::BoxLayout::MainAxisAlignment::kStart); + row_layout->set_cross_axis_alignment( + views::BoxLayout::CrossAxisAlignment::kCenter); + + // Add the side icon. + icon_and_message_row->AddChildView(CreateSideIcon()); + + // Add the message. + auto label = std::make_unique<DeepScanningMessageView>(this); + label->SetText(GetDialogMessage()); + label->SetLineHeight(kLineHeight); + label->SetMultiLine(true); + label->SetVerticalAlignment(gfx::ALIGN_MIDDLE); + label->SetHorizontalAlignment(gfx::ALIGN_LEFT); + message_ = icon_and_message_row->AddChildView(std::move(label)); + + layout->AddView(std::move(icon_and_message_row)); + + // Add padding to distance the message from the button(s). + layout->AddPaddingRow(views::GridLayout::kFixedSize, 10); + } + + return contents_view_; } views::Widget* DeepScanningDialogViews::GetWidget() { @@ -355,7 +407,7 @@ if (is_success()) { DCHECK(contents_view_->parent()); DCHECK_EQ(contents_view_->parent()->children().size(), 2ul); - DCHECK_EQ(contents_view_->parent()->children()[0], contents_view_.get()); + DCHECK_EQ(contents_view_->parent()->children()[0], contents_view_); views::View* button_row_view = contents_view_->parent()->children()[1]; new_height -= button_row_view->GetContentsBounds().height(); @@ -473,57 +525,6 @@ SetupButtons(); - contents_view_ = std::make_unique<views::View>(); - contents_view_->set_owned_by_client(); - - // Create layout - views::GridLayout* layout = - contents_view_->SetLayoutManager(std::make_unique<views::GridLayout>()); - views::ColumnSet* columns = layout->AddColumnSet(0); - columns->AddColumn( - /*h_align=*/views::GridLayout::FILL, - /*v_align=*/views::GridLayout::FILL, - /*resize_percent=*/1.0, - /*size_type=*/views::GridLayout::ColumnSize::kUsePreferred, - /*fixed_width=*/0, - /*min_width=*/0); - - // Add the top image. - layout->StartRow(views::GridLayout::kFixedSize, 0); - image_ = layout->AddView(std::make_unique<DeepScanningTopImageView>(this)); - - // Add padding to distance the top image from the icon and message. - layout->AddPaddingRow(views::GridLayout::kFixedSize, 16); - - // Add the side icon and message row. - layout->StartRow(views::GridLayout::kFixedSize, 0); - auto icon_and_message_row = std::make_unique<views::View>(); - auto* row_layout = - icon_and_message_row->SetLayoutManager(std::make_unique<views::BoxLayout>( - views::BoxLayout::Orientation::kHorizontal, kMessageAndIconRowInsets, - kSideIconBetweenChildSpacing)); - row_layout->set_main_axis_alignment( - views::BoxLayout::MainAxisAlignment::kStart); - row_layout->set_cross_axis_alignment( - views::BoxLayout::CrossAxisAlignment::kCenter); - - // Add the side icon. - icon_and_message_row->AddChildView(CreateSideIcon()); - - // Add the message. - auto label = std::make_unique<DeepScanningMessageView>(this); - label->SetText(GetDialogMessage()); - label->SetLineHeight(kLineHeight); - label->SetMultiLine(true); - label->SetVerticalAlignment(gfx::ALIGN_MIDDLE); - label->SetHorizontalAlignment(gfx::ALIGN_LEFT); - message_ = icon_and_message_row->AddChildView(std::move(label)); - - layout->AddView(std::move(icon_and_message_row)); - - // Add padding to distance the message from the button(s). - layout->AddPaddingRow(views::GridLayout::kFixedSize, 10); - constrained_window::ShowWebModalDialogViews(this, web_contents_); if (observer_for_testing)
diff --git a/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_dialog_views.h b/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_dialog_views.h index 9ebc2af..5e724a4e 100644 --- a/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_dialog_views.h +++ b/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_dialog_views.h
@@ -216,7 +216,7 @@ content::WebContents* web_contents_; // Views above the buttons. |contents_view_| owns every other view. - std::unique_ptr<views::View> contents_view_; + views::View* contents_view_ = nullptr; DeepScanningTopImageView* image_ = nullptr; DeepScanningSideIconImageView* side_icon_image_ = nullptr; DeepScanningSideIconSpinnerView* side_icon_spinner_ = nullptr;
diff --git a/chrome/browser/sharing/click_to_call/click_to_call_metrics.cc b/chrome/browser/sharing/click_to_call/click_to_call_metrics.cc index 6815e47..52f827b 100644 --- a/chrome/browser/sharing/click_to_call/click_to_call_metrics.cc +++ b/chrome/browser/sharing/click_to_call/click_to_call_metrics.cc
@@ -6,25 +6,12 @@ #include <cctype> -#include "base/metrics/histogram_functions.h" -#include "base/time/time.h" -#include "chrome/browser/sharing/click_to_call/click_to_call_utils.h" #include "components/ukm/content/source_url_recorder.h" #include "content/public/browser/web_contents.h" #include "services/metrics/public/cpp/ukm_builders.h" #include "services/metrics/public/cpp/ukm_recorder.h" #include "services/metrics/public/cpp/ukm_source_id.h" -ScopedUmaHistogramMicrosecondsTimer::ScopedUmaHistogramMicrosecondsTimer() = - default; - -ScopedUmaHistogramMicrosecondsTimer::~ScopedUmaHistogramMicrosecondsTimer() { - base::UmaHistogramCustomMicrosecondsTimes( - "Sharing.ClickToCallContextMenuPhoneNumberParsingDelay", timer_.Elapsed(), - base::TimeDelta::FromMicroseconds(1), base::TimeDelta::FromSeconds(1), - /*buckets=*/50); -} - void LogClickToCallUKM(content::WebContents* web_contents, SharingClickToCallEntryPoint entry_point, bool has_devices,
diff --git a/chrome/browser/sharing/click_to_call/click_to_call_metrics.h b/chrome/browser/sharing/click_to_call/click_to_call_metrics.h index 39cbfd0..ee6382d 100644 --- a/chrome/browser/sharing/click_to_call/click_to_call_metrics.h +++ b/chrome/browser/sharing/click_to_call/click_to_call_metrics.h
@@ -5,8 +5,6 @@ #ifndef CHROME_BROWSER_SHARING_CLICK_TO_CALL_CLICK_TO_CALL_METRICS_H_ #define CHROME_BROWSER_SHARING_CLICK_TO_CALL_CLICK_TO_CALL_METRICS_H_ -#include "base/timer/elapsed_timer.h" - namespace content { class WebContents; } // namespace content @@ -33,21 +31,6 @@ kMaxValue = kApp, }; -// TODO(himanshujaju): Make it generic and move to base/metrics/histogram_base.h -// Used to Log delay in parsing phone number in highlighted text to UMA. -class ScopedUmaHistogramMicrosecondsTimer { - public: - ScopedUmaHistogramMicrosecondsTimer(); - ScopedUmaHistogramMicrosecondsTimer( - const ScopedUmaHistogramMicrosecondsTimer&) = delete; - ScopedUmaHistogramMicrosecondsTimer& operator=( - const ScopedUmaHistogramMicrosecondsTimer&) = delete; - ~ScopedUmaHistogramMicrosecondsTimer(); - - private: - const base::ElapsedTimer timer_; -}; - // Records a Click to Call selection to UKM. This is logged after a completed // action like selecting an app or a device to send the phone number to. void LogClickToCallUKM(content::WebContents* web_contents,
diff --git a/chrome/browser/sharing/click_to_call/click_to_call_utils.cc b/chrome/browser/sharing/click_to_call/click_to_call_utils.cc index ed2db195..07acb9e 100644 --- a/chrome/browser/sharing/click_to_call/click_to_call_utils.cc +++ b/chrome/browser/sharing/click_to_call/click_to_call_utils.cc
@@ -7,14 +7,10 @@ #include <algorithm> #include <cctype> -#include "base/metrics/histogram_functions.h" #include "base/optional.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" -#include "base/time/time.h" -#include "base/timer/elapsed_timer.h" #include "chrome/browser/profiles/profile.h" -#include "chrome/browser/sharing/click_to_call/click_to_call_metrics.h" #include "chrome/browser/sharing/click_to_call/feature.h" #include "chrome/browser/sharing/click_to_call/phone_number_regex.h" #include "chrome/browser/sharing/sharing_service.h" @@ -78,7 +74,6 @@ base::Optional<std::string> ExtractPhoneNumber( const std::string& selection_text) { - ScopedUmaHistogramMicrosecondsTimer scoped_uma_timer; std::string parsed_number; const re2::RE2& regex = GetPhoneNumberRegex();
diff --git a/chrome/browser/sharing/webrtc/sharing_mojo_service.cc b/chrome/browser/sharing/webrtc/sharing_mojo_service.cc index 109dee4..cf251138 100644 --- a/chrome/browser/sharing/webrtc/sharing_mojo_service.cc +++ b/chrome/browser/sharing/webrtc/sharing_mojo_service.cc
@@ -14,9 +14,7 @@ content::ServiceProcessHost::Launch<mojom::Sharing>( remote.InitWithNewPipeAndPassReceiver(), content::ServiceProcessHost::Options() -#if defined(OS_MACOSX) - .WithSandboxType(service_manager::SandboxType::kUtility) -#else +#if !defined(OS_MACOSX) .WithSandboxType(service_manager::SandboxType::kSharingService) #endif .WithDisplayName("Sharing Service")
diff --git a/chrome/browser/speech/speech_recognition_service.cc b/chrome/browser/speech/speech_recognition_service.cc index 2cc2d75..d276ff6 100644 --- a/chrome/browser/speech/speech_recognition_service.cc +++ b/chrome/browser/speech/speech_recognition_service.cc
@@ -33,8 +33,6 @@ // is enabled. Otherwise, use the utility sandbox type. #if BUILDFLAG(ENABLE_SODA) .WithSandboxType(service_manager::SandboxType::kSpeechRecognition) -#else - .WithSandboxType(service_manager::SandboxType::kUtility) #endif // BUILDFLAG(ENABLE_SODA) .Pass());
diff --git a/chrome/browser/sync/test/integration/sync_errors_test.cc b/chrome/browser/sync/test/integration/sync_errors_test.cc index cb2596d9..f2459b0 100644 --- a/chrome/browser/sync/test/integration/sync_errors_test.cc +++ b/chrome/browser/sync/test/integration/sync_errors_test.cc
@@ -238,6 +238,32 @@ ASSERT_NE(old_cache_guid, status.sync_id); } +IN_PROC_BROWSER_TEST_F(SyncErrorTest, EncryptionObsoleteErrorTest) { + ASSERT_TRUE(SetupSync()) << "SetupSync() failed."; + + const BookmarkNode* node1 = AddFolder(0, 0, "title1"); + SetTitle(0, node1, "new_title1"); + ASSERT_TRUE(UpdatedProgressMarkerChecker(GetSyncService(0)).Wait()); + + GetFakeServer()->TriggerActionableError( + sync_pb::SyncEnums::ENCRYPTION_OBSOLETE, "Not My Fault", "www.google.com", + sync_pb::SyncEnums::UNKNOWN_ACTION); + + // Now make one more change so we will do another sync. + const BookmarkNode* node2 = AddFolder(0, 0, "title2"); + SetTitle(0, node2, "new_title2"); + EXPECT_TRUE(SyncDisabledChecker(GetSyncService(0)).Wait()); + + // Note: If SyncStandaloneTransport is enabled, then on receiving the error, + // the SyncService will immediately start up again in transport mode, which + // resets the status. So query the status that the checker recorded at the + // time Sync was off. + syncer::SyncStatus status; + GetSyncService(0)->QueryDetailedSyncStatusForDebugging(&status); + EXPECT_EQ(status.sync_protocol_error.error_type, syncer::ENCRYPTION_OBSOLETE); + EXPECT_EQ(status.sync_protocol_error.action, syncer::DISABLE_SYNC_ON_CLIENT); +} + IN_PROC_BROWSER_TEST_F(SyncErrorTest, DisableDatatypeWhileRunning) { ASSERT_TRUE(SetupSync()) << "SetupSync() failed."; syncer::ModelTypeSet synced_datatypes =
diff --git a/chrome/browser/ui/ash/assistant/assistant_client_impl.cc b/chrome/browser/ui/ash/assistant/assistant_client_impl.cc index 7b5eb2cf..760bd86 100644 --- a/chrome/browser/ui/ash/assistant/assistant_client_impl.cc +++ b/chrome/browser/ui/ash/assistant/assistant_client_impl.cc
@@ -187,7 +187,6 @@ content::ServiceProcessHost::Launch( std::move(receiver), content::ServiceProcessHost::Options() - .WithSandboxType(service_manager::SandboxType::kUtility) .WithDisplayName("Assistant Audio Decoder Service") .Pass()); }
diff --git a/chrome/browser/ui/ash/launcher/app_service/app_service_app_window_launcher_controller.cc b/chrome/browser/ui/ash/launcher/app_service/app_service_app_window_launcher_controller.cc index 1d1b3b3..9ac592e 100644 --- a/chrome/browser/ui/ash/launcher/app_service/app_service_app_window_launcher_controller.cc +++ b/chrome/browser/ui/ash/launcher/app_service/app_service_app_window_launcher_controller.cc
@@ -28,6 +28,9 @@ #include "chrome/browser/ui/ash/launcher/chrome_launcher_controller.h" #include "chrome/browser/ui/ash/multi_user/multi_user_util.h" #include "chrome/browser/ui/ash/multi_user/multi_user_window_manager_helper.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_list.h" +#include "chrome/browser/ui/browser_window.h" #include "chrome/services/app_service/public/cpp/instance.h" #include "chrome/services/app_service/public/mojom/types.mojom-shared.h" #include "chrome/services/app_service/public/mojom/types.mojom.h" @@ -70,6 +73,11 @@ std::make_unique<AppServiceAppWindowCrostiniTracker>(this); profile_list_.push_back(owner->profile()); + + for (auto* browser : *BrowserList::GetInstance()) { + if (browser && browser->window() && browser->window()->GetNativeWindow()) + observed_windows_.Add(browser->window()->GetNativeWindow()); + } } AppServiceAppWindowLauncherController:: @@ -126,11 +134,12 @@ void AppServiceAppWindowLauncherController::AdditionalUserAddedToSession( Profile* profile) { // Each users InstanceRegister needs to be observed. - apps::AppServiceProxy* proxy = - apps::AppServiceProxyFactory::GetForProfile(profile); - DCHECK(proxy); - proxy->InstanceRegistry().AddObserver(this); + proxy_ = apps::AppServiceProxyFactory::GetForProfile(profile); + DCHECK(proxy_); + proxy_->InstanceRegistry().AddObserver(this); profile_list_.push_back(profile); + + app_service_instance_helper_->AdditionalUserAddedToSession(profile); } void AppServiceAppWindowLauncherController::OnWindowInitialized( @@ -161,9 +170,7 @@ if (shelf_id.IsNull()) return; - DCHECK(proxy_); - if (proxy_->AppRegistryCache().GetAppType(shelf_id.app_id) != - apps::mojom::AppType::kBuiltIn) + if (GetAppType(shelf_id.app_id) != apps::mojom::AppType::kBuiltIn) return; app_service_instance_helper_->OnInstances(shelf_id.app_id, window, @@ -183,7 +190,7 @@ if (arc_tracker_) arc_tracker_->OnWindowVisibilityChanged(window); - ash::ShelfID shelf_id = GetShelfId(window, false /*search_profile_list*/); + ash::ShelfID shelf_id = GetShelfId(window); if (shelf_id.IsNull()) return; @@ -202,8 +209,11 @@ app_service_instance_helper_->OnInstances(GetAppId(shelf_id.app_id), window, shelf_id.launch_id, state); - if (!visible || shelf_id.app_id == extension_misc::kChromeAppId) + // Only register the visible non-browser |window| for the active user. + if (!visible || shelf_id.app_id == extension_misc::kChromeAppId || + !proxy_->InstanceRegistry().Exists(window)) { return; + } RegisterWindow(window, shelf_id); @@ -222,29 +232,27 @@ // window could be teleported from the inactive user, and isn't saved in the // proxy of the active user's profile, but it should still be removed from // the controller, and the shelf, so search all the proxies. - ash::ShelfID shelf_id = GetShelfId(window, true /*search_profile_list*/); - if (shelf_id.IsNull()) { + std::string app_id = GetShelfId(window).app_id; + if (app_id.empty()) { // For Crostini apps, it could be run from the command line, and not saved // in AppService, so GetShelfId could return null when the window is // destroyed, but it should still be deleted from instance and remove the // app window from the shelf. So if we can get the window from // InstanceRegistry, we should still destroy it from InstanceRegistry and // remove the app window from the shelf - shelf_id = proxy_->InstanceRegistry().GetShelfId(window); - if (shelf_id.IsNull()) + app_id = app_service_instance_helper_->GetAppId(window); + if (app_id.empty()) return; } - if (app_service_instance_helper_->IsOpenedInBrowser(shelf_id.app_id, - window) || - shelf_id.app_id == extension_misc::kChromeAppId) { + if (app_service_instance_helper_->IsOpenedInBrowser(app_id, window) || + app_id == extension_misc::kChromeAppId) { return; } // Delete the instance from InstanceRegistry. - app_service_instance_helper_->OnInstances(GetAppId(shelf_id.app_id), window, - std::string(), - apps::InstanceState::kDestroyed); + app_service_instance_helper_->OnInstances( + GetAppId(app_id), window, std::string(), apps::InstanceState::kDestroyed); auto app_window_it = aura_window_to_app_window_.find(window); if (app_window_it == aura_window_to_app_window_.end()) @@ -304,8 +312,7 @@ (update.State() & apps::InstanceState::kDestroyed) == apps::InstanceState::kUnknown) { std::string app_id = update.AppId(); - if (proxy_->AppRegistryCache().GetAppType(app_id) == - apps::mojom::AppType::kCrostini || + if (GetAppType(app_id) == apps::mojom::AppType::kCrostini || crostini::IsUnmatchedCrostiniShelfAppId(app_id)) { window->SetProperty(aura::client::kAppType, static_cast<int>(ash::AppType::CROSTINI_APP)); @@ -418,8 +425,7 @@ if (!window || !observed_windows_.IsObserving(window)) return; - const ash::ShelfID shelf_id = - GetShelfId(window, false /*search_profile_list*/); + const ash::ShelfID shelf_id = GetShelfId(window); if (shelf_id.IsNull()) return; @@ -541,8 +547,7 @@ } ash::ShelfID AppServiceAppWindowLauncherController::GetShelfId( - aura::Window* window, - bool search_profile_list) const { + aura::Window* window) const { if (crostini_tracker_) { std::string shelf_app_id; shelf_app_id = crostini_tracker_->GetShelfAppId(window); @@ -562,47 +567,32 @@ // If the window exists in InstanceRegistry, get the shelf id from // InstanceRegistry. - if (!search_profile_list) { - // Search from the proxy of the active user's profile, and verify whether - // the app exists in the proxy. - shelf_id = proxy_->InstanceRegistry().GetShelfId(window); - if (shelf_id.IsNull()) { - shelf_id = - ash::ShelfID::Deserialize(window->GetProperty(ash::kShelfIDKey)); - } - if (!shelf_id.IsNull()) { - if (proxy_->AppRegistryCache().GetAppType(shelf_id.app_id) == - apps::mojom::AppType::kUnknown && - shelf_id.app_id != extension_misc::kChromeAppId) { - return ash::ShelfID(); - } - return shelf_id; - } - } else { - for (auto* profile : profile_list_) { - auto* proxy = apps::AppServiceProxyFactory::GetForProfile(profile); - shelf_id = proxy->InstanceRegistry().GetShelfId(window); - if (!shelf_id.IsNull()) - break; - } - if (shelf_id.IsNull()) { - shelf_id = - ash::ShelfID::Deserialize(window->GetProperty(ash::kShelfIDKey)); - } - if (!shelf_id.IsNull()) { - for (auto* profile : profile_list_) { - auto* proxy = apps::AppServiceProxyFactory::GetForProfile(profile); - if (proxy->AppRegistryCache().GetAppType(shelf_id.app_id) != - apps::mojom::AppType::kUnknown || - shelf_id.app_id == extension_misc::kChromeAppId) { - return shelf_id; - } - } - return ash::ShelfID(); + for (auto* profile : profile_list_) { + auto* proxy = apps::AppServiceProxyFactory::GetForProfile(profile); + shelf_id = proxy->InstanceRegistry().GetShelfId(window); + if (!shelf_id.IsNull()) + break; + } + if (shelf_id.IsNull()) { + shelf_id = ash::ShelfID::Deserialize(window->GetProperty(ash::kShelfIDKey)); + } + if (!shelf_id.IsNull() && + GetAppType(shelf_id.app_id) != apps::mojom::AppType::kUnknown) { + return shelf_id; + } + return ash::ShelfID(); +} + +apps::mojom::AppType AppServiceAppWindowLauncherController::GetAppType( + const std::string& app_id) const { + for (auto* profile : profile_list_) { + auto* proxy = apps::AppServiceProxyFactory::GetForProfile(profile); + auto app_type = proxy->AppRegistryCache().GetAppType(app_id); + if (app_type != apps::mojom::AppType::kUnknown) { + return app_type; } } - - return shelf_id; + return apps::mojom::AppType::kUnknown; } void AppServiceAppWindowLauncherController::UserHasAppOnActiveDesktop(
diff --git a/chrome/browser/ui/ash/launcher/app_service/app_service_app_window_launcher_controller.h b/chrome/browser/ui/ash/launcher/app_service/app_service_app_window_launcher_controller.h index 0525d624..c721357 100644 --- a/chrome/browser/ui/ash/launcher/app_service/app_service_app_window_launcher_controller.h +++ b/chrome/browser/ui/ash/launcher/app_service/app_service_app_window_launcher_controller.h
@@ -123,15 +123,13 @@ // AppWindowLauncherController: void OnItemDelegateDiscarded(ash::ShelfItemDelegate* delegate) override; - // Returns the shelf id for |window|. The window could be teleported from the - // inactive user to the active user. When |search_profile_list| is true, we - // should check the all proxies for all profiles, otherwise, only check the - // current active user profile's proxy. - // - // When |window|'s visibility or activate status is changed, - // |search_profile_list| is false to check the active user profile only. When - // |window| is destroyed, |search_profile_list| is true to check all proxies. - ash::ShelfID GetShelfId(aura::Window* window, bool search_profile_list) const; + // Returns the shelf id for |window|. |window| could be teleported from the + // inactive user to the active user, or during the user switch phase, |window| + // could belong to one of the profile. + ash::ShelfID GetShelfId(aura::Window* window) const; + + // Returns the app type for the given |app_id|. + apps::mojom::AppType GetAppType(const std::string& app_id) const; // Register |window| if the owner of the given |window| has a window // teleported of the |window|'s application type to the current desktop.
diff --git a/chrome/browser/ui/ash/launcher/app_service/app_service_instance_registry_helper.cc b/chrome/browser/ui/ash/launcher/app_service/app_service_instance_registry_helper.cc index 278bcda7..feda4c8 100644 --- a/chrome/browser/ui/ash/launcher/app_service/app_service_instance_registry_helper.cc +++ b/chrome/browser/ui/ash/launcher/app_service/app_service_instance_registry_helper.cc
@@ -8,6 +8,7 @@ #include <string> #include <vector> +#include "base/stl_util.h" #include "base/time/time.h" #include "chrome/browser/apps/app_service/app_service_proxy.h" #include "chrome/browser/apps/app_service/app_service_proxy_factory.h" @@ -47,6 +48,11 @@ ProfileManager::GetActiveUserProfile()); } +void AppServiceInstanceRegistryHelper::AdditionalUserAddedToSession( + Profile* profile) { + proxy_ = apps::AppServiceProxyFactory::GetForProfile(profile); +} + void AppServiceInstanceRegistryHelper::OnActiveTabChanged( content::WebContents* old_contents, content::WebContents* new_contents) { @@ -61,14 +67,14 @@ // method is changed from windows to tabs, the app_id could be changed based // on the URL, e.g. google photos, which might cause instance app_id // inconsistent DCHECK error. - std::string app_id = proxy_->InstanceRegistry().GetShelfId(window).app_id; + std::string app_id = GetAppId(window); if (app_id.empty()) app_id = launcher_controller_helper_->GetAppID(old_contents); // If app_id is empty, we should not set it as inactive because this is // Chrome's tab. if (!app_id.empty()) { - apps::InstanceState state = proxy_->InstanceRegistry().GetState(window); + apps::InstanceState state = GetState(window); // If the app has been inactive, we don't need to update the instance. if ((state & apps::InstanceState::kActive) != apps::InstanceState::kUnknown) { @@ -87,7 +93,7 @@ // method is changed from windows to tabs, the app_id could be changed based // on the URL, e.g. google photos, which might cause instance app_id // inconsistent DCHECK error. - std::string app_id = proxy_->InstanceRegistry().GetShelfId(window).app_id; + std::string app_id = GetAppId(window); if (app_id.empty()) app_id = GetAppId(new_contents); @@ -121,12 +127,8 @@ // could generate a temp instance for this window with the Chrome application // app_id. For this case, this temp instance can be deleted, otherwise, DCHECK // error for inconsistent app_id. - std::string old_app_id = app_id; - proxy_->InstanceRegistry().ForOneInstance( - window, [&old_app_id](const apps::InstanceUpdate& update) { - old_app_id = update.AppId(); - }); - if (app_id != old_app_id) { + const std::string old_app_id = GetAppId(window); + if (!old_app_id.empty() && app_id != old_app_id) { OnInstances(old_app_id, window, std::string(), apps::InstanceState::kDestroyed); } @@ -146,17 +148,16 @@ // When the tab is closed, if the window does not exists in the AppService // InstanceRegistry, we don't need to update the status. - if (!proxy_->InstanceRegistry().Exists(window)) + const std::string app_id = GetAppId(window); + if (app_id.empty()) return; - std::string app_id = proxy_->InstanceRegistry().GetShelfId(window).app_id; RemoveTabWindow(app_id, window); OnInstances(app_id, window, std::string(), apps::InstanceState::kDestroyed); } void AppServiceInstanceRegistryHelper::OnBrowserRemoved() { - std::set<aura::Window*> windows = - proxy_->InstanceRegistry().GetWindows(extension_misc::kChromeAppId); + auto windows = GetWindows(extension_misc::kChromeAppId); for (auto* window : windows) { if (!chrome::FindBrowserWithWindow(window)) { // The browser is removed if the window can't be found, so update the @@ -187,7 +188,7 @@ // current active user, so search all proxies. If the instance is found from a // proxy, still save to that proxy, otherwise, save to the current active user // profile's proxy. - auto* proxy = proxy_; + apps::AppServiceProxy* proxy = proxy_; for (auto* profile : controller_->GetProfileList()) { auto* proxy_for_profile = apps::AppServiceProxyFactory::GetForProfile(profile); @@ -208,8 +209,7 @@ // window to compare with the parameter |window|, because we save the tab // window in AppService InstanceRegistry for Web apps, and we should set the // state for the tab window to keep one instance for the Web app. - std::set<aura::Window*> windows = - proxy_->InstanceRegistry().GetWindows(shelf_id.app_id); + auto windows = GetWindows(shelf_id.app_id); for (auto* it : windows) { if (it->GetToplevelWindow() != window) continue; @@ -226,10 +226,9 @@ // For Chrome browser app windows, sets the state for each tab window instance // in this browser. for (auto* it : browser_window_to_tab_window_[window]) { - if (!proxy_->InstanceRegistry().Exists(it)) + const std::string app_id = GetAppId(it); + if (app_id.empty()) continue; - - std::string app_id = proxy_->InstanceRegistry().GetShelfId(it).app_id; apps::InstanceState state = CalculateVisibilityState(it, visible); OnInstances(app_id, it, std::string(), state); } @@ -247,8 +246,7 @@ // window to compare with |window|, because we save the tab // window in AppService InstanceRegistry for Web apps, and we should set the // state for the tab window to keep one instance for the Web app. - std::set<aura::Window*> windows = - proxy_->InstanceRegistry().GetWindows(shelf_id.app_id); + auto windows = GetWindows(shelf_id.app_id); for (auto* it : windows) { if (it->GetToplevelWindow() != window) continue; @@ -278,8 +276,7 @@ // Get the app_id from the existed instance first. The app_id for PWAs could // be changed based on the URL, e.g. google photos, which might cause // instance app_id inconsistent DCHECK error. - std::string app_id = - proxy_->InstanceRegistry().GetShelfId(contents_window).app_id; + const std::string app_id = GetAppId(contents_window); OnInstances(app_id.empty() ? GetAppId(contents) : app_id, contents_window, std::string(), state); return; @@ -288,9 +285,9 @@ // For Chrome browser app windows, sets the state for each tab window instance // in this browser. for (auto* it : browser_window_to_tab_window_[window]) { - if (!proxy_->InstanceRegistry().Exists(it)) + const std::string app_id = GetAppId(it); + if (app_id.empty()) continue; - std::string app_id = proxy_->InstanceRegistry().GetShelfId(it).app_id; apps::InstanceState state = CalculateActivatedState(it, active); OnInstances(app_id, it, std::string(), state); } @@ -302,7 +299,7 @@ apps::InstanceState AppServiceInstanceRegistryHelper::CalculateVisibilityState( aura::Window* window, bool visible) const { - apps::InstanceState state = proxy_->InstanceRegistry().GetState(window); + apps::InstanceState state = GetState(window); state = static_cast<apps::InstanceState>( state | apps::InstanceState::kStarted | apps::InstanceState::kRunning); state = (visible) ? static_cast<apps::InstanceState>( @@ -322,7 +319,7 @@ apps::InstanceState::kActive | apps::InstanceState::kVisible); } - apps::InstanceState state = proxy_->InstanceRegistry().GetState(window); + apps::InstanceState state = GetState(window); state = static_cast<apps::InstanceState>( state | apps::InstanceState::kStarted | apps::InstanceState::kRunning); state = @@ -338,10 +335,17 @@ if (app_id == crostini::kCrostiniTerminalSystemAppId) return true; - apps::mojom::AppType app_type = proxy_->AppRegistryCache().GetAppType(app_id); - if (app_type != apps::mojom::AppType::kExtension && - app_type != apps::mojom::AppType::kWeb) { - return false; + for (auto* profile : controller_->GetProfileList()) { + auto* proxy = apps::AppServiceProxyFactory::GetForProfile(profile); + apps::mojom::AppType app_type = + proxy->AppRegistryCache().GetAppType(app_id); + if (app_type == apps::mojom::AppType::kUnknown) + continue; + + if (app_type != apps::mojom::AppType::kExtension && + app_type != apps::mojom::AppType::kWeb) { + return false; + } } // For Extension apps, and Web apps, AppServiceAppWindowLauncherController @@ -371,6 +375,17 @@ } std::string AppServiceInstanceRegistryHelper::GetAppId( + aura::Window* window) const { + for (auto* profile : controller_->GetProfileList()) { + auto* proxy = apps::AppServiceProxyFactory::GetForProfile(profile); + std::string app_id = proxy->InstanceRegistry().GetShelfId(window).app_id; + if (!app_id.empty()) + return app_id; + } + return std::string(); +} + +std::string AppServiceInstanceRegistryHelper::GetAppId( content::WebContents* contents) const { std::string app_id = launcher_controller_helper_->GetAppID(contents); if (!app_id.empty()) @@ -390,6 +405,28 @@ return window; } +std::set<aura::Window*> AppServiceInstanceRegistryHelper::GetWindows( + const std::string& app_id) { + std::set<aura::Window*> windows; + for (auto* profile : controller_->GetProfileList()) { + auto* proxy = apps::AppServiceProxyFactory::GetForProfile(profile); + auto w = proxy->InstanceRegistry().GetWindows(app_id); + windows = base::STLSetUnion<std::set<aura::Window*>>(windows, w); + } + return windows; +} + +apps::InstanceState AppServiceInstanceRegistryHelper::GetState( + aura::Window* window) const { + for (auto* profile : controller_->GetProfileList()) { + auto* proxy = apps::AppServiceProxyFactory::GetForProfile(profile); + auto state = proxy->InstanceRegistry().GetState(window); + if (state != apps::InstanceState::kUnknown) + return state; + } + return apps::InstanceState::kUnknown; +} + void AppServiceInstanceRegistryHelper::AddTabWindow(const std::string& app_id, aura::Window* window) { if (app_id == extension_misc::kChromeAppId)
diff --git a/chrome/browser/ui/ash/launcher/app_service/app_service_instance_registry_helper.h b/chrome/browser/ui/ash/launcher/app_service/app_service_instance_registry_helper.h index 64e63627..020faab 100644 --- a/chrome/browser/ui/ash/launcher/app_service/app_service_instance_registry_helper.h +++ b/chrome/browser/ui/ash/launcher/app_service/app_service_instance_registry_helper.h
@@ -5,7 +5,9 @@ #ifndef CHROME_BROWSER_UI_ASH_LAUNCHER_APP_SERVICE_APP_SERVICE_INSTANCE_REGISTRY_HELPER_H_ #define CHROME_BROWSER_UI_ASH_LAUNCHER_APP_SERVICE_APP_SERVICE_INSTANCE_REGISTRY_HELPER_H_ +#include <map> #include <memory> +#include <set> #include "chrome/browser/ui/ash/launcher/launcher_controller_helper.h" #include "chrome/services/app_service/public/cpp/instance.h" @@ -32,6 +34,7 @@ ~AppServiceInstanceRegistryHelper(); void ActiveUserChanged(); + void AdditionalUserAddedToSession(Profile* profile); // Notifies the AppService InstanceRegistry that active tabs are changed. void OnActiveTabChanged(content::WebContents* old_contents, @@ -82,6 +85,10 @@ // Return true if the app is opend in a browser. bool IsOpenedInBrowser(const std::string& app_id, aura::Window* window) const; + // Returns an app id for |window| in InstanceRegistry. If there is no |window| + // in InstanceRegistry, returns an empty string. + std::string GetAppId(aura::Window* window) const; + private: // Returns an app id to represent |contents| in InstanceRegistry. If there is // no app in |contents|, returns the app id of the Chrome component @@ -93,6 +100,13 @@ // |contents|, returns the toplevel window. aura::Window* GetWindow(content::WebContents* contents); + // Returns windows in InstanceRegistry for the given |app_id|. + std::set<aura::Window*> GetWindows(const std::string& app_id); + + // Returns the state in InstanceRegistry for the given |app_id|. If there is + // no |window| in InstanceRegistry, returns apps::InstanceState::kUnknown. + apps::InstanceState GetState(aura::Window* window) const; + // Adds the tab's |window| to |browser_window_to_tab_window_|. void AddTabWindow(const std::string& app_id, aura::Window* window); // Removes the tab's |window| from |browser_window_to_tab_window_|.
diff --git a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_unittest.cc b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_unittest.cc index fbcc5d9..ff471ed 100644 --- a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_unittest.cc +++ b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_unittest.cc
@@ -886,6 +886,7 @@ const std::string app_id = ArcAppListPrefs::GetAppId(app_info.package_name, app_info.activity); EXPECT_TRUE(prefs->GetApp(app_id)); + app_service_test().FlushMojoCalls(); return app_id; } @@ -3304,12 +3305,8 @@ TEST_F(MultiProfileMultiBrowserShelfLayoutChromeLauncherControllerTest, V2AppHandlingTwoUsers) { InitLauncherController(); - // Create a profile for our second user (will be destroyed by the framework). - TestingProfile* profile2 = CreateMultiUserProfile("user2"); const AccountId account_id( multi_user_util::GetAccountIdFromProfile(profile())); - const AccountId account_id2( - multi_user_util::GetAccountIdFromProfile(profile2)); // Check that there is a browser. EXPECT_EQ(1, model_->item_count()); @@ -3318,6 +3315,11 @@ V2App v2_app(profile(), extension1_.get()); EXPECT_EQ(2, model_->item_count()); + // Create a profile for our second user (will be destroyed by the framework). + TestingProfile* profile2 = CreateMultiUserProfile("user2"); + const AccountId account_id2( + multi_user_util::GetAccountIdFromProfile(profile2)); + // After switching users the item should go away. SwitchActiveUser(account_id2); EXPECT_EQ(1, model_->item_count()); @@ -3523,10 +3525,15 @@ InitLauncherController(); TestingProfile* profile2 = CreateMultiUserProfile("user-2"); - const AccountId account_id( - multi_user_util::GetAccountIdFromProfile(profile())); const AccountId account_id2( multi_user_util::GetAccountIdFromProfile(profile2)); + // If switch to account_id2 is not run, the following switch to account_id + // is invalid, because the user account is not changed, so switch to + // account_id2 first. + SwitchActiveUser(account_id2); + + const AccountId account_id( + multi_user_util::GetAccountIdFromProfile(profile())); SwitchActiveUser(account_id); EXPECT_EQ(1, model_->item_count());
diff --git a/chrome/browser/ui/content_settings/content_setting_bubble_model.h b/chrome/browser/ui/content_settings/content_setting_bubble_model.h index aa930bc..c0c3dab9 100644 --- a/chrome/browser/ui/content_settings/content_setting_bubble_model.h +++ b/chrome/browser/ui/content_settings/content_setting_bubble_model.h
@@ -21,7 +21,6 @@ #include "chrome/browser/ui/blocked_content/framebust_block_tab_helper.h" #include "chrome/browser/ui/blocked_content/url_list_manager.h" #include "chrome/common/custom_handlers/protocol_handler.h" -#include "chrome/grit/generated_resources.h" #include "components/content_settings/browser/tab_specific_content_settings.h" #include "components/content_settings/core/common/content_settings.h" #include "components/content_settings/core/common/content_settings_types.h"
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc index 5fc0332..f37bf0c 100644 --- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc +++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc
@@ -159,8 +159,11 @@ if (frame()->ShouldDrawFrameHeader()) frame_header_ = CreateFrameHeader(); - if (browser_view()->IsBrowserTypeWebApp()) - SetUpForWebApp(); + if (browser_view()->IsBrowserTypeWebApp() && !browser->is_type_app_popup()) { + // Add the container for extra web app buttons (e.g app menu button). + set_web_app_frame_toolbar(AddChildView( + std::make_unique<WebAppFrameToolbarView>(frame(), browser_view()))); + } browser_view()->immersive_mode_controller()->AddObserver(this); } @@ -697,12 +700,6 @@ return header; } -void BrowserNonClientFrameViewAsh::SetUpForWebApp() { - // Add the container for extra web app buttons (e.g app menu button). - set_web_app_frame_toolbar(AddChildView( - std::make_unique<WebAppFrameToolbarView>(frame(), browser_view()))); -} - void BrowserNonClientFrameViewAsh::UpdateTopViewInset() { // In immersive fullscreen mode, the top view inset property should be 0. const bool immersive =
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.h b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.h index b9adc2fc..8937981 100644 --- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.h +++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.h
@@ -187,9 +187,6 @@ // Creates the frame header for the browser window. std::unique_ptr<ash::FrameHeader> CreateFrameHeader(); - // Creates views and does other setup for a web app. - void SetUpForWebApp(); - // Triggers the web-app origin and icon animations, assumes the web-app UI // elements exist. void StartWebAppAnimation();
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc index f8d29fb0..7960fee4 100644 --- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc +++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc
@@ -39,6 +39,8 @@ #include "chrome/browser/ui/browser_command_controller.h" #include "chrome/browser/ui/browser_commands.h" #include "chrome/browser/ui/browser_list.h" +#include "chrome/browser/ui/browser_navigator.h" +#include "chrome/browser/ui/browser_navigator_params.h" #include "chrome/browser/ui/browser_tabstrip.h" #include "chrome/browser/ui/exclusive_access/fullscreen_controller.h" #include "chrome/browser/ui/exclusive_access/fullscreen_controller_test.h" @@ -87,7 +89,9 @@ #include "ui/aura/test/env_test_helper.h" #include "ui/base/class_property.h" #include "ui/base/hit_test.h" +#include "ui/base/page_transition_types.h" #include "ui/base/pointer/touch_ui_controller.h" +#include "ui/base/window_open_disposition.h" #include "ui/compositor/scoped_animation_duration_scale_mode.h" #include "ui/events/base_event_utils.h" #include "ui/events/event.h" @@ -1236,6 +1240,26 @@ EXPECT_FALSE(GetPaintingAsActive()); } +IN_PROC_BROWSER_TEST_P(WebAppNonClientFrameViewAshTest, PopupHasNoToolbar) { + SetUpWebApp(); + { + NavigateParams navigate_params(app_browser_, GetAppURL(), + ui::PAGE_TRANSITION_LINK); + navigate_params.disposition = WindowOpenDisposition::NEW_POPUP; + + content::TestNavigationObserver navigation_observer(GetAppURL()); + navigation_observer.StartWatchingNewWebContents(); + Navigate(&navigate_params); + navigation_observer.WaitForNavigationFinished(); + } + + Browser* popup_browser = BrowserList::GetInstance()->GetLastActive(); + BrowserView* browser_view = + BrowserView::GetBrowserViewForBrowser(popup_browser); + BrowserNonClientFrameViewAsh* frame_view = GetFrameViewAsh(browser_view); + EXPECT_FALSE(frame_view->web_app_frame_toolbar_for_testing()); +} + namespace { class BrowserNonClientFrameViewAshBackButtonTest
diff --git a/chrome/browser/ui/views/location_bar/content_setting_image_view.cc b/chrome/browser/ui/views/location_bar/content_setting_image_view.cc index 718ddf0..c4eccfe 100644 --- a/chrome/browser/ui/views/location_bar/content_setting_image_view.cc +++ b/chrome/browser/ui/views/location_bar/content_setting_image_view.cc
@@ -14,6 +14,7 @@ #include "chrome/browser/ui/view_ids.h" #include "chrome/browser/ui/views/content_setting_bubble_contents.h" #include "chrome/browser/ui/views/feature_promos/feature_promo_bubble_view.h" +#include "chrome/grit/generated_resources.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/theme_provider.h" #include "ui/events/event_utils.h"
diff --git a/chrome/browser/ui/views/omnibox/omnibox_result_view.cc b/chrome/browser/ui/views/omnibox/omnibox_result_view.cc index ba6c220f..51c3fa62 100644 --- a/chrome/browser/ui/views/omnibox/omnibox_result_view.cc +++ b/chrome/browser/ui/views/omnibox/omnibox_result_view.cc
@@ -80,7 +80,7 @@ remove_suggestion_focus_ring_ = views::FocusRing::Install(remove_suggestion_button_); remove_suggestion_focus_ring_->SetHasFocusPredicate([&](View* view) { - return view->GetVisible() && IsSelected() && + return view->GetVisible() && IsMatchSelected() && popup_contents_view_->IsButtonSelected(); }); @@ -219,7 +219,7 @@ void OmniboxResultView::OnSelectionStateChanged() { UpdateRemoveSuggestionVisibility(); - if (IsSelected()) { + if (IsMatchSelected()) { // Immediately before notifying screen readers that the selected item has // changed, we want to update the name of the newly-selected item so that // any cached values get updated prior to the selection change. @@ -243,8 +243,11 @@ ApplyThemeAndRefreshIcons(); } -bool OmniboxResultView::IsSelected() const { - return popup_contents_view_->IsSelectedIndex(model_index_); +bool OmniboxResultView::IsMatchSelected() const { + // The header button being focused means the match itself is NOT focused. + return popup_contents_view_->IsSelectedIndex(model_index_) && + popup_contents_view_->model()->selected_line_state() != + OmniboxPopupModel::HEADER_BUTTON_FOCUSED; } views::Button* OmniboxResultView::GetSecondaryButton() { @@ -272,9 +275,9 @@ int* label_prefix_length) { int additional_message_id = 0; views::Button* secondary_button = GetSecondaryButton(); - bool button_focused = - IsSelected() && popup_contents_view_->model()->selected_line_state() == - OmniboxPopupModel::BUTTON_FOCUSED; + bool button_focused = IsMatchSelected() && + popup_contents_view_->model()->selected_line_state() == + OmniboxPopupModel::BUTTON_FOCUSED; // If there's a button focused, we don't want the "n of m" message announced. if (button_focused) @@ -303,7 +306,7 @@ } OmniboxPartState OmniboxResultView::GetThemeState() const { - if (IsSelected()) + if (IsMatchSelected()) return OmniboxPartState::SELECTED; // If we don't highlight the whole row when the user has the mouse over the @@ -445,7 +448,7 @@ // When the drag enters or remains within the bounds of this view, either // set the state to be selected or hovered, depending on the mouse button. if (event.IsOnlyLeftMouseButton()) { - if (!IsSelected()) + if (!IsMatchSelected()) popup_contents_view_->SetSelectedLine(model_index_); if (suggestion_tab_switch_button_) { gfx::Point point_in_child_coords(event.location()); @@ -509,7 +512,7 @@ popup_contents_view_->model()->result().size()); node_data->AddBoolAttribute(ax::mojom::BoolAttribute::kSelected, - IsSelected()); + IsMatchSelected()); if (IsMouseHovered()) node_data->AddState(ax::mojom::State::kHovered); } @@ -594,7 +597,7 @@ !match_.ShouldShowTabMatchButton() && base::FeatureList::IsEnabled( omnibox::kOmniboxSuggestionTransparencyOptions) && - (IsSelected() || IsMouseHovered()); + (IsMatchSelected() || IsMouseHovered()); remove_suggestion_button_->SetVisible(new_visibility);
diff --git a/chrome/browser/ui/views/omnibox/omnibox_result_view.h b/chrome/browser/ui/views/omnibox/omnibox_result_view.h index 81ef18e..b6f81b7 100644 --- a/chrome/browser/ui/views/omnibox/omnibox_result_view.h +++ b/chrome/browser/ui/views/omnibox/omnibox_result_view.h
@@ -71,8 +71,9 @@ // Invoked when this result view has been selected or unselected. void OnSelectionStateChanged(); - // Whether |this| matches the model's selected index. - bool IsSelected() const; + // Whether this result view should be considered 'selected'. This returns + // false if this line's header is selected (instead of the match itself). + bool IsMatchSelected() const; // Returns the visible (and keyboard-focusable) secondary button, or nullptr // if none exists for this suggestion.
diff --git a/chrome/browser/ui/views/omnibox/omnibox_tab_switch_button.cc b/chrome/browser/ui/views/omnibox/omnibox_tab_switch_button.cc index df761d0..9f62d8e7 100644 --- a/chrome/browser/ui/views/omnibox/omnibox_tab_switch_button.cc +++ b/chrome/browser/ui/views/omnibox/omnibox_tab_switch_button.cc
@@ -111,7 +111,8 @@ bool OmniboxTabSwitchButton::IsSelected() const { // Is this result selected and is button selected? - return result_view_->IsSelected() && popup_contents_view_->IsButtonSelected(); + return result_view_->IsMatchSelected() && + popup_contents_view_->IsButtonSelected(); } int OmniboxTabSwitchButton::CalculateGoalWidth(int parent_width,
diff --git a/chrome/browser/ui/views/permission_bubble/permission_bubble_interactive_uitest.cc b/chrome/browser/ui/views/permission_bubble/permission_bubble_interactive_uitest.cc index 7701cec1..946e7b9cd 100644 --- a/chrome/browser/ui/views/permission_bubble/permission_bubble_interactive_uitest.cc +++ b/chrome/browser/ui/views/permission_bubble/permission_bubble_interactive_uitest.cc
@@ -22,6 +22,11 @@ public: PermissionBubbleInteractiveUITest() = default; + PermissionBubbleInteractiveUITest(const PermissionBubbleInteractiveUITest&) = + delete; + PermissionBubbleInteractiveUITest& operator=( + const PermissionBubbleInteractiveUITest&) = delete; + void EnsureWindowActive(ui::BaseWindow* window, const char* message) { EnsureWindowActive( views::Widget::GetWidgetForNativeWindow(window->GetNativeWindow()), @@ -37,7 +42,7 @@ } // Send Ctrl/Cmd+keycode in the key window to the browser. - void SendAccelerator(ui::KeyboardCode keycode, bool shift, bool alt) { + void SendAcceleratorSync(ui::KeyboardCode keycode, bool shift, bool alt) { #if defined(OS_MACOSX) bool control = false; bool command = true; @@ -45,8 +50,9 @@ bool control = true; bool command = false; #endif - ui_controls::SendKeyPress(browser()->window()->GetNativeWindow(), keycode, - control, shift, alt, command); + + ASSERT_TRUE(ui_test_utils::SendKeyPressSync(browser(), keycode, control, + shift, alt, command)); } void SetUpOnMainThread() override { @@ -66,16 +72,48 @@ EnsureWindowActive(test_api_->GetPromptWindow(), "show permission bubble"); } + void JumpToNextOpenTab() { +#if defined(OS_MACOSX) + SendAcceleratorSync(ui::VKEY_RIGHT, false, true); +#else + SendAcceleratorSync(ui::VKEY_TAB, false, false); +#endif + } + + void JumpToPreviousOpenTab() { +#if defined(OS_MACOSX) + SendAcceleratorSync(ui::VKEY_LEFT, false, true); +#else + SendAcceleratorSync(ui::VKEY_TAB, true, false); +#endif + } + + void TestSwitchingTabsWithCurlyBraces() { + // Also test switching tabs with curly braces. "VKEY_OEM_4" is + // LeftBracket/Brace on a US keyboard, which ui::MacKeyCodeForWindowsKeyCode + // will map to '{' when shift is passed. Also note there are only two tabs + // so it doesn't matter which direction is taken (it wraps). + chrome::FocusLocationBar(browser()); + SendAcceleratorSync(ui::VKEY_OEM_4, true, false); + EXPECT_EQ(0, browser()->tab_strip_model()->active_index()); + EnsureWindowActive(test_api_->GetPromptWindow(), + "switch to permission tab with curly brace"); + EXPECT_TRUE(test_api_->GetPromptWindow()); + + SendAcceleratorSync(ui::VKEY_OEM_4, true, false); + EXPECT_EQ(1, browser()->tab_strip_model()->active_index()); + browser()->window()->Activate(); + EnsureWindowActive(browser()->window(), "switch away with curly brace"); + EXPECT_FALSE(test_api_->GetPromptWindow()); + } + protected: std::unique_ptr<test::PermissionRequestManagerTestApi> test_api_; - - private: - DISALLOW_COPY_AND_ASSIGN(PermissionBubbleInteractiveUITest); }; -#if defined(OS_WIN) || defined(OS_LINUX) -// TODO(https://crbug.com/866878): Accelerators are broken when this bubble is -// showing on non-Mac. +#if defined(OS_CHROMEOS) +// TODO(crbug.com/1072425): views::test::WidgetTest::GetAllWidgets() crashes +// on Chrome OS, need to investigate\fix that. #define MAYBE_CmdWClosesWindow DISABLED_CmdWClosesWindow #else #define MAYBE_CmdWClosesWindow CmdWClosesWindow @@ -87,27 +125,16 @@ MAYBE_CmdWClosesWindow) { EXPECT_TRUE(browser()->window()->IsVisible()); - SendAccelerator(ui::VKEY_W, false, false); + SendAcceleratorSync(ui::VKEY_W, false, false); - // The actual window close happens via a posted task. - EXPECT_TRUE(browser()->window()->IsVisible()); - ui_test_utils::WaitForBrowserToClose(browser()); - // The window has been destroyed at this point, so there should be no widgets - // hanging around. + // The window has been destroyed so there should be no widgets hanging around. EXPECT_EQ(0u, views::test::WidgetTest::GetAllWidgets().size()); } -#if defined(OS_WIN) || defined(OS_LINUX) -// TODO(https://crbug.com/866878): Accelerators are broken when this bubble is -// showing on non-Mac. -#define MAYBE_SwitchTabs DISABLED_SwitchTabs -#else -#define MAYBE_SwitchTabs SwitchTabs -#endif - -// Add a tab, ensure we can switch away and back using Ctrl/Cmd+Alt+Left/Right -// and curly braces. -IN_PROC_BROWSER_TEST_F(PermissionBubbleInteractiveUITest, MAYBE_SwitchTabs) { +// Add a tab, ensure we can switch away and back using Ctrl+Tab and +// Ctrl+Shift+Tab at aura and using Cmd+Alt+Left/Right and curly braces at +// MacOS. +IN_PROC_BROWSER_TEST_F(PermissionBubbleInteractiveUITest, SwitchTabs) { EXPECT_EQ(0, browser()->tab_strip_model()->active_index()); EXPECT_TRUE(test_api_->GetPromptWindow()); @@ -115,12 +142,14 @@ AddBlankTabAndShow(browser()); EXPECT_EQ(1, browser()->tab_strip_model()->active_index()); +#if defined(OS_MACOSX) // The bubble should hide and give focus back to the browser. However, the // test environment can't guarantee that macOS decides that the Browser window // is actually the "best" window to activate upon closing the current key // window. So activate it manually. browser()->window()->Activate(); EnsureWindowActive(browser()->window(), "tab added"); +#endif // Prompt is hidden while its tab is not active. EXPECT_FALSE(test_api_->GetPromptWindow()); @@ -129,37 +158,27 @@ // accelerator before sending it back unhandled to the browser via IPC. That's // all a bit much to handle in a test, so activate the location bar. chrome::FocusLocationBar(browser()); - SendAccelerator(ui::VKEY_LEFT, false, true); + + JumpToPreviousOpenTab(); EXPECT_EQ(0, browser()->tab_strip_model()->active_index()); - // Note we don't need to makeKeyAndOrderFront: the permission window will take - // focus when it is shown again. - EnsureWindowActive(test_api_->GetPromptWindow(), - "switched to permission tab with arrow"); + // Note we don't need to makeKeyAndOrderFront for mac os: the permission + // window will take focus when it is shown again. + EnsureWindowActive( + test_api_->GetPromptWindow(), + "switched to permission tab with ctrl+shift+tab or arrow at mac os"); EXPECT_TRUE(test_api_->GetPromptWindow()); // Ensure we can switch away with the bubble active. - SendAccelerator(ui::VKEY_RIGHT, false, true); + JumpToNextOpenTab(); EXPECT_EQ(1, browser()->tab_strip_model()->active_index()); browser()->window()->Activate(); - EnsureWindowActive(browser()->window(), "switch away with arrow"); + EnsureWindowActive(browser()->window(), + "switch away with ctrl+tab or arrow at mac os"); EXPECT_FALSE(test_api_->GetPromptWindow()); - // Also test switching tabs with curly braces. "VKEY_OEM_4" is - // LeftBracket/Brace on a US keyboard, which ui::MacKeyCodeForWindowsKeyCode - // will map to '{' when shift is passed. Also note there are only two tabs so - // it doesn't matter which direction is taken (it wraps). - chrome::FocusLocationBar(browser()); - SendAccelerator(ui::VKEY_OEM_4, true, false); - EXPECT_EQ(0, browser()->tab_strip_model()->active_index()); - EnsureWindowActive(test_api_->GetPromptWindow(), - "switch to permission tab with curly brace"); - EXPECT_TRUE(test_api_->GetPromptWindow()); - - SendAccelerator(ui::VKEY_OEM_4, true, false); - EXPECT_EQ(1, browser()->tab_strip_model()->active_index()); - browser()->window()->Activate(); - EnsureWindowActive(browser()->window(), "switch away with curly brace"); - EXPECT_FALSE(test_api_->GetPromptWindow()); +#if defined(OS_MACOSX) + TestSwitchingTabsWithCurlyBraces(); +#endif }
diff --git a/chrome/browser/ui/views/sharing/click_to_call_browsertest.cc b/chrome/browser/ui/views/sharing/click_to_call_browsertest.cc index 03c4b2e..4de15dc 100644 --- a/chrome/browser/ui/views/sharing/click_to_call_browsertest.cc +++ b/chrome/browser/ui/views/sharing/click_to_call_browsertest.cc
@@ -285,7 +285,6 @@ base::HistogramTester::CountsMap expected_counts = { {HistogramName("DevicesToShow"), 1}, {HistogramName("DevicesToShow.ContextMenu"), 1}, - {HistogramName("ContextMenuPhoneNumberParsingDelay"), 1}, }; EXPECT_THAT(GetTotalHistogramCounts(histograms),
diff --git a/chrome/browser/ui/webui/autofill_and_password_manager_internals/OWNERS b/chrome/browser/ui/webui/autofill_and_password_manager_internals/OWNERS index c91bb70..f7b1a42 100644 --- a/chrome/browser/ui/webui/autofill_and_password_manager_internals/OWNERS +++ b/chrome/browser/ui/webui/autofill_and_password_manager_internals/OWNERS
@@ -1,5 +1,5 @@ battre@chromium.org dvadym@chromium.org -koerber@chromium.org +koerber@google.com # COMPONENT: UI>Browser>Passwords
diff --git a/chrome/browser/ui/webui/settings/safety_check_handler.cc b/chrome/browser/ui/webui/settings/safety_check_handler.cc index ac4ca81c..b1831b3d 100644 --- a/chrome/browser/ui/webui/settings/safety_check_handler.cc +++ b/chrome/browser/ui/webui/settings/safety_check_handler.cc
@@ -23,6 +23,8 @@ #include "components/safe_browsing/core/common/safe_browsing_prefs.h" #include "components/strings/grit/components_strings.h" #include "components/version_info/version_info.h" +#include "content/public/browser/browser_context.h" +#include "content/public/browser/storage_partition.h" #include "extensions/browser/extension_prefs_factory.h" #include "extensions/browser/extension_system.h" #include "extensions/common/extension_id.h" @@ -125,6 +127,13 @@ version_updater_.reset(VersionUpdater::Create(web_ui()->GetWebContents())); } DCHECK(version_updater_); + if (!update_helper_) { + update_helper_.reset(new safety_check::UpdateCheckHelper( + content::BrowserContext::GetDefaultStoragePartition( + Profile::FromWebUI(web_ui())) + ->GetURLLoaderFactoryForBrowserProcess())); + } + DCHECK(update_helper_); CheckUpdates(); if (!leak_service_) { @@ -155,12 +164,14 @@ } SafetyCheckHandler::SafetyCheckHandler( + std::unique_ptr<safety_check::UpdateCheckHelper> update_helper, std::unique_ptr<VersionUpdater> version_updater, password_manager::BulkLeakCheckService* leak_service, extensions::PasswordsPrivateDelegate* passwords_delegate, extensions::ExtensionPrefs* extension_prefs, extensions::ExtensionServiceInterface* extension_service) - : version_updater_(std::move(version_updater)), + : update_helper_(std::move(update_helper)), + version_updater_(std::move(version_updater)), leak_service_(leak_service), passwords_delegate_(passwords_delegate), extension_prefs_(extension_prefs), @@ -192,7 +203,7 @@ void SafetyCheckHandler::CheckUpdates() { // Usage of base::Unretained(this) is safe, because we own `version_updater_`. version_updater_->CheckForUpdate( - base::Bind(&SafetyCheckHandler::OnUpdateCheckResult, + base::Bind(&SafetyCheckHandler::OnVersionUpdaterResult, base::Unretained(this)), VersionUpdater::PromoteCallback()); } @@ -262,13 +273,8 @@ } } -void SafetyCheckHandler::OnUpdateCheckResult(VersionUpdater::Status status, - int progress, - bool rollback, - const std::string& version, - int64_t update_size, - const base::string16& message) { - update_status_ = ConvertToUpdateStatus(status); +void SafetyCheckHandler::OnUpdateCheckResult(UpdateStatus status) { + update_status_ = status; if (update_status_ != UpdateStatus::kChecking) { base::UmaHistogramEnumeration("Settings.SafetyCheck.UpdatesResult", update_status_); @@ -544,6 +550,11 @@ } } +void SafetyCheckHandler::DetermineIfOfflineOrError(bool connected) { + OnUpdateCheckResult(connected ? UpdateStatus::kFailed + : UpdateStatus::kFailedOffline); +} + void SafetyCheckHandler::DetermineIfNoPasswordsOrSafe( const std::vector<extensions::api::passwords_private::PasswordUiEntry>& passwords) { @@ -552,6 +563,21 @@ Compromised(0), Done(0), Total(0)); } +void SafetyCheckHandler::OnVersionUpdaterResult(VersionUpdater::Status status, + int progress, + bool rollback, + const std::string& version, + int64_t update_size, + const base::string16& message) { + if (status == VersionUpdater::FAILED) { + update_helper_->CheckConnectivity( + base::BindOnce(&SafetyCheckHandler::DetermineIfOfflineOrError, + base::Unretained(this))); + return; + } + OnUpdateCheckResult(ConvertToUpdateStatus(status)); +} + void SafetyCheckHandler::OnSafeBrowsingCheckResult( SafetyCheckHandler::SafeBrowsingStatus status) { safe_browsing_status_ = status;
diff --git a/chrome/browser/ui/webui/settings/safety_check_handler.h b/chrome/browser/ui/webui/settings/safety_check_handler.h index 01242a2..0c73407 100644 --- a/chrome/browser/ui/webui/settings/safety_check_handler.h +++ b/chrome/browser/ui/webui/settings/safety_check_handler.h
@@ -21,6 +21,7 @@ #include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h" #include "components/password_manager/core/browser/bulk_leak_check_service.h" #include "components/safety_check/safety_check.h" +#include "components/safety_check/update_check_helper.h" #include "extensions/browser/extension_prefs.h" #include "extensions/browser/extension_registry.h" @@ -105,11 +106,13 @@ base::Time system_time); protected: - SafetyCheckHandler(std::unique_ptr<VersionUpdater> version_updater, - password_manager::BulkLeakCheckService* leak_service, - extensions::PasswordsPrivateDelegate* passwords_delegate, - extensions::ExtensionPrefs* extension_prefs, - extensions::ExtensionServiceInterface* extension_service); + SafetyCheckHandler( + std::unique_ptr<safety_check::UpdateCheckHelper> update_helper, + std::unique_ptr<VersionUpdater> version_updater, + password_manager::BulkLeakCheckService* leak_service, + extensions::PasswordsPrivateDelegate* passwords_delegate, + extensions::ExtensionPrefs* extension_prefs, + extensions::ExtensionServiceInterface* extension_service); void SetVersionUpdaterForTesting( std::unique_ptr<VersionUpdater> version_updater) { @@ -147,12 +150,7 @@ void CheckExtensions(); // Callbacks that get triggered when each check completes. - void OnUpdateCheckResult(VersionUpdater::Status status, - int progress, - bool rollback, - const std::string& version, - int64_t update_size, - const base::string16& message); + void OnUpdateCheckResult(UpdateStatus status); void OnPasswordsCheckResult(PasswordsStatus status, Compromised compromised, Done done, @@ -176,6 +174,10 @@ ReenabledUser reenabled_user, ReenabledAdmin reenabled_admin); + // A generic error state often includes the offline state. This method is used + // as a callback for |UpdateCheckHelper| to check connectivity. + void DetermineIfOfflineOrError(bool connected); + // Since the password check API does not distinguish between the cases of // having no compromised passwords and not having any passwords at all, it is // necessary to use this method as a callback for @@ -185,6 +187,15 @@ const std::vector<extensions::api::passwords_private::PasswordUiEntry>& passwords); + // A callback passed to |VersionUpdater::CheckForUpdate| to receive the update + // state. + void OnVersionUpdaterResult(VersionUpdater::Status status, + int progress, + bool rollback, + const std::string& version, + int64_t update_size, + const base::string16& message); + // SafetyCheck::SafetyCheckHandlerInterface implementation. void OnSafeBrowsingCheckResult(SafeBrowsingStatus status) override; @@ -221,6 +232,7 @@ base::Time safety_check_completion_time_; std::unique_ptr<safety_check::SafetyCheck> safety_check_; + std::unique_ptr<safety_check::UpdateCheckHelper> update_helper_; std::unique_ptr<VersionUpdater> version_updater_; password_manager::BulkLeakCheckService* leak_service_ = nullptr;
diff --git a/chrome/browser/ui/webui/settings/safety_check_handler_unittest.cc b/chrome/browser/ui/webui/settings/safety_check_handler_unittest.cc index 89e964d..c6e18dd 100644 --- a/chrome/browser/ui/webui/settings/safety_check_handler_unittest.cc +++ b/chrome/browser/ui/webui/settings/safety_check_handler_unittest.cc
@@ -29,6 +29,7 @@ #include "components/password_manager/core/browser/leak_detection/bulk_leak_check.h" #include "components/prefs/pref_service.h" #include "components/safe_browsing/core/common/safe_browsing_prefs.h" +#include "components/safety_check/test_update_check_helper.h" #include "components/sync_preferences/testing_pref_service_syncable.h" #include "components/version_info/version_info.h" #include "content/public/test/test_web_ui.h" @@ -61,12 +62,14 @@ using SafetyCheckHandler::SetVersionUpdaterForTesting; TestingSafetyCheckHandler( + std::unique_ptr<safety_check::UpdateCheckHelper> update_helper, std::unique_ptr<VersionUpdater> version_updater, password_manager::BulkLeakCheckService* leak_service, extensions::PasswordsPrivateDelegate* passwords_delegate, extensions::ExtensionPrefs* extension_prefs, extensions::ExtensionServiceInterface* extension_service) - : SafetyCheckHandler(std::move(version_updater), + : SafetyCheckHandler(std::move(update_helper), + std::move(version_updater), leak_service, passwords_delegate, extension_prefs, @@ -195,6 +198,7 @@ const std::string& expected); protected: + safety_check::TestUpdateCheckHelper* update_helper_ = nullptr; TestVersionUpdater* version_updater_ = nullptr; std::unique_ptr<password_manager::BulkLeakCheckService> test_leak_service_; TestPasswordsDelegate test_passwords_delegate_; @@ -217,17 +221,19 @@ // The unique pointer to a TestVersionUpdater gets moved to // SafetyCheckHandler, but a raw pointer is retained here to change its // state. + auto update_helper = std::make_unique<safety_check::TestUpdateCheckHelper>(); + update_helper_ = update_helper.get(); auto version_updater = std::make_unique<TestVersionUpdater>(); + version_updater_ = version_updater.get(); test_leak_service_ = std::make_unique<password_manager::BulkLeakCheckService>( nullptr, nullptr); test_passwords_delegate_.SetBulkLeakCheckService(test_leak_service_.get()); - version_updater_ = version_updater.get(); test_web_ui_.set_web_contents(web_contents()); test_extension_prefs_ = extensions::ExtensionPrefs::Get(profile()); safety_check_ = std::make_unique<TestingSafetyCheckHandler>( - std::move(version_updater), test_leak_service_.get(), - &test_passwords_delegate_, test_extension_prefs_, - &test_extension_service_); + std::move(update_helper), std::move(version_updater), + test_leak_service_.get(), &test_passwords_delegate_, + test_extension_prefs_, &test_extension_service_); test_web_ui_.ClearTrackedCalls(); safety_check_->set_web_ui(&test_web_ui_); safety_check_->AllowJavascript(); @@ -425,7 +431,8 @@ SafetyCheckHandler::UpdateStatus::kFailedOffline, 1); } -TEST_F(SafetyCheckHandlerTest, CheckUpdates_Failed) { +TEST_F(SafetyCheckHandlerTest, CheckUpdates_Failed_ConnectivityOnline) { + update_helper_->SetConnectivity(true); version_updater_->SetReturnedStatus(VersionUpdater::Status::FAILED); safety_check_->PerformSafetyCheck(); const base::DictionaryValue* event = @@ -443,6 +450,23 @@ 1); } +TEST_F(SafetyCheckHandlerTest, CheckUpdates_Failed_ConnectivityOffline) { + update_helper_->SetConnectivity(false); + version_updater_->SetReturnedStatus(VersionUpdater::Status::FAILED); + safety_check_->PerformSafetyCheck(); + const base::DictionaryValue* event = + GetSafetyCheckStatusChangedWithDataIfExists( + kUpdates, + static_cast<int>(SafetyCheckHandler::UpdateStatus::kFailedOffline)); + ASSERT_TRUE(event); + VerifyDisplayString(event, + "Browser can't check for updates. Try checking your " + "internet connection."); + histogram_tester_.ExpectBucketCount( + "Settings.SafetyCheck.UpdatesResult", + SafetyCheckHandler::UpdateStatus::kFailedOffline, 1); +} + TEST_F(SafetyCheckHandlerTest, CheckUpdates_DestroyedOnJavascriptDisallowed) { EXPECT_FALSE(TestDestructionVersionUpdater::GetDestructorInvoked()); safety_check_->SetVersionUpdaterForTesting(
diff --git a/chrome/browser/ui/webui/webui_allowlist_provider_unittest.cc b/chrome/browser/ui/webui/webui_allowlist_provider_unittest.cc index 442bec19..bc0beca 100644 --- a/chrome/browser/ui/webui/webui_allowlist_provider_unittest.cc +++ b/chrome/browser/ui/webui/webui_allowlist_provider_unittest.cc
@@ -3,6 +3,7 @@ // found in the LICENSE file. #include "ui/webui/webui_allowlist_provider.h" +#include "components/content_settings/core/browser/content_settings_observer.h" #include "ui/webui/webui_allowlist.h" #include <map> @@ -126,6 +127,21 @@ } } +#if DCHECK_IS_ON() +#define MAYBE_InvalidContentSetting InvalidContentSetting +#else +#define MAYBE_InvalidContentSetting DISABLED_InvalidContentSetting +#endif +TEST_F(WebUIAllowlistProviderTest, MAYBE_InvalidContentSetting) { + auto* allowlist = WebUIAllowlist::GetOrCreate(profile()); + + EXPECT_DEATH_IF_SUPPORTED( + allowlist->RegisterAutoGrantedPermission( + url::Origin::Create(GURL("chrome://test/")), + ContentSettingsType::BLUETOOTH_GUARD, CONTENT_SETTING_DEFAULT), + std::string()); +} + TEST_F(WebUIAllowlistProviderTest, AutoGrantPermissionIsPerProfile) { TestingProfileManager profile_manager(TestingBrowserProcess::GetGlobal()); ASSERT_TRUE(profile_manager.SetUp()); @@ -154,3 +170,57 @@ map2->GetContentSetting(url, url, ContentSettingsType::GEOLOCATION, std::string())); } + +class ContentSettingsChangeObserver : public content_settings::Observer { + public: + ContentSettingsChangeObserver() = default; + ContentSettingsChangeObserver(const ContentSettingsChangeObserver&) = delete; + void operator=(const ContentSettingsChangeObserver&) = delete; + ~ContentSettingsChangeObserver() override = default; + + size_t change_counter() { return change_counter_; } + + // content_settings::Observer: + void OnContentSettingChanged( + const ContentSettingsPattern& primary_pattern, + const ContentSettingsPattern& secondary_pattern, + ContentSettingsType content_type, + const std::string& resource_identifier) override { + change_counter_++; + } + + private: + size_t change_counter_ = 0; +}; + +TEST_F(WebUIAllowlistProviderTest, OnlyNotifyOnChange) { + auto* map = GetHostContentSettingsMap(profile()); + map->SetDefaultContentSetting(ContentSettingsType::BLUETOOTH_GUARD, + CONTENT_SETTING_BLOCK); + + ContentSettingsChangeObserver change_observer; + map->AddObserver(&change_observer); + + const url::Origin origin1 = url::Origin::Create(GURL("chrome://test")); + + auto* allowlist = WebUIAllowlist::GetOrCreate(profile()); + allowlist->RegisterAutoGrantedPermission( + origin1, ContentSettingsType::BLUETOOTH_GUARD); + EXPECT_EQ(1U, change_observer.change_counter()); + + // Registering the same permission should not trigger OnContentSettingChanged. + allowlist->RegisterAutoGrantedPermission( + origin1, ContentSettingsType::BLUETOOTH_GUARD); + EXPECT_EQ(1U, change_observer.change_counter()); + + // Registering a different permission should trigger OnContentSettingChanged. + allowlist->RegisterAutoGrantedPermission(origin1, + ContentSettingsType::GEOLOCATION); + EXPECT_EQ(2U, change_observer.change_counter()); + + // Registering a different origin should trigger OnContentSettingChanged. + const url::Origin origin2 = url::Origin::Create(GURL("chrome://test2")); + allowlist->RegisterAutoGrantedPermission(origin2, + ContentSettingsType::GEOLOCATION); + EXPECT_EQ(3U, change_observer.change_counter()); +}
diff --git a/chrome/services/ipp_parser/ipp_parser_service.cc b/chrome/services/ipp_parser/ipp_parser_service.cc index 7c62a90..8602471 100644 --- a/chrome/services/ipp_parser/ipp_parser_service.cc +++ b/chrome/services/ipp_parser/ipp_parser_service.cc
@@ -16,7 +16,6 @@ content::ServiceProcessHost::Launch<mojom::IppParser>( remote.InitWithNewPipeAndPassReceiver(), content::ServiceProcessHost::Options() - .WithSandboxType(service_manager::SandboxType::kUtility) .WithDisplayName(IDS_UTILITY_PROCESS_IPP_PARSER_SERVICE_NAME) .Pass()); return remote;
diff --git a/chrome/services/media_gallery_util/public/cpp/media_parser_provider.cc b/chrome/services/media_gallery_util/public/cpp/media_parser_provider.cc index 4c466b9..84160273 100644 --- a/chrome/services/media_gallery_util/public/cpp/media_parser_provider.cc +++ b/chrome/services/media_gallery_util/public/cpp/media_parser_provider.cc
@@ -30,7 +30,6 @@ remote_media_parser_factory_.BindNewPipeAndPassReceiver(), content::ServiceProcessHost::Options() .WithDisplayName(IDS_UTILITY_PROCESS_MEDIA_GALLERY_UTILITY_NAME) - .WithSandboxType(service_manager::SandboxType::kUtility) .Pass()); remote_media_parser_factory_.set_disconnect_handler(base::BindOnce( &MediaParserProvider::OnConnectionError, base::Unretained(this)));
diff --git a/chrome/services/qrcode_generator/public/cpp/qrcode_generator_service.cc b/chrome/services/qrcode_generator/public/cpp/qrcode_generator_service.cc index b46a176..09ee008 100644 --- a/chrome/services/qrcode_generator/public/cpp/qrcode_generator_service.cc +++ b/chrome/services/qrcode_generator/public/cpp/qrcode_generator_service.cc
@@ -15,7 +15,6 @@ // TODO: check default sandboxtype return content::ServiceProcessHost::Launch<mojom::QRCodeGeneratorService>( content::ServiceProcessHost::Options() - .WithSandboxType(service_manager::SandboxType::kUtility) .WithDisplayName(IDS_UTILITY_PROCESS_QRCODE_GENERATOR_SERVICE_NAME) .Pass()); }
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index ad80471..33b878f 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -4274,6 +4274,7 @@ "//chrome/services/sharing:unit_tests", "//components/chrome_cleaner/test:test_name_helper", "//components/feature_engagement/test:test_support", + "//components/safety_check:test_support", "//components/send_tab_to_self:test_support", "//components/signin/public/base:signin_buildflags", "//components/sync:test_support",
diff --git a/chrome/test/data/policy/policy_test_cases.json b/chrome/test/data/policy/policy_test_cases.json index 9d56f47a..8cfd027c 100644 --- a/chrome/test/data/policy/policy_test_cases.json +++ b/chrome/test/data/policy/policy_test_cases.json
@@ -5420,19 +5420,7 @@ "note": "This policy is deprecated in M82 and doesn't map to a pref value anymore." }, - "MinimumChromeVersionEnforced": { - "os": ["chromeos"], - "policy_pref_mapping_test": [ - { - "policies": { - "MinimumChromeVersionEnforced": [ - {"chrome_version" : "82","warning_period" : 0, "eol_warning_period" : 14} - ] - }, - "prefs": { "cros.min_version_enforced.chrome": {} } - } - ] - }, + "MinimumChromeVersionEnforced": {}, "DeviceLoginScreenAutoSelectCertificateForUrls": {}, @@ -6044,7 +6032,7 @@ }, "ForceNetworkInProcess": { - "note": "This policy is used directly through the policy service instead of through a pref." + "note": "This policy is deprecated." }, "DeviceWilcoDtcAllowed": {
diff --git a/chrome/test/data/webui/settings/safety_check_page_test.js b/chrome/test/data/webui/settings/safety_check_page_test.js index 5ec58831..1a72efd 100644 --- a/chrome/test/data/webui/settings/safety_check_page_test.js +++ b/chrome/test/data/webui/settings/safety_check_page_test.js
@@ -5,7 +5,7 @@ // clang-format off import {webUIListenerCallback} from 'chrome://resources/js/cr.m.js'; import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; -import {HatsBrowserProxyImpl, LifetimeBrowserProxyImpl, MetricsBrowserProxyImpl, OpenWindowProxyImpl, PasswordManagerImpl, PasswordManagerProxy, Router, routes, SafetyCheckBrowserProxy, SafetyCheckBrowserProxyImpl, SafetyCheckCallbackConstants, SafetyCheckExtensionsStatus, SafetyCheckInteractions, SafetyCheckParentStatus, SafetyCheckPasswordsStatus, SafetyCheckSafeBrowsingStatus, SafetyCheckUpdatesStatus} from 'chrome://settings/settings.js'; +import {HatsBrowserProxyImpl, LifetimeBrowserProxyImpl, MetricsBrowserProxyImpl, OpenWindowProxyImpl, PasswordManagerImpl, PasswordManagerProxy, Router, routes, SafetyCheckBrowserProxy, SafetyCheckBrowserProxyImpl, SafetyCheckCallbackConstants, SafetyCheckExtensionsStatus, SafetyCheckIconStatus, SafetyCheckInteractions, SafetyCheckParentStatus, SafetyCheckPasswordsStatus, SafetyCheckSafeBrowsingStatus, SafetyCheckUpdatesStatus} from 'chrome://settings/settings.js'; import {TestHatsBrowserProxy} from 'chrome://test/settings/test_hats_browser_proxy.js'; import {TestLifetimeBrowserProxy} from 'chrome://test/settings/test_lifetime_browser_proxy.m.js'; import {TestMetricsBrowserProxy} from 'chrome://test/settings/test_metrics_browser_proxy.js'; @@ -15,25 +15,109 @@ // clang-format on -suite('SafetyCheckUiTests', function() { - /** @type {?LifetimeBrowserProxy} */ - let lifetimeBrowserProxy = null; +const testDisplayString = 'Test display string'; + +/** + * Fire a safety check parent event. + * @param {SafetyCheckParentStatus} + */ +function fireSafetyCheckParentEvent(state) { + const event = {}; + event.newState = state; + event.displayString = testDisplayString; + webUIListenerCallback(SafetyCheckCallbackConstants.PARENT_CHANGED, event); +} + +/** + * Fire a safety check updates event. + * @param {SafetyCheckUpdatesStatus} + */ +function fireSafetyCheckUpdatesEvent(state) { + const event = {}; + event.newState = state; + event.displayString = testDisplayString; + webUIListenerCallback(SafetyCheckCallbackConstants.UPDATES_CHANGED, event); +} + +/** + * Fire a safety check passwords event. + * @param {SafetyCheckPasswordsStatus} + */ +function fireSafetyCheckPasswordsEvent(state) { + const event = {}; + event.newState = state; + event.displayString = testDisplayString; + event.passwordsButtonString = null; + webUIListenerCallback(SafetyCheckCallbackConstants.PASSWORDS_CHANGED, event); +} + +/** + * Fire a safety check safe browsing event. + * @param {SafetyCheckSafeBrowsingStatus} + */ +function fireSafetyCheckSafeBrowsingEvent(state) { + const event = {}; + event.newState = state; + event.displayString = testDisplayString; + webUIListenerCallback( + SafetyCheckCallbackConstants.SAFE_BROWSING_CHANGED, event); +} + +/** + * Fire a safety check extensions event. + * @param {SafetyCheckExtensionsStatus} + */ +function fireSafetyCheckExtensionsEvent(state) { + const event = {}; + event.newState = state; + event.displayString = testDisplayString; + webUIListenerCallback(SafetyCheckCallbackConstants.EXTENSIONS_CHANGED, event); +} + +/** + * Verify that the safety check child element of the page has been configured + * as specified. + * @param {!{ + * page: !PolymerElement, + * iconStatus: !SafetyCheckExtensionsStatus, + * label: string, + * buttonLabel: string|undefined, + * buttonAriaLabel: string|undefined, + * buttonClass: string|undefined, + * managedIcon: string|undefined, + * }} destructured1 + */ +function assertSafetyCheckChild({ + page, + iconStatus, + label, + buttonLabel, + buttonAriaLabel, + buttonClass, + managedIcon +}) { + const safetyCheckChild = page.$$('#safetyCheckChild'); + assertTrue(safetyCheckChild.iconStatus === iconStatus); + assertTrue(safetyCheckChild.label === label); + assertTrue(safetyCheckChild.subLabel === testDisplayString); + assertTrue(!buttonLabel || safetyCheckChild.buttonLabel === buttonLabel); + assertTrue( + !buttonAriaLabel || safetyCheckChild.buttonAriaLabel === buttonAriaLabel); + assertTrue(!buttonClass || safetyCheckChild.buttonClass === buttonClass); + assertTrue(!!managedIcon === !!safetyCheckChild.managedIcon); +} + +suite('SafetyCheckPageUiTests', function() { /** @type {settings.TestMetricsBrowserProxy} */ - let metricsBrowserProxy; - /** @type {OpenWindowProxy} */ - let openWindowProxy = null; + let metricsBrowserProxy = null; /** @type {SafetyCheckBrowserProxy} */ let safetyCheckBrowserProxy = null; /** @type {SettingsBasicPageElement} */ - let page; + let page = null; setup(function() { - lifetimeBrowserProxy = new TestLifetimeBrowserProxy(); - LifetimeBrowserProxyImpl.instance_ = lifetimeBrowserProxy; metricsBrowserProxy = new TestMetricsBrowserProxy(); MetricsBrowserProxyImpl.instance_ = metricsBrowserProxy; - openWindowProxy = new TestOpenWindowProxy(); - OpenWindowProxyImpl.instance_ = openWindowProxy; safetyCheckBrowserProxy = TestBrowserProxy.fromClass(SafetyCheckBrowserProxy); safetyCheckBrowserProxy.setResultFor( @@ -50,88 +134,6 @@ page.remove(); }); - function fireSafetyCheckParentEvent(state) { - const event = {}; - event.newState = state; - event.displayString = null; - webUIListenerCallback(SafetyCheckCallbackConstants.PARENT_CHANGED, event); - } - - function fireSafetyCheckUpdatesEvent(state) { - const event = {}; - event.newState = state; - event.displayString = null; - webUIListenerCallback(SafetyCheckCallbackConstants.UPDATES_CHANGED, event); - } - - function fireSafetyCheckPasswordsEvent(state) { - const event = {}; - event.newState = state; - event.displayString = null; - event.passwordsButtonString = null; - webUIListenerCallback( - SafetyCheckCallbackConstants.PASSWORDS_CHANGED, event); - } - - function fireSafetyCheckSafeBrowsingEvent(state) { - const event = {}; - event.newState = state; - event.displayString = null; - webUIListenerCallback( - SafetyCheckCallbackConstants.SAFE_BROWSING_CHANGED, event); - } - - function fireSafetyCheckExtensionsEvent(state) { - const event = {}; - event.newState = state; - event.displayString = null; - webUIListenerCallback( - SafetyCheckCallbackConstants.EXTENSIONS_CHANGED, event); - } - - function assertIconStatusRunning(icon) { - assertTrue(icon.classList.contains('icon-blue')); - assertFalse(icon.classList.contains('icon-red')); - assertEquals('Running', icon.getAttribute('aria-label')); - } - - function assertIconStatusSafe(icon) { - assertTrue(icon.classList.contains('icon-blue')); - assertFalse(icon.classList.contains('icon-red')); - assertEquals('Passed', icon.getAttribute('aria-label')); - } - - function assertIconStatusInfo(icon) { - assertFalse(icon.classList.contains('icon-blue')); - assertFalse(icon.classList.contains('icon-red')); - assertEquals('Info', icon.getAttribute('aria-label')); - } - - function assertIconStatusWarning(icon) { - assertFalse(icon.classList.contains('icon-blue')); - assertTrue(icon.classList.contains('icon-red')); - assertEquals('Warning', icon.getAttribute('aria-label')); - } - - /** - * @return {!Promise} - */ - async function expectExtensionsButtonClickActions() { - // User clicks review extensions button. - page.$$('#safetyCheckExtensionsButton').click(); - // Ensure UMA is logged. - assertEquals( - SafetyCheckInteractions.SAFETY_CHECK_EXTENSIONS_REVIEW, - await metricsBrowserProxy.whenCalled( - 'recordSafetyCheckInteractionHistogram')); - assertEquals( - 'Settings.SafetyCheck.ReviewExtensions', - await metricsBrowserProxy.whenCalled('recordAction')); - // Ensure the browser proxy call is done. - assertEquals( - 'chrome://extensions', await openWindowProxy.whenCalled('openURL')); - } - /** Tests parent element and collapse.from start to completion */ test('testParentAndCollapse', async function() { // Before the check, only the text button is present. @@ -186,40 +188,193 @@ page.$$('#safetyCheckParentButton').click(); return testHatsBrowserProxy.whenCalled('tryShowSurvey'); }); +}); - test('updatesCheckingUiTest', function() { +suite('SafetyCheckChildTests', function() { + /** @type {SettingsBasicPageElement} */ + let page = null; + + setup(function() { + PolymerTest.clearBody(); + page = document.createElement('settings-safety-check-child'); + document.body.appendChild(page); + }); + + teardown(function() { + page.remove(); + }); + + test('testIconStatusRunning', function() { + page.iconStatus = SafetyCheckIconStatus.RUNNING; + flush(); + const statusIconElem = page.$$('#statusIcon'); + assertTrue(!!statusIconElem); + assertTrue(statusIconElem.classList.contains('icon-blue')); + assertFalse(statusIconElem.classList.contains('icon-red')); + assertEquals('Running', statusIconElem.getAttribute('aria-label')); + }); + + test('testIconStatusSafe', function() { + page.iconStatus = SafetyCheckIconStatus.SAFE; + flush(); + const statusIconElem = page.$$('#statusIcon'); + assertTrue(!!statusIconElem); + assertTrue(statusIconElem.classList.contains('icon-blue')); + assertFalse(statusIconElem.classList.contains('icon-red')); + assertEquals('Passed', statusIconElem.getAttribute('aria-label')); + }); + + test('testIconStatusInfo', function() { + page.iconStatus = SafetyCheckIconStatus.INFO; + flush(); + const statusIconElem = page.$$('#statusIcon'); + assertTrue(!!statusIconElem); + assertFalse(statusIconElem.classList.contains('icon-blue')); + assertFalse(statusIconElem.classList.contains('icon-red')); + assertEquals('Info', statusIconElem.getAttribute('aria-label')); + }); + + test('testIconStatusWarning', function() { + page.iconStatus = SafetyCheckIconStatus.WARNING; + flush(); + const statusIconElem = page.$$('#statusIcon'); + assertTrue(!!statusIconElem); + assertFalse(statusIconElem.classList.contains('icon-blue')); + assertTrue(statusIconElem.classList.contains('icon-red')); + assertEquals('Warning', statusIconElem.getAttribute('aria-label')); + }); + + test('testLabelText', function() { + page.label = 'Main label test text'; + flush(); + const label = page.$$('#label'); + assertTrue(!!label); + assertEquals('Main label test text', label.textContent.trim()); + }); + + test('testSubLabelText', function() { + page.subLabel = 'Sub label test text'; + flush(); + const subLabel = page.$$('#subLabel'); + assertTrue(!!subLabel); + assertEquals('Sub label test text', subLabel.textContent.trim()); + }); + + test('testSubLabelNoText', function() { + // sublabel not set -> empty sublabel in element + const subLabel = page.$$('#subLabel'); + assertTrue(!!subLabel); + assertEquals('', subLabel.textContent.trim()); + }); + + test('testButtonWithoutClass', function() { + page.buttonLabel = 'Button label'; + page.buttonAriaLabel = 'Aria label'; + flush(); + const button = page.$$('#button'); + assertTrue(!!button); + assertEquals('Button label', button.textContent.trim()); + assertEquals('Aria label', button.getAttribute('aria-label')); + assertFalse(button.classList.contains('action-button')); + }); + + test('testButtonWithClass', function() { + page.buttonLabel = 'Button label'; + page.buttonAriaLabel = 'Aria label'; + page.buttonClass = 'action-button'; + flush(); + const button = page.$$('#button'); + assertTrue(!!button); + assertEquals('Button label', button.textContent.trim()); + assertEquals('Aria label', button.getAttribute('aria-label')); + assertTrue(button.classList.contains('action-button')); + }); + + test('testNoButton', function() { + // Button label not set -> no button. + assertFalse(!!page.$$('#button')); + }); + + test('testManagedIcon', function() { + page.managedIcon = 'cr20:domain'; + flush(); + assertTrue(!!page.$$('#managedIcon')); + }); + + test('testNoManagedIcon', function() { + // Managed icon not set -> no managed icon. + assertFalse(!!page.$$('#managedIcon')); + }); +}); + +suite('SafetyCheckUpdatesElementUiTests', function() { + /** @type {?LifetimeBrowserProxy} */ + let lifetimeBrowserProxy = null; + /** @type {settings.TestMetricsBrowserProxy} */ + let metricsBrowserProxy = null; + /** @type {SettingsBasicPageElement} */ + let page = null; + + setup(function() { + lifetimeBrowserProxy = new TestLifetimeBrowserProxy(); + LifetimeBrowserProxyImpl.instance_ = lifetimeBrowserProxy; + metricsBrowserProxy = new TestMetricsBrowserProxy(); + MetricsBrowserProxyImpl.instance_ = metricsBrowserProxy; + + PolymerTest.clearBody(); + page = document.createElement('settings-safety-check-updates-element'); + document.body.appendChild(page); + flush(); + }); + + teardown(function() { + page.remove(); + }); + + test('checkingUiTest', function() { fireSafetyCheckUpdatesEvent(SafetyCheckUpdatesStatus.CHECKING); flush(); - assertFalse(!!page.$$('#safetyCheckUpdatesButton')); - assertFalse(!!page.$$('#safetyCheckUpdatesManagedIcon')); - assertIconStatusRunning(page.$$('#updatesIcon')); + assertSafetyCheckChild({ + page: page, + iconStatus: SafetyCheckIconStatus.RUNNING, + label: 'Updates', + }); }); - test('updatesUpdatedUiTest', function() { + test('updatedUiTest', function() { fireSafetyCheckUpdatesEvent(SafetyCheckUpdatesStatus.UPDATED); flush(); - assertFalse(!!page.$$('#safetyCheckUpdatesButton')); - assertFalse(!!page.$$('#safetyCheckUpdatesManagedIcon')); - assertIconStatusSafe(page.$$('#updatesIcon')); + assertSafetyCheckChild({ + page: page, + iconStatus: SafetyCheckIconStatus.SAFE, + label: 'Updates', + }); }); - test('updatesUpdatingUiTest', function() { + test('updatingUiTest', function() { fireSafetyCheckUpdatesEvent(SafetyCheckUpdatesStatus.UPDATING); flush(); - assertFalse(!!page.$$('#safetyCheckUpdatesButton')); - assertFalse(!!page.$$('#safetyCheckUpdatesManagedIcon')); - assertIconStatusRunning(page.$$('#updatesIcon')); + assertSafetyCheckChild({ + page: page, + iconStatus: SafetyCheckIconStatus.RUNNING, + label: 'Updates', + }); }); - test('updatesRelaunchUiTest', async function() { + test('relaunchUiTest', async function() { fireSafetyCheckUpdatesEvent(SafetyCheckUpdatesStatus.RELAUNCH); flush(); - assertTrue(!!page.$$('#safetyCheckUpdatesButton')); - assertFalse(!!page.$$('#safetyCheckUpdatesManagedIcon')); - assertIconStatusInfo(page.$$('#updatesIcon')); + assertSafetyCheckChild({ + page: page, + iconStatus: SafetyCheckIconStatus.INFO, + label: 'Updates', + buttonLabel: page.i18n('aboutRelaunch'), + buttonAriaLabel: page.i18n('safetyCheckUpdatesButtonAriaLabel'), + buttonClass: 'action-button', + }); // User clicks the relaunch button. - page.$$('#safetyCheckUpdatesButton').click(); + page.$$('#safetyCheckChild').$$('#button').click(); // Ensure UMA is logged. assertEquals( SafetyCheckInteractions.SAFETY_CHECK_UPDATES_RELAUNCH, @@ -232,85 +387,106 @@ return lifetimeBrowserProxy.whenCalled('relaunch'); }); - test('updatesDisabledByAdminUiTest', function() { + test('disabledByAdminUiTest', function() { fireSafetyCheckUpdatesEvent(SafetyCheckUpdatesStatus.DISABLED_BY_ADMIN); flush(); - assertFalse(!!page.$$('#safetyCheckUpdatesButton')); - assertTrue(!!page.$$('#safetyCheckUpdatesManagedIcon')); - assertIconStatusInfo(page.$$('#updatesIcon')); + assertSafetyCheckChild({ + page: page, + iconStatus: SafetyCheckIconStatus.INFO, + label: 'Updates', + managedIcon: true, + }); }); - test('updatesFailedOfflineUiTest', function() { + test('failedOfflineUiTest', function() { fireSafetyCheckUpdatesEvent(SafetyCheckUpdatesStatus.FAILED_OFFLINE); flush(); - assertFalse(!!page.$$('#safetyCheckUpdatesButton')); - assertFalse(!!page.$$('#safetyCheckUpdatesManagedIcon')); - assertIconStatusInfo(page.$$('#updatesIcon')); + assertSafetyCheckChild({ + page: page, + iconStatus: SafetyCheckIconStatus.INFO, + label: 'Updates', + }); }); - test('updatesFailedUiTest', function() { + test('failedUiTest', function() { fireSafetyCheckUpdatesEvent(SafetyCheckUpdatesStatus.FAILED); flush(); - assertFalse(!!page.$$('#safetyCheckUpdatesButton')); - assertFalse(!!page.$$('#safetyCheckUpdatesManagedIcon')); - assertIconStatusWarning(page.$$('#updatesIcon')); + assertSafetyCheckChild({ + page: page, + iconStatus: SafetyCheckIconStatus.WARNING, + label: 'Updates', + }); }); - test('updatesUnknownUiTest', function() { + test('unknownUiTest', function() { fireSafetyCheckUpdatesEvent(SafetyCheckUpdatesStatus.UNKNOWN); flush(); - assertFalse(!!page.$$('#safetyCheckUpdatesButton')); - assertFalse(!!page.$$('#safetyCheckUpdatesManagedIcon')); - assertIconStatusInfo(page.$$('#updatesIcon')); + assertSafetyCheckChild({ + page: page, + iconStatus: SafetyCheckIconStatus.INFO, + label: 'Updates', + }); + }); +}); + +suite('SafetyCheckPasswordsElementUiTests', function() { + /** @type {settings.TestMetricsBrowserProxy} */ + let metricsBrowserProxy = null; + /** @type {SettingsBasicPageElement} */ + let page = null; + + setup(function() { + metricsBrowserProxy = new TestMetricsBrowserProxy(); + MetricsBrowserProxyImpl.instance_ = metricsBrowserProxy; + + PolymerTest.clearBody(); + page = document.createElement('settings-safety-check-passwords-element'); + document.body.appendChild(page); + flush(); }); - test('passwordsUiTest', function() { - // Iterate over all states - for (const state of Object.values(SafetyCheckPasswordsStatus)) { - fireSafetyCheckPasswordsEvent(state); - flush(); - - // Button is only visible in COMPROMISED state - assertEquals( - state === SafetyCheckPasswordsStatus.COMPROMISED, - !!page.$$('#safetyCheckPasswordsButton')); - - // Check that icon status is the correct one for this password status. - switch (state) { - case SafetyCheckPasswordsStatus.CHECKING: - assertIconStatusRunning(page.$$('#passwordsIcon')); - break; - case SafetyCheckPasswordsStatus.SAFE: - assertIconStatusSafe(page.$$('#passwordsIcon')); - break; - case SafetyCheckPasswordsStatus.COMPROMISED: - assertIconStatusWarning(page.$$('#passwordsIcon')); - break; - case SafetyCheckPasswordsStatus.OFFLINE: - case SafetyCheckPasswordsStatus.NO_PASSWORDS: - case SafetyCheckPasswordsStatus.SIGNED_OUT: - case SafetyCheckPasswordsStatus.QUOTA_LIMIT: - case SafetyCheckPasswordsStatus.ERROR: - assertIconStatusInfo(page.$$('#passwordsIcon')); - break; - default: - assertNotReached(); - } - } + teardown(function() { + page.remove(); }); - test('passwordsCompromisedUiTest', async function() { + test('passwordCheckingUiTest', function() { + fireSafetyCheckPasswordsEvent(SafetyCheckUpdatesStatus.CHECKING); + flush(); + assertSafetyCheckChild({ + page: page, + iconStatus: SafetyCheckIconStatus.RUNNING, + label: 'Passwords', + }); + }); + + test('passwordSafeUiTest', function() { + fireSafetyCheckPasswordsEvent(SafetyCheckPasswordsStatus.SAFE); + flush(); + assertSafetyCheckChild({ + page: page, + iconStatus: SafetyCheckIconStatus.SAFE, + label: 'Passwords', + }); + }); + + test('passwordCompromisedUiTest', async function() { + fireSafetyCheckPasswordsEvent(SafetyCheckPasswordsStatus.COMPROMISED); + flush(); + assertSafetyCheckChild({ + page: page, + iconStatus: SafetyCheckIconStatus.WARNING, + label: 'Passwords', + buttonLabel: 'Review', + buttonAriaLabel: 'Review passwords', + buttonClass: 'action-button', + }); + loadTimeData.overrideValues({enablePasswordCheck: true}); const passwordManager = new TestPasswordManagerProxy(); PasswordManagerImpl.instance_ = passwordManager; - fireSafetyCheckPasswordsEvent(SafetyCheckPasswordsStatus.COMPROMISED); - flush(); - assertTrue(!!page.$$('#safetyCheckPasswordsButton')); - assertIconStatusWarning(page.$$('#passwordsIcon')); - // User clicks the manage passwords button. - page.$$('#safetyCheckPasswordsButton').click(); + page.$$('#safetyCheckChild').$$('#button').click(); // Ensure UMA is logged. assertEquals( SafetyCheckInteractions.SAFETY_CHECK_PASSWORDS_MANAGE, @@ -330,41 +506,100 @@ PasswordManagerProxy.PasswordCheckReferrer.SAFETY_CHECK, referrer); }); + test('passwordInfoStatesUiTest', function() { + // Iterate over all states + for (const state of Object.values(SafetyCheckPasswordsStatus)) { + fireSafetyCheckPasswordsEvent(state); + flush(); + + // Check that icon status is the correct one for this password status. + switch (state) { + case SafetyCheckPasswordsStatus.OFFLINE: + case SafetyCheckPasswordsStatus.NO_PASSWORDS: + case SafetyCheckPasswordsStatus.SIGNED_OUT: + case SafetyCheckPasswordsStatus.QUOTA_LIMIT: + case SafetyCheckPasswordsStatus.ERROR: + assertSafetyCheckChild({ + page: page, + iconStatus: SafetyCheckIconStatus.INFO, + label: 'Passwords', + }); + break; + default: + // Not covered by this test. + break; + } + } + }); +}); + +suite('SafetyCheckSafeBrowsingElementUiTests', function() { + /** @type {settings.TestMetricsBrowserProxy} */ + let metricsBrowserProxy = null; + /** @type {SettingsBasicPageElement} */ + let page = null; + + setup(function() { + metricsBrowserProxy = new TestMetricsBrowserProxy(); + MetricsBrowserProxyImpl.instance_ = metricsBrowserProxy; + + PolymerTest.clearBody(); + page = + document.createElement('settings-safety-check-safe-browsing-element'); + document.body.appendChild(page); + flush(); + }); + + teardown(function() { + page.remove(); + }); + test('safeBrowsingCheckingUiTest', function() { fireSafetyCheckSafeBrowsingEvent(SafetyCheckSafeBrowsingStatus.CHECKING); flush(); - assertFalse(!!page.$$('#safetyCheckSafeBrowsingButton')); - assertFalse(!!page.$$('#safetyCheckSafeBrowsingManagedIcon')); - assertIconStatusRunning(page.$$('#safeBrowsingIcon')); + assertSafetyCheckChild({ + page: page, + iconStatus: SafetyCheckIconStatus.RUNNING, + label: 'Safe Browsing', + }); }); test('safeBrowsingEnabledStandardUiTest', function() { fireSafetyCheckSafeBrowsingEvent( SafetyCheckSafeBrowsingStatus.ENABLED_STANDARD); flush(); - assertFalse(!!page.$$('#safetyCheckSafeBrowsingButton')); - assertFalse(!!page.$$('#safetyCheckSafeBrowsingManagedIcon')); - assertIconStatusSafe(page.$$('#safeBrowsingIcon')); + assertSafetyCheckChild({ + page: page, + iconStatus: SafetyCheckIconStatus.SAFE, + label: 'Safe Browsing', + }); }); test('safeBrowsingEnabledEnhancedUiTest', function() { fireSafetyCheckSafeBrowsingEvent( SafetyCheckSafeBrowsingStatus.ENABLED_ENHANCED); flush(); - assertFalse(!!page.$$('#safetyCheckSafeBrowsingButton')); - assertFalse(!!page.$$('#safetyCheckSafeBrowsingManagedIcon')); - assertIconStatusSafe(page.$$('#safeBrowsingIcon')); + assertSafetyCheckChild({ + page: page, + iconStatus: SafetyCheckIconStatus.SAFE, + label: 'Safe Browsing', + }); }); test('safeBrowsingDisabledUiTest', async function() { fireSafetyCheckSafeBrowsingEvent(SafetyCheckSafeBrowsingStatus.DISABLED); flush(); - assertTrue(!!page.$$('#safetyCheckSafeBrowsingButton')); - assertFalse(!!page.$$('#safetyCheckSafeBrowsingManagedIcon')); - assertIconStatusInfo(page.$$('#safeBrowsingIcon')); + assertSafetyCheckChild({ + page: page, + iconStatus: SafetyCheckIconStatus.INFO, + label: 'Safe Browsing', + buttonLabel: 'Manage', + buttonAriaLabel: 'Manage Safe Browsing', + buttonClass: 'action-button', + }); // User clicks the manage safe browsing button. - page.$$('#safetyCheckSafeBrowsingButton').click(); + page.$$('#safetyCheckChild').$$('#button').click(); // Ensure UMA is logged. assertEquals( SafetyCheckInteractions.SAFETY_CHECK_SAFE_BROWSING_MANAGE, @@ -381,53 +616,112 @@ fireSafetyCheckSafeBrowsingEvent( SafetyCheckSafeBrowsingStatus.DISABLED_BY_ADMIN); flush(); - assertFalse(!!page.$$('#safetyCheckSafeBrowsingButton')); - assertTrue(!!page.$$('#safetyCheckSafeBrowsingManagedIcon')); - assertIconStatusInfo(page.$$('#safeBrowsingIcon')); + assertSafetyCheckChild({ + page: page, + iconStatus: SafetyCheckIconStatus.INFO, + label: 'Safe Browsing', + managedIcon: true, + }); }); test('safeBrowsingDisabledByExtensionUiTest', function() { fireSafetyCheckSafeBrowsingEvent( SafetyCheckSafeBrowsingStatus.DISABLED_BY_EXTENSION); flush(); - assertFalse(!!page.$$('#safetyCheckSafeBrowsingButton')); - assertTrue(!!page.$$('#safetyCheckSafeBrowsingManagedIcon')); - assertIconStatusInfo(page.$$('#safeBrowsingIcon')); + assertSafetyCheckChild({ + page: page, + iconStatus: SafetyCheckIconStatus.INFO, + label: 'Safe Browsing', + managedIcon: true, + }); }); +}); + +suite('SafetyCheckExtensionsElementUiTests', function() { + /** @type {settings.TestMetricsBrowserProxy} */ + let metricsBrowserProxy = null; + /** @type {OpenWindowProxy} */ + let openWindowProxy = null; + /** @type {SettingsBasicPageElement} */ + let page = null; + + setup(function() { + metricsBrowserProxy = new TestMetricsBrowserProxy(); + MetricsBrowserProxyImpl.instance_ = metricsBrowserProxy; + openWindowProxy = new TestOpenWindowProxy(); + OpenWindowProxyImpl.instance_ = openWindowProxy; + + PolymerTest.clearBody(); + page = document.createElement('settings-safety-check-extensions-element'); + document.body.appendChild(page); + flush(); + }); + + teardown(function() { + page.remove(); + }); + + /** + * @return {!Promise} + */ + async function expectExtensionsButtonClickActions() { + // User clicks review extensions button. + page.$$('#safetyCheckChild').$$('#button').click(); + // Ensure UMA is logged. + assertEquals( + SafetyCheckInteractions.SAFETY_CHECK_EXTENSIONS_REVIEW, + await metricsBrowserProxy.whenCalled( + 'recordSafetyCheckInteractionHistogram')); + assertEquals( + 'Settings.SafetyCheck.ReviewExtensions', + await metricsBrowserProxy.whenCalled('recordAction')); + // Ensure the browser proxy call is done. + assertEquals( + 'chrome://extensions', await openWindowProxy.whenCalled('openURL')); + } test('extensionsCheckingUiTest', function() { fireSafetyCheckExtensionsEvent(SafetyCheckExtensionsStatus.CHECKING); flush(); - assertFalse(!!page.$$('#safetyCheckExtensionsButton')); - assertFalse(!!page.$$('#safetyCheckExtensionsManagedIcon')); - assertIconStatusRunning(page.$$('#extensionsIcon')); + assertSafetyCheckChild({ + page: page, + iconStatus: SafetyCheckIconStatus.RUNNING, + label: 'Extensions', + }); }); test('extensionsErrorUiTest', function() { fireSafetyCheckExtensionsEvent(SafetyCheckExtensionsStatus.ERROR); flush(); - assertFalse(!!page.$$('#safetyCheckExtensionsButton')); - assertFalse(!!page.$$('#safetyCheckExtensionsManagedIcon')); - assertIconStatusInfo(page.$$('#extensionsIcon')); + assertSafetyCheckChild({ + page: page, + iconStatus: SafetyCheckIconStatus.INFO, + label: 'Extensions', + }); }); test('extensionsSafeUiTest', function() { fireSafetyCheckExtensionsEvent( SafetyCheckExtensionsStatus.NO_BLOCKLISTED_EXTENSIONS); flush(); - assertFalse(!!page.$$('#safetyCheckExtensionsButton')); - assertFalse(!!page.$$('#safetyCheckExtensionsManagedIcon')); - assertIconStatusSafe(page.$$('#extensionsIcon')); + assertSafetyCheckChild({ + page: page, + iconStatus: SafetyCheckIconStatus.SAFE, + label: 'Extensions', + }); }); test('extensionsBlocklistedOffUiTest', function() { fireSafetyCheckExtensionsEvent( SafetyCheckExtensionsStatus.BLOCKLISTED_ALL_DISABLED); flush(); - assertTrue(!!page.$$('#safetyCheckExtensionsButton')); - assertFalse(!!page.$$('#safetyCheckExtensionsManagedIcon')); - assertIconStatusSafe(page.$$('#extensionsIcon')); - + assertSafetyCheckChild({ + page: page, + iconStatus: SafetyCheckIconStatus.SAFE, + label: 'Extensions', + buttonLabel: 'Review', + buttonAriaLabel: 'Review extensions', + }); return expectExtensionsButtonClickActions(); }); @@ -435,10 +729,14 @@ fireSafetyCheckExtensionsEvent( SafetyCheckExtensionsStatus.BLOCKLISTED_REENABLED_ALL_BY_USER); flush(); - assertTrue(!!page.$$('#safetyCheckExtensionsButton')); - assertFalse(!!page.$$('#safetyCheckExtensionsManagedIcon')); - assertIconStatusWarning(page.$$('#extensionsIcon')); - + assertSafetyCheckChild({ + page: page, + iconStatus: SafetyCheckIconStatus.WARNING, + label: 'Extensions', + buttonLabel: 'Review', + buttonAriaLabel: 'Review extensions', + buttonClass: 'action-button', + }); return expectExtensionsButtonClickActions(); }); @@ -446,10 +744,15 @@ fireSafetyCheckExtensionsEvent( SafetyCheckExtensionsStatus.BLOCKLISTED_REENABLED_SOME_BY_USER); flush(); - assertTrue(!!page.$$('#safetyCheckExtensionsButton')); - assertFalse(!!page.$$('#safetyCheckExtensionsManagedIcon')); - assertIconStatusWarning(page.$$('#extensionsIcon')); - + assertSafetyCheckChild({ + page: page, + iconStatus: SafetyCheckIconStatus.WARNING, + label: 'Extensions', + buttonLabel: 'Review', + buttonAriaLabel: 'Review extensions', + buttonClass: 'action-button', + managedIcon: false, + }); return expectExtensionsButtonClickActions(); }); @@ -457,8 +760,11 @@ fireSafetyCheckExtensionsEvent( SafetyCheckExtensionsStatus.BLOCKLISTED_REENABLED_ALL_BY_ADMIN); flush(); - assertFalse(!!page.$$('#safetyCheckExtensionsButton')); - assertTrue(!!page.$$('#safetyCheckExtensionsManagedIcon')); - assertIconStatusInfo(page.$$('#extensionsIcon')); + assertSafetyCheckChild({ + page: page, + iconStatus: SafetyCheckIconStatus.INFO, + label: 'Extensions', + managedIcon: true, + }); }); });
diff --git a/chromeos/CHROMEOS_LKGM b/chromeos/CHROMEOS_LKGM index 637fe56..7c765b21 100644 --- a/chromeos/CHROMEOS_LKGM +++ b/chromeos/CHROMEOS_LKGM
@@ -1 +1 @@ -13090.0.0 \ No newline at end of file +13091.0.0 \ No newline at end of file
diff --git a/chromeos/components/sample_system_web_app_ui/sample_system_web_app_ui.cc b/chromeos/components/sample_system_web_app_ui/sample_system_web_app_ui.cc index 12fc1cd..cedd039 100644 --- a/chromeos/components/sample_system_web_app_ui/sample_system_web_app_ui.cc +++ b/chromeos/components/sample_system_web_app_ui/sample_system_web_app_ui.cc
@@ -15,7 +15,7 @@ #include "content/public/common/url_constants.h" namespace chromeos { - +namespace { content::WebUIDataSource* CreateUntrustedSampleSystemWebAppDataSource() { content::WebUIDataSource* untrusted_source = content::WebUIDataSource::Create(kChromeUIUntrustedSampleSystemWebAppURL); @@ -26,6 +26,7 @@ untrusted_source->AddFrameAncestor(GURL(kChromeUISampleSystemWebAppURL)); return untrusted_source; } +} // namespace SampleSystemWebAppUI::SampleSystemWebAppUI(content::WebUI* web_ui) : ui::MojoWebUIController(web_ui) {
diff --git a/chromeos/constants/chromeos_pref_names.cc b/chromeos/constants/chromeos_pref_names.cc index 281259a..c41c642b8c 100644 --- a/chromeos/constants/chromeos_pref_names.cc +++ b/chromeos/constants/chromeos_pref_names.cc
@@ -69,7 +69,7 @@ const char kSamlPasswordChangeUrl[] = "saml.password_change_url"; // Boolean pref indicating whether a user has enabled the display password -// button on the login/lock screen. This can be set to false by policy. +// button on the login/lock screen. const char kLoginDisplayPasswordButtonEnabled[] = "login_display_password_button_enabled";
diff --git a/components/autofill/OWNERS b/components/autofill/OWNERS index 2e5e8da..13ff42e 100644 --- a/components/autofill/OWNERS +++ b/components/autofill/OWNERS
@@ -3,7 +3,7 @@ dvadym@chromium.org estade@chromium.org ftirelo@chromium.org -koerber@chromium.org +koerber@google.com kolos@chromium.org mahmadi@chromium.org rogerm@chromium.org
diff --git a/components/autofill/core/browser/autofill_download_manager.cc b/components/autofill/core/browser/autofill_download_manager.cc index 999d1452..92847181 100644 --- a/components/autofill/core/browser/autofill_download_manager.cc +++ b/components/autofill/core/browser/autofill_download_manager.cc
@@ -98,7 +98,7 @@ }; const char kDefaultAutofillServerURL[] = - "https://clients1.google.com/tbproxy/af/"; + "https://content-autofill.googleapis.com/"; // The default number of days after which to reset the registry of autofill // events for which an upload has been sent. @@ -810,7 +810,8 @@ std::string method = "POST"; if (request_data.request_type == AutofillDownloadManager::REQUEST_QUERY) { - if (GetPayloadLength(request_data.payload) <= kMaxAPIQueryGetSize) { + if (GetPayloadLength(request_data.payload) <= kMaxAPIQueryGetSize && + base::FeatureList::IsEnabled(features::kAutofillCacheQueryResponses)) { resource_id = request_data.payload; method = "GET"; UMA_HISTOGRAM_BOOLEAN("Autofill.Query.ApiUrlIsTooLong", false);
diff --git a/components/autofill/core/browser/autofill_download_manager_unittest.cc b/components/autofill/core/browser/autofill_download_manager_unittest.cc index a3225b9..37a8199 100644 --- a/components/autofill/core/browser/autofill_download_manager_unittest.cc +++ b/components/autofill/core/browser/autofill_download_manager_unittest.cc
@@ -579,10 +579,11 @@ // This is the URL we expect to query the API. The sub-path right after // "/page" corresponds to the serialized AutofillPageQueryRequest proto // (that we filled forms in) encoded in base64. The Autofill - // https://clients1.google.com/ domain URL corresponds to the default domain - // used by the download manager, which is invalid, but good for testing. + // https://content-autofill.googleapis.com/ domain URL corresponds to the + // default domain used by the download manager, which is invalid, but good + // for testing. const std::string expected_url = - R"(https://clients1.google.com/v1/pages/(.+)\?alt=proto)"; + R"(https://content-autofill.googleapis.com/v1/pages/(.+)\?alt=proto)"; std::string encoded_request; ASSERT_TRUE(re2::RE2::FullMatch(request->request.url.spec(), expected_url, &encoded_request)); @@ -676,7 +677,7 @@ test_url_loader_factory_.GetPendingRequest(0); // Verify that the POST URL is used when request data too large. const std::string expected_url = { - "https://clients1.google.com/v1/pages:get?alt=proto"}; + "https://content-autofill.googleapis.com/v1/pages:get?alt=proto"}; // Verify API key header. EXPECT_EQ(request->request.url, expected_url); { @@ -775,11 +776,11 @@ test_url_loader_factory_.GetPendingRequest(0); // This is the URL we expect to upload votes to the API. The Autofill - // https://clients1.google.com/ domain URL corresponds to the + // https://content-autofill.googleapis.com/ domain URL corresponds to the // default one used by the download manager. Request upload data is in the // payload when uploading. const std::string expected_url = - "https://clients1.google.com/v1/forms:vote?alt=proto"; + "https://content-autofill.googleapis.com/v1/forms:vote?alt=proto"; EXPECT_EQ(request->request.url, expected_url); std::string api_key_header_value; EXPECT_TRUE(request->request.headers.GetHeader("X-Goog-Api-Key", @@ -1349,7 +1350,7 @@ base::Unretained(this))); ASSERT_TRUE(server_.Start()); - GURL autofill_server_url(server_.base_url().Resolve("/tbproxy/af/")); + GURL autofill_server_url(server_.base_url()); ASSERT_TRUE(autofill_server_url.is_valid()); // Intialize the autofill driver. @@ -1410,22 +1411,17 @@ run_loop_->QuitWhenIdle(); } - // Helper to extract the value of a query param. Returns "*** not found ***" - // if the requested query param is not in the query string. - std::string GetQueryParam(const std::string& query_str, - const std::string& param_name) { - url::Component query(0, query_str.length()); - url::Component key, value; - while (url::ExtractQueryKeyValue(query_str.c_str(), &query, &key, &value)) { - base::StringPiece key_string(query_str.c_str() + key.begin, key.len); - base::StringPiece param_text(query_str.c_str() + value.begin, value.len); - std::string param_value; - if (key_string == param_name && - base::Base64UrlDecode(param_text, - base::Base64UrlDecodePolicy::REQUIRE_PADDING, - ¶m_value)) { - return param_value; - } + // Helper to extract the value passed to a lookup in the URL. Returns "*** not + // found ***" if the the data cannot be decoded. + std::string GetLookupContent(const std::string& query_path) { + if (query_path.find("/v1/pages/") == std::string::npos) + return "*** not found ***"; + std::string payload = query_path.substr(strlen("/v1/pages/")); + std::string decoded_payload; + if (base::Base64UrlDecode(payload, + base::Base64UrlDecodePolicy::REQUIRE_PADDING, + &decoded_payload)) { + return decoded_payload; } return "*** not found ***"; } @@ -1434,12 +1430,15 @@ GURL absolute_url = server_.GetURL(request.relative_url); ++call_count_; - if (absolute_url.path() == "/tbproxy/af/query") { + if (absolute_url.path().find("/v1/pages") == 0) { payloads_.push_back(!request.content.empty() ? request.content - : GetQueryParam(absolute_url.query(), "q")); - AutofillQueryResponseContents proto; - proto.add_field()->set_overall_type_prediction(NAME_FIRST); + : GetLookupContent(absolute_url.path())); + AutofillQueryResponse proto; + proto.add_form_suggestions() + ->add_field_suggestions() + ->add_predictions() + ->set_type(NAME_FIRST); auto response = std::make_unique<BasicHttpResponse>(); response->set_code(net::HTTP_OK); @@ -1454,7 +1453,7 @@ return response; } - if (absolute_url.path() == "/tbproxy/af/upload") { + if (absolute_url.path() == "/v1/forms:vote") { payloads_.push_back(request.content); auto response = std::make_unique<BasicHttpResponse>(); response->set_code(net::HTTP_OK); @@ -1657,8 +1656,9 @@ histogram.ExpectBucketCount("Autofill.Query.WasInCache", CACHE_MISS, 1); ASSERT_EQ(1u, payloads_.size()); - AutofillQueryContents query_contents; + AutofillPageQueryRequest query_contents; ASSERT_TRUE(query_contents.ParseFromString(payloads_[0])); + ASSERT_EQ(2, query_contents.experiments_size()); EXPECT_EQ(3312923, query_contents.experiments(0)); EXPECT_EQ(3314883, query_contents.experiments(1)); @@ -1789,30 +1789,30 @@ // We should have intercepted exactly on query request. Parse it. ASSERT_EQ(1u, payloads_.size()); - AutofillQueryContents query; + AutofillPageQueryRequest query; ASSERT_TRUE(query.ParseFromString(payloads_.front())); // Validate that we have one form in the query. - ASSERT_EQ(query.form_size(), 1); - const auto& query_form = query.form(0); + ASSERT_EQ(query.forms_size(), 1); + const auto& query_form = query.forms(0); // The form should have metadata, and the metadata value should be equal // those initialized above. - ASSERT_TRUE(query_form.has_form_metadata()); - EXPECT_EQ(UTF8ToUTF16(query_form.form_metadata().id().encoded_bits()), + ASSERT_TRUE(query_form.has_metadata()); + EXPECT_EQ(UTF8ToUTF16(query_form.metadata().id().encoded_bits()), form.id_attribute); - EXPECT_EQ(UTF8ToUTF16(query_form.form_metadata().name().encoded_bits()), + EXPECT_EQ(UTF8ToUTF16(query_form.metadata().name().encoded_bits()), form.name_attribute); // The form should have 3 fields, and their metadata value should be equal // those initialized above. - ASSERT_EQ(3, query_form.field_size()); - ASSERT_EQ(static_cast<int>(form.fields.size()), query_form.field_size()); - for (int i = 0; i < query_form.field_size(); ++i) { - const auto& query_field = query_form.field(i); + ASSERT_EQ(3, query_form.fields_size()); + ASSERT_EQ(static_cast<int>(form.fields.size()), query_form.fields_size()); + for (int i = 0; i < query_form.fields_size(); ++i) { + const auto& query_field = query_form.fields(i); const auto& form_field = form.fields[i]; - ASSERT_TRUE(query_field.has_field_metadata()); - const auto& meta = query_field.field_metadata(); + ASSERT_TRUE(query_field.has_metadata()); + const auto& meta = query_field.metadata(); EXPECT_EQ(UTF8ToUTF16(meta.id().encoded_bits()), form_field.id_attribute); EXPECT_EQ(UTF8ToUTF16(meta.name().encoded_bits()), form_field.name_attribute); @@ -1889,22 +1889,22 @@ // We should have intercepted exactly on query request. Parse it. ASSERT_EQ(1u, payloads_.size()); - AutofillQueryContents query; + AutofillPageQueryRequest query; ASSERT_TRUE(query.ParseFromString(payloads_.front())); // Validate that we have one form in the query. - ASSERT_EQ(query.form_size(), 1); - const auto& query_form = query.form(0); + ASSERT_EQ(query.forms_size(), 1); + const auto& query_form = query.forms(0); // There should be no encoded metadata for the form. - EXPECT_FALSE(query_form.has_form_metadata()); + EXPECT_FALSE(query_form.has_metadata()); // There should be three fields, none of which have encoded metadata. - ASSERT_EQ(3, query_form.field_size()); - ASSERT_EQ(static_cast<int>(form.fields.size()), query_form.field_size()); - for (int i = 0; i < query_form.field_size(); ++i) { - const auto& query_field = query_form.field(i); - EXPECT_FALSE(query_field.has_field_metadata()); + ASSERT_EQ(3, query_form.fields_size()); + ASSERT_EQ(static_cast<int>(form.fields.size()), query_form.fields_size()); + for (int i = 0; i < query_form.fields_size(); ++i) { + const auto& query_field = query_form.fields(i); + EXPECT_FALSE(query_field.has_metadata()); } } @@ -1994,8 +1994,10 @@ true, 1); ASSERT_EQ(1u, payloads_.size()); - AutofillUploadContents upload; - ASSERT_TRUE(upload.ParseFromString(payloads_.front())); + AutofillUploadRequest request; + ASSERT_TRUE(request.ParseFromString(payloads_.front())); + ASSERT_TRUE(request.has_upload()); + const AutofillUploadContents& upload = request.upload(); EXPECT_EQ(upload.language(), form_structure.page_language()); ASSERT_TRUE(upload.has_randomized_form_metadata()); EXPECT_TRUE(upload.randomized_form_metadata().has_id()); @@ -2138,8 +2140,10 @@ // The last middle two uploads were marked as throttle-able. ASSERT_EQ(4u, payloads_.size()); for (size_t i = 0; i < payloads_.size(); ++i) { - AutofillUploadContents upload_contents; - ASSERT_TRUE(upload_contents.ParseFromString(payloads_[i])); + AutofillUploadRequest request; + ASSERT_TRUE(request.ParseFromString(payloads_[i])); + ASSERT_TRUE(request.has_upload()); + const AutofillUploadContents& upload_contents = request.upload(); EXPECT_EQ(upload_contents.was_throttleable(), (i == 1 || i == 2)) << "Wrong was_throttleable value for upload " << i; EXPECT_FALSE(upload_contents.has_randomized_form_metadata());
diff --git a/components/autofill/core/browser/autofill_manager_unittest.cc b/components/autofill/core/browser/autofill_manager_unittest.cc index 8fced3b..69b9c66 100644 --- a/components/autofill/core/browser/autofill_manager_unittest.cc +++ b/components/autofill/core/browser/autofill_manager_unittest.cc
@@ -4671,7 +4671,18 @@ // Test that OnLoadedServerPredictions can obtain the FormStructure with the // signature of the queried form and apply type predictions. -TEST_F(AutofillManagerTest, OnLoadedServerPredictions) { +TEST_F(AutofillManagerTest, OnLoadedServerPredictionsFromLegacyServer) { + // Set features. + // This entire test can be deleted because we have + // OnLoadedServerPredictionsAPI. + base::test::ScopedFeatureList feature_list; + feature_list.InitWithFeatures( + // Enabled + {}, + // Disabled + // We want to query the legacy server rather than the API server. + {features::kAutofillUseApi}); + // Set up our form data. FormData form; test::CreateTestAddressFormData(&form); @@ -4868,18 +4879,22 @@ autofill_manager_->AddSeenFormStructure( std::unique_ptr<TestFormStructure>(form_structure)); - AutofillQueryResponseContents response; - response.add_field()->set_overall_type_prediction(3); + AutofillQueryResponse response; + auto* form_suggestion = response.add_form_suggestions(); + form_suggestion->add_field_suggestions()->set_primary_type_prediction(3); for (int i = 0; i < 7; ++i) { - response.add_field()->set_overall_type_prediction(0); + form_suggestion->add_field_suggestions()->set_primary_type_prediction(0); } - response.add_field()->set_overall_type_prediction(3); - response.add_field()->set_overall_type_prediction(2); - response.add_field()->set_overall_type_prediction(61); + form_suggestion->add_field_suggestions()->set_primary_type_prediction(3); + form_suggestion->add_field_suggestions()->set_primary_type_prediction(2); + form_suggestion->add_field_suggestions()->set_primary_type_prediction(61); std::string response_string; ASSERT_TRUE(response.SerializeToString(&response_string)); + std::string response_string_base64; + base::Base64Encode(response_string, &response_string_base64); + std::vector<std::string> signatures; signatures.push_back(form_structure->FormSignatureAsStr()); @@ -4887,7 +4902,7 @@ autofill_manager_->Reset(); base::HistogramTester histogram_tester; - autofill_manager_->OnLoadedServerPredictionsForTest(response_string, + autofill_manager_->OnLoadedServerPredictionsForTest(response_string_base64, signatures); // Verify that FormStructure::ParseQueryResponse was NOT called. @@ -4924,22 +4939,30 @@ autofill_manager_->AddSeenFormStructure( std::unique_ptr<TestFormStructure>(form_structure)); - AutofillQueryResponseContents response; - response.add_field()->set_overall_type_prediction(CREDIT_CARD_NAME_FIRST); - response.add_field()->set_overall_type_prediction(CREDIT_CARD_NAME_LAST); - response.add_field()->set_overall_type_prediction(CREDIT_CARD_NUMBER); - response.add_field()->set_overall_type_prediction(CREDIT_CARD_EXP_MONTH); - response.add_field()->set_overall_type_prediction( + AutofillQueryResponse response; + auto* form_suggestion = response.add_form_suggestions(); + form_suggestion->add_field_suggestions()->set_primary_type_prediction( + CREDIT_CARD_NAME_FIRST); + form_suggestion->add_field_suggestions()->set_primary_type_prediction( + CREDIT_CARD_NAME_LAST); + form_suggestion->add_field_suggestions()->set_primary_type_prediction( + CREDIT_CARD_NUMBER); + form_suggestion->add_field_suggestions()->set_primary_type_prediction( + CREDIT_CARD_EXP_MONTH); + form_suggestion->add_field_suggestions()->set_primary_type_prediction( CREDIT_CARD_EXP_4_DIGIT_YEAR); std::string response_string; ASSERT_TRUE(response.SerializeToString(&response_string)); + std::string response_string_base64; + base::Base64Encode(response_string, &response_string_base64); + std::vector<std::string> signatures; signatures.push_back(form_structure->FormSignatureAsStr()); base::HistogramTester histogram_tester; - autofill_manager_->OnLoadedServerPredictionsForTest(response_string, + autofill_manager_->OnLoadedServerPredictionsForTest(response_string_base64, signatures); // Verify that FormStructure::ParseQueryResponse was called (here and below). histogram_tester.ExpectBucketCount("Autofill.ServerQueryResponse",
diff --git a/components/autofill/core/browser/autofill_metrics_unittest.cc b/components/autofill/core/browser/autofill_metrics_unittest.cc index 215c926..4da42d39 100644 --- a/components/autofill/core/browser/autofill_metrics_unittest.cc +++ b/components/autofill/core/browser/autofill_metrics_unittest.cc
@@ -10,6 +10,7 @@ #include <utility> #include <vector> +#include "base/base64.h" #include "base/feature_list.h" #include "base/macros.h" #include "base/metrics/metrics_hashes.h" @@ -2623,24 +2624,31 @@ std::move(form_structure)) .second); - AutofillQueryResponseContents response; + AutofillQueryResponse response; + auto* form_suggestion = response.add_form_suggestions(); // Server response will match with autocomplete. - response.add_field()->set_overall_type_prediction(NAME_LAST); + form_suggestion->add_field_suggestions()->set_primary_type_prediction( + NAME_LAST); // Server response will NOT match with autocomplete. - response.add_field()->set_overall_type_prediction(NAME_FIRST); + form_suggestion->add_field_suggestions()->set_primary_type_prediction( + NAME_FIRST); // Server response will have no data. - response.add_field()->set_overall_type_prediction(NO_SERVER_DATA); + form_suggestion->add_field_suggestions()->set_primary_type_prediction( + NO_SERVER_DATA); // Not logged. - response.add_field()->set_overall_type_prediction(NAME_MIDDLE); + form_suggestion->add_field_suggestions()->set_primary_type_prediction( + NAME_MIDDLE); std::string response_string; ASSERT_TRUE(response.SerializeToString(&response_string)); + std::string encoded_response_string; + base::Base64Encode(response_string, &encoded_response_string); std::vector<std::string> signatures; signatures.push_back(form_structure_ptr->FormSignatureAsStr()); base::HistogramTester histogram_tester; - autofill_manager_->OnLoadedServerPredictionsForTest(response_string, + autofill_manager_->OnLoadedServerPredictionsForTest(encoded_response_string, signatures); // Verify that FormStructure::ParseQueryResponse was called (here and below).
diff --git a/components/autofill/core/browser/autofill_test_utils.cc b/components/autofill/core/browser/autofill_test_utils.cc index 087bf69..83e9991 100644 --- a/components/autofill/core/browser/autofill_test_utils.cc +++ b/components/autofill/core/browser/autofill_test_utils.cc
@@ -736,6 +736,17 @@ field->set_type(control_type); } +void FillQueryField(AutofillPageQueryRequest_Form_Field* field, + unsigned signature, + const char* name, + const char* control_type) { + field->set_signature(signature); + if (name) + field->set_name(name); + if (control_type) + field->set_control_type(control_type); +} + void GenerateTestAutofillPopup( AutofillExternalDelegate* autofill_external_delegate) { int query_id = 1;
diff --git a/components/autofill/core/browser/autofill_test_utils.h b/components/autofill/core/browser/autofill_test_utils.h index b5c2d002..900e51f 100644 --- a/components/autofill/core/browser/autofill_test_utils.h +++ b/components/autofill/core/browser/autofill_test_utils.h
@@ -14,6 +14,7 @@ #include "components/autofill/core/browser/data_model/credit_card.h" #include "components/autofill/core/browser/data_model/credit_card_cloud_token_data.h" #include "components/autofill/core/browser/field_types.h" +#include "components/autofill/core/browser/proto/api_v1.pb.h" #include "components/autofill/core/browser/proto/server.pb.h" class PrefService; @@ -268,6 +269,10 @@ unsigned signature, const char* name, const char* control_type); +void FillQueryField(AutofillPageQueryRequest_Form_Field* field, + unsigned signature, + const char* name, + const char* control_type); // Calls the required functions on the given external delegate to cause the // delegate to display a popup.
diff --git a/components/autofill/core/browser/proto/legacy_proto_bridge.cc b/components/autofill/core/browser/proto/legacy_proto_bridge.cc index 9ce166c..2bb51d82 100644 --- a/components/autofill/core/browser/proto/legacy_proto_bridge.cc +++ b/components/autofill/core/browser/proto/legacy_proto_bridge.cc
@@ -14,7 +14,8 @@ api_field.set_signature(legacy_field.signature()); api_field.set_name(legacy_field.name()); api_field.set_control_type(legacy_field.type()); - *api_field.mutable_metadata() = legacy_field.field_metadata(); + if (legacy_field.has_field_metadata()) + *api_field.mutable_metadata() = legacy_field.field_metadata(); return api_field; } @@ -22,7 +23,8 @@ const AutofillQueryContents::Form& legacy_form) { AutofillPageQueryRequest::Form api_form; api_form.set_signature(legacy_form.signature()); - *api_form.mutable_metadata() = legacy_form.form_metadata(); + if (legacy_form.has_form_metadata()) + *api_form.mutable_metadata() = legacy_form.form_metadata(); for (const auto& legacy_field : legacy_form.field()) { *api_form.add_fields() = CreateLegacyFieldFromApiField(legacy_field); }
diff --git a/components/autofill/core/common/autofill_features.cc b/components/autofill/core/common/autofill_features.cc index 9fdaae0..2558915 100644 --- a/components/autofill/core/common/autofill_features.cc +++ b/components/autofill/core/common/autofill_features.cc
@@ -197,7 +197,7 @@ // Controls whether to use the API or use the legacy server. const base::Feature kAutofillUseApi{"AutofillUseApi", - base::FEATURE_DISABLED_BY_DEFAULT}; + base::FEATURE_ENABLED_BY_DEFAULT}; // Controls whether suggestions' labels use the improved label disambiguation // format.
diff --git a/components/autofill_assistant/browser/basic_interactions.cc b/components/autofill_assistant/browser/basic_interactions.cc index fb9ee657..42655e2 100644 --- a/components/autofill_assistant/browser/basic_interactions.cc +++ b/components/autofill_assistant/browser/basic_interactions.cc
@@ -8,6 +8,7 @@ #include "base/i18n/time_formatting.h" #include "base/strings/string_number_conversions.h" #include "base/strings/utf_string_conversions.h" +#include "components/autofill/core/browser/autofill_data_util.h" #include "components/autofill_assistant/browser/script_executor_delegate.h" #include "components/autofill_assistant/browser/trigger_context.h" #include "components/autofill_assistant/browser/user_model.h" @@ -144,6 +145,14 @@ time, proto.date_format().date_format().c_str())); break; } + case ValueProto::kCreditCards: + case ValueProto::kProfiles: + case ValueProto::kLoginOptions: + case ValueProto::kCreditCardResponse: + case ValueProto::kLoginOptionResponse: + DVLOG(2) << "Error evaluating " << __func__ << ": kind not supported for " + << *value; + return false; case ValueProto::KIND_NOT_SET: DVLOG(2) << "Error evaluating " << __func__ << ": kind not set"; return false; @@ -259,6 +268,61 @@ return true; } +bool CreateCreditCardResponse(UserModel* user_model, + const std::string& result_model_identifier, + const CreateCreditCardResponseProto& proto) { + auto value = user_model->GetValue(proto.value()); + if (!value.has_value()) { + DVLOG(2) << "Failed to find value in user model"; + return false; + } + + if (value->credit_cards().values().size() != 1) { + DVLOG(2) << "Error evaluating " << __func__ + << ": expected single CreditCardProto, but got " << *value; + return false; + } + + auto* credit_card = + user_model->GetCreditCard(value->credit_cards().values(0).guid()); + if (!credit_card) { + DVLOG(2) << "Error evaluating " << __func__ << ": card not found for guid " + << value->credit_cards().values(0).guid(); + return false; + } + + // The result is intentionally not client_side_only, irrespective of input. + ValueProto result; + result.mutable_credit_card_response()->set_network( + autofill::data_util::GetPaymentRequestData(credit_card->network()) + .basic_card_issuer_network); + user_model->SetValue(result_model_identifier, result); + return true; +} + +bool CreateLoginOptionResponse(UserModel* user_model, + const std::string& result_model_identifier, + const CreateLoginOptionResponseProto& proto) { + auto value = user_model->GetValue(proto.value()); + if (!value.has_value()) { + DVLOG(2) << "Failed to find value in user model"; + return false; + } + + if (value->login_options().values().size() != 1) { + DVLOG(2) << "Error evaluating " << __func__ + << ": expected single LoginOptionProto, but got " << *value; + return false; + } + + // The result is intentionally not client_side_only, irrespective of input. + ValueProto result; + result.mutable_login_option_response()->set_payload( + value->login_options().values(0).payload()); + user_model->SetValue(result_model_identifier, result); + return true; +} + } // namespace base::WeakPtr<BasicInteractions> BasicInteractions::GetWeakPtr() { @@ -334,6 +398,25 @@ } return IntegerSum(delegate_->GetUserModel(), proto.result_model_identifier(), proto.integer_sum()); + case ComputeValueProto::kCreateCreditCardResponse: + if (!proto.create_credit_card_response().has_value()) { + DVLOG(2) << "Error computing ComputeValue::CreateCreditCardResponse: " + "no value specified"; + return false; + } + return CreateCreditCardResponse(delegate_->GetUserModel(), + proto.result_model_identifier(), + proto.create_credit_card_response()); + case ComputeValueProto::kCreateLoginOptionResponse: + if (!proto.create_login_option_response().has_value()) { + DVLOG(2) << "Error computing ComputeValue::CreateLoginOptionResponse: " + "no value specified"; + return false; + } + return CreateLoginOptionResponse(delegate_->GetUserModel(), + proto.result_model_identifier(), + proto.create_login_option_response()); + break; case ComputeValueProto::KIND_NOT_SET: DVLOG(2) << "Error computing value: kind not set"; return false;
diff --git a/components/autofill_assistant/browser/basic_interactions_unittest.cc b/components/autofill_assistant/browser/basic_interactions_unittest.cc index f7762ad..2c83b02 100644 --- a/components/autofill_assistant/browser/basic_interactions_unittest.cc +++ b/components/autofill_assistant/browser/basic_interactions_unittest.cc
@@ -3,9 +3,11 @@ // found in the LICENSE file. #include "components/autofill_assistant/browser/basic_interactions.h" +#include "base/guid.h" #include "base/test/gmock_callback_support.h" #include "base/test/icu_test_util.h" #include "base/test/mock_callback.h" +#include "components/autofill/core/browser/autofill_test_utils.h" #include "components/autofill_assistant/browser/fake_script_executor_delegate.h" #include "components/autofill_assistant/browser/generic_ui.pb.h" #include "components/autofill_assistant/browser/user_model.h" @@ -395,6 +397,84 @@ EXPECT_EQ(user_model_.GetValue("result"), SimpleValue(true, true)); } +TEST_F(BasicInteractionsTest, ComputeValueCreateCreditCardResponse) { + ComputeValueProto proto; + proto.mutable_create_credit_card_response(); + + // Missing fields. + EXPECT_FALSE(basic_interactions_.ComputeValue(proto)); + proto.mutable_create_credit_card_response() + ->mutable_value() + ->set_model_identifier("value"); + EXPECT_FALSE(basic_interactions_.ComputeValue(proto)); + proto.set_result_model_identifier("result"); + EXPECT_FALSE(basic_interactions_.ComputeValue(proto)); + + autofill::CreditCard credit_card(base::GenerateGUID(), + "https://www.example.com"); + autofill::test::SetCreditCardInfo(&credit_card, "Marion Mitchell", + "4111 1111 1111 1111", "01", "2050", ""); + user_model_.AddCreditCard( + std::make_unique<autofill::CreditCard>(credit_card)); + + ValueProto value_wrong_guid; + value_wrong_guid.mutable_credit_cards()->add_values()->set_guid("wrong"); + user_model_.SetValue("value", value_wrong_guid); + EXPECT_FALSE(basic_interactions_.ComputeValue(proto)); + + ValueProto value_correct_guid; + value_correct_guid.mutable_credit_cards()->add_values()->set_guid( + credit_card.guid()); + user_model_.SetValue("value", value_correct_guid); + EXPECT_TRUE(basic_interactions_.ComputeValue(proto)); + ValueProto expected_response_value; + expected_response_value.mutable_credit_card_response()->set_network("visa"); + expected_response_value.set_is_client_side_only(false); + EXPECT_EQ(user_model_.GetValue("result"), expected_response_value); + + // CreateCreditCardResponse is allowed to extract the card network from + // client-only values. + value_correct_guid.set_is_client_side_only(true); + user_model_.SetValue("value", value_correct_guid); + EXPECT_TRUE(basic_interactions_.ComputeValue(proto)); + EXPECT_EQ(user_model_.GetValue("result"), expected_response_value); + + // Size != 1. + ValueProto value; + value.mutable_credit_cards()->add_values()->set_guid(credit_card.guid()); + value.mutable_credit_cards()->add_values()->set_guid(credit_card.guid()); + user_model_.SetValue("value", value); + EXPECT_FALSE(basic_interactions_.ComputeValue(proto)); +} + +TEST_F(BasicInteractionsTest, ComputeValueCreateLoginOptionResponse) { + ComputeValueProto proto; + proto.mutable_create_login_option_response(); + + // Missing fields. + EXPECT_FALSE(basic_interactions_.ComputeValue(proto)); + proto.mutable_create_login_option_response() + ->mutable_value() + ->set_model_identifier("value"); + EXPECT_FALSE(basic_interactions_.ComputeValue(proto)); + proto.set_result_model_identifier("result"); + EXPECT_FALSE(basic_interactions_.ComputeValue(proto)); + + ValueProto value; + value.mutable_login_options()->add_values()->set_payload("payload"); + value.set_is_client_side_only(true); + user_model_.SetValue("value", value); + EXPECT_TRUE(basic_interactions_.ComputeValue(proto)); + + // LoginOptionResponseProto is allowed to extract the payload from + // client-only values. + ValueProto expected_response_value; + expected_response_value.mutable_login_option_response()->set_payload( + "payload"); + expected_response_value.set_is_client_side_only(false); + EXPECT_EQ(user_model_.GetValue("result"), expected_response_value); +} + TEST_F(BasicInteractionsTest, ToggleUserAction) { ToggleUserActionProto proto; ValueProto user_actions_value;
diff --git a/components/autofill_assistant/browser/generic_ui.proto b/components/autofill_assistant/browser/generic_ui.proto index f6f3aac..5e136197 100644 --- a/components/autofill_assistant/browser/generic_ui.proto +++ b/components/autofill_assistant/browser/generic_ui.proto
@@ -120,6 +120,10 @@ ValueComparisonProto comparison = 6; // Computes the sum of two single integers. IntegerSumProto integer_sum = 7; + // Writes safe-to-transmit parts of the input credit card to the result. + CreateCreditCardResponseProto create_credit_card_response = 8; + // Writes safe-to-transmit parts of the input login option to the result. + CreateLoginOptionResponseProto create_login_option_response = 9; } // The model identifier to write the result to. @@ -194,6 +198,18 @@ reserved 1, 2; } +// Creates a safe-to-transmit CreditCardResponseProto for the input |value|. +message CreateCreditCardResponseProto { + // The input CreditCardProto. + optional ValueReferenceProto value = 1; +} + +// Creates a safe-to-transmit LoginOptionResponseProto for the input |value|. +message CreateLoginOptionResponseProto { + // The input LoginOptionProto. + optional ValueReferenceProto value = 1; +} + // Displays a standard info popup. message ShowInfoPopupProto { optional InfoPopupProto info_popup = 1;
diff --git a/components/autofill_assistant/browser/model.proto b/components/autofill_assistant/browser/model.proto index a6a1433..607825b 100644 --- a/components/autofill_assistant/browser/model.proto +++ b/components/autofill_assistant/browser/model.proto
@@ -15,6 +15,7 @@ optional string identifier = 1; optional ValueProto value = 2; } + // Maps model identifiers to their values. repeated ModelValue values = 1; } @@ -28,6 +29,11 @@ IntList ints = 3; UserActionList user_actions = 4; DateList dates = 5; + CreditCardList credit_cards = 7; + ProfileList profiles = 8; + LoginOptionList login_options = 9; + CreditCardResponseProto credit_card_response = 10; + LoginOptionResponseProto login_option_response = 11; } // If set to true, this value will not be sent to the backend. This flag is // mostly used internally, to prevent certain values from leaving the device. @@ -63,6 +69,18 @@ repeated DateProto values = 1; } +message CreditCardList { + repeated AutofillCreditCardProto values = 1; +} + +message ProfileList { + repeated AutofillProfileProto values = 1; +} + +message LoginOptionList { + repeated LoginOptionProto values = 1; +} + // Next: 25 enum ProcessedActionStatusProto { UNKNOWN_ACTION_STATUS = 0; @@ -299,3 +317,27 @@ optional DateProto date = 1; optional TimeProto time = 2; } + +message AutofillCreditCardProto { + // The GUID of the card. + optional string guid = 1; +} + +message CreditCardResponseProto { + optional string network = 1; +} + +message AutofillProfileProto { + // The GUID of the profile. + optional string guid = 1; +} + +message LoginOptionProto { + optional string label = 1; + optional string sublabel = 2; + optional bytes payload = 3; +} + +message LoginOptionResponseProto { + optional bytes payload = 1; +}
diff --git a/components/autofill_assistant/browser/user_model.cc b/components/autofill_assistant/browser/user_model.cc index 26986d5..9520b83 100644 --- a/components/autofill_assistant/browser/user_model.cc +++ b/components/autofill_assistant/browser/user_model.cc
@@ -143,4 +143,37 @@ observers_.RemoveObserver(observer); } +void UserModel::AddCreditCard( + std::unique_ptr<autofill::CreditCard> credit_card) { + if (!credit_card) { + return; + } + credit_cards_[credit_card->guid()] = std::move(credit_card); +} + +void UserModel::AddProfile(std::unique_ptr<autofill::AutofillProfile> profile) { + if (!profile) { + return; + } + profiles_[profile->guid()] = std::move(profile); +} + +const autofill::CreditCard* UserModel::GetCreditCard( + const std::string& guid) const { + auto it = credit_cards_.find(guid); + if (it == credit_cards_.end()) { + return nullptr; + } + return it->second.get(); +} + +const autofill::AutofillProfile* UserModel::GetProfile( + const std::string& guid) const { + auto it = profiles_.find(guid); + if (it == profiles_.end()) { + return nullptr; + } + return it->second.get(); +} + } // namespace autofill_assistant
diff --git a/components/autofill_assistant/browser/user_model.h b/components/autofill_assistant/browser/user_model.h index 520b907d..dc0dba8 100644 --- a/components/autofill_assistant/browser/user_model.h +++ b/components/autofill_assistant/browser/user_model.h
@@ -13,9 +13,10 @@ #include "base/memory/weak_ptr.h" #include "base/observer_list.h" #include "base/optional.h" +#include "components/autofill/core/browser/data_model/autofill_profile.h" +#include "components/autofill/core/browser/data_model/credit_card.h" #include "components/autofill_assistant/browser/model.pb.h" #include "components/autofill_assistant/browser/value_util.h" - namespace autofill_assistant { // Manages a map of |ValueProto| instances and notifies observers of changes. @@ -71,6 +72,18 @@ return values; } + // Adds |credit_card| to the set of available cards. + void AddCreditCard(std::unique_ptr<autofill::CreditCard> credit_card); + + // Adds |profile| to the set of available cards. + void AddProfile(std::unique_ptr<autofill::AutofillProfile> profile); + + // Returns the credit card with |guid| or nullptr if there is no such card. + const autofill::CreditCard* GetCreditCard(const std::string& guid) const; + + // Returns the profile with |guid| or nullptr if there is no such profile. + const autofill::AutofillProfile* GetProfile(const std::string& guid) const; + void AddObserver(Observer* observer); void RemoveObserver(Observer* observer); @@ -88,6 +101,8 @@ friend class UserModelTest; std::map<std::string, ValueProto> values_; + std::map<std::string, std::unique_ptr<autofill::CreditCard>> credit_cards_; + std::map<std::string, std::unique_ptr<autofill::AutofillProfile>> profiles_; base::ObserverList<Observer> observers_; base::WeakPtrFactory<UserModel> weak_ptr_factory_{this}; DISALLOW_COPY_AND_ASSIGN(UserModel);
diff --git a/components/autofill_assistant/browser/value_util.cc b/components/autofill_assistant/browser/value_util.cc index 3fd5298..8511690 100644 --- a/components/autofill_assistant/browser/value_util.cc +++ b/components/autofill_assistant/browser/value_util.cc
@@ -54,6 +54,17 @@ return value_a.user_actions().values() == value_b.user_actions().values(); case ValueProto::kDates: return value_a.dates().values() == value_b.dates().values(); + case ValueProto::kCreditCards: + return value_a.credit_cards().values() == value_b.credit_cards().values(); + case ValueProto::kProfiles: + return value_a.profiles().values() == value_b.profiles().values(); + case ValueProto::kLoginOptions: + return value_a.login_options().values() == + value_b.login_options().values(); + case ValueProto::kCreditCardResponse: + return value_a.credit_card_response() == value_b.credit_card_response(); + case ValueProto::kLoginOptionResponse: + return value_a.login_option_response() == value_b.login_option_response(); case ValueProto::KIND_NOT_SET: return true; } @@ -83,6 +94,11 @@ return value_a.dates().values(0) < value_b.dates().values(0); case ValueProto::kUserActions: case ValueProto::kBooleans: + case ValueProto::kCreditCards: + case ValueProto::kProfiles: + case ValueProto::kLoginOptions: + case ValueProto::kCreditCardResponse: + case ValueProto::kLoginOptionResponse: case ValueProto::KIND_NOT_SET: NOTREACHED(); return false; @@ -143,6 +159,33 @@ return tuple_a < tuple_b; } +bool operator==(const AutofillCreditCardProto& value_a, + const AutofillCreditCardProto& value_b) { + return value_a.guid() == value_b.guid(); +} + +bool operator==(const AutofillProfileProto& value_a, + const AutofillProfileProto& value_b) { + return value_a.guid() == value_b.guid(); +} + +bool operator==(const LoginOptionProto& value_a, + const LoginOptionProto& value_b) { + return value_a.label() == value_b.label() && + value_a.sublabel() == value_b.sublabel() && + value_a.payload() == value_b.payload(); +} + +bool operator==(const CreditCardResponseProto& value_a, + const CreditCardResponseProto& value_b) { + return value_a.network() == value_b.network(); +} + +bool operator==(const LoginOptionResponseProto& value_a, + const LoginOptionResponseProto& value_b) { + return value_a.payload() == value_b.payload(); +} + // Intended for debugging. Writes a string representation of |values| to |out|. template <typename T> std::ostream& WriteRepeatedField(std::ostream& out, const T& values) { @@ -170,18 +213,44 @@ return WriteRepeatedField(out, values); } -// Intended for debugging. '<<' operator specialization for UserActionProto. std::ostream& operator<<(std::ostream& out, const UserActionProto& value) { out << value.identifier(); return out; } -// Intended for debugging. '<<' operator specialization for DateProto. std::ostream& operator<<(std::ostream& out, const DateProto& value) { out << value.year() << "-" << value.month() << "-" << value.day(); return out; } +std::ostream& operator<<(std::ostream& out, + const AutofillCreditCardProto& value) { + out << value.guid(); + return out; +} + +std::ostream& operator<<(std::ostream& out, const AutofillProfileProto& value) { + out << value.guid(); + return out; +} + +std::ostream& operator<<(std::ostream& out, const LoginOptionProto& value) { + out << value.label() << ", " << value.sublabel() << ", " << value.payload(); + return out; +} + +std::ostream& operator<<(std::ostream& out, + const CreditCardResponseProto& value) { + out << value.network(); + return out; +} + +std::ostream& operator<<(std::ostream& out, + const LoginOptionResponseProto& value) { + out << value.payload(); + return out; +} + // Intended for debugging. Writes a string representation of |value| to |out|. std::ostream& operator<<(std::ostream& out, const ValueProto& value) { switch (value.kind_case()) { @@ -200,6 +269,22 @@ case ValueProto::kDates: out << value.dates().values(); break; + case ValueProto::kCreditCards: + out << value.credit_cards().values(); + break; + case ValueProto::kProfiles: + out << value.profiles().values(); + break; + case ValueProto::kLoginOptions: + out << value.login_options().values(); + break; + case ValueProto::kCreditCardResponse: + out << value.credit_card_response(); + break; + case ValueProto::kLoginOptionResponse: + out << value.login_option_response(); + ; + break; case ValueProto::KIND_NOT_SET: break; } @@ -310,15 +395,25 @@ int GetValueSize(const ValueProto& value) { switch (value.kind_case()) { case ValueProto::kStrings: - return value.strings().values_size(); + return value.strings().values().size(); case ValueProto::kBooleans: - return value.booleans().values_size(); + return value.booleans().values().size(); case ValueProto::kInts: - return value.ints().values_size(); + return value.ints().values().size(); case ValueProto::kUserActions: - return value.user_actions().values_size(); + return value.user_actions().values().size(); case ValueProto::kDates: - return value.dates().values_size(); + return value.dates().values().size(); + case ValueProto::kCreditCards: + return value.credit_cards().values().size(); + case ValueProto::kProfiles: + return value.profiles().values().size(); + case ValueProto::kLoginOptions: + return value.login_options().values().size(); + case ValueProto::kCreditCardResponse: + return 1; + case ValueProto::kLoginOptionResponse: + return 1; case ValueProto::KIND_NOT_SET: return 0; } @@ -354,6 +449,26 @@ *nth_value.mutable_dates()->add_values() = value.dates().values().at(index); return nth_value; + case ValueProto::kCreditCards: + *nth_value.mutable_credit_cards()->add_values() = + value.credit_cards().values().at(index); + return nth_value; + case ValueProto::kProfiles: + *nth_value.mutable_profiles()->add_values() = + value.profiles().values().at(index); + return nth_value; + case ValueProto::kLoginOptions: + *nth_value.mutable_login_options()->add_values() = + value.login_options().values().at(index); + return nth_value; + case ValueProto::kCreditCardResponse: + DCHECK(index == 0); + nth_value = value; + return nth_value; + case ValueProto::kLoginOptionResponse: + DCHECK(index == 0); + nth_value = value; + return nth_value; case ValueProto::KIND_NOT_SET: return base::nullopt; }
diff --git a/components/autofill_assistant/browser/value_util.h b/components/autofill_assistant/browser/value_util.h index 5137ceb5..9d44a6c 100644 --- a/components/autofill_assistant/browser/value_util.h +++ b/components/autofill_assistant/browser/value_util.h
@@ -38,6 +38,26 @@ bool operator==(const DateProto& value_a, const DateProto& value_b); bool operator<(const DateProto& value_a, const DateProto& value_b); +// Custom comparison operator for |AutofillCreditCardProto|. +bool operator==(const AutofillCreditCardProto& value_a, + const AutofillCreditCardProto& value_b); + +// Custom comparison operator for |AutofillProfileProto|. +bool operator==(const AutofillProfileProto& value_a, + const AutofillProfileProto& value_b); + +// Custom comparison operator for |LoginOptionProto|. +bool operator==(const LoginOptionProto& value_a, + const LoginOptionProto& value_b); + +// Custom comparison operator for |CreditCardResponseProto|. +bool operator==(const CreditCardResponseProto& value_a, + const CreditCardResponseProto& value_b); + +// Custom comparison operator for |LoginOptionResponseProto|. +bool operator==(const LoginOptionResponseProto& value_a, + const LoginOptionResponseProto& value_b); + // Intended for debugging. std::ostream& operator<<(std::ostream& out, const ValueProto& value); std::ostream& operator<<(std::ostream& out, @@ -46,6 +66,14 @@ const ModelProto::ModelValue& value); std::ostream& operator<<(std::ostream& out, const UserActionProto& value); std::ostream& operator<<(std::ostream& out, const DateProto& value); +std::ostream& operator<<(std::ostream& out, + const AutofillCreditCardProto& value); +std::ostream& operator<<(std::ostream& out, const AutofillProfileProto& value); +std::ostream& operator<<(std::ostream& out, const LoginOptionProto& value); +std::ostream& operator<<(std::ostream& out, + const CreditCardResponseProto& value); +std::ostream& operator<<(std::ostream& out, + const LoginOptionResponseProto& value); // Convenience constructors. ValueProto SimpleValue(bool value, bool is_client_side_only = false);
diff --git a/components/autofill_assistant/browser/value_util_unittest.cc b/components/autofill_assistant/browser/value_util_unittest.cc index 7cf4d2f..b33a2d2 100644 --- a/components/autofill_assistant/browser/value_util_unittest.cc +++ b/components/autofill_assistant/browser/value_util_unittest.cc
@@ -171,6 +171,67 @@ EXPECT_FALSE(value_a == value_b); } +TEST_F(ValueUtilTest, CreditCardComparison) { + ValueProto value_a; + value_a.mutable_credit_cards()->add_values()->set_guid("GUID"); + ValueProto value_b = value_a; + EXPECT_TRUE(value_a == value_b); + + value_b.mutable_credit_cards()->mutable_values(0)->set_guid("wrong"); + EXPECT_FALSE(value_a == value_b); +} + +TEST_F(ValueUtilTest, ProfileComparison) { + ValueProto value_a; + value_a.mutable_profiles()->add_values()->set_guid("GUID"); + ValueProto value_b = value_a; + EXPECT_TRUE(value_a == value_b); + + value_b.mutable_profiles()->mutable_values(0)->set_guid("wrong"); + EXPECT_FALSE(value_a == value_b); +} + +TEST_F(ValueUtilTest, LoginOptionComparison) { + ValueProto value_a; + auto* option_a = value_a.mutable_login_options()->add_values(); + option_a->set_label("label"); + option_a->set_sublabel("sublabel"); + option_a->set_payload("payload"); + ValueProto value_b = value_a; + EXPECT_TRUE(value_a == value_b); + + option_a->set_label("different"); + EXPECT_FALSE(value_a == value_b); + + option_a->set_label("label"); + option_a->set_sublabel("different"); + EXPECT_FALSE(value_a == value_b); + + option_a->set_sublabel("sublabel"); + option_a->set_payload("different"); + EXPECT_FALSE(value_a == value_b); +} + +TEST_F(ValueUtilTest, CreditCardResponseComparison) { + ValueProto value_a; + value_a.mutable_credit_card_response()->set_network("network"); + ValueProto value_b = value_a; + EXPECT_TRUE(value_a == value_b); + + value_b.mutable_credit_card_response()->set_network("different"); + EXPECT_FALSE(value_a == value_b); +} + +TEST_F(ValueUtilTest, LoginOptionResponseComparison) { + ValueProto value_a; + value_a.mutable_login_option_response()->set_payload("payload"); + ValueProto value_b = value_a; + EXPECT_TRUE(value_a == value_b); + + value_b.mutable_login_option_response()->set_payload("different"); + EXPECT_FALSE(value_a == value_b); +} + TEST_F(ValueUtilTest, AreAllValuesOfType) { ValueProto value_a; ValueProto value_b;
diff --git a/components/browser_ui/settings/android/BUILD.gn b/components/browser_ui/settings/android/BUILD.gn index 3bc0f42..d8e1bf4 100644 --- a/components/browser_ui/settings/android/BUILD.gn +++ b/components/browser_ui/settings/android/BUILD.gn
@@ -25,10 +25,6 @@ "//third_party/android_deps:android_support_v7_appcompat_java", "//third_party/android_deps:androidx_annotation_annotation_java", "//third_party/android_deps:androidx_preference_preference_java", - - # TODO(crbug.com/1017190): Remove the following deps once we stop linting individual targets. - "//components/browser_ui/styles/android:java_resources", - "//third_party/android_deps:com_google_android_material_material_java", "//ui/android:ui_java", ] }
diff --git a/components/browser_ui/styles/android/BUILD.gn b/components/browser_ui/styles/android/BUILD.gn index e3aa975..df18109 100644 --- a/components/browser_ui/styles/android/BUILD.gn +++ b/components/browser_ui/styles/android/BUILD.gn
@@ -11,9 +11,6 @@ ":java_resources", "//base:base_java", "//third_party/android_deps:android_support_v7_appcompat_java", - - # TODO(crbug.com/1017190): Remove this workaround. - "//ui/android:ui_java", ] }
diff --git a/components/external_intents/android/java/src/org/chromium/components/external_intents/ExternalNavigationHandler.java b/components/external_intents/android/java/src/org/chromium/components/external_intents/ExternalNavigationHandler.java index 2d46434..1c780c86 100644 --- a/components/external_intents/android/java/src/org/chromium/components/external_intents/ExternalNavigationHandler.java +++ b/components/external_intents/android/java/src/org/chromium/components/external_intents/ExternalNavigationHandler.java
@@ -97,12 +97,12 @@ // An extra that may be specified on an intent:// URL that contains an encoded value for the // referrer field passed to the market:// URL in the case where the app is not present. @VisibleForTesting - public static final String EXTRA_MARKET_REFERRER = "market_referrer"; + static final String EXTRA_MARKET_REFERRER = "market_referrer"; // A mask of flags that are safe for untrusted content to use when starting an Activity. // This list is not exhaustive and flags not listed here are not necessarily unsafe. @VisibleForTesting - public static final int ALLOWED_INTENT_FLAGS = Intent.FLAG_EXCLUDE_STOPPED_PACKAGES + static final int ALLOWED_INTENT_FLAGS = Intent.FLAG_EXCLUDE_STOPPED_PACKAGES | Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_MATCH_EXTERNAL | Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_MULTIPLE_TASK | Intent.FLAG_ACTIVITY_NEW_DOCUMENT @@ -111,7 +111,7 @@ // These values are persisted in histograms. Please do not renumber. Append only. @IntDef({AiaIntent.FALLBACK_USED, AiaIntent.SERP, AiaIntent.OTHER}) @Retention(RetentionPolicy.SOURCE) - public @interface AiaIntent { + private @interface AiaIntent { int FALLBACK_USED = 0; int SERP = 1; int OTHER = 2; @@ -131,7 +131,7 @@ StandardActions.WEB_SEARCH, StandardActions.FACTORY_TEST, StandardActions.OTHER}) @Retention(RetentionPolicy.SOURCE) @VisibleForTesting - public @interface StandardActions { + @interface StandardActions { int MAIN = 0; int VIEW = 1; int ATTACH_DATA = 2; @@ -158,8 +158,7 @@ } @VisibleForTesting - public static final String INTENT_ACTION_HISTOGRAM = - "Android.Intent.OverrideUrlLoadingIntentAction"; + static final String INTENT_ACTION_HISTOGRAM = "Android.Intent.OverrideUrlLoadingIntentAction"; private final ExternalNavigationDelegate mDelegate; @@ -366,6 +365,7 @@ * @param referrerUrl The HTTP referrer URL. * @param needsToCloseTab Whether this action should close the current tab. */ + @VisibleForTesting protected void startFileIntent( final Intent intent, final String referrerUrl, final boolean needsToCloseTab) { PermissionCallback permissionCallback = new PermissionCallback() { @@ -399,6 +399,7 @@ * @return OverrideUrlLoadingResult (if the tab has been clobbered, or we're launching an * intent.) */ + @VisibleForTesting protected @OverrideUrlLoadingResult int clobberCurrentTab(String url, String referrerUrl) { int transitionType = PageTransition.LINK; final LoadUrlParams loadUrlParams = new LoadUrlParams(url, transitionType); @@ -526,7 +527,7 @@ /** Wrapper of check against the feature to support overriding for testing. */ @VisibleForTesting - public boolean blockExternalFormRedirectsWithoutGesture() { + boolean blockExternalFormRedirectsWithoutGesture() { return ExternalIntentsFeatureList.isEnabled( ExternalIntentsFeatureList.INTENT_BLOCK_EXTERNAL_FORM_REDIRECT_NO_GESTURE); } @@ -1208,7 +1209,8 @@ /** * @return Whether the |url| could be handled by an external application on the system. */ - public boolean canExternalAppHandleUrl(String url) { + @VisibleForTesting + boolean canExternalAppHandleUrl(String url) { if (url.startsWith(WTAI_MC_URL_PREFIX)) return true; Intent intent; try { @@ -1291,7 +1293,7 @@ * @return Whether the URL is a file download. */ @VisibleForTesting - public boolean isPdfDownload(String url) { + boolean isPdfDownload(String url) { String fileExtension = MimeTypeMap.getFileExtensionFromUrl(url); if (TextUtils.isEmpty(fileExtension)) return false; @@ -1308,7 +1310,7 @@ /** * Records the dispatching of an external intent. */ - static void recordExternalNavigationDispatched(Intent intent) { + private static void recordExternalNavigationDispatched(Intent intent) { ArrayList<String> specializedHandlers = intent.getStringArrayListExtra(EXTRA_EXTERNAL_NAV_PACKAGES); if (specializedHandlers != null && specializedHandlers.size() > 0) { @@ -1323,7 +1325,7 @@ * * @param intent Intent to open. */ - static void forcePdfViewerAsIntentHandlerIfNeeded(Intent intent) { + private static void forcePdfViewerAsIntentHandlerIfNeeded(Intent intent) { if (intent == null || !isPdfIntent(intent)) return; resolveIntent(intent, true /* allowSelfOpen (ignored) */); } @@ -1481,7 +1483,7 @@ * Returns the number of specialized intent handlers in {@params infos}. Specialized intent * handlers are intent handlers which handle only a few URLs (e.g. google maps or youtube). */ - int countSpecializedHandlers(List<ResolveInfo> infos) { + private int countSpecializedHandlers(List<ResolveInfo> infos) { return getSpecializedHandlersWithFilter( infos, null, mDelegate.handlesInstantAppLaunchingInternally()) .size(); @@ -1490,12 +1492,13 @@ /** * Returns the subset of {@params infos} that are specialized intent handlers. */ - ArrayList<String> getSpecializedHandlers(List<ResolveInfo> infos) { + private ArrayList<String> getSpecializedHandlers(List<ResolveInfo> infos) { return getSpecializedHandlersWithFilter( infos, null, mDelegate.handlesInstantAppLaunchingInternally()); } - static boolean matchResolveInfoExceptWildCardHost(ResolveInfo info, String filterPackageName) { + private static boolean matchResolveInfoExceptWildCardHost( + ResolveInfo info, String filterPackageName) { IntentFilter intentFilter = info.filter; if (intentFilter == null) { // Error on the side of classifying ResolveInfo as generic. @@ -1525,7 +1528,6 @@ return true; } - @VisibleForTesting public static ArrayList<String> getSpecializedHandlersWithFilter(List<ResolveInfo> infos, String filterPackageName, boolean handlesInstantAppLaunchingInternally) { ArrayList<String> result = new ArrayList<>(); @@ -1590,6 +1592,7 @@ * @param url The requested url. * @return Whether we should block the navigation and request file access before proceeding. */ + @VisibleForTesting protected boolean shouldRequestFileAccess(String url) { // If the tab is null, then do not attempt to prompt for access. if (!mDelegate.hasValidTab()) return false; @@ -1624,6 +1627,7 @@ /** * @return whether this navigation is from the search results page. */ + @VisibleForTesting protected boolean isSerpReferrer() { String referrerUrl = getReferrerUrl(); if (referrerUrl == null) return false;
diff --git a/components/feed/core/proto/libraries/api/internal/stream_data.proto b/components/feed/core/proto/libraries/api/internal/stream_data.proto index e66a0b8..f5e0b26 100644 --- a/components/feed/core/proto/libraries/api/internal/stream_data.proto +++ b/components/feed/core/proto/libraries/api/internal/stream_data.proto
@@ -229,6 +229,10 @@ optional feedwire1.ActionPayload payload = 6; + // The duration for the action in milliseconds. In case of view actions this + // is the duration for which the content is considered "viewed". + optional int64 duration_ms = 7; + reserved 1, 5; // deprecated fields }
diff --git a/components/lookalikes/core/lookalike_url_util.cc b/components/lookalikes/core/lookalike_url_util.cc index a21175fc..1f081d0 100644 --- a/components/lookalikes/core/lookalike_url_util.cc +++ b/components/lookalikes/core/lookalike_url_util.cc
@@ -332,8 +332,7 @@ lookalikes::features::kDetectTargetEmbeddingLookalikes)) { return true; } - return match_type == LookalikeUrlMatchType::kTopSite && - navigated_domain.idn_result.matching_top_domain.is_top_500; + return match_type == LookalikeUrlMatchType::kSkeletonMatchTop500; } bool GetMatchingDomain( @@ -367,7 +366,9 @@ DCHECK_NE(navigated_domain.domain_and_registry, navigated_domain.idn_result.matching_top_domain.domain); *matched_domain = navigated_domain.idn_result.matching_top_domain.domain; - *match_type = LookalikeUrlMatchType::kTopSite; + *match_type = navigated_domain.idn_result.matching_top_domain.is_top_500 + ? LookalikeUrlMatchType::kSkeletonMatchTop500 + : LookalikeUrlMatchType::kSkeletonMatchTop5k; return true; } } @@ -407,9 +408,6 @@ void RecordUMAFromMatchType(LookalikeUrlMatchType match_type) { switch (match_type) { - case LookalikeUrlMatchType::kTopSite: - RecordEvent(NavigationSuggestionEvent::kMatchTopSite); - break; case LookalikeUrlMatchType::kSiteEngagement: RecordEvent(NavigationSuggestionEvent::kMatchSiteEngagement); break; @@ -422,6 +420,12 @@ case LookalikeUrlMatchType::kTargetEmbedding: RecordEvent(NavigationSuggestionEvent::kMatchTargetEmbedding); break; + case LookalikeUrlMatchType::kSkeletonMatchTop500: + RecordEvent(NavigationSuggestionEvent::kMatchSkeletonTop500); + break; + case LookalikeUrlMatchType::kSkeletonMatchTop5k: + RecordEvent(NavigationSuggestionEvent::kMatchSkeletonTop5k); + break; case LookalikeUrlMatchType::kNone: break; }
diff --git a/components/lookalikes/core/lookalike_url_util.h b/components/lookalikes/core/lookalike_url_util.h index 2ab396e0..1bc49c2 100644 --- a/components/lookalikes/core/lookalike_url_util.h +++ b/components/lookalikes/core/lookalike_url_util.h
@@ -25,15 +25,18 @@ // Used for UKM. There is only a single LookalikeUrlMatchType per navigation. enum class LookalikeUrlMatchType { kNone = 0, - kTopSite = 1, + // DEPRECATED: Use kSkeletonMatchTop500 or kSkeletonMatchTop5k. + // kTopSite = 1, kSiteEngagement = 2, kEditDistance = 3, kEditDistanceSiteEngagement = 4, kTargetEmbedding = 5, + kSkeletonMatchTop500 = 6, + kSkeletonMatchTop5k = 7, // Append new items to the end of the list above; do not modify or replace // existing values. Comment out obsolete items. - kMaxValue = kTargetEmbedding, + kMaxValue = kSkeletonMatchTop5k, }; // Used for UKM. There is only a single LookalikeUrlBlockingPageUserAction per @@ -55,15 +58,18 @@ // Interstitial results recorded using security_interstitials::MetricsHelper // kInfobarShown = 1, // kLinkClicked = 2, - kMatchTopSite = 3, + // DEPRECATED: Use kMatchSkeletonTop500 or kMatchSkeletonTop5k. + // kMatchTopSite = 3, kMatchSiteEngagement = 4, kMatchEditDistance = 5, kMatchEditDistanceSiteEngagement = 6, kMatchTargetEmbedding = 7, + kMatchSkeletonTop500 = 8, + kMatchSkeletonTop5k = 9, // Append new items to the end of the list above; do not modify or // replace existing values. Comment out obsolete items. - kMaxValue = kMatchTargetEmbedding, + kMaxValue = kMatchSkeletonTop5k, }; struct DomainInfo {
diff --git a/components/page_info/android/BUILD.gn b/components/page_info/android/BUILD.gn index ee73a9c..060e48f 100644 --- a/components/page_info/android/BUILD.gn +++ b/components/page_info/android/BUILD.gn
@@ -10,10 +10,13 @@ "certificate_viewer_android.cc", "connection_info_popup_android.cc", "connection_info_popup_android.h", + "features.cc", + "features.h", "page_info_client.cc", "page_info_client.h", "page_info_controller_android.cc", "page_info_controller_android.h", + "page_info_feature_list.cc", ] deps = [ "//base", @@ -50,6 +53,8 @@ "java/res/layout/cookie_controls_view.xml", "java/res/layout/page_info.xml", "java/res/layout/page_info_permission_row.xml", + "java/res/layout/page_info_row.xml", + "java/res/layout/page_info_v2.xml", "java/res/values/colors.xml", "java/res/values/dimens.xml", "java/res/values/ids.xml", @@ -71,7 +76,10 @@ "java/src/org/chromium/components/page_info/PageInfoController.java", "java/src/org/chromium/components/page_info/PageInfoControllerDelegate.java", "java/src/org/chromium/components/page_info/PageInfoDialog.java", + "java/src/org/chromium/components/page_info/PageInfoFeatureList.java", + "java/src/org/chromium/components/page_info/PageInfoRowView.java", "java/src/org/chromium/components/page_info/PageInfoView.java", + "java/src/org/chromium/components/page_info/PageInfoViewV2.java", "java/src/org/chromium/components/page_info/SystemSettingsActivityRequiredListener.java", "java/src/org/chromium/components/page_info/VrHandler.java", ] @@ -107,6 +115,7 @@ "java/src/org/chromium/components/page_info/CertificateViewer.java", "java/src/org/chromium/components/page_info/ConnectionInfoPopup.java", "java/src/org/chromium/components/page_info/PageInfoController.java", + "java/src/org/chromium/components/page_info/PageInfoFeatureList.java", ] }
diff --git a/components/page_info/android/features.cc b/components/page_info/android/features.cc new file mode 100644 index 0000000..e670a67 --- /dev/null +++ b/components/page_info/android/features.cc
@@ -0,0 +1,15 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/page_info/android/features.h" + +#include "base/feature_list.h" +#include "base/metrics/field_trial_params.h" + +namespace page_info { + +const base::Feature kPageInfoV2{"PageInfoV2", + base::FEATURE_DISABLED_BY_DEFAULT}; + +} // namespace page_info \ No newline at end of file
diff --git a/components/page_info/android/features.h b/components/page_info/android/features.h new file mode 100644 index 0000000..5daae79 --- /dev/null +++ b/components/page_info/android/features.h
@@ -0,0 +1,19 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_PAGE_INFO_ANDROID_FEATURES_H_ +#define COMPONENTS_PAGE_INFO_ANDROID_FEATURES_H_ + +namespace base { +struct Feature; +} // namespace base + +namespace page_info { + +// Enables the second version of the Page Info View. +extern const base::Feature kPageInfoV2; + +} // namespace page_info + +#endif // COMPONENTS_PAGE_INFO_ANDROID_FEATURES_H_ \ No newline at end of file
diff --git a/components/page_info/android/java/res/layout/page_info_row.xml b/components/page_info/android/java/res/layout/page_info_row.xml new file mode 100644 index 0000000..0b113bf --- /dev/null +++ b/components/page_info/android/java/res/layout/page_info_row.xml
@@ -0,0 +1,48 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + 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. +--> +<merge + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" + xmlns:tools="http://schemas.android.com/tools"> + <RelativeLayout + android:layout_width="match_parent" + android:layout_height="match_parent" + android:paddingTop="12dp" + android:paddingBottom="12dp" + android:paddingEnd="@dimen/page_info_popup_padding_sides" + android:paddingStart="@dimen/page_info_popup_padding_sides" > + + <ImageView + android:id="@+id/page_info_row_icon" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + tools:ignore="ContentDescription" + android:layout_marginEnd="10dp" + android:layout_centerVertical="true" + android:layout_alignParentStart="true" + app:tint="@color/default_icon_color" /> + + <org.chromium.ui.widget.TextViewWithLeading + android:id="@+id/page_info_row_title" + android:textAppearance="@style/TextAppearance.TextLarge.Primary" + android:layout_toEndOf="@id/page_info_row_icon" + android:layout_marginBottom="4dp" + android:layout_height="wrap_content" + android:layout_width="match_parent" /> + + <org.chromium.ui.widget.TextViewWithLeading + android:id="@+id/page_info_row_subtitle" + android:textAppearance="@style/TextAppearance.TextMedium.Secondary" + android:layout_toEndOf="@id/page_info_row_icon" + android:layout_below="@id/page_info_row_title" + app:leading="@dimen/text_size_medium_leading" + android:layout_height="wrap_content" + android:layout_width="match_parent" /> + + </RelativeLayout> +</merge> \ No newline at end of file
diff --git a/components/page_info/android/java/res/layout/page_info_v2.xml b/components/page_info/android/java/res/layout/page_info_v2.xml new file mode 100644 index 0000000..cbb4bc2 --- /dev/null +++ b/components/page_info/android/java/res/layout/page_info_v2.xml
@@ -0,0 +1,137 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + 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. +--> +<LinearLayout + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:paddingBottom="8dp" + android:orientation="vertical" + android:background="@color/sheet_bg_color"> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical" + android:paddingBottom="12dp" + android:paddingEnd="@dimen/page_info_popup_padding_sides" + android:paddingStart="@dimen/page_info_popup_padding_sides" > + + <view class="org.chromium.components.page_info.PageInfoView$ElidedUrlTextView" + android:id="@+id/page_info_url" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:ellipsize="end" + android:lineSpacingExtra="6dp" + android:paddingTop="16dp" + android:textAlignment="viewStart" + android:textAppearance="@style/TextAppearance.TextLarge.Primary" /> + + <View + android:id="@+id/page_info_preview_separator" + android:layout_marginTop="16dp" + style="@style/HorizontalDivider" + android:visibility="gone" /> + + <TextView + android:id="@+id/page_info_preview_message" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:paddingTop="14dp" + android:textAppearance="@style/TextAppearance.TextLarge.Primary" + android:text="@string/page_info_preview_message" + android:visibility="gone" /> + + <TextView + android:id="@+id/page_info_stale_preview_timestamp" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:textAppearance="@style/TextAppearance.TextSmall.Secondary" + android:visibility="gone" /> + + <TextView + android:id="@+id/page_info_preview_load_original" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:paddingTop="12dp" + android:textAppearance="@style/TextAppearance.TextLarge.Primary" + android:visibility="gone" /> + </LinearLayout> + + <LinearLayout + android:id="@+id/page_info_row_wrapper" + android:visibility="gone" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical" + android:showDividers="middle" + android:divider="?android:listDivider" + android:dividerPadding="2dp" > + <org.chromium.components.page_info.PageInfoRowView + android:id="@+id/page_info_connection_row" + android:visibility="gone" + android:layout_height="wrap_content" + android:layout_width="match_parent"/> + <org.chromium.components.page_info.PageInfoRowView + android:id="@+id/page_info_performance_row" + android:visibility="gone" + android:layout_height="wrap_content" + android:layout_width="match_parent"/> + <org.chromium.components.page_info.PageInfoRowView + android:id="@+id/page_info_permissions_row" + android:visibility="gone" + android:layout_height="wrap_content" + android:layout_width="match_parent"/> + <org.chromium.components.page_info.PageInfoRowView + android:id="@+id/page_info_cookies_row" + android:visibility="gone" + android:layout_height="wrap_content" + android:layout_width="match_parent"/> + </LinearLayout> + + <org.chromium.ui.widget.ButtonCompat + android:id="@+id/page_info_instant_app_button" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="start" + android:layout_marginEnd="@dimen/page_info_popup_padding_sides" + android:layout_marginStart="@dimen/page_info_popup_padding_sides" + android:layout_marginTop="12dp" + android:layout_marginBottom="4dp" + android:paddingEnd="@dimen/page_info_popup_button_padding_sides" + android:paddingStart="@dimen/page_info_popup_button_padding_sides" + android:text="@string/page_info_instant_app_button" + app:buttonColor="@color/app_banner_install_button_bg" + style="@style/FilledButton" /> + + <org.chromium.ui.widget.ButtonCompat + android:id="@+id/page_info_site_settings_button" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="end" + android:layout_marginEnd="@dimen/page_info_popup_padding_sides" + android:layout_marginStart="@dimen/page_info_popup_padding_sides" + android:layout_marginTop="2dp" + android:paddingEnd="@dimen/page_info_popup_button_padding_sides" + android:paddingStart="@dimen/page_info_popup_button_padding_sides" + android:text="@string/page_info_site_settings_button" + style="@style/TextButton" /> + + <org.chromium.ui.widget.ButtonCompat + android:id="@+id/page_info_open_online_button" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="end" + android:layout_marginEnd="@dimen/page_info_popup_padding_sides" + android:layout_marginStart="@dimen/page_info_popup_padding_sides" + android:layout_marginTop="2dp" + android:paddingEnd="@dimen/page_info_popup_button_padding_sides" + android:paddingStart="@dimen/page_info_popup_button_padding_sides" + android:text="@string/page_info_open_online_button" + style="@style/TextButton" /> +</LinearLayout>
diff --git a/components/page_info/android/java/src/org/chromium/components/page_info/CookieControlsView.java b/components/page_info/android/java/src/org/chromium/components/page_info/CookieControlsView.java index 0e61a73..d3c25d6 100644 --- a/components/page_info/android/java/src/org/chromium/components/page_info/CookieControlsView.java +++ b/components/page_info/android/java/src/org/chromium/components/page_info/CookieControlsView.java
@@ -29,8 +29,6 @@ /** Parameters to configure the cookie controls view. */ public static class CookieControlsParams { - // Called when the cookie controls UI is closed. - public Runnable onUiClosingCallback; // Called when the toggle controlling third-party cookie blocking changes. public Callback<Boolean> onCheckedChangedCallback; } @@ -50,13 +48,6 @@ mParams = params; } - // FrameLayout: - @Override - protected void onDetachedFromWindow() { - super.onDetachedFromWindow(); - mParams.onUiClosingCallback.run(); - } - public void setCookieBlockingStatus(@CookieControlsStatus int status, boolean isEnforced) { mLastSwitchState = status == CookieControlsStatus.ENABLED; mSwitch.setChecked(mLastSwitchState);
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 f7c8d14b3..172586fb 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
@@ -112,6 +112,9 @@ // Reference to last created PageInfoController for testing. private static WeakReference<PageInfoController> sLastPageInfoControllerForTesting; + // Whether Version 2 of the PageInfoView is enabled. + private boolean mIsV2Enabled; + /** * Creates the PageInfoController, but does not display it. Also initializes the corresponding * C++ object and saves a pointer to it. @@ -123,10 +126,11 @@ */ @VisibleForTesting(otherwise = VisibleForTesting.PROTECTED) public PageInfoController(WebContents webContents, int securityLevel, String publisher, - PageInfoControllerDelegate delegate) { + PageInfoControllerDelegate delegate, boolean isV2Enabled) { mWebContents = webContents; mSecurityLevel = securityLevel; mDelegate = delegate; + mIsV2Enabled = isV2Enabled; mRunAfterDismissConsumer = new Consumer<Runnable>() { @Override public void accept(Runnable r) { @@ -204,6 +208,7 @@ viewParams.siteSettingsButtonShown = false; viewParams.cookieControlsShown = false; } + viewParams.onUiClosingCallback = mDelegate::onUiClosing; mDelegate.initPreviewUiParams(viewParams, mRunAfterDismissConsumer); mDelegate.initOfflinePageUiParams(viewParams, mRunAfterDismissConsumer); @@ -224,7 +229,8 @@ viewParams.instantAppButtonShown = false; } - mView = new PageInfoView(mContext, viewParams); + mView = mIsV2Enabled ? new PageInfoViewV2(mContext, viewParams) + : new PageInfoView(mContext, viewParams); if (isSheet(mContext)) mView.setBackgroundColor(Color.WHITE); // TODO(crbug.com/1040091): Remove when cookie controls are launched. boolean showTitle = viewParams.cookieControlsShown; @@ -232,18 +238,35 @@ mWindowAndroid, mFullUrl, showTitle, this, mView::setPermissions); mNativePageInfoController = PageInfoControllerJni.get().init(this, mWebContents); + if (mIsV2Enabled) { + PageInfoRowView.ViewParams cookieControlsParams = new PageInfoRowView.ViewParams(); + cookieControlsParams.visible = viewParams.cookieControlsShown; + cookieControlsParams.title = + mView.getContext().getResources().getString(R.string.cookies_title); + ((PageInfoViewV2) mView).getCookiesRowView().setParams(cookieControlsParams); + } else { + CookieControlsView.CookieControlsParams cookieControlsParams = + new CookieControlsView.CookieControlsParams(); + cookieControlsParams.onCheckedChangedCallback = (Boolean blockCookies) -> { + recordAction(blockCookies ? PageInfoAction.PAGE_INFO_COOKIE_BLOCKED_FOR_SITE + : PageInfoAction.PAGE_INFO_COOKIE_ALLOWED_FOR_SITE); + mDelegate.setThirdPartyCookieBlockingEnabledForSite(blockCookies); + }; + mView.getCookieControlsView().setParams(cookieControlsParams); + } mDelegate.createCookieControlsBridge(this); - CookieControlsView.CookieControlsParams cookieControlsParams = - new CookieControlsView.CookieControlsParams(); - cookieControlsParams.onUiClosingCallback = mDelegate::onUiClosing; - cookieControlsParams.onCheckedChangedCallback = (Boolean blockCookies) -> { - recordAction(blockCookies ? PageInfoAction.PAGE_INFO_COOKIE_BLOCKED_FOR_SITE - : PageInfoAction.PAGE_INFO_COOKIE_ALLOWED_FOR_SITE); - mDelegate.setThirdPartyCookieBlockingEnabledForSite(blockCookies); - }; - mView.getCookieControlsView().setParams(cookieControlsParams); - mView.showPerformanceInfo(mDelegate.shouldShowPerformanceBadge(mFullUrl)); + if (mIsV2Enabled) { + PageInfoRowView.ViewParams performanceParams = new PageInfoRowView.ViewParams(); + performanceParams.visible = mDelegate.shouldShowPerformanceBadge(mFullUrl); + performanceParams.title = mView.getContext().getResources().getString( + R.string.page_info_fast_site_summary); + performanceParams.subtitle = mView.getContext().getResources().getString( + R.string.page_info_fast_site_message); + ((PageInfoViewV2) mView).getPerformanceRowView().setParams(performanceParams); + } else { + mView.showPerformanceInfo(mDelegate.shouldShowPerformanceBadge(mFullUrl)); + } mWebContentsObserver = new WebContentsObserver(webContents) { @Override @@ -357,7 +380,21 @@ }); }; } - mView.setConnectionInfo(connectionInfoParams); + + if (mIsV2Enabled) { + PageInfoRowView.ViewParams connectionRowParams = new PageInfoRowView.ViewParams(); + connectionRowParams.title = connectionInfoParams.summary != null + ? connectionInfoParams.summary.toString() + : null; + connectionRowParams.subtitle = connectionInfoParams.message != null + ? connectionInfoParams.message.toString() + : null; + connectionRowParams.visible = + connectionRowParams.title != null || connectionRowParams.subtitle != null; + ((PageInfoViewV2) mView).getConnectionRowView().setParams(connectionRowParams); + } else { + mView.setConnectionInfo(connectionInfoParams); + } } @Override @@ -448,7 +485,7 @@ sLastPageInfoControllerForTesting = new WeakReference<>(new PageInfoController(webContents, SecurityStateModel.getSecurityLevelForWebContents(webContents), contentPublisher, - delegate)); + delegate, PageInfoFeatureList.isEnabled(PageInfoFeatureList.PAGE_INFO_V2))); } @VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE) @@ -460,13 +497,21 @@ @Override public void onCookieBlockingStatusChanged( @CookieControlsStatus int status, @CookieControlsEnforcement int enforcement) { - mView.getCookieControlsView().setCookieBlockingStatus( - status, enforcement != CookieControlsEnforcement.NO_ENFORCEMENT); + if (!mIsV2Enabled) { + mView.getCookieControlsView().setCookieBlockingStatus( + status, enforcement != CookieControlsEnforcement.NO_ENFORCEMENT); + } } @Override public void onBlockedCookiesCountChanged(int blockedCookies) { - mView.getCookieControlsView().setBlockedCookiesCount(blockedCookies); + if (mIsV2Enabled) { + String subtitle = mContext.getResources().getQuantityString( + R.plurals.cookie_controls_blocked_cookies, blockedCookies, blockedCookies); + ((PageInfoViewV2) mView).getCookiesRowView().updateSubtitle(subtitle); + } else { + mView.getCookieControlsView().setBlockedCookiesCount(blockedCookies); + } } @NativeMethods
diff --git a/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoFeatureList.java b/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoFeatureList.java new file mode 100644 index 0000000..6efd7b5 --- /dev/null +++ b/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoFeatureList.java
@@ -0,0 +1,44 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.components.page_info; + +import org.chromium.base.FeatureList; +import org.chromium.base.annotations.JNINamespace; +import org.chromium.base.annotations.MainDex; +import org.chromium.base.annotations.NativeMethods; + +/** + * Provides an API for querying the status of Page Info features. + */ +// TODO(crbug.com/1060097): Remove/update this once a generalized FeatureList exists. +@JNINamespace("page_info") +@MainDex +public class PageInfoFeatureList { + public static final String PAGE_INFO_V2 = "PageInfoV2"; + + private PageInfoFeatureList() {} + + /** + * Returns whether the specified feature is enabled or not. + * + * Note: Features queried through this API must be added to the array + * |kFeaturesExposedToJava| in + * //components/page_info/android/page_info_feature_list.cc + * + * @param featureName The name of the feature to query. + * @return Whether the feature is enabled or not. + */ + public static boolean isEnabled(String featureName) { + Boolean testValue = FeatureList.getTestValueForFeature(featureName); + if (testValue != null) return testValue; + assert FeatureList.isNativeInitialized(); + return PageInfoFeatureListJni.get().isEnabled(featureName); + } + + @NativeMethods + interface Natives { + boolean isEnabled(String featureName); + } +} \ No newline at end of file
diff --git a/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoRowView.java b/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoRowView.java new file mode 100644 index 0000000..a81ddd5 --- /dev/null +++ b/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoRowView.java
@@ -0,0 +1,65 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.components.page_info; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.View; +import android.view.View.OnClickListener; +import android.widget.ImageView; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import androidx.annotation.DrawableRes; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +/** + * View showing an icon, title and subtitle for a page info row. + */ +public class PageInfoRowView extends RelativeLayout implements OnClickListener { + /** Parameters to configure the row view. */ + public static class ViewParams { + public boolean visible; + public @DrawableRes int iconResId; + public String title; + public String subtitle; + public Runnable clickCallback; + } + + private final ImageView mIcon; + private final TextView mTitle; + private final TextView mSubtitle; + private Runnable mClickCallback; + + public PageInfoRowView(@NonNull Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + LayoutInflater.from(context).inflate(R.layout.page_info_row, this, true); + mIcon = findViewById(R.id.page_info_row_icon); + mTitle = findViewById(R.id.page_info_row_title); + mSubtitle = findViewById(R.id.page_info_row_subtitle); + } + + public void setParams(ViewParams params) { + setVisibility(params.visible ? View.VISIBLE : View.GONE); + mIcon.setImageResource(params.iconResId); + mTitle.setText(params.title); + updateSubtitle(params.subtitle); + mClickCallback = params.clickCallback; + } + + public void updateSubtitle(String subtitle) { + mSubtitle.setText(subtitle); + mSubtitle.setVisibility(subtitle != null ? View.VISIBLE : View.GONE); + } + + @Override + public void onClick(View view) { + if (mClickCallback != null) { + mClickCallback.run(); + } + } +}
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 81b3a68..6783c5a 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
@@ -168,6 +168,7 @@ public Runnable siteSettingsButtonClickCallback; public Runnable openOnlineButtonClickCallback; public Runnable previewShowOriginalClickCallback; + public Runnable onUiClosingCallback; public CharSequence url; public CharSequence previewLoadOriginalMessage; @@ -198,77 +199,73 @@ public Runnable clickCallback; } - private static final int FADE_DURATION_MS = 200; - private static final int FADE_IN_BASE_DELAY_MS = 150; - private static final int FADE_IN_DELAY_OFFSET_MS = 20; + protected static final int FADE_DURATION_MS = 200; + protected static final int FADE_IN_BASE_DELAY_MS = 150; + protected static final int FADE_IN_DELAY_OFFSET_MS = 20; - private final ElidedUrlTextView mUrlTitle; - private final TextView mConnectionSummary; - private final TextView mConnectionMessage; - private final TextView mPerformanceSummary; - private final TextView mPerformanceMessage; - private final TextView mPreviewMessage; - private final TextView mPreviewStaleTimestamp; - private final TextView mPreviewLoadOriginal; - private final TextView mPermissionsTitle; - private final View mPermissionsSeparator; - private final LinearLayout mPermissionsList; - private final View mCookieControlsSeparator; - private final CookieControlsView mCookieControlsView; - private final View mPreviewSeparator; - private final Button mInstantAppButton; - private final Button mSiteSettingsButton; - private final Button mOpenOnlineButton; - private final Runnable mUrlTitleLongClickCallback; + // Shared UI components between PageInfoView and PageInfoViewV2. This list should shrink as + // these components are replaced with different UI and eventually this class will be replaced + // completely. + protected ElidedUrlTextView mUrlTitle; + protected TextView mPreviewMessage; + protected TextView mPreviewStaleTimestamp; + protected TextView mPreviewLoadOriginal; + protected View mPreviewSeparator; + protected Button mInstantAppButton; + protected Button mSiteSettingsButton; + protected Button mOpenOnlineButton; + protected Runnable mUrlTitleLongClickCallback; + protected Runnable mOnUiClosingCallback; + + // Components specific to this PageInfoView + private TextView mConnectionSummary; + private TextView mConnectionMessage; + private TextView mPerformanceSummary; + private TextView mPerformanceMessage; + private TextView mPermissionsTitle; + private View mPermissionsSeparator; + private LinearLayout mPermissionsList; + private View mCookieControlsSeparator; + private CookieControlsView mCookieControlsView; + + public PageInfoView(Context context) { + super(context); + } public PageInfoView(Context context, PageInfoViewParams params) { super(context); - - // Find the container and all it's important subviews. LayoutInflater.from(context).inflate(R.layout.page_info, this, true); - mUrlTitle = findViewById(R.id.page_info_url); - mConnectionSummary = findViewById(R.id.page_info_connection_summary); - mConnectionMessage = findViewById(R.id.page_info_connection_message); - mPerformanceSummary = findViewById(R.id.page_info_performance_summary); - mPerformanceMessage = findViewById(R.id.page_info_performance_message); - mPreviewMessage = findViewById(R.id.page_info_preview_message); - mPreviewStaleTimestamp = findViewById(R.id.page_info_stale_preview_timestamp); - mPreviewLoadOriginal = findViewById(R.id.page_info_preview_load_original); - mPermissionsTitle = findViewById(R.id.page_info_permissions_list_title); - mPermissionsSeparator = findViewById(R.id.page_info_permissions_separator); - mPermissionsList = findViewById(R.id.page_info_permissions_list); - mCookieControlsSeparator = findViewById(R.id.page_info_cookie_controls_separator); - mCookieControlsView = findViewById(R.id.page_info_cookie_controls_view); - mPreviewSeparator = findViewById(R.id.page_info_preview_separator); - mInstantAppButton = findViewById(R.id.page_info_instant_app_button); - mSiteSettingsButton = findViewById(R.id.page_info_site_settings_button); - mOpenOnlineButton = findViewById(R.id.page_info_open_online_button); + init(params); + } + protected void init(PageInfoViewParams params) { + initUrlTitle(params); + initPreview(params); + initConnection(params); + initPerformance(params); + initPermissions(params); + initCookies(params); + initInstantApp(params); + initSiteSettings(params); + initOpenOnline(params); + } + + protected void initUrlTitle(PageInfoViewParams params) { + mUrlTitle = findViewById(R.id.page_info_url); mUrlTitle.setUrl(params.url, params.urlOriginLength); mUrlTitleLongClickCallback = params.urlTitleLongClickCallback; if (params.urlTitleLongClickCallback != null) { mUrlTitle.setOnLongClickListener(this); } - initializePageInfoViewChild( mUrlTitle, params.urlTitleShown, 0f, params.urlTitleClickCallback); - // Hide the connection summary until its text is set. - initializePageInfoViewChild(mConnectionSummary, false, 0f, null); - initializePageInfoViewChild(mConnectionMessage, params.connectionMessageShown, 0f, null); - initializePageInfoViewChild(mPerformanceSummary, false, 0f, null); - initializePageInfoViewChild(mPerformanceMessage, false, 0f, null); - // Hide the permissions list for sites with no permissions. - initializePageInfoViewChild(mPermissionsTitle, false, 0f, null); - initializePageInfoViewChild(mPermissionsSeparator, false, 0f, null); - initializePageInfoViewChild(mPermissionsList, false, 1f, null); - initializePageInfoViewChild(mInstantAppButton, params.instantAppButtonShown, 0f, - params.instantAppButtonClickCallback); - initializePageInfoViewChild(mSiteSettingsButton, params.siteSettingsButtonShown, 0f, - params.siteSettingsButtonClickCallback); - // The open online button should not fade in. - initializePageInfoViewChild(mOpenOnlineButton, params.openOnlineButtonShown, 1f, - params.openOnlineButtonClickCallback); - // Previews UI initialization. + } + + protected void initPreview(PageInfoViewParams params) { + mPreviewMessage = findViewById(R.id.page_info_preview_message); + mPreviewStaleTimestamp = findViewById(R.id.page_info_stale_preview_timestamp); + mPreviewLoadOriginal = findViewById(R.id.page_info_preview_load_original); + mPreviewSeparator = findViewById(R.id.page_info_preview_separator); initializePageInfoViewChild(mPreviewMessage, params.previewUIShown, 0f, null); initializePageInfoViewChild(mPreviewLoadOriginal, params.previewUIShown, 0f, params.previewShowOriginalClickCallback); @@ -280,14 +277,71 @@ if (!TextUtils.isEmpty(params.previewStaleTimestamp)) { mPreviewStaleTimestamp.setText(params.previewStaleTimestamp); } + } + + protected void initConnection(PageInfoViewParams params) { + mConnectionSummary = findViewById(R.id.page_info_connection_summary); + mConnectionMessage = findViewById(R.id.page_info_connection_message); + // Hide the connection summary until its text is set. + initializePageInfoViewChild(mConnectionSummary, false, 0f, null); + initializePageInfoViewChild(mConnectionMessage, params.connectionMessageShown, 0f, null); + } + + protected void initPerformance(PageInfoViewParams params) { + mPerformanceSummary = findViewById(R.id.page_info_performance_summary); + mPerformanceMessage = findViewById(R.id.page_info_performance_message); + initializePageInfoViewChild(mPerformanceSummary, false, 0f, null); + initializePageInfoViewChild(mPerformanceMessage, false, 0f, null); + } + + protected void initPermissions(PageInfoViewParams params) { + mPermissionsTitle = findViewById(R.id.page_info_permissions_list_title); + mPermissionsSeparator = findViewById(R.id.page_info_permissions_separator); + mPermissionsList = findViewById(R.id.page_info_permissions_list); + // Hide the permissions list for sites with no permissions. + initializePageInfoViewChild(mPermissionsTitle, false, 0f, null); + initializePageInfoViewChild(mPermissionsSeparator, false, 0f, null); + initializePageInfoViewChild(mPermissionsList, false, 1f, null); + } + + protected void initCookies(PageInfoViewParams params) { + mCookieControlsSeparator = findViewById(R.id.page_info_cookie_controls_separator); + mCookieControlsView = findViewById(R.id.page_info_cookie_controls_view); initializePageInfoViewChild(mCookieControlsSeparator, params.cookieControlsShown, 0f, null); initializePageInfoViewChild(mCookieControlsView, params.cookieControlsShown, 0f, null); + mOnUiClosingCallback = params.onUiClosingCallback; + } + + protected void initInstantApp(PageInfoViewParams params) { + mInstantAppButton = findViewById(R.id.page_info_instant_app_button); + initializePageInfoViewChild(mInstantAppButton, params.instantAppButtonShown, 0f, + params.instantAppButtonClickCallback); + } + + protected void initSiteSettings(PageInfoViewParams params) { + mSiteSettingsButton = findViewById(R.id.page_info_site_settings_button); + initializePageInfoViewChild(mSiteSettingsButton, params.siteSettingsButtonShown, 0f, + params.siteSettingsButtonClickCallback); + } + + protected void initOpenOnline(PageInfoViewParams params) { + mOpenOnlineButton = findViewById(R.id.page_info_open_online_button); + // The open online button should not fade in. + initializePageInfoViewChild(mOpenOnlineButton, params.openOnlineButtonShown, 1f, + params.openOnlineButtonClickCallback); } public CookieControlsView getCookieControlsView() { return mCookieControlsView; } + // FrameLayout: + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + mOnUiClosingCallback.run(); + } + public void setPermissions(PermissionParams params) { mPermissionsList.removeAllViews(); // If we have at least one permission show the lower permissions area. @@ -354,7 +408,7 @@ return true; } - private void initializePageInfoViewChild( + protected void initializePageInfoViewChild( View child, boolean shown, float alpha, Runnable clickCallback) { // Make all subviews transparent until the page info view is faded in. child.setAlpha(alpha); @@ -401,7 +455,7 @@ /** * Create a list of all the views which we want to individually fade in. */ - private List<View> collectAnimatableViews() { + protected List<View> collectAnimatableViews() { List<View> animatableViews = new ArrayList<>(); animatableViews.add(mUrlTitle); animatableViews.add(mConnectionSummary); @@ -428,7 +482,7 @@ /** * Create an animator to fade an individual dialog element. */ - private Animator createInnerFadeAnimation(final View view, int position, boolean isEnter) { + protected Animator createInnerFadeAnimation(final View view, int position, boolean isEnter) { ObjectAnimator alphaAnim; if (isEnter) { @@ -446,7 +500,7 @@ /** * Create animations for fading the view in/out. */ - private Animator createFadeAnimations(boolean isEnter) { + protected Animator createFadeAnimations(boolean isEnter) { AnimatorSet animation = new AnimatorSet(); AnimatorSet.Builder builder = animation.play(new AnimatorSet());
diff --git a/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoViewV2.java b/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoViewV2.java new file mode 100644 index 0000000..9b580ff --- /dev/null +++ b/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoViewV2.java
@@ -0,0 +1,92 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.components.page_info; + +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.LinearLayout; + +import java.util.Arrays; +import java.util.List; + +/** + * Represents the view inside the second version of the page info popup. + */ +public class PageInfoViewV2 extends PageInfoView { + // Components specific to this PageInfoView + private LinearLayout mRowWrapper; + private PageInfoRowView mConnectionRow; + private PageInfoRowView mPerformanceRow; + private PageInfoRowView mPermissionsRow; + private PageInfoRowView mCookiesRow; + + public PageInfoViewV2(Context context, PageInfoView.PageInfoViewParams params) { + super(context); + LayoutInflater.from(context).inflate(R.layout.page_info_v2, this, true); + init(params); + } + + @Override + protected void init(PageInfoView.PageInfoViewParams params) { + super.init(params); + mRowWrapper = findViewById(R.id.page_info_row_wrapper); + initializePageInfoViewChild(mRowWrapper, true, 0f, null); + } + + @Override + protected void initUrlTitle(PageInfoView.PageInfoViewParams params) { + super.initUrlTitle(params); + // Adjust the mUrlTitle + mUrlTitle.setTextAlignment(View.TEXT_ALIGNMENT_CENTER); + } + + @Override + protected void initConnection(PageInfoView.PageInfoViewParams params) { + mConnectionRow = findViewById(R.id.page_info_connection_row); + } + + @Override + protected void initPerformance(PageInfoView.PageInfoViewParams params) { + mPerformanceRow = findViewById(R.id.page_info_performance_row); + } + + @Override + protected void initPermissions(PageInfoView.PageInfoViewParams params) { + mPermissionsRow = findViewById(R.id.page_info_permissions_row); + } + + @Override + protected void initCookies(PageInfoView.PageInfoViewParams params) { + mCookiesRow = findViewById(R.id.page_info_cookies_row); + mOnUiClosingCallback = params.onUiClosingCallback; + } + + public PageInfoRowView getConnectionRowView() { + return mConnectionRow; + } + + public PageInfoRowView getPerformanceRowView() { + return mPerformanceRow; + } + + public PageInfoRowView getPermissionsRowView() { + return mPermissionsRow; + } + + public PageInfoRowView getCookiesRowView() { + return mCookiesRow; + } + + /** + * Create a list of all the views which we want to individually fade in. + */ + @Override + protected List<View> collectAnimatableViews() { + return Arrays.asList(mUrlTitle, mPreviewMessage, mPreviewStaleTimestamp, + mPreviewLoadOriginal, mPreviewSeparator, mInstantAppButton, mRowWrapper, + mSiteSettingsButton); + } +}
diff --git a/components/page_info/android/page_info_feature_list.cc b/components/page_info/android/page_info_feature_list.cc new file mode 100644 index 0000000..3e1e0a88 --- /dev/null +++ b/components/page_info/android/page_info_feature_list.cc
@@ -0,0 +1,46 @@ +// 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 "base/android/jni_string.h" +#include "base/feature_list.h" +#include "base/stl_util.h" +#include "components/page_info/android/features.h" +#include "components/page_info/android/jni_headers/PageInfoFeatureList_jni.h" + +using base::android::ConvertJavaStringToUTF8; +using base::android::JavaParamRef; + +namespace page_info { + +namespace { + +// Array of features exposed through the Java ContentFeatureList API. Entries in +// this array may either refer to features defined in the header of this file or +// in other locations in the code base (e.g. content_features.h). +const base::Feature* kFeaturesExposedToJava[] = { + &kPageInfoV2, +}; + +// TODO(crbug.com/1060097): Remove this once a generalized FeatureList exists. +const base::Feature* FindFeatureExposedToJava(const std::string& feature_name) { + for (size_t i = 0; i < base::size(kFeaturesExposedToJava); ++i) { + if (kFeaturesExposedToJava[i]->name == feature_name) + return kFeaturesExposedToJava[i]; + } + NOTREACHED() << "Queried feature not found in PageInfoFeatureList: " + << feature_name; + return nullptr; +} + +} // namespace + +static jboolean JNI_PageInfoFeatureList_IsEnabled( + JNIEnv* env, + const JavaParamRef<jstring>& jfeature_name) { + const base::Feature* feature = + FindFeatureExposedToJava(ConvertJavaStringToUTF8(env, jfeature_name)); + return base::FeatureList::IsEnabled(*feature); +} + +} // namespace page_info \ No newline at end of file
diff --git a/components/page_load_metrics/browser/observers/use_counter_page_load_metrics_observer.cc b/components/page_load_metrics/browser/observers/use_counter_page_load_metrics_observer.cc index c11215f..68ed262 100644 --- a/components/page_load_metrics/browser/observers/use_counter_page_load_metrics_observer.cc +++ b/components/page_load_metrics/browser/observers/use_counter_page_load_metrics_observer.cc
@@ -30,17 +30,6 @@ if (ukm_features_recorded->find(static_cast<size_t>(feature)) != ukm_features_recorded->end()) continue; - // TODO(kochi): https://crbug.com/806671 https://843080 - // as ElementCreateShadowRoot is ~8% and - // DocumentRegisterElement is ~5% as of May, 2018, to meet UKM's data - // volume expectation, reduce the data size by sampling. Revisit and - // remove this code once Shadow DOM V0 and Custom Elements V0 are removed. - const int kSamplingFactor = 10; - if ((feature == WebFeature::kElementCreateShadowRoot || - feature == WebFeature::kDocumentRegisterElement) && - base::RandGenerator(kSamplingFactor) != 0) - continue; - ukm::builders::Blink_UseCounter(source_id) .SetFeature(static_cast<size_t>(feature)) .SetIsMainFrameFeature(
diff --git a/components/performance_manager/BUILD.gn b/components/performance_manager/BUILD.gn index fa84be1..8ab786b 100644 --- a/components/performance_manager/BUILD.gn +++ b/components/performance_manager/BUILD.gn
@@ -50,6 +50,7 @@ "graph/page_node_impl_describer.h", "graph/policies/process_priority_policy.cc", "graph/policies/process_priority_policy.h", + "graph/policies/tab_loading_frame_navigation_policy.cc", "graph/process_node.cc", "graph/process_node_impl.cc", "graph/process_node_impl.h", @@ -96,6 +97,7 @@ "public/graph/node_data_describer_util.h", "public/graph/page_node.h", "public/graph/policies/background_tab_loading_policy.h", + "public/graph/policies/tab_loading_frame_navigation_policy.h", "public/graph/process_node.h", "public/graph/system_node.h", "public/graph/worker_node.h", @@ -182,6 +184,7 @@ "graph/node_base_unittest.cc", "graph/page_node_impl_unittest.cc", "graph/policies/process_priority_policy_unittest.cc", + "graph/policies/tab_loading_frame_navigation_policy_unittest.cc", "graph/process_node_impl_unittest.cc", "graph/properties_unittest.cc", "graph/system_node_impl_unittest.cc",
diff --git a/components/performance_manager/DEPS b/components/performance_manager/DEPS index 1e6ba322..528b3ad 100644 --- a/components/performance_manager/DEPS +++ b/components/performance_manager/DEPS
@@ -4,6 +4,7 @@ "+content/public/test", "+content/shell/browser", "+mojo/public", + "+net/base", "+services/metrics/public/cpp", "+services/service_manager/public/cpp", "+third_party/blink/public/mojom/favicon",
diff --git a/components/performance_manager/graph/policies/tab_loading_frame_navigation_policy.cc b/components/performance_manager/graph/policies/tab_loading_frame_navigation_policy.cc new file mode 100644 index 0000000..bfd7d3a --- /dev/null +++ b/components/performance_manager/graph/policies/tab_loading_frame_navigation_policy.cc
@@ -0,0 +1,298 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/performance_manager/public/graph/policies/tab_loading_frame_navigation_policy.h" + +#include "base/bind.h" +#include "base/task/post_task.h" +#include "base/task/task_traits.h" +#include "components/performance_manager/graph/page_node_impl.h" +#include "components/performance_manager/public/performance_manager.h" +#include "content/public/browser/browser_task_traits.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/browser/navigation_handle.h" +#include "content/public/browser/web_contents.h" +#include "net/base/registry_controlled_domains/registry_controlled_domain.h" +#include "url/gurl.h" + +namespace performance_manager { +namespace policies { + +namespace { + +bool CanThrottleUrlScheme(const GURL& url) { + return url.SchemeIs("http") || url.SchemeIs("https"); +} + +} // namespace + +TabLoadingFrameNavigationPolicy::TabLoadingFrameNavigationPolicy( + StopThrottlingCallback stop_throttling_callback) + : stop_throttling_callback_(stop_throttling_callback) { + DCHECK(!stop_throttling_callback.is_null()); +} + +TabLoadingFrameNavigationPolicy::~TabLoadingFrameNavigationPolicy() { + // All timers and timeouts should have been canceled, as no page nodes + // should be actively tracked. + DCHECK(timeouts_.empty()); + DCHECK(!timeout_timer_.IsRunning()); + DCHECK_EQ(base::TimeTicks::Min(), scheduled_timer_); +} + +// static +bool TabLoadingFrameNavigationPolicy::ShouldThrottleWebContents( + content::WebContents* contents) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + + // Don't throttle unless http or https. + bool throttled = true; + const GURL& url = contents->GetLastCommittedURL(); + if (!CanThrottleUrlScheme(url)) + throttled = false; + + // Post a notification to the graph. Even if we're not throttling the + // notification is sent, just in case the WebContents was previously throttled + // and is being reused for a new navigation. This is racy, as the policy + // object can be destroyed while this message is in flight. This is resolved + // on the PM sequence, with the message only being dispatched if the policy + // object exists in the graph. + PerformanceManager::CallOnGraph( + FROM_HERE, + base::BindOnce(&SetPageNodeThrottled, + PerformanceManager::GetPageNodeForWebContents(contents), + throttled)); + + return throttled; +} + +// static +bool TabLoadingFrameNavigationPolicy::ShouldThrottleNavigation( + content::NavigationHandle* handle) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + + // Don't throttle unless http or https. + const GURL& url = handle->GetURL(); + if (!CanThrottleUrlScheme(url)) + return false; + + // Never throttle the main frame. + if (handle->IsInMainFrame()) + return false; + + // Never throttle frames that are navigating to the same eTLD+1 as the main + // frame. + auto* contents = handle->GetWebContents(); + if (net::registry_controlled_domains::SameDomainOrHost( + url, contents->GetLastCommittedURL(), + net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES)) { + return false; + } + + // Throttle any child-frame navigations to a different eTLD+1. + return true; +} + +void TabLoadingFrameNavigationPolicy::OnBeforePageNodeRemoved( + const PageNode* page_node) { + // There's no public graph accessor. We could cache this in OnPassedToGraph, + // but it's reachable this way. + DCHECK(IsRegistered(page_node->GetGraph())); + MaybeErasePageTimeout(page_node); +} + +void TabLoadingFrameNavigationPolicy::OnFirstContentfulPaint( + const FrameNode* frame_node, + base::TimeDelta time_since_navigation_start) { + // There's no public graph accessor. We could cache this in OnPassedToGraph, + // but it's reachable this way. + DCHECK(IsRegistered(frame_node->GetGraph())); + + // We're only interested in current main-frame FCP notifications. + if (!frame_node->IsMainFrame() || !frame_node->IsCurrent()) + return; + + // Wait for another FCP time period, waiting a minimum of 1 second. + double fcp_ms = time_since_navigation_start.InMillisecondsF(); + double delta_ms = std::max(1000.0, fcp_ms); + MaybeUpdatePageTimeout(frame_node->GetPageNode(), + base::TimeDelta::FromMillisecondsD(delta_ms)); +} + +void TabLoadingFrameNavigationPolicy::OnPassedToGraph(Graph* graph) { + DCHECK(NothingRegistered(graph)); + graph->AddFrameNodeObserver(this); + graph->AddPageNodeObserver(this); + graph->RegisterObject(this); +} + +void TabLoadingFrameNavigationPolicy::OnTakenFromGraph(Graph* graph) { + DCHECK(IsRegistered(graph)); + graph->UnregisterObject(this); + graph->RemovePageNodeObserver(this); + graph->RemoveFrameNodeObserver(this); +} + +// static +void TabLoadingFrameNavigationPolicy::SetPageNodeThrottled( + base::WeakPtr<const PageNode> page_node, + bool throttled, + Graph* graph) { + auto* self = GetFromGraph(graph); + if (!self || !page_node) + return; + self->SetPageNodeThrottledImpl(page_node.get(), throttled); +} + +void TabLoadingFrameNavigationPolicy::SetPageNodeThrottledImpl( + const PageNode* page_node, + bool throttled) { + // There's no public graph accessor. We could cache this in OnPassedToGraph, + // but it's reachable this way. + DCHECK(IsRegistered(page_node->GetGraph())); + + // It's possible for WebContents to be reused if a main-frame renavigates. + // On the UI thread a new scheduler object is created in that case, which will + // cause a timeout entry to be (temporarily) orphaned here. So first cleanup + // existing timeouts. + for (size_t i = 0; i < timeouts_.size(); ++i) { + if (timeouts_[i].page_node == page_node) { + timeouts_.erase(i); + break; + } + } + + if (!throttled) { + MaybeUpdateTimeoutTimer(); + return; + } + + // Create a brand new timeout for the page. + // TODO(chrisha): Make this configurable via Finch experiment. + CreatePageTimeout(page_node, timeout_); +} + +void TabLoadingFrameNavigationPolicy::CreatePageTimeout( + const PageNode* page_node, + base::TimeDelta timeout) { +#if DCHECK_IS_ON() + // Sanity check that no timeout entry already exists for this page. + for (const auto& timeout : timeouts_) { + DCHECK_NE(timeout.page_node, page_node); + } +#endif + base::TimeTicks when = base::TimeTicks::Now() + timeout; + timeouts_.insert(Timeout{page_node, when}); + MaybeUpdateTimeoutTimer(); +} + +void TabLoadingFrameNavigationPolicy::MaybeUpdatePageTimeout( + const PageNode* page_node, + base::TimeDelta timeout) { + // Find or create an entry for the given |page_node|. + size_t i = 0; + for (; i < timeouts_.size(); ++i) { + if (timeouts_[i].page_node == page_node) + break; + } + if (i == timeouts_.size()) + return; + + // Update the entry if need be. + base::TimeTicks when = base::TimeTicks::Now() + timeout; + if (when < timeouts_[i].timeout) { + timeouts_.Replace(i, Timeout{page_node, when}); + MaybeUpdateTimeoutTimer(); + } +} + +void TabLoadingFrameNavigationPolicy::MaybeErasePageTimeout( + const PageNode* page_node) { + for (size_t i = 0; i < timeouts_.size(); ++i) { + if (timeouts_[i].page_node == page_node) { + timeouts_.erase(i); + MaybeUpdateTimeoutTimer(); + return; + } + } +} + +void TabLoadingFrameNavigationPolicy::MaybeUpdateTimeoutTimer() { + if (timeouts_.empty()) { + timeout_timer_.Stop(); + scheduled_timer_ = base::TimeTicks::Min(); + return; + } + + if (timeout_timer_.IsRunning()) { + // If the timer is already set to the right time then it doesn't need + // updating. + if (scheduled_timer_ == timeouts_.top().timeout) + return; + + // Otherwise the timer needs rescheduling. + scheduled_timer_ = base::TimeTicks::Min(); + timeout_timer_.Stop(); + } + + // If the next timeout should already have fired, do so synchronously. + base::TimeTicks now = base::TimeTicks::Now(); + base::TimeTicks when = timeouts_.top().timeout; + if (when <= now) { + StopThrottlingExpiredPages(); + + // Early return if there are no remaining timeouts. + if (timeouts_.empty()) + return; + } + + // Restart the timer for the next event. + DCHECK(!timeouts_.empty()); + when = timeouts_.top().timeout; + DCHECK_LT(now, when); + timeout_timer_.Start( + FROM_HERE, when - now, + base::BindOnce(&TabLoadingFrameNavigationPolicy::OnTimeout, + base::Unretained(this))); + scheduled_timer_ = when; +} + +void TabLoadingFrameNavigationPolicy::OnTimeout() { + DCHECK(!timeouts_.empty()); + timeout_timer_.Stop(); + scheduled_timer_ = base::TimeTicks::Min(); + StopThrottlingExpiredPages(); + MaybeUpdateTimeoutTimer(); +} + +void TabLoadingFrameNavigationPolicy::StopThrottlingExpiredPages() { + DCHECK(!timeouts_.empty()); + + // Send notifications for all expired throttles. + auto now = base::TimeTicks::Now(); + while (timeouts_.size() && now >= timeouts_.top().timeout) { + // There's no public graph accessor. We could cache this in OnPassedToGraph, + // but it's reachable this way. + const PageNode* page_node = timeouts_.top().page_node; + DCHECK(IsRegistered(page_node->GetGraph())); + timeouts_.pop(); + + // Post a task to the UI thread to notify the mechanism to stop throttling + // the contents. + base::PostTask( + FROM_HERE, + {content::BrowserThread::UI, base::TaskPriority::USER_VISIBLE}, + base::BindOnce( + [](StopThrottlingCallback stop_throttling_callback, + const WebContentsProxy& proxy) { + auto* contents = proxy.Get(); + if (contents) + stop_throttling_callback.Run(contents); + }, + stop_throttling_callback_, page_node->GetContentsProxy())); + } +} + +} // namespace policies +} // namespace performance_manager
diff --git a/components/performance_manager/graph/policies/tab_loading_frame_navigation_policy_unittest.cc b/components/performance_manager/graph/policies/tab_loading_frame_navigation_policy_unittest.cc new file mode 100644 index 0000000..ccb6bdc --- /dev/null +++ b/components/performance_manager/graph/policies/tab_loading_frame_navigation_policy_unittest.cc
@@ -0,0 +1,317 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/performance_manager/public/graph/policies/tab_loading_frame_navigation_policy.h" + +#include "base/bind.h" +#include "base/task/post_task.h" +#include "base/task/task_traits.h" +#include "base/test/bind_test_util.h" +#include "base/test/task_environment.h" +#include "components/performance_manager/public/performance_manager.h" +#include "components/performance_manager/test_support/performance_manager_test_harness.h" +#include "content/public/browser/browser_task_traits.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/browser/web_contents.h" +#include "content/public/test/mock_navigation_handle.h" +#include "content/public/test/navigation_simulator.h" +#include "content/public/test/test_renderer_host.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace performance_manager { +namespace policies { + +namespace { + +class TabLoadingFrameNavigationPolicyTest + : public PerformanceManagerTestHarness { + public: + TabLoadingFrameNavigationPolicyTest() + : PerformanceManagerTestHarness( + base::test::TaskEnvironment::TimeSource::MOCK_TIME) {} + TabLoadingFrameNavigationPolicyTest( + const TabLoadingFrameNavigationPolicyTest&) = delete; + TabLoadingFrameNavigationPolicyTest& operator=( + const TabLoadingFrameNavigationPolicyTest&) = delete; + ~TabLoadingFrameNavigationPolicyTest() override = default; + + void SetUp() override { + PerformanceManagerTestHarness::SetUp(); + + // The unittest fixture outlives the graph under test, so passing an + // unretained pointer is safe. + auto callback = base::BindRepeating( + &TabLoadingFrameNavigationPolicyTest::OnStopThrottlingWrapper, + base::Unretained(this)); + + // Create the policy object and inject it into the graph. + std::unique_ptr<TabLoadingFrameNavigationPolicy> policy = + std::make_unique<TabLoadingFrameNavigationPolicy>(callback); + policy_ = policy.get(); + PerformanceManager::PassToGraph(FROM_HERE, std::move(policy)); + + // Ensure that the policy default initializes with no throttles in place. + ExpectThrottledPageCount(0); + start_ = task_environment()->GetMockTickClock()->NowTicks(); + } + + void RunUntilStopThrottling() { + base::RunLoop run_loop; + quit_closure_ = run_loop.QuitClosure(); + run_loop.Run(); + quit_closure_.Reset(); + } + + void ExpectThrottledPageCount(size_t expected_throttled_page_count) { + base::RunLoop run_loop; + + // This will be called back on the UI thread once the throttled page count + // has been retrieved from the PM and validated. + auto on_ui_thread = base::BindLambdaForTesting( + [expected_throttled_page_count, &run_loop](size_t throttled_page_count, + bool timer_running) { + EXPECT_EQ(expected_throttled_page_count, throttled_page_count); + EXPECT_EQ(expected_throttled_page_count > 0, timer_running); + run_loop.Quit(); + }); + + // Call into the graph to get the throttled page count, bounce back to + // the UI thread, then continue. + auto* policy = policy_; + PerformanceManager::CallOnGraph( + FROM_HERE, + base::BindLambdaForTesting([policy, on_ui_thread](Graph* graph_unused) { + size_t throttled_page_count = + policy->GetThrottledPageCountForTesting(); + bool timer_running = policy->IsTimerRunningForTesting(); + + // Post back to the UI thread with the answer, where it will be + // validated and the run loop exited. + base::PostTask(FROM_HERE, {content::BrowserThread::UI}, + base::BindOnce(on_ui_thread, throttled_page_count, + timer_running)); + })); + + // Wait for the response from the graph. + run_loop.Run(); + } + + // Invoked by the policy when throttling should stop for a given contents. + MOCK_METHOD1(OnStopThrottling, void(content::WebContents*)); + + // Accessors. + TabLoadingFrameNavigationPolicy* policy() const { return policy_; } + base::TimeTicks start() const { return start_; } + + // The current time, expressed as a multiple of the timeout period. + double GetRelativeTime() { + base::TimeTicks now = task_environment()->GetMockTickClock()->NowTicks(); + base::TimeDelta elapsed = now - start_; + double relative = + elapsed.InSecondsF() / policy_->GetTimeoutForTesting().InSecondsF(); + return relative; + } + + private: + void OnStopThrottlingWrapper(content::WebContents* contents) { + OnStopThrottling(contents); + + // Time can be manually advanced as well, so we're not always in a RunLoop. + // Only try to invoke the quit closure if it has been set. + if (!quit_closure_.is_null()) + quit_closure_.Run(); + } + + // This is graph owned. + TabLoadingFrameNavigationPolicy* policy_ = nullptr; + base::RepeatingClosure quit_closure_; + base::TimeTicks start_; +}; + +} // namespace + +TEST_F(TabLoadingFrameNavigationPolicyTest, OnlyHttpContentsThrottled) { + // Only contents with http(s) URLs should be throttled. Anything like + // data://, file://, chrome:// or about:// should be ignored. + + // Set the active contents in the RenderViewHostTestHarness. + SetContents(CreateTestWebContents()); + + { + // Expect https:// contents to be throttled. + SCOPED_TRACE("https"); + content::NavigationSimulator::NavigateAndCommitFromBrowser( + web_contents(), GURL("https://www.foo.com/")); + EXPECT_TRUE(policy()->ShouldThrottleWebContents(web_contents())); + ExpectThrottledPageCount(1); + } + + { + // Expect http:// contents to be throttled. + SCOPED_TRACE("http"); + content::NavigationSimulator::NavigateAndCommitFromBrowser( + web_contents(), GURL("http://www.bar.com/")); + EXPECT_TRUE(policy()->ShouldThrottleWebContents(web_contents())); + ExpectThrottledPageCount(1); + } + + { + // Expect chrome:// contents not to be throttled. + SCOPED_TRACE("chrome"); + content::NavigationSimulator::NavigateAndCommitFromBrowser( + web_contents(), GURL("chrome://settings/")); + EXPECT_FALSE(policy()->ShouldThrottleWebContents(web_contents())); + ExpectThrottledPageCount(0); + } + + { + // Expect file:// contents not to be throttled. + SCOPED_TRACE("file"); + content::NavigationSimulator::NavigateAndCommitFromBrowser( + web_contents(), GURL("file:///home/chrome/foo.txt")); + EXPECT_FALSE(policy()->ShouldThrottleWebContents(web_contents())); + ExpectThrottledPageCount(0); + } + + { + // Expect about:// contents not to be throttled. + SCOPED_TRACE("about"); + content::NavigationSimulator::NavigateAndCommitFromBrowser( + web_contents(), GURL("about://blank")); + EXPECT_FALSE(policy()->ShouldThrottleWebContents(web_contents())); + ExpectThrottledPageCount(0); + } + + { + // Expect data:// contents not to be throttled. + SCOPED_TRACE("data"); + content::NavigationSimulator::NavigateAndCommitFromBrowser( + web_contents(), GURL("data:,Hello%2C%20World!")); + EXPECT_FALSE(policy()->ShouldThrottleWebContents(web_contents())); + ExpectThrottledPageCount(0); + } +} + +TEST_F(TabLoadingFrameNavigationPolicyTest, + OnlyAppropriateChildFramesThrottled) { + SetContents(CreateTestWebContents()); + content::NavigationSimulator::NavigateAndCommitFromBrowser( + web_contents(), GURL("https://www.foo.com/")); + + auto* main_frame = web_contents()->GetMainFrame(); + + // Create a child to the exact same domain. It should not be throttled. + auto* child1 = + content::RenderFrameHostTester::For(main_frame)->AppendChild("child1"); + content::MockNavigationHandle handle1(GURL("https://www.foo.com/foo.html"), + child1); + EXPECT_FALSE(policy()->ShouldThrottleNavigation(&handle1)); + + // Create a child to the the same eTLD+1. + auto* child2 = + content::RenderFrameHostTester::For(main_frame)->AppendChild("child2"); + content::MockNavigationHandle handle2(GURL("https://static.foo.com/foo.html"), + child2); + EXPECT_FALSE(policy()->ShouldThrottleNavigation(&handle2)); + + // Create a child to a completely different domain. It should be throttled. + auto* child3 = + content::RenderFrameHostTester::For(main_frame)->AppendChild("child3"); + content::MockNavigationHandle handle3(GURL("https://bar.com"), child3); + EXPECT_TRUE(policy()->ShouldThrottleNavigation(&handle3)); + + // Create a child to a non-HTTP(s) protocol. It should not be throttled. + auto* child4 = + content::RenderFrameHostTester::For(main_frame)->AppendChild("child4"); + content::MockNavigationHandle handle4(GURL("data:,Hello%2C%20World!"), + child4); + EXPECT_FALSE(policy()->ShouldThrottleNavigation(&handle4)); +} + +TEST_F(TabLoadingFrameNavigationPolicyTest, TimeoutWorks) { + // We express times in this test as fractions of a "timeout" period, which + // we'll call T. At the beginning of the test, we are at start() == 0. + ASSERT_EQ(0.0, GetRelativeTime()); + + // Navigate and throttle a first contents. It will expire at time T. + std::unique_ptr<content::WebContents> contents1 = CreateTestWebContents(); + content::NavigationSimulator::NavigateAndCommitFromBrowser( + contents1.get(), GURL("http://www.foo1.com/")); + EXPECT_TRUE(policy()->ShouldThrottleWebContents(contents1.get())); + ExpectThrottledPageCount(1); + + // We expect to still be at time 0. + ASSERT_EQ(0.0, GetRelativeTime()); + + // Advance time by half of a timeout. No callbacks should fire. + task_environment()->FastForwardBy(policy()->GetTimeoutForTesting() * 0.5); + testing::Mock::VerifyAndClearExpectations(this); + + // We are now at time T / 2. + ASSERT_EQ(0.5, GetRelativeTime()); + + // Navigate and throttle a second contents. It will expire at 1.5 T. + std::unique_ptr<content::WebContents> contents2 = CreateTestWebContents(); + content::NavigationSimulator::NavigateAndCommitFromBrowser( + contents2.get(), GURL("https://www.foo2.com/")); + EXPECT_TRUE(policy()->ShouldThrottleWebContents(contents2.get())); + ExpectThrottledPageCount(2); + + // Run until the first contents times out. + EXPECT_CALL(*this, OnStopThrottling(contents1.get())); + RunUntilStopThrottling(); + ExpectThrottledPageCount(1); + base::TimeTicks stop1 = task_environment()->GetMockTickClock()->NowTicks(); + EXPECT_EQ(policy()->GetTimeoutForTesting(), stop1 - start()); + + // We are now at time T. + ASSERT_EQ(1.0, GetRelativeTime()); + + // Navigate and throttle a third contents. It will expire at time 2 T. + std::unique_ptr<content::WebContents> contents3 = CreateTestWebContents(); + content::NavigationSimulator::NavigateAndCommitFromBrowser( + contents3.get(), GURL("https://www.foo3.com/")); + EXPECT_TRUE(policy()->ShouldThrottleWebContents(contents3.get())); + ExpectThrottledPageCount(2); + + // Advance time by a quarter of the timeout period, bringing us to time + // 1.25 T. This means there will be 1/4 of the timeout left on the second as + // it expires at 1.5 T. + task_environment()->FastForwardBy(policy()->GetTimeoutForTesting() * 0.25); + testing::Mock::VerifyAndClearExpectations(this); + ExpectThrottledPageCount(2); + + // We are now at time 1.25 T. + ASSERT_EQ(1.25, GetRelativeTime()); + + // Close the 2nd contents before the timeout expires, and expect the throttled + // count to drop. Now the timer should be running for the 3rd contents. + contents2.reset(); + ExpectThrottledPageCount(1); + + // We are still at time 1.25 T. + ASSERT_EQ(1.25, GetRelativeTime()); + + // Advance time to a time past when the second notification *would* have + // expired, and expect no notifications. We'll go to 1.6 T, so 0.35 T further. + task_environment()->FastForwardBy(policy()->GetTimeoutForTesting() * 0.35); + testing::Mock::VerifyAndClearExpectations(this); + + // We are now at time 1.6 T. + ASSERT_EQ(1.6, GetRelativeTime()); + + // Finally, run until the third contents times out. + EXPECT_CALL(*this, OnStopThrottling(contents3.get())); + RunUntilStopThrottling(); + ExpectThrottledPageCount(0); + base::TimeTicks stop3 = task_environment()->GetMockTickClock()->NowTicks(); + EXPECT_EQ(policy()->GetTimeoutForTesting(), stop3 - stop1); + + // We are now at time 2 T. + ASSERT_EQ(2.0, GetRelativeTime()); +} + +} // namespace policies +} // namespace performance_manager
diff --git a/components/performance_manager/public/graph/policies/tab_loading_frame_navigation_policy.h b/components/performance_manager/public/graph/policies/tab_loading_frame_navigation_policy.h new file mode 100644 index 0000000..ffe9fc9 --- /dev/null +++ b/components/performance_manager/public/graph/policies/tab_loading_frame_navigation_policy.h
@@ -0,0 +1,170 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_GRAPH_POLICIES_TAB_LOADING_FRAME_NAVIGATION_POLICY_H_ +#define COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_GRAPH_POLICIES_TAB_LOADING_FRAME_NAVIGATION_POLICY_H_ + +#include "base/callback.h" +#include "base/containers/intrusive_heap.h" +#include "base/time/time.h" +#include "base/timer/timer.h" +#include "components/performance_manager/public/graph/frame_node.h" +#include "components/performance_manager/public/graph/graph.h" +#include "components/performance_manager/public/graph/graph_registered.h" +#include "components/performance_manager/public/graph/page_node.h" + +namespace content { +class WebContents; +class NavigationHandle; +} // namespace content + +namespace performance_manager { +namespace policies { + +// The policy half of the TabLoadingFrameNavigation system. The policy engine +// is responsible for deciding which WebContents will be throttled, and within +// a WebContents, which frames. Since the decision has to be made synchronously +// on the UI thread before the PM counterparts exist, this policy exposes +// helper functions for "pulling" those decisions from the policy engine, rather +// than having them "pushed" to the mechanism. Once throttling has started the +// subsequent policy decision of when to stop throttling is pushed to the +// mechanism as is more typical. +// +// At this moment the policy is the following: +// +// - Only pages using http or https are throttled. +// - Main frames are never throttled. +// - Child frames with the same eTLD+1 as the main frame are not throttled. +// - All other frames are throttled. +// - Throttling continues until the main frame hits hits LargestContentfulPaint. +// Unfortunately, we can't know LCP in real time, so we use +// 2 x FirstContentfulPaint as an estimate, with an upper bound of the UMA +// measures 95th %ile of LCP. +// +// See design document: +// +// https://docs.google.com/document/d/141gYr7s2m0rPgzDxzAN0PDMtwT2diHEaa7-sZ0V_Q_M/edit#heading=h.7nki9mck5t64 +class TabLoadingFrameNavigationPolicy + : public FrameNode::ObserverDefaultImpl, + public GraphOwned, + public GraphRegisteredImpl<TabLoadingFrameNavigationPolicy>, + public PageNode::ObserverDefaultImpl { + public: + using StopThrottlingCallback = + base::RepeatingCallback<void(content::WebContents*)>; + + // The |stop_throttling_callback| is used to inform the mechanism of when + // navigation throttles applied to a WebContents can be released. + explicit TabLoadingFrameNavigationPolicy( + StopThrottlingCallback stop_throttling_callback); + ~TabLoadingFrameNavigationPolicy() override; + + // Exposes policy decisions to the scheduler. This must be called on the UI + // thread. If this returns true it is assumed that the |contents| is being + // actively scheduled by the corresponding mechanism. + static bool ShouldThrottleWebContents(content::WebContents* contents); + + // Exposes policy decisions to the scheduler. This must be called on the UI + // thread. If this returns true it is assumed that the |handle| will have a + // throttle applies by the corresponding mechanism. + static bool ShouldThrottleNavigation(content::NavigationHandle* handle); + + // Exposed for testing. Only safe to call on the PM thread. + size_t GetThrottledPageCountForTesting() const { return timeouts_.size(); } + bool IsTimerRunningForTesting() const { return timeout_timer_.IsRunning(); } + + // Exposed for testing. Can be called on any sequence, as this is initialized + // at construction and stays constant afterwards. + base::TimeDelta GetTimeoutForTesting() const { return timeout_; } + + private: + // PageNodeObserver: + void OnBeforePageNodeRemoved(const PageNode* page_node) override; + + // FrameNodeObserver: + void OnFirstContentfulPaint( + const FrameNode* frame_node, + base::TimeDelta time_since_navigation_start) override; + + // GraphOwned: + void OnPassedToGraph(Graph* graph) override; + void OnTakenFromGraph(Graph* graph) override; + + // Invoked by ShouldThrottleWebContents logic. + static void SetPageNodeThrottled(base::WeakPtr<const PageNode> page_node, + bool throttled, + Graph* graph); + void SetPageNodeThrottledImpl(const PageNode* page_node, bool throttled); + + // Creates a new page timeout. An entry for |page_node| must not already + // exist. + void CreatePageTimeout(const PageNode* page_node, base::TimeDelta timeout); + + // Updates the entry for |page_node| if it exists and is for a time later than + // |timeout|. Otherwise, does nothing. + void MaybeUpdatePageTimeout(const PageNode* page_node, + base::TimeDelta timeout); + + // Erases the entry for |page_node| if it exists. + void MaybeErasePageTimeout(const PageNode* page_node); + + // Updates the |timeout_timer_| to reflect the current top of the |timeouts_| + // min-heap, or stopping the timer if the heap is empty. + void MaybeUpdateTimeoutTimer(); + + // Called by the |timeout_timer_| when it fires. This will fire notifications + // to the WebContents-affiliated scheduler objects on the UI thread, and then + // reschedule a new timer. + void OnTimeout(); + + // Dispatches StopThrottling notifications for all pages that are currently + // expired. + void StopThrottlingExpiredPages(); + + // A heap of all page nodes that are currently being throttled, sorted + // by the time the throttling will timeout. This is intrusive because pages + // can be removed before popping out of the heap naturally. + struct Timeout { + const PageNode* page_node; + base::TimeTicks timeout; + + // Reverse the comparison operator so this is a min-heap. + bool operator<(const Timeout& rhs) const { return timeout > rhs.timeout; } + + // Dummy implementation of the IntrusiveHeap API. We don't need external + // handles into the heap, as we simply look up elements directly and update + // them in place. + void SetHeapHandle(base::HeapHandle) {} + void ClearHeapHandle() {} + base::HeapHandle GetHeapHandle() const { + return base::HeapHandle::Invalid(); + } + }; + base::IntrusiveHeap<Timeout> timeouts_; + + // The timeout after which throttling is stopped. This defaults to the 99th + // %ile of LargestContentfulPaint (LCP). + // TODO(chrisha): Make this Finch configurable. + const base::TimeDelta timeout_ = base::TimeDelta::FromSeconds(40); + + // A one shot timer that is used to timeout existing throttles. This will be + // running whenever |timeouts_| is not empty. + base::OneShotTimer timeout_timer_; + + // The time that has been set using |timeout_timer_|. When |timeouts_| is + // empty this is set to "base::TimeTicks::Min()". This is used to know if the + // current running timer is okay, or if a new timer is needed (helps to + // minimize abandoned timer tasks). We would use + // timeout_timer_.desired_run_time(), but this isn't precise. + base::TimeTicks scheduled_timer_ = base::TimeTicks::Min(); + + // The callback that is invoked to inform the mechanism that throttling should + // stop. + StopThrottlingCallback stop_throttling_callback_; +}; + +} // namespace policies +} // namespace performance_manager + +#endif // COMPONENTS_PERFORMANCE_MANAGER_GRAPH_POLICIES_TAB_LOADING_FRAME_NAVIGATION_POLICY_H_ \ No newline at end of file
diff --git a/components/performance_manager/test_support/performance_manager_test_harness.cc b/components/performance_manager/test_support/performance_manager_test_harness.cc index 1db3215..36b274c 100644 --- a/components/performance_manager/test_support/performance_manager_test_harness.cc +++ b/components/performance_manager/test_support/performance_manager_test_harness.cc
@@ -8,14 +8,13 @@ namespace performance_manager { -PerformanceManagerTestHarness::PerformanceManagerTestHarness() { - helper_ = std::make_unique<PerformanceManagerTestHarnessHelper>(); -} +PerformanceManagerTestHarness::PerformanceManagerTestHarness() = default; PerformanceManagerTestHarness::~PerformanceManagerTestHarness() = default; void PerformanceManagerTestHarness::SetUp() { Super::SetUp(); + helper_ = std::make_unique<PerformanceManagerTestHarnessHelper>(); helper_->SetUp(); }
diff --git a/components/performance_manager/test_support/performance_manager_test_harness.h b/components/performance_manager/test_support/performance_manager_test_harness.h index 3ca097f..d4aa42c 100644 --- a/components/performance_manager/test_support/performance_manager_test_harness.h +++ b/components/performance_manager/test_support/performance_manager_test_harness.h
@@ -13,14 +13,23 @@ // A test harness that initializes PerformanceManagerImpl, plus the entire // RenderViewHost harness. Allows for creating full WebContents, and their // accompanying structures in the graph. The task environment is accessed -// via content::RenderViewHostTestHarness::test_bundle(). RenderFrameHosts and -// such are not created, so this is suitable for unittests but not browsertests. +// via content::RenderViewHostTestHarness::task_environment(). RenderFrameHosts +// and such are not created, so this is suitable for unittests but not +// browsertests. class PerformanceManagerTestHarness : public content::RenderViewHostTestHarness { public: using Super = content::RenderViewHostTestHarness; PerformanceManagerTestHarness(); + + // Constructs a PerformanceManagerTestHarness which uses |traits| to + // initialize its BrowserTaskEnvironment. + template <typename... TaskEnvironmentTraits> + explicit PerformanceManagerTestHarness(TaskEnvironmentTraits&&... traits) + : RenderViewHostTestHarness( + std::forward<TaskEnvironmentTraits>(traits)...) {} + PerformanceManagerTestHarness(const PerformanceManagerTestHarness&) = delete; PerformanceManagerTestHarness& operator=( const PerformanceManagerTestHarness&) = delete;
diff --git a/components/policy/core/common/BUILD.gn b/components/policy/core/common/BUILD.gn index e5b7fe4a..9c0ac07 100644 --- a/components/policy/core/common/BUILD.gn +++ b/components/policy/core/common/BUILD.gn
@@ -406,6 +406,16 @@ "cloud/user_cloud_policy_store_unittest.cc", ] } + + if (is_fuchsia) { + sources -= [ + "cloud/cloud_policy_manager_unittest.cc", + "cloud/cloud_policy_validator_unittest.cc", + "cloud/machine_level_user_cloud_policy_store_unittest.cc", + "cloud/user_cloud_policy_store_unittest.cc", + ] + } + if (!is_android) { sources += [ "async_policy_provider_unittest.cc" ] }
diff --git a/components/policy/resources/policy_templates.json b/components/policy/resources/policy_templates.json index b4f165b..790ab330 100644 --- a/components/policy/resources/policy_templates.json +++ b/components/policy/resources/policy_templates.json
@@ -14601,7 +14601,7 @@ { 'name': 'MinimumChromeVersionEnforced', 'owners': ['snijhara@google.com'], - 'supported_on': ['chrome_os:84-'], + 'supported_on': ['chrome_os:85-'], 'future': True, 'device_only': True, 'type': 'dict', @@ -18270,24 +18270,17 @@ 'owners': ['services/network/OWNERS'], 'type': 'main', 'schema': { 'type': 'boolean' }, - 'supported_on': ['chrome.win:72-'], + 'supported_on': ['chrome.win:72-83'], 'features': { 'dynamic_refresh': False, 'per_profile': False, }, + 'deprecated': True, 'example_value': False, 'id': 521, 'caption': '''Force networking code to run in the browser process''', 'tags': [], - 'desc': '''This policy forces networking code to run in the browser process. - - This policy is disabled by default, and if enabled, leaves users open to the security issues once the networking process is sandboxed. - - This policy is intended to give enterprises a chance to migrate to 3rd party software that does not depend on hooking the networking APIs. Proxy servers are recommended over LSPs and Win32 API patching. - - If this policy is not set, networking code will run out of the browser process by default. - - This policy will be removed in <ph name="PRODUCT_NAME">$1<ex>Google Chrome</ex></ph> version 84.''', + 'desc': '''This policy is deprecated.''', }, { 'name': 'VoiceInteractionContextEnabled',
diff --git a/components/policy/tools/generate_policy_source.py b/components/policy/tools/generate_policy_source.py index 912917d..91cad02 100755 --- a/components/policy/tools/generate_policy_source.py +++ b/components/policy/tools/generate_policy_source.py
@@ -7,7 +7,7 @@ Pass at least: --chrome-version-file <path to src/chrome/VERSION> or --all-chrome-versions --target-platform <which platform the target code will be generated for and can - be one of (win, mac, linux, chromeos, fuchsia, ios)> + be one of (win, mac, linux, chromeos, ios)> --policy_templates <path to the policy_templates.json input file>.''' @@ -96,7 +96,6 @@ 'chrome.win', 'chrome.linux', 'chrome.mac', - 'chrome.fuchsia', 'chrome.*', 'chrome.win7', ]: @@ -119,7 +118,7 @@ if platform.startswith('chrome.'): platform_sub = platform[7:] if platform_sub == '*': - self.platforms.extend(['win', 'mac', 'linux', 'fuchsia']) + self.platforms.extend(['win', 'mac', 'linux']) elif platform_sub == 'win7': self.platforms.append('win') else: @@ -1024,24 +1023,25 @@ def _WritePolicyConstantSource(policies, policy_atomic_groups, target_platform, f, risk_tags): - f.write('#include "components/policy/policy_constants.h"\n' - '\n' - '#include <algorithm>\n' - '#include <climits>\n' - '#include <memory>\n' - '\n' - '#include "base/logging.h"\n' - '#include "base/stl_util.h" // base::size()\n' - '#include "build/branding_buildflags.h"\n' - '#include "components/policy/core/common/policy_types.h"\n' - '#include "components/policy/core/common/schema_internal.h"\n' - '#include "components/policy/proto/cloud_policy.pb.h"\n' - '#include "components/policy/risk_tag.h"\n' - '\n' - 'namespace em = enterprise_management;\n\n' - '\n' - 'namespace policy {\n' - '\n') + f.write('''#include "components/policy/policy_constants.h" + +#include <algorithm> +#include <climits> +#include <memory> + +#include "base/logging.h" +#include "base/stl_util.h" // base::size() +#include "build/branding_buildflags.h" +#include "components/policy/core/common/policy_types.h" +#include "components/policy/core/common/schema_internal.h" +#include "components/policy/proto/cloud_policy.pb.h" +#include "components/policy/risk_tag.h" + +namespace em = enterprise_management; + +namespace policy { + +''') # Generate the Chrome schema. chrome_schema = { @@ -1065,8 +1065,12 @@ # Chrome schema, so that binary searching in the PropertyNode array gets the # right index on this array as well. See the implementation of # GetChromePolicyDetails() below. - f.write('const PolicyDetails kChromePolicyDetails[] = {\n' - '// is_deprecated is_device_policy id max_external_data_size\n') + # TODO(crbug.com/1074336): kChromePolicyDetails shouldn't be declare if there + # is no policy. + f.write( + '''const __attribute__((unused)) PolicyDetails kChromePolicyDetails[] = { +// is_deprecated is_device_policy id max_external_data_size +''') for policy in policies: if policy.is_supported: assert policy.id >= MIN_POLICY_ID and policy.id <= MAX_POLICY_ID @@ -1094,14 +1098,17 @@ schema_generator.FindSensitiveChildren() schema_generator.Write(f) - f.write('\n' 'namespace {\n') + f.write('\n') - f.write('bool CompareKeys(const internal::PropertyNode& node,\n' - ' const std::string& key) {\n' - ' return node.key < key;\n' - '}\n\n') + if schema_generator.property_nodes: + f.write('namespace {\n') - f.write('} // namespace\n\n') + f.write('bool CompareKeys(const internal::PropertyNode& node,\n' + ' const std::string& key) {\n' + ' return node.key < key;\n' + '}\n\n') + + f.write('} // namespace\n\n') if target_platform == 'win': f.write('#if BUILDFLAG(GOOGLE_CHROME_BRANDING)\n' @@ -1148,34 +1155,38 @@ f.write('}\n' '#endif\n\n') f.write('const PolicyDetails* GetChromePolicyDetails(' - 'const std::string& policy) {\n' - ' // First index in kPropertyNodes of the Chrome policies.\n' - ' static const int begin_index = %s;\n' - ' // One-past-the-end of the Chrome policies in kPropertyNodes.\n' - ' static const int end_index = %s;\n' % - (schema_generator.root_properties_begin, - schema_generator.root_properties_end)) - f.write(' const internal::PropertyNode* begin =\n' - ' kPropertyNodes + begin_index;\n' - ' const internal::PropertyNode* end = kPropertyNodes + end_index;\n' - ' const internal::PropertyNode* it =\n' - ' std::lower_bound(begin, end, policy, CompareKeys);\n' - ' if (it == end || it->key != policy)\n' - ' return NULL;\n' - ' // This relies on kPropertyNodes from begin_index to end_index\n' - ' // having exactly the same policies (and in the same order) as\n' - ' // kChromePolicyDetails, so that binary searching on the first\n' - ' // gets the same results as a binary search on the second would.\n' - ' // However, kPropertyNodes has the policy names and\n' - ' // kChromePolicyDetails doesn\'t, so we obtain the index into\n' - ' // the second array by searching the first to avoid duplicating\n' - ' // the policy name pointers.\n' - ' // Offsetting |it| from |begin| here obtains the index we\'re\n' - ' // looking for.\n' - ' size_t index = it - begin;\n' - ' CHECK_LT(index, base::size(kChromePolicyDetails));\n' - ' return kChromePolicyDetails + index;\n' - '}\n\n') + 'const std::string& policy) {\n') + if schema_generator.property_nodes: + f.write(' // First index in kPropertyNodes of the Chrome policies.\n' + ' static const int begin_index = %s;\n' + ' // One-past-the-end of the Chrome policies in kPropertyNodes.\n' + ' static const int end_index = %s;\n' % + (schema_generator.root_properties_begin, + schema_generator.root_properties_end)) + f.write(''' const internal::PropertyNode* begin = + kPropertyNodes + begin_index; + const internal::PropertyNode* end = kPropertyNodes + end_index; + const internal::PropertyNode* it = + std::lower_bound(begin, end, policy, CompareKeys); + if (it == end || it->key != policy) + return nullptr; + // This relies on kPropertyNodes from begin_index to end_index + // having exactly the same policies (and in the same order) as + // kChromePolicyDetails, so that binary searching on the first + // gets the same results as a binary search on the second would. + // However, kPropertyNodes has the policy names and + // kChromePolicyDetails doesn't, so we obtain the index into + // the second array by searching the first to avoid duplicating + // the policy name pointers. + // Offsetting |it| from |begin| here obtains the index we're + // looking for. + size_t index = it - begin; + CHECK_LT(index, base::size(kChromePolicyDetails)); + return kChromePolicyDetails + index; +''') + else: + f.write('return nullptr;') + f.write('}\n\n') f.write('namespace key {\n\n') for policy in policies: @@ -1313,27 +1324,27 @@ def _WritePolicyRiskTagHeader(policies, policy_atomic_groups, target_platform, f, risk_tags): - f.write('#ifndef CHROME_COMMON_POLICY_RISK_TAG_H_\n' - '#define CHROME_COMMON_POLICY_RISK_TAG_H_\n' - '\n' - '#include <stddef.h>\n' - '\n' - 'namespace policy {\n' - '\n' + - '// The tag of a policy indicates which impact a policy can have on\n' - '// a user\'s privacy and/or security. Ordered descending by \n' - '// impact.\n' - '// The explanation of the single tags is stated in\n' - '// policy_templates.json within the \'risk_tag_definitions\' tag.' - '\n' + risk_tags.GenerateEnum() + '\n' - '// This constant describes how many risk tags were used by the\n' - '// policy which uses the most risk tags. \n' + f.write('''#ifndef CHROME_COMMON_POLICY_RISK_TAG_H_ +#define CHROME_COMMON_POLICY_RISK_TAG_H_ + +#include <stddef.h> + +namespace policy { + +// The tag of a policy indicates which impact a policy can have on +// a user's privacy and/or security. Ordered descending by +// impact. +// The explanation of the single tags is stated in +// policy_templates.json within the 'risk_tag_definitions' tag. +''') + f.write(risk_tags.GenerateEnum() + '\n') + f.write('// This constant describes how many risk tags were used by the\n' + '// policy which uses the most risk tags.\n' 'const size_t kMaxRiskTagCount = ' + risk_tags.GetMaxTags() + ';\n' '\n' - '} // namespace policy\n' + '} // namespace policy\n\n' '\n' - '#endif // CHROME_COMMON_POLICY_RISK_TAG_H_' - '\n') + '#endif // CHROME_COMMON_POLICY_RISK_TAG_H_') #------------------ policy protobufs -------------------------------# @@ -1511,7 +1522,7 @@ # Returns the set of all policy.policy_protobuf_type strings from |policies|. def _GetProtobufTypes(policies): - return set(policy.policy_protobuf_type for policy in policies) + return set(['Integer', 'Boolean', 'String', 'StringList']) # Writes the definition of an array that contains the pointers to the mutable
diff --git a/components/printing/renderer/print_render_frame_helper.cc b/components/printing/renderer/print_render_frame_helper.cc index d82ca3d..690c362 100644 --- a/components/printing/renderer/print_render_frame_helper.cc +++ b/components/printing/renderer/print_render_frame_helper.cc
@@ -63,6 +63,7 @@ #include "third_party/blink/public/web/web_plugin.h" #include "third_party/blink/public/web/web_plugin_container.h" #include "third_party/blink/public/web/web_plugin_document.h" +#include "third_party/blink/public/web/web_print_page_description.h" #include "third_party/blink/public/web/web_print_params.h" #include "third_party/blink/public/web/web_print_preset_options.h" #include "third_party/blink/public/web/web_script_source.h" @@ -151,32 +152,31 @@ PrintMsg_Print_Params page_css_params = page_params; int dpi = GetDPI(page_params); - blink::WebDoubleSize page_size_in_pixels( + blink::WebPrintPageDescription description; + description.size = blink::WebDoubleSize( ConvertUnitDouble(page_params.page_size.width(), dpi, kPixelsPerInch), ConvertUnitDouble(page_params.page_size.height(), dpi, kPixelsPerInch)); - int margin_top_in_pixels = + description.margin_top = ConvertUnit(page_params.margin_top, dpi, kPixelsPerInch); - int margin_right_in_pixels = ConvertUnit( - page_params.page_size.width() - page_params.content_size.width() - - page_params.margin_left, - dpi, kPixelsPerInch); - int margin_bottom_in_pixels = ConvertUnit( + description.margin_right = ConvertUnit(page_params.page_size.width() - + page_params.content_size.width() - + page_params.margin_left, + dpi, kPixelsPerInch); + description.margin_bottom = ConvertUnit( page_params.page_size.height() - page_params.content_size.height() - page_params.margin_top, dpi, kPixelsPerInch); - int margin_left_in_pixels = + description.margin_left = ConvertUnit(page_params.margin_left, dpi, kPixelsPerInch); - if (frame) { - frame->PageSizeAndMarginsInPixels( - page_index, page_size_in_pixels, margin_top_in_pixels, - margin_right_in_pixels, margin_bottom_in_pixels, margin_left_in_pixels); - } + if (frame) + frame->GetPageDescription(page_index, &description); - double new_content_width = page_size_in_pixels.Width() - - margin_left_in_pixels - margin_right_in_pixels; - double new_content_height = page_size_in_pixels.Height() - - margin_top_in_pixels - margin_bottom_in_pixels; + double new_content_width = description.size.Width() - + description.margin_left - description.margin_right; + double new_content_height = description.size.Height() - + description.margin_top - + description.margin_bottom; // Invalid page size and/or margins. We just use the default setting. if (new_content_width < 1 || new_content_height < 1) { @@ -186,16 +186,16 @@ } page_css_params.page_size = - gfx::Size(ConvertUnit(page_size_in_pixels.Width(), kPixelsPerInch, dpi), - ConvertUnit(page_size_in_pixels.Height(), kPixelsPerInch, dpi)); + gfx::Size(ConvertUnit(description.size.Width(), kPixelsPerInch, dpi), + ConvertUnit(description.size.Height(), kPixelsPerInch, dpi)); page_css_params.content_size = gfx::Size(ConvertUnit(new_content_width, kPixelsPerInch, dpi), ConvertUnit(new_content_height, kPixelsPerInch, dpi)); page_css_params.margin_top = - ConvertUnit(margin_top_in_pixels, kPixelsPerInch, dpi); + ConvertUnit(description.margin_top, kPixelsPerInch, dpi); page_css_params.margin_left = - ConvertUnit(margin_left_in_pixels, kPixelsPerInch, dpi); + ConvertUnit(description.margin_left, kPixelsPerInch, dpi); return page_css_params; }
diff --git a/components/query_tiles/switches.cc b/components/query_tiles/switches.cc index 78faf7c..0d8e0ec 100644 --- a/components/query_tiles/switches.cc +++ b/components/query_tiles/switches.cc
@@ -10,6 +10,9 @@ base::FEATURE_DISABLED_BY_DEFAULT}; const base::Feature kQueryTilesInOmnibox{"QueryTilesInOmnibox", base::FEATURE_DISABLED_BY_DEFAULT}; +const base::Feature kQueryTilesEnableQueryEditing{ + "QueryTilesEnableQueryEditing", base::FEATURE_DISABLED_BY_DEFAULT}; + } // namespace features namespace switches {
diff --git a/components/query_tiles/switches.h b/components/query_tiles/switches.h index 5edb3b7b..7d7098d 100644 --- a/components/query_tiles/switches.h +++ b/components/query_tiles/switches.h
@@ -16,6 +16,11 @@ // Feature flag to determine whether query tiles should be shown on omnibox. extern const base::Feature kQueryTilesInOmnibox; +// Feature flag to determine whether the user will have a chance to edit the +// query before in the omnibox sumbitting the search. In this mode only one +// level of tiles will be displayed. +extern const base::Feature kQueryTilesEnableQueryEditing; + } // namespace features namespace switches {
diff --git a/components/safety_check/BUILD.gn b/components/safety_check/BUILD.gn index f57e9b7..a52d8552 100644 --- a/components/safety_check/BUILD.gn +++ b/components/safety_check/BUILD.gn
@@ -33,3 +33,13 @@ "//testing/gtest", ] } + +source_set("test_support") { + testonly = true + sources = [ + "test_update_check_helper.cc", + "test_update_check_helper.h", + ] + + deps = [ ":safety_check" ] +}
diff --git a/components/safety_check/test_update_check_helper.cc b/components/safety_check/test_update_check_helper.cc new file mode 100644 index 0000000..85cf163 --- /dev/null +++ b/components/safety_check/test_update_check_helper.cc
@@ -0,0 +1,23 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/safety_check/test_update_check_helper.h" + +namespace safety_check { + +TestUpdateCheckHelper::TestUpdateCheckHelper() = default; + +TestUpdateCheckHelper::~TestUpdateCheckHelper() = default; + +void TestUpdateCheckHelper::SetConnectivity(bool online) { + online_ = online; +} + +// UpdateCheckHelper implementation. +void TestUpdateCheckHelper::CheckConnectivity( + ConnectivityCheckCallback connection_check_callback) { + std::move(connection_check_callback).Run(online_); +} + +} // namespace safety_check
diff --git a/components/safety_check/test_update_check_helper.h b/components/safety_check/test_update_check_helper.h new file mode 100644 index 0000000..22ca1f8 --- /dev/null +++ b/components/safety_check/test_update_check_helper.h
@@ -0,0 +1,30 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_SAFETY_CHECK_TEST_UPDATE_CHECK_HELPER_H_ +#define COMPONENTS_SAFETY_CHECK_TEST_UPDATE_CHECK_HELPER_H_ + +#include "components/safety_check/update_check_helper.h" + +namespace safety_check { + +// A version of UpdateCheckHelper used for testing. +class TestUpdateCheckHelper : public UpdateCheckHelper { + public: + TestUpdateCheckHelper(); + ~TestUpdateCheckHelper() override; + + void SetConnectivity(bool online); + + // UpdateCheckHelper implementation. + void CheckConnectivity( + ConnectivityCheckCallback connection_check_callback) override; + + private: + bool online_ = true; +}; + +} // namespace safety_check + +#endif // COMPONENTS_SAFETY_CHECK_TEST_UPDATE_CHECK_HELPER_H_
diff --git a/components/safety_check/update_check_helper.cc b/components/safety_check/update_check_helper.cc index 6834c8b..bb23c72 100644 --- a/components/safety_check/update_check_helper.cc +++ b/components/safety_check/update_check_helper.cc
@@ -10,6 +10,8 @@ #include "net/base/load_flags.h" #include "net/http/http_status_code.h" #include "net/traffic_annotation/network_traffic_annotation.h" +#include "services/network/public/cpp/shared_url_loader_factory.h" +#include "services/network/public/cpp/simple_url_loader.h" #include "url/gurl.h" namespace safety_check { @@ -81,6 +83,8 @@ base::Unretained(this))); } +UpdateCheckHelper::UpdateCheckHelper() = default; + void UpdateCheckHelper::OnURLLoadComplete( scoped_refptr<net::HttpResponseHeaders> headers) { DCHECK(url_loader_);
diff --git a/components/safety_check/update_check_helper.h b/components/safety_check/update_check_helper.h index 4aaef19..4f582fd 100644 --- a/components/safety_check/update_check_helper.h +++ b/components/safety_check/update_check_helper.h
@@ -6,8 +6,12 @@ #define COMPONENTS_SAFETY_CHECK_UPDATE_CHECK_HELPER_H_ #include "base/callback_forward.h" -#include "services/network/public/cpp/shared_url_loader_factory.h" -#include "services/network/public/cpp/simple_url_loader.h" +#include "net/http/http_response_headers.h" + +namespace network { +class SharedURLLoaderFactory; +class SimpleURLLoader; +} // namespace network namespace safety_check { @@ -17,7 +21,7 @@ public: explicit UpdateCheckHelper( scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory); - ~UpdateCheckHelper(); + virtual ~UpdateCheckHelper(); using ConnectivityCheckCallback = base::OnceCallback<void(bool connected)>; @@ -25,7 +29,12 @@ // callback with the result. Has a request timeout of 5 seconds. Anything // other than the intended HTTP 204 response is considered as no connectivity // (user behind proxy, etc). - void CheckConnectivity(ConnectivityCheckCallback connection_check_callback); + virtual void CheckConnectivity( + ConnectivityCheckCallback connection_check_callback); + + protected: + // Test-only constructor. + UpdateCheckHelper(); private: void OnURLLoadComplete(scoped_refptr<net::HttpResponseHeaders> headers);
diff --git a/components/services/language_detection/public/cpp/language_detection_service.cc b/components/services/language_detection/public/cpp/language_detection_service.cc index 6e242128..00775ee 100644 --- a/components/services/language_detection/public/cpp/language_detection_service.cc +++ b/components/services/language_detection/public/cpp/language_detection_service.cc
@@ -11,7 +11,6 @@ mojo::Remote<mojom::LanguageDetectionService> LaunchLanguageDetectionService() { return content::ServiceProcessHost::Launch<mojom::LanguageDetectionService>( content::ServiceProcessHost::Options() - .WithSandboxType(service_manager::SandboxType::kUtility) .WithDisplayName("Translate Language Detection") .Pass()); }
diff --git a/components/services/patch/content/patch_service.cc b/components/services/patch/content/patch_service.cc index b023e6a2d..f88e0a9 100644 --- a/components/services/patch/content/patch_service.cc +++ b/components/services/patch/content/patch_service.cc
@@ -15,7 +15,6 @@ content::ServiceProcessHost::Launch<mojom::FilePatcher>( remote.InitWithNewPipeAndPassReceiver(), content::ServiceProcessHost::Options() - .WithSandboxType(service_manager::SandboxType::kUtility) .WithDisplayName(IDS_PATCH_SERVICE_DISPLAY_NAME) .Pass()); return remote;
diff --git a/components/services/unzip/content/unzip_service.cc b/components/services/unzip/content/unzip_service.cc index d664f4fc..8dbfa87 100644 --- a/components/services/unzip/content/unzip_service.cc +++ b/components/services/unzip/content/unzip_service.cc
@@ -28,7 +28,6 @@ content::ServiceProcessHost::Launch<mojom::Unzipper>( remote.InitWithNewPipeAndPassReceiver(), content::ServiceProcessHost::Options() - .WithSandboxType(service_manager::SandboxType::kUtility) .WithDisplayName(IDS_UNZIP_SERVICE_DISPLAY_NAME) .Pass()); return remote;
diff --git a/components/sync/base/syncer_error.cc b/components/sync/base/syncer_error.cc index f0af128..15e11bc 100644 --- a/components/sync/base/syncer_error.cc +++ b/components/sync/base/syncer_error.cc
@@ -39,6 +39,7 @@ ENUM_CASE(SERVER_RETURN_USER_ROLLBACK); ENUM_CASE(SERVER_RETURN_PARTIAL_FAILURE); ENUM_CASE(SERVER_RETURN_CLIENT_DATA_OBSOLETE); + ENUM_CASE(SERVER_RETURN_ENCRYPTION_OBSOLETE); ENUM_CASE(SERVER_MORE_TO_DOWNLOAD); ENUM_CASE(DATATYPE_TRIGGERED_RETRY); ENUM_CASE(SYNCER_OK);
diff --git a/components/sync/base/syncer_error.h b/components/sync/base/syncer_error.h index 04edb6ed..a469d855 100644 --- a/components/sync/base/syncer_error.h +++ b/components/sync/base/syncer_error.h
@@ -40,6 +40,7 @@ SERVER_RETURN_USER_ROLLBACK, SERVER_RETURN_PARTIAL_FAILURE, SERVER_RETURN_CLIENT_DATA_OBSOLETE, + SERVER_RETURN_ENCRYPTION_OBSOLETE, // A datatype decided the sync cycle needed to be performed again. DATATYPE_TRIGGERED_RETRY,
diff --git a/components/sync/driver/profile_sync_service.cc b/components/sync/driver/profile_sync_service.cc index cd4d4bb8..cea197a 100644 --- a/components/sync/driver/profile_sync_service.cc +++ b/components/sync/driver/profile_sync_service.cc
@@ -67,15 +67,15 @@ // decryption, or the version of Chrome being too old. This enum is used to // back a UMA histogram, and should therefore be treated as append-only. enum SyncInitialState { - CAN_START, // Sync can attempt to start up. - NOT_SIGNED_IN, // There is no signed in user. - NOT_REQUESTED, // The user turned off sync. - NOT_REQUESTED_NOT_SETUP, // The user turned off sync and setup completed - // is false. Might indicate a stop-and-clear. - NEEDS_CONFIRMATION, // The user must confirm sync settings. - NOT_ALLOWED_BY_POLICY, // Sync is disallowed by enterprise policy. - NOT_ALLOWED_BY_PLATFORM, // Sync is disallowed by the platform. - SYNC_INITIAL_STATE_LIMIT + CAN_START = 0, // Sync can attempt to start up. + NOT_SIGNED_IN = 1, // There is no signed in user. + NOT_REQUESTED = 2, // The user turned off sync. + NOT_REQUESTED_NOT_SETUP = 3, // The user turned off sync and setup completed + // is false. Might indicate a stop-and-clear. + NEEDS_CONFIRMATION = 4, // The user must confirm sync settings. + NOT_ALLOWED_BY_POLICY = 5, // Sync is disallowed by enterprise policy. + OBSOLETE_NOT_ALLOWED_BY_PLATFORM = 6, + kMaxValue = OBSOLETE_NOT_ALLOWED_BY_PLATFORM }; // These values are persisted to logs. Entries should not be renumbered and @@ -102,12 +102,6 @@ ProfileSyncService::DISABLE_REASON_ENTERPRISE_POLICY)) { sync_state = NOT_ALLOWED_BY_POLICY; } else if (disable_reasons.Has( - ProfileSyncService::DISABLE_REASON_PLATFORM_OVERRIDE)) { - // This case means Android's "MasterSync" toggle. However, that is not - // plumbed into ProfileSyncService until after this method, so we never get - // here. See http://crbug.com/568771. - sync_state = NOT_ALLOWED_BY_PLATFORM; - } else if (disable_reasons.Has( ProfileSyncService::DISABLE_REASON_USER_CHOICE)) { if (first_setup_complete) { sync_state = NOT_REQUESTED; @@ -117,8 +111,7 @@ } else if (!first_setup_complete) { sync_state = NEEDS_CONFIRMATION; } - UMA_HISTOGRAM_ENUMERATION("Sync.InitialState", sync_state, - SYNC_INITIAL_STATE_LIMIT); + base::UmaHistogramEnumeration("Sync.InitialState", sync_state); } constexpr char kSyncUnrecoverableErrorHistogram[] = "Sync.UnrecoverableErrors";
diff --git a/components/sync/engine_impl/sync_scheduler_impl.cc b/components/sync/engine_impl/sync_scheduler_impl.cc index 3e6f993..1f0377d8 100644 --- a/components/sync/engine_impl/sync_scheduler_impl.cc +++ b/components/sync/engine_impl/sync_scheduler_impl.cc
@@ -59,6 +59,7 @@ case CLIENT_DATA_OBSOLETE: case CLEAR_PENDING: case DISABLED_BY_ADMIN: + case ENCRYPTION_OBSOLETE: // If we send terminate sync early then |sync_cycle_ended| notification // would not be sent. If there were no actions then |ACTIONABLE_ERROR| // notification wouldnt be sent either. Then the UI layer would be left @@ -68,6 +69,8 @@ // Make UNKNOWN_ERROR a NOTREACHED. All the other error should be explicitly // handled. case UNKNOWN_ERROR: + // TODO(crbug.com/1081266): This NOTREACHED is questionable because the + // sync server can cause it. NOTREACHED(); return false; }
diff --git a/components/sync/engine_impl/syncer_proto_util.cc b/components/sync/engine_impl/syncer_proto_util.cc index 91194ec..3173ed12 100644 --- a/components/sync/engine_impl/syncer_proto_util.cc +++ b/components/sync/engine_impl/syncer_proto_util.cc
@@ -130,10 +130,18 @@ return CLIENT_DATA_OBSOLETE; case sync_pb::SyncEnums::UNKNOWN: return UNKNOWN_ERROR; - default: - NOTREACHED(); + case sync_pb::SyncEnums::ENCRYPTION_OBSOLETE: + return ENCRYPTION_OBSOLETE; + case sync_pb::SyncEnums::DEPRECATED_ACCESS_DENIED: + case sync_pb::SyncEnums::DEPRECATED_AUTH_EXPIRED: + case sync_pb::SyncEnums::DEPRECATED_AUTH_INVALID: + case sync_pb::SyncEnums::DEPRECATED_USER_NOT_ACTIVATED: + case sync_pb::SyncEnums::DEPRECATED_USER_ROLLBACK: return UNKNOWN_ERROR; } + + NOTREACHED(); + return UNKNOWN_ERROR; } ClientAction PBActionToClientAction(const sync_pb::SyncEnums::Action& action) { @@ -146,10 +154,10 @@ case sync_pb::SyncEnums::DEPRECATED_DISABLE_SYNC_ON_CLIENT: case sync_pb::SyncEnums::UNKNOWN_ACTION: return UNKNOWN_ACTION; - default: - NOTREACHED(); - return UNKNOWN_ACTION; } + + NOTREACHED(); + return UNKNOWN_ACTION; } // Returns true iff |message| is an initial GetUpdates request. @@ -181,7 +189,8 @@ SyncProtocolError error; error.error_type = PBErrorTypeToSyncProtocolErrorType(error_type); if (error_type == sync_pb::SyncEnums::CLEAR_PENDING || - error_type == sync_pb::SyncEnums::NOT_MY_BIRTHDAY) { + error_type == sync_pb::SyncEnums::NOT_MY_BIRTHDAY || + error_type == sync_pb::SyncEnums::ENCRYPTION_OBSOLETE) { error.action = DISABLE_SYNC_ON_CLIENT; } else if (error_type == sync_pb::SyncEnums::CLIENT_DATA_OBSOLETE) { error.action = RESET_LOCAL_SYNC_DATA; @@ -308,6 +317,13 @@ // Legacy server implementation. Compute the error based on |error_code|. sync_protocol_error = ErrorCodeToSyncProtocolError(response.error_code()); } + + // Trivially inferred actions. + if (sync_protocol_error.action == UNKNOWN_ACTION && + sync_protocol_error.error_type == ENCRYPTION_OBSOLETE) { + sync_protocol_error.action = DISABLE_SYNC_ON_CLIENT; + } + return sync_protocol_error; } @@ -556,10 +572,12 @@ return SyncerError(SyncerError::SYNCER_OK); case CLIENT_DATA_OBSOLETE: return SyncerError(SyncerError::SERVER_RETURN_CLIENT_DATA_OBSOLETE); - default: - NOTREACHED(); - return SyncerError(); + case ENCRYPTION_OBSOLETE: + return SyncerError(SyncerError::SERVER_RETURN_ENCRYPTION_OBSOLETE); } + + NOTREACHED(); + return SyncerError(); } // static
diff --git a/components/sync/engine_impl/syncer_proto_util_unittest.cc b/components/sync/engine_impl/syncer_proto_util_unittest.cc index 55aaebb..8c33d64b 100644 --- a/components/sync/engine_impl/syncer_proto_util_unittest.cc +++ b/components/sync/engine_impl/syncer_proto_util_unittest.cc
@@ -206,6 +206,17 @@ EXPECT_EQ(STOP_SYNC_FOR_DISABLED_ACCOUNT, sync_protocol_error.action); } +TEST_F(SyncerProtoUtilTest, VerifyEncryptionObsolete) { + sync_pb::ClientToServerResponse response; + response.set_error_code(sync_pb::SyncEnums::ENCRYPTION_OBSOLETE); + response.set_store_birthday("flan"); + + SyncProtocolError sync_protocol_error = + CallGetProtocolErrorFromResponse(response, context()); + EXPECT_EQ(ENCRYPTION_OBSOLETE, sync_protocol_error.error_type); + EXPECT_EQ(DISABLE_SYNC_ON_CLIENT, sync_protocol_error.action); +} + class DummyConnectionManager : public ServerConnectionManager { public: DummyConnectionManager() : send_error_(false) {}
diff --git a/components/sync/protocol/proto_enum_conversions.cc b/components/sync/protocol/proto_enum_conversions.cc index 0e4dd00..9a92ef38 100644 --- a/components/sync/protocol/proto_enum_conversions.cc +++ b/components/sync/protocol/proto_enum_conversions.cc
@@ -196,6 +196,7 @@ ENUM_CASE(sync_pb::SyncEnums, DEPRECATED_USER_ROLLBACK); ENUM_CASE(sync_pb::SyncEnums, PARTIAL_FAILURE); ENUM_CASE(sync_pb::SyncEnums, CLIENT_DATA_OBSOLETE); + ENUM_CASE(sync_pb::SyncEnums, ENCRYPTION_OBSOLETE); ENUM_CASE(sync_pb::SyncEnums, UNKNOWN); } NOTREACHED();
diff --git a/components/sync/protocol/sync_enums.proto b/components/sync/protocol/sync_enums.proto index d13cfba..9cea98e 100644 --- a/components/sync/protocol/sync_enums.proto +++ b/components/sync/protocol/sync_enums.proto
@@ -87,35 +87,42 @@ enum ErrorType { SUCCESS = 0; DEPRECATED_ACCESS_DENIED = 1; - NOT_MY_BIRTHDAY = 2; // Returned when the server and client disagree - // on the store birthday. - THROTTLED = 3; // Returned when the store has exceeded the - // allowed bandwidth utilization. + // Returned when the server and client disagree on the store birthday. + NOT_MY_BIRTHDAY = 2; + // Returned when the store has exceeded the allowed bandwidth utilization. + THROTTLED = 3; DEPRECATED_AUTH_EXPIRED = 4; DEPRECATED_USER_NOT_ACTIVATED = 5; DEPRECATED_AUTH_INVALID = 6; - CLEAR_PENDING = 7; // A clear of the user data is pending (e.g. - // initiated by privacy request). Client should - // come back later. - TRANSIENT_ERROR = 8; // A transient error occured (eg. backend - // timeout). Client should try again later. - MIGRATION_DONE = 9; // Migration has finished for one or more data - // types. Client should clear the cache for - // these data types only and then re-sync with - // a server. - DISABLED_BY_ADMIN = 10; // An administrator disabled sync for this - // domain. - DEPRECATED_USER_ROLLBACK = 11; // Deprecated in M50. - PARTIAL_FAILURE = 12; // Return when client want to update several - // data types, but some of them failed(e.g. - // throttled). - CLIENT_DATA_OBSOLETE = 13; // Returned when server detects that this - // client's data is obsolete. Client should - // reset local data and restart syncing. - UNKNOWN = 100; // Unknown value. This should never be - // explicitly used; it is the default value when - // an out-of-date client parses a value it - // doesn't recognize. + // A clear of the user data is pending (e.g. initiated by privacy request). + // The client should come back later. + CLEAR_PENDING = 7; + // A transient error occurred (e.g. a backend timeout). The client should + // try again later. + TRANSIENT_ERROR = 8; + // A server-side migration has taken place for one or more data types. The + // client should clear the cache for these data types only and then re-sync + // with a server. + MIGRATION_DONE = 9; + // An administrator disabled sync for this domain. + DISABLED_BY_ADMIN = 10; + // Deprecated in M50. + DEPRECATED_USER_ROLLBACK = 11; + // Returned when the client wants to update several data types, but some of + // them failed (e.g. throttled). + PARTIAL_FAILURE = 12; + // Returned when the server detects that this client's sync metadata is + // obsolete. The client should reset local sync metadata and restart + // syncing. + CLIENT_DATA_OBSOLETE = 13; + // Returned when the server detects that the encryption state (Nigori, + // keystore keys) has been reset/overridden, which means the local + // Nigori-related state is obsolete and should be cleared. + // Introduced in M84. + ENCRYPTION_OBSOLETE = 14; + // Unknown value. This should never be explicitly used; it is the default + // value when an out-of-date client parses a value it doesn't recognize. + UNKNOWN = 100; } enum Action {
diff --git a/components/sync/protocol/sync_protocol_error.cc b/components/sync/protocol/sync_protocol_error.cc index 9739564..0ba670c 100644 --- a/components/sync/protocol/sync_protocol_error.cc +++ b/components/sync/protocol/sync_protocol_error.cc
@@ -25,6 +25,7 @@ ENUM_CASE(DISABLED_BY_ADMIN); ENUM_CASE(PARTIAL_FAILURE); ENUM_CASE(CLIENT_DATA_OBSOLETE); + ENUM_CASE(ENCRYPTION_OBSOLETE); ENUM_CASE(UNKNOWN_ERROR); } NOTREACHED();
diff --git a/components/sync/protocol/sync_protocol_error.h b/components/sync/protocol/sync_protocol_error.h index 08019aa1..5101433 100644 --- a/components/sync/protocol/sync_protocol_error.h +++ b/components/sync/protocol/sync_protocol_error.h
@@ -42,6 +42,11 @@ // should reset local data and restart syncing. CLIENT_DATA_OBSOLETE, + // Returned when the server detects that the encryption state (Nigori, + // keystore keys) has been reset/overridden, which means the local + // Nigori-related state is obsolete and should be cleared. + ENCRYPTION_OBSOLETE, + // The default value. UNKNOWN_ERROR };
diff --git a/components/test/data/autofill_assistant/html/autofill_assistant_target_website_iframe_one.html b/components/test/data/autofill_assistant/html/autofill_assistant_target_website_iframe_one.html index 050ee52..332702a 100644 --- a/components/test/data/autofill_assistant/html/autofill_assistant_target_website_iframe_one.html +++ b/components/test/data/autofill_assistant/html/autofill_assistant_target_website_iframe_one.html
@@ -62,7 +62,7 @@ <form name="address" id="address_section"> <div id="billing"> <h2>Billing Address</h2> - Name: <input type="text" name="name"><br> + Name: <input type="text" name="name" id="name"><br> Address: <input type="text" name="address"><br> City: <input type="text" name="city"><br> State: <select name="state">
diff --git a/components/test/data/autofill_assistant/html/form_target_website.html b/components/test/data/autofill_assistant/html/form_target_website.html index c159db2..2221b6d 100644 --- a/components/test/data/autofill_assistant/html/form_target_website.html +++ b/components/test/data/autofill_assistant/html/form_target_website.html
@@ -28,7 +28,7 @@ <div id="terms" class="terms"> <button id="button" onclick="onClick()"> Button </button> <div id="toggle_on" style="display: none"> Toggle on </div> - </div> + </div> <h4>Credit card</h4> <div> @@ -80,5 +80,7 @@ </form> </div> + <iframe id="iframe" name="test_iframe" width="100%" height="500" src= + "autofill_assistant_target_website_iframe_one.html"></iframe> </body> </html>
diff --git a/components/url_formatter/url_fixer_unittest.cc b/components/url_formatter/url_fixer_unittest.cc index 9c2acd7..607cee3 100644 --- a/components/url_formatter/url_fixer_unittest.cc +++ b/components/url_formatter/url_fixer_unittest.cc
@@ -515,7 +515,7 @@ // Much of the work here comes from GURL's canonicalization stage. {"file://C:/foo/bar", "file:///C:/foo/bar"}, - {"file:c:", "file:///C:/"}, + {"file:c:", "file:///C:"}, {"file:c:WINDOWS", "file:///C:/WINDOWS"}, {"file:c|Program Files", "file:///C:/Program%20Files"}, {"file:/file", "file://file/"},
diff --git a/components/webrtc/android/BUILD.gn b/components/webrtc/android/BUILD.gn index 1c74c40..a335ac2 100644 --- a/components/webrtc/android/BUILD.gn +++ b/components/webrtc/android/BUILD.gn
@@ -14,10 +14,6 @@ "//base:base_java", "//components/browser_ui/notifications/android:java", "//third_party/android_deps:androidx_core_core_java", - - # TODO(crbug.com/1017190): Remove the following deps once we stop linting individual targets. - "//components/browser_ui/styles/android:java_resources", - "//ui/android:ui_java", ] }
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn index 207b641..1732842 100644 --- a/content/browser/BUILD.gn +++ b/content/browser/BUILD.gn
@@ -276,6 +276,8 @@ "$target_gen_dir/devtools/protocol/inspector.h", "$target_gen_dir/devtools/protocol/io.cc", "$target_gen_dir/devtools/protocol/io.h", + "$target_gen_dir/devtools/protocol/log.cc", + "$target_gen_dir/devtools/protocol/log.h", "$target_gen_dir/devtools/protocol/memory.cc", "$target_gen_dir/devtools/protocol/memory.h", "$target_gen_dir/devtools/protocol/network.cc", @@ -775,6 +777,8 @@ "devtools/protocol/inspector_handler.h", "devtools/protocol/io_handler.cc", "devtools/protocol/io_handler.h", + "devtools/protocol/log_handler.cc", + "devtools/protocol/log_handler.h", "devtools/protocol/memory_handler.cc", "devtools/protocol/memory_handler.h", "devtools/protocol/native_input_event_builder.h",
diff --git a/content/browser/appcache/appcache_host.cc b/content/browser/appcache/appcache_host.cc index eef8c30..4268404 100644 --- a/content/browser/appcache/appcache_host.cc +++ b/content/browser/appcache/appcache_host.cc
@@ -217,7 +217,8 @@ AppCachePolicy* policy = service()->appcache_policy(); if (policy && !policy->CanCreateAppCache( - manifest_url, site_for_cookies_.RepresentativeUrl())) { + manifest_url, site_for_cookies_.RepresentativeUrl(), + top_frame_origin_)) { FinishCacheSelection(nullptr, nullptr, mojo::ReportBadMessageCallback()); frontend()->EventRaised( blink::mojom::AppCacheEventID::APPCACHE_CHECKING_EVENT); @@ -406,6 +407,7 @@ // for checking whether the creation of the appcache is allowed. site_for_cookies_ = request->GetSiteForCookies(); site_for_cookies_initialized_ = true; + top_frame_origin_ = request->GetTopFrameOrigin(); return base::WrapUnique(new AppCacheRequestHandler( this, resource_type, should_reset_appcache, std::move(request))); }
diff --git a/content/browser/appcache/appcache_host.h b/content/browser/appcache/appcache_host.h index a3743b4..111775d 100644 --- a/content/browser/appcache/appcache_host.h +++ b/content/browser/appcache/appcache_host.h
@@ -17,6 +17,7 @@ #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" #include "base/observer_list.h" +#include "base/optional.h" #include "content/browser/appcache/appcache_group.h" #include "content/browser/appcache/appcache_service_impl.h" #include "content/browser/appcache/appcache_storage.h" @@ -229,6 +230,10 @@ site_for_cookies_initialized_ = true; } + const base::Optional<url::Origin>& top_frame_origin() const { + return top_frame_origin_; + } + void set_origin_for_url_loader_factory(const url::Origin& origin) { origin_for_url_loader_factory_ = origin; } @@ -413,6 +418,7 @@ // To be used in policy checks. net::SiteForCookies site_for_cookies_; bool site_for_cookies_initialized_ = false; + base::Optional<url::Origin> top_frame_origin_; bool is_origin_trial_required_ = false;
diff --git a/content/browser/appcache/appcache_policy.h b/content/browser/appcache/appcache_policy.h index f864417..93ce034 100644 --- a/content/browser/appcache/appcache_policy.h +++ b/content/browser/appcache/appcache_policy.h
@@ -5,8 +5,14 @@ #ifndef CONTENT_BROWSER_APPCACHE_APPCACHE_POLICY_H_ #define CONTENT_BROWSER_APPCACHE_APPCACHE_POLICY_H_ +#include "base/optional.h" + class GURL; +namespace url { +class Origin; +} + namespace content { class AppCachePolicy { @@ -16,12 +22,18 @@ // Called prior to loading a main resource from the appache. // Returns true if allowed. This is expected to return immediately // without any user prompt. - virtual bool CanLoadAppCache(const GURL& manifest_url, - const GURL& first_party) = 0; + virtual bool CanLoadAppCache( + const GURL& manifest_url, + + const GURL& site_for_cookies, + const base::Optional<url::Origin>& top_frame_origin) = 0; // Called prior to creating a new appcache. Returns true if allowed. - virtual bool CanCreateAppCache(const GURL& manifest_url, - const GURL& first_party) = 0; + virtual bool CanCreateAppCache( + const GURL& manifest_url, + + const GURL& site_for_cookies, + const base::Optional<url::Origin>& top_frame_origin) = 0; // Returns true if origin trial tokens are required in order to fetch or // update manifests, as well as load any resources from such a manifest.
diff --git a/content/browser/appcache/appcache_request.cc b/content/browser/appcache/appcache_request.cc index 598c6e78..a19a46c 100644 --- a/content/browser/appcache/appcache_request.cc +++ b/content/browser/appcache/appcache_request.cc
@@ -5,9 +5,11 @@ #include "content/browser/appcache/appcache_request.h" #include "content/common/appcache_interfaces.h" +#include "net/base/isolation_info.h" #include "net/url_request/redirect_info.h" #include "net/url_request/redirect_util.h" #include "net/url_request/url_request.h" +#include "url/origin.h" namespace content { @@ -30,6 +32,12 @@ return 0; } +base::Optional<url::Origin> AppCacheRequest::GetTopFrameOrigin() const { + return request_.trusted_params + ? request_.trusted_params->isolation_info.top_frame_origin() + : base::nullopt; +} + std::string AppCacheRequest::GetResponseHeaderByName( const std::string& name) const { std::string header;
diff --git a/content/browser/appcache/appcache_request.h b/content/browser/appcache/appcache_request.h index 244ab605..cf189e4 100644 --- a/content/browser/appcache/appcache_request.h +++ b/content/browser/appcache/appcache_request.h
@@ -8,6 +8,7 @@ #include <string> #include "base/memory/weak_ptr.h" +#include "base/optional.h" #include "base/sequence_checker.h" #include "content/common/content_export.h" #include "services/network/public/cpp/resource_request.h" @@ -23,6 +24,10 @@ struct ResourceRequest; } +namespace url { +class Origin; +} + namespace content { // Interface for an AppCache request. Subclasses implement this interface to @@ -44,6 +49,9 @@ return request_.site_for_cookies; } + // Used for cookie policy. + base::Optional<url::Origin> GetTopFrameOrigin() const; + // The referrer for this request. const GURL GetReferrer() const { return request_.referrer; }
diff --git a/content/browser/appcache/appcache_request_handler.cc b/content/browser/appcache/appcache_request_handler.cc index b4f3319..9346278e 100644 --- a/content/browser/appcache/appcache_request_handler.cc +++ b/content/browser/appcache/appcache_request_handler.cc
@@ -360,7 +360,8 @@ bool was_blocked_by_policy = !manifest_url.is_empty() && policy && !policy->CanLoadAppCache(manifest_url, - host_->site_for_cookies().RepresentativeUrl()); + host_->site_for_cookies().RepresentativeUrl(), + host_->top_frame_origin()); if (was_blocked_by_policy) { if (blink::IsResourceTypeFrame(resource_type_)) {
diff --git a/content/browser/appcache/chrome_appcache_service.cc b/content/browser/appcache/chrome_appcache_service.cc index 9eb2d4e..c098e0d 100644 --- a/content/browser/appcache/chrome_appcache_service.cc +++ b/content/browser/appcache/chrome_appcache_service.cc
@@ -56,18 +56,22 @@ partition_ = nullptr; } -bool ChromeAppCacheService::CanLoadAppCache(const GURL& manifest_url, - const GURL& first_party) { +bool ChromeAppCacheService::CanLoadAppCache( + const GURL& manifest_url, + const GURL& site_for_cookies, + const base::Optional<url::Origin>& top_frame_origin) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - return GetContentClient()->browser()->AllowAppCache(manifest_url, first_party, - browser_context_); + return GetContentClient()->browser()->AllowAppCache( + manifest_url, site_for_cookies, top_frame_origin, browser_context_); } bool ChromeAppCacheService::CanCreateAppCache( - const GURL& manifest_url, const GURL& first_party) { + const GURL& manifest_url, + const GURL& site_for_cookies, + const base::Optional<url::Origin>& top_frame_origin) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - return GetContentClient()->browser()->AllowAppCache(manifest_url, first_party, - browser_context_); + return GetContentClient()->browser()->AllowAppCache( + manifest_url, site_for_cookies, top_frame_origin, browser_context_); } bool ChromeAppCacheService::IsOriginTrialRequiredForAppCache() {
diff --git a/content/browser/appcache/chrome_appcache_service.h b/content/browser/appcache/chrome_appcache_service.h index 58e7d8aa..731abba 100644 --- a/content/browser/appcache/chrome_appcache_service.h +++ b/content/browser/appcache/chrome_appcache_service.h
@@ -64,10 +64,14 @@ void Shutdown(); // AppCachePolicy overrides - bool CanLoadAppCache(const GURL& manifest_url, - const GURL& first_party) override; - bool CanCreateAppCache(const GURL& manifest_url, - const GURL& first_party) override; + bool CanLoadAppCache( + const GURL& manifest_url, + const GURL& site_for_cookies, + const base::Optional<url::Origin>& top_frame_origin) override; + bool CanCreateAppCache( + const GURL& manifest_url, + const GURL& site_for_cookies, + const base::Optional<url::Origin>& top_frame_origin) override; bool IsOriginTrialRequiredForAppCache() override; protected:
diff --git a/content/browser/appcache/mock_appcache_policy.cc b/content/browser/appcache/mock_appcache_policy.cc index 5e6a332..c9fbcfa 100644 --- a/content/browser/appcache/mock_appcache_policy.cc +++ b/content/browser/appcache/mock_appcache_policy.cc
@@ -15,14 +15,18 @@ MockAppCachePolicy::~MockAppCachePolicy() = default; -bool MockAppCachePolicy::CanLoadAppCache(const GURL& manifest_url, - const GURL& first_party) { +bool MockAppCachePolicy::CanLoadAppCache( + const GURL& manifest_url, + const GURL& site_for_cookies, + const base::Optional<url::Origin>& top_frame_origin) { requested_manifest_url_ = manifest_url; return can_load_return_value_; } -bool MockAppCachePolicy::CanCreateAppCache(const GURL& manifest_url, - const GURL& first_party) { +bool MockAppCachePolicy::CanCreateAppCache( + const GURL& manifest_url, + const GURL& site_for_cookies, + const base::Optional<url::Origin>& top_frame_origin) { requested_manifest_url_ = manifest_url; return can_create_return_value_; }
diff --git a/content/browser/appcache/mock_appcache_policy.h b/content/browser/appcache/mock_appcache_policy.h index d0704c5..747315e 100644 --- a/content/browser/appcache/mock_appcache_policy.h +++ b/content/browser/appcache/mock_appcache_policy.h
@@ -16,10 +16,14 @@ MockAppCachePolicy(); virtual ~MockAppCachePolicy(); - bool CanLoadAppCache(const GURL& manifest_url, - const GURL& first_party) override; - bool CanCreateAppCache(const GURL& manifest_url, - const GURL& first_party) override; + bool CanLoadAppCache( + const GURL& manifest_url, + const GURL& site_for_cookies, + const base::Optional<url::Origin>& top_frame_origin) override; + bool CanCreateAppCache( + const GURL& manifest_url, + const GURL& site_for_cookies, + const base::Optional<url::Origin>& top_frame_origin) override; bool IsOriginTrialRequiredForAppCache() override; bool can_load_return_value_;
diff --git a/content/browser/browser_main_loop.cc b/content/browser/browser_main_loop.cc index 699e45f..e7009984 100644 --- a/content/browser/browser_main_loop.cc +++ b/content/browser/browser_main_loop.cc
@@ -411,7 +411,6 @@ ServiceProcessHost::Launch( std::move(receiver), ServiceProcessHost::Options() - .WithSandboxType(service_manager::SandboxType::kUtility) .WithDisplayName("Data Decoder Service") .Pass()); }
diff --git a/content/browser/cross_origin_opener_policy_browsertest.cc b/content/browser/cross_origin_opener_policy_browsertest.cc index 95185ffbb..6fc47dc1 100644 --- a/content/browser/cross_origin_opener_policy_browsertest.cc +++ b/content/browser/cross_origin_opener_policy_browsertest.cc
@@ -47,6 +47,7 @@ std::vector<base::Feature> features; feature_list_.InitWithFeatures( {network::features::kCrossOriginOpenerPolicy, + network::features::kCrossOriginOpenerPolicyReporting, network::features::kCrossOriginEmbedderPolicy}, {}); base::CommandLine::ForCurrentProcess()->AppendSwitch( @@ -331,9 +332,7 @@ EXPECT_EQ(iframe_rfh->GetLastCommittedURL(), iframe_navigation_url); EXPECT_EQ(iframe_rfh->GetSiteInstance(), non_coop_iframe_site_instance); - // TODO(pmeuleman, ahemery): Don't store COOP on subframes as it will not be - // used anyway. - EXPECT_EQ(iframe_rfh->cross_origin_opener_policy(), CoopSameOrigin()); + EXPECT_EQ(iframe_rfh->cross_origin_opener_policy(), CoopUnsafeNone()); } IN_PROC_BROWSER_TEST_F(CrossOriginOpenerPolicyBrowserTest,
diff --git a/content/browser/devtools/BUILD.gn b/content/browser/devtools/BUILD.gn index 2cd01cd..d3670fb 100644 --- a/content/browser/devtools/BUILD.gn +++ b/content/browser/devtools/BUILD.gn
@@ -82,6 +82,8 @@ "protocol/inspector.h", "protocol/io.cc", "protocol/io.h", + "protocol/log.cc", + "protocol/log.h", "protocol/memory.cc", "protocol/memory.h", "protocol/network.cc",
diff --git a/content/browser/devtools/devtools_instrumentation.cc b/content/browser/devtools/devtools_instrumentation.cc index df1f100..81f3c5a0 100644 --- a/content/browser/devtools/devtools_instrumentation.cc +++ b/content/browser/devtools/devtools_instrumentation.cc
@@ -3,12 +3,14 @@ // found in the LICENSE file. #include "content/browser/devtools/devtools_instrumentation.h" +#include "base/strings/stringprintf.h" #include "components/download/public/common/download_create_info.h" #include "components/download/public/common/download_item.h" #include "content/browser/devtools/browser_devtools_agent_host.h" #include "content/browser/devtools/devtools_url_loader_interceptor.h" #include "content/browser/devtools/protocol/emulation_handler.h" #include "content/browser/devtools/protocol/fetch_handler.h" +#include "content/browser/devtools/protocol/log_handler.h" #include "content/browser/devtools/protocol/network_handler.h" #include "content/browser/devtools/protocol/page_handler.h" #include "content/browser/devtools/protocol/security_handler.h" @@ -729,6 +731,22 @@ std::move(details))); } +void OnQuicTransportHandshakeFailed(RenderFrameHostImpl* frame, + const GURL& url) { + FrameTreeNode* ftn = frame->frame_tree_node(); + if (!ftn) + return; + std::string text = base::StringPrintf( + "Failed to establish a connection to %s.", url.spec().c_str()); + auto entry = protocol::Log::LogEntry::Create() + .SetSource(protocol::Log::LogEntry::SourceEnum::Network) + .SetLevel(protocol::Log::LogEntry::LevelEnum::Error) + .SetText(text) + .SetTimestamp(base::Time::Now().ToDoubleT() * 1000.0) + .Build(); + DispatchToAgents(ftn, &protocol::LogHandler::EntryAdded, std::move(entry)); +} + } // namespace devtools_instrumentation } // namespace content
diff --git a/content/browser/devtools/devtools_instrumentation.h b/content/browser/devtools/devtools_instrumentation.h index cbe5874..eb975dae 100644 --- a/content/browser/devtools/devtools_instrumentation.h +++ b/content/browser/devtools/devtools_instrumentation.h
@@ -178,6 +178,10 @@ const net::SiteForCookies& site_for_cookies, blink::mojom::SameSiteCookieOperation operation, const base::Optional<std::string>& devtools_request_id); + +void OnQuicTransportHandshakeFailed(RenderFrameHostImpl* frame_host, + const GURL& url); + } // namespace devtools_instrumentation } // namespace content
diff --git a/content/browser/devtools/protocol/log_handler.cc b/content/browser/devtools/protocol/log_handler.cc new file mode 100644 index 0000000..4fca4dd --- /dev/null +++ b/content/browser/devtools/protocol/log_handler.cc
@@ -0,0 +1,43 @@ +// 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 "content/browser/devtools/protocol/log_handler.h" + +#include "content/browser/devtools/devtools_agent_host_impl.h" + +namespace content { +namespace protocol { + +LogHandler::LogHandler() : DevToolsDomainHandler(Log::Metainfo::domainName) {} +LogHandler::~LogHandler() = default; + +// static +std::vector<LogHandler*> LogHandler::ForAgentHost(DevToolsAgentHostImpl* host) { + return host->HandlersByName<LogHandler>(Log::Metainfo::domainName); +} + +void LogHandler::Wire(UberDispatcher* dispatcher) { + frontend_ = std::make_unique<Log::Frontend>(dispatcher->channel()); + Log::Dispatcher::wire(dispatcher, this); +} + +DispatchResponse LogHandler::Disable() { + enabled_ = false; + return Response::FallThrough(); +} + +DispatchResponse LogHandler::Enable() { + enabled_ = true; + return Response::FallThrough(); +} + +void LogHandler::EntryAdded(std::unique_ptr<Log::LogEntry> entry) { + if (!enabled_) { + return; + } + frontend_->EntryAdded(std::move(entry)); +} + +} // namespace protocol +} // namespace content \ No newline at end of file
diff --git a/content/browser/devtools/protocol/log_handler.h b/content/browser/devtools/protocol/log_handler.h new file mode 100644 index 0000000..45b5455 --- /dev/null +++ b/content/browser/devtools/protocol/log_handler.h
@@ -0,0 +1,46 @@ +// 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 CONTENT_BROWSER_DEVTOOLS_PROTOCOL_LOG_HANDLER_H_ +#define CONTENT_BROWSER_DEVTOOLS_PROTOCOL_LOG_HANDLER_H_ + +#include "base/macros.h" +#include "content/browser/devtools/protocol/devtools_domain_handler.h" +#include "content/browser/devtools/protocol/log.h" +#include "mojo/public/cpp/bindings/remote.h" +#include "third_party/blink/public/mojom/leak_detector/leak_detector.mojom.h" + +namespace content { + +class DevToolsAgentHostImpl; + +namespace protocol { + +class LogHandler final : public DevToolsDomainHandler, public Log::Backend { + public: + LogHandler(); + ~LogHandler() override; + + static std::vector<LogHandler*> ForAgentHost(DevToolsAgentHostImpl* host); + + // DevToolsDomainHandler implementation. + void Wire(UberDispatcher* dispatcher) override; + + // Log::Backend implementation. + DispatchResponse Disable() override; + DispatchResponse Enable() override; + + void EntryAdded(std::unique_ptr<Log::LogEntry> entry); + + private: + std::unique_ptr<Log::Frontend> frontend_; + bool enabled_ = false; + + DISALLOW_COPY_AND_ASSIGN(LogHandler); +}; + +} // namespace protocol +} // namespace content + +#endif // CONTENT_BROWSER_DEVTOOLS_PROTOCOL_LOG_HANDLER_H_
diff --git a/content/browser/devtools/protocol_config.json b/content/browser/devtools/protocol_config.json index 3c65670a..604cebf 100644 --- a/content/browser/devtools/protocol_config.json +++ b/content/browser/devtools/protocol_config.json
@@ -39,6 +39,10 @@ "exclude": ["resolveBlob"] }, { + "domain": "Log", + "include": ["LogEntry", "entryAdded", "enable", "disable"] + }, + { "domain": "Memory", "include": ["getBrowserSamplingProfile", "setPressureNotificationsSuppressed", "simulatePressureNotification", "prepareForLeakDetection"], "async": ["prepareForLeakDetection"]
diff --git a/content/browser/devtools/render_frame_devtools_agent_host.cc b/content/browser/devtools/render_frame_devtools_agent_host.cc index 27ecb9a..d70c3971 100644 --- a/content/browser/devtools/render_frame_devtools_agent_host.cc +++ b/content/browser/devtools/render_frame_devtools_agent_host.cc
@@ -29,6 +29,7 @@ #include "content/browser/devtools/protocol/input_handler.h" #include "content/browser/devtools/protocol/inspector_handler.h" #include "content/browser/devtools/protocol/io_handler.h" +#include "content/browser/devtools/protocol/log_handler.h" #include "content/browser/devtools/protocol/memory_handler.h" #include "content/browser/devtools/protocol/network_handler.h" #include "content/browser/devtools/protocol/overlay_handler.h" @@ -106,8 +107,8 @@ } // namespace // static -scoped_refptr<DevToolsAgentHost> -DevToolsAgentHost::GetOrCreateFor(WebContents* web_contents) { +scoped_refptr<DevToolsAgentHost> DevToolsAgentHost::GetOrCreateFor( + WebContents* web_contents) { FrameTreeNode* node = static_cast<WebContentsImpl*>(web_contents)->GetFrameTree()->root(); // TODO(dgozman): this check should not be necessary. See @@ -340,6 +341,7 @@ session->AddHandler(std::make_unique<protocol::TracingHandler>( frame_tree_node_, GetIOContext())); } + session->AddHandler(std::make_unique<protocol::LogHandler>()); #if !defined(OS_ANDROID) session->AddHandler(std::make_unique<protocol::WebAuthnHandler>()); #endif // !defined(OS_ANDROID)
diff --git a/content/browser/frame_host/navigation_request.cc b/content/browser/frame_host/navigation_request.cc index 8e11d6e..05ac3a6 100644 --- a/content/browser/frame_host/navigation_request.cc +++ b/content/browser/frame_host/navigation_request.cc
@@ -2002,8 +2002,8 @@ if (base::FeatureList::IsEnabled( network::features::kCrossOriginOpenerPolicy)) { // The Cross-Origin-Opener-Policy header should be ignored if delivered in - // insecure contexts. - if (!IsOriginSecure(common_params_->url)) { + // insecure contexts, and non-top level documents. + if (!IsOriginSecure(common_params_->url) || !IsInMainFrame()) { response_head_->parsed_headers->cross_origin_opener_policy = network::CrossOriginOpenerPolicy(); }
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc index 369edfa..ca5e9b2 100644 --- a/content/browser/frame_host/render_frame_host_impl.cc +++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -6970,10 +6970,11 @@ void RenderFrameHostImpl::CreateQuicTransportConnector( mojo::PendingReceiver<blink::mojom::QuicTransportConnector> receiver) { - mojo::MakeSelfOwnedReceiver(std::make_unique<QuicTransportConnectorImpl>( - GetProcess()->GetID(), last_committed_origin_, - isolation_info_.network_isolation_key()), - std::move(receiver)); + mojo::MakeSelfOwnedReceiver( + std::make_unique<QuicTransportConnectorImpl>( + GetProcess()->GetID(), weak_ptr_factory_.GetWeakPtr(), + last_committed_origin_, isolation_info_.network_isolation_key()), + std::move(receiver)); } void RenderFrameHostImpl::CreateNotificationService(
diff --git a/content/browser/service_worker/service_worker_provider_host.cc b/content/browser/service_worker/service_worker_provider_host.cc index 1efb02e..5a18dd2 100644 --- a/content/browser/service_worker/service_worker_provider_host.cc +++ b/content/browser/service_worker/service_worker_provider_host.cc
@@ -46,10 +46,10 @@ if (!process) return; - mojo::MakeSelfOwnedReceiver( - std::make_unique<QuicTransportConnectorImpl>( - process_id, origin, net::NetworkIsolationKey(origin, origin)), - std::move(receiver)); + mojo::MakeSelfOwnedReceiver(std::make_unique<QuicTransportConnectorImpl>( + process_id, /*frame=*/nullptr, origin, + net::NetworkIsolationKey(origin, origin)), + std::move(receiver)); } } // anonymous namespace
diff --git a/content/browser/tracing/tracing_service_controller.cc b/content/browser/tracing/tracing_service_controller.cc index 8ce3ade..a7646b2f 100644 --- a/content/browser/tracing/tracing_service_controller.cc +++ b/content/browser/tracing/tracing_service_controller.cc
@@ -88,7 +88,6 @@ ServiceProcessHost::Launch( std::move(receiver), ServiceProcessHost::Options() - .WithSandboxType(service_manager::SandboxType::kUtility) .WithDisplayName("Tracing Service") .Pass()); }
diff --git a/content/browser/webtransport/quic_transport_connector_impl.cc b/content/browser/webtransport/quic_transport_connector_impl.cc index 0acddc5..8602ccd 100644 --- a/content/browser/webtransport/quic_transport_connector_impl.cc +++ b/content/browser/webtransport/quic_transport_connector_impl.cc
@@ -3,19 +3,61 @@ // found in the LICENSE file. #include "content/browser/webtransport/quic_transport_connector_impl.h" +#include "content/browser/devtools/devtools_instrumentation.h" #include "content/public/browser/render_process_host.h" #include "content/public/browser/storage_partition.h" +#include "mojo/public/cpp/bindings/self_owned_receiver.h" namespace content { +namespace { + +using network::mojom::QuicTransportHandshakeClient; + +class InterceptingHandshakeClient final : public QuicTransportHandshakeClient { + public: + InterceptingHandshakeClient( + base::WeakPtr<RenderFrameHostImpl> frame, + const GURL& url, + mojo::PendingRemote<QuicTransportHandshakeClient> remote) + : frame_(std::move(frame)), url_(url), remote_(std::move(remote)) {} + ~InterceptingHandshakeClient() override = default; + + // QuicTransportHandshakeClient implementation: + void OnConnectionEstablished( + mojo::PendingRemote<network::mojom::QuicTransport> transport, + mojo::PendingReceiver<network::mojom::QuicTransportClient> client) + override { + remote_->OnConnectionEstablished(std::move(transport), std::move(client)); + } + void OnHandshakeFailed() override { + remote_->OnHandshakeFailed(); + + if (RenderFrameHostImpl* frame = frame_.get()) { + devtools_instrumentation::OnQuicTransportHandshakeFailed(frame, url_); + } + } + + private: + const base::WeakPtr<RenderFrameHostImpl> frame_; + const GURL url_; + mojo::Remote<QuicTransportHandshakeClient> remote_; +}; + +} // namespace + QuicTransportConnectorImpl::QuicTransportConnectorImpl( int process_id, + base::WeakPtr<RenderFrameHostImpl> frame, const url::Origin& origin, const net::NetworkIsolationKey& network_isolation_key) : process_id_(process_id), + frame_(std::move(frame)), origin_(origin), network_isolation_key_(network_isolation_key) {} +QuicTransportConnectorImpl::~QuicTransportConnectorImpl() = default; + void QuicTransportConnectorImpl::Connect( const GURL& url, mojo::PendingRemote<network::mojom::QuicTransportHandshakeClient> @@ -24,8 +66,19 @@ if (!process) { return; } + + mojo::PendingRemote<QuicTransportHandshakeClient> handshake_client_to_pass; + // TODO(yhirano): Stop using MakeSelfOwnedReceiver here, because the + // QuicTransport implementation in the network service won't notice that + // the QuicTransportHandshakeClient is going away. + mojo::MakeSelfOwnedReceiver( + std::make_unique<InterceptingHandshakeClient>( + frame_, url, std::move(handshake_client)), + handshake_client_to_pass.InitWithNewPipeAndPassReceiver()); + process->GetStoragePartition()->GetNetworkContext()->CreateQuicTransport( - url, origin_, network_isolation_key_, std::move(handshake_client)); + url, origin_, network_isolation_key_, + std::move(handshake_client_to_pass)); } } // namespace content
diff --git a/content/browser/webtransport/quic_transport_connector_impl.h b/content/browser/webtransport/quic_transport_connector_impl.h index b7326128..cd5a8c0 100644 --- a/content/browser/webtransport/quic_transport_connector_impl.h +++ b/content/browser/webtransport/quic_transport_connector_impl.h
@@ -5,6 +5,7 @@ #ifndef CONTENT_BROWSER_WEBTRANSPORT_QUIC_TRANSPORT_CONNECTOR_IMPL_H_ #define CONTENT_BROWSER_WEBTRANSPORT_QUIC_TRANSPORT_CONNECTOR_IMPL_H_ +#include "base/memory/weak_ptr.h" #include "mojo/public/cpp/bindings/pending_remote.h" #include "net/base/network_isolation_key.h" #include "services/network/public/mojom/network_context.mojom.h" @@ -14,13 +15,20 @@ namespace content { +class RenderFrameHostImpl; + class QuicTransportConnectorImpl final : public blink::mojom::QuicTransportConnector { public: + // |frame| is needed for devtools - sometimes (e.g., the connector is for + // workers) there is not appropriate frame to associate, and in that case + // nullptr is provided. QuicTransportConnectorImpl( int process_id, + base::WeakPtr<RenderFrameHostImpl> frame, const url::Origin& origin, const net::NetworkIsolationKey& network_isolation_key); + ~QuicTransportConnectorImpl() override; void Connect(const GURL& url, mojo::PendingRemote<network::mojom::QuicTransportHandshakeClient> @@ -28,6 +36,7 @@ private: const int process_id_; + const base::WeakPtr<RenderFrameHostImpl> frame_; const url::Origin origin_; const net::NetworkIsolationKey network_isolation_key_; };
diff --git a/content/browser/worker_host/dedicated_worker_host.cc b/content/browser/worker_host/dedicated_worker_host.cc index fab014b4..179dbf0b 100644 --- a/content/browser/worker_host/dedicated_worker_host.cc +++ b/content/browser/worker_host/dedicated_worker_host.cc
@@ -385,10 +385,11 @@ // will soon be terminated too, so abort the connection. return; } - mojo::MakeSelfOwnedReceiver(std::make_unique<QuicTransportConnectorImpl>( - worker_process_host_->GetID(), worker_origin_, - isolation_info_.network_isolation_key()), - std::move(receiver)); + mojo::MakeSelfOwnedReceiver( + std::make_unique<QuicTransportConnectorImpl>( + worker_process_host_->GetID(), /*frame=*/nullptr, worker_origin_, + isolation_info_.network_isolation_key()), + std::move(receiver)); } void DedicatedWorkerHost::CreateWakeLockService(
diff --git a/content/browser/worker_host/shared_worker_host.cc b/content/browser/worker_host/shared_worker_host.cc index ab6078e..5350ebb 100644 --- a/content/browser/worker_host/shared_worker_host.cc +++ b/content/browser/worker_host/shared_worker_host.cc
@@ -339,10 +339,11 @@ mojo::PendingReceiver<blink::mojom::QuicTransportConnector> receiver) { DCHECK_CURRENTLY_ON(BrowserThread::UI); const url::Origin origin = url::Origin::Create(instance().url()); - mojo::MakeSelfOwnedReceiver(std::make_unique<QuicTransportConnectorImpl>( - worker_process_host_->GetID(), origin, - net::NetworkIsolationKey(origin, origin)), - std::move(receiver)); + mojo::MakeSelfOwnedReceiver( + std::make_unique<QuicTransportConnectorImpl>( + worker_process_host_->GetID(), /*frame=*/nullptr, origin, + net::NetworkIsolationKey(origin, origin)), + std::move(receiver)); } void SharedWorkerHost::BindCacheStorage(
diff --git a/content/browser/xr/service/xr_device_service.cc b/content/browser/xr/service/xr_device_service.cc index 2947351..5c70413 100644 --- a/content/browser/xr/service/xr_device_service.cc +++ b/content/browser/xr/service/xr_device_service.cc
@@ -28,8 +28,6 @@ content::ServiceProcessHost::Options() #if defined(OS_WIN) .WithSandboxType(service_manager::SandboxType::kXrCompositing) -#else - .WithSandboxType(service_manager::SandboxType::kUtility) #endif .WithDisplayName("Isolated XR Device Service") .Pass());
diff --git a/content/public/browser/content_browser_client.cc b/content/public/browser/content_browser_client.cc index a3743fc..37ada4e8 100644 --- a/content/public/browser/content_browser_client.cc +++ b/content/public/browser/content_browser_client.cc
@@ -305,9 +305,11 @@ return base::FilePath(); } -bool ContentBrowserClient::AllowAppCache(const GURL& manifest_url, - const GURL& first_party, - BrowserContext* context) { +bool ContentBrowserClient::AllowAppCache( + const GURL& manifest_url, + const GURL& site_for_cookies, + const base::Optional<url::Origin>& top_frame_origin, + BrowserContext* context) { return true; }
diff --git a/content/public/browser/content_browser_client.h b/content/public/browser/content_browser_client.h index 57b2172..cd07ed98 100644 --- a/content/public/browser/content_browser_client.h +++ b/content/public/browser/content_browser_client.h
@@ -581,9 +581,11 @@ // Allow the embedder to control if an AppCache can be used for the given url. // This is called on the UI thread. - virtual bool AllowAppCache(const GURL& manifest_url, - const GURL& first_party, - BrowserContext* context); + virtual bool AllowAppCache( + const GURL& manifest_url, + const GURL& site_for_cookies, + const base::Optional<url::Origin>& top_frame_origin, + BrowserContext* context); // Allows the embedder to control if a service worker is allowed at the given // |scope| and can be accessed from |site_for_cookies| and |top_frame_origin|.
diff --git a/content/public/browser/service_process_host.h b/content/public/browser/service_process_host.h index d051a79..acd93c4 100644 --- a/content/public/browser/service_process_host.h +++ b/content/public/browser/service_process_host.h
@@ -35,7 +35,6 @@ // constexpr auto kFooServiceIdleTimeout = base::TimeDelta::FromSeconds(5); // auto foo_service = ServiceProcessHost::Launch<foo::mojom::FooService>( // ServiceProcessHost::Options() -// .WithSandboxType(SandboxType::kUtility) // .WithDisplayName(IDS_FOO_SERVICE_DISPLAY_NAME) // .Pass()); // foo_service.set_idle_handler(
diff --git a/content/public/common/content_switch_dependent_feature_overrides.cc b/content/public/common/content_switch_dependent_feature_overrides.cc index 47cddab..27df27b 100644 --- a/content/public/common/content_switch_dependent_feature_overrides.cc +++ b/content/public/common/content_switch_dependent_feature_overrides.cc
@@ -36,6 +36,9 @@ std::cref(network::features::kCrossOriginOpenerPolicy), base::FeatureList::OVERRIDE_ENABLE_FEATURE}, {switches::kEnableExperimentalWebPlatformFeatures, + std::cref(network::features::kCrossOriginOpenerPolicyReporting), + base::FeatureList::OVERRIDE_ENABLE_FEATURE}, + {switches::kEnableExperimentalWebPlatformFeatures, std::cref(network::features::kCrossOriginEmbedderPolicy), base::FeatureList::OVERRIDE_ENABLE_FEATURE}, {switches::kEnableExperimentalWebPlatformFeatures,
diff --git a/content/test/data/accessibility/event/aria-hidden-changed-expected-uia-win.txt b/content/test/data/accessibility/event/aria-hidden-changed-expected-uia-win.txt index c6206d6..073c1f8 100644 --- a/content/test/data/accessibility/event/aria-hidden-changed-expected-uia-win.txt +++ b/content/test/data/accessibility/event/aria-hidden-changed-expected-uia-win.txt
@@ -1,3 +1,3 @@ -AriaProperties changed on role=document AriaProperties changed on role=heading, name=Item2 +AriaProperties changed on role=heading, name=Item3 AriaProperties changed on role=heading, name=Item4
diff --git a/content/test/data/accessibility/event/aria-selected-changed-expected-uia-win.txt b/content/test/data/accessibility/event/aria-selected-changed-expected-uia-win.txt index 1bb067b..432ded8 100644 --- a/content/test/data/accessibility/event/aria-selected-changed-expected-uia-win.txt +++ b/content/test/data/accessibility/event/aria-selected-changed-expected-uia-win.txt
@@ -13,7 +13,7 @@ SelectionItem_ElementSelected on role=gridcell, name=Grid4, GridCell2 === Start Continuation === === Start Continuation === -AriaProperties changed on role=combobox +AriaProperties changed on role=listitem, name=Select2, Option1 AriaProperties changed on role=listitem, name=Select2, Option2 SelectionItem_ElementSelected on role=listitem, name=Select2, Option2 ValueValue changed on role=combobox
diff --git a/content/test/data/accessibility/event/menulist-collapse-expected-uia-win.txt b/content/test/data/accessibility/event/menulist-collapse-expected-uia-win.txt index 6587810..3b9c78b 100644 --- a/content/test/data/accessibility/event/menulist-collapse-expected-uia-win.txt +++ b/content/test/data/accessibility/event/menulist-collapse-expected-uia-win.txt
@@ -1,6 +1,6 @@ AutomationFocusChanged on role=combobox AutomationFocusChanged on role=combobox === Start Continuation === -AriaProperties changed on role=combobox -SelectionItem_ElementRemovedFromSelection on role=combobox +AriaProperties changed on role=listitem, name=Apple +SelectionItem_ElementRemovedFromSelection on role=listitem, name=Apple ValueValue changed on role=combobox
diff --git a/content/test/data/accessibility/event/menulist-collapse-expected-uia-win7.txt b/content/test/data/accessibility/event/menulist-collapse-expected-uia-win7.txt index 6587810..5309132 100644 --- a/content/test/data/accessibility/event/menulist-collapse-expected-uia-win7.txt +++ b/content/test/data/accessibility/event/menulist-collapse-expected-uia-win7.txt
@@ -1,6 +1,7 @@ AutomationFocusChanged on role=combobox AutomationFocusChanged on role=combobox === Start Continuation === -AriaProperties changed on role=combobox -SelectionItem_ElementRemovedFromSelection on role=combobox +AriaProperties changed on role=listitem, name=Apple +AutomationFocusChanged on role=combobox +SelectionItem_ElementRemovedFromSelection on role=listitem, name=Apple ValueValue changed on role=combobox
diff --git a/content/test/data/accessibility/event/menulist-collapse-next-expected-uia-win.txt b/content/test/data/accessibility/event/menulist-collapse-next-expected-uia-win.txt index 440bad2..c7276f4 100644 --- a/content/test/data/accessibility/event/menulist-collapse-next-expected-uia-win.txt +++ b/content/test/data/accessibility/event/menulist-collapse-next-expected-uia-win.txt
@@ -1,7 +1,7 @@ AutomationFocusChanged on role=combobox AutomationFocusChanged on role=combobox === Start Continuation === -AriaProperties changed on role=combobox +AriaProperties changed on role=listitem, name=Apple AriaProperties changed on role=listitem, name=Orange SelectionItem_ElementSelected on role=listitem, name=Orange ValueValue changed on role=combobox
diff --git a/content/test/data/accessibility/event/menulist-collapse-next-expected-uia-win7.txt b/content/test/data/accessibility/event/menulist-collapse-next-expected-uia-win7.txt index 098dd7d..5b89bc5 100644 --- a/content/test/data/accessibility/event/menulist-collapse-next-expected-uia-win7.txt +++ b/content/test/data/accessibility/event/menulist-collapse-next-expected-uia-win7.txt
@@ -1,7 +1,7 @@ AutomationFocusChanged on role=combobox AutomationFocusChanged on role=combobox === Start Continuation === -AriaProperties changed on role=combobox +AriaProperties changed on role=listitem, name=Apple AriaProperties changed on role=listitem, name=Orange AutomationFocusChanged on role=combobox SelectionItem_ElementSelected on role=listitem, name=Orange
diff --git a/content/test/data/accessibility/event/visibility-hidden-changed-expected-uia-win.txt b/content/test/data/accessibility/event/visibility-hidden-changed-expected-uia-win.txt index b9b6f51d1..d5810d5 100644 --- a/content/test/data/accessibility/event/visibility-hidden-changed-expected-uia-win.txt +++ b/content/test/data/accessibility/event/visibility-hidden-changed-expected-uia-win.txt
@@ -1,4 +1,4 @@ -AriaProperties changed on role=document -AriaProperties changed on role=document +AriaProperties changed on role=heading, name=Item1 AriaProperties changed on role=heading, name=Item2 +AriaProperties changed on role=heading, name=Item3 AriaProperties changed on role=heading, name=Item4
diff --git a/content/test/data/accessibility/event/visibility-hidden-changed-expected-uia-win7.txt b/content/test/data/accessibility/event/visibility-hidden-changed-expected-uia-win7.txt deleted file mode 100644 index c6206d6..0000000 --- a/content/test/data/accessibility/event/visibility-hidden-changed-expected-uia-win7.txt +++ /dev/null
@@ -1,3 +0,0 @@ -AriaProperties changed on role=document -AriaProperties changed on role=heading, name=Item2 -AriaProperties changed on role=heading, name=Item4
diff --git a/content/test/data/accessibility/html/canvas-fallback-expected-uia-win.txt b/content/test/data/accessibility/html/canvas-fallback-expected-uia-win.txt index 5b2328f..9588e63 100644 --- a/content/test/data/accessibility/html/canvas-fallback-expected-uia-win.txt +++ b/content/test/data/accessibility/html/canvas-fallback-expected-uia-win.txt
@@ -10,7 +10,7 @@ ++++++Group Name='Visibility hidden paragraph in fallback content' ++++++++Text Name='This is another paragraph in fallback' ++++++Text Name='<newline> ' -++++++Text Name='Aria hidden paragraph in fallback content' IsControlElement=false +++++++Text Name='Aria hidden paragraph in fallback content' ++++++++Text Name='Aria hidden paragraph in fallback content' IsControlElement=false ++++++Text Name='<newline> ' ++++++Text IsControlElement=false
diff --git a/fuchsia/engine/web_engine_debug_integration_test.cc b/fuchsia/engine/web_engine_debug_integration_test.cc index c474c24..3dd1fe35 100644 --- a/fuchsia/engine/web_engine_debug_integration_test.cc +++ b/fuchsia/engine/web_engine_debug_integration_test.cc
@@ -52,7 +52,13 @@ web_context_provider_.set_error_handler( [](zx_status_t status) { ADD_FAILURE(); }); - WaitForWebEngine(); + // Wait for the OnDirectoryReady event, which indicates that the component's + // outgoing directory is available, including the "/debug" contents accessed + // via the Hub. + base::RunLoop directory_loop; + web_engine_controller_.events().OnDirectoryReady = + [quit_loop = directory_loop.QuitClosure()]() { quit_loop.Run(); }; + directory_loop.Run(); // Enumerate all entries in /hub/c/context_provider.cmx to find WebEngine // instance with |test_arg|. @@ -96,36 +102,6 @@ } protected: - void WaitForWebEngine() { - // Create a throwaway web context to ensure the WebEngine process is - // initialized and a Debug instance can be created. This is necessary - // because the Debug service is not available on the debug directory until - // after the WebEngine is fully initialized. - fuchsia::web::CreateContextParams create_params; - auto directory = base::fuchsia::OpenDirectory( - base::FilePath(base::fuchsia::kServiceDirectoryPath)); - ASSERT_TRUE(directory.is_valid()); - create_params.set_service_directory(std::move(directory)); - - fuchsia::web::ContextPtr web_context; - web_context_provider_->Create(std::move(create_params), - web_context.NewRequest()); - web_context.set_error_handler([](zx_status_t status) { ADD_FAILURE(); }); - - base::RunLoop run_loop; - cr_fuchsia::ResultReceiver< - fuchsia::web::Context_GetRemoteDebuggingPort_Result> - port_receiver(run_loop.QuitClosure()); - web_context->GetRemoteDebuggingPort( - cr_fuchsia::CallbackToFitFunction(port_receiver.GetReceiveCallback())); - run_loop.Run(); - - // Sanity check. - ASSERT_TRUE(port_receiver->is_err()); - ASSERT_EQ(port_receiver->err(), - fuchsia::web::ContextError::REMOTE_DEBUGGING_PORT_NOT_OPENED); - } - base::test::SingleThreadTaskEnvironment task_environment_{ base::test::SingleThreadTaskEnvironment::MainThreadType::IO}; @@ -133,8 +109,7 @@ fidl::Binding<fuchsia::web::DevToolsListener> dev_tools_listener_binding_; std::unique_ptr<sys::ServiceDirectory> debug_dir_; fuchsia::web::ContextProviderPtr web_context_provider_; - fidl::InterfaceHandle<fuchsia::sys::ComponentController> - web_engine_controller_; + fuchsia::sys::ComponentControllerPtr web_engine_controller_; fuchsia::web::DebugSyncPtr debug_; base::OnceClosure on_url_fetch_complete_ack_;
diff --git a/infra/config/generated/commit-queue.cfg b/infra/config/generated/commit-queue.cfg index 6c69a00b..3b87b7e 100644 --- a/infra/config/generated/commit-queue.cfg +++ b/infra/config/generated/commit-queue.cfg
@@ -813,7 +813,12 @@ > builders: < name: "chromium/try/linux-perfetto-rel" - includable_only: true + experiment_percentage: 100 + location_regexp: ".+/[+]/base/trace_event/.+" + location_regexp: ".+/[+]/base/tracing/.+" + location_regexp: ".+/[+]/components/tracing/.+" + location_regexp: ".+/[+]/content/browser/tracing/.+" + location_regexp: ".+/[+]/services/tracing/.+" > builders: < name: "chromium/try/linux-rel"
diff --git a/infra/config/generated/cq-builders.md b/infra/config/generated/cq-builders.md index 8e797e6..cd9adb9e 100644 --- a/infra/config/generated/cq-builders.md +++ b/infra/config/generated/cq-builders.md
@@ -339,6 +339,16 @@ * [fuchsia-compile-x64-dbg](https://ci.chromium.org/p/chromium/builders/try/fuchsia-compile-x64-dbg) ([definition](https://cs.chromium.org/search?q=package:%5Echromium$+file:/cq.star$+-file:/beta/+-file:/stable/+fuchsia-compile-x64-dbg)) ([matching builders](https://cs.chromium.org/search?q=+file:trybots.py+fuchsia-compile-x64-dbg)) * Experiment percentage: 50 +* [linux-perfetto-rel](https://ci.chromium.org/p/chromium/builders/try/linux-perfetto-rel) ([definition](https://cs.chromium.org/search?q=package:%5Echromium$+file:/cq.star$+-file:/beta/+-file:/stable/+linux-perfetto-rel)) ([matching builders](https://cs.chromium.org/search?q=+file:trybots.py+linux-perfetto-rel)) + * Experiment percentage: 100 + + Path regular expressions: + * [`//base/trace_event/.+`](https://cs.chromium.org/chromium/src/base/trace_event/) + * [`//base/tracing/.+`](https://cs.chromium.org/chromium/src/base/tracing/) + * [`//components/tracing/.+`](https://cs.chromium.org/chromium/src/components/tracing/) + * [`//content/browser/tracing/.+`](https://cs.chromium.org/chromium/src/content/browser/tracing/) + * [`//services/tracing/.+`](https://cs.chromium.org/chromium/src/services/tracing/) + * [mac-coverage-rel](https://ci.chromium.org/p/chromium/builders/try/mac-coverage-rel) ([definition](https://cs.chromium.org/search?q=package:%5Echromium$+file:/cq.star$+-file:/beta/+-file:/stable/+mac-coverage-rel)) ([matching builders](https://cs.chromium.org/search?q=+file:trybots.py+mac-coverage-rel)) * Experiment percentage: 3
diff --git a/infra/config/subprojects/chromium/try.star b/infra/config/subprojects/chromium/try.star index 3da2cd5..c6a2465 100644 --- a/infra/config/subprojects/chromium/try.star +++ b/infra/config/subprojects/chromium/try.star
@@ -377,6 +377,16 @@ try_.chromium_linux_builder( name = 'linux-perfetto-rel', + tryjob = try_.job( + experiment_percentage = 100, + location_regexp = [ + '.+/[+]/base/trace_event/.+', + '.+/[+]/base/tracing/.+', + '.+/[+]/components/tracing/.+', + '.+/[+]/content/browser/tracing/.+', + '.+/[+]/services/tracing/.+', + ], + ), ) try_.chromium_linux_builder(
diff --git a/ios/build/chrome_build.gni b/ios/build/chrome_build.gni index e1e42cf..95b3cbf 100644 --- a/ios/build/chrome_build.gni +++ b/ios/build/chrome_build.gni
@@ -21,7 +21,12 @@ # Overridden when using the Google-internal repository to build Chrome on iOS. ios_account_verification_provider_target = "//ios/chrome/common/credential_provider:account_verification_provider_implementation" - # Enable multi-window configuration in Info.plist + # Enable use of SceneDelegate-driven startup flow in + # Info.plist. + ios_enable_scene_startup = false + + # Enable multi-window configuration in Info.plist. Includes all the effects of + # setting |ios_enable_scene_startup| to |true|. ios_enable_multi_window = false # Value of the encryption export compliance code. See "Cryptography and
diff --git a/ios/chrome/app/BUILD.gn b/ios/chrome/app/BUILD.gn index 7c87115..0d6f14b 100644 --- a/ios/chrome/app/BUILD.gn +++ b/ios/chrome/app/BUILD.gn
@@ -91,7 +91,9 @@ info_plists += [ "resources/EncryptionExportCompliance+Info.plist" ] } if (ios_enable_multi_window) { - info_plists += [ "resources/MultiWindow+Info.plist" ] + info_plists += [ "resources/MultiWindowEnabled+Info.plist" ] + } else if (ios_enable_scene_startup) { + info_plists += [ "resources/MultiWindowDisabled+Info.plist" ] } args = [ "--breakpad=$breakpad_enabled_as_int",
diff --git a/ios/chrome/app/application_delegate/app_state.mm b/ios/chrome/app/application_delegate/app_state.mm index 541534f6..4ca4745 100644 --- a/ios/chrome/app/application_delegate/app_state.mm +++ b/ios/chrome/app/application_delegate/app_state.mm
@@ -159,7 +159,7 @@ _mainApplicationDelegate = applicationDelegate; if (@available(iOS 13, *)) { - if (IsMultiwindowSupported()) { + if (IsSceneStartupSupported()) { // Subscribe for scene activation notifications. [[NSNotificationCenter defaultCenter] addObserver:self @@ -515,9 +515,9 @@ } - (NSArray<SceneState*>*)connectedScenes { - if (IsMultiwindowSupported()) { - NSMutableArray* sceneStates = [[NSMutableArray alloc] init]; + if (IsSceneStartupSupported()) { if (@available(iOS 13, *)) { + NSMutableArray* sceneStates = [[NSMutableArray alloc] init]; NSSet* connectedScenes = [UIApplication sharedApplication].connectedScenes; for (UIWindowScene* scene in connectedScenes) { @@ -530,8 +530,10 @@ base::mac::ObjCCastStrict<SceneDelegate>(scene.delegate); [sceneStates addObject:sceneDelegate.sceneState]; } + return sceneStates; } - return sceneStates; + NOTREACHED(); + return @[]; } else { return @[ self.mainSceneState ]; } @@ -593,7 +595,7 @@ // Handler for UISceneDidActivateNotification. - (void)sceneDidActivate:(NSNotification*)notification { - DCHECK(IsMultiwindowSupported()); + DCHECK(IsSceneStartupSupported()); if (@available(iOS 13, *)) { if (!self.firstSceneHasActivated) { self.firstSceneHasActivated = YES;
diff --git a/ios/chrome/app/main_application_delegate.mm b/ios/chrome/app/main_application_delegate.mm index 1da1713..f69b62b5 100644 --- a/ios/chrome/app/main_application_delegate.mm +++ b/ios/chrome/app/main_application_delegate.mm
@@ -75,10 +75,10 @@ [_mainController setAppState:_appState]; [_appState addObserver:_mainController]; - if (!IsMultiwindowSupported()) { - // When multiwindow is not supported, this object holds a "scene" state - // and a "scene" controller. This allows the rest of the app to be mostly - // multiwindow-agnostic. + if (!IsSceneStartupSupported()) { + // When the UIScene APU is not supported, this object holds a "scene" + // state and a "scene" controller. This allows the rest of the app to be + // mostly multiwindow-agnostic. _sceneState = [[SceneState alloc] init]; _appState.mainSceneState = _sceneState; _sceneController = @@ -125,12 +125,12 @@ BOOL requiresHandling = [_appState requiresHandlingAfterLaunchWithOptions:launchOptions stateBackground:inBackground]; - if (!IsMultiwindowSupported()) { + if (!IsSceneStartupSupported()) { self.sceneState.activationLevel = SceneActivationLevelForegroundInactive; } if (@available(iOS 13, *)) { - if (IsMultiwindowSupported()) { + if (IsSceneStartupSupported()) { [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(sceneWillConnect:) @@ -148,7 +148,7 @@ } - (void)applicationDidBecomeActive:(UIApplication*)application { - if (!IsMultiwindowSupported()) { + if (!IsSceneStartupSupported()) { self.sceneState.activationLevel = SceneActivationLevelForegroundActive; } @@ -161,7 +161,7 @@ } - (void)applicationWillResignActive:(UIApplication*)application { - if (!IsMultiwindowSupported()) { + if (!IsSceneStartupSupported()) { self.sceneState.activationLevel = SceneActivationLevelForegroundInactive; } @@ -174,7 +174,7 @@ // Called when going into the background. iOS already broadcasts, so // stakeholders can register for it directly. - (void)applicationDidEnterBackground:(UIApplication*)application { - if (!IsMultiwindowSupported()) { + if (!IsSceneStartupSupported()) { self.sceneState.activationLevel = SceneActivationLevelBackground; } @@ -186,7 +186,7 @@ // Called when returning to the foreground. - (void)applicationWillEnterForeground:(UIApplication*)application { - if (!IsMultiwindowSupported()) { + if (!IsSceneStartupSupported()) { self.sceneState.activationLevel = SceneActivationLevelForegroundInactive; } @@ -215,7 +215,7 @@ #pragma mark - Scenes lifecycle - (NSInteger)foregroundSceneCount { - DCHECK(IsMultiwindowSupported()); + DCHECK(IsSceneStartupSupported()); if (@available(iOS 13, *)) { NSInteger foregroundSceneCount = 0; for (UIScene* scene in UIApplication.sharedApplication.connectedScenes) { @@ -230,7 +230,7 @@ } - (void)sceneWillConnect:(NSNotification*)notification { - DCHECK(IsMultiwindowSupported()); + DCHECK(IsSceneStartupSupported()); if (@available(iOS 13, *)) { UIWindowScene* scene = (UIWindowScene*)notification.object; SceneDelegate* sceneDelegate = (SceneDelegate*)scene.delegate; @@ -251,7 +251,7 @@ } - (void)sceneDidEnterBackground:(NSNotification*)notification { - DCHECK(IsMultiwindowSupported()); + DCHECK(IsSceneStartupSupported()); if (@available(iOS 13, *)) { // When the first scene enters foreground, update the app state. if (self.foregroundSceneCount == 0) {
diff --git a/ios/chrome/app/main_controller.mm b/ios/chrome/app/main_controller.mm index 3fb73ba..090d2b8 100644 --- a/ios/chrome/app/main_controller.mm +++ b/ios/chrome/app/main_controller.mm
@@ -386,7 +386,7 @@ [ProviderRegistration registerProviders]; if (@available(iOS 13, *)) { - if (IsMultiwindowSupported()) { + if (IsSceneStartupSupported()) { // Subscribe for scene connection and disconnection notifications. [[NSNotificationCenter defaultCenter] addObserver:self @@ -557,7 +557,7 @@ postCrashLaunch]; if (@available(iOS 13, *)) { - if (IsMultiwindowSupported()) { + if (IsSceneStartupSupported()) { // The rest of the startup sequence is handled by the Scenes and in // response to notifications. return; @@ -622,7 +622,7 @@ // Handler for UISceneWillConnectNotification. - (void)sceneWillConnect:(NSNotification*)notification { - DCHECK(IsMultiwindowSupported()); + DCHECK(IsSceneStartupSupported()); if (@available(iOS 13, *)) { UIWindowScene* scene = base::mac::ObjCCastStrict<UIWindowScene>(notification.object);
diff --git a/ios/chrome/app/resources/BUILD.gn b/ios/chrome/app/resources/BUILD.gn index 98b9b59..06a8372 100644 --- a/ios/chrome/app/resources/BUILD.gn +++ b/ios/chrome/app/resources/BUILD.gn
@@ -122,12 +122,11 @@ ] } -if (ios_enable_multi_window) { - # Multi window requires both additional plist entries (handled in ../BUILD.gn) and - # an additional storyboard file. - bundle_data_ib_file("base_scene_storyboard") { - source = "BaseScene.storyboard" - } +# The scene startup flow (which is needed for multi-window) requires both +# additional plist entries (handled in ../BUILD.gn) and an additional storyboard +# file. +bundle_data_ib_file("base_scene_storyboard") { + source = "BaseScene.storyboard" } bundle_data_ib_file("launchscreen_xib") {
diff --git a/ios/chrome/app/resources/MultiWindowDisabled+Info.plist b/ios/chrome/app/resources/MultiWindowDisabled+Info.plist new file mode 100644 index 0000000..4d25065 --- /dev/null +++ b/ios/chrome/app/resources/MultiWindowDisabled+Info.plist
@@ -0,0 +1,29 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>UIApplicationSceneManifest</key> + <dict> + <key>UIApplicationSupportsMultipleScenes</key> + <false/> + <key>UISceneConfigurations</key> + <dict> + <key>UIWindowSceneSessionRoleApplication</key> + <array> + <dict> + <key>UISceneClassName</key> + <string>UIWindowScene</string> + <key>UISceneDelegateClassName</key> + <string>SceneDelegate</string> + <key>UISceneConfigurationName</key> + <string>Default Configuration</string> + <key>UILaunchStoryboardName</key> + <string>LaunchScreen</string> + <key>UISceneStoryboardFile</key> + <string>BaseScene</string> + </dict> + </array> + </dict> + </dict> +</dict> +</plist> \ No newline at end of file
diff --git a/ios/chrome/app/resources/MultiWindow+Info.plist b/ios/chrome/app/resources/MultiWindowEnabled+Info.plist similarity index 100% rename from ios/chrome/app/resources/MultiWindow+Info.plist rename to ios/chrome/app/resources/MultiWindowEnabled+Info.plist
diff --git a/ios/chrome/browser/ui/authentication/signin/signin_constants.h b/ios/chrome/browser/ui/authentication/signin/signin_constants.h index b225ddb..74a0089 100644 --- a/ios/chrome/browser/ui/authentication/signin/signin_constants.h +++ b/ios/chrome/browser/ui/authentication/signin/signin_constants.h
@@ -34,6 +34,14 @@ extern NSString* const kUserSigninAttemptedNotification; // Name of accessibility identifier for the skip sign-in button. extern NSString* const kSkipSigninAccessibilityIdentifier; +// Name of accessibility identifier for the add account button in the sign-in +// flow. +extern NSString* const kAddAccountAccessibilityIdentifier; +// Name of accessibility identifier for the confirmation "Yes I'm In" sign-in +// button. +extern NSString* const kConfirmationAccessibilityIdentifier; +// Name of accessibility identifier for the more button in the sign-in flow. +extern NSString* const kMoreAccessibilityIdentifier; // Action that is required to do to complete the sign-in. This action is in // charge of the SigninCoordinator's owner.
diff --git a/ios/chrome/browser/ui/authentication/signin/signin_constants.mm b/ios/chrome/browser/ui/authentication/signin/signin_constants.mm index cabc03b..012ad0e 100644 --- a/ios/chrome/browser/ui/authentication/signin/signin_constants.mm +++ b/ios/chrome/browser/ui/authentication/signin/signin_constants.mm
@@ -11,6 +11,11 @@ NSString* const kUserSigninAttemptedNotification = @"kUserSigninAttempted"; NSString* const kSkipSigninAccessibilityIdentifier = @"kSkipSigninAccessibilityIdentifier"; +NSString* const kAddAccountAccessibilityIdentifier = + @"kAddAccountAccessibilityIdentifier"; +NSString* const kConfirmationAccessibilityIdentifier = + @"kConfirmationAccessibilityIdentifier"; +NSString* const kMoreAccessibilityIdentifier = @"kMoreAccessibilityIdentifier"; @implementation SigninCompletionInfo
diff --git a/ios/chrome/browser/ui/authentication/signin/user_signin/user_signin_view_controller.mm b/ios/chrome/browser/ui/authentication/signin/user_signin/user_signin_view_controller.mm index 03bccc965..cb57ac3 100644 --- a/ios/chrome/browser/ui/authentication/signin/user_signin/user_signin_view_controller.mm +++ b/ios/chrome/browser/ui/authentication/signin/user_signin/user_signin_view_controller.mm
@@ -122,17 +122,23 @@ forState:UIControlStateNormal]; [self setConfirmationStylingWithButton:self.confirmationButton]; self.confirmationButton.tag = AuthenticationButtonTypeAddAccount; + self.confirmationButton.accessibilityIdentifier = + kAddAccountAccessibilityIdentifier; } else if (!self.hasUnifiedConsentScreenReachedBottom) { // User has not scrolled to the bottom of the user consent screen. // Display 'more' button. [self updateButtonAsMoreButton:self.confirmationButton]; self.confirmationButton.tag = AuthenticationButtonTypeMore; + self.confirmationButton.accessibilityIdentifier = + kMoreAccessibilityIdentifier; } else { // By default display 'Yes I'm in' button. [self.confirmationButton setTitle:self.confirmationButtonTitle forState:UIControlStateNormal]; [self setConfirmationStylingWithButton:self.confirmationButton]; self.confirmationButton.tag = AuthenticationButtonTypeConfirmation; + self.confirmationButton.accessibilityIdentifier = + kConfirmationAccessibilityIdentifier; } [self.confirmationButton addTarget:self action:@selector(onConfirmationButtonPressed:)
diff --git a/ios/chrome/browser/ui/main/BUILD.gn b/ios/chrome/browser/ui/main/BUILD.gn index f6c4a42..aac15b3e 100644 --- a/ios/chrome/browser/ui/main/BUILD.gn +++ b/ios/chrome/browser/ui/main/BUILD.gn
@@ -141,7 +141,7 @@ "//net", ] - if (ios_enable_multi_window) { + if (ios_enable_multi_window || ios_enable_scene_startup) { deps += [ "//ios/chrome/app/resources:base_scene_storyboard" ] }
diff --git a/ios/chrome/browser/ui/main/scene_controller.mm b/ios/chrome/browser/ui/main/scene_controller.mm index b7ce43cc..994ab30 100644 --- a/ios/chrome/browser/ui/main/scene_controller.mm +++ b/ios/chrome/browser/ui/main/scene_controller.mm
@@ -206,7 +206,7 @@ // should be created right away. // When multiwindow is supported, the window is created by SceneDelegate, // and fetched by SceneState from UIScene's windows. - if (!IsMultiwindowSupported() && !self.sceneState.window) { + if (!IsSceneStartupSupported() && !self.sceneState.window) { self.sceneState.window = [[ChromeOverlayWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; } @@ -287,9 +287,9 @@ } DCHECK(self.mainController); - if (IsMultiwindowSupported()) { + if (IsSceneStartupSupported()) { // TODO(crbug.com/1012697): This should probably be the only code path for - // multiwindow and non-multiwindow cases. + // UIScene and non-UIScene cases. [self startUpChromeUIPostCrash:NO needRestoration:NO]; }
diff --git a/ios/chrome/browser/ui/main/scene_state.mm b/ios/chrome/browser/ui/main/scene_state.mm index 125d70dc..7867877 100644 --- a/ios/chrome/browser/ui/main/scene_state.mm +++ b/ios/chrome/browser/ui/main/scene_state.mm
@@ -65,7 +65,7 @@ } - (void)setWindow:(UIWindow*)window { - if (IsMultiwindowSupported()) { + if (IsSceneStartupSupported()) { // No need to set anything, instead the getter is backed by scene.windows // property. return; @@ -74,7 +74,7 @@ } - (UIWindow*)window { - if (IsMultiwindowSupported()) { + if (IsSceneStartupSupported()) { UIWindow* mainWindow = nil; if (@available(ios 13, *)) { for (UIWindow* window in self.scene.windows) {
diff --git a/ios/chrome/browser/ui/omnibox/omnibox_egtest.mm b/ios/chrome/browser/ui/omnibox/omnibox_egtest.mm index 82bbe06..9c04076 100644 --- a/ios/chrome/browser/ui/omnibox/omnibox_egtest.mm +++ b/ios/chrome/browser/ui/omnibox/omnibox_egtest.mm
@@ -476,8 +476,7 @@ // TODO(crbug.com/1046787): Test is failing for EG1. #if defined(CHROME_EARL_GREY_1) - if (![ChromeEarlGrey isIPadIdiom] && - base::ios::IsRunningOnOrLater(13, 3, 0)) { + if (![ChromeEarlGrey isIPadIdiom]) { EARL_GREY_TEST_SKIPPED(@"Test skipped on Earl Grey 1."); } #endif
diff --git a/ios/chrome/browser/ui/page_info/BUILD.gn b/ios/chrome/browser/ui/page_info/BUILD.gn index f651c11..78d434d 100644 --- a/ios/chrome/browser/ui/page_info/BUILD.gn +++ b/ios/chrome/browser/ui/page_info/BUILD.gn
@@ -7,16 +7,8 @@ sources = [ "legacy_page_info_view_controller.h", "legacy_page_info_view_controller.mm", - "page_info_consumer.h", - "page_info_cookies_view_controller.h", - "page_info_cookies_view_controller.mm", - "page_info_description.h", - "page_info_description.mm", - "page_info_navigation_commands.h", "page_info_site_security_description.h", "page_info_site_security_description.mm", - "page_info_site_security_view_controller.h", - "page_info_site_security_view_controller.mm", "page_info_view_controller.h", "page_info_view_controller.mm", ] @@ -77,8 +69,6 @@ "page_info_coordinator.mm", "page_info_legacy_coordinator.h", "page_info_legacy_coordinator.mm", - "page_info_mediator.h", - "page_info_mediator.mm", "page_info_site_security_mediator.h", "page_info_site_security_mediator.mm", ]
diff --git a/ios/chrome/browser/ui/page_info/page_info_consumer.h b/ios/chrome/browser/ui/page_info/page_info_consumer.h deleted file mode 100644 index a299867..0000000 --- a/ios/chrome/browser/ui/page_info/page_info_consumer.h +++ /dev/null
@@ -1,18 +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 IOS_CHROME_BROWSER_UI_PAGE_INFO_PAGE_INFO_CONSUMER_H_ -#define IOS_CHROME_BROWSER_UI_PAGE_INFO_PAGE_INFO_CONSUMER_H_ - -#import "ios/chrome/browser/ui/page_info/page_info_description.h" - -// A consumer for page info changes. -@protocol PageInfoConsumer - -// Called when the page info has changed. -- (void)pageInfoChanged:(PageInfoDescription*)pageInfoDescription; - -@end - -#endif // IOS_CHROME_BROWSER_UI_PAGE_INFO_PAGE_INFO_CONSUMER_H_
diff --git a/ios/chrome/browser/ui/page_info/page_info_cookies_view_controller.h b/ios/chrome/browser/ui/page_info/page_info_cookies_view_controller.h deleted file mode 100644 index c30c4a8..0000000 --- a/ios/chrome/browser/ui/page_info/page_info_cookies_view_controller.h +++ /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. - -#ifndef IOS_CHROME_BROWSER_UI_PAGE_INFO_PAGE_INFO_COOKIES_VIEW_CONTROLLER_H_ -#define IOS_CHROME_BROWSER_UI_PAGE_INFO_PAGE_INFO_COOKIES_VIEW_CONTROLLER_H_ - -#import "ios/chrome/browser/ui/table_view/chrome_table_view_controller.h" - -// View Controller for displaying Cookies information. -@interface PageInfoCookiesViewController : ChromeTableViewController - -@end - -#endif // IOS_CHROME_BROWSER_UI_PAGE_INFO_PAGE_INFO_COOKIES_VIEW_CONTROLLER_H_
diff --git a/ios/chrome/browser/ui/page_info/page_info_cookies_view_controller.mm b/ios/chrome/browser/ui/page_info/page_info_cookies_view_controller.mm deleted file mode 100644 index 47612ba..0000000 --- a/ios/chrome/browser/ui/page_info/page_info_cookies_view_controller.mm +++ /dev/null
@@ -1,60 +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. - -#import "ios/chrome/browser/ui/page_info/page_info_cookies_view_controller.h" - -#import "ios/chrome/browser/ui/settings/cells/settings_switch_item.h" -#import "ios/chrome/browser/ui/util/uikit_ui_util.h" -#import "ios/chrome/common/ui/colors/UIColor+cr_semantic_colors.h" -#import "ios/chrome/common/ui/colors/semantic_color_names.h" -#import "ios/chrome/common/ui/util/constraints_ui_util.h" -#include "ios/chrome/grit/ios_strings.h" -#include "ui/base/l10n/l10n_util.h" - -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - -namespace { - -typedef NS_ENUM(NSInteger, SectionIdentifier) { - SectionIdentifierContent = kSectionIdentifierEnumZero, -}; - -typedef NS_ENUM(NSInteger, ItemType) { - ItemTypeCookiesSwitch = kItemTypeEnumZero, -}; - -} // namespace - -@implementation PageInfoCookiesViewController - -#pragma mark - UIViewController - -- (void)viewDidLoad { - [super viewDidLoad]; - - self.view.backgroundColor = [UIColor colorNamed:kBackgroundColor]; - self.title = l10n_util::GetNSString(IDS_IOS_PAGE_INFO_COOKIES_TITLE); - - [self loadModel]; -} - -#pragma mark - ChromeTableViewController - -- (void)loadModel { - [super loadModel]; - [self.tableViewModel addSectionWithIdentifier:SectionIdentifierContent]; - - // Create the switch item. - SettingsSwitchItem* cookiesSwitchItem = - [[SettingsSwitchItem alloc] initWithType:ItemTypeCookiesSwitch]; - cookiesSwitchItem.text = - l10n_util::GetNSString(IDS_IOS_PAGE_INFO_COOKIES_SWITCH_LABEL); - [self.tableViewModel addItem:cookiesSwitchItem - toSectionWithIdentifier:SectionIdentifierContent]; - // TODO(crbug.com/1063824): Implement this. -} - -@end
diff --git a/ios/chrome/browser/ui/page_info/page_info_coordinator.mm b/ios/chrome/browser/ui/page_info/page_info_coordinator.mm index 0046321..5c4893a 100644 --- a/ios/chrome/browser/ui/page_info/page_info_coordinator.mm +++ b/ios/chrome/browser/ui/page_info/page_info_coordinator.mm
@@ -6,14 +6,8 @@ #include "ios/chrome/browser/main/browser.h" #import "ios/chrome/browser/reading_list/offline_page_tab_helper.h" -#import "ios/chrome/browser/ui/commands/browser_commands.h" -#import "ios/chrome/browser/ui/commands/command_dispatcher.h" -#import "ios/chrome/browser/ui/page_info/page_info_cookies_view_controller.h" -#import "ios/chrome/browser/ui/page_info/page_info_mediator.h" -#import "ios/chrome/browser/ui/page_info/page_info_navigation_commands.h" #import "ios/chrome/browser/ui/page_info/page_info_site_security_description.h" #import "ios/chrome/browser/ui/page_info/page_info_site_security_mediator.h" -#import "ios/chrome/browser/ui/page_info/page_info_site_security_view_controller.h" #import "ios/chrome/browser/ui/page_info/page_info_view_controller.h" #import "ios/chrome/browser/web_state_list/web_state_list.h" #include "ios/web/public/navigation/navigation_item.h" @@ -24,11 +18,10 @@ #error "This file requires ARC support." #endif -@interface PageInfoCoordinator () <PageInfoNavigationCommands> +@interface PageInfoCoordinator () @property(nonatomic, strong) CommandDispatcher* dispatcher; @property(nonatomic, strong) PageInfoViewController* viewController; -@property(nonatomic, strong) PageInfoMediator* mediator; @property(nonatomic, strong) UINavigationController* navigationController; @end @@ -41,20 +34,8 @@ #pragma mark - ChromeCoordinator - (void)start { - self.dispatcher = self.browser->GetCommandDispatcher(); - [self.dispatcher - startDispatchingToTarget:self - forProtocol:@protocol(PageInfoNavigationCommands)]; - self.viewController = [[PageInfoViewController alloc] initWithStyle:UITableViewStylePlain]; - self.viewController.handler = - HandlerForProtocol(self.dispatcher, PageInfoNavigationCommands); - - web::WebState* webState = - self.browser->GetWebStateList()->GetActiveWebState(); - self.mediator = [[PageInfoMediator alloc] initWithWebState:webState]; - self.mediator.consumer = self.viewController; self.navigationController = [[UINavigationController alloc] initWithRootViewController:self.viewController]; @@ -65,46 +46,11 @@ } - (void)stop { - [self.dispatcher stopDispatchingToTarget:self]; [self.baseViewController.presentedViewController dismissViewControllerAnimated:YES completion:nil]; - self.dispatcher = nil; self.navigationController = nil; - self.mediator.consumer = nil; - self.mediator = nil; self.viewController = nil; } -#pragma mark - PageInfoNavigationCommands - -- (void)showSiteSecurityInfo { - web::WebState* webState = - self.browser->GetWebStateList()->GetActiveWebState(); - web::NavigationItem* navItem = - webState->GetNavigationManager()->GetVisibleItem(); - - bool offlinePage = - OfflinePageTabHelper::FromWebState(webState)->presenting_offline_page(); - - PageInfoSiteSecurityDescription* description = - [PageInfoSiteSecurityMediator configurationForURL:navItem->GetURL() - SSLStatus:navItem->GetSSL() - offlinePage:offlinePage]; - - PageInfoSiteSecurityViewController* viewController = - [[PageInfoSiteSecurityViewController alloc] - initWitDescription:description]; - - viewController.handler = HandlerForProtocol(self.dispatcher, BrowserCommands); - [self.navigationController pushViewController:viewController animated:YES]; -} - -- (void)showCookiesInfo { - PageInfoCookiesViewController* viewController = - [[PageInfoCookiesViewController alloc] - initWithStyle:UITableViewStylePlain]; - [self.navigationController pushViewController:viewController animated:YES]; -} - @end
diff --git a/ios/chrome/browser/ui/page_info/page_info_description.h b/ios/chrome/browser/ui/page_info/page_info_description.h deleted file mode 100644 index 0d6b1d5..0000000 --- a/ios/chrome/browser/ui/page_info/page_info_description.h +++ /dev/null
@@ -1,36 +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 IOS_CHROME_BROWSER_UI_PAGE_INFO_PAGE_INFO_DESCRIPTION_H_ -#define IOS_CHROME_BROWSER_UI_PAGE_INFO_PAGE_INFO_DESCRIPTION_H_ - -#import <UIKit/UIKit.h> - -class GURL; - -namespace web { -struct SSLStatus; -} - -// Create and store all the data to be displayed inside the root of the page -// info. -@interface PageInfoDescription : NSObject - -// Init based on the |URL|, the SSL |status| and if the current page is an -// |offlinePage|. -- (instancetype)initWithURL:(const GURL&)URL - SSLStatus:(const web::SSLStatus&)status - isPageOffline:(BOOL)isOffline NS_DESIGNATED_INITIALIZER; -- (instancetype)init NS_UNAVAILABLE; - -// Describes the security status of this page, i.e. "Page is secure" or "SSL -// cert expired". -@property(nonatomic, readonly) NSString* pageSecurityStatusDescription; - -// The icon name for the page security status, e.g. a lock. -@property(nonatomic, readonly) NSString* pageSecurityStatusIconImageName; - -@end - -#endif // IOS_CHROME_BROWSER_UI_PAGE_INFO_PAGE_INFO_DESCRIPTION_H_
diff --git a/ios/chrome/browser/ui/page_info/page_info_description.mm b/ios/chrome/browser/ui/page_info/page_info_description.mm deleted file mode 100644 index c288881f..0000000 --- a/ios/chrome/browser/ui/page_info/page_info_description.mm +++ /dev/null
@@ -1,115 +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. - -#import "ios/chrome/browser/ui/page_info/page_info_description.h" - -#include "base/strings/sys_string_conversions.h" -#include "base/strings/utf_string_conversions.h" -#include "components/security_state/core/security_state.h" -#include "components/strings/grit/components_chromium_strings.h" -#include "components/strings/grit/components_google_chrome_strings.h" -#include "components/strings/grit/components_strings.h" -#include "ios/chrome/browser/chrome_url_constants.h" -#include "ios/chrome/grit/ios_strings.h" -#include "ios/components/webui/web_ui_url_constants.h" -#include "ios/web/public/security/ssl_status.h" -#include "ui/base/l10n/l10n_util.h" - -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - -@interface PageInfoDescription () - -@property(nonatomic, assign) web::SSLStatus status; -@property(nonatomic, assign) const GURL& URL; -@property(nonatomic, assign) BOOL isOffline; - -@end - -@implementation PageInfoDescription { - GURL _URL; -} - -- (instancetype)initWithURL:(const GURL&)URL - SSLStatus:(const web::SSLStatus&)status - isPageOffline:(BOOL)isOffline { - self = [super init]; - if (self) { - _URL = URL; - _status = status; - _isOffline = isOffline; - } - return self; -} - -- (NSString*)pageSecurityStatusDescription { - if (self.isOffline) { - return l10n_util::GetNSString(IDS_IOS_PAGE_INFO_OFFLINE_PAGE); - } - - if (self.URL.SchemeIs(kChromeUIScheme)) { - return l10n_util::GetNSString(IDS_PAGE_INFO_INTERNAL_PAGE); - } - - if (!self.status.certificate) { - return l10n_util::GetNSString(IDS_PAGE_INFO_NOT_SECURE_SUMMARY); - } - - if (net::IsCertStatusError((self.status.cert_status)) || - (self.status.security_style == - web::SECURITY_STYLE_AUTHENTICATION_BROKEN)) { - // HTTPS with major errors - return l10n_util::GetNSString(IDS_PAGE_INFO_NOT_SECURE_SUMMARY); - } - - if (self.status.content_status == - web::SSLStatus::DISPLAYED_INSECURE_CONTENT) { - return l10n_util::GetNSString(IDS_PAGE_INFO_NOT_SECURE_SUMMARY); - } - - // Valid HTTPS - return l10n_util::GetNSString(IDS_PAGE_INFO_SECURE_SUMMARY); -} - -- (NSString*)pageSecurityStatusIconImageName { - // If the URL scheme corresponds to Chrome on iOS, the icon is not set. - if (self.URL.SchemeIs(kChromeUIScheme)) - return @""; - - if (self.isOffline) - return @"page_info_offline"; - - if (!self.status.certificate) { - if (security_state::ShouldShowDangerTriangleForWarningLevel()) - return @"page_info_bad"; - - return @"page_info_info"; - } - - if (net::IsCertStatusError(self.status.cert_status) || - self.status.security_style == web::SECURITY_STYLE_AUTHENTICATION_BROKEN) - // HTTPS with major errors - return @"page_info_bad"; - - // The remaining states are valid HTTPS, or HTTPS with minor errors. - if (self.status.content_status == - web::SSLStatus::DISPLAYED_INSECURE_CONTENT) { - if (security_state::ShouldShowDangerTriangleForWarningLevel()) - return @"page_info_bad"; - - return @"page_info"; - } - - // Valid HTTPS - return @"page_info_good"; -} - -#pragma mark - Properties - -- (const GURL&)URL { - return _URL; -} - -@end
diff --git a/ios/chrome/browser/ui/page_info/page_info_mediator.h b/ios/chrome/browser/ui/page_info/page_info_mediator.h deleted file mode 100644 index 4d123de4..0000000 --- a/ios/chrome/browser/ui/page_info/page_info_mediator.h +++ /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. - -#ifndef IOS_CHROME_BROWSER_UI_PAGE_INFO_PAGE_INFO_MEDIATOR_H_ -#define IOS_CHROME_BROWSER_UI_PAGE_INFO_PAGE_INFO_MEDIATOR_H_ - -#import <Foundation/Foundation.h> - -#include "ios/chrome/browser/main/browser.h" -#import "ios/web/public/web_state_observer_bridge.h" - -@protocol PageInfoConsumer; - -// The mediator is pushing the data for the root of the info page page to the -// consumer. -@interface PageInfoMediator : NSObject - -- (instancetype)initWithWebState:(web::WebState*)webState - NS_DESIGNATED_INITIALIZER; - -- (instancetype)init NS_UNAVAILABLE; - -// The consumer for this mediator. -@property(nonatomic, weak) id<PageInfoConsumer> consumer; - -@end - -#endif // IOS_CHROME_BROWSER_UI_PAGE_INFO_PAGE_INFO_MEDIATOR_H_
diff --git a/ios/chrome/browser/ui/page_info/page_info_mediator.mm b/ios/chrome/browser/ui/page_info/page_info_mediator.mm deleted file mode 100644 index d5fdd656..0000000 --- a/ios/chrome/browser/ui/page_info/page_info_mediator.mm +++ /dev/null
@@ -1,57 +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. - -#import "ios/chrome/browser/ui/page_info/page_info_mediator.h" - -#include "ios/chrome/browser/main/browser.h" -#import "ios/chrome/browser/reading_list/offline_page_tab_helper.h" -#import "ios/chrome/browser/ui/page_info/page_info_consumer.h" -#import "ios/chrome/browser/ui/page_info/page_info_description.h" -#import "ios/chrome/browser/web_state_list/web_state_list.h" -#include "ios/web/public/navigation/navigation_item.h" -#include "ios/web/public/navigation/navigation_manager.h" -#import "ios/web/public/web_state.h" - -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - -@interface PageInfoMediator () -@property(nonatomic, assign) web::WebState* webState; -@property(nonatomic, assign) web::NavigationItem* navigationItem; -@end - -@implementation PageInfoMediator - -- (instancetype)initWithWebState:(web::WebState*)webState { - self = [super init]; - if (self) { - _webState = webState; - _navigationItem = _webState->GetNavigationManager()->GetVisibleItem(); - } - return self; -} - -- (void)setConsumer:(id<PageInfoConsumer>)consumer { - if (_consumer == consumer) - return; - - _consumer = consumer; - [self updateConsumer]; -} - -#pragma mark - Private - -- (void)updateConsumer { - const BOOL presentingOfflinePage = - OfflinePageTabHelper::FromWebState(_webState)->presenting_offline_page(); - - PageInfoDescription* description = - [[PageInfoDescription alloc] initWithURL:self.navigationItem->GetURL() - SSLStatus:self.navigationItem->GetSSL() - isPageOffline:presentingOfflinePage]; - [self.consumer pageInfoChanged:description]; -} - -@end
diff --git a/ios/chrome/browser/ui/page_info/page_info_navigation_commands.h b/ios/chrome/browser/ui/page_info/page_info_navigation_commands.h deleted file mode 100644 index e5a912d..0000000 --- a/ios/chrome/browser/ui/page_info/page_info_navigation_commands.h +++ /dev/null
@@ -1,20 +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 IOS_CHROME_BROWSER_UI_PAGE_INFO_PAGE_INFO_NAVIGATION_COMMANDS_H_ -#define IOS_CHROME_BROWSER_UI_PAGE_INFO_PAGE_INFO_NAVIGATION_COMMANDS_H_ - -// Commands related to the Page Info navigation inside the page info view -// controller. -@protocol PageInfoNavigationCommands - -// Shows the site security information. -- (void)showSiteSecurityInfo; - -// Shows the cookies information. -- (void)showCookiesInfo; - -@end - -#endif // IOS_CHROME_BROWSER_UI_PAGE_INFO_PAGE_INFO_NAVIGATION_COMMANDS_H_
diff --git a/ios/chrome/browser/ui/page_info/page_info_site_security_view_controller.h b/ios/chrome/browser/ui/page_info/page_info_site_security_view_controller.h deleted file mode 100644 index 0251e9e..0000000 --- a/ios/chrome/browser/ui/page_info/page_info_site_security_view_controller.h +++ /dev/null
@@ -1,30 +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 IOS_CHROME_BROWSER_UI_PAGE_INFO_PAGE_INFO_SITE_SECURITY_VIEW_CONTROLLER_H_ -#define IOS_CHROME_BROWSER_UI_PAGE_INFO_PAGE_INFO_SITE_SECURITY_VIEW_CONTROLLER_H_ - -#import <UIKit/UIKit.h> - -#import "ios/chrome/browser/ui/page_info/page_info_site_security_description.h" - -@protocol BrowserCommands; - -// View Controller for displaying the site security. -@interface PageInfoSiteSecurityViewController : UIViewController - -- (instancetype)initWitDescription:(PageInfoSiteSecurityDescription*)description - NS_DESIGNATED_INITIALIZER; - -- (instancetype)initWithNibName:(NSString*)nibNameOrNil - bundle:(NSBundle*)nibBundleOrNil NS_UNAVAILABLE; -- (instancetype)initWithCoder:(NSCoder*)aDecoder NS_UNAVAILABLE; -- (instancetype)init NS_UNAVAILABLE; - -// Handler used to navigate outside the page info. -@property(nonatomic, weak) id<BrowserCommands> handler; - -@end - -#endif // IOS_CHROME_BROWSER_UI_PAGE_INFO_PAGE_INFO_SITE_SECURITY_VIEW_CONTROLLER_H_
diff --git a/ios/chrome/browser/ui/page_info/page_info_site_security_view_controller.mm b/ios/chrome/browser/ui/page_info/page_info_site_security_view_controller.mm deleted file mode 100644 index ab23cd6..0000000 --- a/ios/chrome/browser/ui/page_info/page_info_site_security_view_controller.mm +++ /dev/null
@@ -1,218 +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. - -#import "ios/chrome/browser/ui/page_info/page_info_site_security_view_controller.h" - -#include "components/strings/grit/components_strings.h" -#import "ios/chrome/browser/ui/commands/browser_commands.h" -#import "ios/chrome/browser/ui/util/uikit_ui_util.h" -#import "ios/chrome/common/ui/colors/UIColor+cr_semantic_colors.h" -#import "ios/chrome/common/ui/colors/semantic_color_names.h" -#import "ios/chrome/common/ui/util/constraints_ui_util.h" -#include "ios/chrome/grit/ios_strings.h" -#include "ui/base/l10n/l10n_util.h" - -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - -namespace { - -const CGFloat kHorizontalSpacing = 16.0f; - -const CGFloat kVerticalSpacing = 20.0f; - -const CGFloat kIconSize = 20.0f; - -} // namespace - -@interface PageInfoSiteSecurityViewController () - -@property(nonatomic, strong) - PageInfoSiteSecurityDescription* pageInfoSecurityDescription; - -@end - -@implementation PageInfoSiteSecurityViewController - -- (instancetype)initWitDescription: - (PageInfoSiteSecurityDescription*)description { - self = [super initWithNibName:nil bundle:nil]; - if (self) { - _pageInfoSecurityDescription = description; - } - return self; -} - -#pragma mark - UIViewController - -- (void)viewDidLoad { - [super viewDidLoad]; - - self.view.backgroundColor = [UIColor colorNamed:kBackgroundColor]; - self.title = l10n_util::GetNSString(IDS_IOS_PAGE_INFO_SITE_SECURITY); - - // ScrollView that contains site security information. - UIScrollView* scrollView = [[UIScrollView alloc] init]; - scrollView.translatesAutoresizingMaskIntoConstraints = NO; - [self.view addSubview:scrollView]; - AddSameConstraints(self.view, scrollView); - - // Site security information. - UILabel* securitySummary = [[UILabel alloc] init]; - securitySummary.textColor = UIColor.cr_labelColor; - securitySummary.numberOfLines = 0; - securitySummary.adjustsFontForContentSizeCategory = YES; - securitySummary.text = self.pageInfoSecurityDescription.message; - securitySummary.font = [UIFont preferredFontForTextStyle:UIFontTextStyleBody]; - securitySummary.translatesAutoresizingMaskIntoConstraints = NO; - [scrollView addSubview:securitySummary]; - - // Security icon. - UIImage* securityIcon = [self.pageInfoSecurityDescription.image - imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; - UIImageView* securityIconView = - [[UIImageView alloc] initWithImage:securityIcon]; - securityIconView.tintColor = UIColor.cr_labelColor; - securityIconView.translatesAutoresizingMaskIntoConstraints = NO; - [scrollView addSubview:securityIconView]; - - // Website URL. - UILabel* securityURL = [[UILabel alloc] init]; - securityURL.textColor = UIColor.cr_labelColor; - securityURL.adjustsFontForContentSizeCategory = YES; - securityURL.text = self.pageInfoSecurityDescription.title; - securityURL.font = [UIFont preferredFontForTextStyle:UIFontTextStyleHeadline]; - securityURL.translatesAutoresizingMaskIntoConstraints = NO; - [scrollView addSubview:securityURL]; - - // In some cases the icon can be nil. - // e.g, if the URL scheme corresponds to chrome webUI, the icon is not set. - CGFloat iconSize = self.pageInfoSecurityDescription.image ? kIconSize : 0; - CGFloat iconToURLMargin = - self.pageInfoSecurityDescription.image ? kHorizontalSpacing : 0; - - NSArray* constraints = @[ - // SecuritySummary constraints. - [securitySummary.leadingAnchor - constraintEqualToAnchor:self.view.safeAreaLayoutGuide.leadingAnchor - constant:kHorizontalSpacing], - [securitySummary.trailingAnchor - constraintEqualToAnchor:self.view.safeAreaLayoutGuide.trailingAnchor - constant:-kHorizontalSpacing], - [securitySummary.topAnchor constraintEqualToAnchor:scrollView.topAnchor - constant:kVerticalSpacing], - - // SecurityIcon constraints. - [securityIconView.leadingAnchor - constraintEqualToAnchor:self.view.safeAreaLayoutGuide.leadingAnchor - constant:kHorizontalSpacing], - [securityIconView.topAnchor - constraintGreaterThanOrEqualToAnchor:securitySummary.bottomAnchor - constant:kVerticalSpacing], - [securityIconView.heightAnchor constraintEqualToConstant:iconSize], - [securityIconView.widthAnchor - constraintEqualToAnchor:securityIconView.heightAnchor], - - [securityIconView.bottomAnchor - constraintLessThanOrEqualToAnchor:scrollView.bottomAnchor - constant:-kVerticalSpacing], - - // securityURL constraints. - [securityURL.leadingAnchor - constraintEqualToAnchor:securityIconView.trailingAnchor - constant:iconToURLMargin], - [securityURL.trailingAnchor - constraintEqualToAnchor:self.view.safeAreaLayoutGuide.trailingAnchor - constant:-kHorizontalSpacing], - [securityURL.topAnchor - constraintGreaterThanOrEqualToAnchor:securitySummary.bottomAnchor - constant:kVerticalSpacing], - [securityURL.centerYAnchor - constraintEqualToAnchor:securityIconView.centerYAnchor], - [securityURL.bottomAnchor - constraintLessThanOrEqualToAnchor:scrollView.bottomAnchor - constant:-kVerticalSpacing], - ]; - [NSLayoutConstraint activateConstraints:constraints]; - - [self addButtonActionToScrollView:scrollView - securityIconView:securityIconView - securityURL:securityURL]; -} - -#pragma mark - Private - -// Adds a button and his constrainsts based on the |securityIconView| and the -// |securityURL| to the |scrollView|. -- (void)addButtonActionToScrollView:(UIScrollView*)scrollView - securityIconView:(UIImageView*)securityIconView - securityURL:(UILabel*)securityURL { - UIButton* buttonAction = - [self buttonForAction:self.pageInfoSecurityDescription.buttonAction]; - // In some cases there is no actions. - // e.g, if the URL scheme corresponds to chrome webUI, the button is not set. - if (!buttonAction) - return; - - buttonAction.titleLabel.adjustsFontForContentSizeCategory = YES; - buttonAction.titleLabel.font = - [UIFont preferredFontForTextStyle:UIFontTextStyleHeadline]; - - [buttonAction setTitleColor:[UIColor colorNamed:kBlueColor] - forState:UIControlStateNormal]; - buttonAction.translatesAutoresizingMaskIntoConstraints = NO; - - [scrollView addSubview:buttonAction]; - - NSArray* buttonConstraints = @[ - [buttonAction.leadingAnchor - constraintEqualToAnchor:self.view.safeAreaLayoutGuide.leadingAnchor - constant:kHorizontalSpacing], - [buttonAction.leadingAnchor - constraintLessThanOrEqualToAnchor:self.view.safeAreaLayoutGuide - .trailingAnchor - constant:kHorizontalSpacing], - [buttonAction.topAnchor - constraintGreaterThanOrEqualToAnchor:securityIconView.bottomAnchor - constant:kVerticalSpacing], - [buttonAction.topAnchor - constraintGreaterThanOrEqualToAnchor:securityURL.bottomAnchor - constant:kVerticalSpacing], - [buttonAction.bottomAnchor constraintEqualToAnchor:scrollView.bottomAnchor - constant:-kVerticalSpacing], - ]; - [NSLayoutConstraint activateConstraints:buttonConstraints]; -} - -// Returns a button with title and action configured for |buttonAction|. -- (UIButton*)buttonForAction:(PageInfoSiteSecurityButtonAction)buttonAction { - UIButton* button = [UIButton buttonWithType:UIButtonTypeSystem]; - int messageId; - switch (buttonAction) { - case PageInfoSiteSecurityButtonActionNone: - return nil; - case PageInfoSiteSecurityButtonActionShowHelp: - messageId = IDS_LEARN_MORE; - [button addTarget:self.handler - action:@selector(showSecurityHelpPage) - forControlEvents:UIControlEventTouchUpInside]; - break; - case PageInfoSiteSecurityButtonActionReload: - messageId = IDS_IOS_PAGE_INFO_RELOAD; - [button addTarget:self.handler - action:@selector(hidePageInfo) - forControlEvents:UIControlEventTouchUpInside]; - [button addTarget:self.handler - action:@selector(reload) - forControlEvents:UIControlEventTouchUpInside]; - break; - }; - - NSString* title = l10n_util::GetNSStringWithFixup(messageId); - [button setTitle:title forState:UIControlStateNormal]; - return button; -} - -@end
diff --git a/ios/chrome/browser/ui/page_info/page_info_view_controller.h b/ios/chrome/browser/ui/page_info/page_info_view_controller.h index bd9c69e6..13659191 100644 --- a/ios/chrome/browser/ui/page_info/page_info_view_controller.h +++ b/ios/chrome/browser/ui/page_info/page_info_view_controller.h
@@ -7,16 +7,10 @@ #import <UIKit/UIKit.h> -#import "ios/chrome/browser/ui/page_info/page_info_consumer.h" #import "ios/chrome/browser/ui/table_view/chrome_table_view_controller.h" -@protocol PageInfoNavigationCommands; - // View Controller for displaying the page info. -@interface PageInfoViewController : ChromeTableViewController <PageInfoConsumer> - -// Handler used to navigate inside the page info. -@property(nonatomic, weak) id<PageInfoNavigationCommands> handler; +@interface PageInfoViewController : ChromeTableViewController @end
diff --git a/ios/chrome/browser/ui/page_info/page_info_view_controller.mm b/ios/chrome/browser/ui/page_info/page_info_view_controller.mm index 76d62c9..883dc808 100644 --- a/ios/chrome/browser/ui/page_info/page_info_view_controller.mm +++ b/ios/chrome/browser/ui/page_info/page_info_view_controller.mm
@@ -6,7 +6,6 @@ #include "components/content_settings/core/common/features.h" #import "ios/chrome/browser/ui/page_info/features.h" -#import "ios/chrome/browser/ui/page_info/page_info_navigation_commands.h" #import "ios/chrome/browser/ui/table_view/cells/table_view_detail_icon_item.h" #include "ios/chrome/grit/ios_strings.h" #include "ui/base/l10n/l10n_util.h" @@ -15,22 +14,6 @@ #error "This file requires ARC support." #endif -namespace { - -// TODO(crbug.com/1063824): Update this. -NSString* const kPageInfoCookiesImageName = @""; - -typedef NS_ENUM(NSInteger, SectionIdentifier) { - SectionIdentifierContent = kSectionIdentifierEnumZero, -}; - -typedef NS_ENUM(NSInteger, ItemType) { - ItemTypeSecurity = kItemTypeEnumZero, - ItemTypeCookies, -}; - -} // namespace - @implementation PageInfoViewController #pragma mark - UIViewController @@ -41,58 +24,4 @@ self.title = l10n_util::GetNSString(IDS_IOS_PAGE_INFO_SITE_INFORMATION); } -#pragma mark - PageInfoConsumer - -- (void)pageInfoChanged:(PageInfoDescription*)pageInfoDescription { - [self loadModel]; - - [self.tableViewModel addSectionWithIdentifier:SectionIdentifierContent]; - - // Create the Security item. - TableViewDetailIconItem* securityItem = - [[TableViewDetailIconItem alloc] initWithType:ItemTypeSecurity]; - securityItem.text = l10n_util::GetNSString(IDS_IOS_PAGE_INFO_SITE_SECURITY); - securityItem.detailText = pageInfoDescription.pageSecurityStatusDescription; - securityItem.iconImageName = - pageInfoDescription.pageSecurityStatusIconImageName; - securityItem.accessoryType = UITableViewCellAccessoryDisclosureIndicator; - [self.tableViewModel addItem:securityItem - toSectionWithIdentifier:SectionIdentifierContent]; - - if (base::FeatureList::IsEnabled(content_settings::kImprovedCookieControls)) { - // Create the Cookies item. - TableViewDetailIconItem* CookiesItem = - [[TableViewDetailIconItem alloc] initWithType:ItemTypeCookies]; - CookiesItem.text = l10n_util::GetNSString(IDS_IOS_PAGE_INFO_COOKIES_TITLE); - CookiesItem.detailText = - l10n_util::GetNSString(IDS_IOS_PAGE_INFO_COOKIES_DESCRIPTION); - CookiesItem.accessoryType = UITableViewCellAccessoryDisclosureIndicator; - CookiesItem.iconImageName = kPageInfoCookiesImageName; - [self.tableViewModel addItem:CookiesItem - toSectionWithIdentifier:SectionIdentifierContent]; - } - - [self.tableView reloadData]; -} - -#pragma mark - UITableViewDelegate - -- (void)tableView:(UITableView*)tableView - didSelectRowAtIndexPath:(NSIndexPath*)indexPath { - [self.tableView deselectRowAtIndexPath:indexPath animated:YES]; - NSInteger itemType = [self.tableViewModel itemTypeForIndexPath:indexPath]; - switch (itemType) { - case ItemTypeSecurity: { - [self.handler showSiteSecurityInfo]; - break; - } - case ItemTypeCookies: { - [self.handler showCookiesInfo]; - break; - } - default: - break; - } -} - @end
diff --git a/ios/chrome/browser/ui/qr_generator/qr_generator_view_controller.mm b/ios/chrome/browser/ui/qr_generator/qr_generator_view_controller.mm index 3bcdfee..fc2666a 100644 --- a/ios/chrome/browser/ui/qr_generator/qr_generator_view_controller.mm +++ b/ios/chrome/browser/ui/qr_generator/qr_generator_view_controller.mm
@@ -42,8 +42,6 @@ self.alwaysShowImage = YES; self.primaryActionBarButtonStyle = UIBarButtonSystemItemAction; - self.helpButtonAvailable = YES; - #if defined(__IPHONE_13_4) if (@available(iOS 13.4, *)) { if (base::FeatureList::IsEnabled(kPointerSupport)) {
diff --git a/ios/chrome/browser/ui/settings/google_services/accounts_table_view_controller.mm b/ios/chrome/browser/ui/settings/google_services/accounts_table_view_controller.mm index e92ffbc..d5086d1 100644 --- a/ios/chrome/browser/ui/settings/google_services/accounts_table_view_controller.mm +++ b/ios/chrome/browser/ui/settings/google_services/accounts_table_view_controller.mm
@@ -205,12 +205,22 @@ forSectionWithIdentifier:SectionIdentifierAccounts]; signin::IdentityManager* identityManager = IdentityManagerFactory::GetForBrowserState(_browser->GetBrowserState()); + + NSString* authenticatedEmail = [authenticatedIdentity userEmail]; for (const auto& account : identityManager->GetAccountsWithRefreshTokens()) { ChromeIdentity* identity = ios::GetChromeBrowserProvider() ->GetChromeIdentityService() ->GetIdentityWithGaiaID(account.gaia); + // TODO(crbug.com/1081274): This re-ordering will be redundant once we + // apply ordering changes to the account reconciler. TableViewItem* item = [self accountItem:identity]; - [model addItem:item toSectionWithIdentifier:SectionIdentifierAccounts]; + if ([identity.userEmail isEqual:authenticatedEmail]) { + [model insertItem:item + inSectionWithIdentifier:SectionIdentifierAccounts + atIndex:0]; + } else { + [model addItem:item toSectionWithIdentifier:SectionIdentifierAccounts]; + } [mutableIdentityMap setObject:item forKey:identity.gaiaID]; }
diff --git a/ios/chrome/browser/ui/util/BUILD.gn b/ios/chrome/browser/ui/util/BUILD.gn index f0f7969..6bd04e6 100644 --- a/ios/chrome/browser/ui/util/BUILD.gn +++ b/ios/chrome/browser/ui/util/BUILD.gn
@@ -8,7 +8,10 @@ buildflag_header("ios_multi_window_buildflags") { header = "multi_window_buildflags.h" header_dir = "ios/chrome/browser/ui/util" - flags = [ "IOS_MULTIWINDOW_ENABLED=$ios_enable_multi_window" ] + flags = [ + "IOS_MULTIWINDOW_ENABLED=$ios_enable_multi_window", + "IOS_SCENE_STARTUP_ENABLED=$ios_enable_scene_startup", + ] } source_set("multiwindow_util") {
diff --git a/ios/chrome/browser/ui/util/multi_window_support.h b/ios/chrome/browser/ui/util/multi_window_support.h index 2513e4a..83c7591 100644 --- a/ios/chrome/browser/ui/util/multi_window_support.h +++ b/ios/chrome/browser/ui/util/multi_window_support.h
@@ -11,4 +11,9 @@ // supportsMultipleScenes] instead. bool IsMultiwindowSupported(); +// Returns true if the iOS13 UIScene-based startup flow is supported, regardless +// of whether multiple windows are permitted. This always returns true if +// IsMultiwindowSupported() returns true. +bool IsSceneStartupSupported(); + #endif // IOS_CHROME_BROWSER_UI_UTIL_MULTI_WINDOW_SUPPORT_H_
diff --git a/ios/chrome/browser/ui/util/multi_window_support.mm b/ios/chrome/browser/ui/util/multi_window_support.mm index bc2bff5..50e305d 100644 --- a/ios/chrome/browser/ui/util/multi_window_support.mm +++ b/ios/chrome/browser/ui/util/multi_window_support.mm
@@ -18,3 +18,13 @@ return false; #endif } + +bool IsSceneStartupSupported() { + if (IsMultiwindowSupported()) + return true; +#if BUILDFLAG(IOS_SCENE_STARTUP_ENABLED) + return base::ios::IsRunningOnIOS13OrLater(); +#else + return false; +#endif +}
diff --git a/ios/chrome/common/ui/confirmation_alert/confirmation_alert_view_controller.h b/ios/chrome/common/ui/confirmation_alert/confirmation_alert_view_controller.h index 190370c..a80e549f 100644 --- a/ios/chrome/common/ui/confirmation_alert/confirmation_alert_view_controller.h +++ b/ios/chrome/common/ui/confirmation_alert/confirmation_alert_view_controller.h
@@ -41,6 +41,10 @@ // The image. Must be set before the view is loaded. @property(nonatomic, strong) UIImage* image; +// Sets the custom spacing between the image and the title / subtitle. Must be +// set before the view is loaded. +@property(nonatomic, assign) CGFloat customSpacingAfterImage; + // The accessibility label for the image view. If nil, the image won't be // accessible. @property(nonatomic, strong) NSString* imageAccessibilityLabel;
diff --git a/ios/chrome/common/ui/confirmation_alert/confirmation_alert_view_controller.mm b/ios/chrome/common/ui/confirmation_alert/confirmation_alert_view_controller.mm index 0a5a97c..76d98ee 100644 --- a/ios/chrome/common/ui/confirmation_alert/confirmation_alert_view_controller.mm +++ b/ios/chrome/common/ui/confirmation_alert/confirmation_alert_view_controller.mm
@@ -66,6 +66,14 @@ #pragma mark - Public +- (instancetype)init { + self = [super init]; + if (self) { + _customSpacingAfterImage = kStackViewSpacingAfterIllustration; + } + return self; +} + - (void)viewDidLoad { [super viewDidLoad]; @@ -78,8 +86,8 @@ UILabel* title = [self createTitleLabel]; UILabel* subtitle = [self createSubtitleLabel]; - self.stackView = [self - createStackViewWithArrangedSubviews:@[ self.imageView, title, subtitle ]]; + NSArray* stackSubviews = @[ self.imageView, title, subtitle ]; + self.stackView = [self createStackViewWithArrangedSubviews:stackSubviews]; UIScrollView* scrollView = [self createScrollView]; [scrollView addSubview:self.stackView]; @@ -447,7 +455,7 @@ (NSArray<UIView*>*)subviews { UIStackView* stackView = [[UIStackView alloc] initWithArrangedSubviews:subviews]; - [stackView setCustomSpacing:kStackViewSpacingAfterIllustration + [stackView setCustomSpacing:self.customSpacingAfterImage afterView:self.imageView]; if (self.imageHasFixedSize) {
diff --git a/ios/chrome/credential_provider_extension/ui/consent_view_controller.mm b/ios/chrome/credential_provider_extension/ui/consent_view_controller.mm index 1b135ed5..baad69e 100644 --- a/ios/chrome/credential_provider_extension/ui/consent_view_controller.mm +++ b/ios/chrome/credential_provider_extension/ui/consent_view_controller.mm
@@ -8,12 +8,18 @@ #error "This file requires ARC support." #endif +namespace { +constexpr CGFloat kStackViewSpacingAfterIllustration = 37; +} // namespace + @implementation ConsentViewController #pragma mark - Public - (void)loadView { self.image = [UIImage imageNamed:@"consent_illustration"]; + self.customSpacingAfterImage = kStackViewSpacingAfterIllustration; + self.helpButtonAvailable = YES; self.primaryActionAvailable = YES; NSString* titleString =
diff --git a/ios/chrome/credential_provider_extension/ui/empty_credentials_view_controller.mm b/ios/chrome/credential_provider_extension/ui/empty_credentials_view_controller.mm index 2df7db2a..ef4c812f 100644 --- a/ios/chrome/credential_provider_extension/ui/empty_credentials_view_controller.mm +++ b/ios/chrome/credential_provider_extension/ui/empty_credentials_view_controller.mm
@@ -8,12 +8,18 @@ #error "This file requires ARC support." #endif +namespace { +constexpr CGFloat kStackViewSpacingAfterIllustration = 32; +} // namespace + @implementation EmptyCredentialsViewController #pragma mark - Public - (void)loadView { self.image = [UIImage imageNamed:@"empty_credentials_illustration"]; + self.customSpacingAfterImage = kStackViewSpacingAfterIllustration; + self.helpButtonAvailable = NO; self.primaryActionAvailable = NO; NSString* titleString =
diff --git a/ios/chrome/credential_provider_extension/ui/resources/BUILD.gn b/ios/chrome/credential_provider_extension/ui/resources/BUILD.gn index de96e6e..cc216de 100644 --- a/ios/chrome/credential_provider_extension/ui/resources/BUILD.gn +++ b/ios/chrome/credential_provider_extension/ui/resources/BUILD.gn
@@ -13,31 +13,26 @@ ":info_icon", ":password_hide_icon", ":password_reveal_icon", - ":stale_credentials_illustration", ] } imageset("consent_illustration") { sources = [ "consent_illustration.imageset/Contents.json", - "consent_illustration.imageset/illustration_dark.png", - "consent_illustration.imageset/illustration_light.png", + "consent_illustration.imageset/illustration_dark@2x.png", + "consent_illustration.imageset/illustration_dark@3x.png", + "consent_illustration.imageset/illustration_light@2x.png", + "consent_illustration.imageset/illustration_light@3x.png", ] } imageset("empty_credentials_illustration") { sources = [ "empty_credentials_illustration.imageset/Contents.json", - "empty_credentials_illustration.imageset/illustration_dark.png", - "empty_credentials_illustration.imageset/illustration_light.png", - ] -} - -imageset("stale_credentials_illustration") { - sources = [ - "stale_credentials_illustration.imageset/Contents.json", - "stale_credentials_illustration.imageset/illustration_dark.png", - "stale_credentials_illustration.imageset/illustration_light.png", + "empty_credentials_illustration.imageset/illustration_dark@2x.png", + "empty_credentials_illustration.imageset/illustration_dark@3x.png", + "empty_credentials_illustration.imageset/illustration_light@2x.png", + "empty_credentials_illustration.imageset/illustration_light@3x.png", ] }
diff --git a/ios/chrome/credential_provider_extension/ui/resources/consent_illustration.imageset/Contents.json b/ios/chrome/credential_provider_extension/ui/resources/consent_illustration.imageset/Contents.json index e5b1b4d6..1cdd7c5 100644 --- a/ios/chrome/credential_provider_extension/ui/resources/consent_illustration.imageset/Contents.json +++ b/ios/chrome/credential_provider_extension/ui/resources/consent_illustration.imageset/Contents.json
@@ -2,21 +2,53 @@ "images" : [ { "idiom" : "universal", - "filename" : "illustration_light.png" + "scale" : "1x" }, { - "idiom" : "universal", - "filename" : "illustration_dark.png", "appearances" : [ { "appearance" : "luminosity", "value" : "dark" } - ] + ], + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "illustration_light@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "filename" : "illustration_dark@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "illustration_light@3x.png", + "idiom" : "universal", + "scale" : "3x" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "filename" : "illustration_dark@3x.png", + "idiom" : "universal", + "scale" : "3x" } ], "info" : { - "version" : 1, - "author" : "xcode" + "author" : "xcode", + "version" : 1 } -} \ No newline at end of file +}
diff --git a/ios/chrome/credential_provider_extension/ui/resources/consent_illustration.imageset/illustration_dark.png b/ios/chrome/credential_provider_extension/ui/resources/consent_illustration.imageset/illustration_dark.png deleted file mode 100644 index dc7bb7b..0000000 --- a/ios/chrome/credential_provider_extension/ui/resources/consent_illustration.imageset/illustration_dark.png +++ /dev/null Binary files differ
diff --git a/ios/chrome/credential_provider_extension/ui/resources/consent_illustration.imageset/illustration_dark@2x.png b/ios/chrome/credential_provider_extension/ui/resources/consent_illustration.imageset/illustration_dark@2x.png new file mode 100644 index 0000000..77ee54c --- /dev/null +++ b/ios/chrome/credential_provider_extension/ui/resources/consent_illustration.imageset/illustration_dark@2x.png Binary files differ
diff --git a/ios/chrome/credential_provider_extension/ui/resources/consent_illustration.imageset/illustration_dark@3x.png b/ios/chrome/credential_provider_extension/ui/resources/consent_illustration.imageset/illustration_dark@3x.png new file mode 100644 index 0000000..52515ec9c --- /dev/null +++ b/ios/chrome/credential_provider_extension/ui/resources/consent_illustration.imageset/illustration_dark@3x.png Binary files differ
diff --git a/ios/chrome/credential_provider_extension/ui/resources/consent_illustration.imageset/illustration_light.png b/ios/chrome/credential_provider_extension/ui/resources/consent_illustration.imageset/illustration_light.png deleted file mode 100644 index 9edcfcba..0000000 --- a/ios/chrome/credential_provider_extension/ui/resources/consent_illustration.imageset/illustration_light.png +++ /dev/null Binary files differ
diff --git a/ios/chrome/credential_provider_extension/ui/resources/consent_illustration.imageset/illustration_light@2x.png b/ios/chrome/credential_provider_extension/ui/resources/consent_illustration.imageset/illustration_light@2x.png new file mode 100644 index 0000000..d71cfd0 --- /dev/null +++ b/ios/chrome/credential_provider_extension/ui/resources/consent_illustration.imageset/illustration_light@2x.png Binary files differ
diff --git a/ios/chrome/credential_provider_extension/ui/resources/consent_illustration.imageset/illustration_light@3x.png b/ios/chrome/credential_provider_extension/ui/resources/consent_illustration.imageset/illustration_light@3x.png new file mode 100644 index 0000000..2b6deb01 --- /dev/null +++ b/ios/chrome/credential_provider_extension/ui/resources/consent_illustration.imageset/illustration_light@3x.png Binary files differ
diff --git a/ios/chrome/credential_provider_extension/ui/resources/empty_credentials_illustration.imageset/Contents.json b/ios/chrome/credential_provider_extension/ui/resources/empty_credentials_illustration.imageset/Contents.json index e5b1b4d6..1cdd7c5 100644 --- a/ios/chrome/credential_provider_extension/ui/resources/empty_credentials_illustration.imageset/Contents.json +++ b/ios/chrome/credential_provider_extension/ui/resources/empty_credentials_illustration.imageset/Contents.json
@@ -2,21 +2,53 @@ "images" : [ { "idiom" : "universal", - "filename" : "illustration_light.png" + "scale" : "1x" }, { - "idiom" : "universal", - "filename" : "illustration_dark.png", "appearances" : [ { "appearance" : "luminosity", "value" : "dark" } - ] + ], + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "illustration_light@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "filename" : "illustration_dark@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "illustration_light@3x.png", + "idiom" : "universal", + "scale" : "3x" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "filename" : "illustration_dark@3x.png", + "idiom" : "universal", + "scale" : "3x" } ], "info" : { - "version" : 1, - "author" : "xcode" + "author" : "xcode", + "version" : 1 } -} \ No newline at end of file +}
diff --git a/ios/chrome/credential_provider_extension/ui/resources/empty_credentials_illustration.imageset/illustration_dark.png b/ios/chrome/credential_provider_extension/ui/resources/empty_credentials_illustration.imageset/illustration_dark.png deleted file mode 100644 index dc7bb7b..0000000 --- a/ios/chrome/credential_provider_extension/ui/resources/empty_credentials_illustration.imageset/illustration_dark.png +++ /dev/null Binary files differ
diff --git a/ios/chrome/credential_provider_extension/ui/resources/empty_credentials_illustration.imageset/illustration_dark@2x.png b/ios/chrome/credential_provider_extension/ui/resources/empty_credentials_illustration.imageset/illustration_dark@2x.png new file mode 100644 index 0000000..7231a38 --- /dev/null +++ b/ios/chrome/credential_provider_extension/ui/resources/empty_credentials_illustration.imageset/illustration_dark@2x.png Binary files differ
diff --git a/ios/chrome/credential_provider_extension/ui/resources/empty_credentials_illustration.imageset/illustration_dark@3x.png b/ios/chrome/credential_provider_extension/ui/resources/empty_credentials_illustration.imageset/illustration_dark@3x.png new file mode 100644 index 0000000..d9a4709 --- /dev/null +++ b/ios/chrome/credential_provider_extension/ui/resources/empty_credentials_illustration.imageset/illustration_dark@3x.png Binary files differ
diff --git a/ios/chrome/credential_provider_extension/ui/resources/empty_credentials_illustration.imageset/illustration_light.png b/ios/chrome/credential_provider_extension/ui/resources/empty_credentials_illustration.imageset/illustration_light.png deleted file mode 100644 index 9edcfcba..0000000 --- a/ios/chrome/credential_provider_extension/ui/resources/empty_credentials_illustration.imageset/illustration_light.png +++ /dev/null Binary files differ
diff --git a/ios/chrome/credential_provider_extension/ui/resources/empty_credentials_illustration.imageset/illustration_light@2x.png b/ios/chrome/credential_provider_extension/ui/resources/empty_credentials_illustration.imageset/illustration_light@2x.png new file mode 100644 index 0000000..e3a4bbd88 --- /dev/null +++ b/ios/chrome/credential_provider_extension/ui/resources/empty_credentials_illustration.imageset/illustration_light@2x.png Binary files differ
diff --git a/ios/chrome/credential_provider_extension/ui/resources/empty_credentials_illustration.imageset/illustration_light@3x.png b/ios/chrome/credential_provider_extension/ui/resources/empty_credentials_illustration.imageset/illustration_light@3x.png new file mode 100644 index 0000000..663e03f --- /dev/null +++ b/ios/chrome/credential_provider_extension/ui/resources/empty_credentials_illustration.imageset/illustration_light@3x.png Binary files differ
diff --git a/ios/chrome/credential_provider_extension/ui/resources/stale_credentials_illustration.imageset/Contents.json b/ios/chrome/credential_provider_extension/ui/resources/stale_credentials_illustration.imageset/Contents.json deleted file mode 100644 index e5b1b4d6..0000000 --- a/ios/chrome/credential_provider_extension/ui/resources/stale_credentials_illustration.imageset/Contents.json +++ /dev/null
@@ -1,22 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "filename" : "illustration_light.png" - }, - { - "idiom" : "universal", - "filename" : "illustration_dark.png", - "appearances" : [ - { - "appearance" : "luminosity", - "value" : "dark" - } - ] - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file
diff --git a/ios/chrome/credential_provider_extension/ui/resources/stale_credentials_illustration.imageset/illustration_dark.png b/ios/chrome/credential_provider_extension/ui/resources/stale_credentials_illustration.imageset/illustration_dark.png deleted file mode 100644 index dc7bb7b..0000000 --- a/ios/chrome/credential_provider_extension/ui/resources/stale_credentials_illustration.imageset/illustration_dark.png +++ /dev/null Binary files differ
diff --git a/ios/chrome/credential_provider_extension/ui/resources/stale_credentials_illustration.imageset/illustration_light.png b/ios/chrome/credential_provider_extension/ui/resources/stale_credentials_illustration.imageset/illustration_light.png deleted file mode 100644 index 9edcfcba..0000000 --- a/ios/chrome/credential_provider_extension/ui/resources/stale_credentials_illustration.imageset/illustration_light.png +++ /dev/null Binary files differ
diff --git a/ios/chrome/credential_provider_extension/ui/stale_credentials_view_controller.mm b/ios/chrome/credential_provider_extension/ui/stale_credentials_view_controller.mm index 7a0bd33..6a05a7f 100644 --- a/ios/chrome/credential_provider_extension/ui/stale_credentials_view_controller.mm +++ b/ios/chrome/credential_provider_extension/ui/stale_credentials_view_controller.mm
@@ -8,12 +8,18 @@ #error "This file requires ARC support." #endif +namespace { +constexpr CGFloat kStackViewSpacingAfterIllustration = 32; +} // namespace + @implementation StaleCredentialsViewController #pragma mark - Public - (void)loadView { - self.image = [UIImage imageNamed:@"stale_credentials_illustration"]; + self.image = [UIImage imageNamed:@"empty_credentials_illustration"]; + self.customSpacingAfterImage = kStackViewSpacingAfterIllustration; + self.helpButtonAvailable = NO; self.primaryActionAvailable = NO; NSString* titleString =
diff --git a/ios/third_party/material_components_ios/BUILD.gn b/ios/third_party/material_components_ios/BUILD.gn index f0fb742..53d5e054 100644 --- a/ios/third_party/material_components_ios/BUILD.gn +++ b/ios/third_party/material_components_ios/BUILD.gn
@@ -288,6 +288,7 @@ "src/components/ProgressView/src/MaterialProgressView.h", "src/components/ProgressView/src/Theming/MDCProgressView+MaterialTheming.h", "src/components/ProgressView/src/Theming/MaterialProgressView+Theming.h", + "src/components/ProgressView/src/private/MDCProgressGradientView.h", "src/components/ProgressView/src/private/MaterialProgressViewStrings.h", "src/components/ProgressView/src/private/MaterialProgressViewStrings_table.h", "src/components/Ripple/src/MDCRippleTouchController.h", @@ -342,21 +343,21 @@ "src/components/Snackbar/src/private/MDCSnackbarOverlayView.h", "src/components/Snackbar/src/private/MaterialSnackbarStrings.h", "src/components/Snackbar/src/private/MaterialSnackbarStrings_table.h", + "src/components/Tabs/src/ExtendedAlignment/MDCTabBarExtendedAlignment.h", "src/components/Tabs/src/MDCTabBar.h", "src/components/Tabs/src/MDCTabBarAlignment.h", "src/components/Tabs/src/MDCTabBarControllerDelegate.h", "src/components/Tabs/src/MDCTabBarDelegate.h", "src/components/Tabs/src/MDCTabBarDisplayDelegate.h", - "src/components/Tabs/src/MDCTabBarExtendedAlignment.h", "src/components/Tabs/src/MDCTabBarIndicatorAttributes.h", "src/components/Tabs/src/MDCTabBarIndicatorContext.h", "src/components/Tabs/src/MDCTabBarIndicatorTemplate.h", "src/components/Tabs/src/MDCTabBarItemAppearance.h", - "src/components/Tabs/src/MDCTabBarSizeClassDelegate.h", "src/components/Tabs/src/MDCTabBarTextTransform.h", "src/components/Tabs/src/MDCTabBarUnderlineIndicatorTemplate.h", "src/components/Tabs/src/MDCTabBarViewController.h", "src/components/Tabs/src/MaterialTabs.h", + "src/components/Tabs/src/SizeClassDelegate/MDCTabBarSizeClassDelegate.h", "src/components/Tabs/src/TabBarView/MDCTabBarItem.h", "src/components/Tabs/src/TabBarView/MDCTabBarItemCustomViewing.h", "src/components/Tabs/src/TabBarView/MDCTabBarView.h", @@ -636,6 +637,8 @@ "src/components/Snackbar/src/TypographyThemer", "src/components/Snackbar/src/private", "src/components/Tabs/src", + "src/components/Tabs/src/ExtendedAlignment", + "src/components/Tabs/src/SizeClassDelegate", "src/components/Tabs/src/TabBarView", "src/components/Tabs/src/TabBarView/private", "src/components/Tabs/src/Theming", @@ -1112,6 +1115,8 @@ "src/components/ProgressView/src/Theming/MDCProgressView+MaterialTheming.h", "src/components/ProgressView/src/Theming/MDCProgressView+MaterialTheming.m", "src/components/ProgressView/src/Theming/MaterialProgressView+Theming.h", + "src/components/ProgressView/src/private/MDCProgressGradientView.h", + "src/components/ProgressView/src/private/MDCProgressGradientView.m", "src/components/ProgressView/src/private/MaterialProgressViewStrings.h", "src/components/ProgressView/src/private/MaterialProgressViewStrings_table.h", "src/components/Ripple/src/MDCRippleTouchController.h", @@ -1194,25 +1199,25 @@ "src/components/Snackbar/src/private/MDCSnackbarOverlayView.m", "src/components/Snackbar/src/private/MaterialSnackbarStrings.h", "src/components/Snackbar/src/private/MaterialSnackbarStrings_table.h", + "src/components/Tabs/src/ExtendedAlignment/MDCTabBarExtendedAlignment.h", "src/components/Tabs/src/MDCTabBar.h", "src/components/Tabs/src/MDCTabBar.m", "src/components/Tabs/src/MDCTabBarAlignment.h", "src/components/Tabs/src/MDCTabBarControllerDelegate.h", "src/components/Tabs/src/MDCTabBarDelegate.h", "src/components/Tabs/src/MDCTabBarDisplayDelegate.h", - "src/components/Tabs/src/MDCTabBarExtendedAlignment.h", "src/components/Tabs/src/MDCTabBarIndicatorAttributes.h", "src/components/Tabs/src/MDCTabBarIndicatorAttributes.m", "src/components/Tabs/src/MDCTabBarIndicatorContext.h", "src/components/Tabs/src/MDCTabBarIndicatorTemplate.h", "src/components/Tabs/src/MDCTabBarItemAppearance.h", - "src/components/Tabs/src/MDCTabBarSizeClassDelegate.h", "src/components/Tabs/src/MDCTabBarTextTransform.h", "src/components/Tabs/src/MDCTabBarUnderlineIndicatorTemplate.h", "src/components/Tabs/src/MDCTabBarUnderlineIndicatorTemplate.m", "src/components/Tabs/src/MDCTabBarViewController.h", "src/components/Tabs/src/MDCTabBarViewController.m", "src/components/Tabs/src/MaterialTabs.h", + "src/components/Tabs/src/SizeClassDelegate/MDCTabBarSizeClassDelegate.h", "src/components/Tabs/src/TabBarView/MDCTabBarItem.h", "src/components/Tabs/src/TabBarView/MDCTabBarItem.m", "src/components/Tabs/src/TabBarView/MDCTabBarItemCustomViewing.h",
diff --git a/media/gpu/vaapi/vaapi_image_processor_backend.cc b/media/gpu/vaapi/vaapi_image_processor_backend.cc index 6f63daf..4cb6bce 100644 --- a/media/gpu/vaapi/vaapi_image_processor_backend.cc +++ b/media/gpu/vaapi/vaapi_image_processor_backend.cc
@@ -25,6 +25,7 @@ namespace media { +#if defined(OS_CHROMEOS) namespace { // UMA errors that the VaapiImageProcessorBackend class reports. enum class VaIPFailure { @@ -67,6 +68,7 @@ } } // namespace +#endif // static std::unique_ptr<ImageProcessorBackend> VaapiImageProcessorBackend::Create( @@ -78,8 +80,7 @@ // VaapiImageProcessorBackend supports ChromeOS only. #if !defined(OS_CHROMEOS) return nullptr; -#endif - +#else auto input_vafourcc = input_config.fourcc.ToVAFourCC(); if (!input_vafourcc) { VLOGF(2) << "Input fourcc " << input_config.fourcc.ToString() @@ -146,6 +147,7 @@ return base::WrapUnique<ImageProcessorBackend>(new VaapiImageProcessorBackend( std::move(vaapi_wrapper), input_config, output_config, OutputMode::IMPORT, std::move(error_cb), std::move(backend_task_runner))); +#endif } VaapiImageProcessorBackend::VaapiImageProcessorBackend(
diff --git a/services/network/public/cpp/features.cc b/services/network/public/cpp/features.cc index e5aed6e..07e0901 100644 --- a/services/network/public/cpp/features.cc +++ b/services/network/public/cpp/features.cc
@@ -101,6 +101,11 @@ #endif }; +// Enables Cross-Origin Opener Policy (COOP) reporting. +// https://gist.github.com/annevk/6f2dd8c79c77123f39797f6bdac43f3e +const base::Feature kCrossOriginOpenerPolicyReporting{ + "CrossOriginOpenerPolicyReporting", base::FEATURE_DISABLED_BY_DEFAULT}; + // Enables Cross-Origin Embedder Policy (COEP). // https://github.com/mikewest/corpp // Currently this feature is enabled for all platforms except WebView.
diff --git a/services/network/public/cpp/features.h b/services/network/public/cpp/features.h index e85a3c1d..7bc964d 100644 --- a/services/network/public/cpp/features.h +++ b/services/network/public/cpp/features.h
@@ -39,6 +39,8 @@ COMPONENT_EXPORT(NETWORK_CPP) extern const base::Feature kCrossOriginOpenerPolicy; COMPONENT_EXPORT(NETWORK_CPP) +extern const base::Feature kCrossOriginOpenerPolicyReporting; +COMPONENT_EXPORT(NETWORK_CPP) extern const base::Feature kCrossOriginEmbedderPolicy; COMPONENT_EXPORT(NETWORK_CPP) extern const base::Feature kBlockNonSecureExternalRequests;
diff --git a/services/tracing/public/cpp/stack_sampling/tracing_sampler_profiler.cc b/services/tracing/public/cpp/stack_sampling/tracing_sampler_profiler.cc index 67b1bdd5..5adac0c 100644 --- a/services/tracing/public/cpp/stack_sampling/tracing_sampler_profiler.cc +++ b/services/tracing/public/cpp/stack_sampling/tracing_sampler_profiler.cc
@@ -44,7 +44,6 @@ #endif #if BUILDFLAG(ENABLE_LOADER_LOCK_SAMPLING) -#include "base/threading/platform_thread.h" #include "services/tracing/public/cpp/stack_sampling/loader_lock_sampler_win.h" #endif @@ -193,54 +192,8 @@ } #if BUILDFLAG(ENABLE_LOADER_LOCK_SAMPLING) -// The loader lock is process-wide so should only be sampled on a single -// thread. -base::PlatformThreadId g_loader_lock_sample_thread_id = base::kInvalidThreadId; - -bool g_loader_lock_is_held = false; - TracingSamplerProfiler::LoaderLockSampler* g_test_loader_lock_sampler = nullptr; - -void InitializeLoaderLockSamplingForThread(base::PlatformThreadId thread_id) { - InitializeLoaderLockSampling(); - - g_loader_lock_sample_thread_id = thread_id; - - // InitializeLoaderLockSamplingForThread can be called multiple times during - // tests. Make sure each test starts from a known state. - g_loader_lock_is_held = false; -} - -// Checks the state of the loader lock while samples are being taken for thread -// |thread_id|. This function should only be called from the profiler thread -// since it updates global data. -void SampleLoaderLockForThread(base::PlatformThreadId thread_id) { - if (thread_id != g_loader_lock_sample_thread_id) - return; - - bool loader_lock_now_held = - g_test_loader_lock_sampler - ? g_test_loader_lock_sampler->IsLoaderLockHeld() - : IsLoaderLockHeld(); - - // TODO(crbug.com/1065077): It would be cleaner to save the loader lock state - // alongside buffered_samples_ and then add it to the ProcessDescriptor - // packet in - // TracingSamplerProfiler::TracingProfileBuilder::WriteSampleToTrace. But - // ProcessDescriptor is currently not being collected correctly. See the full - // discussion in the linked crbug. - if (loader_lock_now_held && !g_loader_lock_is_held) { - TRACE_EVENT_ASYNC_BEGIN0(TRACE_DISABLED_BY_DEFAULT("cpu_profiler"), - TracingSamplerProfiler::kLoaderLockHeldEventName, - thread_id); - } else if (!loader_lock_now_held && g_loader_lock_is_held) { - TRACE_EVENT_ASYNC_END0(TRACE_DISABLED_BY_DEFAULT("cpu_profiler"), - TracingSamplerProfiler::kLoaderLockHeldEventName, - thread_id); - } - g_loader_lock_is_held = loader_lock_now_held; -} -#endif // BUILDFLAG(ENABLE_LOADER_LOCK_SAMPLING) +#endif } // namespace @@ -296,7 +249,7 @@ std::vector<base::Frame> frames, base::TimeTicks sample_timestamp) { #if BUILDFLAG(ENABLE_LOADER_LOCK_SAMPLING) - SampleLoaderLockForThread(sampled_thread_id_); + SampleLoaderLock(); #endif base::AutoLock l(trace_writer_lock_); @@ -537,6 +490,35 @@ return interned_callstack.id; } +#if BUILDFLAG(ENABLE_LOADER_LOCK_SAMPLING) +void TracingSamplerProfiler::TracingProfileBuilder::SampleLoaderLock() { + if (!should_sample_loader_lock_) + return; + + bool loader_lock_now_held = + g_test_loader_lock_sampler + ? g_test_loader_lock_sampler->IsLoaderLockHeld() + : IsLoaderLockHeld(); + + // TODO(crbug.com/1065077): It would be cleaner to save the loader lock state + // alongside buffered_samples_ and then add it to the ProcessDescriptor + // packet in + // TracingSamplerProfiler::TracingProfileBuilder::WriteSampleToTrace. But + // ProcessDescriptor is currently not being collected correctly. See the full + // discussion in the linked crbug. + if (loader_lock_now_held && !loader_lock_is_held_) { + TRACE_EVENT_ASYNC_BEGIN0(TRACE_DISABLED_BY_DEFAULT("cpu_profiler"), + TracingSamplerProfiler::kLoaderLockHeldEventName, + this); + } else if (!loader_lock_now_held && loader_lock_is_held_) { + TRACE_EVENT_ASYNC_END0(TRACE_DISABLED_BY_DEFAULT("cpu_profiler"), + TracingSamplerProfiler::kLoaderLockHeldEventName, + this); + } + loader_lock_is_held_ = loader_lock_now_held; +} +#endif + // static void TracingSamplerProfiler::MangleModuleIDIfNeeded(std::string* module_id) { #if defined(OS_ANDROID) || defined(OS_LINUX) @@ -559,11 +541,15 @@ // static std::unique_ptr<TracingSamplerProfiler> TracingSamplerProfiler::CreateOnMainThread() { - auto thread_token = base::GetSamplingProfilerCurrentThreadToken(); + auto profiler = std::make_unique<TracingSamplerProfiler>( + base::GetSamplingProfilerCurrentThreadToken()); #if BUILDFLAG(ENABLE_LOADER_LOCK_SAMPLING) - InitializeLoaderLockSamplingForThread(thread_token.id); + // The loader lock is process-wide so should only be sampled on a single + // thread. The main thread is convenient. + InitializeLoaderLockSampling(); + profiler->EnableLoaderLockSampling(); #endif - return std::make_unique<TracingSamplerProfiler>(std::move(thread_token)); + return profiler; } // static @@ -662,6 +648,11 @@ auto profile_builder = std::make_unique<TracingProfileBuilder>( sampled_thread_token_.id, std::move(trace_writer), should_enable_filtering, sample_callback_for_testing_); +#if BUILDFLAG(ENABLE_LOADER_LOCK_SAMPLING) + if (should_sample_loader_lock_) + profile_builder->EnableLoaderLockSampling(); +#endif + profile_builder_ = profile_builder.get(); // Create and start the stack sampling profiler. #if defined(OS_ANDROID)
diff --git a/services/tracing/public/cpp/stack_sampling/tracing_sampler_profiler.h b/services/tracing/public/cpp/stack_sampling/tracing_sampler_profiler.h index 9f01baf..c786476 100644 --- a/services/tracing/public/cpp/stack_sampling/tracing_sampler_profiler.h +++ b/services/tracing/public/cpp/stack_sampling/tracing_sampler_profiler.h
@@ -52,6 +52,12 @@ base::RepeatingClosure()); ~TracingProfileBuilder() override; +#if BUILDFLAG(ENABLE_LOADER_LOCK_SAMPLING) + void EnableLoaderLockSampling() { should_sample_loader_lock_ = true; } + + void SampleLoaderLock(); +#endif + // base::ProfileBuilder base::ModuleCache* GetModuleCache() override; void OnSampleCompleted(std::vector<base::Frame> frames, @@ -104,6 +110,11 @@ base::TimeTicks last_timestamp_; const bool should_enable_filtering_; base::RepeatingClosure sample_callback_for_testing_; + +#if BUILDFLAG(ENABLE_LOADER_LOCK_SAMPLING) + bool should_sample_loader_lock_ = false; + bool loader_lock_is_held_ = false; +#endif }; #if BUILDFLAG(ENABLE_LOADER_LOCK_SAMPLING) @@ -119,6 +130,12 @@ // The name of a trace event that will be recorded when the loader lock is // held. static const char kLoaderLockHeldEventName[]; + + // Registers a mock LoaderLockSampler to be called during tests. |sampler| is + // owned by the caller. It must be reset to |nullptr| at the end of the test. + static void SetLoaderLockSamplerForTesting(LoaderLockSampler* sampler); + + void EnableLoaderLockSampling() { should_sample_loader_lock_ = true; } #endif // Creates sampling profiler on main thread. The profiler *must* be @@ -140,12 +157,6 @@ static void StopTracingForTesting(); static void MangleModuleIDIfNeeded(std::string* module_id); -#if BUILDFLAG(ENABLE_LOADER_LOCK_SAMPLING) - // Registers a mock LoaderLockSampler to be called during tests. |sampler| is - // owned by the caller. It must be reset to |nullptr| at the end of the test. - static void SetLoaderLockSamplerForTesting(LoaderLockSampler* sampler); -#endif - // Returns whether of not the sampler profiling is able to unwind the stack // on this platform. constexpr static bool IsStackUnwindingSupported() { @@ -179,6 +190,10 @@ TracingProfileBuilder* profile_builder_ = nullptr; base::RepeatingClosure sample_callback_for_testing_; +#if BUILDFLAG(ENABLE_LOADER_LOCK_SAMPLING) + bool should_sample_loader_lock_ = false; +#endif + DISALLOW_COPY_AND_ASSIGN(TracingSamplerProfiler); };
diff --git a/services/tracing/public/cpp/stack_sampling/tracing_sampler_profiler_unittest.cc b/services/tracing/public/cpp/stack_sampling/tracing_sampler_profiler_unittest.cc index 13aba1c..0be5803 100644 --- a/services/tracing/public/cpp/stack_sampling/tracing_sampler_profiler_unittest.cc +++ b/services/tracing/public/cpp/stack_sampling/tracing_sampler_profiler_unittest.cc
@@ -483,15 +483,25 @@ EXPECT_EQ(event_analyzer.CountEvents(), 0U); } +TEST_F(TracingSampleProfilerTest, SampleLoaderLockWithoutMock) { + // Use the real loader lock sampler. This tests that it is initialized + // correctly in TracingSamplerProfiler. + TracingSamplerProfiler::SetLoaderLockSamplerForTesting(nullptr); + + auto profiler = TracingSamplerProfiler::CreateOnMainThread(); + BeginTrace(); + base::RunLoop().RunUntilIdle(); + WaitForEvents(); + EndTracing(); + base::RunLoop().RunUntilIdle(); + + // The loader lock may or may not be held during the test, so there's no + // output to test. The test passes if it reaches the end without crashing. +} + #endif // BUILDFLAG(ENABLE_LOADER_LOCK_SAMPLING) -// Crashes on Windows. https://crbug.com/1076768 -#if defined(OS_WIN) -#define MAYBE_ValidModule DISABLED_ValidModule -#else -#define MAYBE_ValidModule ValidModule -#endif -TEST(TracingProfileBuilderTest, MAYBE_ValidModule) { +TEST(TracingProfileBuilderTest, ValidModule) { TestModule module; TracingSamplerProfiler::TracingProfileBuilder profile_builder( base::PlatformThreadId(), @@ -500,13 +510,7 @@ base::TimeTicks()); } -// Crashes on Win7 only. http://crbug.com/1076768 -#if defined(OS_WIN) -#define MAYBE_InvalidModule DISABLED_InvalidModule -#else -#define MAYBE_InvalidModule InvalidModule -#endif -TEST(TracingProfileBuilderTest, MAYBE_InvalidModule) { +TEST(TracingProfileBuilderTest, InvalidModule) { TracingSamplerProfiler::TracingProfileBuilder profile_builder( base::PlatformThreadId(), std::make_unique<MockTraceWriter>(base::DoNothing()), false);
diff --git a/testing/buildbot/chromium.perf.fyi.json b/testing/buildbot/chromium.perf.fyi.json index 3fdbe99..c1c2aef 100644 --- a/testing/buildbot/chromium.perf.fyi.json +++ b/testing/buildbot/chromium.perf.fyi.json
@@ -109,6 +109,10 @@ ], "isolate_name": "performance_test_suite", "merge": { + "args": [ + "--lightweight", + "--skip-perf" + ], "script": "//tools/perf/process_perf_results.py" }, "name": "performance_test_suite", @@ -144,6 +148,14 @@ } ] }, + "android-pixel2-processor-perf-fyi": { + "merge": { + "args": [ + "--lightweight" + ], + "script": "//tools/perf/process_perf_results.py" + } + }, "chromeos-kevin-perf-fyi": { "isolated_scripts": [ {
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index 47a4a125..6315163 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -538,6 +538,32 @@ ] } ], + "AutofillAPIServer": [ + { + "platforms": [ + "android", + "android_weblayer", + "android_webview", + "chromeos", + "ios", + "linux", + "mac", + "windows" + ], + "experiments": [ + { + "name": "API_Enabled", + "params": { + "autofill-server-url": "https://content-autofill.googleapis.com/" + }, + "enable_features": [ + "AutofillServerCommunication", + "AutofillUseApi" + ] + } + ] + } + ], "AutofillAssistantChromeEntryLaunch": [ { "platforms": [ @@ -750,32 +776,6 @@ ] } ], - "AutofillServerBehaviors": [ - { - "platforms": [ - "android", - "android_weblayer", - "android_webview", - "chromeos", - "ios", - "linux", - "mac", - "windows" - ], - "experiments": [ - { - "name": "API_Enabled", - "params": { - "autofill-server-url": "https://content-autofill.googleapis.com/" - }, - "enable_features": [ - "AutofillServerCommunication", - "AutofillUseApi" - ] - } - ] - } - ], "AutofillSmallFormSupport": [ { "platforms": [
diff --git a/third_party/blink/public/BUILD.gn b/third_party/blink/public/BUILD.gn index 3f53f797e..59eb599 100644 --- a/third_party/blink/public/BUILD.gn +++ b/third_party/blink/public/BUILD.gn
@@ -377,6 +377,7 @@ "web/web_plugin_script_forbidden_scope.h", "web/web_popup_menu_info.h", "web/web_prerenderer_client.h", + "web/web_print_page_description.h", "web/web_print_params.h", "web/web_print_preset_options.h", "web/web_print_scaling_option.h",
diff --git a/third_party/blink/public/web/web_local_frame.h b/third_party/blink/public/web/web_local_frame.h index d0795849..3a1668bd 100644 --- a/third_party/blink/public/web/web_local_frame.h +++ b/third_party/blink/public/web/web_local_frame.h
@@ -54,7 +54,6 @@ class WebContentCaptureClient; class WebContentSettingsClient; class WebDocument; -class WebDoubleSize; class WebDOMMessageEvent; class WebLocalFrameClient; class WebFrameWidget; @@ -73,6 +72,7 @@ struct WebAssociatedURLLoaderOptions; struct WebConsoleMessage; struct WebIsolatedWorldInfo; +struct WebPrintPageDescription; struct WebPrintParams; struct WebPrintPresetOptions; struct WebScriptSource; @@ -278,16 +278,11 @@ // Returns the type of @page size styling for the given page. virtual PageSizeType GetPageSizeType(int page_index) = 0; - // Returns the preferred page size and margins in pixels, assuming 96 - // pixels per inch. pageSize, marginTop, marginRight, marginBottom, - // marginLeft must be initialized to the default values that are used if - // auto is specified. - virtual void PageSizeAndMarginsInPixels(int page_index, - WebDoubleSize& page_size, - int& margin_top, - int& margin_right, - int& margin_bottom, - int& margin_left) = 0; + // Gets the description for the specified page. This includes preferred page + // size and margins in pixels, assuming 96 pixels per inch. The size and + // margins must be initialized to the default values that are used if auto is + // specified. + virtual void GetPageDescription(int page_index, WebPrintPageDescription*) = 0; // Scripting --------------------------------------------------------------
diff --git a/third_party/blink/public/web/web_print_page_description.h b/third_party/blink/public/web/web_print_page_description.h new file mode 100644 index 0000000..e7447bd --- /dev/null +++ b/third_party/blink/public/web/web_print_page_description.h
@@ -0,0 +1,23 @@ +// 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_PUBLIC_WEB_WEB_PRINT_PAGE_DESCRIPTION_H_ +#define THIRD_PARTY_BLINK_PUBLIC_WEB_WEB_PRINT_PAGE_DESCRIPTION_H_ + +#include "third_party/blink/public/platform/web_double_size.h" + +namespace blink { + +// Description of a specific page when printing. All sizes are in pixels. +struct WebPrintPageDescription { + WebDoubleSize size; + int margin_top = 0; + int margin_right = 0; + int margin_bottom = 0; + int margin_left = 0; +}; + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_PUBLIC_WEB_WEB_PRINT_PAGE_DESCRIPTION_H_
diff --git a/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_serializer.cc b/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_serializer.cc index 91fd8252..a6418f7 100644 --- a/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_serializer.cc +++ b/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_serializer.cc
@@ -555,9 +555,7 @@ "because it was not transferred."); return false; } - if (stream->IsLocked(script_state_, exception_state).value_or(true)) { - if (exception_state.HadException()) - return false; + if (stream->locked()) { exception_state.ThrowDOMException( DOMExceptionCode::kDataCloneError, "A WritableStream could not be cloned because it was locked"); @@ -587,9 +585,7 @@ if (stream->Readable() ->IsLocked(script_state_, exception_state) .value_or(true) || - stream->Writable() - ->IsLocked(script_state_, exception_state) - .value_or(true)) { + stream->Writable()->locked()) { if (exception_state.HadException()) return false; exception_state.ThrowDOMException(
diff --git a/third_party/blink/renderer/bindings/core/v8/v8_embedder_graph_builder.cc b/third_party/blink/renderer/bindings/core/v8/v8_embedder_graph_builder.cc index 914f3f7..e4c80762 100644 --- a/third_party/blink/renderer/bindings/core/v8/v8_embedder_graph_builder.cc +++ b/third_party/blink/renderer/bindings/core/v8/v8_embedder_graph_builder.cc
@@ -182,24 +182,19 @@ void VisitRoot(const void*, TraceDescriptor, const base::Location&) final; void Visit(const TraceWrapperV8Reference<v8::Value>&) final; void Visit(const void*, TraceDescriptor) final; - void VisitBackingStoreStrongly(const void*, - const void* const*, - TraceDescriptor) final; - void VisitBackingStoreWeakly(const void*, - const void* const*, - TraceDescriptor, - TraceDescriptor, - WeakCallback, - const void*) final; void VisitEphemeron(const void*, const void*, TraceCallback) final; + void VisitWeakContainer(const void*, + const void* const*, + TraceDescriptor, + TraceDescriptor, + WeakCallback, + const void*) final; // Unused Visitor overrides. void VisitWeak(const void* object, const void* object_weak_ref, TraceDescriptor desc, WeakCallback callback) final {} - void VisitBackingStoreOnly(const void*, const void* const*) final {} - void RegisterBackingStoreCallback(const void*, MovingObjectCallback) final {} void RegisterWeakCallback(WeakCallback, const void*) final {} private: @@ -685,27 +680,20 @@ graph_->AddEdge(parent_node, current_node); } -void V8EmbedderGraphBuilder::VisitBackingStoreStrongly( +void V8EmbedderGraphBuilder::VisitWeakContainer( const void* object, - const void* const* object_slot, - TraceDescriptor desc) { - if (!object) - return; - desc.callback(this, desc.base_object_payload); -} - -void V8EmbedderGraphBuilder::VisitBackingStoreWeakly( - const void* object, - const void* const* object_slot, + const void* const* slot, TraceDescriptor strong_desc, - TraceDescriptor weak_desc, - WeakCallback, - const void*) { + TraceDescriptor ephemeron_iteration, + WeakCallback weak_callback, + const void* weak_callback_parameter) { // Only ephemerons have weak callbacks. - if (weak_desc.callback) { + if (ephemeron_iteration.callback) { // Heap snapshot is always run after a GC so we know there are no dead // entries in the backing store, thus it safe to trace it strongly. - VisitBackingStoreStrongly(object, object_slot, strong_desc); + if (object) { + Visit(object, strong_desc); + } } }
diff --git a/third_party/blink/renderer/bindings/generated_in_core.gni b/third_party/blink/renderer/bindings/generated_in_core.gni index 70247a4..e920250 100644 --- a/third_party/blink/renderer/bindings/generated_in_core.gni +++ b/third_party/blink/renderer/bindings/generated_in_core.gni
@@ -276,8 +276,6 @@ "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_css_unparsed_value.h", "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_css_variable_reference_value.cc", "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_css_variable_reference_value.h", - "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_css_viewport_rule.cc", - "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_css_viewport_rule.h", "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_custom_element_registry.cc", "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_custom_element_registry.h", "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_custom_event.cc",
diff --git a/third_party/blink/renderer/core/css/resolver/style_resolver.cc b/third_party/blink/renderer/core/css/resolver/style_resolver.cc index a383649..3ab344f 100644 --- a/third_party/blink/renderer/core/css/resolver/style_resolver.cc +++ b/third_party/blink/renderer/core/css/resolver/style_resolver.cc
@@ -205,6 +205,26 @@ return right_to_left_decl; } +static CSSPropertyValueSet* MarkerUserAgentDeclarations() { + DEFINE_STATIC_LOCAL( + Persistent<MutableCSSPropertyValueSet>, marker_ua_decl, + (MakeGarbageCollected<MutableCSSPropertyValueSet>(kHTMLQuirksMode))); + if (marker_ua_decl->IsEmpty()) { + // Set 'unicode-bidi: isolate' + marker_ua_decl->SetProperty( + CSSPropertyID::kUnicodeBidi, + *CSSIdentifierValue::Create(CSSValueID::kIsolate)); + + // Set 'font-variant-numeric: tabular-nums' + CSSValueList* variant_numeric = CSSValueList::CreateSpaceSeparated(); + variant_numeric->Append( + *CSSIdentifierValue::Create(CSSValueID::kTabularNums)); + marker_ua_decl->SetProperty(CSSPropertyID::kFontVariantNumeric, + *variant_numeric); + } + return marker_ua_decl; +} + static void CollectScopedResolversForHostedShadowTrees( const Element& element, HeapVector<Member<ScopedStyleResolver>, 8>& resolvers) { @@ -1110,20 +1130,8 @@ // but that would use a slow universal element selector. So instead we apply // the styles here as an optimization. if (pseudo_style_request.pseudo_id == kPseudoIdMarker) { - auto* set = MakeGarbageCollected<MutableCSSPropertyValueSet>( - state.GetParserMode()); - - // Set 'unicode-bidi: isolate' - set->SetProperty(CSSPropertyID::kUnicodeBidi, - *CSSIdentifierValue::Create(CSSValueID::kIsolate)); - - // Set 'font-variant-numeric: tabular-nums' - CSSValueList* variant_numeric = CSSValueList::CreateSpaceSeparated(); - variant_numeric->Append( - *CSSIdentifierValue::Create(CSSValueID::kTabularNums)); - set->SetProperty(CSSPropertyID::kFontVariantNumeric, *variant_numeric); - - cascade.MutableMatchResult().AddMatchedProperties(set); + cascade.MutableMatchResult().AddMatchedProperties( + MarkerUserAgentDeclarations()); } // TODO(obrufau): support styling nested pseudo-elements
diff --git a/third_party/blink/renderer/core/dom/document.cc b/third_party/blink/renderer/core/dom/document.cc index 2d919441..cfc73bf4 100644 --- a/third_party/blink/renderer/core/dom/document.cc +++ b/third_party/blink/renderer/core/dom/document.cc
@@ -61,6 +61,7 @@ #include "third_party/blink/public/platform/task_type.h" #include "third_party/blink/public/platform/web_content_settings_client.h" #include "third_party/blink/public/platform/web_theme_engine.h" +#include "third_party/blink/public/web/web_print_page_description.h" #include "third_party/blink/renderer/bindings/core/v8/html_script_element_or_svg_script_element.h" #include "third_party/blink/renderer/bindings/core/v8/isolated_world_csp.h" #include "third_party/blink/renderer/bindings/core/v8/script_controller.h" @@ -3033,16 +3034,12 @@ EVisibility::kHidden; // display property doesn't apply to @page. } -void Document::PageSizeAndMarginsInPixels(int page_index, - DoubleSize& page_size, - int& margin_top, - int& margin_right, - int& margin_bottom, - int& margin_left) { +void Document::GetPageDescription(int page_index, + WebPrintPageDescription* description) { scoped_refptr<const ComputedStyle> style = StyleForPage(page_index); - double width = page_size.Width(); - double height = page_size.Height(); + double width = description->size.Width(); + double height = description->size.Height(); switch (style->GetPageSizeType()) { case PageSizeType::kAuto: break; @@ -3063,23 +3060,21 @@ default: NOTREACHED(); } - page_size = DoubleSize(width, height); + description->size = WebDoubleSize(width, height); // The percentage is calculated with respect to the width even for margin top // and bottom. // http://www.w3.org/TR/CSS2/box.html#margin-properties - margin_top = style->MarginTop().IsAuto() - ? margin_top - : IntValueForLength(style->MarginTop(), width); - margin_right = style->MarginRight().IsAuto() - ? margin_right - : IntValueForLength(style->MarginRight(), width); - margin_bottom = style->MarginBottom().IsAuto() - ? margin_bottom - : IntValueForLength(style->MarginBottom(), width); - margin_left = style->MarginLeft().IsAuto() - ? margin_left - : IntValueForLength(style->MarginLeft(), width); + if (!style->MarginTop().IsAuto()) + description->margin_top = IntValueForLength(style->MarginTop(), width); + if (!style->MarginRight().IsAuto()) + description->margin_right = IntValueForLength(style->MarginRight(), width); + if (!style->MarginBottom().IsAuto()) { + description->margin_bottom = + IntValueForLength(style->MarginBottom(), width); + } + if (!style->MarginLeft().IsAuto()) + description->margin_left = IntValueForLength(style->MarginLeft(), width); } void Document::SetIsViewSource(bool is_view_source) {
diff --git a/third_party/blink/renderer/core/dom/document.h b/third_party/blink/renderer/core/dom/document.h index 028aa87..0a680ab 100644 --- a/third_party/blink/renderer/core/dom/document.h +++ b/third_party/blink/renderer/core/dom/document.h
@@ -129,7 +129,6 @@ class DocumentTimeline; class DocumentType; class DOMFeaturePolicy; -class DoubleSize; class Element; class ElementDataCache; class ElementRegistrationOptions; @@ -217,6 +216,7 @@ struct FocusParams; struct IconURL; struct PhysicalOffset; +struct WebPrintPageDescription; using MouseEventWithHitTestResults = EventWithHitTestResults<WebMouseEvent>; @@ -644,16 +644,11 @@ // Returns true if page box (margin boxes and page borders) is visible. bool IsPageBoxVisible(int page_index); - // Returns the preferred page size and margins in pixels, assuming 96 - // pixels per inch. pageSize, marginTop, marginRight, marginBottom, - // marginLeft must be initialized to the default values that are used if - // auto is specified. - void PageSizeAndMarginsInPixels(int page_index, - DoubleSize& page_size, - int& margin_top, - int& margin_right, - int& margin_bottom, - int& margin_left); + // Gets the description for the specified page. This includes preferred page + // size and margins in pixels, assuming 96 pixels per inch. The size and + // margins must be initialized to the default values that are used if auto is + // specified. + void GetPageDescription(int page_index, WebPrintPageDescription*); ResourceFetcher* Fetcher() const { return fetcher_.Get(); }
diff --git a/third_party/blink/renderer/core/dom/document_test.cc b/third_party/blink/renderer/core/dom/document_test.cc index c66420cb..e908501 100644 --- a/third_party/blink/renderer/core/dom/document_test.cc +++ b/third_party/blink/renderer/core/dom/document_test.cc
@@ -41,6 +41,7 @@ #include "third_party/blink/public/common/browser_interface_broker_proxy.h" #include "third_party/blink/public/common/feature_policy/document_policy_features.h" #include "third_party/blink/public/mojom/feature_policy/feature_policy_feature.mojom-blink.h" +#include "third_party/blink/public/web/web_print_page_description.h" #include "third_party/blink/renderer/bindings/core/v8/isolated_world_csp.h" #include "third_party/blink/renderer/bindings/core/v8/script_promise_tester.h" #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h" @@ -1232,14 +1233,14 @@ GetDocument().GetFrame()->StartPrinting(initial_page_size, initial_page_size); GetDocument().View()->UpdateLifecyclePhasesForPrinting(); - DoubleSize page_size; - int margin[4]; - GetDocument().PageSizeAndMarginsInPixels(0, page_size, margin[0], margin[1], - margin[2], margin[3]); + WebPrintPageDescription description; + GetDocument().GetPageDescription(0, &description); - for (int side_margin : margin) - EXPECT_EQ(50, side_margin); - EXPECT_EQ(DoubleSize(400, 960), page_size); + EXPECT_EQ(50, description.margin_top); + EXPECT_EQ(50, description.margin_right); + EXPECT_EQ(50, description.margin_bottom); + EXPECT_EQ(50, description.margin_left); + EXPECT_EQ(WebDoubleSize(400, 960), description.size); } TEST(Document, HandlesDisconnectDuringHasTrustToken) {
diff --git a/third_party/blink/renderer/core/frame/web_local_frame_impl.cc b/third_party/blink/renderer/core/frame/web_local_frame_impl.cc index 6bc0899..2627293 100644 --- a/third_party/blink/renderer/core/frame/web_local_frame_impl.cc +++ b/third_party/blink/renderer/core/frame/web_local_frame_impl.cc
@@ -1603,16 +1603,10 @@ return GetFrame()->GetDocument()->StyleForPage(page_index)->GetPageSizeType(); } -void WebLocalFrameImpl::PageSizeAndMarginsInPixels(int page_index, - WebDoubleSize& page_size, - int& margin_top, - int& margin_right, - int& margin_bottom, - int& margin_left) { - DoubleSize size = page_size; - GetFrame()->GetDocument()->PageSizeAndMarginsInPixels( - page_index, size, margin_top, margin_right, margin_bottom, margin_left); - page_size = size; +void WebLocalFrameImpl::GetPageDescription( + int page_index, + WebPrintPageDescription* description) { + GetFrame()->GetDocument()->GetPageDescription(page_index, description); } void WebLocalFrameImpl::PrintPagesForTesting(
diff --git a/third_party/blink/renderer/core/frame/web_local_frame_impl.h b/third_party/blink/renderer/core/frame/web_local_frame_impl.h index ea7b06c..66a95b485 100644 --- a/third_party/blink/renderer/core/frame/web_local_frame_impl.h +++ b/third_party/blink/renderer/core/frame/web_local_frame_impl.h
@@ -140,12 +140,7 @@ const WebSourceLocation&) override; void SendOrientationChangeEvent() override; PageSizeType GetPageSizeType(int page_index) override; - void PageSizeAndMarginsInPixels(int page_index, - WebDoubleSize& page_size, - int& margin_top, - int& margin_right, - int& margin_bottom, - int& margin_left) override; + void GetPageDescription(int page_index, WebPrintPageDescription*) override; void ExecuteScript(const WebScriptSource&) override; void ExecuteScriptInIsolatedWorld(int32_t world_id, const WebScriptSource&) override;
diff --git a/third_party/blink/renderer/core/html/forms/html_select_element.cc b/third_party/blink/renderer/core/html/forms/html_select_element.cc index 456e8a2..ef8bcbd2 100644 --- a/third_party/blink/renderer/core/html/forms/html_select_element.cc +++ b/third_party/blink/renderer/core/html/forms/html_select_element.cc
@@ -520,6 +520,16 @@ active_selection_end_ = option; } +void HTMLSelectElement::ScrollToSelection() { + if (!IsFinishedParsingChildren()) + return; + if (UsesMenuList()) + return; + select_type_->ScrollToOption(ActiveSelectionEnd()); + if (AXObjectCache* cache = GetDocument().ExistingAXObjectCache()) + cache->ListboxActiveIndexChanged(this); +} + const HTMLSelectElement::ListItems& HTMLSelectElement::GetListItems() const { if (should_recalc_list_items_) { RecalcListItems(); @@ -1153,8 +1163,10 @@ SelectOption(option, flags); } option->SetDirty(true); + if (UsesMenuList()) + return; select_type_->ListBoxOnChange(); - select_type_->ScrollToSelection(); + ScrollToSelection(); } unsigned HTMLSelectElement::length() const {
diff --git a/third_party/blink/renderer/core/html/forms/html_select_element.h b/third_party/blink/renderer/core/html/forms/html_select_element.h index 0360b9ef..eb28983 100644 --- a/third_party/blink/renderer/core/html/forms/html_select_element.h +++ b/third_party/blink/renderer/core/html/forms/html_select_element.h
@@ -122,6 +122,8 @@ Element* namedItem(const AtomicString& name); HTMLOptionElement* item(unsigned index); + void ScrollToSelection(); + bool CanSelectAll() const; void SelectAll(); int ActiveSelectionEndListIndex() const;
diff --git a/third_party/blink/renderer/core/html/forms/select_type.cc b/third_party/blink/renderer/core/html/forms/select_type.cc index bd7bc87e..11fda22f 100644 --- a/third_party/blink/renderer/core/html/forms/select_type.cc +++ b/third_party/blink/renderer/core/html/forms/select_type.cc
@@ -620,7 +620,6 @@ void DidBlur() override; void DidSetSuggestedOption(HTMLOptionElement* option) override; void SaveLastSelection() override; - void ScrollToSelection() override; void ScrollToOption(HTMLOptionElement* option) override; void SelectAll() override; void SaveListboxActiveSelection() override; @@ -873,7 +872,7 @@ } UpdateMultiSelectFocus(); } else { - ScrollToSelection(); + select_->ScrollToSelection(); } return true; @@ -944,15 +943,7 @@ is_in_non_contiguous_selection_; option->SetMultiSelectFocusedState(is_focused); } - ScrollToSelection(); -} - -void ListBoxSelectType::ScrollToSelection() { - if (!select_->IsFinishedParsingChildren()) - return; - ScrollToOption(select_->ActiveSelectionEnd()); - if (AXObjectCache* cache = select_->GetDocument().ExistingAXObjectCache()) - cache->ListboxActiveIndexChanged(select_); + select_->ScrollToSelection(); } void ListBoxSelectType::ScrollToOption(HTMLOptionElement* option) { @@ -1122,7 +1113,7 @@ UpdateMultiSelectFocus(); select_->SetNeedsValidityCheck(); if (scroll) - ScrollToSelection(); + select_->ScrollToSelection(); select_->NotifyFormStateChanged(); } @@ -1207,7 +1198,7 @@ void SelectType::DidSelectOption(HTMLOptionElement*, HTMLSelectElement::SelectOptionFlags, bool) { - ScrollToSelection(); + select_->ScrollToSelection(); select_->SetNeedsValidityCheck(); } @@ -1233,8 +1224,6 @@ void SelectType::MaximumOptionWidthMightBeChanged() const {} -void SelectType::ScrollToSelection() {} - void SelectType::ScrollToOption(HTMLOptionElement* option) {} void SelectType::SelectAll() {
diff --git a/third_party/blink/renderer/core/html/forms/select_type.h b/third_party/blink/renderer/core/html/forms/select_type.h index d4b81d8..e6eb23d 100644 --- a/third_party/blink/renderer/core/html/forms/select_type.h +++ b/third_party/blink/renderer/core/html/forms/select_type.h
@@ -46,7 +46,6 @@ virtual const ComputedStyle* OptionStyle() const; virtual void MaximumOptionWidthMightBeChanged() const; - virtual void ScrollToSelection(); virtual void ScrollToOption(HTMLOptionElement* option); virtual void SelectAll(); virtual void SaveListboxActiveSelection();
diff --git a/third_party/blink/renderer/core/html/media/media_remoting_interstitial.h b/third_party/blink/renderer/core/html/media/media_remoting_interstitial.h index c00cfa0..6457522 100644 --- a/third_party/blink/renderer/core/html/media/media_remoting_interstitial.h +++ b/third_party/blink/renderer/core/html/media/media_remoting_interstitial.h
@@ -5,7 +5,6 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_HTML_MEDIA_MEDIA_REMOTING_INTERSTITIAL_H_ #define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_MEDIA_MEDIA_REMOTING_INTERSTITIAL_H_ -#include "third_party/blink/public/strings/grit/blink_strings.h" #include "third_party/blink/renderer/core/html/html_div_element.h" #include "third_party/blink/renderer/platform/timer.h"
diff --git a/third_party/blink/renderer/core/inspector/inspector_css_agent.cc b/third_party/blink/renderer/core/inspector/inspector_css_agent.cc index b7637ea..ef7c1ca 100644 --- a/third_party/blink/renderer/core/inspector/inspector_css_agent.cc +++ b/third_party/blink/renderer/core/inspector/inspector_css_agent.cc
@@ -60,6 +60,7 @@ #include "third_party/blink/renderer/core/display_lock/display_lock_utilities.h" #include "third_party/blink/renderer/core/dom/dom_exception.h" #include "third_party/blink/renderer/core/dom/dom_node_ids.h" +#include "third_party/blink/renderer/core/dom/flat_tree_traversal.h" #include "third_party/blink/renderer/core/dom/node.h" #include "third_party/blink/renderer/core/dom/text.h" #include "third_party/blink/renderer/core/frame/local_frame.h" @@ -860,6 +861,19 @@ if (!node_id) return; + // First check whether focus-within was set because focus or focus-within was + // forced for a child node. + NodeIdToNumberFocusedChildren::iterator focused_it = + node_id_to_number_focused_children_.find(node_id); + unsigned focused_count = + focused_it == node_id_to_number_focused_children_.end() + ? 0 + : focused_it->value; + if (pseudo_type == CSSSelector::kPseudoFocusWithin && focused_count > 0) { + *result = true; + return; + } + NodeIdToForcedPseudoState::iterator it = node_id_to_forced_pseudo_state_.find(node_id); if (it == node_id_to_forced_pseudo_state_.end()) @@ -867,6 +881,7 @@ bool force = false; unsigned forced_pseudo_state = it->value; + switch (pseudo_type) { case CSSSelector::kPseudoActive: force = forced_pseudo_state & kPseudoActive; @@ -1637,11 +1652,65 @@ node_id_to_forced_pseudo_state_.Set(node_id, forced_pseudo_state); else node_id_to_forced_pseudo_state_.erase(node_id); + + // When adding focus or focus-within, we force focus-within for ancestor + // nodes to emulate real focus for user convenience. + + // Flips from no forced focus to the forced focus (:focus or :focus-within). + if (((forced_pseudo_state & kPseudoFocus) == kPseudoFocus && + (current_forced_pseudo_state & kPseudoFocus) == 0) || + ((forced_pseudo_state & kPseudoFocusWithin) == kPseudoFocusWithin && + (current_forced_pseudo_state & kPseudoFocusWithin) == 0)) { + IncrementFocusedCountForAncestors(element); + } + + // Flips from the forced focus (:focus or :focus-within) to no focus. + if (((forced_pseudo_state & kPseudoFocus) == 0 && + (current_forced_pseudo_state & kPseudoFocus) == kPseudoFocus) || + ((forced_pseudo_state & kPseudoFocusWithin) == 0 && + (current_forced_pseudo_state & kPseudoFocusWithin) == + kPseudoFocusWithin)) { + DecrementFocusedCountForAncestors(element); + } + element->ownerDocument()->GetStyleEngine().MarkAllElementsForStyleRecalc( StyleChangeReasonForTracing::Create(style_change_reason::kInspector)); return Response::Success(); } +void InspectorCSSAgent::IncrementFocusedCountForAncestors(Element* element) { + for (Node& ancestor : FlatTreeTraversal::AncestorsOf(*element)) { + int node_id = dom_agent_->BoundNodeId(&ancestor); + if (!node_id) + continue; + NodeIdToNumberFocusedChildren::iterator it = + node_id_to_number_focused_children_.find(node_id); + unsigned count = + it == node_id_to_number_focused_children_.end() ? 0 : it->value; + node_id_to_number_focused_children_.Set(node_id, count + 1); + } +} + +void InspectorCSSAgent::DecrementFocusedCountForAncestors(Element* element) { + for (Node& ancestor : FlatTreeTraversal::AncestorsOf(*element)) { + int node_id = dom_agent_->BoundNodeId(&ancestor); + if (!node_id) + continue; + NodeIdToNumberFocusedChildren::iterator it = + node_id_to_number_focused_children_.find(node_id); + unsigned count = + it == node_id_to_number_focused_children_.end() ? 1 : it->value; + if (count <= 1) { + // If `count - 1` is zero or overflows, erase the node_id + // from the map to save memory. If there is zero focused child + // elements, :focus-within should not be forced. + node_id_to_number_focused_children_.erase(node_id); + } else { + node_id_to_number_focused_children_.Set(node_id, count - 1); + } + } +} + std::unique_ptr<protocol::CSS::CSSMedia> InspectorCSSAgent::BuildMediaObject( const MediaList* media, MediaListSource media_list_source, @@ -2154,7 +2223,14 @@ documents_to_change.insert(element->ownerDocument()); } + for (auto& count : node_id_to_number_focused_children_) { + auto* element = To<Element>(dom_agent_->NodeForId(count.key)); + if (element && element->ownerDocument()) + documents_to_change.insert(element->ownerDocument()); + } + node_id_to_forced_pseudo_state_.clear(); + node_id_to_number_focused_children_.clear(); for (auto& document : documents_to_change) { document->GetStyleEngine().MarkAllElementsForStyleRecalc( StyleChangeReasonForTracing::Create(style_change_reason::kInspector));
diff --git a/third_party/blink/renderer/core/inspector/inspector_css_agent.h b/third_party/blink/renderer/core/inspector/inspector_css_agent.h index 5815c86..449b85ea 100644 --- a/third_party/blink/renderer/core/inspector/inspector_css_agent.h +++ b/third_party/blink/renderer/core/inspector/inspector_css_agent.h
@@ -245,6 +245,7 @@ NodeToInspectorStyleSheet; // bogus "stylesheets" with elements' inline // styles typedef HashMap<int, unsigned> NodeIdToForcedPseudoState; + typedef HashMap<int, unsigned> NodeIdToNumberFocusedChildren; void ResourceContentLoaded(std::unique_ptr<EnableCallback>); void CompleteEnabled(); @@ -303,6 +304,9 @@ void ResetPseudoStates(); + void IncrementFocusedCountForAncestors(Element*); + void DecrementFocusedCountForAncestors(Element*); + Member<InspectorDOMAgent> dom_agent_; Member<InspectedFrames> inspected_frames_; Member<InspectorNetworkAgent> network_agent_; @@ -322,6 +326,7 @@ NodeToInspectorStyleSheet node_to_inspector_style_sheet_; NodeIdToForcedPseudoState node_id_to_forced_pseudo_state_; + NodeIdToNumberFocusedChildren node_id_to_number_focused_children_; Member<StyleRuleUsageTracker> tracker_;
diff --git a/third_party/blink/renderer/core/page/print_context.cc b/third_party/blink/renderer/core/page/print_context.cc index f7f90db..6db4817 100644 --- a/third_party/blink/renderer/core/page/print_context.cc +++ b/third_party/blink/renderer/core/page/print_context.cc
@@ -22,6 +22,7 @@ #include <utility> +#include "third_party/blink/public/web/web_print_page_description.h" #include "third_party/blink/renderer/core/frame/local_frame.h" #include "third_party/blink/renderer/core/frame/local_frame_view.h" #include "third_party/blink/renderer/core/layout/layout_view.h" @@ -286,15 +287,20 @@ int margin_right, int margin_bottom, int margin_left) { - DoubleSize page_size(width, height); - frame->GetDocument()->PageSizeAndMarginsInPixels(page_number, page_size, - margin_top, margin_right, - margin_bottom, margin_left); + WebPrintPageDescription description; + description.size = WebDoubleSize(width, height); + description.margin_top = margin_top; + description.margin_right = margin_right; + description.margin_bottom = margin_bottom; + description.margin_left = margin_left; + frame->GetDocument()->GetPageDescription(page_number, &description); - return "(" + String::Number(floor(page_size.Width())) + ", " + - String::Number(floor(page_size.Height())) + ") " + - String::Number(margin_top) + ' ' + String::Number(margin_right) + ' ' + - String::Number(margin_bottom) + ' ' + String::Number(margin_left); + return "(" + String::Number(floor(description.size.Width())) + ", " + + String::Number(floor(description.size.Height())) + ") " + + String::Number(description.margin_top) + ' ' + + String::Number(description.margin_right) + ' ' + + String::Number(description.margin_bottom) + ' ' + + String::Number(description.margin_left); } // static
diff --git a/third_party/blink/renderer/core/streams/writable_stream.h b/third_party/blink/renderer/core/streams/writable_stream.h index 70533b4..99775e5 100644 --- a/third_party/blink/renderer/core/streams/writable_stream.h +++ b/third_party/blink/renderer/core/streams/writable_stream.h
@@ -92,14 +92,6 @@ // Inherited methods used internally. - // https://streams.spec.whatwg.org/#is-writable-stream-locked - // TODO(ricea): Delete this variant once the V8 extras implementation is - // removed. - base::Optional<bool> IsLocked(ScriptState*, ExceptionState&) const { - return IsLocked(this); - } - - // This version can't fail. static bool IsLocked(const WritableStream* stream) { return stream->writer_; } void Serialize(ScriptState*, MessagePort*, ExceptionState&);
diff --git a/third_party/blink/renderer/core/streams/writable_stream_test.cc b/third_party/blink/renderer/core/streams/writable_stream_test.cc index 731c0d3d..df68988 100644 --- a/third_party/blink/renderer/core/streams/writable_stream_test.cc +++ b/third_party/blink/renderer/core/streams/writable_stream_test.cc
@@ -41,14 +41,10 @@ ASSERT_TRUE(stream); EXPECT_FALSE(stream->locked()); - EXPECT_EQ(stream->IsLocked(script_state, ASSERT_NO_EXCEPTION), - base::make_optional(false)); stream->getWriter(script_state, ASSERT_NO_EXCEPTION); EXPECT_TRUE(stream->locked()); - EXPECT_EQ(stream->IsLocked(script_state, ASSERT_NO_EXCEPTION), - base::make_optional(true)); } TEST(WritableStreamTest, Serialize) {
diff --git a/third_party/blink/renderer/modules/mediastream/media_stream_audio_processor.cc b/third_party/blink/renderer/modules/mediastream/media_stream_audio_processor.cc index ea44f010..04477de 100644 --- a/third_party/blink/renderer/modules/mediastream/media_stream_audio_processor.cc +++ b/third_party/blink/renderer/modules/mediastream/media_stream_audio_processor.cc
@@ -603,6 +603,7 @@ blink::EnableTypingDetection(&apm_config, typing_detector_.get()); } + apm_config.residual_echo_detector.enabled = false; audio_processing_->ApplyConfig(apm_config); }
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_encoded_audio_underlying_sink.cc b/third_party/blink/renderer/modules/peerconnection/rtc_encoded_audio_underlying_sink.cc index 4701116..814413870 100644 --- a/third_party/blink/renderer/modules/peerconnection/rtc_encoded_audio_underlying_sink.cc +++ b/third_party/blink/renderer/modules/peerconnection/rtc_encoded_audio_underlying_sink.cc
@@ -53,7 +53,14 @@ return ScriptPromise(); } - transformer_callback_.Run()->SendFrameToSink(std::move(webrtc_frame)); + RTCEncodedAudioStreamTransformer* transformer = transformer_callback_.Run(); + if (!transformer) { + exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError, + "No underlying sink"); + return ScriptPromise(); + } + + transformer->SendFrameToSink(std::move(webrtc_frame)); return ScriptPromise::CastUndefined(script_state); }
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_encoded_audio_underlying_sink_test.cc b/third_party/blink/renderer/modules/peerconnection/rtc_encoded_audio_underlying_sink_test.cc index a3fbf8c6..ad703c4bd 100644 --- a/third_party/blink/renderer/modules/peerconnection/rtc_encoded_audio_underlying_sink_test.cc +++ b/third_party/blink/renderer/modules/peerconnection/rtc_encoded_audio_underlying_sink_test.cc
@@ -11,6 +11,7 @@ #include "third_party/blink/renderer/bindings/core/v8/script_promise_tester.h" #include "third_party/blink/renderer/bindings/core/v8/to_v8_for_core.h" #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h" +#include "third_party/blink/renderer/bindings/core/v8/v8_dom_exception.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_rtc_encoded_audio_frame.h" #include "third_party/blink/renderer/core/streams/writable_stream.h" #include "third_party/blink/renderer/core/streams/writable_stream_default_writer.h" @@ -46,6 +47,17 @@ uint32_t GetSsrc() const override { return 0; } }; +bool IsDOMException(ScriptState* script_state, + ScriptValue value, + DOMExceptionCode code) { + auto* dom_exception = V8DOMException::ToImplWithTypeCheck( + script_state->GetIsolate(), value.V8Value()); + if (!dom_exception) + return false; + + return dom_exception->code() == static_cast<uint16_t>(code); +} + } // namespace class RTCEncodedAudioUnderlyingSinkTest : public testing::Test { @@ -76,6 +88,14 @@ WTF::Unretained(this))); } + RTCEncodedAudioUnderlyingSink* CreateNullCallbackSink( + ScriptState* script_state) { + return MakeGarbageCollected<RTCEncodedAudioUnderlyingSink>( + script_state, + WTF::BindRepeating( + []() -> RTCEncodedAudioStreamTransformer* { return nullptr; })); + } + RTCEncodedAudioStreamTransformer* GetTransformer() { return &transformer_; } ScriptValue CreateEncodedAudioFrameChunk(ScriptState* script_state) { @@ -138,4 +158,25 @@ EXPECT_TRUE(dummy_exception_state.HadException()); } +TEST_F(RTCEncodedAudioUnderlyingSinkTest, WriteToNullCallbackSinkFails) { + V8TestingScope v8_scope; + ScriptState* script_state = v8_scope.GetScriptState(); + auto* sink = CreateNullCallbackSink(script_state); + auto* stream = + WritableStream::CreateWithCountQueueingStrategy(script_state, sink, 1u); + + NonThrowableExceptionState exception_state; + auto* writer = stream->getWriter(script_state, exception_state); + + EXPECT_CALL(*webrtc_callback_, OnTransformedFrame(_)).Times(0); + ScriptPromiseTester write_tester( + script_state, + writer->write(script_state, CreateEncodedAudioFrameChunk(script_state), + exception_state)); + write_tester.WaitUntilSettled(); + EXPECT_TRUE(write_tester.IsRejected()); + EXPECT_TRUE(IsDOMException(script_state, write_tester.Value(), + DOMExceptionCode::kInvalidStateError)); +} + } // namespace blink
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_encoded_video_underlying_sink.cc b/third_party/blink/renderer/modules/peerconnection/rtc_encoded_video_underlying_sink.cc index d48c663..b4b7bd8 100644 --- a/third_party/blink/renderer/modules/peerconnection/rtc_encoded_video_underlying_sink.cc +++ b/third_party/blink/renderer/modules/peerconnection/rtc_encoded_video_underlying_sink.cc
@@ -53,7 +53,14 @@ return ScriptPromise(); } - transformer_callback_.Run()->SendFrameToSink(std::move(webrtc_frame)); + RTCEncodedVideoStreamTransformer* transformer = transformer_callback_.Run(); + if (!transformer) { + exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError, + "No underlying sink"); + return ScriptPromise(); + } + + transformer->SendFrameToSink(std::move(webrtc_frame)); return ScriptPromise::CastUndefined(script_state); }
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_encoded_video_underlying_sink_test.cc b/third_party/blink/renderer/modules/peerconnection/rtc_encoded_video_underlying_sink_test.cc index 7f5c84c..3a606d1 100644 --- a/third_party/blink/renderer/modules/peerconnection/rtc_encoded_video_underlying_sink_test.cc +++ b/third_party/blink/renderer/modules/peerconnection/rtc_encoded_video_underlying_sink_test.cc
@@ -11,6 +11,7 @@ #include "third_party/blink/renderer/bindings/core/v8/script_promise_tester.h" #include "third_party/blink/renderer/bindings/core/v8/to_v8_for_core.h" #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h" +#include "third_party/blink/renderer/bindings/core/v8/v8_dom_exception.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_rtc_encoded_video_frame.h" #include "third_party/blink/renderer/core/streams/writable_stream.h" #include "third_party/blink/renderer/core/streams/writable_stream_default_writer.h" @@ -56,6 +57,17 @@ uint32_t ssrc_; }; +bool IsDOMException(ScriptState* script_state, + ScriptValue value, + DOMExceptionCode code) { + auto* dom_exception = V8DOMException::ToImplWithTypeCheck( + script_state->GetIsolate(), value.V8Value()); + if (!dom_exception) + return false; + + return dom_exception->code() == static_cast<uint16_t>(code); +} + } // namespace class RTCEncodedVideoUnderlyingSinkTest : public testing::Test { @@ -86,6 +98,14 @@ WTF::Unretained(this))); } + RTCEncodedVideoUnderlyingSink* CreateNullCallbackSink( + ScriptState* script_state) { + return MakeGarbageCollected<RTCEncodedVideoUnderlyingSink>( + script_state, + WTF::BindRepeating( + []() -> RTCEncodedVideoStreamTransformer* { return nullptr; })); + } + RTCEncodedVideoStreamTransformer* GetTransformer() { return &transformer_; } ScriptValue CreateEncodedVideoFrameChunk(ScriptState* script_state) { @@ -148,4 +168,25 @@ EXPECT_TRUE(dummy_exception_state.HadException()); } +TEST_F(RTCEncodedVideoUnderlyingSinkTest, WriteToNullCallbackSinkFails) { + V8TestingScope v8_scope; + ScriptState* script_state = v8_scope.GetScriptState(); + auto* sink = CreateNullCallbackSink(script_state); + auto* stream = + WritableStream::CreateWithCountQueueingStrategy(script_state, sink, 1u); + + NonThrowableExceptionState exception_state; + auto* writer = stream->getWriter(script_state, exception_state); + + EXPECT_CALL(*webrtc_callback_, OnTransformedFrame(_)).Times(0); + ScriptPromiseTester write_tester( + script_state, + writer->write(script_state, CreateEncodedVideoFrameChunk(script_state), + exception_state)); + write_tester.WaitUntilSettled(); + EXPECT_TRUE(write_tester.IsRejected()); + EXPECT_TRUE(IsDOMException(script_state, write_tester.Value(), + DOMExceptionCode::kInvalidStateError)); +} + } // namespace blink
diff --git a/third_party/blink/renderer/platform/heap/heap_allocator.h b/third_party/blink/renderer/platform/heap/heap_allocator.h index 298a96e2..f88fca7 100644 --- a/third_party/blink/renderer/platform/heap/heap_allocator.h +++ b/third_party/blink/renderer/platform/heap/heap_allocator.h
@@ -234,19 +234,17 @@ static void TraceVectorBacking(Visitor* visitor, const T* backing, const T* const* backing_slot) { - visitor->TraceBackingStoreStrongly( - reinterpret_cast<const HeapVectorBacking<T>*>(backing), - reinterpret_cast<const HeapVectorBacking<T>* const*>(backing_slot)); + visitor->TraceMovablePointer(backing_slot); + visitor->Trace(reinterpret_cast<const HeapVectorBacking<T>*>(backing)); } template <typename T, typename HashTable> static void TraceHashTableBackingStrongly(Visitor* visitor, const T* backing, const T* const* backing_slot) { - visitor->TraceBackingStoreStrongly( - reinterpret_cast<const HeapHashTableBacking<HashTable>*>(backing), - reinterpret_cast<const HeapHashTableBacking<HashTable>* const*>( - backing_slot)); + visitor->TraceMovablePointer(backing_slot); + visitor->Trace( + reinterpret_cast<const HeapHashTableBacking<HashTable>*>(backing)); } template <typename T, typename HashTable> @@ -255,23 +253,18 @@ const T* const* backing_slot, WeakCallback callback, const void* parameter) { - visitor->TraceBackingStoreWeakly<HashTable>( + visitor->TraceMovablePointer(backing_slot); + visitor->TraceWeakContainer( reinterpret_cast<const HeapHashTableBacking<HashTable>*>(backing), reinterpret_cast<const HeapHashTableBacking<HashTable>* const*>( backing_slot), + TraceTrait<HeapHashTableBacking<HashTable>>::GetTraceDescriptor( + backing), + TraceTrait<HeapHashTableBacking<HashTable>>::GetWeakTraceDescriptor( + backing), callback, parameter); } - template <typename T, typename HashTable> - static void TraceHashTableBackingOnly(Visitor* visitor, - const T* backing, - const T* const* backing_slot) { - visitor->TraceBackingStoreOnly( - reinterpret_cast<const HeapHashTableBacking<HashTable>*>(backing), - reinterpret_cast<const HeapHashTableBacking<HashTable>* const*>( - backing_slot)); - } - private: static Address MarkAsConstructed(Address address) { HeapObjectHeader::FromPayload(reinterpret_cast<void*>(address))
diff --git a/third_party/blink/renderer/platform/heap/incremental_marking_test.cc b/third_party/blink/renderer/platform/heap/incremental_marking_test.cc index 85b9c1c0..b59e372 100644 --- a/third_party/blink/renderer/platform/heap/incremental_marking_test.cc +++ b/third_party/blink/renderer/platform/heap/incremental_marking_test.cc
@@ -68,18 +68,6 @@ const void* object_weak_ref, TraceDescriptor desc, WeakCallback callback) final {} - void VisitBackingStoreStrongly(const void* object, - const void* const* object_slot, - TraceDescriptor desc) final {} - void VisitBackingStoreWeakly(const void*, - const void* const*, - TraceDescriptor, - TraceDescriptor, - WeakCallback, - const void*) final {} - void VisitBackingStoreOnly(const void*, const void* const*) final {} - void RegisterBackingStoreCallback(const void* slot, - MovingObjectCallback) final {} void RegisterWeakCallback(WeakCallback, const void*) final {} void Visit(const TraceWrapperV8Reference<v8::Value>&) final {} @@ -1541,7 +1529,7 @@ driver.FinishGC(); // Weak callback should register the slot. - EXPECT_EQ(driver.GetHeapCompactLastFixupCount(), 2u); + EXPECT_EQ(1u, driver.GetHeapCompactLastFixupCount()); } TEST_F(IncrementalMarkingTest, ConservativeGCWhileCompactionScheduled) {
diff --git a/third_party/blink/renderer/platform/heap/marking_verifier.cc b/third_party/blink/renderer/platform/heap/marking_verifier.cc index eb900719..45067dfe 100644 --- a/third_party/blink/renderer/platform/heap/marking_verifier.cc +++ b/third_party/blink/renderer/platform/heap/marking_verifier.cc
@@ -37,24 +37,12 @@ VerifyChild(object, desc.base_object_payload); } -void MarkingVerifier::VisitBackingStoreStrongly(const void* object, - const void* const*, - TraceDescriptor desc) { - if (!object) - return; - - // Contents of backing stores are verified through page iteration. The - // verification here only makes sure that the backing itself is properly - // marked. - VerifyChild(object, desc.base_object_payload); -} - -void MarkingVerifier::VisitBackingStoreWeakly(const void* object, - const void* const*, - TraceDescriptor strong_desc, - TraceDescriptor weak_desc, - WeakCallback, - const void*) { +void MarkingVerifier::VisitWeakContainer(const void* object, + const void* const*, + TraceDescriptor, + TraceDescriptor weak_desc, + WeakCallback, + const void*) { if (!object) return;
diff --git a/third_party/blink/renderer/platform/heap/marking_verifier.h b/third_party/blink/renderer/platform/heap/marking_verifier.h index 07d12d74..0113d6a 100644 --- a/third_party/blink/renderer/platform/heap/marking_verifier.h +++ b/third_party/blink/renderer/platform/heap/marking_verifier.h
@@ -25,20 +25,14 @@ TraceDescriptor desc, WeakCallback callback) final; - void VisitBackingStoreStrongly(const void*, - const void* const*, - TraceDescriptor) final; - - void VisitBackingStoreWeakly(const void*, - const void* const*, - TraceDescriptor, - TraceDescriptor, - WeakCallback, - const void*) final; + void VisitWeakContainer(const void*, + const void* const*, + TraceDescriptor, + TraceDescriptor, + WeakCallback, + const void*) final; // Unused overrides. - void VisitBackingStoreOnly(const void*, const void* const*) final {} - void RegisterBackingStoreCallback(const void*, MovingObjectCallback) final {} void RegisterWeakCallback(WeakCallback, const void*) final {} void Visit(const TraceWrapperV8Reference<v8::Value>&) final {}
diff --git a/third_party/blink/renderer/platform/heap/marking_visitor.cc b/third_party/blink/renderer/platform/heap/marking_visitor.cc index 1679e23..fef919a 100644 --- a/third_party/blink/renderer/platform/heap/marking_visitor.cc +++ b/third_party/blink/renderer/platform/heap/marking_visitor.cc
@@ -40,15 +40,6 @@ weak_callback_worklist_.Push({callback, object}); } -void MarkingVisitorCommon::RegisterBackingStoreReference( - const void* const* slot) { - if (marking_mode_ != kGlobalMarkingWithCompaction) - return; - if (Heap().ShouldRegisterMovingAddress()) { - movable_reference_worklist_.Push(slot); - } -} - void MarkingVisitorCommon::RegisterBackingStoreCallback( const void* backing, MovingObjectCallback callback) { @@ -59,6 +50,14 @@ } } +void MarkingVisitorCommon::RegisterMovableSlot(const void* const* slot) { + if (marking_mode_ != kGlobalMarkingWithCompaction) + return; + if (Heap().ShouldRegisterMovingAddress()) { + movable_reference_worklist_.Push(slot); + } +} + void MarkingVisitorCommon::VisitWeak(const void* object, const void* object_weak_ref, TraceDescriptor desc, @@ -73,39 +72,6 @@ RegisterWeakCallback(callback, object_weak_ref); } -void MarkingVisitorCommon::VisitBackingStoreStrongly( - const void* object, - const void* const* object_slot, - TraceDescriptor desc) { - RegisterBackingStoreReference(object_slot); - if (!object) - return; - Visit(object, desc); -} - -// All work is registered through RegisterWeakCallback. -void MarkingVisitorCommon::VisitBackingStoreWeakly( - const void* object, - const void* const* object_slot, - TraceDescriptor strong_desc, - TraceDescriptor weak_desc, - WeakCallback weak_callback, - const void* weak_callback_parameter) { - RegisterBackingStoreReference(object_slot); - - // In case there's no object present, weakness processing is omitted. The GC - // relies on the fact that in such cases touching the weak data structure will - // strongify its references. - if (!object) - return; - - // Register final weak processing of the backing store. - RegisterWeakCallback(weak_callback, weak_callback_parameter); - // Register ephemeron callbacks if necessary. - if (weak_desc.callback) - weak_table_worklist_.Push(weak_desc); -} - void MarkingVisitorCommon::VisitEphemeron(const void* key, const void* value, TraceCallback value_trace_callback) { @@ -115,15 +81,37 @@ value_trace_callback(this, value); } -void MarkingVisitorCommon::VisitBackingStoreOnly( +void MarkingVisitorCommon::VisitWeakContainer( const void* object, - const void* const* object_slot) { - RegisterBackingStoreReference(object_slot); + const void* const*, + TraceDescriptor, + TraceDescriptor weak_desc, + WeakCallback weak_callback, + const void* weak_callback_parameter) { + // In case there's no object present, weakness processing is omitted. The GC + // relies on the fact that in such cases touching the weak data structure will + // strongify its references. if (!object) return; + + // Only trace the container initially. Its buckets will be processed after + // marking. The interesting cases are: + // - The backing of the container is dropped using clear(): The backing can + // still be compacted but empty/deleted buckets will only be destroyed once + // the backing is reclaimed by the garbage collector on the next cycle. + // - The container expands/shrinks: Buckets are moved to the new backing + // store and strongified, resulting in all buckets being alive. The old + // backing store is marked but only contains empty/deleted buckets as all + // non-empty/deleted buckets have been moved to the new backing store. HeapObjectHeader* header = HeapObjectHeader::FromPayload(object); MarkHeaderNoTracing(header); AccountMarkedBytes(header); + + // Register final weak processing of the backing store. + RegisterWeakCallback(weak_callback, weak_callback_parameter); + // Register ephemeron callbacks if necessary. + if (weak_desc.callback) + weak_table_worklist_.Push(weak_desc); } // static
diff --git a/third_party/blink/renderer/platform/heap/marking_visitor.h b/third_party/blink/renderer/platform/heap/marking_visitor.h index a128bae..af99c8f 100644 --- a/third_party/blink/renderer/platform/heap/marking_visitor.h +++ b/third_party/blink/renderer/platform/heap/marking_visitor.h
@@ -33,22 +33,14 @@ }; void VisitWeak(const void*, const void*, TraceDescriptor, WeakCallback) final; - void VisitBackingStoreStrongly(const void*, - const void* const*, - TraceDescriptor) final; - void VisitBackingStoreWeakly(const void*, - const void* const*, - TraceDescriptor, - TraceDescriptor, - WeakCallback, - const void*) final; + void VisitWeakContainer(const void*, + const void* const*, + TraceDescriptor, + TraceDescriptor, + WeakCallback, + const void*) final; void VisitEphemeron(const void*, const void*, TraceCallback) final; - // Used to only mark the backing store when it has been registered for weak - // processing. In this case, the contents are processed separately using - // the corresponding traits but the backing store requires marking. - void VisitBackingStoreOnly(const void*, const void* const*) final; - // This callback mechanism is needed to account for backing store objects // containing intra-object pointers, all of which must be relocated/rebased // with respect to the moved-to location. @@ -56,6 +48,9 @@ // For Blink, |HeapLinkedHashSet<>| is currently the only abstraction which // relies on this feature. void RegisterBackingStoreCallback(const void*, MovingObjectCallback) final; + + void RegisterMovableSlot(const void* const*) final; + void RegisterWeakCallback(WeakCallback, const void*) final; // Flush private segments remaining in visitor's worklists to global pools. @@ -78,8 +73,6 @@ // marked upon calling. bool MarkHeaderNoTracing(HeapObjectHeader*); - void RegisterBackingStoreReference(const void* const* slot); - MarkingWorklist::View marking_worklist_; WriteBarrierWorklist::View write_barrier_worklist_; NotFullyConstructedWorklist::View not_fully_constructed_worklist_;
diff --git a/third_party/blink/renderer/platform/heap/visitor.h b/third_party/blink/renderer/platform/heap/visitor.h index ba5f092..b5db7048 100644 --- a/third_party/blink/renderer/platform/heap/visitor.h +++ b/third_party/blink/renderer/platform/heap/visitor.h
@@ -155,45 +155,6 @@ Visit(t, TraceDescriptorFor(t)); } - template <typename T> - void TraceBackingStoreStrongly(const T* backing_store, - const T* const* backing_store_slot) { - static_assert(sizeof(T), "T must be fully defined"); - static_assert(IsGarbageCollectedType<T>::value, - "T needs to be a garbage collected object"); - - VisitBackingStoreStrongly( - backing_store, reinterpret_cast<const void* const*>(backing_store_slot), - TraceDescriptorFor(backing_store)); - } - - template <typename HashTable, typename T> - void TraceBackingStoreWeakly(const T* backing_store, - const T* const* backing_store_slot, - WeakCallback weak_callback, - const void* weak_callback_parameter) { - static_assert(sizeof(T), "T must be fully defined"); - static_assert(IsGarbageCollectedType<T>::value, - "T needs to be a garbage collected object"); - - VisitBackingStoreWeakly( - backing_store, reinterpret_cast<const void* const*>(backing_store_slot), - TraceDescriptorFor(backing_store), - WeakTraceDescriptorFor(backing_store), weak_callback, - weak_callback_parameter); - } - - template <typename T> - void TraceBackingStoreOnly(const T* backing_store, - const T* const* backing_store_slot) { - static_assert(sizeof(T), "T must be fully defined"); - static_assert(IsGarbageCollectedType<T>::value, - "T needs to be a garbage collected object"); - - VisitBackingStoreOnly(backing_store, reinterpret_cast<const void* const*>( - backing_store_slot)); - } - // WeakMember version of the templated trace method. It doesn't keep // the traced thing alive, but will write null to the WeakMember later // if the pointed-to object is dead. It's lying for this to be const, @@ -246,6 +207,26 @@ value, value_trace_callback); } + template <typename T> + void TraceWeakContainer(const T* object, + const T* const* slot, + TraceDescriptor strong_desc, + TraceDescriptor weak_dec, + WeakCallback weak_callback, + const void* weak_callback_parameter) { + static_assert(sizeof(T), "T must be fully defined"); + static_assert(IsGarbageCollectedType<T>::value, + "T needs to be a garbage collected object"); + VisitWeakContainer(reinterpret_cast<const void*>(object), + reinterpret_cast<const void* const*>(slot), strong_desc, + weak_dec, weak_callback, weak_callback_parameter); + } + + template <typename T> + void TraceMovablePointer(const T* const* slot) { + RegisterMovableSlot(reinterpret_cast<const void* const*>(slot)); + } + // Registers an instance method using |RegisterWeakCallback|. See description // below. template <typename T, void (T::*method)(const LivenessBroker&)> @@ -278,22 +259,25 @@ TraceDescriptor, WeakCallback) = 0; - // Visitors for collection backing stores. - virtual void VisitBackingStoreStrongly(const void*, - const void* const*, - TraceDescriptor) = 0; - virtual void VisitBackingStoreWeakly(const void*, - const void* const*, - TraceDescriptor, - TraceDescriptor, - WeakCallback, - const void*) = 0; - virtual void VisitBackingStoreOnly(const void*, const void* const*) = 0; - // Visits ephemeron pairs which are a combination of weak and strong keys and // values. virtual void VisitEphemeron(const void*, const void*, TraceCallback) {} + // Visits a container |object| holding ephemeron pairs held from |slot|. The + // descriptor |strong_desc| can be used to enforce strong treatment of + // |object|. The |weak_desc| descriptor is invoked repeatedly until no + // more new objects are found. It is expected that |weak_desc| processing + // ultimately yields in a call to VisitEphemeron. After marking all reachable + // objects, |weak_callback| is invoked with |weak_callback_parameter|. It is + // expected that this callback is used to reset non-live entries in the + // ephemeron container. + virtual void VisitWeakContainer(const void* object, + const void* const* slot, + TraceDescriptor strong_desc, + TraceDescriptor weak_desc, + WeakCallback weak_callback, + const void* weak_callback_parameter) {} + // Visits cross-component references to V8. virtual void Visit(const TraceWrapperV8Reference<v8::Value>&) = 0; @@ -301,7 +285,9 @@ // Registers backing store pointers so that they can be moved and properly // updated. virtual void RegisterBackingStoreCallback(const void* backing, - MovingObjectCallback) = 0; + MovingObjectCallback) {} + + virtual void RegisterMovableSlot(const void* const* slot) {} // Adds a |callback| that is invoked with |parameter| after liveness has been // computed on the whole object graph. The |callback| may use the provided @@ -333,11 +319,6 @@ return TraceTrait<T>::GetTraceDescriptor(traceable); } - template <typename T> - static inline TraceDescriptor WeakTraceDescriptorFor(const T* traceable) { - return TraceTrait<T>::GetWeakTraceDescriptor(traceable); - } - private: template <typename T> static void HandleWeakCell(const LivenessBroker&, const void*);
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5 index 5a4d13f..64c3d17 100644 --- a/third_party/blink/renderer/platform/runtime_enabled_features.json5 +++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -349,9 +349,7 @@ }, { name: "ContactsManagerExtraProperties", - origin_trial_feature_name: "ContactsManagerExtraProperties", - origin_trial_os: ["android"], - status: {"Android": "experimental", "default": "test"}, + status: {"Android": "stable", "default": "test"}, }, { name: "ContentIndex",
diff --git a/third_party/blink/renderer/platform/wtf/hash_table.h b/third_party/blink/renderer/platform/wtf/hash_table.h index 5a4468d..2ad6f20b 100644 --- a/third_party/blink/renderer/platform/wtf/hash_table.h +++ b/third_party/blink/renderer/platform/wtf/hash_table.h
@@ -2174,17 +2174,6 @@ // Weak HashTable. The HashTable may be held alive strongly from somewhere // else, e.g., an iterator. - // Only trace the backing store. Its buckets will be processed after - // marking. The interesting cases for marking are: - // - The backing is dropped using clear(): The backing can still be - // compacted but empty/deleted buckets will only be destroyed once the - // backing is reclaimed by the garbage collector on the next cycle. - // - The hash table expands/shrinks: Buckets are moved to the new backing - // store and strongified, resulting in all buckets being alive. The old - // backing store is marked but only contains empty/deleted buckets as all - // non-empty/deleted buckets have been moved to the new backing store. - Allocator::template TraceHashTableBackingOnly<ValueType, HashTable>( - visitor, table, &table_); // Trace the table weakly. For marking this will result in delaying the // processing until the end of the atomic pause. It is safe to trace // weakly multiple times.
diff --git a/third_party/blink/web_tests/NeverFixTests b/third_party/blink/web_tests/NeverFixTests index a5a5556..5457919 100644 --- a/third_party/blink/web_tests/NeverFixTests +++ b/third_party/blink/web_tests/NeverFixTests
@@ -1979,11 +1979,6 @@ [ Linux ] virtual/origin-trials-runtimeflags-disabled/http/tests/origin_trials/webexposed/web-nfc-origin-trial-interfaces.html [ Skip ] [ Mac ] virtual/origin-trials-runtimeflags-disabled/http/tests/origin_trials/webexposed/web-nfc-origin-trial-interfaces.html [ Skip ] -# Chrome Win/Linux/Mac don't support Contacts Picker API yet. -[ Win ] virtual/origin-trials-runtimeflags-disabled/http/tests/origin_trials/webexposed/contacts-manager-extra-properties-trial-interfaces.html [ Skip ] -[ Linux ] virtual/origin-trials-runtimeflags-disabled/http/tests/origin_trials/webexposed/contacts-manager-extra-properties-trial-interfaces.html [ Skip ] -[ Mac ] virtual/origin-trials-runtimeflags-disabled/http/tests/origin_trials/webexposed/contacts-manager-extra-properties-trial-interfaces.html [ Skip ] - crbug.com/626703 [ Win7 ] external/wpt/pointerevents/pointerevent_fractional_coordinates-manual.html [ Skip ] # These tests require a preferred dark color-scheme and are only run as virtual tests
diff --git a/third_party/blink/web_tests/editing/selection/caret-ltr-2-left.html b/third_party/blink/web_tests/editing/selection/caret-ltr-2-left.html deleted file mode 100644 index a308ee2..0000000 --- a/third_party/blink/web_tests/editing/selection/caret-ltr-2-left.html +++ /dev/null
@@ -1,24 +0,0 @@ -<!DOCTYPE html> -<html> -<body> -<p> -This tests that clicking in a contenteditable div will set the caret in the right position for LTR text in a RTL block. -To test manually, click the left of the text. The caret should be on the left edge. -</p> -<div style="direction: rtl; font-size: 20px; width: 20ex; border: solid thin black; padding: 10px;" contenteditable>WebKit2</div> -<script src="resources/caret-edge-shared.js"></script> -<script> - -var clickOn = 'left'; -var expectedOffset = 7; -if (window.internals && internals.runtimeFlags.bidiCaretAffinityEnabled) { - // When bidi caret affinity is enabled, carets are shown at different visual - // locations. Use the changed test expectations in this case. - expectedOffset = 0; -} - -runTest(); - -</script> -</body> -</html>
diff --git a/third_party/blink/web_tests/editing/selection/caret-ltr-2.html b/third_party/blink/web_tests/editing/selection/caret-ltr-2.html index 13e52e9a..06c8716 100644 --- a/third_party/blink/web_tests/editing/selection/caret-ltr-2.html +++ b/third_party/blink/web_tests/editing/selection/caret-ltr-2.html
@@ -1,24 +1,52 @@ -<!DOCTYPE html> -<html> -<body> -<p> -This tests that clicking in a contenteditable div will set the caret in the right position for LTR text in a RTL block. -To test manually, click the right of the text. The caret should be on the right edge. -</p> -<div style="direction: rtl; font-size: 20px; width: 20ex; border: solid thin black; padding: 10px;" contenteditable>WebKit2</div> -<script src="resources/caret-edge-shared.js"></script> +<!doctype html> +<script src="../../resources/testharness.js"></script> +<script src="../../resources/testharnessreport.js"></script> +<script src="../assert_selection.js"></script> <script> +const bidiCaretAffinityEnabled = + window.internals && internals.runtimeFlags.bidiCaretAffinityEnabled; -var clickOn = 'right'; -var expectedOffset = 0; -if (window.internals && internals.runtimeFlags.bidiCaretAffinityEnabled) { - // When bidi caret affinity is enabled, carets are shown at different visual - // locations. Use the changed test expectations in this case. - expectedOffset = 7; -} +selection_test( + [ + '<div contenteditable id="target" style="direction: rtl">', + 'abc', + '</div>', + ], + selection => { + if (!window.eventSender) + throw 'This test requires eventSender.'; + const target = selection.document.getElementById('target'); + eventSender.mouseMoveTo( + selection.computeLeft(target) + 3, + selection.computeLeft(target) + 3); + eventSender.mouseDown(); + eventSender.mouseUp(); + }, + [ + '<div contenteditable id="target" style="direction: rtl">', + bidiCaretAffinityEnabled ? '|abc' : 'abc|', + '</div>', + ], 'Click left'); -runTest(); - +selection_test( + [ + '<div contenteditable id="target" style="direction: rtl">', + 'abc', + '</div>', + ], + selection => { + if (!window.eventSender) + throw 'This test requires eventSender.'; + const target = selection.document.getElementById('target'); + eventSender.mouseMoveTo( + selection.computeLeft(target) + target.offsetWidth - 3, + selection.computeLeft(target) + 3); + eventSender.mouseDown(); + eventSender.mouseUp(); + }, + [ + '<div contenteditable id="target" style="direction: rtl">', + bidiCaretAffinityEnabled ? 'abc|' : '|abc', + '</div>', + ], 'Click right'); </script> -</body> -</html>
diff --git a/third_party/blink/web_tests/editing/selection/caret-rtl-2-left.html b/third_party/blink/web_tests/editing/selection/caret-rtl-2-left.html deleted file mode 100644 index b140353..0000000 --- a/third_party/blink/web_tests/editing/selection/caret-rtl-2-left.html +++ /dev/null
@@ -1,24 +0,0 @@ -<!DOCTYPE html> -<html> -<body> -<p> -This tests that clicking in a contenteditable div will set the caret in the right position for RTL text in a LTR block. -To test manually, click the left of the text. The caret should be on the left edge. -</p> -<div style="font-size: 20px; width: 20ex; border: solid thin black; padding: 10px;" contenteditable>שדה בור</div> -<script src="resources/caret-edge-shared.js"></script> -<script> - -var clickOn = 'left'; -var expectedOffset = 0; -if (window.internals && internals.runtimeFlags.bidiCaretAffinityEnabled) { - // When bidi caret affinity is enabled, carets are shown at different visual - // locations. Use the changed test expectations in this case. - expectedOffset = 7; -} - -runTest(); - -</script> -</body> -</html>
diff --git a/third_party/blink/web_tests/editing/selection/caret-rtl-2.html b/third_party/blink/web_tests/editing/selection/caret-rtl-2.html index ebd2a2e..fe64760 100644 --- a/third_party/blink/web_tests/editing/selection/caret-rtl-2.html +++ b/third_party/blink/web_tests/editing/selection/caret-rtl-2.html
@@ -1,24 +1,55 @@ -<!DOCTYPE html> -<html> -<body> -<p> -This tests that clicking in a contenteditable div will set the caret in the right position for RTL text in a RTL block. -To test manually, click the right of the text. The caret should be on the right edge. -</p> -<div style="font-size: 20px; width: 20ex; border: solid thin black; padding: 10px;" contenteditable>שדה בור</div> -<script src="resources/caret-edge-shared.js"></script> +<!doctype html> +<script src="../../resources/testharness.js"></script> +<script src="../../resources/testharnessreport.js"></script> +<script src="../assert_selection.js"></script> <script> +const bidiCaretAffinityEnabled = + window.internals && internals.runtimeFlags.bidiCaretAffinityEnabled; -var clickOn = 'right'; -var expectedOffset = 7; -if (window.internals && internals.runtimeFlags.bidiCaretAffinityEnabled) { - // When bidi caret affinity is enabled, carets are shown at different visual - // locations. Use the changed test expectations in this case. - expectedOffset = 0; -} - -runTest(); - +selection_test( + [ + '<div contenteditable id="target">', + '\u05e9;\u05d3;\u05d4; \u05d1;\u05d5;\u05e8;', + '</div>', + ], + selection => { + if (!window.eventSender) + throw 'This test requires eventSender.'; + const target = selection.document.getElementById('target'); + eventSender.mouseMoveTo( + selection.computeLeft(target) + 3, + selection.computeLeft(target) + 3); + eventSender.mouseDown(); + eventSender.mouseUp(); + }, + [ + '<div contenteditable id="target">', + bidiCaretAffinityEnabled + ? '\u05e9;\u05d3;\u05d4; \u05d1;\u05d5;\u05e8;|' + : '|\u05e9;\u05d3;\u05d4; \u05d1;\u05d5;\u05e8;', + '</div>', + ], 'Click left'); +selection_test( + [ + '<div contenteditable id="target">', + '\u05e9;\u05d3;\u05d4; \u05d1;\u05d5;\u05e8;', + '</div>', + ], + selection => { + if (!window.eventSender) + throw 'This test requires eventSender.'; + const target = selection.document.getElementById('target'); + eventSender.mouseMoveTo( + selection.computeLeft(target) + target.offsetWidth - 3, + selection.computeLeft(target) + 3); + eventSender.mouseDown(); + eventSender.mouseUp(); + }, + [ + '<div contenteditable id="target">', + bidiCaretAffinityEnabled + ? '|\u05e9;\u05d3;\u05d4; \u05d1;\u05d5;\u05e8;' + : '\u05e9;\u05d3;\u05d4; \u05d1;\u05d5;\u05e8;|', + '</div>', + ], 'Click right'); </script> -</body> -</html>
diff --git a/third_party/blink/web_tests/editing/selection/caret-rtl-right.html b/third_party/blink/web_tests/editing/selection/caret-rtl-right.html deleted file mode 100644 index 49165f2..0000000 --- a/third_party/blink/web_tests/editing/selection/caret-rtl-right.html +++ /dev/null
@@ -1,19 +0,0 @@ -<!DOCTYPE html> -<html> -<body> -<p> -This tests that clicking in a contenteditable div will set the caret in the right position for RTL text in a RTL block. -To test manually, click the right of the text. The caret should be on the right edge. -</p> -<div style="direction: rtl; font-size: 20px; width: 20ex; border: solid thin black; padding: 10px;" contenteditable>שדה בור</div> -<script src="resources/caret-edge-shared.js"></script> -<script> - -var clickOn = 'right'; -var expectedOffset = 0; - -runTest(); - -</script> -</body> -</html>
diff --git a/third_party/blink/web_tests/editing/selection/caret-rtl.html b/third_party/blink/web_tests/editing/selection/caret-rtl.html index 5424545..e807b2d 100644 --- a/third_party/blink/web_tests/editing/selection/caret-rtl.html +++ b/third_party/blink/web_tests/editing/selection/caret-rtl.html
@@ -1,19 +1,50 @@ -<!DOCTYPE html> -<html> -<body> -<p> -This tests that clicking in a contenteditable div will set the caret in the right position for RTL text in a RTL block. -To test manually, click the left of the text. The caret should be on the left edge. -</p> -<div style="direction: rtl; font-size: 20px; width: 20ex; border: solid thin black; padding: 10px;" contenteditable>שדה בור</div> -<script src="resources/caret-edge-shared.js"></script> +<!doctype html> +<script src="../../resources/testharness.js"></script> +<script src="../../resources/testharnessreport.js"></script> +<script src="../assert_selection.js"></script> <script> - -var clickOn = 'left'; -var expectedOffset = 7; - -runTest(); - +selection_test( + [ + '<div contenteditable dir="rtl" id="target">', + '\u05e9;\u05d3;\u05d4; \u05d1;\u05d5;\u05e8;', + '</div>', + ], + selection => { + if (!window.eventSender) + throw 'This test requires eventSender.'; + const target = selection.document.getElementById('target'); + eventSender.mouseMoveTo( + selection.computeLeft(target) + 3, + selection.computeLeft(target) + 3); + eventSender.mouseDown(); + eventSender.mouseUp(); + }, + [ + '<div contenteditable dir="rtl" id="target">', + '\u05e9;\u05d3;\u05d4; \u05d1;\u05d5;\u05e8;|', + '</div>', + ], + 'Click left'); +selection_test( + [ + '<div contenteditable dir="rtl" id="target">', + '\u05e9;\u05d3;\u05d4; \u05d1;\u05d5;\u05e8;', + '</div>', + ], + selection => { + if (!window.eventSender) + throw 'This test requires eventSender.'; + const target = selection.document.getElementById('target'); + eventSender.mouseMoveTo( + selection.computeLeft(target) + target.offsetWidth - 3, + selection.computeLeft(target) + 3); + eventSender.mouseDown(); + eventSender.mouseUp(); + }, + [ + '<div contenteditable dir="rtl" id="target">', + '|\u05e9;\u05d3;\u05d4; \u05d1;\u05d5;\u05e8;', + '</div>', + ], + 'Click right'); </script> -</body> -</html>
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 6acb1a1..6a5b80cc0 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
@@ -78626,7 +78626,7 @@ ] ], "ruby-reflow-001-opaqueruby.html": [ - "fe4a80423839f6167fa0e42315b6b814cc839b92", + "77feb2e6b8dcdd514114dbec9867529e3bda0323", [ null, [ @@ -78639,7 +78639,7 @@ ] ], "ruby-reflow-001-transparentruby.html": [ - "3e7112c4d61397e74cd1d75519292f3ecca5e9ee", + "008c5250bc364d4a9e15643ce38dc4d18eb7a145", [ null, [ @@ -78665,7 +78665,7 @@ ] ], "ruby-whitespace-001.html": [ - "9df61585700777911c19e8336beed37827ce78d4", + "9072a8e6841925a5023730ad48b5a2f074b1d0dd", [ null, [ @@ -78678,7 +78678,7 @@ ] ], "ruby-whitespace-002.html": [ - "bc84919a123c0554d9a6f80bea7d78341eb6cafe", + "98ed78913375ad36d2422ca231cb880a07032741", [ null, [ @@ -152835,10 +152835,6 @@ "b7affbe7d41dd9e7bf555aa151cf6d31fb2279a9", [] ], - "post-redirect-stacktrace.https-expected.txt": [ - "2eda089f8375b53dcb928bb0ebf8ff46ba270868", - [] - ], "post-redirect-stacktrace.https.html.headers": [ "644ed867f3303048120bc72e4ca5a5ede3fa6d3b", [] @@ -153526,6 +153522,14 @@ "b8a1d0a6098492b615dfae8a1e5e44ade8a2f3db", [] ], + "idlharness.tentative.https.any.sharedworker-expected.txt": [ + "ad18929256152fa1478c17ef8acb9acfbdaf8096", + [] + ], + "idlharness.tentative.https.any.worker-expected.txt": [ + "ad18929256152fa1478c17ef8acb9acfbdaf8096", + [] + ], "resources": { "always_changing_sw.sub.js": [ "9fdf99848fa50316e275cd6636a5755270a9bb1e", @@ -175578,11 +175582,11 @@ [] ], "ruby-whitespace-001-ref.html": [ - "d24e207f8676d010cdfef2ddac1412833944faaf", + "04fa59e6ba038e03a13c8101fcbb6ea39561eed8", [] ], "ruby-whitespace-002-ref.html": [ - "8aade20051630ee89d258916b1029a71d91ce0fb", + "2b22891738cb1a776e411857b33a7a993c120363", [] ], "support": { @@ -198792,7 +198796,11 @@ [] ], "cache-storage-reporting-dedicated-worker.https-expected.txt": [ - "020757c74f1d8efd65818362c5529f4f0377b6b9", + "f305a39c1e214f9e9c968998b50c327b288c0fec", + [] + ], + "cache-storage-reporting-shared-worker.https-expected.txt": [ + "643200226b30cbe10b5b55f74162c1e7129a52bf", [] ], "data.https.html.headers": [ @@ -198831,6 +198839,10 @@ "289659a41fdf41178781c764643f8946f4ec09b7", [] ], + "reporting-subresource-corp.https-expected.txt": [ + "62ff46ed2ac3185f83e4a9dd6ba1c3d3206a2511", + [] + ], "reporting.https-expected.txt": [ "59458db4e4866cab0622b22614c82421bc71a1c7", [] @@ -198869,7 +198881,7 @@ [] ], "cache-storage-reporting.js": [ - "af36ccf9d3df852f75af46339e7df6bff23a5402", + "86dff9c8459003b7ceeb664ebbac920518505db3", [] ], "coep-frame.html": [ @@ -198940,6 +198952,10 @@ "b7c8b304178b4f4aa213703d6870e84267acba6c", [] ], + "reporting-worker.js": [ + "0f8a2ce4c87da7c0721b3a3d18af0d231fbacda2", + [] + ], "require-corp-sw-import-scripts.js": [ "e652c5bf303074d7c396f53146bb8af6c3f35644", [] @@ -205567,6 +205583,10 @@ "4f7c4f2cb3497108feba281dc2bf5f276c8372fd", [] ], + "image-loading-lazy-referrerpolicy-change.sub-expected.txt": [ + "aa09bf93e1326d379228a5334b59fe1b7f06d35c", + [] + ], "image-loading-lazy-slow-aspect-ratio-ref.html": [ "6de01a9b3bbf19567555af2524f8950abdfb2d81", [] @@ -208480,10 +208500,6 @@ "navigatorcookies-cookieenabled-false-manual-expected.txt": [ "a95972302bfe24a2e207a7085bde0d103426de8f", [] - ], - "protocol.https-expected.txt": [ - "de0d8507d99a8e73d7eacd090e7c2633c99c2207", - [] ] } }, @@ -210268,7 +210284,7 @@ ] }, "lint.ignore": [ - "acdeddbff3935e919bc582bdbdb1af1d6693f26d", + "49f88ddc7b339434e071522958fcc2a6aec5d237", [] ], "loading": { @@ -220850,7 +220866,7 @@ ], "tasks": { "test.yml": [ - "6e22cc57081ad222c5fd6df7f3783da8ed44d72d", + "318437a80ec3240721a17cc6253f241109038b64", [] ] }, @@ -226257,8 +226273,12 @@ "bf829d93e968d4a6bccfa6798fb974bf98ff7d60", [] ], + "actions.py": [ + "fc43dd665a2f3bc5576cb535f29d49abbc9593fd", + [] + ], "base.py": [ - "ab36c95c11339951c9c5ccd5da4c19551ba8f8de", + "5d6c283737e6a768279f69503094345c0f942880", [] ], "executorchrome.py": [ @@ -277248,7 +277268,7 @@ ] ], "outline-width-interpolation.html": [ - "c024c7cf6a08e0f6e02ccb451ca04d0b4a8c9251", + "a46907a169074b9af0ac85d7f39ebc0e568f8c64", [ null, {} @@ -277523,7 +277543,7 @@ ] ], "outline-width-computed.html": [ - "33eb9c9b99cba713d282010e4ddd5293b7b00aac", + "abd5826bbb387ec6dcbebfcd9e2870df8aea6ab9", [ null, {} @@ -323997,7 +324017,7 @@ ] ], "cache-storage-reporting-dedicated-worker.https.html": [ - "c9c2a9ac715658dc8c7a1d5f66bf0e8d93912aa4", + "d88bf56ec2cb16dc3ab03035a0bdf15f10f54c04", [ null, { @@ -324006,7 +324026,7 @@ ] ], "cache-storage-reporting-document.https.html": [ - "d5ae757facfc5742a1bbb134dbd67bd6fbdeb4df", + "efb7e7a779587de7f5c142383d36470a54908f5c", [ null, { @@ -324015,16 +324035,14 @@ ] ], "cache-storage-reporting-service-worker.https.html": [ - "6b5b78bba088671d4d6eb5b7833bf1c873963eee", + "b9ec8d95a59ade8a8120a0af04248d3c930c1dac", [ null, - { - "timeout": "long" - } + {} ] ], "cache-storage-reporting-shared-worker.https.html": [ - "0b13de8657f93aeba0980831f98e378b753f4c83", + "d7bd191a84e9c2e5b766ea258ac615791471fb95", [ null, { @@ -324134,6 +324152,15 @@ } ] ], + "reporting-subresource-corp.https.html": [ + "aa76bbe8d21d259ed0b9dcadb1d942635134ac79", + [ + null, + { + "timeout": "long" + } + ] + ], "reporting.https.html": [ "42d5e6cc33537e988daf77d740fdcdeab64508c5", [ @@ -330909,6 +330936,13 @@ {} ] ], + "iframe-loading-lazy-referrerpolicy-change.sub.tentative.html": [ + "145df404003cdb3ee1c0688351a5300603780789", + [ + null, + {} + ] + ], "iframe-nosrc.html": [ "57189a0b884d3a55e4bb2ba1a1d3aa83066c0eb3", [ @@ -331565,7 +331599,7 @@ ] ], "image-loading-lazy-crossorigin-change.sub.html": [ - "13560324854dceeca26bda3433301cafe07fb62a", + "3fb827df2d6159de73c9fe0417cf790d0d484ff6", [ null, {} @@ -331634,6 +331668,13 @@ {} ] ], + "image-loading-lazy-referrerpolicy-change.sub.html": [ + "307d9571b498e108f121b97f02dc56412cd6f21e", + [ + null, + {} + ] + ], "image-loading-lazy-srcset.html": [ "21c11c7233c7b8f845a31b6aa25dda14ca381960", [ @@ -331753,13 +331794,6 @@ {} ] ], - "original-referrer-policy-applied.sub.html": [ - "c300119f72fbd3742d6dbf7e2439d967911303a5", - [ - null, - {} - ] - ], "picture-loading-lazy.html": [ "0ab2fb27367309814094071ccad7fa2922aa80f9", [ @@ -336061,7 +336095,7 @@ ] ], "referrer-origin-when-cross-origin.sub.html": [ - "4cd427ee88766f7f836ef86a3617244864ac5e40", + "fd4c1ea49649cf348d99ab0d881aa8f966be416e", [ null, {} @@ -364511,6 +364545,13 @@ {} ] ], + "finish-animation.html": [ + "87bcc41a6a222d883ebe2b249ae103b05275019d", + [ + null, + {} + ] + ], "idlharness.window.js": [ "90157580ce00716403346f369b1e25bba8db23c2", [ @@ -406753,7 +406794,7 @@ ] ], "ruby-reflow-001-noruby.html": [ - "4c00573422b3954853965a3d86ad1464a53a244f", + "eda07deddb2d5ec93f45675854998f2b27d5a683", [ null, {}
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/coop-sandbox.https.html b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/coop-sandbox.https.html index 5fd1164..6f10945c 100644 --- a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/coop-sandbox.https.html +++ b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/coop-sandbox.https.html
@@ -26,4 +26,20 @@ })); }, `<iframe sandbox="${sandboxValue}"> ${document.title}`); }); + +async_test(t => { + const frame = document.createElement("iframe"); + const channel = new BroadcastChannel(token()); + frame.sandbox = "allow-scripts allow-same-origin"; + frame.name = `iframe-${channel.name}`; + frame.src = `resources/coop-coep.py?coop=same-origin&coep=&channel=${channel.name}`; + channel.onmessage = t.step_func( event => { + const payload = event.data; + assert_equals(payload.name, frame.name, "name"); + t.done(); + }); + t.step_timeout(t.unreached_func("Timed out while waiting for iframe's message"), 1500); + t.add_cleanup(() => frame.remove()); + document.body.append(frame); +}, `Iframe with sandbox and COOP must load.`); </script>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/referrer-origin-when-cross-origin.sub.html b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/referrer-origin-when-cross-origin.sub.html index 4cd427e..fd4c1ea4 100644 --- a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/referrer-origin-when-cross-origin.sub.html +++ b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/module/referrer-origin-when-cross-origin.sub.html
@@ -24,7 +24,7 @@ import { referrer as referrerRemoteSame } from "http://{{domains[www1]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/module/resources/import-same-origin-referrer-checker-from-remote-origin.sub.js?name=remote_same"; const origin = (new URL(location.href)).origin + "/"; -const remoteOrigin = "http://{{domains[www1]}}:{{ports[http][0]}}/"; +const remoteOrigin = new URL("http://{{domains[www1]}}:{{ports[http][0]}}/").origin + "/"; test(t => { assert_equals(
diff --git a/third_party/blink/web_tests/external/wpt/tools/ci/tc/tasks/test.yml b/third_party/blink/web_tests/external/wpt/tools/ci/tc/tasks/test.yml index 6e22cc5..318437a 100644 --- a/third_party/blink/web_tests/external/wpt/tools/ci/tc/tasks/test.yml +++ b/third_party/blink/web_tests/external/wpt/tools/ci/tc/tasks/test.yml
@@ -230,6 +230,7 @@ -- --channel=${vars.channel} --verify + --verify-no-chaos-mode - wpt-${vars.browser}-${vars.channel}-results: use:
diff --git a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/executors/actions.py b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/executors/actions.py new file mode 100644 index 0000000..fc43dd6 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/executors/actions.py
@@ -0,0 +1,184 @@ + +class ClickAction(object): + name = "click" + + def __init__(self, logger, protocol): + self.logger = logger + self.protocol = protocol + + def __call__(self, payload): + selector = payload["selector"] + element = self.protocol.select.element_by_selector(selector) + self.logger.debug("Clicking element: %s" % selector) + self.protocol.click.element(element) + + +class SendKeysAction(object): + name = "send_keys" + + def __init__(self, logger, protocol): + self.logger = logger + self.protocol = protocol + + def __call__(self, payload): + selector = payload["selector"] + keys = payload["keys"] + element = self.protocol.select.element_by_selector(selector) + self.logger.debug("Sending keys to element: %s" % selector) + self.protocol.send_keys.send_keys(element, keys) + + +class ActionSequenceAction(object): + name = "action_sequence" + + def __init__(self, logger, protocol): + self.logger = logger + self.protocol = protocol + + def __call__(self, payload): + # TODO: some sort of shallow error checking + actions = payload["actions"] + for actionSequence in actions: + if actionSequence["type"] == "pointer": + for action in actionSequence["actions"]: + if (action["type"] == "pointerMove" and + isinstance(action["origin"], dict)): + action["origin"] = self.get_element(action["origin"]["selector"], action["frame"]["frame"]) + self.protocol.action_sequence.send_actions({"actions": actions}) + + def get_element(self, element_selector, frame): + element = self.protocol.select.element_by_selector(element_selector, frame) + return element + +class GenerateTestReportAction(object): + name = "generate_test_report" + + def __init__(self, logger, protocol): + self.logger = logger + self.protocol = protocol + + def __call__(self, payload): + message = payload["message"] + self.logger.debug("Generating test report: %s" % message) + self.protocol.generate_test_report.generate_test_report(message) + +class SetPermissionAction(object): + name = "set_permission" + + def __init__(self, logger, protocol): + self.logger = logger + self.protocol = protocol + + def __call__(self, payload): + permission_params = payload["permission_params"] + descriptor = permission_params["descriptor"] + name = descriptor["name"] + state = permission_params["state"] + one_realm = permission_params.get("oneRealm", False) + self.logger.debug("Setting permission %s to %s, oneRealm=%s" % (name, state, one_realm)) + self.protocol.set_permission.set_permission(descriptor, state, one_realm) + +class AddVirtualAuthenticatorAction(object): + name = "add_virtual_authenticator" + + def __init__(self, logger, protocol): + self.logger = logger + self.protocol = protocol + + def __call__(self, payload): + self.logger.debug("Adding virtual authenticator") + config = payload["config"] + authenticator_id = self.protocol.virtual_authenticator.add_virtual_authenticator(config) + self.logger.debug("Authenticator created with ID %s" % authenticator_id) + return authenticator_id + +class RemoveVirtualAuthenticatorAction(object): + name = "remove_virtual_authenticator" + + def __init__(self, logger, protocol): + self.logger = logger + self.protocol = protocol + + def __call__(self, payload): + authenticator_id = payload["authenticator_id"] + self.logger.debug("Removing virtual authenticator %s" % authenticator_id) + return self.protocol.virtual_authenticator.remove_virtual_authenticator(authenticator_id) + + +class AddCredentialAction(object): + name = "add_credential" + + def __init__(self, logger, protocol): + self.logger = logger + self.protocol = protocol + + def __call__(self, payload): + authenticator_id = payload["authenticator_id"] + credential = payload["credential"] + self.logger.debug("Adding credential to virtual authenticator %s " % authenticator_id) + return self.protocol.virtual_authenticator.add_credential(authenticator_id, credential) + +class GetCredentialsAction(object): + name = "get_credentials" + + def __init__(self, logger, protocol): + self.logger = logger + self.protocol = protocol + + def __call__(self, payload): + authenticator_id = payload["authenticator_id"] + self.logger.debug("Getting credentials from virtual authenticator %s " % authenticator_id) + return self.protocol.virtual_authenticator.get_credentials(authenticator_id) + +class RemoveCredentialAction(object): + name = "remove_credential" + + def __init__(self, logger, protocol): + self.logger = logger + self.protocol = protocol + + def __call__(self, payload): + authenticator_id = payload["authenticator_id"] + credential_id = payload["credential_id"] + self.logger.debug("Removing credential %s from authenticator %s" % (credential_id, authenticator_id)) + return self.protocol.virtual_authenticator.remove_credential(authenticator_id, credential_id) + +class RemoveAllCredentialsAction(object): + name = "remove_all_credentials" + + def __init__(self, logger, protocol): + self.logger = logger + self.protocol = protocol + + def __call__(self, payload): + authenticator_id = payload["authenticator_id"] + self.logger.debug("Removing all credentials from authenticator %s" % authenticator_id) + return self.protocol.virtual_authenticator.remove_all_credentials(authenticator_id) + +class SetUserVerifiedAction(object): + name = "set_user_verified" + + def __init__(self, logger, protocol): + self.logger = logger + self.protocol = protocol + + def __call__(self, payload): + authenticator_id = payload["authenticator_id"] + uv = payload["uv"] + self.logger.debug( + "Setting user verified flag on authenticator %s to %s" % (authenticator_id, uv["isUserVerified"])) + return self.protocol.virtual_authenticator.set_user_verified(authenticator_id, uv) + + +actions = [ClickAction, + SendKeysAction, + ActionSequenceAction, + GenerateTestReportAction, + SetPermissionAction, + AddVirtualAuthenticatorAction, + RemoveVirtualAuthenticatorAction, + AddCredentialAction, + GetCredentialsAction, + RemoveCredentialAction, + RemoveAllCredentialsAction, + SetUserVerifiedAction]
diff --git a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/executors/base.py b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/executors/base.py index ab36c95..5d6c2837 100644 --- a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/executors/base.py +++ b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/executors/base.py
@@ -13,6 +13,7 @@ from six.moves.urllib.parse import urljoin, urlsplit, urlunsplit from ..testrunner import Stop +from .actions import actions from .protocol import Protocol, BaseProtocolPart here = os.path.split(__file__)[0] @@ -681,20 +682,7 @@ "complete": self.process_complete } - self.actions = { - "click": ClickAction(self.logger, self.protocol), - "send_keys": SendKeysAction(self.logger, self.protocol), - "action_sequence": ActionSequenceAction(self.logger, self.protocol), - "generate_test_report": GenerateTestReportAction(self.logger, self.protocol), - "set_permission": SetPermissionAction(self.logger, self.protocol), - "add_virtual_authenticator": AddVirtualAuthenticatorAction(self.logger, self.protocol), - "remove_virtual_authenticator": RemoveVirtualAuthenticatorAction(self.logger, self.protocol), - "add_credential": AddCredentialAction(self.logger, self.protocol), - "get_credentials": GetCredentialsAction(self.logger, self.protocol), - "remove_credential": RemoveCredentialAction(self.logger, self.protocol), - "remove_all_credentials": RemoveAllCredentialsAction(self.logger, self.protocol), - "set_user_verified": SetUserVerifiedAction(self.logger, self.protocol), - } + self.actions = {cls.name: cls(self.logger, self.protocol) for cls in actions} def __call__(self, result): url, command, payload = result @@ -735,150 +723,3 @@ def _send_message(self, message_type, status, message=None): self.protocol.testdriver.send_message(message_type, status, message=message) - - -class ClickAction(object): - def __init__(self, logger, protocol): - self.logger = logger - self.protocol = protocol - - def __call__(self, payload): - selector = payload["selector"] - element = self.protocol.select.element_by_selector(selector) - self.logger.debug("Clicking element: %s" % selector) - self.protocol.click.element(element) - - -class SendKeysAction(object): - def __init__(self, logger, protocol): - self.logger = logger - self.protocol = protocol - - def __call__(self, payload): - selector = payload["selector"] - keys = payload["keys"] - element = self.protocol.select.element_by_selector(selector) - self.logger.debug("Sending keys to element: %s" % selector) - self.protocol.send_keys.send_keys(element, keys) - - -class ActionSequenceAction(object): - def __init__(self, logger, protocol): - self.logger = logger - self.protocol = protocol - - def __call__(self, payload): - # TODO: some sort of shallow error checking - actions = payload["actions"] - for actionSequence in actions: - if actionSequence["type"] == "pointer": - for action in actionSequence["actions"]: - if (action["type"] == "pointerMove" and - isinstance(action["origin"], dict)): - action["origin"] = self.get_element(action["origin"]["selector"], action["frame"]["frame"]) - self.protocol.action_sequence.send_actions({"actions": actions}) - - def get_element(self, element_selector, frame): - element = self.protocol.select.element_by_selector(element_selector, frame) - return element - -class GenerateTestReportAction(object): - def __init__(self, logger, protocol): - self.logger = logger - self.protocol = protocol - - def __call__(self, payload): - message = payload["message"] - self.logger.debug("Generating test report: %s" % message) - self.protocol.generate_test_report.generate_test_report(message) - -class SetPermissionAction(object): - def __init__(self, logger, protocol): - self.logger = logger - self.protocol = protocol - - def __call__(self, payload): - permission_params = payload["permission_params"] - descriptor = permission_params["descriptor"] - name = descriptor["name"] - state = permission_params["state"] - one_realm = permission_params.get("oneRealm", False) - self.logger.debug("Setting permission %s to %s, oneRealm=%s" % (name, state, one_realm)) - self.protocol.set_permission.set_permission(descriptor, state, one_realm) - -class AddVirtualAuthenticatorAction(object): - def __init__(self, logger, protocol): - self.logger = logger - self.protocol = protocol - - def __call__(self, payload): - self.logger.debug("Adding virtual authenticator") - config = payload["config"] - authenticator_id = self.protocol.virtual_authenticator.add_virtual_authenticator(config) - self.logger.debug("Authenticator created with ID %s" % authenticator_id) - return authenticator_id - -class RemoveVirtualAuthenticatorAction(object): - def __init__(self, logger, protocol): - self.logger = logger - self.protocol = protocol - - def __call__(self, payload): - authenticator_id = payload["authenticator_id"] - self.logger.debug("Removing virtual authenticator %s" % authenticator_id) - return self.protocol.virtual_authenticator.remove_virtual_authenticator(authenticator_id) - - -class AddCredentialAction(object): - def __init__(self, logger, protocol): - self.logger = logger - self.protocol = protocol - - def __call__(self, payload): - authenticator_id = payload["authenticator_id"] - credential = payload["credential"] - self.logger.debug("Adding credential to virtual authenticator %s " % authenticator_id) - return self.protocol.virtual_authenticator.add_credential(authenticator_id, credential) - -class GetCredentialsAction(object): - def __init__(self, logger, protocol): - self.logger = logger - self.protocol = protocol - - def __call__(self, payload): - authenticator_id = payload["authenticator_id"] - self.logger.debug("Getting credentials from virtual authenticator %s " % authenticator_id) - return self.protocol.virtual_authenticator.get_credentials(authenticator_id) - -class RemoveCredentialAction(object): - def __init__(self, logger, protocol): - self.logger = logger - self.protocol = protocol - - def __call__(self, payload): - authenticator_id = payload["authenticator_id"] - credential_id = payload["credential_id"] - self.logger.debug("Removing credential %s from authenticator %s" % (credential_id, authenticator_id)) - return self.protocol.virtual_authenticator.remove_credential(authenticator_id, credential_id) - -class RemoveAllCredentialsAction(object): - def __init__(self, logger, protocol): - self.logger = logger - self.protocol = protocol - - def __call__(self, payload): - authenticator_id = payload["authenticator_id"] - self.logger.debug("Removing all credentials from authenticator %s" % authenticator_id) - return self.protocol.virtual_authenticator.remove_all_credentials(authenticator_id) - -class SetUserVerifiedAction(object): - def __init__(self, logger, protocol): - self.logger = logger - self.protocol = protocol - - def __call__(self, payload): - authenticator_id = payload["authenticator_id"] - uv = payload["uv"] - self.logger.debug( - "Setting user verified flag on authenticator %s to %s" % (authenticator_id, uv["isUserVerified"])) - return self.protocol.virtual_authenticator.set_user_verified(authenticator_id, uv)
diff --git a/third_party/blink/web_tests/http/tests/devtools/sources/debugger-ui/function-generator-details-expected.txt b/third_party/blink/web_tests/http/tests/devtools/sources/debugger-ui/function-generator-details-expected.txt index 5c8f1d4..899313af 100644 --- a/third_party/blink/web_tests/http/tests/devtools/sources/debugger-ui/function-generator-details-expected.txt +++ b/third_party/blink/web_tests/http/tests/devtools/sources/debugger-ui/function-generator-details-expected.txt
@@ -1,7 +1,7 @@ Tests that Debugger.getGeneratorObjectDetails command returns correct result. -Running: testIterNotStarted +Running: testiterNotStarted iterNotStarted: type = object, subtype = generator lineNumber = 17 columnNumber = 19 @@ -16,7 +16,7 @@ [[GeneratorReceiver]] = Window [[Scopes]] = Scopes[2] -Running: testIterSuspended +Running: testiterSuspended iterSuspended: type = object, subtype = generator lineNumber = 19 columnNumber = 10 @@ -31,7 +31,7 @@ [[GeneratorReceiver]] = Window [[Scopes]] = Scopes[2] -Running: testIterClosed +Running: testiterClosed iterClosed: type = object, subtype = generator lineNumber = 17 columnNumber = 19 @@ -45,7 +45,7 @@ } [[GeneratorReceiver]] = Window -Running: testIterObjGenerator +Running: testiterObjGenerator iterObjGenerator: type = object, subtype = generator lineNumber = 28 columnNumber = 14 @@ -60,7 +60,7 @@ [[GeneratorReceiver]] = Object [[Scopes]] = Scopes[2] -Running: testAnonymousGenIter +Running: testanonymousGenIter anonymousGenIter: type = object, subtype = generator lineNumber = 42 columnNumber = 10
diff --git a/third_party/blink/web_tests/http/tests/devtools/sources/debugger-ui/function-generator-details.js b/third_party/blink/web_tests/http/tests/devtools/sources/debugger-ui/function-generator-details.js index 4d40b13b..49aa1e454 100644 --- a/third_party/blink/web_tests/http/tests/devtools/sources/debugger-ui/function-generator-details.js +++ b/third_party/blink/web_tests/http/tests/devtools/sources/debugger-ui/function-generator-details.js
@@ -86,7 +86,7 @@ ]; function createTestSuiteFunction(expression) { - var functionName = 'test' + expression.toTitleCase(); + var functionName = 'test' + expression; return eval( 'function ' + functionName + '(next)\n' + '{\n' +
diff --git a/third_party/blink/web_tests/http/tests/devtools/sources/debugger-ui/show-generator-location-expected.txt b/third_party/blink/web_tests/http/tests/devtools/sources/debugger-ui/show-generator-location-expected.txt index 0a293f9..1be1543 100644 --- a/third_party/blink/web_tests/http/tests/devtools/sources/debugger-ui/show-generator-location-expected.txt +++ b/third_party/blink/web_tests/http/tests/devtools/sources/debugger-ui/show-generator-location-expected.txt
@@ -1,18 +1,18 @@ Tests that "Show Generator Location" jumps to the correct location. -Running: testIterNotStarted +Running: testiterNotStarted Generator location revealed: [17:20] -Running: testIterSuspended1 +Running: testiterSuspended1 Generator location revealed: [19:11] -Running: testIterSuspended2 +Running: testiterSuspended2 Generator location revealed: [20:11] -Running: testIterSuspended3 +Running: testiterSuspended3 Generator location revealed: [21:11] -Running: testIterClosed +Running: testiterClosed Generator location revealed: [17:20]
diff --git a/third_party/blink/web_tests/http/tests/devtools/sources/debugger-ui/show-generator-location.js b/third_party/blink/web_tests/http/tests/devtools/sources/debugger-ui/show-generator-location.js index 771124d2..543b79e 100644 --- a/third_party/blink/web_tests/http/tests/devtools/sources/debugger-ui/show-generator-location.js +++ b/third_party/blink/web_tests/http/tests/devtools/sources/debugger-ui/show-generator-location.js
@@ -66,7 +66,7 @@ ]; function createTestSuiteFunction(expression) { - var functionName = 'test' + expression.toTitleCase(); + var functionName = 'test' + expression; return eval( 'function ' + functionName + '(next)\n' + '{\n' +
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/quic-transport-handshake-failure-expected.txt b/third_party/blink/web_tests/http/tests/inspector-protocol/quic-transport-handshake-failure-expected.txt new file mode 100644 index 0000000..f1ae8e5 --- /dev/null +++ b/third_party/blink/web_tests/http/tests/inspector-protocol/quic-transport-handshake-failure-expected.txt
@@ -0,0 +1,8 @@ +Check the console message printed on a QuicTransport handshake failure. +Log Enabled +Instantiate QuicTransport. +Log.onEntryAdded +source: network +level: error +text: Failed to establish a connection to quic-transport://localhost/. +
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/quic-transport-handshake-failure.js b/third_party/blink/web_tests/http/tests/inspector-protocol/quic-transport-handshake-failure.js new file mode 100644 index 0000000..5047742 --- /dev/null +++ b/third_party/blink/web_tests/http/tests/inspector-protocol/quic-transport-handshake-failure.js
@@ -0,0 +1,20 @@ +(async function(testRunner) { + const {session, dp} = await testRunner.startBlank( + `Check the console message printed on a QuicTransport handshake failure.`); + const url = 'quic-transport://localhost'; + + await dp.Log.enable(); + testRunner.log('Log Enabled'); + + dp.Log.onEntryAdded(event => { + const entry = event.params.entry; + testRunner.log('Log.onEntryAdded'); + testRunner.log(`source: ${entry.source}`); + testRunner.log(`level: ${entry.level}`); + testRunner.log(`text: ${entry.text}`); + testRunner.completeTest(); + }); + + session.evaluate(`new QuicTransport('${url}');`); + testRunner.log('Instantiate QuicTransport.'); +})
diff --git a/third_party/blink/web_tests/http/tests/origin_trials/webexposed/contacts-manager-extra-properties-trial-interfaces.html b/third_party/blink/web_tests/http/tests/origin_trials/webexposed/contacts-manager-extra-properties-trial-interfaces.html deleted file mode 100644 index c3345589..0000000 --- a/third_party/blink/web_tests/http/tests/origin_trials/webexposed/contacts-manager-extra-properties-trial-interfaces.html +++ /dev/null
@@ -1,23 +0,0 @@ -<!DOCTYPE html> -<meta charset="utf-8"> -<!-- Generate token with the command: -generate_token.py http://127.0.0.1:8000 ContactsManagerExtraProperties --expire-timestamp=2000000000 ---> -<meta http-equiv="origin-trial" content="Ag08kQBxaZIHRn4szFwJFlEfUhOPCV2CZtU7mqRMQqxt3kGuuPu9Qom6hRdF+vAQIBcHOrDw0d4ajhMzeUETXQ0AAABmeyJvcmlnaW4iOiAiaHR0cDovLzEyNy4wLjAuMTo4MDAwIiwgImZlYXR1cmUiOiAiQ29udGFjdHNNYW5hZ2VyRXh0cmFQcm9wZXJ0aWVzIiwgImV4cGlyeSI6IDIwMDAwMDAwMDB9" /> -<title>Contacts Manager Extra Properties - exposed by origin trial</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<script src="/resources/origin-trials-helper.js"></script> -<script> - -test(() => { - OriginTrialsHelper.check_properties_exist(this, { 'ContactsManager': ['select', 'getProperties'] }); -}, 'Contact API interfaces and properties in Origin-Trial enabled document.'); - -promise_test(async () => { - const properties = await navigator.contacts.getProperties(); - assert_true(properties.includes('address')); - assert_true(properties.includes('icon')); -}, '`address` and `icon` properties are exposed.'); - -</script>
diff --git a/third_party/blink/web_tests/inspector-protocol/debugger/wasm-streaming-url-expected.txt b/third_party/blink/web_tests/inspector-protocol/debugger/wasm-streaming-url-expected.txt index dcab134..11cedcb 100644 --- a/third_party/blink/web_tests/inspector-protocol/debugger/wasm-streaming-url-expected.txt +++ b/third_party/blink/web_tests/inspector-protocol/debugger/wasm-streaming-url-expected.txt
@@ -1,6 +1,6 @@ Test script URL for wasm streaming compilation. Did enable debugger -Instantiating. -Waiting for wasm script -URL is preserved: true +URL is preserved in the main thread: true +Worker created +URL is preserved in the worker: true
diff --git a/third_party/blink/web_tests/inspector-protocol/debugger/wasm-streaming-url.js b/third_party/blink/web_tests/inspector-protocol/debugger/wasm-streaming-url.js index 544982b..497ac76 100644 --- a/third_party/blink/web_tests/inspector-protocol/debugger/wasm-streaming-url.js +++ b/third_party/blink/web_tests/inspector-protocol/debugger/wasm-streaming-url.js
@@ -2,14 +2,22 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -function instantiate() { +function compileStreamingAndSendToWorker() { + let workerBlob = new Blob([` + onmessage = function(e) { + let instance = new WebAssembly.Instance(e.data.module); + }`], + {type: 'application/javascript'}); + let worker = new Worker(URL.createObjectURL(workerBlob)); + const magicModuleHeader = [0x00, 0x61, 0x73, 0x6d], moduleVersion = [0x01, 0x00, 0x00, 0x00]; const wasm = Uint8Array.from([...magicModuleHeader, ...moduleVersion]); let b = new Blob([wasm.buffer], {type: 'application/wasm'}); let bURL = URL.createObjectURL(b); + fetch(bURL) - .then(WebAssembly.instantiateStreaming) - .catch(console.error); + .then(WebAssembly.compileStreaming) + .then(module => worker.postMessage(module)) return bURL.toString(); } @@ -19,13 +27,23 @@ await dp.Debugger.enable(); testRunner.log('Did enable debugger'); + let url = await session.evaluate('(' + compileStreamingAndSendToWorker + ')()'); - testRunner.log('Instantiating.'); - var response = await dp.Runtime - .evaluate({expression: '(' + instantiate + ')()'}); - testRunner.log('Waiting for wasm script'); - const {params: wasm_script} = await dp.Debugger.onceScriptParsed(); + // Wait for script creation in the main thread. + let {params: main_script} = await dp.Debugger.onceScriptParsed(); + testRunner.log('URL is preserved in the main thread: ' + (main_script.url == url)); - testRunner.log('URL is preserved: ' + (wasm_script.url == response.result.result.value)); + // Wait for worker. + const attachedPromise = dp.Target.onceAttachedToTarget(); + await dp.Target.setAutoAttach({autoAttach: true, waitForDebuggerOnStart: false, + flatten: true}); + const event = await attachedPromise; + const childSession = session.createChild(event.params.sessionId); + testRunner.log('Worker created'); + + // Wait for script creation in the worker. + await childSession.protocol.Debugger.enable({}); + let {params: worker_script} = await childSession.protocol.Debugger.onceScriptParsed(); + testRunner.log('URL is preserved in the worker: ' + (worker_script.url == url)); testRunner.completeTest(); })
diff --git a/third_party/blink/web_tests/platform/linux/editing/selection/caret-ltr-2-expected.png b/third_party/blink/web_tests/platform/linux/editing/selection/caret-ltr-2-expected.png deleted file mode 100644 index 14bcc3c..0000000 --- a/third_party/blink/web_tests/platform/linux/editing/selection/caret-ltr-2-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/editing/selection/caret-ltr-2-left-expected.png b/third_party/blink/web_tests/platform/linux/editing/selection/caret-ltr-2-left-expected.png deleted file mode 100644 index 9fc79ef3..0000000 --- a/third_party/blink/web_tests/platform/linux/editing/selection/caret-ltr-2-left-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/editing/selection/caret-rtl-2-expected.png b/third_party/blink/web_tests/platform/linux/editing/selection/caret-rtl-2-expected.png deleted file mode 100644 index 635fe4f..0000000 --- a/third_party/blink/web_tests/platform/linux/editing/selection/caret-rtl-2-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/editing/selection/caret-rtl-2-left-expected.png b/third_party/blink/web_tests/platform/linux/editing/selection/caret-rtl-2-left-expected.png deleted file mode 100644 index 5b84dbf..0000000 --- a/third_party/blink/web_tests/platform/linux/editing/selection/caret-rtl-2-left-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/editing/selection/caret-rtl-expected.png b/third_party/blink/web_tests/platform/linux/editing/selection/caret-rtl-expected.png deleted file mode 100644 index 67c9037..0000000 --- a/third_party/blink/web_tests/platform/linux/editing/selection/caret-rtl-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/editing/selection/caret-rtl-right-expected.png b/third_party/blink/web_tests/platform/linux/editing/selection/caret-rtl-right-expected.png deleted file mode 100644 index 1d62fbf7..0000000 --- a/third_party/blink/web_tests/platform/linux/editing/selection/caret-rtl-right-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/editing/selection/caret-ltr-2-expected.png b/third_party/blink/web_tests/platform/mac/editing/selection/caret-ltr-2-expected.png deleted file mode 100644 index 83c402bc..0000000 --- a/third_party/blink/web_tests/platform/mac/editing/selection/caret-ltr-2-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/editing/selection/caret-ltr-2-left-expected.png b/third_party/blink/web_tests/platform/mac/editing/selection/caret-ltr-2-left-expected.png deleted file mode 100644 index abe1f25be..0000000 --- a/third_party/blink/web_tests/platform/mac/editing/selection/caret-ltr-2-left-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/editing/selection/caret-rtl-2-expected.png b/third_party/blink/web_tests/platform/mac/editing/selection/caret-rtl-2-expected.png deleted file mode 100644 index 9c9a6a3..0000000 --- a/third_party/blink/web_tests/platform/mac/editing/selection/caret-rtl-2-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/editing/selection/caret-rtl-2-left-expected.png b/third_party/blink/web_tests/platform/mac/editing/selection/caret-rtl-2-left-expected.png deleted file mode 100644 index 3ef829c..0000000 --- a/third_party/blink/web_tests/platform/mac/editing/selection/caret-rtl-2-left-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/editing/selection/caret-rtl-expected.png b/third_party/blink/web_tests/platform/mac/editing/selection/caret-rtl-expected.png deleted file mode 100644 index e7634af..0000000 --- a/third_party/blink/web_tests/platform/mac/editing/selection/caret-rtl-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/editing/selection/caret-rtl-right-expected.png b/third_party/blink/web_tests/platform/mac/editing/selection/caret-rtl-right-expected.png deleted file mode 100644 index 494efca..0000000 --- a/third_party/blink/web_tests/platform/mac/editing/selection/caret-rtl-right-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/editing/selection/caret-ltr-2-expected.png b/third_party/blink/web_tests/platform/win/editing/selection/caret-ltr-2-expected.png deleted file mode 100644 index b7003f3..0000000 --- a/third_party/blink/web_tests/platform/win/editing/selection/caret-ltr-2-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/editing/selection/caret-ltr-2-left-expected.png b/third_party/blink/web_tests/platform/win/editing/selection/caret-ltr-2-left-expected.png deleted file mode 100644 index 98b1381c..0000000 --- a/third_party/blink/web_tests/platform/win/editing/selection/caret-ltr-2-left-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/editing/selection/caret-rtl-2-expected.png b/third_party/blink/web_tests/platform/win/editing/selection/caret-rtl-2-expected.png deleted file mode 100644 index 7a22f25f..0000000 --- a/third_party/blink/web_tests/platform/win/editing/selection/caret-rtl-2-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/editing/selection/caret-rtl-2-left-expected.png b/third_party/blink/web_tests/platform/win/editing/selection/caret-rtl-2-left-expected.png deleted file mode 100644 index 98eb2f1ad..0000000 --- a/third_party/blink/web_tests/platform/win/editing/selection/caret-rtl-2-left-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/editing/selection/caret-rtl-expected.png b/third_party/blink/web_tests/platform/win/editing/selection/caret-rtl-expected.png deleted file mode 100644 index ec96dec6..0000000 --- a/third_party/blink/web_tests/platform/win/editing/selection/caret-rtl-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/editing/selection/caret-rtl-right-expected.png b/third_party/blink/web_tests/platform/win/editing/selection/caret-rtl-right-expected.png deleted file mode 100644 index 3444f8d..0000000 --- a/third_party/blink/web_tests/platform/win/editing/selection/caret-rtl-right-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/external/wpt/url/a-element-expected.txt b/third_party/blink/web_tests/platform/win/external/wpt/url/a-element-expected.txt index c2ace28..c5c521b 100644 --- a/third_party/blink/web_tests/platform/win/external/wpt/url/a-element-expected.txt +++ b/third_party/blink/web_tests/platform/win/external/wpt/url/a-element-expected.txt
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -Found 527 tests; 334 PASS, 193 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 527 tests; 337 PASS, 190 FAIL, 0 TIMEOUT, 0 NOTRUN. PASS Loading data… PASS Parsing: <http://example . org> against <http://example.org/foo/bar> @@ -410,7 +410,7 @@ PASS Parsing: <..> against <file:///C:/> PASS Parsing: <..> against <file:///> PASS Parsing: </> against <file:///C:/a/b> -FAIL Parsing: <//d:> against <file:///C:/a/b> assert_equals: href expected "file:///d:" but got "file:///D:/" +FAIL Parsing: <//d:> against <file:///C:/a/b> assert_equals: href expected "file:///d:" but got "file:///D:" FAIL Parsing: <//d:/..> against <file:///C:/a/b> assert_equals: href expected "file:///d:/" but got "file:///D:/" PASS Parsing: <..> against <file:///ab:/> PASS Parsing: <..> against <file:///1:/> @@ -437,9 +437,9 @@ PASS Parsing: <file://> against <file://ape/> PASS Parsing: </rooibos> against <file://tea/> PASS Parsing: </?chai> against <file://tea/> -FAIL Parsing: <C|> against <file://host/dir/file> assert_equals: href expected "file:///C:" but got "file:///C:/" -FAIL Parsing: <C|#> against <file://host/dir/file> assert_equals: href expected "file:///C:#" but got "file:///C:/#" -FAIL Parsing: <C|?> against <file://host/dir/file> assert_equals: href expected "file:///C:?" but got "file:///C:/?" +PASS Parsing: <C|> against <file://host/dir/file> +PASS Parsing: <C|#> against <file://host/dir/file> +PASS Parsing: <C|?> against <file://host/dir/file> PASS Parsing: <C|/> against <file://host/dir/file> PASS Parsing: <C| /> against <file://host/dir/file>
diff --git a/third_party/blink/web_tests/platform/win/external/wpt/url/a-element-xhtml-expected.txt b/third_party/blink/web_tests/platform/win/external/wpt/url/a-element-xhtml-expected.txt index c2ace28..c5c521b 100644 --- a/third_party/blink/web_tests/platform/win/external/wpt/url/a-element-xhtml-expected.txt +++ b/third_party/blink/web_tests/platform/win/external/wpt/url/a-element-xhtml-expected.txt
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -Found 527 tests; 334 PASS, 193 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 527 tests; 337 PASS, 190 FAIL, 0 TIMEOUT, 0 NOTRUN. PASS Loading data… PASS Parsing: <http://example . org> against <http://example.org/foo/bar> @@ -410,7 +410,7 @@ PASS Parsing: <..> against <file:///C:/> PASS Parsing: <..> against <file:///> PASS Parsing: </> against <file:///C:/a/b> -FAIL Parsing: <//d:> against <file:///C:/a/b> assert_equals: href expected "file:///d:" but got "file:///D:/" +FAIL Parsing: <//d:> against <file:///C:/a/b> assert_equals: href expected "file:///d:" but got "file:///D:" FAIL Parsing: <//d:/..> against <file:///C:/a/b> assert_equals: href expected "file:///d:/" but got "file:///D:/" PASS Parsing: <..> against <file:///ab:/> PASS Parsing: <..> against <file:///1:/> @@ -437,9 +437,9 @@ PASS Parsing: <file://> against <file://ape/> PASS Parsing: </rooibos> against <file://tea/> PASS Parsing: </?chai> against <file://tea/> -FAIL Parsing: <C|> against <file://host/dir/file> assert_equals: href expected "file:///C:" but got "file:///C:/" -FAIL Parsing: <C|#> against <file://host/dir/file> assert_equals: href expected "file:///C:#" but got "file:///C:/#" -FAIL Parsing: <C|?> against <file://host/dir/file> assert_equals: href expected "file:///C:?" but got "file:///C:/?" +PASS Parsing: <C|> against <file://host/dir/file> +PASS Parsing: <C|#> against <file://host/dir/file> +PASS Parsing: <C|?> against <file://host/dir/file> PASS Parsing: <C|/> against <file://host/dir/file> PASS Parsing: <C| /> against <file://host/dir/file>
diff --git a/third_party/blink/web_tests/platform/win/external/wpt/url/url-constructor-expected.txt b/third_party/blink/web_tests/platform/win/external/wpt/url/url-constructor-expected.txt index 9c6ddd5..7934a6b 100644 --- a/third_party/blink/web_tests/platform/win/external/wpt/url/url-constructor-expected.txt +++ b/third_party/blink/web_tests/platform/win/external/wpt/url/url-constructor-expected.txt
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -Found 527 tests; 399 PASS, 128 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 527 tests; 402 PASS, 125 FAIL, 0 TIMEOUT, 0 NOTRUN. PASS Loading data… PASS Parsing: <http://example . org> against <http://example.org/foo/bar> @@ -450,7 +450,7 @@ PASS Parsing: <..> against <file:///C:/> PASS Parsing: <..> against <file:///> PASS Parsing: </> against <file:///C:/a/b> -FAIL Parsing: <//d:> against <file:///C:/a/b> assert_equals: href expected "file:///d:" but got "file:///D:/" +FAIL Parsing: <//d:> against <file:///C:/a/b> assert_equals: href expected "file:///d:" but got "file:///D:" FAIL Parsing: <//d:/..> against <file:///C:/a/b> assert_equals: href expected "file:///d:/" but got "file:///D:/" PASS Parsing: <..> against <file:///ab:/> PASS Parsing: <..> against <file:///1:/> @@ -477,9 +477,9 @@ PASS Parsing: <file://> against <file://ape/> PASS Parsing: </rooibos> against <file://tea/> PASS Parsing: </?chai> against <file://tea/> -FAIL Parsing: <C|> against <file://host/dir/file> assert_equals: href expected "file:///C:" but got "file:///C:/" -FAIL Parsing: <C|#> against <file://host/dir/file> assert_equals: href expected "file:///C:#" but got "file:///C:/#" -FAIL Parsing: <C|?> against <file://host/dir/file> assert_equals: href expected "file:///C:?" but got "file:///C:/?" +PASS Parsing: <C|> against <file://host/dir/file> +PASS Parsing: <C|#> against <file://host/dir/file> +PASS Parsing: <C|?> against <file://host/dir/file> PASS Parsing: <C|/> against <file://host/dir/file> PASS Parsing: <C| /> against <file://host/dir/file>
diff --git a/third_party/blink/web_tests/platform/win/fast/url/relative-win-expected.txt b/third_party/blink/web_tests/platform/win/fast/url/relative-win-expected.txt index 54c11a5..f84c2ee 100644 --- a/third_party/blink/web_tests/platform/win/fast/url/relative-win-expected.txt +++ b/third_party/blink/web_tests/platform/win/fast/url/relative-win-expected.txt
@@ -9,7 +9,7 @@ FAIL canonicalize('\\\\another\\path') should be . Was file://another/path. PASS canonicalize('//c:/foo') is 'file:///C:/foo' PASS canonicalize('//localhost/c:/foo') is 'file:///C:/foo' -FAIL canonicalize('c:') should be . Was file:///C:/. +FAIL canonicalize('c:') should be . Was file:///C:. FAIL canonicalize('c:/foo') should be . Was file:///C:/foo. FAIL canonicalize('c:\\foo') should be . Was file:///C:/foo. PASS canonicalize('/z:/bar') is 'file:///Z:/bar'
diff --git a/third_party/blink/web_tests/virtual/form-controls-refresh-disabled/fast/forms/date-multiple-fields/date-multiple-fields-wheel-event.html b/third_party/blink/web_tests/virtual/form-controls-refresh-disabled/fast/forms/date-multiple-fields/date-multiple-fields-wheel-event.html index 0e02af2..c3a3605 100644 --- a/third_party/blink/web_tests/virtual/form-controls-refresh-disabled/fast/forms/date-multiple-fields/date-multiple-fields-wheel-event.html +++ b/third_party/blink/web_tests/virtual/form-controls-refresh-disabled/fast/forms/date-multiple-fields/date-multiple-fields-wheel-event.html
@@ -2,6 +2,7 @@ <html> <head> <script src="../../../resources/js-test.js"></script> +<script src="../../../../../resources/gesture-util.js"></script> <script src="../resources/common-wheel-event.js"></script> </head> <body>
diff --git a/third_party/blink/web_tests/virtual/form-controls-refresh-disabled/fast/forms/datetimelocal-multiple-fields/datetimelocal-multiple-fields-wheel-event.html b/third_party/blink/web_tests/virtual/form-controls-refresh-disabled/fast/forms/datetimelocal-multiple-fields/datetimelocal-multiple-fields-wheel-event.html index d8e3c05..c7db2c1f 100644 --- a/third_party/blink/web_tests/virtual/form-controls-refresh-disabled/fast/forms/datetimelocal-multiple-fields/datetimelocal-multiple-fields-wheel-event.html +++ b/third_party/blink/web_tests/virtual/form-controls-refresh-disabled/fast/forms/datetimelocal-multiple-fields/datetimelocal-multiple-fields-wheel-event.html
@@ -2,6 +2,7 @@ <html> <head> <script src="../../../resources/js-test.js"></script> +<script src="../../../../../resources/gesture-util.js"></script> <script src="../resources/common-wheel-event.js"></script> </head> <body>
diff --git a/third_party/blink/web_tests/virtual/form-controls-refresh-disabled/fast/forms/month-multiple-fields/month-multiple-fields-wheel-event.html b/third_party/blink/web_tests/virtual/form-controls-refresh-disabled/fast/forms/month-multiple-fields/month-multiple-fields-wheel-event.html index a1d3a22..bbfeaec 100644 --- a/third_party/blink/web_tests/virtual/form-controls-refresh-disabled/fast/forms/month-multiple-fields/month-multiple-fields-wheel-event.html +++ b/third_party/blink/web_tests/virtual/form-controls-refresh-disabled/fast/forms/month-multiple-fields/month-multiple-fields-wheel-event.html
@@ -2,6 +2,7 @@ <html> <head> <script src="../../../resources/js-test.js"></script> +<script src="../../../../../resources/gesture-util.js"></script> <script src="../resources/common-wheel-event.js"></script> </head> <body>
diff --git a/third_party/blink/web_tests/virtual/form-controls-refresh-disabled/fast/forms/resources/common-wheel-event.js b/third_party/blink/web_tests/virtual/form-controls-refresh-disabled/fast/forms/resources/common-wheel-event.js index 8e952e6..58299e5 100644 --- a/third_party/blink/web_tests/virtual/form-controls-refresh-disabled/fast/forms/resources/common-wheel-event.js +++ b/third_party/blink/web_tests/virtual/form-controls-refresh-disabled/fast/forms/resources/common-wheel-event.js
@@ -1,13 +1,22 @@ -function dispatchWheelEvent(element, deltaX, deltaY) +async function dispatchWheelEvent(element, deltaX, deltaY) { var rect = element.getClientRects()[0] - eventSender.mouseMoveTo(rect.left, rect.top); - eventSender.mouseScrollBy(deltaX, deltaY); + + const x = rect.left; + const y = rect.top; + const source = GestureSourceType.MOUSE_INPUT; + const speed = SPEED_INSTANT; + const precise_scrolling_deltas = false; + + await mouseMoveTo(x, y); + await smoothScrollWithXY(deltaX, deltaY, x, y, source, speed, + precise_scrolling_deltas); } var input; -function testWheelEvent(parameters) +async function testWheelEvent(parameters) { + window.jsTestIsAsync = true; var inputType = parameters['inputType']; var initialValue = parameters['initialValue']; var stepUpValue1 = parameters['stepUpValue1']; @@ -20,38 +29,39 @@ input.focus(); debug('Initial value is ' + initialValue + '. We\'ll wheel up by 1:'); - dispatchWheelEvent(input, 0, 1); + await dispatchWheelEvent(input, 0, -1); shouldBeEqualToString('input.value', stepUpValue1); debug('Wheel up by 100:'); - dispatchWheelEvent(input, 0, 100); + await dispatchWheelEvent(input, 0, -100); shouldBeEqualToString('input.value', stepUpValue2); debug('Wheel down by 1:'); - dispatchWheelEvent(input, 0, -1); + await dispatchWheelEvent(input, 0, 1); shouldBeEqualToString('input.value', stepUpValue1); debug('Wheel down by 256:'); - dispatchWheelEvent(input, 0, -256); + await dispatchWheelEvent(input, 0, 256); shouldBeEqualToString('input.value', initialValue); debug('Disabled input element:'); input.disabled = true; - dispatchWheelEvent(input, 0, 1); + await dispatchWheelEvent(input, 0, -1); shouldBeEqualToString('input.value', initialValue); input.removeAttribute('disabled'); debug('Read-only input element:'); input.readOnly = true; - dispatchWheelEvent(input, 0, 1); + await dispatchWheelEvent(input, 0, -1); shouldBeEqualToString('input.value', initialValue); input.readOnly = false; debug('No focus:'); document.getElementById('another').focus(); - dispatchWheelEvent(input, 0, 1); + await dispatchWheelEvent(input, 0, -1); shouldBeEqualToString('input.value', initialValue); parent.parentNode.removeChild(parent); + finishJSTest(); }
diff --git a/third_party/blink/web_tests/virtual/form-controls-refresh-disabled/fast/forms/time-multiple-fields/time-multiple-fields-wheel-event.html b/third_party/blink/web_tests/virtual/form-controls-refresh-disabled/fast/forms/time-multiple-fields/time-multiple-fields-wheel-event.html index a5869d6..6dd8cbd8 100644 --- a/third_party/blink/web_tests/virtual/form-controls-refresh-disabled/fast/forms/time-multiple-fields/time-multiple-fields-wheel-event.html +++ b/third_party/blink/web_tests/virtual/form-controls-refresh-disabled/fast/forms/time-multiple-fields/time-multiple-fields-wheel-event.html
@@ -2,6 +2,7 @@ <html> <head> <script src="../../../resources/js-test.js"></script> +<script src="../../../../../resources/gesture-util.js"></script> <script src="../resources/common-wheel-event.js"></script> </head> <body>
diff --git a/third_party/blink/web_tests/virtual/form-controls-refresh-disabled/fast/forms/week-multiple-fields/week-multiple-fields-wheel-event.html b/third_party/blink/web_tests/virtual/form-controls-refresh-disabled/fast/forms/week-multiple-fields/week-multiple-fields-wheel-event.html index 1737161..a6e65ce 100644 --- a/third_party/blink/web_tests/virtual/form-controls-refresh-disabled/fast/forms/week-multiple-fields/week-multiple-fields-wheel-event.html +++ b/third_party/blink/web_tests/virtual/form-controls-refresh-disabled/fast/forms/week-multiple-fields/week-multiple-fields-wheel-event.html
@@ -2,6 +2,7 @@ <html> <head> <script src="../../../resources/js-test.js"></script> +<script src="../../../../../resources/gesture-util.js"></script> <script src="../resources/common-wheel-event.js"></script> </head> <body>
diff --git a/third_party/freetype/README.chromium b/third_party/freetype/README.chromium index 2d1c54a..9603fd54 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-1-125-g093f87bfe -Revision: 093f87bfe45160195ade7bd5174bbaaf50ebd6be +Version: VER-2-10-1-127-g3f70e6d20 +Revision: 3f70e6d20c82b28174096adcd0657b3c998b007b CPEPrefix: cpe:/a:freetype:freetype:2.10.1 License: Custom license "inspired by the BSD, Artistic, and IJG (Independent JPEG Group) licenses"
diff --git a/third_party/freetype/include/freetype-custom-config/ftmodule.h b/third_party/freetype/include/freetype-custom-config/ftmodule.h index 72eda05..7d1271f 100644 --- a/third_party/freetype/include/freetype-custom-config/ftmodule.h +++ b/third_party/freetype/include/freetype-custom-config/ftmodule.h
@@ -23,8 +23,6 @@ FT_USE_MODULE( FT_Renderer_Class, ft_raster1_renderer_class ) FT_USE_MODULE( FT_Module_Class, sfnt_module_class ) FT_USE_MODULE( FT_Renderer_Class, ft_smooth_renderer_class ) -FT_USE_MODULE( FT_Renderer_Class, ft_smooth_lcd_renderer_class ) -FT_USE_MODULE( FT_Renderer_Class, ft_smooth_lcdv_renderer_class ) FT_USE_MODULE( FT_Module_Class, psaux_module_class ) #if defined(PDFIUM_REQUIRED_MODULES)
diff --git a/third_party/freetype/include/freetype-custom-config/ftoption.h b/third_party/freetype/include/freetype-custom-config/ftoption.h index 197b5fc..151ed6b 100644 --- a/third_party/freetype/include/freetype-custom-config/ftoption.h +++ b/third_party/freetype/include/freetype-custom-config/ftoption.h
@@ -121,10 +121,8 @@ * mitigate color fringes inherent to this technology, you also need to * explicitly set up LCD filtering. * - * Note that this feature is covered by several Microsoft patents and - * should not be activated in any default build of the library. When this - * macro is not defined, FreeType offers alternative LCD rendering - * technology that produces excellent output without LCD filtering. + * When this macro is not defined, FreeType offers alternative LCD + * rendering technology that produces excellent output. */ #define FT_CONFIG_OPTION_SUBPIXEL_RENDERING
diff --git a/third_party/libaddressinput/OWNERS b/third_party/libaddressinput/OWNERS index f57c6c2..7a40bb9 100644 --- a/third_party/libaddressinput/OWNERS +++ b/third_party/libaddressinput/OWNERS
@@ -1,6 +1,6 @@ battre@chromium.org dvadym@chromium.org -koerber@chromium.org +koerber@google.com kolos@chromium.org mathp@chromium.org rouslan@chromium.org
diff --git a/third_party/libphonenumber/OWNERS b/third_party/libphonenumber/OWNERS index f57c6c2..7a40bb9 100644 --- a/third_party/libphonenumber/OWNERS +++ b/third_party/libphonenumber/OWNERS
@@ -1,6 +1,6 @@ battre@chromium.org dvadym@chromium.org -koerber@chromium.org +koerber@google.com kolos@chromium.org mathp@chromium.org rouslan@chromium.org
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index 27d59a4..8671fef 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -8397,6 +8397,32 @@ <int value="6" label="FAILED_INCLUSION_PROOF_SERVER"/> </enum> +<enum name="CertProvisioningEvent"> + <int value="0" label="kRegisteredToInvalidationTopic"/> + <int value="1" label="kInvalidationReceived"/> + <int value="2" label="kWorkerRetryWithoutInvalidation"/> + <int value="3" label="kWorkerRetrySucceededWithoutInvalidation"/> + <int value="4" label="kProfileRetriedManually"/> + <int value="5" label="kWorkerCreated"/> + <int value="6" label="kWorkerDeserialized"/> + <int value="7" label="kWorkerDeserializationFailed"/> +</enum> + +<enum name="CertProvisioningWorkerState"> + <int value="0" label="kInitState"/> + <int value="1" label="kKeypairGenerated"/> + <int value="2" label="kStartCsrResponseReceived"/> + <int value="3" label="kVaChallengeFinished"/> + <int value="4" label="kKeyRegistered"/> + <int value="5" label="kKeypairMarked"/> + <int value="6" label="kSignCsrFinished"/> + <int value="7" label="kFinishCsrResponseReceived"/> + <int value="8" label="kSucceeded"/> + <int value="9" label="kInconsistentDataError"/> + <int value="10" label="kFailed"/> + <int value="11" label="kCanceled"/> +</enum> + <enum name="CertVerifierTrialComparisonResult"> <int value="0" label="Invalid"/> <int value="1" label="Equal"/> @@ -38337,6 +38363,7 @@ <int value="-1899409297" label="ProcessSharingWithStrictSiteInstances:disabled"/> <int value="-1898386671" label="PasswordCheck:enabled"/> + <int value="-1896871201" label="CrossOriginOpenerPolicyReporting:enabled"/> <int value="-1896394207" label="PasswordChange:disabled"/> <int value="-1895719323" label="VrBrowsingTabsView:enabled"/> <int value="-1894699049" label="AudioFocusEnforcement:disabled"/> @@ -38864,6 +38891,7 @@ <int value="-1322882747" label="disable-datasaver-prompt"/> <int value="-1319688939" label="ignore-gpu-blacklist"/> <int value="-1318914924" label="OverflowIconsForMediaControls:enabled"/> + <int value="-1316769004" label="CrossOriginOpenerPolicyReporting:disabled"/> <int value="-1314603238" label="ChromeHomePullToRefreshIphAtTop:enabled"/> <int value="-1313810940" label="StrictOriginIsolation:disabled"/> <int value="-1311575452" @@ -39836,6 +39864,7 @@ <int value="-203968600" label="SyncSupportSecondaryAccount:disabled"/> <int value="-202007318" label="AndroidAIAFetching:enabled"/> <int value="-200805659" label="ContextualSuggestionsButton:enabled"/> + <int value="-199690952" label="PageInfoV2:enabled"/> <int value="-196110497" label="force-text-direction"/> <int value="-195029497" label="MediaRemoting:disabled"/> <int value="-192919826" label="ViewsSimplifiedFullscreenUI:enabled"/> @@ -40208,6 +40237,7 @@ <int value="229476202" label="CryptAuthV2Enrollment:enabled"/> <int value="229877058" label="ShelfScrollable:disabled"/> <int value="233721248" label="DownloadRename:disabled"/> + <int value="237066116" label="PageInfoV2:disabled"/> <int value="237570976" label="CommandLineOnNonRooted:disabled"/> <int value="237964589" label="enable-manual-fallback-for-password-saving:disabled"/> @@ -40999,6 +41029,7 @@ label="AutofillCreditCardLastUsedDateDisplay:disabled"/> <int value="1155905651" label="DrawVerticallyEdgeToEdge:disabled"/> <int value="1155923106" label="NTPOfflinePages:enabled"/> + <int value="1158333871" label="QueryTilesEnableQueryEditing:enabled"/> <int value="1163255347" label="ash-enable-touch-view-touch-feedback"/> <int value="1164377197" label="SwipingFromLeftEdgeToGoBack:enabled"/> <int value="1164460660" label="AutofillEnableVirtualCard:enabled"/> @@ -41559,6 +41590,7 @@ <int value="1798347197" label="ContextualSuggestionsIPHReverseScroll:disabled"/> <int value="1799521026" label="LegacyTLSEnforced:disabled"/> + <int value="1802874714" label="QueryTilesEnableQueryEditing:disabled"/> <int value="1803465156" label="enable-zero-suggest-most-visited"/> <int value="1803470125" label="SyncUSSSessions:enabled"/> <int value="1803914892" label="TemporaryUnexpireFlagsM76:enabled"/> @@ -45795,6 +45827,12 @@ <int value="7" label="A navigation suggestion is found using target embedding against a top domain"/> + <int value="8" + label="A navigation suggestion is found using a skeleton match against + a top 500 domain"/> + <int value="9" + label="A navigation suggestion is found using a skeleton match against + a top 5k (but not top 500) domain"/> </enum> <enum name="NavigationURLScheme"> @@ -61055,6 +61093,17 @@ </int> </enum> +<!-- + SharingActionSource must be kept in sync with ValidSharingActionSource defined + in //ui/file_manager/file_manager/foreground/js/file_manager_commands.js. +--> + +<enum name="SharingActionSource"> + <int value="0" label="Unknown"/> + <int value="1" label="Context Menu"/> + <int value="2" label="Share Button"/> +</enum> + <enum name="SharingClickToCallEntryPoint"> <int value="0" label="Left click on a phone link"/> <int value="1" label="Right click on a phone link"/> @@ -65281,7 +65330,8 @@ <int value="3" label="Turned off and setup not completed"/> <int value="4" label="Must confirm sync settings"/> <int value="5" label="Disallowed by enterprise policy"/> - <int value="6" label="Disallowed by the platform"/> + <int value="6" + label="Disallowed by the platform (obsolete, was never recorded)"/> </enum> <enum name="SyncKeystoreDecryptionFailure">
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 0efc92e..581cb78 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -24751,6 +24751,56 @@ <summary>Records the session duration in Chrome OS camera service.</summary> </histogram> +<histogram name="ChromeOS.CertProvisioning.CsrSignTime" units="ms" + expires_after="2021-06-01"> + <owner>miersh@google.com</owner> + <owner>pmarko@chromium.org</owner> + <summary> + The amount of time it took to sign one CSR by certificate provisioning + worker. + </summary> +</histogram> + +<histogram name="ChromeOS.CertProvisioning.Event" enum="CertProvisioningEvent" + expires_after="2021-06-01"> + <owner>miersh@google.com</owner> + <owner>pmarko@chromium.org</owner> + <summary> + Number of times each event is reached during certificate provisioning flow. + </summary> +</histogram> + +<histogram name="ChromeOS.CertProvisioning.KeypairGenerationTime" units="ms" + expires_after="2021-06-01"> + <owner>miersh@google.com</owner> + <owner>pmarko@chromium.org</owner> + <summary> + The amount of time it took to generate one key pair by certificate + provisioning worker. + </summary> +</histogram> + +<histogram name="ChromeOS.CertProvisioning.Result" + enum="CertProvisioningWorkerState" expires_after="2021-06-01"> + <owner>miersh@google.com</owner> + <owner>pmarko@chromium.org</owner> + <summary> + For final states (see the list in cert_provisioning::IsFinalState): number + of times certificate provisioning worker finished on every state. For other + states: number of times the worker failed on every state. + </summary> +</histogram> + +<histogram name="ChromeOS.CertProvisioning.VaTime" units="ms" + expires_after="2021-06-01"> + <owner>miersh@google.com</owner> + <owner>pmarko@chromium.org</owner> + <summary> + The amount of time it took to build one Verified Access response by + certificate provisioning worker. + </summary> +</histogram> + <histogram name="ChromeOS.CWP.CollectHeap" enum="ChromeOSProfileCollectionStatus" expires_after="2020-02-01"> <obsolete> @@ -58733,6 +58783,35 @@ </summary> </histogram> +<histogram name="FileBrowser.Share.ActionSource" enum="SharingActionSource" + expires_after="2021-05-05"> + <owner>lucmult@chromium.org</owner> + <owner>majewski@chromium.org</owner> + <summary>Chrome OS File Browser: the source of file sharing action.</summary> +</histogram> + +<!-- TODO(crbug.com/1063169): record Share.AppId AppID for each entity. --> + +<histogram name="FileBrowser.Share.FileCount" units="files" + expires_after="2021-05-05"> + <owner>lucmult@chromium.org</owner> + <owner>majewski@chromium.org</owner> + <summary> + Chrome OS File Browser: The number of files shared via a single Share + action. + </summary> +</histogram> + +<histogram name="FileBrowser.Share.FileType" enum="ViewFileType" + expires_after="2021-05-05"> + <owner>lucmult@chromium.org</owner> + <owner>majewski@chromium.org</owner> + <summary> + Chrome OS File Browser: The type of the file shared via Share action. + Recorded for each file being shared by a share action + </summary> +</histogram> + <histogram name="FileBrowser.SuggestApps.CloseDialog" enum="SuggestAppsDialogCloseReason" expires_after="M89"> <owner>slangley@chromium.org</owner> @@ -153150,6 +153229,9 @@ <histogram name="Sharing.ClickToCallContextMenuPhoneNumberParsingDelay" units="microseconds" expires_after="M84"> + <obsolete> + Removed in M84 after gathering enough data as a baseline. + </obsolete> <owner>himanshujaju@chromium.org</owner> <owner>knollr@chromium.org</owner> <owner>peter@chromium.org</owner> @@ -175188,10 +175270,12 @@ </histogram> <histogram name="UserSessionManager.RestoreOnCrash.AccountIdValid" - enum="BooleanValid" expires_after="2020-02-16"> - <owner>msarda@chromium.org</owner> + enum="BooleanValid" expires_after="2021-02-16"> + <owner>rsorokin@chromium.org</owner> + <owner>cros-oac@google.com</owner> <summary> - The result of restoring account id on Chrome restart after crash. + The result of restoring account id on Chrome restart after crash on Chrome + OS. </summary> </histogram> @@ -189677,6 +189761,16 @@ <affected-histogram name="DiskBasedCertCache.CertIo"/> </histogram_suffixes> +<histogram_suffixes name="CertProvisioningScope" separator="."> + <suffix name="Device" label=""/> + <suffix name="User" label=""/> + <affected-histogram name="ChromeOS.CertProvisioning.CsrSignTime"/> + <affected-histogram name="ChromeOS.CertProvisioning.Event"/> + <affected-histogram name="ChromeOS.CertProvisioning.KeypairGenerationTime"/> + <affected-histogram name="ChromeOS.CertProvisioning.Result"/> + <affected-histogram name="ChromeOS.CertProvisioning.VaTime"/> +</histogram_suffixes> + <histogram_suffixes name="CertVerifyProcImpl" separator="."> <suffix name="Android" label="CertVerifyProcAndroid"/> <suffix name="Builtin" label="CertVerifyProcBuiltin"/>
diff --git a/tools/perf/core/perf_data_generator.py b/tools/perf/core/perf_data_generator.py index 92de396..a2d88c1a 100755 --- a/tools/perf/core/perf_data_generator.py +++ b/tools/perf/core/perf_data_generator.py
@@ -93,7 +93,7 @@ # This is an opt-in list for tester which will skip the perf data handling. # The perf data will be handled on a separated 'processor' VM. # This list will be removed or replace by an opt-out list. -LIGHTWEIGHT_TESTERS = ['linux-perf-fyi'] +LIGHTWEIGHT_TESTERS = ['linux-perf-fyi', 'android-pixel2-perf-fyi'] FYI_BUILDERS = { 'android-nexus5x-perf-fyi': { @@ -209,6 +209,10 @@ 'platform': 'linux', 'perf_processor': True, }, + 'android-pixel2-processor-perf-fyi': { + 'platform': 'linux', + 'perf_processor': True, + }, } # These configurations are taken from chromium_perf.py in @@ -1085,6 +1089,7 @@ if 'additional_compile_targets' in condensed_config: config['additional_compile_targets'] = ( condensed_config['additional_compile_targets']) + # TODO(crbug.com/1078675): remove this setting if 'perf_processor' in condensed_config: config['merge'] = { 'script': '//tools/perf/process_perf_results.py',
diff --git a/ui/accessibility/platform/ax_platform_node_textrangeprovider_win_unittest.cc b/ui/accessibility/platform/ax_platform_node_textrangeprovider_win_unittest.cc index 3da634f4..7f30023e 100644 --- a/ui/accessibility/platform/ax_platform_node_textrangeprovider_win_unittest.cc +++ b/ui/accessibility/platform/ax_platform_node_textrangeprovider_win_unittest.cc
@@ -2971,13 +2971,13 @@ // // root // | - // paragraph________________________ - // | | | - // static_text link search input - // | | | - // text_node static_text text_node - // | - // text_node + // paragraph_________________________________________ + // | | | | + // static_text link search input pdf_highlight + // | | | | + // text_node static_text text_node static_text + // | | + // text_node text_node ui::AXNodeData root_data; root_data.id = 1; @@ -3024,6 +3024,21 @@ search_text.SetName("placeholder"); search_box.child_ids.push_back(search_text.id); + ui::AXNodeData pdf_highlight_data; + pdf_highlight_data.id = 10; + pdf_highlight_data.role = ax::mojom::Role::kPdfActionableHighlight; + paragraph_data.child_ids.push_back(pdf_highlight_data.id); + + ui::AXNodeData static_text_data3; + static_text_data3.id = 11; + static_text_data3.role = ax::mojom::Role::kStaticText; + pdf_highlight_data.child_ids.push_back(static_text_data3.id); + + ui::AXNodeData inline_text_data3; + inline_text_data3.id = 12; + inline_text_data3.role = ax::mojom::Role::kInlineTextBox; + static_text_data3.child_ids.push_back(inline_text_data3.id); + ui::AXTreeUpdate update; ui::AXTreeData tree_data; tree_data.tree_id = ui::AXTreeID::CreateNewAXTreeID(); @@ -3039,6 +3054,9 @@ update.nodes.push_back(inline_text_data2); update.nodes.push_back(search_box); update.nodes.push_back(search_text); + update.nodes.push_back(pdf_highlight_data); + update.nodes.push_back(static_text_data3); + update.nodes.push_back(inline_text_data3); Init(update); @@ -3051,6 +3069,9 @@ AXNode* inline_text_node2 = static_text_node2->children()[0]; AXNode* search_box_node = paragraph_node->children()[2]; AXNode* search_text_node = search_box_node->children()[0]; + AXNode* pdf_highlight_node = paragraph_node->children()[3]; + AXNode* static_text_node3 = pdf_highlight_node->children()[0]; + AXNode* inline_text_node3 = static_text_node3->children()[0]; ComPtr<IRawElementProviderSimple> link_node_raw = QueryInterfaceFromNode<IRawElementProviderSimple>(link_node); @@ -3064,6 +3085,10 @@ QueryInterfaceFromNode<IRawElementProviderSimple>(search_box_node); ComPtr<IRawElementProviderSimple> search_text_node_raw = QueryInterfaceFromNode<IRawElementProviderSimple>(search_text_node); + ComPtr<IRawElementProviderSimple> pdf_highlight_node_raw = + QueryInterfaceFromNode<IRawElementProviderSimple>(pdf_highlight_node); + ComPtr<IRawElementProviderSimple> inline_text_node_raw3 = + QueryInterfaceFromNode<IRawElementProviderSimple>(inline_text_node3); // Test GetEnclosingElement for the two leaves text nodes. The enclosing // element of the first one should be its static text parent (because inline @@ -3106,6 +3131,18 @@ EXPECT_HRESULT_SUCCEEDED( text_range_provider->GetEnclosingElement(&enclosing_element)); EXPECT_EQ(search_box_node_raw.Get(), enclosing_element.Get()); + + // The enclosing element for the text node that is grandchild of the + // pdf_highlight node should return the pdf_highlight node. + EXPECT_HRESULT_SUCCEEDED(inline_text_node_raw3->GetPatternProvider( + UIA_TextPatternId, &text_provider)); + + EXPECT_HRESULT_SUCCEEDED( + text_provider->get_DocumentRange(&text_range_provider)); + + EXPECT_HRESULT_SUCCEEDED( + text_range_provider->GetEnclosingElement(&enclosing_element)); + EXPECT_EQ(pdf_highlight_node_raw.Get(), enclosing_element.Get()); } TEST_F(AXPlatformNodeTextRangeProviderTest,
diff --git a/ui/accessibility/platform/ax_platform_node_win.cc b/ui/accessibility/platform/ax_platform_node_win.cc index fd242e19..2d93a5f 100644 --- a/ui/accessibility/platform/ax_platform_node_win.cc +++ b/ui/accessibility/platform/ax_platform_node_win.cc
@@ -6800,12 +6800,7 @@ // UIA provides multiple "views": raw, content and control. We only want to // populate the content and control views with items that make sense to // traverse over. - if (GetDelegate()->IsWebContent()) { - // Invisible or ignored elements should not show up in control view at all. - if (IsInvisibleOrIgnored()) - return false; - if (IsTextOnlyObject()) { // A text leaf can be a UIAControl, but text inside of a heading, link, // button, etc. where the role allows the name to be generated from the @@ -6845,8 +6840,7 @@ } parent = FromNativeViewAccessible(parent->GetParent()); } - } // end of text only case. - + } const AXNodeData& data = GetData(); // https://docs.microsoft.com/en-us/windows/win32/winauto/uiauto-treeoverview#control-view // The control view also includes noninteractive UI items that contribute @@ -6898,10 +6892,9 @@ !data.HasState(ax::mojom::State::kFocusable) && !data.IsClickable()) { return false; } - return true; - } // end of web-content only case. - + } + // non web-content case. const AXNodeData& data = GetData(); return !((IsReadOnlySupported(data.role) && data.IsReadOnlyOrDisabled()) || data.HasState(ax::mojom::State::kInvisible) || @@ -6978,8 +6971,13 @@ // TODO(bebeaudr): We might be able to remove ax::mojom::Role::kLink once // http://crbug.com/1054514 is fixed. Links should not have to hide their // children. + // TODO(virens): |kPdfActionableHighlight| needs to follow a fix similar to + // links. At present Pdf highlghts have text nodes as children. But, we may + // enable pdf highlights to have complex children like links based on user + // feedback. case ax::mojom::Role::kLink: case ax::mojom::Role::kTextField: + case ax::mojom::Role::kPdfActionableHighlight: return true; default: return false;
diff --git a/ui/accessibility/platform/ax_platform_node_win_unittest.cc b/ui/accessibility/platform/ax_platform_node_win_unittest.cc index 4a43009..a848ea1 100644 --- a/ui/accessibility/platform/ax_platform_node_win_unittest.cc +++ b/ui/accessibility/platform/ax_platform_node_win_unittest.cc
@@ -3823,93 +3823,6 @@ UIA_IsDialogPropertyId, true); } -TEST_F(AXPlatformNodeWinTest, - UIAGetPropertyValueIsControlElementIgnoredInvisible) { - AXNodeData root; - root.id = 1; - root.role = ax::mojom::Role::kRootWebArea; - root.child_ids = {2, 3, 4, 5, 6, 7, 8}; - - AXNodeData normal_button; - normal_button.id = 2; - normal_button.role = ax::mojom::Role::kButton; - - AXNodeData ignored_button; - ignored_button.id = 3; - ignored_button.role = ax::mojom::Role::kButton; - ignored_button.AddState(ax::mojom::State::kIgnored); - - AXNodeData invisible_button; - invisible_button.id = 4; - invisible_button.role = ax::mojom::Role::kButton; - invisible_button.AddState(ax::mojom::State::kInvisible); - - AXNodeData invisible_focusable_button; - invisible_focusable_button.id = 5; - invisible_focusable_button.role = ax::mojom::Role::kButton; - invisible_focusable_button.AddState(ax::mojom::State::kInvisible); - invisible_focusable_button.AddState(ax::mojom::State::kFocusable); - - AXNodeData focusable_generic_container; - focusable_generic_container.id = 6; - focusable_generic_container.role = ax::mojom::Role::kGenericContainer; - focusable_generic_container.AddState(ax::mojom::State::kFocusable); - - AXNodeData ignored_focusable_generic_container; - ignored_focusable_generic_container.id = 7; - ignored_focusable_generic_container.role = ax::mojom::Role::kGenericContainer; - ignored_focusable_generic_container.AddState(ax::mojom::State::kIgnored); - focusable_generic_container.AddState(ax::mojom::State::kFocusable); - - AXNodeData invisible_focusable_generic_container; - invisible_focusable_generic_container.id = 8; - invisible_focusable_generic_container.role = - ax::mojom::Role::kGenericContainer; - invisible_focusable_generic_container.AddState(ax::mojom::State::kInvisible); - invisible_focusable_generic_container.AddState(ax::mojom::State::kFocusable); - - Init(root, normal_button, ignored_button, invisible_button, - invisible_focusable_button, focusable_generic_container, - ignored_focusable_generic_container, - invisible_focusable_generic_container); - - // Turn on web content mode for the AXTree. - TestAXNodeWrapper::SetGlobalIsWebContent(true); - - // Normal button (id=2), no invisible or ignored state set. Should be a - // control element. - EXPECT_UIA_BOOL_EQ(GetIRawElementProviderSimpleFromChildIndex(0), - UIA_IsControlElementPropertyId, true); - - // Button with ignored state (id=3). Should not be a control element. - EXPECT_UIA_BOOL_EQ(GetIRawElementProviderSimpleFromChildIndex(1), - UIA_IsControlElementPropertyId, false); - - // Button with invisible state (id=4). Should not be a control element. - EXPECT_UIA_BOOL_EQ(GetIRawElementProviderSimpleFromChildIndex(2), - UIA_IsControlElementPropertyId, false); - - // Button with invisible state, but focusable (id=5). Should not be a control - // element. - EXPECT_UIA_BOOL_EQ(GetIRawElementProviderSimpleFromChildIndex(3), - UIA_IsControlElementPropertyId, false); - - // Generic container, focusable (id=6). Should be a control - // element. - EXPECT_UIA_BOOL_EQ(GetIRawElementProviderSimpleFromChildIndex(4), - UIA_IsControlElementPropertyId, true); - - // Generic container, ignored but focusable (id=7). Should not be a control - // element. - EXPECT_UIA_BOOL_EQ(GetIRawElementProviderSimpleFromChildIndex(5), - UIA_IsControlElementPropertyId, false); - - // Generic container, invisible and ignored, but focusable (id=8). Should not - // be a control element. - EXPECT_UIA_BOOL_EQ(GetIRawElementProviderSimpleFromChildIndex(6), - UIA_IsControlElementPropertyId, false); -} - TEST_F(AXPlatformNodeWinTest, TestUIAGetControllerForPropertyId) { AXNodeData root; root.id = 1;
diff --git a/ui/file_manager/file_manager/foreground/js/BUILD.gn b/ui/file_manager/file_manager/foreground/js/BUILD.gn index a01b496d..17706b1 100644 --- a/ui/file_manager/file_manager/foreground/js/BUILD.gn +++ b/ui/file_manager/file_manager/foreground/js/BUILD.gn
@@ -383,6 +383,15 @@ externs_list = [ "//ui/file_manager/externs/command_handler_deps.js" ] } +js_unittest("file_manager_commands_unittest") { + deps = [ + ":file_manager_commands", + ":file_tasks", + "//ui/file_manager/file_manager/background/js:mock_volume_manager", + "//ui/webui/resources/js:webui_resource_test", + ] +} + js_library("file_selection") { deps = [ ":constants", @@ -798,6 +807,7 @@ deps = [ ":actions_model_unittest", ":file_list_model_unittest", + ":file_manager_commands_unittest", ":file_tasks_unittest", ":file_transfer_controller_unittest", ":import_controller_unittest",
diff --git a/ui/file_manager/file_manager/foreground/js/file_manager_commands.js b/ui/file_manager/file_manager/foreground/js/file_manager_commands.js index d657153..5cd0ed33 100644 --- a/ui/file_manager/file_manager/foreground/js/file_manager_commands.js +++ b/ui/file_manager/file_manager/foreground/js/file_manager_commands.js
@@ -32,6 +32,58 @@ const CommandUtil = {}; /** + * Possible share action sources for UMA. + * @enum {string} + * @const + */ +CommandUtil.SharingActionSourceForUMA = { + UNKNOWN: 'Unknown', + CONTEXT_MENU: 'Context Menu', + SHARE_BUTTON: 'Share Button', +}; + +/** + * The IDs of elements that can trigger share action. + * @enum {string} + * @const + */ +CommandUtil.SharingActionElementId = { + CONTEXT_MENU: 'file-list', + SHARE_BUTTON: 'share-menu-button', +}; + +/** + * A list of supported values for SharingActionSource enum. Keep this in sync + * with SharingActionSource defined in //tools/metrics/histograms/enums.xml. + */ +CommandUtil.ValidSharingActionSource = [ + CommandUtil.SharingActionSourceForUMA.UNKNOWN, + CommandUtil.SharingActionSourceForUMA.CONTEXT_MENU, + CommandUtil.SharingActionSourceForUMA.SHARE_BUTTON, +]; + +/** + * Helper function that for the given event returns the source of a share + * action. If the source cannot be determined, this function returns + * CommandUtil.SharingActionSourceForUMA.UNKNOWN. + * @param {!Event} event The event that triggered share action. + * @return {!CommandUtil.SharingActionSourceForUMA} + */ +CommandUtil.getSharingActionSource = event => { + const id = event.target.id; + switch (id) { + case CommandUtil.SharingActionElementId.CONTEXT_MENU: + return CommandUtil.SharingActionSourceForUMA.CONTEXT_MENU; + case CommandUtil.SharingActionElementId.SHARE_BUTTON: + return CommandUtil.SharingActionSourceForUMA.SHARE_BUTTON; + default: { + console.error('Unrecognized event.target.id for sharing action "%s"', id); + return CommandUtil.SharingActionSourceForUMA.UNKNOWN; + } + } +}; + +/** * Extracts entry on which command event was dispatched. * * @param {!CommandHandlerDeps} fileManager @@ -554,6 +606,24 @@ }; /** + * Records UMA statistics about Share action. + * @param {!Event} event The event that triggered sharing action. + * @param {!Array<!FileEntry>} entries File entries to be shared. + */ +CommandHandler.recordSharingAction = (event, entries) => { + const source = CommandUtil.getSharingActionSource(event); + metrics.recordEnum( + 'Share.ActionSource', source, CommandUtil.ValidSharingActionSource); + metrics.recordSmallCount('Share.FileCount', entries.length); + for (const entry of entries) { + metrics.recordEnum( + 'Share.FileType', FileTasks.getViewFileType(entry), + FileTasks.UMA_INDEX_KNOWN_EXTENSIONS); + } + // TODO(crbug.com/1063169): record Share.AppId AppID for each entity. +}; + +/** * Commands. * @private @const {Object<Command>} */ @@ -1751,6 +1821,7 @@ CommandHandler.COMMANDS_['share'] = new class extends Command { execute(event, fileManager) { const entries = CommandUtil.getCommandEntries(fileManager, event.target); + CommandHandler.recordSharingAction(event, entries); const actionsController = fileManager.actionsController; fileManager.actionsController.getActionsForEntries(entries).then(
diff --git a/ui/file_manager/file_manager/foreground/js/file_manager_commands_unittest.js b/ui/file_manager/file_manager/foreground/js/file_manager_commands_unittest.js new file mode 100644 index 0000000..4a2728fb --- /dev/null +++ b/ui/file_manager/file_manager/foreground/js/file_manager_commands_unittest.js
@@ -0,0 +1,94 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * Utility function that appends value under a given name in the store. + * @param {!Map<string, !Array<string|number>>} store + * @param {string} name + * @param {string|number} value + */ +function record(store, name, value) { + let recorded = store.get(name); + if (!recorded) { + recorded = []; + store.set(name, recorded); + } + recorded.push(value); +} + +/** + * Checks that a correct sharing action source is extracted from an event. + */ +function testGetSharingActionSource() { + const testData = [ + { + event: {target: {id: CommandUtil.SharingActionElementId.CONTEXT_MENU}}, + expected: CommandUtil.SharingActionSourceForUMA.CONTEXT_MENU, + }, + { + event: {target: {id: CommandUtil.SharingActionElementId.SHARE_BUTTON}}, + expected: CommandUtil.SharingActionSourceForUMA.SHARE_BUTTON, + }, + { + event: {target: {id: '__no_such_id__'}}, + expected: CommandUtil.SharingActionSourceForUMA.UNKNOWN, + }, + { + event: {target: {id: null}}, + expected: CommandUtil.SharingActionSourceForUMA.UNKNOWN, + }, + ]; + for (const data of testData) { + const source = CommandUtil.getSharingActionSource(data.event); + assertEquals(data.expected, source); + } +} + +/** + * Checks that we are correctly recording UMA about Share action. + */ +function testReportSharingAction() { + // Setup: create a fake metrics object that can be examined for content. + const enumMap = new Map(); + const countMap = new Map(); + window.metrics = { + recordEnum: (name, value, valid) => { + assertTrue(valid.includes(value)); + record(enumMap, name, value); + }, + recordSmallCount: (name, value) => { + record(countMap, name, value); + }, + }; + const mockFileSystem = new MockFileSystem('volumeId'); + + // Actual tests. + CommandHandler.recordSharingAction( + /** @type {!Event} */ ( + {target: {id: CommandUtil.SharingActionElementId.CONTEXT_MENU}}), + [ + MockFileEntry.create(mockFileSystem, '/test.log'), + MockFileEntry.create(mockFileSystem, '/test.doc'), + MockFileEntry.create(mockFileSystem, '/test.__no_such_extension__'), + ]); + assertArrayEquals( + enumMap.get('Share.ActionSource'), + [CommandUtil.SharingActionSourceForUMA.CONTEXT_MENU]); + assertArrayEquals(countMap.get('Share.FileCount'), [3]); + assertArrayEquals(enumMap.get('Share.FileType'), ['.log', '.doc', 'other']); + + CommandHandler.recordSharingAction( + /** @type {!Event} */ ( + {target: {id: CommandUtil.SharingActionElementId.SHARE_BUTTON}}), + [ + MockFileEntry.create(mockFileSystem, '/test.log'), + ]); + assertArrayEquals(enumMap.get('Share.ActionSource'), [ + CommandUtil.SharingActionSourceForUMA.CONTEXT_MENU, + CommandUtil.SharingActionSourceForUMA.SHARE_BUTTON, + ]); + assertArrayEquals(countMap.get('Share.FileCount'), [3, 1]); + assertArrayEquals( + enumMap.get('Share.FileType'), ['.log', '.doc', 'other', '.log']); +}
diff --git a/ui/file_manager/file_manager/foreground/js/file_tasks.js b/ui/file_manager/file_manager/foreground/js/file_tasks.js index 8c764d15b..4149326 100644 --- a/ui/file_manager/file_manager/foreground/js/file_tasks.js +++ b/ui/file_manager/file_manager/foreground/js/file_tasks.js
@@ -240,6 +240,19 @@ } /** + * Returns ViewFileType enum or 'other' for the given entry. + * @param {!Entry} entry The entry for which ViewFileType is computed. + * @return {string} A ViewFileType enum or 'other'. + */ + static getViewFileType(entry) { + let extension = FileType.getExtension(entry).toLowerCase(); + if (FileTasks.UMA_INDEX_KNOWN_EXTENSIONS.indexOf(extension) < 0) { + extension = 'other'; + } + return extension; + } + + /** * Records trial of opening file grouped by extensions. * * @param {!VolumeManager} volumeManager @@ -248,13 +261,9 @@ */ static recordViewingFileTypeUMA_(volumeManager, entries) { for (let i = 0; i < entries.length; i++) { - const entry = entries[i]; - let extension = FileType.getExtension(entry).toLowerCase(); - if (FileTasks.UMA_INDEX_KNOWN_EXTENSIONS.indexOf(extension) < 0) { - extension = 'other'; - } FileTasks.recordEnumWithOnlineAndOffline_( - volumeManager, 'ViewingFileType', extension, + volumeManager, 'ViewingFileType', + FileTasks.getViewFileType(entries[i]), FileTasks.UMA_INDEX_KNOWN_EXTENSIONS); } } @@ -1215,7 +1224,7 @@ * * The list must also match the FileBrowser ViewFileType entry in enums.xml. * - * @const {Array<string>} + * @const {!Array<string>} */ FileTasks.UMA_INDEX_KNOWN_EXTENSIONS = Object.freeze([ 'other', '.3ga', '.3gp',
diff --git a/ui/file_manager/file_manager/foreground/js/file_tasks_unittest.js b/ui/file_manager/file_manager/foreground/js/file_tasks_unittest.js index cc99b2f..faeea81 100644 --- a/ui/file_manager/file_manager/foreground/js/file_tasks_unittest.js +++ b/ui/file_manager/file_manager/foreground/js/file_tasks_unittest.js
@@ -611,3 +611,21 @@ reportPromise(showImportCrostiniImageDialogIsCalled([mockEntry]), callback); } + +/** + * Checks that the function that returns a file type for file entry handles + * correctly identifies files with known and unknown extensions. + */ +function testGetViewFileType() { + const mockFileSystem = new MockFileSystem('volumeId'); + const testData = [ + {extension: 'log', expected: '.log'}, + {extension: '__unknown_extension__', expected: 'other'}, + ]; + for (const data of testData) { + const mockEntry = + MockFileEntry.create(mockFileSystem, `/report.${data.extension}`); + const type = FileTasks.getViewFileType(mockEntry); + assertEquals(data.expected, type); + } +}
diff --git a/ui/file_manager/file_manager/foreground/js/ui/search_box.js b/ui/file_manager/file_manager/foreground/js/ui/search_box.js index ef22efec..100824a 100644 --- a/ui/file_manager/file_manager/foreground/js/ui/search_box.js +++ b/ui/file_manager/file_manager/foreground/js/ui/search_box.js
@@ -108,7 +108,7 @@ element.parentNode.appendChild(this.autocompleteList); } - /** @private {boolean} */ + /** @return {boolean} */ get collapsed() { return this.searchWrapper.hasAttribute('collapsed'); }
diff --git a/ui/views/focus/focus_manager.cc b/ui/views/focus/focus_manager.cc index 8978d632..6acdf0e 100644 --- a/ui/views/focus/focus_manager.cc +++ b/ui/views/focus/focus_manager.cc
@@ -17,6 +17,7 @@ #include "ui/base/ime/text_input_client.h" #include "ui/events/event.h" #include "ui/events/keycodes/keyboard_codes.h" +#include "ui/views/bubble/bubble_dialog_delegate_view.h" #include "ui/views/focus/focus_manager_delegate.h" #include "ui/views/focus/focus_search.h" #include "ui/views/focus/widget_focus_manager.h" @@ -522,7 +523,14 @@ bool FocusManager::ProcessAccelerator(const ui::Accelerator& accelerator) { if (accelerator_manager_.Process(accelerator)) return true; - return delegate_ && delegate_->ProcessAccelerator(accelerator); + if (delegate_ && delegate_->ProcessAccelerator(accelerator)) + return true; + return RedirectAcceleratorToBubbleAnchorWidget(accelerator); +} + +bool FocusManager::IsAcceleratorRegistered( + const ui::Accelerator& accelerator) const { + return accelerator_manager_.IsRegistered(accelerator); } bool FocusManager::HasPriorityHandler( @@ -591,4 +599,25 @@ SetFocusedView(nullptr); } +bool FocusManager::RedirectAcceleratorToBubbleAnchorWidget( + const ui::Accelerator& accelerator) { + Widget* anchor_widget = GetBubbleAnchorWidget(); + if (!anchor_widget) + return false; + + FocusManager* focus_manager = anchor_widget->GetFocusManager(); + if (!focus_manager->IsAcceleratorRegistered(accelerator)) + return false; + + // The parent view must be focused for it to process events. + focus_manager->SetFocusedView(anchor_widget->GetRootView()); + return focus_manager->ProcessAccelerator(accelerator); +} + +Widget* FocusManager::GetBubbleAnchorWidget() { + BubbleDialogDelegateView* widget_delegate = + widget_->widget_delegate()->AsBubbleDialogDelegate(); + return widget_delegate ? widget_delegate->anchor_widget() : nullptr; +} + } // namespace views
diff --git a/ui/views/focus/focus_manager.h b/ui/views/focus/focus_manager.h index c09ee132..8c7888ae 100644 --- a/ui/views/focus/focus_manager.h +++ b/ui/views/focus/focus_manager.h
@@ -256,6 +256,9 @@ void AddFocusChangeListener(FocusChangeListener* listener); void RemoveFocusChangeListener(FocusChangeListener* listener); + // Whether the given |accelerator| is registered. + bool IsAcceleratorRegistered(const ui::Accelerator& accelerator) const; + // Whether the given |accelerator| has a priority handler associated with it. bool HasPriorityHandler(const ui::Accelerator& accelerator) const; @@ -328,6 +331,14 @@ // ViewObserver: void OnViewIsDeleting(View* view) override; + // Try to redirect the accelerator to bubble's anchor widget to process it if + // the bubble didn't. + bool RedirectAcceleratorToBubbleAnchorWidget( + const ui::Accelerator& accelerator); + + // Returns bubble's anchor widget. + Widget* GetBubbleAnchorWidget(); + // Whether arrow key traversal is enabled globally. static bool arrow_key_traversal_enabled_;
diff --git a/ui/views/focus/focus_manager_unittest.cc b/ui/views/focus/focus_manager_unittest.cc index d7a64896e..b4438b0 100644 --- a/ui/views/focus/focus_manager_unittest.cc +++ b/ui/views/focus/focus_manager_unittest.cc
@@ -54,6 +54,9 @@ SetID(view_id); } + SimpleTestView(const SimpleTestView&) = delete; + SimpleTestView& operator=(const SimpleTestView&) = delete; + void OnFocus() override { event_list_->push_back({ ON_FOCUS, @@ -72,8 +75,6 @@ private: std::vector<FocusTestEvent>* event_list_; - - DISALLOW_COPY_AND_ASSIGN(SimpleTestView); }; // Tests that the appropriate Focus related methods are called when a View @@ -379,6 +380,11 @@ FocusManager* focus_manager) : accelerator_(accelerator), focus_manager_(focus_manager) {} + SelfUnregisteringAcceleratorTarget( + const SelfUnregisteringAcceleratorTarget&) = delete; + SelfUnregisteringAcceleratorTarget& operator=( + const SelfUnregisteringAcceleratorTarget&) = delete; + // ui::TestAcceleratorTarget: bool AcceleratorPressed(const ui::Accelerator& accelerator) override { focus_manager_->UnregisterAccelerator(accelerator, this); @@ -388,8 +394,6 @@ private: ui::Accelerator accelerator_; FocusManager* focus_manager_; - - DISALLOW_COPY_AND_ASSIGN(SelfUnregisteringAcceleratorTarget); }; TEST_F(FocusManagerTest, CallsSelfDeletingAcceleratorTarget) { @@ -438,20 +442,22 @@ : FocusManager(widget, nullptr /* delegate */), dtor_tracker_(dtor_tracker) {} + FocusManagerDtorTracked(const FocusManagerDtorTracked&) = delete; + FocusManagerDtorTracked& operator=(const FocusManagerDtorTracked&) = delete; + ~FocusManagerDtorTracked() override { dtor_tracker_->push_back("FocusManagerDtorTracked"); } DtorTrackVector* dtor_tracker_; - - private: - DISALLOW_COPY_AND_ASSIGN(FocusManagerDtorTracked); }; class TestFocusManagerFactory : public FocusManagerFactory { public: explicit TestFocusManagerFactory(DtorTrackVector* dtor_tracker) : dtor_tracker_(dtor_tracker) {} + TestFocusManagerFactory(const TestFocusManagerFactory&) = delete; + TestFocusManagerFactory& operator=(const TestFocusManagerFactory&) = delete; ~TestFocusManagerFactory() override = default; std::unique_ptr<FocusManager> CreateFocusManager(Widget* widget) override { @@ -460,8 +466,6 @@ private: DtorTrackVector* dtor_tracker_; - - DISALLOW_COPY_AND_ASSIGN(TestFocusManagerFactory); }; class WindowDtorTracked : public Widget { @@ -506,6 +510,11 @@ public: FocusInAboutToRequestFocusFromTabTraversalView() = default; + FocusInAboutToRequestFocusFromTabTraversalView( + const FocusInAboutToRequestFocusFromTabTraversalView&) = delete; + FocusInAboutToRequestFocusFromTabTraversalView& operator=( + const FocusInAboutToRequestFocusFromTabTraversalView&) = delete; + void set_view_to_focus(View* view) { view_to_focus_ = view; } void AboutToRequestFocusFromTabTraversal(bool reverse) override { @@ -514,8 +523,6 @@ private: views::View* view_to_focus_ = nullptr; - - DISALLOW_COPY_AND_ASSIGN(FocusInAboutToRequestFocusFromTabTraversalView); }; } // namespace @@ -643,6 +650,10 @@ public testing::WithParamInterface<bool> { public: FocusManagerArrowKeyTraversalTest() = default; + FocusManagerArrowKeyTraversalTest(const FocusManagerArrowKeyTraversalTest&) = + delete; + FocusManagerArrowKeyTraversalTest& operator=( + const FocusManagerArrowKeyTraversalTest&) = delete; ~FocusManagerArrowKeyTraversalTest() override = default; // FocusManagerTest overrides: @@ -671,8 +682,6 @@ base::test::ScopedRestoreICUDefaultLocale restore_locale_; bool previous_arrow_key_traversal_enabled_ = false; - - DISALLOW_COPY_AND_ASSIGN(FocusManagerArrowKeyTraversalTest); }; // Instantiate the Boolean which is used to toggle RTL in @@ -852,6 +861,9 @@ class AdvanceFocusWidgetDelegate : public WidgetDelegate { public: explicit AdvanceFocusWidgetDelegate(Widget* widget) : widget_(widget) {} + AdvanceFocusWidgetDelegate(const AdvanceFocusWidgetDelegate&) = delete; + AdvanceFocusWidgetDelegate& operator=(const AdvanceFocusWidgetDelegate&) = + delete; ~AdvanceFocusWidgetDelegate() override = default; // WidgetDelegate: @@ -860,8 +872,6 @@ private: Widget* widget_; - - DISALLOW_COPY_AND_ASSIGN(AdvanceFocusWidgetDelegate); }; class TestBubbleDialogDelegateView : public BubbleDialogDelegateView { @@ -870,8 +880,23 @@ : BubbleDialogDelegateView(anchor, BubbleBorder::NONE) { DialogDelegate::SetButtons(ui::DIALOG_BUTTON_NONE); } + TestBubbleDialogDelegateView(const TestBubbleDialogDelegateView&) = delete; + TestBubbleDialogDelegateView& operator=(const TestBubbleDialogDelegateView&) = + delete; ~TestBubbleDialogDelegateView() override = default; + static TestBubbleDialogDelegateView* CreateAndShowBubble(View* anchor) { + TestBubbleDialogDelegateView* bubble = + new TestBubbleDialogDelegateView(anchor); + Widget* bubble_widget = BubbleDialogDelegateView::CreateBubble(bubble); + bubble_widget->SetFocusTraversableParent( + bubble->anchor_widget()->GetFocusTraversable()); + bubble_widget->SetFocusTraversableParentView(anchor); + bubble->set_close_on_deactivate(false); + bubble_widget->Show(); + return bubble; + } + // If this is called, the bubble will be forced to use a NativeWidgetAura. // If not set, it might get a DesktopNativeWidgetAura depending on the // platform and other factors. @@ -890,8 +915,6 @@ private: bool use_native_widget_aura_ = false; - - DISALLOW_COPY_AND_ASSIGN(TestBubbleDialogDelegateView); }; } // namespace @@ -975,21 +998,15 @@ parent3->AddChildView(new View()); BubbleDialogDelegateView* bubble_delegate = - new TestBubbleDialogDelegateView(parent3); - test::WidgetTest::WidgetAutoclosePtr bubble_widget( - BubbleDialogDelegateView::CreateBubble(bubble_delegate)); - bubble_widget->SetFocusTraversableParent( - bubble_delegate->anchor_widget()->GetFocusTraversable()); + TestBubbleDialogDelegateView::CreateAndShowBubble(parent3); + Widget* bubble_widget = bubble_delegate->GetWidget(); - bubble_widget->SetFocusTraversableParentView(parent3); View* child1 = new View(); View* child2 = new View(); child1->SetFocusBehavior(View::FocusBehavior::ALWAYS); child2->SetFocusBehavior(View::FocusBehavior::ALWAYS); bubble_widget->GetRootView()->AddChildView(child1); bubble_widget->GetRootView()->AddChildView(child2); - bubble_delegate->set_close_on_deactivate(false); - bubble_widget->Show(); parent1->RequestFocus(); @@ -1039,20 +1056,15 @@ GetWidget()->GetRootView()->AddChildView(parent4); BubbleDialogDelegateView* bubble_delegate = - new TestBubbleDialogDelegateView(parent_group); - test::WidgetTest::WidgetAutoclosePtr bubble_widget( - BubbleDialogDelegateView::CreateBubble(bubble_delegate)); - bubble_widget->SetFocusTraversableParent( - bubble_delegate->anchor_widget()->GetFocusTraversable()); - bubble_widget->SetFocusTraversableParentView(parent_group); + TestBubbleDialogDelegateView::CreateAndShowBubble(parent3); + Widget* bubble_widget = bubble_delegate->GetWidget(); + View* child1 = new View(); View* child2 = new View(); child1->SetFocusBehavior(View::FocusBehavior::ALWAYS); child2->SetFocusBehavior(View::FocusBehavior::ALWAYS); bubble_widget->GetRootView()->AddChildView(child1); bubble_widget->GetRootView()->AddChildView(child2); - bubble_delegate->set_close_on_deactivate(false); - bubble_widget->Show(); parent1->RequestFocus(); @@ -1088,14 +1100,8 @@ View* anchor = pane->AddChildView(std::make_unique<View>()); anchor->SetFocusBehavior(View::FocusBehavior::ALWAYS); - BubbleDialogDelegateView* bubble = new TestBubbleDialogDelegateView(anchor); - test::WidgetTest::WidgetAutoclosePtr bubble_widget( - BubbleDialogDelegateView::CreateBubble(bubble)); - bubble_widget->SetFocusTraversableParent( - bubble->anchor_widget()->GetFocusTraversable()); - bubble_widget->SetFocusTraversableParentView(anchor); - bubble->set_close_on_deactivate(false); - bubble_widget->Show(); + BubbleDialogDelegateView* bubble = + TestBubbleDialogDelegateView::CreateAndShowBubble(anchor); // We need a focusable view inside our bubble to check that focus traverses // in. @@ -1118,6 +1124,9 @@ class DesktopWidgetFocusManagerTest : public FocusManagerTest { public: DesktopWidgetFocusManagerTest() = default; + DesktopWidgetFocusManagerTest(const DesktopWidgetFocusManagerTest&) = delete; + DesktopWidgetFocusManagerTest& operator=( + const DesktopWidgetFocusManagerTest&) = delete; ~DesktopWidgetFocusManagerTest() override = default; // FocusManagerTest: @@ -1125,9 +1134,6 @@ set_native_widget_type(NativeWidgetType::kDesktop); FocusManagerTest::SetUp(); } - - private: - DISALLOW_COPY_AND_ASSIGN(DesktopWidgetFocusManagerTest); }; TEST_F(DesktopWidgetFocusManagerTest, AnchoredDialogInDesktopNativeWidgetAura) { @@ -1149,18 +1155,13 @@ widget.GetRootView()->AddChildView(parent2); TestBubbleDialogDelegateView* bubble_delegate = - new TestBubbleDialogDelegateView(parent2); + TestBubbleDialogDelegateView::CreateAndShowBubble(parent2); + Widget* bubble_widget = bubble_delegate->GetWidget(); bubble_delegate->UseNativeWidgetAura(); - test::WidgetTest::WidgetAutoclosePtr bubble_widget( - BubbleDialogDelegateView::CreateBubble(bubble_delegate)); - bubble_widget->SetFocusTraversableParent( - bubble_delegate->anchor_widget()->GetFocusTraversable()); - bubble_widget->SetFocusTraversableParentView(parent2); + View* child = new View(); child->SetFocusBehavior(View::FocusBehavior::ALWAYS); bubble_widget->GetRootView()->AddChildView(child); - bubble_delegate->set_close_on_deactivate(false); - bubble_widget->Show(); widget.Activate(); parent1->RequestFocus(); @@ -1225,4 +1226,83 @@ EXPECT_FALSE(left->HasFocus()); } +#if defined(USE_AURA) +class RedirectToParentFocusManagerTest : public FocusManagerTest { + public: + RedirectToParentFocusManagerTest() = default; + RedirectToParentFocusManagerTest(const RedirectToParentFocusManagerTest&) = + delete; + RedirectToParentFocusManagerTest& operator=( + const RedirectToParentFocusManagerTest&) = delete; + ~RedirectToParentFocusManagerTest() override = default; + + // FocusManagerTest: + void SetUp() override { + FocusManagerTest::SetUp(); + + View* anchor = + GetWidget()->GetRootView()->AddChildView(std::make_unique<View>()); + anchor->SetFocusBehavior(View::FocusBehavior::ALWAYS); + + BubbleDialogDelegateView* bubble_delegate = + TestBubbleDialogDelegateView::CreateAndShowBubble(anchor); + Widget* bubble_widget = bubble_delegate->GetWidget(); + + parent_focus_manager_ = anchor->GetFocusManager(); + bubble_focus_manager_ = bubble_widget->GetFocusManager(); + } + + void TearDown() override { + FocusManagerFactory::Install(nullptr); + FocusManagerTest::TearDown(); + } + + protected: + FocusManager* parent_focus_manager_; + FocusManager* bubble_focus_manager_; +}; + +// Test that when an accelerator is sent to a bubble that isn't registered, +// the bubble's parent handles it instead. +TEST_F(RedirectToParentFocusManagerTest, ParentHandlesAcceleratorFromBubble) { + ui::Accelerator return_accelerator(ui::VKEY_RETURN, ui::EF_NONE); + ui::TestAcceleratorTarget parent_return_target(true); + + EXPECT_EQ(0, parent_return_target.accelerator_count()); + parent_focus_manager_->RegisterAccelerator( + return_accelerator, ui::AcceleratorManager::kNormalPriority, + &parent_return_target); + + EXPECT_TRUE( + !bubble_focus_manager_->IsAcceleratorRegistered(return_accelerator)); + // Accelerator was proccesed by the parent. + EXPECT_TRUE(bubble_focus_manager_->ProcessAccelerator(return_accelerator)); + EXPECT_EQ(parent_return_target.accelerator_count(), 1); +} + +// Test that when an accelerator is sent to a bubble that is registered on both +// it and its parent, the bubble handles it. +TEST_F(RedirectToParentFocusManagerTest, BubbleHandlesRegisteredAccelerators) { + ui::Accelerator return_accelerator(ui::VKEY_RETURN, ui::EF_NONE); + ui::TestAcceleratorTarget parent_return_target(true); + ui::TestAcceleratorTarget bubble_return_target(true); + + EXPECT_EQ(0, bubble_return_target.accelerator_count()); + EXPECT_EQ(0, parent_return_target.accelerator_count()); + + bubble_focus_manager_->RegisterAccelerator( + return_accelerator, ui::AcceleratorManager::kNormalPriority, + &bubble_return_target); + parent_focus_manager_->RegisterAccelerator( + return_accelerator, ui::AcceleratorManager::kNormalPriority, + &parent_return_target); + + // Accelerator was proccesed by the bubble and not by the parent. + EXPECT_TRUE(bubble_focus_manager_->ProcessAccelerator(return_accelerator)); + EXPECT_EQ(1, bubble_return_target.accelerator_count()); + EXPECT_EQ(0, parent_return_target.accelerator_count()); +} + +#endif + } // namespace views
diff --git a/ui/webui/webui_allowlist.cc b/ui/webui/webui_allowlist.cc index 2232b83..62b5ca6 100644 --- a/ui/webui/webui_allowlist.cc +++ b/ui/webui/webui_allowlist.cc
@@ -62,12 +62,20 @@ void WebUIAllowlist::RegisterAutoGrantedPermission(const url::Origin& origin, ContentSettingsType type, ContentSetting setting) { + // It doesn't make sense to grant a default content setting. + DCHECK_NE(CONTENT_SETTING_DEFAULT, setting); + // We only support auto-granting permissions to chrome://, // chrome-untrusted://, and devtools:// schemes. DCHECK(origin.scheme() == content::kChromeUIScheme || origin.scheme() == content::kChromeUIUntrustedScheme || origin.scheme() == content::kChromeDevToolsScheme); + // If the same permission is already registered, do nothing. We don't want to + // notify the provider of ContentSettingChange when it is unnecessary. + if (permissions_[type][origin] == setting) + return; + permissions_[type][origin] = setting; // Notify the provider. |provider_| can be nullptr if
diff --git a/url/url_canon_fileurl.cc b/url/url_canon_fileurl.cc index 6277289..067ed58 100644 --- a/url/url_canon_fileurl.cc +++ b/url/url_canon_fileurl.cc
@@ -76,8 +76,8 @@ Component sub_path = MakeRange(after_drive, path.end()); Component fake_output_path; success = CanonicalizePath(spec, sub_path, output, &fake_output_path); - } else { - // No input path, canonicalize to a slash. + } else if (after_drive == path.begin) { + // No input path and no drive spec, canonicalize to a slash. output->push_back('/'); }
diff --git a/url/url_canon_unittest.cc b/url/url_canon_unittest.cc index b1b6dfd..87fb406 100644 --- a/url/url_canon_unittest.cc +++ b/url/url_canon_unittest.cc
@@ -1517,6 +1517,10 @@ {"file:///C:/gaba?query#ref", NULL, NULL, NULL, "filer", NULL, "/foo", "b", "c", "file://filer/foo?b#c"}, // Replace nothing {"file:///C:/gaba?query#ref", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "file:///C:/gaba?query#ref"}, + {"file:///Y:", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "file:///Y:"}, + {"file:///Y:/", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "file:///Y:/"}, + {"file:///./Y", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "file:///Y"}, + {"file:///./Y:", NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "file:///Y:"}, // Clear non-path components (common) {"file:///C:/gaba?query#ref", NULL, NULL, NULL, NULL, NULL, NULL, kDeleteComp, kDeleteComp, "file:///C:/gaba"}, // Replace path with something that doesn't begin with a slash and make @@ -1532,6 +1536,7 @@ for (size_t i = 0; i < base::size(replace_cases); i++) { const ReplaceCase& cur = replace_cases[i]; + SCOPED_TRACE(cur.base); int base_len = static_cast<int>(strlen(cur.base)); Parsed parsed; ParseFileURL(cur.base, base_len, &parsed);
diff --git a/weblayer/browser/android/javatests/skew/expectations.txt b/weblayer/browser/android/javatests/skew/expectations.txt index 0b3c487..6f1c3db 100644 --- a/weblayer/browser/android/javatests/skew/expectations.txt +++ b/weblayer/browser/android/javatests/skew/expectations.txt
@@ -45,9 +45,10 @@ # https://crbug.com/1079491. [ impl_lte_83 ] org.chromium.weblayer.test.NavigationTest#testSetUserAgentString [ Skip ] +# Implemented in https://crrev.com/0193f6791133ee7a90d034aa4009 +[ impl_lte_81 ] org.chromium.weblayer.test.TabTest#testBeforeUnload [ Skip ] + # Many M81 tests are broken, see https://crbug.com/1081102. -[ impl_lte_81 ] org.chromium.weblayer.test.BottomControlsTest#testBasic [ Skip ] -[ impl_lte_81 ] org.chromium.weblayer.test.BottomControlsTest#testNoTopControl [ Skip ] [ impl_lte_81 ] org.chromium.weblayer.test.BrowserFragmentLifecycleTest#restoreAfterRecreate [ Skip ] [ impl_lte_81 ] org.chromium.weblayer.test.BrowserFragmentLifecycleTest#restoreTabGuidAfterRecreate [ Skip ] [ impl_lte_81 ] org.chromium.weblayer.test.BrowserFragmentLifecycleTest#restoresTabGuid [ Skip ] @@ -68,14 +69,12 @@ [ impl_lte_81 ] org.chromium.weblayer.test.ExternalNavigationTest#testExternalIntentInSameTabLaunchedOnLinkClick [ Skip ] [ impl_lte_81 ] org.chromium.weblayer.test.ExternalNavigationTest#testExternalIntentWithFallbackUrlAfterRedirectLaunched [ Skip ] [ impl_lte_81 ] org.chromium.weblayer.test.ExternalNavigationTest#testNonHandledExternalIntentWithFallbackUrlAfterRedirectGoesToFallbackUrl [ Skip ] -[ impl_lte_81 ] org.chromium.weblayer.test.FindInPageTest#testHideOnNavigate [ Skip ] [ impl_lte_81 ] org.chromium.weblayer.test.InputTypesTest#testColorInput [ Skip ] [ impl_lte_81 ] org.chromium.weblayer.test.NavigationTest#testRepostConfirmation [ Skip ] [ impl_lte_81 ] org.chromium.weblayer.test.NavigationTest#testSetRequestHeaderInRedirect [ Skip ] [ impl_lte_81 ] org.chromium.weblayer.test.NavigationTest#testSetRequestHeaderInStart [ Skip ] [ impl_lte_81 ] org.chromium.weblayer.test.NavigationTest#testSetRequestHeaderThrowsExceptionInCompleted [ Skip ] [ impl_lte_81 ] org.chromium.weblayer.test.NavigationTest#testSetRequestHeaderThrowsExceptionWithInvalidValue [ Skip ] -[ impl_lte_81 ] org.chromium.weblayer.test.NavigationTest#testSetUserAgentString [ Skip ] [ impl_lte_81 ] org.chromium.weblayer.test.NavigationTest#testStopFromOnNavigationStarted [ Skip ] [ impl_lte_81 ] org.chromium.weblayer.test.ProfileTest#testDestroyAndDeleteDataFromDisk [ Skip ] [ impl_lte_81 ] org.chromium.weblayer.test.ProfileTest#testDestroyAndDeleteDataFromDiskIncognito [ Skip ] @@ -87,13 +86,12 @@ [ impl_lte_81 ] org.chromium.weblayer.test.TabCallbackTest#testShowContextMenuImg [ Skip ] [ impl_lte_81 ] org.chromium.weblayer.test.TabCallbackTest#testTabModalOverlay [ Skip ] [ impl_lte_81 ] org.chromium.weblayer.test.TabCallbackTest#testTabModalOverlayOnBackgroundTab [ Skip ] -[ impl_lte_81 ] org.chromium.weblayer.test.TabTest#testBeforeUnload [ Skip ] # ------------------------------------- # Tests against older WebLayer clients. # ------------------------------------- -# https://crbug.com/1078973. +# Intentionally changed in M84, https://crrev.com/c/2130790. See https://crbug.com/1078973. [ client_lte_83 ] org.chromium.weblayer.test.ExternalNavigationTest#testExternalIntentLaunchedViaOnLoad [ Skip ] [ client_lte_83 ] org.chromium.weblayer.test.ExternalNavigationTest#testNonHandledExternalIntentWithFallbackUrlThatLaunchesIntentAfterRedirectLaunchesFallbackIntent [ Skip ]
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/ExternalNavigationDelegateImpl.java b/weblayer/browser/java/org/chromium/weblayer_private/ExternalNavigationDelegateImpl.java index 31dbfd3..4f776eff 100644 --- a/weblayer/browser/java/org/chromium/weblayer_private/ExternalNavigationDelegateImpl.java +++ b/weblayer/browser/java/org/chromium/weblayer_private/ExternalNavigationDelegateImpl.java
@@ -5,7 +5,6 @@ package org.chromium.weblayer_private; import android.app.Activity; -import android.content.Context; import android.content.Intent; import org.chromium.base.ContextUtils; @@ -26,6 +25,7 @@ private boolean mTabDestroyed; public ExternalNavigationDelegateImpl(TabImpl tab) { + assert tab != null; mTab = tab; } @@ -38,10 +38,6 @@ return ContextUtils.activityFromContext(mTab.getBrowser().getContext()); } - private Context getAvailableContext() { - return ExternalNavigationHandler.getAvailableContext(this); - } - @Override public boolean willChromeHandleIntent(Intent intent) { return false; @@ -163,13 +159,11 @@ @Override public WindowAndroid getWindowAndroid() { - if (mTab == null) return null; return mTab.getBrowser().getWindowAndroid(); } @Override public WebContents getWebContents() { - if (mTab == null) return null; return mTab.getWebContents(); }
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/WebLayerImpl.java b/weblayer/browser/java/org/chromium/weblayer_private/WebLayerImpl.java index 10c193d..b17e3ab 100644 --- a/weblayer/browser/java/org/chromium/weblayer_private/WebLayerImpl.java +++ b/weblayer/browser/java/org/chromium/weblayer_private/WebLayerImpl.java
@@ -40,6 +40,7 @@ import org.chromium.base.library_loader.LibraryLoader; import org.chromium.base.library_loader.LibraryProcessType; import org.chromium.components.embedder_support.application.ClassLoaderContextWrapperFactory; +import org.chromium.components.embedder_support.application.FirebaseConfig; import org.chromium.content_public.browser.BrowserStartupController; import org.chromium.content_public.browser.ChildProcessCreationParams; import org.chromium.content_public.browser.DeviceUtils; @@ -214,6 +215,8 @@ } BuildInfo.setBrowserPackageInfo(packageInfo); + BuildInfo.setFirebaseAppId( + FirebaseConfig.getFirebaseAppIdForPackage(packageInfo.packageName)); // TODO: The call to onResourcesLoaded() can be slow, we may need to parallelize this with // other expensive startup tasks. R.onResourcesLoaded(forceCorrectPackageId(remoteContext));