diff --git a/AUTHORS b/AUTHORS index a2a305f2..6ef7b10 100644 --- a/AUTHORS +++ b/AUTHORS
@@ -262,6 +262,7 @@ Dillon Sellars <dill.sellars@gmail.com> Divya Bansal <divya.bansal@samsung.com> Dmitry Shachnev <mitya57@gmail.com> +Dmitry Sokolov <dimanne@gmail.com> Dominic Farolino <domfarolino@gmail.com> Dominic Jodoin <dominic.jodoin@gmail.com> Dominik Röttsches <dominik.rottsches@intel.com>
diff --git a/DEPS b/DEPS index fea6c6f..e7fc0abb 100644 --- a/DEPS +++ b/DEPS
@@ -195,11 +195,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': 'e96cdd18ac5ff04774b55775bf66f1f3ccbe4d62', + 'skia_revision': '842805ced156080fd25bfbb6410851dbe6a8b447', # 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': '95c0414b1889f2d761e26024a8a040d647f81854', + 'v8_revision': 'fa4bfe45ff53e2c21b96728ef9132c40969b3159', # 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. @@ -207,11 +207,11 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ANGLE # and whatever else without interference from each other. - 'angle_revision': '2663e6012911a3dc3e978a41f7c52d5c12c48c69', + 'angle_revision': 'dbb090f41f9b9017a88ba0ae44a09bdebd4b9dda', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling SwiftShader # and whatever else without interference from each other. - 'swiftshader_revision': '44be0942f9a8b965f877f294f1c2d8fb15f88ec6', + 'swiftshader_revision': '1075baee443cbfd02714d7d3793d194fd227d476', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling PDFium # and whatever else without interference from each other. @@ -258,7 +258,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': '18d69fb4e7b2225974dfc306ca0c11a58fe4e917', + 'catapult_revision': '0f6ed710764d9858eb9d2ad2a2f92fde89d1634b', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # and whatever else without interference from each other. @@ -266,7 +266,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': '0d33d0e062db344a70d991abee0e4163d5c66137', + 'devtools_frontend_revision': '5c1904772b3655454d1da01210b83e6fa5fbceb2', # 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. @@ -302,7 +302,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. - 'spv_tools_revision': '4b07d50cd9a0a537ccb28252227f87d36273cf53', + 'spv_tools_revision': 'c6ca885c0b4af75735944c725be56b642a77b17d', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. @@ -318,7 +318,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. - 'dawn_revision': '62139fcca727c3592b65be32c0146ca1a3a195cc', + 'dawn_revision': 'b2a4e87ad27403bcb0113406ba935477baae4a8c', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. @@ -901,7 +901,7 @@ }, 'src/third_party/depot_tools': - Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'ead81e2ba233835d7feb4dd6158014a1c3962ecb', + Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '991ead187c148de57990cbeecb9ad35767987a7c', 'src/third_party/devtools-frontend/src': Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'), @@ -1254,7 +1254,7 @@ }, 'src/third_party/perfetto': - Var('android_git') + '/platform/external/perfetto.git' + '@' + '88c194fccd3bfdcff22b4dfd0987230a433b5e96', + Var('android_git') + '/platform/external/perfetto.git' + '@' + '76404b01d5314c251218a4a34111a1aa8a3803ad', 'src/third_party/perl': { 'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3', @@ -1332,7 +1332,7 @@ 'packages': [ { 'package': 'fuchsia/third_party/aemu/linux-amd64', - 'version': 'FfxmX7LQ9OID3pVAmcemr6u9lK3xjXzAXxvqzEcclMwC' + 'version': 'oJeWXQJJ1lVY6P7l39pBV-mrbeWlw0swPZQuNmcix5AC' }, ], 'condition': 'host_os == "linux" and checkout_fuchsia',
diff --git a/android_webview/browser/aw_content_browser_client.cc b/android_webview/browser/aw_content_browser_client.cc index 2a6c7ac..d5e7790 100644 --- a/android_webview/browser/aw_content_browser_client.cc +++ b/android_webview/browser/aw_content_browser_client.cc
@@ -420,6 +420,11 @@ ::switches::kEnableCrashReporterForTesting)) { command_line->AppendSwitch(::switches::kEnableCrashReporterForTesting); } + // Pass WebView's force little cores flag to renderer process. + if (base::CommandLine::ForCurrentProcess()->HasSwitch( + ::switches::kWebViewForceLittleCores)) { + command_line->AppendSwitch(::switches::kWebViewForceLittleCores); + } } }
diff --git a/android_webview/common/aw_switches.cc b/android_webview/common/aw_switches.cc index 8372ebc3..1436c2d 100644 --- a/android_webview/common/aw_switches.cc +++ b/android_webview/common/aw_switches.cc
@@ -49,4 +49,7 @@ // variations seed. const char kFinchSeedMinUpdatePeriod[] = "finch-seed-min-update-period"; +// Force WebView renderer to run in little cores +const char kWebViewForceLittleCores[] = "webview-force-little-cores"; + } // namespace switches
diff --git a/android_webview/common/aw_switches.h b/android_webview/common/aw_switches.h index c883e89..c639426 100644 --- a/android_webview/common/aw_switches.h +++ b/android_webview/common/aw_switches.h
@@ -18,6 +18,7 @@ extern const char kFinchSeedIgnorePendingDownload[]; extern const char kFinchSeedMinDownloadPeriod[]; extern const char kFinchSeedMinUpdatePeriod[]; +extern const char kWebViewForceLittleCores[]; } // namespace switches
diff --git a/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java b/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java index c27c16ec..1395555 100644 --- a/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java +++ b/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java
@@ -88,5 +88,7 @@ + "Elements v0, and HTML Imports)."), Flag.baseFeature(AwFeatures.WEBVIEW_DISPLAY_CUTOUT, "Enables display cutout (notch) support in WebView for Android P and above."), + Flag.commandLine(AwSwitches.WEBVIEW_FORCE_LITTLE_CORES, + "Forces WebView to do rendering work in little cores"), }; }
diff --git a/android_webview/lib/aw_main_delegate.cc b/android_webview/lib/aw_main_delegate.cc index 6007355..e4e5262a 100644 --- a/android_webview/lib/aw_main_delegate.cc +++ b/android_webview/lib/aw_main_delegate.cc
@@ -28,6 +28,7 @@ #include "base/check_op.h" #include "base/command_line.h" #include "base/cpu.h" +#include "base/cpu_affinity_posix.h" #include "base/i18n/icu_util.h" #include "base/i18n/rtl.h" #include "base/posix/global_descriptors.h" @@ -298,6 +299,10 @@ if (process_type == switches::kRendererProcess) { InitResourceBundleRendererSide(); + if (command_line.HasSwitch(switches::kWebViewForceLittleCores)) { + base::SetProcessCpuAffinityMode(base::GetCurrentProcessHandle(), + base::CpuAffinityMode::kLittleCoresOnly); + } } EnableCrashReporter(process_type);
diff --git a/ash/public/cpp/external_arc/message_center/arc_notification_content_view.cc b/ash/public/cpp/external_arc/message_center/arc_notification_content_view.cc index 134f978..0f3b83c 100644 --- a/ash/public/cpp/external_arc/message_center/arc_notification_content_view.cc +++ b/ash/public/cpp/external_arc/message_center/arc_notification_content_view.cc
@@ -249,7 +249,7 @@ control_buttons_view_(message_view) { DCHECK(message_view); - // kNotificationWidth must be 360, since this value is separately defiend in + // kNotificationWidth must be 360, since this value is separately defined in // ArcNotificationWrapperView class in Android side. DCHECK_EQ(360, message_center::kNotificationWidth); @@ -348,7 +348,7 @@ return; // Add the guard to prevent an infinite loop. Changing visibility may generate - // an event and it may call thie method again. + // an event and it may call this method again. base::AutoReset<bool> reset(&updating_control_buttons_visibility_, true); if (target_visibility) @@ -559,7 +559,8 @@ auto mask_painter = std::make_unique<message_center::NotificationBackgroundPainter>( - top_radius_, bottom_radius_); + top_radius_, bottom_radius_, + message_center::kNotificationBackgroundColor); // Set insets to round visible notification corners. https://crbug.com/866777 mask_painter->set_insets(new_insets);
diff --git a/ash/public/cpp/external_arc/message_center/arc_notification_content_view_unittest.cc b/ash/public/cpp/external_arc/message_center/arc_notification_content_view_unittest.cc index da7bd1fd..891584e 100644 --- a/ash/public/cpp/external_arc/message_center/arc_notification_content_view_unittest.cc +++ b/ash/public/cpp/external_arc/message_center/arc_notification_content_view_unittest.cc
@@ -29,6 +29,7 @@ #include "components/exo/buffer.h" #include "components/exo/keyboard.h" #include "components/exo/keyboard_delegate.h" +#include "components/exo/keyboard_modifiers.h" #include "components/exo/notification_surface.h" #include "components/exo/seat.h" #include "components/exo/surface.h" @@ -40,6 +41,7 @@ #include "ui/aura/window.h" #include "ui/events/keycodes/dom/dom_code.h" #include "ui/events/test/event_generator.h" +#include "ui/message_center/public/cpp/message_center_constants.h" #include "ui/message_center/public/cpp/notification.h" #include "ui/message_center/views/message_view_factory.h" #include "ui/message_center/views/notification_control_buttons_view.h" @@ -75,15 +77,15 @@ OnKeyboardKey, (base::TimeTicks, ui::DomCode, bool), (override)); - MOCK_METHOD(void, OnKeyboardModifiers, (int), (override)); + MOCK_METHOD(void, + OnKeyboardModifiers, + (const exo::KeyboardModifiers&), + (override)); MOCK_METHOD(void, OnKeyRepeatSettingsChanged, (bool, base::TimeDelta, base::TimeDelta), (override)); - MOCK_METHOD(void, - OnKeyboardLayoutUpdated, - (const std::string& layout_name), - (override)); + MOCK_METHOD(void, OnKeyboardLayoutUpdated, (base::StringPiece), (override)); }; class FakeNotificationSurface : public exo::NotificationSurface {
diff --git a/build/protoc_java.py b/build/protoc_java.py index e6147d8b..fe602a9 100755 --- a/build/protoc_java.py +++ b/build/protoc_java.py
@@ -5,7 +5,7 @@ """Generate java source files from protobuf files. -This is a helper file for the genproto_java action in protoc_java.gypi. +This is the action script for the proto_java_library template. It performs the following steps: 1. Deletes all old sources (ensures deleted classes are not part of new jars). @@ -17,51 +17,63 @@ from __future__ import print_function +import argparse import os -import optparse import shutil import subprocess import sys -sys.path.append(os.path.join(os.path.dirname(__file__), "android", "gyp")) +sys.path.append(os.path.join(os.path.dirname(__file__), 'android', 'gyp')) from util import build_utils + +def _HasJavaPackage(proto_lines): + return any(line.strip().startswith('option java_package') + for line in proto_lines) + + +def _EnforceJavaPackage(proto_srcs): + for proto_path in proto_srcs: + with open(proto_path) as in_proto: + if not _HasJavaPackage(in_proto.readlines()): + raise Exception('Proto files for java must contain a "java_package" ' + 'line: {}'.format(proto_path)) + + def main(argv): - parser = optparse.OptionParser() + parser = argparse.ArgumentParser() build_utils.AddDepfileOption(parser) - parser.add_option("--protoc", help="Path to protoc binary.") - parser.add_option("--proto-path", help="Path to proto directory.") - parser.add_option("--java-out-dir", - help="Path to output directory for java files.") - parser.add_option("--srcjar", help="Path to output srcjar.") - parser.add_option("--stamp", help="File to touch on success.") - parser.add_option("--nano", - help="Use to generate nano protos.", action='store_true') - parser.add_option("--import-dir", action="append", default=[], - help="Extra import directory for protos, can be repeated.") - options, args = parser.parse_args(argv) + parser.add_argument('--protoc', required=True, help='Path to protoc binary.') + parser.add_argument('--proto-path', + required=True, + help='Path to proto directory.') + parser.add_argument('--java-out-dir', + help='Path to output directory for java files.') + parser.add_argument('--srcjar', help='Path to output srcjar.') + parser.add_argument('--stamp', help='File to touch on success.') + parser.add_argument( + '--import-dir', + action='append', + default=[], + help='Extra import directory for protos, can be repeated.') + parser.add_argument('protos', nargs='+', help='proto source files') + options = parser.parse_args(argv) - build_utils.CheckOptions(options, parser, ['protoc', 'proto_path']) if not options.java_out_dir and not options.srcjar: - print('One of --java-out-dir or --srcjar must be specified.') - return 1 + raise Exception('One of --java-out-dir or --srcjar must be specified.') - proto_path_args = ['--proto_path', options.proto_path] - for path in options.import_dir: - proto_path_args += ["--proto_path", path] + _EnforceJavaPackage(options.protos) with build_utils.TempDir() as temp_dir: - if options.nano: - # Specify arguments to the generator. - generator_args = ['optional_field_style=reftypes', - 'store_unknown_fields=true'] - out_arg = '--javanano_out=' + ','.join(generator_args) + ':' + temp_dir - else: - out_arg = '--java_out=lite:' + temp_dir + out_arg = '--java_out=lite:' + temp_dir + + proto_path_args = ['--proto_path', options.proto_path] + for path in options.import_dir: + proto_path_args += ["--proto_path", path] # Generate Java files using protoc. build_utils.CheckOutput( - [options.protoc] + proto_path_args + [out_arg] + args, + [options.protoc] + proto_path_args + [out_arg] + options.protos, # protoc generates superfluous warnings about LITE_RUNTIME deprecation # even though we are using the new non-deprecated method. stderr_filter=lambda output: build_utils.FilterLines( @@ -76,7 +88,7 @@ if options.depfile: assert options.srcjar - deps = args + [options.protoc] + deps = options.protos + [options.protoc] build_utils.WriteDepfile(options.depfile, options.srcjar, deps) if options.stamp:
diff --git a/chrome/android/chrome_java_resources.gni b/chrome/android/chrome_java_resources.gni index 369a6e4..ee42e6f 100644 --- a/chrome/android/chrome_java_resources.gni +++ b/chrome/android/chrome_java_resources.gni
@@ -709,6 +709,7 @@ "java/res/drawable/ic_signal_cellular_2_bar.xml", "java/res/drawable/ic_signal_cellular_3_bar.xml", "java/res/drawable/ic_signal_cellular_4_bar.xml", + "java/res/drawable/ic_signout_40dp.xml", "java/res/drawable/ic_site_timer.xml", "java/res/drawable/ic_swap_vert_round.xml", "java/res/drawable/ic_sync_badge_error_20dp.xml",
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantBottomBarCoordinator.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantBottomBarCoordinator.java index ef0672e..d22bd23 100644 --- a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantBottomBarCoordinator.java +++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantBottomBarCoordinator.java
@@ -37,6 +37,7 @@ import org.chromium.components.browser_ui.bottomsheet.BottomSheetContent; import org.chromium.components.browser_ui.bottomsheet.BottomSheetController; import org.chromium.components.browser_ui.bottomsheet.BottomSheetController.SheetState; +import org.chromium.components.browser_ui.bottomsheet.BottomSheetController.StateChangeReason; import org.chromium.components.browser_ui.bottomsheet.BottomSheetObserver; import org.chromium.components.browser_ui.bottomsheet.EmptyBottomSheetObserver; import org.chromium.content_public.browser.UiThreadTaskTraits; @@ -204,13 +205,6 @@ if (newState != BottomSheetController.SheetState.SCROLLING) { maybeShowHeaderChips(); } - - if (newState == BottomSheetController.SheetState.HIDDEN) { - AssistantBottomBarDelegate delegate = mModel.getBottomBarDelegate(); - if (delegate != null) { - delegate.onBottomSheetDismissed(); - } - } } @Override @@ -224,6 +218,14 @@ public void onSheetOffsetChanged(float heightFraction, float offsetPx) { updateVisualViewportHeight(); } + + @Override + public void onSheetClosed(@StateChangeReason int reason) { + AssistantBottomBarDelegate delegate = mModel.getBottomBarDelegate(); + if (reason == StateChangeReason.SWIPE && delegate != null) { + delegate.onBottomSheetClosedWithSwipe(); + } + } }; controller.addObserver(mBottomSheetObserver);
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantBottomBarDelegate.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantBottomBarDelegate.java index 6fb9de1..1486979 100644 --- a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantBottomBarDelegate.java +++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantBottomBarDelegate.java
@@ -13,6 +13,9 @@ // the new bottom sheet state and have the logic to shutdown there. Currently, this would be // tricky to do because it would interfere with the existing Controller::SetBottomSheetState // method and in particular tab switching. - /** The bottom sheet was dismissed. */ - void onBottomSheetDismissed(); + /** + * The bottom sheet was closed with a swipe gesture. Note that this will be fired both when + * going into the PEEK state as well as when dismissing the sheet altogether. + */ + void onBottomSheetClosedWithSwipe(); }
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantBottomBarNativeDelegate.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantBottomBarNativeDelegate.java index 3109e2c..6c75215c 100644 --- a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantBottomBarNativeDelegate.java +++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantBottomBarNativeDelegate.java
@@ -32,9 +32,9 @@ } @Override - public void onBottomSheetDismissed() { + public void onBottomSheetClosedWithSwipe() { if (mNativeAssistantBottomBarDelegate != 0) { - AssistantBottomBarNativeDelegateJni.get().onBottomSheetDismissed( + AssistantBottomBarNativeDelegateJni.get().onBottomSheetClosedWithSwipe( mNativeAssistantBottomBarDelegate, AssistantBottomBarNativeDelegate.this); } } @@ -48,7 +48,7 @@ interface Natives { boolean onBackButtonClicked( long nativeAssistantBottomBarDelegate, AssistantBottomBarNativeDelegate caller); - void onBottomSheetDismissed( + void onBottomSheetClosedWithSwipe( long nativeAssistantBottomBarDelegate, AssistantBottomBarNativeDelegate caller); } }
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantOnboardingCoordinator.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantOnboardingCoordinator.java index dbb66da..5c37989 100644 --- a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantOnboardingCoordinator.java +++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AssistantOnboardingCoordinator.java
@@ -111,7 +111,7 @@ } @Override - public void onBottomSheetDismissed() {} + public void onBottomSheetClosedWithSwipe() {} }); initContent(callback); BottomSheetUtils.showContentAndMaybeExpand(
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiController.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiController.java index 78ad982..4619e8d 100644 --- a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiController.java +++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiController.java
@@ -166,7 +166,8 @@ dismissSnackbar(); if (tab == null) { - safeOnTabSwitched(getModel().getBottomSheetState()); + safeOnTabSwitched(getModel().getBottomSheetState(), + /* activityChanged = */ false); // A null tab indicates that there's no selected tab; Most likely, we're // in the process of selecting a new tab. Hide the UI for possible reuse // later. @@ -183,7 +184,8 @@ } } else { // - safeOnTabSwitched(getModel().getBottomSheetState()); + safeOnTabSwitched(getModel().getBottomSheetState(), + /* activityChanged = */ false); // A new tab was selected. If Autofill Assistant is running on it, // attach the UI to that other instance, otherwise destroy the UI. AutofillAssistantClient.fromWebContents(mWebContents) @@ -205,7 +207,8 @@ return; } - safeOnTabSwitched(getModel().getBottomSheetState()); + safeOnTabSwitched( + getModel().getBottomSheetState(), /* activityChanged = */ true); // If we have an open snackbar, execute the callback immediately. This // may shut down the Autofill Assistant. if (mSnackbarController != null) { @@ -481,10 +484,10 @@ } } - private void safeOnTabSwitched(@SheetState int state) { + private void safeOnTabSwitched(@SheetState int state, boolean activityChanged) { if (mNativeUiController != 0) { - AutofillAssistantUiControllerJni.get().onTabSwitched( - mNativeUiController, AutofillAssistantUiController.this, state); + AutofillAssistantUiControllerJni.get().onTabSwitched(mNativeUiController, + AutofillAssistantUiController.this, state, activityChanged); } } @@ -514,7 +517,7 @@ void setVisible(long nativeUiControllerAndroid, AutofillAssistantUiController caller, boolean visible); void onTabSwitched(long nativeUiControllerAndroid, AutofillAssistantUiController caller, - @SheetState int state); + @SheetState int state, boolean activityChanged); void onTabSelected(long nativeUiControllerAndroid, AutofillAssistantUiController caller); } }
diff --git a/chrome/android/features/start_surface/public/java/src/org/chromium/chrome/features/start_surface/StartSurfaceConfiguration.java b/chrome/android/features/start_surface/public/java/src/org/chromium/chrome/features/start_surface/StartSurfaceConfiguration.java index 4089881f..e38652f2 100644 --- a/chrome/android/features/start_surface/public/java/src/org/chromium/chrome/features/start_surface/StartSurfaceConfiguration.java +++ b/chrome/android/features/start_surface/public/java/src/org/chromium/chrome/features/start_surface/StartSurfaceConfiguration.java
@@ -6,6 +6,7 @@ import androidx.annotation.VisibleForTesting; +import org.chromium.base.Log; import org.chromium.base.SysUtils; import org.chromium.base.metrics.RecordHistogram; import org.chromium.chrome.browser.flags.BooleanCachedFieldTrialParameter; @@ -25,6 +26,7 @@ * which variation should be used. */ public class StartSurfaceConfiguration { + private static final String TAG = "StartSurfaceConfig"; public static final StringCachedFieldTrialParameter START_SURFACE_VARIATION = new StringCachedFieldTrialParameter( ChromeFeatureList.START_SURFACE_ANDROID, "start_surface_variation", ""); @@ -144,7 +146,7 @@ */ public static void recordHistogram(String name, long timeDurationMs, boolean isInstantStart) { if (timeDurationMs < 0) return; - + Log.i(TAG, "Recorded %s = %d ms", getHistogramName(name, isInstantStart), timeDurationMs); RecordHistogram.recordTimesHistogram( getHistogramName(name, isInstantStart), timeDurationMs); }
diff --git a/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/FeedDataInjectRule.java b/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/FeedDataInjectRule.java index 6a5e29d..e7d316a 100644 --- a/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/FeedDataInjectRule.java +++ b/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/FeedDataInjectRule.java
@@ -41,8 +41,7 @@ * public FeedDataInjectRule mDataInjector = new FeedDataInjectRule(); * * @Rule - * public ChromeActivityTestRule<ChromeTabbedActivity> mActivityTestRule = - * new ChromeActivityTestRule(ChromeTabbedActivity.class); + * public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule(); * * @Test * @Feature({"FeedNewTabPage"}) @@ -58,13 +57,8 @@ * } * } * </pre> - * - * Note when using this test rule, do not also use ChromeTabbedActivityTestRule. - * ChromeTabbedActivityTestRule also try to set a default feed response file and - * it could results to strange behaviors in test, such as always see the same - * set of cards in each test case. */ -final class FeedDataInjectRule extends TestWatcher { +public final class FeedDataInjectRule extends TestWatcher { private static final String TAG = "FeedDataInjectRule"; private static final int FIRST_CARD_BASE_POSITION = 2;
diff --git a/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/tooltip/FeedTooltipTest.java b/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/tooltip/FeedTooltipTest.java index 26c8799..046f84e4 100644 --- a/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/tooltip/FeedTooltipTest.java +++ b/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/tooltip/FeedTooltipTest.java
@@ -21,7 +21,6 @@ import androidx.test.espresso.matcher.RootMatchers; import androidx.test.filters.MediumTest; -import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Rule; @@ -31,7 +30,8 @@ import org.chromium.base.test.util.CallbackHelper; import org.chromium.base.test.util.CommandLineFlags; import org.chromium.base.test.util.Feature; -import org.chromium.chrome.browser.feed.FeedProcessScopeFactory; +import org.chromium.chrome.browser.feed.DataFilePath; +import org.chromium.chrome.browser.feed.FeedDataInjectRule; import org.chromium.chrome.browser.feed.shared.stream.Stream; import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.flags.ChromeSwitches; @@ -64,8 +64,10 @@ private static final int FIRST_CARD_POSITION = 3; @Rule - public ChromeTabbedActivityTestRule mActivityTestRule = - new ChromeTabbedActivityTestRule(FEED_TEST_RESPONSE_FILE_PATH); + public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule(); + + @Rule + public FeedDataInjectRule mFeedDataInjector = new FeedDataInjectRule(false); @Rule public SuggestionsDependenciesRule mSuggestionsDeps = new SuggestionsDependenciesRule(); @@ -105,14 +107,10 @@ mStream.addOnContentChangedListener(mTestObserver); } - @After - public void tearDown() { - FeedProcessScopeFactory.setTestNetworkClient(null); - } - @Test @MediumTest @Feature({"FeedNewTabPage"}) + @DataFilePath(FEED_TEST_RESPONSE_FILE_PATH) public void testShowTooltip() throws Exception { int callCount = mTestObserver.firstCardShownCallback.getCallCount(); TestThreadUtils.runOnUiThreadBlocking(() -> mStream.triggerRefresh());
diff --git a/chrome/android/java/res/drawable/ic_signout_40dp.xml b/chrome/android/java/res/drawable/ic_signout_40dp.xml new file mode 100644 index 0000000..30ad189 --- /dev/null +++ b/chrome/android/java/res/drawable/ic_signout_40dp.xml
@@ -0,0 +1,18 @@ +<?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. --> +<vector + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:width="40dp" + android:height="40dp" + android:viewportWidth="40" + android:viewportHeight="40" + tools:targetApi="21"> + + <path + android:pathData="M24.166 15.833l-1.175 1.175 2.15 2.159h-8.474v1.666h8.474l-2.15 2.15 1.175 1.184L28.334 20l-4.166-4.167zm-10.833-1.666H20V12.5h-6.667c-0.917 0-1.667 0.75-1.667 1.667v11.666c0 0.917 0.75 1.667 1.667 1.667H20v-1.667h-6.667V14.167z" + android:fillColor="@color/default_icon_color_secondary" + android:fillType="evenOdd"/> +</vector>
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/sync/settings/AccountManagementFragment.java b/chrome/android/java/src/org/chromium/chrome/browser/sync/settings/AccountManagementFragment.java index 8f958b6..752c7f5 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/sync/settings/AccountManagementFragment.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/sync/settings/AccountManagementFragment.java
@@ -197,6 +197,10 @@ getPreferenceScreen().removePreference(signOutPreference); getPreferenceScreen().removePreference(findPreference(PREF_SIGN_OUT_DIVIDER)); } else { + if (ChromeFeatureList.isEnabled(ChromeFeatureList.MOBILE_IDENTITY_CONSISTENCY)) { + signOutPreference.setLayoutResource(R.layout.account_management_account_row); + signOutPreference.setIcon(R.drawable.ic_signout_40dp); + } signOutPreference.setTitle(getSignOutPreferenceText()); signOutPreference.setEnabled(getSignOutAllowedPreferenceValue()); signOutPreference.setOnPreferenceClickListener(preference -> {
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/signin/SigninManagerTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/signin/SigninManagerTest.java index 9dbed005..95671c3 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/signin/SigninManagerTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/signin/SigninManagerTest.java
@@ -12,20 +12,18 @@ import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doAnswer; -import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; -import static org.mockito.MockitoAnnotations.initMocks; +import org.junit.After; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; -import org.mockito.Mock; import org.mockito.stubbing.Answer; import org.robolectric.annotation.Config; @@ -54,65 +52,66 @@ @Rule public final JniMocker mocker = new JniMocker(); - @Mock - SigninManager.Natives mNativeMock; + private static final AccountInfo ACCOUNT_INFO = new AccountInfo( + new CoreAccountId("gaia-id-user"), "user@domain.com", "gaia-id-user", null); - private AccountTrackerService mAccountTrackerService; + private final SigninManager.Natives mNativeMock = mock(SigninManager.Natives.class); + private final AccountTrackerService mAccountTrackerService = mock(AccountTrackerService.class); + private final IdentityMutator mIdentityMutator = mock(IdentityMutator.class); + private final AndroidSyncSettings mAndroidSyncSettings = mock(AndroidSyncSettings.class); + private final ExternalAuthUtils mExternalAuthUtils = mock(ExternalAuthUtils.class); private IdentityManager mIdentityManager; - private IdentityMutator mIdentityMutator; + private SigninManager mSigninManager; - private CoreAccountInfo mAccount; - private AndroidSyncSettings mAndroidSyncSettings; @Before public void setUp() { - initMocks(this); - mocker.mock(SigninManagerJni.TEST_HOOKS, mNativeMock); doReturn(true).when(mNativeMock).isSigninAllowedByPolicy(anyLong()); - - mAccountTrackerService = mock(AccountTrackerService.class); - - mIdentityMutator = mock(IdentityMutator.class); + // Pretend Google Play services are available as it is required for the sign-in + doReturn(false).when(mExternalAuthUtils).isGooglePlayServicesMissing(any()); mIdentityManager = spy( new IdentityManager(0 /* nativeIdentityManager */, null /* OAuth2TokenService */)); - - mAndroidSyncSettings = mock(AndroidSyncSettings.class); - - ExternalAuthUtils externalAuthUtils = mock(ExternalAuthUtils.class); - // Pretend Google Play services are available as it is required for the sign-in - doReturn(false).when(externalAuthUtils).isGooglePlayServicesMissing(any()); - doReturn(null).when(mIdentityManager).getPrimaryAccountInfo(anyInt()); + } + + @After + public void tearDown() { + if (mSigninManager != null) { + mSigninManager.destroy(); + mSigninManager = null; + } + } + + private void createSigninManager() { mSigninManager = new SigninManager(0 /* nativeSigninManagerAndroid */, mAccountTrackerService, mIdentityManager, mIdentityMutator, mAndroidSyncSettings, - externalAuthUtils); - - mAccount = new AccountInfo( - new CoreAccountId("gaia-id-user"), "user@domain.com", "gaia-id-user", null); + mExternalAuthUtils); } @Test public void signinAndTurnSyncOn() { doReturn(true).when(mAccountTrackerService).checkAndSeedSystemAccounts(); - doReturn(mAccount) + doReturn(ACCOUNT_INFO) .when(mIdentityManager) .findExtendedAccountInfoForAccountWithRefreshTokenByEmailAddress( - eq(mAccount.getEmail())); + eq(ACCOUNT_INFO.getEmail())); doReturn(true).when(mIdentityMutator).setPrimaryAccount(any(), anyInt()); + createSigninManager(); mSigninManager.onFirstRunCheckDone(); SigninManager.SignInCallback callback = mock(SigninManager.SignInCallback.class); - mSigninManager.signinAndEnableSync(SigninAccessPoint.START_PAGE, mAccount, callback); + mSigninManager.signinAndEnableSync(SigninAccessPoint.START_PAGE, ACCOUNT_INFO, callback); - verify(mNativeMock).fetchAndApplyCloudPolicy(anyLong(), eq(mAccount), any()); + verify(mNativeMock).fetchAndApplyCloudPolicy(anyLong(), eq(ACCOUNT_INFO), any()); mSigninManager.finishSignInAfterPolicyEnforced(); - verify(mIdentityMutator).setPrimaryAccount(mAccount.getId(), ConsentLevel.SYNC); - verify(mAndroidSyncSettings).updateAccount(CoreAccountInfo.getAndroidAccountFrom(mAccount)); + verify(mIdentityMutator).setPrimaryAccount(ACCOUNT_INFO.getId(), ConsentLevel.SYNC); + verify(mAndroidSyncSettings) + .updateAccount(CoreAccountInfo.getAndroidAccountFrom(ACCOUNT_INFO)); verify(mAndroidSyncSettings).enableChromeSync(); // Signin should be complete and callback should be invoked. verify(callback).onSignInComplete(); @@ -122,21 +121,22 @@ @Test public void signinNoTurnSyncOn() { doReturn(true).when(mAccountTrackerService).checkAndSeedSystemAccounts(); - doReturn(mAccount) + doReturn(ACCOUNT_INFO) .when(mIdentityManager) .findExtendedAccountInfoForAccountWithRefreshTokenByEmailAddress( - eq(mAccount.getEmail())); + eq(ACCOUNT_INFO.getEmail())); doReturn(true).when(mIdentityMutator).setPrimaryAccount(any(), anyInt()); + createSigninManager(); mSigninManager.onFirstRunCheckDone(); SigninManager.SignInCallback callback = mock(SigninManager.SignInCallback.class); - mSigninManager.signin(mAccount, callback); + mSigninManager.signin(ACCOUNT_INFO, callback); // Signin without turning on sync shouldn't apply policies. verify(mNativeMock, never()).fetchAndApplyCloudPolicy(anyLong(), any(), any()); - verify(mIdentityMutator).setPrimaryAccount(mAccount.getId(), ConsentLevel.NOT_REQUIRED); + verify(mIdentityMutator).setPrimaryAccount(ACCOUNT_INFO.getId(), ConsentLevel.NOT_REQUIRED); verify(mAndroidSyncSettings, never()).updateAccount(any()); verify(mAndroidSyncSettings, never()).enableChromeSync(); @@ -147,14 +147,10 @@ @Test public void signOutFromJavaWithManagedDomain() { - // Stub out various native calls. Some of these are verified as never called - // and those stubs simply allow that verification to catch any issues. - doNothing().when(mNativeMock).wipeProfileData(anyLong(), any()); - doNothing().when(mNativeMock).wipeGoogleServiceWorkerCaches(anyLong(), any()); - // See verification of nativeWipeProfileData below. doReturn("TestDomain").when(mNativeMock).getManagementDomain(anyLong()); + createSigninManager(); // Trigger the sign out flow! mSigninManager.signOut(SignoutReason.SIGNOUT_TEST); @@ -164,7 +160,7 @@ verify(mNativeMock, never()).wipeGoogleServiceWorkerCaches(anyLong(), any()); // Simulate native callback to trigger clearing of account data. - mIdentityManager.onPrimaryAccountCleared(mAccount); + mIdentityManager.onPrimaryAccountCleared(ACCOUNT_INFO); // Sign-out should only clear the profile when the user is managed. verify(mNativeMock, times(1)).wipeProfileData(anyLong(), any()); @@ -173,15 +169,10 @@ @Test public void signOutFromJavaWithNullDomain() { - // Stub out various native calls. Some of these are verified as never called - // and those stubs simply allow that verification to catch any issues. - doNothing().when(mNativeMock).wipeProfileData(anyLong(), any()); - doNothing().when(mNativeMock).wipeGoogleServiceWorkerCaches(anyLong(), any()); - - // See verification of nativeWipeGoogleServiceWorkerCaches below. + // Simulate sign-out with non-managed account. doReturn(null).when(mNativeMock).getManagementDomain(anyLong()); - // Trigger the sign out flow! + createSigninManager(); mSigninManager.signOut(SignoutReason.SIGNOUT_TEST); // PrimaryAccountCleared should be called *before* clearing any account data. @@ -190,7 +181,7 @@ verify(mNativeMock, never()).wipeGoogleServiceWorkerCaches(anyLong(), any()); // Simulate native callback to trigger clearing of account data. - mIdentityManager.onPrimaryAccountCleared(mAccount); + mIdentityManager.onPrimaryAccountCleared(ACCOUNT_INFO); // Sign-out should only clear the service worker cache when the user is not managed. verify(mNativeMock, never()).wipeProfileData(anyLong(), any()); @@ -199,15 +190,10 @@ @Test public void signOutFromJavaWithNullDomainAndForceWipe() { - // Stub out various native calls. Some of these are verified as never called - // and those stubs simply allow that verification to catch any issues. - doNothing().when(mNativeMock).wipeProfileData(anyLong(), any()); - doNothing().when(mNativeMock).wipeGoogleServiceWorkerCaches(anyLong(), any()); - // See verification of nativeWipeGoogleServiceWorkerCaches below. doReturn(null).when(mNativeMock).getManagementDomain(anyLong()); - // Trigger the sign out flow + createSigninManager(); mSigninManager.signOut(SignoutReason.SIGNOUT_TEST, null, true); // PrimaryAccountCleared should be called *before* clearing any account data. @@ -216,7 +202,7 @@ verify(mNativeMock, never()).wipeGoogleServiceWorkerCaches(anyLong(), any()); // Simulate native callback to trigger clearing of account data. - mIdentityManager.onPrimaryAccountCleared(mAccount); + mIdentityManager.onPrimaryAccountCleared(ACCOUNT_INFO); // Sign-out should only clear the service worker cache when the user is not managed. verify(mNativeMock, times(1)).wipeProfileData(anyLong(), any()); @@ -225,13 +211,9 @@ @Test public void signOutFromNative() { - // Stub out various native calls. Some of these are verified as never called - // and those stubs simply allow that verification to catch any issues. - doNothing().when(mNativeMock).wipeProfileData(anyLong(), any()); - doNothing().when(mNativeMock).wipeGoogleServiceWorkerCaches(anyLong(), any()); - - // Trigger the sign out flow! - mIdentityManager.onPrimaryAccountCleared(mAccount); + createSigninManager(); + // Simulate native initiating the sign-out. + mIdentityManager.onPrimaryAccountCleared(ACCOUNT_INFO); // Sign-out should only clear the profile when the user is managed. verify(mNativeMock, times(1)).wipeProfileData(anyLong(), any()); @@ -240,10 +222,8 @@ @Test public void clearingAccountCookiesTriggersSignout() { - // Stub out various native calls. Some of these are verified as never called - // and those stubs simply allow that verification to catch any issues. - doNothing().when(mNativeMock).wipeProfileData(anyLong(), any()); - doNothing().when(mNativeMock).wipeGoogleServiceWorkerCaches(anyLong(), any()); + // Create SigninManager so it adds an observer for onAccountsCookieDeletedByUserAction. + createSigninManager(); // Clearing cookies shouldn't do anything when there's no primary account. doReturn(null).when(mIdentityManager).getPrimaryAccountInfo(anyInt()); @@ -251,12 +231,14 @@ verify(mIdentityMutator, never()).clearPrimaryAccount(anyInt(), anyInt(), anyInt()); // Clearing cookies shouldn't do anything when there's sync account. - doReturn(mAccount).when(mIdentityManager).getPrimaryAccountInfo(anyInt()); + doReturn(ACCOUNT_INFO).when(mIdentityManager).getPrimaryAccountInfo(anyInt()); mIdentityManager.onAccountsCookieDeletedByUserAction(); verify(mIdentityMutator, never()).clearPrimaryAccount(anyInt(), anyInt(), anyInt()); // Clearing cookies when there's only an unconsented account should trigger sign-out. - doReturn(mAccount).when(mIdentityManager).getPrimaryAccountInfo(ConsentLevel.NOT_REQUIRED); + doReturn(ACCOUNT_INFO) + .when(mIdentityManager) + .getPrimaryAccountInfo(ConsentLevel.NOT_REQUIRED); doReturn(null).when(mIdentityManager).getPrimaryAccountInfo(ConsentLevel.SYNC); mIdentityManager.onAccountsCookieDeletedByUserAction(); verify(mIdentityMutator) @@ -270,6 +252,7 @@ @Test public void callbackNotifiedWhenNoOperationIsInProgress() { + createSigninManager(); assertFalse(mSigninManager.isOperationInProgress()); AtomicInteger callCount = new AtomicInteger(0); @@ -280,12 +263,13 @@ @Test public void callbackNotifiedOnSignout() { doAnswer(invocation -> { - mIdentityManager.onPrimaryAccountCleared(mAccount); + mIdentityManager.onPrimaryAccountCleared(ACCOUNT_INFO); return null; }) .when(mIdentityMutator) .clearPrimaryAccount(anyInt(), anyInt(), anyInt()); + createSigninManager(); mSigninManager.signOut(SignoutReason.SIGNOUT_TEST); assertTrue(mSigninManager.isOperationInProgress()); AtomicInteger callCount = new AtomicInteger(0); @@ -304,9 +288,6 @@ // No need to seed accounts to the native code. doReturn(true).when(mAccountTrackerService).checkAndSeedSystemAccounts(); - // Request that policy is loaded. It will pause sign-in until onPolicyCheckedBeforeSignIn is - // invoked. - doNothing().when(mNativeMock).fetchAndApplyCloudPolicy(anyLong(), any(), any()); doReturn(account) .when(mIdentityManager) @@ -320,8 +301,8 @@ doAnswer(setPrimaryAccountAnswer) .when(mIdentityMutator) .setPrimaryAccount(account.getId(), ConsentLevel.SYNC); - doNothing().when(mIdentityMutator).reloadAllAccountsFromSystemWithPrimaryAccount(any()); + createSigninManager(); mSigninManager.onFirstRunCheckDone(); // Allow sign-in. mSigninManager.signinAndEnableSync(SigninAccessPoint.UNKNOWN, account, null); @@ -342,15 +323,13 @@ // No need to seed accounts to the native code. doReturn(true).when(mAccountTrackerService).checkAndSeedSystemAccounts(); - // Request that policy is loaded. It will pause sign-in until onPolicyCheckedBeforeSignIn is - // invoked. - doNothing().when(mNativeMock).fetchAndApplyCloudPolicy(anyLong(), any(), any()); doReturn(account) .when(mIdentityManager) .findExtendedAccountInfoForAccountWithRefreshTokenByEmailAddress(any()); doReturn(true).when(mIdentityManager).hasPrimaryAccount(); + createSigninManager(); mSigninManager.onFirstRunCheckDone(); // Allow sign-in. mSigninManager.signinAndEnableSync(SigninAccessPoint.UNKNOWN, account, null);
diff --git a/chrome/app/chromeos_strings.grdp b/chrome/app/chromeos_strings.grdp index b03cce9..185a959a 100644 --- a/chrome/app/chromeos_strings.grdp +++ b/chrome/app/chromeos_strings.grdp
@@ -2597,6 +2597,27 @@ <message name="IDS_ENTERPRISE_LOGIN_ERROR_ALLOWLIST" desc="Couldn't sign in because user is not authorized by the administrator."> You are not authorized to use this device. Please contact the administrator for sign-in permission. </message> + <message name="IDS_LOCK_SCREEN_VERIFY_ACCOUNT" desc="Title of online account verification on the lock screen"> + Verify account + </message> + <message name="IDS_LOCK_SCREEN_VERIFY_BUTTON" desc="Next button for online account verification on the lock screen"> + Verify + </message> + <message name="IDS_LOCK_SCREEN_VERIFY_AGAIN_BUTTON" desc="Next button for 2nd online account verification on the lock screen"> + Verify again + </message> + <message name="IDS_LOCK_SCREEN_CANCEL_BUTTON" desc="Cancel button for online account verification on the lock screen"> + Cancel + </message> + <message name="IDS_LOCK_SCREEN_VERIFICATION_FAILED" desc="Title of incorrect user online reauthentication on the lock screen"> + Verification was not successful + </message> + <message name="IDS_LOCK_SCREEN_WRONG_USER" desc="User that was not logged in tries to unlock the device"> + The account you verified is not authorized to access this device. Please make sure you are verifying <ph name="ACCOUNT">$1<ex>test@example.com</ex></ph> to unlock the session. + </message> + <message name="IDS_LOCK_SCREEN_REAUTH_SUBTITLE" desc="Subtitle for lock screen user re-auth dialog"> + Sign in to <ph name="ACCOUNT">$1<ex>test@example.com</ex></ph> again to verify this account + </message> <message name="IDS_LOGIN_ERROR_GOOGLE_ACCOUNT_NOT_ALLOWED" desc="Couldn't sign into Google account on the Active Directory managed device."> Sorry, Google accounts are not allowed on this device. </message>
diff --git a/chrome/app/chromeos_strings_grdp/IDS_LOCK_SCREEN_CANCEL_BUTTON.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_LOCK_SCREEN_CANCEL_BUTTON.png.sha1 new file mode 100644 index 0000000..617ed8a --- /dev/null +++ b/chrome/app/chromeos_strings_grdp/IDS_LOCK_SCREEN_CANCEL_BUTTON.png.sha1
@@ -0,0 +1 @@ +078b283c6e11478112e9461ae86bf07a0f9aceb7 \ No newline at end of file
diff --git a/chrome/app/chromeos_strings_grdp/IDS_LOCK_SCREEN_REAUTH_SUBTITLE.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_LOCK_SCREEN_REAUTH_SUBTITLE.png.sha1 new file mode 100644 index 0000000..617ed8a --- /dev/null +++ b/chrome/app/chromeos_strings_grdp/IDS_LOCK_SCREEN_REAUTH_SUBTITLE.png.sha1
@@ -0,0 +1 @@ +078b283c6e11478112e9461ae86bf07a0f9aceb7 \ No newline at end of file
diff --git a/chrome/app/chromeos_strings_grdp/IDS_LOCK_SCREEN_VERIFICATION_FAILED.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_LOCK_SCREEN_VERIFICATION_FAILED.png.sha1 new file mode 100644 index 0000000..5f4e4a5 --- /dev/null +++ b/chrome/app/chromeos_strings_grdp/IDS_LOCK_SCREEN_VERIFICATION_FAILED.png.sha1
@@ -0,0 +1 @@ +9ae3a4fddbcc6f3f1533b1f366ff444fe6da91cb \ No newline at end of file
diff --git a/chrome/app/chromeos_strings_grdp/IDS_LOCK_SCREEN_VERIFY_ACCOUNT.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_LOCK_SCREEN_VERIFY_ACCOUNT.png.sha1 new file mode 100644 index 0000000..617ed8a --- /dev/null +++ b/chrome/app/chromeos_strings_grdp/IDS_LOCK_SCREEN_VERIFY_ACCOUNT.png.sha1
@@ -0,0 +1 @@ +078b283c6e11478112e9461ae86bf07a0f9aceb7 \ No newline at end of file
diff --git a/chrome/app/chromeos_strings_grdp/IDS_LOCK_SCREEN_VERIFY_AGAIN_BUTTON.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_LOCK_SCREEN_VERIFY_AGAIN_BUTTON.png.sha1 new file mode 100644 index 0000000..5f4e4a5 --- /dev/null +++ b/chrome/app/chromeos_strings_grdp/IDS_LOCK_SCREEN_VERIFY_AGAIN_BUTTON.png.sha1
@@ -0,0 +1 @@ +9ae3a4fddbcc6f3f1533b1f366ff444fe6da91cb \ No newline at end of file
diff --git a/chrome/app/chromeos_strings_grdp/IDS_LOCK_SCREEN_VERIFY_BUTTON.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_LOCK_SCREEN_VERIFY_BUTTON.png.sha1 new file mode 100644 index 0000000..617ed8a --- /dev/null +++ b/chrome/app/chromeos_strings_grdp/IDS_LOCK_SCREEN_VERIFY_BUTTON.png.sha1
@@ -0,0 +1 @@ +078b283c6e11478112e9461ae86bf07a0f9aceb7 \ No newline at end of file
diff --git a/chrome/app/chromeos_strings_grdp/IDS_LOCK_SCREEN_WRONG_USER.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_LOCK_SCREEN_WRONG_USER.png.sha1 new file mode 100644 index 0000000..5f4e4a5 --- /dev/null +++ b/chrome/app/chromeos_strings_grdp/IDS_LOCK_SCREEN_WRONG_USER.png.sha1
@@ -0,0 +1 @@ +9ae3a4fddbcc6f3f1533b1f366ff444fe6da91cb \ No newline at end of file
diff --git a/chrome/browser/android/autofill_assistant/assistant_bottom_bar_delegate.cc b/chrome/browser/android/autofill_assistant/assistant_bottom_bar_delegate.cc index a76bc60f..76ea8b8 100644 --- a/chrome/browser/android/autofill_assistant/assistant_bottom_bar_delegate.cc +++ b/chrome/browser/android/autofill_assistant/assistant_bottom_bar_delegate.cc
@@ -30,10 +30,10 @@ return ui_controller_->OnBackButtonClicked(); } -void AssistantBottomBarDelegate::OnBottomSheetDismissed( +void AssistantBottomBarDelegate::OnBottomSheetClosedWithSwipe( JNIEnv* env, const base::android::JavaParamRef<jobject>& jcaller) { - ui_controller_->OnBottomSheetDismissed(); + ui_controller_->OnBottomSheetClosedWithSwipe(); } base::android::ScopedJavaGlobalRef<jobject>
diff --git a/chrome/browser/android/autofill_assistant/assistant_bottom_bar_delegate.h b/chrome/browser/android/autofill_assistant/assistant_bottom_bar_delegate.h index 92d77d6..7665d32b 100644 --- a/chrome/browser/android/autofill_assistant/assistant_bottom_bar_delegate.h +++ b/chrome/browser/android/autofill_assistant/assistant_bottom_bar_delegate.h
@@ -19,7 +19,7 @@ bool OnBackButtonClicked(JNIEnv* env, const base::android::JavaParamRef<jobject>& jcaller); - void OnBottomSheetDismissed( + void OnBottomSheetClosedWithSwipe( JNIEnv* env, const base::android::JavaParamRef<jobject>& jcaller);
diff --git a/chrome/browser/android/autofill_assistant/ui_controller_android.cc b/chrome/browser/android/autofill_assistant/ui_controller_android.cc index e29ca397..fd1f484 100644 --- a/chrome/browser/android/autofill_assistant/ui_controller_android.cc +++ b/chrome/browser/android/autofill_assistant/ui_controller_android.cc
@@ -696,11 +696,21 @@ void UiControllerAndroid::OnTabSwitched( JNIEnv* env, const base::android::JavaParamRef<jobject>& jcaller, - jint state) { + jint state, + jboolean activity_changed) { if (ui_delegate_ == nullptr) { return; } + // TODO(b/167947210) Allow lite scripts to transition from CCT to regular + // scripts. + if (activity_changed && ui_delegate_->IsRunningLiteScript()) { + // Destroying UI here because Shutdown does not do so in all cases. + DestroySelf(); + Shutdown(Metrics::DropOutReason::CUSTOM_TAB_CLOSED); + return; + } + ui_delegate_->SetBottomSheetState( ui_controller_android_utils::ToNativeBottomSheetState(state)); ui_delegate_->SetTabSelected(false); @@ -922,7 +932,7 @@ return true; } -void UiControllerAndroid::OnBottomSheetDismissed() { +void UiControllerAndroid::OnBottomSheetClosedWithSwipe() { if (ui_delegate_->IsTabSelected() && ui_delegate_->IsRunningLiteScript()) { // Destroying UI here because Shutdown does not do so in all cases. DestroySelf();
diff --git a/chrome/browser/android/autofill_assistant/ui_controller_android.h b/chrome/browser/android/autofill_assistant/ui_controller_android.h index eed8efa..9439169 100644 --- a/chrome/browser/android/autofill_assistant/ui_controller_android.h +++ b/chrome/browser/android/autofill_assistant/ui_controller_android.h
@@ -168,7 +168,7 @@ // Called by AssistantBottomBarNativeDelegate: bool OnBackButtonClicked(); - void OnBottomSheetDismissed(); + void OnBottomSheetClosedWithSwipe(); // Called by Java. void SnackbarResult(JNIEnv* env, @@ -203,7 +203,8 @@ jboolean visible); void OnTabSwitched(JNIEnv* env, const base::android::JavaParamRef<jobject>& jcaller, - jint state); + jint state, + jboolean activity_changed); void OnTabSelected(JNIEnv* env, const base::android::JavaParamRef<jobject>& jcaller);
diff --git a/chrome/browser/browser_resources.grd b/chrome/browser/browser_resources.grd index 694349ed..8145d5e 100644 --- a/chrome/browser/browser_resources.grd +++ b/chrome/browser/browser_resources.grd
@@ -267,7 +267,10 @@ <include name="IDR_CONFIRM_PASSWORD_CHANGE_JS" file="resources\chromeos\password_change\confirm_password_change.js" type="chrome_html" /> <include name="IDR_URGENT_PASSWORD_EXPIRY_NOTIFICATION_HTML" file="resources\chromeos\password_change\urgent_password_expiry_notification.html" flattenhtml="true" allowexternalscript="true" type="chrome_html" /> <include name="IDR_URGENT_PASSWORD_EXPIRY_NOTIFICATION_JS" file="resources\chromeos\password_change\urgent_password_expiry_notification.js" type="chrome_html" /> - + <include name="IDR_GAIA_AUTH_AUTHENTICATOR_JS" file="resources\gaia_auth_host\authenticator.js" flattenhtml="true" type="BINDATA" /> + <include name="IDR_LOCK_SCREEN_REAUTH_HTML" file="resources\chromeos\password_change\lock_screen_reauth.html" flattenhtml="true" type="BINDATA" /> + <include name="IDR_LOCK_SCREEN_REAUTH_JS" file="resources\chromeos\password_change\lock_screen_reauth.js" type="BINDATA" /> + <include name="IDR_CROSTINI_INSTALLER_INDEX_HTML" file="resources\chromeos\crostini_installer\index.html" type="BINDATA" /> <include name="IDR_CROSTINI_INSTALLER_APP_JS" file="${root_gen_dir}\chrome\browser\resources\chromeos\crostini_installer\app.js" type="BINDATA" use_base_dir="false" /> <include name="IDR_CROSTINI_INSTALLER_BROWSER_PROXY_JS" file="resources\chromeos\crostini_installer\browser_proxy.js" type="BINDATA" />
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn index 0e31872..983b342 100644 --- a/chrome/browser/chromeos/BUILD.gn +++ b/chrome/browser/chromeos/BUILD.gn
@@ -959,6 +959,8 @@ "crosapi/browser_manager.h", "crosapi/browser_util.cc", "crosapi/browser_util.h", + "crosapi/environment_provider.cc", + "crosapi/environment_provider.h", "crosapi/feedback_ash.cc", "crosapi/feedback_ash.h", "crosapi/keystore_service_ash.cc", @@ -3018,6 +3020,8 @@ "login/test/test_condition_waiter.h", "login/test/test_predicate_waiter.cc", "login/test/test_predicate_waiter.h", + "login/test/wizard_controller_screen_exit_waiter.cc", + "login/test/wizard_controller_screen_exit_waiter.h", "login/version_updater/mock_version_updater_delegate.cc", "login/version_updater/mock_version_updater_delegate.h", "platform_keys/key_permissions/mock_key_permissions_service.cc",
diff --git a/chrome/browser/chromeos/attestation/tpm_challenge_key_subtle.cc b/chrome/browser/chromeos/attestation/tpm_challenge_key_subtle.cc index c8697d0b..8a73400 100644 --- a/chrome/browser/chromeos/attestation/tpm_challenge_key_subtle.cc +++ b/chrome/browser/chromeos/attestation/tpm_challenge_key_subtle.cc
@@ -248,8 +248,7 @@ DCHECK(profile_); PrefService* prefs = profile_->GetPrefs(); - // TODO(crbug.com/1000589): Check it's mandatory after fixing corp policy. - if (prefs) { + if (prefs && prefs->IsManagedPreference(prefs::kAttestationEnabled)) { return prefs->GetBoolean(prefs::kAttestationEnabled); } return false;
diff --git a/chrome/browser/chromeos/crosapi/browser_manager.cc b/chrome/browser/chromeos/crosapi/browser_manager.cc index 5d5094a..83764de5 100644 --- a/chrome/browser/chromeos/crosapi/browser_manager.cc +++ b/chrome/browser/chromeos/crosapi/browser_manager.cc
@@ -7,6 +7,7 @@ #include <fcntl.h> #include <unistd.h> +#include <memory> #include <string> #include <utility> #include <vector> @@ -30,6 +31,7 @@ #include "chrome/browser/chromeos/crosapi/ash_chrome_service_impl.h" #include "chrome/browser/chromeos/crosapi/browser_loader.h" #include "chrome/browser/chromeos/crosapi/browser_util.h" +#include "chrome/browser/chromeos/crosapi/environment_provider.h" #include "chrome/browser/chromeos/crosapi/test_mojo_connection_manager.h" #include "chrome/browser/component_updater/cros_component_manager.h" #include "chrome/browser/profiles/profile_manager.h" @@ -139,7 +141,8 @@ BrowserManager::BrowserManager( scoped_refptr<component_updater::CrOSComponentManager> manager) - : component_manager_(manager) { + : component_manager_(manager), + environment_provider_(std::make_unique<EnvironmentProvider>()) { DCHECK(!g_instance); g_instance = this; @@ -296,7 +299,7 @@ // TODO(crbug.com/1124490): Support multiple mojo connections from lacros. lacros_chrome_service_ = browser_util::SendMojoInvitationToLacrosChrome( - channel.TakeLocalEndpoint(), + environment_provider_.get(), channel.TakeLocalEndpoint(), base::BindOnce(&BrowserManager::OnMojoDisconnected, weak_factory_.GetWeakPtr()), base::BindOnce(&BrowserManager::OnAshChromeServiceReceiverReceived,
diff --git a/chrome/browser/chromeos/crosapi/browser_manager.h b/chrome/browser/chromeos/crosapi/browser_manager.h index de94b53..fb2318aa 100644 --- a/chrome/browser/chromeos/crosapi/browser_manager.h +++ b/chrome/browser/chromeos/crosapi/browser_manager.h
@@ -12,6 +12,7 @@ #include "base/memory/scoped_refptr.h" #include "base/memory/weak_ptr.h" #include "base/process/process.h" +#include "chrome/browser/chromeos/crosapi/environment_provider.h" #include "chromeos/crosapi/mojom/crosapi.mojom.h" #include "components/session_manager/core/session_manager_observer.h" #include "mojo/public/cpp/bindings/remote.h" @@ -166,6 +167,9 @@ // '--lacros-mojo-socket-for-testing' is present in the command line. std::unique_ptr<TestMojoConnectionManager> test_mojo_connection_manager_; + // Used to pass ash-chrome specific flags/configurations to lacros-chrome. + std::unique_ptr<EnvironmentProvider> environment_provider_; + base::WeakPtrFactory<BrowserManager> weak_factory_{this}; };
diff --git a/chrome/browser/chromeos/crosapi/browser_util.cc b/chrome/browser/chromeos/crosapi/browser_util.cc index b451bce..f930270 100644 --- a/chrome/browser/chromeos/crosapi/browser_util.cc +++ b/chrome/browser/chromeos/crosapi/browser_util.cc
@@ -54,13 +54,16 @@ } } -mojom::LacrosInitParamsPtr GetLacrosInitParams() { +mojom::LacrosInitParamsPtr GetLacrosInitParams( + EnvironmentProvider* environment_provider) { auto params = mojom::LacrosInitParams::New(); params->ash_chrome_service_version = crosapi::mojom::AshChromeService::Version_; params->ash_metrics_enabled_has_value = true; params->ash_metrics_enabled = g_browser_process->local_state()->GetBoolean( metrics::prefs::kMetricsReportingEnabled); + + params->session_type = environment_provider->GetSessionType(); return params; } @@ -120,6 +123,7 @@ mojo::Remote<crosapi::mojom::LacrosChromeService> SendMojoInvitationToLacrosChrome( + EnvironmentProvider* environment_provider, mojo::PlatformChannelEndpoint local_endpoint, base::OnceClosure mojo_disconnected_callback, base::OnceCallback< @@ -132,7 +136,7 @@ invitation.AttachMessagePipe(0 /* token */), /*version=*/0)); lacros_chrome_service.set_disconnect_handler( std::move(mojo_disconnected_callback)); - lacros_chrome_service->Init(GetLacrosInitParams()); + lacros_chrome_service->Init(GetLacrosInitParams(environment_provider)); lacros_chrome_service->RequestAshChromeServiceReceiver( std::move(ash_chrome_service_callback)); mojo::OutgoingInvitation::Send(std::move(invitation),
diff --git a/chrome/browser/chromeos/crosapi/browser_util.h b/chrome/browser/chromeos/crosapi/browser_util.h index 1930eeb8..a0ced50 100644 --- a/chrome/browser/chromeos/crosapi/browser_util.h +++ b/chrome/browser/chromeos/crosapi/browser_util.h
@@ -6,6 +6,7 @@ #define CHROME_BROWSER_CHROMEOS_CROSAPI_BROWSER_UTIL_H_ #include "base/callback_forward.h" +#include "chrome/browser/chromeos/crosapi/environment_provider.h" #include "chromeos/crosapi/mojom/crosapi.mojom.h" #include "mojo/public/cpp/bindings/pending_receiver.h" #include "mojo/public/cpp/bindings/remote.h" @@ -57,6 +58,7 @@ // available already when lacros-chrome accepts the invitation. mojo::Remote<crosapi::mojom::LacrosChromeService> SendMojoInvitationToLacrosChrome( + ::crosapi::EnvironmentProvider* environment_provider, mojo::PlatformChannelEndpoint local_endpoint, base::OnceClosure mojo_disconnected_callback, base::OnceCallback<
diff --git a/chrome/browser/chromeos/crosapi/environment_provider.cc b/chrome/browser/chromeos/crosapi/environment_provider.cc new file mode 100644 index 0000000..1f1370c --- /dev/null +++ b/chrome/browser/chromeos/crosapi/environment_provider.cc
@@ -0,0 +1,27 @@ +// 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/crosapi/environment_provider.h" +#include "chrome/browser/chromeos/profiles/profile_helper.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/profiles/profiles_state.h" +#include "components/user_manager/user.h" +#include "components/user_manager/user_manager.h" + +crosapi::EnvironmentProvider::EnvironmentProvider() = default; +crosapi::EnvironmentProvider::~EnvironmentProvider() = default; + +crosapi::mojom::SessionType crosapi::EnvironmentProvider::GetSessionType() { + const user_manager::User* const user = + user_manager::UserManager::Get()->GetActiveUser(); + const Profile* const profile = + chromeos::ProfileHelper::Get()->GetProfileByUser(user); + if (profile->IsGuestSession()) { + return crosapi::mojom::SessionType::kGuestSession; + } + if (profiles::IsPublicSession()) { + return crosapi::mojom::SessionType::kPublicSession; + } + return crosapi::mojom::SessionType::kRegularSession; +}
diff --git a/chrome/browser/chromeos/crosapi/environment_provider.h b/chrome/browser/chromeos/crosapi/environment_provider.h new file mode 100644 index 0000000..8c02e4a86 --- /dev/null +++ b/chrome/browser/chromeos/crosapi/environment_provider.h
@@ -0,0 +1,26 @@ +// 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_CROSAPI_ENVIRONMENT_PROVIDER_H_ +#define CHROME_BROWSER_CHROMEOS_CROSAPI_ENVIRONMENT_PROVIDER_H_ + +#include "chromeos/crosapi/mojom/crosapi.mojom.h" + +namespace crosapi { + +// Provides ash-chrome specific flags/configurations (like session type). +class EnvironmentProvider { + public: + EnvironmentProvider(); + EnvironmentProvider(const EnvironmentProvider&) = delete; + EnvironmentProvider& operator=(const EnvironmentProvider&) = delete; + virtual ~EnvironmentProvider(); + + // Virtual for tests. + virtual crosapi::mojom::SessionType GetSessionType(); +}; + +} // namespace crosapi + +#endif // CHROME_BROWSER_CHROMEOS_CROSAPI_ENVIRONMENT_PROVIDER_H_
diff --git a/chrome/browser/chromeos/crosapi/test_mojo_connection_manager.cc b/chrome/browser/chromeos/crosapi/test_mojo_connection_manager.cc index 3e00073..5799249 100644 --- a/chrome/browser/chromeos/crosapi/test_mojo_connection_manager.cc +++ b/chrome/browser/chromeos/crosapi/test_mojo_connection_manager.cc
@@ -24,6 +24,12 @@ namespace { +class FakeEnvironmentProvider : public EnvironmentProvider { + crosapi::mojom::SessionType GetSessionType() override { + return crosapi::mojom::SessionType::kRegularSession; + } +}; + // TODO(crbug.com/1124494): Refactor the code to share with ARC. base::ScopedFD CreateSocketForTesting(const base::FilePath& socket_path) { auto endpoint = mojo::NamedPlatformChannel({socket_path.value()}); @@ -45,7 +51,8 @@ } // namespace TestMojoConnectionManager::TestMojoConnectionManager( - const base::FilePath& socket_path) { + const base::FilePath& socket_path) + : environment_provider_(std::make_unique<FakeEnvironmentProvider>()) { base::ThreadPool::PostTaskAndReplyWithResult( FROM_HERE, {base::MayBlock()}, base::BindOnce(&CreateSocketForTesting, socket_path), @@ -79,7 +86,7 @@ // TODO(crbug.com/1124490): Support multiple mojo connections from lacros. mojo::PlatformChannel channel; lacros_chrome_service_ = browser_util::SendMojoInvitationToLacrosChrome( - channel.TakeLocalEndpoint(), + environment_provider_.get(), channel.TakeLocalEndpoint(), base::BindOnce(&TestMojoConnectionManager::OnMojoDisconnected, weak_factory_.GetWeakPtr()), base::BindOnce(
diff --git a/chrome/browser/chromeos/crosapi/test_mojo_connection_manager.h b/chrome/browser/chromeos/crosapi/test_mojo_connection_manager.h index f52bf516..9e5999ce 100644 --- a/chrome/browser/chromeos/crosapi/test_mojo_connection_manager.h +++ b/chrome/browser/chromeos/crosapi/test_mojo_connection_manager.h
@@ -13,6 +13,7 @@ #include "base/files/file_path.h" #include "base/files/scoped_file.h" #include "base/memory/weak_ptr.h" +#include "chrome/browser/chromeos/crosapi/environment_provider.h" #include "chromeos/crosapi/mojom/crosapi.mojom.h" #include "mojo/public/cpp/bindings/remote.h" @@ -76,6 +77,9 @@ std::unique_ptr<base::FileDescriptorWatcher::Controller> testing_socket_watcher_; + // Used to pass ash-chrome specific flags/configurations to lacros-chrome. + std::unique_ptr<EnvironmentProvider> environment_provider_; + base::WeakPtrFactory<TestMojoConnectionManager> weak_factory_{this}; };
diff --git a/chrome/browser/chromeos/login/saml/in_session_password_sync_manager.cc b/chrome/browser/chromeos/login/saml/in_session_password_sync_manager.cc index e7cc47a..b9440d1f 100644 --- a/chrome/browser/chromeos/login/saml/in_session_password_sync_manager.cc +++ b/chrome/browser/chromeos/login/saml/in_session_password_sync_manager.cc
@@ -26,7 +26,6 @@ clock_(base::DefaultClock::GetInstance()), primary_user_(ProfileHelper::Get()->GetUserByProfile(primary_profile)) { DCHECK(primary_user_); - auto* session_manager = session_manager::SessionManager::Get(); // Extra check as SessionManager may be not initialized in some unit // tests
diff --git a/chrome/browser/chromeos/login/saml/in_session_password_sync_manager.h b/chrome/browser/chromeos/login/saml/in_session_password_sync_manager.h index a0e4867..80d82b0 100644 --- a/chrome/browser/chromeos/login/saml/in_session_password_sync_manager.h +++ b/chrome/browser/chromeos/login/saml/in_session_password_sync_manager.h
@@ -13,6 +13,7 @@ #include "base/time/time.h" #include "chrome/browser/chromeos/login/saml/password_sync_token_fetcher.h" #include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/webui/chromeos/in_session_password_change/lock_screen_reauth_dialogs.h" #include "chromeos/components/proximity_auth/screenlock_bridge.h" #include "components/account_id/account_id.h" #include "components/keyed_service/core/keyed_service.h" @@ -81,6 +82,8 @@ void OnTokenVerified(bool is_valid) override; void OnApiCallFailed(PasswordSyncTokenFetcher::ErrorType error_type) override; + std::unique_ptr<LockScreenStartReauthDialog> lock_screen_start_reauth_dialog; + private: void UpdateOnlineAuth(); // Password sync token API calls.
diff --git a/chrome/browser/chromeos/login/screens/family_link_notice_browsertest.cc b/chrome/browser/chromeos/login/screens/family_link_notice_browsertest.cc index 1922273..dae11650 100644 --- a/chrome/browser/chromeos/login/screens/family_link_notice_browsertest.cc +++ b/chrome/browser/chromeos/login/screens/family_link_notice_browsertest.cc
@@ -9,9 +9,9 @@ #include "chrome/browser/chromeos/login/test/local_policy_test_server_mixin.h" #include "chrome/browser/chromeos/login/test/login_manager_mixin.h" #include "chrome/browser/chromeos/login/test/oobe_base_test.h" -#include "chrome/browser/chromeos/login/test/oobe_screen_exit_waiter.h" #include "chrome/browser/chromeos/login/test/oobe_screen_waiter.h" #include "chrome/browser/chromeos/login/test/user_policy_mixin.h" +#include "chrome/browser/chromeos/login/test/wizard_controller_screen_exit_waiter.h" #include "chrome/browser/chromeos/login/ui/login_display_host.h" #include "chrome/browser/chromeos/login/wizard_controller.h" #include "chrome/browser/profiles/profile_manager.h" @@ -53,7 +53,7 @@ void LoginAsRegularUser() { login_manager_mixin_.LoginAsNewRegularUser(); - OobeScreenExitWaiter(UserCreationView::kScreenId).Wait(); + WizardControllerExitWaiter(UserCreationView::kScreenId).Wait(); } void ExpectHelpAppPrefValue(bool expected) { @@ -145,7 +145,7 @@ void LoginAsChildUser() { login_manager_mixin_.LoginAsNewChildUser(); - OobeScreenExitWaiter(UserCreationView::kScreenId).Wait(); + WizardControllerExitWaiter(UserCreationView::kScreenId).Wait(); } private: @@ -186,7 +186,7 @@ void LoginAsManagedUser() { user_policy_mixin_.RequestPolicyUpdate(); login_manager_mixin_.LoginWithDefaultContext(test_user_); - OobeScreenExitWaiter(UserCreationView::kScreenId).Wait(); + WizardControllerExitWaiter(UserCreationView::kScreenId).Wait(); } private:
diff --git a/chrome/browser/chromeos/login/test/oobe_screen_exit_waiter.cc b/chrome/browser/chromeos/login/test/oobe_screen_exit_waiter.cc index 6a7cce6..2114e87 100644 --- a/chrome/browser/chromeos/login/test/oobe_screen_exit_waiter.cc +++ b/chrome/browser/chromeos/login/test/oobe_screen_exit_waiter.cc
@@ -17,14 +17,14 @@ OobeScreenExitWaiter::~OobeScreenExitWaiter() = default; void OobeScreenExitWaiter::Wait() { - DCHECK_EQ(State::IDLE, state_); + ASSERT_EQ(State::IDLE, state_); OobeUI* oobe_ui = GetOobeUI(); if (!oobe_ui || oobe_ui->current_screen() != target_screen_) { state_ = State::DONE; return; } - DCHECK(!run_loop_); + ASSERT_FALSE(run_loop_); oobe_ui_observer_.Add(GetOobeUI()); @@ -43,7 +43,7 @@ void OobeScreenExitWaiter::OnCurrentScreenChanged(OobeScreenId current_screen, OobeScreenId new_screen) { - DCHECK_NE(state_, State::IDLE); + ASSERT_NE(state_, State::IDLE); if (new_screen != target_screen_) EndWait(); }
diff --git a/chrome/browser/chromeos/login/test/wizard_controller_screen_exit_waiter.cc b/chrome/browser/chromeos/login/test/wizard_controller_screen_exit_waiter.cc new file mode 100644 index 0000000..692f768 --- /dev/null +++ b/chrome/browser/chromeos/login/test/wizard_controller_screen_exit_waiter.cc
@@ -0,0 +1,71 @@ +// 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/login/test/wizard_controller_screen_exit_waiter.h" + +#include "base/logging.h" +#include "base/run_loop.h" +#include "chrome/browser/chromeos/login/wizard_controller.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace chromeos { + +WizardControllerExitWaiter::WizardControllerExitWaiter(OobeScreenId screen_id) + : WizardControllerExitWaiter( + WizardController::default_controller()->GetScreen(screen_id)) {} + +WizardControllerExitWaiter::WizardControllerExitWaiter( + BaseScreen* target_screen) + : target_screen_(target_screen) {} + +WizardControllerExitWaiter::~WizardControllerExitWaiter() = default; + +void WizardControllerExitWaiter::Wait() { + ASSERT_EQ(State::IDLE, state_); + + WizardController* wizard_controller = WizardController::default_controller(); + if (!wizard_controller || + wizard_controller->current_screen() != target_screen_) { + state_ = State::DONE; + return; + } + ASSERT_FALSE(run_loop_); + + screen_observer_.Add(wizard_controller); + + state_ = State::WAITING_FOR_SCREEN_EXIT; + + LOG(INFO) << "Actually waiting for exiting screen " + << target_screen_->screen_id(); + + run_loop_ = std::make_unique<base::RunLoop>(); + run_loop_->Run(); + run_loop_.reset(); + + ASSERT_EQ(State::DONE, state_); + + screen_observer_.RemoveAll(); +} + +void WizardControllerExitWaiter::OnCurrentScreenChanged( + BaseScreen* new_screen) { + ASSERT_NE(state_, State::IDLE); + if (new_screen != target_screen_) + EndWait(); +} + +void WizardControllerExitWaiter::OnShutdown() { + screen_observer_.RemoveAll(); + EndWait(); +} + +void WizardControllerExitWaiter::EndWait() { + if (state_ == State::DONE) + return; + + state_ = State::DONE; + run_loop_->Quit(); +} + +} // namespace chromeos
diff --git a/chrome/browser/chromeos/login/test/wizard_controller_screen_exit_waiter.h b/chrome/browser/chromeos/login/test/wizard_controller_screen_exit_waiter.h new file mode 100644 index 0000000..63b5efe --- /dev/null +++ b/chrome/browser/chromeos/login/test/wizard_controller_screen_exit_waiter.h
@@ -0,0 +1,54 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_TEST_WIZARD_CONTROLLER_SCREEN_EXIT_WAITER_H_ +#define CHROME_BROWSER_CHROMEOS_LOGIN_TEST_WIZARD_CONTROLLER_SCREEN_EXIT_WAITER_H_ + +#include "base/macros.h" +#include "base/scoped_observer.h" +#include "chrome/browser/chromeos/login/oobe_screen.h" +#include "chrome/browser/chromeos/login/screens/base_screen.h" +#include "chrome/browser/chromeos/login/test/test_condition_waiter.h" +#include "chrome/browser/chromeos/login/wizard_controller.h" + +namespace base { +class RunLoop; +} + +namespace chromeos { + +// A waiter that blocks until the the current WizardController screen is +// different than the target screen, or the WizardController is destroyed. +class WizardControllerExitWaiter : public test::TestConditionWaiter, + public WizardController::ScreenObserver { + public: + explicit WizardControllerExitWaiter(OobeScreenId screen_id); + explicit WizardControllerExitWaiter(BaseScreen* target_screen); + ~WizardControllerExitWaiter() override; + + // WizardController::ScreenObserver: + void OnCurrentScreenChanged(BaseScreen* new_screen) override; + void OnShutdown() override; + + // TestConditionWaiter; + void Wait() override; + + private: + enum class State { IDLE, WAITING_FOR_SCREEN_EXIT, DONE }; + + void EndWait(); + + const BaseScreen* target_screen_; + + State state_ = State::IDLE; + + ScopedObserver<WizardController, WizardController::ScreenObserver> + screen_observer_{this}; + + std::unique_ptr<base::RunLoop> run_loop_; +}; + +} // namespace chromeos + +#endif // CHROME_BROWSER_CHROMEOS_LOGIN_TEST_WIZARD_CONTROLLER_SCREEN_EXIT_WAITER_H_
diff --git a/chrome/browser/chromeos/login/wizard_controller.cc b/chrome/browser/chromeos/login/wizard_controller.cc index ada2e1a..9b8805f 100644 --- a/chrome/browser/chromeos/login/wizard_controller.cc +++ b/chrome/browser/chromeos/login/wizard_controller.cc
@@ -371,6 +371,8 @@ } WizardController::~WizardController() { + for (ScreenObserver& obs : screen_observers_) + obs.OnShutdown(); screen_manager_.reset(); } @@ -1572,8 +1574,10 @@ previous_screen_ = current_screen_; current_screen_ = new_current; - if (!current_screen_) + if (!current_screen_) { + NotifyScreenChanged(); return; + } // Record show time for UMA. screen_show_times_[new_current->screen_id()] = base::TimeTicks::Now(); @@ -1586,6 +1590,7 @@ UpdateStatusAreaVisibilityForScreen(current_screen_->screen_id()); current_screen_->Show(wizard_context_.get()); + NotifyScreenChanged(); } void WizardController::UpdateStatusAreaVisibilityForScreen( @@ -1874,6 +1879,14 @@ screen_id == GaiaView::kScreenId; } +void WizardController::AddObserver(ScreenObserver* obs) { + screen_observers_.AddObserver(obs); +} + +void WizardController::RemoveObserver(ScreenObserver* obs) { + screen_observers_.RemoveObserver(obs); +} + void WizardController::OnLocalStateInitialized(bool /* succeeded */) { if (GetLocalState()->GetInitializationStatus() != PrefService::INITIALIZATION_STATUS_ERROR) { @@ -2033,6 +2046,11 @@ SetCurrentScreen(screen); } +void WizardController::NotifyScreenChanged() { + for (ScreenObserver& obs : screen_observers_) + obs.OnCurrentScreenChanged(current_screen_); +} + AutoEnrollmentController* WizardController::GetAutoEnrollmentController() { if (!auto_enrollment_controller_) auto_enrollment_controller_ = std::make_unique<AutoEnrollmentController>();
diff --git a/chrome/browser/chromeos/login/wizard_controller.h b/chrome/browser/chromeos/login/wizard_controller.h index da9c0fe..0161eb5 100644 --- a/chrome/browser/chromeos/login/wizard_controller.h +++ b/chrome/browser/chromeos/login/wizard_controller.h
@@ -70,6 +70,12 @@ // interacts with screen controllers to move the user between screens. class WizardController { public: + class ScreenObserver : public base::CheckedObserver { + public: + virtual void OnCurrentScreenChanged(BaseScreen* new_screen) = 0; + virtual void OnShutdown() = 0; + }; + WizardController(); ~WizardController(); @@ -203,6 +209,9 @@ return first_screen_for_testing_; } + void AddObserver(ScreenObserver* obs); + void RemoveObserver(ScreenObserver* obs); + private: // Create BaseScreen instances. These are owned by |screen_manager_|. std::vector<std::unique_ptr<BaseScreen>> CreateScreens(); @@ -373,9 +382,7 @@ // attestation-based enrollment if appropriate. void StartEnrollmentScreen(bool force_interactive); - void OnConfigurationLoaded( - OobeScreenId first_screen, - std::unique_ptr<base::DictionaryValue> configuration); + void NotifyScreenChanged(); // Returns auto enrollment controller (lazily initializes one if it doesn't // exist already). @@ -462,6 +469,8 @@ bool is_initialized_ = false; + base::ObserverList<ScreenObserver> screen_observers_; + base::WeakPtrFactory<WizardController> weak_factory_{this}; DISALLOW_COPY_AND_ASSIGN(WizardController);
diff --git a/chrome/browser/chromeos/platform_keys/key_permissions/key_permissions_manager_user_service.h b/chrome/browser/chromeos/platform_keys/key_permissions/key_permissions_manager_user_service.h deleted file mode 100644 index d5996c9..0000000 --- a/chrome/browser/chromeos/platform_keys/key_permissions/key_permissions_manager_user_service.h +++ /dev/null
@@ -1,54 +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 CHROME_BROWSER_CHROMEOS_PLATFORM_KEYS_KEY_PERMISSIONS_KEY_PERMISSIONS_MANAGER_USER_SERVICE_H_ -#define CHROME_BROWSER_CHROMEOS_PLATFORM_KEYS_KEY_PERMISSIONS_KEY_PERMISSIONS_MANAGER_USER_SERVICE_H_ - -#include "base/no_destructor.h" -#include "chrome/browser/chromeos/platform_keys/key_permissions/key_permissions_manager.h" -#include "components/keyed_service/content/browser_context_keyed_service_factory.h" -#include "components/keyed_service/core/keyed_service.h" - -namespace user_prefs { -class PrefRegistrySyncable; -} - -namespace chromeos { -namespace platform_keys { - -// KeyPermissionsManagerUserService is a wrapper over KeyPermissionsManager -// (KPM) to provide KPMs keyed by profile. KPM is not a KeyedService by itself -// so as future work can introduce a global device-wide KPM instance. -class KeyPermissionsManagerUserService : public KeyedService { - public: - KeyPermissionsManagerUserService(); - ~KeyPermissionsManagerUserService() override; - - virtual KeyPermissionsManager* key_permissions_manager() = 0; -}; - -class KeyPermissionsManagerUserServiceFactory - : public BrowserContextKeyedServiceFactory { - public: - static KeyPermissionsManagerUserService* GetForBrowserContext( - content::BrowserContext* context); - static KeyPermissionsManagerUserServiceFactory* GetInstance(); - - private: - friend class base::NoDestructor<KeyPermissionsManagerUserServiceFactory>; - - KeyPermissionsManagerUserServiceFactory(); - ~KeyPermissionsManagerUserServiceFactory() override = default; - - // BrowserStateKeyedServiceFactory. - KeyedService* BuildServiceInstanceFor( - content::BrowserContext* context) const override; - void RegisterProfilePrefs( - user_prefs::PrefRegistrySyncable* registry) override; -}; - -} // namespace platform_keys -} // namespace chromeos - -#endif // CHROME_BROWSER_CHROMEOS_PLATFORM_KEYS_KEY_PERMISSIONS_KEY_PERMISSIONS_MANAGER_USER_SERVICE_H_
diff --git a/chrome/browser/chromeos/policy/device_cloud_policy_store_chromeos.cc b/chrome/browser/chromeos/policy/device_cloud_policy_store_chromeos.cc index 365aa553..9dec32e 100644 --- a/chrome/browser/chromeos/policy/device_cloud_policy_store_chromeos.cc +++ b/chrome/browser/chromeos/policy/device_cloud_policy_store_chromeos.cc
@@ -206,9 +206,14 @@ if (service_status == chromeos::DeviceSettingsService::STORE_SUCCESS) { policy_ = std::make_unique<em::PolicyData>(); const em::PolicyData* policy_data = device_settings_service_->policy_data(); - if (policy_data) + if (policy_data) { policy_->MergeFrom(*policy_data); + RecordDeviceIdValidityMetric( + "Enterprise.CachedDevicePolicyDeviceIdValidity", *policy_data, + *install_attributes_); + } + PolicyMap new_policy_map; if (is_managed()) { DecodeDevicePolicy(*device_settings_service_->device_settings(),
diff --git a/chrome/browser/chromeos/policy/dlp/enterprise_clipboard_dlp_controller.cc b/chrome/browser/chromeos/policy/dlp/enterprise_clipboard_dlp_controller.cc index 80183a1..29a2dc0 100644 --- a/chrome/browser/chromeos/policy/dlp/enterprise_clipboard_dlp_controller.cc +++ b/chrome/browser/chromeos/policy/dlp/enterprise_clipboard_dlp_controller.cc
@@ -8,7 +8,9 @@ #include "ash/public/cpp/toast_data.h" #include "ash/public/cpp/toast_manager.h" +#include "base/notreached.h" #include "base/optional.h" +#include "base/strings/utf_string_conversions.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/chromeos/crostini/crostini_util.h" #include "chrome/browser/chromeos/plugin_vm/plugin_vm_util.h" @@ -60,13 +62,16 @@ DlpRulesManager::Component::kPluginVm, DlpRulesManager::Component::kCrostini}, DlpRulesManager::Restriction::kClipboard); + } else if (data_dst->type() == ui::EndpointType::kArc) { + level = DlpRulesManager::Get()->IsRestrictedComponent( + data_src->origin()->GetURL(), DlpRulesManager::Component::kArc, + DlpRulesManager::Restriction::kClipboard); } else { NOTREACHED(); } - // TODO(crbug.com/1129345): Add a separate handling for ARC if (level == DlpRulesManager::Level::kBlock) { - ShowBlockToast(GetToastText(data_dst)); + ShowBlockToast(GetToastText(data_src, data_dst)); } return level == DlpRulesManager::Level::kAllow; @@ -81,7 +86,12 @@ } base::string16 EnterpriseClipboardDlpController::GetToastText( + const ui::ClipboardDataEndpoint* const data_src, const ui::ClipboardDataEndpoint* const data_dst) const { + DCHECK(data_src); + DCHECK(data_src->origin()); + base::string16 host_name = base::UTF8ToUTF16(data_src->origin()->host()); + if (data_dst && data_dst->type() == ui::EndpointType::kGuestOs) { ProfileManager* profile_manager = g_browser_process->profile_manager(); Profile* profile = @@ -92,22 +102,30 @@ if (is_crostini_running && is_plugin_vm_running) { return l10n_util::GetStringFUTF16( - IDS_POLICY_DLP_CLIPBOARD_BLOCKED_ON_COPY_TWO_VMS, + IDS_POLICY_DLP_CLIPBOARD_BLOCKED_ON_COPY_TWO_VMS, host_name, l10n_util::GetStringUTF16(IDS_CROSTINI_LINUX), l10n_util::GetStringUTF16(IDS_PLUGIN_VM_APP_NAME)); } else if (is_crostini_running) { return l10n_util::GetStringFUTF16( - IDS_POLICY_DLP_CLIPBOARD_BLOCKED_ON_COPY_VM, + IDS_POLICY_DLP_CLIPBOARD_BLOCKED_ON_COPY_VM, host_name, l10n_util::GetStringUTF16(IDS_CROSTINI_LINUX)); } else if (is_plugin_vm_running) { return l10n_util::GetStringFUTF16( - IDS_POLICY_DLP_CLIPBOARD_BLOCKED_ON_COPY_VM, + IDS_POLICY_DLP_CLIPBOARD_BLOCKED_ON_COPY_VM, host_name, l10n_util::GetStringUTF16(IDS_PLUGIN_VM_APP_NAME)); } else { NOTREACHED(); } } - return l10n_util::GetStringUTF16(IDS_POLICY_DLP_CLIPBOARD_BLOCKED_ON_PASTE); + + if (data_dst && data_dst->type() == ui::EndpointType::kArc) { + return l10n_util::GetStringFUTF16( + IDS_POLICY_DLP_CLIPBOARD_BLOCKED_ON_COPY_VM, host_name, + l10n_util::GetStringUTF16(IDS_POLICY_DLP_ANDROID_APPS)); + } + + return l10n_util::GetStringFUTF16(IDS_POLICY_DLP_CLIPBOARD_BLOCKED_ON_PASTE, + host_name); } } // namespace policy
diff --git a/chrome/browser/chromeos/policy/dlp/enterprise_clipboard_dlp_controller.h b/chrome/browser/chromeos/policy/dlp/enterprise_clipboard_dlp_controller.h index 7529be1..bc4254e6 100644 --- a/chrome/browser/chromeos/policy/dlp/enterprise_clipboard_dlp_controller.h +++ b/chrome/browser/chromeos/policy/dlp/enterprise_clipboard_dlp_controller.h
@@ -38,8 +38,9 @@ void ShowBlockToast(const base::string16& text) const; // The text will be different if the clipboard data is shared with Crostini - // or Parallels or both of them. + // or Parallels or ARC. base::string16 GetToastText( + const ui::ClipboardDataEndpoint* const data_src, const ui::ClipboardDataEndpoint* const data_dst) const; };
diff --git a/chrome/browser/extensions/api/passwords_private/password_check_delegate_unittest.cc b/chrome/browser/extensions/api/passwords_private/password_check_delegate_unittest.cc index 073767d9..4a65754 100644 --- a/chrome/browser/extensions/api/passwords_private/password_check_delegate_unittest.cc +++ b/chrome/browser/extensions/api/passwords_private/password_check_delegate_unittest.cc
@@ -25,7 +25,7 @@ #include "chrome/browser/extensions/api/passwords_private/passwords_private_event_router.h" #include "chrome/browser/extensions/api/passwords_private/passwords_private_event_router_factory.h" #include "chrome/browser/password_manager/bulk_leak_check_service_factory.h" -#include "chrome/browser/password_manager/password_store_factory.h" +#include "chrome/browser/password_manager/password_manager_test_util.h" #include "chrome/common/extensions/api/passwords_private.h" #include "chrome/test/base/testing_profile.h" #include "components/keyed_service/core/keyed_service.h" @@ -120,17 +120,6 @@ }))); } -scoped_refptr<TestPasswordStore> CreateAndUseTestPasswordStore( - Profile* profile) { - return base::WrapRefCounted(static_cast<TestPasswordStore*>( - PasswordStoreFactory::GetInstance() - ->SetTestingFactoryAndUse( - profile, - base::BindRepeating(&password_manager::BuildPasswordStore< - content::BrowserContext, TestPasswordStore>)) - .get())); -} - BulkLeakCheckService* CreateAndUseBulkLeakCheckService( signin::IdentityManager* identity_manager, Profile* profile) {
diff --git a/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl_unittest.cc b/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl_unittest.cc index a48896f8..0564e2a 100644 --- a/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl_unittest.cc +++ b/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl_unittest.cc
@@ -25,7 +25,7 @@ #include "chrome/browser/extensions/api/passwords_private/passwords_private_event_router_factory.h" #include "chrome/browser/password_manager/account_password_store_factory.h" #include "chrome/browser/password_manager/chrome_password_manager_client.h" -#include "chrome/browser/password_manager/password_store_factory.h" +#include "chrome/browser/password_manager/password_manager_test_util.h" #include "chrome/common/extensions/api/passwords_private.h" #include "chrome/test/base/testing_profile.h" #include "components/autofill/core/common/password_form.h" @@ -67,17 +67,6 @@ using MockPlaintextPasswordCallback = base::MockCallback<PasswordsPrivateDelegate::PlaintextPasswordCallback>; -scoped_refptr<TestPasswordStore> CreateAndUseTestPasswordStore( - Profile* profile) { - return base::WrapRefCounted(static_cast<TestPasswordStore*>( - PasswordStoreFactory::GetInstance() - ->SetTestingFactoryAndUse( - profile, - base::BindRepeating(&password_manager::BuildPasswordStore< - content::BrowserContext, TestPasswordStore>)) - .get())); -} - scoped_refptr<TestPasswordStore> CreateAndUseTestAccountPasswordStore( Profile* profile) { if (!base::FeatureList::IsEnabled(
diff --git a/chrome/browser/extensions/forced_extensions/force_installed_metrics_unittest.cc b/chrome/browser/extensions/forced_extensions/force_installed_metrics_unittest.cc index 897c589..21d8c03 100644 --- a/chrome/browser/extensions/forced_extensions/force_installed_metrics_unittest.cc +++ b/chrome/browser/extensions/forced_extensions/force_installed_metrics_unittest.cc
@@ -865,7 +865,8 @@ } // Errors occurred because the fetched update manifest was invalid because app -// status was not OK. +// status was not OK. Verifies that this error with app status error as +// "error-unknownApplication" is considered as a misconfiguration. TEST_F(ForceInstalledMetricsTest, ExtensionManifestInvalidAppStatusError) { SetupForceList(); auto extension = @@ -883,6 +884,11 @@ histogram_tester_.ExpectUniqueSample( kExtensionManifestInvalidAppStatusError, InstallStageTracker::AppStatusError::kErrorUnknownApplication, 1); + // Verify that the session with either all the extensions installed + // successfully, or all failures as admin-side misconfigurations is recorded + // here and BAD_APP_STATUS error is considered as a misconfiguration. + histogram_tester_.ExpectBucketCount(kPossibleNonMisconfigurationFailures, 0, + 1); } // Session in which either all the extensions installed successfully, or all
diff --git a/chrome/browser/extensions/forced_extensions/force_installed_tracker.cc b/chrome/browser/extensions/forced_extensions/force_installed_tracker.cc index d736a6c..3e471a4 100644 --- a/chrome/browser/extensions/forced_extensions/force_installed_tracker.cc +++ b/chrome/browser/extensions/forced_extensions/force_installed_tracker.cc
@@ -224,6 +224,13 @@ } } + if (installation_data.manifest_invalid_error == + ManifestInvalidError::BAD_APP_STATUS && + installation_data.app_status_error == + InstallStageTracker::AppStatusError::kErrorUnknownApplication) { + return true; + } + return false; }
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json index e4478c8..f3f3d6b 100644 --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json
@@ -2340,7 +2340,7 @@ { "name": "enable-webrtc-pipewire-capturer", "owners": [ "tomas.popela@gmail.com" ], - "expiry_milestone": 86 + "expiry_milestone": 90 }, { "name": "enable-webrtc-remote-event-log",
diff --git a/chrome/browser/importer/profile_writer_unittest.cc b/chrome/browser/importer/profile_writer_unittest.cc index 7bc05e0..63eb09ee 100644 --- a/chrome/browser/importer/profile_writer_unittest.cc +++ b/chrome/browser/importer/profile_writer_unittest.cc
@@ -17,7 +17,7 @@ #include "chrome/browser/bookmarks/bookmark_model_factory.h" #include "chrome/browser/history/history_service_factory.h" #include "chrome/browser/importer/importer_unittest_utils.h" -#include "chrome/browser/password_manager/password_store_factory.h" +#include "chrome/browser/password_manager/password_manager_test_util.h" #include "chrome/browser/search_engines/template_url_service_factory.h" #include "chrome/common/importer/imported_bookmark_entry.h" #include "chrome/test/base/testing_profile.h" @@ -42,17 +42,6 @@ using bookmarks::UrlAndTitle; using password_manager::TestPasswordStore; -scoped_refptr<TestPasswordStore> CreateAndUseTestPasswordStore( - Profile* profile) { - return base::WrapRefCounted(static_cast<TestPasswordStore*>( - PasswordStoreFactory::GetInstance() - ->SetTestingFactoryAndUse( - profile, - base::BindRepeating(&password_manager::BuildPasswordStore< - content::BrowserContext, TestPasswordStore>)) - .get())); -} - PasswordForm MakePasswordForm() { PasswordForm form; form.url = GURL("https://example.com/");
diff --git a/chrome/browser/nearby_sharing/local_device_data/nearby_share_local_device_data_manager_impl_unittest.cc b/chrome/browser/nearby_sharing/local_device_data/nearby_share_local_device_data_manager_impl_unittest.cc index b6e2da65..e06b66f8 100644 --- a/chrome/browser/nearby_sharing/local_device_data/nearby_share_local_device_data_manager_impl_unittest.cc +++ b/chrome/browser/nearby_sharing/local_device_data/nearby_share_local_device_data_manager_impl_unittest.cc
@@ -8,6 +8,7 @@ #include "base/optional.h" #include "base/test/bind_test_util.h" +#include "build/build_config.h" #include "chrome/browser/nearby_sharing/client/fake_nearby_share_client.h" #include "chrome/browser/nearby_sharing/common/nearby_share_prefs.h" #include "chrome/browser/nearby_sharing/local_device_data/fake_nearby_share_device_data_updater.h" @@ -259,7 +260,13 @@ EXPECT_EQ(id, manager()->GetId()); } -TEST_F(NearbyShareLocalDeviceDataManagerImplTest, ValidateDeviceName) { +// Test is flaky. crbug.com/1133295. +#if defined(OS_CHROMEOS) +#define MAYBE_ValidateDeviceName DISABLED_ValidateDeviceName +#else +#define MAYBE_ValidateDeviceName ValidateDeviceName +#endif +TEST_F(NearbyShareLocalDeviceDataManagerImplTest, MAYBE_ValidateDeviceName) { CreateManager(); EXPECT_EQ(manager()->ValidateDeviceName(kFakeDeviceName), nearby_share::mojom::DeviceNameValidationResult::kValid); @@ -272,7 +279,13 @@ nearby_share::mojom::DeviceNameValidationResult::kErrorNotValidUtf8); } -TEST_F(NearbyShareLocalDeviceDataManagerImplTest, SetDeviceName) { +// Test is flaky. crbug.com/1133295. +#if defined(OS_CHROMEOS) +#define MAYBE_SetDeviceName DISABLED_SetDeviceName +#else +#define MAYBE_SetDeviceName SetDeviceName +#endif +TEST_F(NearbyShareLocalDeviceDataManagerImplTest, MAYBE_SetDeviceName) { CreateManager(); // The default device name is set in the ctor when the device name is empty.
diff --git a/chrome/browser/password_check/android/password_check_manager_unittest.cc b/chrome/browser/password_check/android/password_check_manager_unittest.cc index c38db36c..0511a69 100644 --- a/chrome/browser/password_check/android/password_check_manager_unittest.cc +++ b/chrome/browser/password_check/android/password_check_manager_unittest.cc
@@ -16,8 +16,8 @@ #include "base/time/time.h" #include "chrome/browser/password_check/android/password_check_ui_status.h" #include "chrome/browser/password_manager/bulk_leak_check_service_factory.h" +#include "chrome/browser/password_manager/password_manager_test_util.h" #include "chrome/browser/password_manager/password_scripts_fetcher_factory.h" -#include "chrome/browser/password_manager/password_store_factory.h" #include "chrome/browser/sync/profile_sync_service_factory.h" #include "chrome/test/base/testing_profile.h" #include "components/password_manager/core/browser/bulk_leak_check_service.h" @@ -97,19 +97,6 @@ MOCK_METHOD(bool, IsScriptAvailable, (const url::Origin&), (const override)); }; -// TODO(crbug.com/1112804): Extract this into a password manager test utils -// file, since it's used across multiple tests. -scoped_refptr<TestPasswordStore> CreateAndUseTestPasswordStore( - Profile* profile) { - return base::WrapRefCounted(static_cast<TestPasswordStore*>( - PasswordStoreFactory::GetInstance() - ->SetTestingFactoryAndUse( - profile, - base::BindRepeating(&password_manager::BuildPasswordStore< - content::BrowserContext, TestPasswordStore>)) - .get())); -} - BulkLeakCheckService* CreateAndUseBulkLeakCheckService( signin::IdentityManager* identity_manager, Profile* profile) {
diff --git a/chrome/browser/password_manager/android/all_passwords_bottom_sheet_controller_unittest.cc b/chrome/browser/password_manager/android/all_passwords_bottom_sheet_controller_unittest.cc index 205bb647..b9f2907 100644 --- a/chrome/browser/password_manager/android/all_passwords_bottom_sheet_controller_unittest.cc +++ b/chrome/browser/password_manager/android/all_passwords_bottom_sheet_controller_unittest.cc
@@ -7,7 +7,7 @@ #include "base/strings/utf_string_conversions.h" #include "base/test/mock_callback.h" #include "base/util/type_safety/pass_key.h" -#include "chrome/browser/password_manager/password_store_factory.h" +#include "chrome/browser/password_manager/password_manager_test_util.h" #include "chrome/browser/ui/android/passwords/all_passwords_bottom_sheet_view.h" #include "chrome/test/base/testing_profile.h" #include "components/autofill/core/common/mojom/autofill_types.mojom-forward.h" @@ -82,17 +82,6 @@ return form; } -scoped_refptr<TestPasswordStore> CreateAndUseTestPasswordStore( - Profile* profile) { - return base::WrapRefCounted(static_cast<TestPasswordStore*>( - PasswordStoreFactory::GetInstance() - ->SetTestingFactoryAndUse( - profile, - base::BindRepeating(&password_manager::BuildPasswordStore< - content::BrowserContext, TestPasswordStore>)) - .get())); -} - class AllPasswordsBottomSheetControllerTest : public testing::Test { protected: AllPasswordsBottomSheetControllerTest() {
diff --git a/chrome/browser/password_manager/password_manager_test_util.cc b/chrome/browser/password_manager/password_manager_test_util.cc new file mode 100644 index 0000000..f896557 --- /dev/null +++ b/chrome/browser/password_manager/password_manager_test_util.cc
@@ -0,0 +1,24 @@ +// 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/password_manager/password_manager_test_util.h" + +#include "chrome/browser/password_manager/password_store_factory.h" +#include "chrome/browser/profiles/profile.h" +#include "components/password_manager/core/browser/password_manager_test_utils.h" +#include "components/password_manager/core/browser/test_password_store.h" + +using password_manager::TestPasswordStore; + +scoped_refptr<TestPasswordStore> CreateAndUseTestPasswordStore( + Profile* profile) { + TestPasswordStore* store = static_cast<TestPasswordStore*>( + PasswordStoreFactory::GetInstance() + ->SetTestingFactoryAndUse( + profile, + base::BindRepeating(&password_manager::BuildPasswordStore< + content::BrowserContext, TestPasswordStore>)) + .get()); + return base::WrapRefCounted(store); +}
diff --git a/chrome/browser/password_manager/password_manager_test_util.h b/chrome/browser/password_manager/password_manager_test_util.h new file mode 100644 index 0000000..c90800f2 --- /dev/null +++ b/chrome/browser/password_manager/password_manager_test_util.h
@@ -0,0 +1,18 @@ +// 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_PASSWORD_MANAGER_PASSWORD_MANAGER_TEST_UTIL_H_ +#define CHROME_BROWSER_PASSWORD_MANAGER_PASSWORD_MANAGER_TEST_UTIL_H_ + +#include "base/memory/scoped_refptr.h" + +class Profile; +namespace password_manager { +class TestPasswordStore; +} + +scoped_refptr<password_manager::TestPasswordStore> +CreateAndUseTestPasswordStore(Profile* profile); + +#endif // CHROME_BROWSER_PASSWORD_MANAGER_PASSWORD_MANAGER_TEST_UTIL_H_
diff --git a/chrome/browser/password_manager/password_store_utils.cc b/chrome/browser/password_manager/password_store_utils.cc index 08f26c6a..dc853f1 100644 --- a/chrome/browser/password_manager/password_store_utils.cc +++ b/chrome/browser/password_manager/password_store_utils.cc
@@ -8,8 +8,14 @@ #include "chrome/browser/password_manager/password_store_factory.h" #include "chrome/browser/profiles/profile.h" #include "components/autofill/core/common/password_form.h" +#include "components/password_manager/core/browser/password_manager_metrics_util.h" #include "components/password_manager/core/browser/password_store.h" +namespace { +using password_manager::metrics_util::IsPasswordChanged; +using password_manager::metrics_util::IsUsernameChanged; +} // namespace + void EditSavedPasswords( Profile* profile, const base::span<const std::unique_ptr<autofill::PasswordForm>> @@ -20,8 +26,10 @@ const std::string signon_realm = forms_to_change[0]->signon_realm; - const bool username_changed = - new_username != forms_to_change[0]->username_value; + IsUsernameChanged username_changed(new_username != + forms_to_change[0]->username_value); + IsPasswordChanged password_changed(new_password != + forms_to_change[0]->password_value); // An updated username implies a change in the primary key, thus we need to // make sure to call the right API. Update every entry in the equivalence @@ -47,6 +55,8 @@ store->UpdateLogin(new_form); } } + password_manager::metrics_util::LogPasswordEditResult(username_changed, + password_changed); } scoped_refptr<password_manager::PasswordStore> GetPasswordStore(
diff --git a/chrome/browser/policy/configuration_policy_handler_list_factory.cc b/chrome/browser/policy/configuration_policy_handler_list_factory.cc index b6c26dc..8db2e78 100644 --- a/chrome/browser/policy/configuration_policy_handler_list_factory.cc +++ b/chrome/browser/policy/configuration_policy_handler_list_factory.cc
@@ -709,6 +709,9 @@ { key::kURLsToNotCheckComplianceOfUploadedContent, prefs::kURLsToNotCheckComplianceOfUploadedContent, base::Value::Type::LIST }, + { key::kWebRtcAllowLegacyTLSProtocols, + prefs::kWebRTCAllowLegacyTLSProtocols, + base::Value::Type::BOOLEAN }, #endif // defined(OS_ANDROID) #if defined(OS_CHROMEOS)
diff --git a/chrome/browser/profiles/profile.cc b/chrome/browser/profiles/profile.cc index b841f58..ca36c316 100644 --- a/chrome/browser/profiles/profile.cc +++ b/chrome/browser/profiles/profile.cc
@@ -9,6 +9,7 @@ #include "base/path_service.h" #include "base/strings/string_util.h" #include "build/build_config.h" +#include "build/chromeos_buildflags.h" #include "chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.h" #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/net/profile_network_context_service.h" @@ -64,6 +65,10 @@ #include "extensions/browser/pref_names.h" #endif +#if BUILDFLAG(IS_LACROS) +#include "chromeos/lacros/lacros_chrome_service_impl.h" +#endif + #if DCHECK_IS_ON() #include <set> @@ -376,8 +381,17 @@ chromeos::switches::kGuestSession); return is_guest_session; #else +#if BUILDFLAG(IS_LACROS) + DCHECK(chromeos::LacrosChromeServiceImpl::Get()); + if (chromeos::LacrosChromeServiceImpl::Get()->init_params()->session_type != + crosapi::mojom::SessionType::kUnknown) { + return chromeos::LacrosChromeServiceImpl::Get() + ->init_params() + ->session_type == crosapi::mojom::SessionType::kGuestSession; + } +#endif // BUILDFLAG(IS_LACROS) return is_guest_profile_; -#endif +#endif // defined(OS_CHROMEOS) } bool Profile::IsSystemProfile() const {
diff --git a/chrome/browser/profiles/profiles_state.cc b/chrome/browser/profiles/profiles_state.cc index b338e9f..169aaf1f 100644 --- a/chrome/browser/profiles/profiles_state.cc +++ b/chrome/browser/profiles/profiles_state.cc
@@ -8,6 +8,7 @@ #include "base/files/file_path.h" #include "base/strings/utf_string_conversions.h" #include "build/build_config.h" +#include "build/chromeos_buildflags.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.h" #include "chrome/browser/profiles/profile.h" @@ -40,6 +41,10 @@ #include "components/signin/public/base/signin_pref_names.h" #endif +#if BUILDFLAG(IS_LACROS) +#include "chromeos/lacros/lacros_chrome_service_impl.h" +#endif + namespace profiles { bool IsMultipleProfilesEnabled() { @@ -262,6 +267,11 @@ if (chromeos::LoginState::IsInitialized()) { return chromeos::LoginState::Get()->IsPublicSessionUser(); } +#elif BUILDFLAG(IS_LACROS) + DCHECK(chromeos::LacrosChromeServiceImpl::Get()); + return chromeos::LacrosChromeServiceImpl::Get() + ->init_params() + ->session_type == crosapi::mojom::SessionType::kPublicSession; #endif return false; }
diff --git a/chrome/browser/renderer_preferences_util.cc b/chrome/browser/renderer_preferences_util.cc index 7ba5b3d..ddc3c1d 100644 --- a/chrome/browser/renderer_preferences_util.cc +++ b/chrome/browser/renderer_preferences_util.cc
@@ -141,6 +141,8 @@ const base::ListValue* allowed_urls = pref_service->GetList(prefs::kWebRtcLocalIpsAllowedUrls); prefs->webrtc_local_ips_allowed_urls = GetLocalIpsAllowedUrls(allowed_urls); + prefs->webrtc_allow_legacy_tls_protocols = + pref_service->GetBoolean(prefs::kWebRTCAllowLegacyTLSProtocols); #if defined(USE_AURA) prefs->focus_ring_color = SkColorSetRGB(0x4D, 0x90, 0xFE); #if defined(OS_CHROMEOS)
diff --git a/chrome/browser/resources/BUILD.gn b/chrome/browser/resources/BUILD.gn index ddf68c4..60ea26a 100644 --- a/chrome/browser/resources/BUILD.gn +++ b/chrome/browser/resources/BUILD.gn
@@ -510,13 +510,18 @@ } grit("profile_picker_resources") { - source = "signin/profile_picker/profile_picker_resources.grd" - - deps = [ "//chrome/browser/resources/signin/profile_picker:web_components" ] grit_flags = [ "-E", "root_gen_dir=" + rebase_path(root_gen_dir, root_build_dir), ] + if (optimize_webui) { + source = "signin/profile_picker/profile_picker_resources_vulcanized.grd" + deps = [ "//chrome/browser/resources/signin/profile_picker:build" ] + } else { + source = "signin/profile_picker/profile_picker_resources.grd" + deps = + [ "//chrome/browser/resources/signin/profile_picker:web_components" ] + } defines = chrome_grit_defines outputs = [
diff --git a/chrome/browser/resources/chromeos/password_change/lock_screen_reauth.html b/chrome/browser/resources/chromeos/password_change/lock_screen_reauth.html new file mode 100644 index 0000000..c830eb3d --- /dev/null +++ b/chrome/browser/resources/chromeos/password_change/lock_screen_reauth.html
@@ -0,0 +1,129 @@ +<!doctype html> +<html dir="$i18n{textdirection}" lang="$i18n{language}"> + +<head> + <include src="../login/components/oobe_icons.html"> + <link rel="stylesheet" href="chrome://resources/css/text_defaults.css"> + + <script src="chrome://resources/js/cr.js"></script> + <script src="chrome://resources/js/cr/event_target.js"></script> + <script src="chrome://resources/js/load_time_data.js"></script> + <script src="chrome://resources/js/util.js"></script> + <script src="chrome://lock-reauth/authenticator.js"></script> + + <script type="module" src="chrome://lock-reauth/lock_screen_reauth.js"></script> + + <dom-module id="lock-reauth"> + <template> + <style> + ::part(dialog) { + /* The HTML dialog should fill the entire system dialog. */ + height: 100%; + width: 100%; + display: flex; + } + + ::part(wrapper) { + height: 100%; + width: 100%; + display: flex; + } + + #saml-close-button { + --cr-icon-button-margin-end: 0; + --cr-icon-button-margin-start: 0; + } + + [slot='body'], + #signin-frame { + width: 100%; + height: 100%; + } + + #title-icon { + --iron-icon-height: 32px; + --iron-icon-width: 32px; + /* #1a73e8 */ + --iron-icon-fill-color: rgb(26, 115, 232); + } + + [slot='header'] { + background: white; + padding-bottom: 0; + padding-inline-end: 64px; + padding-inline-start: 64px; + padding-top: 64px; + flex: 1; + } + + [slot='header'], + #title { + /* #202124 */ + color: rgb(32, 33, 36); + font-size: 28px; + font-weight: 400; + padding-top: 20px; + margin: 0; + } + + [slot='header'], + #subtitle { + /* #5f6368 */ + color: rgb(95, 99, 104); + font-size: 13px; + font-weight: 400; + padding-top: 8px; + margin: 0; + } + + [slot="button-container"] { + padding: 40px; + } + </style> + <cr-dialog id="dialog" exportparts="dialog"> + <div slot="header"> + <iron-icon id="title-icon" icon="oobe-64:alert"></iron-icon> + <div id="title" hidden="[[isErrorDisplayed_]]"> + $i18n{loginWelcomeMessage} + </div> + <div id="title" hidden="[[!isErrorDisplayed_]]"> + $i18n{loginWelcomeMessageWithError} + </div> + <div id="subtitle" hidden="[[isErrorDisplayed_]]"> + $i18n{lockScreenReauthSubtitile} + </div> + <div id="subtitle" hidden="[[!isErrorDisplayed_]]"> + $i18n{lockScreenReauthSubtitileWithError} + </div> + </div> + <div slot="body" hidden="[[isButtonsEnabled_]]"> + <cr-icon-button id="saml-close-button" iron-icon="cr:close" on-click="onCloseTap_"> + </cr-icon-button> + <webview id="signin-frame" name="signin-frame" class="flex"> + </webview> + </div> + <div slot="button-container" class="flex layout horizontal"> + <cr-button id="cancelButton" class="cancel-button" on-click="onCloseTap_" + hidden="[[!isButtonsEnabled_]]"> + $i18n{lockScreenCancelButton} + </cr-button> + <cr-button id="nextButton" class="action-button" on-click="onNext_" + hidden="[[!isVerifyButtonEnabled_]]"> + $i18n{lockScreenVerifyButton} + </cr-button> + <cr-button id="nextButton" class="action-button" on-click="onNext_" + hidden="[[!isVerifyAgainButtonEnabled_]]"> + $i18n{lockScreenVerifyAgainButton} + </cr-button> + </div> + </cr-dialog> + </template> + </dom-module> +</head> + +<body> + <lock-reauth id="main-element"> + </lock-reauth> +</body> + +</html> \ No newline at end of file
diff --git a/chrome/browser/resources/chromeos/password_change/lock_screen_reauth.js b/chrome/browser/resources/chromeos/password_change/lock_screen_reauth.js new file mode 100644 index 0000000..fd9503d5 --- /dev/null +++ b/chrome/browser/resources/chromeos/password_change/lock_screen_reauth.js
@@ -0,0 +1,106 @@ +// 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 An UI component to let user init online re-auth flow on + * the lock screen. + */ + + +import {assert} from 'chrome://resources/js/assert.m.js'; +import {I18nBehavior} from 'chrome://resources/js/i18n_behavior.m.js'; +import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js'; +import {Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import 'chrome://resources/cr_elements/cr_button/cr_button.m.js'; +import 'chrome://resources/cr_elements/cr_dialog/cr_dialog.m.js'; +import 'chrome://resources/cr_elements/icons.m.js'; + + +Polymer({ + is: 'lock-reauth', + behaviors: [I18nBehavior], + + properties: { + isErrorDisplayed_: { + type: Boolean, + value: false, + }, + + isButtonsEnabled_: { + type: Boolean, + value: true, + }, + + isVerifyButtonEnabled_: { + type: Boolean, + computed: + 'computeVerifyButtonEnabled_(isErrorDisplayed_,isButtonsEnabled_)', + }, + + isVerifyAgainButtonEnabled_: { + type: Boolean, + computed: + 'computeVerifyAgainButtonEnabled_(isErrorDisplayed_,isButtonsEnabled_)', + }, + }, + + /** + * The UI component that hosts IdP pages. + * @type {!cr.login.Authenticator|undefined} + */ + authenticator_: undefined, + + /** + * Webview that view IdP page + * @type {!webview|undefined} + * @private + */ + signinFrame_: undefined, + + /** @override */ + attached() { + this.$.dialog.showModal(); + }, + + /** @override */ + ready() { + this.signinFrame_ = this.getSigninFrame_(); + this.authenticator_ = new cr.login.Authenticator(this.signinFrame_); + chrome.send('initialize'); + }, + + /** + * @return {!Element} + * @private + */ + getSigninFrame_() { + // Note: Can't use |this.$|, since it returns cached references to elements + // originally present in DOM, while the signin-frame is dynamically + // recreated (see Authenticator.setWebviewPartition()). + const signinFrame = this.shadowRoot.getElementById('signin-frame'); + assert(signinFrame); + return signinFrame; + }, + + /** @private */ + computeVerifyButtonEnabled_(isErrorDisplayed, isButtonsEnabled) { + return !isErrorDisplayed && isButtonsEnabled; + }, + + /** @private */ + computeVerifyAgainButtonEnabled_(isErrorDisplayed, isButtonsEnabled) { + return isErrorDisplayed && isButtonsEnabled; + }, + + /** @private */ + onNext_() { + this.isButtonsEnabled_ = false; + }, + + /** @private */ + onCloseTap_() { + chrome.send('dialogClose'); + }, + +});
diff --git a/chrome/browser/resources/gaia_auth_host/post_message_channel.js b/chrome/browser/resources/gaia_auth_host/post_message_channel.js index 0fab561d..c8bbd4a 100644 --- a/chrome/browser/resources/gaia_auth_host/post_message_channel.js +++ b/chrome/browser/resources/gaia_auth_host/post_message_channel.js
@@ -20,8 +20,12 @@ * Allowed origins of the hosting page. * @type {Array<string>} */ - const ALLOWED_ORIGINS = - ['chrome://oobe', 'chrome://chrome-signin', 'chrome://password-change']; + const ALLOWED_ORIGINS = [ + 'chrome://oobe', + 'chrome://chrome-signin', + 'chrome://password-change', + 'chrome://lock-reauth' + ]; /** @const */ const PORT_MESSAGE = 'post-message-port-message';
diff --git a/chrome/browser/resources/new_tab_page/app.js b/chrome/browser/resources/new_tab_page/app.js index 915ea2d..f4ee9ed 100644 --- a/chrome/browser/resources/new_tab_page/app.js +++ b/chrome/browser/resources/new_tab_page/app.js
@@ -323,7 +323,9 @@ async loadOneGoogleBar_() { if (this.iframeOneGoogleBarEnabled_) { const oneGoogleBar = document.querySelector('#oneGoogleBar'); - oneGoogleBar.remove(); + if (oneGoogleBar) { + oneGoogleBar.remove(); + } return; }
diff --git a/chrome/browser/resources/print_preview/BUILD.gn b/chrome/browser/resources/print_preview/BUILD.gn index 4c41b69..2cb2c36 100644 --- a/chrome/browser/resources/print_preview/BUILD.gn +++ b/chrome/browser/resources/print_preview/BUILD.gn
@@ -136,7 +136,6 @@ "ui/destination_dropdown_cros.js", "ui/destination_select_cros.js", "ui/pin_settings.js", - "ui/printer_status_icon_cros.js", ] } else { in_files += [
diff --git a/chrome/browser/resources/print_preview/data/printer_status_cros.js b/chrome/browser/resources/print_preview/data/printer_status_cros.js index 0a8ac4a0..4a4907e 100644 --- a/chrome/browser/resources/print_preview/data/printer_status_cros.js +++ b/chrome/browser/resources/print_preview/data/printer_status_cros.js
@@ -51,16 +51,6 @@ }; /** - * Enumeration used to choose styling based on whether this icon is located in - * the destination display or the destination dropdown. - * @enum {number} - */ -export const IconLocation = { - DISPLAY: 0, - DROPDOWN: 1, -}; - -/** * A container for the results of a printer status query. A printer status query * can return multiple error reasons. |timestamp| is set at the time of status * creation.
diff --git a/chrome/browser/resources/print_preview/ui/BUILD.gn b/chrome/browser/resources/print_preview/ui/BUILD.gn index 4954831e..9542918 100644 --- a/chrome/browser/resources/print_preview/ui/BUILD.gn +++ b/chrome/browser/resources/print_preview/ui/BUILD.gn
@@ -56,7 +56,6 @@ ":destination_dropdown_cros", ":destination_select_cros", ":pin_settings", - ":printer_status_icon_cros", ] } else { deps += [ ":destination_select" ] @@ -187,19 +186,12 @@ js_library("destination_dropdown_cros") { deps = [ - ":printer_status_icon_cros", "..:print_preview_utils", "//third_party/polymer/v3_0/components-chromium/iron-dropdown:iron-dropdown", "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", "//ui/webui/resources/cr_elements/cr_input:cr_input.m", ] } - - js_library("printer_status_icon_cros") { - deps = [ - "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", - ] - } } else { js_library("destination_select") { deps = [ @@ -571,7 +563,6 @@ "destination_dropdown_cros.js", "destination_select_cros.js", "pin_settings.js", - "printer_status_icon_cros.js", ] } else { js_files += [ "destination_select.js" ]
diff --git a/chrome/browser/resources/print_preview/ui/printer_status_icon_cros.html b/chrome/browser/resources/print_preview/ui/printer_status_icon_cros.html deleted file mode 100644 index 542255b6..0000000 --- a/chrome/browser/resources/print_preview/ui/printer_status_icon_cros.html +++ /dev/null
@@ -1,71 +0,0 @@ -<style include="cr-shared-style"> - div { - display: inline; - position: relative; - } - - .badge { - border-radius: 50%; - display: inline-block; - position: absolute; - --status-badge-radius: 8px; - --background-badge-radius: 12px; - --background-badge-left: 12px; - --background-badge-top: 6px; - } - - :host-context([dir='rtl']) .badge { - --background-badge-left: -4px; - } - - #status-badge { - height: var(--status-badge-radius); - left: calc(var(--background-badge-left) + (var(--background-badge-radius) - var(--status-badge-radius))/2); - top: calc(var(--background-badge-top) + (var(--background-badge-radius) - var(--status-badge-radius))/2); - width: var(--status-badge-radius); - } - - :host([printer-state='0']) #status-badge { - background-color: var(--google-green-700); - } - - :host([printer-state='1']) #status-badge { - background-color: var(--google-red-600); - } - - :host([printer-state='2']) #status-badge { - background-color: var(--google-grey-500); - } - - :host-context([dir='rtl']) #status-badge { - right: calc(var(--background-badge-left) + (var(--background-badge-radius) - var(--status-badge-radius))/2); - } - - #background-badge { - height: var(--background-badge-radius); - left: var(--background-badge-left); - top: var(--background-badge-top); - width: var(--background-badge-radius); - } - - :host([icon-location='0']) #background-badge { - background-color: var(--google-grey-refresh-100); - } - - :host([icon-location='1']) #background-badge { - background-color: white; - } - - :host-context([dir='rtl']) #background-badge { - right: var(--background-badge-left); - } - - :host-context(.highlighted) #background-badge { - background-color: var(--google-blue-refresh-100); - } -</style> -<div> - <iron-icon icon="print-preview:print"></iron-icon> - <span id="background-badge" class="badge"></span> - <span id="status-badge" class="badge"></span> -</div>
diff --git a/chrome/browser/resources/print_preview/ui/printer_status_icon_cros.js b/chrome/browser/resources/print_preview/ui/printer_status_icon_cros.js deleted file mode 100644 index 6984175..0000000 --- a/chrome/browser/resources/print_preview/ui/printer_status_icon_cros.js +++ /dev/null
@@ -1,40 +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 'chrome://resources/cr_elements/shared_vars_css.m.js'; -import './icons.js'; - -import {html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; - -import {IconLocation, PrinterState} from '../data/printer_status_cros.js'; - -Polymer({ - is: 'printer-status-icon-cros', - - properties: { - /** Determines color of the background badge. */ - background: String, - - /** - * State of the associated printer. Determines color of the status badge. - * @type {!PrinterState} - */ - printerState: { - type: Number, - reflectToAttribute: true, - }, - - /** - * Location of this icon. Determines color of the background badge. - * @type {!IconLocation} - */ - iconLocation: { - type: Number, - reflectToAttribute: true, - }, - }, - - _template: html`{__html_template__}`, - -});
diff --git a/chrome/browser/resources/settings/autofill_page/password_edit_dialog.js b/chrome/browser/resources/settings/autofill_page/password_edit_dialog.js index 142eefe..2e05bc2 100644 --- a/chrome/browser/resources/settings/autofill_page/password_edit_dialog.js +++ b/chrome/browser/resources/settings/autofill_page/password_edit_dialog.js
@@ -70,7 +70,7 @@ * Check if editPasswordsInSettings flag is true and entry isn't federation * credential. * @private - * */ + */ isEditDialog_: { type: Boolean, computed: 'computeIsEditDialog_(editPasswordsInSettings_, entry)' @@ -118,21 +118,21 @@ .map(item => item.username)); }, + /** Closes the dialog. */ + close() { + this.$.dialog.close(); + }, + /** * Helper function that checks if editPasswordsInSettings flag is true and * entry isn't federation credential. * @return {boolean} * @private - * */ + */ computeIsEditDialog_() { return this.editPasswordsInSettings_ && !this.entry.federationText; }, - /** Closes the dialog. */ - close() { - this.$.dialog.close(); - }, - /** * Handler for tapping the 'cancel' button. Should just dismiss the dialog. * @private @@ -251,7 +251,10 @@ return this.isEditDialog_ ? this.i18n('save') : this.i18n('done'); }, - /** Manually de-select texts for readonly inputs. */ + /** + * Manually de-select texts for readonly inputs. + * @private + */ onInputBlur_() { this.shadowRoot.getSelection().removeAllRanges(); }, @@ -259,6 +262,7 @@ /** * Gets the HTML-formatted message to indicate in which locations the password * is stored. + * @private */ getStorageDetailsMessage_() { if (this.entry.isPresentInAccount() && this.entry.isPresentOnDevice()) {
diff --git a/chrome/browser/resources/settings/autofill_page/password_move_to_account_dialog.js b/chrome/browser/resources/settings/autofill_page/password_move_to_account_dialog.js index 0ecb377..b5a9d42 100644 --- a/chrome/browser/resources/settings/autofill_page/password_move_to_account_dialog.js +++ b/chrome/browser/resources/settings/autofill_page/password_move_to_account_dialog.js
@@ -42,9 +42,7 @@ behaviors: [I18nBehavior], properties: { - /** - * @type {!MultiStorePasswordUiEntry} - */ + /** @type {!MultiStorePasswordUiEntry} */ passwordToMove: Object, }, @@ -60,9 +58,7 @@ this.$.dialog.showModal(); }, - /** - * @private - */ + /** @private */ onMoveButtonClick_() { assert(this.passwordToMove.isPresentOnDevice()); PasswordManagerImpl.getInstance() @@ -71,9 +67,7 @@ this.$.dialog.close(); }, - /** - * @private - */ + /** @private */ onCancelButtonClick_() { this.$.dialog.close(); }
diff --git a/chrome/browser/resources/settings/autofill_page/password_remove_dialog.js b/chrome/browser/resources/settings/autofill_page/password_remove_dialog.js index 8dd3b91..7ba17a4 100644 --- a/chrome/browser/resources/settings/autofill_page/password_remove_dialog.js +++ b/chrome/browser/resources/settings/autofill_page/password_remove_dialog.js
@@ -44,9 +44,7 @@ */ duplicatedPassword: Object, - /** - * @private - */ + /** @private */ removeFromAccountChecked_: { type: Boolean, // Both checkboxes are selected by default (see |removeFromDeviceChecked_| @@ -54,17 +52,13 @@ value: true, }, - /** - * @private - */ + /** @private */ removeFromDeviceChecked_: { type: Boolean, value: true, }, - /** - * @private - */ + /** @private */ accountEmail_: { type: String, value: '', @@ -89,9 +83,7 @@ }); }, - /** - * @private - */ + /** @private */ onRemoveButtonClick_() { /** @type{!Array<number>} */ const idsToRemove = []; @@ -110,9 +102,7 @@ }); }, - /** - * @private - */ + /** @private */ onCancelButtonClick_() { this.$.dialog.close(); },
diff --git a/chrome/browser/resources/settings/autofill_page/passwords_device_section.js b/chrome/browser/resources/settings/autofill_page/passwords_device_section.js index 442b237..97ed8162 100644 --- a/chrome/browser/resources/settings/autofill_page/passwords_device_section.js +++ b/chrome/browser/resources/settings/autofill_page/passwords_device_section.js
@@ -29,7 +29,7 @@ import {GlobalScrollTargetBehavior} from '../global_scroll_target_behavior.m.js'; import {loadTimeData} from '../i18n_setup.js'; import {OpenWindowProxyImpl} from '../open_window_proxy.js'; -import {StoredAccount, SyncBrowserProxyImpl, SyncStatus} from '../people_page/sync_browser_proxy.m.js'; +import {StoredAccount, SyncBrowserProxyImpl} from '../people_page/sync_browser_proxy.m.js'; import {routes} from '../route.js'; import {Route, RouteObserverBehavior, Router} from '../router.m.js'; @@ -89,8 +89,7 @@ /** * Passwords displayed in the device-only subsection. - * @type {!Array<!MultiStorePasswordUiEntry>} - * @private + * @private {!Array<!MultiStorePasswordUiEntry>} */ deviceOnlyPasswords_: { type: Array, @@ -101,8 +100,7 @@ /** * Passwords displayed in the 'device and account' subsection. - * @type {!Array<!MultiStorePasswordUiEntry>} - * @private + * @private {!Array<!MultiStorePasswordUiEntry>} */ deviceAndAccountPasswords_: { type: Array, @@ -120,6 +118,7 @@ /** @private */ accountEmail_: String, + /** @private */ isUserAllowedToAccessPage_: { type: Boolean, computed: 'computeIsUserAllowedToAccessPage_(signedIn_, syncDisabled_,' + @@ -128,8 +127,7 @@ /** * Whether the user is signed in, one of the requirements to view this page. - * @private - * @type {boolean?} + * @private {boolean?} */ signedIn_: { type: Boolean, @@ -138,8 +136,7 @@ /** * Whether Sync is disabled, one of the requirements to view this page. - * @private - * @type {boolean?} + * @private {boolean?} */ syncDisabled_: { type: Boolean, @@ -149,18 +146,14 @@ /** * Whether the user has opted in to the account-scoped password storage, one * of the requirements to view this page. - * @private - * @type {boolean?} + * @private {boolean?} */ optedInForAccountStorage_: { type: Boolean, value: null, }, - /** - * @private - * @type {Route?} - */ + /** @private {Route?} */ currentRoute_: { type: Object, value: null, @@ -168,13 +161,22 @@ }, + keyBindings: { + // <if expr="is_macosx"> + 'meta+z': 'onUndoKeyBinding_', + // </if> + // <if expr="not is_macosx"> + 'ctrl+z': 'onUndoKeyBinding_', + // </if> + }, + + /** @private {!function(boolean): void} */ + accountStorageOptInStateListener_: Function, + observers: ['maybeRedirectToPasswordsPage_(isUserAllowedToAccessPage_, ' + 'currentRoute_)'], - /** @type {!function(boolean): void} */ - accountStorageOptInStateListener_: Function, - /** @override */ attached() { this.addListenersForAccountStorageRequirements_(); @@ -197,59 +199,6 @@ }, /** - * @private - */ - addListenersForAccountStorageRequirements_() { - const setSyncDisabled = syncStatus => { - this.syncDisabled_ = !syncStatus.signedIn; - }; - SyncBrowserProxyImpl.getInstance().getSyncStatus().then(setSyncDisabled); - this.addWebUIListener('sync-status-changed', setSyncDisabled); - - const setSignedIn = storedAccounts => { - this.signedIn_ = storedAccounts.length > 0; - }; - SyncBrowserProxyImpl.getInstance().getStoredAccounts().then(setSignedIn); - this.addWebUIListener('stored-accounts-updated', setSignedIn); - - const setOptedIn = optedInForAccountStorage => { - this.optedInForAccountStorage_ = optedInForAccountStorage; - }; - PasswordManagerImpl.getInstance().isOptedInForAccountStorage().then( - setOptedIn); - PasswordManagerImpl.getInstance().addAccountStorageOptInStateListener( - setOptedIn); - this.accountStorageOptInStateListener_ = setOptedIn; - }, - - /** - * From RouteObserverBehavior. - * @param {!Route|undefined} route - * @protected - */ - currentRouteChanged(route) { - this.currentRoute_ = route || null; - }, - - /** - * @param {!Array<!MultiStorePasswordUiEntry>} passwords - * @return {boolean} - * @private - */ - isNonEmpty_(passwords) { - return passwords.length > 0; - }, - - keyBindings: { - // <if expr="is_macosx"> - 'meta+z': 'onUndoKeyBinding_', - // </if> - // <if expr="not is_macosx"> - 'ctrl+z': 'onUndoKeyBinding_', - // </if> - }, - - /** * @return {!Array<!MultiStorePasswordUiEntry>} * @private */ @@ -281,6 +230,48 @@ }, /** + * From RouteObserverBehavior. + * @param {!Route|undefined} route + * @protected + */ + currentRouteChanged(route) { + this.currentRoute_ = route || null; + }, + + /** @private */ + addListenersForAccountStorageRequirements_() { + const setSyncDisabled = syncStatus => { + this.syncDisabled_ = !syncStatus.signedIn; + }; + SyncBrowserProxyImpl.getInstance().getSyncStatus().then(setSyncDisabled); + this.addWebUIListener('sync-status-changed', setSyncDisabled); + + const setSignedIn = storedAccounts => { + this.signedIn_ = storedAccounts.length > 0; + }; + SyncBrowserProxyImpl.getInstance().getStoredAccounts().then(setSignedIn); + this.addWebUIListener('stored-accounts-updated', setSignedIn); + + const setOptedIn = optedInForAccountStorage => { + this.optedInForAccountStorage_ = optedInForAccountStorage; + }; + PasswordManagerImpl.getInstance().isOptedInForAccountStorage().then( + setOptedIn); + PasswordManagerImpl.getInstance().addAccountStorageOptInStateListener( + setOptedIn); + this.accountStorageOptInStateListener_ = setOptedIn; + }, + + /** + * @param {!Array<!MultiStorePasswordUiEntry>} passwords + * @return {boolean} + * @private + */ + isNonEmpty_(passwords) { + return passwords.length > 0; + }, + + /** * @param {!Array<!MultiStorePasswordUiEntry>} passwords * @param {string} filter * @return {!Array<!MultiStorePasswordUiEntry>}
diff --git a/chrome/browser/resources/settings/autofill_page/passwords_list_handler.html b/chrome/browser/resources/settings/autofill_page/passwords_list_handler.html index 0ead0c2e..23d780f 100644 --- a/chrome/browser/resources/settings/autofill_page/passwords_list_handler.html +++ b/chrome/browser/resources/settings/autofill_page/passwords_list_handler.html
@@ -13,7 +13,7 @@ <cr-action-menu id="menu" role-description="$i18n{menu}"> <button id="menuCopyPassword" class="dropdown-item" - hidden$="[[activePassword.entry.federationText]]" + hidden$="[[activePassword_.entry.federationText]]" on-click="onMenuCopyPasswordButtonTap_">$i18n{copyPassword}</button> <button id="menuEditPassword" class="dropdown-item" on-click="onMenuEditPasswordTap_"> @@ -23,7 +23,7 @@ on-click="onMenuRemovePasswordTap_">$i18n{removePassword}</button> <button id="menuMovePasswordToAccount" on-click="onMenuMovePasswordToAccountTap_" - hidden$="[[!shouldShowMoveToAccountOption_(activePassword, + hidden$="[[!shouldShowMoveToAccountOption_(activePassword_, allowMoveToAccountOption, firstSignedInAccountEmail_)]]" class="dropdown-item">$i18n{movePasswordToAccount}</button> </cr-action-menu> @@ -34,21 +34,21 @@ <if expr="chromeos"> token-request-manager="[[tokenRequestManager]]" </if> - entry="[[activePassword.entry]]" saved-passwords="[[savedPasswords]]" + entry="[[activePassword_.entry]]" saved-passwords="[[savedPasswords]]" should-show-storage-details="[[shouldShowStorageDetails]]"> </password-edit-dialog> </template> <template is="dom-if" if="[[showPasswordMoveToAccountDialog_]]" restamp> <password-move-to-account-dialog id="passwordMoveToAccountDialog" - password-to-move="[[activePassword.entry]]" + password-to-move="[[activePassword_.entry]]" on-close="onPasswordMoveToAccountDialogClosed_"> </password-move-to-account-dialog> </template> <template is="dom-if" if="[[showPasswordRemoveDialog_]]" restamp> <password-remove-dialog id="passwordRemoveDialog" - duplicated-password="[[activePassword.entry]]" + duplicated-password="[[activePassword_.entry]]" on-close="onPasswordRemoveDialogClosed_"> </password-remove-dialog> </template>
diff --git a/chrome/browser/resources/settings/autofill_page/passwords_list_handler.js b/chrome/browser/resources/settings/autofill_page/passwords_list_handler.js index 982055ee5..0082dea 100644 --- a/chrome/browser/resources/settings/autofill_page/passwords_list_handler.js +++ b/chrome/browser/resources/settings/autofill_page/passwords_list_handler.js
@@ -39,6 +39,11 @@ _template: html`{__html_template__}`, + behaviors: [ + I18nBehavior, + WebUIListenerBehavior, + ], + properties: { /** * Saved passwords after deduplicating versions that are repeated in the @@ -51,16 +56,6 @@ }, /** - * The model for any active menus or dialogs. The value is reset to null - * whenever actions from the menus/dialogs are concluded. - * @private {?PasswordListItemElement} - */ - activePassword: { - type: Object, - value: null, - }, - - /** * Whether the edit dialog and removal notification should show information * about which location(s) a password is stored. */ @@ -83,6 +78,16 @@ tokenRequestManager: Object, // </if> + /** + * The model for any active menus or dialogs. The value is reset to null + * whenever actions from the menus/dialogs are concluded. + * @private {?PasswordListItemElement} + */ + activePassword_: { + type: Object, + value: null, + }, + /** @private */ editPasswordsInSettings_: { type: Boolean, @@ -95,10 +100,11 @@ * Check if editPasswordsInSettings flag is true and entry isn't federation * credential. * @private - * */ + */ isEditDialog_: { type: Boolean, - computed: 'computeIsEditDialog_(editPasswordsInSettings_, activePassword)' + computed: + 'computeIsEditDialog_(editPasswordsInSettings_, activePassword_)' }, /** @private */ @@ -137,20 +143,15 @@ } }, - behaviors: [ - I18nBehavior, - WebUIListenerBehavior, - ], - - listeners: { - 'password-more-actions-clicked': 'onPasswordMoreActionsClicked_', - 'password-remove-dialog-passwords-removed': - 'onPasswordRemoveDialogPasswordsRemoved_', - }, - /** @private {?PasswordManagerProxy} */ passwordManager_: null, + listeners: { + 'password-more-actions-clicked': 'passwordMoreActionsClickedHandler_', + 'password-remove-dialog-passwords-removed': + 'passwordRemoveDialogPasswordsRemovedHandler_', + }, + /** @override */ attached() { this.passwordManager_ = PasswordManagerImpl.getInstance(); @@ -172,17 +173,6 @@ }, /** - * Helper function that checks if editPasswordsInSettings flag is true and - * entry isn't federation credential. - * @return {boolean} - * @private - * */ - computeIsEditDialog_() { - return this.editPasswordsInSettings_ && - (!this.activePassword || !this.activePassword.entry.federationText); - }, - - /** * Closes the toast manager. */ onSavedPasswordOrExceptionRemoved() { @@ -194,15 +184,35 @@ * @param {PasswordMoreActionsClickedEvent} event * @private */ - onPasswordMoreActionsClicked_(event) { + passwordMoreActionsClickedHandler_(event) { const target = event.detail.target; - this.activePassword = event.detail.listItem; + this.activePassword_ = event.detail.listItem; this.$.menu.showAt(target); this.activeDialogAnchor_ = target; }, /** + * @param {PasswordRemoveDialogPasswordsRemovedEvent} event + * @private + */ + passwordRemoveDialogPasswordsRemovedHandler_(event) { + this.displayRemovalNotification_( + event.detail.removedFromAccount, event.detail.removedFromDevice); + }, + + /** + * Helper function that checks if editPasswordsInSettings flag is true and + * entry isn't federation credential. + * @return {boolean} + * @private + */ + computeIsEditDialog_() { + return this.editPasswordsInSettings_ && + (!this.activePassword_ || !this.activePassword_.entry.federationText); + }, + + /** * Requests the plaintext password for the current active password. * @param {!chrome.passwordsPrivate.PlaintextReason} reason The reason why the * plaintext password is requested. @@ -212,7 +222,7 @@ */ requestActivePlaintextPassword_(reason, callback) { this.passwordManager_ - .requestPlaintextPassword(this.activePassword.entry.getAnyId(), reason) + .requestPlaintextPassword(this.activePassword_.entry.getAnyId(), reason) .then(callback, error => { // <if expr="chromeos"> // If no password was found, refresh auth token and retry. @@ -228,14 +238,14 @@ if (this.isEditDialog_) { this.requestActivePlaintextPassword_( chrome.passwordsPrivate.PlaintextReason.EDIT, password => { - this.set('activePassword.entry.password', password); + this.set('activePassword_.entry.password', password); this.showPasswordEditDialog_ = true; }); } else { this.showPasswordEditDialog_ = true; } this.$.menu.close(); - this.activePassword.hide(); + this.activePassword_.hide(); }, /** @@ -252,8 +262,8 @@ this.showPasswordEditDialog_ = false; focusWithoutInk(assert(this.activeDialogAnchor_)); this.activeDialogAnchor_ = null; - this.activePassword.hide(); - this.activePassword = null; + this.activePassword_.hide(); + this.activePassword_ = null; }, /** @private */ @@ -261,7 +271,7 @@ this.showPasswordEditDialog_ = false; focusWithoutInk(assert(this.activeDialogAnchor_)); this.activeDialogAnchor_ = null; - this.activePassword = null; + this.activePassword_ = null; }, /** @@ -273,7 +283,7 @@ // result back to javascript. this.requestActivePlaintextPassword_( chrome.passwordsPrivate.PlaintextReason.COPY, _ => { - this.activePassword = null; + this.activePassword_ = null; }); this.$.menu.close(); @@ -288,20 +298,20 @@ onMenuRemovePasswordTap_() { this.$.menu.close(); - if (this.activePassword.entry.isPresentOnDevice() && - this.activePassword.entry.isPresentInAccount()) { + if (this.activePassword_.entry.isPresentOnDevice() && + this.activePassword_.entry.isPresentInAccount()) { this.showPasswordRemoveDialog_ = true; return; } - const idToRemove = this.activePassword.entry.isPresentInAccount() ? - this.activePassword.entry.accountId : - this.activePassword.entry.deviceId; + const idToRemove = this.activePassword_.entry.isPresentInAccount() ? + this.activePassword_.entry.accountId : + this.activePassword_.entry.deviceId; this.passwordManager_.removeSavedPassword(idToRemove); this.displayRemovalNotification_( - this.activePassword.entry.isPresentInAccount(), - this.activePassword.entry.isPresentOnDevice()); - this.activePassword = null; + this.activePassword_.entry.isPresentInAccount(), + this.activePassword_.entry.isPresentOnDevice()); + this.activePassword_ = null; }, /** @@ -328,24 +338,14 @@ this.fire('iron-announce', {text: this.i18n('undoDescription')}); }, - /** - * @param {PasswordRemoveDialogPasswordsRemovedEvent} event - */ - onPasswordRemoveDialogPasswordsRemoved_(event) { - this.displayRemovalNotification_( - event.detail.removedFromAccount, event.detail.removedFromDevice); - }, - - /** - * @private - */ + /** @private */ onUndoButtonClick_() { this.passwordManager_.undoRemoveSavedPasswordOrException(); this.onSavedPasswordOrExceptionRemoved(); }, /** - * Should only be called when |activePassword| has a device copy. + * Should only be called when |activePassword_| has a device copy. * @private */ onMenuMovePasswordToAccountTap_() { @@ -353,23 +353,19 @@ this.showPasswordMoveToAccountDialog_ = true; }, - /** - * @private - */ + /** @private */ onPasswordMoveToAccountDialogClosed_() { this.showPasswordMoveToAccountDialog_ = false; - this.activePassword = null; + this.activePassword_ = null; // The entry possibly disappeared, so don't reset the focus. this.activeDialogAnchor_ = null; }, - /** - * @private - */ + /** @private */ onPasswordRemoveDialogClosed_() { this.showPasswordRemoveDialog_ = false; - this.activePassword = null; + this.activePassword_ = null; // A removal possibly happened, so don't reset the focus. this.activeDialogAnchor_ = null; @@ -381,9 +377,10 @@ * @return {boolean} */ shouldShowMoveToAccountOption_() { - const isFirstSignedInAccountPassword = !!this.activePassword && - this.activePassword.entry.urls.origin.includes('accounts.google.com') && - this.activePassword.entry.username === this.firstSignedInAccountEmail_; + const isFirstSignedInAccountPassword = !!this.activePassword_ && + this.activePassword_.entry.urls.origin.includes( + 'accounts.google.com') && + this.activePassword_.entry.username === this.firstSignedInAccountEmail_; // It's not useful to move a password for an account into that same account. return this.allowMoveToAccountOption && !isFirstSignedInAccountPassword; },
diff --git a/chrome/browser/resources/settings/autofill_page/passwords_section.js b/chrome/browser/resources/settings/autofill_page/passwords_section.js index c9ed577f..57d731a 100644 --- a/chrome/browser/resources/settings/autofill_page/passwords_section.js +++ b/chrome/browser/resources/settings/autofill_page/passwords_section.js
@@ -8,7 +8,6 @@ * save any passwords. */ - /** @typedef {!{model: !{item: !chrome.passwordsPrivate.ExceptionEntry}}} */ let ExceptionEntryEntryEvent; @@ -23,7 +22,6 @@ import {assert} from 'chrome://resources/js/assert.m.js'; import {focusWithoutInk} from 'chrome://resources/js/cr/ui/focus_without_ink.m.js'; import {I18nBehavior} from 'chrome://resources/js/i18n_behavior.m.js'; -import {getImage} from 'chrome://resources/js/icon.m.js'; import {getDeepActiveElement} from 'chrome://resources/js/util.m.js'; import {WebUIListenerBehavior} from 'chrome://resources/js/web_ui_listener_behavior.m.js'; import {IronA11yAnnouncer} from 'chrome://resources/polymer/v3_0/iron-a11y-announcer/iron-a11y-announcer.js'; @@ -42,7 +40,6 @@ import {MergeExceptionsStoreCopiesBehavior} from './merge_exceptions_store_copies_behavior.js'; import {MergePasswordsStoreCopiesBehavior} from './merge_passwords_store_copies_behavior.js'; import {MultiStorePasswordUiEntry} from './multi_store_password_ui_entry.js'; -import {MultiStoreExceptionEntry} from './multi_store_exception_entry.js'; import {Router} from '../router.m.js'; import '../settings_shared_css.m.js'; import '../site_favicon.js'; @@ -53,7 +50,6 @@ import './passwords_export_dialog.js'; import './passwords_shared_css.js'; import './avatar_icon.js'; -import {ProfileInfo, ProfileInfoBrowserProxy, ProfileInfoBrowserProxyImpl} from '../people_page/profile_info_browser_proxy.m.js'; // <if expr="chromeos"> import '../controls/password_prompt_dialog.m.js'; import {BlockingRequestManager} from './blocking_request_manager.js'; @@ -90,10 +86,6 @@ ], properties: { - // <if expr="not chromeos"> - /** @private */ - storedAccounts_: Array, - // </if> /** @type {!Map<string, (string|Function)>} */ focusConfig: { @@ -119,6 +111,17 @@ value: () => document, }, + /** Filter on the saved passwords and exceptions. */ + filter: { + type: String, + value: '', + }, + + // <if expr="not chromeos"> + /** @private */ + storedAccounts_: Array, + // </if> + /** @private */ signedIn_: { type: Boolean, @@ -163,6 +166,7 @@ computed: 'computeHasPasswordExceptions_(passwordExceptions)', }, + /** @private */ shouldShowBanner_: { type: Boolean, value: true, @@ -173,6 +177,7 @@ /** * Whether the edit dialog and removal notification should show * information about which location(s) a password is stored. + * @private */ shouldShowStorageDetails_: { type: Boolean, @@ -252,12 +257,6 @@ /** @private {SyncStatus} */ syncStatus_: Object, - /** Filter on the saved passwords and exceptions. */ - filter: { - type: String, - value: '', - }, - /** @private {!MultiStorePasswordUiEntry} */ lastFocused_: Object, @@ -269,7 +268,7 @@ showPasswordPromptDialog_: Boolean, /** @private {BlockingRequestManager} */ - tokenRequestManager_: Object + tokenRequestManager_: Object, // </if> }, @@ -295,36 +294,12 @@ /** @private {?PasswordManagerProxy} */ passwordManager_: null, - /** - * @type {?function(boolean):void} - * @private - */ + /** @private {?function(boolean):void} */ setIsOptedInForAccountStorageListener_: null, - /** - * @type {?function(!Array<PasswordManagerProxy.ExceptionEntry>):void} - * @private - */ + /** @private {?function(!Array<PasswordManagerProxy.ExceptionEntry>):void} */ setPasswordExceptionsListener_: null, - /** - * @param {!Map<string, string>} newConfig - * @param {?Map<string, string>} oldConfig - * @private - */ - focusConfigChanged_(newConfig, oldConfig) { - // focusConfig is set only once on the parent, so this observer should - // only fire once. - assert(!oldConfig); - - // Populate the |focusConfig| map of the parent <settings-autofill-page> - // element, with additional entries that correspond to subpage trigger - // elements residing in this element's Shadow DOM. - this.focusConfig.set(assert(routes.CHECK_PASSWORDS).path, () => { - focusWithoutInk(assert(this.$$('#icon'))); - }); - }, - /** @override */ attached() { // Create listener functions. @@ -388,56 +363,6 @@ }, /** - * Shows the check passwords sub page. - * @private - */ - onCheckPasswordsClick_() { - Router.getInstance().navigateTo( - routes.CHECK_PASSWORDS, new URLSearchParams('start=true')); - this.passwordManager_.recordPasswordCheckReferrer( - PasswordManagerProxy.PasswordCheckReferrer.PASSWORD_SETTINGS); - }, - - /** - * Shows the 'device passwords' page. - */ - onDevicePasswordsLinkClicked_() { - Router.getInstance().navigateTo(routes.DEVICE_PASSWORDS); - }, - - // <if expr="chromeos"> - /** - * When this event fired, it means that the password-prompt-dialog succeeded - * in creating a fresh token in the quickUnlockPrivate API. Because new tokens - * can only ever be created immediately following a GAIA password check, the - * passwordsPrivate API can now safely grant requests for secure data (i.e. - * saved passwords) for a limited time. This observer resolves the request, - * triggering a callback that requires a fresh auth token to succeed and that - * was provided to the BlockingRequestManager by another DOM element seeking - * secure data. - * - * @param {!CustomEvent<!chrome.quickUnlockPrivate.TokenInfo>} e - Contains - * newly created auth token. Note that its precise value is not relevant - * here, only the facts that it's created. - * @private - */ - onTokenObtained_(e) { - assert(e.detail); - this.tokenRequestManager_.resolve(); - }, - - onPasswordPromptClosed_() { - this.showPasswordPromptDialog_ = false; - focusWithoutInk(assert(this.activeDialogAnchorStack_.pop())); - }, - - openPasswordPromptDialog_() { - this.activeDialogAnchorStack_.push(getDeepActiveElement()); - this.showPasswordPromptDialog_ = true; - }, - // </if> - - /** * @return {boolean} * @private */ @@ -525,6 +450,86 @@ }, /** + * @private + * @return {boolean} + */ + computeHasLeakedCredentials_() { + return this.leakedPasswords.length > 0; + }, + + /** + * @private + * @return {boolean} + */ + computeHasNeverCheckedPasswords_() { + return !this.status.elapsedTimeSinceLastCheck; + }, + + /** + * @private + * @return {string} + */ + computeDevicePasswordsLinkLabel_() { + return this.numberOfDevicePasswords_ === 1 ? + this.i18n('devicePasswordsLinkLabelSingular') : + this.i18n( + 'devicePasswordsLinkLabelPlural', this.numberOfDevicePasswords_); + }, + + /** + * Shows the check passwords sub page. + * @private + */ + onCheckPasswordsClick_() { + Router.getInstance().navigateTo( + routes.CHECK_PASSWORDS, new URLSearchParams('start=true')); + this.passwordManager_.recordPasswordCheckReferrer( + PasswordManagerProxy.PasswordCheckReferrer.PASSWORD_SETTINGS); + }, + + /** + * Shows the 'device passwords' page. + * @private + */ + onDevicePasswordsLinkClicked_() { + Router.getInstance().navigateTo(routes.DEVICE_PASSWORDS); + }, + + // <if expr="chromeos"> + /** + * When this event fired, it means that the password-prompt-dialog succeeded + * in creating a fresh token in the quickUnlockPrivate API. Because new tokens + * can only ever be created immediately following a GAIA password check, the + * passwordsPrivate API can now safely grant requests for secure data (i.e. + * saved passwords) for a limited time. This observer resolves the request, + * triggering a callback that requires a fresh auth token to succeed and that + * was provided to the BlockingRequestManager by another DOM element seeking + * secure data. + * + * @param {!CustomEvent<!chrome.quickUnlockPrivate.TokenInfo>} e - Contains + * newly created auth token. Note that its precise value is not relevant + * here, only the facts that it's created. + * @private + */ + onTokenObtained_(e) { + assert(e.detail); + this.tokenRequestManager_.resolve(); + }, + + /** @private */ + onPasswordPromptClosed_() { + this.showPasswordPromptDialog_ = false; + focusWithoutInk(assert(this.activeDialogAnchorStack_.pop())); + }, + + /** @private */ + openPasswordPromptDialog_() { + this.activeDialogAnchorStack_.push(getDeepActiveElement()); + this.showPasswordPromptDialog_ = true; + }, + // </if> + + /** * @param {string} filter * @return {!Array<!MultiStorePasswordUiEntry>} * @private @@ -644,33 +649,6 @@ }, /** - * @private - * @return {boolean} - */ - computeHasLeakedCredentials_() { - return this.leakedPasswords.length > 0; - }, - - /** - * @private - * @return {boolean} - */ - computeHasNeverCheckedPasswords_() { - return !this.status.elapsedTimeSinceLastCheck; - }, - - /** - * @private - * @return {string} - */ - computeDevicePasswordsLinkLabel_() { - return this.numberOfDevicePasswords_ === 1 ? - this.i18n('devicePasswordsLinkLabelSingular') : - this.i18n( - 'devicePasswordsLinkLabelPlural', this.numberOfDevicePasswords_); - }, - - /** * Return the first available stored account. This is useful when trying to * figure out the account logged into the content area which seems to always * be first even if multiple accounts are available. @@ -683,4 +661,22 @@ this.storedAccounts_[0].email : ''; }, + + /** + * @param {!Map<string, string>} newConfig + * @param {?Map<string, string>} oldConfig + * @private + */ + focusConfigChanged_(newConfig, oldConfig) { + // focusConfig is set only once on the parent, so this observer should + // only fire once. + assert(!oldConfig); + + // Populate the |focusConfig| map of the parent <settings-autofill-page> + // element, with additional entries that correspond to subpage trigger + // elements residing in this element's Shadow DOM. + this.focusConfig.set(assert(routes.CHECK_PASSWORDS).path, () => { + focusWithoutInk(assert(this.$$('#icon'))); + }); + }, });
diff --git a/chrome/browser/resources/settings/chromeos/os_languages_page/BUILD.gn b/chrome/browser/resources/settings/chromeos/os_languages_page/BUILD.gn index 786172c9..12a0d76 100644 --- a/chrome/browser/resources/settings/chromeos/os_languages_page/BUILD.gn +++ b/chrome/browser/resources/settings/chromeos/os_languages_page/BUILD.gn
@@ -371,6 +371,7 @@ ":os_languages_page_module", ":os_languages_page_v2_module", ":os_languages_section_module", + ":shared_style_module", ":smart_inputs_page_module", "../../languages_page:languages_module", "../../languages_page:modulize", @@ -467,6 +468,12 @@ auto_imports = os_settings_auto_imports } +polymer_modulizer("shared_style") { + js_file = "shared_style.m.js" + html_file = "shared_style.html" + html_type = "style-module" +} + polymer_modulizer("smart_inputs_page") { js_file = "smart_inputs_page.js" html_file = "smart_inputs_page.html"
diff --git a/chrome/browser/resources/settings/chromeos/os_languages_page/add_input_methods_dialog.html b/chrome/browser/resources/settings/chromeos/os_languages_page/add_input_methods_dialog.html index 42fd0fb..86ca8b04 100644 --- a/chrome/browser/resources/settings/chromeos/os_languages_page/add_input_methods_dialog.html +++ b/chrome/browser/resources/settings/chromeos/os_languages_page/add_input_methods_dialog.html
@@ -7,12 +7,13 @@ <link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout-classes.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-list/iron-list.html"> <link rel="import" href="../metrics_recorder.html"> +<link rel="import" href="shared_style.html"> <link rel="import" href="../../languages_page/languages.html"> <link rel="import" href="../../settings_shared_css.html"> <dom-module id="os-settings-add-input-methods-dialog"> <template> - <style include="settings-shared iron-flex"> + <style include="settings-shared iron-flex shared-style"> #dialogBody { display: flex; flex-direction: column; @@ -22,9 +23,7 @@ } cr-search-field { - --cr-search-field-search-input-width: 100%; - padding-bottom: 8px; - padding-inline-end: 20px; + margin-bottom: 8px; } .label {
diff --git a/chrome/browser/resources/settings/chromeos/os_languages_page/change_device_language_dialog.html b/chrome/browser/resources/settings/chromeos/os_languages_page/change_device_language_dialog.html index bfe7d76f..cc897ca 100644 --- a/chrome/browser/resources/settings/chromeos/os_languages_page/change_device_language_dialog.html +++ b/chrome/browser/resources/settings/chromeos/os_languages_page/change_device_language_dialog.html
@@ -10,6 +10,7 @@ <link rel="import" href="chrome://resources/polymer/v1_0/iron-list/iron-list.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-ripple/paper-ripple.html"> <link rel="import" href="languages_metrics_proxy.html"> +<link rel="import" href="shared_style.html"> <link rel="import" href="../localized_link/localized_link.html"> <link rel="import" href="../metrics_recorder.html"> <link rel="import" href="../../languages_page/languages.html"> @@ -18,7 +19,7 @@ <dom-module id="os-settings-change-device-language-dialog"> <template> - <style include="settings-shared iron-flex"> + <style include="settings-shared iron-flex shared-style"> #dialogBody { display: flex; flex-direction: column; @@ -30,6 +31,7 @@ cr-search-field { margin-bottom: 16px; + margin-inline-start: 20px; margin-top: 16px; } @@ -56,6 +58,7 @@ } .padded { + padding-inline-end: 20px; padding-inline-start: 20px; } @@ -71,7 +74,7 @@ localized-string="[[i18nAdvanced( 'changeDeviceLanguageDialogDescription')]]"> </settings-localized-link> - <cr-search-field class="padded" label="$i18n{searchLanguages}" + <cr-search-field label="$i18n{searchLanguages}" id="search" on-search-changed="onSearchChanged_" clear-label="$i18n{clearSearch}" on-keydown="onKeydown_" autofocus> </cr-search-field>
diff --git a/chrome/browser/resources/settings/chromeos/os_languages_page/input_page.html b/chrome/browser/resources/settings/chromeos/os_languages_page/input_page.html index 0ec67f9..bf8a462c 100644 --- a/chrome/browser/resources/settings/chromeos/os_languages_page/input_page.html +++ b/chrome/browser/resources/settings/chromeos/os_languages_page/input_page.html
@@ -89,6 +89,7 @@ .subsection .list-frame { padding-inline-end: 0; + padding-inline-start: 40px; } .subsection > settings-toggle-button,
diff --git a/chrome/browser/resources/settings/chromeos/os_languages_page/os_add_languages_dialog.html b/chrome/browser/resources/settings/chromeos/os_languages_page/os_add_languages_dialog.html index 61d14f5..9ad3af03b 100644 --- a/chrome/browser/resources/settings/chromeos/os_languages_page/os_add_languages_dialog.html +++ b/chrome/browser/resources/settings/chromeos/os_languages_page/os_add_languages_dialog.html
@@ -7,13 +7,15 @@ <link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html"> <link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html"> <link rel="import" href="chrome://resources/html/find_shortcut_behavior.html"> +<link rel="import" href="chrome://resources/html/load_time_data.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-list/iron-list.html"> +<link rel="import" href="shared_style.html"> <link rel="import" href="../../languages_page/languages.html"> <link rel="import" href="../../settings_shared_css.html"> <dom-module id="os-settings-add-languages-dialog"> <template> - <style include="settings-shared"> + <style include="settings-shared shared-style"> #dialog-body { display: flex; flex-direction: column; @@ -23,21 +25,20 @@ } cr-search-field { - padding-inline-end: 24px; + margin-bottom: 16px; } iron-list { flex: 1; } - .ripple-padding { - /* Create a little extra space for checkbox ink ripple to flow into. */ - padding-inline-start: 20px; - } - cr-checkbox::part(label-container) { white-space: nowrap; } + + .list-item { + min-height: 36px; + } </style> <cr-dialog id="dialog" close-text="$i18n{close}"> <div slot="title">$i18n{addLanguagesDialogTitle}</div> @@ -46,7 +47,7 @@ on-search-changed="onSearchChanged_" on-keydown="onKeydown_" clear-label="$i18n{clearSearch}" autofocus> </cr-search-field> - <iron-list class="ripple-padding" scroll-target="[[$$('[slot=body]')]]" + <iron-list scroll-target="[[$$('[slot=body]')]]" items="[[getLanguages_( languages.supported, languages.enabled.*, filterValue_)]]"> <template>
diff --git a/chrome/browser/resources/settings/chromeos/os_languages_page/shared_style.html b/chrome/browser/resources/settings/chromeos/os_languages_page/shared_style.html new file mode 100644 index 0000000..a8940ac6 --- /dev/null +++ b/chrome/browser/resources/settings/chromeos/os_languages_page/shared_style.html
@@ -0,0 +1,33 @@ + +<!-- Common styles for 'Languages and inputs' section. --> +<dom-module id="shared-style"> + <template> + <style> + cr-search-field { + --cr-search-field-clear-icon-fill: var(--cros-icon-color-secondary); + --cr-search-field-clear-icon-margin-end: 8px; + --cr-search-field-clear-icon-size: 18px; + --cr-search-field-input-border-bottom: none; + --cr-search-field-input-min-height: 32px; + --cr-search-field-input-padding-bottom: 0; + --cr-search-field-input-padding-start: 8px; + --cr-search-field-input-padding-top: 0; + --cr-search-field-input-width: 100%; + --cr-search-field-search-icon-display: none; + --cr-search-field-search-icon-fill: var(--cros-icon-color-secondary); + --cr-search-field-search-icon-inline-display: block; + --cr-search-field-search-icon-inline-margin-start: 6px; + background-color: var(--google-grey-100); + border-radius: 4px; + margin-inline-end: 20px; + } + + cr-dialog [slot=button-container] { + padding-bottom: 20px; + padding-inline-end: 20px; + padding-inline-start: 20px; + padding-top: 20px; + } + </style> + </template> +</dom-module> \ No newline at end of file
diff --git a/chrome/browser/resources/settings/chromeos/os_settings_resources_v3.grdp b/chrome/browser/resources/settings/chromeos/os_settings_resources_v3.grdp index de2f3d8e4..bc2d741 100644 --- a/chrome/browser/resources/settings/chromeos/os_settings_resources_v3.grdp +++ b/chrome/browser/resources/settings/chromeos/os_settings_resources_v3.grdp
@@ -209,6 +209,11 @@ use_base_dir="false" compress="false" type="BINDATA" /> + <include name="IDR_OS_SETTINGS_LANGUAGES_PAGE_SHARED_STYLE_M_JS" + file="${root_gen_dir}/chrome/browser/resources/settings/chromeos/os_languages_page/shared_style.m.js" + use_base_dir="false" + compress="false" + type="BINDATA" /> <include name="IDR_OS_SETTINGS_LANGUAGES_PAGE_SMART_INPUTS_PAGE_M_JS" file="${root_gen_dir}/chrome/browser/resources/settings/chromeos/os_languages_page/smart_inputs_page.m.js" use_base_dir="false"
diff --git a/chrome/browser/resources/settings/os_settings_resources.grd b/chrome/browser/resources/settings/os_settings_resources.grd index 0e5d673d..f83bf32 100644 --- a/chrome/browser/resources/settings/os_settings_resources.grd +++ b/chrome/browser/resources/settings/os_settings_resources.grd
@@ -779,6 +779,9 @@ <structure name="IDR_OS_SETTINGS_LANGUAGES_INPUT_METHOD_UTIL_JS" file="chromeos/os_languages_page/input_method_util.js" compress="false" type="chrome_html" /> + <structure name="IDR_OS_SETTINGS_LANGUAGES_SHARED_STYLE_HTML" + file="chromeos/os_languages_page/shared_style.html" + compress="false" type="chrome_html" /> <structure name="IDR_OS_SETTINGS_LANGUAGES_SMART_INPUTS_PAGE_HTML" file="chromeos/os_languages_page/smart_inputs_page.html" compress="false" type="chrome_html" />
diff --git a/chrome/browser/resources/signin/profile_picker/BUILD.gn b/chrome/browser/resources/signin/profile_picker/BUILD.gn index 833539b..8886a31 100644 --- a/chrome/browser/resources/signin/profile_picker/BUILD.gn +++ b/chrome/browser/resources/signin/profile_picker/BUILD.gn
@@ -2,8 +2,77 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import("//chrome/common/features.gni") import("//third_party/closure_compiler/compile_js.gni") +import("//tools/grit/preprocess_grit.gni") import("//tools/polymer/html_to_js.gni") +import("../../optimize_webui.gni") + +if (optimize_webui) { + preprocess_folder = "preprocessed" + + optimize_webui("build") { + host = "profile-picker" + js_module_in_files = [ + "profile_picker.js", + "lazy_load.js", + ] + input = rebase_path("$target_gen_dir/$preprocess_folder", root_build_dir) + js_out_files = [ + "profile_picker.rollup.js", + "lazy_load.rollup.js", + "shared.rollup.js", + ] + + deps = [ + ":preprocess", + ":preprocess_generated", + ":shared", + "../../../../../ui/webui/resources:preprocess", + ] + excludes = [ + "chrome://resources/js/cr.m.js", + "chrome://resources/mojo/mojo/public/js/mojo_bindings_lite.js", + "chrome://resources/mojo/skia/public/mojom/skcolor.mojom-lite.js", + ] + } + + preprocess_grit("preprocess") { + in_folder = "./" + out_folder = "$target_gen_dir/$preprocess_folder" + in_files = [ + "profile_picker.js", + "navigation_behavior.js", + "policy_helper.js", + "icons.js", + "lazy_load.js", + "ensure_lazy_loaded.js", + "manage_profiles_browser_proxy.js", + ] + } + + preprocess_grit("shared") { + in_folder = "../" + out_folder = "$target_gen_dir/$preprocess_folder" + in_files = [ "signin_icons.js" ] + } + + preprocess_grit("preprocess_generated") { + deps = [ ":web_components" ] + in_folder = target_gen_dir + out_folder = "$target_gen_dir/$preprocess_folder" + in_files = [ + "profile_picker_app.js", + "profile_picker_main_view.js", + "profile_card.js", + "profile_card_menu.js", + "profile_creation_flow/profile_type_choice.js", + "profile_creation_flow/local_profile_customization.js", + "profile_picker_shared_css.js", + "profile_creation_flow/shared_css.js", + ] + } +} group("closure_compile") { deps = [ @@ -20,11 +89,38 @@ "js_module_root=./gen/chrome/browser/resources/signin/profile_picker/", ] deps = [ + ":ensure_lazy_loaded", + ":lazy_load", + ":navigation_behavior", + ":policy_helper", + ":profile_card", + ":profile_card_menu", + ":profile_picker", ":profile_picker_app", ":profile_picker_main_view", ] } +js_library("profile_picker") { + deps = [ + ":ensure_lazy_loaded", + ":manage_profiles_browser_proxy", + ":navigation_behavior", + ":profile_picker_app", + ] +} + +js_library("ensure_lazy_loaded") { + deps = [ ":lazy_load" ] +} + +js_library("lazy_load") { + deps = [ + "profile_creation_flow:local_profile_customization", + "profile_creation_flow:profile_type_choice", + ] +} + js_library("profile_picker_main_view") { deps = [ ":manage_profiles_browser_proxy", @@ -50,7 +146,9 @@ js_library("profile_picker_app") { deps = [ + ":ensure_lazy_loaded", ":navigation_behavior", + ":profile_picker_main_view", "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", "//ui/webui/resources/cr_elements/cr_lazy_render:cr_lazy_render.m", "//ui/webui/resources/cr_elements/cr_view_manager:cr_view_manager.m",
diff --git a/chrome/browser/resources/signin/profile_picker/profile_creation_flow/ensure_lazy_loaded.js b/chrome/browser/resources/signin/profile_picker/ensure_lazy_loaded.js similarity index 92% rename from chrome/browser/resources/signin/profile_picker/profile_creation_flow/ensure_lazy_loaded.js rename to chrome/browser/resources/signin/profile_picker/ensure_lazy_loaded.js index 0bea58dc..78ccede 100644 --- a/chrome/browser/resources/signin/profile_picker/profile_creation_flow/ensure_lazy_loaded.js +++ b/chrome/browser/resources/signin/profile_picker/ensure_lazy_loaded.js
@@ -13,7 +13,7 @@ if (!lazyLoadPromise) { const script = document.createElement('script'); script.type = 'module'; - script.src = './profile_creation_flow/lazy_load.js'; + script.src = './lazy_load.js'; document.body.appendChild(script); lazyLoadPromise = Promise.all([
diff --git a/chrome/browser/resources/signin/profile_picker/lazy_load.js b/chrome/browser/resources/signin/profile_picker/lazy_load.js new file mode 100644 index 0000000..6ed3d8f8 --- /dev/null +++ b/chrome/browser/resources/signin/profile_picker/lazy_load.js
@@ -0,0 +1,6 @@ +// 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 './profile_creation_flow/profile_type_choice.js'; +import './profile_creation_flow/local_profile_customization.js';
diff --git a/chrome/browser/resources/signin/profile_picker/profile_creation_flow/BUILD.gn b/chrome/browser/resources/signin/profile_picker/profile_creation_flow/BUILD.gn index 9c3a1c9e..e5b2e17 100644 --- a/chrome/browser/resources/signin/profile_picker/profile_creation_flow/BUILD.gn +++ b/chrome/browser/resources/signin/profile_picker/profile_creation_flow/BUILD.gn
@@ -13,9 +13,6 @@ ] } -js_library("ensure_lazy_loaded") { -} - js_library("profile_type_choice") { deps = [ "..:manage_profiles_browser_proxy",
diff --git a/chrome/browser/resources/signin/profile_picker/profile_creation_flow/lazy_load.js b/chrome/browser/resources/signin/profile_picker/profile_creation_flow/lazy_load.js deleted file mode 100644 index ab38aa4..0000000 --- a/chrome/browser/resources/signin/profile_picker/profile_creation_flow/lazy_load.js +++ /dev/null
@@ -1,6 +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 './profile_type_choice.js'; -import './local_profile_customization.js'; \ No newline at end of file
diff --git a/chrome/browser/resources/signin/profile_picker/profile_creation_flow/local_profile_customization.html b/chrome/browser/resources/signin/profile_picker/profile_creation_flow/local_profile_customization.html index 534c545..688e73e3 100644 --- a/chrome/browser/resources/signin/profile_picker/profile_creation_flow/local_profile_customization.html +++ b/chrome/browser/resources/signin/profile_picker/profile_creation_flow/local_profile_customization.html
@@ -127,7 +127,7 @@ <div id="wrapperContainer"> <div id="wrapper"> - <cr-input id="nameInput" value="{{profileName_}}" pattern=".*\\S.*" + <cr-input id="nameInput" value="{{profileName_}}" pattern="[[pattern_]]" placeholder="$i18n{createProfileNamePlaceholder}" auto-validate spellcheck="false"> </cr-input>
diff --git a/chrome/browser/resources/signin/profile_picker/profile_creation_flow/local_profile_customization.js b/chrome/browser/resources/signin/profile_picker/profile_creation_flow/local_profile_customization.js index 98262e8..e5836bd 100644 --- a/chrome/browser/resources/signin/profile_picker/profile_creation_flow/local_profile_customization.js +++ b/chrome/browser/resources/signin/profile_picker/profile_creation_flow/local_profile_customization.js
@@ -91,6 +91,12 @@ type: Boolean, value: false, }, + + /** @private */ + pattern_: { + type: String, + value: '.*\\S.*', + }, }, /** @private {?ManageProfilesBrowserProxy} */
diff --git a/chrome/browser/resources/signin/profile_picker/profile_picker.html b/chrome/browser/resources/signin/profile_picker/profile_picker.html index 50393e2a..354582a6 100644 --- a/chrome/browser/resources/signin/profile_picker/profile_picker.html +++ b/chrome/browser/resources/signin/profile_picker/profile_picker.html
@@ -1,6 +1,7 @@ <!doctype html> <html dir="$i18n{textdirection}" lang="$i18n{language}"> <head> + <base href="chrome://profile-picker"> <meta charset="utf-8"> <link rel="stylesheet" href="chrome://resources/css/md_colors.css"> <link rel="stylesheet" href="chrome://resources/css/text_defaults_md.css"> @@ -18,6 +19,6 @@ } </style> <profile-picker-app></profile-picker-app> - <script type="module" src="profile_picker_app.js"></script> + <script type="module" src="profile_picker.js"></script> </body> </html>
diff --git a/chrome/browser/resources/signin/profile_picker/profile_picker.js b/chrome/browser/resources/signin/profile_picker/profile_picker.js new file mode 100644 index 0000000..371ba51 --- /dev/null +++ b/chrome/browser/resources/signin/profile_picker/profile_picker.js
@@ -0,0 +1,5 @@ +import './profile_picker_app.js'; + +export {ensureLazyLoaded} from './ensure_lazy_loaded.js'; +export {ManageProfilesBrowserProxy, ManageProfilesBrowserProxyImpl} from './manage_profiles_browser_proxy.js'; +export {navigateTo, Routes} from './navigation_behavior.js';
diff --git a/chrome/browser/resources/signin/profile_picker/profile_picker_app.js b/chrome/browser/resources/signin/profile_picker/profile_picker_app.js index 0fa0fdd0..3220292 100644 --- a/chrome/browser/resources/signin/profile_picker/profile_picker_app.js +++ b/chrome/browser/resources/signin/profile_picker/profile_picker_app.js
@@ -11,10 +11,10 @@ import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js'; import {html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {ensureLazyLoaded} from './ensure_lazy_loaded.js'; import {AutogeneratedThemeColorInfo, ManageProfilesBrowserProxy, ManageProfilesBrowserProxyImpl} from './manage_profiles_browser_proxy.js'; import {navigateTo, NavigationBehavior, ProfileCreationSteps, Routes} from './navigation_behavior.js'; import {isProfileCreationAllowed} from './policy_helper.js'; -import {ensureLazyLoaded} from './profile_creation_flow/ensure_lazy_loaded.js'; Polymer({ is: 'profile-picker-app',
diff --git a/chrome/browser/resources/signin/profile_picker/profile_picker_resources.grd b/chrome/browser/resources/signin/profile_picker/profile_picker_resources.grd index 66f0f145..5113e8d 100644 --- a/chrome/browser/resources/signin/profile_picker/profile_picker_resources.grd +++ b/chrome/browser/resources/signin/profile_picker/profile_picker_resources.grd
@@ -63,6 +63,11 @@ type="chrome_html" compress="false"/> <structure + name="IDR_PROFILE_PICKER_PROFILE_PICKER_JS" + file="profile_picker.js" + type="chrome_html" + compress="false"/> + <structure name="IDR_PROFILE_PICKER_NAVIGATION_BEHAVIOR_JS" file="navigation_behavior.js" type="chrome_html" @@ -78,18 +83,13 @@ type="chrome_html" compress="false"/> <structure - name="IDR_SIGNIN_ICONS_JS" - file="../signin_icons.js" - type="chrome_html" - compress="false"/> - <structure name="IDR_PROFILE_PICKER_LAZY_LOAD_JS" - file="profile_creation_flow/lazy_load.js" + file="lazy_load.js" type="chrome_html" compress="false"/> <structure name="IDR_PROFILE_PICKER_ENSURE_LAZY_LOADED_JS" - file="profile_creation_flow/ensure_lazy_loaded.js" + file="ensure_lazy_loaded.js" type="chrome_html" compress="false"/> <structure
diff --git a/chrome/browser/resources/signin/profile_picker/profile_picker_resources_vulcanized.grd b/chrome/browser/resources/signin/profile_picker/profile_picker_resources_vulcanized.grd new file mode 100644 index 0000000..a63a97c --- /dev/null +++ b/chrome/browser/resources/signin/profile_picker/profile_picker_resources_vulcanized.grd
@@ -0,0 +1,50 @@ +<?xml version="1.0" encoding="UTF-8"?> +<grit latest_public_release="0" current_release="1" output_all_resource_defines="false"> + <outputs> + <output filename="grit/profile_picker_resources.h" type="rc_header"> + <emit emit_type='prepend'></emit> + </output> + <output filename="grit/profile_picker_resources_map.cc" + type="resource_map_source" /> + <output filename="grit/profile_picker_resources_map.h" + type="resource_map_header" /> + <output filename="profile_picker_resources.pak" type="data_package" /> + </outputs> + <release seq="1"> + <includes> + <include name="IDR_PROFILE_PICKER_PROFILE_PICKER_HTML" + file="profile_picker.html" + type="chrome_html" /> + <include name="IDR_PROFILE_PICKER_PROFILE_PICKER_ROLLUP_JS" + file="${root_gen_dir}/chrome/browser/resources/signin/profile_picker/profile_picker.rollup.js" + use_base_dir="false" + type="chrome_html" /> + <include name="IDR_PROFILE_PICKER_LAZY_LOAD_ROLLUP_JS" + file="${root_gen_dir}/chrome/browser/resources/signin/profile_picker/lazy_load.rollup.js" + type="BINDATA" + use_base_dir="false" /> + <include name="IDR_PROFILE_PICKER_SHARED_ROLLUP_JS" + file="${root_gen_dir}/chrome/browser/resources/signin/profile_picker/shared.rollup.js" + type="BINDATA" + use_base_dir="false" /> + <include name="IDR_PROFILE_PICKER_IMAGES_LEFT_BANNER_IMAGE" + file="images/left_banner_image.svg" + type="BINDATA" /> + <include name="IDR_PROFILE_PICKER_IMAGES_RIGHT_BANNER_IMAGE" + file="images/right_banner_image.svg" + type="BINDATA" /> + <include name="IDR_PROFILE_PICKER_IMAGES_DARK_MODE_LEFT_BANNER_IMAGE" + file="images/dark_mode_left_banner_image.svg" + type="BINDATA" /> + <include name="IDR_PROFILE_PICKER_IMAGES_DARK_MODE_RIGHT_BANNER_IMAGE" + file="images/dark_mode_right_banner_image.svg" + type="BINDATA" /> + <include name="IDR_PROFILE_PICKER_PROFILE_CREATION_FLOW_IMAGES_BANNER_LIGHT_IMAGE" + file="profile_creation_flow/images/banner_light_image.svg" + type="BINDATA" /> + <include name="IDR_PROFILE_PICKER_PROFILE_CREATION_FLOW_IMAGES_BANNER_DARK_IMAGE" + file="profile_creation_flow/images/banner_dark_image.svg" + type="BINDATA" /> + </includes> + </release> +</grit>
diff --git a/chrome/browser/ssl/sct_reporting_service_browsertest.cc b/chrome/browser/ssl/sct_reporting_service_browsertest.cc index f9f46979..16ce472e 100644 --- a/chrome/browser/ssl/sct_reporting_service_browsertest.cc +++ b/chrome/browser/ssl/sct_reporting_service_browsertest.cc
@@ -53,7 +53,7 @@ std::unique_ptr<net::StreamSocket> socket) override {} void WaitForConnections(size_t num_connections) { - if (connections_seen_ >= connections_expected_) + if (connections_seen_ >= num_connections) return; connections_expected_ = num_connections; @@ -206,7 +206,7 @@ // Tests that disabling Extended Reporting causes the cache to be cleared. IN_PROC_BROWSER_TEST_F(SCTReportingServiceBrowserTest, - DISABLED_OptingOutClearsSCTAuditingCache) { + OptingOutClearsSCTAuditingCache) { // Enable SCT auditing and enqueue a report. SetExtendedReportingEnabled(true); @@ -231,7 +231,7 @@ // Tests that reports are still sent for opted-in profiles after the network // service crashes and is restarted. IN_PROC_BROWSER_TEST_F(SCTReportingServiceBrowserTest, - DISABLED_ReportsSentAfterNetworkServiceRestart) { + ReportsSentAfterNetworkServiceRestart) { // This test is only applicable to out-of-process network service because it // tests what happens when the network service crashes and restarts. if (content::IsInProcessNetworkService()) {
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index 91f180fe2..523123b9 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -2181,6 +2181,12 @@ "webui/chromeos/image_source.h", "webui/chromeos/in_session_password_change/confirm_password_change_handler.cc", "webui/chromeos/in_session_password_change/confirm_password_change_handler.h", + "webui/chromeos/in_session_password_change/lock_screen_reauth_dialogs.cc", + "webui/chromeos/in_session_password_change/lock_screen_reauth_dialogs.h", + "webui/chromeos/in_session_password_change/lock_screen_reauth_handler.cc", + "webui/chromeos/in_session_password_change/lock_screen_reauth_handler.h", + "webui/chromeos/in_session_password_change/lock_screen_start_reauth_ui.cc", + "webui/chromeos/in_session_password_change/lock_screen_start_reauth_ui.h", "webui/chromeos/in_session_password_change/password_change_dialogs.cc", "webui/chromeos/in_session_password_change/password_change_dialogs.h", "webui/chromeos/in_session_password_change/password_change_handler.cc",
diff --git a/chrome/browser/ui/app_list/search/files/drive_zero_state_provider.cc b/chrome/browser/ui/app_list/search/files/drive_zero_state_provider.cc index 8f409b0d..6c8991acc 100644 --- a/chrome/browser/ui/app_list/search/files/drive_zero_state_provider.cc +++ b/chrome/browser/ui/app_list/search/files/drive_zero_state_provider.cc
@@ -13,6 +13,7 @@ #include "base/bind.h" #include "base/files/file_util.h" #include "base/metrics/histogram_macros.h" +#include "base/strings/utf_string_conversions.h" #include "base/task/post_task.h" #include "base/task/task_traits.h" #include "base/task/thread_pool.h" @@ -27,7 +28,9 @@ namespace app_list { namespace { -constexpr char kSchema[] = "drive_zero_state://"; +// Schemas of result IDs for the results list and suggestion chips. +constexpr char kListSchema[] = "drive_zero_state://"; +constexpr char kChipSchema[] = "drive_zero_state_chip://"; // Given an absolute path representing a file in the user's Drive, returns a // reparented version of the path within the user's drive fs mount. @@ -56,18 +59,36 @@ task_runner_ = base::ThreadPool::CreateSequencedTaskRunner( {base::TaskPriority::BEST_EFFORT, base::MayBlock(), base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN}); + + // Warm the results cache if or when drivefs is mounted by fetching from the + // Drive QuickAccess API. This is necessary only if the suggested files + // experiment is enabled, so that results are ready for display in the + // suggested chips on the first launcher open after login. + if (suggested_files_enabled_ && drive_service_) { + if (drive_service_->IsMounted()) { + // Drivefs is mounted, so we can fetch results immediately. + OnFileSystemMounted(); + } else { + // Wait for DriveFS to be mounted, then fetch results. This happens in + // OnFileSystemMounted. + drive_service_->AddObserver(this); + } + } } -DriveZeroStateProvider::~DriveZeroStateProvider() = default; +DriveZeroStateProvider::~DriveZeroStateProvider() { + if (suggested_files_enabled_ && drive_service_) + drive_service_->RemoveObserver(this); +} void DriveZeroStateProvider::OnFileSystemMounted() { + // This method is called on login, and each time the device wakes from sleep. + // We only want to warm the cache once. if (have_warmed_up_cache_) return; have_warmed_up_cache_ = true; - // TODO(crbug.com/1034842): Query ItemSuggest. We may need to call - // SearchController::Start afterwards, or preferably could just publish the - // results for this search provider. + item_suggest_cache_.UpdateCache(); } void DriveZeroStateProvider::AppListShown() { @@ -144,10 +165,10 @@ // the result. provider_results.emplace_back( - MakeResult(path_or_error->get_path(), score, /*is_chip=*/false)); + MakeListResult(path_or_error->get_path(), score)); if (suggested_files_enabled_) { provider_results.emplace_back( - MakeResult(path_or_error->get_path(), score, /*is_chip=*/true)); + MakeChipResult(path_or_error->get_path(), score)); } } @@ -155,16 +176,22 @@ SwapResults(&provider_results); } -std::unique_ptr<FileResult> DriveZeroStateProvider::MakeResult( +std::unique_ptr<FileResult> DriveZeroStateProvider::MakeListResult( const base::FilePath& filepath, - const float relevance, - const bool is_chip) { + const float relevance) { return std::make_unique<FileResult>( - kSchema, ReparentToDriveMount(filepath, drive_service_), + kListSchema, ReparentToDriveMount(filepath, drive_service_), + ash::AppListSearchResultType::kDriveQuickAccess, + ash::SearchResultDisplayType::kList, relevance, profile_); +} + +std::unique_ptr<FileResult> DriveZeroStateProvider::MakeChipResult( + const base::FilePath& filepath, + const float relevance) { + return std::make_unique<FileResult>( + kChipSchema, ReparentToDriveMount(filepath, drive_service_), ash::AppListSearchResultType::kDriveQuickAccessChip, - is_chip ? ash::SearchResultDisplayType::kChip - : ash::SearchResultDisplayType::kList, - relevance, profile_); + ash::SearchResultDisplayType::kChip, relevance, profile_); } } // namespace app_list
diff --git a/chrome/browser/ui/app_list/search/files/drive_zero_state_provider.h b/chrome/browser/ui/app_list/search/files/drive_zero_state_provider.h index a87a991e..fd8bb422 100644 --- a/chrome/browser/ui/app_list/search/files/drive_zero_state_provider.h +++ b/chrome/browser/ui/app_list/search/files/drive_zero_state_provider.h
@@ -50,9 +50,10 @@ void OnFilePathsLocated( base::Optional<std::vector<drivefs::mojom::FilePathOrErrorPtr>> paths); - std::unique_ptr<FileResult> MakeResult(const base::FilePath& filepath, - const float relevance, - const bool is_chip); + std::unique_ptr<FileResult> MakeListResult(const base::FilePath& filepath, + const float relevance); + std::unique_ptr<FileResult> MakeChipResult(const base::FilePath& filepath, + const float relevance); Profile* const profile_; drive::DriveIntegrationService* const drive_service_;
diff --git a/chrome/browser/ui/app_list/search/files/file_result.cc b/chrome/browser/ui/app_list/search/files/file_result.cc index cf90088f..d017dfeb 100644 --- a/chrome/browser/ui/app_list/search/files/file_result.cc +++ b/chrome/browser/ui/app_list/search/files/file_result.cc
@@ -58,8 +58,10 @@ SetResultType(result_type); switch (result_type) { case ResultType::kDriveQuickAccess: + case ResultType::kDriveQuickAccessChip: SetMetricsType(ash::DRIVE_QUICK_ACCESS); break; + case ResultType::kFileChip: case ResultType::kZeroStateFile: SetMetricsType(ash::ZERO_STATE_FILE); break;
diff --git a/chrome/browser/ui/ash/launcher/chrome_launcher_controller.cc b/chrome/browser/ui/ash/launcher/chrome_launcher_controller.cc index 5075fb3..2d98a99 100644 --- a/chrome/browser/ui/ash/launcher/chrome_launcher_controller.cc +++ b/chrome/browser/ui/ash/launcher/chrome_launcher_controller.cc
@@ -18,6 +18,7 @@ #include "ash/public/cpp/window_animation_types.h" #include "base/bind.h" #include "base/bind_helpers.h" +#include "base/debug/dump_without_crashing.h" #include "base/feature_list.h" #include "base/metrics/histogram_macros.h" #include "base/strings/pattern.h" @@ -1153,7 +1154,13 @@ ash::ShelfItemType shelf_item_type, const base::string16& title) { CHECK(item_delegate); - CHECK(!GetItem(item_delegate->shelf_id())); + if (GetItem(item_delegate->shelf_id())) { + // TODO(crbug.com/1090134): try and identify why this would be called when + // there is an already existing shelf item for this ID. + base::debug::DumpWithoutCrashing(); + return item_delegate->shelf_id(); + } + ash::ShelfItem item; item.status = status; item.type = shelf_item_type;
diff --git a/chrome/browser/ui/ash/login_screen_client.cc b/chrome/browser/ui/ash/login_screen_client.cc index 2adc1562..0337c40 100644 --- a/chrome/browser/ui/ash/login_screen_client.cc +++ b/chrome/browser/ui/ash/login_screen_client.cc
@@ -15,16 +15,22 @@ #include "chrome/browser/chromeos/login/help_app_launcher.h" #include "chrome/browser/chromeos/login/lock/screen_locker.h" #include "chrome/browser/chromeos/login/login_auth_recorder.h" +#include "chrome/browser/chromeos/login/login_pref_names.h" #include "chrome/browser/chromeos/login/reauth_stats.h" +#include "chrome/browser/chromeos/login/saml/in_session_password_sync_manager.h" +#include "chrome/browser/chromeos/login/saml/in_session_password_sync_manager_factory.h" #include "chrome/browser/chromeos/login/ui/login_display_host.h" #include "chrome/browser/chromeos/login/ui/user_adding_screen.h" +#include "chrome/browser/chromeos/profiles/profile_helper.h" #include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/profiles/profile_metrics.h" #include "chrome/browser/ui/ash/wallpaper_controller_client.h" #include "chrome/browser/ui/settings_window_manager_chromeos.h" +#include "chrome/browser/ui/webui/chromeos/in_session_password_change/lock_screen_reauth_dialogs.h" #include "chrome/browser/ui/webui/chromeos/login/l10n_util.h" #include "chrome/browser/ui/webui/settings/chromeos/constants/routes.mojom.h" #include "chrome/common/webui_url_constants.h" +#include "components/session_manager/core/session_manager.h" #include "components/user_manager/remove_user_delegate.h" #include "components/user_manager/user_names.h" @@ -329,5 +335,21 @@ if (chromeos::LoginDisplayHost::default_host()) { chromeos::LoginDisplayHost::default_host()->ShowGaiaDialog( prefilled_account); + } else { + const user_manager::User* user = + user_manager::UserManager::Get()->FindUser(prefilled_account); + Profile* profile = chromeos::ProfileHelper::Get()->GetProfileByUser(user); + if (profile->GetPrefs()->GetBoolean( + chromeos::prefs::kSamlLockScreenReauthenticationEnabled)) { + DCHECK(session_manager::SessionManager::Get()->IsScreenLocked()); + chromeos::InSessionPasswordSyncManager* password_sync_manager = + chromeos::InSessionPasswordSyncManagerFactory::GetForProfile(profile); + if (!password_sync_manager->lock_screen_start_reauth_dialog) { + password_sync_manager->lock_screen_start_reauth_dialog = + std::unique_ptr<chromeos::LockScreenStartReauthDialog>( + new chromeos::LockScreenStartReauthDialog()); + } + password_sync_manager->lock_screen_start_reauth_dialog->Show(); + } } }
diff --git a/chrome/browser/ui/browser_ui_prefs.cc b/chrome/browser/ui/browser_ui_prefs.cc index 887bfc8..796f732 100644 --- a/chrome/browser/ui/browser_ui_prefs.cc +++ b/chrome/browser/ui/browser_ui_prefs.cc
@@ -94,6 +94,7 @@ registry->RegisterStringPref(prefs::kWebRTCUDPPortRange, std::string()); registry->RegisterBooleanPref(prefs::kWebRtcEventLogCollectionAllowed, false); registry->RegisterListPref(prefs::kWebRtcLocalIpsAllowedUrls); + registry->RegisterBooleanPref(prefs::kWebRTCAllowLegacyTLSProtocols, false); // Dictionaries to keep track of default tasks in the file browser. registry->RegisterDictionaryPref(
diff --git a/chrome/browser/ui/exclusive_access/fullscreen_controller_interactive_browsertest.cc b/chrome/browser/ui/exclusive_access/fullscreen_controller_interactive_browsertest.cc index 4a414df0..d9e3dcd4 100644 --- a/chrome/browser/ui/exclusive_access/fullscreen_controller_interactive_browsertest.cc +++ b/chrome/browser/ui/exclusive_access/fullscreen_controller_interactive_browsertest.cc
@@ -420,7 +420,7 @@ // embedded flash fullscreen, since the Flash plugin handles user permissions // requests itself). // Flaky on Linux: crbug.com/1066607 -#if defined(OS_LINUX) || defined(OS_CHROMEOS) +#if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_MAC) #define MAYBE_PrivilegedMouseLockAndFullscreen \ DISABLED_PrivilegedMouseLockAndFullscreen #else
diff --git a/chrome/browser/ui/web_applications/test/web_app_browsertest_util.cc b/chrome/browser/ui/web_applications/test/web_app_browsertest_util.cc index 37e19db..c5a0f7d4 100644 --- a/chrome/browser/ui/web_applications/test/web_app_browsertest_util.cc +++ b/chrome/browser/ui/web_applications/test/web_app_browsertest_util.cc
@@ -84,7 +84,7 @@ // Launches the app, waits for the app url to load. Browser* LaunchWebAppBrowserAndWait(Profile* profile, const AppId& app_id) { ui_test_utils::UrlLoadObserver url_observer( - WebAppProvider::Get(profile)->registrar().GetAppStartUrl(app_id), + WebAppProvider::Get(profile)->registrar().GetAppLaunchUrl(app_id), content::NotificationService::AllSources()); Browser* const app_browser = LaunchWebAppBrowser(profile, app_id); url_observer.Wait();
diff --git a/chrome/browser/ui/web_applications/web_app_launch_manager.cc b/chrome/browser/ui/web_applications/web_app_launch_manager.cc index fe87220..3befff5 100644 --- a/chrome/browser/ui/web_applications/web_app_launch_manager.cc +++ b/chrome/browser/ui/web_applications/web_app_launch_manager.cc
@@ -131,7 +131,7 @@ params.override_url.is_empty() ? os_integration_manager .GetMatchingFileHandlerURL(params.app_id, params.launch_files) - .value_or(provider_->registrar().GetAppStartUrl(params.app_id)) + .value_or(provider_->registrar().GetAppLaunchUrl(params.app_id)) : params.override_url; // Place new windows on the specified display.
diff --git a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc index c414e6cd..eb6691ef 100644 --- a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc +++ b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
@@ -34,6 +34,7 @@ #include "chrome/browser/ui/webui/chromeos/account_manager/account_manager_welcome_ui.h" #include "chrome/browser/ui/webui/chromeos/account_manager/account_migration_welcome_ui.h" #include "chrome/browser/ui/webui/chromeos/chrome_url_disabled/chrome_url_disabled_ui.h" +#include "chrome/browser/ui/webui/chromeos/in_session_password_change/lock_screen_start_reauth_ui.h" #include "chrome/browser/ui/webui/chromeos/in_session_password_change/password_change_ui.h" #include "chrome/browser/ui/webui/commander/commander_ui.h" #include "chrome/browser/ui/webui/components/components_ui.h" @@ -623,6 +624,13 @@ } return &NewWebUI<chromeos::UrgentPasswordExpiryNotificationUI>; } + if (url.host_piece() == chrome::kChromeUILockScreenStartReauthHost) { + if (!profile->GetPrefs()->GetBoolean( + chromeos::prefs::kSamlLockScreenReauthenticationEnabled)) { + return nullptr; + } + return &NewWebUI<chromeos::LockScreenStartReauthUI>; + } if (url.host_piece() == chrome::kChromeUIAccountManagerErrorHost) return &NewWebUI<chromeos::AccountManagerErrorUI>; if (url.host_piece() == chrome::kChromeUIAccountManagerWelcomeHost)
diff --git a/chrome/browser/ui/webui/chromeos/in_session_password_change/lock_screen_reauth_dialogs.cc b/chrome/browser/ui/webui/chromeos/in_session_password_change/lock_screen_reauth_dialogs.cc new file mode 100644 index 0000000..0275b3f --- /dev/null +++ b/chrome/browser/ui/webui/chromeos/in_session_password_change/lock_screen_reauth_dialogs.cc
@@ -0,0 +1,93 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/webui/chromeos/in_session_password_change/lock_screen_reauth_dialogs.h" + +#include <memory> + +#include "base/bind.h" +#include "base/json/json_writer.h" +#include "chrome/browser/ui/webui/chromeos/in_session_password_change/confirm_password_change_handler.h" +#include "chrome/common/webui_url_constants.h" +#include "chrome/grit/browser_resources.h" +#include "chrome/grit/generated_resources.h" +#include "content/public/browser/browser_thread.h" +#include "content/public/browser/web_ui_data_source.h" +#include "ui/display/display.h" +#include "ui/display/screen.h" +#include "ui/strings/grit/ui_strings.h" + +namespace chromeos { + +namespace { + +LockScreenStartReauthDialog* g_dialog = nullptr; + +constexpr gfx::Size kLockScreenReauthSize(768, 640); + +gfx::Size FitSizeToDisplay(const gfx::Size& desired) { + const display::Display display = + display::Screen::GetScreen()->GetPrimaryDisplay(); + + gfx::Size display_size = display.size(); + + if (display.rotation() == display::Display::ROTATE_90 || + display.rotation() == display::Display::ROTATE_270) { + display_size = gfx::Size(display_size.height(), display_size.width()); + } + + display_size.SetToMin(desired); + return display_size; +} + +} // namespace + +BaseLockDialog::BaseLockDialog(GURL url, gfx::Size desired_size) + : SystemWebDialogDelegate(url, /*title=*/base::string16()), + desired_size_(desired_size) {} + +BaseLockDialog::~BaseLockDialog() {} + +void BaseLockDialog::GetDialogSize(gfx::Size* size) const { + *size = FitSizeToDisplay(desired_size_); +} + +void BaseLockDialog::AdjustWidgetInitParams(views::Widget::InitParams* params) { + params->type = views::Widget::InitParams::TYPE_WINDOW_FRAMELESS; +} + +ui::ModalType BaseLockDialog::GetDialogModalType() const { + return ui::ModalType::MODAL_TYPE_SYSTEM; +} + +void LockScreenStartReauthDialog::Show() { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + if (g_dialog) { + g_dialog->Focus(); + return; + } + g_dialog = new LockScreenStartReauthDialog(); + g_dialog->ShowSystemDialog(); +} + +void LockScreenStartReauthDialog::Dismiss() { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + if (g_dialog) + g_dialog->Close(); +} + +bool LockScreenStartReauthDialog::IsRunning() { + return g_dialog; +} + +LockScreenStartReauthDialog::LockScreenStartReauthDialog() + : BaseLockDialog(GURL(chrome::kChromeUILockScreenStartReauthURL), + kLockScreenReauthSize) {} + +LockScreenStartReauthDialog::~LockScreenStartReauthDialog() { + DCHECK_EQ(this, g_dialog); + g_dialog = nullptr; +} + +} // namespace chromeos
diff --git a/chrome/browser/ui/webui/chromeos/in_session_password_change/lock_screen_reauth_dialogs.h b/chrome/browser/ui/webui/chromeos/in_session_password_change/lock_screen_reauth_dialogs.h new file mode 100644 index 0000000..f46252c --- /dev/null +++ b/chrome/browser/ui/webui/chromeos/in_session_password_change/lock_screen_reauth_dialogs.h
@@ -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. + +#ifndef CHROME_BROWSER_UI_WEBUI_CHROMEOS_IN_SESSION_PASSWORD_CHANGE_LOCK_SCREEN_REAUTH_DIALOGS_H_ +#define CHROME_BROWSER_UI_WEBUI_CHROMEOS_IN_SESSION_PASSWORD_CHANGE_LOCK_SCREEN_REAUTH_DIALOGS_H_ + +#include "base/macros.h" +#include "base/strings/string16.h" +#include "chrome/browser/ui/webui/chromeos/system_web_dialog_delegate.h" +#include "ui/web_dialogs/web_dialog_ui.h" + +namespace chromeos { + +// A modal system dialog without any frame decorating it. +class BaseLockDialog : public SystemWebDialogDelegate { + protected: + BaseLockDialog(GURL url, gfx::Size desired_size); + BaseLockDialog(BaseLockDialog const&) = delete; + ~BaseLockDialog() override; + + // ui::WebDialogDelegate: + void GetDialogSize(gfx::Size* size) const override; + void AdjustWidgetInitParams(views::Widget::InitParams* params) override; + ui::ModalType GetDialogModalType() const override; + + private: + gfx::Size desired_size_; +}; + +class LockScreenStartReauthDialog : public BaseLockDialog { + public: + LockScreenStartReauthDialog(); + LockScreenStartReauthDialog(LockScreenStartReauthDialog const&) = delete; + ~LockScreenStartReauthDialog() override; + + void Show(); + void Dismiss(); + bool IsRunning(); +}; + +} // namespace chromeos + +#endif // CHROME_BROWSER_UI_WEBUI_CHROMEOS_IN_SESSION_PASSWORD_CHANGE_LOCK_SCREEN_REAUTH_DIALOGS_H_
diff --git a/chrome/browser/ui/webui/chromeos/in_session_password_change/lock_screen_reauth_handler.cc b/chrome/browser/ui/webui/chromeos/in_session_password_change/lock_screen_reauth_handler.cc new file mode 100644 index 0000000..58d29d6f --- /dev/null +++ b/chrome/browser/ui/webui/chromeos/in_session_password_change/lock_screen_reauth_handler.cc
@@ -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. + +#include "chrome/browser/ui/webui/chromeos/in_session_password_change/lock_screen_reauth_handler.h" + +namespace chromeos { + +LockScreenReauthHandler::LockScreenReauthHandler() = default; +LockScreenReauthHandler::~LockScreenReauthHandler() = default; + +void LockScreenReauthHandler::HandleInitialize(const base::ListValue* value) {} + +void LockScreenReauthHandler::RegisterMessages() { + web_ui()->RegisterMessageCallback( + "initialize", + base::BindRepeating(&LockScreenReauthHandler::HandleInitialize, + weak_factory_.GetWeakPtr())); +} + +} // namespace chromeos \ No newline at end of file
diff --git a/chrome/browser/ui/webui/chromeos/in_session_password_change/lock_screen_reauth_handler.h b/chrome/browser/ui/webui/chromeos/in_session_password_change/lock_screen_reauth_handler.h new file mode 100644 index 0000000..f8871e1 --- /dev/null +++ b/chrome/browser/ui/webui/chromeos/in_session_password_change/lock_screen_reauth_handler.h
@@ -0,0 +1,31 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_WEBUI_CHROMEOS_IN_SESSION_PASSWORD_CHANGE_LOCK_SCREEN_REAUTH_HANDLER_H_ +#define CHROME_BROWSER_UI_WEBUI_CHROMEOS_IN_SESSION_PASSWORD_CHANGE_LOCK_SCREEN_REAUTH_HANDLER_H_ + +#include "base/memory/weak_ptr.h" +#include "base/values.h" +#include "chrome/browser/chromeos/profiles/profile_helper.h" +#include "components/user_manager/user.h" +#include "content/public/browser/web_ui_message_handler.h" + +namespace chromeos { + +class LockScreenReauthHandler : public content::WebUIMessageHandler { + public: + LockScreenReauthHandler(); + ~LockScreenReauthHandler() override; + + void RegisterMessages() override; + + void HandleInitialize(const base::ListValue*); + + private: + base::WeakPtrFactory<LockScreenReauthHandler> weak_factory_{this}; +}; + +} // namespace chromeos + +#endif // CHROME_BROWSER_UI_WEBUI_CHROMEOS_IN_SESSION_PASSWORD_CHANGE_LOCK_SCREEN_REAUTH_HANDLER_H_
diff --git a/chrome/browser/ui/webui/chromeos/in_session_password_change/lock_screen_start_reauth_ui.cc b/chrome/browser/ui/webui/chromeos/in_session_password_change/lock_screen_start_reauth_ui.cc new file mode 100644 index 0000000..b358215 --- /dev/null +++ b/chrome/browser/ui/webui/chromeos/in_session_password_change/lock_screen_start_reauth_ui.cc
@@ -0,0 +1,68 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/webui/chromeos/in_session_password_change/lock_screen_start_reauth_ui.h" + +#include <memory> + +#include "chrome/browser/chromeos/policy/user_cloud_policy_manager_chromeos.h" +#include "chrome/browser/ui/webui/chromeos/in_session_password_change/lock_screen_reauth_handler.h" +#include "chrome/common/webui_url_constants.h" +#include "chrome/grit/browser_resources.h" +#include "chrome/grit/generated_resources.h" +#include "content/public/browser/web_ui_data_source.h" +#include "ui/base/l10n/l10n_util.h" + +namespace chromeos { + +LockScreenStartReauthUI::LockScreenStartReauthUI(content::WebUI* web_ui) + : ui::WebDialogUI(web_ui) { + Profile* profile = Profile::FromWebUI(web_ui); + const user_manager::User* user = + ProfileHelper::Get()->GetUserByProfile(profile); + std::string email; + if (user) { + email = user->GetDisplayEmail(); + } + + content::WebUIDataSource* source = content::WebUIDataSource::Create( + chrome::kChromeUILockScreenStartReauthHost); + + web_ui->AddMessageHandler(std::make_unique<LockScreenReauthHandler>()); + + // TODO(crbug.com/1098690): Trusted Type Polymer + source->DisableTrustedTypesCSP(); + + source->AddString("lockScreenReauthSubtitile", + l10n_util::GetStringFUTF16(IDS_LOCK_SCREEN_REAUTH_SUBTITLE, + base::UTF8ToUTF16(email))); + source->AddString("lockScreenReauthSubtitileWithError", + l10n_util::GetStringFUTF16(IDS_LOCK_SCREEN_WRONG_USER, + base::UTF8ToUTF16(email))); + + source->AddString("lockScreenVerifyButton", + l10n_util::GetStringUTF16(IDS_LOCK_SCREEN_VERIFY_BUTTON)); + source->AddString( + "lockScreenVerifyAgainButton", + l10n_util::GetStringUTF16(IDS_LOCK_SCREEN_VERIFY_AGAIN_BUTTON)); + source->AddString("lockScreenCancelButton", + l10n_util::GetStringUTF16(IDS_LOCK_SCREEN_CANCEL_BUTTON)); + source->AddString("loginWelcomeMessage", + l10n_util::GetStringUTF16(IDS_LOCK_SCREEN_VERIFY_ACCOUNT)); + source->AddString( + "loginWelcomeMessageWithError", + l10n_util::GetStringUTF16(IDS_LOCK_SCREEN_VERIFICATION_FAILED)); + + source->SetDefaultResource(IDR_LOCK_SCREEN_REAUTH_HTML); + + source->AddResourcePath("authenticator.js", IDR_GAIA_AUTH_AUTHENTICATOR_JS); + + source->AddResourcePath("lock_screen_reauth.js", IDR_LOCK_SCREEN_REAUTH_JS); + + content::WebUIDataSource::Add(profile, source); +} + +LockScreenStartReauthUI::~LockScreenStartReauthUI() = default; + +} // namespace chromeos
diff --git a/chrome/browser/ui/webui/chromeos/in_session_password_change/lock_screen_start_reauth_ui.h b/chrome/browser/ui/webui/chromeos/in_session_password_change/lock_screen_start_reauth_ui.h new file mode 100644 index 0000000..99dfba9e --- /dev/null +++ b/chrome/browser/ui/webui/chromeos/in_session_password_change/lock_screen_start_reauth_ui.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_UI_WEBUI_CHROMEOS_IN_SESSION_PASSWORD_CHANGE_LOCK_SCREEN_START_REAUTH_UI_H_ +#define CHROME_BROWSER_UI_WEBUI_CHROMEOS_IN_SESSION_PASSWORD_CHANGE_LOCK_SCREEN_START_REAUTH_UI_H_ + +#include "ui/web_dialogs/web_dialog_ui.h" + +namespace chromeos { + +// For chrome:://lock-reauth +class LockScreenStartReauthUI : public ui::WebDialogUI { + public: + explicit LockScreenStartReauthUI(content::WebUI* web_ui); + ~LockScreenStartReauthUI() override; +}; + +} // namespace chromeos + +#endif // CHROME_BROWSER_UI_WEBUI_CHROMEOS_IN_SESSION_PASSWORD_CHANGE_LOCK_SCREEN_START_REAUTH_UI_H_
diff --git a/chrome/browser/ui/webui/new_tab_page/promo_browser_command/promo_browser_command_handler.cc b/chrome/browser/ui/webui/new_tab_page/promo_browser_command/promo_browser_command_handler.cc index 57ce137..8a70b840 100644 --- a/chrome/browser/ui/webui/new_tab_page/promo_browser_command/promo_browser_command_handler.cc +++ b/chrome/browser/ui/webui/new_tab_page/promo_browser_command/promo_browser_command_handler.cc
@@ -6,6 +6,7 @@ #include "base/feature_list.h" #include "base/metrics/histogram_functions.h" +#include "base/metrics/user_metrics.h" #include "chrome/browser/browser_features.h" #include "chrome/browser/command_updater_impl.h" #include "chrome/browser/profiles/profile.h" @@ -64,6 +65,8 @@ case Command::kOpenSafetyCheck: NavigateToURL(GURL(chrome::GetSettingsUrl(chrome::kSafetyCheckSubPage)), disposition); + base::RecordAction( + base::UserMetricsAction("NewTabPage_Promos_SafetyCheck")); break; default: NOTREACHED() << "Unspecified behavior for command " << id;
diff --git a/chrome/browser/ui/webui/settings/chromeos/OWNERS b/chrome/browser/ui/webui/settings/chromeos/OWNERS index 2161067..b89ca31 100644 --- a/chrome/browser/ui/webui/settings/chromeos/OWNERS +++ b/chrome/browser/ui/webui/settings/chromeos/OWNERS
@@ -2,5 +2,6 @@ per-file languages_section*=myy@chromium.org per-file multidevice_handler*=file://chromeos/components/multidevice/OWNERS +per-file account_manager_*=file://chromeos/components/account_manager/OWNERS # COMPONENT: OS>Systems>Settings
diff --git a/chrome/browser/ui/webui/settings/chromeos/account_manager_handler_browsertest.cc b/chrome/browser/ui/webui/settings/chromeos/account_manager_handler_browsertest.cc index dda1439..3cd2374 100644 --- a/chrome/browser/ui/webui/settings/chromeos/account_manager_handler_browsertest.cc +++ b/chrome/browser/ui/webui/settings/chromeos/account_manager_handler_browsertest.cc
@@ -14,7 +14,6 @@ #include "chrome/browser/chromeos/profiles/profile_helper.h" #include "chrome/browser/signin/identity_manager_factory.h" #include "chrome/browser/supervised_user/supervised_user_constants.h" -#include "chrome/browser/web_applications/external_web_app_manager.h" #include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/testing_profile.h" #include "chromeos/components/account_manager/account_manager.h" @@ -127,11 +126,6 @@ delete; void SetUpOnMainThread() override { - // Disable preinstalled app scan, it is not compatible with the testing - // profile we create here. - // TODO(crbug.com/1131834): Make it compatible. - web_app::ExternalWebAppManager::SkipStartupForTesting(); - user_manager_enabler_ = std::make_unique<user_manager::ScopedUserManager>( std::make_unique<chromeos::FakeChromeUserManager>()); ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); @@ -232,8 +226,9 @@ std::unique_ptr<TestingAccountManagerUIHandler> handler_; }; +// TODO(https://crbug.com/1131834): Re-enable flaky test. IN_PROC_BROWSER_TEST_P(AccountManagerUIHandlerTest, - OnGetAccountsNoSecondaryAccounts) { + DISABLED_OnGetAccountsNoSecondaryAccounts) { const std::vector<AccountManager::Account> account_manager_accounts = GetAccountsFromAccountManager(); // Only Primary account. @@ -276,8 +271,9 @@ } } +// TODO(https://crbug.com/1131819): Re-enable flaky test. IN_PROC_BROWSER_TEST_P(AccountManagerUIHandlerTest, - OnGetAccountsWithSecondaryAccounts) { + DISABLED_OnGetAccountsWithSecondaryAccounts) { UpsertAccount("secondary1@example.com"); UpsertAccount("secondary2@example.com"); const std::vector<AccountManager::Account> account_manager_accounts =
diff --git a/chrome/browser/ui/webui/signin/profile_picker_ui.cc b/chrome/browser/ui/webui/signin/profile_picker_ui.cc index 088614e3..c047c18 100644 --- a/chrome/browser/ui/webui/signin/profile_picker_ui.cc +++ b/chrome/browser/ui/webui/signin/profile_picker_ui.cc
@@ -16,6 +16,7 @@ #include "chrome/browser/ui/webui/webui_util.h" #include "chrome/common/pref_names.h" #include "chrome/common/webui_url_constants.h" +#include "chrome/grit/browser_resources.h" #include "chrome/grit/chromium_strings.h" #include "chrome/grit/generated_resources.h" #include "chrome/grit/profile_picker_resources.h" @@ -136,12 +137,40 @@ std::string generated_path = "@out_folder@/gen/chrome/browser/resources/signin/profile_picker/"; + + AddStrings(html_source); +#if BUILDFLAG(OPTIMIZE_WEBUI) + webui::SetupBundledWebUIDataSource( + html_source, "profile_picker.js", + IDR_PROFILE_PICKER_PROFILE_PICKER_ROLLUP_JS, + IDR_PROFILE_PICKER_PROFILE_PICKER_HTML); + html_source->AddResourcePath("lazy_load.js", + IDR_PROFILE_PICKER_LAZY_LOAD_ROLLUP_JS); + html_source->AddResourcePath("shared.rollup.js", + IDR_PROFILE_PICKER_SHARED_ROLLUP_JS); + html_source->AddResourcePath("images/left_banner_image.svg", + IDR_PROFILE_PICKER_IMAGES_LEFT_BANNER_IMAGE); + html_source->AddResourcePath("images/right_banner_image.svg", + IDR_PROFILE_PICKER_IMAGES_RIGHT_BANNER_IMAGE); + html_source->AddResourcePath( + "images/dark_mode_left_banner_image.svg", + IDR_PROFILE_PICKER_IMAGES_DARK_MODE_LEFT_BANNER_IMAGE); + html_source->AddResourcePath( + "images/dark_mode_right_banner_image.svg", + IDR_PROFILE_PICKER_IMAGES_DARK_MODE_RIGHT_BANNER_IMAGE); + html_source->AddResourcePath( + "profile_creation_flow/images/banner_light_image.svg", + IDR_PROFILE_PICKER_PROFILE_CREATION_FLOW_IMAGES_BANNER_LIGHT_IMAGE); + html_source->AddResourcePath( + "profile_creation_flow/images/banner_dark_image.svg", + IDR_PROFILE_PICKER_PROFILE_CREATION_FLOW_IMAGES_BANNER_DARK_IMAGE); +#else + html_source->AddResourcePath("signin_icons.js", IDR_SIGNIN_ICONS_JS); webui::SetupWebUIDataSource( html_source, base::make_span(kProfilePickerResources, kProfilePickerResourcesSize), generated_path, IDR_PROFILE_PICKER_PROFILE_PICKER_HTML); - html_source->AddResourcePath("signin_icons.js", IDR_SIGNIN_ICONS_JS); - AddStrings(html_source); +#endif content::WebUIDataSource::Add(profile, html_source); }
diff --git a/chrome/browser/web_applications/components/app_registrar.cc b/chrome/browser/web_applications/components/app_registrar.cc index b308ea6a..103e40c 100644 --- a/chrome/browser/web_applications/components/app_registrar.cc +++ b/chrome/browser/web_applications/components/app_registrar.cc
@@ -131,6 +131,23 @@ profile()->GetPrefs(), app_id, install_source); } +GURL AppRegistrar::GetAppLaunchUrl(const AppId& app_id) const { + const GURL& start_url = GetAppStartUrl(app_id); + const std::string* launch_query_params = GetAppLaunchQueryParams(app_id); + if (!start_url.is_valid() || !launch_query_params) + return start_url; + + GURL::Replacements replacements; + if (start_url.query_piece().empty()) { + replacements.SetQueryStr(*launch_query_params); + return start_url.ReplaceComponents(replacements); + } + + std::string query_params = start_url.query() + "&" + *launch_query_params; + replacements.SetQueryStr(query_params); + return start_url.ReplaceComponents(replacements); +} + extensions::BookmarkAppRegistrar* AppRegistrar::AsBookmarkAppRegistrar() { return nullptr; }
diff --git a/chrome/browser/web_applications/components/app_registrar.h b/chrome/browser/web_applications/components/app_registrar.h index a974a94..96f637c 100644 --- a/chrome/browser/web_applications/components/app_registrar.h +++ b/chrome/browser/web_applications/components/app_registrar.h
@@ -90,6 +90,11 @@ virtual base::Optional<SkColor> GetAppBackgroundColor( const AppId& app_id) const = 0; virtual const GURL& GetAppStartUrl(const AppId& app_id) const = 0; + virtual const std::string* GetAppLaunchQueryParams( + const AppId& app_id) const = 0; + + // Returns the start_url with launch_query_params appended to the end if any. + GURL GetAppLaunchUrl(const AppId& app_id) const; // TODO(crbug.com/910016): Replace uses of this with GetAppScope(). virtual base::Optional<GURL> GetAppScopeInternal(
diff --git a/chrome/browser/web_applications/components/external_install_options.cc b/chrome/browser/web_applications/components/external_install_options.cc index ffbc0c33..5b49a29f 100644 --- a/chrome/browser/web_applications/components/external_install_options.cc +++ b/chrome/browser/web_applications/components/external_install_options.cc
@@ -120,6 +120,8 @@ params.additional_search_terms = install_options.additional_search_terms; + params.launch_query_params = install_options.launch_query_params; + return params; }
diff --git a/chrome/browser/web_applications/components/external_install_options.h b/chrome/browser/web_applications/components/external_install_options.h index b1555403..589c1f6 100644 --- a/chrome/browser/web_applications/components/external_install_options.h +++ b/chrome/browser/web_applications/components/external_install_options.h
@@ -103,6 +103,9 @@ // it. bool reinstall_placeholder = false; + // Optional query parameters to add to the start_url when launching the app. + base::Optional<std::string> launch_query_params; + // Whether we should load |service_worker_registration_url| after successful // installation to allow the site to install its service worker and set up // offline caching.
diff --git a/chrome/browser/web_applications/components/install_manager.h b/chrome/browser/web_applications/components/install_manager.h index 6701606..b0dff73 100644 --- a/chrome/browser/web_applications/components/install_manager.h +++ b/chrome/browser/web_applications/components/install_manager.h
@@ -122,6 +122,8 @@ bool require_manifest = false; std::vector<std::string> additional_search_terms; + + base::Optional<std::string> launch_query_params; }; // Starts a background web app installation process for a given // |web_contents|.
diff --git a/chrome/browser/web_applications/extensions/bookmark_app_registrar.cc b/chrome/browser/web_applications/extensions/bookmark_app_registrar.cc index 313d4d5..379f1253 100644 --- a/chrome/browser/web_applications/extensions/bookmark_app_registrar.cc +++ b/chrome/browser/web_applications/extensions/bookmark_app_registrar.cc
@@ -149,6 +149,12 @@ : GURL::EmptyGURL(); } +// Only implemented for WebApp. Bookmark apps are going away. +const std::string* BookmarkAppRegistrar::GetAppLaunchQueryParams( + const web_app::AppId& app_id) const { + return nullptr; +} + base::Optional<GURL> BookmarkAppRegistrar::GetAppScopeInternal( const web_app::AppId& app_id) const { const Extension* extension = GetBookmarkAppDchecked(app_id);
diff --git a/chrome/browser/web_applications/extensions/bookmark_app_registrar.h b/chrome/browser/web_applications/extensions/bookmark_app_registrar.h index 3931f26..dcb11e2 100644 --- a/chrome/browser/web_applications/extensions/bookmark_app_registrar.h +++ b/chrome/browser/web_applications/extensions/bookmark_app_registrar.h
@@ -46,6 +46,8 @@ base::Optional<SkColor> GetAppBackgroundColor( const web_app::AppId& app_id) const override; const GURL& GetAppStartUrl(const web_app::AppId& app_id) const override; + const std::string* GetAppLaunchQueryParams( + const web_app::AppId& app_id) const override; base::Optional<GURL> GetAppScopeInternal( const web_app::AppId& app_id) const override; web_app::DisplayMode GetAppDisplayMode(
diff --git a/chrome/browser/web_applications/external_web_app_manager_browsertest.cc b/chrome/browser/web_applications/external_web_app_manager_browsertest.cc index 296a8d7..e134328 100644 --- a/chrome/browser/web_applications/external_web_app_manager_browsertest.cc +++ b/chrome/browser/web_applications/external_web_app_manager_browsertest.cc
@@ -81,8 +81,73 @@ ~ExternalWebAppManagerBrowserTest() override = default; }; -// This JSON config functionality is only available on Chrome OS. -#if defined(OS_CHROMEOS) +IN_PROC_BROWSER_TEST_F(ExternalWebAppManagerBrowserTest, + LaunchQueryParamsBasic) { + ASSERT_TRUE(embedded_test_server()->Start()); + + GURL start_url = embedded_test_server()->GetURL("/web_apps/basic.html"); + AppId app_id = GenerateAppIdFromURL(start_url); + EXPECT_FALSE(registrar().IsInstalled(app_id)); + + InstallResultCode code = + SyncDefaultAppConfig(start_url, base::ReplaceStringPlaceholders( + R"({ + "app_url": "$1", + "launch_container": "window", + "user_type": ["unmanaged"], + "launch_query_params": "test_launch_params" + })", + {start_url.spec()}, nullptr)); + EXPECT_EQ(code, InstallResultCode::kSuccessNewInstall); + + EXPECT_TRUE(registrar().IsInstalled(app_id)); + EXPECT_EQ(registrar().GetAppStartUrl(app_id).spec(), start_url); + + GURL launch_url = + embedded_test_server()->GetURL("/web_apps/basic.html?test_launch_params"); + EXPECT_EQ(registrar().GetAppLaunchUrl(app_id), launch_url); + + Browser* app_browser = LaunchWebAppBrowserAndWait(profile(), app_id); + EXPECT_EQ( + app_browser->tab_strip_model()->GetActiveWebContents()->GetVisibleURL(), + launch_url); +} + +IN_PROC_BROWSER_TEST_F(ExternalWebAppManagerBrowserTest, + LaunchQueryParamsComplex) { + ASSERT_TRUE(embedded_test_server()->Start()); + + GURL install_url = embedded_test_server()->GetURL( + "/web_apps/query_params_in_start_url.html"); + GURL start_url = embedded_test_server()->GetURL( + "/web_apps/query_params_in_start_url.html?query_params=in&start=url"); + AppId app_id = GenerateAppIdFromURL(start_url); + EXPECT_FALSE(registrar().IsInstalled(app_id)); + + InstallResultCode code = + SyncDefaultAppConfig(install_url, base::ReplaceStringPlaceholders( + R"({ + "app_url": "$1", + "launch_container": "window", + "user_type": ["unmanaged"], + "launch_query_params": "!@#$$%^*&)(" + })", + {install_url.spec()}, nullptr)); + EXPECT_EQ(code, InstallResultCode::kSuccessNewInstall); + + EXPECT_TRUE(registrar().IsInstalled(app_id)); + EXPECT_EQ(registrar().GetAppStartUrl(app_id).spec(), start_url); + + GURL launch_url = embedded_test_server()->GetURL( + "/web_apps/" + "query_params_in_start_url.html?query_params=in&start=url&!@%23$%^*&)("); + EXPECT_EQ(registrar().GetAppLaunchUrl(app_id), launch_url); + + Browser* app_browser = LaunchWebAppBrowserAndWait(profile(), app_id); + EXPECT_EQ( + app_browser->tab_strip_model()->GetActiveWebContents()->GetVisibleURL(), + launch_url); +} IN_PROC_BROWSER_TEST_F(ExternalWebAppManagerBrowserTest, UninstallAndReplace) { ASSERT_TRUE(embedded_test_server()->Start()); @@ -117,6 +182,10 @@ EXPECT_EQ(app, uninstalled_app.get()); } +// The offline manifest JSON config functionality is only available on Chrome +// OS. +#if defined(OS_CHROMEOS) + // Check that offline fallback installs work offline. IN_PROC_BROWSER_TEST_F(ExternalWebAppManagerBrowserTest, OfflineFallbackManifestSiteOffline) {
diff --git a/chrome/browser/web_applications/external_web_app_utils.cc b/chrome/browser/web_applications/external_web_app_utils.cc index 19046c7..77f5cb24 100644 --- a/chrome/browser/web_applications/external_web_app_utils.cc +++ b/chrome/browser/web_applications/external_web_app_utils.cc
@@ -71,6 +71,10 @@ constexpr char kLaunchContainerTab[] = "tab"; constexpr char kLaunchContainerWindow[] = "window"; +// kLaunchQueryParams is an optional string which specifies query parameters to +// add to the start_url when launching the app. +constexpr char kLaunchQueryParams[] = "launch_query_params"; + // kLoadAndAwaitServiceWorkerRegistration is an optional bool that specifies // whether to fetch the |kServiceWorkerRegistrationUrl| after installation to // allow time for the app to register its service worker. This is done as a @@ -281,6 +285,16 @@ return Result::Error(); } + // launch_query_params + value = app_config.FindKey(kLaunchQueryParams); + if (value) { + if (!value->is_string()) { + LOG(ERROR) << file << " had an invalid " << kLaunchQueryParams; + return Result::Error(); + } + options.launch_query_params = value->GetString(); + } + // load_and_await_service_worker_registration value = app_config.FindKey(kLoadAndAwaitServiceWorkerRegistration); if (value) {
diff --git a/chrome/browser/web_applications/proto/web_app.proto b/chrome/browser/web_applications/proto/web_app.proto index 1b73095..5d8a5198 100644 --- a/chrome/browser/web_applications/proto/web_app.proto +++ b/chrome/browser/web_applications/proto/web_app.proto
@@ -157,4 +157,6 @@ optional RunOnOsLoginMode user_run_on_os_login_mode = 24; optional ShareTarget share_target = 25; + + optional string launch_query_params = 26; }
diff --git a/chrome/browser/web_applications/test/test_app_registrar.cc b/chrome/browser/web_applications/test/test_app_registrar.cc index 9e22814..eb8fb30a 100644 --- a/chrome/browser/web_applications/test/test_app_registrar.cc +++ b/chrome/browser/web_applications/test/test_app_registrar.cc
@@ -112,6 +112,11 @@ return iterator->second.launch_url; } +const std::string* TestAppRegistrar::GetAppLaunchQueryParams( + const AppId& app_id) const { + return nullptr; +} + base::Optional<GURL> TestAppRegistrar::GetAppScopeInternal( const AppId& app_id) const { const auto& result = installed_apps_.find(app_id);
diff --git a/chrome/browser/web_applications/test/test_app_registrar.h b/chrome/browser/web_applications/test/test_app_registrar.h index 4bb0b6b..28683cf 100644 --- a/chrome/browser/web_applications/test/test_app_registrar.h +++ b/chrome/browser/web_applications/test/test_app_registrar.h
@@ -60,6 +60,8 @@ base::Optional<SkColor> GetAppBackgroundColor( const AppId& app_id) const override; const GURL& GetAppStartUrl(const AppId& app_id) const override; + const std::string* GetAppLaunchQueryParams( + const AppId& app_id) const override; base::Optional<GURL> GetAppScopeInternal(const AppId& app_id) const override; DisplayMode GetAppDisplayMode(const AppId& app_id) const override; DisplayMode GetAppUserDisplayMode(const AppId& app_id) const override;
diff --git a/chrome/browser/web_applications/web_app.cc b/chrome/browser/web_applications/web_app.cc index ad7b65f..47407e200 100644 --- a/chrome/browser/web_applications/web_app.cc +++ b/chrome/browser/web_applications/web_app.cc
@@ -263,6 +263,11 @@ sync_fallback_data_ = std::move(sync_fallback_data); } +void WebApp::SetLaunchQueryParams( + base::Optional<std::string> launch_query_params) { + launch_query_params_ = std::move(launch_query_params); +} + WebApp::SyncFallbackData::SyncFallbackData() = default; WebApp::SyncFallbackData::~SyncFallbackData() = default; @@ -288,6 +293,9 @@ out << "app_id: " << app.app_id_ << std::endl << " name: " << app.name_ << std::endl << " start_url: " << app.start_url_ << std::endl + << " launch_query_params: " + << (app.launch_query_params_ ? *app.launch_query_params_ : std::string()) + << std::endl << " scope: " << app.scope_ << std::endl << " theme_color: " << ColorToString(app.theme_color_) << std::endl << " background_color: " << ColorToString(app.background_color_) @@ -354,8 +362,8 @@ bool operator==(const WebApp& app1, const WebApp& app2) { return std::tie(app1.app_id_, app1.sources_, app1.name_, app1.start_url_, - app1.description_, app1.scope_, app1.theme_color_, - app1.background_color_, app1.icon_infos_, + app1.launch_query_params_, app1.description_, app1.scope_, + app1.theme_color_, app1.background_color_, app1.icon_infos_, app1.downloaded_icon_sizes_any_, app1.downloaded_icon_sizes_maskable_, app1.is_generated_icon_, app1.display_mode_, app1.display_mode_override_, @@ -367,8 +375,8 @@ app1.sync_fallback_data_, app1.last_launch_time_, app1.install_time_, app1.run_on_os_login_mode_) == std::tie(app2.app_id_, app2.sources_, app2.name_, app2.start_url_, - app2.description_, app2.scope_, app2.theme_color_, - app2.background_color_, app2.icon_infos_, + app2.launch_query_params_, app2.description_, app2.scope_, + app2.theme_color_, app2.background_color_, app2.icon_infos_, app2.downloaded_icon_sizes_any_, app2.downloaded_icon_sizes_maskable_, app2.is_generated_icon_, app2.display_mode_, app2.display_mode_override_,
diff --git a/chrome/browser/web_applications/web_app.h b/chrome/browser/web_applications/web_app.h index 63edf22..5aa6546 100644 --- a/chrome/browser/web_applications/web_app.h +++ b/chrome/browser/web_applications/web_app.h
@@ -45,6 +45,11 @@ const std::string& description() const { return description_; } const GURL& start_url() const { return start_url_; } + + const std::string* launch_query_params() const { + return launch_query_params_ ? &launch_query_params_.value() : nullptr; + } + const GURL& scope() const { return scope_; } const base::Optional<SkColor>& theme_color() const { return theme_color_; } @@ -171,6 +176,7 @@ void SetName(const std::string& name); void SetDescription(const std::string& description); void SetStartUrl(const GURL& launch_url); + void SetLaunchQueryParams(base::Optional<std::string> launch_query_params); void SetScope(const GURL& scope); void SetThemeColor(base::Optional<SkColor> theme_color); void SetBackgroundColor(base::Optional<SkColor> background_color); @@ -218,6 +224,7 @@ std::string name_; std::string description_; GURL start_url_; + base::Optional<std::string> launch_query_params_; // TODO(loyso): Implement IsValid() function that verifies that the start_url // is within the scope. GURL scope_;
diff --git a/chrome/browser/web_applications/web_app_database.cc b/chrome/browser/web_applications/web_app_database.cc index 7115c45..89743aa3 100644 --- a/chrome/browser/web_applications/web_app_database.cc +++ b/chrome/browser/web_applications/web_app_database.cc
@@ -157,6 +157,9 @@ local_data->set_is_locally_installed(web_app.is_locally_installed()); // Optional fields: + if (web_app.launch_query_params()) + local_data->set_launch_query_params(*web_app.launch_query_params()); + if (web_app.display_mode() != DisplayMode::kUndefined) { local_data->set_display_mode( ToWebAppProtoDisplayMode(web_app.display_mode())); @@ -394,6 +397,9 @@ } // Optional fields: + if (local_data.has_launch_query_params()) + web_app->SetLaunchQueryParams(local_data.launch_query_params()); + if (local_data.has_display_mode()) web_app->SetDisplayMode(ToMojomDisplayMode(local_data.display_mode()));
diff --git a/chrome/browser/web_applications/web_app_database_unittest.cc b/chrome/browser/web_applications/web_app_database_unittest.cc index 2985706..be9328f4 100644 --- a/chrome/browser/web_applications/web_app_database_unittest.cc +++ b/chrome/browser/web_applications/web_app_database_unittest.cc
@@ -245,6 +245,9 @@ app->SetDisplayModeOverride(std::vector<DisplayMode>( display_mode_override.begin(), display_mode_override.end())); + if (random.next_bool()) + app->SetLaunchQueryParams(base::NumberToString(random.next_uint())); + const RunOnOsLoginMode run_on_os_login_modes[3] = { RunOnOsLoginMode::kUndefined, RunOnOsLoginMode::kWindowed, RunOnOsLoginMode::kMinimized};
diff --git a/chrome/browser/web_applications/web_app_install_task.cc b/chrome/browser/web_applications/web_app_install_task.cc index 9faa11fb..2fd18154 100644 --- a/chrome/browser/web_applications/web_app_install_task.cc +++ b/chrome/browser/web_applications/web_app_install_task.cc
@@ -449,6 +449,9 @@ if (!search_term.empty()) web_app_info->additional_search_terms.push_back(std::move(search_term)); } + + if (install_params_->launch_query_params) + web_app_info->launch_query_params = install_params_->launch_query_params; } data_retriever_->CheckInstallabilityAndRetrieveManifest(
diff --git a/chrome/browser/web_applications/web_app_installation_utils.cc b/chrome/browser/web_applications/web_app_installation_utils.cc index 6833d7c9..8c3540f 100644 --- a/chrome/browser/web_applications/web_app_installation_utils.cc +++ b/chrome/browser/web_applications/web_app_installation_utils.cc
@@ -157,6 +157,7 @@ web_app.SetDisplayModeOverride(web_app_info.display_override); web_app.SetDescription(base::UTF16ToUTF8(web_app_info.description)); + web_app.SetLaunchQueryParams(web_app_info.launch_query_params); web_app.SetScope(web_app_info.scope); DCHECK(!web_app_info.theme_color.has_value() || SkColorGetA(*web_app_info.theme_color) == SK_AlphaOPAQUE);
diff --git a/chrome/browser/web_applications/web_app_registrar.cc b/chrome/browser/web_applications/web_app_registrar.cc index e1b0403..87d11c3 100644 --- a/chrome/browser/web_applications/web_app_registrar.cc +++ b/chrome/browser/web_applications/web_app_registrar.cc
@@ -92,6 +92,12 @@ return web_app ? web_app->start_url() : GURL::EmptyGURL(); } +const std::string* WebAppRegistrar::GetAppLaunchQueryParams( + const AppId& app_id) const { + auto* web_app = GetAppById(app_id); + return web_app ? web_app->launch_query_params() : nullptr; +} + base::Optional<GURL> WebAppRegistrar::GetAppScopeInternal( const AppId& app_id) const { auto* web_app = GetAppById(app_id);
diff --git a/chrome/browser/web_applications/web_app_registrar.h b/chrome/browser/web_applications/web_app_registrar.h index be0be8f..184a167 100644 --- a/chrome/browser/web_applications/web_app_registrar.h +++ b/chrome/browser/web_applications/web_app_registrar.h
@@ -49,6 +49,8 @@ base::Optional<SkColor> GetAppBackgroundColor( const AppId& app_id) const override; const GURL& GetAppStartUrl(const AppId& app_id) const override; + const std::string* GetAppLaunchQueryParams( + const AppId& app_id) const override; base::Optional<GURL> GetAppScopeInternal(const AppId& app_id) const override; DisplayMode GetAppDisplayMode(const AppId& app_id) const override; DisplayMode GetAppUserDisplayMode(const AppId& app_id) const override;
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt index 9210e94..98ceb1d1 100644 --- a/chrome/build/linux.pgo.txt +++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@ -chrome-linux-master-1601337561-307983a438d89a0d060ed0a79e008eada61629c3.profdata +chrome-linux-master-1601380366-03c4c1b9f0c0034a1b47d4510e955a5823e9948c.profdata
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt index 8b06fed..1b99a0a0 100644 --- a/chrome/build/mac.pgo.txt +++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@ -chrome-mac-master-1601337561-8feee235133953607f7453082566ed5b7d8ffb34.profdata +chrome-mac-master-1601380366-c2cef07ee462371a6daba327da84ce5730b353c6.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt index 89dfc05..ad3768ed 100644 --- a/chrome/build/win32.pgo.txt +++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@ -chrome-win32-master-1601294375-ec6f4fd0c2345f1003140fa4e4e991347147fa6d.profdata +chrome-win32-master-1601326576-88be268f41c8e627e3f353defda83bb3fe16d327.profdata
diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc index f5b1882..c865923d 100644 --- a/chrome/common/pref_names.cc +++ b/chrome/common/pref_names.cc
@@ -1559,6 +1559,10 @@ // Holds URL patterns that specify URLs for which local IP addresses are exposed // in ICE candidates. const char kWebRtcLocalIpsAllowedUrls[] = "webrtc.local_ips_allowed_urls"; +// Whether WebRTC PeerConnections are allowed to use legacy versions of the TLS +// and DTLS protocols. +const char kWebRTCAllowLegacyTLSProtocols[] = + "webrtc.allow_legacy_tls_protocols"; #if !defined(OS_ANDROID) // Whether or not this profile has been shown the Welcome page.
diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h index 6ad2e8ff..196240e 100644 --- a/chrome/common/pref_names.h +++ b/chrome/common/pref_names.h
@@ -503,6 +503,7 @@ extern const char kWebRTCUDPPortRange[]; extern const char kWebRtcEventLogCollectionAllowed[]; extern const char kWebRtcLocalIpsAllowedUrls[]; +extern const char kWebRTCAllowLegacyTLSProtocols[]; #if !defined(OS_ANDROID) extern const char kHasSeenWelcomePage[];
diff --git a/chrome/common/web_application_info.h b/chrome/common/web_application_info.h index 34c81d1d..2ec0fe7 100644 --- a/chrome/common/web_application_info.h +++ b/chrome/common/web_application_info.h
@@ -103,6 +103,9 @@ // https://www.w3.org/TR/appmanifest/#start_url-member GURL start_url; + // Optional query parameters to add to the start_url when launching the app. + base::Optional<std::string> launch_query_params; + // Scope for the app. Dictates what URLs will be opened in the app. GURL scope;
diff --git a/chrome/common/webui_url_constants.cc b/chrome/common/webui_url_constants.cc index 4ca3af4..51a36ce 100644 --- a/chrome/common/webui_url_constants.cc +++ b/chrome/common/webui_url_constants.cc
@@ -255,6 +255,8 @@ const char kChromeUIInternetDetailDialogHost[] = "internet-detail-dialog"; const char kChromeUICrostiniCreditsHost[] = "crostini-credits"; const char kChromeUICrostiniCreditsURL[] = "chrome://crostini-credits/"; +const char kChromeUILockScreenStartReauthHost[] = "lock-reauth"; +const char kChromeUILockScreenStartReauthURL[] = "chrome://lock-reauth"; const char kChromeUIMachineLearningInternalsHost[] = "machine-learning-internals"; const char kChromeUIMobileSetupHost[] = "mobilesetup"; @@ -315,6 +317,7 @@ kChromeUIFirstRunHost, kChromeUIInternetConfigDialogHost, kChromeUIInternetDetailDialogHost, + kChromeUILockScreenStartReauthHost, kChromeUIMobileSetupHost, kChromeUIMultiDeviceSetupHost, kChromeUINetworkHost,
diff --git a/chrome/common/webui_url_constants.h b/chrome/common/webui_url_constants.h index 2fd2995..d9e05e4b 100644 --- a/chrome/common/webui_url_constants.h +++ b/chrome/common/webui_url_constants.h
@@ -246,6 +246,8 @@ extern const char kChromeUIInternetDetailDialogHost[]; extern const char kChromeUICrostiniCreditsHost[]; extern const char kChromeUICrostiniCreditsURL[]; +extern const char kChromeUILockScreenStartReauthHost[]; +extern const char kChromeUILockScreenStartReauthURL[]; extern const char kChromeUIMachineLearningInternalsHost[]; extern const char kChromeUIMobileSetupHost[]; extern const char kChromeUIMobileSetupURL[];
diff --git a/chrome/installer/util/work_item_list.cc b/chrome/installer/util/work_item_list.cc index c3485a0..9b06f78 100644 --- a/chrome/installer/util/work_item_list.cc +++ b/chrome/installer/util/work_item_list.cc
@@ -175,10 +175,9 @@ const std::wstring& value_name, int64_t value_data, bool overwrite) { - WorkItem* item = - reinterpret_cast<WorkItem*>(WorkItem::CreateSetRegValueWorkItem( - predefined_root, key_path, wow64_access, value_name, value_data, - overwrite)); + WorkItem* item = WorkItem::CreateSetRegValueWorkItem( + predefined_root, key_path, wow64_access, value_name, value_data, + overwrite); AddWorkItem(item); return item; }
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index 7983783..07c059f 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -125,6 +125,8 @@ "../browser/notifications/notification_display_service_tester.h", "../browser/notifications/stub_notification_platform_bridge.cc", "../browser/notifications/stub_notification_platform_bridge.h", + "../browser/password_manager/password_manager_test_util.cc", + "../browser/password_manager/password_manager_test_util.h", "../browser/permissions/crowd_deny_fake_safe_browsing_database_manager.cc", "../browser/permissions/crowd_deny_fake_safe_browsing_database_manager.h", "../browser/search_engines/template_url_service_factory_test_util.cc",
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeTabbedActivityTestRule.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeTabbedActivityTestRule.java index 98702d3..e31193f 100644 --- a/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeTabbedActivityTestRule.java +++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeTabbedActivityTestRule.java
@@ -4,55 +4,13 @@ package org.chromium.chrome.test; -import org.junit.runner.Description; -import org.junit.runners.model.Statement; - -import org.chromium.base.test.util.UrlUtils; import org.chromium.chrome.browser.ChromeTabbedActivity; -import org.chromium.chrome.browser.feed.FeedProcessScopeFactory; -import org.chromium.chrome.browser.feed.TestNetworkClient; /** - * Custom ActivityTestRule for test using ChromeTabbedActivity + * Custom ActivityTestRule for tests using ChromeTabbedActivity */ public class ChromeTabbedActivityTestRule extends ChromeActivityTestRule<ChromeTabbedActivity> { - // Response file for Feed's network stub. - private static final String DEFAULT_FEED_TEST_RESPONSE_FILE_PATH = - "/chrome/test/data/android/feed/feed_large.gcl.bin"; - - private final String mFeedTestResponseFilePath; - public ChromeTabbedActivityTestRule() { - this(DEFAULT_FEED_TEST_RESPONSE_FILE_PATH); - } - - /** - * @param feedTestResponseFilePath The file path of the response that the feed library returns - * in tests. - */ - public ChromeTabbedActivityTestRule(String feedTestResponseFilePath) { super(ChromeTabbedActivity.class); - mFeedTestResponseFilePath = feedTestResponseFilePath; - } - - @Override - public Statement apply(final Statement base, Description description) { - Statement tabbedActivityStatement = new Statement() { - @Override - public void evaluate() throws Throwable { - // Setup Feed stubs. - TestNetworkClient client = new TestNetworkClient(); - client.setNetworkResponseFile( - UrlUtils.getIsolatedTestFilePath(mFeedTestResponseFilePath)); - FeedProcessScopeFactory.setTestNetworkClient(client); - - base.evaluate(); - - // Teardown the network stubs for Feed if they've been setup. - FeedProcessScopeFactory.setTestNetworkClient(null); - } - }; - - return super.apply(tabbedActivityStatement, description); } }
diff --git a/chrome/test/data/policy/policy_test_cases.json b/chrome/test/data/policy/policy_test_cases.json index 02009bab5..f6e45a1 100644 --- a/chrome/test/data/policy/policy_test_cases.json +++ b/chrome/test/data/policy/policy_test_cases.json
@@ -8199,5 +8199,14 @@ "prefs": { "policy.dlp_rules_list": { "local_state": true } } } ] + }, + "WebRtcAllowLegacyTLSProtocols": { + "os": ["win", "linux", "mac", "chromeos"], + "policy_pref_mapping_test": [ + { + "policies": { "WebRtcAllowLegacyTLSProtocols": false }, + "prefs": { "webrtc.allow_legacy_tls_protocols": {} } + } + ] } }
diff --git a/chrome/test/data/web_apps/query_params_in_start_url.html b/chrome/test/data/web_apps/query_params_in_start_url.html new file mode 100644 index 0000000..df7ac91e --- /dev/null +++ b/chrome/test/data/web_apps/query_params_in_start_url.html
@@ -0,0 +1,13 @@ +<!DOCTYPE html> +<html> +<head> + <link rel="manifest" href="query_params_in_start_url.json"> + <link rel="icon" href="basic-48.png"> +</head> +<body> + <h1>Query params in start_url</h1> + <script> + navigator.serviceWorker.register('/web_apps/service_worker.js'); + </script> +</body> +</html>
diff --git a/chrome/test/data/web_apps/query_params_in_start_url.json b/chrome/test/data/web_apps/query_params_in_start_url.json new file mode 100644 index 0000000..cf2955d --- /dev/null +++ b/chrome/test/data/web_apps/query_params_in_start_url.json
@@ -0,0 +1,17 @@ +{ + "name": "Query params in start_url", + "icons": [ + { + "src": "basic-48.png", + "sizes": "48x48", + "type": "image/png" + }, + { + "src": "basic-192.png", + "sizes": "192x192", + "type": "image/png" + } + ], + "start_url": "query_params_in_start_url.html?query_params=in&start=url", + "display": "standalone" +}
diff --git a/chrome/test/data/webui/settings/passwords_device_section_test.js b/chrome/test/data/webui/settings/passwords_device_section_test.js index 3411f49..bb424635 100644 --- a/chrome/test/data/webui/settings/passwords_device_section_test.js +++ b/chrome/test/data/webui/settings/passwords_device_section_test.js
@@ -5,7 +5,7 @@ /** @fileoverview Runs the Polymer tests for the PasswordsDeviceSection page. */ import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; -import {MultiStorePasswordUiEntry, PasswordManagerImpl, PasswordManagerProxy, Router, routes, SyncBrowserProxyImpl} from 'chrome://settings/settings.js'; +import {MultiStorePasswordUiEntry, PasswordManagerImpl, Router, routes, SyncBrowserProxyImpl} from 'chrome://settings/settings.js'; import {createMultiStorePasswordEntry, createPasswordEntry} from 'chrome://test/settings/passwords_and_autofill_fake_data.js'; import {simulateStoredAccounts, simulateSyncStatus} from 'chrome://test/settings/sync_test_util.m.js'; import {TestPasswordManagerProxy} from 'chrome://test/settings/test_password_manager_proxy.js';
diff --git a/chrome/test/data/webui/settings/passwords_section_test.js b/chrome/test/data/webui/settings/passwords_section_test.js index 60bebf7..1a593ef2 100644 --- a/chrome/test/data/webui/settings/passwords_section_test.js +++ b/chrome/test/data/webui/settings/passwords_section_test.js
@@ -8,15 +8,13 @@ import {isChromeOS, webUIListenerCallback} from 'chrome://resources/js/cr.m.js'; import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js'; import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; -import {MultiStoreExceptionEntry, MultiStorePasswordUiEntry, PasswordManagerImpl, PasswordManagerProxy, ProfileInfoBrowserProxyImpl, Router, routes, SettingsPluralStringProxyImpl} from 'chrome://settings/settings.js'; +import {MultiStoreExceptionEntry, MultiStorePasswordUiEntry, PasswordManagerImpl, PasswordManagerProxy, Router, routes, SettingsPluralStringProxyImpl} from 'chrome://settings/settings.js'; import {createExceptionEntry, createMultiStoreExceptionEntry, createMultiStorePasswordEntry, createPasswordEntry, makeCompromisedCredential, makePasswordCheckStatus, PasswordSectionElementFactory} from 'chrome://test/settings/passwords_and_autofill_fake_data.js'; import {runCancelExportTest, runExportFlowErrorRetryTest, runExportFlowErrorTest, runExportFlowFastTest, runExportFlowSlowTest, runFireCloseEventAfterExportCompleteTest,runStartExportTest} from 'chrome://test/settings/passwords_export_test.js'; import {getSyncAllPrefs, simulateStoredAccounts, simulateSyncStatus} from 'chrome://test/settings/sync_test_util.m.js'; import {TestPasswordManagerProxy} from 'chrome://test/settings/test_password_manager_proxy.js'; -import {TestProfileInfoBrowserProxy} from 'chrome://test/settings/test_profile_info_browser_proxy.m.js'; import {TestPluralStringProxy} from 'chrome://test/test_plural_string_proxy.js'; import {eventToPromise} from 'chrome://test/test_util.m.js'; - // clang-format on const PasswordCheckState = chrome.passwordsPrivate.PasswordCheckState;
diff --git a/chrome/test/data/webui/signin/BUILD.gn b/chrome/test/data/webui/signin/BUILD.gn index 09d855d..b80ad1d2 100644 --- a/chrome/test/data/webui/signin/BUILD.gn +++ b/chrome/test/data/webui/signin/BUILD.gn
@@ -36,7 +36,7 @@ deps = [ "..:chai_assert", "..:test_util.m", - "//chrome/browser/resources/signin/profile_picker/profile_creation_flow:profile_type_choice", + "//chrome/browser/resources/signin/profile_picker:lazy_load", ] } @@ -45,10 +45,7 @@ ":test_manage_profiles_browser_proxy", "..:chai_assert", "..:test_util.m", - "//chrome/browser/resources/signin/profile_picker:navigation_behavior", - "//chrome/browser/resources/signin/profile_picker:profile_picker_app", - "//chrome/browser/resources/signin/profile_picker/profile_creation_flow:ensure_lazy_loaded", - "//chrome/browser/resources/signin/profile_picker/profile_creation_flow:local_profile_customization", + "//chrome/browser/resources/signin/profile_picker:profile_picker", ] } @@ -62,6 +59,6 @@ js_library("test_manage_profiles_browser_proxy") { deps = [ "..:test_browser_proxy.m", - "//chrome/browser/resources/signin/profile_picker:manage_profiles_browser_proxy", + "//chrome/browser/resources/signin/profile_picker:profile_picker", ] }
diff --git a/chrome/test/data/webui/signin/profile_creation_flow_test.js b/chrome/test/data/webui/signin/profile_creation_flow_test.js index 0663c21..a4a8f02 100644 --- a/chrome/test/data/webui/signin/profile_creation_flow_test.js +++ b/chrome/test/data/webui/signin/profile_creation_flow_test.js
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'chrome://profile-picker/profile_creation_flow/profile_type_choice.js'; +import 'chrome://profile-picker/lazy_load.js'; import {assertTrue} from '../chai_assert.js'; import {isChildVisible} from '../test_util.m.js';
diff --git a/chrome/test/data/webui/signin/profile_picker_app_test.js b/chrome/test/data/webui/signin/profile_picker_app_test.js index de5b0387..811eec7c 100644 --- a/chrome/test/data/webui/signin/profile_picker_app_test.js +++ b/chrome/test/data/webui/signin/profile_picker_app_test.js
@@ -2,11 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'chrome://profile-picker/profile_picker_app.js'; - -import {ManageProfilesBrowserProxyImpl} from 'chrome://profile-picker/manage_profiles_browser_proxy.js'; -import {navigateTo, Routes} from 'chrome://profile-picker/navigation_behavior.js'; -import {ensureLazyLoaded} from 'chrome://profile-picker/profile_creation_flow/ensure_lazy_loaded.js'; +import {ensureLazyLoaded, ManageProfilesBrowserProxyImpl, navigateTo, Routes} from 'chrome://profile-picker/profile_picker.js'; import {assertTrue} from '../chai_assert.js'; import {waitBeforeNextRender} from '../test_util.m.js';
diff --git a/chrome/test/data/webui/signin/test_manage_profiles_browser_proxy.js b/chrome/test/data/webui/signin/test_manage_profiles_browser_proxy.js index 3c6126b..adc1aa9 100644 --- a/chrome/test/data/webui/signin/test_manage_profiles_browser_proxy.js +++ b/chrome/test/data/webui/signin/test_manage_profiles_browser_proxy.js
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import {ManageProfilesBrowserProxy} from 'chrome://profile-picker/manage_profiles_browser_proxy.js'; +import {ManageProfilesBrowserProxy} from 'chrome://profile-picker/profile_picker.js'; import {TestBrowserProxy} from '../test_browser_proxy.m.js';
diff --git a/chromeos/components/camera_app_ui/resources/css/main.css b/chromeos/components/camera_app_ui/resources/css/main.css index 082b2c63..ef0de76 100644 --- a/chromeos/components/camera_app_ui/resources/css/main.css +++ b/chromeos/components/camera_app_ui/resources/css/main.css
@@ -11,8 +11,11 @@ } body { + --default-font-family: 'Google Sans', sans-serif; + background: black; bottom: 0; + font-family: var(--default-font-family); height: 100%; left: 0; margin: 0; @@ -269,7 +272,6 @@ border-radius: 16px/50%; color: white; display: inline-block; - font-family: 'Roboto', sans-serif; font-size: 14px; font-weight: 500; line-height: 32px; @@ -517,7 +519,6 @@ #timer-tick-msg { color: white; - font-family: 'Roboto', sans-serif; font-size: 72px; visibility: hidden; } @@ -825,7 +826,6 @@ } #preview-metadata { - font-family: 'Roboto', sans-serif; font-size: 14px; left: 60px; position: absolute; @@ -1024,7 +1024,6 @@ #record-time [i18n-content=record_video_paused_msg] { color: white; flex-shrink: 0; - font-family: 'Roboto', sans-serif; font-size: 13px; } @@ -1059,7 +1058,6 @@ background: rgba(241, 243, 244, 0.8); border-radius: 2px; color: rgb(32, 33, 36); - font-family: 'Roboto', sans-serif; font-size: 12px; left: 0; line-height: 22px; @@ -1081,7 +1079,6 @@ background: rgb(30, 30, 35); border-radius: 16px; color: white; - font-family: 'Roboto', sans-serif; font-size: 16px; line-height: 32px; opacity: 0; @@ -1158,13 +1155,13 @@ } #banner-title-text { - font: 450 18px 'Google Sans', sans-serif; + font: 450 18px var(--default-font-family); vertical-align: middle; } #banner-msg { color: rgb(95, 99, 104); - font: 375 15px/22px 'Roboto'; + font: 375 15px/22px var(--default-font-family); } #banner-close { @@ -1199,7 +1196,6 @@ color: rgb(241, 243, 244); display: flex; flex-shrink: 0; - font-family: 'Roboto', sans-serif; font-size: 13px; height: 64px; justify-content: flex-start; @@ -1394,7 +1390,6 @@ } #view-warning #error-msg { - font-family: 'Roboto', sans-serif; font-size: 18px; line-height: 32px; text-align: center; @@ -1423,7 +1418,6 @@ .dialog .dialog-msg { color: rgb(32, 33, 36); cursor: text; - font-family: 'Roboto', sans-serif; font-size: 14px; max-height: 320px; max-width: 472px; @@ -1459,7 +1453,6 @@ background-color: white; border-style: solid; color: rgb(37, 129, 223); - font-family: 'Roboto', sans-serif; font-size: 12px; margin: 4px; padding: 6px 18px;
diff --git a/chromeos/components/telemetry_extension_ui/diagnostics_service.cc b/chromeos/components/telemetry_extension_ui/diagnostics_service.cc index a95cb23..c79d92f 100644 --- a/chromeos/components/telemetry_extension_ui/diagnostics_service.cc +++ b/chromeos/components/telemetry_extension_ui/diagnostics_service.cc
@@ -190,6 +190,22 @@ std::move(callback))); } +void DiagnosticsService::RunDiskReadRoutine( + health::mojom::DiskReadRoutineTypeEnum type, + uint32_t length_seconds, + uint32_t file_size_mb, + RunDiskReadRoutineCallback callback) { + GetService()->RunDiskReadRoutine( + converters::Convert(type), length_seconds, file_size_mb, + base::BindOnce( + [](health::mojom::DiagnosticsService::RunDiskReadRoutineCallback + callback, + cros_healthd::mojom::RunRoutineResponsePtr ptr) { + std::move(callback).Run(converters::ConvertPtr(std::move(ptr))); + }, + std::move(callback))); +} + void DiagnosticsService::RunPrimeSearchRoutine( uint32_t length_seconds, uint64_t max_num,
diff --git a/chromeos/components/telemetry_extension_ui/diagnostics_service.h b/chromeos/components/telemetry_extension_ui/diagnostics_service.h index 750fe33..381b470a 100644 --- a/chromeos/components/telemetry_extension_ui/diagnostics_service.h +++ b/chromeos/components/telemetry_extension_ui/diagnostics_service.h
@@ -63,6 +63,10 @@ void RunNvmeSelfTestRoutine( health::mojom::NvmeSelfTestTypeEnum nvme_self_test_type, RunNvmeSelfTestRoutineCallback callback) override; + void RunDiskReadRoutine(health::mojom::DiskReadRoutineTypeEnum type, + uint32_t length_seconds, + uint32_t file_size_mb, + RunDiskReadRoutineCallback callback) override; void RunPrimeSearchRoutine(uint32_t length_seconds, uint64_t max_num, RunPrimeSearchRoutineCallback callback) override;
diff --git a/chromeos/components/telemetry_extension_ui/diagnostics_service_converters.cc b/chromeos/components/telemetry_extension_ui/diagnostics_service_converters.cc index d837e10..999a1a2 100644 --- a/chromeos/components/telemetry_extension_ui/diagnostics_service_converters.cc +++ b/chromeos/components/telemetry_extension_ui/diagnostics_service_converters.cc
@@ -205,5 +205,20 @@ 1); } +cros_healthd::mojom::DiskReadRoutineTypeEnum Convert( + health::mojom::DiskReadRoutineTypeEnum input) { + switch (input) { + case health::mojom::DiskReadRoutineTypeEnum::kLinearRead: + return cros_healthd::mojom::DiskReadRoutineTypeEnum::kLinearRead; + case health::mojom::DiskReadRoutineTypeEnum::kRandomRead: + return cros_healthd::mojom::DiskReadRoutineTypeEnum::kRandomRead; + } + NOTREACHED(); + return static_cast<cros_healthd::mojom::DiskReadRoutineTypeEnum>( + static_cast<int>( + cros_healthd::mojom::DiskReadRoutineTypeEnum::kMaxValue) + + 1); +} + } // namespace converters } // namespace chromeos
diff --git a/chromeos/components/telemetry_extension_ui/diagnostics_service_converters.h b/chromeos/components/telemetry_extension_ui/diagnostics_service_converters.h index 14d1bd6..5a12bd3f 100644 --- a/chromeos/components/telemetry_extension_ui/diagnostics_service_converters.h +++ b/chromeos/components/telemetry_extension_ui/diagnostics_service_converters.h
@@ -63,6 +63,9 @@ cros_healthd::mojom::NvmeSelfTestTypeEnum Convert( health::mojom::NvmeSelfTestTypeEnum input); +cros_healthd::mojom::DiskReadRoutineTypeEnum Convert( + health::mojom::DiskReadRoutineTypeEnum input); + } // namespace converters } // namespace chromeos
diff --git a/chromeos/components/telemetry_extension_ui/diagnostics_service_converters_unittest.cc b/chromeos/components/telemetry_extension_ui/diagnostics_service_converters_unittest.cc index 0150e5a..83985a9 100644 --- a/chromeos/components/telemetry_extension_ui/diagnostics_service_converters_unittest.cc +++ b/chromeos/components/telemetry_extension_ui/diagnostics_service_converters_unittest.cc
@@ -86,5 +86,15 @@ cros_healthd::NvmeSelfTestTypeEnum::kLongSelfTest); } +TEST(DiagnosticsServiceConvertersTest, ConvertDiskReadRoutineTypeEnum) { + namespace cros_healthd = ::chromeos::cros_healthd::mojom; + namespace health = ::chromeos::health::mojom; + + EXPECT_EQ(Convert(health::DiskReadRoutineTypeEnum::kLinearRead), + cros_healthd::DiskReadRoutineTypeEnum::kLinearRead); + EXPECT_EQ(Convert(health::DiskReadRoutineTypeEnum::kRandomRead), + cros_healthd::DiskReadRoutineTypeEnum::kRandomRead); +} + } // namespace converters } // namespace chromeos
diff --git a/chromeos/components/telemetry_extension_ui/mojom/diagnostics_service.mojom b/chromeos/components/telemetry_extension_ui/mojom/diagnostics_service.mojom index 8f8d4c9..759a5bd6 100644 --- a/chromeos/components/telemetry_extension_ui/mojom/diagnostics_service.mojom +++ b/chromeos/components/telemetry_extension_ui/mojom/diagnostics_service.mojom
@@ -184,6 +184,28 @@ RunNvmeSelfTestRoutine(NvmeSelfTestTypeEnum nvme_self_test_type) => (RunRoutineResponse response); + // Requests that the DiskRead routine is created and started on the platform. + // The routine will create a test file with md5 checksum, read the test file + // either randomly or linearly, repeatedly for a dedicated duration. If the + // md5 checksum of read back is validated, then the test will pass. + // This routine is only available if GetAvailableRoutines returned kDiskRead. + // + // The request: + // * |type| - type of how disk reading is performed, either linear or random. + // + // * |length_seconds| - length of time, in seconds, to run the DiskRead + // routine for. This parameter needs to be strictly + // greater than zero. + // - TODO(b:167963397) - limit routine duration. + // * |file_size_mb| - test file size, in mega bytes, to test with DiskRead + // routine. Maximum file size is 10 GB. + // The response: + // * |response| - contains a unique identifier and status for the created + // routine. + RunDiskReadRoutine(DiskReadRoutineTypeEnum type, uint32 length_seconds, + uint32 file_size_mb) + => (RunRoutineResponse response); + // Requests that the PrimeSearch routine is created and started on the // platform. Calculate prime numbers between 2 to max_num and verify the // calculation repeatedly in a duration. This routine is only available @@ -355,3 +377,9 @@ kShortSelfTest = 0, // Short time self-test. kLongSelfTest = 1, // Long time self-test. }; + +// Enumeration of the possible DiskRead routine's command type +enum DiskReadRoutineTypeEnum { + kLinearRead, + kRandomRead, +};
diff --git a/chromeos/components/telemetry_extension_ui/resources/message_types.js b/chromeos/components/telemetry_extension_ui/resources/message_types.js index bb51f8a7..153b19a 100644 --- a/chromeos/components/telemetry_extension_ui/resources/message_types.js +++ b/chromeos/components/telemetry_extension_ui/resources/message_types.js
@@ -35,6 +35,7 @@ 'DiagnosticsService.RunNvmeWearLevelRoutine', DIAGNOSTICS_RUN_NVME_SELF_TEST_ROUTINE: 'DiagnosticsService.RunNvmeSelfTestRoutine', + DIAGNOSTICS_RUN_DISK_READ_ROUTINE: 'DiagnosticsService.RunDiskReadRoutine', DIAGNOSTICS_RUN_PRIME_SEARCH_ROUTINE: 'DiagnosticsService.RunPrimeSearchRoutine', DIAGNOSTICS_RUN_BATTERY_DISCHARGE_ROUTINE: @@ -146,6 +147,16 @@ /** * Request message sent by the unprivileged context to the privileged + * context to run disk read routine. + * @typedef {{ + * type: !string, + * lengthSeconds: !number, + * fileSizeMb: !number}} + */ +dpsl_internal.DiagnosticsRunDiskReadRoutineRequest; + +/** + * Request message sent by the unprivileged context to the privileged * context to run prime search routine. * @typedef {{ * lengthSeconds: !number,
diff --git a/chromeos/components/telemetry_extension_ui/resources/trusted.js b/chromeos/components/telemetry_extension_ui/resources/trusted.js index d4f3cad..b2837e00d 100644 --- a/chromeos/components/telemetry_extension_ui/resources/trusted.js +++ b/chromeos/components/telemetry_extension_ui/resources/trusted.js
@@ -162,6 +162,24 @@ throw RangeError( 'nvmeSelfTestTypeToEnum_ does not contain all items from enum!'); } + + const diskReadRoutineTypeEnum = + chromeos.health.mojom.DiskReadRoutineTypeEnum; + + /** + * @type { !Map<!string, !chromeos.health.mojom.DiskReadRoutineTypeEnum> } + * @const + */ + this.diskReadRoutineTypeToEnum_ = new Map([ + ['linear-read', diskReadRoutineTypeEnum.kLinearRead], + ['random-read', diskReadRoutineTypeEnum.kRandomRead], + ]); + + if (this.diskReadRoutineTypeToEnum_.size !== + diskReadRoutineTypeEnum.MAX_VALUE + 1) { + throw RangeError( + 'diskReadRoutineTypeToEnum_ does not contain all items from enum!'); + } } /** @@ -478,6 +496,48 @@ }; /** + * Converts disk read type string to DiskReadRoutineTypeEnum. + * @param { !string } type + * @return { !chromeos.health.mojom.DiskReadRoutineTypeEnum } + */ + convertDiskReadTypeToEnum(type) { + if (!this.diskReadRoutineTypeToEnum_.has(type)) { + throw TypeError(`Diagnostic disk read type '${type}' is unknown.`); + } + + return this.diskReadRoutineTypeToEnum_.get(type); + } + + /** + * Throws an error if fileSizeMb exceeds maxSizeMb. + * @param { !number } fileSizeMb + * @param { !number } maxSizeMb + */ + assertFileSizeLargerThan(fileSizeMb, maxSizeMb) { + if (fileSizeMb > maxSizeMb) { + throw RangeError( + `Diagnostic disk read routine does not allow file sizes greater ` + + `than '${maxSizeMb}'.`); + } + } + + /** + * Runs disk read routine. + * @param { !Object } message + * @return { !RunRoutineResponsePromise } + */ + async handleRunDiskReadRoutine(message) { + const request = + /** @type {!dpsl_internal.DiagnosticsRunDiskReadRoutineRequest} */ + (message); + this.assertNumberIsPositive(request.lengthSeconds); + this.assertFileSizeLargerThan(request.fileSizeMb, 10 * 1000); + return await getOrCreateDiagnosticsService().runDiskReadRoutine( + this.convertDiskReadTypeToEnum(request.type), request.lengthSeconds, + request.fileSizeMb); + }; + + /** * Runs prime search routine. * @param { !Object } message * @return { !RunRoutineResponsePromise } @@ -857,6 +917,12 @@ message)); untrustedMessagePipe.registerHandler( + dpsl_internal.Message.DIAGNOSTICS_RUN_DISK_READ_ROUTINE, + (message) => diagnosticsProxy.genericRunRoutineHandler( + (message) => diagnosticsProxy.handleRunDiskReadRoutine(message), + message)); + +untrustedMessagePipe.registerHandler( dpsl_internal.Message.DIAGNOSTICS_RUN_PRIME_SEARCH_ROUTINE, (message) => diagnosticsProxy.genericRunRoutineHandler( (message) => diagnosticsProxy.handleRunPrimeSearchRoutine(message),
diff --git a/chromeos/components/telemetry_extension_ui/resources/untrusted.js b/chromeos/components/telemetry_extension_ui/resources/untrusted.js index 42de8883..e77f3db 100644 --- a/chromeos/components/telemetry_extension_ui/resources/untrusted.js +++ b/chromeos/components/telemetry_extension_ui/resources/untrusted.js
@@ -268,6 +268,30 @@ } /** + * Requests disk read routine to be run. + * @param { !string } type + * @param { !number } lengthSeconds + * @param { !number } fileSizeMb + * @return { !Promise<!Object> } + * @public + */ + async runDiskReadRoutine(type, lengthSeconds, fileSizeMb) { + const message = + /** + @type {!dpsl_internal.DiagnosticsRunDiskReadRoutineRequest} + */ + ({type: type, lengthSeconds: lengthSeconds, fileSizeMb: fileSizeMb}); + const response = + /** @type {!Object} */ (await messagePipe.sendMessage( + dpsl_internal.Message.DIAGNOSTICS_RUN_DISK_READ_ROUTINE, + message)); + if (response instanceof Error) { + throw response; + } + return response; + } + + /** * Requests prime search routine to be run. * @param { !number } lengthSeconds * @param { !number } maximumNumber
diff --git a/chromeos/components/telemetry_extension_ui/test/telemetry_extension_ui_browsertest.js b/chromeos/components/telemetry_extension_ui/test/telemetry_extension_ui_browsertest.js index 4944cbc..afba56c2 100644 --- a/chromeos/components/telemetry_extension_ui/test/telemetry_extension_ui_browsertest.js +++ b/chromeos/components/telemetry_extension_ui/test/telemetry_extension_ui_browsertest.js
@@ -133,6 +133,15 @@ diagnosticsProxy.convertNvmeSelfTestTypeToEnum('long-self-test'), nvmeSelfTestTypeEnum.kLongSelfTest); + // Unit tests for convertDiskReadTypeToEnum + const diskReadRoutineTypeEnum = chromeos.health.mojom.DiskReadRoutineTypeEnum; + assertEquals( + diagnosticsProxy.convertDiskReadTypeToEnum('linear-read'), + diskReadRoutineTypeEnum.kLinearRead); + assertEquals( + diagnosticsProxy.convertDiskReadTypeToEnum('random-read'), + diskReadRoutineTypeEnum.kRandomRead); + testDone(); }); @@ -391,6 +400,8 @@ ['UntrustedDiagnosticsRequestRunNvmeWearLevelRoutine'], ['UntrustedDiagnosticsRequestRunNvmeSelfTestRoutineInvalidInput'], ['UntrustedDiagnosticsRequestRunNvmeSelfTestRoutine'], + ['UntrustedDiagnosticsRequestRunDiskReadRoutineInvalidInput'], + ['UntrustedDiagnosticsRequestRunDiskReadRoutine'], ['UntrustedDiagnosticsRequestRunPrimeSearchRoutineInvalidInput'], ['UntrustedDiagnosticsRequestRunPrimeSearchRoutine'], ['UntrustedDiagnosticsRequestRunBatteryDischargeRoutineInvalidInput'],
diff --git a/chromeos/components/telemetry_extension_ui/test/untrusted_browsertest.js b/chromeos/components/telemetry_extension_ui/test/untrusted_browsertest.js index fa22efe..d9a5512d 100644 --- a/chromeos/components/telemetry_extension_ui/test/untrusted_browsertest.js +++ b/chromeos/components/telemetry_extension_ui/test/untrusted_browsertest.js
@@ -279,6 +279,66 @@ assertDeepEquals(response2, {id: 123456789, status: 'ready'}); }); +// Tests that runDiskReadRoutine throws the correct error when invalid enum +// is passed as input. +UNTRUSTED_TEST( + 'UntrustedDiagnosticsRequestRunDiskReadRoutineInvalidInput', async () => { + let caughtError1; + try { + await chromeos.diagnostics.runDiskReadRoutine( + 'this-does-not-exist', 10, 10); + } catch (error) { + caughtError1 = error; + } + + assertEquals(caughtError1.name, 'TypeError'); + assertEquals( + caughtError1.message, + `Diagnostic disk read type \'this-does-not-exist\' is unknown.`); + + let caughtError2; + try { + await chromeos.diagnostics.runDiskReadRoutine('linear-read', 0, 10); + } catch (error) { + caughtError2 = error; + } + let caughtError3; + try { + await chromeos.diagnostics.runDiskReadRoutine( + 'random-read', -2147483648, 10); + } catch (error) { + caughtError3 = error; + } + + assertEquals(caughtError3.name, 'RangeError'); + assertEquals(caughtError3.message, `Parameter must be positive.`); + + let caughtError4; + try { + await chromeos.diagnostics.runDiskReadRoutine( + 'random-read', 10, 987654321); + } catch (error) { + caughtError4 = error; + } + + assertEquals(caughtError4.name, 'RangeError'); + assertEquals( + caughtError4.message, + `Diagnostic disk read routine does not allow file sizes greater ` + + `than '10000'.`); + }); + +// Tests that runDiskReadRoutine returns the correct Object. +UNTRUSTED_TEST('UntrustedDiagnosticsRequestRunDiskReadRoutine', async () => { + const response1 = + await chromeos.diagnostics.runDiskReadRoutine('linear-read', 12, 20); + assertDeepEquals(response1, {id: 123456789, status: 'ready'}); + + const response2 = + await chromeos.diagnostics.runDiskReadRoutine('random-read', 20, 10); + assertDeepEquals(response2, {id: 123456789, status: 'ready'}); +}); + // Tests that runPrimeSearchRoutine throws the correct error when invalid enum // is passed as input. UNTRUSTED_TEST(
diff --git a/chromeos/crosapi/mojom/crosapi.mojom b/chromeos/crosapi/mojom/crosapi.mojom index f1a6557..22f2efd 100644 --- a/chromeos/crosapi/mojom/crosapi.mojom +++ b/chromeos/crosapi/mojom/crosapi.mojom
@@ -62,6 +62,14 @@ [MinVersion=3] OnLacrosStartup@6(LacrosInfo lacros_info); }; +[Stable, Extensible] +enum SessionType { + kUnknown, + kRegularSession, + kGuestSession, + kPublicSession +}; + // LacrosInitParams is a set of parameters for initialization of lacros-chrome, // which is passed from ash-chrome to lacros-chrome. Since ash-chrome and // lacros-chrome may have different versions, lacros-chrome must handle this @@ -96,6 +104,10 @@ // consent via settings. [MinVersion=2] bool ash_metrics_enabled@2; + + // Type of the ash-chrome session. + [MinVersion=3] + SessionType session_type@3; }; // LacrosChromeService defines the APIs that live in lacros-chrome and
diff --git a/components/arc/clipboard/arc_clipboard_bridge.cc b/components/arc/clipboard/arc_clipboard_bridge.cc index 9c01aa2..860b420 100644 --- a/components/arc/clipboard/arc_clipboard_bridge.cc +++ b/components/arc/clipboard/arc_clipboard_bridge.cc
@@ -49,7 +49,7 @@ // Unused. URL is sent from CreatePlainText() by reading it from the Bookmark. std::string url; uint32_t fragment_start, fragment_end; - const ui::ClipboardDataEndpoint data_dst(ui::EndpointType::kGuestOs); + const ui::ClipboardDataEndpoint data_dst(ui::EndpointType::kArc); clipboard->ReadHTML(ui::ClipboardBuffer::kCopyPaste, &data_dst, &markup16, &url, &fragment_start, &fragment_end); @@ -71,7 +71,7 @@ base::string16 title; std::string text; std::string mime_type(ui::kMimeTypeText); - const ui::ClipboardDataEndpoint data_dst(ui::EndpointType::kGuestOs); + const ui::ClipboardDataEndpoint data_dst(ui::EndpointType::kArc); // Both Bookmark and AsciiText are represented by text/plain. If both are // present, only use Bookmark. @@ -87,7 +87,7 @@ DCHECK(clipboard); std::vector<base::string16> mime_types; - const ui::ClipboardDataEndpoint data_dst(ui::EndpointType::kGuestOs); + const ui::ClipboardDataEndpoint data_dst(ui::EndpointType::kArc); clipboard->ReadAvailableTypes(ui::ClipboardBuffer::kCopyPaste, &data_dst, &mime_types); @@ -178,7 +178,7 @@ base::AutoReset<bool> auto_reset(&event_originated_at_instance_, true); ui::ScopedClipboardWriter writer( ui::ClipboardBuffer::kCopyPaste, - std::make_unique<ui::ClipboardDataEndpoint>(ui::EndpointType::kGuestOs)); + std::make_unique<ui::ClipboardDataEndpoint>(ui::EndpointType::kArc)); for (const auto& repr : clip_data->representations) { const std::string& mime_type(repr->mime_type);
diff --git a/components/autofill/core/browser/form_parsing/form_field.cc b/components/autofill/core/browser/form_parsing/form_field.cc index 474a952..cafb28d 100644 --- a/components/autofill/core/browser/form_parsing/form_field.cc +++ b/components/autofill/core/browser/form_parsing/form_field.cc
@@ -11,6 +11,7 @@ #include <string> #include <utility> +#include "base/feature_list.h" #include "base/strings/string_piece.h" #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" @@ -159,6 +160,13 @@ return ParseFieldSpecifics(scanner, pattern, MATCH_DEFAULT, match, logging); } +bool FormField::ParseField(AutofillScanner* scanner, + const std::vector<MatchingPattern>& patterns, + AutofillField** match, + const RegExLogging& logging) { + return ParseFieldSpecifics(scanner, patterns, match, logging); +} + bool FormField::ParseFieldSpecifics(AutofillScanner* scanner, const base::string16& pattern, int match_field_attributes, @@ -178,6 +186,43 @@ match_field_input_types, match, logging); } +bool FormField::ParseFieldSpecifics( + AutofillScanner* scanner, + const std::vector<MatchingPattern>& patterns, + AutofillField** match, + const RegExLogging& logging) { + if (scanner->IsEnd()) + return false; + + const AutofillField* field = scanner->Cursor(); + + for (const auto& pattern : patterns) { + if (!MatchesFormControlType(field->form_control_type, + pattern.match_field_input_types)) { + continue; + } + + // TODO(crbug.com/1132831): Remove feature check once launched. + if (base::FeatureList::IsEnabled( + features:: + kAutofillApplyNegativePatternsForFieldTypeDetectionHeuristics)) { + if (FormField::Match(field, base::UTF8ToUTF16(pattern.negative_pattern), + pattern.match_field_attributes, + pattern.match_field_input_types, logging)) { + continue; + } + } + + if (MatchAndAdvance(scanner, base::UTF8ToUTF16(pattern.positive_pattern), + pattern.match_field_attributes, + pattern.match_field_input_types, match, logging)) { + return true; + } + } + + return false; +} + // static bool FormField::ParseFieldSpecifics(AutofillScanner* scanner, const base::string16& pattern,
diff --git a/components/autofill/core/browser/form_parsing/form_field.h b/components/autofill/core/browser/form_parsing/form_field.h index 5e024f6..b4e66505 100644 --- a/components/autofill/core/browser/form_parsing/form_field.h +++ b/components/autofill/core/browser/form_parsing/form_field.h
@@ -66,6 +66,11 @@ AutofillField** match, const RegExLogging& logging = {}); + static bool ParseField(AutofillScanner* scanner, + const std::vector<MatchingPattern>& patterns, + AutofillField** match, + const RegExLogging& logging = {}); + // Parses the stream of fields in |scanner| with regular expression |pattern| // as specified in the |match_type| bit field (see |MatchType|). If |match| // is non-NULL and the pattern matches, |match| will be set to the matched @@ -77,6 +82,11 @@ AutofillField** match, const RegExLogging& logging = {}); + static bool ParseFieldSpecifics(AutofillScanner* scanner, + const std::vector<MatchingPattern>& patterns, + AutofillField** match, + const RegExLogging& logging = {}); + // The same as ParseFieldSpecifics but with splitted match_types into // MatchAttributes and MatchFieldTypes. static bool ParseFieldSpecifics(AutofillScanner* scanner,
diff --git a/components/autofill/core/browser/pattern_provider/pattern_provider.h b/components/autofill/core/browser/pattern_provider/pattern_provider.h index 78563b53..2cb7422 100644 --- a/components/autofill/core/browser/pattern_provider/pattern_provider.h +++ b/components/autofill/core/browser/pattern_provider/pattern_provider.h
@@ -9,7 +9,6 @@ #include "base/macros.h" #include "base/no_destructor.h" -#include "base/synchronization/lock.h" #include "components/autofill/core/browser/field_types.h" #include "components/autofill/core/browser/form_parsing/autofill_parsing_utils.h" #include "components/autofill/core/common/autofill_regex_constants.h"
diff --git a/components/autofill/core/common/autofill_features.cc b/components/autofill/core/common/autofill_features.cc index a90f58fe..50444cf 100644 --- a/components/autofill/core/common/autofill_features.cc +++ b/components/autofill/core/common/autofill_features.cc
@@ -48,6 +48,13 @@ const base::Feature kAutofillAlwaysFillAddresses{ "AlwaysFillAddresses", base::FEATURE_ENABLED_BY_DEFAULT}; +// Controls whether negative patterns are used to parse the field type. +// TODO(crbug.com/1132831): Remove once launched. +const base::Feature + kAutofillApplyNegativePatternsForFieldTypeDetectionHeuristics{ + "AutofillApplyNegativePatternsForFieldTypeDetectionHeuristics", + base::FEATURE_DISABLED_BY_DEFAULT}; + // Controls the use of GET (instead of POST) to fetch cacheable autofill query // responses. const base::Feature kAutofillCacheQueryResponses{
diff --git a/components/autofill/core/common/autofill_features.h b/components/autofill/core/common/autofill_features.h index 82f5615..1bbf2397 100644 --- a/components/autofill/core/common/autofill_features.h +++ b/components/autofill/core/common/autofill_features.h
@@ -26,6 +26,8 @@ extern const base::Feature kAutofillAllowHtmlTypeCountryCodesWithFullNames; extern const base::Feature kAutofillAllowNonHttpActivation; extern const base::Feature kAutofillAlwaysFillAddresses; +extern const base::Feature + kAutofillApplyNegativePatternsForFieldTypeDetectionHeuristics; extern const base::Feature kAutofillCacheQueryResponses; extern const base::Feature kAutofillCreateDataForTest; extern const base::Feature kAutofillEnableAccountWalletStorage;
diff --git a/components/autofill_assistant/browser/actions/select_option_action.cc b/components/autofill_assistant/browser/actions/select_option_action.cc index 0f659d06..2a4fdfb0 100644 --- a/components/autofill_assistant/browser/actions/select_option_action.cc +++ b/components/autofill_assistant/browser/actions/select_option_action.cc
@@ -8,9 +8,11 @@ #include "base/bind.h" #include "base/callback.h" +#include "components/autofill/core/browser/data_model/autofill_profile.h" #include "components/autofill_assistant/browser/actions/action_delegate.h" #include "components/autofill_assistant/browser/actions/action_delegate_util.h" #include "components/autofill_assistant/browser/client_status.h" +#include "components/autofill_assistant/browser/field_formatter.h" namespace autofill_assistant { @@ -23,50 +25,86 @@ SelectOptionAction::~SelectOptionAction() {} void SelectOptionAction::InternalProcessAction(ProcessActionCallback callback) { + process_action_callback_ = std::move(callback); const SelectOptionProto& select_option = proto_.select_option(); - // A non prefilled |select_option| is not supported. - if (!select_option.has_selected_option()) { - VLOG(1) << __func__ << ": empty option"; - UpdateProcessedAction(INVALID_ACTION); - std::move(callback).Run(std::move(processed_action_proto_)); - return; - } Selector selector = Selector(select_option.element()); if (selector.empty()) { VLOG(1) << __func__ << ": empty selector"; - UpdateProcessedAction(INVALID_SELECTOR); - std::move(callback).Run(std::move(processed_action_proto_)); + EndAction(ClientStatus(INVALID_SELECTOR)); return; } + + switch (select_option.value_case()) { + case SelectOptionProto::kSelectedOption: + if (select_option.selected_option().empty()) { + VLOG(1) << __func__ << ": empty |selected_option|"; + EndAction(ClientStatus(INVALID_ACTION)); + return; + } + + value_ = select_option.selected_option(); + break; + case SelectOptionProto::kAutofillValue: { + if (select_option.autofill_value().profile().identifier().empty() || + select_option.autofill_value().value_expression().empty()) { + VLOG(1) << "SelectOptionAction: |autofill_value| with empty " + "|profile.identifier| or |value_expression|"; + EndAction(ClientStatus(INVALID_ACTION)); + return; + } + + const autofill::AutofillProfile* address = + delegate_->GetUserData()->selected_address( + select_option.autofill_value().profile().identifier()); + if (address == nullptr) { + VLOG(1) << "SelectOptionAction: requested unknown address '" + << select_option.autofill_value().profile().identifier() << "'"; + EndAction(ClientStatus(PRECONDITION_FAILED)); + return; + } + + auto value = field_formatter::FormatString( + select_option.autofill_value().value_expression(), + field_formatter::CreateAutofillMappings(*address, + /* locale= */ "en-US")); + if (!value.has_value()) { + EndAction(ClientStatus(AUTOFILL_INFO_NOT_AVAILABLE)); + return; + } + + value_ = *value; + break; + } + default: + VLOG(1) << "Unrecognized field for SelectOptionAction"; + EndAction(ClientStatus(INVALID_ACTION)); + return; + } + delegate_->ShortWaitForElement( selector, base::BindOnce(&SelectOptionAction::OnWaitForElement, - weak_ptr_factory_.GetWeakPtr(), - std::move(callback), selector)); + weak_ptr_factory_.GetWeakPtr(), selector)); } -void SelectOptionAction::OnWaitForElement(ProcessActionCallback callback, - const Selector& selector, +void SelectOptionAction::OnWaitForElement(const Selector& selector, const ClientStatus& element_status) { if (!element_status.ok()) { - UpdateProcessedAction(element_status.proto_status()); - std::move(callback).Run(std::move(processed_action_proto_)); + EndAction(element_status); return; } ActionDelegateUtil::FindElementAndPerform( delegate_, selector, base::BindOnce(&ActionDelegate::SelectOption, delegate_->GetWeakPtr(), - proto_.select_option().selected_option(), - proto_.select_option().select_strategy()), - base::BindOnce(&SelectOptionAction::OnSelectOption, - weak_ptr_factory_.GetWeakPtr(), std::move(callback))); + value_, proto_.select_option().select_strategy()), + base::BindOnce(&SelectOptionAction::EndAction, + weak_ptr_factory_.GetWeakPtr())); } -void SelectOptionAction::OnSelectOption(ProcessActionCallback callback, - const ClientStatus& status) { +void SelectOptionAction::EndAction(const ClientStatus& status) { UpdateProcessedAction(status); - std::move(callback).Run(std::move(processed_action_proto_)); + std::move(process_action_callback_).Run(std::move(processed_action_proto_)); } } // namespace autofill_assistant
diff --git a/components/autofill_assistant/browser/actions/select_option_action.h b/components/autofill_assistant/browser/actions/select_option_action.h index d178b195..e47160d 100644 --- a/components/autofill_assistant/browser/actions/select_option_action.h +++ b/components/autofill_assistant/browser/actions/select_option_action.h
@@ -28,11 +28,13 @@ // Overrides Action: void InternalProcessAction(ProcessActionCallback callback) override; - void OnWaitForElement(ProcessActionCallback callback, - const Selector& selector, + void OnWaitForElement(const Selector& selector, const ClientStatus& element_status); - void OnSelectOption(ProcessActionCallback callback, - const ClientStatus& status); + + void EndAction(const ClientStatus& status); + + std::string value_; + ProcessActionCallback process_action_callback_; base::WeakPtrFactory<SelectOptionAction> weak_ptr_factory_{this};
diff --git a/components/autofill_assistant/browser/actions/select_option_action_unittest.cc b/components/autofill_assistant/browser/actions/select_option_action_unittest.cc index 0380902..3470225b 100644 --- a/components/autofill_assistant/browser/actions/select_option_action_unittest.cc +++ b/components/autofill_assistant/browser/actions/select_option_action_unittest.cc
@@ -4,8 +4,14 @@ #include "components/autofill_assistant/browser/actions/select_option_action.h" +#include "base/guid.h" +#include "base/strings/strcat.h" +#include "base/strings/string_number_conversions.h" #include "base/test/gmock_callback_support.h" #include "base/test/mock_callback.h" +#include "components/autofill/core/browser/autofill_test_utils.h" +#include "components/autofill/core/browser/data_model/autofill_profile.h" +#include "components/autofill/core/browser/field_types.h" #include "components/autofill_assistant/browser/actions/action_test_utils.h" #include "components/autofill_assistant/browser/actions/mock_action_delegate.h" #include "components/autofill_assistant/browser/selector.h" @@ -20,6 +26,7 @@ using ::testing::InSequence; using ::testing::Pointee; using ::testing::Property; +using ::testing::Return; class SelectOptionActionTest : public testing::Test { public: @@ -29,6 +36,9 @@ protected: void Run() { + ON_CALL(mock_action_delegate_, GetUserData) + .WillByDefault(Return(&user_data_)); + ActionProto action_proto; *action_proto.mutable_select_option() = proto_; SelectOptionAction action(&mock_action_delegate_, action_proto); @@ -38,9 +48,10 @@ MockActionDelegate mock_action_delegate_; base::MockCallback<Action::ProcessActionCallback> callback_; SelectOptionProto proto_; + UserData user_data_; }; -TEST_F(SelectOptionActionTest, EmptyOptionFails) { +TEST_F(SelectOptionActionTest, NoValueToSelectFails) { Selector selector({"#select"}); *proto_.mutable_element() = selector.proto; EXPECT_CALL( @@ -49,6 +60,26 @@ Run(); } +TEST_F(SelectOptionActionTest, EmptySelectedOptionFails) { + Selector selector({"#select"}); + *proto_.mutable_element() = selector.proto; + proto_.set_selected_option(""); + EXPECT_CALL( + callback_, + Run(Pointee(Property(&ProcessedActionProto::status, INVALID_ACTION)))); + Run(); +} + +TEST_F(SelectOptionActionTest, EmptyAutofillValueFails) { + Selector selector({"#select"}); + *proto_.mutable_element() = selector.proto; + proto_.mutable_autofill_value(); + EXPECT_CALL( + callback_, + Run(Pointee(Property(&ProcessedActionProto::status, INVALID_ACTION)))); + Run(); +} + TEST_F(SelectOptionActionTest, EmptySelectorFails) { proto_.set_selected_option("option"); EXPECT_CALL( @@ -82,5 +113,77 @@ Run(); } +TEST_F(SelectOptionActionTest, RequestDataFromUnknownProfile) { + Selector selector({"#select"}); + *proto_.mutable_element() = selector.proto; + auto* value = proto_.mutable_autofill_value(); + value->mutable_profile()->set_identifier("none"); + value->set_value_expression("value"); + EXPECT_CALL(callback_, Run(Pointee(Property(&ProcessedActionProto::status, + PRECONDITION_FAILED)))); + Run(); +} + +TEST_F(SelectOptionActionTest, RequestUnknownDataFromProfile) { + autofill::AutofillProfile contact(base::GenerateGUID(), + autofill::test::kEmptyOrigin); + // Middle name is expected to be empty. + autofill::test::SetProfileInfo(&contact, "John", /* middle name */ "", "Doe", + "", "", "", "", "", "", "", "", ""); + user_data_.selected_addresses_["contact"] = + std::make_unique<autofill::AutofillProfile>(contact); + + Selector selector({"#select"}); + *proto_.mutable_element() = selector.proto; + auto* value = proto_.mutable_autofill_value(); + value->mutable_profile()->set_identifier("contact"); + value->set_value_expression( + base::StrCat({"${", + base::NumberToString(static_cast<int>( + autofill::ServerFieldType::NAME_MIDDLE)), + "}"})); + + EXPECT_CALL(callback_, Run(Pointee(Property(&ProcessedActionProto::status, + AUTOFILL_INFO_NOT_AVAILABLE)))); + Run(); +} + +TEST_F(SelectOptionActionTest, SelectOptionFromProfileValue) { + autofill::AutofillProfile contact(base::GenerateGUID(), + autofill::test::kEmptyOrigin); + autofill::test::SetProfileInfo(&contact, "John", "", "Doe", "", "", "", "", + "", "", "", "", ""); + user_data_.selected_addresses_["contact"] = + std::make_unique<autofill::AutofillProfile>(contact); + + InSequence sequence; + + Selector selector({"#select"}); + *proto_.mutable_element() = selector.proto; + auto* value = proto_.mutable_autofill_value(); + value->mutable_profile()->set_identifier("contact"); + value->set_value_expression( + base::StrCat({"${", + base::NumberToString(static_cast<int>( + autofill::ServerFieldType::NAME_FIRST)), + "}"})); + + Selector expected_selector = selector; + EXPECT_CALL(mock_action_delegate_, + OnShortWaitForElement(expected_selector, _)) + .WillOnce(RunOnceCallback<1>(OkClientStatus())); + EXPECT_CALL(mock_action_delegate_, + SelectOption("John", _, + EqualsElement(test_util::MockFindElement( + mock_action_delegate_, expected_selector)), + _)) + .WillOnce(RunOnceCallback<3>(OkClientStatus())); + + EXPECT_CALL( + callback_, + Run(Pointee(Property(&ProcessedActionProto::status, ACTION_APPLIED)))); + Run(); +} + } // namespace } // namespace autofill_assistant
diff --git a/components/autofill_assistant/browser/actions/set_form_field_value_action.cc b/components/autofill_assistant/browser/actions/set_form_field_value_action.cc index 595b5c8..92d47a8 100644 --- a/components/autofill_assistant/browser/actions/set_form_field_value_action.cc +++ b/components/autofill_assistant/browser/actions/set_form_field_value_action.cc
@@ -8,9 +8,11 @@ #include "base/bind.h" #include "base/callback.h" +#include "components/autofill/core/browser/data_model/autofill_profile.h" #include "components/autofill_assistant/browser/actions/action_delegate.h" #include "components/autofill_assistant/browser/actions/action_delegate_util.h" #include "components/autofill_assistant/browser/client_status.h" +#include "components/autofill_assistant/browser/field_formatter.h" namespace autofill_assistant { namespace { @@ -57,6 +59,7 @@ } // Check proto fields. + int keypress_index = 0; for (const auto& keypress : proto_.set_form_value().value()) { switch (keypress.keypress_case()) { case SetFormFieldValueProto_KeyPress::kKeycode: @@ -68,7 +71,7 @@ VLOG(1) << "SetFormFieldValueAction: field `keycode' is deprecated " << "and only supports US-ASCII values (encountered value > " "127). Use field `key' instead."; - EndAction(ClientStatus(INVALID_ACTION)); + FailAction(ClientStatus(INVALID_ACTION), keypress_index); return; } field_inputs_.emplace_back( @@ -79,7 +82,7 @@ if (keypress.keyboard_input().empty()) { VLOG(1) << "SetFormFieldValueAction: field 'keyboard_input' must be " "non-empty if set."; - EndAction(ClientStatus(INVALID_ACTION)); + FailAction(ClientStatus(INVALID_ACTION), keypress_index); return; } field_inputs_.emplace_back( @@ -93,7 +96,7 @@ if (!delegate_->GetUserData()->selected_login_.has_value()) { VLOG(1) << "SetFormFieldValueAction: requested login details not " "available in client memory."; - EndAction(ClientStatus(PRECONDITION_FAILED)); + FailAction(ClientStatus(PRECONDITION_FAILED), keypress_index); return; } if (keypress.keypress_case() == @@ -112,7 +115,7 @@ case SetFormFieldValueProto_KeyPress::kClientMemoryKey: if (keypress.client_memory_key().empty()) { VLOG(1) << "SetFormFieldValueAction: empty |client_memory_key|"; - EndAction(ClientStatus(INVALID_ACTION)); + FailAction(ClientStatus(INVALID_ACTION), keypress_index); return; } if (!delegate_->GetUserData()->has_additional_value( @@ -125,7 +128,7 @@ VLOG(1) << "SetFormFieldValueAction: requested key '" << keypress.client_memory_key() << "' not available in client memory"; - EndAction(ClientStatus(PRECONDITION_FAILED)); + FailAction(ClientStatus(PRECONDITION_FAILED), keypress_index); return; } field_inputs_.emplace_back( @@ -134,11 +137,43 @@ ->strings() .values(0)); break; + case SetFormFieldValueProto_KeyPress::kAutofillValue: { + if (keypress.autofill_value().profile().identifier().empty() || + keypress.autofill_value().value_expression().empty()) { + VLOG(1) << "SetFormFieldValueAction: |autofill_value| with empty " + "|profile.identifier| or |value_expression|"; + FailAction(ClientStatus(INVALID_ACTION), keypress_index); + return; + } + + const autofill::AutofillProfile* address = + delegate_->GetUserData()->selected_address( + keypress.autofill_value().profile().identifier()); + if (address == nullptr) { + VLOG(1) << "SetFormFieldValueAction: requested unknown address '" + << keypress.autofill_value().profile().identifier() << "'"; + FailAction(ClientStatus(PRECONDITION_FAILED), keypress_index); + return; + } + + auto value = field_formatter::FormatString( + keypress.autofill_value().value_expression(), + field_formatter::CreateAutofillMappings(*address, + /* locale= */ "en-US")); + if (!value.has_value()) { + FailAction(ClientStatus(AUTOFILL_INFO_NOT_AVAILABLE), keypress_index); + return; + } + + field_inputs_.emplace_back(*value); + break; + } default: VLOG(1) << "Unrecognized field for SetFormFieldValueProto_KeyPress"; - EndAction(ClientStatus(INVALID_ACTION)); + FailAction(ClientStatus(INVALID_ACTION), keypress_index); return; } + ++keypress_index; } delegate_->ShortWaitForElement( @@ -278,6 +313,14 @@ } } +void SetFormFieldValueAction::FailAction(const ClientStatus& status, + int keypress_index) { + processed_action_proto_->mutable_status_details() + ->mutable_form_field_error_info() + ->set_invalid_keypress_index(keypress_index); + EndAction(status); +} + void SetFormFieldValueAction::EndAction(const ClientStatus& status) { // Clear immediately, to prevent sensitive information from staying in memory. field_inputs_.clear();
diff --git a/components/autofill_assistant/browser/actions/set_form_field_value_action.h b/components/autofill_assistant/browser/actions/set_form_field_value_action.h index 6a5b3674..ccdf3ab5 100644 --- a/components/autofill_assistant/browser/actions/set_form_field_value_action.h +++ b/components/autofill_assistant/browser/actions/set_form_field_value_action.h
@@ -70,6 +70,7 @@ void OnGetStoredPassword(int field_index, bool success, std::string password); + void FailAction(const ClientStatus& status, int keypress_index); void EndAction(const ClientStatus& status); Selector selector_;
diff --git a/components/autofill_assistant/browser/actions/set_form_field_value_action_unittest.cc b/components/autofill_assistant/browser/actions/set_form_field_value_action_unittest.cc index 4e6b98e..74f221d 100644 --- a/components/autofill_assistant/browser/actions/set_form_field_value_action_unittest.cc +++ b/components/autofill_assistant/browser/actions/set_form_field_value_action_unittest.cc
@@ -7,8 +7,14 @@ #include <string> #include <utility> +#include "base/guid.h" +#include "base/strings/strcat.h" +#include "base/strings/string_number_conversions.h" #include "base/test/gmock_callback_support.h" #include "base/test/mock_callback.h" +#include "components/autofill/core/browser/autofill_test_utils.h" +#include "components/autofill/core/browser/data_model/autofill_profile.h" +#include "components/autofill/core/browser/field_types.h" #include "components/autofill_assistant/browser/actions/action_test_utils.h" #include "components/autofill_assistant/browser/actions/mock_action_delegate.h" #include "components/autofill_assistant/browser/client_status.h" @@ -357,4 +363,80 @@ EXPECT_TRUE(action.field_inputs_.empty()); } +TEST_F(SetFormFieldValueActionTest, EmptyProfileValueFails) { + set_form_field_proto_->add_value()->mutable_autofill_value(); + SetFormFieldValueAction action(&mock_action_delegate_, proto_); + + EXPECT_CALL( + callback_, + Run(Pointee(Property(&ProcessedActionProto::status, INVALID_ACTION)))); + action.ProcessAction(callback_.Get()); +} + +TEST_F(SetFormFieldValueActionTest, RequestDataFromUnknownProfile) { + auto* value = set_form_field_proto_->add_value()->mutable_autofill_value(); + value->mutable_profile()->set_identifier("none"); + value->set_value_expression("value"); + SetFormFieldValueAction action(&mock_action_delegate_, proto_); + + EXPECT_CALL(callback_, Run(Pointee(Property(&ProcessedActionProto::status, + PRECONDITION_FAILED)))); + action.ProcessAction(callback_.Get()); +} + +TEST_F(SetFormFieldValueActionTest, RequestUnknownDataFromProfile) { + autofill::AutofillProfile contact(base::GenerateGUID(), + autofill::test::kEmptyOrigin); + // Middle name is expected to be empty. + autofill::test::SetProfileInfo(&contact, "John", /* middle name */ "", "Doe", + "", "", "", "", "", "", "", "", ""); + user_data_.selected_addresses_["contact"] = + std::make_unique<autofill::AutofillProfile>(contact); + + auto* value = set_form_field_proto_->add_value()->mutable_autofill_value(); + value->mutable_profile()->set_identifier("contact"); + value->set_value_expression( + base::StrCat({"${", + base::NumberToString(static_cast<int>( + autofill::ServerFieldType::NAME_MIDDLE)), + "}"})); + SetFormFieldValueAction action(&mock_action_delegate_, proto_); + + EXPECT_CALL(callback_, Run(Pointee(Property(&ProcessedActionProto::status, + AUTOFILL_INFO_NOT_AVAILABLE)))); + action.ProcessAction(callback_.Get()); +} + +TEST_F(SetFormFieldValueActionTest, SetFieldFromProfileValue) { + autofill::AutofillProfile contact(base::GenerateGUID(), + autofill::test::kEmptyOrigin); + autofill::test::SetProfileInfo(&contact, "John", "", "Doe", "", "", "", "", + "", "", "", "", ""); + user_data_.selected_addresses_["contact"] = + std::make_unique<autofill::AutofillProfile>(contact); + + auto* value = set_form_field_proto_->add_value()->mutable_autofill_value(); + value->mutable_profile()->set_identifier("contact"); + value->set_value_expression( + base::StrCat({"${", + base::NumberToString(static_cast<int>( + autofill::ServerFieldType::NAME_FIRST)), + "}"})); + SetFormFieldValueAction action(&mock_action_delegate_, proto_); + + ON_CALL(mock_action_delegate_, OnGetFieldValue(_, _)) + .WillByDefault(RunOnceCallback<1>(OkClientStatus(), "not empty")); + EXPECT_CALL(mock_action_delegate_, + OnSetFieldValue("John", _, _, + EqualsElement(test_util::MockFindElement( + mock_action_delegate_, fake_selector_)), + _)) + .WillOnce(RunOnceCallback<4>(OkClientStatus())); + + EXPECT_CALL( + callback_, + Run(Pointee(Property(&ProcessedActionProto::status, ACTION_APPLIED)))); + action.ProcessAction(callback_.Get()); +} + } // namespace autofill_assistant
diff --git a/components/autofill_assistant/browser/service.proto b/components/autofill_assistant/browser/service.proto index 9edb5a1..c489932 100644 --- a/components/autofill_assistant/browser/service.proto +++ b/components/autofill_assistant/browser/service.proto
@@ -459,6 +459,21 @@ CLICK = 3; } +message AutofillValue { + message Profile { optional string identifier = 1; } + + // The profile to be used. This has to be requested with a + // |CollectUserDataAction| first. + optional Profile profile = 1; + + // A string containing any number of "${key}" placeholders, where the key is + // an integer corresponding to entries from field_types.h or + // |AutofillFormatProto::AutofillAssistantCustomField|. + // Note that the set of actually available fields are outside of our + // control and are retrieved automatically from the provided profile. + optional string value_expression = 2; +} + // An action could be performed. message ActionProto { // Wait these many milliseconds before executing the action, if set. @@ -607,6 +622,9 @@ // More information included for autofill related errors. optional AutofillErrorInfoProto autofill_error_info = 3; + + // More information included for |SetFormFieldValueProto| related errors. + optional SetFormFieldErrorInfoProto form_field_error_info = 4; } message NavigationInfoProto { @@ -711,6 +729,13 @@ repeated AutofillFieldError autofill_field_error = 5; } +// Message to report |SetFormFieldValueProto| related errors for debugging +// purposes. +message SetFormFieldErrorInfoProto { + // The index of |keypress| that caused the action to be invalid. + optional int32 invalid_keypress_index = 1; +} + // The pseudo type values come from // https://chromedevtools.github.io/devtools-protocol/tot/DOM#type-PseudoType. enum PseudoType { @@ -914,13 +939,20 @@ // The drop down element on which to select an option. optional SelectorProto element = 2; - // Value of the option to use. - optional string selected_option = 3; + oneof value { + // Value of the option to use. + string selected_option = 3; + // A value from an Autofill source. Note that this must be proceeded by a + // |CollectUserDataAction|. + AutofillValue autofill_value = 5; + } // The strategy used to select a value option. This defaults to // |LABEL_STARTS_WITH| for the legacy case. optional DropdownSelectStrategy select_strategy = 4 [default = LABEL_STARTS_WITH]; + + reserved 1; } // Contain a localized text message from the server. @@ -993,9 +1025,9 @@ // Message used to indicate what form fields should be filled with what // information coming from the address. message RequiredField { - // A string containing either a single integer key or multiple "${key}" - // placeholders, where the key is an integer corresponding to entries from - // field_types.h or AutofillFormatProto::AutofillAssistantCustomField. + // A string containing any number of "${key}" placeholders, where the key + // is an integer corresponding to entries from field_types.h or + // |AutofillFormatProto::AutofillAssistantCustomField|. // Example: // * "3" -> First name. // * "${3}" -> First name. @@ -1059,9 +1091,9 @@ // Message used to indicate what form fields should be filled with what // information. message RequiredField { - // A string containing either a single integer key or multiple "${key}" - // placeholders, where the key is an integer corresponding to entries from - // field_types.h or AutofillFormatProto::AutofillAssistantCustomField. + // A string containing any number of "${key}" placeholders, where the key + // is an integer corresponding to entries from field_types.h or + // |AutofillFormatProto::AutofillAssistantCustomField|. // Example: // * "51" -> Full name. // * "${51}" -> Full Name. @@ -1918,6 +1950,9 @@ bool use_password = 5; // Use the value stored at the specified memory location. string client_memory_key = 6; + // A value from an Autofill source. Note that this must be proceeded by a + // |CollectUserDataAction|. + AutofillValue autofill_value = 8; } reserved 7;
diff --git a/components/content_settings/core/common/content_settings_pattern.cc b/components/content_settings/core/common/content_settings_pattern.cc index 7e13ce9..2693e1c 100644 --- a/components/content_settings/core/common/content_settings_pattern.cc +++ b/components/content_settings/core/common/content_settings_pattern.cc
@@ -15,12 +15,14 @@ #include "base/notreached.h" #include "base/optional.h" #include "base/stl_util.h" +#include "base/strings/strcat.h" #include "base/strings/string_piece.h" #include "base/strings/string_split.h" #include "base/strings/string_util.h" #include "components/content_settings/core/common/content_settings_pattern_parser.h" #include "net/base/url_util.h" #include "url/gurl.h" +#include "url/url_constants.h" namespace { @@ -240,9 +242,18 @@ parts->scheme = base::ToLowerASCII(parts->scheme); if (parts->scheme == url::kFileScheme && !parts->is_path_wildcard) { - GURL url(std::string(url::kFileScheme) + - std::string(url::kStandardSchemeSeparator) + parts->path); - parts->path = url.path(); + // TODO(crbug.com/1132957): Remove this loop once GURL canonicalization is + // idempotent (see crbug.com/1128999). + while (true) { + std::string url_spec = base::StrCat( + {url::kFileScheme, url::kStandardSchemeSeparator, parts->path}); + GURL url(url_spec); + if (!url.is_valid()) + return false; + if (parts->path == url.path_piece()) + break; + parts->path = url.path(); + } } // Canonicalize the host part.
diff --git a/components/exo/BUILD.gn b/components/exo/BUILD.gn index 26d8a6ef7..b3e128a 100644 --- a/components/exo/BUILD.gn +++ b/components/exo/BUILD.gn
@@ -2,9 +2,17 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import("//build/config/linux/pkg_config.gni") import("//build/config/ui.gni") import("//chrome/common/features.gni") import("//testing/test.gni") +import("//ui/base/ui_features.gni") + +if (use_xkbcommon) { + pkg_config("xkbcommon") { + packages = [ "xkbcommon" ] + } +} static_library("exo") { sources = [ @@ -160,6 +168,9 @@ "xkb_tracker.cc", "xkb_tracker.h", ] + if (use_xkbcommon) { + configs += [ ":xkbcommon" ] + } } if (is_chromecast) {
diff --git a/components/exo/keyboard.cc b/components/exo/keyboard.cc index 5cd88fae..24b7438d 100644 --- a/components/exo/keyboard.cc +++ b/components/exo/keyboard.cc
@@ -14,11 +14,13 @@ #include "components/exo/input_trace.h" #include "components/exo/keyboard_delegate.h" #include "components/exo/keyboard_device_configuration_delegate.h" +#include "components/exo/keyboard_modifiers.h" #include "components/exo/seat.h" #include "components/exo/shell_surface.h" #include "components/exo/shell_surface_util.h" #include "components/exo/surface.h" #include "components/exo/wm_helper.h" +#include "components/exo/xkb_tracker.h" #include "ui/aura/client/aura_constants.h" #include "ui/aura/client/focus_client.h" #include "ui/aura/window.h" @@ -169,7 +171,7 @@ ash::ImeControllerImpl* ime_controller = ash::Shell::Get()->ime_controller(); ime_controller->AddObserver(this); - delegate_->OnKeyboardLayoutUpdated(ime_controller->keyboard_layout_name()); + delegate_->OnKeyboardLayoutUpdated(seat_->xkb_tracker()->GetKeymap().get()); OnSurfaceFocused(seat_->GetFocusedSurface()); OnKeyRepeatSettingsChanged( ash::KeyboardController::Get()->GetKeyRepeatSettings()); @@ -278,7 +280,9 @@ ConsumedByIme(focus_, event); // Always update modifiers. - delegate_->OnKeyboardModifiers(event->flags()); + // XkbTracker must be updated in the Seat, before calling this method. + // Ensured by the observer registration order. + delegate_->OnKeyboardModifiers(seat_->xkb_tracker()->GetModifiers()); // TODO(yhanada): This is a quick fix for https://crbug.com/859071. Remove // ARC-specific code path once we can find a way to manage press/release @@ -401,7 +405,9 @@ void Keyboard::OnCapsLockChanged(bool enabled) {} void Keyboard::OnKeyboardLayoutNameChanged(const std::string& layout_name) { - delegate_->OnKeyboardLayoutUpdated(layout_name); + // XkbTracker must be updated in the Seat, before calling this method. + // Ensured by the observer registration order. + delegate_->OnKeyboardLayoutUpdated(seat_->xkb_tracker()->GetKeymap().get()); } //////////////////////////////////////////////////////////////////////////////// @@ -416,7 +422,7 @@ } if (surface) { pressed_keys_ = seat_->pressed_keys(); - delegate_->OnKeyboardModifiers(seat_->modifier_flags()); + delegate_->OnKeyboardModifiers(seat_->xkb_tracker()->GetModifiers()); delegate_->OnKeyboardEnter(surface, pressed_keys_); focus_ = surface; focus_->AddSurfaceObserver(this);
diff --git a/components/exo/keyboard_delegate.h b/components/exo/keyboard_delegate.h index 0470e0d..ff97652 100644 --- a/components/exo/keyboard_delegate.h +++ b/components/exo/keyboard_delegate.h
@@ -7,6 +7,7 @@ #include "base/containers/flat_map.h" #include "base/containers/flat_set.h" +#include "base/strings/string_piece.h" #include "base/time/time.h" namespace ui { @@ -14,6 +15,7 @@ } namespace exo { +struct KeyboardModifiers; class Surface; // Handles events on keyboards in context-specific ways. @@ -42,7 +44,7 @@ bool pressed) = 0; // Called when keyboard modifier state changed. - virtual void OnKeyboardModifiers(int modifier_flags) = 0; + virtual void OnKeyboardModifiers(const KeyboardModifiers& modifiers) = 0; // Called when key repeat settings are changed. virtual void OnKeyRepeatSettingsChanged(bool enabled, @@ -50,9 +52,7 @@ base::TimeDelta interval) = 0; // Called when keyboard layout is updated. - // TODO(hidehiko): Update the argument to pass the keymap - // when XkbTracker is moved out from WaylandKeyboardDelegate. - virtual void OnKeyboardLayoutUpdated(const std::string& layout_name) = 0; + virtual void OnKeyboardLayoutUpdated(base::StringPiece keymap) = 0; }; } // namespace exo
diff --git a/components/exo/keyboard_unittest.cc b/components/exo/keyboard_unittest.cc index 0cde39b7..60fd3d9 100644 --- a/components/exo/keyboard_unittest.cc +++ b/components/exo/keyboard_unittest.cc
@@ -16,6 +16,7 @@ #include "components/exo/buffer.h" #include "components/exo/keyboard_delegate.h" #include "components/exo/keyboard_device_configuration_delegate.h" +#include "components/exo/keyboard_modifiers.h" #include "components/exo/keyboard_observer.h" #include "components/exo/seat.h" #include "components/exo/shell_surface.h" @@ -35,6 +36,12 @@ namespace exo { namespace { +// XKB mod masks for the default keymap. +constexpr uint32_t kShiftMask = 1 << 0; +constexpr uint32_t kControlMask = 1 << 2; +constexpr uint32_t kAltMask = 1 << 3; +constexpr uint32_t kNumLockMask = 1 << 4; + using KeyboardTest = test::ExoTestBase; class MockKeyboardDelegate : public KeyboardDelegate { @@ -48,11 +55,11 @@ (Surface*, (const base::flat_map<ui::DomCode, ui::DomCode>&))); MOCK_METHOD(void, OnKeyboardLeave, (Surface*)); MOCK_METHOD(uint32_t, OnKeyboardKey, (base::TimeTicks, ui::DomCode, bool)); - MOCK_METHOD(void, OnKeyboardModifiers, (int)); + MOCK_METHOD(void, OnKeyboardModifiers, (const KeyboardModifiers&)); MOCK_METHOD(void, OnKeyRepeatSettingsChanged, (bool, base::TimeDelta, base::TimeDelta)); - MOCK_METHOD(void, OnKeyboardLayoutUpdated, (const std::string&)); + MOCK_METHOD(void, OnKeyboardLayoutUpdated, (base::StringPiece)); }; using NiceMockKeyboardDelegate = ::testing::NiceMock<MockKeyboardDelegate>; @@ -165,9 +172,11 @@ Keyboard keyboard(std::move(delegate), &seat); testing::Mock::VerifyAndClearExpectations(delegate_ptr); + // Set up expectation for the key release. EXPECT_CALL(*delegate_ptr, CanAcceptKeyboardEventsForSurface(surface.get())) .WillOnce(testing::Return(true)); - EXPECT_CALL(*delegate_ptr, OnKeyboardModifiers(ui::EF_SHIFT_DOWN)); + EXPECT_CALL(*delegate_ptr, OnKeyboardModifiers(KeyboardModifiers{ + kShiftMask | kNumLockMask, 0, 0, 0})); EXPECT_CALL(*delegate_ptr, OnKeyboardEnter(surface.get(), base::flat_map<ui::DomCode, ui::DomCode>( @@ -185,7 +194,8 @@ // Key should no longer be pressed when focus returns. EXPECT_CALL(*delegate_ptr, CanAcceptKeyboardEventsForSurface(surface.get())) .WillOnce(testing::Return(true)); - EXPECT_CALL(*delegate_ptr, OnKeyboardModifiers(ui::EF_SHIFT_DOWN)); + EXPECT_CALL(*delegate_ptr, OnKeyboardModifiers(KeyboardModifiers{ + kShiftMask | kNumLockMask, 0, 0, 0})); EXPECT_CALL(*delegate_ptr, OnKeyboardEnter(surface.get(), base::flat_map<ui::DomCode, ui::DomCode>())); @@ -213,7 +223,8 @@ ON_CALL(*delegate_ptr, CanAcceptKeyboardEventsForSurface(surface.get())) .WillByDefault(testing::Return(true)); - EXPECT_CALL(*delegate_ptr, OnKeyboardModifiers(0)); + EXPECT_CALL(*delegate_ptr, + OnKeyboardModifiers(KeyboardModifiers{kNumLockMask, 0, 0, 0})); EXPECT_CALL(*delegate_ptr, OnKeyboardEnter(surface.get(), base::flat_map<ui::DomCode, ui::DomCode>())); @@ -224,7 +235,8 @@ focus_client->FocusWindow(nullptr); testing::Mock::VerifyAndClearExpectations(delegate_ptr); - EXPECT_CALL(*delegate_ptr, OnKeyboardModifiers(0)); + EXPECT_CALL(*delegate_ptr, + OnKeyboardModifiers(KeyboardModifiers{kNumLockMask, 0, 0, 0})); EXPECT_CALL(*delegate_ptr, OnKeyboardEnter(surface.get(), base::flat_map<ui::DomCode, ui::DomCode>())); @@ -259,7 +271,8 @@ EXPECT_CALL(*delegate_ptr, CanAcceptKeyboardEventsForSurface(surface.get())) .WillOnce(testing::Return(true)); - EXPECT_CALL(*delegate_ptr, OnKeyboardModifiers(0)); + EXPECT_CALL(*delegate_ptr, + OnKeyboardModifiers(KeyboardModifiers{kNumLockMask, 0, 0, 0})); EXPECT_CALL(*delegate_ptr, OnKeyboardEnter(surface.get(), base::flat_map<ui::DomCode, ui::DomCode>())); @@ -288,7 +301,8 @@ // Test key event rewriting. In this case, ARROW_DOWN is rewritten to KEY_END // as a result of ALT being pressed. EXPECT_CALL(*delegate_ptr, OnKeyboardKey(testing::_, ui::DomCode::END, true)); - EXPECT_CALL(*delegate_ptr, OnKeyboardModifiers(ui::EF_ALT_DOWN)); + EXPECT_CALL(*delegate_ptr, OnKeyboardModifiers(KeyboardModifiers{ + kAltMask | kNumLockMask, 0, 0, 0})); seat.set_physical_code_for_currently_processing_event_for_testing( ui::DomCode::ARROW_DOWN); generator.PressKey(ui::VKEY_END, ui::EF_ALT_DOWN); @@ -298,7 +312,8 @@ // associated with the key press. EXPECT_CALL(*delegate_ptr, OnKeyboardKey(testing::_, ui::DomCode::END, false)); - EXPECT_CALL(*delegate_ptr, OnKeyboardModifiers(0)); + EXPECT_CALL(*delegate_ptr, + OnKeyboardModifiers(KeyboardModifiers{kNumLockMask, 0, 0, 0})); generator.ReleaseKey(ui::VKEY_DOWN, 0); testing::Mock::VerifyAndClearExpectations(delegate_ptr); @@ -313,7 +328,8 @@ // Key should be pressed when focus returns. EXPECT_CALL(*delegate_ptr, CanAcceptKeyboardEventsForSurface(surface.get())) .WillOnce(testing::Return(true)); - EXPECT_CALL(*delegate_ptr, OnKeyboardModifiers(ui::EF_CONTROL_DOWN)); + EXPECT_CALL(*delegate_ptr, OnKeyboardModifiers(KeyboardModifiers{ + kControlMask | kNumLockMask, 0, 0, 0})); EXPECT_CALL(*delegate_ptr, OnKeyboardEnter(surface.get(), base::flat_map<ui::DomCode, ui::DomCode>( @@ -375,7 +391,8 @@ EXPECT_CALL(*delegate_ptr, CanAcceptKeyboardEventsForSurface(surface.get())) .WillOnce(testing::Return(true)); - EXPECT_CALL(*delegate_ptr, OnKeyboardModifiers(0)); + EXPECT_CALL(*delegate_ptr, + OnKeyboardModifiers(KeyboardModifiers{kNumLockMask, 0, 0, 0})); EXPECT_CALL(*delegate_ptr, OnKeyboardEnter(surface.get(), base::flat_map<ui::DomCode, ui::DomCode>())); @@ -459,7 +476,8 @@ EXPECT_CALL(*delegate_ptr, CanAcceptKeyboardEventsForSurface(surface.get())) .WillOnce(testing::Return(true)); - EXPECT_CALL(*delegate_ptr, OnKeyboardModifiers(0)); + EXPECT_CALL(*delegate_ptr, + OnKeyboardModifiers(KeyboardModifiers{kNumLockMask, 0, 0, 0})); EXPECT_CALL(*delegate_ptr, OnKeyboardEnter(surface.get(), base::flat_map<ui::DomCode, ui::DomCode>())); @@ -470,7 +488,8 @@ // This should generate a modifier event. EXPECT_CALL(*delegate_ptr, OnKeyboardKey(testing::_, ui::DomCode::US_A, true)); - EXPECT_CALL(*delegate_ptr, OnKeyboardModifiers(ui::EF_SHIFT_DOWN)); + EXPECT_CALL(*delegate_ptr, OnKeyboardModifiers(KeyboardModifiers{ + kShiftMask | kNumLockMask, 0, 0, 0})); seat.set_physical_code_for_currently_processing_event_for_testing( ui::DomCode::US_A); generator.PressKey(ui::VKEY_A, ui::EF_SHIFT_DOWN); @@ -480,7 +499,8 @@ EXPECT_CALL(*delegate_ptr, OnKeyboardKey(testing::_, ui::DomCode::US_B, true)); EXPECT_CALL(*delegate_ptr, - OnKeyboardModifiers(ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN)); + OnKeyboardModifiers(KeyboardModifiers{ + kShiftMask | kAltMask | kNumLockMask, 0, 0, 0})); seat.set_physical_code_for_currently_processing_event_for_testing( ui::DomCode::US_B); generator.PressKey(ui::VKEY_B, ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN); @@ -489,7 +509,8 @@ // This should generate a third modifier event. EXPECT_CALL(*delegate_ptr, OnKeyboardKey(testing::_, ui::DomCode::US_B, false)); - EXPECT_CALL(*delegate_ptr, OnKeyboardModifiers(0)); + EXPECT_CALL(*delegate_ptr, + OnKeyboardModifiers(KeyboardModifiers{kNumLockMask, 0, 0, 0})); generator.ReleaseKey(ui::VKEY_B, 0); // Verify before destroying keyboard to make sure the expected call // is made on the methods above, rather than in the destructor. @@ -792,10 +813,12 @@ auto* delegate_ptr = delegate.get(); Seat seat; Keyboard keyboard(std::move(delegate), &seat); + testing::Mock::VerifyAndClearExpectations(delegate_ptr); EXPECT_CALL(*delegate_ptr, CanAcceptKeyboardEventsForSurface(surface.get())) .WillOnce(testing::Return(true)); - EXPECT_CALL(*delegate_ptr, OnKeyboardModifiers(0)); + EXPECT_CALL(*delegate_ptr, + OnKeyboardModifiers(KeyboardModifiers{kNumLockMask, 0, 0, 0})); EXPECT_CALL(*delegate_ptr, OnKeyboardEnter(surface.get(), base::flat_map<ui::DomCode, ui::DomCode>())); @@ -806,7 +829,8 @@ // to ShellSurface. ui::test::EventGenerator generator(ash::Shell::GetPrimaryRootWindow()); // Press KEY_W with Ctrl. - EXPECT_CALL(*delegate_ptr, OnKeyboardModifiers(4)); + EXPECT_CALL(*delegate_ptr, OnKeyboardModifiers(KeyboardModifiers{ + kControlMask | kNumLockMask, 0, 0, 0})); EXPECT_CALL(*shell_surface.get(), AcceleratorPressed(ui::Accelerator( ui::VKEY_W, ui::EF_CONTROL_DOWN, ui::Accelerator::KeyState::PRESSED))) @@ -877,7 +901,8 @@ testing::Mock::VerifyAndClearExpectations(shell_surface.get()); // Release the key and reset modifier_flags. - EXPECT_CALL(*delegate_ptr, OnKeyboardModifiers(0)); + EXPECT_CALL(*delegate_ptr, + OnKeyboardModifiers(KeyboardModifiers{kNumLockMask, 0, 0, 0})); EXPECT_CALL(*delegate_ptr, OnKeyboardKey(testing::_, ui::DomCode::US_W, false)); generator.ReleaseKey(ui::VKEY_W, 0); @@ -906,7 +931,8 @@ EXPECT_CALL(*delegate_ptr, CanAcceptKeyboardEventsForSurface(surface.get())) .WillOnce(testing::Return(true)); - EXPECT_CALL(*delegate_ptr, OnKeyboardModifiers(0)).Times(1); + EXPECT_CALL(*delegate_ptr, + OnKeyboardModifiers(KeyboardModifiers{kNumLockMask, 0, 0, 0})); EXPECT_CALL(*delegate_ptr, OnKeyboardEnter(surface.get(), base::flat_map<ui::DomCode, ui::DomCode>())); @@ -917,7 +943,9 @@ keyboard.SetNeedKeyboardKeyAcks(true); // Press KEY_W with Ctrl. - EXPECT_CALL(*delegate_ptr, OnKeyboardModifiers(4)).Times(1); + EXPECT_CALL(*delegate_ptr, OnKeyboardModifiers(KeyboardModifiers{ + kControlMask | kNumLockMask, 0, 0, 0})) + .Times(1); EXPECT_CALL(*delegate_ptr, OnKeyboardKey(testing::_, ui::DomCode::US_W, true)) .WillOnce(testing::Return(1)); seat.set_physical_code_for_currently_processing_event_for_testing( @@ -954,7 +982,8 @@ EXPECT_CALL(*delegate_ptr, CanAcceptKeyboardEventsForSurface(surface.get())) .WillOnce(testing::Return(true)); - EXPECT_CALL(*delegate_ptr, OnKeyboardModifiers(0)); + EXPECT_CALL(*delegate_ptr, + OnKeyboardModifiers(KeyboardModifiers{kNumLockMask, 0, 0, 0})); EXPECT_CALL(*delegate_ptr, OnKeyboardEnter(surface.get(), base::flat_map<ui::DomCode, ui::DomCode>())); @@ -965,7 +994,8 @@ keyboard.SetNeedKeyboardKeyAcks(true); // Press KEY_W with Ctrl. - EXPECT_CALL(*delegate_ptr, OnKeyboardModifiers(4)); + EXPECT_CALL(*delegate_ptr, OnKeyboardModifiers(KeyboardModifiers{ + kControlMask | kNumLockMask, 0, 0, 0})); EXPECT_CALL(*delegate_ptr, OnKeyboardKey(testing::_, ui::DomCode::US_W, true)) .WillOnce(testing::Return(1)); seat.set_physical_code_for_currently_processing_event_for_testing( @@ -996,7 +1026,8 @@ keyboard.AckKeyboardKey(1, false /* handled */); // Release the key and reset modifier_flags. - EXPECT_CALL(*delegate_ptr, OnKeyboardModifiers(0)); + EXPECT_CALL(*delegate_ptr, + OnKeyboardModifiers(KeyboardModifiers{kNumLockMask, 0, 0, 0})); EXPECT_CALL(*delegate_ptr, OnKeyboardKey(testing::_, ui::DomCode::US_W, false)); generator.ReleaseKey(ui::VKEY_W, 0); @@ -1044,7 +1075,8 @@ EXPECT_CALL(*delegate_ptr, CanAcceptKeyboardEventsForSurface(surface.get())) .WillOnce(testing::Return(true)); - EXPECT_CALL(*delegate_ptr, OnKeyboardModifiers(0)); + EXPECT_CALL(*delegate_ptr, + OnKeyboardModifiers(KeyboardModifiers{kNumLockMask, 0, 0, 0})); EXPECT_CALL(*delegate_ptr, OnKeyboardEnter(surface.get(), base::flat_map<ui::DomCode, ui::DomCode>())); @@ -1055,7 +1087,8 @@ keyboard.SetNeedKeyboardKeyAcks(true); // Press KEY_W with Ctrl. - EXPECT_CALL(*delegate_ptr, OnKeyboardModifiers(4)); + EXPECT_CALL(*delegate_ptr, OnKeyboardModifiers(KeyboardModifiers{ + kControlMask | kNumLockMask, 0, 0, 0})); EXPECT_CALL(*delegate_ptr, OnKeyboardKey(testing::_, ui::DomCode::US_W, true)) .WillOnce(testing::Return(1)); seat.set_physical_code_for_currently_processing_event_for_testing(
diff --git a/components/exo/seat.cc b/components/exo/seat.cc index c7881a30..6b8c9db 100644 --- a/components/exo/seat.cc +++ b/components/exo/seat.cc
@@ -25,6 +25,7 @@ #include "components/exo/shell_surface_util.h" #include "components/exo/surface.h" #include "components/exo/wm_helper.h" +#include "components/exo/xkb_tracker.h" #include "services/data_decoder/public/cpp/decode_image.h" #include "ui/aura/client/focus_client.h" #include "ui/base/clipboard/clipboard_data_endpoint.h" @@ -62,6 +63,14 @@ ui::PlatformEventSource::GetInstance()->AddPlatformEventObserver(this); #if defined(OS_CHROMEOS) ui_lock_controller_ = std::make_unique<UILockController>(this); + + // Seat needs to be registered as observers before any Keyboard, + // because Keyboard expects that the XkbTracker is up-to-date when its + // observer method is called. + xkb_tracker_ = std::make_unique<XkbTracker>(); + ash::ImeControllerImpl* ime_controller = ash::Shell::Get()->ime_controller(); + xkb_tracker_->UpdateKeyboardLayout(ime_controller->keyboard_layout_name()); + ime_controller->AddObserver(this); #endif } @@ -74,6 +83,9 @@ return; shutdown_ = true; DCHECK(!selection_source_) << "DataSource must be released before Seat"; +#if defined(OS_CHROMEOS) + ash::Shell::Get()->ime_controller()->RemoveObserver(this); +#endif WMHelper::GetInstance()->RemoveFocusObserver(this); WMHelper::GetInstance()->RemovePreTargetHandler(this); ui::ClipboardMonitor::GetInstance()->RemoveObserver(this); @@ -291,7 +303,9 @@ break; } } - modifier_flags_ = event->flags(); +#if defined(OS_CHROMEOS) + xkb_tracker_->UpdateKeyboardModifiers(event->flags()); +#endif } //////////////////////////////////////////////////////////////////////////////// @@ -304,6 +318,17 @@ selection_source_.reset(); } +#if defined(OS_CHROMEOS) +//////////////////////////////////////////////////////////////////////////////// +// ash::ImeControllerImpl::Observer overrides: + +void Seat::OnCapsLockChanged(bool enabled) {} + +void Seat::OnKeyboardLayoutNameChanged(const std::string& layout_name) { + xkb_tracker_->UpdateKeyboardLayout(layout_name); +} +#endif + //////////////////////////////////////////////////////////////////////////////// // DataSourceObserver overrides:
diff --git a/components/exo/seat.h b/components/exo/seat.h index 2a6940e5..348f1f1 100644 --- a/components/exo/seat.h +++ b/components/exo/seat.h
@@ -19,6 +19,7 @@ #include "ui/events/platform/platform_event_observer.h" #if defined(OS_CHROMEOS) +#include "ash/ime/ime_controller_impl.h" #include "components/exo/ui_lock_controller.h" #endif @@ -32,6 +33,7 @@ class ScopedDataSource; class SeatObserver; class Surface; +class XkbTracker; // The maximum number of different data types that we will write to the // clipboard (plain text, RTF, HTML, image) @@ -43,6 +45,9 @@ public ui::PlatformEventObserver, public ui::EventHandler, public ui::ClipboardObserver, +#if defined(OS_CHROMEOS) + public ash::ImeControllerImpl::Observer, +#endif public DataSourceObserver { public: Seat(); @@ -62,8 +67,9 @@ return pressed_keys_; } - // Returns current set of modifier flags. - int modifier_flags() const { return modifier_flags_; } +#if defined(OS_CHROMEOS) + const XkbTracker* xkb_tracker() const { return xkb_tracker_.get(); } +#endif // Returns physical code for the currently processing event. ui::DomCode physical_code_for_currently_processing_event() const { @@ -102,6 +108,12 @@ // Overridden from DataSourceObserver: void OnDataSourceDestroying(DataSource* source) override; +#if defined(OS_CHROMEOS) + // Overridden from ash::ImeControllerImpl::Observer: + void OnCapsLockChanged(bool enabled) override; + void OnKeyboardLayoutNameChanged(const std::string& layout_name) override; +#endif + void set_physical_code_for_currently_processing_event_for_testing( ui::DomCode physical_code_for_currently_processing_event) { physical_code_for_currently_processing_event_ = @@ -149,7 +161,6 @@ // physical key press generated. base::flat_map<ui::DomCode, ui::DomCode> pressed_keys_; ui::DomCode physical_code_for_currently_processing_event_ = ui::DomCode::NONE; - int modifier_flags_ = 0; // Data source being used as a clipboard content. std::unique_ptr<ScopedDataSource> selection_source_; @@ -165,6 +176,7 @@ #if defined(OS_CHROMEOS) std::unique_ptr<UILockController> ui_lock_controller_; + std::unique_ptr<XkbTracker> xkb_tracker_; #endif // defined(OS_CHROMEOS) base::WeakPtrFactory<Seat> weak_ptr_factory_{this};
diff --git a/components/exo/wayland/BUILD.gn b/components/exo/wayland/BUILD.gn index 34c6897..cb90905 100644 --- a/components/exo/wayland/BUILD.gn +++ b/components/exo/wayland/BUILD.gn
@@ -2,19 +2,12 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -import("//build/config/linux/pkg_config.gni") import("//build/config/ui.gni") import("//gpu/vulkan/features.gni") import("//testing/test.gni") import("//ui/base/ui_features.gni") import("//ui/ozone/ozone.gni") -if (use_xkbcommon) { - pkg_config("xkbcommon") { - packages = [ "xkbcommon" ] - } -} - source_set("wayland") { sources = [ "scoped_wl.cc", @@ -136,7 +129,6 @@ } if (use_xkbcommon) { - configs += [ ":xkbcommon" ] deps += [ "//ui/events/keycodes:xkb" ] }
diff --git a/components/exo/wayland/fuzzer/harness_unittest.cc b/components/exo/wayland/fuzzer/harness_unittest.cc index 446eb5b..d2c8d7fd 100644 --- a/components/exo/wayland/fuzzer/harness_unittest.cc +++ b/components/exo/wayland/fuzzer/harness_unittest.cc
@@ -5,7 +5,6 @@ #include "components/exo/wayland/fuzzer/harness.h" #include "base/files/scoped_temp_dir.h" -#include "base/macros.h" #include "base/threading/thread.h" #include "base/time/time.h" #include "components/exo/display.h" @@ -13,20 +12,36 @@ #include "components/exo/wayland/fuzzer/actions.pb.h" #include "components/exo/wayland/server.h" +#if defined(OS_CHROMEOS) +#include "components/exo/test/exo_test_base.h" +#endif + namespace exo { namespace wayland_fuzzer { namespace { -class WaylandFuzzerTest : public test::ExoTestBaseViews { +// Use ExoTestBase on Chrome OS because Server starts to depends on ash::Shell, +// which is unavailable on other platforms so then ExoTestBaseViews instead. +using TestBase = +#if defined(OS_CHROMEOS) + test::ExoTestBase +#else + test::ExoTestBaseViews +#endif + ; + +class WaylandFuzzerTest : public TestBase { protected: WaylandFuzzerTest() = default; + WaylandFuzzerTest(const WaylandFuzzerTest&) = delete; + WaylandFuzzerTest& operator=(const WaylandFuzzerTest&) = delete; ~WaylandFuzzerTest() override = default; void SetUp() override { ASSERT_TRUE(xdg_temp_dir_.CreateUniqueTempDir()); setenv("XDG_RUNTIME_DIR", xdg_temp_dir_.GetPath().MaybeAsASCII().c_str(), 1 /* overwrite */); - test::ExoTestBaseViews::SetUp(); + TestBase::SetUp(); display_ = std::make_unique<exo::Display>(); server_ = wayland::Server::Create(display_.get()); } @@ -34,15 +49,12 @@ void TearDown() override { server_.reset(); display_.reset(); - test::ExoTestBaseViews::TearDown(); + TestBase::TearDown(); } base::ScopedTempDir xdg_temp_dir_; std::unique_ptr<exo::Display> display_; std::unique_ptr<wayland::Server> server_; - - private: - DISALLOW_COPY_AND_ASSIGN(WaylandFuzzerTest); }; void RunHarness(Harness* harness, base::WaitableEvent* event) {
diff --git a/components/exo/wayland/server.cc b/components/exo/wayland/server.cc index a6ce378..20b98bc 100644 --- a/components/exo/wayland/server.cc +++ b/components/exo/wayland/server.cc
@@ -215,8 +215,8 @@ wl_global_create(wl_display_.get(), &zcr_extended_drag_v1_interface, 1, display_, bind_extended_drag); - zwp_text_manager_data_ = - std::make_unique<WaylandTextInputManager>(serial_tracker_.get()); + zwp_text_manager_data_ = std::make_unique<WaylandTextInputManager>( + display_->seat()->xkb_tracker(), serial_tracker_.get()); wl_global_create(wl_display_.get(), &zwp_text_input_manager_v1_interface, 1, zwp_text_manager_data_.get(), bind_text_input_manager);
diff --git a/components/exo/wayland/server_unittest.cc b/components/exo/wayland/server_unittest.cc index 004daee..ef827b1 100644 --- a/components/exo/wayland/server_unittest.cc +++ b/components/exo/wayland/server_unittest.cc
@@ -20,6 +20,10 @@ #include "components/exo/test/exo_test_base_views.h" #include "testing/gtest/include/gtest/gtest.h" +#if defined(OS_CHROMEOS) +#include "components/exo/test/exo_test_base.h" +#endif + namespace exo { namespace wayland { namespace { @@ -31,22 +35,32 @@ g_next_socket_id.GetNext()); } -class ServerTest : public test::ExoTestBaseViews { +// Use ExoTestBase on Chrome OS because Server starts to depends on ash::Shell, +// which is unavailable on other platforms so then ExoTestBaseViews instead. +using TestBase = +#if defined(OS_CHROMEOS) + test::ExoTestBase +#else + test::ExoTestBaseViews +#endif + ; + +class ServerTest : public TestBase { public: - ServerTest() {} - ~ServerTest() override {} + ServerTest() = default; + ServerTest(const ServerTest&) = delete; + ServerTest& operator=(const ServerTest&) = delete; + ~ServerTest() override = default; void SetUp() override { ASSERT_TRUE(xdg_temp_dir_.CreateUniqueTempDir()); setenv("XDG_RUNTIME_DIR", xdg_temp_dir_.GetPath().MaybeAsASCII().c_str(), 1 /* overwrite */); - test::ExoTestBaseViews::SetUp(); + TestBase::SetUp(); } private: base::ScopedTempDir xdg_temp_dir_; - - DISALLOW_COPY_AND_ASSIGN(ServerTest); }; TEST_F(ServerTest, AddSocket) {
diff --git a/components/exo/wayland/wayland_keyboard_delegate.cc b/components/exo/wayland/wayland_keyboard_delegate.cc index e8d9d38..ffc05a7 100644 --- a/components/exo/wayland/wayland_keyboard_delegate.cc +++ b/components/exo/wayland/wayland_keyboard_delegate.cc
@@ -10,11 +10,13 @@ #include <wayland-server-protocol-core.h> #include "base/containers/flat_map.h" -#include "components/exo/keyboard_modifiers.h" #include "components/exo/wayland/serial_tracker.h" -#include "components/exo/xkb_tracker.h" #include "ui/events/keycodes/dom/dom_code.h" +#if BUILDFLAG(USE_XKBCOMMON) +#include <xkbcommon/xkbcommon.h> +#endif + namespace exo { namespace wayland { @@ -22,9 +24,7 @@ WaylandKeyboardDelegate::WaylandKeyboardDelegate(wl_resource* keyboard_resource, SerialTracker* serial_tracker) - : keyboard_resource_(keyboard_resource), - serial_tracker_(serial_tracker), - xkb_tracker_(std::make_unique<XkbTracker>()) {} + : keyboard_resource_(keyboard_resource), serial_tracker_(serial_tracker) {} WaylandKeyboardDelegate::~WaylandKeyboardDelegate() = default; @@ -88,11 +88,9 @@ return serial; } -void WaylandKeyboardDelegate::OnKeyboardModifiers(int modifier_flags) { - xkb_tracker_->UpdateKeyboardModifiers(modifier_flags); - +void WaylandKeyboardDelegate::OnKeyboardModifiers( + const KeyboardModifiers& modifiers) { // Send the update only when they're different. - const KeyboardModifiers modifiers = xkb_tracker_->GetModifiers(); if (current_modifiers_ == modifiers) return; current_modifiers_ = modifiers; @@ -100,9 +98,23 @@ } void WaylandKeyboardDelegate::OnKeyboardLayoutUpdated( - const std::string& layout_name) { - xkb_tracker_->UpdateKeyboardLayout(layout_name); - SendLayout(); + base::StringPiece keymap) { + // Sent the content of |keymap| with trailing '\0' termination via shared + // memory. + base::UnsafeSharedMemoryRegion shared_keymap_region = + base::UnsafeSharedMemoryRegion::Create(keymap.size() + 1); + base::WritableSharedMemoryMapping shared_keymap = shared_keymap_region.Map(); + base::subtle::PlatformSharedMemoryRegion platform_shared_keymap = + base::UnsafeSharedMemoryRegion::TakeHandleForSerialization( + std::move(shared_keymap_region)); + DCHECK(shared_keymap.IsValid()); + + std::memcpy(shared_keymap.memory(), keymap.data(), keymap.size()); + static_cast<uint8_t*>(shared_keymap.memory())[keymap.size()] = '\0'; + wl_keyboard_send_keymap(keyboard_resource_, WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1, + platform_shared_keymap.GetPlatformHandle().fd, + keymap.size() + 1); + wl_client_flush(client()); } uint32_t WaylandKeyboardDelegate::DomCodeToKey(ui::DomCode code) const { @@ -124,25 +136,6 @@ wl_client_flush(client()); } -void WaylandKeyboardDelegate::SendLayout() { - auto keymap = xkb_tracker_->GetKeymap(); - size_t keymap_size = strlen(keymap.get()) + 1; - - base::UnsafeSharedMemoryRegion shared_keymap_region = - base::UnsafeSharedMemoryRegion::Create(keymap_size); - base::WritableSharedMemoryMapping shared_keymap = shared_keymap_region.Map(); - base::subtle::PlatformSharedMemoryRegion platform_shared_keymap = - base::UnsafeSharedMemoryRegion::TakeHandleForSerialization( - std::move(shared_keymap_region)); - DCHECK(shared_keymap.IsValid()); - - std::memcpy(shared_keymap.memory(), keymap.get(), keymap_size); - wl_keyboard_send_keymap(keyboard_resource_, WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1, - platform_shared_keymap.GetPlatformHandle().fd, - keymap_size); - wl_client_flush(client()); -} - // Convert from ChromeOS's key repeat interval to Wayland's key repeat rate. // For example, an interval of 500ms is a rate of 1000/500 = 2 Hz. //
diff --git a/components/exo/wayland/wayland_keyboard_delegate.h b/components/exo/wayland/wayland_keyboard_delegate.h index 98be676c..fd112ed 100644 --- a/components/exo/wayland/wayland_keyboard_delegate.h +++ b/components/exo/wayland/wayland_keyboard_delegate.h
@@ -16,18 +16,10 @@ #include "ui/base/buildflags.h" #include "ui/events/keycodes/dom/keycode_converter.h" -#if BUILDFLAG(USE_XKBCOMMON) -#include <xkbcommon/xkbcommon.h> -#include "ui/events/keycodes/scoped_xkb.h" // nogncheck -#endif - struct wl_client; struct wl_resource; namespace exo { - -class XkbTracker; - namespace wayland { class SerialTracker; @@ -50,11 +42,11 @@ uint32_t OnKeyboardKey(base::TimeTicks time_stamp, ui::DomCode key, bool pressed) override; - void OnKeyboardModifiers(int modifier_flags) override; + void OnKeyboardModifiers(const KeyboardModifiers& modifiers) override; void OnKeyRepeatSettingsChanged(bool enabled, base::TimeDelta delay, base::TimeDelta interval) override; - void OnKeyboardLayoutUpdated(const std::string& layout_name) override; + void OnKeyboardLayoutUpdated(base::StringPiece keymap) override; private: // Returns the corresponding key given a dom code. @@ -63,9 +55,6 @@ // Sends the current modifiers to the client. void SendKeyboardModifiers(); - // Send the current keyboard layout to the client. - void SendLayout(); - // The client who own this keyboard instance. wl_client* client() const; @@ -75,10 +64,6 @@ // Owned by Server, which always outlives this delegate. SerialTracker* const serial_tracker_; - // TODO(hidehiko): Move this to the server in order to share it with - // zwp_text_input. - std::unique_ptr<XkbTracker> xkb_tracker_; - // Tracks the latest modifiers. KeyboardModifiers current_modifiers_{};
diff --git a/components/exo/wayland/zwp_text_input_manager.cc b/components/exo/wayland/zwp_text_input_manager.cc index b9b420d..927c060 100644 --- a/components/exo/wayland/zwp_text_input_manager.cc +++ b/components/exo/wayland/zwp_text_input_manager.cc
@@ -14,6 +14,7 @@ #include "components/exo/text_input.h" #include "components/exo/wayland/serial_tracker.h" #include "components/exo/wayland/server_util.h" +#include "components/exo/xkb_tracker.h" #include "ui/events/event.h" #include "ui/events/keycodes/dom/keycode_converter.h" @@ -29,8 +30,11 @@ class WaylandTextInputDelegate : public TextInput::Delegate { public: WaylandTextInputDelegate(wl_resource* text_input, + const XkbTracker* xkb_tracker, SerialTracker* serial_tracker) - : text_input_(text_input), serial_tracker_(serial_tracker) {} + : text_input_(text_input), + xkb_tracker_(xkb_tracker), + serial_tracker_(serial_tracker) {} ~WaylandTextInputDelegate() override = default; void set_surface(wl_resource* surface) { surface_ = surface; } @@ -113,7 +117,8 @@ } void SendKey(const ui::KeyEvent& event) override { - uint32_t code = ui::KeycodeConverter::DomCodeToNativeKeycode(event.code()); + uint32_t keysym = xkb_tracker_->GetKeysym( + ui::KeycodeConverter::DomCodeToNativeKeycode(event.code())); bool pressed = (event.type() == ui::ET_KEY_PRESSED); // TODO(mukai): consolidate the definition of this modifiers_mask with other // similar ones in components/exo/keyboard.cc or arc_ime_service.cc. @@ -127,7 +132,7 @@ zwp_text_input_v1_send_keysym( text_input_, TimeTicksToMilliseconds(event.time_stamp()), serial_tracker_->GetNextSerial(SerialTracker::EventType::OTHER_EVENT), - code, + keysym, pressed ? WL_KEYBOARD_KEY_STATE_PRESSED : WL_KEYBOARD_KEY_STATE_RELEASED, modifiers); @@ -156,10 +161,12 @@ wl_resource* text_input_; wl_resource* surface_ = nullptr; + // Owned by Seat, which is updated before calling the callbacks of this + // class. + const XkbTracker* const xkb_tracker_; + // Owned by Server, which always outlives this delegate. SerialTracker* const serial_tracker_; - - DISALLOW_COPY_AND_ASSIGN(WaylandTextInputDelegate); }; void text_input_activate(wl_client* client, @@ -353,7 +360,7 @@ SetImplementation( text_input_resource, &text_input_v1_implementation, std::make_unique<TextInput>(std::make_unique<WaylandTextInputDelegate>( - text_input_resource, data->serial_tracker))); + text_input_resource, data->xkb_tracker, data->serial_tracker))); } const struct zwp_text_input_manager_v1_interface
diff --git a/components/exo/wayland/zwp_text_input_manager.h b/components/exo/wayland/zwp_text_input_manager.h index 1cfd994..5578cdcc 100644 --- a/components/exo/wayland/zwp_text_input_manager.h +++ b/components/exo/wayland/zwp_text_input_manager.h
@@ -7,22 +7,26 @@ #include <stdint.h> -#include "base/macros.h" - struct wl_client; namespace exo { +class XkbTracker; + namespace wayland { class SerialTracker; struct WaylandTextInputManager { - WaylandTextInputManager(SerialTracker* serial_tracker) - : serial_tracker(serial_tracker) {} + WaylandTextInputManager(const XkbTracker* xkb_tracker, + SerialTracker* serial_tracker) + : xkb_tracker(xkb_tracker), serial_tracker(serial_tracker) {} + WaylandTextInputManager(const WaylandTextInputManager&) = delete; + WaylandTextInputManager& operator=(const WaylandTextInputManager&) = delete; + + // Owned by Seat, which also always outlives zwp_text_input_manager. + const XkbTracker* const xkb_tracker; // Owned by Server, which always outlives zwp_text_input_manager. SerialTracker* const serial_tracker; - - DISALLOW_COPY_AND_ASSIGN(WaylandTextInputManager); }; void bind_text_input_manager(wl_client* client,
diff --git a/components/exo/xkb_tracker.cc b/components/exo/xkb_tracker.cc index a8d98237..5358f83 100644 --- a/components/exo/xkb_tracker.cc +++ b/components/exo/xkb_tracker.cc
@@ -46,6 +46,10 @@ UpdateKeyboardModifiersInternal(); } +uint32_t XkbTracker::GetKeysym(uint32_t xkb_keycode) const { + return xkb_state_key_get_one_sym(xkb_state_.get(), xkb_keycode); +} + std::unique_ptr<char, base::FreeDeleter> XkbTracker::GetKeymap() const { return std::unique_ptr<char, base::FreeDeleter>( xkb_keymap_get_as_string(xkb_keymap_.get(), XKB_KEYMAP_FORMAT_TEXT_V1));
diff --git a/components/exo/xkb_tracker.h b/components/exo/xkb_tracker.h index bef65a8..74d4a09 100644 --- a/components/exo/xkb_tracker.h +++ b/components/exo/xkb_tracker.h
@@ -41,6 +41,10 @@ // ui::EventFlags. void UpdateKeyboardModifiers(int modifier_flags); + // Returns the keysym for the given XKB keycode, based on the current + // keymap and its modifier state. + uint32_t GetKeysym(uint32_t xkb_keycode) const; + // Returns the XKB keymap data. std::unique_ptr<char, base::FreeDeleter> GetKeymap() const;
diff --git a/components/password_manager/core/browser/password_manager_metrics_util.cc b/components/password_manager/core/browser/password_manager_metrics_util.cc index a9d424ee..c33cc4c8 100644 --- a/components/password_manager/core/browser/password_manager_metrics_util.cc +++ b/components/password_manager/core/browser/password_manager_metrics_util.cc
@@ -336,6 +336,22 @@ void LogProtectedPasswordReuse(PasswordType reused_password_type) {} #endif +void LogPasswordEditResult(IsUsernameChanged username_changed, + IsPasswordChanged password_changed) { + PasswordEditUpdatedValues values; + if (username_changed && password_changed) { + values = PasswordEditUpdatedValues::kBoth; + } else if (username_changed) { + values = PasswordEditUpdatedValues::kUsername; + } else if (password_changed) { + values = PasswordEditUpdatedValues::kPassword; + } else { + values = PasswordEditUpdatedValues::kNone; + } + base::UmaHistogramEnumeration("PasswordManager.PasswordEditUpdatedValues", + values); +} + } // namespace metrics_util } // namespace password_manager
diff --git a/components/password_manager/core/browser/password_manager_metrics_util.h b/components/password_manager/core/browser/password_manager_metrics_util.h index 9f70069..2cfe214 100644 --- a/components/password_manager/core/browser/password_manager_metrics_util.h +++ b/components/password_manager/core/browser/password_manager_metrics_util.h
@@ -17,6 +17,9 @@ namespace metrics_util { +using IsUsernameChanged = util::StrongAlias<class IsUsernameChangedTag, bool>; +using IsPasswordChanged = util::StrongAlias<class IsPasswordChangedTag, bool>; + // These values are persisted to logs. Entries should not be renumbered and // numeric values should never be reused. // Metrics: "PasswordBubble.DisplayDisposition" @@ -473,6 +476,20 @@ kMaxValue = kGroupUrlOverrideUsed, }; +// Used to record what exactly was updated during password editing flow. +// Entries should not be renumbered and numeric values should never be reused. +enum class PasswordEditUpdatedValues { + // Nothing was updated. + kNone = 0, + // Only username was changed. + kUsername = 1, + // Only password was changed. + kPassword = 2, + // Both password and username were updated. + kBoth = 3, + kMaxValue = kBoth, +}; + std::string GetPasswordAccountStorageUserStateHistogramSuffix( PasswordAccountStorageUserState user_state); @@ -619,6 +636,10 @@ #endif +// Log the result of the password edit action. +void LogPasswordEditResult(IsUsernameChanged password_changed, + IsPasswordChanged username_changed); + } // namespace metrics_util } // namespace password_manager
diff --git a/components/plugins/renderer/webview_plugin.cc b/components/plugins/renderer/webview_plugin.cc index 07e15b07..f3959c7 100644 --- a/components/plugins/renderer/webview_plugin.cc +++ b/components/plugins/renderer/webview_plugin.cc
@@ -223,7 +223,7 @@ if (event.GetType() == blink::WebInputEvent::Type::kContextMenu) { if (delegate_) { const WebMouseEvent& mouse_event = - reinterpret_cast<const WebMouseEvent&>(event); + static_cast<const WebMouseEvent&>(event); delegate_->ShowContextMenu(mouse_event); } return blink::WebInputEventResult::kHandledSuppressed;
diff --git a/components/policy/resources/policy_templates.json b/components/policy/resources/policy_templates.json index 65f28da..f8b9ee2 100644 --- a/components/policy/resources/policy_templates.json +++ b/components/policy/resources/policy_templates.json
@@ -9348,14 +9348,9 @@ 'admin-sharing', 'google-sharing', ], - 'desc': '''Controls whether usage metrics and diagnostic data, including crash reports, are reported back to Google. + 'desc': '''Setting the policy to Enabled has <ph name="PRODUCT_OS_NAME">$2<ex>Google Chrome OS</ex></ph> report usage metrics and diagnostic data, including crash reports, back to Google. Setting the policy to Disabled turns off metrics and diagnostic data reporting. - If set to true, <ph name="PRODUCT_OS_NAME">$2<ex>Google Chrome OS</ex></ph> will report usage metrics and diagnostic data. - - If set to false, metrics and diagnostic data reporting will be disabled. - - If not configured, metrics and diagnostic data reporting will be disabled on unmanaged devices and enabled on managed devices.''', - + Leaving the policy unset keeps metrics and diagnostic data reporting off on unmanaged devices and on for managed devices.''', 'arc_support': 'This policy also controls Android usage and diagnostic data collection.', }, { @@ -23415,7 +23410,29 @@ - Format the URL patterns according to this format ( https://www.chromium.org/administrators/url-blacklist-filter-format ). If the policy is left not set, no restrictions will be applied.''', - } + }, + { + 'name': 'WebRtcAllowLegacyTLSProtocols', + 'owners': ['hta@chromium.org', 'guidou@chromium.org'], + 'type': 'main', + 'schema': { 'type': 'boolean' }, + 'supported_on': ['chrome.*:87-', 'chrome_os:87-'], + 'features': { + 'dynamic_refresh': False, + 'per_profile': False, + }, + 'example_value': False, + 'id': 787, + 'caption': '''Allow legacy TLS/DTLS downgrade in WebRTC''', + 'tags': [], + 'desc': '''If enabled, WebRTC peer connections can downgrade to obsolete + versions of the TLS/DTLS (DTLS 1.0, TLS 1.0 and TLS 1.1) protocols. + When this policy is disabled or not set, these TLS/DTLS versions are + disabled. + + This policy is temporary and will be removed in a future version + of <ph name="PRODUCT_NAME">$1<ex>Google Chrome</ex></ph>.''', + }, ], 'messages': { @@ -24340,6 +24357,6 @@ ], 'placeholders': [], 'deleted_policy_ids': [114, 115, 412, 476, 544, 546, 562, 569, 578], - 'highest_id_currently_used': 786, + 'highest_id_currently_used': 787, 'highest_atomic_group_id_currently_used': 40 }
diff --git a/components/policy_strings.grdp b/components/policy_strings.grdp index 0f639fdb..c93f5ecf 100644 --- a/components/policy_strings.grdp +++ b/components/policy_strings.grdp
@@ -571,13 +571,16 @@ <!-- Strings for Data Leak Prevention --> <message name="IDS_POLICY_DLP_CLIPBOARD_BLOCKED_ON_PASTE" desc="A toast informing the user that paste is blocked."> - Pasting to this location is blocked by your administrator + Pasting from <ph name="ORIGIN_NAME">$1<ex>corp.google.com</ex></ph> to this location is blocked by your administrator </message> <message name="IDS_POLICY_DLP_CLIPBOARD_BLOCKED_ON_COPY_VM" desc="A toast informing the user that sharing clipboard data to VMs is blocked."> - Your administrator has blocked sharing this content to <ph name="VM_NAME">$1<ex>Linux</ex></ph> + Your administrator has blocked sharing from <ph name="ORIGIN_NAME">$1<ex>corp.google.com</ex></ph> to <ph name="VM_NAME">$2<ex>Linux</ex></ph> </message> <message name="IDS_POLICY_DLP_CLIPBOARD_BLOCKED_ON_COPY_TWO_VMS" desc="A toast informing the user that sharing clipboard data to VMs is blocked."> - Your administrator has blocked sharing this content to <ph name="VM_NAME_1">$1<ex>Linux</ex></ph> and <ph name="VM_NAME_2">$2<ex>Parallels</ex></ph> + Your administrator has blocked sharing from <ph name="ORIGIN_NAME">$1<ex>corp.google.com</ex></ph> to <ph name="VM_NAME_1">$2<ex>Linux</ex></ph> and <ph name="VM_NAME_2">$3<ex>Parallels</ex></ph> + </message> + <message name="IDS_POLICY_DLP_ANDROID_APPS" desc="Name shown for ARC in data leak prevention toasts."> + Android apps </message> <message name="IDS_POLICY_DLP_PRINTING_BLOCKED" desc="A toast informing the user that printing is blocked."> Printing of this content is blocked by your administrator
diff --git a/components/policy_strings_grdp/IDS_POLICY_DLP_ANDROID_APPS.png.sha1 b/components/policy_strings_grdp/IDS_POLICY_DLP_ANDROID_APPS.png.sha1 new file mode 100644 index 0000000..1deee24 --- /dev/null +++ b/components/policy_strings_grdp/IDS_POLICY_DLP_ANDROID_APPS.png.sha1
@@ -0,0 +1 @@ +c8b41368266afc8b1d606cea145ddc2c5ab62527 \ No newline at end of file
diff --git a/components/policy_strings_grdp/IDS_POLICY_DLP_CLIPBOARD_BLOCKED_ON_COPY_TWO_VMS.png.sha1 b/components/policy_strings_grdp/IDS_POLICY_DLP_CLIPBOARD_BLOCKED_ON_COPY_TWO_VMS.png.sha1 index 7118f95..bd19021 100644 --- a/components/policy_strings_grdp/IDS_POLICY_DLP_CLIPBOARD_BLOCKED_ON_COPY_TWO_VMS.png.sha1 +++ b/components/policy_strings_grdp/IDS_POLICY_DLP_CLIPBOARD_BLOCKED_ON_COPY_TWO_VMS.png.sha1
@@ -1 +1 @@ -ba7801e163005f543316c314426956e16845fc59 \ No newline at end of file +022ba1ffbe4205b99e454b5f24bbef05ba3d7d9e \ No newline at end of file
diff --git a/components/policy_strings_grdp/IDS_POLICY_DLP_CLIPBOARD_BLOCKED_ON_COPY_VM.png.sha1 b/components/policy_strings_grdp/IDS_POLICY_DLP_CLIPBOARD_BLOCKED_ON_COPY_VM.png.sha1 index ad4d6cdd..61838f2 100644 --- a/components/policy_strings_grdp/IDS_POLICY_DLP_CLIPBOARD_BLOCKED_ON_COPY_VM.png.sha1 +++ b/components/policy_strings_grdp/IDS_POLICY_DLP_CLIPBOARD_BLOCKED_ON_COPY_VM.png.sha1
@@ -1 +1 @@ -4515755cb0f170f6853402d1950084b03ddd0af2 \ No newline at end of file +dc8420bbab243a1ccc2442778128a5ff7ae2fa9c \ No newline at end of file
diff --git a/components/policy_strings_grdp/IDS_POLICY_DLP_CLIPBOARD_BLOCKED_ON_PASTE.png.sha1 b/components/policy_strings_grdp/IDS_POLICY_DLP_CLIPBOARD_BLOCKED_ON_PASTE.png.sha1 index 5a473a2..d5d99c9e 100644 --- a/components/policy_strings_grdp/IDS_POLICY_DLP_CLIPBOARD_BLOCKED_ON_PASTE.png.sha1 +++ b/components/policy_strings_grdp/IDS_POLICY_DLP_CLIPBOARD_BLOCKED_ON_PASTE.png.sha1
@@ -1 +1 @@ -dafd5167bf4927eefb41f21f0457e9b1591f78de \ No newline at end of file +311127f5b9c8e964067c9805ae7f86d559ec2a6d \ No newline at end of file
diff --git a/components/signin/ios/browser/account_consistency_service.mm b/components/signin/ios/browser/account_consistency_service.mm index e6440c33..f321946f 100644 --- a/components/signin/ios/browser/account_consistency_service.mm +++ b/components/signin/ios/browser/account_consistency_service.mm
@@ -26,6 +26,8 @@ #include "ios/web/common/web_view_creation_util.h" #include "ios/web/public/browser_state.h" #import "ios/web/public/navigation/web_state_policy_decider.h" +#import "ios/web/public/web_state.h" +#include "ios/web/public/web_state_observer.h" #include "net/base/mac/url_conversions.h" #include "net/base/registry_controlled_domains/registry_controlled_domain.h" #include "net/cookies/canonical_cookie.h" @@ -63,14 +65,22 @@ // reacting on the X-Chrome-Manage-Accounts header and notifying its delegate. // It also notifies the AccountConsistencyService of domains it should add the // CHROME_CONNECTED cookie to. -class AccountConsistencyHandler : public web::WebStatePolicyDecider { +class AccountConsistencyHandler : public web::WebStatePolicyDecider, + public web::WebStateObserver { public: AccountConsistencyHandler(web::WebState* web_state, AccountConsistencyService* service, AccountReconcilor* account_reconcilor, id<ManageAccountsDelegate> delegate); + void WebStateDestroyed(web::WebState* web_state) override; + private: + // web::WebStateObserver override. + void PageLoaded( + web::WebState* web_state, + web::PageLoadCompletionStatus load_completion_status) override; + // web::WebStatePolicyDecider override. // Decides on navigation corresponding to |response| whether the navigation // should continue and updates authentication cookies on Google domains. @@ -80,6 +90,7 @@ base::OnceCallback<void(PolicyDecision)> callback) override; void WebStateDestroyed() override; + bool show_consistency_promo_ = false; AccountConsistencyService* account_consistency_service_; // Weak. AccountReconcilor* account_reconcilor_; // Weak. __weak id<ManageAccountsDelegate> delegate_; @@ -94,7 +105,9 @@ : web::WebStatePolicyDecider(web_state), account_consistency_service_(service), account_reconcilor_(account_reconcilor), - delegate_(delegate) {} + delegate_(delegate) { + web_state->AddObserver(this); +} void AccountConsistencyHandler::ShouldAllowResponse( NSURLResponse* response, @@ -134,6 +147,11 @@ base::SysNSStringToUTF8(manage_accounts_header)); account_reconcilor_->OnReceivedManageAccountsResponse(params.service_type); + // Reset boolean that tracks displaying the sign-in consistency promo. This + // ensures that the promo is cancelled once navigation has started and the + // WKWebView is cancelling previous navigations. + show_consistency_promo_ = false; + switch (params.service_type) { case signin::GAIA_SERVICE_TYPE_INCOGNITO: { GURL continue_url = GURL(params.continue_url); @@ -145,7 +163,12 @@ case signin::GAIA_SERVICE_TYPE_SIGNUP: case signin::GAIA_SERVICE_TYPE_ADDSESSION: if (params.show_consistency_promo) { - [delegate_ onShowConsistencyPromo]; + show_consistency_promo_ = true; + // Allows the URL response to load before showing the consistency promo. + // The promo should always be displayed in the foreground of Gaia + // sign-on. + std::move(callback).Run(PolicyDecision::Allow()); + return; } else { [delegate_ onAddAccount]; } @@ -169,6 +192,20 @@ std::move(callback).Run(PolicyDecision::Cancel()); } +void AccountConsistencyHandler::PageLoaded( + web::WebState* web_state, + web::PageLoadCompletionStatus load_completion_status) { + if (!show_consistency_promo_ || + !gaia::IsGaiaSignonRealm(web_state->GetLastCommittedURL().GetOrigin()) || + load_completion_status == web::PageLoadCompletionStatus::FAILURE) { + return; + } + [delegate_ onShowConsistencyPromo]; + show_consistency_promo_ = false; +} + +void AccountConsistencyHandler::WebStateDestroyed(web::WebState* web_state) {} + void AccountConsistencyHandler::WebStateDestroyed() { account_consistency_service_->RemoveWebStateHandler(web_state()); } @@ -222,6 +259,8 @@ void AccountConsistencyService::RemoveWebStateHandler( web::WebState* web_state) { DCHECK_LT(0u, web_state_handlers_.count(web_state)); + web_state->RemoveObserver( + (AccountConsistencyHandler*)web_state_handlers_[web_state].get()); web_state_handlers_.erase(web_state); }
diff --git a/components/signin/ios/browser/account_consistency_service_unittest.mm b/components/signin/ios/browser/account_consistency_service_unittest.mm index d256525..e3645053 100644 --- a/components/signin/ios/browser/account_consistency_service_unittest.mm +++ b/components/signin/ios/browser/account_consistency_service_unittest.mm
@@ -276,6 +276,13 @@ /*domain=*/std::string())); } + // Simulate navigating to a URL with the given page load completion status. + void SimulateNavigateToUrl(web::PageLoadCompletionStatus status, + const GURL& url) { + web_state_.SetCurrentURL(url); + web_state_.OnPageLoaded(status); + } + // Simulate the action of the action GaiaCookieManagerService to cleanup // the cookies once the sign-out is done. void SimulateGaiaCookieManagerServiceLogout() { @@ -467,8 +474,111 @@ EXPECT_CALL(*account_reconcilor_, OnReceivedManageAccountsResponse( signin::GAIA_SERVICE_TYPE_ADDSESSION)) .Times(1); - EXPECT_FALSE( + EXPECT_TRUE( web_state_.ShouldAllowResponse(response, /* for_main_frame = */ true)); + SimulateNavigateToUrl(web::PageLoadCompletionStatus::SUCCESS, + GURL("https://accounts.google.com/")); + web_state_.WebStateDestroyed(); + + EXPECT_OCMOCK_VERIFY(delegate); +} + +// Tests that the consistency promo is not displayed when a page fails to load. +TEST_F(AccountConsistencyServiceTest, + ChromeManageAccountsNotShowConsistencyPromoOnPageLoadFailure) { + id delegate = + [OCMockObject mockForProtocol:@protocol(ManageAccountsDelegate)]; + [[delegate reject] onShowConsistencyPromo]; + + NSDictionary* headers = [NSDictionary + dictionaryWithObject:@"action=ADDSESSION,show_consistency_promo=true" + forKey:@"X-Chrome-Manage-Accounts"]; + NSHTTPURLResponse* response = [[NSHTTPURLResponse alloc] + initWithURL:[NSURL URLWithString:@"https://accounts.google.com/"] + statusCode:200 + HTTPVersion:@"HTTP/1.1" + headerFields:headers]; + account_consistency_service_->SetWebStateHandler(&web_state_, delegate); + EXPECT_CALL(*account_reconcilor_, OnReceivedManageAccountsResponse( + signin::GAIA_SERVICE_TYPE_ADDSESSION)) + .Times(1); + EXPECT_TRUE( + web_state_.ShouldAllowResponse(response, /* for_main_frame = */ true)); + SimulateNavigateToUrl(web::PageLoadCompletionStatus::FAILURE, + GURL("https://accounts.google.com/")); + web_state_.WebStateDestroyed(); + + EXPECT_OCMOCK_VERIFY(delegate); +} + +// Tests that the consistency promo is not displayed when a page fails to load +// and user chooses another action. +TEST_F(AccountConsistencyServiceTest, + ChromeManageAccountsNotShowConsistencyPromoOnPageLoadFailureRedirect) { + id delegate = + [OCMockObject mockForProtocol:@protocol(ManageAccountsDelegate)]; + [[delegate expect] onAddAccount]; + [[delegate reject] onShowConsistencyPromo]; + + NSDictionary* headers = [NSDictionary + dictionaryWithObject:@"action=ADDSESSION,show_consistency_promo=true" + forKey:@"X-Chrome-Manage-Accounts"]; + account_consistency_service_->SetWebStateHandler(&web_state_, delegate); + EXPECT_CALL(*account_reconcilor_, OnReceivedManageAccountsResponse( + signin::GAIA_SERVICE_TYPE_ADDSESSION)) + .Times(2); + + NSHTTPURLResponse* responseSignin = [[NSHTTPURLResponse alloc] + initWithURL:[NSURL URLWithString:@"https://accounts.google.com/"] + statusCode:200 + HTTPVersion:@"HTTP/1.1" + headerFields:headers]; + EXPECT_TRUE(web_state_.ShouldAllowResponse(responseSignin, + /* for_main_frame = */ true)); + const GURL accountsUrl = GURL("https://accounts.google.com/"); + SimulateNavigateToUrl(web::PageLoadCompletionStatus::FAILURE, accountsUrl); + + NSDictionary* headersAddAccount = + [NSDictionary dictionaryWithObject:@"action=ADDSESSION" + forKey:@"X-Chrome-Manage-Accounts"]; + NSHTTPURLResponse* responseAddAccount = [[NSHTTPURLResponse alloc] + initWithURL:[NSURL URLWithString:@"https://accounts.google.com/"] + statusCode:200 + HTTPVersion:@"HTTP/1.1" + headerFields:headersAddAccount]; + EXPECT_FALSE(web_state_.ShouldAllowResponse(responseAddAccount, + /* for_main_frame = */ true)); + SimulateNavigateToUrl(web::PageLoadCompletionStatus::SUCCESS, accountsUrl); + + web_state_.WebStateDestroyed(); + + EXPECT_OCMOCK_VERIFY(delegate); +} + +// Tests that the consistency promo is not displayed when a non GAIA URL is +// committed. +TEST_F(AccountConsistencyServiceTest, + ChromeManageAccountsNotShowConsistencyPromoOnNonGaiaURL) { + id delegate = + [OCMockObject mockForProtocol:@protocol(ManageAccountsDelegate)]; + [[delegate reject] onShowConsistencyPromo]; + + NSDictionary* headers = [NSDictionary + dictionaryWithObject:@"action=ADDSESSION,show_consistency_promo=true" + forKey:@"X-Chrome-Manage-Accounts"]; + NSHTTPURLResponse* response = [[NSHTTPURLResponse alloc] + initWithURL:[NSURL URLWithString:@"https://accounts.google.com/"] + statusCode:200 + HTTPVersion:@"HTTP/1.1" + headerFields:headers]; + account_consistency_service_->SetWebStateHandler(&web_state_, delegate); + EXPECT_CALL(*account_reconcilor_, OnReceivedManageAccountsResponse( + signin::GAIA_SERVICE_TYPE_ADDSESSION)) + .Times(1); + EXPECT_TRUE( + web_state_.ShouldAllowResponse(response, /* for_main_frame = */ true)); + SimulateNavigateToUrl(web::PageLoadCompletionStatus::SUCCESS, + GURL("https://youtube.com/")); web_state_.WebStateDestroyed(); EXPECT_OCMOCK_VERIFY(delegate); @@ -680,5 +790,6 @@ headerFields:headers]; EXPECT_TRUE(web_state_.ShouldAllowResponse(responseGaia, /* for_main_frame = */ true)); + web_state_.WebStateDestroyed(); CheckDomainHasChromeConnectedCookie("google.com"); }
diff --git a/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager.h b/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager.h index b98601d..779139e7 100644 --- a/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager.h +++ b/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager.h
@@ -42,10 +42,11 @@ // within a given WebContents. It contains a mapping of all activated // RenderFrameHosts, along with their associated DocumentSubresourceFilters. // -// The class is designed to be used by a Delegate, which shares lifetime with -// this class (aka the typical lifetime of a WebContentsObserver). The delegate -// will be notified of the first disallowed subresource load for a top level -// navgation, and has veto power for frame activation. +// The class is designed to be used by a SubresourceFilterClient instance that +// shares lifetime with this class (aka the typical lifetime of a +// WebContentsObserver). The client will be notified of the first disallowed +// subresource load for a top level navgation, and has veto power for frame +// activation. class ContentSubresourceFilterThrottleManager : public content::WebContentsObserver, public mojom::SubresourceFilterHost,
diff --git a/components/sync/driver/glue/sync_engine_impl.cc b/components/sync/driver/glue/sync_engine_impl.cc index 126ffacc..b5f0f89 100644 --- a/components/sync/driver/glue/sync_engine_impl.cc +++ b/components/sync/driver/glue/sync_engine_impl.cc
@@ -31,6 +31,7 @@ #include "components/sync/engine/sync_manager_factory.h" #include "components/sync/engine/sync_string_conversions.h" #include "components/sync/invalidations/fcm_handler.h" +#include "components/sync/invalidations/switches.h" #include "components/sync/invalidations/sync_invalidations_service.h" namespace syncer { @@ -44,9 +45,29 @@ : name_(name), sync_prefs_(sync_prefs), invalidator_(invalidator), - sync_invalidations_service_(sync_invalidations_service) { + sync_invalidations_service_(sync_invalidations_service), +#if defined(OS_ANDROID) + sessions_invalidation_enabled_(false) { +#else + sessions_invalidation_enabled_(true) { +#endif backend_ = base::MakeRefCounted<SyncEngineBackend>( name_, sync_data_folder, weak_ptr_factory_.GetWeakPtr()); + + // If the new invalidations system (SyncInvalidationsService) is fully + // enabled, then the SyncService doesn't need to communicate with the old + // InvalidationService anymore. + if (invalidator_ && + base::FeatureList::IsEnabled(switches::kSyncSendInterestedDataTypes) && + base::FeatureList::IsEnabled(switches::kUseSyncInvalidations) && + base::FeatureList::IsEnabled( + switches::kUseSyncInvalidationsForWalletAndOffer)) { + invalidator_->RegisterInvalidationHandler(this); + bool success = invalidator_->UpdateInterestedTopics(this, /*topics=*/{}); + DCHECK(success); + invalidator_->UnregisterInvalidationHandler(this); + invalidator_ = nullptr; + } } SyncEngineImpl::~SyncEngineImpl() { @@ -285,19 +306,7 @@ const ModelTypeSet failed_configuration_types, base::OnceCallback<void(ModelTypeSet, ModelTypeSet)> ready_task) { last_enabled_types_ = enabled_types; - if (invalidator_) { - // No need to register invalidations for CommitOnlyTypes(). - ModelTypeSet invalidation_enabled_types( - Difference(enabled_types, CommitOnlyTypes())); -#if defined(OS_ANDROID) - if (!sessions_invalidation_enabled_) { - invalidation_enabled_types.Remove(syncer::SESSIONS); - } -#endif - bool success = invalidator_->UpdateInterestedTopics( - this, ModelTypeSetToTopicSet(invalidation_enabled_types)); - DCHECK(success); - } + SendInterestedTopicsToInvalidator(); if (!ready_task.is_null()) { std::move(ready_task) @@ -324,6 +333,7 @@ // Fake a state change to initialize the SyncManager's cached invalidator // state. + // TODO(crbug.com/1132868): Do this for the new invalidations as well. OnInvalidatorStateChange(invalidator_->GetInvalidatorState()); } @@ -445,20 +455,7 @@ void SyncEngineImpl::SetInvalidationsForSessionsEnabled(bool enabled) { sessions_invalidation_enabled_ = enabled; - // TODO(crbug.com/1050970): unify logic here and in - // FinishConfigureDataTypesOnFrontedLoop() and factor it out. - // |last_enabled_types_| contains all datatypes, for which user - // has enabled Sync. There is no need to register invalidations for - // CommitOnlyTypes(), so they are filtered out. - ModelTypeSet enabled_for_invalidation( - Difference(last_enabled_types_, CommitOnlyTypes())); - if (!enabled) { - enabled_for_invalidation.Remove(syncer::SESSIONS); - } - bool success = invalidator_->UpdateInterestedTopics( - this, ModelTypeSetToTopicSet(enabled_for_invalidation)); - DCHECK(success); - // TODO(crbug.com/1102312): update enabled data types for sync invalidations. + SendInterestedTopicsToInvalidator(); } void SyncEngineImpl::GetNigoriNodeForDebugging(AllNodesCallback callback) { @@ -490,4 +487,28 @@ std::move(callback).Run(); } +void SyncEngineImpl::SendInterestedTopicsToInvalidator() { + if (!invalidator_) { + return; + } + + // No need to register invalidations for CommitOnlyTypes(). + ModelTypeSet invalidation_enabled_types( + Difference(last_enabled_types_, CommitOnlyTypes())); + if (!sessions_invalidation_enabled_) { + invalidation_enabled_types.Remove(syncer::SESSIONS); + } + // switches::kUseSyncInvalidations means that the new invalidations system is + // used for all data types except Wallet and Offer, so only keep these types. + if (base::FeatureList::IsEnabled(switches::kSyncSendInterestedDataTypes) && + base::FeatureList::IsEnabled(switches::kUseSyncInvalidations)) { + invalidation_enabled_types.RetainAll( + {AUTOFILL_WALLET_DATA, AUTOFILL_WALLET_OFFER}); + } + + bool success = invalidator_->UpdateInterestedTopics( + this, ModelTypeSetToTopicSet(invalidation_enabled_types)); + DCHECK(success); +} + } // namespace syncer
diff --git a/components/sync/driver/glue/sync_engine_impl.h b/components/sync/driver/glue/sync_engine_impl.h index c753a98..bd33225 100644 --- a/components/sync/driver/glue/sync_engine_impl.h +++ b/components/sync/driver/glue/sync_engine_impl.h
@@ -186,6 +186,8 @@ void OnCookieJarChangedDoneOnFrontendLoop(base::OnceClosure callback); + void SendInterestedTopicsToInvalidator(); + // The task runner where all the sync engine operations happen. scoped_refptr<base::SequencedTaskRunner> sync_task_runner_; @@ -222,7 +224,7 @@ SyncInvalidationsService* sync_invalidations_service_ = nullptr; ModelTypeSet last_enabled_types_; - bool sessions_invalidation_enabled_ = false; + bool sessions_invalidation_enabled_; SyncStatus cached_status_;
diff --git a/components/sync/driver/glue/sync_engine_impl_unittest.cc b/components/sync/driver/glue/sync_engine_impl_unittest.cc index dd3eab87..9eecc10 100644 --- a/components/sync/driver/glue/sync_engine_impl_unittest.cc +++ b/components/sync/driver/glue/sync_engine_impl_unittest.cc
@@ -340,6 +340,21 @@ NiceMock<MockSyncInvalidationsService> mock_instance_id_driver_; }; +class SyncEngineImplWithSyncInvalidationsForWalletAndOfferTest + : public SyncEngineImplTest { + public: + SyncEngineImplWithSyncInvalidationsForWalletAndOfferTest() { + override_features_.InitWithFeatures( + /*enabled_features=*/{switches::kSyncSendInterestedDataTypes, + switches::kUseSyncInvalidations, + switches::kUseSyncInvalidationsForWalletAndOffer}, + /*disabled_features=*/{}); + } + + protected: + base::test::ScopedFeatureList override_features_; +}; + // Test basic initialization with no initial types (first time initialization). // Only the nigori should be configured. TEST_F(SyncEngineImplTest, InitShutdown) { @@ -678,6 +693,32 @@ EXPECT_EQ(1, fake_manager_->GetInvalidationCount(ModelType::PREFERENCES)); } +TEST_F(SyncEngineImplWithSyncInvalidationsTest, + UseOldInvalidationsOnlyForWalletAndOffer) { + enabled_types_.PutAll({AUTOFILL_WALLET_DATA, AUTOFILL_WALLET_OFFER}); + + InitializeBackend(/*expect_success=*/true); + EXPECT_CALL( + invalidator_, + UpdateInterestedTopics( + backend_.get(), ModelTypeSetToTopicSet( + {AUTOFILL_WALLET_DATA, AUTOFILL_WALLET_OFFER}))); + ConfigureDataTypes(); + + // At shutdown, we clear the registered invalidation ids. + EXPECT_CALL(invalidator_, UpdateInterestedTopics(backend_.get(), TopicSet())); +} + +TEST_F(SyncEngineImplWithSyncInvalidationsForWalletAndOfferTest, + DoNotUseOldInvalidationsAtAll) { + enabled_types_.PutAll({AUTOFILL_WALLET_DATA, AUTOFILL_WALLET_OFFER}); + + InitializeBackend(/*expect_success=*/true); + EXPECT_CALL(invalidator_, UpdateInterestedTopics(testing::_, testing::_)) + .Times(0); + ConfigureDataTypes(); +} + } // namespace } // namespace syncer
diff --git a/components/sync/driver/profile_sync_service.cc b/components/sync/driver/profile_sync_service.cc index ca6816a..127b899 100644 --- a/components/sync/driver/profile_sync_service.cc +++ b/components/sync/driver/profile_sync_service.cc
@@ -1459,8 +1459,9 @@ return; } - // No need to register invalidations for commit-only types. - ModelTypeSet types = Difference(GetDataTypesToConfigure(), CommitOnlyTypes()); + // No need to register invalidations for non-protocol or commit-only types. + ModelTypeSet types = Intersection(GetDataTypesToConfigure(), ProtocolTypes()); + types.RemoveAll(CommitOnlyTypes()); if (!sessions_invalidations_enabled_) { types.Remove(SESSIONS); }
diff --git a/components/sync/invalidations/switches.h b/components/sync/invalidations/switches.h index 26e27d3..75f3074 100644 --- a/components/sync/invalidations/switches.h +++ b/components/sync/invalidations/switches.h
@@ -16,12 +16,15 @@ // If enabled, the device will register with FCM and listen to new // invalidations. Also, FCM token will be set in DeviceInfo, which signals to // the server that device listens to new invalidations. +// The device will not subscribe to old invalidations for any data types except +// Wallet and Offer, since that will be covered by the new system. // SyncSendInterestedDataTypes must be enabled for this to take effect. extern const base::Feature kUseSyncInvalidations; // If enabled, types related to Wallet and Offer will be included in interested // data types, and the device will listen to new invalidations for those types // (if they are enabled). +// The device will not register for old invalidations at all. // UseSyncInvalidations must be enabled for this to take effect. extern const base::Feature kUseSyncInvalidationsForWalletAndOffer;
diff --git a/components/sync_bookmarks/bookmark_model_type_processor_unittest.cc b/components/sync_bookmarks/bookmark_model_type_processor_unittest.cc index 4c8cf3f..ff551d5f 100644 --- a/components/sync_bookmarks/bookmark_model_type_processor_unittest.cc +++ b/components/sync_bookmarks/bookmark_model_type_processor_unittest.cc
@@ -263,10 +263,9 @@ } sync_pb::BookmarkModelMetadata BuildBookmarkModelMetadataWithoutFullTitles() { - base::test::ScopedFeatureList features; - features.InitAndDisableFeature(switches::kSyncReuploadBookmarkFullTitles); sync_pb::BookmarkModelMetadata model_metadata = processor()->GetTrackerForTest()->BuildBookmarkModelMetadata(); + model_metadata.clear_bookmarks_full_title_reuploaded(); return model_metadata; }
diff --git a/components/sync_bookmarks/switches.cc b/components/sync_bookmarks/switches.cc index 12e7704..16812cc 100644 --- a/components/sync_bookmarks/switches.cc +++ b/components/sync_bookmarks/switches.cc
@@ -10,7 +10,7 @@ "SyncDoNotCommitBookmarksWithoutFavicon", base::FEATURE_ENABLED_BY_DEFAULT}; const base::Feature kSyncReuploadBookmarkFullTitles{ - "SyncReuploadBookmarkFullTitles", base::FEATURE_DISABLED_BY_DEFAULT}; + "SyncReuploadBookmarkFullTitles", base::FEATURE_ENABLED_BY_DEFAULT}; const base::Feature kSyncDeduplicateAllBookmarksWithSameGUID{ "SyncDeduplicateAllBookmarksWithSameGUID",
diff --git a/components/url_formatter/url_fixer.cc b/components/url_formatter/url_fixer.cc index 70aedd34..125a2f1 100644 --- a/components/url_formatter/url_fixer.cc +++ b/components/url_formatter/url_fixer.cc
@@ -394,6 +394,9 @@ // We need to fix up the segmentation for "www.example.com:/". For this // case, we guess that schemes with a "." are not actually schemes. + // + // Note: This logic deviates from GURL, where "www.example.com:" would be + // parsed as having "www.example.com" as the scheme with an empty hostname. if (canon_scheme->find('.') != std::string::npos) return false;
diff --git a/components/url_formatter/url_fixer.h b/components/url_formatter/url_fixer.h index b7c592d39..8e3e5fd 100644 --- a/components/url_formatter/url_fixer.h +++ b/components/url_formatter/url_fixer.h
@@ -19,10 +19,13 @@ struct Parsed; } -// This object is designed to convert various types of input into URLs that we -// know are valid. For example, user typing in the URL bar or command line -// options. This is NOT the place for converting between different types of URLs -// or parsing them, see net_util.h for that. +// These methods process user typed input that is meant to be a URL - like user +// typing in the URL bar or command line switches. The output is NOT guaranteed +// to be a valid URL. +// +// This is NOT the place for converting between different types of URLs or +// parsing them, see net_util.h for that. These methods should only be used on +// user typed input, NOT untrusted strings sourced from the web or elsewhere. namespace url_formatter { // Segments the given text string into parts of a URL. This is most useful for @@ -33,13 +36,15 @@ std::string SegmentURL(const std::string& text, url::Parsed* parts); base::string16 SegmentURL(const base::string16& text, url::Parsed* parts); -// Converts |text| to a fixed-up URL and returns it. Attempts to make some -// "smart" adjustments to obviously-invalid input where possible. -// |text| may be an absolute path to a file, which will get converted to a -// "file:" URL. +// Attempts to fix common problems in user-typed text, making some "smart" +// adjustments to obviously-invalid input where possible. // -// The result will be a "more" valid URL than the input. It may still not be -// valid, so check the return value's validity or use possibly_invalid_spec(). +// The result can still be invalid, so check the return value's validity or +// use possibly_invalid_spec(). DO NOT USE this method on untrusted strings +// from the web or elsewhere. Only use this for user-typed input. +// +// If |text| may be an absolute path to a file, it will get converted to a +// "file:" URL. // // Schemes "about" and "chrome" are normalized to "chrome://", with slashes. // "about:blank" is unaltered, as Webkit allows frames to access about:blank.
diff --git a/components/variations/net/variations_http_headers.cc b/components/variations/net/variations_http_headers.cc index 5ff5a3db..e71505f9 100644 --- a/components/variations/net/variations_http_headers.cc +++ b/components/variations/net/variations_http_headers.cc
@@ -196,8 +196,7 @@ const network::ResourceRequest& resource_request) { bool use_first_party_visibility = IsFirstPartyContext(owner, resource_request) && - VariationsIdsProvider::GetInstance() - ->IsRestrictGoogleWebVisibilityEnabled(); + base::FeatureList::IsEnabled(internal::kRestrictGoogleWebVisibility); return use_first_party_visibility ? variations::mojom::GoogleWebVisibility::FIRST_PARTY
diff --git a/components/variations/variations_ids_provider.cc b/components/variations/variations_ids_provider.cc index b0a531d..9752559 100644 --- a/components/variations/variations_ids_provider.cc +++ b/components/variations/variations_ids_provider.cc
@@ -215,13 +215,8 @@ if (variation_ids_cache_initialized_) return; - // Must be done before AddObserver() to avoid deadlock in - // OnFieldTrialGroupFinalized(). - is_restrict_google_web_visibility_enabled_ = - base::FeatureList::IsEnabled(internal::kRestrictGoogleWebVisibility); - - // Register for additional cache updates. This is done before initializing the - // cache to avoid a race that could cause registered FieldTrials to be missed. + // Register for additional cache updates. This is done first to avoid a race + // that could cause registered FieldTrials to be missed. bool success = base::FieldTrialList::AddObserver(this); DCHECK(success); @@ -295,7 +290,8 @@ proto.add_variation_id(entry.first); break; case GOOGLE_WEB_PROPERTIES_FIRST_PARTY: - if (IsRestrictGoogleWebVisibilityEnabled()) { + if (base::FeatureList::IsEnabled( + internal::kRestrictGoogleWebVisibility)) { if (is_first_party_context) proto.add_variation_id(entry.first); } else { @@ -309,7 +305,8 @@ proto.add_trigger_variation_id(entry.first); break; case GOOGLE_WEB_PROPERTIES_TRIGGER_FIRST_PARTY: - if (IsRestrictGoogleWebVisibilityEnabled()) { + if (base::FeatureList::IsEnabled( + internal::kRestrictGoogleWebVisibility)) { if (is_first_party_context) proto.add_trigger_variation_id(entry.first); } else {
diff --git a/components/variations/variations_ids_provider.h b/components/variations/variations_ids_provider.h index 14afd29..0dbfc80 100644 --- a/components/variations/variations_ids_provider.h +++ b/components/variations/variations_ids_provider.h
@@ -126,12 +126,6 @@ // Resets any cached state for tests. void ResetForTesting(); - // Returns true if kRestrictGoogleWebVisibility is enabled and false - // otherwise. - bool IsRestrictGoogleWebVisibilityEnabled() { - return is_restrict_google_web_visibility_enabled_; - } - private: friend struct base::DefaultSingletonTraits<VariationsIdsProvider>; @@ -227,9 +221,6 @@ // Whether or not we've initialized the caches. bool variation_ids_cache_initialized_; - // Denotes whether kRestrictGoogleWebVisibility is enabled. - bool is_restrict_google_web_visibility_enabled_ = false; - // Keep a cache of variation IDs that are transmitted in headers to Google. // This consists of a list of valid IDs, and the actual transmitted header. std::set<VariationIDEntry> variation_ids_set_;
diff --git a/components/viz/service/display/direct_renderer.cc b/components/viz/service/display/direct_renderer.cc index 3324da8..e237e42 100644 --- a/components/viz/service/display/direct_renderer.cc +++ b/components/viz/service/display/direct_renderer.cc
@@ -352,12 +352,11 @@ // If we promote any quad to an underlay then the main plane must support // alpha. - // TODO(ccameron): We should update |frame_color_space|, and + // TODO(ccameron): We should update + // |root_render_pass->has_transparent_background|, |frame_color_space|, and // |frame_buffer_format| based on the change in |frame_has_alpha|. - if (current_frame()->output_surface_plane) { + if (current_frame()->output_surface_plane) frame_has_alpha |= current_frame()->output_surface_plane->enable_blending; - root_render_pass->has_transparent_background = frame_has_alpha; - } overlay_processor_->AdjustOutputSurfaceOverlay( &(current_frame()->output_surface_plane));
diff --git a/components/viz/service/display_embedder/output_presenter.cc b/components/viz/service/display_embedder/output_presenter.cc index be04b31..a1ea3f8 100644 --- a/components/viz/service/display_embedder/output_presenter.cc +++ b/components/viz/service/display_embedder/output_presenter.cc
@@ -115,14 +115,4 @@ } } -std::unique_ptr<OutputPresenter::Image> -OutputPresenter::AllocateBackgroundImage(gfx::ColorSpace color_space, - gfx::Size image_size) { - return nullptr; -} - -void OutputPresenter::ScheduleBackground(Image* image) { - NOTREACHED(); -} - } // namespace viz
diff --git a/components/viz/service/display_embedder/output_presenter.h b/components/viz/service/display_embedder/output_presenter.h index 7916c94..52b9ed3 100644 --- a/components/viz/service/display_embedder/output_presenter.h +++ b/components/viz/service/display_embedder/output_presenter.h
@@ -86,9 +86,6 @@ gfx::ColorSpace color_space, gfx::Size image_size, size_t num_images) = 0; - virtual std::unique_ptr<Image> AllocateBackgroundImage( - gfx::ColorSpace color_space, - gfx::Size image_size); virtual void SwapBuffers(SwapCompletionCallback completion_callback, BufferPresentedCallback presentation_callback) = 0; virtual void PostSubBuffer(const gfx::Rect& rect, @@ -105,7 +102,6 @@ gpu::SharedImageRepresentationOverlay::ScopedReadAccess; virtual void ScheduleOverlays(SkiaOutputSurface::OverlayList overlays, std::vector<ScopedOverlayAccess*> accesses) = 0; - virtual void ScheduleBackground(Image* image); }; } // namespace viz
diff --git a/components/viz/service/display_embedder/output_presenter_gl.cc b/components/viz/service/display_embedder/output_presenter_gl.cc index d1ef91a..d587bf4 100644 --- a/components/viz/service/display_embedder/output_presenter_gl.cc +++ b/components/viz/service/display_embedder/output_presenter_gl.cc
@@ -17,7 +17,6 @@ #include "ui/display/types/display_snapshot.h" #include "ui/gfx/buffer_format_util.h" #include "ui/gfx/geometry/rect_conversions.h" -#include "ui/gfx/overlay_transform.h" #include "ui/gl/gl_fence.h" #include "ui/gl/gl_surface.h" @@ -283,20 +282,6 @@ return images; } -std::unique_ptr<OutputPresenter::Image> -OutputPresenterGL::AllocateBackgroundImage(gfx::ColorSpace color_space, - gfx::Size image_size) { - auto image = std::make_unique<PresenterImageGL>(); - if (!image->Initialize(shared_image_factory_, - shared_image_representation_factory_, image_size, - color_space, image_format_, dependency_, - shared_image_usage_)) { - DLOG(ERROR) << "Failed to initialize image."; - return nullptr; - } - return image; -} - void OutputPresenterGL::SwapBuffers( SwapCompletionCallback completion_callback, BufferPresentedCallback presentation_callback) { @@ -344,22 +329,6 @@ plane.enable_blending, std::move(fence)); } -void OutputPresenterGL::ScheduleBackground(Image* image) { - // Background is not seen by user, and is created before buffer queue buffers. - // So fence is not needed. - auto* gl_image = - reinterpret_cast<PresenterImageGL*>(image)->GetGLImage(nullptr); - - // Background is also z-order 0. - constexpr int kPlaneZOrder = INT32_MIN; - // Background always uses the full texture. - constexpr gfx::RectF kUVRect(0.f, 0.f, 1.0f, 1.0f); - gl_surface_->ScheduleOverlayPlane( - kPlaneZOrder, gfx::OVERLAY_TRANSFORM_NONE, gl_image, gfx::Rect(), - /*crop_rect=*/kUVRect, - /*enable_blend=*/false, /*gpu_fence=*/nullptr); -} - void OutputPresenterGL::CommitOverlayPlanes( SwapCompletionCallback completion_callback, BufferPresentedCallback presentation_callback) {
diff --git a/components/viz/service/display_embedder/output_presenter_gl.h b/components/viz/service/display_embedder/output_presenter_gl.h index 7bf8c8b7..4cb0ef9a 100644 --- a/components/viz/service/display_embedder/output_presenter_gl.h +++ b/components/viz/service/display_embedder/output_presenter_gl.h
@@ -49,8 +49,6 @@ gfx::ColorSpace color_space, gfx::Size image_size, size_t num_images) final; - std::unique_ptr<Image> AllocateBackgroundImage(gfx::ColorSpace color_space, - gfx::Size image_size) final; void SwapBuffers(SwapCompletionCallback completion_callback, BufferPresentedCallback presentation_callback) final; void PostSubBuffer(const gfx::Rect& rect, @@ -64,7 +62,6 @@ bool is_submitted) final; void ScheduleOverlays(SkiaOutputSurface::OverlayList overlays, std::vector<ScopedOverlayAccess*> accesses) final; - void ScheduleBackground(Image* image) final; private: scoped_refptr<gl::GLSurface> gl_surface_;
diff --git a/components/viz/service/display_embedder/skia_output_device_buffer_queue.cc b/components/viz/service/display_embedder/skia_output_device_buffer_queue.cc index fc8a0df62..ce891e94 100644 --- a/components/viz/service/display_embedder/skia_output_device_buffer_queue.cc +++ b/components/viz/service/display_embedder/skia_output_device_buffer_queue.cc
@@ -102,15 +102,13 @@ SkiaOutputSurfaceDependency* deps, gpu::SharedImageRepresentationFactory* representation_factory, gpu::MemoryTracker* memory_tracker, - const DidSwapBufferCompleteCallback& did_swap_buffer_complete_callback, - bool needs_background_image) + const DidSwapBufferCompleteCallback& did_swap_buffer_complete_callback) : SkiaOutputDevice(deps->GetSharedContextState()->gr_context(), memory_tracker, did_swap_buffer_complete_callback), presenter_(std::move(presenter)), dependency_(deps), - representation_factory_(representation_factory), - needs_background_image_(needs_background_image) { + representation_factory_(representation_factory) { capabilities_.uses_default_gl_framebuffer = false; capabilities_.preserve_buffer_content = true; capabilities_.only_invalidates_damage_rect = false; @@ -192,21 +190,6 @@ void SkiaOutputDeviceBufferQueue::SchedulePrimaryPlane( const base::Optional<OverlayProcessorInterface::OutputSurfaceOverlayPlane>& plane) { - if (background_image_) { - if (!background_image_is_scheduled_) - background_image_->BeginPresent(); - - // WaylandWindow can attach a null wl_buffer to its surface to hide its - // content so needs to reschedule |background_image_| so that - // the wl_surface has a non-null wl_buffer when the window re-appears. - // - // TODO(fangzhoug): It should not be necessary to schedule - // |background_image_| every frame. Make this a responsibility of - // WaylandWindow instead. - presenter_->ScheduleBackground(background_image_.get()); - background_image_is_scheduled_ = true; - } - if (plane) { // If the current_image_ is nullptr, it means there is no change on the // primary plane. So we just need to schedule the last submitted image. @@ -437,12 +420,6 @@ image_size_ = size; FreeAllSurfaces(); - if (needs_background_image_ && !background_image_) { - background_image_ = - presenter_->AllocateBackgroundImage(color_space_, gfx::Size(4, 4)); - background_image_is_scheduled_ = false; - } - images_ = presenter_->AllocateImages(color_space_, image_size_, capabilities_.number_of_buffers); if (images_.empty())
diff --git a/components/viz/service/display_embedder/skia_output_device_buffer_queue.h b/components/viz/service/display_embedder/skia_output_device_buffer_queue.h index 9b439107..cf1e7604 100644 --- a/components/viz/service/display_embedder/skia_output_device_buffer_queue.h +++ b/components/viz/service/display_embedder/skia_output_device_buffer_queue.h
@@ -30,8 +30,7 @@ SkiaOutputSurfaceDependency* deps, gpu::SharedImageRepresentationFactory* representation_factory, gpu::MemoryTracker* memory_tracker, - const DidSwapBufferCompleteCallback& did_swap_buffer_complete_callback, - bool needs_background_image); + const DidSwapBufferCompleteCallback& did_swap_buffer_complete_callback); ~SkiaOutputDeviceBufferQueue() override; @@ -124,13 +123,6 @@ // Set to true if no image is to be used for the primary plane of this frame. bool current_frame_has_no_primary_plane_ = false; - // Whether the platform needs an occluded background image. Wayland needs it - // for opaque accelerated widgets and event wiring. - bool needs_background_image_ = false; - // A 4x4 small image that will be scaled to cover an opaque region. - std::unique_ptr<OutputPresenter::Image> background_image_ = nullptr; - // Set to true if background has been scheduled in a frame. - bool background_image_is_scheduled_ = false; }; } // namespace viz
diff --git a/components/viz/service/display_embedder/skia_output_device_buffer_queue_unittest.cc b/components/viz/service/display_embedder/skia_output_device_buffer_queue_unittest.cc index d4edc49..981986d9 100644 --- a/components/viz/service/display_embedder/skia_output_device_buffer_queue_unittest.cc +++ b/components/viz/service/display_embedder/skia_output_device_buffer_queue_unittest.cc
@@ -237,7 +237,7 @@ gl_surface_, dependency_.get(), shared_image_factory_.get(), shared_image_representation_factory_.get(), shared_image_usage), dependency_.get(), shared_image_representation_factory_.get(), - memory_tracker_.get(), present_callback, false); + memory_tracker_.get(), present_callback); output_device_ = std::move(onscreen_device); }
diff --git a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc index 5073e2e6..30a8812 100644 --- a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc +++ b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc
@@ -1126,26 +1126,16 @@ if (MakeCurrent(true /* need_fbo0 */)) { if (gl_surface_->IsSurfaceless()) { -#if defined(USE_OZONE) - bool needs_background_image = ui::OzonePlatform::GetInstance() - ->GetPlatformProperties() - .needs_background_image; -#else // defined(USE_OZONE) - bool needs_background_image = false; -#endif // !defined(USE_OZONE) - #if !defined(OS_WIN) output_device_ = std::make_unique<SkiaOutputDeviceBufferQueue>( std::make_unique<OutputPresenterGL>( gl_surface_, dependency_, shared_image_factory_.get(), shared_image_representation_factory_.get()), dependency_, shared_image_representation_factory_.get(), - memory_tracker_, GetDidSwapBuffersCompleteCallback(), - needs_background_image); -#else // !defined(OS_WIN) + memory_tracker_, GetDidSwapBuffersCompleteCallback()); +#else NOTIMPLEMENTED(); - (void)needs_background_image; -#endif // defined(OS_WIN) +#endif } else { if (dependency_->NeedsSupportForExternalStencil()) { output_device_ = std::make_unique<SkiaOutputDeviceWebView>( @@ -1197,14 +1187,6 @@ } #endif // defined(USE_X11) -#if defined(USE_OZONE) - bool needs_background_image = ui::OzonePlatform::GetInstance() - ->GetPlatformProperties() - .needs_background_image; -#else // defined(USE_OZONE) - bool needs_background_image = false; -#endif // !defined(USE_OZONE) - #if !defined(OS_WIN) #if defined(OS_FUCHSIA) auto output_presenter = OutputPresenterFuchsia::Create( @@ -1223,11 +1205,10 @@ output_device_ = std::make_unique<SkiaOutputDeviceBufferQueue>( std::move(output_presenter), dependency_, shared_image_representation_factory_.get(), memory_tracker_, - GetDidSwapBuffersCompleteCallback(), needs_background_image); + GetDidSwapBuffersCompleteCallback()); return true; } #endif // !defined(OS_WIN) - (void)needs_background_image; auto output_device = SkiaOutputDeviceVulkan::Create( vulkan_context_provider_, dependency_->GetSurfaceHandle(),
diff --git a/content/browser/loader/navigation_url_loader_impl.cc b/content/browser/loader/navigation_url_loader_impl.cc index 394ad03..3a0f7d0 100644 --- a/content/browser/loader/navigation_url_loader_impl.cc +++ b/content/browser/loader/navigation_url_loader_impl.cc
@@ -203,6 +203,8 @@ new_request->trusted_params = network::ResourceRequest::TrustedParams(); new_request->trusted_params->isolation_info = request_info->isolation_info; new_request->trusted_params->cookie_observer = std::move(cookie_observer); + new_request->trusted_params->client_security_state = + request_info->client_security_state.Clone(); new_request->is_main_frame = request_info->is_main_frame; net::RequestPriority net_priority = net::HIGHEST;
diff --git a/content/browser/renderer_host/agent_scheduling_group_host.cc b/content/browser/renderer_host/agent_scheduling_group_host.cc index 9e6ab8648..e773a359 100644 --- a/content/browser/renderer_host/agent_scheduling_group_host.cc +++ b/content/browser/renderer_host/agent_scheduling_group_host.cc
@@ -127,6 +127,11 @@ return absl::visit([](auto& remote) { return remote.is_bound(); }, remote_); } +mojom::AgentSchedulingGroup* +AgentSchedulingGroupHost::MaybeAssociatedRemote::get() { + return absl::visit([](auto& r) { return r.get(); }, remote_); +} + // AgentSchedulingGroupHost: // static @@ -236,16 +241,30 @@ void AgentSchedulingGroupHost::CreateFrame(mojom::CreateFrameParamsPtr params) { SetUpMojoIfNeeded(); - process_.GetRendererInterface()->CreateFrame(std::move(params)); + mojo_remote_.get()->CreateFrame(std::move(params)); } void AgentSchedulingGroupHost::CreateView(mojom::CreateViewParamsPtr params) { SetUpMojoIfNeeded(); - process_.GetRendererInterface()->CreateView(std::move(params)); + mojo_remote_.get()->CreateView(std::move(params)); } void AgentSchedulingGroupHost::DestroyView(int32_t routing_id) { - process_.GetRendererInterface()->DestroyView(routing_id); + if (mojo_remote_.is_bound()) + mojo_remote_.get()->DestroyView(routing_id); +} + +void AgentSchedulingGroupHost::CreateFrameProxy( + int32_t routing_id, + int32_t render_view_routing_id, + const base::Optional<base::UnguessableToken>& opener_frame_token, + int32_t parent_routing_id, + const FrameReplicationState& replicated_state, + const base::UnguessableToken& frame_token, + const base::UnguessableToken& devtools_frame_token) { + mojo_remote_.get()->CreateFrameProxy( + routing_id, render_view_routing_id, opener_frame_token, parent_routing_id, + replicated_state, frame_token, devtools_frame_token); } void AgentSchedulingGroupHost::GetRoute(
diff --git a/content/browser/renderer_host/agent_scheduling_group_host.h b/content/browser/renderer_host/agent_scheduling_group_host.h index e9902ccc..4d13d699 100644 --- a/content/browser/renderer_host/agent_scheduling_group_host.h +++ b/content/browser/renderer_host/agent_scheduling_group_host.h
@@ -81,6 +81,14 @@ void CreateFrame(mojom::CreateFrameParamsPtr params); void CreateView(mojom::CreateViewParamsPtr params); void DestroyView(int32_t routing_id); + void CreateFrameProxy( + int32_t routing_id, + int32_t render_view_routing_id, + const base::Optional<base::UnguessableToken>& opener_frame_token, + int32_t parent_routing_id, + const FrameReplicationState& replicated_state, + const base::UnguessableToken& frame_token, + const base::UnguessableToken& devtools_frame_token); private: // `MaybeAssociatedReceiver` and `MaybeAssociatedRemote` are temporary helper @@ -136,6 +144,7 @@ void reset(); bool is_bound(); + mojom::AgentSchedulingGroup* get(); private: absl::variant<mojo::Remote<mojom::AgentSchedulingGroup>,
diff --git a/content/browser/renderer_host/navigation_request.cc b/content/browser/renderer_host/navigation_request.cc index 136d721c..6881841 100644 --- a/content/browser/renderer_host/navigation_request.cc +++ b/content/browser/renderer_host/navigation_request.cc
@@ -2791,6 +2791,31 @@ interceptor.push_back(web_bundle_handle_->TakeInterceptor()); net::HttpRequestHeaders cors_exempt_headers; std::swap(cors_exempt_headers, cors_exempt_request_headers_); + + // For subresource requests the ClientSecurityState is passed through + // URLLoaderFactoryParams. That does not work for navigation requests + // because they all share a common factory, so each request is tagged with + // a ClientSecurityState to use instead. + // + // We currently define the client of the fetch as the parent frame, if any. + // This is probably incorrect: frames can cause others in the same browsing + // context group to navigate to pages, without being the parent. Additionally + // there is no client security state for top-level navigations, which mainly + // means that CORS-RFC1918 checks are skipped for such requests. + // + // TODO(https://crbug.com/1129326): Figure out the UX story for top-level + // navigations and spooky-action-at-a-distance navigations, then revisit this. + // The client security state might need to be that of the initiator of the + // navigation, or we might need to take into account both the parent frame and + // the initiator's client security states. In any case, we should probably + // always provide a client security state. + network::mojom::ClientSecurityStatePtr client_security_state = nullptr; + RenderFrameHostImpl* parent = GetParentFrame(); + if (parent) { + client_security_state = + parent->last_committed_client_security_state().Clone(); + } + loader_ = NavigationURLLoader::Create( browser_context, partition, std::make_unique<NavigationRequestInfo>( @@ -2806,7 +2831,7 @@ : nullptr, devtools_navigation_token(), frame_tree_node_->devtools_frame_token(), OriginPolicyThrottle::ShouldRequestOriginPolicy(common_params_->url), - std::move(cors_exempt_headers), nullptr /* client_security_state */), + std::move(cors_exempt_headers), std::move(client_security_state)), std::move(navigation_ui_data), service_worker_handle_.get(), appcache_handle_.get(), std::move(prefetched_signed_exchange_cache_), this, IsServedFromBackForwardCache(), CreateCookieAccessObserver(),
diff --git a/content/browser/renderer_host/navigation_request.h b/content/browser/renderer_host/navigation_request.h index ba4804c..b5a7d2c 100644 --- a/content/browser/renderer_host/navigation_request.h +++ b/content/browser/renderer_host/navigation_request.h
@@ -1113,6 +1113,7 @@ // In that case, the caller must immediately return. bool MaybeCancelFailedNavigation(); + // Never null. The pointee node owns this navigation request instance. FrameTreeNode* const frame_tree_node_; // Value of |is_for_commit| supplied to the constructor.
diff --git a/content/browser/renderer_host/navigation_request_info.h b/content/browser/renderer_host/navigation_request_info.h index ea285de..c52014a94 100644 --- a/content/browser/renderer_host/navigation_request_info.h +++ b/content/browser/renderer_host/navigation_request_info.h
@@ -95,6 +95,9 @@ // Specifies the security state applying to the navigation. For iframes, this // is the security state of their parent. Nullptr otherwise. + // + // TODO(https://crbug.com/1129326): Set this for top-level navigation requests + // too once the UX story is sorted out. const network::mojom::ClientSecurityStatePtr client_security_state; };
diff --git a/content/browser/renderer_host/render_frame_host_impl_browsertest.cc b/content/browser/renderer_host/render_frame_host_impl_browsertest.cc index 712b33a..3fe3daa 100644 --- a/content/browser/renderer_host/render_frame_host_impl_browsertest.cc +++ b/content/browser/renderer_host/render_frame_host_impl_browsertest.cc
@@ -87,7 +87,6 @@ namespace content { namespace { -using ::testing::EndsWith; using ::testing::NotNull; // Implementation of ContentBrowserClient that overrides @@ -3938,11 +3937,8 @@ // Check that the child iframe failed to fetch. ASSERT_EQ(1ul, root_frame_host()->child_count()); auto* child_frame = root_frame_host()->child_at(0)->current_frame_host(); - // TODO(crbug.com/1124346): Expect 0 once the load fails. - EXPECT_EQ(200, child_frame->last_http_status_code()); - // TODO(crbug.com/1124346): Expect an empty URL once the load fails. - EXPECT_THAT(child_frame->last_successful_url().spec(), - EndsWith("/empty.html")); + EXPECT_EQ(0, child_frame->last_http_status_code()); + EXPECT_EQ(GURL(), child_frame->last_successful_url()); } namespace {
diff --git a/content/browser/renderer_host/render_frame_proxy_host.cc b/content/browser/renderer_host/render_frame_proxy_host.cc index ea76464..7aacc0e 100644 --- a/content/browser/renderer_host/render_frame_proxy_host.cc +++ b/content/browser/renderer_host/render_frame_proxy_host.cc
@@ -253,10 +253,12 @@ } int view_routing_id = GetRenderViewHost()->GetRoutingID(); - GetProcess()->GetRendererInterface()->CreateFrameProxy( - routing_id_, view_routing_id, opener_frame_token, parent_routing_id, - frame_tree_node_->current_replication_state(), frame_token_, - frame_tree_node_->devtools_frame_token()); + static_cast<SiteInstanceImpl*>(site_instance_.get()) + ->GetAgentSchedulingGroup() + .CreateFrameProxy(routing_id_, view_routing_id, opener_frame_token, + parent_routing_id, + frame_tree_node_->current_replication_state(), + frame_token_, frame_tree_node_->devtools_frame_token()); SetRenderFrameProxyCreated(true);
diff --git a/content/browser/site_per_process_browsertest.cc b/content/browser/site_per_process_browsertest.cc index 56c0213..b76139eb 100644 --- a/content/browser/site_per_process_browsertest.cc +++ b/content/browser/site_per_process_browsertest.cc
@@ -52,6 +52,7 @@ #include "components/viz/common/features.h" #include "content/browser/child_process_security_policy_impl.h" #include "content/browser/gpu/compositor_util.h" +#include "content/browser/renderer_host/agent_scheduling_group_host.h" #include "content/browser/renderer_host/cross_process_frame_connector.h" #include "content/browser/renderer_host/frame_navigation_entry.h" #include "content/browser/renderer_host/frame_tree.h" @@ -6193,6 +6194,8 @@ SiteInstance* site_instance_a = root->current_frame_host()->GetSiteInstance(); RenderProcessHost* process_a = root->render_manager()->current_frame_host()->GetProcess(); + AgentSchedulingGroupHost* agent_scheduling_group_a = + AgentSchedulingGroupHost::Get(*site_instance_a, *process_a); int new_routing_id = process_a->GetNextRoutingID(); int view_routing_id = root->frame_tree()->GetRenderViewHost(site_instance_a)->GetRoutingID(); @@ -6207,7 +6210,7 @@ // Send the message to create a proxy for B's new child frame in A. This // used to crash, as parent_routing_id refers to a proxy that doesn't exist // anymore. - process_a->GetRendererInterface()->CreateFrameProxy( + agent_scheduling_group_a->CreateFrameProxy( new_routing_id, view_routing_id, base::nullopt, parent_routing_id, FrameReplicationState(), base::UnguessableToken::Create(), base::UnguessableToken::Create()); @@ -6252,6 +6255,10 @@ // attempted. RenderProcessHost* process = node->render_manager()->speculative_frame_host()->GetProcess(); + AgentSchedulingGroupHost* agent_scheduling_group = + AgentSchedulingGroupHost::Get( + *node->render_manager()->speculative_frame_host()->GetSiteInstance(), + *process); RenderProcessHostWatcher watcher( process, RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT); int frame_routing_id = @@ -6282,7 +6289,7 @@ params->frame_owner_properties = blink::mojom::FrameOwnerProperties::New(); params->frame_token = frame_token; params->devtools_frame_token = base::UnguessableToken::Create(); - process->GetRendererInterface()->CreateFrame(std::move(params)); + agent_scheduling_group->CreateFrame(std::move(params)); } // Disable the BackForwardCache to ensure the old process is going to be @@ -6322,6 +6329,9 @@ // observer to ensure there is no crash when a new RenderFrame creation is // attempted. RenderProcessHost* process = node->current_frame_host()->GetProcess(); + AgentSchedulingGroupHost* agent_scheduling_group = + AgentSchedulingGroupHost::Get( + *node->current_frame_host()->GetSiteInstance(), *process); RenderProcessHostWatcher watcher( process, RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT); int frame_routing_id = node->current_frame_host()->GetRoutingID(); @@ -6372,7 +6382,7 @@ params->replication_state.unique_name = "name"; params->frame_token = frame_token; params->devtools_frame_token = base::UnguessableToken::Create(); - process->GetRendererInterface()->CreateFrame(std::move(params)); + agent_scheduling_group->CreateFrame(std::move(params)); } // The test must wait for the process to exit, but if there is no leak, the
diff --git a/content/common/agent_scheduling_group.mojom b/content/common/agent_scheduling_group.mojom index df10b27..e5aa8aa 100644 --- a/content/common/agent_scheduling_group.mojom +++ b/content/common/agent_scheduling_group.mojom
@@ -4,12 +4,236 @@ module content.mojom; -// Interface for general communication between AgentSchedulingGroup and -// AgentSchedulingGroupHost. +import "content/common/document_scoped_interface_bundle.mojom"; +import "content/common/native_types.mojom"; +import "content/public/common/web_preferences.mojom"; +import "ipc/constants.mojom"; +import "mojo/public/mojom/base/generic_pending_receiver.mojom"; +import "mojo/public/mojom/base/unguessable_token.mojom"; +import "third_party/blink/public/mojom/frame/frame_owner_properties.mojom"; +import "third_party/blink/public/mojom/page/page.mojom"; +import "third_party/blink/public/mojom/page/widget.mojom"; +import "third_party/blink/public/mojom/renderer_preferences.mojom"; +import "third_party/blink/public/mojom/widget/visual_properties.mojom"; + +// A View (i.e. a "main frame") can be created for a few different cases, these +// values are used to specify which it is. +enum ViewWidgetType { + // A standard view that's the top-level widget in a frame hierarchy. + kTopLevel, + // A GuestView used to render contents inside a <webview> element. + kGuestView, + // A view used to render contents inside a <portal> element. + kPortal +}; + +struct CreateViewParams { + // Renderer-wide preferences. + blink.mojom.RendererPreferences renderer_preferences; + + // Preferences for this view. + WebPreferences web_preferences; + + // The ID of the view to be created. + int32 view_id = IPC.mojom.kRoutingIdNone; + + // The ID of the main frame hosted in the view, or None if creating a view to + // host a main frame proxy. If this is None, then |proxy_routing_id| should be + // set to something other than None. The |main_frame_widget_routing_id| is + // None if this is None. + int32 main_frame_routing_id = IPC.mojom.kRoutingIdNone; + + // The ID of the widget for the main frame. The |main_frame_routing_id| is + // None if this is None. + int32 main_frame_widget_routing_id = IPC.mojom.kRoutingIdNone; + + // This is null precisely when |main_frame_routing_id| is MSG_ROUTING_NONE, + // that is, when creating a RenderView for a remote main frame. + DocumentScopedInterfaceBundle? main_frame_interface_bundle; + + // The communication interfaces for the WebFrameWidget in blink. All should + // be set if there is a |main_frame_routing_id|. + pending_associated_remote<blink.mojom.FrameWidgetHost>? frame_widget_host; + pending_associated_receiver<blink.mojom.FrameWidget>? frame_widget; + pending_associated_remote<blink.mojom.WidgetHost>? widget_host; + pending_associated_receiver<blink.mojom.Widget>? widget; + + // The session storage namespace ID this view should use. + string session_storage_namespace_id; + + // The frame token of the opener RenderFrame or RenderFrameProxy, if we need + // to set one (base::nullopt otherwise). + mojo_base.mojom.UnguessableToken? opener_frame_token; + + // Carries replicated information, such as frame name and sandbox flags, for + // this view's main frame, which will be a proxy when |main_frame_routing_id| + // is None (due to site isolation), or a RenderFrame in all other cases. + FrameReplicationState replicated_frame_state; + + // This represents the frame token for the MainFrame. It will be always set. + // If |main_frame_routing_id| is set, it will store a unique identifier for + // the LocalFrame<-->RenderFrameHostImpl mapping. + // If |proxy_routing_id| is set, it will store a unique identifier for + // the RemoteFrame<-->RenderFrameProxyHost mapping. + mojo_base.mojom.UnguessableToken main_frame_frame_token; + + // Used for devtools instrumentation and trace-ability. The token is + // propagated to Blink's LocalFrame and both Blink and content/ + // can tag calls and requests with this instrumentation token in order to + // attribute them to the context frame. + // |devtools_main_frame_token| is only defined by the browser and is never + // sent back from the renderer in the control calls. + mojo_base.mojom.UnguessableToken devtools_main_frame_token; + + // The ID of the proxy object for the main frame in this view. It is only + // used if |main_frame_routing_id| is None, and exactly one of the two + // should be set to an id other than None at any time. + int32 proxy_routing_id = IPC.mojom.kRoutingIdNone; + + // Whether the RenderView should initially be hidden. + bool hidden; + + // When true, all RenderWidgets under this RenderView will never be shown to + // the user, and thus never composited, and will not need to produce pixels + // for display. This allows the renderer to optimize and avoid resources used + // for displaying graphical output. + bool never_composited; + + // Whether the window associated with this view was created with an opener. + bool window_was_created_with_opener; + + // Whether or not the frame has previously committed a real load. + bool has_committed_real_load; + + // Initial state for the main frame RenderWidget. + // TODO(danakj): This should be optional and not included when there is no + // main_frame_widget_routing_id. + blink.mojom.VisualProperties visual_properties; + + // Whether lookup of frames in the created RenderView (e.g. lookup via + // window.open or via <a target=...>) should be renderer-wide (i.e. going + // beyond the usual opener-relationship-based BrowsingInstance boundaries). + bool renderer_wide_named_frame_lookup; + + // Indicates whether the view is a regular top-level widget or some other + // nested "main frame" widget type. + ViewWidgetType type; + + // Endpoint for any messages that are broadcast to all views in a WebContents. + pending_associated_receiver<blink.mojom.PageBroadcast> blink_page_broadcast; +}; + +struct CreateFrameWidgetParams { + // Gives the routing ID for the RenderWidget that will be attached to the + // new RenderFrame. + int32 routing_id; + + // The communication interfaces for the WebFrameWidget in blink. + pending_associated_remote<blink.mojom.FrameWidgetHost> frame_widget_host; + pending_associated_receiver<blink.mojom.FrameWidget> frame_widget; + pending_associated_remote<blink.mojom.WidgetHost> widget_host; + pending_associated_receiver<blink.mojom.Widget> widget; + + // The initial visual properties of the widget. + blink.mojom.VisualProperties visual_properties; +}; + +struct CreateFrameParams { + // Specifies the routing ID of the new RenderFrame object. + int32 routing_id; + + // If a valid |previous_routing_id| is provided, the new frame will be + // configured to replace either the previous frame or the previous proxy on + // commit. + int32 previous_routing_id; + + // The frame token. It is a unique identifier for + // the LocalFrame<-->RenderFrameHostImpl mapping. + mojo_base.mojom.UnguessableToken frame_token; + + // Specifies the new frame's opener. The opener will be null if this is + // base::nullopt. + mojo_base.mojom.UnguessableToken? opener_frame_token; + + // The new frame should be created as a child of the object + // identified by |parent_routing_id| or as top level if that is + // MSG_ROUTING_NONE. + int32 parent_routing_id; + + // Identifies the previous sibling of the new frame, so that the new frame is + // inserted into the correct place in the frame tree. If this is + // MSG_ROUTING_NONE, the frame will be created as the leftmost child of its + // parent frame, in front of any other children. + int32 previous_sibling_routing_id; + + DocumentScopedInterfaceBundle interface_bundle; + + // When the new frame has a parent, |replication_state| holds the new frame's + // properties replicated from the process rendering the parent frame, such as + // the new frame's sandbox flags. + FrameReplicationState replication_state; + + // Used for devtools instrumentation and trace-ability. The token is + // propagated to Blink's LocalFrame and both Blink and content/ + // can tag calls and requests with this instrumentation token in order to + // attribute them to the context frame. + // |devtools_frame_token| is only defined by the browser and is never + // sent back from the renderer in the control calls. + mojo_base.mojom.UnguessableToken devtools_frame_token; + + // When the new frame has a parent, |frame_owner_properties| holds the + // properties of the HTMLFrameOwnerElement from the parent process. + // Note that unlike FrameReplicationState, this is not replicated for remote + // frames. + blink.mojom.FrameOwnerProperties frame_owner_properties; + + // Specifies properties for a new RenderWidget that will be attached to the + // new RenderFrame (if one is needed). + CreateFrameWidgetParams? widget_params; + + // Whether or not the frame has previously committed a real load. + bool has_committed_real_load; +}; + + +// Interface for general communication between the renderer process's +// AgentSchedulingGroup and the browser process's AgentSchedulingGroupHost. +// Implemented by AgentSchedulingGroupHost (in the browser process). interface AgentSchedulingGroupHost { }; -// Interface for general communication between AgentSchedulingGroupHost and -// AgentSchedulingGroup. +// Interface for general communication between the browser process's +// AgentSchedulingGroupHost and the renderer process's AgentSchedulingGroup. +// Implemented by content::AgentSchedulingGroup (in the renderer process). interface AgentSchedulingGroup { + // Tells the renderer to create a new view. + CreateView(CreateViewParams params); + + // Tells the renderer to destroy an existing view. This method must be called + // exactly once for each invocation of CreateView. |view_id| is synonymous + // with |routing_id|. + DestroyView(int32 view_id); + + // Tells the renderer to create a new RenderFrame. + CreateFrame(CreateFrameParams params); + + // Tells the renderer to create a new RenderFrameProxy object with + // |routing_id|. |render_view_routing_id| identifies the + // RenderView to be associated with this proxy. The new proxy's opener should + // be set to the object identified by |opener_frame_token|, or to null if that + // is base::nullopt. The new proxy should be created as a child of the + // object identified by |parent_routing_id| or as top level if that is + // MSG_ROUTING_NONE. + // |proxy_frame_token| is used uniquely identify the + // RemoteFrame <--> RenderFrameProxyHost mapping. + // |devtools_frame_token| is used for devtools instrumentation + // and trace-ability. It is defined by the browser and is never + // sent back from the renderer in the control calls. + CreateFrameProxy(int32 routing_id, int32 render_view_routing_id, + mojo_base.mojom.UnguessableToken? opener_frame_token, + int32 parent_routing_id, + FrameReplicationState replication_state, + mojo_base.mojom.UnguessableToken proxy_frame_token, + mojo_base.mojom.UnguessableToken devtools_frame_token); + };
diff --git a/content/common/renderer.mojom b/content/common/renderer.mojom index 5515b7cf..e73b879 100644 --- a/content/common/renderer.mojom +++ b/content/common/renderer.mojom
@@ -5,202 +5,13 @@ module content.mojom; import "content/common/agent_scheduling_group.mojom"; -import "content/common/document_scoped_interface_bundle.mojom"; import "content/common/native_types.mojom"; -import "content/public/common/web_preferences.mojom"; -import "ipc/constants.mojom"; import "mojo/public/mojom/base/generic_pending_receiver.mojom"; import "mojo/public/mojom/base/time.mojom"; -import "mojo/public/mojom/base/unguessable_token.mojom"; import "services/network/public/mojom/network_types.mojom"; -import "third_party/blink/public/mojom/frame/frame_owner_properties.mojom"; -import "third_party/blink/public/mojom/manifest/manifest.mojom"; -import "third_party/blink/public/mojom/page/page.mojom"; -import "third_party/blink/public/mojom/page/widget.mojom"; -import "third_party/blink/public/mojom/renderer_preferences.mojom"; -import "third_party/blink/public/mojom/widget/visual_properties.mojom"; import "third_party/blink/public/mojom/user_agent/user_agent_metadata.mojom"; import "ui/gfx/geometry/mojom/geometry.mojom"; -// A View (i.e. a "main frame") can be created for a few different cases, these -// values are used to specify which it is. -enum ViewWidgetType { - // A standard view that's the top-level widget in a frame hierarchy. - kTopLevel, - // A GuestView used to render contents inside a <webview> element. - kGuestView, - // A view used to render contents inside a <portal> element. - kPortal -}; - -struct CreateViewParams { - // Renderer-wide preferences. - blink.mojom.RendererPreferences renderer_preferences; - - // Preferences for this view. - WebPreferences web_preferences; - - // The ID of the view to be created. - int32 view_id = IPC.mojom.kRoutingIdNone; - - // The ID of the main frame hosted in the view, or None if creating a view to - // host a main frame proxy. If this is None, then |proxy_routing_id| should be - // set to something other than None. The |main_frame_widget_routing_id| is - // None if this is None. - int32 main_frame_routing_id = IPC.mojom.kRoutingIdNone; - - // The ID of the widget for the main frame. The |main_frame_routing_id| is - // None if this is None. - int32 main_frame_widget_routing_id = IPC.mojom.kRoutingIdNone; - - // This is null precisely when |main_frame_routing_id| is MSG_ROUTING_NONE, - // that is, when creating a RenderView for a remote main frame. - DocumentScopedInterfaceBundle? main_frame_interface_bundle; - - // The communication interfaces for the WebFrameWidget in blink. All should - // be set if there is a |main_frame_routing_id|. - pending_associated_remote<blink.mojom.FrameWidgetHost>? frame_widget_host; - pending_associated_receiver<blink.mojom.FrameWidget>? frame_widget; - pending_associated_remote<blink.mojom.WidgetHost>? widget_host; - pending_associated_receiver<blink.mojom.Widget>? widget; - - // The session storage namespace ID this view should use. - string session_storage_namespace_id; - - // The frame token of the opener RenderFrame or RenderFrameProxy, if we need - // to set one (base::nullopt otherwise). - mojo_base.mojom.UnguessableToken? opener_frame_token; - - // Carries replicated information, such as frame name and sandbox flags, for - // this view's main frame, which will be a proxy when |main_frame_routing_id| - // is None (due to site isolation), or a RenderFrame in all other cases. - FrameReplicationState replicated_frame_state; - - // This represents the frame token for the MainFrame. It will be always set. - // If |main_frame_routing_id| is set, it will store a unique identifier for - // the LocalFrame<-->RenderFrameHostImpl mapping. - // If |proxy_routing_id| is set, it will store a unique identifier for - // the RemoteFrame<-->RenderFrameProxyHost mapping. - mojo_base.mojom.UnguessableToken main_frame_frame_token; - - // Used for devtools instrumentation and trace-ability. The token is - // propagated to Blink's LocalFrame and both Blink and content/ - // can tag calls and requests with this instrumentation token in order to - // attribute them to the context frame. - // |devtools_main_frame_token| is only defined by the browser and is never - // sent back from the renderer in the control calls. - mojo_base.mojom.UnguessableToken devtools_main_frame_token; - - // The ID of the proxy object for the main frame in this view. It is only - // used if |main_frame_routing_id| is None, and exactly one of the two - // should be set to an id other than None at any time. - int32 proxy_routing_id = IPC.mojom.kRoutingIdNone; - - // Whether the RenderView should initially be hidden. - bool hidden; - - // When true, all RenderWidgets under this RenderView will never be shown to - // the user, and thus never composited, and will not need to produce pixels - // for display. This allows the renderer to optimize and avoid resources used - // for displaying graphical output. - bool never_composited; - - // Whether the window associated with this view was created with an opener. - bool window_was_created_with_opener; - - // Whether or not the frame has previously committed a real load. - bool has_committed_real_load; - - // Initial state for the main frame RenderWidget. - // TODO(danakj): This should be optional and not included when there is no - // main_frame_widget_routing_id. - blink.mojom.VisualProperties visual_properties; - - // Whether lookup of frames in the created RenderView (e.g. lookup via - // window.open or via <a target=...>) should be renderer-wide (i.e. going - // beyond the usual opener-relationship-based BrowsingInstance boundaries). - bool renderer_wide_named_frame_lookup; - - // Indicates whether the view is a regular top-level widget or some other - // nested "main frame" widget type. - ViewWidgetType type; - - // Endpoint for any messages that are broadcast to all views in a WebContents. - pending_associated_receiver<blink.mojom.PageBroadcast> blink_page_broadcast; -}; - -struct CreateFrameWidgetParams { - // Gives the routing ID for the RenderWidget that will be attached to the - // new RenderFrame. - int32 routing_id; - - // The communication interfaces for the WebFrameWidget in blink. - pending_associated_remote<blink.mojom.FrameWidgetHost> frame_widget_host; - pending_associated_receiver<blink.mojom.FrameWidget> frame_widget; - pending_associated_remote<blink.mojom.WidgetHost> widget_host; - pending_associated_receiver<blink.mojom.Widget> widget; - - // The initial visual properties of the widget. - blink.mojom.VisualProperties visual_properties; -}; - -struct CreateFrameParams { - // Specifies the routing ID of the new RenderFrame object. - int32 routing_id; - - // If a valid |previous_routing_id| is provided, the new frame will be - // configured to replace either the previous frame or the previous proxy on - // commit. - int32 previous_routing_id; - - // The frame token. It is a unique identifier for - // the LocalFrame<-->RenderFrameHostImpl mapping. - mojo_base.mojom.UnguessableToken frame_token; - - // Specifies the new frame's opener. The opener will be null if this is - // base::nullopt. - mojo_base.mojom.UnguessableToken? opener_frame_token; - - // The new frame should be created as a child of the object - // identified by |parent_routing_id| or as top level if that is - // MSG_ROUTING_NONE. - int32 parent_routing_id; - - // Identifies the previous sibling of the new frame, so that the new frame is - // inserted into the correct place in the frame tree. If this is - // MSG_ROUTING_NONE, the frame will be created as the leftmost child of its - // parent frame, in front of any other children. - int32 previous_sibling_routing_id; - - DocumentScopedInterfaceBundle interface_bundle; - - // When the new frame has a parent, |replication_state| holds the new frame's - // properties replicated from the process rendering the parent frame, such as - // the new frame's sandbox flags. - FrameReplicationState replication_state; - - // Used for devtools instrumentation and trace-ability. The token is - // propagated to Blink's LocalFrame and both Blink and content/ - // can tag calls and requests with this instrumentation token in order to - // attribute them to the context frame. - // |devtools_frame_token| is only defined by the browser and is never - // sent back from the renderer in the control calls. - mojo_base.mojom.UnguessableToken devtools_frame_token; - - // When the new frame has a parent, |frame_owner_properties| holds the - // properties of the HTMLFrameOwnerElement from the parent process. - // Note that unlike FrameReplicationState, this is not replicated for remote - // frames. - blink.mojom.FrameOwnerProperties frame_owner_properties; - - // Specifies properties for a new RenderWidget that will be attached to the - // new RenderFrame (if one is needed). - CreateFrameWidgetParams? widget_params; - - // Whether or not the frame has previously committed a real load. - bool has_committed_real_load; -}; - struct UpdateScrollbarThemeParams { // TODO(avi): Update these to optional values when optional numeric types are // allowed. (https://crbug.com/657632) @@ -247,17 +58,6 @@ // This should be used for implementing browser-to-renderer control messages // which need to retain FIFO with respect to legacy IPC messages. interface Renderer { - // Tells the renderer to create a new view. - CreateView(CreateViewParams params); - - // Tells the renderer to destroy an existing view. This method must be called - // exactly once for each invocation of CreateView. |view_id| is synonymous - // with |routing_id|. - DestroyView(int32 view_id); - - // Tells the renderer to create a new RenderFrame. - CreateFrame(CreateFrameParams params); - // Tells the renderer to create a new AgentSchedulingGroup, that will // communicate via the pending |agent_scheduling_group_host| and // |agent_scheduling_group|. This will create "independent" interfaces that @@ -278,25 +78,6 @@ pending_associated_receiver<AgentSchedulingGroup> agent_scheduling_group ); - // Tells the renderer to create a new RenderFrameProxy object with - // |routing_id|. |render_view_routing_id| identifies the - // RenderView to be associated with this proxy. The new proxy's opener should - // be set to the object identified by |opener_frame_token|, or to null if that - // is base::nullopt. The new proxy should be created as a child of the - // object identified by |parent_routing_id| or as top level if that is - // MSG_ROUTING_NONE. - // |proxy_frame_token| is used uniquely identify the - // RemoteFrame <--> RenderFrameProxyHost mapping. - // |devtools_frame_token| is used for devtools instrumentation - // and trace-ability. It is defined by the browser and is never - // sent back from the renderer in the control calls. - CreateFrameProxy(int32 routing_id, int32 render_view_routing_id, - mojo_base.mojom.UnguessableToken? opener_frame_token, - int32 parent_routing_id, - FrameReplicationState replication_state, - mojo_base.mojom.UnguessableToken proxy_frame_token, - mojo_base.mojom.UnguessableToken devtools_frame_token); - // Tells the renderer that the network type has changed so that // navigator.onLine and navigator.connection can be updated. OnNetworkConnectionChanged(NetworkConnectionType connection_type,
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/JavaBridgeActivityTestRule.java b/content/public/android/javatests/src/org/chromium/content/browser/JavaBridgeActivityTestRule.java index f0d153f..fa8864b 100644 --- a/content/public/android/javatests/src/org/chromium/content/browser/JavaBridgeActivityTestRule.java +++ b/content/public/android/javatests/src/org/chromium/content/browser/JavaBridgeActivityTestRule.java
@@ -9,8 +9,6 @@ import org.junit.runners.model.Statement; import org.chromium.base.Log; -import org.chromium.base.test.SetUpStatement; -import org.chromium.base.test.SetUpTestRule; import org.chromium.base.test.params.ParameterProvider; import org.chromium.base.test.params.ParameterSet; import org.chromium.base.test.util.UrlUtils; @@ -28,8 +26,10 @@ /** * ActivityTestRule with common functionality for testing the Java Bridge. */ -public class JavaBridgeActivityTestRule - extends ContentShellActivityTestRule implements SetUpTestRule<JavaBridgeActivityTestRule> { +public class JavaBridgeActivityTestRule extends ContentShellActivityTestRule { + /** Shared name for batched JavaBridge tests. */ + public static final String BATCH = "JavaBridgeActivityTestRule"; + /** * {@link ParameterProvider} used for parameterized test that provides the Mojo usage state. */ @@ -58,7 +58,6 @@ } private TestCallbackHelperContainer mTestCallbackHelperContainer; - private boolean mSetup; private boolean mUseMojo; public static class Controller { @@ -183,18 +182,7 @@ @Override public Statement apply(Statement base, Description desc) { - SetUpStatement setUpBase = new SetUpStatement(base, this, mSetup); - return super.apply(setUpBase, desc); - } - - @Override - public JavaBridgeActivityTestRule shouldSetUp(boolean runSetUp) { - mSetup = runSetUp; - return this; - } - - @Override - public void setUp() { setUpContentView(); + return super.apply(base, desc); } }
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/JavaBridgeArrayCoercionTest.java b/content/public/android/javatests/src/org/chromium/content/browser/JavaBridgeArrayCoercionTest.java index f942e47..61af28f 100644 --- a/content/public/android/javatests/src/org/chromium/content/browser/JavaBridgeArrayCoercionTest.java +++ b/content/public/android/javatests/src/org/chromium/content/browser/JavaBridgeArrayCoercionTest.java
@@ -17,6 +17,7 @@ import org.chromium.base.test.params.ParameterAnnotations.UseMethodParameterBefore; import org.chromium.base.test.params.ParameterAnnotations.UseRunnerDelegate; import org.chromium.base.test.params.ParameterizedRunner; +import org.chromium.base.test.util.Batch; import org.chromium.base.test.util.Feature; import org.chromium.content.browser.JavaBridgeActivityTestRule.Controller; @@ -33,12 +34,12 @@ */ @RunWith(ParameterizedRunner.class) @UseRunnerDelegate(BaseJUnit4RunnerDelegate.class) +@Batch(JavaBridgeActivityTestRule.BATCH) public class JavaBridgeArrayCoercionTest { private static final double ASSERTION_DELTA = 0; @Rule - public JavaBridgeActivityTestRule mActivityTestRule = - new JavaBridgeActivityTestRule().shouldSetUp(true); + public JavaBridgeActivityTestRule mActivityTestRule = new JavaBridgeActivityTestRule(); private static class TestObject extends Controller { private final Object mObjectInstance;
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/JavaBridgeArrayTest.java b/content/public/android/javatests/src/org/chromium/content/browser/JavaBridgeArrayTest.java index 3c1b3476..24a0d0a 100644 --- a/content/public/android/javatests/src/org/chromium/content/browser/JavaBridgeArrayTest.java +++ b/content/public/android/javatests/src/org/chromium/content/browser/JavaBridgeArrayTest.java
@@ -17,6 +17,7 @@ import org.chromium.base.test.params.ParameterAnnotations.UseMethodParameterBefore; import org.chromium.base.test.params.ParameterAnnotations.UseRunnerDelegate; import org.chromium.base.test.params.ParameterizedRunner; +import org.chromium.base.test.util.Batch; import org.chromium.base.test.util.Feature; import org.chromium.content.browser.JavaBridgeActivityTestRule.Controller; @@ -32,10 +33,10 @@ */ @RunWith(ParameterizedRunner.class) @UseRunnerDelegate(BaseJUnit4RunnerDelegate.class) +@Batch(JavaBridgeActivityTestRule.BATCH) public class JavaBridgeArrayTest { @Rule - public JavaBridgeActivityTestRule mActivityTestRule = - new JavaBridgeActivityTestRule().shouldSetUp(true); + public JavaBridgeActivityTestRule mActivityTestRule = new JavaBridgeActivityTestRule(); private static class TestObject extends Controller { private boolean mBooleanValue;
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/JavaBridgeBareboneTest.java b/content/public/android/javatests/src/org/chromium/content/browser/JavaBridgeBareboneTest.java index 660140fd..c89009f 100644 --- a/content/public/android/javatests/src/org/chromium/content/browser/JavaBridgeBareboneTest.java +++ b/content/public/android/javatests/src/org/chromium/content/browser/JavaBridgeBareboneTest.java
@@ -7,7 +7,6 @@ import androidx.test.filters.SmallTest; import org.junit.Assert; -import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; @@ -17,22 +16,21 @@ import org.chromium.base.test.params.ParameterAnnotations.UseMethodParameterBefore; import org.chromium.base.test.params.ParameterAnnotations.UseRunnerDelegate; import org.chromium.base.test.params.ParameterizedRunner; +import org.chromium.base.test.util.Batch; import org.chromium.base.test.util.DisabledTest; import org.chromium.base.test.util.Feature; -import org.chromium.base.test.util.UrlUtils; import org.chromium.content_public.browser.test.util.TestCallbackHelperContainer; import org.chromium.content_public.browser.test.util.TestCallbackHelperContainer.OnEvaluateJavaScriptResultHelper; -import org.chromium.content_public.browser.test.util.TestCallbackHelperContainer.OnPageFinishedHelper; /** * Common functionality for testing the Java Bridge. */ @RunWith(ParameterizedRunner.class) @UseRunnerDelegate(BaseJUnit4RunnerDelegate.class) +@Batch(JavaBridgeActivityTestRule.BATCH) public class JavaBridgeBareboneTest { @Rule - public JavaBridgeActivityTestRule mActivityTestRule = - new JavaBridgeActivityTestRule().shouldSetUp(false); + public JavaBridgeActivityTestRule mActivityTestRule = new JavaBridgeActivityTestRule(); private TestCallbackHelperContainer mTestCallbackHelperContainer; private boolean mUseMojo; @@ -43,15 +41,6 @@ mActivityTestRule.setupMojoTest(useMojo); } - @Before - public void setUp() { - mActivityTestRule.launchContentShellWithUrl( - UrlUtils.encodeHtmlDataUri("<html><head></head><body>test</body></html>")); - mActivityTestRule.waitForActiveShellToBeDoneLoading(); - mTestCallbackHelperContainer = - new TestCallbackHelperContainer(mActivityTestRule.getWebContents()); - } - private void injectDummyObject(final String name) throws Throwable { mActivityTestRule.runOnUiThread(new Runnable() { @Override @@ -69,19 +58,6 @@ return javascriptHelper.getJsonResultAndClear(); } - private void reloadSync() throws Throwable { - OnPageFinishedHelper pageFinishedHelper = - mTestCallbackHelperContainer.getOnPageFinishedHelper(); - int currentCallCount = pageFinishedHelper.getCallCount(); - mActivityTestRule.runOnUiThread(new Runnable() { - @Override - public void run() { - mActivityTestRule.getWebContents().getNavigationController().reload(true); - } - }); - pageFinishedHelper.waitForCallback(currentCallCount); - } - // If inection happens before evaluating any JS code, then the first evaluation // triggers the same condition as page reload, which causes Java Bridge to add // a JS wrapper. @@ -121,7 +97,7 @@ @UseMethodParameter(JavaBridgeActivityTestRule.MojoTestParams.class) @DisabledTest(message = "Flaky - https://crbug.com/1117003") public void testImmediateAdditionAfterReload(boolean useMojo) throws Throwable { - reloadSync(); + mActivityTestRule.synchronousPageReload(); injectDummyObject("testObject"); Assert.assertEquals("\"object\"", evaluateJsSync("typeof testObject")); } @@ -132,7 +108,7 @@ @UseMethodParameter(JavaBridgeActivityTestRule.MojoTestParams.class) public void testReloadAfterAddition(boolean useMojo) throws Throwable { injectDummyObject("testObject"); - reloadSync(); + mActivityTestRule.synchronousPageReload(); Assert.assertEquals("\"object\"", evaluateJsSync("typeof testObject")); } }
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/JavaBridgeBasicsTest.java b/content/public/android/javatests/src/org/chromium/content/browser/JavaBridgeBasicsTest.java index a0e5ad47e..f031f11 100644 --- a/content/public/android/javatests/src/org/chromium/content/browser/JavaBridgeBasicsTest.java +++ b/content/public/android/javatests/src/org/chromium/content/browser/JavaBridgeBasicsTest.java
@@ -10,7 +10,6 @@ import androidx.test.filters.SmallTest; -import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Rule; @@ -51,11 +50,10 @@ */ @RunWith(ParameterizedRunner.class) @UseRunnerDelegate(ContentJUnit4RunnerDelegate.class) -@Batch(Batch.PER_CLASS) +@Batch(JavaBridgeActivityTestRule.BATCH) public class JavaBridgeBasicsTest { @Rule - public JavaBridgeActivityTestRule mActivityTestRule = - new JavaBridgeActivityTestRule().shouldSetUp(false); + public JavaBridgeActivityTestRule mActivityTestRule = new JavaBridgeActivityTestRule(); private static class TestController extends Controller { private int mIntValue; @@ -117,18 +115,10 @@ @Before public void setUp() { - mActivityTestRule.setUpContentView(); mTestController = new TestController(); mActivityTestRule.injectObjectAndReload(mTestController, "testController"); } - @After - public void tearDown() throws Exception { - // TODO(yfriedman): Instead of finishing the activity, re-use it and launch a new Shell to - // minimize overhead. - mActivityTestRule.getActivity().finish(); - } - // Note that this requires that we can pass a JavaScript string to Java. protected String executeJavaScriptAndGetStringResult(String script) throws Throwable { mActivityTestRule.executeJavaScript("testController.setStringValue(" + script + ");");
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/JavaBridgeChildFrameTest.java b/content/public/android/javatests/src/org/chromium/content/browser/JavaBridgeChildFrameTest.java index fd43eca..d1e4612 100644 --- a/content/public/android/javatests/src/org/chromium/content/browser/JavaBridgeChildFrameTest.java +++ b/content/public/android/javatests/src/org/chromium/content/browser/JavaBridgeChildFrameTest.java
@@ -18,6 +18,7 @@ import org.chromium.base.test.params.ParameterAnnotations.UseMethodParameterBefore; import org.chromium.base.test.params.ParameterAnnotations.UseRunnerDelegate; import org.chromium.base.test.params.ParameterizedRunner; +import org.chromium.base.test.util.Batch; import org.chromium.base.test.util.CommandLineFlags; import org.chromium.base.test.util.DisabledTest; import org.chromium.base.test.util.Feature; @@ -41,10 +42,10 @@ */ @RunWith(ParameterizedRunner.class) @UseRunnerDelegate(ContentJUnit4RunnerDelegate.class) +@Batch(JavaBridgeActivityTestRule.BATCH) public class JavaBridgeChildFrameTest { @Rule - public JavaBridgeActivityTestRule mActivityTestRule = - new JavaBridgeActivityTestRule().shouldSetUp(true); + public JavaBridgeActivityTestRule mActivityTestRule = new JavaBridgeActivityTestRule(); private static class TestController extends Controller { private String mStringValue;
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/JavaBridgeCoercionTest.java b/content/public/android/javatests/src/org/chromium/content/browser/JavaBridgeCoercionTest.java index 4c617c9..13fdaa3 100644 --- a/content/public/android/javatests/src/org/chromium/content/browser/JavaBridgeCoercionTest.java +++ b/content/public/android/javatests/src/org/chromium/content/browser/JavaBridgeCoercionTest.java
@@ -19,6 +19,7 @@ import org.chromium.base.test.params.ParameterAnnotations.UseMethodParameterBefore; import org.chromium.base.test.params.ParameterAnnotations.UseRunnerDelegate; import org.chromium.base.test.params.ParameterizedRunner; +import org.chromium.base.test.util.Batch; import org.chromium.base.test.util.Feature; import org.chromium.base.test.util.UrlUtils; import org.chromium.content.browser.JavaBridgeActivityTestRule.Controller; @@ -39,12 +40,12 @@ */ @RunWith(ParameterizedRunner.class) @UseRunnerDelegate(BaseJUnit4RunnerDelegate.class) +@Batch(JavaBridgeActivityTestRule.BATCH) public class JavaBridgeCoercionTest { private static final double ASSERTION_DELTA = 0; @Rule - public JavaBridgeActivityTestRule mActivityTestRule = - new JavaBridgeActivityTestRule().shouldSetUp(true); + public JavaBridgeActivityTestRule mActivityTestRule = new JavaBridgeActivityTestRule(); private static class TestObject extends Controller { private Object mObjectInstance;
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/JavaBridgeFieldsTest.java b/content/public/android/javatests/src/org/chromium/content/browser/JavaBridgeFieldsTest.java index b978ece..6a9fdfb 100644 --- a/content/public/android/javatests/src/org/chromium/content/browser/JavaBridgeFieldsTest.java +++ b/content/public/android/javatests/src/org/chromium/content/browser/JavaBridgeFieldsTest.java
@@ -17,6 +17,7 @@ import org.chromium.base.test.params.ParameterAnnotations.UseMethodParameterBefore; import org.chromium.base.test.params.ParameterAnnotations.UseRunnerDelegate; import org.chromium.base.test.params.ParameterizedRunner; +import org.chromium.base.test.util.Batch; import org.chromium.base.test.util.Feature; import org.chromium.content.browser.JavaBridgeActivityTestRule.Controller; @@ -26,10 +27,10 @@ */ @RunWith(ParameterizedRunner.class) @UseRunnerDelegate(BaseJUnit4RunnerDelegate.class) +@Batch(JavaBridgeActivityTestRule.BATCH) public class JavaBridgeFieldsTest { @Rule - public JavaBridgeActivityTestRule mActivityTestRule = - new JavaBridgeActivityTestRule().shouldSetUp(true); + public JavaBridgeActivityTestRule mActivityTestRule = new JavaBridgeActivityTestRule(); private static class TestObject extends Controller { private String mStringValue;
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/JavaBridgeReturnValuesTest.java b/content/public/android/javatests/src/org/chromium/content/browser/JavaBridgeReturnValuesTest.java index e0ab9f5..a5e30dee 100644 --- a/content/public/android/javatests/src/org/chromium/content/browser/JavaBridgeReturnValuesTest.java +++ b/content/public/android/javatests/src/org/chromium/content/browser/JavaBridgeReturnValuesTest.java
@@ -17,6 +17,7 @@ import org.chromium.base.test.params.ParameterAnnotations.UseMethodParameterBefore; import org.chromium.base.test.params.ParameterAnnotations.UseRunnerDelegate; import org.chromium.base.test.params.ParameterizedRunner; +import org.chromium.base.test.util.Batch; import org.chromium.base.test.util.Feature; import org.chromium.content.browser.JavaBridgeActivityTestRule.Controller; @@ -33,10 +34,10 @@ */ @RunWith(ParameterizedRunner.class) @UseRunnerDelegate(BaseJUnit4RunnerDelegate.class) +@Batch(JavaBridgeActivityTestRule.BATCH) public class JavaBridgeReturnValuesTest { @Rule - public JavaBridgeActivityTestRule mActivityTestRule = - new JavaBridgeActivityTestRule().shouldSetUp(true); + public JavaBridgeActivityTestRule mActivityTestRule = new JavaBridgeActivityTestRule(); // An instance of this class is injected into the page to test returning // Java values to JavaScript.
diff --git a/content/renderer/agent_scheduling_group.cc b/content/renderer/agent_scheduling_group.cc index 849b1bc..ec818b5 100644 --- a/content/renderer/agent_scheduling_group.cc +++ b/content/renderer/agent_scheduling_group.cc
@@ -5,8 +5,8 @@ #include "content/renderer/agent_scheduling_group.h" #include "base/feature_list.h" +#include "base/util/type_safety/pass_key.h" #include "content/public/common/content_features.h" -#include "content/public/renderer/render_thread.h" #include "content/renderer/render_thread_impl.h" namespace content { @@ -21,6 +21,8 @@ using ::mojo::Receiver; using ::mojo::Remote; +using PassKey = ::util::PassKey<AgentSchedulingGroup>; + namespace { RenderThreadImpl& ToImpl(RenderThread& render_thread) { DCHECK(RenderThreadImpl::current()); @@ -137,6 +139,32 @@ RenderThread::Get()->RemoveRoute(routing_id); } +void AgentSchedulingGroup::CreateView(mojom::CreateViewParamsPtr params) { + ToImpl(render_thread_).CreateView(std::move(params), PassKey()); +} + +void AgentSchedulingGroup::DestroyView(int32_t view_id) { + ToImpl(render_thread_).DestroyView(view_id, PassKey()); +} + +void AgentSchedulingGroup::CreateFrame(mojom::CreateFrameParamsPtr params) { + ToImpl(render_thread_).CreateFrame(std::move(params), PassKey()); +} + +void AgentSchedulingGroup::CreateFrameProxy( + int32_t routing_id, + int32_t render_view_routing_id, + const base::Optional<base::UnguessableToken>& opener_frame_token, + int32_t parent_routing_id, + const FrameReplicationState& replicated_state, + const base::UnguessableToken& frame_token, + const base::UnguessableToken& devtools_frame_token) { + ToImpl(render_thread_) + .CreateFrameProxy(routing_id, render_view_routing_id, opener_frame_token, + parent_routing_id, replicated_state, frame_token, + devtools_frame_token, PassKey()); +} + void AgentSchedulingGroup::GetRoute( int32_t routing_id, mojo::PendingAssociatedReceiver<blink::mojom::AssociatedInterfaceProvider>
diff --git a/content/renderer/agent_scheduling_group.h b/content/renderer/agent_scheduling_group.h index 4be0122e..658ef85dd 100644 --- a/content/renderer/agent_scheduling_group.h +++ b/content/renderer/agent_scheduling_group.h
@@ -104,6 +104,19 @@ remote_; }; + // mojom::AgentSchedulingGroup: + void CreateView(mojom::CreateViewParamsPtr params) override; + void DestroyView(int32_t view_id) override; + void CreateFrame(mojom::CreateFrameParamsPtr params) override; + void CreateFrameProxy( + int32_t routing_id, + int32_t render_view_routing_id, + const base::Optional<base::UnguessableToken>& opener_frame_token, + int32_t parent_routing_id, + const FrameReplicationState& replicated_state, + const base::UnguessableToken& frame_token, + const base::UnguessableToken& devtools_frame_token) override; + // mojom::RouteProvider void GetRoute( int32_t routing_id,
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc index c1e18ed..b2bd0e0e 100644 --- a/content/renderer/render_frame_impl.cc +++ b/content/renderer/render_frame_impl.cc
@@ -4973,6 +4973,10 @@ return web_media_stream_device_observer_.get(); } +bool RenderFrameImpl::AllowRTCLegacyTLSProtocols() { + return GetRendererPreferences().webrtc_allow_legacy_tls_protocols; +} + blink::WebEncryptedMediaClient* RenderFrameImpl::EncryptedMediaClient() { return media_factory_.EncryptedMediaClient(); }
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h index 1e22885..a880d8b 100644 --- a/content/renderer/render_frame_impl.h +++ b/content/renderer/render_frame_impl.h
@@ -707,6 +707,7 @@ int world_id) override; void DidChangeScrollOffset() override; blink::WebMediaStreamDeviceObserver* MediaStreamDeviceObserver() override; + bool AllowRTCLegacyTLSProtocols() override; blink::WebEncryptedMediaClient* EncryptedMediaClient() override; blink::WebString UserAgentOverride() override; base::Optional<blink::UserAgentMetadata> UserAgentMetadataOverride() override;
diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc index 0352f127..6e646c9 100644 --- a/content/renderer/render_thread_impl.cc +++ b/content/renderer/render_thread_impl.cc
@@ -158,8 +158,8 @@ #endif #if defined(OS_WIN) -#include <windows.h> #include <objbase.h> +#include <windows.h> #endif #ifdef ENABLE_VTUNE_JIT_INTERFACE @@ -181,20 +181,21 @@ #include "base/test/clang_profiling.h" #endif -using base::ThreadRestrictions; -using blink::WebDocument; -using blink::WebFrame; -using blink::WebNetworkStateNotifier; -using blink::WebRuntimeFeatures; -using blink::WebScriptController; -using blink::WebSecurityPolicy; -using blink::WebString; -using blink::WebView; - namespace content { namespace { +using ::base::ThreadRestrictions; +using ::blink::WebDocument; +using ::blink::WebFrame; +using ::blink::WebNetworkStateNotifier; +using ::blink::WebRuntimeFeatures; +using ::blink::WebScriptController; +using ::blink::WebSecurityPolicy; +using ::blink::WebString; +using ::blink::WebView; +using ::util::PassKey; + #if defined(OS_ANDROID) // Unique identifier for each output surface created. uint32_t g_next_layer_tree_frame_sink_id = 1; @@ -218,14 +219,19 @@ // v8::MemoryPressureLevel should correspond to base::MemoryPressureListener. static_assert(static_cast<v8::MemoryPressureLevel>( - base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE) == - v8::MemoryPressureLevel::kNone, "none level not align"); -static_assert(static_cast<v8::MemoryPressureLevel>( - base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE) == - v8::MemoryPressureLevel::kModerate, "moderate level not align"); -static_assert(static_cast<v8::MemoryPressureLevel>( - base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL) == - v8::MemoryPressureLevel::kCritical, "critical level not align"); + base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE) == + v8::MemoryPressureLevel::kNone, + "none level not align"); +static_assert( + static_cast<v8::MemoryPressureLevel>( + base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE) == + v8::MemoryPressureLevel::kModerate, + "moderate level not align"); +static_assert( + static_cast<v8::MemoryPressureLevel>( + base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL) == + v8::MemoryPressureLevel::kCritical, + "critical level not align"); // WebMemoryPressureLevel should correspond to base::MemoryPressureListener. static_assert(static_cast<blink::WebMemoryPressureLevel>( @@ -243,21 +249,20 @@ blink::kWebMemoryPressureLevelCritical, "blink::WebMemoryPressureLevelCritical not align"); -void* CreateHistogram( - const char *name, int min, int max, size_t buckets) { +void* CreateHistogram(const char* name, int min, int max, size_t buckets) { if (min <= 0) min = 1; std::string histogram_name; RenderThreadImpl* render_thread_impl = RenderThreadImpl::current(); if (render_thread_impl) { // Can be null in tests. - histogram_name = render_thread_impl-> - histogram_customizer()->ConvertToCustomHistogramName(name); + histogram_name = render_thread_impl->histogram_customizer() + ->ConvertToCustomHistogramName(name); } else { histogram_name = std::string(name); } - base::HistogramBase* histogram = base::Histogram::FactoryGet( - histogram_name, min, max, buckets, - base::Histogram::kUmaTargetedHistogramFlag); + base::HistogramBase* histogram = + base::Histogram::FactoryGet(histogram_name, min, max, buckets, + base::Histogram::kUmaTargetedHistogramFlag); return histogram; } @@ -390,7 +395,8 @@ RenderThreadImpl::HistogramCustomizer::~HistogramCustomizer() {} void RenderThreadImpl::HistogramCustomizer::RenderViewNavigatedToHost( - const std::string& host, size_t view_count) { + const std::string& host, + size_t view_count) { if (base::CommandLine::ForCurrentProcess()->HasSwitch( switches::kDisableHistogramCustomizer)) { return; @@ -1380,7 +1386,7 @@ // more informative stack, since we will otherwise just crash later when we // try to restart it. CHECK(!base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kSingleProcess)); + switches::kSingleProcess)); ChildThreadImpl::OnChannelError(); } @@ -1821,7 +1827,8 @@ return gpu_->GetGpuChannel().get(); } -void RenderThreadImpl::CreateView(mojom::CreateViewParamsPtr params) { +void RenderThreadImpl::CreateView(mojom::CreateViewParamsPtr params, + PassKey<AgentSchedulingGroup>) { CompositorDependencies* compositor_deps = this; is_scroll_animator_enabled_ = params->web_preferences.enable_scroll_animator; // TODO(crbug.com/1111231): For as long as views are created via the @@ -1836,7 +1843,8 @@ GetWebMainThreadScheduler()->DefaultTaskRunner()); } -void RenderThreadImpl::DestroyView(int32_t view_id) { +void RenderThreadImpl::DestroyView(int32_t view_id, + PassKey<AgentSchedulingGroup>) { RenderViewImpl* view = RenderViewImpl::FromRoutingID(view_id); DCHECK(view); @@ -1850,7 +1858,8 @@ base::BindOnce(&RenderViewImpl::Destroy, base::Unretained(view))); } -void RenderThreadImpl::CreateFrame(mojom::CreateFrameParamsPtr params) { +void RenderThreadImpl::CreateFrame(mojom::CreateFrameParamsPtr params, + PassKey<AgentSchedulingGroup>) { CompositorDependencies* compositor_deps = this; mojo::PendingRemote<service_manager::mojom::InterfaceProvider> interface_provider( @@ -1912,7 +1921,8 @@ int32_t parent_routing_id, const FrameReplicationState& replicated_state, const base::UnguessableToken& frame_token, - const base::UnguessableToken& devtools_frame_token) { + const base::UnguessableToken& devtools_frame_token, + PassKey<AgentSchedulingGroup>) { // TODO(crbug.com/1111231): For as long as frame proxies are created via the // `Renderer` interface (as opposed to `AgentSchedulingGroup`), we will always // have *exactly one* `AgentSchedulingGroup` in the process. @@ -2330,8 +2340,7 @@ // Called on the listener thread. void RenderThreadImpl::UnfreezableMessageFilter:: - RemoveListenerUnfreezableTaskRunner( - int32_t routing_id) { + RemoveListenerUnfreezableTaskRunner(int32_t routing_id) { base::AutoLock lock(unfreezable_task_runners_lock_); unfreezable_task_runners_.erase(routing_id); }
diff --git a/content/renderer/render_thread_impl.h b/content/renderer/render_thread_impl.h index 05bd7da62..b8ec7807 100644 --- a/content/renderer/render_thread_impl.h +++ b/content/renderer/render_thread_impl.h
@@ -27,6 +27,7 @@ #include "base/optional.h" #include "base/strings/string16.h" #include "base/time/time.h" +#include "base/util/type_safety/pass_key.h" #include "build/build_config.h" #include "cc/mojom/render_frame_metadata.mojom.h" #include "content/child/child_thread_impl.h" @@ -214,6 +215,22 @@ // viz::mojom::CompositingModeWatcher implementation. void CompositingModeFallbackToSoftware() override; + // Formerly in mojom::Renderer (moved to mojom::AgentSchedulingGroup): + void CreateView(mojom::CreateViewParamsPtr params, + util::PassKey<AgentSchedulingGroup>); + void DestroyView(int32_t view_id, util::PassKey<AgentSchedulingGroup>); + void CreateFrame(mojom::CreateFrameParamsPtr params, + util::PassKey<AgentSchedulingGroup>); + void CreateFrameProxy( + int32_t routing_id, + int32_t render_view_routing_id, + const base::Optional<base::UnguessableToken>& opener_frame_token, + int32_t parent_routing_id, + const FrameReplicationState& replicated_state, + const base::UnguessableToken& frame_token, + const base::UnguessableToken& devtools_frame_token, + util::PassKey<AgentSchedulingGroup>); + // Whether gpu compositing is being used or is disabled for software // compositing. Clients of the compositor should give resources that match // the appropriate mode. @@ -439,9 +456,6 @@ void OnGetAccessibilityTree(); // mojom::Renderer: - void CreateView(mojom::CreateViewParamsPtr params) override; - void DestroyView(int32_t view_id) override; - void CreateFrame(mojom::CreateFrameParamsPtr params) override; void CreateAgentSchedulingGroup( mojo::PendingRemote<mojom::AgentSchedulingGroupHost> agent_scheduling_group_host, @@ -452,14 +466,6 @@ agent_scheduling_group_host, mojo::PendingAssociatedReceiver<mojom::AgentSchedulingGroup> agent_scheduling_group) override; - void CreateFrameProxy( - int32_t routing_id, - int32_t render_view_routing_id, - const base::Optional<base::UnguessableToken>& opener_frame_token, - int32_t parent_routing_id, - const FrameReplicationState& replicated_state, - const base::UnguessableToken& frame_token, - const base::UnguessableToken& devtools_frame_token) override; void OnNetworkConnectionChanged( net::NetworkChangeNotifier::ConnectionType type, double max_bandwidth_mbps) override;
diff --git a/content/test/fuzzer/BUILD.gn b/content/test/fuzzer/BUILD.gn index 6a8f1117..a24d572d 100644 --- a/content/test/fuzzer/BUILD.gn +++ b/content/test/fuzzer/BUILD.gn
@@ -187,6 +187,24 @@ ] } +mojolpm_fuzzer_test("file_system_manager_mojolpm_fuzzer") { + sources = [ "file_system_manager_mojolpm_fuzzer.cc" ] + + proto_source = "file_system_manager_mojolpm_fuzzer.proto" + + deps = [ + "//base/test:test_support", + "//content/browser:for_content_tests", + "//content/public/browser:browser_sources", + "//content/test:test_support", + "//services/network:test_support", + "//storage/browser:test_support", + "//third_party/icu:icudata", + ] + + proto_deps = [ "//third_party/blink/public/mojom:mojom_platform_mojolpm" ] +} + fuzzer_test("speech_audio_encoder_fuzzer") { sources = [ "../../browser/speech/audio_buffer.cc",
diff --git a/content/test/fuzzer/file_system_manager_mojolpm_fuzzer.cc b/content/test/fuzzer/file_system_manager_mojolpm_fuzzer.cc new file mode 100644 index 0000000..6334f54 --- /dev/null +++ b/content/test/fuzzer/file_system_manager_mojolpm_fuzzer.cc
@@ -0,0 +1,418 @@ +// 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 <stdint.h> +#include <utility> + +#include "base/at_exit.h" +#include "base/base_switches.h" +#include "base/command_line.h" +#include "base/files/scoped_temp_dir.h" +#include "base/i18n/icu_util.h" +#include "base/task/post_task.h" +#include "base/test/scoped_feature_list.h" +#include "base/test/test_switches.h" +#include "base/test/test_timeouts.h" +#include "base/threading/platform_thread.h" +#include "base/threading/thread.h" +#include "content/browser/blob_storage/chrome_blob_storage_context.h" // nogncheck +#include "content/browser/file_system/file_system_manager_impl.h" // nogncheck +#include "content/browser/storage_partition_impl_map.h" // nogncheck +#include "content/public/browser/browser_task_traits.h" +#include "content/public/test/browser_task_environment.h" +#include "content/public/test/test_browser_context.h" +#include "content/public/test/test_content_client_initializer.h" +#include "content/test/fuzzer/file_system_manager_mojolpm_fuzzer.pb.h" +#include "mojo/core/embedder/embedder.h" +#include "storage/browser/quota/special_storage_policy.h" +#include "storage/browser/test/mock_special_storage_policy.h" +#include "storage/browser/test/test_file_system_context.h" +#include "third_party/blink/public/mojom/filesystem/file_system.mojom-mojolpm.h" +#include "third_party/libprotobuf-mutator/src/src/libfuzzer/libfuzzer_macro.h" +#include "url/origin.h" + +using url::Origin; + +namespace content { + +const size_t kNumRenderers = 2; +const char* cmdline[] = {"file_system_manager_mojolpm_fuzzer", nullptr}; + +// Global environment needed to run the interface being tested. +// +// This will be created once, before fuzzing starts, and will be shared between +// all testcases. It is created on the main thread. +// +// At a minimum, we should always be able to set up the command line, i18n and +// mojo, and create the thread on which the fuzzer will be run. We want to avoid +// (as much as is reasonable) any state being preserved between testcases. +// +// For FileSystemManager, we can also safely re-use a single +// BrowserTaskEnvironment and the TestContentClientInitializer between +// testcases. We try to create an environment that matches the real browser +// process as much as possible, so we use real platform threads in the task +// environment. +class ContentFuzzerEnvironment { + public: + ContentFuzzerEnvironment() + : fuzzer_thread_("fuzzer_thread"), + task_environment_( + (base::CommandLine::Init(1, cmdline), + TestTimeouts::Initialize(), + base::test::TaskEnvironment::MainThreadType::DEFAULT), + base::test::TaskEnvironment::ThreadPoolExecutionMode::ASYNC, + base::test::TaskEnvironment::ThreadingMode::MULTIPLE_THREADS, + content::BrowserTaskEnvironment::REAL_IO_THREAD) { + logging::SetMinLogLevel(logging::LOG_FATAL); + mojo::core::Init(); + base::i18n::InitializeICU(); + fuzzer_thread_.StartAndWaitForTesting(); + } + + scoped_refptr<base::SequencedTaskRunner> fuzzer_task_runner() { + return fuzzer_thread_.task_runner(); + } + + private: + base::AtExitManager at_exit_manager_; + base::Thread fuzzer_thread_; + content::BrowserTaskEnvironment task_environment_; + content::TestContentClientInitializer content_client_initializer_; +}; + +ContentFuzzerEnvironment& GetEnvironment() { + static base::NoDestructor<ContentFuzzerEnvironment> environment; + return *environment; +} + +scoped_refptr<base::SequencedTaskRunner> GetFuzzerTaskRunner() { + return GetEnvironment().fuzzer_task_runner(); +} + +// Per-testcase state needed to run the interface being tested. +// +// The lifetime of this is scoped to a single testcase, and it is created and +// destroyed from the fuzzer sequence. +// +// For FileSystemManager, this needs the basic common Browser process state +// provided by TestBrowserContext, and to set up the storage contexts that will +// be used. The filesystem APIs also depend on the Blob subsystem, so in +// addition to the FileSystemContext we also need a BlobStorageContext. +// +// Since the Browser process will host one FileSystemManagerImpl per +// RenderProcessHost, we emulate this by allowing the fuzzer to create (and +// destroy) multiple FileSystemManagerImpl instances. +class FileSystemManagerTestcase { + public: + explicit FileSystemManagerTestcase( + const content::fuzzing::file_system_manager::proto::Testcase& testcase); + + // Returns true once either all of the actions in the testcase have been + // performed, or the per-testcase action limit has been exceeded. + // + // This should only be called from the fuzzer sequence. + bool IsFinished(); + + // If there are still actions remaining in the testcase, this will perform the + // next sequence of actions before returning. + // + // If IsFinished() would return true, then calling this function is a no-op. + // + // This should only be called from the fuzzer sequence. + void NextAction(); + + void SetUp(); + void TearDown(); + + private: + using Action = content::fuzzing::file_system_manager::proto::Action; + + void SetUpOnIOThread(); + void SetUpOnUIThread(); + void TearDownOnIOThread(); + void TearDownOnUIThread(); + + // Used by AddFileSystemManager to create and bind FileSystemManagerImpl on the + // UI thread. + void AddFileSystemManagerImpl( + uint32_t id, + content::fuzzing::file_system_manager::proto::NewFileSystemManagerAction:: + RenderProcessId render_process_id, + mojo::PendingReceiver<::blink::mojom::FileSystemManager>&& receiver); + + // Create and bind a new instance for fuzzing. This needs to make sure that + // the new instance has been created and bound on the correct sequence before + // returning. + void AddFileSystemManager( + uint32_t id, + content::fuzzing::file_system_manager::proto::NewFileSystemManagerAction:: + RenderProcessId render_process_id); + + // The proto message describing the test actions to perform. + const content::fuzzing::file_system_manager::proto::Testcase& testcase_; + + // Apply a reasonable upper-bound on testcase complexity to avoid timeouts. + const int max_action_count_ = 512; + + // Count of total actions performed in this testcase. + int action_count_ = 0; + + // The index of the next sequence of actions to execute. + int next_sequence_idx_ = 0; + + // Prerequisite state + TestBrowserContext browser_context_; + base::ScopedTempDir temp_dir_; + scoped_refptr<storage::FileSystemContext> file_system_context_; + scoped_refptr<ChromeBlobStorageContext> blob_storage_context_; + + // Mapping from renderer id to FileSystemManagerImpl instances being fuzzed. + // Access only from UI thread. + std::unique_ptr<FileSystemManagerImpl> + file_system_manager_impls_[kNumRenderers]; + + SEQUENCE_CHECKER(sequence_checker_); +}; + +FileSystemManagerTestcase::FileSystemManagerTestcase( + const content::fuzzing::file_system_manager::proto::Testcase& testcase) + : testcase_(testcase), browser_context_() { + // FileSystemManagerTestcase is created on the main thread, but the actions + // that we want to validate the sequencing of take place on the fuzzer + // sequence. + DETACH_FROM_SEQUENCE(sequence_checker_); +} + +void FileSystemManagerTestcase::SetUp() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + base::RunLoop io_run_loop(base::RunLoop::Type::kNestableTasksAllowed); + base::PostTaskAndReply( + FROM_HERE, {BrowserThread::IO}, + base::BindOnce(&FileSystemManagerTestcase::SetUpOnIOThread, + base::Unretained(this)), + io_run_loop.QuitClosure()); + io_run_loop.Run(); + + base::RunLoop ui_run_loop(base::RunLoop::Type::kNestableTasksAllowed); + base::PostTaskAndReply( + FROM_HERE, {BrowserThread::UI}, + base::BindOnce(&FileSystemManagerTestcase::SetUpOnUIThread, + base::Unretained(this)), + ui_run_loop.QuitClosure()); + ui_run_loop.Run(); +} + +void FileSystemManagerTestcase::SetUpOnIOThread() { + CHECK(temp_dir_.CreateUniqueTempDir()); + file_system_context_ = + storage::CreateFileSystemContextForTesting(nullptr, temp_dir_.GetPath()); + + blob_storage_context_ = base::MakeRefCounted<ChromeBlobStorageContext>(); + blob_storage_context_->InitializeOnIOThread( + temp_dir_.GetPath(), temp_dir_.GetPath(), + base::CreateSingleThreadTaskRunner({BrowserThread::IO})); +} + +void FileSystemManagerTestcase::SetUpOnUIThread() { + ChildProcessSecurityPolicyImpl* p = + ChildProcessSecurityPolicyImpl::GetInstance(); + p->RegisterFileSystemPermissionPolicy(storage::kFileSystemTypeTest, + storage::FILE_PERMISSION_SANDBOX); + p->RegisterFileSystemPermissionPolicy(storage::kFileSystemTypeTemporary, + storage::FILE_PERMISSION_SANDBOX); + + // Note - FileSystemManagerImpl must be constructed on the UI thread, but all + // other methods are expected to be called on the IO thread - see comments in + // content/browser/file_system/file_system_manager_impl.h + for (size_t i = 0; i < kNumRenderers; i++) { + file_system_manager_impls_[i] = std::make_unique<FileSystemManagerImpl>( + i, file_system_context_, blob_storage_context_); + p->Add(i, &browser_context_); + } +} + +void FileSystemManagerTestcase::TearDown() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + base::RunLoop ui_run_loop(base::RunLoop::Type::kNestableTasksAllowed); + base::PostTaskAndReply( + FROM_HERE, {content::BrowserThread::UI}, + base::BindOnce(&FileSystemManagerTestcase::TearDownOnUIThread, + base::Unretained(this)), + ui_run_loop.QuitClosure()); + ui_run_loop.Run(); + + base::RunLoop io_run_loop(base::RunLoop::Type::kNestableTasksAllowed); + base::PostTaskAndReply( + FROM_HERE, {content::BrowserThread::IO}, + base::BindOnce(&FileSystemManagerTestcase::TearDownOnIOThread, + base::Unretained(this)), + io_run_loop.QuitClosure()); + io_run_loop.Run(); +} + +void FileSystemManagerTestcase::TearDownOnIOThread() { + for (size_t i = 0; i < kNumRenderers; i++) { + file_system_manager_impls_[i].reset(); + } +} + +void FileSystemManagerTestcase::TearDownOnUIThread() { + ChildProcessSecurityPolicyImpl* p = + ChildProcessSecurityPolicyImpl::GetInstance(); + for (size_t i = 0; i < kNumRenderers; i++) { + p->Remove(i); + } +} + +bool FileSystemManagerTestcase::IsFinished() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + return next_sequence_idx_ >= testcase_.sequence_indexes_size(); +} + +void FileSystemManagerTestcase::NextAction() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + if (next_sequence_idx_ < testcase_.sequence_indexes_size()) { + auto sequence_idx = testcase_.sequence_indexes(next_sequence_idx_++); + const auto& sequence = + testcase_.sequences(sequence_idx % testcase_.sequences_size()); + for (auto action_idx : sequence.action_indexes()) { + if (!testcase_.actions_size() || ++action_count_ > max_action_count_) { + return; + } + const auto& action = + testcase_.actions(action_idx % testcase_.actions_size()); + switch (action.action_case()) { + case Action::kNewFileSystemManager: + AddFileSystemManager( + action.new_file_system_manager().id(), + action.new_file_system_manager().render_process_id()); + break; + + case Action::kRunThread: + if (action.run_thread().id()) { + base::RunLoop run_loop(base::RunLoop::Type::kNestableTasksAllowed); + base::PostTask(FROM_HERE, {BrowserThread::UI}, + run_loop.QuitClosure()); + run_loop.Run(); + } else { + base::RunLoop run_loop(base::RunLoop::Type::kNestableTasksAllowed); + base::PostTask(FROM_HERE, {BrowserThread::IO}, + run_loop.QuitClosure()); + run_loop.Run(); + } + break; + + case Action::kFileSystemManagerRemoteAction: + mojolpm::HandleRemoteAction( + action.file_system_manager_remote_action()); + break; + + case Action::kFileSystemCancellableOperationRemoteAction: + mojolpm::HandleRemoteAction( + action.file_system_cancellable_operation_remote_action()); + break; + + case Action::ACTION_NOT_SET: + break; + } + } + } +} + +void FileSystemManagerTestcase::AddFileSystemManagerImpl( + uint32_t id, + content::fuzzing::file_system_manager::proto::NewFileSystemManagerAction:: + RenderProcessId render_process_id, + mojo::PendingReceiver<::blink::mojom::FileSystemManager>&& receiver) { + size_t offset = render_process_id == + content::fuzzing::file_system_manager::proto:: + NewFileSystemManagerAction_RenderProcessId_ZERO + ? 0 + : 1; + file_system_manager_impls_[offset]->BindReceiver(std::move(receiver)); +} + +void FileSystemManagerTestcase::AddFileSystemManager( + uint32_t id, + content::fuzzing::file_system_manager::proto::NewFileSystemManagerAction:: + RenderProcessId render_process_id) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + mojo::Remote<::blink::mojom::FileSystemManager> remote; + auto receiver = remote.BindNewPipeAndPassReceiver(); + + base::RunLoop run_loop(base::RunLoop::Type::kNestableTasksAllowed); + base::PostTaskAndReply( + FROM_HERE, {content::BrowserThread::IO}, + base::BindOnce(&FileSystemManagerTestcase::AddFileSystemManagerImpl, + base::Unretained(this), id, render_process_id, + std::move(receiver)), + run_loop.QuitClosure()); + run_loop.Run(); + + mojolpm::GetContext()->AddInstance(id, std::move(remote)); +} +} // namespace content + +// Helper function to keep scheduling fuzzer actions on the current runloop +// until the testcase has completed, and then quit the runloop. +void NextAction(content::FileSystemManagerTestcase* testcase, + base::RepeatingClosure quit_closure) { + if (!testcase->IsFinished()) { + testcase->NextAction(); + content::GetFuzzerTaskRunner()->PostTask( + FROM_HERE, base::BindOnce(NextAction, base::Unretained(testcase), + std::move(quit_closure))); + } else { + content::GetFuzzerTaskRunner()->PostTask(FROM_HERE, + std::move(quit_closure)); + } +} + +// Helper function to setup and run the testcase, since we need to do that from +// the fuzzer sequence rather than the main thread. +void RunTestcase(content::FileSystemManagerTestcase* testcase) { + mojo::Message message; + auto dispatch_context = + std::make_unique<mojo::internal::MessageDispatchContext>(&message); + + testcase->SetUp(); + + mojolpm::GetContext()->StartTestcase(); + + base::RunLoop fuzzer_run_loop(base::RunLoop::Type::kNestableTasksAllowed); + content::GetFuzzerTaskRunner()->PostTask( + FROM_HERE, base::BindOnce(NextAction, base::Unretained(testcase), + fuzzer_run_loop.QuitClosure())); + fuzzer_run_loop.Run(); + + mojolpm::GetContext()->EndTestcase(); + + testcase->TearDown(); +} + +DEFINE_BINARY_PROTO_FUZZER( + const content::fuzzing::file_system_manager::proto::Testcase& + proto_testcase) { + if (!proto_testcase.actions_size() || !proto_testcase.sequences_size() || + !proto_testcase.sequence_indexes_size()) { + return; + } + + // Make sure that the environment is initialized before we do anything else. + content::GetEnvironment(); + + content::FileSystemManagerTestcase testcase(proto_testcase); + + base::RunLoop ui_run_loop(base::RunLoop::Type::kNestableTasksAllowed); + + // Unretained is safe here, because ui_run_loop has to finish before testcase + // goes out of scope. + content::GetFuzzerTaskRunner()->PostTaskAndReply( + FROM_HERE, base::BindOnce(RunTestcase, base::Unretained(&testcase)), + ui_run_loop.QuitClosure()); + + ui_run_loop.Run(); +}
diff --git a/content/test/fuzzer/file_system_manager_mojolpm_fuzzer.proto b/content/test/fuzzer/file_system_manager_mojolpm_fuzzer.proto new file mode 100644 index 0000000..ce269768 --- /dev/null +++ b/content/test/fuzzer/file_system_manager_mojolpm_fuzzer.proto
@@ -0,0 +1,59 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Message format for the MojoLPM fuzzer for the FileSystemManager interface. + +syntax = "proto2"; + +package content.fuzzing.file_system_manager.proto; + +import "third_party/blink/public/mojom/filesystem/file_system.mojom.mojolpm.proto"; + +// Bind a new FileSystemManager remote +message NewFileSystemManagerAction { + enum RenderProcessId { + ZERO = 0; + ONE = 1; + } + + required uint32 id = 1; + required RenderProcessId render_process_id = 2; +} + +// Run the specific sequence for (an indeterminate) period. This is not +// intended to create a specific ordering, but to allow the fuzzer to delay a +// later task until previous tasks have completed. +message RunThreadAction { + enum ThreadId { + IO = 0; + UI = 1; + } + + required ThreadId id = 1; +} + +// Actions that can be performed by the fuzzer. +message Action { + oneof action { + NewFileSystemManagerAction new_file_system_manager = 1; + RunThreadAction run_thread = 2; + mojolpm.blink.mojom.FileSystemManager.RemoteAction + file_system_manager_remote_action = 3; + mojolpm.blink.mojom.FileSystemCancellableOperation.RemoteAction + file_system_cancellable_operation_remote_action = 4; + } +} + +// Sequence provides a level of indirection which allows Testcase to compactly +// express repeated sequences of actions. +message Sequence { + repeated uint32 action_indexes = 1 [packed = true]; +} + +// Testcase is the top-level message type interpreted by the fuzzer. +message Testcase { + repeated Action actions = 1; + repeated Sequence sequences = 2; + repeated uint32 sequence_indexes = 3 [packed = true]; +} \ No newline at end of file
diff --git a/content/test/gpu/gpu_tests/test_expectations/screenshot_sync_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/screenshot_sync_expectations.txt index f1ac381..9909a20 100644 --- a/content/test/gpu/gpu_tests/test_expectations/screenshot_sync_expectations.txt +++ b/content/test/gpu/gpu_tests/test_expectations/screenshot_sync_expectations.txt
@@ -22,7 +22,3 @@ crbug.com/1006045 [ android android-nexus-5x skia-renderer ] ScreenshotSync_GPURasterWithDivs [ Failure ] crbug.com/1006045 [ android android-nexus-5x skia-renderer ] ScreenshotSync_SWRasterWithCanvas [ Failure ] crbug.com/1006045 [ android android-nexus-5x skia-renderer ] ScreenshotSync_SWRasterWithDivs [ Failure ] - -# Fuchsia -crbug.com/1097962 [ fuchsia ] ScreenshotSync_SWRasterWithCanvas [ RetryOnFailure ] -crbug.com/1097962 [ fuchsia ] ScreenshotSync_GPURasterWithCanvas [ RetryOnFailure ]
diff --git a/device/gamepad/gamepad_provider.cc b/device/gamepad/gamepad_provider.cc index 89439c77..ecc5837 100644 --- a/device/gamepad/gamepad_provider.cc +++ b/device/gamepad/gamepad_provider.cc
@@ -29,6 +29,8 @@ namespace device { +constexpr int64_t kPollingIntervalMilliseconds = 4; // ~250 Hz + GamepadProvider::GamepadProvider( GamepadConnectionChangeClient* connection_change_client) : gamepad_shared_buffer_(std::make_unique<GamepadSharedBuffer>()), @@ -139,7 +141,7 @@ void GamepadProvider::Initialize(std::unique_ptr<GamepadDataFetcher> fetcher) { sampling_interval_delta_ = - base::TimeDelta::FromMilliseconds(features::GetGamepadPollingInterval()); + base::TimeDelta::FromMilliseconds(kPollingIntervalMilliseconds); base::SystemMonitor* monitor = base::SystemMonitor::Get(); if (monitor)
diff --git a/device/gamepad/public/cpp/gamepad_features.cc b/device/gamepad/public/cpp/gamepad_features.cc index c74ddbb2..d942501 100644 --- a/device/gamepad/public/cpp/gamepad_features.cc +++ b/device/gamepad/public/cpp/gamepad_features.cc
@@ -15,24 +15,6 @@ namespace features { -namespace { - -const size_t kPollingIntervalMillisecondsMin = 4; // ~250 Hz -const size_t kPollingIntervalMillisecondsMax = 16; // ~62.5 Hz - -size_t OverrideIntervalIfValid(base::StringPiece param_value, - size_t default_interval) { - size_t interval; - if (param_value.empty() || !base::StringToSizeT(param_value, &interval)) - return default_interval; - // Clamp interval duration to valid range. - interval = std::max(interval, kPollingIntervalMillisecondsMin); - interval = std::min(interval, kPollingIntervalMillisecondsMax); - return interval; -} - -} // namespace - // Enables gamepadbuttondown, gamepadbuttonup, gamepadbuttonchange, // gamepadaxismove non-standard gamepad events. const base::Feature kEnableGamepadButtonAxisEvents{ @@ -42,15 +24,9 @@ const base::Feature kEnableWindowsGamingInputDataFetcher{ "EnableWindowsGamingInputDataFetcher", base::FEATURE_DISABLED_BY_DEFAULT}; -// Overrides the gamepad polling interval. -const base::Feature kGamepadPollingInterval{"GamepadPollingInterval", - base::FEATURE_DISABLED_BY_DEFAULT}; - const base::Feature kRestrictGamepadAccess{"RestrictGamepadAccess", base::FEATURE_DISABLED_BY_DEFAULT}; -const char kGamepadPollingIntervalParamKey[] = "interval-ms"; - bool AreGamepadButtonAxisEventsEnabled() { // Check if button and axis events are enabled by a field trial. if (base::FeatureList::IsEnabled(kEnableGamepadButtonAxisEvents)) @@ -66,27 +42,4 @@ return false; } -size_t GetGamepadPollingInterval() { - // Default to the minimum polling interval. - size_t polling_interval = kPollingIntervalMillisecondsMin; - - // Check if the polling interval is overridden by a field trial. - if (base::FeatureList::IsEnabled(kGamepadPollingInterval)) { - std::string param_value = base::GetFieldTrialParamValueByFeature( - kGamepadPollingInterval, kGamepadPollingIntervalParamKey); - polling_interval = OverrideIntervalIfValid(param_value, polling_interval); - } - - // Check if the polling interval is overridden by a command-line flag. - base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); - if (command_line && - command_line->HasSwitch(switches::kGamepadPollingInterval)) { - std::string switch_value = - command_line->GetSwitchValueASCII(switches::kGamepadPollingInterval); - polling_interval = OverrideIntervalIfValid(switch_value, polling_interval); - } - - return polling_interval; -} - } // namespace features
diff --git a/device/gamepad/public/cpp/gamepad_features.h b/device/gamepad/public/cpp/gamepad_features.h index d5fc29c7..12e8576 100644 --- a/device/gamepad/public/cpp/gamepad_features.h +++ b/device/gamepad/public/cpp/gamepad_features.h
@@ -14,12 +14,9 @@ kEnableGamepadButtonAxisEvents; GAMEPAD_FEATURES_EXPORT extern const base::Feature kEnableWindowsGamingInputDataFetcher; -GAMEPAD_FEATURES_EXPORT extern const base::Feature kGamepadPollingInterval; GAMEPAD_FEATURES_EXPORT extern const base::Feature kRestrictGamepadAccess; -GAMEPAD_FEATURES_EXPORT extern const char kGamepadPollingIntervalParamKey[]; GAMEPAD_FEATURES_EXPORT bool AreGamepadButtonAxisEventsEnabled(); -GAMEPAD_FEATURES_EXPORT size_t GetGamepadPollingInterval(); } // namespace features
diff --git a/docs/memory/debugging_memory_issues.md b/docs/memory/debugging_memory_issues.md index 892abe7..db23edd 100644 --- a/docs/memory/debugging_memory_issues.md +++ b/docs/memory/debugging_memory_issues.md
@@ -78,7 +78,7 @@ This interface surfaces all available information, but can be overwhelming and is usually unnecessary for investigating heap dumps. * Important note: Heap profiling in the field uses - [poison process sampling](https://bugs.chromium.org/p/chromium/issues/detail?id=810748) + [Poisson process sampling](https://bugs.chromium.org/p/chromium/issues/detail?id=810748) with a rate parameter of 10000. This means that for large/frequent allocations [e.g. >100 MB], the noise will be quite small [much less than 1%]. But there is noise so counts will not be exact.
diff --git a/docs/no_sources_assignment_filter.md b/docs/no_sources_assignment_filter.md index 7b9087b..428cc9c2 100644 --- a/docs/no_sources_assignment_filter.md +++ b/docs/no_sources_assignment_filter.md
@@ -10,8 +10,9 @@ that will be used to filter names every time a variable named "sources" is assigned a value. -As Chromium calls this function in build/BUILDCONFIG.gn, the patterns are -applied to every BUILD.gn file in the project. This has multiple drawbacks: +Historically, Chromium used to call this function in build/BUILDCONFIG.gn thus +causing the patterns to be applied to every BUILD.gn file in the project. This +had multiple drawbacks: 1. the configuration of the list of patterns is located far from the point where they are applied and developer are usually confused when a file @@ -26,6 +27,9 @@ in the whole project, thus it has significant negative impact on the performance of gn +Since September 2020, the filter is enabled only for the files that have not +yet been converted. Eventually, this will be removed. + ## Conversion pattern To convert a BUILD.gn file it is necessary to change the following: @@ -70,19 +74,14 @@ it is compatible whether the set_sources_assignment_filter feature is used or not. -## Preventing regression - -As said above, while the converted file are compatible with the feature, there -is a risk of regression. To prevent such regression, the following is added at -the top of every BUILD.gn file after it has been converted: +Once conversion is done, remove the following lines from the top of the file +to avoid regressions: ``` - # Reset sources_assignment_filter for the BUILD.gn file to prevent - # regression during the migration of Chromium away from the feature. - # See docs/no_sources_assignment_filter.md for more information. - # TODO(crbug.com/1018739): remove this when migration is done. - set_sources_assignment_filter([]) +import("//build/config/deprecated_default_sources_assignment_filter.gni") +sources_assignment_filter = deprecated_default_sources_assignment_filter ``` + [0]: https://groups.google.com/a/chromium.org/d/topic/chromium-dev/hyLuCU6g2V4/discussion [1]: https://groups.google.com/a/chromium.org/d/topic/gn-dev/oQcYStl_WkI/discussion
diff --git a/extensions/common/api/_api_features.json b/extensions/common/api/_api_features.json index c73061c8..6c6480d 100644 --- a/extensions/common/api/_api_features.json +++ b/extensions/common/api/_api_features.json
@@ -231,7 +231,8 @@ "chrome://hats/*", "chrome://mobilesetup/*", "chrome://oobe/*", - "chrome://password-change/*" + "chrome://password-change/*", + "chrome://lock-reauth/*" ] } ], @@ -652,7 +653,8 @@ "chrome://home/*", "chrome://mobilesetup/*", "chrome://oobe/*", - "chrome://password-change/*" + "chrome://password-change/*", + "chrome://lock-reauth/*" ] }], "webViewInternal": [{ @@ -673,7 +675,8 @@ "chrome://home/*", "chrome://mobilesetup/*", "chrome://oobe/*", - "chrome://password-change/*" + "chrome://password-change/*", + "chrome://lock-reauth/*" ] }], "webViewRequest": [{
diff --git a/extensions/renderer/api/automation/automation_ax_tree_wrapper.cc b/extensions/renderer/api/automation/automation_ax_tree_wrapper.cc index 1fffef3..39cc85a 100644 --- a/extensions/renderer/api/automation/automation_ax_tree_wrapper.cc +++ b/extensions/renderer/api/automation/automation_ax_tree_wrapper.cc
@@ -280,7 +280,7 @@ bool root_changed, const std::vector<ui::AXTreeObserver::Change>& changes) { DCHECK_EQ(&tree_, tree); - for (const auto change : changes) { + for (const auto& change : changes) { ui::AXNode* node = change.node; switch (change.type) { case NODE_CREATED:
diff --git a/gpu/command_buffer/service/external_vk_image_backing.cc b/gpu/command_buffer/service/external_vk_image_backing.cc index 6ac0998..48bb0d8 100644 --- a/gpu/command_buffer/service/external_vk_image_backing.cc +++ b/gpu/command_buffer/service/external_vk_image_backing.cc
@@ -166,7 +166,7 @@ // static std::unique_ptr<ExternalVkImageBacking> ExternalVkImageBacking::Create( - SharedContextState* context_state, + scoped_refptr<SharedContextState> context_state, VulkanCommandPool* command_pool, const Mailbox& mailbox, viz::ResourceFormat format, @@ -206,7 +206,7 @@ // Must request all available image usage flags if aliasing GL texture. This // is a spec requirement per EXT_memory_object. However, if // ANGLE_memory_object_flags is supported, usage flags can be arbitrary. - if (UseMinimalUsageFlags(context_state)) { + if (UseMinimalUsageFlags(context_state.get())) { // The following additional usage flags are provided for ANGLE: // // - TRANSFER_SRC: Used for copies from this image. @@ -247,10 +247,11 @@ if (!image) return nullptr; - bool use_separate_gl_texture = UseSeparateGLTexture(context_state, format); + bool use_separate_gl_texture = + UseSeparateGLTexture(context_state.get(), format); auto backing = std::make_unique<ExternalVkImageBacking>( util::PassKey<ExternalVkImageBacking>(), mailbox, format, size, - color_space, surface_origin, alpha_type, usage, context_state, + color_space, surface_origin, alpha_type, usage, std::move(context_state), std::move(image), command_pool, use_separate_gl_texture); if (!pixel_data.empty()) { @@ -263,7 +264,7 @@ // static std::unique_ptr<ExternalVkImageBacking> ExternalVkImageBacking::CreateFromGMB( - SharedContextState* context_state, + scoped_refptr<SharedContextState> context_state, VulkanCommandPool* command_pool, const Mailbox& mailbox, gfx::GpuMemoryBufferHandle handle, @@ -293,11 +294,12 @@ } bool use_separate_gl_texture = - UseSeparateGLTexture(context_state, resource_format); + UseSeparateGLTexture(context_state.get(), resource_format); auto backing = std::make_unique<ExternalVkImageBacking>( util::PassKey<ExternalVkImageBacking>(), mailbox, resource_format, size, - color_space, surface_origin, alpha_type, usage, context_state, - std::move(image), command_pool, use_separate_gl_texture); + color_space, surface_origin, alpha_type, usage, + std::move(context_state), std::move(image), command_pool, + use_separate_gl_texture); backing->SetCleared(); return backing; } @@ -313,10 +315,10 @@ if (!shared_memory_wrapper.Initialize(handle, size, resource_format)) return nullptr; - auto backing = - Create(context_state, command_pool, mailbox, resource_format, size, - color_space, surface_origin, alpha_type, usage, image_usage_cache, - base::span<const uint8_t>(), true /* using_gmb */); + auto backing = Create(std::move(context_state), command_pool, mailbox, + resource_format, size, color_space, surface_origin, + alpha_type, usage, image_usage_cache, + base::span<const uint8_t>(), true /* using_gmb */); if (!backing) return nullptr; @@ -333,7 +335,7 @@ GrSurfaceOrigin surface_origin, SkAlphaType alpha_type, uint32_t usage, - SharedContextState* context_state, + scoped_refptr<SharedContextState> context_state, std::unique_ptr<VulkanImage> image, VulkanCommandPool* command_pool, bool use_separate_gl_texture) @@ -346,7 +348,7 @@ usage, image->device_size(), false /* is_thread_safe */), - context_state_(context_state), + context_state_(std::move(context_state)), image_(std::move(image)), backend_texture_(size.width(), size.height(), @@ -554,10 +556,8 @@ // signalling but have not been signalled. In that case, we have to release // them via fence helper to make sure all submitted GPU works is finished // before releasing them. - // |context_state_| is out live fence_helper, so it is safe to use - // base::Unretained(context_state_). fence_helper()->EnqueueCleanupTaskForSubmittedWork(base::BindOnce( - [](SharedContextState* shared_context_state, + [](scoped_refptr<SharedContextState> shared_context_state, std::vector<ExternalSemaphore>, VulkanDeviceQueue* device_queue, bool device_lost) { if (!gl::GLContext::GetCurrent()) { @@ -565,7 +565,7 @@ /*needs_gl=*/true); } }, - base::Unretained(context_state_), std::move(semaphores))); + context_state_, std::move(semaphores))); } } @@ -662,7 +662,7 @@ // If ANGLE_memory_object_flags is supported, use that to communicate the // exact create and usage flags the image was created with. DCHECK(image_->usage() != 0); - if (UseMinimalUsageFlags(context_state_)) { + if (UseMinimalUsageFlags(context_state())) { api->glTexStorageMemFlags2DANGLEFn( GL_TEXTURE_2D, 1, internal_format, size().width(), size().height(), memory_object->id(), 0, image_->flags(), image_->usage()); @@ -749,7 +749,7 @@ scoped_refptr<SharedContextState> context_state) { // This backing type is only used when vulkan is enabled, so SkiaRenderer // should also be using Vulkan. - DCHECK_EQ(context_state_, context_state.get()); + DCHECK_EQ(context_state_, context_state); DCHECK(context_state->GrContextIsVulkan()); return std::make_unique<ExternalVkImageSkiaRepresentation>(manager, this, tracker);
diff --git a/gpu/command_buffer/service/external_vk_image_backing.h b/gpu/command_buffer/service/external_vk_image_backing.h index 4d4523a..27397700 100644 --- a/gpu/command_buffer/service/external_vk_image_backing.h +++ b/gpu/command_buffer/service/external_vk_image_backing.h
@@ -34,7 +34,7 @@ class ExternalVkImageBacking final : public ClearTrackingSharedImageBacking { public: static std::unique_ptr<ExternalVkImageBacking> Create( - SharedContextState* context_state, + scoped_refptr<SharedContextState> context_state, VulkanCommandPool* command_pool, const Mailbox& mailbox, viz::ResourceFormat format, @@ -48,7 +48,7 @@ bool using_gmb = false); static std::unique_ptr<ExternalVkImageBacking> CreateFromGMB( - SharedContextState* context_state, + scoped_refptr<SharedContextState> context_state, VulkanCommandPool* command_pool, const Mailbox& mailbox, gfx::GpuMemoryBufferHandle handle, @@ -68,14 +68,14 @@ GrSurfaceOrigin surface_origin, SkAlphaType alpha_type, uint32_t usage, - SharedContextState* context_state, + scoped_refptr<SharedContextState> context_state, std::unique_ptr<VulkanImage> image, VulkanCommandPool* command_pool, bool use_separate_gl_texture); ~ExternalVkImageBacking() override; - SharedContextState* context_state() const { return context_state_; } + SharedContextState* context_state() const { return context_state_.get(); } const GrBackendTexture& backend_texture() const { return backend_texture_; } VulkanImage* image() const { return image_.get(); } const scoped_refptr<gles2::TexturePassthrough>& GetTexturePassthrough() @@ -178,7 +178,7 @@ void CopyPixelsFromGLTextureToVkImage(); void CopyPixelsFromShmToGLTexture(); - SharedContextState* const context_state_; + scoped_refptr<SharedContextState> context_state_; std::unique_ptr<VulkanImage> image_; GrBackendTexture backend_texture_; VulkanCommandPool* const command_pool_;
diff --git a/gpu/command_buffer/service/external_vk_image_factory.cc b/gpu/command_buffer/service/external_vk_image_factory.cc index be1f1ad8..1ac61030 100644 --- a/gpu/command_buffer/service/external_vk_image_factory.cc +++ b/gpu/command_buffer/service/external_vk_image_factory.cc
@@ -61,8 +61,8 @@ } // namespace ExternalVkImageFactory::ExternalVkImageFactory( - SharedContextState* context_state) - : context_state_(context_state), + scoped_refptr<SharedContextState> context_state) + : context_state_(std::move(context_state)), command_pool_(context_state_->vk_context_provider() ->GetDeviceQueue() ->CreateCommandPool()),
diff --git a/gpu/command_buffer/service/external_vk_image_factory.h b/gpu/command_buffer/service/external_vk_image_factory.h index 63d36f2..f736400c 100644 --- a/gpu/command_buffer/service/external_vk_image_factory.h +++ b/gpu/command_buffer/service/external_vk_image_factory.h
@@ -22,7 +22,8 @@ // that allow it to be exported out and shared with GL. class ExternalVkImageFactory : public SharedImageBackingFactory { public: - explicit ExternalVkImageFactory(SharedContextState* context_state); + explicit ExternalVkImageFactory( + scoped_refptr<SharedContextState> context_state); ~ExternalVkImageFactory() override; // SharedImageBackingFactory implementation. @@ -66,7 +67,7 @@ void TransitionToColorAttachment(VkImage image); - SharedContextState* const context_state_; + scoped_refptr<SharedContextState> context_state_; std::unique_ptr<VulkanCommandPool> command_pool_; const VulkanImageUsageCache image_usage_cache_;
diff --git a/gpu/ipc/shared_image_interface_in_process.cc b/gpu/ipc/shared_image_interface_in_process.cc index 958355a..c0629c8 100644 --- a/gpu/ipc/shared_image_interface_in_process.cc +++ b/gpu/ipc/shared_image_interface_in_process.cc
@@ -84,8 +84,10 @@ void SharedImageInterfaceInProcess::DestroyOnGpu( base::WaitableEvent* completion) { bool have_context = MakeContextCurrent(); - if (shared_image_factory_) + if (shared_image_factory_) { shared_image_factory_->DestroyAllSharedImages(have_context); + shared_image_factory_ = nullptr; + } if (sync_point_client_state_) { sync_point_client_state_->Destroy();
diff --git a/ios/chrome/browser/ui/browser_view/browser_view_controller_unittest.mm b/ios/chrome/browser/ui/browser_view/browser_view_controller_unittest.mm index 24c6aff3..972d0f3 100644 --- a/ios/chrome/browser/ui/browser_view/browser_view_controller_unittest.mm +++ b/ios/chrome/browser/ui/browser_view/browser_view_controller_unittest.mm
@@ -178,10 +178,6 @@ [[bvc_ view] removeFromSuperview]; [bvc_ shutdown]; - // Cleanup to avoid debugger crash in non empty observer lists. - browser_->GetWebStateList()->CloseAllWebStates( - WebStateList::ClosingFlags::CLOSE_NO_FLAGS); - BlockCleanupTest::TearDown(); }
diff --git a/ios/chrome/browser/ui/history/history_ui_egtest.mm b/ios/chrome/browser/ui/history/history_ui_egtest.mm index c4a279714..f6d4ba34 100644 --- a/ios/chrome/browser/ui/history/history_ui_egtest.mm +++ b/ios/chrome/browser/ui/history/history_ui_egtest.mm
@@ -33,12 +33,10 @@ #endif using chrome_test_util::ButtonWithAccessibilityLabelId; -using chrome_test_util::CopyLinkButton; using chrome_test_util::HistoryEntry; using chrome_test_util::NavigationBarDoneButton; -using chrome_test_util::OpenLinkInNewTabButton; -using chrome_test_util::OpenLinkInIncognitoButton; using chrome_test_util::OpenLinkInNewWindowButton; +using chrome_test_util::DeleteButton; namespace { char kURL1[] = "/firstURL"; @@ -392,12 +390,7 @@ // Select "Open in New Tab" and confirm that new tab is opened with selected // URL. - [[EarlGrey selectElementWithMatcher:OpenLinkInNewTabButton()] - performAction:grey_tap()]; - [[EarlGrey selectElementWithMatcher:chrome_test_util::OmniboxText( - _URL1.GetContent())] - assertWithMatcher:grey_notNil()]; - [ChromeEarlGrey waitForMainTabCount:2]; + [ChromeEarlGrey verifyOpenInNewTabActionWithURL:_URL1.GetContent()]; } // Tests display and selection of 'Open in New Window' in a context menu on a @@ -444,31 +437,15 @@ // Select "Open in New Incognito Tab" and confirm that new tab is opened in // incognito with the selected URL. - [[EarlGrey selectElementWithMatcher:OpenLinkInIncognitoButton([ChromeEarlGrey - isNativeContextMenusEnabled])] - performAction:grey_tap()]; - [[EarlGrey selectElementWithMatcher:chrome_test_util::OmniboxText( - _URL1.GetContent())] - assertWithMatcher:grey_notNil()]; - [ChromeEarlGrey waitForMainTabCount:1]; - [ChromeEarlGrey waitForIncognitoTabCount:1]; + [ChromeEarlGrey + verifyOpenInIncognitoActionWithURL:_URL1.GetContent() + useNewString:[ChromeEarlGrey + isNativeContextMenusEnabled]]; } // Tests display and selection of 'Copy URL' in a context menu on a history // entry. -// TODO(crbug.com/1067812): Test won't pass on devices. -#if TARGET_IPHONE_SIMULATOR -#define MAYBE_testContextMenuCopy testContextMenuCopy -#else -#define MAYBE_testContextMenuCopy DISABLED_testContextMenuCopy -#endif -- (void)MAYBE_testContextMenuCopy { - ProceduralBlock clearPasteboard = ^{ - [[UIPasteboard generalPasteboard] setURLs:nil]; - }; - [self setTearDownHandler:clearPasteboard]; - clearPasteboard(); - +- (void)testContextMenuCopy { [self loadTestURLs]; [self openHistoryPanel]; @@ -478,16 +455,66 @@ performAction:grey_longPress()]; // Tap "Copy URL" and wait for the URL to be copied to the pasteboard. - [[EarlGrey selectElementWithMatcher:CopyLinkButton([ChromeEarlGrey - isNativeContextMenusEnabled])] - performAction:grey_tap()]; - bool success = base::test::ios::WaitUntilConditionOrTimeout( - base::test::ios::kWaitForUIElementTimeout, ^{ - return _URL1 == - net::GURLWithNSURL([UIPasteboard generalPasteboard].URL); - }); - GREYAssertTrue(success, @"Pasteboard URL was not set to %s", - _URL1.spec().c_str()); + [ChromeEarlGrey + verifyCopyLinkActionWithText:[NSString stringWithUTF8String:_URL1.spec() + .c_str()] + useNewString:[ChromeEarlGrey + isNativeContextMenusEnabled]]; +} + +// Tests display and selection of "Share" in the context menu for a history +// entry. +- (void)testContextMenuShare { + if (![ChromeEarlGrey isNativeContextMenusEnabled]) { + EARL_GREY_TEST_SKIPPED( + @"Test disabled when Native Context Menus feature flag is off."); + } + + [self loadTestURLs]; + [self openHistoryPanel]; + + // Long press on the history element. + [[EarlGrey + selectElementWithMatcher:HistoryEntry(_URL1.GetOrigin().spec(), kTitle1)] + performAction:grey_longPress()]; + + [ChromeEarlGrey + verifyShareActionWithPageTitle:[NSString stringWithUTF8String:kTitle1]]; +} + +// Tests the Delete context menu action for a History entry. +- (void)testContextMenuDelete { + if (![ChromeEarlGrey isNativeContextMenusEnabled]) { + EARL_GREY_TEST_SKIPPED( + @"Test disabled when Native Context Menus feature flag is off."); + } + + [self loadTestURLs]; + [self openHistoryPanel]; + + // Long press on the history element. + [[EarlGrey + selectElementWithMatcher:HistoryEntry(_URL1.GetOrigin().spec(), kTitle1)] + performAction:grey_longPress()]; + + [[EarlGrey selectElementWithMatcher:DeleteButton()] performAction:grey_tap()]; + + // Assert that the deleted entry is gone and the other two remain. + [[EarlGrey + selectElementWithMatcher:HistoryEntry(_URL1.GetOrigin().spec(), kTitle1)] + assertWithMatcher:grey_nil()]; + + // Wait for the animations to be done, then validate. + [ChromeEarlGrey + waitForSufficientlyVisibleElementWithMatcher:HistoryEntry( + _URL2.GetOrigin().spec(), + kTitle2)]; + [[EarlGrey + selectElementWithMatcher:HistoryEntry(_URL2.GetOrigin().spec(), kTitle2)] + assertWithMatcher:grey_notNil()]; + [[EarlGrey selectElementWithMatcher:HistoryEntry(_URL3.GetOrigin().spec(), + _URL3.GetContent())] + assertWithMatcher:grey_notNil()]; } // Tests that the VC can be dismissed by swiping down.
diff --git a/ios/chrome/browser/ui/recent_tabs/recent_tabs_egtest.mm b/ios/chrome/browser/ui/recent_tabs/recent_tabs_egtest.mm index ba23a30b..c9d9ee82 100644 --- a/ios/chrome/browser/ui/recent_tabs/recent_tabs_egtest.mm +++ b/ios/chrome/browser/ui/recent_tabs/recent_tabs_egtest.mm
@@ -321,7 +321,8 @@ // Tests the Copy Link action on a recent tab's context menu. - (void)testContextMenuCopyLink { if (![ChromeEarlGrey isNativeContextMenusEnabled]) { - EARL_GREY_TEST_SKIPPED(@"Test disabled on when feature flag is off."); + EARL_GREY_TEST_SKIPPED( + @"Test disabled when Native Context Menus feature flag is off."); } [self loadTestURL]; @@ -338,7 +339,8 @@ // Tests the Open in New Tab action on a recent tab's context menu. - (void)testContextMenuOpenInNewTab { if (![ChromeEarlGrey isNativeContextMenusEnabled]) { - EARL_GREY_TEST_SKIPPED(@"Test disabled on when feature flag is off."); + EARL_GREY_TEST_SKIPPED( + @"Test disabled when Native Context Menus feature flag is off."); } [self loadTestURL]; @@ -355,7 +357,8 @@ // Tests the Share action on a recent tab's context menu. - (void)testContextMenuShare { if (![ChromeEarlGrey isNativeContextMenusEnabled]) { - EARL_GREY_TEST_SKIPPED(@"Test disabled on when feature flag is off."); + EARL_GREY_TEST_SKIPPED( + @"Test disabled when Native Context Menus feature flag is off."); } [self loadTestURL];
diff --git a/ios/chrome/browser/ui/settings/password/passwords_mediator.mm b/ios/chrome/browser/ui/settings/password/passwords_mediator.mm index 9021bfce..01d469b3 100644 --- a/ios/chrome/browser/ui/settings/password/passwords_mediator.mm +++ b/ios/chrome/browser/ui/settings/password/passwords_mediator.mm
@@ -90,15 +90,15 @@ _syncService = syncService; _savedPasswordsConsumer = std::make_unique<ios::SavePasswordsConsumer>(self); + _passwordStoreObserver = + std::make_unique<PasswordStoreObserverBridge>(self); + _passwordStore->AddObserver(_passwordStoreObserver.get()); if (base::FeatureList::IsEnabled( password_manager::features::kPasswordCheck)) { _passwordCheckManager = passwordCheckManager; _passwordCheckObserver = std::make_unique<PasswordCheckObserverBridge>( self, _passwordCheckManager.get()); - _passwordStoreObserver = - std::make_unique<PasswordStoreObserverBridge>(self); - _passwordStore->AddObserver(_passwordStoreObserver.get()); } } return self;
diff --git a/ios/chrome/browser/ui/tab_grid/grid/grid_cell.h b/ios/chrome/browser/ui/tab_grid/grid/grid_cell.h index 97ec81f..396d110 100644 --- a/ios/chrome/browser/ui/tab_grid/grid/grid_cell.h +++ b/ios/chrome/browser/ui/tab_grid/grid/grid_cell.h
@@ -32,7 +32,7 @@ @property(nonatomic, weak) UIImage* snapshot; @property(nonatomic, copy) NSString* title; @property(nonatomic, assign) BOOL titleHidden; -@property(nonatomic, readonly) UIBezierPath* visiblePath; +@property(nonatomic, readonly) UIDragPreviewParameters* dragPreviewParameters; @end // A GridCell for use in animated transitions that only shows selection state
diff --git a/ios/chrome/browser/ui/tab_grid/grid/grid_cell.mm b/ios/chrome/browser/ui/tab_grid/grid/grid_cell.mm index 2349999..83339c3 100644 --- a/ios/chrome/browser/ui/tab_grid/grid/grid_cell.mm +++ b/ios/chrome/browser/ui/tab_grid/grid/grid_cell.mm
@@ -255,10 +255,13 @@ _titleHidden = titleHidden; } -- (UIBezierPath*)visiblePath { - return [UIBezierPath +- (UIDragPreviewParameters*)dragPreviewParameters { + UIBezierPath* visiblePath = [UIBezierPath bezierPathWithRoundedRect:self.bounds cornerRadius:self.contentView.layer.cornerRadius]; + UIDragPreviewParameters* params = [[UIDragPreviewParameters alloc] init]; + params.visiblePath = visiblePath; + return params; } #pragma mark - Private
diff --git a/ios/chrome/browser/ui/tab_grid/grid/grid_drag_drop_handler.h b/ios/chrome/browser/ui/tab_grid/grid/grid_drag_drop_handler.h index dd35a39..1391156 100644 --- a/ios/chrome/browser/ui/tab_grid/grid/grid_drag_drop_handler.h +++ b/ios/chrome/browser/ui/tab_grid/grid/grid_drag_drop_handler.h
@@ -25,10 +25,21 @@ // Tells the receiver to incorporate the |dragItem| into the model layer at the // |destinationIndex|. |fromSameCollection| is an indication that the operation -// is a reorder within the same collection. +// is a reorder within the same collection. |dragItem| must have a localObject, +// which means the item is dragged from within the same app. - (void)dropItem:(UIDragItem*)dragItem toIndex:(NSUInteger)destinationIndex fromSameCollection:(BOOL)fromSameCollection; + +// Tells the receiver to asynchronously extract data from |itemProvider| into +// the model layer at the |destinationIndex|. |placeholderContext| is used to +// delete the placeholder once the item is ready to be inserted into the model +// layer. +- (void)dropItemFromProvider:(NSItemProvider*)itemProvider + toIndex:(NSUInteger)destinationIndex + placeholderContext: + (id<UICollectionViewDropPlaceholderContext>)placeholderContext; + @end #endif // IOS_CHROME_BROWSER_UI_TAB_GRID_GRID_GRID_DRAG_DROP_HANDLER_H_
diff --git a/ios/chrome/browser/ui/tab_grid/grid/grid_view_controller.mm b/ios/chrome/browser/ui/tab_grid/grid/grid_view_controller.mm index d9eac9ed..27e781f 100644 --- a/ios/chrome/browser/ui/tab_grid/grid/grid_view_controller.mm +++ b/ios/chrome/browser/ui/tab_grid/grid/grid_view_controller.mm
@@ -438,11 +438,9 @@ - (UIDragPreviewParameters*)collectionView:(UICollectionView*)collectionView dragPreviewParametersForItemAtIndexPath:(NSIndexPath*)indexPath { - UIDragPreviewParameters* params = [[UIDragPreviewParameters alloc] init]; - GridCell* cell = base::mac::ObjCCastStrict<GridCell>( + GridCell* gridCell = base::mac::ObjCCastStrict<GridCell>( [self.collectionView cellForItemAtIndexPath:indexPath]); - params.visiblePath = cell.visiblePath; - return params; + return gridCell.dragPreviewParameters; } #pragma mark - UICollectionViewDropDelegate @@ -471,21 +469,52 @@ (id<UICollectionViewDropCoordinator>)coordinator { id<UICollectionViewDropItem> item = coordinator.items.firstObject; - NSIndexPath* dropIndexPath = coordinator.destinationIndexPath; - if (!dropIndexPath) { - dropIndexPath = [NSIndexPath indexPathForItem:(self.items.count - 1) - inSection:0]; + // Append to the end of the collection, unless drop index is specified. + NSUInteger destinationIndex = self.items.count; + if (item.sourceIndexPath) { + // The sourceIndexPath is non-nil if the drop item is from this same + // collection view. Move to last position rather than appending if this is a + // reorder operation. + destinationIndex = self.items.count - 1; + } + if (coordinator.destinationIndexPath) { + destinationIndex = + base::checked_cast<NSUInteger>(coordinator.destinationIndexPath.item); + } + NSIndexPath* dropIndexPath = [NSIndexPath indexPathForItem:destinationIndex + inSection:0]; + + // Drop synchronously if local object is available. + if (item.dragItem.localObject) { + [coordinator dropItem:item.dragItem toItemAtIndexPath:dropIndexPath]; + // The sourceIndexPath is non-nil if the drop item is from this same + // collection view. + [self.dragDropHandler dropItem:item.dragItem + toIndex:destinationIndex + fromSameCollection:(item.sourceIndexPath != nil)]; + return; } - NSUInteger destinationIndex = - base::checked_cast<NSUInteger>(dropIndexPath.item); - [coordinator dropItem:item.dragItem toItemAtIndexPath:dropIndexPath]; + // Drop asynchronously if local object is not available. + UICollectionViewDropPlaceholder* placeholder = + [[UICollectionViewDropPlaceholder alloc] + initWithInsertionIndexPath:dropIndexPath + reuseIdentifier:kCellIdentifier]; + placeholder.cellUpdateHandler = ^(UICollectionViewCell* placeholderCell) { + GridCell* gridCell = base::mac::ObjCCastStrict<GridCell>(placeholderCell); + gridCell.theme = self.theme; + }; + placeholder.previewParametersProvider = + ^UIDragPreviewParameters*(UICollectionViewCell* placeholderCell) { + GridCell* gridCell = base::mac::ObjCCastStrict<GridCell>(placeholderCell); + return gridCell.dragPreviewParameters; + }; - // TODO(crbug.com/1095200): Handle the edge case that two windows are - // simultaneously dragging and dropping. - [self.dragDropHandler dropItem:item.dragItem - toIndex:destinationIndex - fromSameCollection:collectionView.hasActiveDrag]; + id<UICollectionViewDropPlaceholderContext> context = + [coordinator dropItem:item.dragItem toPlaceholder:placeholder]; + [self.dragDropHandler dropItemFromProvider:item.dragItem.itemProvider + toIndex:destinationIndex + placeholderContext:context]; } #pragma mark - UIScrollViewDelegate
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_egtest.mm b/ios/chrome/browser/ui/tab_grid/tab_grid_egtest.mm index 6373e03d..d4c2bfc 100644 --- a/ios/chrome/browser/ui/tab_grid/tab_grid_egtest.mm +++ b/ios/chrome/browser/ui/tab_grid/tab_grid_egtest.mm
@@ -160,7 +160,8 @@ // Tests the Copy Link action on a recent tab's context menu. - (void)testRecentTabsContextMenuCopyLink { if (![ChromeEarlGrey isNativeContextMenusEnabled]) { - EARL_GREY_TEST_SKIPPED(@"Test disabled on when feature flag is off."); + EARL_GREY_TEST_SKIPPED( + @"Test disabled when Native Context Menus feature flag is off."); } [self prepareRecentTabWithURL:_URL1 response:kResponse1]; @@ -175,7 +176,8 @@ // Tests the Open in New Tab action on a recent tab's context menu. - (void)testRecentTabsContextMenuOpenInNewTab { if (![ChromeEarlGrey isNativeContextMenusEnabled]) { - EARL_GREY_TEST_SKIPPED(@"Test disabled on when feature flag is off."); + EARL_GREY_TEST_SKIPPED( + @"Test disabled when Native Context Menus feature flag is off."); } [self prepareRecentTabWithURL:_URL1 response:kResponse1]; @@ -191,7 +193,8 @@ // Tests the Share action on a recent tab's context menu. - (void)testRecentTabsContextMenuShare { if (![ChromeEarlGrey isNativeContextMenusEnabled]) { - EARL_GREY_TEST_SKIPPED(@"Test disabled on when feature flag is off."); + EARL_GREY_TEST_SKIPPED( + @"Test disabled when Native Context Menus feature flag is off."); } [self prepareRecentTabWithURL:_URL1 response:kResponse1];
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_mediator.mm b/ios/chrome/browser/ui/tab_grid/tab_grid_mediator.mm index 65902ff2..90eac23 100644 --- a/ios/chrome/browser/ui/tab_grid/tab_grid_mediator.mm +++ b/ios/chrome/browser/ui/tab_grid/tab_grid_mediator.mm
@@ -465,31 +465,34 @@ withURL:net::GURLWithNSURL(droppedURL)]; return; } +} - // Handle URLs from other apps asynchronously, as synchronous is not possible - // with NSItemProvider. - NSItemProvider* itemProvider = dragItem.itemProvider; - if ([itemProvider canLoadObjectOfClass:[NSURL class]]) { - // The parameter type has changed with Xcode 12 SDK. - // TODO(crbug.com/1098318): Remove this once Xcode 11 support is dropped. -#if defined(__IPHONE_14_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_14_0 - using providerType = __kindof id<NSItemProviderReading>; -#else - using providerType = id<NSItemProviderReading>; -#endif - - auto loadHandler = ^(providerType providedItem, NSError* error) { - dispatch_async(dispatch_get_main_queue(), ^{ - NSURL* droppedURL = static_cast<NSURL*>(providedItem); - [self insertNewItemAtIndex:destinationIndex - withURL:net::GURLWithNSURL(droppedURL)]; - }); - }; - - [itemProvider loadObjectOfClass:[NSURL class] - completionHandler:loadHandler]; +- (void)dropItemFromProvider:(NSItemProvider*)itemProvider + toIndex:(NSUInteger)destinationIndex + placeholderContext: + (id<UICollectionViewDropPlaceholderContext>)placeholderContext { + if (![itemProvider canLoadObjectOfClass:[NSURL class]]) { + [placeholderContext deletePlaceholder]; return; } + + // The parameter type has changed with Xcode 12 SDK. + // TODO(crbug.com/1098318): Remove this once Xcode 11 support is dropped. +#if defined(__IPHONE_14_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_14_0 + using providerType = __kindof id<NSItemProviderReading>; +#else + using providerType = id<NSItemProviderReading>; +#endif + + auto loadHandler = ^(providerType providedItem, NSError* error) { + dispatch_async(dispatch_get_main_queue(), ^{ + [placeholderContext deletePlaceholder]; + NSURL* droppedURL = static_cast<NSURL*>(providedItem); + [self insertNewItemAtIndex:destinationIndex + withURL:net::GURLWithNSURL(droppedURL)]; + }); + }; + [itemProvider loadObjectOfClass:[NSURL class] completionHandler:loadHandler]; } #pragma mark - GridImageDataSource
diff --git a/ios/chrome/test/earl_grey/chrome_earl_grey.h b/ios/chrome/test/earl_grey/chrome_earl_grey.h index ac287ae..5bbb599 100644 --- a/ios/chrome/test/earl_grey/chrome_earl_grey.h +++ b/ios/chrome/test/earl_grey/chrome_earl_grey.h
@@ -582,6 +582,12 @@ // present in the omnibox. - (void)verifyOpenInNewTabActionWithURL:(const std::string&)URL; +// Taps on the Open in Incognito context menu action and waits for the |URL| to +// be present in the omnibox. |useNewString| determines which action string +// to use. +- (void)verifyOpenInIncognitoActionWithURL:(const std::string&)URL + useNewString:(BOOL)useNewString; + // Taps on the Share context menu action and validates that the ActivityView // was brought up with |pageTitle| in its header. - (void)verifyShareActionWithPageTitle:(NSString*)pageTitle;
diff --git a/ios/chrome/test/earl_grey/chrome_earl_grey.mm b/ios/chrome/test/earl_grey/chrome_earl_grey.mm index bc5fe2d..24aff468 100644 --- a/ios/chrome/test/earl_grey/chrome_earl_grey.mm +++ b/ios/chrome/test/earl_grey/chrome_earl_grey.mm
@@ -41,6 +41,7 @@ using chrome_test_util::ActivityViewHeader; using chrome_test_util::CopyLinkButton; using chrome_test_util::OpenLinkInNewTabButton; +using chrome_test_util::OpenLinkInIncognitoButton; using chrome_test_util::ShareButton; namespace { @@ -1058,6 +1059,7 @@ - (void)verifyCopyLinkActionWithText:(NSString*)text useNewString:(BOOL)useNewString { + [ChromeEarlGreyAppInterface clearPasteboardURLs]; [[EarlGrey selectElementWithMatcher:CopyLinkButton(useNewString)] performAction:grey_tap()]; [self verifyStringCopied:text]; @@ -1065,12 +1067,31 @@ - (void)verifyOpenInNewTabActionWithURL:(const std::string&)URL { // Check tab count prior to execution. - NSUInteger oldTabCount = [ChromeEarlGreyAppInterface mainTabCount]; + NSUInteger oldRegularTabCount = [ChromeEarlGreyAppInterface mainTabCount]; + NSUInteger oldIncognitoTabCount = + [ChromeEarlGreyAppInterface incognitoTabCount]; [[EarlGrey selectElementWithMatcher:OpenLinkInNewTabButton()] performAction:grey_tap()]; - [self waitForMainTabCount:oldTabCount + 1]; + [self waitForMainTabCount:oldRegularTabCount + 1]; + [self waitForIncognitoTabCount:oldIncognitoTabCount]; + [[EarlGrey selectElementWithMatcher:chrome_test_util::OmniboxText(URL)] + assertWithMatcher:grey_notNil()]; +} + +- (void)verifyOpenInIncognitoActionWithURL:(const std::string&)URL + useNewString:(BOOL)useNewString { + // Check tab count prior to execution. + NSUInteger oldRegularTabCount = [ChromeEarlGreyAppInterface mainTabCount]; + NSUInteger oldIncognitoTabCount = + [ChromeEarlGreyAppInterface incognitoTabCount]; + + [[EarlGrey selectElementWithMatcher:OpenLinkInIncognitoButton(useNewString)] + performAction:grey_tap()]; + + [self waitForIncognitoTabCount:oldIncognitoTabCount + 1]; + [self waitForMainTabCount:oldRegularTabCount]; [[EarlGrey selectElementWithMatcher:chrome_test_util::OmniboxText(URL)] assertWithMatcher:grey_notNil()]; }
diff --git a/ios/chrome/test/earl_grey/chrome_earl_grey_app_interface.h b/ios/chrome/test/earl_grey/chrome_earl_grey_app_interface.h index a5b18cceb..a9c60b56 100644 --- a/ios/chrome/test/earl_grey/chrome_earl_grey_app_interface.h +++ b/ios/chrome/test/earl_grey/chrome_earl_grey_app_interface.h
@@ -482,6 +482,9 @@ #pragma mark - Pasteboard utilities +// Clears the URLs stored in the pasteboard, from the tested app's perspective. ++ (void)clearPasteboardURLs; + // Retrieves the currently stored string on the pasteboard from the tested app's // perspective. + (NSString*)pasteboardString;
diff --git a/ios/chrome/test/earl_grey/chrome_earl_grey_app_interface.mm b/ios/chrome/test/earl_grey/chrome_earl_grey_app_interface.mm index bcaff7e6..fd4f648f 100644 --- a/ios/chrome/test/earl_grey/chrome_earl_grey_app_interface.mm +++ b/ios/chrome/test/earl_grey/chrome_earl_grey_app_interface.mm
@@ -840,6 +840,10 @@ #pragma mark - Pasteboard utilities ++ (void)clearPasteboardURLs { + [[UIPasteboard generalPasteboard] setURLs:nil]; +} + + (NSString*)pasteboardString { return [UIPasteboard generalPasteboard].string; }
diff --git a/ios/chrome/test/earl_grey/chrome_matchers.h b/ios/chrome/test/earl_grey/chrome_matchers.h index fa940ae4d..6f36bab 100644 --- a/ios/chrome/test/earl_grey/chrome_matchers.h +++ b/ios/chrome/test/earl_grey/chrome_matchers.h
@@ -330,7 +330,7 @@ // Matcher for the Move option on the updated context menus. id<GREYMatcher> MoveButton(); -// Matcher for the Share option on the updated context menus. +// Matcher for the Delete option on the updated context menus. id<GREYMatcher> DeleteButton(); // Returns matcher for the Copy item on the old-style context menu.
diff --git a/media/capture/BUILD.gn b/media/capture/BUILD.gn index 5a0dfd1..0a27e9d 100644 --- a/media/capture/BUILD.gn +++ b/media/capture/BUILD.gn
@@ -169,6 +169,8 @@ if (is_mac) { sources += [ + "video/mac/pixel_buffer_pool_mac.cc", + "video/mac/pixel_buffer_pool_mac.h", "video/mac/video_capture_device_avfoundation_legacy_mac.h", "video/mac/video_capture_device_avfoundation_legacy_mac.mm", "video/mac/video_capture_device_avfoundation_mac.h", @@ -195,6 +197,7 @@ "CoreVideo.framework", "Foundation.framework", "IOSurface.framework", + "VideoToolbox.framework", ] } @@ -407,6 +410,7 @@ "video/linux/camera_config_chromeos_unittest.cc", "video/linux/v4l2_capture_delegate_unittest.cc", "video/linux/video_capture_device_factory_linux_unittest.cc", + "video/mac/pixel_buffer_pool_mac_unittest.mm", "video/mac/test/mock_video_capture_device_avfoundation_frame_receiver_mac.h", "video/mac/test/mock_video_capture_device_avfoundation_frame_receiver_mac.mm", "video/mac/test/video_capture_test_utils_mac.h", @@ -459,6 +463,7 @@ frameworks = [ "AVFoundation.framework", "CoreMedia.framework", + "CoreVideo.framework", ] }
diff --git a/media/capture/video/mac/pixel_buffer_pool_mac.cc b/media/capture/video/mac/pixel_buffer_pool_mac.cc new file mode 100644 index 0000000..b53db6a --- /dev/null +++ b/media/capture/video/mac/pixel_buffer_pool_mac.cc
@@ -0,0 +1,144 @@ +// 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 "media/capture/video/mac/pixel_buffer_pool_mac.h" + +#include "base/check.h" +#include "base/logging.h" +#include "base/numerics/safe_conversions.h" + +namespace media { + +namespace { + +template <typename T> +class CFNumber { + public: + CFNumber(CFNumberType type, T value) + : value_(value), number_(CFNumberCreate(nil, type, &value_)) {} + + T* get() { return &value_; } + const T* get() const { return &value_; } + CFNumberRef cf_number_ref() { return number_.get(); } + + private: + T value_; + base::ScopedCFTypeRef<CFNumberRef> number_; +}; + +base::ScopedCFTypeRef<CFDictionaryRef> CreateEmptyCFDictionary() { + return base::ScopedCFTypeRef<CFDictionaryRef>( + CFDictionaryCreate(nil, nil, nil, 0, &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks)); +} + +} // namespace + +// static +std::unique_ptr<PixelBufferPool> PixelBufferPool::Create( + OSType format, + int width, + int height, + base::Optional<size_t> max_buffers) { + // Pixel buffer attributes: The attributes of buffers created by the pool. + CFStringRef pixel_buffer_attribute_keys[] = { + kCVPixelBufferIOSurfacePropertiesKey, // We want IOSurfaces. + kCVPixelBufferPixelFormatTypeKey, kCVPixelBufferWidthKey, + kCVPixelBufferHeightKey}; + constexpr size_t pixel_buffer_attribute_count = + sizeof(pixel_buffer_attribute_keys) / + sizeof(pixel_buffer_attribute_keys[0]); + // Rely on default IOSurface properties. + base::ScopedCFTypeRef<CFDictionaryRef> io_surface_options = + CreateEmptyCFDictionary(); + CFNumber<int> pixel_buffer_format(kCFNumberSInt32Type, format); + CFNumber<int> pixel_buffer_width(kCFNumberSInt32Type, width); + CFNumber<int> pixel_buffer_height(kCFNumberSInt32Type, height); + CFTypeRef pixel_buffer_attribute_values[] = { + io_surface_options.get(), pixel_buffer_format.cf_number_ref(), + pixel_buffer_width.cf_number_ref(), pixel_buffer_height.cf_number_ref()}; + static_assert(pixel_buffer_attribute_count == + sizeof(pixel_buffer_attribute_values) / + sizeof(pixel_buffer_attribute_values[0]), + "Key count and value count must match"); + base::ScopedCFTypeRef<CFDictionaryRef> pixel_buffer_attributes( + CFDictionaryCreate(nil, (const void**)pixel_buffer_attribute_keys, + (const void**)pixel_buffer_attribute_values, + pixel_buffer_attribute_count, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks)); + + // Create the pool. + // We don't specify any pool attributes. It is unclear from the documentation + // what pool attributes are available; they might be + // kCVPixelBufferPoolMinimumBufferCountKey and + // kCVPixelBufferPoolMaximumBufferAgeKey unless these are more auxiliary + // attributes for CVPixelBufferPoolCreatePixelBufferWithAuxAttributes(). + base::ScopedCFTypeRef<CVPixelBufferPoolRef> buffer_pool; + CVReturn pool_creation_error = CVPixelBufferPoolCreate( + nil, nil, pixel_buffer_attributes.get(), buffer_pool.InitializeInto()); + if (pool_creation_error != noErr) { + DLOG(ERROR) << "Failed to create CVPixelBufferPool with CVReturn error: " + << pool_creation_error; + return nullptr; + } + return std::make_unique<PixelBufferPool>(std::move(buffer_pool), + std::move(max_buffers)); +} + +PixelBufferPool::PixelBufferPool( + base::ScopedCFTypeRef<CVPixelBufferPoolRef> buffer_pool, + base::Optional<size_t> max_buffers) + : buffer_pool_(std::move(buffer_pool)), + max_buffers_(std::move(max_buffers)) { + DCHECK(buffer_pool_); +} + +PixelBufferPool::~PixelBufferPool() { + // Flushing before freeing probably isn't needed, but it can't hurt. + Flush(); +} + +base::ScopedCFTypeRef<CVPixelBufferRef> PixelBufferPool::CreateBuffer() { + DCHECK(buffer_pool_); + base::ScopedCFTypeRef<CVPixelBufferRef> buffer; + CVReturn buffer_creation_error; + if (!max_buffers_.has_value()) { + buffer_creation_error = CVPixelBufferPoolCreatePixelBuffer( + nil, buffer_pool_, buffer.InitializeInto()); + } else { + // Specify the allocation threshold using auxiliary attributes. + CFStringRef attribute_keys[] = {kCVPixelBufferPoolAllocationThresholdKey}; + constexpr size_t attribute_count = + sizeof(attribute_keys) / sizeof(attribute_keys[0]); + CFNumber<int> poolAllocationThreshold( + kCFNumberSInt32Type, base::checked_cast<int>(max_buffers_.value())); + CFTypeRef attribute_values[] = {poolAllocationThreshold.cf_number_ref()}; + static_assert(attribute_count == + sizeof(attribute_values) / sizeof(attribute_values[0]), + "Key count and value count must match"); + base::ScopedCFTypeRef<CFDictionaryRef> attributes(CFDictionaryCreate( + nil, (const void**)attribute_keys, (const void**)attribute_values, + attribute_count, &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks)); + buffer_creation_error = CVPixelBufferPoolCreatePixelBufferWithAuxAttributes( + nil, buffer_pool_, attributes.get(), buffer.InitializeInto()); + } + if (buffer_creation_error == kCVReturnWouldExceedAllocationThreshold) { + // PixelBufferPool cannot create more buffers. + return base::ScopedCFTypeRef<CVPixelBufferRef>(nil); + } + // If |max_buffers_| wasn't reached, this operation must succeed. + CHECK(buffer_creation_error == noErr) + << "Failed to create destination CVPixelBuffer with CVReturn error: " + << buffer_creation_error; + return buffer; +} + +void PixelBufferPool::Flush() { + DCHECK(buffer_pool_); + CVPixelBufferPoolFlush(buffer_pool_, kCVPixelBufferPoolFlushExcessBuffers); +} + +} // namespace media
diff --git a/media/capture/video/mac/pixel_buffer_pool_mac.h b/media/capture/video/mac/pixel_buffer_pool_mac.h new file mode 100644 index 0000000..3e9c7cf --- /dev/null +++ b/media/capture/video/mac/pixel_buffer_pool_mac.h
@@ -0,0 +1,59 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MEDIA_CAPTURE_VIDEO_MAC_PIXEL_BUFFER_POOL_MAC_H_ +#define MEDIA_CAPTURE_VIDEO_MAC_PIXEL_BUFFER_POOL_MAC_H_ + +#import <VideoToolbox/VideoToolbox.h> +#include <memory> + +#include "base/mac/scoped_cftyperef.h" +#include "base/optional.h" +#include "media/capture/capture_export.h" + +namespace media { + +class CAPTURE_EXPORT PixelBufferPool { + public: + // All buffers created by the pool will have the specified properties. + // If specified, the pool allows at most |max_buffers| to exist at a time by + // having CreateBuffer() returns null if this threshold would be exceeded. + // + // If an unsupportd |format| is specified, or the pool cannot be created for + // unknown reasons, null is returned. + static std::unique_ptr<PixelBufferPool> Create( + OSType format, + int width, + int height, + base::Optional<size_t> max_buffers); + ~PixelBufferPool(); + + // Creates a new buffer from the pool, or returns null if |max_buffers_| would + // be exceeded. The underlying buffers may be recycled. + // + // The caller owns the returned buffer and is responsible for calling + // CFRelease() after they are done using it. This returns the underlying + // buffer to the pool. In order to free memory, you must both release all + // buffers and call Flush() or delete the pool. It is safe for a buffer to + // outlive its pool. + base::ScopedCFTypeRef<CVPixelBufferRef> CreateBuffer(); + + // Frees the memory of any released buffers returned to the pool. + void Flush(); + + private: + friend std::unique_ptr<PixelBufferPool> std::make_unique<PixelBufferPool>( + base::ScopedCFTypeRef<CVPixelBufferPoolRef>&& buffer_pool, + base::Optional<size_t>&& max_buffers); + + PixelBufferPool(base::ScopedCFTypeRef<CVPixelBufferPoolRef> buffer_pool, + base::Optional<size_t> max_buffers); + + base::ScopedCFTypeRef<CVPixelBufferPoolRef> buffer_pool_; + const base::Optional<size_t> max_buffers_; +}; + +} // namespace media + +#endif // MEDIA_CAPTURE_VIDEO_MAC_PIXEL_BUFFER_POOL_MAC_H_
diff --git a/media/capture/video/mac/pixel_buffer_pool_mac_unittest.mm b/media/capture/video/mac/pixel_buffer_pool_mac_unittest.mm new file mode 100644 index 0000000..b366cdb5e --- /dev/null +++ b/media/capture/video/mac/pixel_buffer_pool_mac_unittest.mm
@@ -0,0 +1,109 @@ +// 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 "media/capture/video/mac/pixel_buffer_pool_mac.h" + +#include "base/bind.h" +#include "base/mac/scoped_nsobject.h" +#import "media/capture/video/mac/test/video_capture_test_utils_mac.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace media { + +namespace { + +// NV12, also known as 420v, also known as media::PIXEL_FORMAT_NV12. +constexpr OSType kPixelFormatNv12 = + kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange; +// A common 4:3 resolution. +constexpr int kVgaWidth = 640; +constexpr int kVgaHeight = 480; + +} // namespace + +TEST(PixelBufferPoolTest, CannotCreatePoolWithNonsenseArguments) { + EXPECT_FALSE(PixelBufferPool::Create(0, -1, -1, 1)); +} + +TEST(PixelBufferPoolTest, CreatedBufferHasSpecifiedAttributes) { + std::unique_ptr<PixelBufferPool> pool = + PixelBufferPool::Create(kPixelFormatNv12, kVgaWidth, kVgaHeight, 1); + base::ScopedCFTypeRef<CVPixelBufferRef> buffer = pool->CreateBuffer(); + EXPECT_TRUE(CVPixelBufferGetPixelFormatType(buffer) == kPixelFormatNv12); + EXPECT_EQ(CVPixelBufferGetWidth(buffer), static_cast<size_t>(kVgaWidth)); + EXPECT_EQ(CVPixelBufferGetHeight(buffer), static_cast<size_t>(kVgaHeight)); +} + +TEST(PixelBufferPoolTest, CreatedBufferHasIOSurface) { + std::unique_ptr<PixelBufferPool> pool = + PixelBufferPool::Create(kPixelFormatNv12, kVgaWidth, kVgaHeight, 1); + base::ScopedCFTypeRef<CVPixelBufferRef> buffer = pool->CreateBuffer(); + EXPECT_TRUE(CVPixelBufferGetIOSurface(buffer)); +} + +TEST(PixelBufferPoolTest, CannotExceedMaxBuffers) { + std::unique_ptr<PixelBufferPool> pool = + PixelBufferPool::Create(kPixelFormatNv12, kVgaWidth, kVgaHeight, 2); + base::ScopedCFTypeRef<CVPixelBufferRef> first_buffer = pool->CreateBuffer(); + EXPECT_TRUE(first_buffer); + base::ScopedCFTypeRef<CVPixelBufferRef> second_buffer = pool->CreateBuffer(); + EXPECT_TRUE(second_buffer); + base::ScopedCFTypeRef<CVPixelBufferRef> third_buffer = pool->CreateBuffer(); + EXPECT_FALSE(third_buffer); +} + +TEST(PixelBufferPoolTest, CanCreateBuffersIfMaxIsNull) { + std::unique_ptr<PixelBufferPool> pool = PixelBufferPool::Create( + kPixelFormatNv12, kVgaWidth, kVgaHeight, base::nullopt); + base::ScopedCFTypeRef<CVPixelBufferRef> first_buffer = pool->CreateBuffer(); + EXPECT_TRUE(first_buffer); + base::ScopedCFTypeRef<CVPixelBufferRef> second_buffer = pool->CreateBuffer(); + EXPECT_TRUE(second_buffer); + base::ScopedCFTypeRef<CVPixelBufferRef> third_buffer = pool->CreateBuffer(); + EXPECT_TRUE(third_buffer); +} + +TEST(PixelBufferPoolTest, CanCreateBufferAfterPreviousBufferIsReleased) { + std::unique_ptr<PixelBufferPool> pool = + PixelBufferPool::Create(kPixelFormatNv12, kVgaWidth, kVgaHeight, 1); + base::ScopedCFTypeRef<CVPixelBufferRef> buffer = pool->CreateBuffer(); + buffer.reset(); + buffer = pool->CreateBuffer(); + EXPECT_TRUE(buffer); +} + +TEST(PixelBufferPoolTest, BuffersCanOutliveThePool) { + std::unique_ptr<PixelBufferPool> pool = + PixelBufferPool::Create(kPixelFormatNv12, kVgaWidth, kVgaHeight, 1); + base::ScopedCFTypeRef<CVPixelBufferRef> buffer = pool->CreateBuffer(); + pool.reset(); + EXPECT_TRUE(CVPixelBufferGetPixelFormatType(buffer) == kPixelFormatNv12); + EXPECT_EQ(CVPixelBufferGetWidth(buffer), static_cast<size_t>(kVgaWidth)); + EXPECT_EQ(CVPixelBufferGetHeight(buffer), static_cast<size_t>(kVgaHeight)); + EXPECT_TRUE(CVPixelBufferGetIOSurface(buffer)); +} + +TEST(PixelBufferPoolTest, CanFlushWhileBufferIsInUse) { + std::unique_ptr<PixelBufferPool> pool = PixelBufferPool::Create( + kPixelFormatNv12, kVgaWidth, kVgaHeight, base::nullopt); + base::ScopedCFTypeRef<CVPixelBufferRef> retained_buffer = + pool->CreateBuffer(); + base::ScopedCFTypeRef<CVPixelBufferRef> released_buffer = + pool->CreateBuffer(); + released_buffer.reset(); + // We expect the memory of |released_buffer| to be freed now, but there is no + // way to assert this in a unittest. + pool->Flush(); + // We expect |retained_buffer| is still usable. Inspecting its properties. + EXPECT_TRUE(CVPixelBufferGetPixelFormatType(retained_buffer) == + kPixelFormatNv12); + EXPECT_EQ(CVPixelBufferGetWidth(retained_buffer), + static_cast<size_t>(kVgaWidth)); + EXPECT_EQ(CVPixelBufferGetHeight(retained_buffer), + static_cast<size_t>(kVgaHeight)); + EXPECT_TRUE(CVPixelBufferGetIOSurface(retained_buffer)); +} + +} // namespace media
diff --git a/net/android/java/src/org/chromium/net/ProxyChangeListener.java b/net/android/java/src/org/chromium/net/ProxyChangeListener.java index 8b88d996..d48c60b 100644 --- a/net/android/java/src/org/chromium/net/ProxyChangeListener.java +++ b/net/android/java/src/org/chromium/net/ProxyChangeListener.java
@@ -18,10 +18,10 @@ import android.os.Handler; import android.os.Looper; import android.text.TextUtils; -import android.util.Log; import org.chromium.base.BuildConfig; import org.chromium.base.ContextUtils; +import org.chromium.base.Log; import org.chromium.base.annotations.CalledByNative; import org.chromium.base.annotations.JNINamespace; import org.chromium.base.annotations.NativeClassQualifiedName; @@ -233,6 +233,9 @@ return ProxyConfig.DIRECT; } + // Temporary logging to debug crbug.com/1122903 + Log.i(TAG, "ProxyInfo: " + proxyInfo.toString()); + if (Build.VERSION.SDK_INT == Build.VERSION_CODES.Q && proxyInfo.getHost().equals("localhost") && proxyInfo.getPort() == -1) { // There's a bug in Android Q's PAC support. If ConnectivityManager
diff --git a/services/network/url_loader.cc b/services/network/url_loader.cc index ff2ca894..e13745d 100644 --- a/services/network/url_loader.cc +++ b/services/network/url_loader.cc
@@ -589,8 +589,24 @@ CrossOriginReadBlockingExceptionForPlugin::ShouldAllowForPlugin( factory_params_->process_id); request_mode_ = request.mode; + if (request.trusted_params) { has_user_activation_ = request.trusted_params->has_user_activation; + + if (factory_params_->client_security_state) { + // Enforce that only one ClientSecurityState is ever given to us, as this + // is an invariant in the current codebase. In case of a compromised + // renderer process, we might be passed both, in which case we prefer to + // use the factory params' value: contrary to the request params, it is + // always sourced from the browser process. + DCHECK(!request.trusted_params->client_security_state) + << "Must not provide a ClientSecurityState in both " + "URLLoaderFactoryParams and ResourceRequest::TrustedParams."; + } else { + // This might be nullptr, but that does not matter. Clone it anyways. + request_client_security_state_ = + request.trusted_params->client_security_state.Clone(); + } } throttling_token_ = network::ScopedThrottlingToken::MaybeCreate( @@ -977,8 +993,24 @@ return net::ERR_INSECURE_PRIVATE_NETWORK_REQUEST; } - const mojom::ClientSecurityStatePtr& security_state = - factory_params_->client_security_state; + // Depending on the type of URL request, we source the client security state + // from either the URLRequest's trusted params (for navigations, which share + // a factory) or the URLLoaderFactory's params. We prefer the factory params + // over the request params, as the former always come from the browser + // process. + // + // We use a raw pointer instead of a const-ref to a StructPtr in order to be + // able to assign a new value to the variable. A ternary operator would let us + // define a const-ref but would prevent logging which branch was taken. + const mojom::ClientSecurityState* security_state = + factory_params_->client_security_state.get(); + if (security_state) { + DVLOG(1) << "CORS-RFC1918 check: using factory client security state."; + } else { + DVLOG(1) << "CORS-RFC1918 check: using request client security state."; + security_state = request_client_security_state_.get(); + } + if (!security_state) { DVLOG(1) << "CORS-RFC1918 check: skipped, missing client security state."; return net::OK;
diff --git a/services/network/url_loader.h b/services/network/url_loader.h index ed6dfca8..70518f4 100644 --- a/services/network/url_loader.h +++ b/services/network/url_loader.h
@@ -509,6 +509,13 @@ // Observer listening to all cookie reads and writes made by this request. mojo::Remote<mojom::CookieAccessObserver> cookie_observer_; + // Client security state copied from the input ResourceRequest. + // + // If |factory_params_->client_security_state| is non-null, this is null. + // We indeed prefer the factory params over the request params as we trust the + // former more, given that they always come from the browser process. + mojom::ClientSecurityStatePtr request_client_security_state_; + // Indicates |url_request_| is fetch upload request and that has streaming // body. const bool has_fetch_streaming_upload_body_;
diff --git a/services/network/url_loader_unittest.cc b/services/network/url_loader_unittest.cc index 914cd69f3..bd8415c7 100644 --- a/services/network/url_loader_unittest.cc +++ b/services/network/url_loader_unittest.cc
@@ -566,6 +566,9 @@ if (request_body_) request.request_body = request_body_; + request.trusted_params->client_security_state.Swap( + &request_client_security_state_); + base::RunLoop delete_run_loop; mojo::Remote<mojom::URLLoader> loader; std::unique_ptr<URLLoader> url_loader; @@ -573,7 +576,7 @@ mojom::URLLoaderFactoryParams params; params.process_id = mojom::kBrowserProcessId; params.is_corb_enabled = false; - params.client_security_state.Swap(&client_security_state_); + params.client_security_state.Swap(&factory_client_security_state_); url::Origin origin = url::Origin::Create(url); params.isolation_info = @@ -749,8 +752,11 @@ DCHECK(!ran_); expect_redirect_ = true; } - void set_client_security_state(mojom::ClientSecurityStatePtr state) { - client_security_state_ = std::move(state); + void set_factory_client_security_state(mojom::ClientSecurityStatePtr state) { + factory_client_security_state_ = std::move(state); + } + void set_request_client_security_state(mojom::ClientSecurityStatePtr state) { + request_client_security_state_ = std::move(state); } void set_request_body(scoped_refptr<ResourceRequestBody> request_body) { request_body_ = request_body; @@ -875,7 +881,8 @@ bool send_ssl_with_response_ = false; bool send_ssl_for_cert_error_ = false; bool expect_redirect_ = false; - mojom::ClientSecurityStatePtr client_security_state_; + mojom::ClientSecurityStatePtr factory_client_security_state_; + mojom::ClientSecurityStatePtr request_client_security_state_; scoped_refptr<ResourceRequestBody> request_body_; // Used to ensure that methods are called either before or after a request is @@ -936,7 +943,7 @@ auto client_security_state = NewSecurityState(); client_security_state->is_web_secure_context = true; client_security_state->ip_address_space = mojom::IPAddressSpace::kUnknown; - set_client_security_state(std::move(client_security_state)); + set_factory_client_security_state(std::move(client_security_state)); EXPECT_THAT(Load(test_server()->GetURL("/empty.html")), IsOk()); } @@ -945,7 +952,7 @@ auto client_security_state = NewSecurityState(); client_security_state->is_web_secure_context = true; client_security_state->ip_address_space = mojom::IPAddressSpace::kPublic; - set_client_security_state(std::move(client_security_state)); + set_factory_client_security_state(std::move(client_security_state)); EXPECT_THAT(Load(test_server()->GetURL("/empty.html")), IsOk()); } @@ -954,7 +961,7 @@ auto client_security_state = NewSecurityState(); client_security_state->is_web_secure_context = true; client_security_state->ip_address_space = mojom::IPAddressSpace::kPrivate; - set_client_security_state(std::move(client_security_state)); + set_factory_client_security_state(std::move(client_security_state)); EXPECT_THAT(Load(test_server()->GetURL("/empty.html")), IsOk()); } @@ -963,7 +970,7 @@ auto client_security_state = NewSecurityState(); client_security_state->is_web_secure_context = true; client_security_state->ip_address_space = mojom::IPAddressSpace::kLocal; - set_client_security_state(std::move(client_security_state)); + set_factory_client_security_state(std::move(client_security_state)); EXPECT_THAT(Load(test_server()->GetURL("/empty.html")), IsOk()); } @@ -976,7 +983,7 @@ client_security_state->private_network_request_policy = mojom::PrivateNetworkRequestPolicy::kAllow; client_security_state->ip_address_space = mojom::IPAddressSpace::kUnknown; - set_client_security_state(std::move(client_security_state)); + set_factory_client_security_state(std::move(client_security_state)); EXPECT_THAT(Load(test_server()->GetURL("/empty.html")), IsOk()); } @@ -986,7 +993,7 @@ client_security_state->private_network_request_policy = mojom::PrivateNetworkRequestPolicy::kAllow; client_security_state->ip_address_space = mojom::IPAddressSpace::kPublic; - set_client_security_state(std::move(client_security_state)); + set_factory_client_security_state(std::move(client_security_state)); EXPECT_THAT(Load(test_server()->GetURL("/empty.html")), IsOk()); } @@ -996,7 +1003,7 @@ client_security_state->private_network_request_policy = mojom::PrivateNetworkRequestPolicy::kAllow; client_security_state->ip_address_space = mojom::IPAddressSpace::kPrivate; - set_client_security_state(std::move(client_security_state)); + set_factory_client_security_state(std::move(client_security_state)); EXPECT_THAT(Load(test_server()->GetURL("/empty.html")), IsOk()); } @@ -1006,7 +1013,7 @@ client_security_state->private_network_request_policy = mojom::PrivateNetworkRequestPolicy::kAllow; client_security_state->ip_address_space = mojom::IPAddressSpace::kLocal; - set_client_security_state(std::move(client_security_state)); + set_factory_client_security_state(std::move(client_security_state)); EXPECT_THAT(Load(test_server()->GetURL("/empty.html")), IsOk()); } @@ -1025,7 +1032,7 @@ auto client_security_state = NewSecurityState(); client_security_state->is_web_secure_context = false; client_security_state->ip_address_space = mojom::IPAddressSpace::kUnknown; - set_client_security_state(std::move(client_security_state)); + set_factory_client_security_state(std::move(client_security_state)); EXPECT_THAT(Load(test_server()->GetURL("/empty.html")), IsError(net::ERR_INSECURE_PRIVATE_NETWORK_REQUEST)); @@ -1035,7 +1042,7 @@ auto client_security_state = NewSecurityState(); client_security_state->is_web_secure_context = false; client_security_state->ip_address_space = mojom::IPAddressSpace::kPublic; - set_client_security_state(std::move(client_security_state)); + set_factory_client_security_state(std::move(client_security_state)); EXPECT_THAT(Load(test_server()->GetURL("/empty.html")), IsError(net::ERR_INSECURE_PRIVATE_NETWORK_REQUEST)); @@ -1045,7 +1052,7 @@ auto client_security_state = NewSecurityState(); client_security_state->is_web_secure_context = false; client_security_state->ip_address_space = mojom::IPAddressSpace::kPrivate; - set_client_security_state(std::move(client_security_state)); + set_factory_client_security_state(std::move(client_security_state)); EXPECT_THAT(Load(test_server()->GetURL("/empty.html")), IsError(net::ERR_INSECURE_PRIVATE_NETWORK_REQUEST)); @@ -1055,11 +1062,25 @@ auto client_security_state = NewSecurityState(); client_security_state->is_web_secure_context = false; client_security_state->ip_address_space = mojom::IPAddressSpace::kLocal; - set_client_security_state(std::move(client_security_state)); + set_factory_client_security_state(std::move(client_security_state)); EXPECT_THAT(Load(test_server()->GetURL("/empty.html")), IsOk()); } +// This test verifies that if the request's TrustedParams field carries a client +// security state indicating that the request initiator is not a secure context +// and came from the public IP address space, requests to local IP addresses +// are blocked. +TEST_F(URLLoaderTest, TrustedParamsInsecurePublicToLocalIsBlocked) { + auto client_security_state = NewSecurityState(); + client_security_state->is_web_secure_context = false; + client_security_state->ip_address_space = mojom::IPAddressSpace::kPublic; + set_request_client_security_state(std::move(client_security_state)); + + EXPECT_THAT(Load(test_server()->GetURL("/empty.html")), + IsError(net::ERR_INSECURE_PRIVATE_NETWORK_REQUEST)); +} + // Bundles together the inputs to a parameterized private network request test. struct URLLoaderFakeTransportInfoTestParams { // The address space of the client. @@ -1119,7 +1140,7 @@ auto client_security_state = NewSecurityState(); client_security_state->ip_address_space = params.client_address_space; - set_client_security_state(std::move(client_security_state)); + set_factory_client_security_state(std::move(client_security_state)); const GURL url("http://fake-endpoint");
diff --git a/storage/browser/quota/quota_features.cc b/storage/browser/quota/quota_features.cc index 42cc63ea..76be3c1 100644 --- a/storage/browser/quota/quota_features.cc +++ b/storage/browser/quota/quota_features.cc
@@ -8,15 +8,6 @@ namespace features { -const base::Feature kQuotaExpandPoolSize{"QuotaExpandPoolSize", - base::FEATURE_ENABLED_BY_DEFAULT}; - -constexpr base::FeatureParam<double> kExperimentalPoolSizeRatio{ - &kQuotaExpandPoolSize, "PoolSizeRatio", 0.8}; - -constexpr base::FeatureParam<double> kPerHostRatio{&kQuotaExpandPoolSize, - "PerHostRatio", 0.75}; - // QuotaUnlimitedPoolSize removes limitations around disk space consumption with // respect to client-side storage web platform APIs. When enabled, quota will // set no limit on how much space a single origin can consume, as well as
diff --git a/storage/browser/quota/quota_features.h b/storage/browser/quota/quota_features.h index 1ddc0305..d69cbc6 100644 --- a/storage/browser/quota/quota_features.h +++ b/storage/browser/quota/quota_features.h
@@ -14,11 +14,6 @@ namespace features { COMPONENT_EXPORT(STORAGE_BROWSER) -extern const base::Feature kQuotaExpandPoolSize; -extern const base::FeatureParam<double> kExperimentalPoolSizeRatio; -extern const base::FeatureParam<double> kPerHostRatio; - -COMPONENT_EXPORT(STORAGE_BROWSER) extern const base::Feature kQuotaUnlimitedPoolSize; COMPONENT_EXPORT(STORAGE_BROWSER)
diff --git a/storage/browser/quota/quota_settings.cc b/storage/browser/quota/quota_settings.cc index d5f6709..cdf8882 100644 --- a/storage/browser/quota/quota_settings.cc +++ b/storage/browser/quota/quota_settings.cc
@@ -26,6 +26,8 @@ const int64_t kMBytes = 1024 * 1024; const int kRandomizedPercentage = 10; +const double kDefaultPerHostRatio = 0.75; +const double kDefaultPoolSizeRatio = 0.8; // Skews |value| by +/- |percent|. int64_t RandomizeByPercent(int64_t value, int percent) { @@ -77,7 +79,7 @@ const double kTemporaryPoolSizeRatio = base::FeatureList::IsEnabled(features::kQuotaUnlimitedPoolSize) ? 1.0 - : features::kExperimentalPoolSizeRatio.Get(); + : kDefaultPoolSizeRatio; // The amount of the device's storage the browser attempts to // keep free. If there is less than this amount of storage free @@ -114,7 +116,7 @@ const double kPerHostTemporaryRatio = base::FeatureList::IsEnabled(features::kQuotaUnlimitedPoolSize) ? 1.0 - : features::kPerHostRatio.Get(); + : kDefaultPerHostRatio; // SessionOnly (or ephemeral) origins are allotted a fraction of what // normal origins are provided, and the amount is capped to a hard limit.
diff --git a/storage/browser/quota/quota_settings_unittest.cc b/storage/browser/quota/quota_settings_unittest.cc index 34fb66e..8a8eba2c 100644 --- a/storage/browser/quota/quota_settings_unittest.cc +++ b/storage/browser/quota/quota_settings_unittest.cc
@@ -140,29 +140,6 @@ EXPECT_TRUE(callback_executed); } -TEST_F(QuotaSettingsTest, ExpandedTempPool) { - MockQuotaDeviceInfoHelper device_info_helper; - ON_CALL(device_info_helper, AmountOfTotalDiskSpace(_)) - .WillByDefault(::testing::Return(2000)); - scoped_feature_list_.InitAndEnableFeatureWithParameters( - features::kQuotaExpandPoolSize, - {{"PoolSizeRatio", "0.75"}, {"PerHostRatio", "0.5"}}); - - bool callback_executed = false; - GetNominalDynamicSettings( - profile_path(), false, &device_info_helper, - base::BindLambdaForTesting([&](base::Optional<QuotaSettings> settings) { - callback_executed = true; - ASSERT_NE(settings, base::nullopt); - // 1500 = 2000 * PoolSizeRatio - EXPECT_EQ(settings->pool_size, 1500); - // 750 = 1500 * PerHostRatio - EXPECT_EQ(settings->per_host_quota, 750); - })); - task_environment_.RunUntilIdle(); - EXPECT_TRUE(callback_executed); -} - TEST_F(QuotaSettingsTest, UnlimitedTempPool) { MockQuotaDeviceInfoHelper device_info_helper; ON_CALL(device_info_helper, AmountOfTotalDiskSpace(_))
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index b1e15ab..d3dd3271 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -2959,30 +2959,6 @@ ] } ], - "GamepadPollingInterval": [ - { - "platforms": [ - "windows", - "mac", - "chromeos", - "linux", - "android", - "android_weblayer", - "android_webview" - ], - "experiments": [ - { - "name": "EnabledGamepadPolling250Hz", - "params": { - "interval-ms": "4" - }, - "enable_features": [ - "GamepadPollingInterval" - ] - } - ] - } - ], "GestureNavigation": [ { "platforms": [ @@ -4563,6 +4539,7 @@ "name": "Enabled", "enable_features": [ "DisableSearchSuggestChips", + "IframeOneGoogleBar", "NtpWebUI" ] } @@ -5777,30 +5754,6 @@ ] } ], - "QuotaExpandPoolSize": [ - { - "platforms": [ - "android", - "android_weblayer", - "chromeos", - "linux", - "mac", - "windows" - ], - "experiments": [ - { - "name": "Enabled_Pool_Four_Fifths_Origin_ThreeQuarters_20190710", - "params": { - "PerHostRatio": "0.75", - "PoolSizeRatio": "0.8" - }, - "enable_features": [ - "QuotaExpandPoolSize" - ] - } - ] - } - ], "ReleaseNotesNotification": [ { "platforms": [ @@ -6611,26 +6564,6 @@ ] } ], - "SyncReuploadBookmarkFullTitles": [ - { - "platforms": [ - "android", - "chromeos", - "ios", - "linux", - "mac", - "windows" - ], - "experiments": [ - { - "name": "Enabled", - "enable_features": [ - "SyncReuploadBookmarkFullTitles" - ] - } - ] - } - ], "SyncTriggerFullKeystoreMigration": [ { "platforms": [
diff --git a/third_party/blink/public/mojom/renderer_preferences.mojom b/third_party/blink/public/mojom/renderer_preferences.mojom index c7d1b39..bdfe1ae 100644 --- a/third_party/blink/public/mojom/renderer_preferences.mojom +++ b/third_party/blink/public/mojom/renderer_preferences.mojom
@@ -90,6 +90,10 @@ array<string> webrtc_local_ips_allowed_urls; + // Whether WebRTC peer connections are allowed to use legacy versions of the + // TLS/DTLS protocols. + bool webrtc_allow_legacy_tls_protocols = false; + // The user agent given to WebKit when it requests one and the user agent is // being overridden for the current navigation. UserAgentOverride user_agent_override;
diff --git a/third_party/blink/public/web/web_local_frame_client.h b/third_party/blink/public/web/web_local_frame_client.h index 08804af..069ebc8 100644 --- a/third_party/blink/public/web/web_local_frame_client.h +++ b/third_party/blink/public/web/web_local_frame_client.h
@@ -553,6 +553,9 @@ return nullptr; } + // WebRTC + virtual bool AllowRTCLegacyTLSProtocols() { return false; } + // Encrypted Media ------------------------------------------------- virtual WebEncryptedMediaClient* EncryptedMediaClient() { return nullptr; }
diff --git a/third_party/blink/renderer/bindings/bindings.gni b/third_party/blink/renderer/bindings/bindings.gni index 563db10..deb188d 100644 --- a/third_party/blink/renderer/bindings/bindings.gni +++ b/third_party/blink/renderer/bindings/bindings.gni
@@ -19,7 +19,6 @@ "core/v8/callback_invoke_helper.cc", "core/v8/callback_invoke_helper.h", "core/v8/callback_promise_adapter.h", - "core/v8/classic_evaluation_result.h", "core/v8/custom/v8_custom_xpath_ns_resolver.cc", "core/v8/custom/v8_custom_xpath_ns_resolver.h", "core/v8/custom/v8_dev_tools_host_custom.cc", @@ -78,6 +77,8 @@ "core/v8/script_custom_element_definition_builder.cc", "core/v8/script_custom_element_definition_builder.h", "core/v8/script_custom_element_definition_data.h", + "core/v8/script_evaluation_result.cc", + "core/v8/script_evaluation_result.h", "core/v8/script_event_listener.cc", "core/v8/script_event_listener.h", "core/v8/script_function.cc",
diff --git a/third_party/blink/renderer/bindings/core/v8/classic_evaluation_result.h b/third_party/blink/renderer/bindings/core/v8/classic_evaluation_result.h deleted file mode 100644 index 61edac3..0000000 --- a/third_party/blink/renderer/bindings/core/v8/classic_evaluation_result.h +++ /dev/null
@@ -1,61 +0,0 @@ -// Copyright 2020 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef THIRD_PARTY_BLINK_RENDERER_BINDINGS_CORE_V8_CLASSIC_EVALUATION_RESULT_H_ -#define THIRD_PARTY_BLINK_RENDERER_BINDINGS_CORE_V8_CLASSIC_EVALUATION_RESULT_H_ - -#include "third_party/blink/renderer/bindings/core/v8/script_source_location_type.h" -#include "third_party/blink/renderer/bindings/core/v8/v8_code_cache.h" -#include "third_party/blink/renderer/core/core_export.h" -#include "third_party/blink/renderer/platform/bindings/trace_wrapper_v8_reference.h" -#include "third_party/blink/renderer/platform/loader/fetch/cached_metadata_handler.h" -#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" -#include "third_party/blink/renderer/platform/wtf/text/text_position.h" -#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" -#include "third_party/blink/renderer/platform/wtf/vector.h" -#include "v8/include/v8.h" - -namespace blink { - -// ClassicEvaluationResult encapsulates the result of a classic script -// evaluation. -// - If IsEmpty() is false: -// A script is evaluated successfully. -// No exceptions are thrown. -// GetValue() returns a non-Empty value. -// - If IsEmpty() is true: -// Script evaluation failed (compile error, evaluation error, or so). -// An exception might or might not be thrown in V8. -// Unlike v8::MaybeLocal<>, there are cases where no exceptions are thrown -// to V8 while returning an Empty ClassicEvaluationResult, like when: -// - An exception is thrown during script evaluation but caught and passed -// to https://html.spec.whatwg.org/C/#report-the-error, instead of -// being rethrown, or -// - Script evaluation is skipped due to checks within Blink. -// -// TODO(crbug/1111134): Consider merging with ModuleEvaluationResult later. -// Right now classic and module evaluation paths are not yet merged, and -// top-level await (crbug/1022182) will modify ModuleEvaluationResult. -class CORE_EXPORT ClassicEvaluationResult final { - STACK_ALLOCATED(); - - public: - ClassicEvaluationResult() = default; - explicit ClassicEvaluationResult(v8::Local<v8::Value> value) : value_(value) { - DCHECK(!IsEmpty()); - } - - bool IsEmpty() const { return value_.IsEmpty(); } - v8::Local<v8::Value> GetValue() const { - DCHECK(!IsEmpty()); - return value_; - } - - private: - v8::Local<v8::Value> value_; -}; - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_BINDINGS_CORE_V8_CLASSIC_EVALUATION_RESULT_H_
diff --git a/third_party/blink/renderer/bindings/core/v8/module_record.cc b/third_party/blink/renderer/bindings/core/v8/module_record.cc index f6eaa51..b85a1fc 100644 --- a/third_party/blink/renderer/bindings/core/v8/module_record.cc +++ b/third_party/blink/renderer/bindings/core/v8/module_record.cc
@@ -20,51 +20,6 @@ namespace blink { -// static -ModuleEvaluationResult ModuleEvaluationResult::Empty() { - return ModuleEvaluationResult(true, {}); -} - -// static -ModuleEvaluationResult ModuleEvaluationResult::FromResult( - v8::Local<v8::Value> promise) { - DCHECK(base::FeatureList::IsEnabled(features::kTopLevelAwait) || - promise.IsEmpty()); - DCHECK(!base::FeatureList::IsEnabled(features::kTopLevelAwait) || - promise->IsPromise()); - return ModuleEvaluationResult(true, promise); -} - -// static -ModuleEvaluationResult ModuleEvaluationResult::FromException( - v8::Local<v8::Value> exception) { - DCHECK(!exception.IsEmpty()); - return ModuleEvaluationResult(false, exception); -} - -ModuleEvaluationResult& ModuleEvaluationResult::Escape( - ScriptState::EscapableScope* scope) { - value_ = scope->Escape(value_); - return *this; -} - -v8::Local<v8::Value> ModuleEvaluationResult::GetException() const { - DCHECK(IsException()); - DCHECK(!value_.IsEmpty()); - return value_; -} - -ScriptPromise ModuleEvaluationResult::GetPromise( - ScriptState* script_state) const { - DCHECK(base::FeatureList::IsEnabled(features::kTopLevelAwait)); - DCHECK(!value_.IsEmpty()); - if (IsSuccess()) { - return ScriptPromise(script_state, value_); - } else { - return ScriptPromise::Reject(script_state, value_); - } -} - ModuleRecordProduceCacheData::ModuleRecordProduceCacheData( v8::Isolate* isolate, SingleCachedMetadataHandler* cache_handler, @@ -168,7 +123,7 @@ return ScriptValue(); } -ModuleEvaluationResult ModuleRecord::Evaluate(ScriptState* script_state, +ScriptEvaluationResult ModuleRecord::Evaluate(ScriptState* script_state, v8::Local<v8::Module> record, const KURL& source_url) { v8::Isolate* isolate = script_state->GetIsolate(); @@ -192,13 +147,9 @@ if (!V8ScriptRunner::EvaluateModule(isolate, execution_context, record, script_state->GetContext()) .ToLocal(&result)) { - return ModuleEvaluationResult::FromException(try_catch.Exception()); + return ScriptEvaluationResult::FromModuleException(try_catch.Exception()); } - if (base::FeatureList::IsEnabled(features::kTopLevelAwait)) { - return ModuleEvaluationResult::FromResult(result); - } else { - return ModuleEvaluationResult::Empty(); - } + return ScriptEvaluationResult::FromModuleSuccess(result); } void ModuleRecord::ReportException(ScriptState* script_state,
diff --git a/third_party/blink/renderer/bindings/core/v8/module_record.h b/third_party/blink/renderer/bindings/core/v8/module_record.h index 6a9d5de..36b21f1 100644 --- a/third_party/blink/renderer/bindings/core/v8/module_record.h +++ b/third_party/blink/renderer/bindings/core/v8/module_record.h
@@ -6,6 +6,7 @@ #define THIRD_PARTY_BLINK_RENDERER_BINDINGS_CORE_V8_MODULE_RECORD_H_ #include "third_party/blink/renderer/bindings/core/v8/module_request.h" +#include "third_party/blink/renderer/bindings/core/v8/script_evaluation_result.h" #include "third_party/blink/renderer/bindings/core/v8/script_source_location_type.h" #include "third_party/blink/renderer/bindings/core/v8/v8_code_cache.h" #include "third_party/blink/renderer/core/core_export.h" @@ -24,48 +25,6 @@ class ScriptFetchOptions; class ScriptState; class ScriptValue; -class ScriptPromise; - -// ModuleEvaluationResult encapsulates the result of a module evaluation. -// - Without top-level-await -// - succeed and not return a value, or -// (IsSuccess() == true), no return value is available. -// - throw any object. -// (IsException() == true && GetException()) returns the thrown exception -// - With top-level-await a module can either -// - return a promise, or -// (IsSuccess() == true && GetPromise()) returns a valid ScriptPromise()) -// - throw any object. -// (IsException() == true && GetException()) returns the thrown exception -class CORE_EXPORT ModuleEvaluationResult final { - STACK_ALLOCATED(); - - public: - ModuleEvaluationResult() = delete; - static ModuleEvaluationResult Empty(); - static ModuleEvaluationResult FromResult(v8::Local<v8::Value> promise); - static ModuleEvaluationResult FromException(v8::Local<v8::Value> exception); - - ModuleEvaluationResult(const ModuleEvaluationResult& value) = default; - ModuleEvaluationResult& operator=(const ModuleEvaluationResult& value) = - default; - ~ModuleEvaluationResult() = default; - - ModuleEvaluationResult& Escape(ScriptState::EscapableScope* scope); - - bool IsSuccess() const { return is_success_; } - bool IsException() const { return !is_success_; } - - v8::Local<v8::Value> GetException() const; - ScriptPromise GetPromise(ScriptState* script_state) const; - - private: - ModuleEvaluationResult(bool is_success, v8::Local<v8::Value> value) - : is_success_(is_success), value_(value) {} - - bool is_success_; - v8::Local<v8::Value> value_; -}; // ModuleRecordProduceCacheData is a parameter object for // ModuleRecord::ProduceCache(). @@ -121,7 +80,7 @@ v8::Local<v8::Module> record, const KURL& source_url); - static ModuleEvaluationResult Evaluate(ScriptState*, + static ScriptEvaluationResult Evaluate(ScriptState*, v8::Local<v8::Module> record, const KURL& source_url);
diff --git a/third_party/blink/renderer/bindings/core/v8/module_record_test.cc b/third_party/blink/renderer/bindings/core/v8/module_record_test.cc index efcb338..37a219a 100644 --- a/third_party/blink/renderer/bindings/core/v8/module_record_test.cc +++ b/third_party/blink/renderer/bindings/core/v8/module_record_test.cc
@@ -238,7 +238,7 @@ ASSERT_TRUE(ModuleRecord::Instantiate(scope.GetScriptState(), module_failure, js_url_f) .IsEmpty()); - ModuleEvaluationResult evaluation_result1 = + ScriptEvaluationResult evaluation_result1 = ModuleRecord::Evaluate(scope.GetScriptState(), module_failure, js_url_f); resolver->PrepareMockResolveResult(module_failure); @@ -252,12 +252,14 @@ ASSERT_TRUE( ModuleRecord::Instantiate(scope.GetScriptState(), module, js_url_c) .IsEmpty()); - ModuleEvaluationResult evaluation_result2 = + ScriptEvaluationResult evaluation_result2 = ModuleRecord::Evaluate(scope.GetScriptState(), module, js_url_f); if (base::FeatureList::IsEnabled(features::kTopLevelAwait)) { - EXPECT_TRUE(evaluation_result1.IsSuccess()); - EXPECT_TRUE(evaluation_result2.IsSuccess()); + EXPECT_EQ(evaluation_result1.GetResultType(), + ScriptEvaluationResult::ResultType::kSuccess); + EXPECT_EQ(evaluation_result2.GetResultType(), + ScriptEvaluationResult::ResultType::kSuccess); ScriptValue value1; ScriptValue value2; @@ -273,10 +275,12 @@ EXPECT_FALSE(value2.IsEmpty()); EXPECT_EQ(value1, value2); } else { - EXPECT_TRUE(evaluation_result1.IsException()); - EXPECT_TRUE(evaluation_result2.IsException()); - EXPECT_EQ(evaluation_result1.GetException(), - evaluation_result2.GetException()); + EXPECT_EQ(evaluation_result1.GetResultType(), + ScriptEvaluationResult::ResultType::kException); + EXPECT_EQ(evaluation_result2.GetResultType(), + ScriptEvaluationResult::ResultType::kException); + EXPECT_EQ(evaluation_result1.GetExceptionForModule(), + evaluation_result2.GetExceptionForModule()); } ASSERT_EQ(1u, resolver->ResolveCount()); @@ -300,8 +304,9 @@ ModuleRecord::Instantiate(scope.GetScriptState(), module, js_url); ASSERT_TRUE(exception.IsEmpty()); - EXPECT_TRUE(ModuleRecord::Evaluate(scope.GetScriptState(), module, js_url) - .IsSuccess()); + EXPECT_EQ(ModuleRecord::Evaluate(scope.GetScriptState(), module, js_url) + .GetResultType(), + ScriptEvaluationResult::ResultType::kSuccess); v8::Local<v8::Value> value = ClassicScript::CreateUnspecifiedScript(ScriptSourceCode("window.foo")) ->RunScriptAndReturnValue(&scope.GetFrame()); @@ -334,12 +339,13 @@ ModuleRecord::Instantiate(scope.GetScriptState(), module, js_url); ASSERT_TRUE(exception.IsEmpty()); - ModuleEvaluationResult result = + ScriptEvaluationResult result = ModuleRecord::Evaluate(scope.GetScriptState(), module, js_url); v8::Local<v8::Value> value; if (base::FeatureList::IsEnabled(features::kTopLevelAwait)) { - ASSERT_TRUE(result.IsSuccess()); + ASSERT_EQ(result.GetResultType(), + ScriptEvaluationResult::ResultType::kSuccess); ScriptValue script_value; result.GetPromise(scope.GetScriptState()) .Then(v8::Local<v8::Function>(), @@ -350,8 +356,9 @@ EXPECT_FALSE(script_value.IsEmpty()); value = script_value.V8Value(); } else { - ASSERT_TRUE(result.IsException()); - value = result.GetException(); + ASSERT_EQ(result.GetResultType(), + ScriptEvaluationResult::ResultType::kException); + value = result.GetExceptionForModule(); } ASSERT_TRUE(value->IsString()); EXPECT_EQ("bar", ToCoreString(v8::Local<v8::String>::Cast(value)));
diff --git a/third_party/blink/renderer/bindings/core/v8/script_evaluation_result.cc b/third_party/blink/renderer/bindings/core/v8/script_evaluation_result.cc new file mode 100644 index 0000000..b9241cb --- /dev/null +++ b/third_party/blink/renderer/bindings/core/v8/script_evaluation_result.cc
@@ -0,0 +1,127 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/blink/renderer/bindings/core/v8/script_evaluation_result.h" + +#include "base/feature_list.h" +#include "third_party/blink/public/common/features.h" +#include "third_party/blink/public/mojom/script/script_type.mojom-blink.h" +#include "third_party/blink/renderer/bindings/core/v8/script_promise.h" +#include "third_party/blink/renderer/platform/bindings/exception_state.h" + +namespace blink { + +ScriptEvaluationResult::ScriptEvaluationResult( + mojom::blink::ScriptType script_type, + ResultType result_type, + v8::Local<v8::Value> value) + : +#if DCHECK_IS_ON() + script_type_(script_type), +#endif + result_type_(result_type), + value_(value) { +} + +// static +ScriptEvaluationResult ScriptEvaluationResult::FromClassicNotRun() { + return ScriptEvaluationResult(mojom::blink::ScriptType::kClassic, + ResultType::kNotRun, {}); +} + +// static +ScriptEvaluationResult ScriptEvaluationResult::FromModuleNotRun() { + return ScriptEvaluationResult(mojom::blink::ScriptType::kModule, + ResultType::kNotRun, {}); +} + +// static +ScriptEvaluationResult ScriptEvaluationResult::FromClassicSuccess( + v8::Local<v8::Value> value) { + DCHECK(!value.IsEmpty()); + return ScriptEvaluationResult(mojom::blink::ScriptType::kClassic, + ResultType::kSuccess, value); +} + +// static +ScriptEvaluationResult ScriptEvaluationResult::FromModuleSuccess( + v8::Local<v8::Value> value) { + DCHECK(!value.IsEmpty()); + DCHECK(!base::FeatureList::IsEnabled(features::kTopLevelAwait) || + value->IsPromise()); + + return ScriptEvaluationResult(mojom::blink::ScriptType::kModule, + ResultType::kSuccess, value); +} + +// static +ScriptEvaluationResult ScriptEvaluationResult::FromClassicException() { + return ScriptEvaluationResult(mojom::blink::ScriptType::kClassic, + ResultType::kException, {}); +} + +// static +ScriptEvaluationResult ScriptEvaluationResult::FromModuleException( + v8::Local<v8::Value> exception) { + DCHECK(!exception.IsEmpty()); + return ScriptEvaluationResult(mojom::blink::ScriptType::kModule, + ResultType::kException, exception); +} + +// static +ScriptEvaluationResult ScriptEvaluationResult::FromClassicAborted() { + return ScriptEvaluationResult(mojom::blink::ScriptType::kClassic, + ResultType::kAborted, {}); +} + +// static +ScriptEvaluationResult ScriptEvaluationResult::FromModuleAborted() { + return ScriptEvaluationResult(mojom::blink::ScriptType::kModule, + ResultType::kAborted, {}); +} + +ScriptEvaluationResult& ScriptEvaluationResult::Escape( + ScriptState::EscapableScope* scope) { + value_ = scope->Escape(value_); + return *this; +} + +v8::Local<v8::Value> ScriptEvaluationResult::GetSuccessValue() const { + DCHECK_EQ(result_type_, ResultType::kSuccess); + DCHECK(!value_.IsEmpty()); + return value_; +} + +v8::Local<v8::Value> ScriptEvaluationResult::GetExceptionForModule() const { +#if DCHECK_IS_ON() + DCHECK_EQ(script_type_, mojom::blink::ScriptType::kModule); +#endif + DCHECK_EQ(result_type_, ResultType::kException); + DCHECK(!value_.IsEmpty()); + + return value_; +} + +ScriptPromise ScriptEvaluationResult::GetPromise( + ScriptState* script_state) const { + DCHECK(base::FeatureList::IsEnabled(features::kTopLevelAwait)); +#if DCHECK_IS_ON() + DCHECK_EQ(script_type_, mojom::blink::ScriptType::kModule); +#endif + + switch (result_type_) { + case ResultType::kSuccess: + return ScriptPromise(script_state, GetSuccessValue()); + + case ResultType::kException: + return ScriptPromise::Reject(script_state, GetExceptionForModule()); + + case ResultType::kNotRun: + case ResultType::kAborted: + NOTREACHED(); + return ScriptPromise::Reject(script_state, v8::Local<v8::Value>()); + } +} + +} // namespace blink
diff --git a/third_party/blink/renderer/bindings/core/v8/script_evaluation_result.h b/third_party/blink/renderer/bindings/core/v8/script_evaluation_result.h new file mode 100644 index 0000000..f31b03e --- /dev/null +++ b/third_party/blink/renderer/bindings/core/v8/script_evaluation_result.h
@@ -0,0 +1,135 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef THIRD_PARTY_BLINK_RENDERER_BINDINGS_CORE_V8_SCRIPT_EVALUATION_RESULT_H_ +#define THIRD_PARTY_BLINK_RENDERER_BINDINGS_CORE_V8_SCRIPT_EVALUATION_RESULT_H_ + +#include "third_party/blink/public/mojom/script/script_type.mojom-blink-forward.h" +#include "third_party/blink/renderer/core/core_export.h" +#include "third_party/blink/renderer/platform/bindings/script_state.h" +#include "v8/include/v8.h" + +namespace blink { + +class ScriptPromise; + +// ScriptEvaluationResult encapsulates the result of a classic or module script +// evaluation: +// - https://html.spec.whatwg.org/C/#run-a-classic-script +// - https://html.spec.whatwg.org/C/#run-a-module-script +// +// Note: Top-level await (TLA, https://github.com/whatwg/html/pull/4352) will +// affect the semantics where mentioned below. +class CORE_EXPORT ScriptEvaluationResult final { + STACK_ALLOCATED(); + + public: + ScriptEvaluationResult() = delete; + ScriptEvaluationResult(const ScriptEvaluationResult& value) = default; + ScriptEvaluationResult& operator=(const ScriptEvaluationResult& value) = + default; + ~ScriptEvaluationResult() = default; + + enum class ResultType { + // The script is not evaluated. + // Spec: NormalCompletion with empty [[Value]] + // |value_| is empty. + kNotRun, + + // The script is successfully evaluated. + // Spec: #run-a-classic-script/#run-a-module-script return + // NormalCompletion with non-empty [[Value]]. + // |value_| is its non-empty [[Value]]. + // + // Modules after TLA: + // |value_| is the promise returned by #run-a-module-script. + // Note: The promise can be rejected. + // The script is either: + // - Successfully evaluated synchronously + // (|value_|'s [[PromiseState]] is fulfilled), or + // - Throwing synchronously during evaluation + // (|value_|'s [[PromiseState]] is rejected), or + // - Successfully evaluated until a top-level await and is waiting for the + // promise awaited + // (|value_|'s [[PromiseState]] is pending). + kSuccess, + + // The script is evaluated and an exception is thrown. + // Spec: #run-a-classic-script/#run-a-module-script return an abrupt + // completion. + // |value_| is the non-empty exception thrown for module scripts, or + // empty for classic scripts. + // + // Note: The exception can be already caught and passed to + // https://html.spec.whatwg.org/C/#report-the-error, instead of being + // rethrown. + // + // Modules after TLA: #run-a-module-script returns a promise where + // [[PromiseState]] is rejected and [[PromiseResult]] is |value_|, + // only if #concept-script-error-to-rethrow is not null, i.e. + // only for parse/instantiation errors. + // Module scripts throwing synchronously during evaluation return kSuccess. + // TODO(cbruni, hiroshige): Consider cleaning up this semantics. + kException, + + // The script is evaluated and aborted prematurely by + // #abort-a-running-script. + // |value_| is empty. + // This corresponds to that TryCatch::CanContinue() is false, and currently + // only checked in classic scripts in WorkerOrWorkletGlobalScope, for + // handling e.g. + // worker.terminate(). + // TODO(crbug.com/1129793): Check TryCatch::CanContinue() also in module + // scripts. + kAborted + }; + + static ScriptEvaluationResult FromClassicNotRun(); + static ScriptEvaluationResult FromClassicSuccess(v8::Local<v8::Value> value); + static ScriptEvaluationResult FromClassicException(); + static ScriptEvaluationResult FromClassicAborted(); + + static ScriptEvaluationResult FromModuleNotRun(); + static ScriptEvaluationResult FromModuleSuccess(v8::Local<v8::Value> value); + static ScriptEvaluationResult FromModuleException( + v8::Local<v8::Value> exception); + static ScriptEvaluationResult FromModuleAborted(); + + ScriptEvaluationResult& Escape(ScriptState::EscapableScope* scope); + + ResultType GetResultType() const { return result_type_; } + + // Can be called only when GetResultType() == kSuccess. + // TODO(crbug.com/1132793): Fix some of the callers (in unit tests) that + // expect bool, string, etc., because after TLA is enabled this will return a + // promise for modules. + v8::Local<v8::Value> GetSuccessValue() const; + + // Returns the exception thrown. + // Can be called only when GetResultType() == kException. + v8::Local<v8::Value> GetExceptionForModule() const; + + // Returns the promise returned by #run-a-module-script. + // Can be called only + // - For module script with TLA is enabled, and + // - If GetResultType() == kSuccess or kException. + // (For kNotRun/kAborted, we should do nothing) + ScriptPromise GetPromise(ScriptState* script_state) const; + + private: + ScriptEvaluationResult(mojom::blink::ScriptType, + ResultType, + v8::Local<v8::Value>); + +#if DCHECK_IS_ON() + mojom::blink::ScriptType script_type_; +#endif + + ResultType result_type_; + v8::Local<v8::Value> value_; +}; + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_BINDINGS_CORE_V8_SCRIPT_EVALUATION_RESULT_H_
diff --git a/third_party/blink/renderer/bindings/core/v8/v8_initializer.cc b/third_party/blink/renderer/bindings/core/v8/v8_initializer.cc index 211ea70..3c7a7a56 100644 --- a/third_party/blink/renderer/bindings/core/v8/v8_initializer.cc +++ b/third_party/blink/renderer/bindings/core/v8/v8_initializer.cc
@@ -355,11 +355,6 @@ v8::Local<v8::Context> context, v8::Local<v8::String> source) { if (ExecutionContext* execution_context = ToExecutionContext(context)) { - DCHECK(execution_context->IsWindow() || - execution_context->IsMainThreadWorkletGlobalScope()); - - v8::Context::Scope scope(context); - // Note this callback is only triggered for contexts which have eval // disabled. Hence we don't need to handle the case of isolated world // contexts with no CSP specified. (They should be exempt from the page CSP. @@ -367,6 +362,7 @@ if (ContentSecurityPolicy* policy = execution_context->GetContentSecurityPolicyForCurrentWorld()) { + v8::Context::Scope scope(context); v8::String::Value source_str(context->GetIsolate(), source); UChar snippet[ContentSecurityPolicy::kMaxSampleLength + 1]; size_t len = std::min((sizeof(snippet) / sizeof(UChar)) - 1, @@ -786,6 +782,8 @@ isolate->SetStackLimit(WTF::GetCurrentStackPosition() - kWorkerMaxStackSize); isolate->SetPromiseRejectCallback(PromiseRejectHandlerInWorker); + isolate->SetModifyCodeGenerationFromStringsCallback( + CodeGenerationCheckCallbackInMainThread); } } // namespace blink
diff --git a/third_party/blink/renderer/bindings/core/v8/worker_or_worklet_script_controller.cc b/third_party/blink/renderer/bindings/core/v8/worker_or_worklet_script_controller.cc index 4443d82..dc9b7f4f 100644 --- a/third_party/blink/renderer/bindings/core/v8/worker_or_worklet_script_controller.cc +++ b/third_party/blink/renderer/bindings/core/v8/worker_or_worklet_script_controller.cc
@@ -312,13 +312,14 @@ } // https://html.spec.whatwg.org/C/#run-a-classic-script -ClassicEvaluationResult WorkerOrWorkletScriptController::EvaluateAndReturnValue( +ScriptEvaluationResult WorkerOrWorkletScriptController::EvaluateAndReturnValue( const ScriptSourceCode& source_code, SanitizeScriptErrors sanitize_script_errors, mojom::blink::V8CacheOptions v8_cache_options, RethrowErrorsOption rethrow_errors) { - if (IsExecutionForbidden()) - return ClassicEvaluationResult(); + if (IsExecutionForbidden()) { + return ScriptEvaluationResult::FromClassicNotRun(); + } // Scope for |TRACE_EVENT1| and |v8::TryCatch| below. { @@ -368,7 +369,7 @@ // script evaluation code paths. if (!block.CanContinue()) { ForbidExecution(); - return ClassicEvaluationResult(); + return ScriptEvaluationResult::FromClassicAborted(); } CHECK(!IsExecutionForbidden()); @@ -377,10 +378,9 @@ // Step 10. If evaluationStatus is a normal completion, then return // evaluationStatus. [spec text] v8::Local<v8::Value> result; - if (!maybe_result.ToLocal(&result)) - return ClassicEvaluationResult(); - - return ClassicEvaluationResult(result); + bool success = maybe_result.ToLocal(&result); + DCHECK(success); + return ScriptEvaluationResult::FromClassicSuccess(result); } DCHECK(maybe_result.IsEmpty()); @@ -398,7 +398,7 @@ // reported to WorkerGlobalScope.onerror via `TryCatch::SetVerbose(true)` // called at top-level worker script evaluation. block.ReThrow(); - return ClassicEvaluationResult(); + return ScriptEvaluationResult::FromClassicException(); } } // |v8::TryCatch| is (and should be) exited, before ThrowException() below. @@ -418,12 +418,12 @@ isolate_, V8ThrowDOMException::CreateOrEmpty( isolate_, DOMExceptionCode::kNetworkError, rethrow_errors.Message())); - return ClassicEvaluationResult(); + return ScriptEvaluationResult::FromClassicException(); } // #report-the-error for rethrow errors == true is already handled via // |TryCatch::SetVerbose(true)| above. - return ClassicEvaluationResult(); + return ScriptEvaluationResult::FromClassicException(); } void WorkerOrWorkletScriptController::ForbidExecution() {
diff --git a/third_party/blink/renderer/bindings/core/v8/worker_or_worklet_script_controller.h b/third_party/blink/renderer/bindings/core/v8/worker_or_worklet_script_controller.h index 14ce99f..5ab5e584 100644 --- a/third_party/blink/renderer/bindings/core/v8/worker_or_worklet_script_controller.h +++ b/third_party/blink/renderer/bindings/core/v8/worker_or_worklet_script_controller.h
@@ -33,9 +33,9 @@ #include "base/macros.h" #include "third_party/blink/public/mojom/v8_cache_options.mojom-blink.h" -#include "third_party/blink/renderer/bindings/core/v8/classic_evaluation_result.h" #include "third_party/blink/renderer/bindings/core/v8/rejected_promises.h" #include "third_party/blink/renderer/bindings/core/v8/sanitize_script_errors.h" +#include "third_party/blink/renderer/bindings/core/v8/script_evaluation_result.h" #include "third_party/blink/renderer/bindings/core/v8/script_value.h" #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h" #include "third_party/blink/renderer/core/core_export.h" @@ -96,7 +96,7 @@ // https://html.spec.whatwg.org/C/#run-a-classic-script // Callers should enter ScriptState::Scope before calling this. - ClassicEvaluationResult EvaluateAndReturnValue( + ScriptEvaluationResult EvaluateAndReturnValue( const ScriptSourceCode&, SanitizeScriptErrors sanitize_script_errors, mojom::blink::V8CacheOptions = mojom::blink::V8CacheOptions::kDefault,
diff --git a/third_party/blink/renderer/core/css/view-source.css b/third_party/blink/renderer/core/css/view-source.css index 699f4b0..3ed9294 100644 --- a/third_party/blink/renderer/core/css/view-source.css +++ b/third_party/blink/renderer/core/css/view-source.css
@@ -27,7 +27,7 @@ } table { - width: 100%; + width: max-content; border-spacing: 0; white-space: pre; margin: 0;
diff --git a/third_party/blink/renderer/core/display_lock/display_lock_context.cc b/third_party/blink/renderer/core/display_lock/display_lock_context.cc index 3edb10e..968b50a9 100644 --- a/third_party/blink/renderer/core/display_lock/display_lock_context.cc +++ b/third_party/blink/renderer/core/display_lock/display_lock_context.cc
@@ -395,14 +395,17 @@ DCHECK(IsLocked()); DCHECK(ShouldCommitForActivation(DisplayLockActivationReason::kAny)); - // Find in page scrolls content into view. However, if the position of the - // target is outside of the bounds that would cause the auto-context to - // unlock, then we can scroll into wrong content while the context remains - // lock. To avoid this, unlock it until the next lifecycle. If the scroll is - // successful, then we will gain visibility anyway so the context will be - // unlocked for other reasons. - // TODO(vmpstr): See if scrollIntoView() needs this as well. - if (reason == DisplayLockActivationReason::kFindInPage) { + // The following actions (can) scroll content into view. However, if the + // position of the target is outside of the bounds that would cause the + // auto-context to unlock, then we can scroll into wrong content while the + // context remains lock. To avoid this, unlock it until the next lifecycle. + // If the scroll is successful, then we will gain visibility anyway so the + // context will be unlocked for other reasons. + if (reason == DisplayLockActivationReason::kAccessibility || + reason == DisplayLockActivationReason::kFindInPage || + reason == DisplayLockActivationReason::kFragmentNavigation || + reason == DisplayLockActivationReason::kScrollIntoView || + reason == DisplayLockActivationReason::kSimulatedClick) { // Note that because the visibility is only determined at the _end_ of the // next frame, we need to ensure that we stay unlocked for two frames. SetKeepUnlockedUntilLifecycleCount(2);
diff --git a/third_party/blink/renderer/core/html/forms/html_input_element.cc b/third_party/blink/renderer/core/html/forms/html_input_element.cc index 240a846..e73c739 100644 --- a/third_party/blink/renderer/core/html/forms/html_input_element.cc +++ b/third_party/blink/renderer/core/html/forms/html_input_element.cc
@@ -1966,6 +1966,14 @@ return input_type_->SupportsInputModeAttribute(); } +void HTMLInputElement::CapsLockStateMayHaveChanged() { + input_type_view_->CapsLockStateMayHaveChanged(); +} + +bool HTMLInputElement::ShouldDrawCapsLockIndicator() const { + return input_type_view_->ShouldDrawCapsLockIndicator(); +} + void HTMLInputElement::SetShouldRevealPassword(bool value) { if (!!should_reveal_password_ == value) return;
diff --git a/third_party/blink/renderer/core/html/forms/html_input_element.h b/third_party/blink/renderer/core/html/forms/html_input_element.h index 04857422..b8eaae0 100644 --- a/third_party/blink/renderer/core/html/forms/html_input_element.h +++ b/third_party/blink/renderer/core/html/forms/html_input_element.h
@@ -316,6 +316,8 @@ bool SupportsInputModeAttribute() const; + void CapsLockStateMayHaveChanged(); + bool ShouldDrawCapsLockIndicator() const; void SetShouldRevealPassword(bool value); bool ShouldRevealPassword() const { return should_reveal_password_; } AXObject* PopupRootAXObject();
diff --git a/third_party/blink/renderer/core/html/forms/input_type_view.cc b/third_party/blink/renderer/core/html/forms/input_type_view.cc index e5251f5..8819c83 100644 --- a/third_party/blink/renderer/core/html/forms/input_type_view.cc +++ b/third_party/blink/renderer/core/html/forms/input_type_view.cc
@@ -180,6 +180,12 @@ void InputTypeView::ListAttributeTargetChanged() {} +void InputTypeView::CapsLockStateMayHaveChanged() {} + +bool InputTypeView::ShouldDrawCapsLockIndicator() const { + return false; +} + void InputTypeView::UpdateClearButtonVisibility() {} void InputTypeView::UpdatePlaceholderText() {}
diff --git a/third_party/blink/renderer/core/html/forms/input_type_view.h b/third_party/blink/renderer/core/html/forms/input_type_view.h index ad0d260..f2a5ed4 100644 --- a/third_party/blink/renderer/core/html/forms/input_type_view.h +++ b/third_party/blink/renderer/core/html/forms/input_type_view.h
@@ -132,6 +132,8 @@ virtual void ValueAttributeChanged(); virtual void DidSetValue(const String&, bool value_changed); virtual void ListAttributeTargetChanged(); + virtual void CapsLockStateMayHaveChanged(); + virtual bool ShouldDrawCapsLockIndicator() const; virtual void UpdateClearButtonVisibility(); virtual void UpdatePlaceholderText(); virtual AXObject* PopupRootAXObject();
diff --git a/third_party/blink/renderer/core/html/forms/password_input_type.cc b/third_party/blink/renderer/core/html/forms/password_input_type.cc index 92f00a1f..bdc7976 100644 --- a/third_party/blink/renderer/core/html/forms/password_input_type.cc +++ b/third_party/blink/renderer/core/html/forms/password_input_type.cc
@@ -43,6 +43,7 @@ #include "third_party/blink/renderer/core/html/forms/form_controller.h" #include "third_party/blink/renderer/core/html/forms/html_input_element.h" #include "third_party/blink/renderer/core/html/shadow/shadow_element_names.h" +#include "third_party/blink/renderer/core/input/keyboard_event_manager.h" #include "third_party/blink/renderer/core/input_type_names.h" #include "third_party/blink/renderer/core/layout/layout_text_control_single_line.h" #include "third_party/blink/renderer/platform/wtf/assertions.h" @@ -126,6 +127,30 @@ UpdatePasswordRevealButton(); } +void PasswordInputType::CapsLockStateMayHaveChanged() { + auto& document = GetElement().GetDocument(); + LocalFrame* frame = document.GetFrame(); + // Only draw the caps lock indicator if these things are true: + // 1) The field is a password field + // 2) The frame is active + // 3) The element is focused + // 4) The caps lock is on + const bool should_draw_caps_lock_indicator = + frame && frame->Selection().FrameIsFocusedAndActive() && + document.FocusedElement() == GetElement() && + KeyboardEventManager::CurrentCapsLockState(); + + if (should_draw_caps_lock_indicator != should_draw_caps_lock_indicator_) { + should_draw_caps_lock_indicator_ = should_draw_caps_lock_indicator; + if (auto* layout_object = GetElement().GetLayoutObject()) + layout_object->SetShouldDoFullPaintInvalidation(); + } +} + +bool PasswordInputType::ShouldDrawCapsLockIndicator() const { + return should_draw_caps_lock_indicator_; +} + void PasswordInputType::UpdatePasswordRevealButton() { Element* button = GetElement().UserAgentShadowRoot()->getElementById( shadow_element_names::kIdPasswordRevealButton); @@ -163,6 +188,16 @@ } } +void PasswordInputType::ForwardEvent(Event& event) { + BaseTextInputType::ForwardEvent(event); + + if (GetElement().GetLayoutObject() && + !GetElement().GetForceReattachLayoutTree() && + (event.type() == event_type_names::kBlur || + event.type() == event_type_names::kFocus)) + CapsLockStateMayHaveChanged(); +} + void PasswordInputType::HandleBlurEvent() { if (RuntimeEnabledFeatures::PasswordRevealEnabled()) { should_show_reveal_button_ = false;
diff --git a/third_party/blink/renderer/core/html/forms/password_input_type.h b/third_party/blink/renderer/core/html/forms/password_input_type.h index 8dff1f7..5ac3317 100644 --- a/third_party/blink/renderer/core/html/forms/password_input_type.h +++ b/third_party/blink/renderer/core/html/forms/password_input_type.h
@@ -54,16 +54,20 @@ void CreateShadowSubtree() override; void UpdateView() override; + void CapsLockStateMayHaveChanged() override; + bool ShouldDrawCapsLockIndicator() const override; void UpdatePasswordRevealButton(); void DidSetValueByUserEdit() override; void DidSetValue(const String&, bool value_changed) override; + void ForwardEvent(Event& event) override; void HandleKeydownEvent(KeyboardEvent&) override; void HandleBeforeTextInsertedEvent(BeforeTextInsertedEvent&) override; void HandleBlurEvent() override; bool SupportsInputModeAttribute() const override; + bool should_draw_caps_lock_indicator_ = false; bool should_show_reveal_button_ = false; };
diff --git a/third_party/blink/renderer/core/html/forms/text_field_input_type.cc b/third_party/blink/renderer/core/html/forms/text_field_input_type.cc index b0e6c4b..b7938ca 100644 --- a/third_party/blink/renderer/core/html/forms/text_field_input_type.cc +++ b/third_party/blink/renderer/core/html/forms/text_field_input_type.cc
@@ -239,8 +239,6 @@ event.HasInterface(event_interface_names::kWheelEvent) || event.type() == event_type_names::kBlur || event.type() == event_type_names::kFocus)) { - auto* layout_text_control = - To<LayoutTextControlSingleLine>(GetElement().GetLayoutObject()); if (event.type() == event_type_names::kBlur) { if (LayoutBox* inner_editor_layout_object = GetElement().InnerEditorElement()->GetLayoutBox()) { @@ -253,10 +251,6 @@ } } } - - layout_text_control->CapsLockStateMayHaveChanged(); - } else if (event.type() == event_type_names::kFocus) { - layout_text_control->CapsLockStateMayHaveChanged(); } GetElement().ForwardEvent(event);
diff --git a/third_party/blink/renderer/core/html/forms/text_field_input_type.h b/third_party/blink/renderer/core/html/forms/text_field_input_type.h index 645df53..4f24cb60 100644 --- a/third_party/blink/renderer/core/html/forms/text_field_input_type.h +++ b/third_party/blink/renderer/core/html/forms/text_field_input_type.h
@@ -58,6 +58,7 @@ void DisabledAttributeChanged() override; void ReadonlyAttributeChanged() override; bool SupportsReadOnly() const override; + void ForwardEvent(Event&) override; void HandleBlurEvent() override; void HandleBeforeTextInsertedEvent(BeforeTextInsertedEvent&) override; String SanitizeValue(const String&) const override; @@ -84,7 +85,6 @@ bool MayTriggerVirtualKeyboard() const final; bool IsTextField() const final; bool ValueMissing(const String&) const override; - void ForwardEvent(Event&) final; bool ShouldSubmitImplicitly(const Event&) final; bool ShouldRespectListAttribute() override; void ListAttributeTargetChanged() override;
diff --git a/third_party/blink/renderer/core/html/html_view_source_document.cc b/third_party/blink/renderer/core/html/html_view_source_document.cc index 3176975..797ff5d1 100644 --- a/third_party/blink/renderer/core/html/html_view_source_document.cc +++ b/third_party/blink/renderer/core/html/html_view_source_document.cc
@@ -70,7 +70,6 @@ body->ParserAppendChild(div); auto* table = MakeGarbageCollected<HTMLTableElement>(*this); - table->SetInlineStyleProperty(CSSPropertyID::kWhiteSpace, CSSValueID::kPre); body->ParserAppendChild(table); tbody_ = MakeGarbageCollected<HTMLTableSectionElement>(html_names::kTbodyTag, *this);
diff --git a/third_party/blink/renderer/core/html/html_view_source_document_test.cc b/third_party/blink/renderer/core/html/html_view_source_document_test.cc index 391645e..8110668 100644 --- a/third_party/blink/renderer/core/html/html_view_source_document_test.cc +++ b/third_party/blink/renderer/core/html/html_view_source_document_test.cc
@@ -38,8 +38,7 @@ EXPECT_EQ( GetDocument().documentElement()->outerHTML(), "<html><head></head><body><div " - "class=\"line-gutter-backdrop\"></div><table style=\"white-space: " - "pre;\"><tbody><tr><td " + "class=\"line-gutter-backdrop\"></div><table><tbody><tr><td " "class=\"line-number\" value=\"1\"></td><td " "class=\"line-content\"><br></td></tr><tr><td class=\"line-number\" " "value=\"2\"></td><td class=\"line-content\"> <span " @@ -92,8 +91,7 @@ EXPECT_EQ( GetDocument().documentElement()->outerHTML(), "<html><head></head><body><div " - "class=\"line-gutter-backdrop\"></div><table style=\"white-space: " - "pre;\"><tbody><tr><td " + "class=\"line-gutter-backdrop\"></div><table><tbody><tr><td " "class=\"line-number\" value=\"1\"></td><td " "class=\"line-content\"><br></td></tr><tr><td class=\"line-number\" " "value=\"2\"></td><td class=\"line-content\"> <span " @@ -145,8 +143,7 @@ EXPECT_EQ( GetDocument().documentElement()->outerHTML(), "<html><head></head><body><div " - "class=\"line-gutter-backdrop\"></div><table style=\"white-space: " - "pre;\"><tbody><tr><td " + "class=\"line-gutter-backdrop\"></div><table><tbody><tr><td " "class=\"line-number\" value=\"1\"></td><td " "class=\"line-content\"><br></td></tr><tr><td class=\"line-number\" " "value=\"2\"></td><td class=\"line-content\"> <span " @@ -211,8 +208,7 @@ EXPECT_EQ( GetDocument().documentElement()->outerHTML(), "<html><head></head><body><div " - "class=\"line-gutter-backdrop\"></div><table style=\"white-space: " - "pre;\"><tbody><tr><td " + "class=\"line-gutter-backdrop\"></div><table><tbody><tr><td " "class=\"line-number\" value=\"1\"></td><td " "class=\"line-content\"><br></td></tr><tr><td class=\"line-number\" " "value=\"2\"></td><td class=\"line-content\"> <span " @@ -280,8 +276,7 @@ EXPECT_EQ( GetDocument().documentElement()->outerHTML(), "<html><head></head><body><div " - "class=\"line-gutter-backdrop\"></div><table style=\"white-space: " - "pre;\"><tbody><tr><td " + "class=\"line-gutter-backdrop\"></div><table><tbody><tr><td " "class=\"line-number\" value=\"1\"></td><td " "class=\"line-content\"><br></td></tr><tr><td class=\"line-number\" " "value=\"2\"></td><td class=\"line-content\"><br></td></tr><tr><td " @@ -313,8 +308,7 @@ LoadMainResource((many_spaces + std::string(" <b>A</b> ")).c_str()); std::string expected_beginning( "<html><head></head><body><div " - "class=\"line-gutter-backdrop\"></div><table style=\"white-space: " - "pre;\"><tbody><tr><td " + "class=\"line-gutter-backdrop\"></div><table><tbody><tr><td " "class=\"line-number\" value=\"1\"></td><td class=\"line-content\"> " " "); std::string expected_ending( @@ -330,8 +324,7 @@ LoadMainResource("1234567"); EXPECT_EQ(GetDocument().documentElement()->outerHTML(), "<html><head></head><body><div " - "class=\"line-gutter-backdrop\"></div><table style=\"white-space: " - "pre;\"><tbody><tr><td " + "class=\"line-gutter-backdrop\"></div><table><tbody><tr><td " "class=\"line-number\" value=\"1\"></td><td " "class=\"line-content\">1234567<span " "class=\"html-end-of-file\"></span></td></tr></tbody></table></" @@ -353,8 +346,7 @@ EXPECT_EQ( GetDocument().documentElement()->outerHTML(), "<html><head></head><body><div " - "class=\"line-gutter-backdrop\"></div><table style=\"white-space: " - "pre;\"><tbody><tr><td " + "class=\"line-gutter-backdrop\"></div><table><tbody><tr><td " "class=\"line-number\" value=\"1\"></td><td " "class=\"line-content\"><br></td></tr><tr><td class=\"line-number\" " "value=\"2\"></td><td class=\"line-content\"> <span " @@ -421,8 +413,7 @@ EXPECT_EQ( GetDocument().documentElement()->outerHTML(), "<html><head></head><body><div " - "class=\"line-gutter-backdrop\"></div><table style=\"white-space: " - "pre;\"><tbody><tr><td " + "class=\"line-gutter-backdrop\"></div><table><tbody><tr><td " "class=\"line-number\" value=\"1\"></td><td " "class=\"line-content\"><br></td></tr><tr><td class=\"line-number\" " "value=\"2\"></td><td class=\"line-content\"> <span " @@ -453,8 +444,7 @@ EXPECT_EQ( GetDocument().documentElement()->outerHTML(), "<html><head></head><body><div " - "class=\"line-gutter-backdrop\"></div><table style=\"white-space: " - "pre;\"><tbody><tr><td " + "class=\"line-gutter-backdrop\"></div><table><tbody><tr><td " "class=\"line-number\" value=\"1\"></td><td " "class=\"line-content\"><br></td></tr><tr><td class=\"line-number\" " "value=\"2\"></td><td class=\"line-content\"> Incomplete token " @@ -476,8 +466,7 @@ EXPECT_EQ( GetDocument().documentElement()->outerHTML(), "<html><head></head><body><div " - "class=\"line-gutter-backdrop\"></div><table style=\"white-space: " - "pre;\"><tbody><tr><td " + "class=\"line-gutter-backdrop\"></div><table><tbody><tr><td " "class=\"line-number\" value=\"1\"></td><td class=\"line-content\"><span " "class=\"html-tag\"><textarea></span>foobar in " "textarea</td></tr><tr><td class=\"line-number\" value=\"2\"></td><td " @@ -492,8 +481,7 @@ EXPECT_EQ( GetDocument().documentElement()->outerHTML(), "<html><head></head><body><div " - "class=\"line-gutter-backdrop\"></div><table style=\"white-space: " - "pre;\"><tbody><tr><td " + "class=\"line-gutter-backdrop\"></div><table><tbody><tr><td " "class=\"line-number\" value=\"1\"></td><td class=\"line-content\"><span " "class=\"html-tag\"><script></span>foobar in " "script</td></tr><tr><td class=\"line-number\" value=\"2\"></td><td "
diff --git a/third_party/blink/renderer/core/input/keyboard_event_manager.cc b/third_party/blink/renderer/core/input/keyboard_event_manager.cc index 875aae45..9776ad8aa 100644 --- a/third_party/blink/renderer/core/input/keyboard_event_manager.cc +++ b/third_party/blink/renderer/core/input/keyboard_event_manager.cc
@@ -18,13 +18,12 @@ #include "third_party/blink/renderer/core/frame/local_dom_window.h" #include "third_party/blink/renderer/core/frame/local_frame_client.h" #include "third_party/blink/renderer/core/frame/settings.h" +#include "third_party/blink/renderer/core/html/forms/html_input_element.h" #include "third_party/blink/renderer/core/html/html_dialog_element.h" #include "third_party/blink/renderer/core/input/event_handler.h" #include "third_party/blink/renderer/core/input/event_handling_util.h" #include "third_party/blink/renderer/core/input/input_device_capabilities.h" #include "third_party/blink/renderer/core/input/scroll_manager.h" -#include "third_party/blink/renderer/core/layout/layout_object.h" -#include "third_party/blink/renderer/core/layout/layout_text_control_single_line.h" #include "third_party/blink/renderer/core/page/chrome_client.h" #include "third_party/blink/renderer/core/page/focus_controller.h" #include "third_party/blink/renderer/core/page/page.h" @@ -348,10 +347,8 @@ void KeyboardEventManager::CapsLockStateMayHaveChanged() { if (Element* element = frame_->GetDocument()->FocusedElement()) { - if (LayoutObject* r = element->GetLayoutObject()) { - if (auto* text_control = DynamicTo<LayoutTextControlSingleLine>(r)) - text_control->CapsLockStateMayHaveChanged(); - } + if (auto* text_control = DynamicTo<HTMLInputElement>(element)) + text_control->CapsLockStateMayHaveChanged(); } }
diff --git a/third_party/blink/renderer/core/inspector/inspector_network_agent.cc b/third_party/blink/renderer/core/inspector/inspector_network_agent.cc index 20e71fd..9e41b60 100644 --- a/third_party/blink/renderer/core/inspector/inspector_network_agent.cc +++ b/third_party/blink/renderer/core/inspector/inspector_network_agent.cc
@@ -641,9 +641,11 @@ break; } - // Use mime type from cached resource in case the one in response is empty. + // Use mime type from cached resource in case the one in response is empty + // or the response is a 304 Not Modified. String mime_type = response.MimeType(); - if (mime_type.IsEmpty() && cached_resource) + if (cached_resource && + (mime_type.IsEmpty() || response.HttpStatusCode() == 304)) mime_type = cached_resource->GetResponse().MimeType(); if (is_empty)
diff --git a/third_party/blink/renderer/core/inspector/inspector_style_sheet.cc b/third_party/blink/renderer/core/inspector/inspector_style_sheet.cc index a484ab4..461ae6d 100644 --- a/third_party/blink/renderer/core/inspector/inspector_style_sheet.cc +++ b/third_party/blink/renderer/core/inspector/inspector_style_sheet.cc
@@ -1900,6 +1900,24 @@ CSSRuleVector& parsed_rules = parsed_flat_rules_; + if (page_style_sheet_->IsConstructed()) { + // If we are dealing with constructed stylesheets, the order + // of the parsed_rules matches the order of cssom_rules + // because the source CSS is generated based on CSSOM rules + // in the same order. + // Therefore, we can skip the expensive diff algorithm below + // that causes performance issues if there are subtle differences + // in rules due to specific issues with the CSS parser. + // See crbug.com/1131113, crbug.com/604023, crbug.com/1132778. + DCHECK(parsed_rules.size() == cssom_rules.size()); + auto min_size = std::min(parsed_rules.size(), cssom_rules.size()); + for (wtf_size_t i = 0; i < min_size; ++i) { + rule_to_source_data_.Set(i, i); + source_data_to_rule_.Set(i, i); + } + return; + } + Vector<String> cssom_rules_text = Vector<String>(); Vector<String> parsed_rules_text = Vector<String>(); for (wtf_size_t i = 0; i < cssom_rules.size(); ++i)
diff --git a/third_party/blink/renderer/core/layout/layout_text_control_single_line.cc b/third_party/blink/renderer/core/layout/layout_text_control_single_line.cc index b9e56a2..7be1af4 100644 --- a/third_party/blink/renderer/core/layout/layout_text_control_single_line.cc +++ b/third_party/blink/renderer/core/layout/layout_text_control_single_line.cc
@@ -26,15 +26,10 @@ #include "third_party/blink/renderer/core/css_value_keywords.h" #include "third_party/blink/renderer/core/dom/shadow_root.h" -#include "third_party/blink/renderer/core/editing/frame_selection.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/html/shadow/shadow_element_names.h" -#include "third_party/blink/renderer/core/input/keyboard_event_manager.h" -#include "third_party/blink/renderer/core/input_type_names.h" #include "third_party/blink/renderer/core/layout/hit_test_result.h" #include "third_party/blink/renderer/core/layout/layout_analyzer.h" -#include "third_party/blink/renderer/core/layout/layout_theme.h" -#include "third_party/blink/renderer/core/paint/paint_layer.h" #include "third_party/blink/renderer/core/paint/text_control_single_line_painter.h" #include "third_party/blink/renderer/platform/fonts/simple_font_data.h" @@ -42,7 +37,7 @@ LayoutTextControlSingleLine::LayoutTextControlSingleLine( HTMLInputElement* element) - : LayoutTextControl(element), should_draw_caps_lock_indicator_(false) {} + : LayoutTextControl(element) {} LayoutTextControlSingleLine::~LayoutTextControlSingleLine() = default; @@ -179,31 +174,6 @@ return true; } -void LayoutTextControlSingleLine::CapsLockStateMayHaveChanged() { - NOT_DESTROYED(); - if (!GetNode()) - return; - - // Only draw the caps lock indicator if these things are true: - // 1) The field is a password field - // 2) The frame is active - // 3) The element is focused - // 4) The caps lock is on - bool should_draw_caps_lock_indicator = false; - - if (LocalFrame* frame = GetDocument().GetFrame()) - should_draw_caps_lock_indicator = - InputElement()->type() == input_type_names::kPassword && - frame->Selection().FrameIsFocusedAndActive() && - GetDocument().FocusedElement() == GetNode() && - KeyboardEventManager::CurrentCapsLockState(); - - if (should_draw_caps_lock_indicator != should_draw_caps_lock_indicator_) { - should_draw_caps_lock_indicator_ = should_draw_caps_lock_indicator; - SetShouldDoFullPaintInvalidation(); - } -} - LayoutUnit LayoutTextControlSingleLine::PreferredContentLogicalWidth( float char_width) const { NOT_DESTROYED();
diff --git a/third_party/blink/renderer/core/layout/layout_text_control_single_line.h b/third_party/blink/renderer/core/layout/layout_text_control_single_line.h index 006b889..d727acc 100644 --- a/third_party/blink/renderer/core/layout/layout_text_control_single_line.h +++ b/third_party/blink/renderer/core/layout/layout_text_control_single_line.h
@@ -42,12 +42,6 @@ LayoutTextControlSingleLine(HTMLInputElement*); ~LayoutTextControlSingleLine() override; - void CapsLockStateMayHaveChanged(); - bool ShouldDrawCapsLockIndicator() const { - NOT_DESTROYED(); - return should_draw_caps_lock_indicator_; - } - protected: Element* ContainerElement() const; Element* EditingViewPortElement() const; @@ -90,8 +84,6 @@ } HTMLElement* InnerSpinButtonElement() const; - - bool should_draw_caps_lock_indicator_; }; template <>
diff --git a/third_party/blink/renderer/core/layout/ng/custom/layout_worklet_test.cc b/third_party/blink/renderer/core/layout/ng/custom/layout_worklet_test.cc index 3bf55bf..34bffe0 100644 --- a/third_party/blink/renderer/core/layout/ng/custom/layout_worklet_test.cc +++ b/third_party/blink/renderer/core/layout/ng/custom/layout_worklet_test.cc
@@ -44,7 +44,7 @@ return GetGlobalScope()->ScriptController()->GetScriptState(); } - ModuleEvaluationResult EvaluateScriptModule(const String& source_code) { + ScriptEvaluationResult EvaluateScriptModule(const String& source_code) { ScriptState* script_state = GetScriptState(); EXPECT_TRUE(script_state); @@ -69,7 +69,7 @@ TEST_F(LayoutWorkletTest, ParseProperties) { ScriptState::Scope scope(GetScriptState()); - EXPECT_TRUE(EvaluateScriptModule(R"JS( + EXPECT_EQ(EvaluateScriptModule(R"JS( registerLayout('foo', class { static get inputProperties() { return ['--prop', 'flex-basis', 'thing'] } static get childInputProperties() { return ['--child-prop', 'margin-top', 'other-thing'] } @@ -77,7 +77,8 @@ async layout() { } }); )JS") - .IsSuccess()); + .GetResultType(), + ScriptEvaluationResult::ResultType::kSuccess); LayoutWorkletGlobalScope* global_scope = GetGlobalScope(); CSSLayoutDefinition* definition = global_scope->FindDefinition("foo"); @@ -105,14 +106,15 @@ TEST_F(LayoutWorkletTest, RegisterLayout) { ScriptState::Scope scope(GetScriptState()); - ModuleEvaluationResult result = EvaluateScriptModule(R"JS( + ScriptEvaluationResult result = EvaluateScriptModule(R"JS( registerLayout('foo', class { async intrinsicSizes() { } async layout() { } }); )JS"); - EXPECT_TRUE(result.IsSuccess()); + EXPECT_EQ(result.GetResultType(), + ScriptEvaluationResult::ResultType::kSuccess); result = EvaluateScriptModule(R"JS( registerLayout('bar', class { @@ -123,23 +125,25 @@ }); )JS"); - EXPECT_TRUE(result.IsSuccess()); + EXPECT_EQ(result.GetResultType(), + ScriptEvaluationResult::ResultType::kSuccess); } TEST_F(LayoutWorkletTest, RegisterLayout_EmptyName) { ScriptState::Scope scope(GetScriptState()); - ModuleEvaluationResult result = EvaluateScriptModule(R"JS( + ScriptEvaluationResult result = EvaluateScriptModule(R"JS( registerLayout('', class { }); )JS"); // "The empty string is not a valid name." - EXPECT_TRUE(result.IsException()); + EXPECT_EQ(result.GetResultType(), + ScriptEvaluationResult::ResultType::kException); } TEST_F(LayoutWorkletTest, RegisterLayout_Duplicate) { ScriptState::Scope scope(GetScriptState()); - ModuleEvaluationResult result = EvaluateScriptModule(R"JS( + ScriptEvaluationResult result = EvaluateScriptModule(R"JS( registerLayout('foo', class { async intrinsicSizes() { } async layout() { } @@ -151,95 +155,103 @@ )JS"); // "A class with name:'foo' is already registered." - EXPECT_TRUE(result.IsException()); + EXPECT_EQ(result.GetResultType(), + ScriptEvaluationResult::ResultType::kException); } TEST_F(LayoutWorkletTest, RegisterLayout_NoIntrinsicSizes) { ScriptState::Scope scope(GetScriptState()); - ModuleEvaluationResult result = EvaluateScriptModule(R"JS( + ScriptEvaluationResult result = EvaluateScriptModule(R"JS( registerLayout('foo', class { }); )JS"); // "The 'intrinsicSizes' property on the prototype does not exist." - EXPECT_TRUE(result.IsException()); + EXPECT_EQ(result.GetResultType(), + ScriptEvaluationResult::ResultType::kException); } TEST_F(LayoutWorkletTest, RegisterLayout_ThrowingPropertyGetter) { ScriptState::Scope scope(GetScriptState()); - ModuleEvaluationResult result = EvaluateScriptModule(R"JS( + ScriptEvaluationResult result = EvaluateScriptModule(R"JS( registerLayout('foo', class { static get inputProperties() { throw Error(); } }); )JS"); // "Uncaught Error" - EXPECT_TRUE(result.IsException()); + EXPECT_EQ(result.GetResultType(), + ScriptEvaluationResult::ResultType::kException); } TEST_F(LayoutWorkletTest, RegisterLayout_BadPropertyGetter) { ScriptState::Scope scope(GetScriptState()); - ModuleEvaluationResult result = EvaluateScriptModule(R"JS( + ScriptEvaluationResult result = EvaluateScriptModule(R"JS( registerLayout('foo', class { static get inputProperties() { return 42; } }); )JS"); // "The provided value cannot be converted to a sequence." - EXPECT_TRUE(result.IsException()); + EXPECT_EQ(result.GetResultType(), + ScriptEvaluationResult::ResultType::kException); } TEST_F(LayoutWorkletTest, RegisterLayout_NoPrototype) { ScriptState::Scope scope(GetScriptState()); - ModuleEvaluationResult result = EvaluateScriptModule(R"JS( + ScriptEvaluationResult result = EvaluateScriptModule(R"JS( const foo = function() { }; foo.prototype = undefined; registerLayout('foo', foo); )JS"); // "The 'prototype' object on the class does not exist." - EXPECT_TRUE(result.IsException()); + EXPECT_EQ(result.GetResultType(), + ScriptEvaluationResult::ResultType::kException); } TEST_F(LayoutWorkletTest, RegisterLayout_BadPrototype) { ScriptState::Scope scope(GetScriptState()); - ModuleEvaluationResult result = EvaluateScriptModule(R"JS( + ScriptEvaluationResult result = EvaluateScriptModule(R"JS( const foo = function() { }; foo.prototype = 42; registerLayout('foo', foo); )JS"); // "The 'prototype' property on the class is not an object." - EXPECT_TRUE(result.IsException()); + EXPECT_EQ(result.GetResultType(), + ScriptEvaluationResult::ResultType::kException); } TEST_F(LayoutWorkletTest, RegisterLayout_BadIntrinsicSizes) { ScriptState::Scope scope(GetScriptState()); - ModuleEvaluationResult result = EvaluateScriptModule(R"JS( + ScriptEvaluationResult result = EvaluateScriptModule(R"JS( registerLayout('foo', class { get intrinsicSizes() { return 42; } }); )JS"); // "The 'intrinsicSizes' property on the prototype is not a function." - EXPECT_TRUE(result.IsException()); + EXPECT_EQ(result.GetResultType(), + ScriptEvaluationResult::ResultType::kException); } TEST_F(LayoutWorkletTest, RegisterLayout_NoLayout) { ScriptState::Scope scope(GetScriptState()); - ModuleEvaluationResult result = EvaluateScriptModule(R"JS( + ScriptEvaluationResult result = EvaluateScriptModule(R"JS( registerLayout('foo', class { async intrinsicSizes() { } }); )JS"); // "The 'layout' property on the prototype does not exist." - EXPECT_TRUE(result.IsException()); + EXPECT_EQ(result.GetResultType(), + ScriptEvaluationResult::ResultType::kException); } TEST_F(LayoutWorkletTest, RegisterLayout_BadLayout) { ScriptState::Scope scope(GetScriptState()); - ModuleEvaluationResult result = EvaluateScriptModule(R"JS( + ScriptEvaluationResult result = EvaluateScriptModule(R"JS( registerLayout('foo', class { async intrinsicSizes() { } get layout() { return 42; } @@ -247,7 +259,8 @@ )JS"); // "The 'layout' property on the prototype is not a function." - EXPECT_TRUE(result.IsException()); + EXPECT_EQ(result.GetResultType(), + ScriptEvaluationResult::ResultType::kException); } } // namespace blink
diff --git a/third_party/blink/renderer/core/layout/ng/layout_box_utils.cc b/third_party/blink/renderer/core/layout/ng/layout_box_utils.cc index b6327df..4b258bf 100644 --- a/third_party/blink/renderer/core/layout/ng/layout_box_utils.cc +++ b/third_party/blink/renderer/core/layout/ng/layout_box_utils.cc
@@ -13,6 +13,7 @@ #include "third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.h" #include "third_party/blink/renderer/core/layout/ng/ng_constraint_space_builder.h" #include "third_party/blink/renderer/core/layout/ng/ng_length_utils.h" +#include "third_party/blink/renderer/core/layout/ng/ng_physical_box_fragment.h" #include "third_party/blink/renderer/core/paint/paint_layer.h" namespace blink { @@ -170,4 +171,33 @@ return LayoutBox::SkipContainingBlockForPercentHeightCalculation(cb); } +LayoutUnit LayoutBoxUtils::TotalBlockSize(const LayoutBox& box) { + wtf_size_t num_fragments = box.PhysicalFragmentCount(); + DCHECK_GT(num_fragments, 0u); + + // Calculate the total block size by looking at the last two block fragments + // with a non-zero block-size. + LayoutUnit total_block_size; + while (num_fragments > 0) { + LayoutUnit block_size = + box.GetPhysicalFragment(num_fragments - 1) + ->Size() + .ConvertToLogical(box.StyleRef().GetWritingMode()) + .block_size; + if (block_size > LayoutUnit()) { + total_block_size += block_size; + break; + } + num_fragments--; + } + + if (num_fragments > 1) { + total_block_size += + To<NGBlockBreakToken>( + box.GetPhysicalFragment(num_fragments - 2)->BreakToken()) + ->ConsumedBlockSize(); + } + return total_block_size; +} + } // namespace blink
diff --git a/third_party/blink/renderer/core/layout/ng/layout_box_utils.h b/third_party/blink/renderer/core/layout/ng/layout_box_utils.h index c8ef21f..497beee 100644 --- a/third_party/blink/renderer/core/layout/ng/layout_box_utils.h +++ b/third_party/blink/renderer/core/layout/ng/layout_box_utils.h
@@ -38,6 +38,9 @@ static bool SkipContainingBlockForPercentHeightCalculation( const LayoutBlock* cb); + + // The total block size of all fragments. + static LayoutUnit TotalBlockSize(const LayoutBox& box); }; } // namespace blink
diff --git a/third_party/blink/renderer/core/layout/ng/ng_absolute_utils.cc b/third_party/blink/renderer/core/layout/ng/ng_absolute_utils.cc index 5a5955eb..862e7db 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_absolute_utils.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_absolute_utils.cc
@@ -425,19 +425,28 @@ const ComputedStyle& style, const NGBoxStrut& border_padding, const NGLogicalStaticPosition& static_position, - const base::Optional<MinMaxSizes>& min_max_sizes, + const base::Optional<MinMaxSizes>& minmax_content_sizes, + const base::Optional<MinMaxSizes>& minmax_intrinsic_sizes_for_ar, const base::Optional<LogicalSize>& replaced_size, const WritingMode container_writing_mode, const TextDirection container_direction, NGLogicalOutOfFlowDimensions* dimensions) { DCHECK(dimensions); - LayoutUnit min_inline_size = ResolveMinInlineLength( - space, style, border_padding, min_max_sizes, style.LogicalMinWidth(), - LengthResolvePhase::kLayout); + Length min_inline_length = style.LogicalMinWidth(); + base::Optional<MinMaxSizes> min_size_minmax = minmax_content_sizes; + // We don't need to check for IsInlineSizeComputableFromBlockSize; this is + // done by the caller. + if (minmax_intrinsic_sizes_for_ar) { + min_inline_length = Length::MinIntrinsic(); + min_size_minmax = minmax_intrinsic_sizes_for_ar; + } + LayoutUnit min_inline_size = + ResolveMinInlineLength(space, style, border_padding, min_size_minmax, + min_inline_length, LengthResolvePhase::kLayout); LayoutUnit max_inline_size = ResolveMaxInlineLength( - space, style, border_padding, min_max_sizes, style.LogicalMaxWidth(), - LengthResolvePhase::kLayout); + space, style, border_padding, minmax_content_sizes, + style.LogicalMaxWidth(), LengthResolvePhase::kLayout); // This implements the transferred min/max sizes per // https://drafts.csswg.org/css-sizing-4/#aspect-ratio @@ -451,8 +460,9 @@ bool is_table = style.IsDisplayTableBox(); base::Optional<LayoutUnit> inline_size; if (!style.LogicalWidth().IsAuto()) { - LayoutUnit resolved_inline_size = ResolveMainInlineLength( - space, style, border_padding, min_max_sizes, style.LogicalWidth()); + LayoutUnit resolved_inline_size = + ResolveMainInlineLength(space, style, border_padding, + minmax_content_sizes, style.LogicalWidth()); // Tables use the inline-size as a minimum. if (is_table) @@ -462,8 +472,8 @@ } else if (replaced_size.has_value()) { inline_size = replaced_size->inline_size; } else if (IsInlineSizeComputableFromBlockSize(style)) { - DCHECK(min_max_sizes.has_value()); - inline_size = min_max_sizes->min_size; + DCHECK(minmax_content_sizes.has_value()); + inline_size = minmax_content_sizes->min_size; } bool is_start_dominant; @@ -478,7 +488,7 @@ } ComputeAbsoluteSize( - border_padding.InlineSum(), min_max_sizes, + border_padding.InlineSum(), minmax_content_sizes, space.PercentageResolutionInlineSizeForParentWritingMode(), space.AvailableSize().inline_size, style.MarginStart(), style.MarginEnd(), style.LogicalInlineStart(), style.LogicalInlineEnd(), min_inline_size,
diff --git a/third_party/blink/renderer/core/layout/ng/ng_absolute_utils.h b/third_party/blink/renderer/core/layout/ng/ng_absolute_utils.h index ec4a18d..4bd7b44a 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_absolute_utils.h +++ b/third_party/blink/renderer/core/layout/ng/ng_absolute_utils.h
@@ -61,6 +61,8 @@ // Computes part of the absolute position which depends on the child's // inline-size. +// |minmax_intrinsic_size_for_ar| is only used for min-inline-size: auto in +// combination with aspect-ratio. // |replaced_size| should be set if and only if element is replaced element. // Returns the partially filled position. CORE_EXPORT void ComputeOutOfFlowInlineDimensions( @@ -68,7 +70,8 @@ const ComputedStyle&, const NGBoxStrut& border_padding, const NGLogicalStaticPosition&, - const base::Optional<MinMaxSizes>& child_minmax, + const base::Optional<MinMaxSizes>& minmax_content_sizes, + const base::Optional<MinMaxSizes>& minmax_intrinsic_sizes_for_ar, const base::Optional<LogicalSize>& replaced_size, const WritingMode container_writing_mode, const TextDirection container_direction,
diff --git a/third_party/blink/renderer/core/layout/ng/ng_absolute_utils_test.cc b/third_party/blink/renderer/core/layout/ng/ng_absolute_utils_test.cc index 07dad74..2a8ff06 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_absolute_utils_test.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_absolute_utils_test.cc
@@ -161,10 +161,10 @@ SetHorizontalStyle(NGAuto, NGAuto, NGAuto, NGAuto, NGAuto); EXPECT_EQ(AbsoluteNeedsChildInlineSize(*style_), true); estimated_inline = min_max_60; - ComputeOutOfFlowInlineDimensions(ltr_space_, *style_, ltr_border_padding, - static_position, estimated_inline, - base::nullopt, WritingMode::kHorizontalTb, - TextDirection::kLtr, &dimensions); + ComputeOutOfFlowInlineDimensions( + ltr_space_, *style_, ltr_border_padding, static_position, + estimated_inline, base::nullopt, base::nullopt, + WritingMode::kHorizontalTb, TextDirection::kLtr, &dimensions); EXPECT_EQ(min_max_60.min_size, dimensions.size.inline_size); EXPECT_EQ(LayoutUnit(0), dimensions.inset.inline_start); @@ -172,18 +172,18 @@ SetHorizontalStyle(NGAuto, NGAuto, NGAuto, NGAuto, NGAuto); EXPECT_EQ(AbsoluteNeedsChildInlineSize(*style_), true); estimated_inline = min_max_60; - ComputeOutOfFlowInlineDimensions(ltr_space_, *style_, ltr_border_padding, - static_position_inline_end, estimated_inline, - base::nullopt, WritingMode::kHorizontalTb, - TextDirection::kLtr, &dimensions); + ComputeOutOfFlowInlineDimensions( + ltr_space_, *style_, ltr_border_padding, static_position_inline_end, + estimated_inline, base::nullopt, base::nullopt, + WritingMode::kHorizontalTb, TextDirection::kLtr, &dimensions); EXPECT_EQ(min_max_60.min_size, dimensions.size.inline_size); EXPECT_EQ(container_size_.inline_size, dimensions.inset.inline_end); // All auto + RTL. - ComputeOutOfFlowInlineDimensions(rtl_space_, *style_, rtl_border_padding, - static_position, estimated_inline, - base::nullopt, WritingMode::kHorizontalTb, - TextDirection::kLtr, &dimensions); + ComputeOutOfFlowInlineDimensions( + rtl_space_, *style_, rtl_border_padding, static_position, + estimated_inline, base::nullopt, base::nullopt, + WritingMode::kHorizontalTb, TextDirection::kLtr, &dimensions); EXPECT_EQ(min_max_60.min_size, dimensions.size.inline_size); EXPECT_EQ(container_size_.inline_size - min_max_60.min_size, dimensions.inset.inline_end); @@ -192,10 +192,10 @@ SetHorizontalStyle(left, NGAuto, width, NGAuto, right); EXPECT_EQ(AbsoluteNeedsChildInlineSize(*style_), false); estimated_inline.reset(); - ComputeOutOfFlowInlineDimensions(ltr_space_, *style_, ltr_border_padding, - static_position, estimated_inline, - base::nullopt, WritingMode::kHorizontalTb, - TextDirection::kLtr, &dimensions); + ComputeOutOfFlowInlineDimensions( + ltr_space_, *style_, ltr_border_padding, static_position, + estimated_inline, base::nullopt, base::nullopt, + WritingMode::kHorizontalTb, TextDirection::kLtr, &dimensions); LayoutUnit margin_space = (container_size_.inline_size - left - right - dimensions.size.inline_size) / 2; @@ -229,10 +229,10 @@ // left, right, and width are known, not enough space for margins LTR. SetHorizontalStyle(left, NGAuto, LayoutUnit(200), NGAuto, right); estimated_inline.reset(); - ComputeOutOfFlowInlineDimensions(ltr_space_, *style_, ltr_border_padding, - static_position, estimated_inline, - base::nullopt, WritingMode::kHorizontalTb, - TextDirection::kLtr, &dimensions); + ComputeOutOfFlowInlineDimensions( + ltr_space_, *style_, ltr_border_padding, static_position, + estimated_inline, base::nullopt, base::nullopt, + WritingMode::kHorizontalTb, TextDirection::kLtr, &dimensions); EXPECT_EQ(left, dimensions.inset.inline_start); EXPECT_EQ(-left, dimensions.inset.inline_end); @@ -240,10 +240,10 @@ SetHorizontalStyle(left, NGAuto, LayoutUnit(200), NGAuto, right, WritingMode::kHorizontalTb); estimated_inline.reset(); - ComputeOutOfFlowInlineDimensions(rtl_space_, *style_, rtl_border_padding, - static_position, estimated_inline, - base::nullopt, WritingMode::kHorizontalTb, - TextDirection::kRtl, &dimensions); + ComputeOutOfFlowInlineDimensions( + rtl_space_, *style_, rtl_border_padding, static_position, + estimated_inline, base::nullopt, base::nullopt, + WritingMode::kHorizontalTb, TextDirection::kRtl, &dimensions); EXPECT_EQ(-right, dimensions.inset.inline_start); EXPECT_EQ(right, dimensions.inset.inline_end); @@ -251,20 +251,20 @@ SetHorizontalStyle(NGAuto, margin_left, NGAuto, margin_right, right); EXPECT_EQ(AbsoluteNeedsChildInlineSize(*style_), true); estimated_inline = min_max_60; - ComputeOutOfFlowInlineDimensions(ltr_space_, *style_, ltr_border_padding, - static_position, estimated_inline, - base::nullopt, WritingMode::kHorizontalTb, - TextDirection::kLtr, &dimensions); + ComputeOutOfFlowInlineDimensions( + ltr_space_, *style_, ltr_border_padding, static_position, + estimated_inline, base::nullopt, base::nullopt, + WritingMode::kHorizontalTb, TextDirection::kLtr, &dimensions); EXPECT_EQ(min_max_60.min_size, dimensions.size.inline_size); // Rule 2 left and right are auto LTR. SetHorizontalStyle(NGAuto, margin_left, width, margin_right, NGAuto); EXPECT_EQ(AbsoluteNeedsChildInlineSize(*style_), false); estimated_inline.reset(); - ComputeOutOfFlowInlineDimensions(ltr_space_, *style_, ltr_border_padding, - static_position, estimated_inline, - base::nullopt, WritingMode::kHorizontalTb, - TextDirection::kLtr, &dimensions); + ComputeOutOfFlowInlineDimensions( + ltr_space_, *style_, ltr_border_padding, static_position, + estimated_inline, base::nullopt, base::nullopt, + WritingMode::kHorizontalTb, TextDirection::kLtr, &dimensions); EXPECT_EQ(margin_left, dimensions.inset.inline_start); EXPECT_EQ(container_size_.inline_size - margin_left - width, dimensions.inset.inline_end); @@ -273,10 +273,10 @@ SetHorizontalStyle(NGAuto, margin_left, width, margin_right, NGAuto); EXPECT_EQ(AbsoluteNeedsChildInlineSize(*style_), false); estimated_inline.reset(); - ComputeOutOfFlowInlineDimensions(rtl_space_, *style_, rtl_border_padding, - static_position, estimated_inline, - base::nullopt, WritingMode::kHorizontalTb, - TextDirection::kLtr, &dimensions); + ComputeOutOfFlowInlineDimensions( + rtl_space_, *style_, rtl_border_padding, static_position, + estimated_inline, base::nullopt, base::nullopt, + WritingMode::kHorizontalTb, TextDirection::kLtr, &dimensions); EXPECT_EQ(margin_left, dimensions.inset.inline_start); EXPECT_EQ(container_size_.inline_size - margin_left - width, dimensions.inset.inline_end); @@ -285,10 +285,10 @@ SetHorizontalStyle(left, margin_left, NGAuto, margin_right, NGAuto); EXPECT_EQ(AbsoluteNeedsChildInlineSize(*style_), true); estimated_inline = min_max_60; - ComputeOutOfFlowInlineDimensions(ltr_space_, *style_, ltr_border_padding, - static_position, estimated_inline, - base::nullopt, WritingMode::kHorizontalTb, - TextDirection::kLtr, &dimensions); + ComputeOutOfFlowInlineDimensions( + ltr_space_, *style_, ltr_border_padding, static_position, + estimated_inline, base::nullopt, base::nullopt, + WritingMode::kHorizontalTb, TextDirection::kLtr, &dimensions); EXPECT_EQ( container_size_.inline_size - min_max_60.min_size - left - margin_left, dimensions.inset.inline_end); @@ -298,10 +298,10 @@ SetHorizontalStyle(NGAuto, margin_left, width, margin_right, right); EXPECT_EQ(AbsoluteNeedsChildInlineSize(*style_), false); estimated_inline.reset(); - ComputeOutOfFlowInlineDimensions(ltr_space_, *style_, ltr_border_padding, - static_position, estimated_inline, - base::nullopt, WritingMode::kHorizontalTb, - TextDirection::kLtr, &dimensions); + ComputeOutOfFlowInlineDimensions( + ltr_space_, *style_, ltr_border_padding, static_position, + estimated_inline, base::nullopt, base::nullopt, + WritingMode::kHorizontalTb, TextDirection::kLtr, &dimensions); EXPECT_EQ(left + margin_left, dimensions.inset.inline_start); // Rule 4: left is auto, EBoxSizing::kContentBox @@ -311,10 +311,10 @@ margin_right, right); EXPECT_EQ(AbsoluteNeedsChildInlineSize(*style_), false); estimated_inline.reset(); - ComputeOutOfFlowInlineDimensions(ltr_space_, *style_, ltr_border_padding, - static_position, estimated_inline, - base::nullopt, WritingMode::kHorizontalTb, - TextDirection::kLtr, &dimensions); + ComputeOutOfFlowInlineDimensions( + ltr_space_, *style_, ltr_border_padding, static_position, + estimated_inline, base::nullopt, base::nullopt, + WritingMode::kHorizontalTb, TextDirection::kLtr, &dimensions); EXPECT_EQ(left + margin_left, dimensions.inset.inline_start); style_->SetBoxSizing(EBoxSizing::kBorderBox); @@ -322,20 +322,20 @@ SetHorizontalStyle(left, margin_left, width, margin_right, NGAuto); EXPECT_EQ(AbsoluteNeedsChildInlineSize(*style_), false); estimated_inline.reset(); - ComputeOutOfFlowInlineDimensions(ltr_space_, *style_, ltr_border_padding, - static_position, estimated_inline, - base::nullopt, WritingMode::kHorizontalTb, - TextDirection::kLtr, &dimensions); + ComputeOutOfFlowInlineDimensions( + ltr_space_, *style_, ltr_border_padding, static_position, + estimated_inline, base::nullopt, base::nullopt, + WritingMode::kHorizontalTb, TextDirection::kLtr, &dimensions); EXPECT_EQ(right + margin_right, dimensions.inset.inline_end); // Rule 6: width is auto. SetHorizontalStyle(left, margin_left, NGAuto, margin_right, right); EXPECT_EQ(AbsoluteNeedsChildInlineSize(*style_), false); estimated_inline.reset(); - ComputeOutOfFlowInlineDimensions(ltr_space_, *style_, ltr_border_padding, - static_position, estimated_inline, - base::nullopt, WritingMode::kHorizontalTb, - TextDirection::kLtr, &dimensions); + ComputeOutOfFlowInlineDimensions( + ltr_space_, *style_, ltr_border_padding, static_position, + estimated_inline, base::nullopt, base::nullopt, + WritingMode::kHorizontalTb, TextDirection::kLtr, &dimensions); EXPECT_EQ(width, dimensions.size.inline_size); } @@ -430,7 +430,7 @@ EXPECT_EQ(AbsoluteNeedsChildInlineSize(*style_), false); ComputeOutOfFlowInlineDimensions(vlr_space_, *style_, vlr_border_padding, static_position, min_max_60, base::nullopt, - WritingMode::kHorizontalTb, + base::nullopt, WritingMode::kHorizontalTb, TextDirection::kLtr, &dimensions); EXPECT_EQ(top + margin_space, dimensions.inset.inline_start); EXPECT_EQ(bottom + margin_space, dimensions.inset.inline_end); @@ -441,7 +441,7 @@ EXPECT_EQ(AbsoluteNeedsChildInlineSize(*style_), false); ComputeOutOfFlowInlineDimensions(vrl_space_, *style_, vrl_border_padding, static_position, min_max_60, base::nullopt, - WritingMode::kHorizontalTb, + base::nullopt, WritingMode::kHorizontalTb, TextDirection::kLtr, &dimensions); EXPECT_EQ(top + margin_space, dimensions.inset.inline_start); EXPECT_EQ(bottom + margin_space, dimensions.inset.inline_end); @@ -549,7 +549,7 @@ ComputeOutOfFlowInlineDimensions( ltr_space_, *style_, border_padding, static_position, - MinMaxSizes{LayoutUnit(), LayoutUnit(1000)}, base::nullopt, + MinMaxSizes{LayoutUnit(), LayoutUnit(1000)}, base::nullopt, base::nullopt, WritingMode::kHorizontalTb, TextDirection::kLtr, &dimensions); EXPECT_EQ(LayoutUnit(100), dimensions.size.inline_size); EXPECT_EQ(LayoutUnit(100), dimensions.inset.inline_start); @@ -557,7 +557,7 @@ ComputeOutOfFlowInlineDimensions( ltr_space_, *style_, border_padding, static_position, - MinMaxSizes{LayoutUnit(), LayoutUnit(1000)}, base::nullopt, + MinMaxSizes{LayoutUnit(), LayoutUnit(1000)}, base::nullopt, base::nullopt, WritingMode::kHorizontalTb, TextDirection::kRtl, &dimensions); EXPECT_EQ(LayoutUnit(100), dimensions.size.inline_size); EXPECT_EQ(LayoutUnit(100), dimensions.inset.inline_start); @@ -595,26 +595,26 @@ // width < min gets set to min. SetHorizontalStyle(NGAuto, NGAuto, LayoutUnit(5), NGAuto, NGAuto); - ComputeOutOfFlowInlineDimensions(ltr_space_, *style_, ltr_border_padding, - static_position, estimated_inline, - base::nullopt, WritingMode::kHorizontalTb, - TextDirection::kLtr, &dimensions); + ComputeOutOfFlowInlineDimensions( + ltr_space_, *style_, ltr_border_padding, static_position, + estimated_inline, base::nullopt, base::nullopt, + WritingMode::kHorizontalTb, TextDirection::kLtr, &dimensions); EXPECT_EQ(min, dimensions.size.inline_size); // width > max gets set to max. SetHorizontalStyle(NGAuto, NGAuto, LayoutUnit(200), NGAuto, NGAuto); - ComputeOutOfFlowInlineDimensions(ltr_space_, *style_, ltr_border_padding, - static_position, estimated_inline, - base::nullopt, WritingMode::kHorizontalTb, - TextDirection::kLtr, &dimensions); + ComputeOutOfFlowInlineDimensions( + ltr_space_, *style_, ltr_border_padding, static_position, + estimated_inline, base::nullopt, base::nullopt, + WritingMode::kHorizontalTb, TextDirection::kLtr, &dimensions); EXPECT_EQ(max, dimensions.size.inline_size); // Unspecified width becomes min_max, gets clamped to min. SetHorizontalStyle(NGAuto, NGAuto, NGAuto, NGAuto, NGAuto); - ComputeOutOfFlowInlineDimensions(ltr_space_, *style_, ltr_border_padding, - static_position, estimated_inline, - base::nullopt, WritingMode::kHorizontalTb, - TextDirection::kLtr, &dimensions); + ComputeOutOfFlowInlineDimensions( + ltr_space_, *style_, ltr_border_padding, static_position, + estimated_inline, base::nullopt, base::nullopt, + WritingMode::kHorizontalTb, TextDirection::kLtr, &dimensions); EXPECT_EQ(min, dimensions.size.inline_size); // HEIGHT TESTS
diff --git a/third_party/blink/renderer/core/layout/ng/ng_container_fragment_builder.cc b/third_party/blink/renderer/core/layout/ng/ng_container_fragment_builder.cc index 4a3cdf6..28a5293 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_container_fragment_builder.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_container_fragment_builder.cc
@@ -87,8 +87,8 @@ descendant.static_position.ConvertToLogical(empty_outer_size); oof_positioned_fragmentainer_descendants_.emplace_back( descendant.node, static_position, descendant.inline_container, - /* needs_block_offset_adjustment */ false, - containing_block_offset, containing_block_fragment); + /* needs_block_offset_adjustment */ false, containing_block_offset, + containing_block_fragment); } } }
diff --git a/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm.cc index 3daed90..c19d6e3 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm.cc
@@ -157,6 +157,9 @@ } } + LogicalSize adjusted_padding_box_size = + ShrinkLogicalSize(border_box_size_, borders_); + NGBlockNode legend = Node().GetRenderedLegend(); if (legend) { if (!IsResumingLayout(BreakToken())) @@ -168,40 +171,35 @@ minimum_border_box_block_size_ = intrinsic_block_size_ + padding_.BlockSum() + borders_.block_end; } - } - LogicalSize adjusted_padding_box_size = - ShrinkLogicalSize(border_box_size_, borders_); + if (adjusted_padding_box_size.block_size != kIndefiniteSize) { + DCHECK_NE(border_box_size_.block_size, kIndefiniteSize); + LayoutUnit legend_size_contribution; + if (IsResumingLayout(BreakToken())) { + // The legend has been laid out in previous fragments, and + // adjusted_padding_box_size will need to be adjusted further to account + // for block size taken up by the legend. + // + // To calculate its size contribution to the border block-start area, + // take the difference between the previously consumed block-size of the + // fieldset excluding its specified block-start border, and the consumed + // block-size of the contents wrapper. + LayoutUnit content_consumed_block_size = + content_break_token ? content_break_token->ConsumedBlockSize() + : LayoutUnit(); + legend_size_contribution = consumed_block_size_ - borders_.block_start - + content_consumed_block_size; + } else { + // We're at the first fragment. The current layout position + // (intrinsic_block_size_) is at the outer block-end edge of the legend + // or just after the block-start border, whichever is larger. + legend_size_contribution = intrinsic_block_size_ - borders_.block_start; + } - // If the legend has been laid out in previous fragments, - // adjusted_padding_box_size will need to be adjusted further to account for - // block size taken up by the legend. - if (adjusted_padding_box_size.block_size != kIndefiniteSize && legend) { - LayoutUnit content_consumed_block_size = - content_break_token ? content_break_token->ConsumedBlockSize() - : LayoutUnit(); - - // Calculate the amount of the border block-start that was consumed in - // previous fragments. - LayoutUnit consumed_border_block_start = - borders_.block_start - intrinsic_block_size_; - - // Calculate the amount of the border block-end that was consumed in - // previous fragments. - DCHECK_NE(border_box_size_.block_size, kIndefiniteSize); - LayoutUnit consumed_border_block_end = - std::max(consumed_block_size_ - - (border_box_size_.block_size - borders_.block_end), - LayoutUnit()); - - LayoutUnit legend_block_size = - consumed_block_size_ - content_consumed_block_size - - consumed_border_block_start - consumed_border_block_end; - DCHECK_GE(legend_block_size, LayoutUnit()); - - adjusted_padding_box_size.block_size = - std::max(padding_.BlockSum(), - adjusted_padding_box_size.block_size - legend_block_size); + adjusted_padding_box_size.block_size = std::max( + adjusted_padding_box_size.block_size - legend_size_contribution, + padding_.BlockSum()); + } } // Proceed with normal fieldset children (excluding the rendered legend). They
diff --git a/third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.cc b/third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.cc index b59601e..f6f8f550 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.cc
@@ -244,7 +244,13 @@ LayoutUnit fragments_total_block_size = builder->FragmentsTotalBlockSize(); LayoutUnit desired_block_size = fragments_total_block_size - previously_consumed_block_size; - DCHECK_GE(desired_block_size, LayoutUnit()); + + // Consumed block-size stored in the break tokens is always stretched to the + // fragmentainers. If this wasn't also the case for all previous fragments + // (because we reached the end of the node and were overflowing), we may end + // up with negative values here. + desired_block_size = desired_block_size.ClampNegativeToZero(); + LayoutUnit intrinsic_block_size = builder->IntrinsicBlockSize(); LayoutUnit final_block_size = desired_block_size; @@ -318,8 +324,18 @@ sides.block_end = false; builder->SetSidesToInclude(sides); - builder->SetConsumedBlockSize(previously_consumed_block_size + - final_block_size); + LayoutUnit consumed_here = final_block_size; + if (builder->DidBreakSelf() || builder->HasChildBreakInside()) { + // If this node is to be resumed in the next fragmentainer, consumed + // block-size always includes the entire remainder of the fragmentainer. The + // frament itself will only do that unless we've reached the end of the node + // (and we are breaking because of overflow). We include the entire + // fragmentainer in consumed block-size in order to write offsets correctly + // back to legacy layout, which would otherwise become incorrect for + // overflowing content. + consumed_here = std::max(consumed_here, space_left); + } + builder->SetConsumedBlockSize(previously_consumed_block_size + consumed_here); builder->SetFragmentBlockSize(final_block_size); if (builder->FoundColumnSpanner())
diff --git a/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.cc b/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.cc index 518d2cc2..d48b156 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.cc
@@ -310,6 +310,9 @@ const ComputedStyle& style = containing_block->StyleRef(); LogicalSize size = containing_block_fragment->Size().ConvertToLogical( style.GetWritingMode()); + size.block_size = + LayoutBoxUtils::TotalBlockSize(*ToLayoutBox(containing_block)); + const NGPhysicalBoxFragment* fragment = To<NGPhysicalBoxFragment>(containing_block_fragment); @@ -743,13 +746,16 @@ bool should_be_considered_as_replaced = node.ShouldBeConsideredAsReplaced(); bool absolute_needs_child_block_size = AbsoluteNeedsChildBlockSize(candidate_style); + base::Optional<MinMaxSizes> minmax_intrinsic_sizes_for_ar; // We also include items with aspect ratio here, because if the inline size // is auto and we have a definite block size, we want to use that for the // inline size calculation. + bool compute_inline_from_ar = + IsInlineSizeComputableFromBlockSize(candidate_style); if (AbsoluteNeedsChildInlineSize(candidate_style) || NeedMinMaxSize(candidate_style) || should_be_considered_as_replaced || - IsInlineSizeComputableFromBlockSize(candidate_style)) { + compute_inline_from_ar) { MinMaxSizesInput input(kIndefiniteSize, MinMaxSizesType::kContent); if (is_replaced) { input.percentage_resolution_block_size = @@ -764,6 +770,15 @@ has_computed_block_dimensions = true; input.percentage_resolution_block_size = node_dimensions.size.block_size; } + if (compute_inline_from_ar && + candidate_style.OverflowInlineDirection() == EOverflow::kVisible) { + MinMaxSizesInput intrinsic_input(input); + intrinsic_input.type = MinMaxSizesType::kIntrinsic; + minmax_intrinsic_sizes_for_ar = + node.ComputeMinMaxSizes(candidate_writing_mode, intrinsic_input, + &candidate_constraint_space) + .sizes; + } min_max_sizes = node.ComputeMinMaxSizes(candidate_writing_mode, input, &candidate_constraint_space) @@ -795,10 +810,11 @@ kIndefiniteSize}; } - ComputeOutOfFlowInlineDimensions( - candidate_constraint_space, candidate_style, border_padding, - candidate_static_position, min_max_sizes, replaced_size, - default_writing_mode, container_direction, &node_dimensions); + ComputeOutOfFlowInlineDimensions(candidate_constraint_space, candidate_style, + border_padding, candidate_static_position, + min_max_sizes, minmax_intrinsic_sizes_for_ar, + replaced_size, default_writing_mode, + container_direction, &node_dimensions); // |should_be_considered_as_replaced| sets the inline-size. // It does not set the block-size. This is a compatibility quirk. @@ -1185,8 +1201,9 @@ column_size.block_size = column_size.block_size.ClampNegativeToZero(); } - // TODO(layout-dev): Calculate correct percentage resolution size. - LogicalSize percentage_resolution_size = column_size; + LogicalSize percentage_resolution_size = + LogicalSize(column_size.inline_size, + container_builder_->ChildAvailableSize().block_size); // TODO(bebeaudr): Need to handle different fragmentation types. It won't // always be multi-column.
diff --git a/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part_test.cc b/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part_test.cc index c7213a840..5e70bb5d 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part_test.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part_test.cc
@@ -1138,5 +1138,114 @@ EXPECT_EQ(expectation, dump); } +// Fragmented OOF element with block-size percentage resolution. +TEST_F(NGOutOfFlowLayoutPartTest, AbsposFragmentationPctResolution) { + SetBodyInnerHTML( + R"HTML( + <style> + #multicol { + column-count:2; column-fill:auto; column-gap:16px; height:40px; + } + .rel { + position: relative; width:30px; + } + .abs { + position:absolute; top:30px; width:5px; height:100%; + } + .spanner { + column-span:all; height:25%; + } + </style> + <div id="container"> + <div id="multicol"> + <div class="rel"> + <div class="abs"></div> + <div style="width: 10px; height:30px;"></div> + </div> + <div class="spanner"></div> + </div> + </div> + )HTML"); + String dump = DumpFragmentTree(GetElementById("container")); + + String expectation = R"DUMP(.:: LayoutNG Physical Fragment Tree ::. + offset:unplaced size:1000x40 + offset:0,0 size:1000x40 + offset:0,0 size:492x15 + offset:0,0 size:30x15 + offset:0,0 size:10x15 + offset:508,0 size:492x15 + offset:0,0 size:30x15 + offset:0,0 size:10x15 + offset:0,15 size:1000x10 + offset:0,25 size:492x15 + offset:0,0 size:5x15 + offset:508,25 size:492x15 + offset:0,0 size:5x15 +)DUMP"; + EXPECT_EQ(expectation, dump); +} + +// Fragmented OOF element with block-size percentage resolution and overflow. +TEST_F(NGOutOfFlowLayoutPartTest, + AbsposFragmentationPctResolutionWithOverflow) { + SetBodyInnerHTML( + R"HTML( + <style> + #multicol { + columns:5; column-fill:auto; column-gap:0px; height:100px; + } + .rel { + position: relative; width:55px; + } + .abs { + position:absolute; top:0px; width:5px; height:100%; + } + </style> + <div id="container"> + <div id="multicol"> + <div style="height:30px;"></div> + <div class="rel"> + <div class="abs"></div> + <div style="width:44px; height:200px;"> + <div style="width:33px; height:400px;"></div> + </div> + </div> + </div> + </div> + )HTML"); + String dump = DumpFragmentTree(GetElementById("container")); + + String expectation = R"DUMP(.:: LayoutNG Physical Fragment Tree ::. + offset:unplaced size:1000x100 + offset:0,0 size:1000x100 + offset:0,0 size:200x100 + offset:0,0 size:200x30 + offset:0,30 size:55x70 + offset:0,0 size:44x70 + offset:0,0 size:33x70 + offset:0,30 size:5x70 + offset:200,0 size:200x100 + offset:0,0 size:55x100 + offset:0,0 size:44x100 + offset:0,0 size:33x100 + offset:0,0 size:5x100 + offset:400,0 size:200x100 + offset:0,0 size:55x30 + offset:0,0 size:44x30 + offset:0,0 size:33x100 + offset:0,0 size:5x30 + offset:600,0 size:200x100 + offset:0,0 size:55x0 + offset:0,0 size:44x0 + offset:0,0 size:33x100 + offset:800,0 size:200x100 + offset:0,0 size:55x0 + offset:0,0 size:44x0 + offset:0,0 size:33x30 +)DUMP"; + EXPECT_EQ(expectation, dump); +} + } // namespace } // namespace blink
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_image.h b/third_party/blink/renderer/core/layout/svg/layout_svg_image.h index 23b1b601..ed0bca5 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_image.h +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_image.h
@@ -69,6 +69,11 @@ LayoutSVGModelObject::IsOfType(type); } + AffineTransform LocalSVGTransform() const override { + NOT_DESTROYED(); + return local_transform_; + } + const char* GetName() const override { NOT_DESTROYED(); return "LayoutSVGImage"; @@ -96,11 +101,6 @@ const PhysicalOffset& accumulated_offset, HitTestAction) override; - AffineTransform LocalSVGTransform() const override { - NOT_DESTROYED(); - return local_transform_; - } - FloatSize CalculateObjectSize() const; bool HasOverriddenIntrinsicSize() const;
diff --git a/third_party/blink/renderer/core/paint/svg_container_painter.cc b/third_party/blink/renderer/core/paint/svg_container_painter.cc index 0c0d457..0ec0ecda 100644 --- a/third_party/blink/renderer/core/paint/svg_container_painter.cc +++ b/third_party/blink/renderer/core/paint/svg_container_painter.cc
@@ -28,6 +28,15 @@ } // namespace +bool SVGContainerPainter::CanUseCullRect() const { + // LayoutSVGHiddenContainer's visual rect is always empty but we need to + // paint its descendants so we cannot skip painting. + if (layout_svg_container_.IsSVGHiddenContainer()) + return false; + return SVGModelObjectPainter::CanUseCullRect( + layout_svg_container_.StyleRef()); +} + void SVGContainerPainter::Paint(const PaintInfo& paint_info) { // Spec: An empty viewBox on the <svg> element disables rendering. DCHECK(layout_svg_container_.GetElement()); @@ -36,20 +45,20 @@ if (svg_svg_element && svg_svg_element->HasEmptyViewBox()) return; - if (SVGModelObjectPainter(layout_svg_container_) - .CullRectSkipsPainting(paint_info)) { - return; - } - const auto* properties = layout_svg_container_.FirstFragment().PaintProperties(); PaintInfo paint_info_before_filtering(paint_info); - if (SVGModelObjectPainter::ShouldUseInfiniteCullRect( - layout_svg_container_.StyleRef())) { + if (CanUseCullRect()) { + if (!paint_info.GetCullRect().IntersectsTransformed( + layout_svg_container_.LocalToSVGParentTransform(), + layout_svg_container_.VisualRectInLocalSVGCoordinates())) + return; + if (properties) { + if (const auto* transform = properties->Transform()) + paint_info_before_filtering.TransformCullRect(*transform); + } + } else { paint_info_before_filtering.ApplyInfiniteCullRect(); - } else if (properties) { - if (const auto* transform = properties->Transform()) - paint_info_before_filtering.TransformCullRect(*transform); } ScopedSVGTransformState transform_state(
diff --git a/third_party/blink/renderer/core/paint/svg_container_painter.h b/third_party/blink/renderer/core/paint/svg_container_painter.h index 9c13032a..4c26d62a 100644 --- a/third_party/blink/renderer/core/paint/svg_container_painter.h +++ b/third_party/blink/renderer/core/paint/svg_container_painter.h
@@ -22,6 +22,8 @@ void Paint(const PaintInfo&); private: + bool CanUseCullRect() const; + const LayoutSVGContainer& layout_svg_container_; };
diff --git a/third_party/blink/renderer/core/paint/svg_image_painter.cc b/third_party/blink/renderer/core/paint/svg_image_painter.cc index 1f6d0d2f..8c6726a 100644 --- a/third_party/blink/renderer/core/paint/svg_image_painter.cc +++ b/third_party/blink/renderer/core/paint/svg_image_painter.cc
@@ -31,15 +31,16 @@ !layout_svg_image_.ImageResource()->HasImage()) return; - if (SVGModelObjectPainter(layout_svg_image_) - .CullRectSkipsPainting(paint_info)) { - return; + if (SVGModelObjectPainter::CanUseCullRect(layout_svg_image_.StyleRef())) { + if (!paint_info.GetCullRect().IntersectsTransformed( + layout_svg_image_.LocalSVGTransform(), + layout_svg_image_.VisualRectInLocalSVGCoordinates())) + return; } // Images cannot have children so do not call TransformCullRect. ScopedSVGTransformState transform_state( - paint_info, layout_svg_image_, - layout_svg_image_.LocalToSVGParentTransform()); + paint_info, layout_svg_image_, layout_svg_image_.LocalSVGTransform()); { ScopedSVGPaintState paint_state(layout_svg_image_, paint_info); if (paint_state.ApplyEffects() &&
diff --git a/third_party/blink/renderer/core/paint/svg_model_object_painter.cc b/third_party/blink/renderer/core/paint/svg_model_object_painter.cc index dbe2a07..681754a 100644 --- a/third_party/blink/renderer/core/paint/svg_model_object_painter.cc +++ b/third_party/blink/renderer/core/paint/svg_model_object_painter.cc
@@ -11,33 +11,18 @@ namespace blink { -bool SVGModelObjectPainter::ShouldUseInfiniteCullRect( - const ComputedStyle& style) { +bool SVGModelObjectPainter::CanUseCullRect(const ComputedStyle& style) { // We do not apply cull rect optimizations across transforms for two reasons: // 1) Performance: We can optimize transform changes by not repainting. // 2) Complexity: Difficulty updating clips when ancestor transforms change. // For these reasons, we do not cull painting if there is a transform. if (style.HasTransform()) - return true; + return false; // If the filter "moves pixels" we may require input from outside the cull // rect. if (style.HasFilter() && style.Filter().HasFilterThatMovesPixels()) - return true; - return false; -} - -bool SVGModelObjectPainter::CullRectSkipsPainting(const PaintInfo& paint_info) { - if (ShouldUseInfiniteCullRect(layout_svg_model_object_.StyleRef())) return false; - - // LayoutSVGHiddenContainer's visual rect is always empty but we need to - // paint its descendants so we cannot skip painting. - if (layout_svg_model_object_.IsSVGHiddenContainer()) - return false; - - return !paint_info.GetCullRect().IntersectsTransformed( - layout_svg_model_object_.LocalToSVGParentTransform(), - layout_svg_model_object_.VisualRectInLocalSVGCoordinates()); + return true; } void SVGModelObjectPainter::RecordHitTestData(const LayoutObject& svg_object,
diff --git a/third_party/blink/renderer/core/paint/svg_model_object_painter.h b/third_party/blink/renderer/core/paint/svg_model_object_painter.h index 3157b1a..7b3fd23c 100644 --- a/third_party/blink/renderer/core/paint/svg_model_object_painter.h +++ b/third_party/blink/renderer/core/paint/svg_model_object_painter.h
@@ -29,12 +29,7 @@ // Should we use an infinite cull rect when painting an object with the // specified style. - static bool ShouldUseInfiniteCullRect(const ComputedStyle&); - - // If the object is outside the cull rect, painting can be skipped in most - // cases. An important exception is when there is a transform style: see the - // comment in the implementation. - bool CullRectSkipsPainting(const PaintInfo&); + static bool CanUseCullRect(const ComputedStyle&); void PaintOutline(const PaintInfo&);
diff --git a/third_party/blink/renderer/core/paint/svg_shape_painter.cc b/third_party/blink/renderer/core/paint/svg_shape_painter.cc index cd517c0..533ecd27 100644 --- a/third_party/blink/renderer/core/paint/svg_shape_painter.cc +++ b/third_party/blink/renderer/core/paint/svg_shape_painter.cc
@@ -47,9 +47,11 @@ layout_svg_shape_.IsShapeEmpty()) return; - if (SVGModelObjectPainter(layout_svg_shape_) - .CullRectSkipsPainting(paint_info)) { - return; + if (SVGModelObjectPainter::CanUseCullRect(layout_svg_shape_.StyleRef())) { + if (!paint_info.GetCullRect().IntersectsTransformed( + layout_svg_shape_.LocalSVGTransform(), + layout_svg_shape_.VisualRectInLocalSVGCoordinates())) + return; } // Shapes cannot have children so do not call TransformCullRect.
diff --git a/third_party/blink/renderer/core/paint/text_control_single_line_painter.cc b/third_party/blink/renderer/core/paint/text_control_single_line_painter.cc index a49d62e..350d7733 100644 --- a/third_party/blink/renderer/core/paint/text_control_single_line_painter.cc +++ b/third_party/blink/renderer/core/paint/text_control_single_line_painter.cc
@@ -4,6 +4,7 @@ #include "third_party/blink/renderer/core/paint/text_control_single_line_painter.h" +#include "third_party/blink/renderer/core/html/forms/html_input_element.h" #include "third_party/blink/renderer/core/layout/layout_text_control_single_line.h" #include "third_party/blink/renderer/core/layout/layout_theme.h" #include "third_party/blink/renderer/core/paint/block_painter.h" @@ -18,7 +19,8 @@ BlockPainter(text_control_).Paint(paint_info); if (!ShouldPaintSelfBlockBackground(paint_info.phase) || - !text_control_.ShouldDrawCapsLockIndicator()) + !To<HTMLInputElement>(text_control_.GetNode()) + ->ShouldDrawCapsLockIndicator()) return; if (DrawingRecorder::UseCachedDrawingIfPossible(
diff --git a/third_party/blink/renderer/core/script/classic_script.cc b/third_party/blink/renderer/core/script/classic_script.cc index fd4014b..eaefbcb2 100644 --- a/third_party/blink/renderer/core/script/classic_script.cc +++ b/third_party/blink/renderer/core/script/classic_script.cc
@@ -57,11 +57,11 @@ DCHECK(global_scope.IsContextThread()); ScriptState::Scope scope(global_scope.ScriptController()->GetScriptState()); - ClassicEvaluationResult result = + ScriptEvaluationResult result = global_scope.ScriptController()->EvaluateAndReturnValue( GetScriptSourceCode(), sanitize_script_errors_, global_scope.GetV8CacheOptions()); - return !result.IsEmpty(); + return result.GetResultType() == ScriptEvaluationResult::ResultType::kSuccess; } std::pair<size_t, size_t> ClassicScript::GetClassicScriptSizes() const {
diff --git a/third_party/blink/renderer/core/script/dynamic_module_resolver.cc b/third_party/blink/renderer/core/script/dynamic_module_resolver.cc index 8e45173..8340bf7 100644 --- a/third_party/blink/renderer/core/script/dynamic_module_resolver.cc +++ b/third_party/blink/renderer/core/script/dynamic_module_resolver.cc
@@ -153,85 +153,94 @@ // <spec step="7">Run the module script result, with the rethrow errors // boolean set to true.</spec> - ModuleEvaluationResult result = modulator_->ExecuteModule( + ScriptEvaluationResult result = modulator_->ExecuteModule( module_script, Modulator::CaptureEvalErrorFlag::kCapture); - // <spec step="8">If running the module script throws an exception, ...</spec> - if (result.IsException()) { - // <spec step="8">... then perform - // FinishDynamicImport(referencingScriptOrModule, specifier, - // promiseCapability, the thrown exception completion).</spec> - // - // Note: "the thrown exception completion" is |error|. - // - // <spec - // href="https://tc39.github.io/proposal-dynamic-import/#sec-finishdynamicimport" - // step="1">If completion is an abrupt completion, then perform ! - // Call(promiseCapability.[[Reject]], undefined, « completion.[[Value]] - // »).</spec> - promise_resolver_->Reject(result.GetException()); - return; + switch (result.GetResultType()) { + case ScriptEvaluationResult::ResultType::kException: + // <spec step="8">If running the module script throws an exception, + // ...</spec> <spec step="8">... then perform + // FinishDynamicImport(referencingScriptOrModule, specifier, + // promiseCapability, the thrown exception completion).</spec> + // + // Note: "the thrown exception completion" is |error|. + // + // <spec + // href="https://tc39.github.io/proposal-dynamic-import/#sec-finishdynamicimport" + // step="1">If completion is an abrupt completion, then perform ! + // Call(promiseCapability.[[Reject]], undefined, « completion.[[Value]] + // »).</spec> + promise_resolver_->Reject(result.GetExceptionForModule()); + break; + + case ScriptEvaluationResult::ResultType::kNotRun: + case ScriptEvaluationResult::ResultType::kAborted: + // Do nothing when script is disabled or after a script is aborted. + break; + + case ScriptEvaluationResult::ResultType::kSuccess: { + // <spec step="9">Otherwise, perform + // FinishDynamicImport(referencingScriptOrModule, specifier, + // promiseCapability, NormalCompletion(undefined)).</spec> + // + // <spec + // href="https://tc39.github.io/proposal-dynamic-import/#sec-finishdynamicimport" + // step="2.1">Assert: completion is a normal completion and + // completion.[[Value]] is undefined.</spec> + + if (base::FeatureList::IsEnabled(features::kTopLevelAwait)) { + ScriptPromise promise = result.GetPromise(script_state); + v8::Local<v8::Function> callback_success = + ModuleResolutionSuccessCallback::CreateFunction( + script_state, promise_resolver_, module_script); + v8::Local<v8::Function> callback_failure = + ModuleResolutionFailureCallback::CreateFunction(script_state, + promise_resolver_); + promise.Then(callback_success, callback_failure); + return; + } + + // <spec + // href="https://tc39.github.io/proposal-dynamic-import/#sec-finishdynamicimport" + // step="2.2">Let moduleRecord be ! + // HostResolveImportedModule(referencingScriptOrModule, specifier).</spec> + // + // Note: We skip invocation of ModuleRecordResolver here. The + // result of HostResolveImportedModule is guaranteed to be + // |module_script|. + v8::Local<v8::Module> record = module_script->V8Module(); + DCHECK(!record.IsEmpty()); + + // <spec + // href="https://tc39.github.io/proposal-dynamic-import/#sec-finishdynamicimport" + // step="2.3">Assert: Evaluate has already been invoked on moduleRecord + // and successfully completed.</spec> + // + // Because |error| is empty, we are sure that ExecuteModule() above was + // successfully completed. + + // <spec + // href="https://tc39.github.io/proposal-dynamic-import/#sec-finishdynamicimport" + // step="2.4">Let namespace be GetModuleNamespace(moduleRecord).</spec> + v8::Local<v8::Value> module_namespace = ModuleRecord::V8Namespace(record); + + // <spec + // href="https://tc39.github.io/proposal-dynamic-import/#sec-finishdynamicimport" + // step="2.5">If namespace is an abrupt completion, perform ! + // Call(promiseCapability.[[Reject]], undefined, « namespace.[[Value]] + // »).</spec> + // + // Note: Blink's implementation never allows |module_namespace| to be + // an abrupt completion. + + // <spec + // href="https://tc39.github.io/proposal-dynamic-import/#sec-finishdynamicimport" + // step="2.6">Otherwise, perform ! Call(promiseCapability.[[Resolve]], + // undefined, « namespace.[[Value]] »).</spec> + promise_resolver_->Resolve(module_namespace); + break; + } } - - // <spec step="9">Otherwise, perform - // FinishDynamicImport(referencingScriptOrModule, specifier, - // promiseCapability, NormalCompletion(undefined)).</spec> - // - // <spec - // href="https://tc39.github.io/proposal-dynamic-import/#sec-finishdynamicimport" - // step="2.1">Assert: completion is a normal completion and - // completion.[[Value]] is undefined.</spec> - DCHECK(result.IsSuccess()); - - if (base::FeatureList::IsEnabled(features::kTopLevelAwait)) { - ScriptPromise promise = result.GetPromise(script_state); - v8::Local<v8::Function> callback_success = - ModuleResolutionSuccessCallback::CreateFunction( - script_state, promise_resolver_, module_script); - v8::Local<v8::Function> callback_failure = - ModuleResolutionFailureCallback::CreateFunction(script_state, - promise_resolver_); - promise.Then(callback_success, callback_failure); - return; - } - - // <spec - // href="https://tc39.github.io/proposal-dynamic-import/#sec-finishdynamicimport" - // step="2.2">Let moduleRecord be ! - // HostResolveImportedModule(referencingScriptOrModule, specifier).</spec> - // - // Note: We skip invocation of ModuleRecordResolver here. The - // result of HostResolveImportedModule is guaranteed to be |module_script|. - v8::Local<v8::Module> record = module_script->V8Module(); - DCHECK(!record.IsEmpty()); - - // <spec - // href="https://tc39.github.io/proposal-dynamic-import/#sec-finishdynamicimport" - // step="2.3">Assert: Evaluate has already been invoked on moduleRecord and - // successfully completed.</spec> - // - // Because |error| is empty, we are sure that ExecuteModule() above was - // successfully completed. - - // <spec - // href="https://tc39.github.io/proposal-dynamic-import/#sec-finishdynamicimport" - // step="2.4">Let namespace be GetModuleNamespace(moduleRecord).</spec> - v8::Local<v8::Value> module_namespace = ModuleRecord::V8Namespace(record); - - // <spec - // href="https://tc39.github.io/proposal-dynamic-import/#sec-finishdynamicimport" - // step="2.5">If namespace is an abrupt completion, perform ! - // Call(promiseCapability.[[Reject]], undefined, « namespace.[[Value]] - // »).</spec> - // - // Note: Blink's implementation never allows |module_namespace| to be - // an abrupt completion. - - // <spec - // href="https://tc39.github.io/proposal-dynamic-import/#sec-finishdynamicimport" - // step="2.6">Otherwise, perform ! Call(promiseCapability.[[Resolve]], - // undefined, « namespace.[[Value]] »).</spec> - promise_resolver_->Resolve(module_namespace); } void DynamicImportTreeClient::Trace(Visitor* visitor) const {
diff --git a/third_party/blink/renderer/core/script/dynamic_module_resolver_test.cc b/third_party/blink/renderer/core/script/dynamic_module_resolver_test.cc index 727bbf4c..dc1e4ba 100644 --- a/third_party/blink/renderer/core/script/dynamic_module_resolver_test.cc +++ b/third_party/blink/renderer/core/script/dynamic_module_resolver_test.cc
@@ -91,13 +91,13 @@ fetch_tree_was_called_ = true; } - ModuleEvaluationResult ExecuteModule( + ScriptEvaluationResult ExecuteModule( ModuleScript* module_script, CaptureEvalErrorFlag capture_error) final { EXPECT_EQ(CaptureEvalErrorFlag::kCapture, capture_error); ScriptState::EscapableScope scope(script_state_); - ModuleEvaluationResult result = ModuleRecord::Evaluate( + ScriptEvaluationResult result = ModuleRecord::Evaluate( script_state_, module_script->V8Module(), module_script->SourceURL()); return result.Escape(&scope); }
diff --git a/third_party/blink/renderer/core/script/modulator.h b/third_party/blink/renderer/core/script/modulator.h index af13a118..b6387d8 100644 --- a/third_party/blink/renderer/core/script/modulator.h +++ b/third_party/blink/renderer/core/script/modulator.h
@@ -201,14 +201,14 @@ // CaptureEvalErrorFlag is used to implement "rethrow errors" parameter in // run-a-module-script. // - When "rethrow errors" is to be set, use kCapture for EvaluateModule(). - // Then EvaluateModule() wraps exceptions in a ModuleEvaluationResult instead + // Then EvaluateModule() wraps exceptions in a ScriptEvaluationResult instead // of throwing it and the caller should rethrow the exception. // - When "rethrow errors" is not to be set, use kReport. If there is an error // to throw, EvaluateModule() "report the error" inside it, and returns - // ModuleEvaluationResult wrapping the error. Otherwise, it returns either a - // ModuleEvaluationResult that is empty or contains the successful evaluation + // ScriptEvaluationResult wrapping the error. Otherwise, it returns either a + // ScriptEvaluationResult that is empty or contains the successful evaluation // result. - virtual ModuleEvaluationResult ExecuteModule(ModuleScript*, + virtual ScriptEvaluationResult ExecuteModule(ModuleScript*, CaptureEvalErrorFlag) = 0; virtual ModuleScriptFetcher* CreateModuleScriptFetcher(
diff --git a/third_party/blink/renderer/core/script/modulator_impl_base.cc b/third_party/blink/renderer/core/script/modulator_impl_base.cc index 15bc5d0..4cc48c7 100644 --- a/third_party/blink/renderer/core/script/modulator_impl_base.cc +++ b/third_party/blink/renderer/core/script/modulator_impl_base.cc
@@ -337,7 +337,7 @@ // <specdef href="https://html.spec.whatwg.org/C/#run-a-module-script"> // Spec with TLA: https://github.com/whatwg/html/pull/4352 -ModuleEvaluationResult ModulatorImplBase::ExecuteModule( +ScriptEvaluationResult ModulatorImplBase::ExecuteModule( ModuleScript* module_script, CaptureEvalErrorFlag capture_error) { // <spec step="1">If rethrow errors is not given, let it be false.</spec> @@ -348,8 +348,9 @@ // <spec step="3">Check if we can run script with settings. If this returns // "do not run" then return NormalCompletion(empty).</spec> - if (IsScriptingDisabled()) - return ModuleEvaluationResult::Empty(); + if (IsScriptingDisabled()) { + return ScriptEvaluationResult::FromModuleNotRun(); + } // <spec step="4">Prepare to run script given settings.</spec> // @@ -361,7 +362,7 @@ ScriptState::EscapableScope scope(script_state_); // Without TLA: <spec step="5">Let evaluationStatus be null.</spec> - ModuleEvaluationResult result = ModuleEvaluationResult::Empty(); + ScriptEvaluationResult result = ScriptEvaluationResult::FromModuleNotRun(); // <spec step="6">If script's error to rethrow is not null, ...</spec> if (module_script->HasErrorToRethrow()) { @@ -371,7 +372,7 @@ // With TLA: <spec step="5">If script's error to rethrow is not null, // then let valuationPromise be a promise rejected with script's error // to rethrow.</spec> - result = ModuleEvaluationResult::FromException( + result = ScriptEvaluationResult::FromModuleException( module_script->CreateErrorToRethrow().V8Value()); } else { // <spec step="7">Otherwise:</spec> @@ -390,7 +391,8 @@ // DOMException, [[Target]]: empty }.</spec> // [not specced] Store V8 code cache on successful evaluation. - if (result.IsSuccess()) { + if (result.GetResultType() == + ScriptEvaluationResult::ResultType::kSuccess) { TaskRunner()->PostTask( FROM_HERE, WTF::Bind(&ModulatorImplBase::ProduceCacheModuleTreeTopLevel, @@ -398,27 +400,26 @@ } } - if (base::FeatureList::IsEnabled(features::kTopLevelAwait)) { - if (capture_error == CaptureEvalErrorFlag::kReport) { + if (capture_error == CaptureEvalErrorFlag::kReport) { + if (base::FeatureList::IsEnabled(features::kTopLevelAwait)) { // <spec step="7"> If report errors is true, then upon rejection of // evaluationPromise with reason, report the exception given by reason // for script.</spec> v8::Local<v8::Function> callback_failure = ModuleEvaluationRejectionCallback::CreateFunction(script_state_); - // Add a rejection handler to report back errors once the result promise - // is rejected. + // Add a rejection handler to report back errors once the result + // promise is rejected. result.GetPromise(script_state_) .Then(v8::Local<v8::Function>(), callback_failure); - } - } else { - // <spec step="8">If evaluationStatus is an abrupt completion, then:</spec> - if (result.IsException()) { - // <spec step="8.1">If rethrow errors is true, rethrow the exception given - // by evaluationStatus.[[Value]].</spec> - if (capture_error == CaptureEvalErrorFlag::kReport) { + } else { + // <spec step="8">If evaluationStatus is an abrupt completion, + // then:</spec> + if (result.GetResultType() == + ScriptEvaluationResult::ResultType::kException) { // <spec step="8.2">Otherwise, report the exception given by // evaluationStatus.[[Value]] for script.</spec> - ModuleRecord::ReportException(script_state_, result.GetException()); + ModuleRecord::ReportException(script_state_, + result.GetExceptionForModule()); } } }
diff --git a/third_party/blink/renderer/core/script/modulator_impl_base.h b/third_party/blink/renderer/core/script/modulator_impl_base.h index 03f875ba..6b03d3f5 100644 --- a/third_party/blink/renderer/core/script/modulator_impl_base.h +++ b/third_party/blink/renderer/core/script/modulator_impl_base.h
@@ -89,7 +89,7 @@ ScriptValue InstantiateModule(v8::Local<v8::Module>, const KURL&) override; Vector<ModuleRequest> ModuleRequestsFromModuleRecord( v8::Local<v8::Module>) override; - ModuleEvaluationResult ExecuteModule(ModuleScript*, + ScriptEvaluationResult ExecuteModule(ModuleScript*, CaptureEvalErrorFlag) override; // Populates |reason| and returns true if the dynamic import is disallowed on
diff --git a/third_party/blink/renderer/core/script/module_script.cc b/third_party/blink/renderer/core/script/module_script.cc index bb775ea..7970c77 100644 --- a/third_party/blink/renderer/core/script/module_script.cc +++ b/third_party/blink/renderer/core/script/module_script.cc
@@ -101,7 +101,7 @@ } void ModuleScript::RunScript(LocalFrame* frame) { - // We need a HandleScope for the ModuleEvaluationResult that is created + // We need a HandleScope for the ScriptEvaluationResult that is created // in ::ExecuteModule(...). ScriptState::Scope scope(SettingsObject()->GetScriptState()); DVLOG(1) << *this << "::RunScript()"; @@ -112,7 +112,7 @@ bool ModuleScript::RunScriptOnWorkerOrWorklet( WorkerOrWorkletGlobalScope& global_scope) { - // We need a HandleScope for the ModuleEvaluationResult that is created + // We need a HandleScope for the ScriptEvaluationResult that is created // in ::ExecuteModule(...). ScriptState::Scope scope(SettingsObject()->GetScriptState()); DCHECK(global_scope.IsContextThread()); @@ -120,9 +120,10 @@ // This |error| is always null because the second argument is |kReport|. // TODO(nhiroki): Catch an error when an evaluation error happens. // (https://crbug.com/680046) - ModuleEvaluationResult result = SettingsObject()->ExecuteModule( + ScriptEvaluationResult result = SettingsObject()->ExecuteModule( this, Modulator::CaptureEvalErrorFlag::kReport); - return result.IsSuccess(); + + return result.GetResultType() == ScriptEvaluationResult::ResultType::kSuccess; } std::pair<size_t, size_t> ModuleScript::GetClassicScriptSizes() const {
diff --git a/third_party/blink/renderer/core/script/module_script_test.cc b/third_party/blink/renderer/core/script/module_script_test.cc index eb25d05..c1773ac6 100644 --- a/third_party/blink/renderer/core/script/module_script_test.cc +++ b/third_party/blink/renderer/core/script/module_script_test.cc
@@ -167,10 +167,11 @@ module_script->V8Module(), module_script->SourceURL()) .IsEmpty()); - ASSERT_TRUE(ModuleRecord::Evaluate(scope.GetScriptState(), - module_script->V8Module(), - module_script->SourceURL()) - .IsSuccess()); + ASSERT_EQ(ModuleRecord::Evaluate(scope.GetScriptState(), + module_script->V8Module(), + module_script->SourceURL()) + .GetResultType(), + ScriptEvaluationResult::ResultType::kSuccess); TestFoo(scope); Checkpoint checkpoint; @@ -293,10 +294,11 @@ module_script->V8Module(), module_script->SourceURL()) .IsEmpty()); - ASSERT_TRUE(ModuleRecord::Evaluate(scope.GetScriptState(), - module_script->V8Module(), - module_script->SourceURL()) - .IsSuccess()); + ASSERT_EQ(ModuleRecord::Evaluate(scope.GetScriptState(), + module_script->V8Module(), + module_script->SourceURL()) + .GetResultType(), + ScriptEvaluationResult::ResultType::kSuccess); TestFoo(scope); Checkpoint checkpoint;
diff --git a/third_party/blink/renderer/core/testing/dummy_modulator.cc b/third_party/blink/renderer/core/testing/dummy_modulator.cc index a32dd5da..cf3218f 100644 --- a/third_party/blink/renderer/core/testing/dummy_modulator.cc +++ b/third_party/blink/renderer/core/testing/dummy_modulator.cc
@@ -169,10 +169,10 @@ return Vector<ModuleRequest>(); } -ModuleEvaluationResult DummyModulator::ExecuteModule(ModuleScript*, +ScriptEvaluationResult DummyModulator::ExecuteModule(ModuleScript*, CaptureEvalErrorFlag) { NOTREACHED(); - return ModuleEvaluationResult::Empty(); + return ScriptEvaluationResult::FromModuleNotRun(); } ModuleScriptFetcher* DummyModulator::CreateModuleScriptFetcher(
diff --git a/third_party/blink/renderer/core/testing/dummy_modulator.h b/third_party/blink/renderer/core/testing/dummy_modulator.h index b461b49..26f54cd 100644 --- a/third_party/blink/renderer/core/testing/dummy_modulator.h +++ b/third_party/blink/renderer/core/testing/dummy_modulator.h
@@ -75,7 +75,7 @@ ScriptValue InstantiateModule(v8::Local<v8::Module>, const KURL&) override; Vector<ModuleRequest> ModuleRequestsFromModuleRecord( v8::Local<v8::Module>) override; - ModuleEvaluationResult ExecuteModule(ModuleScript*, + ScriptEvaluationResult ExecuteModule(ModuleScript*, CaptureEvalErrorFlag) override; ModuleScriptFetcher* CreateModuleScriptFetcher( ModuleScriptCustomFetchType,
diff --git a/third_party/blink/renderer/core/workers/worker_global_scope.cc b/third_party/blink/renderer/core/workers/worker_global_scope.cc index c1e4291..ba9586b 100644 --- a/third_party/blink/renderer/core/workers/worker_global_scope.cc +++ b/third_party/blink/renderer/core/workers/worker_global_scope.cc
@@ -330,7 +330,7 @@ ReportingProxy().WillEvaluateImportedClassicScript( source_code.length(), handler ? handler->GetCodeCacheSize() : 0); ScriptState::Scope scope(ScriptController()->GetScriptState()); - ClassicEvaluationResult result = ScriptController()->EvaluateAndReturnValue( + ScriptEvaluationResult result = ScriptController()->EvaluateAndReturnValue( ScriptSourceCode(source_code, ScriptSourceLocationType::kUnknown, handler, ScriptSourceCode::UsePostRedirectURL() ? response_url @@ -342,7 +342,7 @@ // Step 5.2: "If an exception was thrown or if the script was prematurely // aborted, then abort all these steps, letting the exception or aborting // continue to be processed by the calling script." - if (result.IsEmpty()) + if (result.GetResultType() != ScriptEvaluationResult::ResultType::kSuccess) return; } }
diff --git a/third_party/blink/renderer/core/workers/worklet_module_tree_client.cc b/third_party/blink/renderer/core/workers/worklet_module_tree_client.cc index f0a1614..f8f4090 100644 --- a/third_party/blink/renderer/core/workers/worklet_module_tree_client.cc +++ b/third_party/blink/renderer/core/workers/worklet_module_tree_client.cc
@@ -70,7 +70,7 @@ } // Step 5: "Run a module script given script." - ModuleEvaluationResult result = + ScriptEvaluationResult result = Modulator::From(script_state_) ->ExecuteModule(module_script, Modulator::CaptureEvalErrorFlag::kReport); @@ -78,7 +78,8 @@ auto* global_scope = To<WorkletGlobalScope>(ExecutionContext::From(script_state_)); - global_scope->ReportingProxy().DidEvaluateTopLevelScript(result.IsSuccess()); + global_scope->ReportingProxy().DidEvaluateTopLevelScript( + result.GetResultType() == ScriptEvaluationResult::ResultType::kSuccess); // Step 6: "Queue a task on outsideSettings's responsible event loop to run // these steps:"
diff --git a/third_party/blink/renderer/modules/animationworklet/animation_worklet_global_scope_test.cc b/third_party/blink/renderer/modules/animationworklet/animation_worklet_global_scope_test.cc index b1be9f9..3ef1a12 100644 --- a/third_party/blink/renderer/modules/animationworklet/animation_worklet_global_scope_test.cc +++ b/third_party/blink/renderer/modules/animationworklet/animation_worklet_global_scope_test.cc
@@ -157,11 +157,12 @@ DCHECK(isolate); ScriptState::Scope scope(script_state); - ClassicEvaluationResult result = + ScriptEvaluationResult result = global_scope->ScriptController()->EvaluateAndReturnValue( ScriptSourceCode(script), SanitizeScriptErrors::kSanitize); - DCHECK(!result.IsEmpty()); - return ToBoolean(isolate, result.GetValue(), ASSERT_NO_EXCEPTION); + DCHECK_EQ(result.GetResultType(), + ScriptEvaluationResult::ResultType::kSuccess); + return ToBoolean(isolate, result.GetSuccessValue(), ASSERT_NO_EXCEPTION); } void RunConstructAndAnimateTestOnWorklet(
diff --git a/third_party/blink/renderer/modules/peerconnection/peer_connection_dependency_factory.cc b/third_party/blink/renderer/modules/peerconnection/peer_connection_dependency_factory.cc index ea3c51fe..602abb7 100644 --- a/third_party/blink/renderer/modules/peerconnection/peer_connection_dependency_factory.cc +++ b/third_party/blink/renderer/modules/peerconnection/peer_connection_dependency_factory.cc
@@ -31,6 +31,7 @@ #include "third_party/blink/public/web/modules/mediastream/media_stream_video_source.h" #include "third_party/blink/public/web/web_document.h" #include "third_party/blink/public/web/web_local_frame.h" +#include "third_party/blink/public/web/web_local_frame_client.h" #include "third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler.h" #include "third_party/blink/renderer/modules/webrtc/webrtc_audio_device_impl.h" #include "third_party/blink/renderer/platform/mediastream/media_constraints.h" @@ -56,6 +57,7 @@ #include "third_party/webrtc/media/engine/webrtc_media_engine.h" #include "third_party/webrtc/modules/audio_processing/include/audio_processing.h" #include "third_party/webrtc/modules/video_coding/codecs/h264/include/h264.h" +#include "third_party/webrtc/rtc_base/openssl_stream_adapter.h" #include "third_party/webrtc/rtc_base/ref_counted_object.h" #include "third_party/webrtc/rtc_base/ssl_adapter.h" #include "third_party/webrtc_overrides/task_queue_factory.h" @@ -349,6 +351,8 @@ if (!GetPcFactory().get()) return nullptr; + rtc::SetAllowLegacyTLSProtocols( + web_frame->Client()->AllowRTCLegacyTLSProtocols()); webrtc::PeerConnectionDependencies dependencies(observer); dependencies.allocator = CreatePortAllocator(web_frame); dependencies.async_resolver_factory = CreateAsyncResolverFactory();
diff --git a/third_party/blink/renderer/modules/webaudio/audio_worklet_global_scope_test.cc b/third_party/blink/renderer/modules/webaudio/audio_worklet_global_scope_test.cc index 463db2d..d37ab20c 100644 --- a/third_party/blink/renderer/modules/webaudio/audio_worklet_global_scope_test.cc +++ b/third_party/blink/renderer/modules/webaudio/audio_worklet_global_scope_test.cc
@@ -148,9 +148,10 @@ ModuleRecord::Instantiate(script_state, module, js_url); EXPECT_TRUE(exception.IsEmpty()); - ModuleEvaluationResult result = + ScriptEvaluationResult result = ModuleRecord::Evaluate(script_state, module, js_url); - return result.IsSuccess(); + return result.GetResultType() == + ScriptEvaluationResult::ResultType::kSuccess; } // Test if AudioWorkletGlobalScope and V8 components (ScriptState, Isolate)
diff --git a/third_party/blink/renderer/modules/webaudio/audio_worklet_thread_test.cc b/third_party/blink/renderer/modules/webaudio/audio_worklet_thread_test.cc index fe18563..0a1daa3 100644 --- a/third_party/blink/renderer/modules/webaudio/audio_worklet_thread_test.cc +++ b/third_party/blink/renderer/modules/webaudio/audio_worklet_thread_test.cc
@@ -120,9 +120,10 @@ ScriptValue exception = ModuleRecord::Instantiate(script_state, module, js_url); EXPECT_TRUE(exception.IsEmpty()); - ModuleEvaluationResult result = + ScriptEvaluationResult result = ModuleRecord::Evaluate(script_state, module, js_url); - EXPECT_TRUE(result.IsSuccess()); + EXPECT_EQ(result.GetResultType(), + ScriptEvaluationResult::ResultType::kSuccess); wait_event->Signal(); }
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_buffer.cc b/third_party/blink/renderer/modules/webgpu/gpu_buffer.cc index 36f0827c..3d590aa00 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_buffer.cc +++ b/third_party/blink/renderer/modules/webgpu/gpu_buffer.cc
@@ -291,6 +291,16 @@ resolver->Reject(MakeGarbageCollected<DOMException>( DOMExceptionCode::kOperationError, "Device is lost")); break; + case WGPUBufferMapAsyncStatus_DestroyedBeforeCallback: + resolver->Reject(MakeGarbageCollected<DOMException>( + DOMExceptionCode::kOperationError, + "Buffer is destroyed before the mapping is resolved")); + break; + case WGPUBufferMapAsyncStatus_UnmappedBeforeCallback: + resolver->Reject(MakeGarbageCollected<DOMException>( + DOMExceptionCode::kOperationError, + "Buffer is unmapped before the mapping is resolved")); + break; default: NOTREACHED(); }
diff --git a/third_party/blink/renderer/modules/worklet/animation_and_paint_worklet_thread_test.cc b/third_party/blink/renderer/modules/worklet/animation_and_paint_worklet_thread_test.cc index 658dd80c..e4bfb7de 100644 --- a/third_party/blink/renderer/modules/worklet/animation_and_paint_worklet_thread_test.cc +++ b/third_party/blink/renderer/modules/worklet/animation_and_paint_worklet_thread_test.cc
@@ -81,8 +81,9 @@ ScriptValue exception = ModuleRecord::Instantiate(script_state, module, js_url); EXPECT_TRUE(exception.IsEmpty()); - EXPECT_TRUE( - ModuleRecord::Evaluate(script_state, module, js_url).IsSuccess()); + EXPECT_EQ( + ModuleRecord::Evaluate(script_state, module, js_url).GetResultType(), + ScriptEvaluationResult::ResultType::kSuccess); wait_event->Signal(); } };
diff --git a/third_party/blink/renderer/platform/fonts/utf16_ragel_iterator_test.cc b/third_party/blink/renderer/platform/fonts/utf16_ragel_iterator_test.cc index a967dd9..fe01532 100644 --- a/third_party/blink/renderer/platform/fonts/utf16_ragel_iterator_test.cc +++ b/third_party/blink/renderer/platform/fonts/utf16_ragel_iterator_test.cc
@@ -105,9 +105,11 @@ TEST(UTF16RagelIteratorTest, InvalidOperationOnEmpty) { UTF16RagelIterator ragel_iterator; CHECK_EQ(ragel_iterator.Cursor(), 0u); +#if DCHECK_IS_ON() EXPECT_DEATH_IF_SUPPORTED(ragel_iterator++, ""); EXPECT_DEATH_IF_SUPPORTED(ragel_iterator--, ""); EXPECT_DEATH_IF_SUPPORTED(*ragel_iterator, ""); +#endif } TEST(UTF16RagelIteratorTest, CursorPositioning) { @@ -128,9 +130,11 @@ CHECK_EQ(*(ragel_iterator.SetCursor(6)), UTF16RagelIterator::EMOJI_TEXT_PRESENTATION); +#if DCHECK_IS_ON() EXPECT_DEATH_IF_SUPPORTED(ragel_iterator.SetCursor(-1), ""); EXPECT_DEATH_IF_SUPPORTED( ragel_iterator.SetCursor(ragel_iterator.end().Cursor()), ""); +#endif } } // namespace blink
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index 51c7de4..a7c6ee3 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -273,7 +273,6 @@ crbug.com/1007229 external/wpt/intersection-observer/same-origin-grand-child-iframe.sub.html [ Pass Failure ] # Not supported yet -crbug.com/1045668 external/wpt/css/css-sizing/aspect-ratio/abspos-013.tentative.html [ Failure ] crbug.com/1045668 external/wpt/css/css-sizing/aspect-ratio/flex-aspect-ratio-013.tentative.html [ Failure ] crbug.com/1045668 external/wpt/css/css-sizing/aspect-ratio/flex-aspect-ratio-014.tentative.html [ Failure ] crbug.com/1045668 external/wpt/css/css-sizing/aspect-ratio/replaced-element-016.tentative.html [ Failure ] @@ -1084,11 +1083,6 @@ crbug.com/1061423 virtual/layout_ng_block_frag/fast/multicol/flipped-blocks-hit-test.html [ Failure ] crbug.com/829028 virtual/layout_ng_block_frag/fast/multicol/float-margin-at-row-boundary.html [ Failure ] crbug.com/829028 virtual/layout_ng_block_frag/fast/multicol/float-margin-at-row-boundary-fixed-multicol-height.html [ Failure ] -crbug.com/829028 virtual/layout_ng_block_frag/fast/multicol/float-moved-by-child-line-and-unbreakable.html [ Failure ] -crbug.com/829028 virtual/layout_ng_block_frag/fast/multicol/float-with-margin-moved-by-child-block-and-unbreakable.html [ Failure ] -crbug.com/829028 virtual/layout_ng_block_frag/fast/multicol/float-with-margin-moved-by-child-block.html [ Failure Timeout ] -crbug.com/829028 virtual/layout_ng_block_frag/fast/multicol/float-with-margin-moved-by-child-line-and-unbreakable.html [ Failure ] -crbug.com/829028 virtual/layout_ng_block_frag/fast/multicol/float-with-margin-moved-by-child-line.html [ Failure ] crbug.com/829028 virtual/layout_ng_block_frag/fast/multicol/forced-break-in-nested-columns.html [ Failure ] crbug.com/829028 virtual/layout_ng_block_frag/fast/multicol/forced-break-too-short-column.html [ Failure ] crbug.com/829028 virtual/layout_ng_block_frag/fast/multicol/hit-test-above-or-below.html [ Failure ] @@ -1166,7 +1160,6 @@ crbug.com/829028 virtual/layout_ng_block_frag/fragmentation/auto-scrollbar-shrink-to-fit.html [ Failure ] crbug.com/1079031 virtual/layout_ng_block_frag/fragmentation/content-preceding-first-fragmentainer.html [ Crash Failure ] crbug.com/829028 virtual/layout_ng_block_frag/fragmentation/float-after-forced-break.html [ Failure ] -crbug.com/829028 virtual/layout_ng_block_frag/fragmentation/overflow-crossing-boundary.html [ Failure ] crbug.com/1079031 virtual/layout_ng_block_frag/fragmentation/relayout-abspos.html [ Failure ] ### With LayoutNGFragmentTraversal (and LayoutNGFragmentItem) enabled: @@ -1822,9 +1815,6 @@ crbug.com/524160 [ Debug ] http/tests/media/media-source/stream_memory_tests/mediasource-appendbuffer-quota-exceeded-default-buffers.html [ Timeout ] -# Awaiting DevTools roll. -crbug.com/1109224 inspector-protocol/overlay/overlay-persistent-overlays.js [ Pass Failure ] - # On these platforms (all but Android) media tests don't currently use gpu-accelerated (proprietary) codecs, so no # benefit to running them again with gpu acceleration enabled. crbug.com/555703 [ Linux ] virtual/media-gpu-accelerated/* [ Skip ] @@ -3069,9 +3059,6 @@ crbug.com/626703 external/wpt/css/css-lists/content-property/marker-text-matches-square.html [ Failure ] crbug.com/626703 external/wpt/svg/linking/reftests/use-descendant-combinator-003.html [ Failure ] crbug.com/626703 external/wpt/css/css-lists/content-property/marker-text-matches-circle.html [ Failure ] -crbug.com/626703 external/wpt/content-security-policy/securitypolicyviolation/inside-service-worker.https.html [ Timeout ] -crbug.com/626703 external/wpt/content-security-policy/securitypolicyviolation/inside-shared-worker.html [ Timeout ] -crbug.com/626703 external/wpt/content-security-policy/securitypolicyviolation/inside-dedicated-worker.html [ Timeout ] crbug.com/626703 external/wpt/content-security-policy/securitypolicyviolation/targeting.html [ Timeout ] crbug.com/863355 [ Mac ] external/wpt/svg/shapes/reftests/pathlength-002.svg [ Failure ] crbug.com/366559 external/wpt/svg/shapes/reftests/pathlength-003.svg [ Failure ]
diff --git a/third_party/blink/web_tests/WPTOverrideExpectations b/third_party/blink/web_tests/WPTOverrideExpectations index b373135..40bcef8 100644 --- a/third_party/blink/web_tests/WPTOverrideExpectations +++ b/third_party/blink/web_tests/WPTOverrideExpectations
@@ -176,9 +176,6 @@ external/wpt/content-security-policy/reporting-api/reporting-api-works-on-frame-src.https.sub.html [ Pass ] # wpt_subtest_failure external/wpt/content-security-policy/script-src/script-src-strict_dynamic_hashes.html [ Failure ] external/wpt/content-security-policy/securitypolicyviolation/img-src-redirect-upgrade-reporting.https.html [ Timeout ] # wpt_subtest_failure -external/wpt/content-security-policy/securitypolicyviolation/inside-dedicated-worker.html [ Timeout ] # wpt_subtest_failure -external/wpt/content-security-policy/securitypolicyviolation/inside-service-worker.https.html [ Timeout ] # wpt_subtest_failure -external/wpt/content-security-policy/securitypolicyviolation/inside-shared-worker.html [ Timeout ] # wpt_subtest_failure external/wpt/content-security-policy/securitypolicyviolation/securitypolicyviolation-block-cross-origin-image.sub.html [ Pass ] # wpt_subtest_failure external/wpt/content-security-policy/securitypolicyviolation/targeting.html [ Timeout ] # wpt_subtest_failure external/wpt/content-security-policy/worker-src/service-none.https.sub.html [ Pass Failure ]
diff --git a/third_party/blink/web_tests/external/wpt/css/css-contain/content-visibility/content-visibility-026.html b/third_party/blink/web_tests/external/wpt/css/css-contain/content-visibility/content-visibility-026.html index 1306493..6b3de88 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-contain/content-visibility/content-visibility-026.html +++ b/third_party/blink/web_tests/external/wpt/css/css-contain/content-visibility/content-visibility-026.html
@@ -69,7 +69,7 @@ t.step(() => assert_equals(getComputedStyle(offscreen_container).contain, "size layout style paint", "frame 2 offscreen")); requestAnimationFrame(() => { - offscreen_container.scrollIntoView(); + window.scrollBy(0, 10000); // Frame 3 checks: t.step(() => assert_equals(getComputedStyle(offscreen_container).contain, "size layout style paint", "frame 3"));
diff --git a/third_party/blink/web_tests/external/wpt/css/css-contain/content-visibility/content-visibility-058-ref.html b/third_party/blink/web_tests/external/wpt/css/css-contain/content-visibility/content-visibility-058-ref.html index 067d064..ee55290 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-contain/content-visibility/content-visibility-058-ref.html +++ b/third_party/blink/web_tests/external/wpt/css/css-contain/content-visibility/content-visibility-058-ref.html
@@ -35,7 +35,7 @@ </style> <div class=spacer></div> -<div id=container class="container size_contained"> +<div id=container class="container"> <div class=child></div> <div id=target></div> </div> @@ -45,7 +45,6 @@ function runReference() { document.getElementById("target").scrollIntoView(true /* alignToTop */); - document.getElementById("container").classList.remove("size_contained"); requestAnimationFrame(takeScreenshot); }
diff --git a/third_party/blink/web_tests/external/wpt/css/css-contain/content-visibility/content-visibility-075-ref.html b/third_party/blink/web_tests/external/wpt/css/css-contain/content-visibility/content-visibility-075-ref.html new file mode 100644 index 0000000..05799e0 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-contain/content-visibility/content-visibility-075-ref.html
@@ -0,0 +1,37 @@ +<!doctype HTML> +<html class="reftest-wait"> +<meta charset="utf8"> +<title>CSS Content Visibility: auto + scrollIntoView/fragment nav when size estimate is off (reference)</title> +<link rel="author" title="Vladimir Levin" href="mailto:vmpstr@chromium.org"> +<link rel="help" href="https://drafts.csswg.org/css-contain/#content-visibility"> + +<script src="/common/reftest-wait.js"></script> + +<style> +.small_child { + height: 500px; +} +.large_child { + height: 5000px; + position: relative; +} +#target { + position: absolute; + bottom: 0; +} +</style> + +<div class=auto><div class=small_child></div></div> +<div class=auto><div class=small_child></div></div> +<div class=auto><div class=large_child><div id=target>target</div></div></div> +<div class=auto><div class=large_child></div></div> +<div class=auto><div class=small_child></div></div> + +<script> +function runReference() { + target.scrollIntoView(); + takeScreenshot(); +} + +window.onload = () => requestAnimationFrame(() => requestAnimationFrame(runReference)); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-contain/content-visibility/content-visibility-075.html b/third_party/blink/web_tests/external/wpt/css/css-contain/content-visibility/content-visibility-075.html new file mode 100644 index 0000000..cecbf9b --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-contain/content-visibility/content-visibility-075.html
@@ -0,0 +1,41 @@ +<!doctype HTML> +<html class="reftest-wait"> +<meta charset="utf8"> +<title>CSS Content Visibility: auto + scrollIntoView when size estimate is off</title> +<link rel="author" title="Vladimir Levin" href="mailto:vmpstr@chromium.org"> +<link rel="help" href="https://drafts.csswg.org/css-contain/#content-visibility"> +<link rel="match" href="content-visibility-075-ref.html"> +<meta name="assert" content="With content-visibility: auto, scrollIntoView targets the right element"> + +<script src="/common/reftest-wait.js"></script> + +<style> +.auto { + content-visibility: auto; + contain-intrinsic-size: 1px 500px; +} +.child { + height: 5000px; + position: relative; +} +#target { + position: absolute; + bottom: 0; +} +</style> + +<div class=auto><div class=child></div></div> +<div class=auto><div class=child></div></div> +<div class=auto><div class=child><div id=target>target</div></div></div> +<div class=auto><div class=child></div></div> +<div class=auto><div class=child></div></div> + +<script> +function runTest() { + target.scrollIntoView(); + // Double rAF to ensure that rendering has "settled". + requestAnimationFrame(() => requestAnimationFrame(takeScreenshot)); +} + +window.onload = () => requestAnimationFrame(() => requestAnimationFrame(runTest)); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-contain/content-visibility/content-visibility-076-ref.html b/third_party/blink/web_tests/external/wpt/css/css-contain/content-visibility/content-visibility-076-ref.html new file mode 100644 index 0000000..6ea5fcf --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-contain/content-visibility/content-visibility-076-ref.html
@@ -0,0 +1,37 @@ +<!doctype HTML> +<html class="reftest-wait"> +<meta charset="utf8"> +<title>CSS Content Visibility: auto + scorllIntoView when size estimate is off (reference)</title> +<link rel="author" title="Vladimir Levin" href="mailto:vmpstr@chromium.org"> +<link rel="help" href="https://drafts.csswg.org/css-contain/#content-visibility"> + +<script src="/common/reftest-wait.js"></script> + +<style> +.small_child { + height: 500px; +} +.large_child { + height: 5000px; + position: relative; +} +#target { + position: absolute; + bottom: 0; +} +</style> + +<div class=auto><div class=small_child></div></div> +<div class=auto><div class=small_child></div></div> +<div class=auto><div class=large_child><div id=target>target</div></div></div> +<div class=auto><div class=large_child></div></div> +<div class=auto><div class=small_child></div></div> + +<script> +function runReference() { + target.scrollIntoView(); + takeScreenshot(); +} + +window.onload = () => requestAnimationFrame(() => requestAnimationFrame(runReference)); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-contain/content-visibility/content-visibility-076.html b/third_party/blink/web_tests/external/wpt/css/css-contain/content-visibility/content-visibility-076.html new file mode 100644 index 0000000..8ba2bbe --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-contain/content-visibility/content-visibility-076.html
@@ -0,0 +1,41 @@ +<!doctype HTML> +<html class="reftest-wait"> +<meta charset="utf8"> +<title>CSS Content Visibility: auto + fragment nav when size estimate is off</title> +<link rel="author" title="Vladimir Levin" href="mailto:vmpstr@chromium.org"> +<link rel="help" href="https://drafts.csswg.org/css-contain/#content-visibility"> +<link rel="match" href="content-visibility-075-ref.html"> +<meta name="assert" content="With content-visibility: auto, scrollIntoView targets the right element"> + +<script src="/common/reftest-wait.js"></script> + +<style> +.auto { + content-visibility: auto; + contain-intrinsic-size: 1px 500px; +} +.child { + height: 5000px; + position: relative; +} +#target { + position: absolute; + bottom: 0; +} +</style> + +<div class=auto><div class=child></div></div> +<div class=auto><div class=child></div></div> +<div class=auto><div class=child><div id=target>target</div></div></div> +<div class=auto><div class=child></div></div> +<div class=auto><div class=child></div></div> + +<script> +function runTest() { + window.location.href += "#target"; + // Double rAF to ensure that rendering has "settled". + requestAnimationFrame(() => requestAnimationFrame(takeScreenshot)); +} + +window.onload = () => requestAnimationFrame(() => requestAnimationFrame(runTest)); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/mediacapture-image/MediaStreamTrack-applyConstraints-reject.html b/third_party/blink/web_tests/external/wpt/mediacapture-image/MediaStreamTrack-applyConstraints-reject.html index 45599c0..02ba251f 100644 --- a/third_party/blink/web_tests/external/wpt/mediacapture-image/MediaStreamTrack-applyConstraints-reject.html +++ b/third_party/blink/web_tests/external/wpt/mediacapture-image/MediaStreamTrack-applyConstraints-reject.html
@@ -72,6 +72,10 @@ capabilities => ({ saturation: capabilities.saturation.min - 1 }), capabilities => ({ sharpness: capabilities.sharpness.max + 1 }), capabilities => ({ sharpness: capabilities.sharpness.min - 1 }), + capabilities => ({ pan: capabilities.pan.max + 1 }), + capabilities => ({ pan: capabilities.pan.min - 1 }), + capabilities => ({ tilt: capabilities.tilt.max + 1 }), + capabilities => ({ tilt: capabilities.tilt.min - 1 }), capabilities => ({ zoom: capabilities.zoom.max + 1 }), capabilities => ({ zoom: capabilities.zoom.min - 1 }), capabilities => ({ torch: true }),
diff --git a/third_party/blink/web_tests/external/wpt/trusted-types/WorkerGlobalScope-eval.html b/third_party/blink/web_tests/external/wpt/trusted-types/WorkerGlobalScope-eval.html new file mode 100644 index 0000000..92487849 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/trusted-types/WorkerGlobalScope-eval.html
@@ -0,0 +1,42 @@ +<!doctype html> +<html> +<head> + <meta http-equiv="Content-Security-Policy" content="require-trusted-types-for 'script';"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> +</head> +<body> +<div id=log></div> + +<script> + +// To test workers, we need to importScripts source files in the workers. +// Since the point of this test is to test blocking of importScripts, we need +// to set up one policy that will blindly pass through URLs for use in the test +// setup, and then have additional policies for the actual test cases. +// +// For the same reason we cannot use the otherwise preferred 'META: workers' +// tag, since that test setup would be blocked as soon as trusted types +// enforcement is enabled. +const test_setup_policy = trustedTypes.createPolicy("hurrayanythinggoes", { + createScriptURL: x => x}); +const test_url = + test_setup_policy.createScriptURL("support/WorkerGlobalScope-eval.https.js"); + +fetch_tests_from_worker(new Worker(test_url)); + +fetch_tests_from_worker(new SharedWorker(test_url)); + +// Cargo-culted from code generated from "META: worker". +if ('serviceWorker' in navigator) { + (async function() { + const scope = 'support/some/scope/for/this/test'; + let reg = await navigator.serviceWorker.getRegistration(scope); + if (reg) await reg.unregister(); + reg = await navigator.serviceWorker.register(test_url, {scope}); + fetch_tests_from_worker(reg.installing); + })(); +} + +</script> +</body>
diff --git a/third_party/blink/web_tests/external/wpt/trusted-types/support/WorkerGlobalScope-eval.https.js b/third_party/blink/web_tests/external/wpt/trusted-types/support/WorkerGlobalScope-eval.https.js new file mode 100644 index 0000000..be0a430 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/trusted-types/support/WorkerGlobalScope-eval.https.js
@@ -0,0 +1,37 @@ +let test_setup_policy = trustedTypes.createPolicy("hurrayanythinggoes", { + createScriptURL: x => x +}); +importScripts(test_setup_policy.createScriptURL("/resources/testharness.js")); + +// Determine worker type (for better logging) +let worker_type = "unknown"; +if (this.DedicatedWorkerGlobalScope !== undefined) { + worker_type = "dedicated worker"; +} else if (this.SharedWorkerGlobalScope !== undefined) { + worker_type = "shared worker"; +} else if (this.ServiceWorkerGlobalScope !== undefined) { + worker_type = "service worker"; +} + +// Test eval(string) +test(t => { + assert_throws_js(EvalError, _ => eval("2")); +}, "eval(string) in " + worker_type); + +// Test eval(TrustedScript) +let test_policy = trustedTypes.createPolicy("xxx", { + createScript: x => x.replace("2", "7") +}); +test(t => { + assert_equals(eval(test_policy.createScript("2")), 7); +}, "eval(TrustedScript) in " + worker_type); + +// Test eval(String) with default policy +trustedTypes.createPolicy("default", { + createScript: x => x.replace("2", "5") +}); +test(t => { + assert_equals(eval("2"), 5); +}, "eval(string) with default policy in " + worker_type); + +done();
diff --git a/third_party/blink/web_tests/external/wpt/trusted-types/support/WorkerGlobalScope-eval.https.js.headers b/third_party/blink/web_tests/external/wpt/trusted-types/support/WorkerGlobalScope-eval.https.js.headers new file mode 100644 index 0000000..604e765 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/trusted-types/support/WorkerGlobalScope-eval.https.js.headers
@@ -0,0 +1 @@ +Content-Security-Policy: require-trusted-types-for 'script';
diff --git a/third_party/blink/web_tests/http/tests/devtools/network/network-not-modified-images-mime-type-expected.txt b/third_party/blink/web_tests/http/tests/devtools/network/network-not-modified-images-mime-type-expected.txt new file mode 100644 index 0000000..12197f7 --- /dev/null +++ b/third_party/blink/web_tests/http/tests/devtools/network/network-not-modified-images-mime-type-expected.txt
@@ -0,0 +1,6 @@ +Tests that if an image is cached and the server responds with 304, the image MIME type is shown correctly. + +http://127.0.0.1:8000/devtools/network/resources/resource.php?type=image&cached=1 200 image/png +Page reloaded. +http://127.0.0.1:8000/devtools/network/resources/resource.php?type=image&cached=1 304 image/png +
diff --git a/third_party/blink/web_tests/http/tests/devtools/network/network-not-modified-images-mime-type.js b/third_party/blink/web_tests/http/tests/devtools/network/network-not-modified-images-mime-type.js new file mode 100644 index 0000000..fe49efa --- /dev/null +++ b/third_party/blink/web_tests/http/tests/devtools/network/network-not-modified-images-mime-type.js
@@ -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. + +(async function() { + TestRunner.addResult(`Tests that if an image is cached and the server responds with 304, the image MIME type is shown correctly.\n`); + await TestRunner.loadModule('network_test_runner'); + await TestRunner.loadModule('console_test_runner'); + await TestRunner.showPanel('network'); + NetworkTestRunner.recordNetwork(); + await TestRunner.navigatePromise('resources/cached-image.html'); + const requests = NetworkTestRunner.networkRequests(); + const imageRequest = requests[requests.length - 1]; + TestRunner.addResult(`${imageRequest.url()} ${imageRequest.statusCode} ${imageRequest.mimeType}`); + TestRunner.reloadPage(function () { + const requests = NetworkTestRunner.networkRequests(); + const imageRequest = requests[requests.length - 1]; + TestRunner.addResult(`${imageRequest.url()} ${imageRequest.statusCode} ${imageRequest.mimeType}`); + TestRunner.completeTest(); + }); +})();
diff --git a/third_party/blink/web_tests/http/tests/devtools/network/resources/cached-image.html b/third_party/blink/web_tests/http/tests/devtools/network/resources/cached-image.html new file mode 100644 index 0000000..cd8ec68 --- /dev/null +++ b/third_party/blink/web_tests/http/tests/devtools/network/resources/cached-image.html
@@ -0,0 +1 @@ +<img src="resource.php?type=image&cached=1" /> \ No newline at end of file
diff --git a/third_party/blink/web_tests/inspector-protocol/overlay/overlay-persistent-overlays.js b/third_party/blink/web_tests/inspector-protocol/overlay/overlay-persistent-overlays.js index 468bda9..2e1319b 100644 --- a/third_party/blink/web_tests/inspector-protocol/overlay/overlay-persistent-overlays.js +++ b/third_party/blink/web_tests/inspector-protocol/overlay/overlay-persistent-overlays.js
@@ -42,6 +42,11 @@ }] }); + // Wait for overlay rendering to finish by requesting an animation frame. + await session.evaluate(() => { + return new Promise(resolve => requestAnimationFrame(resolve)); + }); + testRunner.log('Expected 3 track size labels; actual: ' + await getTrackSizeLabels()); testRunner.completeTest();
diff --git a/third_party/usrsctp/OWNERS b/third_party/usrsctp/OWNERS index f1ba0bb..aae538b0 100644 --- a/third_party/usrsctp/OWNERS +++ b/third_party/usrsctp/OWNERS
@@ -1,4 +1,4 @@ hta@chromium.org orphis@chromium.org -# COMPONENT: Internals>Networking +# COMPONENT: Blink>WebRTC>Network
diff --git a/third_party/zlib/contrib/tests/fuzzers/deflate_fuzzer.cc b/third_party/zlib/contrib/tests/fuzzers/deflate_fuzzer.cc index 6098ff1..c00e7155 100644 --- a/third_party/zlib/contrib/tests/fuzzers/deflate_fuzzer.cc +++ b/third_party/zlib/contrib/tests/fuzzers/deflate_fuzzer.cc
@@ -2,46 +2,73 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include <fuzzer/FuzzedDataProvider.h> #include <stddef.h> #include <stdint.h> +#include <stdio.h> +#include <stdlib.h> #include <string.h> -#include <cassert> #include <vector> #include "third_party/zlib/zlib.h" -static Bytef buffer[256 * 1024] = {0}; +// Fuzzer builds often have NDEBUG set, so roll our own assert macro. +#define ASSERT(cond) \ + do { \ + if (!(cond)) { \ + fprintf(stderr, "%s:%d Assert failed: %s\n", __FILE__, __LINE__, #cond); \ + exit(1); \ + } \ + } while (0) -// Entry point for LibFuzzer. extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { - // zlib's deflate requires non-zero input sizes - if (!size) - return 0; - - // We need to strip the 'const' for zlib. - std::vector<unsigned char> input_buffer{data, data+size}; - - uLongf buffer_length = static_cast<uLongf>(sizeof(buffer)); + FuzzedDataProvider fdp(data, size); + int level = fdp.PickValueInArray({0, 1, 2, 3, 4, 5, 6, 7, 8, 9}); + int windowBits = fdp.PickValueInArray({9, 10, 11, 12, 13, 14, 15}); + int memLevel = fdp.PickValueInArray({1, 2, 3, 4, 5, 6, 7, 8, 9}); + int strategy = fdp.PickValueInArray( + {Z_DEFAULT_STRATEGY, Z_FILTERED, Z_HUFFMAN_ONLY, Z_RLE, Z_FIXED}); + std::vector<uint8_t> src = fdp.ConsumeRemainingBytes<uint8_t>(); z_stream stream; - stream.next_in = input_buffer.data(); - stream.avail_in = size; - stream.total_in = size; - stream.next_out = buffer; - stream.avail_out = buffer_length; - stream.total_out = buffer_length; stream.zalloc = Z_NULL; stream.zfree = Z_NULL; - if (Z_OK != deflateInit(&stream, Z_DEFAULT_COMPRESSION)) { - deflateEnd(&stream); - assert(false); + // Compress the data one byte at a time to exercise the streaming code. + int ret = + deflateInit2(&stream, level, Z_DEFLATED, windowBits, memLevel, strategy); + ASSERT(ret == Z_OK); + std::vector<uint8_t> compressed(src.size() * 2 + 1000); + stream.next_out = compressed.data(); + stream.avail_out = compressed.size(); + for (uint8_t b : src) { + stream.next_in = &b; + stream.avail_in = 1; + ret = deflate(&stream, Z_NO_FLUSH); + ASSERT(ret == Z_OK); } - - auto deflate_result = deflate(&stream, Z_NO_FLUSH); + stream.next_in = Z_NULL; + stream.avail_in = 0; + ret = deflate(&stream, Z_FINISH); + ASSERT(ret == Z_STREAM_END); + compressed.resize(compressed.size() - stream.avail_out); deflateEnd(&stream); - if (Z_OK != deflate_result) - assert(false); + + // Verify that the data decompresses correctly. + ret = inflateInit2(&stream, windowBits); + ASSERT(ret == Z_OK); + // Make room for at least one byte so it's never empty. + std::vector<uint8_t> decompressed(src.size() + 1); + stream.next_in = compressed.data(); + stream.avail_in = compressed.size(); + stream.next_out = decompressed.data(); + stream.avail_out = decompressed.size(); + ret = inflate(&stream, Z_FINISH); + ASSERT(ret == Z_STREAM_END); + decompressed.resize(decompressed.size() - stream.avail_out); + inflateEnd(&stream); + + ASSERT(decompressed == src); return 0; }
diff --git a/tools/android/instant_start/.style.yapf b/tools/android/instant_start/.style.yapf new file mode 100644 index 0000000..557fa7b --- /dev/null +++ b/tools/android/instant_start/.style.yapf
@@ -0,0 +1,2 @@ +[style] +based_on_style = pep8
diff --git a/tools/android/instant_start/.vpython b/tools/android/instant_start/.vpython new file mode 100644 index 0000000..06dc729 --- /dev/null +++ b/tools/android/instant_start/.vpython
@@ -0,0 +1,61 @@ +# 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. + +# //.vpython doesn't have scipy, so we have to use our own .vpython file. +# The wheel specs are from //v8/tools/callstats.py.vpython and //.vpython. + +# pandas for python3 is not yet available in cipd. +# TODO(crbug.com/1130251): update to python3 +python_version: "2.7" + +wheel: < + name: "infra/python/wheels/scipy/${vpython_platform}" + version: "version:0.19.0" + match_tag: < + abi: "cp27mu" + platform: "manylinux1_i686" + > + match_tag: < + abi: "cp27mu" + platform: "manylinux1_x86_64" + > +> +wheel: < + name: "infra/python/wheels/numpy/${vpython_platform}" + version: "version:1.11.3" +> +wheel: < + name: "infra/python/wheels/six-py2_py3" + version: "version:1.15.0" +> +wheel: < + name: "infra/python/wheels/pandas/${vpython_platform}" + version: "version:0.23.4" + match_tag: < + platform: "win32" + > + match_tag: < + platform: "win_amd64" + > + match_tag: < + abi: "cp27mu" + platform: "manylinux1_i686" + > + match_tag: < + abi: "cp27mu" + platform: "manylinux1_x86_64" + > + match_tag: < + platform: "macosx_10_6_intel" + > +> +wheel: < + name: "infra/python/wheels/pytz-py2_py3" + version: "version:2018.4" +> +wheel: < + name: "infra/python/wheels/python-dateutil-py2_py3" + version: "version:2.7.3" +> +
diff --git a/tools/android/instant_start/OWNERS b/tools/android/instant_start/OWNERS new file mode 100644 index 0000000..39230171 --- /dev/null +++ b/tools/android/instant_start/OWNERS
@@ -0,0 +1 @@ +wychen@chromium.org
diff --git a/tools/android/instant_start/README.md b/tools/android/instant_start/README.md new file mode 100644 index 0000000..5448990 --- /dev/null +++ b/tools/android/instant_start/README.md
@@ -0,0 +1,52 @@ +# Benchmarking and analyzing scripts for Instant Start + +## Introduction + +In order to understand the performance implication of a CL, we can do a local +benchmark to compare the before/after metrics. + +## Usage + +Build two APKs for before and after a CL, on gn target `monochrome_apk`, and +make sure they are on different Chrome channels, like Canary (gn args +`android_channel = "canary"`) and default (unspecified) because they will be +installed side by side. Depending on your preferred workflow, you can use two +separate workspaces like `~/code/clankium/src` and `~/code/clankium2/src`, or +use the same workspace but two different output directories like `./out/Release` +and `./out/Release2`, or simply use the same output directory but rename the APK +like `out/Release/bin/monochrome_before_apk` and +`out/Release/bin/monochrome_after_apk`. + +On the device, uninstall Chrome of these two channels to make sure the +environment is clean. Otherwise, chrome://flags changes and Finch trials could +introduce undesirable differences. You can use the `--reinstall` option to +automate this. When running benchmark.py, first-run experience (FRE) would be +skipped, but you'll need to manually create one tab, make sure Feed is loaded, +and swipe away the login prompt in the dry-run step. Follow the instructions of +the script. + +The command line looks like this: + +```bash +./tools/android/instant_start/benchmark.py --control-apk out/Release/bin/monochrome_before_apk --experiment-apk out/Release/bin/monochrome_after_apk -v --repeat 100 --reinstall +``` + +The metrics are persisted to `runs.pickle` by default, and the filename can be +specified by `--data-output` option. This can later be analyzed like this: + +```bash +./tools/android/instant_start/analyze.py runs.pickle +``` + +The output looks like: + +``` +Reading runs-pixel3xl.pickle with {'model': 'Pixel 3 XL', 'start_time': datetime.datetime(2020, 9, 19, 14, 55, 34, 596731)} +100 samples on Pixel 3 XL + Median Diff with control p-value +FirstDrawCompletedTime 155.0ms -13.5ms (-8.71%) 0.000000 +SingleTabTitleAvailableTime 117.0ms -13.0ms (-11.11%) 0.000000 +FeedStreamCreatedTime 356.0ms -35.5ms (-9.97%) 0.000001 +FeedsLoadingPlaceholderShown 94.5ms -2.0ms (-2.12%) 0.007312 +FeedContentFirstLoadedTime 924.0ms -6.5ms (-0.70%) 0.034100 +```
diff --git a/tools/android/instant_start/analyze.py b/tools/android/instant_start/analyze.py new file mode 100755 index 0000000..2590747 --- /dev/null +++ b/tools/android/instant_start/analyze.py
@@ -0,0 +1,37 @@ +#!/usr/bin/env vpython +# +# 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. +"""Analyze benchmark results for Instant start.""" + +from __future__ import print_function + +import argparse +import pickle +import sys + +import stats.analyze + + +def main(): + """Main program""" + parser = argparse.ArgumentParser( + description=__doc__, + formatter_class=argparse.ArgumentDefaultsHelpFormatter) + parser.add_argument('pickles', + nargs='+', + help='The pickle files saved by benchmark.py.') + args = parser.parse_args() + + runs = [] + for filename in args.pickles: + with open(filename, 'rb') as file: + metadata = pickle.load(file) + print('Reading "%s" with %s' % (filename, metadata)) + runs.extend(pickle.load(file)) + stats.analyze.print_report(runs, metadata['model']) + + +if __name__ == '__main__': + sys.exit(main())
diff --git a/tools/android/instant_start/benchmark.py b/tools/android/instant_start/benchmark.py new file mode 100755 index 0000000..6e0b11d --- /dev/null +++ b/tools/android/instant_start/benchmark.py
@@ -0,0 +1,205 @@ +#!/usr/bin/env vpython +# +# 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. +"""Run benchmark for Instant start.""" + +from __future__ import print_function + +import argparse +from datetime import datetime +import logging +import os +import pickle +import random +import re +import subprocess +import sys +import time + +import stats.analyze + + +def get_timestamp(adb_log_line): + """Parse the timestamp in the adb log""" + # adb log doesn't have the year field printed out. + parsed = datetime.strptime(adb_log_line[0:18], '%m-%d %H:%M:%S.%f') + return parsed.replace(year=datetime.now().year) + + +def keep_awake(): + """Keep the device awake. This works for non-rooted devices as well.""" + os.system("adb shell svc power stayon true") + os.system("adb shell input keyevent mouse") + + +def get_model(): + """Get the device model.""" + return subprocess.check_output( + ['adb', 'shell', 'getprop', 'ro.product.model']).rstrip() + + +def run_apk(variant, dry_run=False, reinstall=False, check_state=False): + """Run Chrome and return metrics""" + + keep_awake() + + variant_name, apk_script, extra_cmd = variant + logging.warning('Running variant "%s"', variant_name) + assert os.path.exists(apk_script), "Script '%s' doesn't exist" % apk_script + + features = '--enable-features=' + ','.join([ + 'TabGroupsAndroid<Study', 'TabSwitcherOnReturn<Study', + 'StartSurfaceAndroid<Study', 'InstantStart<Study' + ]) + + args = '--args=' + ' '.join([ + '--disable-fre', '--disable-field-trial-config', features, + '--force-fieldtrials=Study/Group', + '--force-fieldtrial-params=Study.Group:' + 'tab_switcher_on_return_time_ms/0' + '/start_surface_variation/single' + '/show_last_active_tab_only/true' + '/open_ntp_instead_of_start/true' + '/exclude_mv_tiles/true' + ] + extra_cmd) + + if reinstall: + logging.warning('Uninstalling') + cmd = [apk_script, 'uninstall'] + logging.info('Running %s', cmd) + logging.info(subprocess.check_output(cmd, stderr=subprocess.STDOUT)) + + # Use "unbuffer" to force flushing the output of |apk_script|. + cmd = ['unbuffer', apk_script, 'run', '-vvv', args] + logging.info('Running %s', cmd) + # Use unbuffered pipe to avoid blocking. + proc = subprocess.Popen(cmd, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + bufsize=0) + latencies = [] + events_re = re.compile( + r"Startup.Android.(?P<name>[0-9a-zA-Z_]+)[^ ]* = (?P<value>[0-9.]+)") + + # Avoid buffering in proc.stdout.next(). + # "for line in prod.stdout" might block. + # See https://stackoverflow.com/questions/1183643/ + for line in iter(proc.stdout.readline, b''): + if isinstance(line, bytes): + line = line.decode(encoding='utf8') + logging.debug(line.rstrip()) + if ('ActivityTaskManager' in line + or 'ActivityManager' in line) and 'START' in line: + start_timestamp = get_timestamp(line) + logging.info('Chrome started at %s', start_timestamp) + if dry_run: + time.sleep(5) + if check_state: + logging.warning('Make sure there is at least one tab, ' + 'and the Feed is loaded. ' + 'Press Enter to continue.') + sys.stdin.readline() + break + groups = events_re.search(line) + if groups: + latency = {} + latency['variant_name'] = variant_name + latency['metric_name'] = groups.group('name') + latency['value'] = groups.group('value') + latencies.append(latency) + logging.info(line.rstrip()) + logging.info('Got %s = %s', groups.group('name'), + groups.group('value')) + if len(latencies) >= 5: + break + + proc.kill() + return latencies + + +def main(): + """Entry point of the benchmark script""" + parser = argparse.ArgumentParser( + description=__doc__, + formatter_class=argparse.ArgumentDefaultsHelpFormatter) + parser.add_argument('--control-apk', + default='out/Release/bin/monochrome_apk', + help='The APK script file for control behavior.') + parser.add_argument('--experiment-apk', + default='out/Release/bin/monochrome_apk', + help='The APK script file for experiment behavior.') + parser.add_argument('--reinstall', + action='store_true', + help='Uninstall before installing the APKs.') + parser.add_argument('--repeat', + type=int, + default=3, + help='How many times to repeat running.') + parser.add_argument('--data-output', + default='runs.pickle', + help='The output file for benchmark data.') + parser.add_argument('-v', + '--verbose', + action='count', + default=0, + help='Be more verbose.') + args, _ = parser.parse_known_args() + + level = logging.WARNING + if args.verbose == 1: + level = logging.INFO + elif args.verbose >= 2: + level = logging.DEBUG + logging.basicConfig(level=level, + format='%(asctime)-2s %(levelname)-8s %(message)s') + logging.addLevelName( + logging.WARNING, + "\033[1;31m%s\033[1;0m" % logging.getLevelName(logging.WARNING)) + logging.addLevelName( + logging.ERROR, + "\033[1;41m%s\033[1;0m" % logging.getLevelName(logging.ERROR)) + + try: + subprocess.check_output('which unbuffer', shell=True) + except subprocess.CalledProcessError: + sys.exit('ERROR: "unbuffer" not found. ' + + 'Install by running "sudo apt install expect".') + + logging.warning('Make sure the device screen is unlocked. ' + 'Otherwise the benchmark might get stuck.') + + # List control/experiment APKs for side-by-side comparison. + variants = [] + variants.append(('control', args.control_apk, [])) + variants.append(('experiment', args.experiment_apk, [])) + + metadata = {'model': get_model(), 'start_time': datetime.now()} + + logging.warning('Pre-run for flag caching.') + for variant in variants: + run_apk(variant, dry_run=True, reinstall=args.reinstall) + + logging.warning('Dry-run for manual state checking.') + for variant in variants: + run_apk(variant, dry_run=True, check_state=True) + + runs = [] + for i in range(args.repeat): + logging.warning('Run %d/%d', i + 1, args.repeat) + random.shuffle(variants) + for variant in variants: + result = run_apk(variant) + logging.info('Results: %s', result) + runs.extend(result) + time.sleep(10) # try to avoid overloading the device. + with open(args.data_output, 'wb') as pickle_file: + pickle.dump(metadata, pickle_file) + pickle.dump(runs, pickle_file) + logging.info('Saved "%s"', args.data_output) + stats.analyze.print_report(runs, metadata['model']) + + +if __name__ == '__main__': + sys.exit(main())
diff --git a/tools/android/instant_start/stats/__init__.py b/tools/android/instant_start/stats/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/tools/android/instant_start/stats/__init__.py
diff --git a/tools/android/instant_start/stats/analyze.py b/tools/android/instant_start/stats/analyze.py new file mode 100644 index 0000000..a0ba8ee --- /dev/null +++ b/tools/android/instant_start/stats/analyze.py
@@ -0,0 +1,34 @@ +# 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. +"""Library for analyzing benchmark results for Instant start.""" + +import pandas +from scipy import stats + + +def print_report(runs, model, control='control', experiment='experiment'): + """Print stats of A/B testing""" + all_df = pandas.DataFrame(runs, dtype=float) + report = pandas.DataFrame( + columns=['Median', 'Diff with control', 'p-value']) + for metric in sorted(set(all_df['metric_name'])): + mdf = all_df[all_df['metric_name'] == metric] + df = pandas.DataFrame() + for variant in sorted(set(all_df['variant_name'])): + df[variant] = mdf[mdf['variant_name'] == variant]\ + .value.reset_index(drop=True) + + diff_df = pandas.DataFrame() + diff_df = df[experiment] - df[control] + n = len(diff_df) + + row = {} + row['Median'] = '%.1fms' % df[experiment].median() + row['Diff with control'] = '%.1fms (%.2f%%)' % ( + diff_df.median(), diff_df.median() / df[experiment].median() * 100) + row['p-value'] = '%f' % (stats.ttest_rel(df[experiment], + df[control])[1]) + report = report.append(pandas.Series(data=row, name=metric)) + print('%d samples on %s' % (n, model)) + print(report.sort_values(by='p-value'))
diff --git a/tools/gritsettings/resource_ids.spec b/tools/gritsettings/resource_ids.spec index 3ea5e383..a411c2a 100644 --- a/tools/gritsettings/resource_ids.spec +++ b/tools/gritsettings/resource_ids.spec
@@ -195,7 +195,10 @@ "includes": [1830], "structures": [1840], }, - "chrome/browser/resources/signin/profile_picker/profile_picker_resources.grd": { + "chrome/browser/resources/signin/profile_picker/profile_picker_resources_vulcanized.grd": { + "includes": [1850], + }, + "chrome/browser/resources/signin/profile_picker/profile_picker_resources.grd": { "includes": [1860], "structures": [1870], },
diff --git a/tools/metrics/actions/actions.xml b/tools/metrics/actions/actions.xml index 25f69a4f..f617667 100644 --- a/tools/metrics/actions/actions.xml +++ b/tools/metrics/actions/actions.xml
@@ -16089,6 +16089,13 @@ </description> </action> +<action name="NewTabPage_Promos_SafetyCheck"> + <owner>msramek@chromium.org</owner> + <description> + Recorded when the user clicks a Safety Check promotion on the New Tab Page. + </description> +</action> + <action name="NewTabPage_ReopenTab"> <owner>Please list the metric's owners. Add more owner tags as needed.</owner> <description>Please enter the description of this user action.</description>
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index a55f662..c7fc4b17 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -21829,6 +21829,7 @@ <int value="784" label="QuickUnlockModeAllowlist"/> <int value="785" label="AttestationExtensionAllowlist"/> <int value="786" label="DataLeakPreventionRulesList"/> + <int value="787" label="WebRtcAllowLegacyTLSProtocols"/> </enum> <enum name="EnterprisePolicyDeviceIdValidity"> @@ -54918,6 +54919,13 @@ <int value="1" label="Passwords and generate new password"/> </enum> +<enum name="PasswordEditUpdatedValues"> + <int value="0" label="None"/> + <int value="1" label="Username"/> + <int value="2" label="Password"/> + <int value="3" label="Both"/> +</enum> + <enum name="PasswordFormQueryVolume"> <int value="0" label="New password query"/> <int value="1" label="Current query"/>
diff --git a/tools/metrics/histograms/histograms_xml/content/histograms.xml b/tools/metrics/histograms/histograms_xml/content/histograms.xml index c8e6fc8..937d515d97 100644 --- a/tools/metrics/histograms/histograms_xml/content/histograms.xml +++ b/tools/metrics/histograms/histograms_xml/content/histograms.xml
@@ -264,8 +264,9 @@ </histogram> <histogram name="ContentSettings.EphemeralFlashPermission" - enum="ContentSettings.EphemeralFlashPermission" expires_after="M87"> + enum="ContentSettings.EphemeralFlashPermission" expires_after="M89"> <owner>engedy@chromium.org</owner> + <owner>src/components/permissions/PERMISSIONS_OWNERS</owner> <summary> Records the number of times Flash permission is granted for a host. </summary>
diff --git a/tools/metrics/histograms/histograms_xml/cryptohome/histograms.xml b/tools/metrics/histograms/histograms_xml/cryptohome/histograms.xml index 70823b44..6115181 100644 --- a/tools/metrics/histograms/histograms_xml/cryptohome/histograms.xml +++ b/tools/metrics/histograms/histograms_xml/cryptohome/histograms.xml
@@ -266,6 +266,16 @@ </summary> </histogram> +<histogram name="Cryptohome.InvalidateDirCryptoKeyResult" enum="BooleanSuccess" + expires_after="2021-09-26"> + <owner>yich@google.com</owner> + <owner>cros-hwsec+uma@chromium.org</owner> + <summary> + The errors resulting from interacting with the InvalidateDirCryptoKey + operation. + </summary> +</histogram> + <histogram base="true" name="Cryptohome.LECredential" enum="CryptohomeLECredError" expires_after="2021-02-28"> <!-- Name completed by histogram_suffixes name="LECredentialOps" -->
diff --git a/tools/metrics/histograms/histograms_xml/enterprise/histograms.xml b/tools/metrics/histograms/histograms_xml/enterprise/histograms.xml index 953f78d8..1f616844 100644 --- a/tools/metrics/histograms/histograms_xml/enterprise/histograms.xml +++ b/tools/metrics/histograms/histograms_xml/enterprise/histograms.xml
@@ -170,6 +170,18 @@ <summary>URL fetcher status for auto-enrollment requests.</summary> </histogram> +<histogram base="true" name="Enterprise.CachedDevicePolicyDeviceIdValidity" + enum="EnterprisePolicyDeviceIdValidity" expires_after="M95"> + <owner>emaxx@chromium.org</owner> + <owner>rodmartin@chromium.org</owner> + <summary> + Result of the device ID validation in the device policy blob for those which + were loaded from disk. This validation happens on enrolled devices on + startup, on scheduled policy reloads that happen every few hours, and on + forced policy reloads. + </summary> +</histogram> + <histogram name="Enterprise.CBCMPolicyInvalidations" enum="EnterprisePolicyInvalidations" expires_after="2021-06-16"> <owner>anthonyvd@google.com</owner>
diff --git a/tools/metrics/histograms/histograms_xml/file/histograms.xml b/tools/metrics/histograms/histograms_xml/file/histograms.xml index 0b626ed3..adb51da 100644 --- a/tools/metrics/histograms/histograms_xml/file/histograms.xml +++ b/tools/metrics/histograms/histograms_xml/file/histograms.xml
@@ -129,6 +129,20 @@ </summary> </histogram> +<histogram name="FileBrowser.DriveHostedFilePinSuccess" enum="BooleanSuccess" + expires_after="M92"> + <owner>austinct@chromium.org</owner> + <owner>dats@chromium.org</owner> + <summary>Tracks success rate of pinning hosted files in Drive.</summary> +</histogram> + +<histogram name="FileBrowser.DrivePinSuccess" enum="BooleanSuccess" + expires_after="M92"> + <owner>austinct@chromium.org</owner> + <owner>dats@chromium.org</owner> + <summary>Tracks success rate of pinning files in Drive.</summary> +</histogram> + <histogram name="FileBrowser.FileSystemProviderMounted" enum="FileSystemProviderMountType" expires_after="M89"> <owner>slangley@chromium.org</owner>
diff --git a/tools/metrics/histograms/histograms_xml/geolocation/histograms.xml b/tools/metrics/histograms/histograms_xml/geolocation/histograms.xml index 8b3bbd6..fe051f9b 100644 --- a/tools/metrics/histograms/histograms_xml/geolocation/histograms.xml +++ b/tools/metrics/histograms/histograms_xml/geolocation/histograms.xml
@@ -136,7 +136,7 @@ </histogram> <histogram base="true" name="Geolocation.SettingsDialog.AcceptEvent" - enum="GeolocationSettingsDialogBackOff" expires_after="M87"> + enum="GeolocationSettingsDialogBackOff" expires_after="M89"> <owner>engedy@chromium.org</owner> <owner>src/components/permissions/PERMISSIONS_OWNERS</owner> <summary> @@ -146,7 +146,7 @@ </histogram> <histogram base="true" name="Geolocation.SettingsDialog.DenyEvent" - enum="GeolocationSettingsDialogBackOff" expires_after="M87"> + enum="GeolocationSettingsDialogBackOff" expires_after="M89"> <owner>engedy@chromium.org</owner> <owner>src/components/permissions/PERMISSIONS_OWNERS</owner> <summary> @@ -156,7 +156,7 @@ </histogram> <histogram base="true" name="Geolocation.SettingsDialog.ShowEvent" - enum="GeolocationSettingsDialogBackOff" expires_after="M87"> + enum="GeolocationSettingsDialogBackOff" expires_after="M89"> <owner>engedy@chromium.org</owner> <owner>src/components/permissions/PERMISSIONS_OWNERS</owner> <summary> @@ -166,7 +166,7 @@ </histogram> <histogram base="true" name="Geolocation.SettingsDialog.SuppressEvent" - enum="GeolocationSettingsDialogBackOff" expires_after="M87"> + enum="GeolocationSettingsDialogBackOff" expires_after="M89"> <owner>engedy@chromium.org</owner> <owner>src/components/permissions/PERMISSIONS_OWNERS</owner> <summary>
diff --git a/tools/metrics/histograms/histograms_xml/others/histograms.xml b/tools/metrics/histograms/histograms_xml/others/histograms.xml index ba10b33..d90974c 100644 --- a/tools/metrics/histograms/histograms_xml/others/histograms.xml +++ b/tools/metrics/histograms/histograms_xml/others/histograms.xml
@@ -7956,10 +7956,9 @@ </histogram> <histogram name="ManagedUsers.SafetyFilter" - enum="SupervisedUserSafetyFilterResult" expires_after="M85"> - <owner>treib@chromium.org</owner> - <owner>escordeiro@chromium.org</owner> - <owner>menegola@chromium.org</owner> + enum="SupervisedUserSafetyFilterResult" expires_after="2021-09-27"> + <owner>agawronska@chromium.org</owner> + <owner>cros-families-eng@google.com</owner> <summary> The counts of results from the supervised user safety filter. Each entry includes the outcome of the filter (i.e. allowed, blocked, or unknown) and
diff --git a/tools/metrics/histograms/histograms_xml/password/histograms.xml b/tools/metrics/histograms/histograms_xml/password/histograms.xml index d24e4a4..e65cf0d6 100644 --- a/tools/metrics/histograms/histograms_xml/password/histograms.xml +++ b/tools/metrics/histograms/histograms_xml/password/histograms.xml
@@ -1572,6 +1572,16 @@ <summary>Logs the state of the password dropdown when it's shown.</summary> </histogram> +<histogram name="PasswordManager.PasswordEditUpdatedValues" + enum="PasswordEditUpdatedValues" expires_after="M92"> + <owner>vsemeniuk@google.com</owner> + <owner>vasilii@chromium.org</owner> + <summary> + This metric shows what exactly users change in the password edit dialog: + nothing, username, password or both. + </summary> +</histogram> + <histogram name="PasswordManager.PasswordReuse.NumberOfMatches" units="credentials" expires_after="2021-01-30"> <owner>vakh@chromium.org</owner>
diff --git a/tools/metrics/histograms/histograms_xml/settings/histograms.xml b/tools/metrics/histograms/histograms_xml/settings/histograms.xml index 3c364db..16df0e2 100644 --- a/tools/metrics/histograms/histograms_xml/settings/histograms.xml +++ b/tools/metrics/histograms/histograms_xml/settings/histograms.xml
@@ -482,8 +482,9 @@ </histogram> <histogram name="SettingsResetPrompt.PromptAccepted" enum="BooleanAccepted" - expires_after="M85"> - <owner>alito@chromium.org</owner> + expires_after="M90"> + <owner>proberge@chromium.org</owner> + <owner>chrome-safebrowsing-alerts@google.com</owner> <summary> Indicates whether the user accepted the settings reset prompt. </summary>
diff --git a/ui/base/clipboard/clipboard_data_endpoint.h b/ui/base/clipboard/clipboard_data_endpoint.h index 6ec606b..9e6f12d 100644 --- a/ui/base/clipboard/clipboard_data_endpoint.h +++ b/ui/base/clipboard/clipboard_data_endpoint.h
@@ -16,11 +16,14 @@ // Whenever a new format is supported, a new enum should be added. enum class EndpointType { #if defined(OS_CHROMEOS) || (OS_LINUX) || (OS_FUCHSIA) - kGuestOs = 0, // Guest OS: ARC++, PluginVM, Crostini. -#endif - kUrl = 1, // Website URL e.g. www.example.com. - kClipboardHistory = - 2, // Clipboard History UI has privileged access to any clipboard data. + kGuestOs = 0, // Guest OS: PluginVM, Crostini. +#endif // defined(OS_CHROMEOS) || (OS_LINUX) || (OS_FUCHSIA) +#if defined(OS_CHROMEOS) + kArc = 1, // ARC. +#endif // defined(OS_CHROMEOS) + kUrl = 2, // Website URL e.g. www.example.com. + kClipboardHistory = 3, // Clipboard History UI has privileged access to any + // clipboard data. kMaxValue = kClipboardHistory };
diff --git a/ui/chromeos/file_manager_strings.grdp b/ui/chromeos/file_manager_strings.grdp index b2b35588..3c035508 100644 --- a/ui/chromeos/file_manager_strings.grdp +++ b/ui/chromeos/file_manager_strings.grdp
@@ -768,7 +768,7 @@ Copy operation failed, unexpected error: <ph name="ERROR_MESSAGE">$1<ex>Could not copy</ex></ph> </message> <message name="IDS_FILE_BROWSER_FILE_COPIED" desc="File Manager status message. 'Item' is used here as a generic term for file or directory."> - <ph name="NUMBER_OF_ITEMS">$1<ex>3</ex></ph> copied. + <ph name="FILE_NAME">$1<ex>big.xz</ex></ph> copied. </message> <message name="IDS_FILE_BROWSER_FILE_ITEMS" desc="File Manager status message. 'Item' is used here as a generic term for file or directory."> <ph name="NUMBER_OF_ITEMS">$1<ex>3</ex></ph> items @@ -780,7 +780,7 @@ <ph name="NUMBER_OF_ITEMS">$1<ex>3</ex></ph> items moved. </message> <message name="IDS_FILE_BROWSER_FILE_MOVED" desc="File Manager status message. 'Item' is used here as a generic term for file or directory."> - <ph name="NUMBER_OF_ITEMS">$1<ex>3</ex></ph> moved. + <ph name="FILE_NAME">$1<ex>big.xz</ex></ph> moved. </message> <!-- TODO (crbug/1093603): Clean up after FilesTransferDetails launch. --> <message name="IDS_FILE_BROWSER_MOVE_FILE_NAME" desc="File Manager status message.">
diff --git a/ui/chromeos/file_manager_strings_grdp/IDS_FILE_BROWSER_FILE_COPIED.png.sha1 b/ui/chromeos/file_manager_strings_grdp/IDS_FILE_BROWSER_FILE_COPIED.png.sha1 index 99fbde2..b315822 100644 --- a/ui/chromeos/file_manager_strings_grdp/IDS_FILE_BROWSER_FILE_COPIED.png.sha1 +++ b/ui/chromeos/file_manager_strings_grdp/IDS_FILE_BROWSER_FILE_COPIED.png.sha1
@@ -1 +1 @@ -d0218c6981c069857eba06ad3f94bf373dc40573 \ No newline at end of file +82c96c11c0634040463a9670fa9ab31af88bf927 \ No newline at end of file
diff --git a/ui/chromeos/file_manager_strings_grdp/IDS_FILE_BROWSER_FILE_MOVED.png.sha1 b/ui/chromeos/file_manager_strings_grdp/IDS_FILE_BROWSER_FILE_MOVED.png.sha1 index 502f68e..149d18f 100644 --- a/ui/chromeos/file_manager_strings_grdp/IDS_FILE_BROWSER_FILE_MOVED.png.sha1 +++ b/ui/chromeos/file_manager_strings_grdp/IDS_FILE_BROWSER_FILE_MOVED.png.sha1
@@ -1 +1 @@ -6cb05b5c6046c76d4cec2360f28df27c93c37c66 \ No newline at end of file +5d5c3b153e7bc697e43b9546acc4b15499f54553 \ No newline at end of file
diff --git a/ui/file_manager/file_manager/foreground/js/actions_model.js b/ui/file_manager/file_manager/foreground/js/actions_model.js index 89a95d9..b829f94 100644 --- a/ui/file_manager/file_manager/foreground/js/actions_model.js +++ b/ui/file_manager/file_manager/foreground/js/actions_model.js
@@ -254,6 +254,11 @@ // Check the result of pinning. entryPinned: () => { error = !!chrome.runtime.lastError; + metrics.recordBoolean('DrivePinSuccess', !error); + if (this.metadataModel_.getCache([currentEntry], ['hosted'])[0] + .hosted) { + metrics.recordBoolean('DriveHostedFilePinSuccess', !error); + } if (error && this.value_) { this.metadataModel_.get([currentEntry], ['size']).then(results => { steps.showError(results[0].size);
diff --git a/ui/file_manager/file_manager/foreground/js/actions_model_unittest.js b/ui/file_manager/file_manager/foreground/js/actions_model_unittest.js index ece9076..dde8567 100644 --- a/ui/file_manager/file_manager/foreground/js/actions_model_unittest.js +++ b/ui/file_manager/file_manager/foreground/js/actions_model_unittest.js
@@ -109,6 +109,17 @@ installMockChrome(mockChrome); new MockCommandLinePrivate(); + // Mock metrics. + window.metrics = { + calls: { + DrivePinSuccess: 0, + DriveHostedFilePinSuccess: 0, + }, + recordBoolean: function(name) { + window.metrics.calls[name]++; + }, + }; + // Setup Drive file system. volumeManager = new MockVolumeManager(); let type = VolumeManagerCommon.VolumeType.DRIVE; @@ -265,6 +276,9 @@ assertTrue(metadataModel.properties.pinned); assertEquals(1, invalidated); + assertEquals(1, window.metrics.calls['DrivePinSuccess']); + assertEquals(0, window.metrics.calls['DriveHostedFilePinSuccess']); + // The model is invalidated, as list of actions have changed. // Recreated the model and check that the actions are updated. model = new ActionsModel( @@ -382,6 +396,9 @@ assertTrue(!!metadataModel.getCache([testDocument])[0].pinned); assertTrue(!!metadataModel.getCache([testFile])[0].pinned); + assertEquals(2, window.metrics.calls['DrivePinSuccess']); + assertEquals(1, window.metrics.calls['DriveHostedFilePinSuccess']); + model = new ActionsModel( volumeManager, metadataModel, shortcutsModel, driveSyncHandler, ui, [testDocument, testFile]); @@ -489,6 +506,9 @@ assertFalse(!!metadataModel.getCache([testDocument])[0].pinned); assertTrue(!!metadataModel.getCache([testFile])[0].pinned); + assertEquals(1, window.metrics.calls['DrivePinSuccess']); + assertEquals(0, window.metrics.calls['DriveHostedFilePinSuccess']); + model = new ActionsModel( volumeManager, metadataModel, shortcutsModel, driveSyncHandler, ui, [testDocument, testFile]);
diff --git a/ui/file_manager/image_loader/BUILD.gn b/ui/file_manager/image_loader/BUILD.gn index 82e3096..f369640 100644 --- a/ui/file_manager/image_loader/BUILD.gn +++ b/ui/file_manager/image_loader/BUILD.gn
@@ -41,7 +41,6 @@ ":cache", ":image_request_task", ":load_image_request", - ":piex_loader", ":scheduler", "//ui/file_manager/externs:file_manager_private", ]
diff --git a/ui/file_manager/image_loader/image_loader.js b/ui/file_manager/image_loader/image_loader.js index c79c95d0..3a7dc1d 100644 --- a/ui/file_manager/image_loader/image_loader.js +++ b/ui/file_manager/image_loader/image_loader.js
@@ -21,12 +21,6 @@ */ this.scheduler_ = new Scheduler(); - /** - * Piex loader for RAW images. - * @private {!PiexLoader} - */ - this.piexLoader_ = new PiexLoader(); - // Grant permissions to all volumes, initialize the cache and then start the // scheduler. chrome.fileManagerPrivate.getVolumeMetadataList(function(volumeMetadataList) { @@ -155,8 +149,8 @@ return false; // No callback calls. } else { // Create a request task and add it to the scheduler (queue). - const requestTask = new ImageRequestTask( - requestId, this.cache_, this.piexLoader_, request, callback); + const requestTask = + new ImageRequestTask(requestId, this.cache_, request, callback); this.scheduler_.add(requestTask); return true; // Request will call the callback. }
diff --git a/ui/file_manager/image_loader/image_request_task.js b/ui/file_manager/image_loader/image_request_task.js index cc39051..e9eba78 100644 --- a/ui/file_manager/image_loader/image_request_task.js +++ b/ui/file_manager/image_loader/image_request_task.js
@@ -8,12 +8,11 @@ * * @param {string} id Request ID. * @param {ImageCache} cache Cache object. - * @param {!PiexLoader} piexLoader Piex loader for RAW file. * @param {!LoadImageRequest} request Request message as a hash array. * @param {function(!LoadImageResponse)} callback Response handler. * @constructor */ -function ImageRequestTask(id, cache, piexLoader, request, callback) { +function ImageRequestTask(id, cache, request, callback) { /** * Global ID (concatenated client ID and client request ID). * @type {string} @@ -28,12 +27,6 @@ this.cache_ = cache; /** - * @type {!PiexLoader} - * @private - */ - this.piexLoader_ = piexLoader; - - /** * @type {!LoadImageRequest} * @private */ @@ -339,7 +332,8 @@ // Load RAW image source thumbnail. if (fileType.type === 'raw') { - this.piexLoader_.load(this.request_.url, chrome.runtime.reload) + const piexLoader = ImageRequestTask.getPiexLoaderInstance(); + piexLoader.load(this.request_.url, chrome.runtime.reload) .then( function(data) { this.request_.orientation = @@ -636,3 +630,14 @@ this.canvas_.width = 0; this.canvas_.height = 0; }; + +/** + * Returns the singleton instance of the PiexLoader RAW image loader. + * @return {!PiexLoader} PiexLoader object. + */ +ImageRequestTask.getPiexLoaderInstance = function() { + if (!ImageRequestTask.piexLoaderInstance_) { + ImageRequestTask.piexLoaderInstance_ = new PiexLoader(); + } + return ImageRequestTask.piexLoaderInstance_; +};
diff --git a/ui/gtk/native_theme_gtk.cc b/ui/gtk/native_theme_gtk.cc index e4b9c5e5..a77c571 100644 --- a/ui/gtk/native_theme_gtk.cc +++ b/ui/gtk/native_theme_gtk.cc
@@ -77,6 +77,8 @@ // Dialogs case ui::NativeTheme::kColorId_DialogBackground: case ui::NativeTheme::kColorId_BubbleBackground: + // Notifications + case ui::NativeTheme::kColorId_NotificationDefaultBackground: return GetBgColor(""); case ui::NativeTheme::kColorId_DialogForeground: case ui::NativeTheme::kColorId_BubbleForeground:
diff --git a/ui/message_center/views/message_view.cc b/ui/message_center/views/message_view.cc index a32dd95..4a0e6ba 100644 --- a/ui/message_center/views/message_view.cc +++ b/ui/message_center/views/message_view.cc
@@ -173,9 +173,7 @@ void MessageView::UpdateCornerRadius(int top_radius, int bottom_radius) { SetCornerRadius(top_radius, bottom_radius); - SetBackground(views::CreateBackgroundFromPainter( - std::make_unique<NotificationBackgroundPainter>(top_radius, - bottom_radius))); + UpdateBackgroundPainter(); SchedulePaint(); } @@ -251,7 +249,7 @@ } bool MessageView::OnKeyReleased(const ui::KeyEvent& event) { - // Space key handling is triggerred at key-release timing. See + // Space key handling is triggered at key-release timing. See // ui/views/controls/buttons/button.cc for why. if (event.flags() != ui::EF_NONE || event.key_code() != ui::VKEY_SPACE) return false; @@ -327,6 +325,7 @@ void MessageView::OnThemeChanged() { InkDropHostView::OnThemeChanged(); + UpdateBackgroundPainter(); SetNestedBorderIfNecessary(); } @@ -472,6 +471,14 @@ } } +void MessageView::UpdateBackgroundPainter() { + SkColor background_color = GetNativeTheme()->GetSystemColor( + ui::NativeTheme::kColorId_NotificationDefaultBackground); + SetBackground(views::CreateBackgroundFromPainter( + std::make_unique<NotificationBackgroundPainter>( + top_radius_, bottom_radius_, background_color))); +} + void MessageView::UpdateControlButtonsVisibility() { auto* control_buttons_view = GetControlButtonsView(); if (control_buttons_view)
diff --git a/ui/message_center/views/message_view.h b/ui/message_center/views/message_view.h index af921ef..4cd34fce 100644 --- a/ui/message_center/views/message_view.h +++ b/ui/message_center/views/message_view.h
@@ -209,6 +209,9 @@ // Sets the border if |is_nested_| is true. void SetNestedBorderIfNecessary(); + // Updates the background painter using the themed background color and radii. + void UpdateBackgroundPainter(); + std::string notification_id_; views::ScrollView* scroller_ = nullptr;
diff --git a/ui/message_center/views/notification_background_painter.h b/ui/message_center/views/notification_background_painter.h index a31dd1f..33f8de47 100644 --- a/ui/message_center/views/notification_background_painter.h +++ b/ui/message_center/views/notification_background_painter.h
@@ -6,7 +6,6 @@ #define UI_MESSAGE_CENTER_VIEWS_NOTIFICATION_BACKGROUND_PAINTER_H_ #include "ui/message_center/message_center_export.h" -#include "ui/message_center/public/cpp/message_center_constants.h" #include "ui/views/painter.h" namespace message_center { @@ -19,7 +18,7 @@ public: NotificationBackgroundPainter(int top_radius, int bottom_radius, - SkColor color = kNotificationBackgroundColor); + SkColor color); ~NotificationBackgroundPainter() override; // views::Painter
diff --git a/ui/native_theme/common_theme.cc b/ui/native_theme/common_theme.cc index 977cefd..35301a2f 100644 --- a/ui/native_theme/common_theme.cc +++ b/ui/native_theme/common_theme.cc
@@ -70,6 +70,7 @@ case NativeTheme::kColorId_ButtonColor: case NativeTheme::kColorId_DialogBackground: case NativeTheme::kColorId_BubbleBackground: + case NativeTheme::kColorId_NotificationDefaultBackground: return color_utils::AlphaBlend(SK_ColorWHITE, gfx::kGoogleGrey900, 0.04f); case NativeTheme::kColorId_DialogForeground: return gfx::kGoogleGrey500; @@ -246,6 +247,7 @@ case NativeTheme::kColorId_ButtonColor: case NativeTheme::kColorId_DialogBackground: case NativeTheme::kColorId_BubbleBackground: + case NativeTheme::kColorId_NotificationDefaultBackground: return SK_ColorWHITE; case NativeTheme::kColorId_DialogForeground: return gfx::kGoogleGrey700; @@ -422,15 +424,21 @@ return gfx::kGoogleBlue600; // Notification view - // TODO(crbug.com/1065604): Add support for dark mode. - case NativeTheme::kColorId_NotificationDefaultBackground: case NativeTheme::kColorId_NotificationPlaceholderIconColor: return SK_ColorWHITE; case NativeTheme::kColorId_NotificationActionsRowBackground: - case NativeTheme::kColorId_NotificationInlineSettingsBackground: - return SkColorSetRGB(0xee, 0xee, 0xee); - case NativeTheme::kColorId_NotificationLargeImageBackground: - return SkColorSetRGB(0xf5, 0xf5, 0xf5); + case NativeTheme::kColorId_NotificationInlineSettingsBackground: { + const SkColor bg = base_theme->GetSystemColor( + NativeTheme::kColorId_NotificationDefaultBackground, color_scheme); + // The alpha value here (0x14) is chosen to generate 0xEEE from 0xFFF. + return color_utils::BlendTowardMaxContrast(bg, 0x14); + } + case NativeTheme::kColorId_NotificationLargeImageBackground: { + const SkColor bg = base_theme->GetSystemColor( + NativeTheme::kColorId_NotificationDefaultBackground, color_scheme); + // The alpha value here (0x0C) is chosen to generate 0xF5F5F5 from 0xFFF. + return color_utils::BlendTowardMaxContrast(bg, 0x0C); + } case NativeTheme::kColorId_NotificationEmptyPlaceholderIconColor: return SkColorSetA(SK_ColorWHITE, 0x60); case NativeTheme::kColorId_NotificationEmptyPlaceholderTextColor:
diff --git a/ui/native_theme/native_theme_win.cc b/ui/native_theme/native_theme_win.cc index d6fa761f..95095614 100644 --- a/ui/native_theme/native_theme_win.cc +++ b/ui/native_theme/native_theme_win.cc
@@ -611,6 +611,7 @@ case kColorId_TableBackgroundAlternate: case kColorId_TooltipBackground: case kColorId_ProminentButtonDisabledColor: + case kColorId_NotificationDefaultBackground: return system_colors_[SystemThemeColor::kWindow]; // Window Text
diff --git a/ui/ozone/platform/wayland/gpu/wayland_surface_factory_unittest.cc b/ui/ozone/platform/wayland/gpu/wayland_surface_factory_unittest.cc index ad0f3bb..1c5062651 100644 --- a/ui/ozone/platform/wayland/gpu/wayland_surface_factory_unittest.cc +++ b/ui/ozone/platform/wayland/gpu/wayland_surface_factory_unittest.cc
@@ -255,7 +255,7 @@ // Prepare overlay plane. gl_surface->ScheduleOverlayPlane( - INT32_MIN, gfx::OverlayTransform::OVERLAY_TRANSFORM_FLIP_VERTICAL, + 0, gfx::OverlayTransform::OVERLAY_TRANSFORM_FLIP_VERTICAL, gl_image.get(), window_->GetBounds(), {}, false, nullptr); std::vector<scoped_refptr<FakeGLImageNativePixmap>> gl_images; @@ -452,10 +452,8 @@ Sync(); } - auto* root_surface = server_.GetObject<wl::MockSurface>( - window_->root_surface()->GetSurfaceId()); auto* mock_primary_surface = server_.GetObject<wl::MockSurface>( - window_->primary_subsurface()->wayland_surface()->GetSurfaceId()); + window_->root_surface()->GetSurfaceId()); CallbacksHelper cbs_helper; // Submit a frame with only primary plane @@ -490,11 +488,9 @@ // Also, we expect only one buffer to be committed. EXPECT_CALL(*mock_primary_surface, Attach(_, _, _)).Times(1); - EXPECT_CALL(*mock_primary_surface, Frame(_)).Times(0); + EXPECT_CALL(*mock_primary_surface, Frame(_)).Times(1); EXPECT_CALL(*mock_primary_surface, DamageBuffer(_, _, _, _)).Times(1); EXPECT_CALL(*mock_primary_surface, Commit()).Times(1); - EXPECT_CALL(*root_surface, Frame(_)).Times(1); - EXPECT_CALL(*root_surface, Commit()).Times(1); Sync(); @@ -550,15 +546,13 @@ // Expect one buffer to be committed. EXPECT_CALL(*mock_primary_surface, Attach(_, _, _)).Times(1); - EXPECT_CALL(*mock_primary_surface, Frame(_)).Times(0); + EXPECT_CALL(*mock_primary_surface, Frame(_)).Times(1); EXPECT_CALL(*mock_primary_surface, DamageBuffer(_, _, _, _)).Times(1); EXPECT_CALL(*mock_primary_surface, Commit()).Times(1); - EXPECT_CALL(*root_surface, Frame(_)).Times(1); - EXPECT_CALL(*root_surface, Commit()).Times(1); // Send the frame callback so that pending buffer for swap id=1u is processed // and swapped. - root_surface->SendFrameCallback(); + mock_primary_surface->SendFrameCallback(); Sync(); @@ -610,19 +604,15 @@ base::BindOnce(&CallbacksHelper::BufferPresented, base::Unretained(&cbs_helper), swap_id)); } - - // Do not expect parent surface to be committed. + // Expect parent surface to be committed without a buffer. EXPECT_CALL(*mock_primary_surface, Attach(_, _, _)).Times(0); - EXPECT_CALL(*mock_primary_surface, Frame(_)).Times(0); + EXPECT_CALL(*mock_primary_surface, Frame(_)).Times(1); EXPECT_CALL(*mock_primary_surface, DamageBuffer(_, _, _, _)).Times(0); - EXPECT_CALL(*mock_primary_surface, Commit()).Times(0); - // Expect root surface to be committed. - EXPECT_CALL(*root_surface, Frame(_)).Times(1); - EXPECT_CALL(*root_surface, Commit()).Times(1); + EXPECT_CALL(*mock_primary_surface, Commit()).Times(1); // Send the frame callback so that pending buffer for swap id=2u is processed // and swapped. - root_surface->SendFrameCallback(); + mock_primary_surface->SendFrameCallback(); Sync(); @@ -701,10 +691,8 @@ Sync(); } - auto* root_surface = server_.GetObject<wl::MockSurface>( - window_->root_surface()->GetSurfaceId()); auto* mock_primary_surface = server_.GetObject<wl::MockSurface>( - window_->primary_subsurface()->wayland_surface()->GetSurfaceId()); + window_->root_surface()->GetSurfaceId()); CallbacksHelper cbs_helper; // Submit a frame with 1 primary plane and 1 overlay @@ -749,13 +737,11 @@ // Let's sync so that 1) GbmSurfacelessWayland submits the buffer according to // internal queue and fake server processes the request. - // Also, we expect primary buffer to be committed. + // Also, we expect only one buffer to be committed. EXPECT_CALL(*mock_primary_surface, Attach(_, _, _)).Times(1); - EXPECT_CALL(*mock_primary_surface, Frame(_)).Times(0); + EXPECT_CALL(*mock_primary_surface, Frame(_)).Times(1); EXPECT_CALL(*mock_primary_surface, DamageBuffer(_, _, _, _)).Times(1); EXPECT_CALL(*mock_primary_surface, Commit()).Times(1); - EXPECT_CALL(*root_surface, Frame(_)).Times(1); - EXPECT_CALL(*root_surface, Commit()).Times(1); Sync(); @@ -824,25 +810,21 @@ base::Unretained(&cbs_helper), swap_id)); } - // Expect primary buffer to be committed. + // Expect one buffer to be committed. EXPECT_CALL(*mock_primary_surface, Attach(_, _, _)).Times(1); - EXPECT_CALL(*mock_primary_surface, Frame(_)).Times(0); + EXPECT_CALL(*mock_primary_surface, Frame(_)).Times(1); EXPECT_CALL(*mock_primary_surface, DamageBuffer(_, _, _, _)).Times(1); EXPECT_CALL(*mock_primary_surface, Commit()).Times(1); - // Expect overlay buffer to be committed. + // Expect one buffer to be committed. EXPECT_CALL(*mock_overlay_surface, Attach(_, _, _)).Times(1); EXPECT_CALL(*mock_overlay_surface, Frame(_)).Times(0); EXPECT_CALL(*mock_overlay_surface, DamageBuffer(_, _, _, _)).Times(1); EXPECT_CALL(*mock_overlay_surface, Commit()).Times(1); - // Expect root surface to be committed without buffer. - EXPECT_CALL(*root_surface, Frame(_)).Times(1); - EXPECT_CALL(*root_surface, Commit()).Times(1); - // Send the frame callback so that pending buffer for swap id=1u is processed // and swapped. - root_surface->SendFrameCallback(); + mock_primary_surface->SendFrameCallback(); Sync();
diff --git a/ui/ozone/platform/wayland/host/wayland_buffer_manager_host.cc b/ui/ozone/platform/wayland/host/wayland_buffer_manager_host.cc index 954fb5b..5fa747f3 100644 --- a/ui/ozone/platform/wayland/host/wayland_buffer_manager_host.cc +++ b/ui/ozone/platform/wayland/host/wayland_buffer_manager_host.cc
@@ -234,11 +234,9 @@ // If the same buffer has been submitted again right after the client // received OnSubmission for that buffer, just damage the buffer and - // commit the surface again. However, if the buffer is released, it's safe - // to reattach the buffer. + // commit the surface again. if (submitted_buffers_.empty() || - submitted_buffers_.back().buffer_id != buffer->buffer_id || - buffer->released) { + submitted_buffers_.back().buffer_id != buffer->buffer_id) { // Once the BufferRelease is called, the buffer will be released. DCHECK(buffer->released); buffer->released = false; @@ -925,21 +923,11 @@ if (!surface->HasBuffers() && !surface->HasSurface()) surfaces_.erase(window->root_surface()); } - if (!destroyed_count) { - surface = GetSurface(window->primary_subsurface()->wayland_surface()); - if (surface) { - destroyed_count = surface->DestroyBuffer(buffer_id); - if (!surface->HasBuffers() && !surface->HasSurface()) - surfaces_.erase(window->root_surface()); - } - } - if (!destroyed_count) { - const auto& subsurfaces = window->wayland_subsurfaces(); - for (const auto& it : subsurfaces) { - Surface* subsurface = GetSurface((*it).wayland_surface()); - if (subsurface) - destroyed_count += subsurface->DestroyBuffer(buffer_id); - } + const auto& subsurfaces = window->wayland_subsurfaces(); + for (const auto& it : subsurfaces) { + Surface* subsurface = GetSurface((*it).wayland_surface()); + if (subsurface) + destroyed_count += subsurface->DestroyBuffer(buffer_id); } } else { // Case 3)
diff --git a/ui/ozone/platform/wayland/host/wayland_subsurface.cc b/ui/ozone/platform/wayland/host/wayland_subsurface.cc index b2bee41..9b27f617 100644 --- a/ui/ozone/platform/wayland/host/wayland_subsurface.cc +++ b/ui/ozone/platform/wayland/host/wayland_subsurface.cc
@@ -19,11 +19,13 @@ int32_t parent_buffer_scale) { // TODO(fangzhoug): Verify the correctness of using ui_scale here, and in // other ozone wayland files. - // Currently, the subsurface tree is at most 1 depth, gpu already sees buffer - // bounds in the root_surface-local coordinates. So translation is not - // needed for now. + const auto parent_bounds_dip = + gfx::ScaleToRoundedRect(parent_bounds_px, 1.0 / ui_scale); const auto bounds_dip = gfx::ScaleToRoundedRect(bounds_px, 1.0 / ui_scale); - return gfx::ScaleToRoundedRect(bounds_dip, ui_scale / parent_buffer_scale); + auto new_bounds_dip = + wl::TranslateBoundsToParentCoordinates(bounds_dip, parent_bounds_dip); + return gfx::ScaleToRoundedRect(new_bounds_dip, + ui_scale / parent_buffer_scale); } } // namespace
diff --git a/ui/ozone/platform/wayland/host/wayland_surface.cc b/ui/ozone/platform/wayland/host/wayland_surface.cc index f3092c43..3cfccaa 100644 --- a/ui/ozone/platform/wayland/host/wayland_surface.cc +++ b/ui/ozone/platform/wayland/host/wayland_surface.cc
@@ -7,7 +7,6 @@ #include <viewporter-client-protocol.h> #include "ui/gfx/geometry/rect_conversions.h" -#include "ui/gfx/geometry/size.h" #include "ui/gfx/native_widget_types.h" #include "ui/ozone/platform/wayland/common/wayland_util.h" #include "ui/ozone/platform/wayland/host/wayland_connection.h" @@ -97,6 +96,8 @@ if (!display_size_px_.IsEmpty()) { viewport_dst = gfx::ScaleToCeiledSize(display_size_px_, 1.f / buffer_scale_); + wp_viewport_set_destination(viewport(), viewport_dst.width(), + viewport_dst.height()); } if (connection_->compositor_version() >= @@ -158,14 +159,6 @@ buffer_scale_ = new_scale; wl_surface_set_buffer_scale(surface_.get(), buffer_scale_); - - if (!display_size_px_.IsEmpty()) { - gfx::Size viewport_dst = - gfx::ScaleToCeiledSize(display_size_px_, 1.f / buffer_scale_); - wp_viewport_set_destination(viewport(), viewport_dst.width(), - viewport_dst.height()); - } - connection_->ScheduleFlush(); } @@ -207,10 +200,6 @@ wp_viewport_set_destination(viewport(), -1, -1); } display_size_px_ = dest_size_px; - gfx::Size viewport_dst = - gfx::ScaleToCeiledSize(display_size_px_, 1.f / buffer_scale_); - wp_viewport_set_destination(viewport(), viewport_dst.width(), - viewport_dst.height()); } wl::Object<wl_subsurface> WaylandSurface::CreateSubsurface(
diff --git a/ui/ozone/platform/wayland/host/wayland_surface.h b/ui/ozone/platform/wayland/host/wayland_surface.h index c026bc22..7747c6e 100644 --- a/ui/ozone/platform/wayland/host/wayland_surface.h +++ b/ui/ozone/platform/wayland/host/wayland_surface.h
@@ -74,14 +74,10 @@ // See: // https://cgit.freedesktop.org/wayland/wayland-protocols/tree/stable/viewporter/viewporter.xml // If |src_rect| is empty, the source rectangle is unset. - // Note this method does not send corresponding wayland requests until - // attaching the next buffer. void SetViewportSource(const gfx::RectF& src_rect); // Set the destination size of the associated wl_surface according to // |dest_size_px|, which should be in physical pixels. - // Note this method sends corresponding wayland requests immediately because - // it does not need a new buffer attach to take effect. void SetViewportDestination(const gfx::Size& dest_size_px); // Creates a wl_subsurface relating this surface and a parent surface,
diff --git a/ui/ozone/platform/wayland/host/wayland_window.cc b/ui/ozone/platform/wayland/host/wayland_window.cc index ec28f73..567ff7f 100644 --- a/ui/ozone/platform/wayland/host/wayland_window.cc +++ b/ui/ozone/platform/wayland/host/wayland_window.cc
@@ -47,8 +47,6 @@ PlatformEventSource::GetInstance()->RemovePlatformEventDispatcher(this); - connection_->wayland_window_manager()->RemoveSubsurface( - GetWidget(), primary_subsurface_.get()); for (const auto& widget_subsurface : wayland_subsurfaces()) { connection_->wayland_window_manager()->RemoveSubsurface( GetWidget(), widget_subsurface.get()); @@ -353,12 +351,6 @@ if (!OnInitialize(std::move(properties))) return false; - primary_subsurface_ = std::make_unique<WaylandSubsurface>(connection_, this); - if (!primary_subsurface_->surface()) - return false; - connection_->wayland_window_manager()->AddSubsurface( - GetWidget(), primary_subsurface_.get()); - connection_->ScheduleFlush(); PlatformEventSource::GetInstance()->AddPlatformEventDispatcher(this); @@ -555,10 +547,6 @@ size_t above = (overlays.end() - split) - num_primary_planes; size_t below = split - overlays.begin(); - - if (overlays.front()->z_order == INT32_MIN) - --below; - // Re-arrange the list of subsurfaces to fit the |overlays|. Request extra // subsurfaces if needed. if (!ArrangeSubsurfaceStack(above, below)) @@ -571,14 +559,12 @@ auto overlay_iter = split - 1; for (auto iter = subsurface_stack_below_.begin(); iter != subsurface_stack_below_.end(); ++iter, --overlay_iter) { - if (overlays.front()->z_order == INT32_MIN - ? overlay_iter >= ++overlays.begin() - : overlay_iter >= overlays.begin()) { + if (overlay_iter >= overlays.begin()) { WaylandSurface* reference_above = nullptr; if (overlay_iter == split - 1) { // It's possible that |overlays| does not contain primary plane, we // still want to place relative to the surface with z_order=0. - reference_above = primary_subsurface_->wayland_surface(); + reference_above = root_surface(); } else { reference_above = (*std::next(iter))->wayland_surface(); } @@ -607,7 +593,7 @@ if (overlay_iter == split + num_primary_planes) { // It's possible that |overlays| does not contain primary plane, we // still want to place relative to the surface with z_order=0. - reference_below = primary_subsurface_->wayland_surface(); + reference_below = root_surface(); } else { reference_below = (*std::prev(iter))->wayland_surface(); } @@ -627,22 +613,11 @@ } if (num_primary_planes) { - primary_subsurface_->ConfigureAndShowSurface( - (*split)->transform, (*split)->crop_rect, (*split)->bounds_rect, - (*split)->enable_blend, nullptr, nullptr); connection_->buffer_manager_host()->CommitBufferInternal( - primary_subsurface_->wayland_surface(), (*split)->buffer_id, - (*split)->damage_region, /*wait_for_frame_callback=*/false); - } - - root_surface_->SetViewportDestination(bounds_px_.size()); - if (overlays.front()->z_order == INT32_MIN) { - connection_->buffer_manager_host()->CommitBufferInternal( - root_surface(), overlays.front()->buffer_id, - /*damage_region=*/gfx::Rect(0, 0, 1, 1), + root_surface(), (*split)->buffer_id, (*split)->damage_region, /*wait_for_frame_callback=*/true); } else { - // Subsurfaces are set to sync, above surface configs will only take effect + // Subsurfaces are set to sync, above operations will only take effects // when root_surface is committed. connection_->buffer_manager_host()->CommitWithoutBufferInternal( root_surface(), /*wait_for_frame_callback=*/true);
diff --git a/ui/ozone/platform/wayland/host/wayland_window.h b/ui/ozone/platform/wayland/host/wayland_window.h index 69ac955..cd9f1e9f 100644 --- a/ui/ozone/platform/wayland/host/wayland_window.h +++ b/ui/ozone/platform/wayland/host/wayland_window.h
@@ -59,9 +59,6 @@ void UpdateBufferScale(bool update_bounds); WaylandSurface* root_surface() const { return root_surface_.get(); } - WaylandSubsurface* primary_subsurface() const { - return primary_subsurface_.get(); - } const WidgetSubsurfaceSet& wayland_subsurfaces() const { return wayland_subsurfaces_; } @@ -230,18 +227,13 @@ WaylandWindow* parent_window_ = nullptr; WaylandWindow* child_window_ = nullptr; - // |root_surface_| is a surface for the opaque background. Its z-order is - // INT32_MIN. std::unique_ptr<WaylandSurface> root_surface_; - // |primary_subsurface| is the primary that shows the widget content. - std::unique_ptr<WaylandSubsurface> primary_subsurface_; - // Subsurfaces excluding the primary_subsurface WidgetSubsurfaceSet wayland_subsurfaces_; // The stack of sub-surfaces to take effect when Commit() is called. // |subsurface_stack_above_| refers to subsurfaces that are stacked above the - // primary. - // Subsurface at the front of the list is the closest to the primary. + // parent. + // Subsurface at the front of the list is the closest to the parent. std::list<WaylandSubsurface*> subsurface_stack_above_; std::list<WaylandSubsurface*> subsurface_stack_below_;
diff --git a/ui/ozone/platform/wayland/ozone_platform_wayland.cc b/ui/ozone/platform/wayland/ozone_platform_wayland.cc index 44c0299..e4968f1 100644 --- a/ui/ozone/platform/wayland/ozone_platform_wayland.cc +++ b/ui/ozone/platform/wayland/ozone_platform_wayland.cc
@@ -235,12 +235,6 @@ properties->ignore_screen_bounds_for_menus = true; properties->app_modal_dialogs_use_event_blocker = true; - // Primary planes can be transluscent due to underlay strategy. As a - // result Wayland server draws contents occluded by an accelerated widget. - // To prevent this, an opaque background image is stacked below the - // accelerated widget to occlude contents below. - properties->needs_background_image = true; - initialised = true; }
diff --git a/ui/ozone/public/ozone_platform.h b/ui/ozone/public/ozone_platform.h index fd59031..764945e 100644 --- a/ui/ozone/public/ozone_platform.h +++ b/ui/ozone/public/ozone_platform.h
@@ -104,10 +104,6 @@ // calculating bounds of menu windows. bool ignore_screen_bounds_for_menus = false; - // Wayland only: determines whether BufferQueue needs a background image to - // be stacked below an AcceleratedWidget to make a widget opaque. - bool needs_background_image = false; - // If true, the platform shows and updates the drag image. bool platform_shows_drag_image = true;
diff --git a/ui/webui/resources/cr_elements/cr_search_field/cr_search_field.html b/ui/webui/resources/cr_elements/cr_search_field/cr_search_field.html index 11763c5..373e581 100644 --- a/ui/webui/resources/cr_elements/cr_search_field/cr_search_field.html +++ b/ui/webui/resources/cr_elements/cr_search_field/cr_search_field.html
@@ -14,31 +14,39 @@ :host { display: flex; user-select: none; + --cr-search-field-input-border-bottom: 1px solid var(--cr-secondary-text-color); } #searchIcon { align-self: center; + display: var(--cr-search-field-search-icon-display, inherit); height: 16px; padding: 4px; vertical-align: middle; width: 16px; } + #searchIconInline { + --iron-icon-fill-color: var(--cr-search-field-search-icon-fill, inherit); + display: var(--cr-search-field-search-icon-inline-display, none); + margin-inline-start: var(--cr-search-field-search-icon-inline-margin-start, 0); + } + #searchInput { --cr-input-background-color: transparent; - --cr-input-border-bottom: 1px solid var(--cr-secondary-text-color); + --cr-input-border-bottom: var(--cr-search-field-input-border-bottom); --cr-input-border-radius: 0; --cr-input-error-display: none; - --cr-input-min-height: 24px; + --cr-input-min-height: var(--cr-search-field-input-min-height, 24px); --cr-input-padding-end: 0; - --cr-input-padding-start: 0; - --cr-input-padding-bottom: 2px; - --cr-input-padding-top: 2px; + --cr-input-padding-start: var(--cr-search-field-input-padding-start, 0); + --cr-input-padding-bottom: var(--cr-search-field-input-padding-bottom, 2px); + --cr-input-padding-top: var(--cr-search-field-input-padding-top, 2px); align-self: stretch; color: var(--cr-primary-text-color); display: block; font-size: 92.3076923%; /* To 12px from 13px. */ - width: var(--cr-search-field-search-input-width, 160px); + width: var(--cr-search-field-input-width, 160px); } :host([has-search-text]) #searchInput { @@ -47,9 +55,10 @@ #clearSearch { /* A 16px icon that fits on the input line. */ - --cr-icon-button-icon-size: 16px; + --cr-icon-button-fill-color: var(--cr-search-field-clear-icon-fill, inherit); + --cr-icon-button-icon-size: var(--cr-search-field-clear-icon-size, 16px); --cr-icon-button-size: 24px; - margin-inline-end: -4px; + margin-inline-end: var(--cr-search-field-clear-icon-margin-end, -4px); margin-inline-start: 4px; position: absolute; right: 0; @@ -64,6 +73,7 @@ <cr-input id="searchInput" on-search="onSearchTermSearch" on-input="onSearchTermInput" aria-label$="[[label]]" type="search" autofocus="[[autofocus]]" placeholder="[[label]]" spellcheck="false"> + <iron-icon id="searchIconInline" slot="inline-prefix" icon="cr:search"></iron-icon> <cr-icon-button id="clearSearch" class="icon-cancel" hidden$="[[!hasSearchText]]" slot="suffix" on-click="onTapClear_" title="[[clearLabel]]">