diff --git a/AUTHORS b/AUTHORS index 402af24..73ad432 100644 --- a/AUTHORS +++ b/AUTHORS
@@ -1172,6 +1172,7 @@ Facebook, Inc. <*@oculus.com> Google Inc. <*@google.com> Hewlett-Packard Development Company, L.P. <*@hp.com> +HyperConnect Inc. <*@hpcnt.com> IBM Inc. <*@*.ibm.com> IBM Inc. <*@ibm.com> Igalia S.L. <*@igalia.com>
diff --git a/DEPS b/DEPS index 02bafcce..288a5671 100644 --- a/DEPS +++ b/DEPS
@@ -195,7 +195,7 @@ # 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': '3d41d509a6a98c9d14a8e70e2b1c362e0e5498f1', + 'skia_revision': '18f6a54fc3cea32dd92a28e8808e4525c5180782', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # 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': '29b1f07f4ab23475ca2ece790cd85affd6d774db', + 'angle_revision': '65dcbe124508f9799348fd4828cbb0f76cf80671', # 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': 'b24900a1aa39721dc53824c01d4169c1d1a4a6e1', + 'swiftshader_revision': '41974f57973ebcdab4cfde6cc60354f6b79a5901', # 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': 'bdb38e31199e618c1cdab83900154872f43e06d6', + 'catapult_revision': '13bf1254829136fb3df678699236ba9eb5d87587', # 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': '88a5d76f5f629f70e73592f7a5f075dfa081bb05', + 'devtools_frontend_revision': '2b117e76f5dc52b8cdcd7518790ce1892f140084', # 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. @@ -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': '498d5ea20aed3b313cfc456d07a8003b95318764', + 'dawn_revision': '9427c97d9c2917d66e79e49ffaa718aac2e7d6ad', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. @@ -334,7 +334,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling wuffs # and whatever else without interference from each other. - 'wuffs_revision': '67503b5bda0274b637671e277ede1e34dd08b1d7', + 'wuffs_revision': 'ba75ce9c5f224a646d92801b0b8ef74f555d490e', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libgifcodec # and whatever else without interference from each other. @@ -545,7 +545,7 @@ }, 'src/ios/third_party/material_components_ios/src': { - 'url': Var('chromium_git') + '/external/github.com/material-components/material-components-ios.git' + '@' + '959e66d5aea00e0aa124b5ac604c29856b6c4905', + 'url': Var('chromium_git') + '/external/github.com/material-components/material-components-ios.git' + '@' + '58ae5f81390b44bd675a0694caaf4e385a6e39a1', 'condition': 'checkout_ios', }, @@ -876,7 +876,7 @@ # Tools used when building Chrome for Chrome OS. This affects both the Simple # Chrome workflow, as well as the chromeos-chrome ebuild. 'src/third_party/chromite': { - 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'd281ff18627341a0ff2c33e19691159d504923f8', + 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '607aa13c8b9aa57ef1fa23cc044b969ae6757db2', 'condition': 'checkout_chromeos', }, @@ -1249,7 +1249,7 @@ }, 'src/third_party/perfetto': - Var('android_git') + '/platform/external/perfetto.git' + '@' + 'e6cf9658552491bf5fdffd98d2e67aacb51661f4', + Var('android_git') + '/platform/external/perfetto.git' + '@' + '625eb197594ebdc42f57db8d36837e5bb99ee41b', 'src/third_party/perl': { 'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3', @@ -1471,7 +1471,7 @@ }, 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + '9e9c8b7155d49c2f38b82fe9c9707181c57073c9', + Var('webrtc_git') + '/src.git' + '@' + 'fc83cdc8198b0609f8986313ef48e565b558e8a7', 'src/third_party/libgifcodec': Var('skia_git') + '/libgifcodec' + '@'+ Var('libgifcodec_revision'), @@ -1543,7 +1543,7 @@ Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'), 'src-internal': { - 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@2f11d877efaaa202ae38a26df97aca0685b57205', + 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@12e6ff85f6e21468f21f154acf81707805441e89', 'condition': 'checkout_src_internal', }, @@ -1551,7 +1551,7 @@ 'packages': [ { 'package': 'chromeos_internal/apps/help_app/app', - 'version': 'mluAO-o7A3mN4nCwt4x0R0SnXS6cuF3Fo--glimMpfkC', + 'version': 'ewmYZK3dZxBbgR06k6qpzdRqlikpeAfsd40KuNLCOSYC', }, ], 'condition': 'checkout_chromeos and checkout_src_internal', @@ -1562,7 +1562,7 @@ 'packages': [ { 'package': 'chromeos_internal/apps/media_app/app', - 'version': 'AsR6b9xlxrEC7Kxx3tzZ2Pn1DDftdw15hFUg0Q8B6ZoC', + 'version': 'rr3VhMXsq7y_PFGfYuF4xO5k6h8d3dTyYtD20gc4jK8C', }, ], 'condition': 'checkout_chromeos and checkout_src_internal',
diff --git a/PRESUBMIT.py b/PRESUBMIT.py index ffb230d..9afa0705 100644 --- a/PRESUBMIT.py +++ b/PRESUBMIT.py
@@ -74,11 +74,15 @@ _TEST_ONLY_WARNING = ( 'You might be calling functions intended only for testing from\n' - 'production code. It is OK to ignore this warning if you know what\n' - 'you are doing, as the heuristics used to detect the situation are\n' - 'not perfect. The commit queue will not block on this warning,\n' - 'however the android-binary-size trybot will block if the method\n' - 'exists in the release apk.') + 'production code. If you are doing this from inside another method\n' + 'named as *ForTesting(), then consider exposing things to have tests\n' + 'make that same call directly.\n' + 'If that is not possible, you may put a comment on the same line with\n' + ' // IN-TEST \n' + 'to tell the PRESUBMIT script that the code is inside a *ForTesting()\n' + 'method and can be ignored. Do not do this inside production code.\n' + 'The android-binary-size trybot will block if the method exists in the\n' + 'release apk.') _INCLUDE_ORDER_WARNING = (
diff --git a/WATCHLISTS b/WATCHLISTS index cd6b005..2b0f4573 100644 --- a/WATCHLISTS +++ b/WATCHLISTS
@@ -257,7 +257,7 @@ 'device/battery/', }, 'bfcache': { - 'filepath': 'content/browser/frame_host/back_forward_cache.*|'\ + 'filepath': 'content/browser/renderer_host/back_forward_cache.*|'\ 'content/browser/back_forward_cache_browsertest.cc|'\ 'content/test/data/back_forward_cache/|'\ 'content/public/browser/back_forward_cache.*|'\ @@ -1326,7 +1326,7 @@ 'filepath': '^native_client_sdk/', }, 'navigation': { - 'filepath': 'content/browser/frame_host|'\ + 'filepath': 'content/browser/renderer_host|'\ 'content/browser/renderer_host/render_process_host.*|'\ 'content/browser/renderer_host/render_view_host.*|'\ 'content/browser/web_contents/web_contents_impl.*|'\
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwContentCaptureTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwContentCaptureTest.java index 2bdaaba..ad98a3c4 100644 --- a/android_webview/javatests/src/org/chromium/android_webview/test/AwContentCaptureTest.java +++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwContentCaptureTest.java
@@ -21,6 +21,7 @@ import org.chromium.base.test.util.CallbackHelper; import org.chromium.base.test.util.CommandLineFlags; import org.chromium.base.test.util.Feature; +import org.chromium.base.test.util.FlakyTest; import org.chromium.components.content_capture.ContentCaptureConsumer; import org.chromium.components.content_capture.ContentCaptureController; import org.chromium.components.content_capture.ContentCaptureData; @@ -608,6 +609,7 @@ @Test @SmallTest + @FlakyTest(message = "https://crbug.com/1126950") @Feature({"AndroidWebView"}) public void testMultipleConsumers() throws Throwable { TestThreadUtils.runOnUiThreadBlocking(() -> {
diff --git a/android_webview/tools/run_cts.py b/android_webview/tools/run_cts.py index 41731e5..d78242d 100755 --- a/android_webview/tools/run_cts.py +++ b/android_webview/tools/run_cts.py
@@ -310,8 +310,8 @@ if known_args.devices: # test_runner.py parses --device as nargs instead of append args forwarded_args.extend(['--device'] + known_args.devices) - if known_args.blacklist_file: - forwarded_args.extend(['--blacklist-file', known_args.blacklist_file]) + if known_args.denylist_file: + forwarded_args.extend(['--denylist-file', known_args.denylist_file]) if known_args.verbose: forwarded_args.extend(['-' + 'v' * known_args.verbose]) @@ -332,7 +332,7 @@ emulator_instance.Start(writable_system=True) device_utils.DeviceUtils(emulator_instance.serial).WaitUntilFullyBooted() - devices = script_common.GetDevices(args.devices, args.blacklist_file) + devices = script_common.GetDevices(args.devices, args.denylist_file) device = devices[0] if len(devices) > 1: logging.warning('Detection of arch and cts-release will use 1st of %d '
diff --git a/android_webview/tools/run_simpleperf.py b/android_webview/tools/run_simpleperf.py index 8c892bb..af7bea0 100755 --- a/android_webview/tools/run_simpleperf.py +++ b/android_webview/tools/run_simpleperf.py
@@ -321,7 +321,7 @@ logging_common.InitializeLogging(args) devil_chromium.Initialize(adb_path=args.adb_path) - devices = script_common.GetDevices(args.devices, args.blacklist_file) + devices = script_common.GetDevices(args.devices, args.denylist_file) device = devices[0] if len(devices) > 1:
diff --git a/ash/app_list/views/assistant/assistant_privacy_info_view.h b/ash/app_list/views/assistant/assistant_privacy_info_view.h index 68bca5a..514dcbf 100644 --- a/ash/app_list/views/assistant/assistant_privacy_info_view.h +++ b/ash/app_list/views/assistant/assistant_privacy_info_view.h
@@ -7,7 +7,6 @@ #include "ash/app_list/views/privacy_info_view.h" #include "ui/views/controls/button/button.h" -#include "ui/views/controls/styled_label_listener.h" namespace ash {
diff --git a/ash/app_list/views/search_result_view.cc b/ash/app_list/views/search_result_view.cc index 42c02c26..21828bc 100644 --- a/ash/app_list/views/search_result_view.cc +++ b/ash/app_list/views/search_result_view.cc
@@ -81,7 +81,7 @@ badge_icon_->set_can_process_events_within_subtree(false); set_context_menu_controller(this); - set_notify_enter_exit_on_child(true); + SetNotifyEnterExitOnChild(true); } SearchResultView::~SearchResultView() = default;
diff --git a/ash/app_list/views/suggested_content_info_view.h b/ash/app_list/views/suggested_content_info_view.h index 4b5e80e..045ab07 100644 --- a/ash/app_list/views/suggested_content_info_view.h +++ b/ash/app_list/views/suggested_content_info_view.h
@@ -7,7 +7,6 @@ #include "ash/app_list/views/privacy_info_view.h" #include "ui/views/controls/button/button.h" -#include "ui/views/controls/styled_label_listener.h" namespace ash {
diff --git a/ash/login/ui/lock_contents_view.cc b/ash/login/ui/lock_contents_view.cc index 909b05e0..e2e04805 100644 --- a/ash/login/ui/lock_contents_view.cc +++ b/ash/login/ui/lock_contents_view.cc
@@ -1979,7 +1979,7 @@ *bold_start += shortcut_offset_in_string; } - auto label = std::make_unique<views::StyledLabel>(this); + auto label = std::make_unique<views::StyledLabel>(); label->SetText(error_text); MakeSectionBold(label.get(), error_text, bold_start, bold_length); label->SetAutoColorReadabilityEnabled(false);
diff --git a/ash/login/ui/lock_contents_view.h b/ash/login/ui/lock_contents_view.h index 750e493c..b7c3491 100644 --- a/ash/login/ui/lock_contents_view.h +++ b/ash/login/ui/lock_contents_view.h
@@ -32,7 +32,6 @@ #include "chromeos/dbus/power_manager/power_supply_properties.pb.h" #include "ui/display/display_observer.h" #include "ui/display/screen.h" -#include "ui/views/controls/styled_label_listener.h" #include "ui/views/metadata/metadata_header_macros.h" #include "ui/views/view.h" @@ -42,7 +41,6 @@ namespace views { class BoxLayout; -class StyledLabel; } // namespace views namespace ash { @@ -69,7 +67,6 @@ public LoginDataDispatcher::Observer, public SystemTrayFocusObserver, public display::DisplayObserver, - public views::StyledLabelListener, public KeyboardControllerObserver, public chromeos::PowerManagerClient::Observer { public: @@ -213,11 +210,6 @@ void OnDisplayMetricsChanged(const display::Display& display, uint32_t changed_metrics) override; - // views::StyledLabelListener: - void StyledLabelLinkClicked(views::StyledLabel* label, - const gfx::Range& range, - int event_flags) override {} - // KeyboardControllerObserver: void OnKeyboardVisibilityChanged(bool is_visible) override;
diff --git a/ash/login/ui/lock_screen_media_controls_view.cc b/ash/login/ui/lock_screen_media_controls_view.cc index 18bbd39..12552b9 100644 --- a/ash/login/ui/lock_screen_media_controls_view.cc +++ b/ash/login/ui/lock_screen_media_controls_view.cc
@@ -227,7 +227,7 @@ // Media controls have not been dismissed initially. Shell::Get()->media_controller()->SetMediaControlsDismissed(false); - set_notify_enter_exit_on_child(true); + SetNotifyEnterExitOnChild(true); contents_view_ = AddChildView(std::make_unique<views::View>()); contents_view_->SetLayoutManager(std::make_unique<views::BoxLayout>(
diff --git a/ash/login/ui/login_expanded_public_account_view.cc b/ash/login/ui/login_expanded_public_account_view.cc index 8a191e0f..2f3e73a 100644 --- a/ash/login/ui/login_expanded_public_account_view.cc +++ b/ash/login/ui/login_expanded_public_account_view.cc
@@ -35,6 +35,7 @@ #include "ui/views/controls/styled_label_listener.h" #include "ui/views/layout/box_layout.h" #include "ui/views/layout/fill_layout.h" + namespace ash { namespace {
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 55c2fe6..134f978 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
@@ -254,7 +254,7 @@ DCHECK_EQ(360, message_center::kNotificationWidth); SetFocusBehavior(FocusBehavior::ALWAYS); - set_notify_enter_exit_on_child(true); + SetNotifyEnterExitOnChild(true); item_->IncrementWindowRefCount(); item_->AddObserver(this);
diff --git a/ash/shelf/shelf_tooltip_preview_bubble.cc b/ash/shelf/shelf_tooltip_preview_bubble.cc index ed05d35..c2f70356 100644 --- a/ash/shelf/shelf_tooltip_preview_bubble.cc +++ b/ash/shelf/shelf_tooltip_preview_bubble.cc
@@ -49,7 +49,7 @@ set_margins(gfx::Insets()); // We hide this tooltip on mouse exit, so we want to get enter/exit events // at this level, even for subviews. - set_notify_enter_exit_on_child(true); + SetNotifyEnterExitOnChild(true); SetLayoutManager(std::make_unique<views::BoxLayout>( views::BoxLayout::Orientation::kHorizontal,
diff --git a/ash/strings/ash_strings_mk.xtb b/ash/strings/ash_strings_mk.xtb index add8efaf..4997110 100644 --- a/ash/strings/ash_strings_mk.xtb +++ b/ash/strings/ash_strings_mk.xtb
@@ -603,7 +603,7 @@ <translation id="7654687942625752712">Притиснете ги и задржете ги двете копчиња за јачина на звук пет секунди за да оневозможите говорни повратни информации.</translation> <translation id="7658239707568436148">Откажи</translation> <translation id="7705524343798198388">VPN</translation> -<translation id="7705822912736783206">Извршете проверка со отпечаток</translation> +<translation id="7705822912736783206">Автентицирајте со отпечаток</translation> <translation id="7723389094756330927">{NUM_NOTIFICATIONS,plural, =1{1 известување}one{# известување}other{# известувања}}</translation> <translation id="7724603315864178912">Исечи</translation> <translation id="7749443890790263709">Достигнат е максималниот број работни простори.</translation> @@ -621,7 +621,7 @@ <translation id="7886277072580235377">Сесијата на интернет ќе се исчисти кога ќе се одјавите. <ph name="LEARN_MORE" /></translation> <translation id="788781083998633524">Испрати е-порака</translation> <translation id="7897375687985782769">Ја притиснавте кратенката од тастатура за ротација на екранот. Дали сакате да го ротирате екранот?</translation> -<translation id="7901405293566323524">Телефонски комутатор</translation> +<translation id="7901405293566323524">Phone Hub</translation> <translation id="7904094684485781019">Администраторот за оваа сметка не дозволува повеќекратно пријавување.</translation> <translation id="7933084174919150729">„Помошникот на Google“ е достапен само за примарниот профил.</translation> <translation id="79341161159229895"><ph name="FIRST_PARENT_EMAIL" /> и <ph name="SECOND_PARENT_EMAIL" /> управуваат со сметката</translation>
diff --git a/ash/strings/ash_strings_or.xtb b/ash/strings/ash_strings_or.xtb index a22aaff5..93726be 100644 --- a/ash/strings/ash_strings_or.xtb +++ b/ash/strings/ash_strings_or.xtb
@@ -116,6 +116,7 @@ <translation id="2127372758936585790">କମ୍-ଶକ୍ତି ବିଶିଷ୍ଟ ଚାର୍ଜର୍</translation> <translation id="2135456203358955318">ଡକ୍ଡ ମ୍ୟାଗ୍ନିଫାୟର୍</translation> <translation id="2144487987174258011">Adobe ଫ୍ଲାସ୍ ପ୍ଲେୟାର୍କୁ ଅପ୍ଡେଟ୍ କରିବା ପାଇଁ ରିଷ୍ଟାର୍ଟ କରନ୍ତୁ</translation> +<translation id="2180011262286780504">ସ୍କ୍ରିନ୍ କ୍ୟାପଚର୍ କରିବାର କ୍ଷମତା ଆପଣଙ୍କ ଆଡମିନିଷ୍ଟ୍ରେଟରଙ୍କ ଦ୍ୱାରା ଅକ୍ଷମ କରାଯାଇଛି।</translation> <translation id="2208323208084708176">ଏକୀକୃତ ଡେସ୍କଟପ୍ ମୋଡ୍</translation> <translation id="2220572644011485463">ପିନ୍ କିମ୍ବା ପାସ୍ୱର୍ଡ</translation> <translation id="2222338659135520253">ସାଇନ୍ ଇନ୍ କରିବା ଆବଶ୍ୟକ</translation> @@ -239,6 +240,7 @@ <translation id="3428447136709161042"><ph name="NETWORK_NAME" />ରୁ ବିଚ୍ଛିନ୍ନ କରନ୍ତୁ</translation> <translation id="3430396595145920809">ପଛକୁ ଫେରିବାକୁ ଡାହାଣ ପାର୍ଶ୍ୱରୁ ସ୍ୱାଇପ୍ କରନ୍ତୁ</translation> <translation id="343571671045587506">ରିମାଇଣ୍ଡର୍ ଏଡିଟ୍ କରନ୍ତୁ</translation> +<translation id="3435967511775410570">ଟିପଚିହ୍ନ ଚିହ୍ନଟ କରାଯାଇଛି</translation> <translation id="3445925074670675829">USB-C ଡିଭାଇସ୍</translation> <translation id="3454224730401036106">ଆପଣଙ୍କର ସଂଯୋଗକୁ ଏକ ଅଧିକ ସୁରକ୍ଷିତ ନେଟ୍ୱର୍କକୁ ସ୍ୱିଚ୍ କରିଦିଆଯାଇଛି</translation> <translation id="3465223694362104965">ଆପଣ ଗତଥର ପାଇଁ ସାଇନ୍ ଇନ୍ କରିବା ପରେ ଅନ୍ୟ ଏକ କୀ'ବୋର୍ଡ ଏହି ଡିଭାଇସ୍ରେ ସଂଯୁକ୍ତ ହୋଇଛି। ଆପଣ ଏହି କୀ'ବୋର୍ଡକୁ ବ୍ୟବହାର କରିବା ପୂର୍ବରୁ ଏହା ଭରସାଯୋଗ୍ୟ ବୋଲି ସୁନିଶ୍ଚିତ କରନ୍ତୁ।</translation> @@ -600,6 +602,7 @@ <translation id="7654687942625752712">କୁହାଯାଇଥିବା ମତାମତ ଅକ୍ଷମ କରିବାକୁ ଉଭୟ ଭଲ୍ୟୁମ୍ କୀ ଦବାଇ ରଖନ୍ତୁ।</translation> <translation id="7658239707568436148">ବାତିଲ୍</translation> <translation id="7705524343798198388">VPN</translation> +<translation id="7705822912736783206">ଟିପଚିହ୍ନ ସାହାଯ୍ୟରେ ପ୍ରମାଣିତ କରନ୍ତୁ</translation> <translation id="7723389094756330927">{NUM_NOTIFICATIONS,plural, =1{1ଟି ବିଜ୍ଞପ୍ତି}other{#ଟି ବିଜ୍ଞପ୍ତି}}</translation> <translation id="7724603315864178912">Cut</translation> <translation id="7749443890790263709">ସର୍ବାଧିକ ସଂଖ୍ୟକ ଡେସ୍କରେ ପହଞ୍ଚିଯାଇଛି।</translation> @@ -617,6 +620,7 @@ <translation id="7886277072580235377">ଯେତେବେଳେ ଆପଣ ସାଇନ୍ ଆଉଟ୍ କରିବେ ସେତେବେଳେ ଆପଣଙ୍କ ଇଣ୍ଟର୍ନେଟ୍ ଅବଧି ଖାଲି ହୋଇଯିବ। <ph name="LEARN_MORE" /></translation> <translation id="788781083998633524">ଏକ ଇମେଲ୍ ପଠାନ୍ତୁ</translation> <translation id="7897375687985782769">ଆପଣ ସ୍କ୍ରିନ୍ର ଘୂର୍ଣ୍ଣନ ପାଇଁ କୀବୋର୍ଡ ସର୍ଟକଟ୍ ଦବାଇଛନ୍ତି। ଆପଣ କ'ଣ ସ୍କ୍ରିନ୍କୁ ଘୂରାଇବାକୁ ଚାହୁଁଛନ୍ତି?</translation> +<translation id="7901405293566323524">ଫୋନ୍ ହବ୍</translation> <translation id="7904094684485781019">ଏହି ଆକାଉଣ୍ଟର ବ୍ୟବସ୍ଥାପକ ଏକାଧିକ ସାଇନ୍ ଇନ୍ ପାଇଁ ଅନୁମତି ଦେଇନାହାନ୍ତି।</translation> <translation id="7933084174919150729">Google Assistant କେବଳ ପ୍ରାଥମିକ ପ୍ରୋଫାଇଲ୍ ପାଇଁ ଉପଲବ୍ଧ ଅଟେ।</translation> <translation id="79341161159229895"><ph name="FIRST_PARENT_EMAIL" /> ଏବଂ <ph name="SECOND_PARENT_EMAIL" /> ଦ୍ୱାରା ଆକାଉଣ୍ଟ ପରିଚାଳିତ ହେଉଛି</translation> @@ -627,6 +631,7 @@ <translation id="7982789257301363584">ନେଟୱାର୍କ</translation> <translation id="7984197416080286869">ଅନେକ ଟିପଚିହ୍ନ ପ୍ରଚେଷ୍ଟା</translation> <translation id="7994370417837006925">ଏକାଧିକ ସାଇନ୍-ଇନ୍</translation> +<translation id="7995804128062002838">ସ୍କ୍ରିନ୍ କ୍ୟାପଚର୍ କରିବା ବିଫଳ ହୋଇଛି</translation> <translation id="8000066093800657092">କୌଣସି ନେଟ୍ୱର୍କ ନାହିଁ</translation> <translation id="8004512796067398576">ବୃଦ୍ଧି</translation> <translation id="8029629653277878342">ଅଧିକ ସୁରକ୍ଷା ପାଇଁ PIN କିମ୍ବା ପାସୱାର୍ଡ ଆବଶ୍ୟକ</translation> @@ -714,6 +719,7 @@ <translation id="8843682306134542540">ଘୂର୍ଣ୍ଣନ ଲକ୍ ଟୋଗଲ୍ କରନ୍ତୁ। <ph name="STATE_TEXT" /></translation> <translation id="8850991929411075241">Search+Esc</translation> <translation id="8853703225951107899">ଆପଣଙ୍କ PIN କିମ୍ବା ପାସୱାର୍ଡକୁ ଏବେ ବି ଯାଞ୍ଚ କରାଯାଇପାରିଲା ନାହିଁ। ଧ୍ୟାନ ଦିଅନ୍ତୁ: ଯଦି ଆପଣ ଆପଣଙ୍କ ପାସୱାର୍ଡକୁ ବର୍ତ୍ତମାନ ପରିବର୍ତ୍ତନ କରିଛନ୍ତି, ତେବେ ପୁରୁଣା ପାସୱାର୍ଡ ବ୍ୟବହାର କରନ୍ତୁ। ଆପଣ ସାଇନ୍ ଆଉଟ୍ କରିବା ପରେ ଆପଣଙ୍କ ନୂଆ ପାସୱାର୍ଡ ଲାଗୁ ହେବ।</translation> +<translation id="885387440427703469">ସ୍କ୍ରିନ୍ କ୍ୟାପଚର୍ ଅକ୍ଷମ କରାଯାଇଛି</translation> <translation id="8870509716567206129">ଆପ୍ ସ୍ପ୍ଲିଟ୍-ସ୍କ୍ରୀନକୁ ସମର୍ଥନ କରେନାହିଁ।</translation> <translation id="8874184842967597500">ସଂଯୁକ୍ତ ନାହିଁ</translation> <translation id="8877788021141246043">ଗୋଟିଏ ରିମାଇଣ୍ଡର୍କୁ ସେଟ୍ କରନ୍ତୁ</translation>
diff --git a/ash/system/holding_space/holding_space_item_chip_view.cc b/ash/system/holding_space/holding_space_item_chip_view.cc index 6b9d576e..d109c3b7 100644 --- a/ash/system/holding_space/holding_space_item_chip_view.cc +++ b/ash/system/holding_space/holding_space_item_chip_view.cc
@@ -60,7 +60,7 @@ SetFocusBehavior(FocusBehavior::ALWAYS); SetInkDropMode(InkDropMode::ON_NO_GESTURE_HANDLER); set_ink_drop_visible_opacity(ShelfConfig::Get()->GetInkDropVisibleOpacity()); - set_notify_enter_exit_on_child(true); + SetNotifyEnterExitOnChild(true); // Ink drop layers should be clipped to match the corner radius of this view. views::InstallRoundRectHighlightPathGenerator(this, gfx::Insets(),
diff --git a/ash/system/network/network_state_list_detailed_view.cc b/ash/system/network/network_state_list_detailed_view.cc index 25efb6d..0ba5a8409 100644 --- a/ash/system/network/network_state_list_detailed_view.cc +++ b/ash/system/network/network_state_list_detailed_view.cc
@@ -115,7 +115,7 @@ SetArrow(views::BubbleBorder::NONE); set_shadow(views::BubbleBorder::NO_ASSETS); set_anchor_view_insets(gfx::Insets(0, 0, kBubbleMargin, 0)); - set_notify_enter_exit_on_child(true); + SetNotifyEnterExitOnChild(true); SetLayoutManager(std::make_unique<views::FillLayout>()); AddChildView(content); }
diff --git a/ash/system/tray/actionable_view.cc b/ash/system/tray/actionable_view.cc index 3870df2..a4627c5 100644 --- a/ash/system/tray/actionable_view.cc +++ b/ash/system/tray/actionable_view.cc
@@ -27,7 +27,7 @@ ink_drop_style_(ink_drop_style) { SetFocusBehavior(FocusBehavior::ALWAYS); set_has_ink_drop_action_on_click(false); - set_notify_enter_exit_on_child(true); + SetNotifyEnterExitOnChild(true); // TODO(pbos): Replace the use of FocusPainter with the FocusRing (using the // below HighlightPathGenerator). SetInstallFocusRingOnFocus(false);
diff --git a/ash/system/tray/hover_highlight_view.cc b/ash/system/tray/hover_highlight_view.cc index 72970f8..4690422d 100644 --- a/ash/system/tray/hover_highlight_view.cc +++ b/ash/system/tray/hover_highlight_view.cc
@@ -32,7 +32,7 @@ : ActionableView(TrayPopupInkDropStyle::FILL_BOUNDS), listener_(listener), use_unified_theme_(use_unified_theme) { - set_notify_enter_exit_on_child(true); + SetNotifyEnterExitOnChild(true); SetInkDropMode(InkDropMode::ON); }
diff --git a/ash/system/tray/tray_background_view.cc b/ash/system/tray/tray_background_view.cc index b22d7d2..149d4f66 100644 --- a/ash/system/tray/tray_background_view.cc +++ b/ash/system/tray/tray_background_view.cc
@@ -159,7 +159,7 @@ show_when_collapsed_(true), widget_observer_(new TrayWidgetObserver(this)) { DCHECK(shelf_); - set_notify_enter_exit_on_child(true); + SetNotifyEnterExitOnChild(true); set_ink_drop_base_color(ShelfConfig::Get()->GetInkDropBaseColor()); set_ink_drop_visible_opacity(ShelfConfig::Get()->GetInkDropVisibleOpacity());
diff --git a/ash/system/tray/tray_bubble_view.cc b/ash/system/tray/tray_bubble_view.cc index 37810db..4017715e 100644 --- a/ash/system/tray/tray_bubble_view.cc +++ b/ash/system/tray/tray_bubble_view.cc
@@ -236,7 +236,7 @@ bubble_border_->set_avoid_shadow_overlap(true); set_parent_window(params_.parent_window); SetCanActivate(false); - set_notify_enter_exit_on_child(true); + SetNotifyEnterExitOnChild(true); set_close_on_deactivate(init_params.close_on_deactivate); set_margins(gfx::Insets());
diff --git a/ash/wm/window_cycle_list.cc b/ash/wm/window_cycle_list.cc index a9565ed..222eee14 100644 --- a/ash/wm/window_cycle_list.cc +++ b/ash/wm/window_cycle_list.cc
@@ -122,7 +122,7 @@ public: explicit WindowCycleItemView(aura::Window* window) : WindowMiniView(window) { SetFocusBehavior(FocusBehavior::ALWAYS); - set_notify_enter_exit_on_child(true); + SetNotifyEnterExitOnChild(true); } WindowCycleItemView(const WindowCycleItemView&) = delete; WindowCycleItemView& operator=(const WindowCycleItemView&) = delete;
diff --git a/base/BUILD.gn b/base/BUILD.gn index ce8ed11..7bdb379 100644 --- a/base/BUILD.gn +++ b/base/BUILD.gn
@@ -1304,38 +1304,47 @@ "allocator/allocator_shim_override_cpp_symbols.h", "allocator/allocator_shim_override_libc_symbols.h", ] + if (is_android) { + sources += + [ "allocator/allocator_shim_override_linker_wrapped_symbols.h" ] + all_dependent_configs += [ "//base/allocator:wrap_malloc_symbols" ] + } + if (is_apple) { + sources += [ "allocator/allocator_shim_override_mac_symbols.h" ] + } + if (is_chromeos || is_linux) { + sources += [ "allocator/allocator_shim_override_glibc_weak_symbols.h" ] + } if (is_win) { sources += [ - "allocator/allocator_shim_default_dispatch_to_winheap.cc", "allocator/allocator_shim_override_ucrt_symbols_win.h", "allocator/winheap_stubs_win.cc", "allocator/winheap_stubs_win.h", ] - } else if ((is_linux || is_chromeos) && use_allocator == "tcmalloc") { - sources += [ - "allocator/allocator_shim_default_dispatch_to_tcmalloc.cc", - "allocator/allocator_shim_override_glibc_weak_symbols.h", - ] - deps += [ "//base/allocator:tcmalloc" ] - } else if ((is_linux || is_chromeos) && use_allocator == "none") { - sources += [ "allocator/allocator_shim_default_dispatch_to_glibc.cc" ] - } else if ((is_linux || is_chromeos || is_android) && - use_allocator == "partition") { + } + + if (use_allocator == "partition") { sources += [ "allocator/allocator_shim_default_dispatch_to_partition_alloc.cc" ] - } else if (is_android) { - sources += - [ "allocator/allocator_shim_override_linker_wrapped_symbols.h" ] - all_dependent_configs += [ "//base/allocator:wrap_malloc_symbols" ] - if (use_allocator == "none") { + } else if (use_allocator == "tcmalloc") { + sources += [ "allocator/allocator_shim_default_dispatch_to_tcmalloc.cc" ] + deps += [ "//base/allocator:tcmalloc" ] + } else if (use_allocator == "none") { + if (is_android) { sources += [ "allocator/allocator_shim_default_dispatch_to_linker_wrapped_symbols.cc" ] } - } else if (is_apple) { - sources += [ - "allocator/allocator_shim_default_dispatch_to_mac_zoned_malloc.cc", - "allocator/allocator_shim_default_dispatch_to_mac_zoned_malloc.h", - "allocator/allocator_shim_override_mac_symbols.h", - ] + if (is_apple) { + sources += [ + "allocator/allocator_shim_default_dispatch_to_mac_zoned_malloc.cc", + "allocator/allocator_shim_default_dispatch_to_mac_zoned_malloc.h", + ] + } + if (is_chromeos || is_linux) { + sources += [ "allocator/allocator_shim_default_dispatch_to_glibc.cc" ] + } + if (is_win) { + sources += [ "allocator/allocator_shim_default_dispatch_to_winheap.cc" ] + } } } @@ -1767,6 +1776,7 @@ "allocator/partition_allocator/partition_cookie.h", "allocator/partition_allocator/partition_direct_map_extent.h", "allocator/partition_allocator/partition_freelist_entry.h", + "allocator/partition_allocator/partition_lock.cc", "allocator/partition_allocator/partition_lock.h", "allocator/partition_allocator/partition_oom.cc", "allocator/partition_allocator/partition_oom.h", @@ -1778,8 +1788,6 @@ "allocator/partition_allocator/partition_tag_bitmap.h", "allocator/partition_allocator/random.cc", "allocator/partition_allocator/random.h", - "allocator/partition_allocator/thread_cache.cc", - "allocator/partition_allocator/thread_cache.h", ] if (is_win) { sources += @@ -3201,7 +3209,6 @@ "allocator/partition_allocator/memory_reclaimer_unittest.cc", "allocator/partition_allocator/page_allocator_unittest.cc", "allocator/partition_allocator/partition_alloc_unittest.cc", - "allocator/partition_allocator/thread_cache_unittest.cc", ] }
diff --git a/base/allocator/allocator_interception_mac.h b/base/allocator/allocator_interception_mac.h index 68f1d53..c206c656 100644 --- a/base/allocator/allocator_interception_mac.h +++ b/base/allocator/allocator_interception_mac.h
@@ -15,6 +15,11 @@ struct MallocZoneFunctions; +// This initializes AllocatorDispatch::default_dispatch by saving pointers to +// the functions in the current default malloc zone. This must be called before +// the default malloc zone is changed to have its intended effect. +void InitializeDefaultDispatchToMacAllocator(); + // Saves the function pointers currently used by the default zone. void StoreFunctionsForDefaultZone();
diff --git a/base/allocator/allocator_interception_mac.mm b/base/allocator/allocator_interception_mac.mm index 10f2b97..3d7299c 100644 --- a/base/allocator/allocator_interception_mac.mm +++ b/base/allocator/allocator_interception_mac.mm
@@ -310,6 +310,10 @@ return *result != NULL; } +void InitializeDefaultDispatchToMacAllocator() { + StoreFunctionsForAllZones(); +} + void StoreFunctionsForDefaultZone() { ChromeMallocZone* default_zone = reinterpret_cast<ChromeMallocZone*>( malloc_default_zone());
diff --git a/base/allocator/allocator_shim.cc b/base/allocator/allocator_shim.cc index b1518ec..216337b 100644 --- a/base/allocator/allocator_shim.cc +++ b/base/allocator/allocator_shim.cc
@@ -329,7 +329,6 @@ // On Windows we use plain link-time overriding of the CRT symbols. #include "base/allocator/allocator_shim_override_ucrt_symbols_win.h" #elif defined(OS_APPLE) -#include "base/allocator/allocator_shim_default_dispatch_to_mac_zoned_malloc.h" #include "base/allocator/allocator_shim_override_mac_symbols.h" #else #include "base/allocator/allocator_shim_override_libc_symbols.h"
diff --git a/base/allocator/allocator_shim_default_dispatch_to_mac_zoned_malloc.cc b/base/allocator/allocator_shim_default_dispatch_to_mac_zoned_malloc.cc index 55e17bb..9e3cedc 100644 --- a/base/allocator/allocator_shim_default_dispatch_to_mac_zoned_malloc.cc +++ b/base/allocator/allocator_shim_default_dispatch_to_mac_zoned_malloc.cc
@@ -88,10 +88,6 @@ } // namespace -void InitializeDefaultDispatchToMacAllocator() { - StoreFunctionsForAllZones(); -} - const AllocatorDispatch AllocatorDispatch::default_dispatch = { &MallocImpl, /* alloc_function */ &CallocImpl, /* alloc_zero_initialized_function */
diff --git a/base/allocator/allocator_shim_default_dispatch_to_mac_zoned_malloc.h b/base/allocator/allocator_shim_default_dispatch_to_mac_zoned_malloc.h index 77d533c1..c248203 100644 --- a/base/allocator/allocator_shim_default_dispatch_to_mac_zoned_malloc.h +++ b/base/allocator/allocator_shim_default_dispatch_to_mac_zoned_malloc.h
@@ -8,11 +8,6 @@ namespace base { namespace allocator { -// This initializes AllocatorDispatch::default_dispatch by saving pointers to -// the functions in the current default malloc zone. This must be called before -// the default malloc zone is changed to have its intended effect. -void InitializeDefaultDispatchToMacAllocator(); - } // namespace allocator } // namespace base
diff --git a/base/allocator/allocator_shim_default_dispatch_to_partition_alloc.cc b/base/allocator/allocator_shim_default_dispatch_to_partition_alloc.cc index 92b2a8d4..85fbbca 100644 --- a/base/allocator/allocator_shim_default_dispatch_to_partition_alloc.cc +++ b/base/allocator/allocator_shim_default_dispatch_to_partition_alloc.cc
@@ -5,9 +5,9 @@ #include "base/allocator/allocator_shim.h" #include "base/allocator/allocator_shim_internals.h" #include "base/allocator/partition_allocator/partition_alloc.h" -#include "base/allocator/partition_allocator/partition_alloc_constants.h" #include "base/bits.h" #include "base/no_destructor.h" +#include "build/build_config.h" namespace { @@ -74,8 +74,8 @@ return *root; } - auto* new_root = new (g_allocator_buffer) base::ThreadSafePartitionRoot( - false /* enforce_alignment */, true /* enable_thread_cache */); + auto* new_root = new (g_allocator_buffer) + base::ThreadSafePartitionRoot(false /* enforce_alignment */); g_root_.store(new_root, std::memory_order_release); // Semantically equivalent to base::Lock::Release(). @@ -100,9 +100,8 @@ size_t alignment, size_t size, void* context) { - // Since the general-purpose allocator uses the thread cache, this one cannot. static base::NoDestructor<base::ThreadSafePartitionRoot> aligned_allocator{ - true /* enforce_alignment */, false /* enable_thread_cache */}; + true /* enforce_alignment */}; return aligned_allocator->AlignedAllocFlags(base::PartitionAllocNoHooks, alignment, size); } @@ -151,12 +150,16 @@ extern "C" { +#if !defined(OS_APPLE) + SHIM_ALWAYS_EXPORT void malloc_stats(void) __THROW {} SHIM_ALWAYS_EXPORT int mallopt(int cmd, int value) __THROW { return 0; } +#endif // !defined(OS_APPLE) + #ifdef HAVE_STRUCT_MALLINFO SHIM_ALWAYS_EXPORT struct mallinfo mallinfo(void) __THROW { return {};
diff --git a/base/allocator/allocator_shim_internals.h b/base/allocator/allocator_shim_internals.h index 0196f89..da1e5a6 100644 --- a/base/allocator/allocator_shim_internals.h +++ b/base/allocator/allocator_shim_internals.h
@@ -5,6 +5,8 @@ #ifndef BASE_ALLOCATOR_ALLOCATOR_SHIM_INTERNALS_H_ #define BASE_ALLOCATOR_ALLOCATOR_SHIM_INTERNALS_H_ +#include "build/build_config.h" + #if defined(__GNUC__) #include <sys/cdefs.h> // for __THROW @@ -39,6 +41,11 @@ // impression that they can hook the allocator. #define SHIM_ALWAYS_EXPORT __attribute__((visibility("default"), noinline)) +#elif defined(OS_WIN) // __GNUC__ + +#define __THROW +#define SHIM_ALWAYS_EXPORT __declspec(noinline) + #endif // __GNUC__ #endif // BASE_ALLOCATOR_ALLOCATOR_SHIM_INTERNALS_H_
diff --git a/base/allocator/partition_allocator/partition_alloc.cc b/base/allocator/partition_allocator/partition_alloc.cc index 6fd2622..869efdcc 100644 --- a/base/allocator/partition_allocator/partition_alloc.cc +++ b/base/allocator/partition_allocator/partition_alloc.cc
@@ -203,8 +203,7 @@ } template <bool thread_safe> -void PartitionRoot<thread_safe>::Init(bool enforce_alignment, - bool enable_thread_cache) { +void PartitionRoot<thread_safe>::Init(bool enforce_alignment) { ScopedGuard guard{lock_}; if (initialized) return; @@ -218,10 +217,6 @@ // If alignment needs to be enforced, disallow adding cookies and/or tags at // the beginning of the slot. allow_extras = !enforce_alignment; - with_thread_cache = enable_thread_cache; - - if (with_thread_cache) - internal::ThreadCache::ClaimThreadCacheAndCheck(); // We mark the sentinel bucket/page as free to make sure it is skipped by our // logic to find a new active page. @@ -288,9 +283,6 @@ } template <bool thread_safe> -PartitionRoot<thread_safe>::~PartitionRoot() = default; - -template <bool thread_safe> bool PartitionRoot<thread_safe>::ReallocDirectMappedInPlace( internal::PartitionPage<thread_safe>* page, size_t raw_size) { @@ -629,10 +621,6 @@ PartitionPurgeBucket(bucket); } } - - // Purges only this thread's cache. - if (with_thread_cache && internal::g_thread_cache) - internal::g_thread_cache->Purge(); } template <bool thread_safe> @@ -820,8 +808,7 @@ PartitionAllocatorAlignment alignment) { partition_root_.Init( alignment == - PartitionAllocatorAlignment::kAlignedAlloc /* enforce_alignment */, - false); + PartitionAllocatorAlignment::kAlignedAlloc /* enforce_alignment */); PartitionAllocMemoryReclaimer::Instance()->RegisterPartition( &partition_root_); }
diff --git a/base/allocator/partition_allocator/partition_alloc.h b/base/allocator/partition_allocator/partition_alloc.h index 7b8f0c31..1f335d9 100644 --- a/base/allocator/partition_allocator/partition_alloc.h +++ b/base/allocator/partition_allocator/partition_alloc.h
@@ -53,7 +53,6 @@ #include <limits.h> #include <string.h> -#include <memory> #include <atomic> @@ -69,7 +68,6 @@ #include "base/allocator/partition_allocator/partition_page.h" #include "base/allocator/partition_allocator/partition_ref_count.h" #include "base/allocator/partition_allocator/partition_tag.h" -#include "base/allocator/partition_allocator/thread_cache.h" #include "base/base_export.h" #include "base/bits.h" #include "base/check_op.h" @@ -373,8 +371,6 @@ using DirectMapExtent = internal::PartitionDirectMapExtent<thread_safe>; using ScopedGuard = internal::ScopedGuard<thread_safe>; - bool with_thread_cache = false; - internal::MaybeSpinLock<thread_safe> lock_; // Invariant: total_size_of_committed_pages <= // total_size_of_super_pages + @@ -413,10 +409,10 @@ Bucket buckets[kNumBuckets] = {}; PartitionRoot() = default; - PartitionRoot(bool enable_tag_pointers, bool enable_thread_cache) { - Init(enable_tag_pointers, enable_thread_cache); + explicit PartitionRoot(bool enable_tag_pointers) { + Init(enable_tag_pointers); } - ~PartitionRoot(); + ~PartitionRoot() = default; // Public API // @@ -428,7 +424,7 @@ // // Moving it a layer lower couples PartitionRoot and PartitionBucket, but // preserves the layering of the includes. - void Init(bool enforce_alignment, bool enable_thread_cache); + void Init(bool enforce_alignment); ALWAYS_INLINE static bool IsValidPage(Page* page); ALWAYS_INLINE static PartitionRoot* FromPage(Page* page); @@ -466,7 +462,9 @@ // this is marked |ALWAYS_INLINE|. ALWAYS_INLINE void* AllocFlagsNoHooks(int flags, size_t size); - ALWAYS_INLINE void* Realloc(void* ptr, size_t newize, const char* type_name); + ALWAYS_INLINE void* Realloc(void* ptr, + size_t new_size, + const char* type_name); // Overload that may return nullptr if reallocation isn't possible. In this // case, |ptr| remains valid. ALWAYS_INLINE void* TryRealloc(void* ptr, @@ -497,18 +495,13 @@ // Frees memory, with |ptr| as returned by |RawAlloc()|. ALWAYS_INLINE void RawFree(void* ptr, Page* page); - internal::ThreadCache* thread_cache_for_testing() const { - return with_thread_cache ? internal::g_thread_cache.get() : nullptr; - } - private: // Allocates memory, without any cookies / tags. // // |flags| and |size| are as in AllocFlags(). |allocated_size| and // is_already_zeroed| are output only. |allocated_size| is guaranteed to be // larger or equal to |size|. - ALWAYS_INLINE void* RawAlloc(Bucket* bucket, - int flags, + ALWAYS_INLINE void* RawAlloc(int flags, size_t size, size_t* allocated_size, bool* is_already_zeroed); @@ -530,13 +523,13 @@ #endif } + private: + ALWAYS_INLINE void* AllocFromBucket(Bucket* bucket, int flags, size_t size) + EXCLUSIVE_LOCKS_REQUIRED(lock_); bool ReallocDirectMappedInPlace(internal::PartitionPage<thread_safe>* page, size_t raw_size) EXCLUSIVE_LOCKS_REQUIRED(lock_); void DecommitEmptyPages() EXCLUSIVE_LOCKS_REQUIRED(lock_); - static void RawFreeStatic(void* ptr); - - friend class internal::ThreadCache; }; static_assert(sizeof(PartitionRoot<internal::ThreadSafe>) == @@ -619,15 +612,6 @@ // static template <bool thread_safe> ALWAYS_INLINE void PartitionRoot<thread_safe>::FreeNoHooks(void* ptr) { - // The thread cache is added "in the middle" of the main allocator, that is: - // - After all the cookie/tag management - // - Before the "raw" allocator. - // - // On the deallocation side: - // 1. Check cookies / tags, adjust the pointer - // 2. Deallocation - // a. Return to the thread cache of possible. If it succeeds, return. - // b. Otherwise, call the "raw" allocator <-- Locking if (UNLIKELY(!ptr)) return; @@ -694,19 +678,6 @@ memset(ptr, kFreedByte, page->GetAllocatedSize()); #endif - // TLS access can be expensive, do a cheap local check first. - // - // Also the thread-unsafe variant doesn't have a use for a thread cache, so - // make it statically known to the compiler. - if (thread_safe && root->with_thread_cache && - LIKELY(!page->bucket->is_direct_mapped())) { - PA_DCHECK(page->bucket >= root->buckets); - size_t bucket_index = page->bucket - root->buckets; - internal::ThreadCache* thread_cache = internal::g_thread_cache.get(); - if (thread_cache && thread_cache->MaybePutInCache(ptr, bucket_index)) - return; - } - root->RawFree(ptr, page); } @@ -722,14 +693,6 @@ // static template <bool thread_safe> -void PartitionRoot<thread_safe>::RawFreeStatic(void* ptr) { - Page* page = Page::FromPointerNoAlignmentCheck(ptr); - auto* root = PartitionRoot<thread_safe>::FromPage(page); - root->RawFree(ptr, page); -} - -// static -template <bool thread_safe> ALWAYS_INLINE bool PartitionRoot<thread_safe>::IsValidPage(Page* page) { PartitionRoot* root = FromPage(page); return root->inverted_self == ~reinterpret_cast<uintptr_t>(root); @@ -848,6 +811,7 @@ size_t sub_order_index = size & kOrderSubIndexMask[order]; Bucket* bucket = bucket_lookups[(order << kNumBucketsPerOrderBits) + order_index + !!sub_order_index]; + PA_CHECK(bucket); PA_DCHECK(!bucket->slot_size || bucket->slot_size >= size); PA_DCHECK(!(bucket->slot_size % kSmallestBucket)); return bucket; @@ -870,7 +834,7 @@ return result; #else PA_DCHECK(initialized); - void* ret = nullptr; + void* ret; const bool hooks_enabled = PartitionAllocHooks::AreHooksEnabled(); if (UNLIKELY(hooks_enabled)) { if (PartitionAllocHooks::AllocationOverrideHookIfEnabled(&ret, flags, size, @@ -894,63 +858,13 @@ template <bool thread_safe> ALWAYS_INLINE void* PartitionRoot<thread_safe>::AllocFlagsNoHooks(int flags, size_t size) { - // The thread cache is added "in the middle" of the main allocator, that is: - // - After all the cookie/tag management - // - Before the "raw" allocator. - // - // That is, the general allocation flow is: - // 1. Adjustment of requested size to make room for tags / cookies - // 2. Allocation: - // a. Call to the thread cache, if it succeeds, go to step 3. - // b. Otherwise, call the "raw" allocator <-- Locking - // 3. Handle cookies/tags, zero allocation if required size_t requested_size = size; size = internal::PartitionSizeAdjustAdd(allow_extras, size); PA_CHECK(size >= requested_size); // check for overflows - auto* bucket = SizeToBucket(size); size_t allocated_size; bool is_already_zeroed; - void* ret = nullptr; - - // !thread_safe => !with_thread_cache, but adding the condition allows the - // compiler to statically remove this branch for the thread-unsafe variant. - if (thread_safe && with_thread_cache) { - if (UNLIKELY(!internal::g_thread_cache)) - internal::g_thread_cache = internal::ThreadCache::Create(this); - // bucket->slot_size is 0 for direct-mapped allocations, as their bucket is - // the sentinel one. However, since we are touching *bucket, we may as well - // check it directly, rather than fetching the sentinel one, and comparing - // the addresses. Since the sentinel bucket is *not* part of the the buckets - // array, |bucket_index| is not valid for the sentinel one. - // - // TODO(lizeb): Consider making Bucket::sentinel per-PartitionRoot, at the - // end of the |buckets| array. This would remove this branch. - if (LIKELY(bucket->slot_size)) { - PA_DCHECK(bucket != Bucket::get_sentinel_bucket()); - PA_DCHECK(bucket >= buckets && bucket < (buckets + kNumBuckets)); - size_t bucket_index = bucket - buckets; - ret = internal::g_thread_cache->GetFromCache(bucket_index); - is_already_zeroed = false; - allocated_size = bucket->slot_size; - -#if DCHECK_IS_ON() - // Make sure that the allocated pointer comes from the same place it would - // for a non-thread cache allocation. - if (ret) { - Page* page = Page::FromPointerNoAlignmentCheck(ret); - PA_DCHECK(IsValidPage(page)); - PA_DCHECK(page->bucket == &buckets[bucket_index]); - } -#endif - } else { - PA_DCHECK(bucket == Bucket::get_sentinel_bucket()); - } - } - - if (!ret) - ret = RawAlloc(bucket, flags, size, &allocated_size, &is_already_zeroed); - + void* ret = RawAlloc(flags, size, &allocated_size, &is_already_zeroed); if (UNLIKELY(!ret)) return nullptr; @@ -1011,14 +925,18 @@ template <bool thread_safe> ALWAYS_INLINE void* PartitionRoot<thread_safe>::RawAlloc( - Bucket* bucket, int flags, size_t size, size_t* allocated_size, bool* is_already_zeroed) { - internal::ScopedGuard<thread_safe> guard{lock_}; - return AllocFromBucket(bucket, flags, size, allocated_size, - is_already_zeroed); + auto* bucket = SizeToBucket(size); + PA_DCHECK(bucket); + + { + internal::ScopedGuard<thread_safe> guard{lock_}; + return AllocFromBucket(bucket, flags, size, allocated_size, + is_already_zeroed); + } } template <bool thread_safe>
diff --git a/base/allocator/partition_allocator/partition_alloc_perftest.cc b/base/allocator/partition_allocator/partition_alloc_perftest.cc index 9f73792b..18ce987 100644 --- a/base/allocator/partition_allocator/partition_alloc_perftest.cc +++ b/base/allocator/partition_allocator/partition_alloc_perftest.cc
@@ -2,10 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include <algorithm> #include <atomic> -#include <limits> -#include <memory> #include <vector> #include "base/allocator/partition_allocator/partition_alloc.h" @@ -33,7 +30,7 @@ // Change kTimeLimit to something higher if you need more time to capture a // trace. constexpr base::TimeDelta kTimeLimit = base::TimeDelta::FromSeconds(2); -constexpr int kWarmupRuns = 10000; +constexpr int kWarmupRuns = 5; constexpr int kTimeCheckInterval = 100000; // Size constants are mostly arbitrary, but try to simulate something like CSS @@ -81,10 +78,12 @@ void* Alloc(size_t size) override { return alloc_.AllocFlagsNoHooks(0, size); } - void Free(void* data) override { ThreadSafePartitionRoot::FreeNoHooks(data); } + void Free(void* data) override { + base::ThreadSafePartitionRoot::FreeNoHooks(data); + } private: - ThreadSafePartitionRoot alloc_{false, false}; + base::ThreadSafePartitionRoot alloc_{false}; }; class TestLoopThread : public PlatformThread::Delegate {
diff --git a/base/allocator/partition_allocator/partition_lock.cc b/base/allocator/partition_allocator/partition_lock.cc new file mode 100644 index 0000000..1af9089 --- /dev/null +++ b/base/allocator/partition_allocator/partition_lock.cc
@@ -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. + +#include "base/allocator/partition_allocator/partition_lock.h" + +#if !DCHECK_IS_ON() + +#include "base/threading/platform_thread.h" + +#if defined(OS_WIN) +#include <windows.h> +#elif defined(OS_POSIX) || defined(OS_FUCHSIA) +#include <sched.h> +#endif + +// The YIELD_PROCESSOR macro wraps an architecture specific-instruction that +// informs the processor we're in a busy wait, so it can handle the branch more +// intelligently and e.g. reduce power to our core or give more resources to the +// other hyper-thread on this core. See the following for context: +// https://software.intel.com/en-us/articles/benefitting-power-and-performance-sleep-loops +// +// The YIELD_THREAD macro tells the OS to relinquish our quantum. This is +// basically a worst-case fallback, and if you're hitting it with any frequency +// you really should be using a proper lock (such as |base::Lock|)rather than +// these spinlocks. +#if defined(OS_WIN) + +#define YIELD_PROCESSOR YieldProcessor() +#define YIELD_THREAD SwitchToThread() + +#elif defined(OS_POSIX) || defined(OS_FUCHSIA) + +#if defined(ARCH_CPU_X86_64) || defined(ARCH_CPU_X86) +#define YIELD_PROCESSOR __asm__ __volatile__("pause") +#elif (defined(ARCH_CPU_ARMEL) && __ARM_ARCH >= 6) || defined(ARCH_CPU_ARM64) +#define YIELD_PROCESSOR __asm__ __volatile__("yield") +#elif defined(ARCH_CPU_MIPSEL) +// The MIPS32 docs state that the PAUSE instruction is a no-op on older +// architectures (first added in MIPS32r2). To avoid assembler errors when +// targeting pre-r2, we must encode the instruction manually. +#define YIELD_PROCESSOR __asm__ __volatile__(".word 0x00000140") +#elif defined(ARCH_CPU_MIPS64EL) && __mips_isa_rev >= 2 +// Don't bother doing using .word here since r2 is the lowest supported mips64 +// that Chromium supports. +#define YIELD_PROCESSOR __asm__ __volatile__("pause") +#elif defined(ARCH_CPU_PPC64_FAMILY) +#define YIELD_PROCESSOR __asm__ __volatile__("or 31,31,31") +#elif defined(ARCH_CPU_S390_FAMILY) +// just do nothing +#define YIELD_PROCESSOR ((void)0) +#endif // ARCH + +#ifndef YIELD_PROCESSOR +#warning "Processor yield not supported on this architecture." +#define YIELD_PROCESSOR ((void)0) +#endif + +#define YIELD_THREAD sched_yield() + +#else // Other OS + +#warning "Thread yield not supported on this OS." +#define YIELD_THREAD ((void)0) + +#endif // OS_WIN + +namespace base { +namespace internal { + +void SpinLock::AcquireSlow() { + // The value of |kYieldProcessorTries| is cargo culted from TCMalloc, Windows + // critical section defaults, and various other recommendations. + static const int kYieldProcessorTries = 1000; + // The value of |kYieldThreadTries| is completely made up. + static const int kYieldThreadTries = 10; + int yield_thread_count = 0; + do { + do { + for (int count = 0; count < kYieldProcessorTries; ++count) { + // Let the processor know we're spinning. + YIELD_PROCESSOR; + if (!lock_.load(std::memory_order_relaxed) && + LIKELY(!lock_.exchange(true, std::memory_order_acquire))) + return; + } + + if (yield_thread_count < kYieldThreadTries) { + ++yield_thread_count; + // Give the OS a chance to schedule something on this core. + YIELD_THREAD; + } else { + // At this point, it's likely that the lock is held by a lower priority + // thread that is unavailable to finish its work because of higher + // priority threads spinning here. Sleeping should ensure that they make + // progress. + PlatformThread::Sleep(TimeDelta::FromMilliseconds(1)); + } + } while (lock_.load(std::memory_order_relaxed)); + } while (UNLIKELY(lock_.exchange(true, std::memory_order_acquire))); +} + +} // namespace internal +} // namespace base + +#endif // !DCHECK_IS_ON()
diff --git a/base/allocator/partition_allocator/partition_lock.h b/base/allocator/partition_allocator/partition_lock.h index 60f0456..9167697 100644 --- a/base/allocator/partition_allocator/partition_lock.h +++ b/base/allocator/partition_allocator/partition_lock.h
@@ -6,9 +6,10 @@ #define BASE_ALLOCATOR_PARTITION_ALLOCATOR_PARTITION_LOCK_H_ #include <atomic> +#include <type_traits> +#include "base/allocator/buildflags.h" #include "base/no_destructor.h" -#include "base/partition_alloc_buildflags.h" #include "base/synchronization/lock.h" #include "base/threading/platform_thread.h" #include "build/build_config.h" @@ -38,6 +39,35 @@ MaybeSpinLock<thread_safe>& lock_; }; +#if !DCHECK_IS_ON() +// Spinlock. Do not use, to be removed. crbug.com/1061437. +class BASE_EXPORT SpinLock { + public: + SpinLock() = default; + ~SpinLock() = default; + + ALWAYS_INLINE void Acquire() { + if (LIKELY(!lock_.exchange(true, std::memory_order_acquire))) + return; + AcquireSlow(); + } + + ALWAYS_INLINE void Release() { + lock_.store(false, std::memory_order_release); + } + + // Not supported. + void AssertAcquired() const {} + + private: + // This is called if the initial attempt to acquire the lock fails. It's + // slower, but has a much better scheduling and power consumption behavior. + void AcquireSlow(); + + std::atomic_int lock_{0}; +}; +#endif // !DCHECK_IS_ON() + template <> class LOCKABLE MaybeSpinLock<true> { public: @@ -90,14 +120,22 @@ } private: +#if DCHECK_IS_ON() // NoDestructor to avoid issues with the "static destruction order fiasco". // - // This also means that for DCHECK_IS_ON() builds we leak a lock when a - // partition is destructed. This will in practice only show in some tests, as - // partitions are not destructed in regular use. In addition, on most - // platforms, base::Lock doesn't allocate memory and neither does the OS - // library, and the destructor is a no-op. + // This also means that we leak a lock when a partition is destructed. This + // will in practice only show in some tests, as partitions are not destructed + // in regular use. In addition, on most platforms, base::Lock doesn't allocate + // memory and neither does the OS library, and the destructor is a no-op. base::NoDestructor<base::Lock> lock_; +#else + // base::Lock is slower on the fast path than SpinLock, hence we still use it + // on non-DCHECK() builds. crbug.com/1125999 + base::NoDestructor<SpinLock> lock_; + // base::NoDestructor is here to use the same code elsewhere, we are not + // leaking anything. + static_assert(std::is_trivially_destructible<SpinLock>::value, ""); +#endif #if BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) && DCHECK_IS_ON() std::atomic<PlatformThreadRef> owning_thread_ref_ GUARDED_BY(lock_);
diff --git a/base/allocator/partition_allocator/thread_cache.cc b/base/allocator/partition_allocator/thread_cache.cc deleted file mode 100644 index 0f170b2..0000000 --- a/base/allocator/partition_allocator/thread_cache.cc +++ /dev/null
@@ -1,76 +0,0 @@ -// Copyright 2020 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/allocator/partition_allocator/thread_cache.h" - -#include <sys/types.h> -#include <atomic> -#include <vector> - -#include "base/allocator/partition_allocator/partition_alloc.h" - -namespace base { - -namespace internal { - -// static -std::unique_ptr<ThreadCache> ThreadCache::Create( - PartitionRoot<internal::ThreadSafe>* root) { - PA_CHECK(root); - - // Placement new and RawAlloc() are used, as otherwise when this partition is - // the malloc() implementation, the memory allocated for the new thread cache - // would make this code reentrant. - // - // This also means that deallocation must use RawFreeStatic(), hence the - // operator delete() implementation below. - size_t allocated_size; - bool already_zeroed; - - auto* bucket = root->SizeToBucket(sizeof(ThreadCache)); - void* buffer = - root->RawAlloc(bucket, PartitionAllocZeroFill, sizeof(ThreadCache), - &allocated_size, &already_zeroed); - ThreadCache* tcache = new (buffer) ThreadCache(); - return std::unique_ptr<ThreadCache>(tcache); -} - -void ThreadCache::operator delete(void* ptr) { - PartitionRoot<internal::ThreadSafe>::RawFreeStatic(ptr); -} - -void ThreadCache::Purge() { - for (Bucket& bucket : buckets_) { - size_t count = bucket.count; - - while (bucket.freelist_head) { - auto* entry = bucket.freelist_head; - bucket.freelist_head = EncodedPartitionFreelistEntry::Decode(entry->next); - - PartitionRoot<ThreadSafe>::RawFreeStatic(entry); - count--; - } - CHECK_EQ(0u, count); - bucket.count = 0; - } -} - -// Since |g_thread_cache| is shared, make sure that no more than one -// PartitionRoot can use it. -static std::atomic<bool> g_has_instance; - -// static -void ThreadCache::ClaimThreadCacheAndCheck() { - bool expected = false; - if (!g_has_instance.compare_exchange_strong(expected, true, - std::memory_order_seq_cst, - std::memory_order_seq_cst)) { - PA_CHECK(false) - << "Only one PartitionRoot is allowed to have a thread cache"; - } -} - -} // namespace internal - -} // namespace base
diff --git a/base/allocator/partition_allocator/thread_cache.h b/base/allocator/partition_allocator/thread_cache.h deleted file mode 100644 index 9c238b3d..0000000 --- a/base/allocator/partition_allocator/thread_cache.h +++ /dev/null
@@ -1,165 +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 BASE_ALLOCATOR_PARTITION_ALLOCATOR_THREAD_CACHE_H_ -#define BASE_ALLOCATOR_PARTITION_ALLOCATOR_THREAD_CACHE_H_ - -#include <cstdint> -#include <memory> - -#include "base/allocator/partition_allocator/partition_alloc_forward.h" -#include "base/allocator/partition_allocator/partition_cookie.h" -#include "base/allocator/partition_allocator/partition_freelist_entry.h" -#include "base/base_export.h" -#include "base/gtest_prod_util.h" -#include "base/partition_alloc_buildflags.h" - -namespace base { - -namespace internal { - -class ThreadCache; -#pragma clang diagnostic push -// Silences the global destructor warning, as the name does not imply. -#pragma clang diagnostic ignored "-Wglobal-constructors" -#pragma clang diagnostic ignored "-Wexit-time-destructors" -// This is *not* using base::NoDestructor<> as we do want the destructor to be -// called when a thread is destroyed. -// -// Cannot be a static member of ThreadCache, as it is "dllexport" (BASE_EXPORT), -// and that is not supported by the Windows linker. -static thread_local std::unique_ptr<ThreadCache> g_thread_cache; -#pragma clang diagnostic pop - -// Per-thread cache. *Not* threadsafe, must only be accessed from a single -// thread. -// -// In practice, this is easily enforced as long as only |instance| is -// manipulated, as it is a thread_local member. As such, any -// |ThreadCache::instance->*()| call will necessarily be done from a single -// thread. -class BASE_EXPORT ThreadCache { - public: - // Create a new ThreadCache associated with |root|. - static std::unique_ptr<ThreadCache> Create(PartitionRoot<ThreadSafe>* root); - static std::unique_ptr<ThreadCache> Create( - PartitionRoot<NotThreadSafe>* root) { - IMMEDIATE_CRASH(); - } - - ~ThreadCache(); - void operator delete(void* ptr); - ThreadCache(const ThreadCache&) = delete; - ThreadCache(const ThreadCache&&) = delete; - ThreadCache& operator=(const ThreadCache&) = delete; - - // CHECK()s that the thread cache has not been claimed by another - // PartitionRoot, and mark it as claimed. - static void ClaimThreadCacheAndCheck(); - - // Tries to put a memory block at |address| into the cache. - // The block comes from the bucket at index |bucket_index| from the partition - // this cache is for. - // - // Returns true if the memory was put in the cache, and false otherwise. This - // can happen either because the cache is full or the allocation was too - // large. - ALWAYS_INLINE bool MaybePutInCache(void* address, size_t bucket_index); - - // Tries to allocate memory from the cache. - // Returns nullptr for failure. - // - // Has the same behavior as RawAlloc(), that is: no cookie nor tag handling. - ALWAYS_INLINE void* GetFromCache(size_t bucket_index); - - // Empties the cache. - void Purge(); - - size_t bucket_count_for_testing(size_t index) const { - return buckets_[index].count; - } - - private: - ThreadCache() = default; - - struct Bucket { - size_t count; - PartitionFreelistEntry* freelist_head; - }; - - // TODO(lizeb): Optimize the threshold, and define it as an allocation size - // rather than a bucket index. - static constexpr size_t kBucketCount = 40; - static_assert( - kBucketCount < kNumBuckets, - "Cannot have more cached buckets than what the allocator supports"); - // TODO(lizeb): Tune this constant, and adapt it to the bucket size / - // allocation patterns. - static constexpr size_t kMaxCountPerBucket = 100; - - Bucket buckets_[kBucketCount]; - - FRIEND_TEST_ALL_PREFIXES(ThreadCacheTest, LargeAllocationsAreNotCached); - FRIEND_TEST_ALL_PREFIXES(ThreadCacheTest, MultipleThreadCaches); -}; - -// Some platforms which don't build PartitionAlloc (iOS for instance) still end -// up including partition_alloc.h, and then this file as a side-effect. The -// proper fix is to fix these dependencies, and make partition_alloc.h inclusion -// require USE_PARTITION_ALLOC. -inline ThreadCache::~ThreadCache() { -#if !BUILDFLAG(USE_PARTITION_ALLOC) - IMMEDIATE_CRASH(); -#else - Purge(); -#endif // !BUILDFLAG(USE_PARTITION_ALLOC) -} - -#if !BUILDFLAG(USE_PARTITION_ALLOC) -inline void ThreadCache::operator delete(void* ptr) {} -#endif // !BUILDFLAG(USE_PARTITION_ALLOC) - -ALWAYS_INLINE bool ThreadCache::MaybePutInCache(void* address, - size_t bucket_index) { - if (bucket_index >= kBucketCount) - return false; - - auto& bucket = buckets_[bucket_index]; - - if (bucket.count >= kMaxCountPerBucket) - return false; - - PA_DCHECK(bucket.count != 0 || bucket.freelist_head == nullptr); - - auto* entry = reinterpret_cast<PartitionFreelistEntry*>(address); - entry->next = PartitionFreelistEntry::Encode(bucket.freelist_head); - bucket.freelist_head = entry; - bucket.count++; - return true; -} - -ALWAYS_INLINE void* ThreadCache::GetFromCache(size_t bucket_index) { - // Only handle "small" allocations. - if (bucket_index >= kBucketCount) - return nullptr; - - auto& bucket = buckets_[bucket_index]; - auto* result = bucket.freelist_head; - if (!result) { - PA_DCHECK(bucket.count == 0); - return nullptr; - } - PA_DCHECK(bucket.count != 0); - auto* next = EncodedPartitionFreelistEntry::Decode(result->next); - PA_DCHECK(result != next); - bucket.count--; - PA_DCHECK(bucket.count != 0 || !next); - bucket.freelist_head = next; - return result; -} - -} // namespace internal -} // namespace base - -#endif // BASE_ALLOCATOR_PARTITION_ALLOCATOR_THREAD_CACHE_H_
diff --git a/base/allocator/partition_allocator/thread_cache_unittest.cc b/base/allocator/partition_allocator/thread_cache_unittest.cc deleted file mode 100644 index 411d7ff6..0000000 --- a/base/allocator/partition_allocator/thread_cache_unittest.cc +++ /dev/null
@@ -1,218 +0,0 @@ -// Copyright 2020 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/allocator/partition_allocator/thread_cache.h" - -#include <vector> - -#include "base/allocator/buildflags.h" -#include "base/allocator/partition_allocator/partition_alloc.h" -#include "base/bind.h" -#include "base/callback.h" -#include "base/synchronization/lock.h" -#include "base/test/bind_test_util.h" -#include "base/threading/platform_thread.h" -#include "testing/gtest/include/gtest/gtest.h" - -// Only a single partition can have a thread cache at a time. When -// PartitionAlloc is malloc(), it is already in use. -// -// With *SAN, PartitionAlloc is replaced in partition_alloc.h by ASAN, so we -// cannot test the thread cache. -#if !BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) && \ - !defined(MEMORY_TOOL_REPLACES_ALLOCATOR) - -namespace base { -namespace internal { - -namespace { - -class LambdaThreadDelegate : public PlatformThread::Delegate { - public: - explicit LambdaThreadDelegate(OnceClosure f) : f_(std::move(f)) {} - void ThreadMain() override { std::move(f_).Run(); } - - private: - OnceClosure f_; -}; - -// Need to be a global object without a destructor, because the cache is a -// global object with a destructor (to handle thread destruction), and the -// PartitionRoot has to outlive it. -// -// Forbid extras, since they make finding out which bucket is used harder. -NoDestructor<ThreadSafePartitionRoot> g_root{true, true}; - -size_t BucketIndexForSize(size_t size) { - auto* bucket = g_root->SizeToBucket(size); - return bucket - g_root->buckets; -} - -size_t FillThreadCacheAndReturnIndex(size_t size, size_t count = 1) { - size_t bucket_index = BucketIndexForSize(size); - std::vector<void*> allocated_data; - - for (size_t i = 0; i < count; ++i) { - allocated_data.push_back(g_root->Alloc(size, "")); - } - for (void* ptr : allocated_data) { - g_root->Free(ptr); - } - - return bucket_index; -} - -} // namespace - -class ThreadCacheTest : public ::testing::Test { - protected: - void SetUp() override { - auto* tcache = g_root->thread_cache_for_testing(); - if (tcache) - tcache->Purge(); - } - void TearDown() override {} -}; - -TEST_F(ThreadCacheTest, Simple) { - const size_t kTestSize = 12; - void* ptr = g_root->Alloc(kTestSize, ""); - ASSERT_TRUE(ptr); - - // There is a cache. - auto* tcache = g_root->thread_cache_for_testing(); - EXPECT_TRUE(tcache); - - size_t index = BucketIndexForSize(kTestSize); - EXPECT_EQ(0u, tcache->bucket_count_for_testing(index)); - - g_root->Free(ptr); - // Freeing fills the thread cache. - EXPECT_EQ(1u, tcache->bucket_count_for_testing(index)); - - void* ptr2 = g_root->Alloc(kTestSize, ""); - EXPECT_EQ(ptr, ptr2); - // Allocated from the thread cache. - EXPECT_EQ(0u, tcache->bucket_count_for_testing(index)); -} - -TEST_F(ThreadCacheTest, InexactSizeMatch) { - const size_t kTestSize = 12; - void* ptr = g_root->Alloc(kTestSize, ""); - ASSERT_TRUE(ptr); - - // There is a cache. - auto* tcache = g_root->thread_cache_for_testing(); - EXPECT_TRUE(tcache); - - size_t index = BucketIndexForSize(kTestSize); - EXPECT_EQ(0u, tcache->bucket_count_for_testing(index)); - - g_root->Free(ptr); - // Freeing fills the thread cache. - EXPECT_EQ(1u, tcache->bucket_count_for_testing(index)); - - void* ptr2 = g_root->Alloc(kTestSize + 1, ""); - EXPECT_EQ(ptr, ptr2); - // Allocated from the thread cache. - EXPECT_EQ(0u, tcache->bucket_count_for_testing(index)); -} - -TEST_F(ThreadCacheTest, MultipleObjectsCachedPerBucket) { - size_t bucket_index = FillThreadCacheAndReturnIndex(100, 10); - auto* tcache = g_root->thread_cache_for_testing(); - EXPECT_EQ(10u, tcache->bucket_count_for_testing(bucket_index)); -} - -TEST_F(ThreadCacheTest, ObjectsCachedCountIsLimited) { - size_t bucket_index = FillThreadCacheAndReturnIndex(100, 1000); - auto* tcache = g_root->thread_cache_for_testing(); - EXPECT_LT(tcache->bucket_count_for_testing(bucket_index), 1000u); -} - -TEST_F(ThreadCacheTest, Purge) { - size_t bucket_index = FillThreadCacheAndReturnIndex(100, 10); - auto* tcache = g_root->thread_cache_for_testing(); - EXPECT_EQ(10u, tcache->bucket_count_for_testing(bucket_index)); - tcache->Purge(); - EXPECT_EQ(0u, tcache->bucket_count_for_testing(bucket_index)); -} - -TEST_F(ThreadCacheTest, NoCrossPartitionCache) { - const size_t kTestSize = 12; - ThreadSafePartitionRoot root{true, false}; - - size_t bucket_index = FillThreadCacheAndReturnIndex(kTestSize); - void* ptr = root.Alloc(kTestSize, ""); - ASSERT_TRUE(ptr); - - auto* tcache = g_root->thread_cache_for_testing(); - EXPECT_EQ(1u, tcache->bucket_count_for_testing(bucket_index)); - - ThreadSafePartitionRoot::Free(ptr); - EXPECT_EQ(1u, tcache->bucket_count_for_testing(bucket_index)); -} - -#if ENABLE_THREAD_CACHE_STATISTICS // Required to record hits and misses. -TEST_F(ThreadCacheTest, LargeAllocationsAreNotCached) { - auto* tcache = g_root->thread_cache_for_testing(); - size_t hits_before = tcache ? tcache->hits_ : 0; - - FillThreadCacheAndReturnIndex(100 * 1024); - tcache = g_root->thread_cache_for_testing(); - EXPECT_EQ(hits_before, tcache->hits_); -} -#endif - -TEST_F(ThreadCacheTest, MultipleThreadCaches) { - const size_t kTestSize = 100; - FillThreadCacheAndReturnIndex(kTestSize); - auto* parent_thread_tcache = g_root->thread_cache_for_testing(); - ASSERT_TRUE(parent_thread_tcache); - - LambdaThreadDelegate delegate{BindLambdaForTesting([&]() { - EXPECT_FALSE(g_root->thread_cache_for_testing()); // No allocations yet. - FillThreadCacheAndReturnIndex(kTestSize); - auto* tcache = g_root->thread_cache_for_testing(); - EXPECT_TRUE(tcache); - - EXPECT_NE(parent_thread_tcache, tcache); - })}; - - PlatformThreadHandle thread_handle; - PlatformThread::Create(0, &delegate, &thread_handle); - PlatformThread::Join(thread_handle); -} - -TEST_F(ThreadCacheTest, ThreadCacheReclaimedWhenThreadExits) { - const size_t kTestSize = 100; - // Make sure that there is always at least one object allocated in the test - // bucket, so that the PartitionPage is no reclaimed. - void* tmp = g_root->Alloc(kTestSize, ""); - void* other_thread_ptr; - - LambdaThreadDelegate delegate{BindLambdaForTesting([&]() { - EXPECT_FALSE(g_root->thread_cache_for_testing()); // No allocations yet. - other_thread_ptr = g_root->Alloc(kTestSize, ""); - g_root->Free(other_thread_ptr); - // |other_thread_ptr| is now in the thread cache. - })}; - - PlatformThreadHandle thread_handle; - PlatformThread::Create(0, &delegate, &thread_handle); - PlatformThread::Join(thread_handle); - - void* this_thread_ptr = g_root->Alloc(kTestSize, ""); - // |other_thread_ptr| was returned to the central allocator, and is returned - // |here, as is comes from the freelist. - EXPECT_EQ(this_thread_ptr, other_thread_ptr); - g_root->Free(other_thread_ptr); - g_root->Free(tmp); -} - -} // namespace internal -} // namespace base - -#endif // !BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) && - // !defined(MEMORY_TOOL_REPLACES_ALLOCATOR)
diff --git a/base/strings/string_split.h b/base/strings/string_split.h index 73c15d7..d8b218ef 100644 --- a/base/strings/string_split.h +++ b/base/strings/string_split.h
@@ -45,8 +45,7 @@ // To split on either commas or semicolons, keeping all whitespace: // // std::vector<std::string> tokens = base::SplitString( -// input, ", WARN_UNUSED_RESULT;", base::KEEP_WHITESPACE, -// base::SPLIT_WANT_ALL) WARN_UNUSED_RESULT; +// input, ",;", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL); BASE_EXPORT std::vector<std::string> SplitString(StringPiece input, StringPiece separators, WhitespaceHandling whitespace,
diff --git a/base/threading/sequence_bound.h b/base/threading/sequence_bound.h index 217a1d53..b7299ed 100644 --- a/base/threading/sequence_bound.h +++ b/base/threading/sequence_bound.h
@@ -509,10 +509,10 @@ // Note: this doesn't handle a void return type, which has an explicit // specialization below. template <typename ReturnType> - class AsyncCallWithBoundArgsBuilder + class AsyncCallWithBoundArgsBuilderDefault : public AsyncCallWithBoundArgsBuilderBase<ReturnType> { public: - ~AsyncCallWithBoundArgsBuilder() { + ~AsyncCallWithBoundArgsBuilderDefault() { // Must use Then() since the method's return type is not void. // Should be optimized out if the code is bug-free. CHECK(!this->sequence_bound_); @@ -535,13 +535,13 @@ private: friend SequenceBound; - AsyncCallWithBoundArgsBuilder(AsyncCallWithBoundArgsBuilder&&) = default; - AsyncCallWithBoundArgsBuilder& operator=(AsyncCallWithBoundArgsBuilder&&) = - default; + AsyncCallWithBoundArgsBuilderDefault( + AsyncCallWithBoundArgsBuilderDefault&&) = default; + AsyncCallWithBoundArgsBuilderDefault& operator=( + AsyncCallWithBoundArgsBuilderDefault&&) = default; }; - template <> - class AsyncCallWithBoundArgsBuilder<void> + class AsyncCallWithBoundArgsBuilderVoid : public AsyncCallWithBoundArgsBuilderBase<void> { public: // Note: despite being here, this is actually still protected, since it is @@ -549,7 +549,7 @@ using AsyncCallWithBoundArgsBuilderBase< void>::AsyncCallWithBoundArgsBuilderBase; - ~AsyncCallWithBoundArgsBuilder() { + ~AsyncCallWithBoundArgsBuilderVoid() { if (this->sequence_bound_) { this->sequence_bound_->impl_task_runner_->PostTask( *this->location_, std::move(this->callback_)); @@ -566,11 +566,18 @@ private: friend SequenceBound; - AsyncCallWithBoundArgsBuilder(AsyncCallWithBoundArgsBuilder&&) = default; - AsyncCallWithBoundArgsBuilder& operator=(AsyncCallWithBoundArgsBuilder&&) = + AsyncCallWithBoundArgsBuilderVoid(AsyncCallWithBoundArgsBuilderVoid&&) = default; + AsyncCallWithBoundArgsBuilderVoid& operator=( + AsyncCallWithBoundArgsBuilderVoid&&) = default; }; + template <typename ReturnType> + using AsyncCallWithBoundArgsBuilder = typename std::conditional< + std::is_void<ReturnType>::value, + AsyncCallWithBoundArgsBuilderVoid, + AsyncCallWithBoundArgsBuilderDefault<ReturnType>>::type; + void PostTaskAndThenHelper(const Location& location, OnceCallback<void()> callback, OnceClosure then_callback) {
diff --git a/build/apple/tweak_info_plist.py b/build/apple/tweak_info_plist.py index ff11acbf..7f47e762 100755 --- a/build/apple/tweak_info_plist.py +++ b/build/apple/tweak_info_plist.py
@@ -43,22 +43,8 @@ """Runs a subprocess and waits for termination. Returns (stdout, returncode) of the process. stderr is attached to the parent.""" proc = subprocess.Popen(args, stdout=subprocess.PIPE) - (stdout, stderr) = proc.communicate() - return (stdout, proc.returncode) - - -def _GetOutputNoError(args): - """Similar to _GetOutput() but ignores stderr. If there's an error launching - the child (like file not found), the exception will be caught and (None, 1) - will be returned to mimic quiet failure.""" - try: - proc = subprocess.Popen(args, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE) - except OSError: - return (None, 1) - (stdout, stderr) = proc.communicate() - return (stdout, proc.returncode) + stdout, _ = proc.communicate() + return stdout.decode('UTF-8'), proc.returncode def _RemoveKeys(plist, *keys): @@ -194,9 +180,9 @@ components_len = len(components) combinations = 1 << components_len tag_suffixes = [] - for combination in xrange(0, combinations): + for combination in range(0, combinations): tag_suffix = '' - for component_index in xrange(0, components_len): + for component_index in range(0, components_len): if combination & (1 << component_index): tag_suffix += '-' + components[component_index] tag_suffixes.append(tag_suffix)
diff --git a/build/config/ios/codesign.py b/build/config/ios/codesign.py index 994981e..1c6e3ce 100644 --- a/build/config/ios/codesign.py +++ b/build/config/ios/codesign.py
@@ -2,6 +2,8 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +from __future__ import print_function + import argparse import codecs import datetime @@ -15,6 +17,11 @@ import sys import tempfile +if sys.version_info.major < 3: + basestring_compat = basestring +else: + basestring_compat = str + def GetProvisioningProfilesDir(): """Returns the location of the installed mobile provisioning profiles. @@ -27,6 +34,21 @@ os.environ['HOME'], 'Library', 'MobileDevice', 'Provisioning Profiles') +def ReadPlistFromString(plist_bytes): + """Parse property list from given |plist_bytes|. + + Args: + plist_bytes: contents of property list to load. Must be bytes in python 3. + + Returns: + The contents of property list as a python object. + """ + if sys.version_info.major == 2: + return plistlib.readPlistFromString(plist_bytes) + else: + return plistlib.loads(plist_bytes) + + def LoadPlistFile(plist_path): """Loads property list file at |plist_path|. @@ -36,8 +58,9 @@ Returns: The content of the property list file as a python object. """ - return plistlib.readPlistFromString(subprocess.check_output([ - 'xcrun', 'plutil', '-convert', 'xml1', '-o', '-', plist_path])) + return ReadPlistFromString( + subprocess.check_output( + ['xcrun', 'plutil', '-convert', 'xml1', '-o', '-', plist_path])) class Bundle(object): @@ -74,7 +97,7 @@ error message. The dictionary will be empty if there are no errors. """ errors = {} - for key, expected_value in expected_mappings.iteritems(): + for key, expected_value in expected_mappings.items(): if key in self._data: value = self._data[key] if value != expected_value: @@ -88,9 +111,11 @@ def __init__(self, provisioning_profile_path): """Initializes the ProvisioningProfile with data from profile file.""" self._path = provisioning_profile_path - self._data = plistlib.readPlistFromString(subprocess.check_output([ - 'xcrun', 'security', 'cms', '-D', '-u', 'certUsageAnyCA', - '-i', provisioning_profile_path])) + self._data = ReadPlistFromString( + subprocess.check_output([ + 'xcrun', 'security', 'cms', '-D', '-u', 'certUsageAnyCA', '-i', + provisioning_profile_path + ])) @property def path(self): @@ -155,13 +180,13 @@ self._data = self._ExpandVariables(self._data, substitutions) def _ExpandVariables(self, data, substitutions): - if isinstance(data, str): - for key, substitution in substitutions.iteritems(): + if isinstance(data, basestring_compat): + for key, substitution in substitutions.items(): data = data.replace('$(%s)' % (key,), substitution) return data if isinstance(data, dict): - for key, value in data.iteritems(): + for key, value in data.items(): data[key] = self._ExpandVariables(value, substitutions) return data @@ -172,7 +197,7 @@ return data def LoadDefaults(self, defaults): - for key, value in defaults.iteritems(): + for key, value in defaults.items(): if key not in self._data: self._data[key] = value
diff --git a/build/config/ios/compile_xcassets.py b/build/config/ios/compile_xcassets.py index c1f4680b..5ed43e8b 100644 --- a/build/config/ios/compile_xcassets.py +++ b/build/config/ios/compile_xcassets.py
@@ -32,16 +32,18 @@ # Regular expressions matching spurious messages from actool that should be # ignored (as they are bogus). Generally a bug should be filed with Apple # when adding a pattern here. -SPURIOUS_PATTERNS = map(re.compile, [ - # crbug.com/770634, likely a bug in Xcode 9.1 beta, remove once build - # requires a version of Xcode with a fix. - r'\[\]\[ipad\]\[76x76\]\[\]\[\]\[1x\]\[\]\[\]: notice: \(null\)', +SPURIOUS_PATTERNS = [ + re.compile(v) for v in [ + # crbug.com/770634, likely a bug in Xcode 9.1 beta, remove once build + # requires a version of Xcode with a fix. + r'\[\]\[ipad\]\[76x76\]\[\]\[\]\[1x\]\[\]\[\]: notice: \(null\)', - # crbug.com/770634, likely a bug in Xcode 9.2 beta, remove once build - # requires a version of Xcode with a fix. - r'\[\]\[ipad\]\[76x76\]\[\]\[\]\[1x\]\[\]\[\]: notice: 76x76@1x app icons' - ' only apply to iPad apps targeting releases of iOS prior to 10.0.', -]) + # crbug.com/770634, likely a bug in Xcode 9.2 beta, remove once build + # requires a version of Xcode with a fix. + r'\[\]\[ipad\]\[76x76\]\[\]\[\]\[1x\]\[\]\[\]: notice: 76x76@1x app icons' + ' only apply to iPad apps targeting releases of iOS prior to 10.0.', + ] +] # Map special type of asset catalog to the corresponding command-line # parameter that need to be passed to actool. @@ -193,7 +195,7 @@ stdout, _ = process.communicate() # Filter the output to remove all garbarge and to fix the paths. - stdout = FilterCompilerOutput(stdout, relative_paths) + stdout = FilterCompilerOutput(stdout.decode('UTF-8'), relative_paths) if process.returncode or stdout: sys.stderr.write(stdout)
diff --git a/build/config/ios/strip_arm64e.py b/build/config/ios/strip_arm64e.py index 53a1a573..f21baf423 100644 --- a/build/config/ios/strip_arm64e.py +++ b/build/config/ios/strip_arm64e.py
@@ -18,9 +18,9 @@ if process.returncode: sys.stderr.write('error: command failed with retcode %d: %s\n\n' % (process.returncode, ' '.join(map(repr, command)))) - sys.stderr.write(errs) + sys.stderr.write(errs.decode('UTF-8', errors='ignore')) sys.exit(process.returncode) - return outs + return outs.decode('UTF-8') def check_call(command):
diff --git a/build/config/ios/write_framework_hmap.py b/build/config/ios/write_framework_hmap.py index 08ea9e9e..ac467ee9 100644 --- a/build/config/ios/write_framework_hmap.py +++ b/build/config/ios/write_framework_hmap.py
@@ -50,7 +50,7 @@ count = len(filelist) capacity = NextGreaterPowerOf2(count) strings_offset = 24 + (12 * capacity) - max_value_length = len(max(filelist.items(), key=lambda (k,v):len(v))[1]) + max_value_length = len(max(filelist.values(), key=lambda v: len(v))) out = open(output_name, 'wb') out.write(struct.pack('<LHHLLLL', magic, version, _reserved, strings_offset, @@ -86,14 +86,17 @@ for bucket in buckets: if bucket is not None: (file, path) = bucket - out.write(struct.pack('<%ds' % len(file), file)) - out.write(struct.pack('<s', '\0')) base = os.path.dirname(path) + os.sep - out.write(struct.pack('<%ds' % len(base), base)) - out.write(struct.pack('<s', '\0')) path = os.path.basename(path) + file = file.encode('UTF-8') + base = base.encode('UTF-8') + path = path.encode('UTF-8') + out.write(struct.pack('<%ds' % len(file), file)) + out.write(struct.pack('<s', b'\0')) + out.write(struct.pack('<%ds' % len(base), base)) + out.write(struct.pack('<s', b'\0')) out.write(struct.pack('<%ds' % len(path), path)) - out.write(struct.pack('<s', '\0')) + out.write(struct.pack('<s', b'\0')) if __name__ == '__main__':
diff --git a/build/config/mac/package_framework.py b/build/config/mac/package_framework.py index 7560409..0026f46 100644 --- a/build/config/mac/package_framework.py +++ b/build/config/mac/package_framework.py
@@ -23,7 +23,7 @@ # Foo.framework/Versions/Current symlink to it. if args.version: try: - os.makedirs(os.path.join(args.framework, VERSIONS, args.version), 0755) + os.makedirs(os.path.join(args.framework, VERSIONS, args.version), 0o755) except OSError as e: if e.errno != errno.EEXIST: raise e
diff --git a/build/config/mac/plist_util.py b/build/config/mac/plist_util.py index 56e74e6..d89b4188 100644 --- a/build/config/mac/plist_util.py +++ b/build/config/mac/plist_util.py
@@ -12,6 +12,10 @@ import tempfile import shlex +if sys.version_info.major < 3: + basestring_compat = basestring +else: + basestring_compat = str # Xcode substitutes variables like ${PRODUCT_NAME} or $(PRODUCT_NAME) when # compiling Info.plist. It also supports supports modifiers like :identifier @@ -80,10 +84,10 @@ substitution. """ if isinstance(value, dict): - return {k: Interpolate(v, substitutions) for k, v in value.iteritems()} + return {k: Interpolate(v, substitutions) for k, v in value.items()} if isinstance(value, list): return [Interpolate(v, substitutions) for v in value] - if isinstance(value, str): + if isinstance(value, basestring_compat): return InterpolateString(value, substitutions) return value @@ -93,7 +97,7 @@ fd, name = tempfile.mkstemp() try: subprocess.check_call(['plutil', '-convert', 'xml1', '-o', name, path]) - with os.fdopen(fd, 'r') as f: + with os.fdopen(fd, 'rb') as f: return plistlib.readPlist(f) finally: os.unlink(name) @@ -109,7 +113,7 @@ # it does exist. if os.path.exists(path): os.unlink(path) - with os.fdopen(fd, 'w') as f: + with os.fdopen(fd, 'wb') as f: plistlib.writePlist(data, f) subprocess.check_call(['plutil', '-convert', format, '-o', path, name]) finally: @@ -134,7 +138,7 @@ are concatenated. """ result = plist1.copy() - for key, value in plist2.iteritems(): + for key, value in plist2.items(): if isinstance(value, dict): old_value = result.get(key) if isinstance(old_value, dict):
diff --git a/build/config/mac/sdk_info.py b/build/config/mac/sdk_info.py index 1ad11d3..46f3435 100644 --- a/build/config/mac/sdk_info.py +++ b/build/config/mac/sdk_info.py
@@ -13,6 +13,11 @@ import subprocess import sys +if sys.version_info.major < 3: + basestring_compat = basestring +else: + basestring_compat = str + # src directory ROOT_SRC_DIR = os.path.dirname( os.path.dirname( @@ -61,7 +66,8 @@ settings['xcode_build'] = version_plist['ProductBuildVersion'] return - lines = subprocess.check_output(['xcodebuild', '-version']).splitlines() + lines = subprocess.check_output(['xcodebuild', + '-version']).decode('UTF-8').splitlines() settings['xcode_version'] = FormatVersion(lines[0].split()[-1]) settings['xcode_version_int'] = int(settings['xcode_version'], 10) settings['xcode_build'] = lines[-1].split()[-1] @@ -69,8 +75,8 @@ def FillMachineOSBuild(settings): """Fills OS build number into |settings|.""" - machine_os_build = subprocess.check_output(['sw_vers', '-buildVersion'], - universal_newlines=True).strip() + machine_os_build = subprocess.check_output(['sw_vers', '-buildVersion' + ]).decode('UTF-8').strip() settings['machine_os_build'] = machine_os_build # The reported build number is made up from the kernel major version number, @@ -91,14 +97,17 @@ def FillSDKPathAndVersion(settings, platform, xcode_version): """Fills the SDK path and version for |platform| into |settings|.""" - settings['sdk_path'] = subprocess.check_output([ - 'xcrun', '-sdk', platform, '--show-sdk-path']).strip() - settings['sdk_version'] = subprocess.check_output([ - 'xcrun', '-sdk', platform, '--show-sdk-version']).strip() - settings['sdk_platform_path'] = subprocess.check_output([ - 'xcrun', '-sdk', platform, '--show-sdk-platform-path']).strip() + settings['sdk_path'] = subprocess.check_output( + ['xcrun', '-sdk', platform, '--show-sdk-path']).decode('UTF-8').strip() + settings['sdk_version'] = subprocess.check_output( + ['xcrun', '-sdk', platform, + '--show-sdk-version']).decode('UTF-8').strip() + settings['sdk_platform_path'] = subprocess.check_output( + ['xcrun', '-sdk', platform, + '--show-sdk-platform-path']).decode('UTF-8').strip() settings['sdk_build'] = subprocess.check_output( - ['xcrun', '-sdk', platform, '--show-sdk-build-version']).strip() + ['xcrun', '-sdk', platform, + '--show-sdk-build-version']).decode('UTF-8').strip() def CreateXcodeSymlinkAt(src, dst): @@ -157,6 +166,6 @@ value = settings[key] if args.create_symlink_at and '_path' in key: value = CreateXcodeSymlinkAt(value, args.create_symlink_at) - if isinstance(value, str): + if isinstance(value, basestring_compat): value = '"%s"' % value print('%s=%s' % (key, value))
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1 index b4bfd20..21c0165 100644 --- a/build/fuchsia/linux.sdk.sha1 +++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@ -0.20200910.0.1 +0.20200910.1.1
diff --git a/build/mac/find_sdk.py b/build/mac/find_sdk.py index 58362bf..d86f310 100755 --- a/build/mac/find_sdk.py +++ b/build/mac/find_sdk.py
@@ -65,7 +65,7 @@ print(out, file=sys.stderr) print(err, file=sys.stderr) raise Exception('Error %d running xcode-select' % job.returncode) - dev_dir = out.rstrip() + dev_dir = out.decode('UTF-8').rstrip() sdk_dir = os.path.join( dev_dir, 'Platforms/MacOSX.platform/Developer/SDKs')
diff --git a/build/toolchain/mac/filter_libtool.py b/build/toolchain/mac/filter_libtool.py index cbde5c65..8be2679 100644 --- a/build/toolchain/mac/filter_libtool.py +++ b/build/toolchain/mac/filter_libtool.py
@@ -12,14 +12,16 @@ # This script executes libool and filters out logspam lines like: # '/path/to/libtool: file: foo.o has no symbols' -BLACKLIST_PATTERNS = map(re.compile, [ - r'^.*libtool: (?:for architecture: \S* )?file: .* has no symbols$', - r'^.*libtool: warning for library: .* the table of contents is empty ' +BLACKLIST_PATTERNS = [ + re.compile(v) for v in [ + r'^.*libtool: (?:for architecture: \S* )?file: .* has no symbols$', + r'^.*libtool: warning for library: .* the table of contents is empty ' r'\(no object file members in the library define global symbols\)$', - r'^.*libtool: warning same member name \(\S*\) in output file used for ' + r'^.*libtool: warning same member name \(\S*\) in output file used for ' r'input files: \S* and: \S* \(due to use of basename, truncation, ' r'blank padding or duplicate input files\)$', -]) + ] +] def IsBlacklistedLine(line): @@ -34,7 +36,7 @@ env = os.environ.copy() libtoolout = subprocess.Popen(cmd_list, stderr=subprocess.PIPE, env=env) _, err = libtoolout.communicate() - for line in err.splitlines(): + for line in err.decode('UTF-8').splitlines(): if not IsBlacklistedLine(line): print(line, file=sys.stderr) return libtoolout.returncode
diff --git a/cc/metrics/compositor_frame_reporter.cc b/cc/metrics/compositor_frame_reporter.cc index 872b81a..8aa63e34 100644 --- a/cc/metrics/compositor_frame_reporter.cc +++ b/cc/metrics/compositor_frame_reporter.cc
@@ -214,18 +214,11 @@ base::TimeDelta::FromSeconds(5); constexpr int kEventLatencyHistogramBucketCount = 100; -bool ShouldReportLatencyMetricsForSequenceType( - FrameSequenceTrackerType sequence_type) { - return sequence_type != FrameSequenceTrackerType::kUniversal; -} - std::string GetCompositorLatencyHistogramName( const int report_type_index, FrameSequenceTrackerType frame_sequence_tracker_type, const int stage_type_index) { DCHECK_LE(frame_sequence_tracker_type, FrameSequenceTrackerType::kMaxType); - DCHECK( - ShouldReportLatencyMetricsForSequenceType(frame_sequence_tracker_type)); const char* tracker_type_name = FrameSequenceTracker::GetFrameSequenceTrackerTypeName( frame_sequence_tracker_type); @@ -538,7 +531,6 @@ for (size_t fst_type = 0; fst_type < active_trackers_.size(); ++fst_type) { const auto tracker_type = static_cast<FrameSequenceTrackerType>(fst_type); if (!active_trackers_.test(fst_type) || - tracker_type == FrameSequenceTrackerType::kUniversal || tracker_type == FrameSequenceTrackerType::kCustom || tracker_type == FrameSequenceTrackerType::kMaxType) { continue; @@ -576,7 +568,6 @@ UMA_HISTOGRAM_ENUMERATION("CompositorLatency.Type.ScrollbarScroll", report_type); break; - case FrameSequenceTrackerType::kUniversal: case FrameSequenceTrackerType::kCustom: case FrameSequenceTrackerType::kMaxType: NOTREACHED(); @@ -596,8 +587,6 @@ void CompositorFrameReporter::ReportStageHistogramWithBreakdown( const CompositorFrameReporter::StageData& stage, FrameSequenceTrackerType frame_sequence_tracker_type) const { - if (!ShouldReportLatencyMetricsForSequenceType(frame_sequence_tracker_type)) - return; base::TimeDelta stage_delta = stage.end_time - stage.start_time; ReportCompositorLatencyHistogram(frame_sequence_tracker_type, static_cast<int>(stage.stage_type),
diff --git a/cc/metrics/frame_sequence_metrics.cc b/cc/metrics/frame_sequence_metrics.cc index 56c6157..0a688f5 100644 --- a/cc/metrics/frame_sequence_metrics.cc +++ b/cc/metrics/frame_sequence_metrics.cc
@@ -105,7 +105,6 @@ // SetScrollingThread(). if ((thread_type == ThreadType::kCompositor || thread_type == ThreadType::kMain) && - type != FrameSequenceTrackerType::kUniversal && type != FrameSequenceTrackerType::kCustom) jank_reporter_ = std::make_unique<JankMetrics>(type, thread_type); } @@ -113,17 +112,8 @@ FrameSequenceMetrics::~FrameSequenceMetrics() = default; void FrameSequenceMetrics::ReportLeftoverData() { - if (HasDataLeftForReporting()) { - // Do this before ReportMetrics() which clears the throughput data. - // TODO(xidachen): Find a way to make ThroughputUkmReporter to directly talk - // to LayerTreeHostClient, and submit throughput data. Instead of storing - // the values in ThroughputUkmReporter. - if (type_ == FrameSequenceTrackerType::kUniversal && - HasEnoughDataForReporting()) { - throughput_ukm_reporter_->ComputeUniversalThroughput(this); - } + if (HasDataLeftForReporting()) ReportMetrics(); - } } void FrameSequenceMetrics::SetScrollingThread(ThreadType scrolling_thread) { @@ -161,9 +151,6 @@ case FrameSequenceTrackerType::kWheelScroll: return scrolling_thread_; - case FrameSequenceTrackerType::kUniversal: - return ThreadType::kSlower; - case FrameSequenceTrackerType::kCustom: return ThreadType::kMain; @@ -246,16 +233,14 @@ main_throughput_); // Report for the 'slower thread' for the metrics where it makes sense. - bool should_report_slower_thread = - IsInteractionType(type_) || type_ == FrameSequenceTrackerType::kUniversal; + bool should_report_slower_thread = IsInteractionType(type_); base::Optional<int> aggregated_throughput_percent; if (should_report_slower_thread) { aggregated_throughput_percent = ThroughputData::ReportHistogram( this, ThreadType::kSlower, GetIndexForMetric(FrameSequenceMetrics::ThreadType::kSlower, type_), aggregated_throughput_); - if (aggregated_throughput_percent.has_value() && throughput_ukm_reporter_ && - type_ != FrameSequenceTrackerType::kUniversal) { + if (aggregated_throughput_percent.has_value() && throughput_ukm_reporter_) { throughput_ukm_reporter_->ReportThroughputUkm( aggregated_throughput_percent, impl_throughput_percent, main_throughput_percent, type_); @@ -426,7 +411,6 @@ } if (!is_animation && !IsInteractionType(sequence_type) && - sequence_type != FrameSequenceTrackerType::kUniversal && sequence_type != FrameSequenceTrackerType::kVideo) { return base::nullopt; }
diff --git a/cc/metrics/frame_sequence_metrics.h b/cc/metrics/frame_sequence_metrics.h index 8b0d56b..323dec4 100644 --- a/cc/metrics/frame_sequence_metrics.h +++ b/cc/metrics/frame_sequence_metrics.h
@@ -24,7 +24,6 @@ kPinchZoom = 2, kRAF = 3, kTouchScroll = 4, - kUniversal = 5, kVideo = 6, kWheelScroll = 7, kScrollbarScroll = 8,
diff --git a/cc/metrics/frame_sequence_metrics_unittest.cc b/cc/metrics/frame_sequence_metrics_unittest.cc index e99209a7..6f514d1 100644 --- a/cc/metrics/frame_sequence_metrics_unittest.cc +++ b/cc/metrics/frame_sequence_metrics_unittest.cc
@@ -27,28 +27,6 @@ EXPECT_EQ(first.aggregated_throughput().frames_produced, 0u); } -// Test that ThroughputUkmReporter::ReportThroughputUkm isn't called for the -// kUniversal tracker. -TEST(FrameSequenceMetricsTest, UniversalNotReportUkmAtRenderer) { - auto recorder = std::make_unique<ukm::TestUkmRecorder>(); - auto ukm_manager = std::make_unique<UkmManager>(std::move(recorder)); - ThroughputUkmReporter reporter(ukm_manager.get()); - auto metric = std::make_unique<FrameSequenceMetrics>( - FrameSequenceTrackerType::kUniversal, &reporter); - - metric->impl_throughput().frames_expected = 200u; - metric->impl_throughput().frames_produced = 190u; - metric->aggregated_throughput().frames_expected = 170u; - metric->aggregated_throughput().frames_produced = 150u; - metric->ReportMetrics(); - - // The corresponding |samples_to_next_event_| element is 0 if the - // ReportThroughputUkm isn't called. - EXPECT_EQ(reporter.GetSamplesToNextEventForTesting( - static_cast<int>(FrameSequenceTrackerType::kUniversal)), - 1u); -} - TEST(FrameSequenceMetricsTest, MergeMetrics) { // Create a metric with only a small number of frames. It shouldn't report any // metrics. @@ -139,20 +117,6 @@ "Graphics.Smoothness.PercentDroppedFrames.MainThread.TouchScroll", 1u); // All the metrics have now been reported. No data should be left over. EXPECT_FALSE(first.HasDataLeftForReporting()); - - FrameSequenceMetrics third(FrameSequenceTrackerType::kUniversal, nullptr); - third.impl_throughput().frames_expected = 120; - third.impl_throughput().frames_produced = 80; - third.main_throughput().frames_expected = 120; - third.main_throughput().frames_produced = 80; - EXPECT_TRUE(third.HasEnoughDataForReporting()); - third.ReportMetrics(); - - histograms.ExpectTotalCount( - "Graphics.Smoothness.PercentDroppedFrames.CompositorThread.Universal", - 1u); - histograms.ExpectTotalCount( - "Graphics.Smoothness.PercentDroppedFrames.MainThread.Universal", 1u); } TEST(FrameSequenceMetricsTest, IrrelevantMetricsNotReported) {
diff --git a/cc/metrics/frame_sequence_tracker.cc b/cc/metrics/frame_sequence_tracker.cc index 3d2f484c..56019f9 100644 --- a/cc/metrics/frame_sequence_tracker.cc +++ b/cc/metrics/frame_sequence_tracker.cc
@@ -52,8 +52,6 @@ return "RAF"; case FrameSequenceTrackerType::kTouchScroll: return "TouchScroll"; - case FrameSequenceTrackerType::kUniversal: - return "Universal"; case FrameSequenceTrackerType::kVideo: return "Video"; case FrameSequenceTrackerType::kWheelScroll:
diff --git a/cc/metrics/frame_sequence_tracker_collection.cc b/cc/metrics/frame_sequence_tracker_collection.cc index bd5d684..1519c456 100644 --- a/cc/metrics/frame_sequence_tracker_collection.cc +++ b/cc/metrics/frame_sequence_tracker_collection.cc
@@ -67,7 +67,6 @@ metrics->SetScrollingThread(scrolling_thread); } - if (type != FrameSequenceTrackerType::kUniversal) { if (metrics->GetEffectiveThread() == ThreadType::kCompositor) { if (compositor_frame_reporting_controller_ && compositor_thread_driving_smoothness_ == 0) { @@ -84,7 +83,6 @@ } ++main_thread_driving_smoothness_; } - } return frame_trackers_[key].get(); } @@ -133,7 +131,6 @@ tracker->type()); } - if (type != FrameSequenceTrackerType::kUniversal) { if (tracker->metrics()->GetEffectiveThread() == ThreadType::kCompositor) { DCHECK_GT(compositor_thread_driving_smoothness_, 0u); --compositor_thread_driving_smoothness_; @@ -151,7 +148,6 @@ ThreadType::kMain, false); } } - } frame_trackers_.erase(key); tracker->ScheduleTerminate(); @@ -298,35 +294,6 @@ DestroyTrackers(); } -bool FrameSequenceTrackerCollection::HasThroughputData() const { - return throughput_ukm_reporter_ && - throughput_ukm_reporter_->HasThroughputData(); -} - -int FrameSequenceTrackerCollection::TakeLastAggregatedPercent() { - DCHECK(throughput_ukm_reporter_); - return throughput_ukm_reporter_->TakeLastAggregatedPercent(); -} - -int FrameSequenceTrackerCollection::TakeLastImplPercent() { - DCHECK(throughput_ukm_reporter_); - return throughput_ukm_reporter_->TakeLastImplPercent(); -} - -base::Optional<int> FrameSequenceTrackerCollection::TakeLastMainPercent() { - DCHECK(throughput_ukm_reporter_); - return throughput_ukm_reporter_->TakeLastMainPercent(); -} - -void FrameSequenceTrackerCollection::ComputeUniversalThroughputForTesting() { - DCHECK(throughput_ukm_reporter_); - const auto type = FrameSequenceTrackerType::kUniversal; - auto key = std::make_pair(type, ThreadType::kUnknown); - DCHECK(frame_trackers_.contains(key)); - throughput_ukm_reporter_->ComputeUniversalThroughput( - frame_trackers_[key]->metrics()); -} - void FrameSequenceTrackerCollection::DestroyTrackers() { for (auto& tracker : removal_trackers_) { if (tracker->termination_status() == @@ -351,15 +318,10 @@ accumulated_metrics_.erase(key); } - if (metrics->HasEnoughDataForReporting()) { - // Do this before ReportMetrics() which clears the throughput data. - if (metrics->type() == FrameSequenceTrackerType::kUniversal) - throughput_ukm_reporter_->ComputeUniversalThroughput(metrics.get()); + if (metrics->HasEnoughDataForReporting()) metrics->ReportMetrics(); - } - if (metrics->HasDataLeftForReporting()) { + if (metrics->HasDataLeftForReporting()) accumulated_metrics_[key] = std::move(metrics); - } } }
diff --git a/cc/metrics/frame_sequence_tracker_collection.h b/cc/metrics/frame_sequence_tracker_collection.h index 9bb8566..e54f39f 100644 --- a/cc/metrics/frame_sequence_tracker_collection.h +++ b/cc/metrics/frame_sequence_tracker_collection.h
@@ -112,15 +112,6 @@ void SetUkmManager(UkmManager* manager); - // These methods directly calls corresponding APIs in ThroughputUkmReporter, - // please refer to the ThroughputUkmReporter for details. - bool HasThroughputData() const; - int TakeLastAggregatedPercent(); - int TakeLastImplPercent(); - base::Optional<int> TakeLastMainPercent(); - - void ComputeUniversalThroughputForTesting(); - using NotifyCustomerTrackerResutlsCallback = base::RepeatingCallback<void(CustomTrackerResults)>; void set_custom_tracker_results_added_callback(
diff --git a/cc/metrics/frame_sequence_tracker_unittest.cc b/cc/metrics/frame_sequence_tracker_unittest.cc index d9e343e..0c044df5 100644 --- a/cc/metrics/frame_sequence_tracker_unittest.cc +++ b/cc/metrics/frame_sequence_tracker_unittest.cc
@@ -347,35 +347,13 @@ viz::BeginFrameAck(args_2, true), args_1); } -TEST_F(FrameSequenceTrackerTest, UniversalTrackerCreation) { - // The universal tracker should be explicitly created by the object that - // manages the |collection_| - EXPECT_FALSE(TrackerExists(FrameSequenceTrackerType::kUniversal)); -} - -TEST_F(FrameSequenceTrackerTest, UniversalTrackerRestartableAfterClearAll) { - collection_.StartSequence(FrameSequenceTrackerType::kUniversal); - EXPECT_TRUE(TrackerExists(FrameSequenceTrackerType::kUniversal)); - - collection_.ClearAll(); - EXPECT_FALSE(TrackerExists(FrameSequenceTrackerType::kUniversal)); - - collection_.StartSequence(FrameSequenceTrackerType::kUniversal); - EXPECT_TRUE(TrackerExists(FrameSequenceTrackerType::kUniversal)); -} - TEST_F(FrameSequenceTrackerTest, TestNotifyFramePresented) { collection_.StartSequence(FrameSequenceTrackerType::kCompositorAnimation); collection_.StartSequence(FrameSequenceTrackerType::kMainThreadAnimation); - // The kTouchScroll tracker is created in the test constructor, and the - // kUniversal tracker is created in the FrameSequenceTrackerCollection - // constructor. EXPECT_EQ(NumberOfTrackers(), 3u); - collection_.StartSequence(FrameSequenceTrackerType::kUniversal); - EXPECT_EQ(NumberOfTrackers(), 4u); collection_.StopSequence(FrameSequenceTrackerType::kCompositorAnimation); - EXPECT_EQ(NumberOfTrackers(), 3u); + EXPECT_EQ(NumberOfTrackers(), 2u); EXPECT_TRUE(TrackerExists(FrameSequenceTrackerType::kMainThreadAnimation)); EXPECT_TRUE(TrackerExists(FrameSequenceTrackerType::kTouchScroll)); // StopSequence should have destroyed all trackers because there is no frame @@ -1904,29 +1882,6 @@ EXPECT_EQ(active_encoded, 16); // 1 << 4 } -TEST_F(FrameSequenceTrackerTest, UniversalTrackerSubmitThroughput) { - auto recorder = std::make_unique<ukm::TestUkmRecorder>(); - auto ukm_manager = std::make_unique<UkmManager>(std::move(recorder)); - - collection_.ClearAll(); - collection_.SetUkmManager(ukm_manager.get()); - auto* tracker = - collection_.StartSequence(FrameSequenceTrackerType::kUniversal); - ImplThroughput(tracker).frames_expected = 200u; - ImplThroughput(tracker).frames_produced = 190u; - MainThroughput(tracker).frames_expected = 100u; - MainThroughput(tracker).frames_produced = 50u; - AggregatedThroughput(tracker).frames_expected = 200u; - AggregatedThroughput(tracker).frames_produced = 150u; - - collection_.ComputeUniversalThroughputForTesting(); - DCHECK(collection_.HasThroughputData()); - EXPECT_EQ(collection_.TakeLastAggregatedPercent(), 25); - EXPECT_EQ(collection_.TakeLastImplPercent(), 5); - EXPECT_EQ(collection_.TakeLastMainPercent().value(), 50); - EXPECT_FALSE(collection_.HasThroughputData()); -} - // Test that when an impl frame caused no damage is due to waiting on main, the // computation of aggregated throughput is correct. TEST_F(FrameSequenceTrackerTest, ImplFrameNoDamageWaitingOnMain1) {
diff --git a/cc/metrics/jank_metrics.cc b/cc/metrics/jank_metrics.cc index fba24b1..1164269c 100644 --- a/cc/metrics/jank_metrics.cc +++ b/cc/metrics/jank_metrics.cc
@@ -99,8 +99,7 @@ } void JankMetrics::ReportJankMetrics(int frames_expected) { - if (tracker_type_ == FrameSequenceTrackerType::kUniversal || - tracker_type_ == FrameSequenceTrackerType::kCustom) + if (tracker_type_ == FrameSequenceTrackerType::kCustom) return; int jank_percent = static_cast<int>(100 * jank_count_ / frames_expected);
diff --git a/cc/metrics/jank_metrics_unittest.cc b/cc/metrics/jank_metrics_unittest.cc index 687a835..e96e7dd 100644 --- a/cc/metrics/jank_metrics_unittest.cc +++ b/cc/metrics/jank_metrics_unittest.cc
@@ -228,28 +228,6 @@ histogram_tester.ExpectTotalCount(invalid_metric, 0u); } -// Test if jank reporting is correctly disabled for Universal trackers. -TEST_F(JankMetricsTest, UniversalNotReported) { - base::HistogramTester histogram_tester; - FrameSequenceTrackerType tracker_type = FrameSequenceTrackerType::kUniversal; - FrameSequenceMetrics::ThreadType thread_type = - FrameSequenceMetrics::ThreadType::kCompositor; - JankMetrics jank_reporter{tracker_type, thread_type}; - - // There should be 4 janks, but the jank reporter does not track or report - // them. - auto feedbacks = CreateFeedbackSequence({16, +33, +48, 16, +33, +48}, 16.67); - - AddPresentedFramesToJankReporter(&jank_reporter, feedbacks); - jank_reporter.ReportJankMetrics(100u); - - // Expect no jank reports even though the sequence contains jank - histogram_tester.ExpectTotalCount("Graphics.Smoothness.Jank.Main.Universal", - 0u); - histogram_tester.ExpectTotalCount( - "Graphics.Smoothness.Jank.Compositor.Universal", 0u); -} - // Test if jank reporting is correctly disabled for Custom trackers. TEST_F(JankMetricsTest, CustomNotReported) { base::HistogramTester histogram_tester;
diff --git a/cc/metrics/throughput_ukm_reporter.cc b/cc/metrics/throughput_ukm_reporter.cc index 39f1a33..e384da5 100644 --- a/cc/metrics/throughput_ukm_reporter.cc +++ b/cc/metrics/throughput_ukm_reporter.cc
@@ -16,11 +16,6 @@ ThroughputUkmReporter::ThroughputUkmReporter(UkmManager* ukm_manager) : ukm_manager_(ukm_manager) { DCHECK(ukm_manager_); - // TODO(crbug.com/1040634): Setting it to 1 such that the first sample is - // ignored. TThis is because the universal tracker is active during the page - // load and the first sample is heavily biased by loading as a result. - samples_to_next_event_[static_cast<int>( - FrameSequenceTrackerType::kUniversal)] = 1; } ThroughputUkmReporter::~ThroughputUkmReporter() = default; @@ -36,10 +31,9 @@ if (!ukm_manager_) return; if (samples_to_next_event_[static_cast<int>(type)] == 0) { - // Sample every 100 events. Using the Universal tracker as an example - // which reports UMA every 5s, then the system collects UKM once per - // 100*5 = 500 seconds. This number may need to be tuned to not throttle - // the UKM system. + // Sample every 100 events. If a tracker reports UMA every 5s, then the + // system collects UKM once per 100*5 = 500 seconds. This number may need to + // be tuned to not throttle the UKM system. samples_to_next_event_[static_cast<int>(type)] = kNumberOfSamplesToReport; if (impl_throughput_percent) { ukm_manager_->RecordThroughputUKM( @@ -70,39 +64,6 @@ --samples_for_aggregated_report_; } -void ThroughputUkmReporter::ComputeUniversalThroughput( - FrameSequenceMetrics* metrics) { - last_impl_percent_ = metrics->impl_throughput().DroppedFramePercent(); - last_main_percent_ = metrics->main_throughput().DroppedFramePercent(); - last_aggregated_percent_ = - metrics->aggregated_throughput().DroppedFramePercent(); -} - -bool ThroughputUkmReporter::HasThroughputData() const { - return last_aggregated_percent_.has_value(); -} - -int ThroughputUkmReporter::TakeLastAggregatedPercent() { - int ret_value = last_aggregated_percent_.value(); - DCHECK(ret_value >= 0 && ret_value <= 100); - last_aggregated_percent_ = base::nullopt; - return ret_value; -} - -int ThroughputUkmReporter::TakeLastImplPercent() { - int ret_value = last_impl_percent_.value(); - DCHECK(ret_value >= 0 && ret_value <= 100); - last_impl_percent_ = base::nullopt; - return ret_value; -} - -base::Optional<int> ThroughputUkmReporter::TakeLastMainPercent() { - base::Optional<int> ret_value = last_main_percent_; - DCHECK(!ret_value || (ret_value.value() >= 0 && ret_value.value() <= 100)); - last_main_percent_ = base::nullopt; - return ret_value; -} - uint32_t ThroughputUkmReporter::GetSamplesToNextEventForTesting(int index) { DCHECK_LT(index, static_cast<int>(FrameSequenceTrackerType::kMaxType)); return samples_to_next_event_[index];
diff --git a/cc/metrics/throughput_ukm_reporter.h b/cc/metrics/throughput_ukm_reporter.h index c92fdfe..ba8581a5 100644 --- a/cc/metrics/throughput_ukm_reporter.h +++ b/cc/metrics/throughput_ukm_reporter.h
@@ -36,21 +36,6 @@ void ReportAggregateThroughput(AggregationType aggregation_type, int throughput); - void ComputeUniversalThroughput(FrameSequenceMetrics* metrics); - - // Once the kUniversal tracker reported its throughput to UMA, this returns - // true. In this case, the |last_aggregated_percent_| and |last_impl_percent_| - // must have value. - bool HasThroughputData() const; - // These functions are called only when HasThroughputData is true. They return - // the throughput value of the corresponding thread, and reset them to nullopt - // to indicate the value has been reported. - int TakeLastAggregatedPercent(); - int TakeLastImplPercent(); - // This could be nullopt even if the HasThroughputData() is true, because it - // could happen that all the frames are generated from the compositor thread. - base::Optional<int> TakeLastMainPercent(); - uint32_t GetSamplesToNextEventForTesting(int index); private: @@ -65,18 +50,6 @@ // initialized right after the LayerTreeHostImpl is created. So when this // pointer is initialized, there should be no trackers yet. UkmManager* const ukm_manager_; - - // The last "PercentDroppedFrames" reported to UMA. LayerTreeHostImpl will - // read this number and send to the GPU process. When this page is done, we - // will report to UKM using these numbers. Currently only meaningful to the - // kUniversal tracker. - // Possible values: - // 1. A non-negative int value which is the percent of frames dropped. - // 2. base::nullopt: when they are fetched by LayerTreeHostImpl, so that it - // knows that the last value has been reported. - base::Optional<int> last_aggregated_percent_; - base::Optional<int> last_main_percent_; - base::Optional<int> last_impl_percent_; }; } // namespace cc
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc index f160222..04e6025 100644 --- a/cc/trees/layer_tree_host_impl.cc +++ b/cc/trees/layer_tree_host_impl.cc
@@ -2315,19 +2315,6 @@ std::move(compositor_frame), /*hit_test_data_changed=*/false, debug_state_.show_hit_test_borders); - // This is expected to be true roughly every 5 seconds. - if (frame_trackers_.HasThroughputData()) { - ukm::SourceId source_id = ukm_manager_->source_id(); - // source_id can be invalid in tests. - if (source_id != ukm::kInvalidSourceId) { - int aggregated_percent = frame_trackers_.TakeLastAggregatedPercent(); - int impl_percent = frame_trackers_.TakeLastImplPercent(); - base::Optional<int> main_percent = frame_trackers_.TakeLastMainPercent(); - client_->SubmitThroughputData(source_id, aggregated_percent, impl_percent, - main_percent); - } - } - #if DCHECK_IS_ON() if (!doing_sync_draw_) { // The throughput computation (in |FrameSequenceTracker|) depends on the @@ -3602,7 +3589,6 @@ has_valid_layer_tree_frame_sink_ = true; auto* context_provider = layer_tree_frame_sink_->context_provider(); - frame_trackers_.StartSequence(FrameSequenceTrackerType::kUniversal); if (context_provider) { max_texture_size_ =
diff --git a/cc/trees/ukm_manager.cc b/cc/trees/ukm_manager.cc index 5b014c0..a41e299a 100644 --- a/cc/trees/ukm_manager.cc +++ b/cc/trees/ukm_manager.cc
@@ -114,7 +114,6 @@ CASE_FOR_MAIN_THREAD_TRACKER(RAF); CASE_FOR_MAIN_THREAD_TRACKER(ScrollbarScroll); CASE_FOR_MAIN_THREAD_TRACKER(TouchScroll); - CASE_FOR_MAIN_THREAD_TRACKER(Universal); CASE_FOR_MAIN_THREAD_TRACKER(Video); CASE_FOR_MAIN_THREAD_TRACKER(WheelScroll); #undef CASE_FOR_MAIN_THREAD_TRACKER @@ -138,7 +137,6 @@ CASE_FOR_COMPOSITOR_THREAD_TRACKER(RAF); CASE_FOR_COMPOSITOR_THREAD_TRACKER(ScrollbarScroll); CASE_FOR_COMPOSITOR_THREAD_TRACKER(TouchScroll); - CASE_FOR_COMPOSITOR_THREAD_TRACKER(Universal); CASE_FOR_COMPOSITOR_THREAD_TRACKER(Video); CASE_FOR_COMPOSITOR_THREAD_TRACKER(WheelScroll); #undef CASE_FOR_COMPOSITOR_THREAD_TRACKER @@ -161,7 +159,6 @@ CASE_FOR_SLOWER_THREAD_TRACKER(RAF); CASE_FOR_SLOWER_THREAD_TRACKER(ScrollbarScroll); CASE_FOR_SLOWER_THREAD_TRACKER(TouchScroll); - CASE_FOR_SLOWER_THREAD_TRACKER(Universal); CASE_FOR_SLOWER_THREAD_TRACKER(Video); CASE_FOR_SLOWER_THREAD_TRACKER(WheelScroll); #undef CASE_FOR_SLOWER_THREAD_TRACKER @@ -272,8 +269,6 @@ continue; const auto frame_sequence_tracker_type = static_cast<FrameSequenceTrackerType>(type); - if (frame_sequence_tracker_type == FrameSequenceTrackerType::kUniversal) - continue; switch (frame_sequence_tracker_type) { #define CASE_FOR_TRACKER(name) \ case FrameSequenceTrackerType::k##name: \
diff --git a/cc/trees/ukm_manager_unittest.cc b/cc/trees/ukm_manager_unittest.cc index e8cf3a6..a00d682 100644 --- a/cc/trees/ukm_manager_unittest.cc +++ b/cc/trees/ukm_manager_unittest.cc
@@ -77,7 +77,6 @@ const char kRAF[] = "RAF"; const char kScrollbarScroll[] = "ScrollbarScroll"; const char kTouchScroll[] = "TouchScroll"; -const char kUniversal[] = "Universal"; const char kVideo[] = "Video"; const char kWheelScroll[] = "WheelScroll"; @@ -268,8 +267,6 @@ static_cast<size_t>(FrameSequenceTrackerType::kTouchScroll)); active_trackers.set( static_cast<size_t>(FrameSequenceTrackerType::kCompositorAnimation)); - active_trackers.set( - static_cast<size_t>(FrameSequenceTrackerType::kUniversal)); manager_->RecordCompositorLatencyUKM(report_type(), stage_history, active_trackers, viz_breakdown); @@ -344,7 +341,6 @@ EXPECT_FALSE(test_ukm_recorder_->EntryHasMetric(entry, kMainThreadAnimation)); EXPECT_FALSE(test_ukm_recorder_->EntryHasMetric(entry, kPinchZoom)); EXPECT_FALSE(test_ukm_recorder_->EntryHasMetric(entry, kRAF)); - EXPECT_FALSE(test_ukm_recorder_->EntryHasMetric(entry, kUniversal)); EXPECT_FALSE(test_ukm_recorder_->EntryHasMetric(entry, kVideo)); EXPECT_FALSE(test_ukm_recorder_->EntryHasMetric(entry, kWheelScroll)); }
diff --git a/chrome/android/features/media_router/java/res/layout/caf_controller_media_route_button.xml b/chrome/android/features/media_router/java/res/layout/caf_controller_media_route_button.xml index b168fd96..9801fece 100644 --- a/chrome/android/features/media_router/java/res/layout/caf_controller_media_route_button.xml +++ b/chrome/android/features/media_router/java/res/layout/caf_controller_media_route_button.xml
@@ -3,7 +3,7 @@ Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. --> -<androidx.appcompat.app.MediaRouteButton +<androidx.mediarouter.app.MediaRouteButton xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/cast_controller_media_route_button" android:layout_width="wrap_content"
diff --git a/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/StartSurfaceMediator.java b/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/StartSurfaceMediator.java index 5db0330..7a72412 100644 --- a/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/StartSurfaceMediator.java +++ b/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/StartSurfaceMediator.java
@@ -531,10 +531,10 @@ mIsIncognito = mTabModelSelector.isIncognitoSelected(); mPropertyModel.set(IS_INCOGNITO, mIsIncognito); - // if OvervieModeState is NOT_SHOWN, default to SHOWING_HOMEPAGE. This should only + // if OvervieModeState is NOT_SHOWN, default to SHOWING_TABSWITCHER. This should only // happen when entering Start through SwipeDown gesture on URL bar. if (mOverviewModeState == OverviewModeState.NOT_SHOWN) { - mOverviewModeState = OverviewModeState.SHOWING_HOMEPAGE; + mOverviewModeState = OverviewModeState.SHOWING_TABSWITCHER; } // set OverviewModeState @@ -744,9 +744,11 @@ if (mSecondaryTasksSurfacePropertyModel == null) { mSecondaryTasksSurfaceController = mSecondaryTasksSurfaceInitializer.initialize(); } - mSecondaryTasksSurfacePropertyModel.set(IS_FAKE_SEARCH_BOX_VISIBLE, - mIsIncognito && mOverviewModeState == OverviewModeState.SHOWN_HOMEPAGE); - mSecondaryTasksSurfacePropertyModel.set(IS_INCOGNITO, mIsIncognito); + if (mSecondaryTasksSurfacePropertyModel != null) { + mSecondaryTasksSurfacePropertyModel.set(IS_FAKE_SEARCH_BOX_VISIBLE, + mIsIncognito && mOverviewModeState == OverviewModeState.SHOWN_HOMEPAGE); + mSecondaryTasksSurfacePropertyModel.set(IS_INCOGNITO, mIsIncognito); + } if (mSecondaryTasksSurfaceController != null) { mSecondaryTasksSurfaceController.showOverview(false); }
diff --git a/chrome/android/features/start_surface/internal/junit/src/org/chromium/chrome/features/start_surface/StartSurfaceMediatorUnitTest.java b/chrome/android/features/start_surface/internal/junit/src/org/chromium/chrome/features/start_surface/StartSurfaceMediatorUnitTest.java index 7348a4c11..de9ed76 100644 --- a/chrome/android/features/start_surface/internal/junit/src/org/chromium/chrome/features/start_surface/StartSurfaceMediatorUnitTest.java +++ b/chrome/android/features/start_surface/internal/junit/src/org/chromium/chrome/features/start_surface/StartSurfaceMediatorUnitTest.java
@@ -323,6 +323,11 @@ .addOverviewModeObserver(mOverviewModeObserverCaptor.capture()); assertThat(mediator.getOverviewState(), equalTo(OverviewModeState.NOT_SHOWN)); + // Sets the current OvervieModeState to SHOWING_START before calling the + // {@link StartSurfaceMediator#showOverview()}. This is because if the current + // OvervieModeState is NOT_SHOWN, the state will be set default to SHOWING_TABSWITCHER in + // {@link StartSurfaceMediator#showOverview()}. + mediator.setOverviewState(OverviewModeState.SHOWING_START); mediator.showOverview(false); verify(mMainTabGridController).showOverview(eq(false)); @@ -368,6 +373,11 @@ .addOverviewModeObserver(mOverviewModeObserverCaptor.capture()); assertThat(mediator.getOverviewState(), equalTo(OverviewModeState.NOT_SHOWN)); + // Sets the current OvervieModeState to SHOWING_START before calling the + // {@link StartSurfaceMediator#showOverview()}. This is because if the current + // OvervieModeState is NOT_SHOWN, the state will be set default to SHOWING_TABSWITCHER in + // {@link StartSurfaceMediator#showOverview()}. + mediator.setOverviewState(OverviewModeState.SHOWING_START); mediator.showOverview(false); verify(mMainTabGridController).showOverview(eq(false)); @@ -414,6 +424,11 @@ .addOverviewModeObserver(mOverviewModeObserverCaptor.capture()); assertThat(mediator.getOverviewState(), equalTo(OverviewModeState.NOT_SHOWN)); + // Sets the current OvervieModeState to SHOWING_START before calling the + // {@link StartSurfaceMediator#showOverview()}. This is because if the current + // OvervieModeState is NOT_SHOWN, the state will be set default to SHOWING_TABSWITCHER in + // {@link StartSurfaceMediator#showOverview()}. + mediator.setOverviewState(OverviewModeState.SHOWING_START); mediator.showOverview(false); verify(mMainTabGridController).showOverview(eq(false)); @@ -1364,7 +1379,7 @@ assertThat(mediator.getOverviewState(), equalTo(OverviewModeState.NOT_SHOWN)); mediator.showOverview(false); - assertThat(mediator.getOverviewState(), equalTo(OverviewModeState.SHOWN_HOMEPAGE)); + assertThat(mediator.getOverviewState(), equalTo(OverviewModeState.SHOWN_TABSWITCHER)); } @Test @@ -1500,6 +1515,11 @@ .when(mBrowserControlsStateProvider) .addObserver(mBrowserControlsStateProviderCaptor.capture()); StartSurfaceMediator mediator = createStartSurfaceMediator(SurfaceMode.SINGLE_PANE, false); + // Sets the current OvervieModeState to SHOWING_START before calling the + // {@link StartSurfaceMediator#showOverview()}. This is because if the current + // OvervieModeState is NOT_SHOWN, the state will be set default to SHOWING_TABSWITCHER in + // {@link StartSurfaceMediator#showOverview()}. + mediator.setOverviewState(OverviewModeState.SHOWING_START); mediator.showOverview(false); verify(mBrowserControlsStateProvider).addObserver(ArgumentMatchers.any()); @@ -1527,6 +1547,11 @@ .addOverviewModeObserver(mOverviewModeObserverCaptor.capture()); assertThat(mediator.getOverviewState(), equalTo(OverviewModeState.NOT_SHOWN)); + // Sets the current OvervieModeState to SHOWING_START before calling the + // {@link StartSurfaceMediator#showOverview()}. This is because if the current + // OvervieModeState is NOT_SHOWN, the state will be set default to SHOWING_TABSWITCHER in + // {@link StartSurfaceMediator#showOverview()}. + mediator.setOverviewState(OverviewModeState.SHOWING_START); mediator.showOverview(false); assertThat(mediator.getOverviewState(), equalTo(OverviewModeState.SHOWN_HOMEPAGE)); assertThat(mPropertyModel.get(IS_EXPLORE_SURFACE_VISIBLE), equalTo(false));
diff --git a/chrome/android/java/res/layout/personalized_signin_promo_view_body.xml b/chrome/android/java/res/layout/personalized_signin_promo_view_body.xml index 71ee8a7..98aa62f 100644 --- a/chrome/android/java/res/layout/personalized_signin_promo_view_body.xml +++ b/chrome/android/java/res/layout/personalized_signin_promo_view_body.xml
@@ -16,7 +16,7 @@ android:layout_marginBottom="8dp" android:gravity="center" android:textAppearance="@style/TextAppearance.TextMediumThick.Primary" - android:text="@string/signin_promo_status_message" + android:text="@string/sync_error_card_title" android:visibility="gone"/> <TextView
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/paint_preview/PaintPreviewHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/paint_preview/PaintPreviewHelper.java index b9694e7..bb47d2c 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/paint_preview/PaintPreviewHelper.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/paint_preview/PaintPreviewHelper.java
@@ -13,7 +13,6 @@ import org.chromium.chrome.browser.metrics.UmaUtils; import org.chromium.chrome.browser.multiwindow.MultiWindowUtils; import org.chromium.chrome.browser.paint_preview.services.PaintPreviewTabServiceFactory; -import org.chromium.chrome.browser.paint_preview.services.PaintPreviewTabServiceNativeInitObserver; import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tabmodel.EmptyTabModelSelectorObserver; import org.chromium.chrome.browser.tabmodel.TabModelSelector; @@ -50,9 +49,6 @@ } sActivityCreationTimeMs = activity.getOnCreateTimestampMs(); - activity.getLifecycleDispatcher().register( - new PaintPreviewTabServiceNativeInitObserver(activity.getLifecycleDispatcher())); - // TODO(crbug/1074428): verify this doesn't cause a memory leak if the user exits Chrome // prior to onTabStateInitialized being called. tabModelSelector.addObserver(new EmptyTabModelSelectorObserver() {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentAppFactoryInterface.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentAppFactoryInterface.java index b0bff6a..7fe761a5 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentAppFactoryInterface.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentAppFactoryInterface.java
@@ -13,6 +13,10 @@ * 3) Call delegate.onPaymentAppCreated(app) for apps that match the method data. * 4) Call delegate.onDoneCreatingPaymentApps(this) exactly once. * + * If called while the RenderFrameHost object is still available in Java, but its counterparts + * has been deleted in C++, then none of the `delegate` methods are expected to be called, + * because the frame is being unloaded. + * * @param delegate Provides information about payment request and receives a list of payment * apps. */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestFactory.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestFactory.java index 816df05..def0a8f 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestFactory.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestFactory.java
@@ -132,6 +132,7 @@ @Override public String getInvalidSslCertificateErrorMessage() { WebContents webContents = getWebContents(); + if (webContents == null || webContents.isDestroyed()) return null; if (!OriginSecurityChecker.isSchemeCryptographic(webContents.getLastCommittedUrl())) { return null; } @@ -146,8 +147,10 @@ @Override public boolean prefsCanMakePayment() { - return UserPrefs.get(Profile.fromWebContents(getWebContents())) - .getBoolean(Pref.CAN_MAKE_PAYMENT_ENABLED); + WebContents webContents = getWebContents(); + return webContents != null && !webContents.isDestroyed() + && UserPrefs.get(Profile.fromWebContents(webContents)) + .getBoolean(Pref.CAN_MAKE_PAYMENT_ENABLED); } @Override @@ -161,6 +164,7 @@ return activity != null ? mPackageManager.getTwaPackageName(activity) : null; } + @Nullable private WebContents getWebContents() { return WebContentsStatics.fromRenderFrameHost(mRenderFrameHost); } @@ -196,6 +200,8 @@ } WebContents webContents = WebContentsStatics.fromRenderFrameHost(mRenderFrameHost); + if (webContents == null || webContents.isDestroyed()) return new InvalidPaymentRequest(); + return ComponentPaymentRequestImpl.createPaymentRequest(mRenderFrameHost, /*isOffTheRecord=*/delegate.isOffTheRecord(webContents), /*skipUiForBasicCard=*/delegate.skipUiForBasicCard(),
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/ServiceWorkerPaymentAppBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/ServiceWorkerPaymentAppBridge.java index 916dd78..63764e7b3 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/payments/ServiceWorkerPaymentAppBridge.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/ServiceWorkerPaymentAppBridge.java
@@ -141,10 +141,10 @@ /** * Notify closing the opened payment app window. * - * @param webContents The web contents in the opened window. + * @param webContents The web contents in the opened window. Can be null. */ - public static void onClosingPaymentAppWindow(WebContents webContents) { - if (webContents.isDestroyed()) return; + public static void onClosingPaymentAppWindow(@Nullable WebContents webContents) { + if (webContents == null || webContents.isDestroyed()) return; ServiceWorkerPaymentAppBridgeJni.get().onClosingPaymentAppWindow( webContents, PaymentEventResponseType.PAYMENT_HANDLER_WINDOW_CLOSING); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/sync/AndroidSyncSettings.java b/chrome/android/java/src/org/chromium/chrome/browser/sync/AndroidSyncSettings.java index 0e12ac3d..3160cd7 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/sync/AndroidSyncSettings.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/sync/AndroidSyncSettings.java
@@ -118,8 +118,18 @@ updateSyncability(callback); mSyncContentResolverDelegate.addStatusChangeListener( - ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS, - new AndroidSyncSettingsChangedObserver()); + ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS, new SyncStatusObserver() { + @Override + public void onStatusChanged(int which) { + if (which == ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS) { + // Sync settings have changed; update our cached values. + if (updateCachedSettings()) { + // If something actually changed, tell our observers. + notifyObservers(); + } + } + } + }); } /** @@ -287,24 +297,6 @@ } /** - * Helper class to be used by observers whenever sync settings change. - * - * To register the observer, call AndroidSyncSettings.registerObserver(...). - */ - private class AndroidSyncSettingsChangedObserver implements SyncStatusObserver { - @Override - public void onStatusChanged(int which) { - if (which == ContentResolver.SYNC_OBSERVER_TYPE_SETTINGS) { - // Sync settings have changed; update our cached values. - if (updateCachedSettings()) { - // If something actually changed, tell our observers. - notifyObservers(); - } - } - } - } - - /** * Update the three cached settings from the content resolver. * * @return Whether either chromeSyncEnabled or masterSyncEnabled changed.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/sync/ProfileSyncService.java b/chrome/android/java/src/org/chromium/chrome/browser/sync/ProfileSyncService.java index 7d6a21c..ae05364 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/sync/ProfileSyncService.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/sync/ProfileSyncService.java
@@ -195,6 +195,16 @@ mNativeProfileSyncServiceAndroid, ProfileSyncService.this); } + public void setDecoupledFromAndroidMasterSync() { + ProfileSyncServiceJni.get().setDecoupledFromAndroidMasterSync( + mNativeProfileSyncServiceAndroid, ProfileSyncService.this); + } + + public boolean getDecoupledFromAndroidMasterSync() { + return ProfileSyncServiceJni.get().getDecoupledFromAndroidMasterSync( + mNativeProfileSyncServiceAndroid, ProfileSyncService.this); + } + /** * Gets the set of data types that are "preferred" in sync. Those are the * chosen ones (see getChosenDataTypes), plus any that are implied by them. @@ -652,6 +662,10 @@ int getAuthError(long nativeProfileSyncServiceAndroid, ProfileSyncService caller); boolean requiresClientUpgrade( long nativeProfileSyncServiceAndroid, ProfileSyncService caller); + void setDecoupledFromAndroidMasterSync( + long nativeProfileSyncServiceAndroid, ProfileSyncService caller); + boolean getDecoupledFromAndroidMasterSync( + long nativeProfileSyncServiceAndroid, ProfileSyncService caller); boolean isEngineInitialized( long nativeProfileSyncServiceAndroid, ProfileSyncService caller); boolean isEncryptEverythingAllowed(
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/sync/settings/SyncErrorCardPreference.java b/chrome/android/java/src/org/chromium/chrome/browser/sync/settings/SyncErrorCardPreference.java index 448b36a..645aa5f 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/sync/settings/SyncErrorCardPreference.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/sync/settings/SyncErrorCardPreference.java
@@ -127,7 +127,6 @@ errorCardView.getDismissButton().setVisibility(View.GONE); errorCardView.getStatusMessage().setVisibility(View.VISIBLE); - errorCardView.getStatusMessage().setText(R.string.sync_error_card_title); errorCardView.getDescription().setText( SyncSettingsUtils.getSyncErrorHint(getContext(), mSyncError));
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/page_info/PageInfoControllerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/page_info/PageInfoControllerTest.java index f42af4e7..8878341 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/page_info/PageInfoControllerTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/page_info/PageInfoControllerTest.java
@@ -104,7 +104,7 @@ new PageInfoController(tab.getWebContents(), ConnectionSecurityLevel.NONE, /*publisher=*/null, chromePageInfoControllerDelegate, chromePermissionParamsListBuilderDelegate); - PageInfoView pageInfoView = pageInfo.getPageInfoViewForTesting(); + PageInfoView pageInfoView = (PageInfoView) pageInfo.getPageInfoViewForTesting(); // Test that the title contains the Unicode hostname rather than strict equality, as // the test server will be bound to a random port. Assert.assertTrue(
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/page_info/PageInfoViewTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/page_info/PageInfoViewTest.java index c9b4524..beaeb48 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/page_info/PageInfoViewTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/page_info/PageInfoViewTest.java
@@ -41,7 +41,6 @@ import org.chromium.components.location.LocationUtils; import org.chromium.components.page_info.PageInfoController; import org.chromium.components.page_info.PageInfoFeatureList; -import org.chromium.components.page_info.PageInfoView; import org.chromium.components.user_prefs.UserPrefs; import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.content_public.common.ContentSwitches; @@ -90,10 +89,10 @@ onView(withId(R.id.location_bar_status_icon)).perform(click()); } - private PageInfoView getPageInfoView() { + private View getPageInfoView() { PageInfoController controller = PageInfoController.getLastPageInfoControllerForTesting(); assertNotNull(controller); - PageInfoView view = controller.getPageInfoViewForTesting(); + View view = controller.getPageInfoViewForTesting(); assertNotNull(view); return view; } @@ -266,9 +265,8 @@ @Features.EnableFeatures(PageInfoFeatureList.PAGE_INFO_V2) public void testShowConnectionInfoSubpage() throws IOException { loadUrlAndOpenPageInfo(mTestServerRule.getServer().getURL(mPath)); - View dialog = (View) getPageInfoView().getParent(); onView(withId(R.id.page_info_connection_row)).perform(click()); - mRenderTestRule.render(dialog, "PageInfo_ConnectionInfoSubpage"); + mRenderTestRule.render(getPageInfoView(), "PageInfo_ConnectionInfoSubpage"); } /** @@ -280,9 +278,8 @@ @Features.EnableFeatures(PageInfoFeatureList.PAGE_INFO_V2) public void testShowPermissionsSubpage() throws IOException { loadUrlAndOpenPageInfo(mTestServerRule.getServer().getURL(mPath)); - View dialog = (View) getPageInfoView().getParent(); onView(withId(R.id.page_info_permissions_row)).perform(click()); - mRenderTestRule.render(dialog, "PageInfo_PermissionsSubpage"); + mRenderTestRule.render(getPageInfoView(), "PageInfo_PermissionsSubpage"); } /** @@ -295,9 +292,8 @@ public void testShowCookiesSubpage() throws IOException { setThirdPartyCookieBlocking(CookieControlsMode.BLOCK_THIRD_PARTY); loadUrlAndOpenPageInfo(mTestServerRule.getServer().getURL(mPath)); - View dialog = (View) getPageInfoView().getParent(); onView(withId(R.id.page_info_cookies_row)).perform(click()); - mRenderTestRule.render(dialog, "PageInfo_CookiesSubpage"); + mRenderTestRule.render(getPageInfoView(), "PageInfo_CookiesSubpage"); } // TODO(1071762): Add tests for preview pages, offline pages, offline state and other states.
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/paint_preview/services/PaintPreviewTabServiceTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/paint_preview/services/PaintPreviewTabServiceTest.java index b80f138..1d0dfd6 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/paint_preview/services/PaintPreviewTabServiceTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/paint_preview/services/PaintPreviewTabServiceTest.java
@@ -151,6 +151,44 @@ } /** + * Tests that capturing and deleting via an audit works as expected. + */ + @Test + @MediumTest + @Feature({"PaintPreview"}) + public void testCapturedAndDeleteViaAudit() throws Exception { + EmbeddedTestServer testServer = mActivityTestRule.getTestServer(); + final String url = testServer.getURL("/chrome/test/data/android/about.html"); + + TestThreadUtils.runOnUiThreadBlocking(() -> { + mPaintPreviewTabService = PaintPreviewTabServiceFactory.getServiceInstance(); + // Use capture on switch mode. + mPaintPreviewTabService.onRestoreCompleted(mTabModelSelector, true, true); + mTab.loadUrl(new LoadUrlParams(url)); + }); + // Give the tab time to complete layout before hiding. + TimeUnit.SECONDS.sleep(1); + + // This will hide mTab so that a capture occurs. + mActivityTestRule.loadUrlInNewTab(url); + + int tabId = mTab.getId(); + CriteriaHelper.pollUiThread(() -> { + return mPaintPreviewTabService.hasCaptureForTab(tabId); + }, "Paint Preview didn't get captured.", TIMEOUT_MS, POLLING_INTERVAL_MS); + + TestThreadUtils.runOnUiThreadBlocking(() -> { + // Use the incognito tab model as the normal tab model will still have the tab ids + // active. + mPaintPreviewTabService.auditOnStart(mTabModelSelector.getModel(/*incognito=*/true)); + }); + + CriteriaHelper.pollUiThread(() -> { + return !mPaintPreviewTabService.hasCaptureForTab(tabId); + }, "Paint Preview didn't get deleted.", TIMEOUT_MS, POLLING_INTERVAL_MS); + } + + /** * Verifies the early cache is created correctly. */ @Test
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/sync/SyncTestRule.java b/chrome/android/javatests/src/org/chromium/chrome/browser/sync/SyncTestRule.java index f4c940ef..cfa8c63 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/sync/SyncTestRule.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/sync/SyncTestRule.java
@@ -202,8 +202,10 @@ * @return the test account that is signed in. */ public Account setUpAccountAndSignInForTesting() { - Account account = addTestAccount(); - signinAndEnableSync(account); + Account account = mAccountManagerTestRule.addAndSignInTestAccount(mProfileSyncService); + enableUKM(); + SyncTestUtil.waitForSyncActive(); + SyncTestUtil.triggerSyncAndWaitForCompletion(); return account; } @@ -429,10 +431,8 @@ Assert.fail("Sign-in was aborted"); } }); - // Outside of tests, URL-keyed anonymized data collection is enabled by sign-in UI. - UnifiedConsentServiceBridge.setUrlKeyedAnonymizedDataCollectionEnabled( - Profile.getLastUsedRegularProfile(), true); }); + enableUKM(); if (setFirstSetupComplete) { SyncTestUtil.waitForSyncActive(); SyncTestUtil.triggerSyncAndWaitForCompletion(); @@ -441,4 +441,12 @@ } Assert.assertEquals(account, mAccountManagerTestRule.getCurrentSignedInAccount()); } + + private static void enableUKM() { + TestThreadUtils.runOnUiThreadBlocking(() -> { + // Outside of tests, URL-keyed anonymized data collection is enabled by sign-in UI. + UnifiedConsentServiceBridge.setUrlKeyedAnonymizedDataCollectionEnabled( + Profile.getLastUsedRegularProfile(), true); + }); + } }
diff --git a/chrome/app/resources/generated_resources_bn.xtb b/chrome/app/resources/generated_resources_bn.xtb index 497ee88b..51b3760 100644 --- a/chrome/app/resources/generated_resources_bn.xtb +++ b/chrome/app/resources/generated_resources_bn.xtb
@@ -4478,6 +4478,7 @@ <translation id="6415900369006735853">আপনার ফোনের মাধ্যমে ইন্টারনেটে কানেক্ট করুন</translation> <translation id="6416743254476733475">আপনার কম্পিউটারে অনুমতি দিন বা ব্লক করুন।</translation> <translation id="6417265370957905582">Google Assistant</translation> +<translation id="6417468503703810114">ডিফল্ট মোড</translation> <translation id="6418160186546245112"><ph name="IDS_SHORT_PRODUCT_NAME" /> এর পূর্বে ইনস্টল করা সংস্করণে ফিরিয়ে নিয়ে যাওয়া হচ্ছে</translation> <translation id="6418481728190846787">সমস্ত অ্যাপ্লিকেশানের অ্যাক্সেস স্থায়ীভাবে সরান</translation> <translation id="6418511932144861495">জরুরী আপডেট ইনস্টল করুন</translation> @@ -5553,6 +5554,7 @@ <translation id="7766082757934713382">অ্যাপ ও সিস্টেমের অটোমেটিক আপডেট পজ করে নেটওয়ার্ক ডেটার ব্যবহার কম করতে সাহায্য করে</translation> <translation id="7766807826975222231">একবার ঘুরে দেখুন</translation> <translation id="7766838926148951335">অনুমতিগুলি স্বীকার করুন</translation> +<translation id="7768507955883790804">আপনি সাইট খুললে সেটি অটোমেটিক এই সেটিংস মেনে কাজ করবে</translation> <translation id="7768770796815395237">পরিবর্তন করুন</translation> <translation id="7768784765476638775">বাছুন ও শুনুন</translation> <translation id="7769672763586021400">মডেল আইডি</translation>
diff --git a/chrome/app/resources/generated_resources_or.xtb b/chrome/app/resources/generated_resources_or.xtb index f0b0aa6..c1abbc13 100644 --- a/chrome/app/resources/generated_resources_or.xtb +++ b/chrome/app/resources/generated_resources_or.xtb
@@ -506,6 +506,7 @@ <translation id="158849752021629804">ହୋମ୍ ନେଟ୍ୱର୍କ ଦରକାର</translation> <translation id="1588870296199743671">ଏହା ମାଧ୍ୟମରେ ଲିଙ୍କ ଖୋଲନ୍ତୁ...</translation> <translation id="1589055389569595240">'ବନାନ ଏବଂ ବ୍ୟାକରଣ' ବିକଳ୍ପ ଦେଖାନ୍ତୁ</translation> +<translation id="1591679663873027990">Parallels Desktopକୁ USB ଡିଭାଇସଗୁଡ଼ିକୁ ଆକ୍ସେସ୍ କରିବାକୁ ଅନୁମତି ଦିଅନ୍ତୁ। କୌଣସି USB ଡିଭାଇସକୁ କାଢ଼ି ଦିଆଯିବା ପରେ Parallels Desktop ଏହାକୁ ମନେ ରଖିବ ନାହିଁ।</translation> <translation id="1593594475886691512">ଫର୍ମାଟ୍ କରାଯାଉଛି…</translation> <translation id="159359590073980872">ଛବି କେଚ୍</translation> <translation id="1593926297800505364">ପେମେଣ୍ଟ ପଦ୍ଧତିକୁ ସେଭ୍ କରନ୍ତୁ</translation> @@ -820,6 +821,7 @@ <translation id="1954813140452229842">ସେୟାର୍ ଖଞ୍ଜିବାରେ ତ୍ରୁଟି। ଦୟାକରି ଆପଣଙ୍କର କ୍ରେଡେନ୍ସିଆଲ୍ ଯାଞ୍ଚ କରନ୍ତୁ ଏବଂ ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।</translation> <translation id="1956050014111002555">ଫାଇଲ୍ରେ ଅନେକ ସାର୍ଟିଫିକେଟ୍ ଅଛି, ଏଥିମଧ୍ୟରୁ କୌଣସିଟି ଇମ୍ପୋର୍ଟ ହୋଇନାହିଁ:</translation> <translation id="1956390763342388273">ଏହା "<ph name="FOLDER_PATH" />"ରୁ ସମସ୍ତ ଫାଇଲ୍କୁ ଅପ୍ଲୋଡ୍ କରିବ। ଆପଣ ଯଦି ସାଇଟ୍କୁ ବିଶ୍ଵାସ କରନ୍ତି, ତା'ହେଲେ ହିଁ ଏହା କରନ୍ତୁ।</translation> +<translation id="196040970347962278">ପ୍ରଥମେ ଏକ ଇଣ୍ଟରନେଟ୍ ସଂଯୋଗ ସ୍ଥାପନ କରନ୍ତୁ</translation> <translation id="1962233722219655970">ଏହି ପୃଷ୍ଠାକୁ ଏପରି ମୂଳ କ୍ଲାଏଣ୍ଟର ବ୍ୟବହାର କରେ ଯାହା ଆପଣଙ୍କର କମ୍ପ୍ୟୁଟର୍ରେ କାର୍ଯ୍ୟ କରେନାହିଁ।</translation> <translation id="1963227389609234879">ସମସ୍ତ ଅପସାରଣ କରନ୍ତୁ</translation> <translation id="1963976881984600709">ଷ୍ଟାଣ୍ଡାର୍ଡ ସୁରକ୍ଷା</translation> @@ -1857,6 +1859,7 @@ <translation id="321834671654278338">Linux ଅନ୍ଇନ୍ଷ୍ଟଲର୍</translation> <translation id="3220586366024592812"><ph name="CLOUD_PRINT_NAME" />ସଂଯୋଜକ ପ୍ରକ୍ରିୟା କ୍ରାସ୍ ହୋଇଯାଇଛି। ରିଷ୍ଟାର୍ଟ କରିବେ?</translation> <translation id="3222066309010235055">ପୂର୍ବପ୍ରସ୍ତୁତି: <ph name="PRERENDER_CONTENTS_NAME" /></translation> +<translation id="3222779980972075989"><ph name="USB_VM_NAME" />ରେ ସଂଯୋଗ କରନ୍ତୁ</translation> <translation id="3223531857777746191">ବଟନ୍କୁ ରିସେଟ୍ କରନ୍ତୁ</translation> <translation id="3225084153129302039">ଡିଫଲ୍ଟ ପର୍ପଲ୍ ଅବତାର</translation> <translation id="3225319735946384299">କୋଡ୍ ହସ୍ତାକ୍ଷର</translation> @@ -1869,6 +1872,7 @@ <translation id="3246107497225150582">{0,plural, =1{ଗୋଟିଏ ଦିନ ଭିତରେ ଡିଭାଇସ୍ ଅପଡେଟ୍ କରନ୍ତୁ}other{# ଦିନ ଭିତରେ ଡିଭାଇସ୍ ଅପଡେଟ୍ କରନ୍ତୁ}}</translation> <translation id="324849028894344899"><ph name="WINDOW_TITLE" /> - ନେଟ୍ୱର୍କ ତ୍ରୁଟି</translation> <translation id="3248902735035392926">ସୁରକ୍ଷା ଗୁରୁତ୍ୱପୂର୍ଣ୍ଣ ଅଟେ। କିଛି ସମୟ ନିଅନ୍ତୁ ଏବଂ <ph name="BEGIN_LINK" />ବର୍ତ୍ତମାନ ଆପଣଙ୍କ ଏକ୍ସଟେନ୍ସନ୍ଗୁଡ଼ିକର ଯାଞ୍ଚ କରନ୍ତୁ<ph name="END_LINK" /></translation> +<translation id="325036368918787455">ଇନକଗ୍ନିଟୋ ୱିଣ୍ଡୋ ବନ୍ଦ କରନ୍ତୁ</translation> <translation id="3251759466064201842"><ସାର୍ଟିଫିକେଟ୍ର ଅଂଶ ନୁହେଁ></translation> <translation id="3253225298092156258">ଉପଲବ୍ଧ ନାହିଁ</translation> <translation id="3253448572569133955">ଅଜଣା ଆକାଉଣ୍ଟ</translation> @@ -2108,6 +2112,7 @@ <translation id="3527085408025491307">ଫୋଲ୍ଡର୍</translation> <translation id="3528498924003805721">ସର୍ଟକଟ୍ ଟାର୍ଗେଟ୍</translation> <translation id="3532273508346491126">ସିଙ୍କ୍ ପରିଚାଳନା</translation> +<translation id="3532521178906420528">ନେଟୱାର୍କ ସଂଯୋଗ ସ୍ଥାପନ କରାଯାଉଛି ...</translation> <translation id="353316712352074340"><ph name="WINDOW_TITLE" /> - ଅଡିଓକୁ ମ୍ୟୁଟ୍ କରାଗଲା</translation> <translation id="3537881477201137177">ଏହାକୁ ସେଟିଂସରେ ପରେ ପରିବର୍ତ୍ତନ କରାଯାଇପାରିବ</translation> <translation id="3538066758857505094">Linux ଅନ୍ଇନ୍ଷ୍ଟଲ୍ କରିବା ସମୟରେ ତ୍ରୁଟି ହୋଇଛି। ଦୟାକରି ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।</translation> @@ -3116,6 +3121,7 @@ <translation id="4750394297954878236">ପରାମର୍ଶ</translation> <translation id="475088594373173692">ପ୍ରଥମ ଉପଯୋଗକର୍ତ୍ତା</translation> <translation id="4751476147751820511">ମୋସନ୍ କିମ୍ବା ଲାଇଟ୍ ସେନ୍ସର୍</translation> +<translation id="4752124003533492687"><ph name="USB_DEVICE_NAME" />କୁ ସଂଯୋଗ କରିବା ପାଇଁ ସେଟିଂସ୍ ଖୋଲନ୍ତୁ</translation> <translation id="4756378406049221019">ବନ୍ଦ/ପୁଣି ଲୋଡ୍ କରନ୍ତୁ</translation> <translation id="4756388243121344051">&ଇତିବୃତ୍ତି</translation> <translation id="4759238208242260848">ଡାଉନଲୋଡସମୂହ</translation> @@ -4634,6 +4640,7 @@ <ph name="EXTENSION_NAME" /> ସ୍ଥାୟୀ ଆକ୍ସେସ୍ ଚାହୁଁଛି।</translation> <translation id="6635944431854494329">'ସେଟିଂସ୍ > ଉନ୍ନତ > ସ୍ଵଚାଳିତ ଭାବେ Googleକୁ ଡାଏଗ୍ନୋଷ୍ଟିକ୍ ଓ ବ୍ୟବହାର ଡାଟା ପଠାନ୍ତୁ'ରୁ ମାଲିକ ଏହି ଫିଚରକୁ ନିୟନ୍ତ୍ରଣ କରିପାରିବେ।</translation> <translation id="6635956300022133031">ଟେକ୍ସଟ୍ରୁ ସ୍ପିଚ୍ ଭଏସ୍ ବାଛନ୍ତୁ ଏବଂ କଷ୍ଟମାଇଜ୍ କରନ୍ତୁ</translation> +<translation id="6636588250634969791">ଆଗକୁ ବଢ଼ିବା ପୂର୍ବରୁ SIM ଇନସାର୍ଟ କରନ୍ତୁ</translation> <translation id="6639554308659482635">SQLite ମେମୋରୀ</translation> <translation id="6641138807883536517">ମିଶାମିଶି ସୃଷ୍ଟି ହେଉଥିବା ସୁରକ୍ଷିତ ମଡ୍ୟୁଲ୍ ପାସ୍ୱର୍ଡ ଉପଲବ୍ଧ ନାହିଁ। ଏକ ପାୱାର୍ୱାସ୍ ପରେ ଏହା ସ୍ୱାଭାବିକ ଅଟେ।</translation> <translation id="6642720633335369752">ସବୁ ଦେଖିବା ପାଇଁ ଆପ୍ ୱିଣ୍ଡୋ ଖୋଲନ୍ତୁ, ତଳୁ ଉପରକୁ ସ୍ୱାଇପ୍ କରି ଧରି ରଖନ୍ତୁ।</translation> @@ -5176,6 +5183,7 @@ <translation id="7303900363563182677">କ୍ଲିପବୋର୍ଡ୍କୁ ଛବି କପି କରିବା ଏବଂ ଟେକ୍ସଟ୍ ଦେଖିବାରୁ ଏହି ସାଇଟ୍କୁ ଅବରୋଧ କରିଦିଆଯାଇଛି।</translation> <translation id="7305123176580523628">USB ପ୍ରିଣ୍ଟର୍ ସଂଯୋଗ କରାଯାଇଛି</translation> <translation id="730515362922783851">ସ୍ଥାନୀୟ ନେଟ୍ୱର୍କ କିମ୍ବା ଇଣ୍ଟର୍ନେଟ୍ରେ ଥିବା ଯେକୌଣସି ଡିଭାଇସ୍ ସହିତ ଡାଟା ଆଦାନ-ପ୍ରଦାନ କରନ୍ତୁ</translation> +<translation id="7306521477691455105"><ph name="USB_DEVICE_NAME" />କୁ <ph name="USB_VM_NAME" />ରେ ସଂଯୋଗ କରିବା ପାଇଁ ସେଟିଂସ୍ ଖୋଲନ୍ତୁ</translation> <translation id="7307129035224081534">ବିରତ କରାଯାଇଛି</translation> <translation id="7308002049209013926">ନୂଆ ଆପ୍ ଓ ଗତିବିଧିଗୁଡ଼ିକୁ ଶୀଘ୍ର ପ୍ରାପ୍ତ କରିବା ପାଇଁ ଲଞ୍ଚର୍ ବ୍ୟବହାର କରନ୍ତୁ। କୀବୋର୍ଡ ଦ୍ୱାରା ଏଠାରେ ପହଞ୍ଚିବା ପାଇଁ, Alt + Shift + L ଦବାନ୍ତୁ।</translation> <translation id="7309257895202129721">&ନିୟନ୍ତ୍ରଣଗୁଡ଼ିକ ଦେଖାନ୍ତୁ</translation> @@ -6794,6 +6802,7 @@ <translation id="947329552760389097">&ଉପାଦାନଗୁଡ଼ିକ ନିରୀକ୍ଷଣ କରନ୍ତୁ</translation> <translation id="951991426597076286">ଅଗ୍ରାହ୍ୟ କରନ୍ତୁ</translation> <translation id="952992212772159698">ସକ୍ରିୟ ହୋଇନାହିଁ</translation> +<translation id="956444359529327203">ଅତିଥି ୱିଣ୍ଡୋ ବନ୍ଦ କରନ୍ତୁ</translation> <translation id="956500788634395331">ଆପଣ ସମ୍ଭାବ୍ୟ କ୍ଷତିକାରକ ଏକ୍ସଟେନସନଗୁଡ଼ିକରୁ ସୁରକ୍ଷିତ ଅଛନ୍ତି</translation> <translation id="957960681186851048">ଏହି ସାଇଟ୍ ସ୍ୱଚାଳିତ ଭାବେ ଏକାଧିକ ଫାଇଲ୍ ଡାଉନ୍ଲୋଡ୍ କରିବାକୁ ଚେଷ୍ଟା କରୁଛି</translation> <translation id="9580706199804957">Google ସେବା ସହ ସଂଯୋଗ ହୋଇପାରିଲା ନାହିଁ</translation>
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index f4837be..7d3b989d 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -300,6 +300,8 @@ "component_updater/crowd_deny_component_installer.h", "component_updater/file_type_policies_component_installer.cc", "component_updater/file_type_policies_component_installer.h", + "component_updater/first_party_sets_component_installer.cc", + "component_updater/first_party_sets_component_installer.h", "component_updater/floc_blocklist_component_installer.cc", "component_updater/floc_blocklist_component_installer.h", "component_updater/games_component_installer.cc",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index ea7422e..121ca25 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -5939,6 +5939,10 @@ flag_descriptions::kReleaseNotesNotificationName, flag_descriptions::kReleaseNotesNotificationDescription, kOsCrOS, FEATURE_VALUE_TYPE(chromeos::features::kReleaseNotesNotification)}, + {"use-wallpaper-staging-url", + flag_descriptions::kUseWallpaperStagingUrlName, + flag_descriptions::kUseWallpaperStagingUrlDescription, kOsCrOS, + FEATURE_VALUE_TYPE(chromeos::features::kUseWallpaperStagingUrl)}, #endif // defined(OS_CHROMEOS) {"passive-mixed-content-warning",
diff --git a/chrome/browser/apps/app_shim/app_shim_manager_mac.cc b/chrome/browser/apps/app_shim/app_shim_manager_mac.cc index 041afeb..56e14baa 100644 --- a/chrome/browser/apps/app_shim/app_shim_manager_mac.cc +++ b/chrome/browser/apps/app_shim/app_shim_manager_mac.cc
@@ -297,9 +297,18 @@ std::unique_ptr<AppShimHostBootstrap> bootstrap) { DCHECK(crx_file::id_util::IdIsValid(bootstrap->GetAppId())); switch (bootstrap->GetLaunchType()) { - case chrome::mojom::AppShimLaunchType::kNormal: - OnShimProcessConnectedForLaunch(std::move(bootstrap)); + case chrome::mojom::AppShimLaunchType::kNormal: { + const web_app::AppId app_id = bootstrap->GetAppId(); + const base::FilePath profile_path = bootstrap->GetProfilePath(); + const std::vector<base::FilePath> launch_files = + bootstrap->GetLaunchFiles(); + LoadAndLaunchAppCallback launch_callback = base::BindOnce( + &AppShimManager::OnShimProcessConnectedAndAllLaunchesDone, + weak_factory_.GetWeakPtr(), std::move(bootstrap)); + LoadAndLaunchApp(app_id, profile_path, launch_files, + std::move(launch_callback)); break; + } case chrome::mojom::AppShimLaunchType::kRegisterOnly: OnShimProcessConnectedForRegisterOnly(std::move(bootstrap)); break; @@ -339,18 +348,17 @@ } OnShimProcessConnectedAndAllLaunchesDone( - profile_state, - profile_state ? chrome::mojom::AppShimLaunchResult::kSuccess - : chrome::mojom::AppShimLaunchResult::kSuccessAndDisconnect, - std::move(bootstrap)); + std::move(bootstrap), profile_state, + profile_state + ? chrome::mojom::AppShimLaunchResult::kSuccess + : chrome::mojom::AppShimLaunchResult::kSuccessAndDisconnect); } -void AppShimManager::OnShimProcessConnectedForLaunch( - std::unique_ptr<AppShimHostBootstrap> bootstrap) { - const web_app::AppId& app_id = bootstrap->GetAppId(); - DCHECK_EQ(bootstrap->GetLaunchType(), - chrome::mojom::AppShimLaunchType::kNormal); - +void AppShimManager::LoadAndLaunchApp( + const web_app::AppId& app_id, + const base::FilePath& profile_path, + std::vector<base::FilePath> launch_files, + LoadAndLaunchAppCallback launch_callback) { // Retrieve the list of last-active profiles. If there are no last-active // profiles (which is rare -- e.g, when the last-active profiles were // removed), then use all profiles for which the app is installed. @@ -364,8 +372,7 @@ // Construct |profile_paths_to_launch| to be the list of all profiles to // attempt to launch, starting with the profile specified in |bootstrap|, // at the front of the list. - std::vector<base::FilePath> profile_paths_to_launch = { - bootstrap->GetProfilePath()}; + std::vector<base::FilePath> profile_paths_to_launch = {profile_path}; for (const auto& profile_path : last_active_profile_paths) profile_paths_to_launch.push_back(profile_path); @@ -373,9 +380,9 @@ // they're loaded (or have failed to load), call // OnShimProcessConnectedAndProfilesToLaunchLoaded. base::OnceClosure callback = base::BindOnce( - &AppShimManager::OnShimProcessConnectedAndProfilesToLaunchLoaded, - weak_factory_.GetWeakPtr(), std::move(bootstrap), - profile_paths_to_launch); + &AppShimManager::LoadAndLaunchApp_OnProfilesAndAppReady, + weak_factory_.GetWeakPtr(), app_id, std::move(launch_files), + profile_paths_to_launch, std::move(launch_callback)); { // This will update |callback| to be a chain of callbacks that load the // profiles in |profile_paths_to_load|, one by one, using @@ -385,7 +392,7 @@ for (const auto& profile_path : profile_paths_to_launch) { if (profile_path.empty()) continue; - LoadProfileAppCallback callback_wrapped = + LoadProfileAndAppCallback callback_wrapped = base::BindOnce([](base::OnceClosure callback_to_wrap, Profile*) { std::move(callback_to_wrap).Run(); }, std::move(callback)); @@ -397,16 +404,11 @@ std::move(callback).Run(); } -void AppShimManager::OnShimProcessConnectedAndProfilesToLaunchLoaded( - std::unique_ptr<AppShimHostBootstrap> bootstrap, - const std::vector<base::FilePath>& profile_paths_to_launch) { - // The the profile specified in |bootstrap| (even if it's empty) should be the - // first profile listed in |profile_paths_to_launch|. - DCHECK_EQ(profile_paths_to_launch[0], bootstrap->GetProfilePath()); - - const auto& app_id = bootstrap->GetAppId(); - auto launch_files = bootstrap->GetLaunchFiles(); - +void AppShimManager::LoadAndLaunchApp_OnProfilesAndAppReady( + const web_app::AppId& app_id, + std::vector<base::FilePath> launch_files, + const std::vector<base::FilePath>& profile_paths_to_launch, + LoadAndLaunchAppCallback launch_callback) { // Launch all of the profiles in |profile_paths_to_launch|. Record the most // profile successfully launched in |launched_profile_state|, and the most // recent reason for a failure (if any) in |launch_result|. @@ -472,14 +474,13 @@ if (launched_profile_state) launch_result = chrome::mojom::AppShimLaunchResult::kSuccess; - OnShimProcessConnectedAndAllLaunchesDone(launched_profile_state, - launch_result, std::move(bootstrap)); + std::move(launch_callback).Run(launched_profile_state, launch_result); } void AppShimManager::OnShimProcessConnectedAndAllLaunchesDone( + std::unique_ptr<AppShimHostBootstrap> bootstrap, ProfileState* profile_state, - chrome::mojom::AppShimLaunchResult result, - std::unique_ptr<AppShimHostBootstrap> bootstrap) { + chrome::mojom::AppShimLaunchResult result) { // If we failed because the profile was locked, launch the profile manager. if (result == chrome::mojom::AppShimLaunchResult::kProfileLocked) LaunchUserManager(); @@ -565,22 +566,23 @@ void AppShimManager::LoadProfileAndApp(const base::FilePath& profile_path, const web_app::AppId& app_id, - LoadProfileAppCallback callback) { + LoadProfileAndAppCallback callback) { // Run |profile_loaded_callback| when the profile is loaded (be that now, or // after having to asynchronously load the profile). auto profile_loaded_callback = base::BindOnce( - &AppShimManager::OnProfileLoaded, weak_factory_.GetWeakPtr(), - profile_path, app_id, std::move(callback)); + &AppShimManager::LoadProfileAndApp_OnProfileLoaded, + weak_factory_.GetWeakPtr(), profile_path, app_id, std::move(callback)); if (auto* profile = ProfileForPath(profile_path)) std::move(profile_loaded_callback).Run(profile); else LoadProfileAsync(profile_path, std::move(profile_loaded_callback)); } -void AppShimManager::OnProfileLoaded(const base::FilePath& profile_path, - const web_app::AppId& app_id, - LoadProfileAppCallback callback, - Profile* profile) { +void AppShimManager::LoadProfileAndApp_OnProfileLoaded( + const base::FilePath& profile_path, + const web_app::AppId& app_id, + LoadProfileAndAppCallback callback, + Profile* profile) { // It may be that the profile fails to load. DCHECK_CURRENTLY_ON(content::BrowserThread::UI); if (!profile) { @@ -593,15 +595,15 @@ // launching. // https://crbug.com/1094419. auto registry_ready_callback = base::BindOnce( - &AppShimManager::OnProfileAppRegistryReady, weak_factory_.GetWeakPtr(), - profile_path, app_id, std::move(callback)); + &AppShimManager::LoadProfileAndApp_OnProfileAppRegistryReady, + weak_factory_.GetWeakPtr(), profile_path, app_id, std::move(callback)); WaitForAppRegistryReadyAsync(profile, std::move(registry_ready_callback)); } -void AppShimManager::OnProfileAppRegistryReady( +void AppShimManager::LoadProfileAndApp_OnProfileAppRegistryReady( const base::FilePath& profile_path, const web_app::AppId& app_id, - LoadProfileAppCallback callback) { + LoadProfileAndAppCallback callback) { // It may be that the profile was destroyed while waiting for the callback to // be issued. Profile* profile = ProfileForPath(profile_path); @@ -611,9 +613,9 @@ } // Run |app_enabled_callback| once the app is enabled (now or async). Note // that this is only relevant for extension-based apps. - auto app_enabled_callback = - base::BindOnce(&AppShimManager::OnAppEnabled, weak_factory_.GetWeakPtr(), - profile_path, app_id, std::move(callback)); + auto app_enabled_callback = base::BindOnce( + &AppShimManager::LoadProfileAndApp_OnAppEnabled, + weak_factory_.GetWeakPtr(), profile_path, app_id, std::move(callback)); if (delegate_->AppIsInstalled(profile, app_id)) { std::move(app_enabled_callback).Run(); } else { @@ -622,9 +624,10 @@ } } -void AppShimManager::OnAppEnabled(const base::FilePath& profile_path, - const web_app::AppId& app_id, - LoadProfileAppCallback callback) { +void AppShimManager::LoadProfileAndApp_OnAppEnabled( + const base::FilePath& profile_path, + const web_app::AppId& app_id, + LoadProfileAndAppCallback callback) { std::move(callback).Run(ProfileForPath(profile_path)); }
diff --git a/chrome/browser/apps/app_shim/app_shim_manager_mac.h b/chrome/browser/apps/app_shim/app_shim_manager_mac.h index 7ae2f41..0aac4a5 100644 --- a/chrome/browser/apps/app_shim/app_shim_manager_mac.h +++ b/chrome/browser/apps/app_shim/app_shim_manager_mac.h
@@ -242,27 +242,39 @@ void OnShimProcessConnectedForRegisterOnly( std::unique_ptr<AppShimHostBootstrap> bootstrap); - // This is called by OnShimProcessConnected when the shim was was launched - // not by Chrome, and needs to launch the app (that is, open a new app - // window). - void OnShimProcessConnectedForLaunch( - std::unique_ptr<AppShimHostBootstrap> bootstrap); - - // Continuation of OnShimProcessConnectedForLaunch, once all of the profiles - // to use have been loaded. The list of profiles to launch is in - // |profile_paths_to_launch|. The first entry corresponds to the bootstrap- - // specified profile, and may be a blank path. - void OnShimProcessConnectedAndProfilesToLaunchLoaded( - std::unique_ptr<AppShimHostBootstrap> bootstrap, - const std::vector<base::FilePath>& profile_paths_to_launch); + // The function LoadAndLaunchApp will: + // - Find the appropriate profiles for which |app_id| should be launched. + // - Load the profiles and ensure the app is enabled (using + // LoadProfileAndApp). + // - Launch the app, if appropriate. + // The "if appropriate" above is defined as: + // - If |launch_files| is non-empty, then will always launch the app + // - If |profile_path| is non-empty, then use that profile. + // - In the most recently used profile, otherwise + // - If |launch_files| is empty, then launch the app only if: + // - If |profile_path| is non-empty, then launch if the app is not running + // in that profile. + // - Otherwise, launch the app only if it is not running any profile. + using LoadAndLaunchAppCallback = + base::OnceCallback<void(ProfileState* profile_state, + chrome::mojom::AppShimLaunchResult result)>; + void LoadAndLaunchApp(const web_app::AppId& app_id, + const base::FilePath& profile_path, + std::vector<base::FilePath> launch_files, + LoadAndLaunchAppCallback launch_callback); + void LoadAndLaunchApp_OnProfilesAndAppReady( + const web_app::AppId& app_id, + std::vector<base::FilePath> launch_files, + const std::vector<base::FilePath>& profile_paths_to_launch, + LoadAndLaunchAppCallback launch_callback); // The final step of both paths for OnShimProcessConnected. This will connect // |bootstrap| to |profile_state|'s AppShimHost, if possible. The value of // |profile_state| is non-null if and only if |result| is success. void OnShimProcessConnectedAndAllLaunchesDone( + std::unique_ptr<AppShimHostBootstrap> bootstrap, ProfileState* profile_state, - chrome::mojom::AppShimLaunchResult result, - std::unique_ptr<AppShimHostBootstrap> bootstrap); + chrome::mojom::AppShimLaunchResult result); // Continuation of OnShimSelectedProfile, once the profile has loaded. void OnShimSelectedProfileAndAppLoaded(const web_app::AppId& app_id, @@ -270,20 +282,21 @@ // Load the specified profile and extension, and run |callback| with // the result. The callback's arguments may be nullptr on failure. - using LoadProfileAppCallback = base::OnceCallback<void(Profile*)>; + using LoadProfileAndAppCallback = base::OnceCallback<void(Profile*)>; void LoadProfileAndApp(const base::FilePath& profile_path, const web_app::AppId& app_id, - LoadProfileAppCallback callback); - void OnProfileLoaded(const base::FilePath& profile_path, - const web_app::AppId& app_id, - LoadProfileAppCallback callback, - Profile* profile); - void OnProfileAppRegistryReady(const base::FilePath& profile_path, - const web_app::AppId& app_id, - LoadProfileAppCallback callback); - void OnAppEnabled(const base::FilePath& profile_path, - const web_app::AppId& app_id, - LoadProfileAppCallback callback); + LoadProfileAndAppCallback callback); + void LoadProfileAndApp_OnProfileLoaded(const base::FilePath& profile_path, + const web_app::AppId& app_id, + LoadProfileAndAppCallback callback, + Profile* profile); + void LoadProfileAndApp_OnProfileAppRegistryReady( + const base::FilePath& profile_path, + const web_app::AppId& app_id, + LoadProfileAndAppCallback callback); + void LoadProfileAndApp_OnAppEnabled(const base::FilePath& profile_path, + const web_app::AppId& app_id, + LoadProfileAndAppCallback callback); // Update the profiles menu for the specified host. void UpdateAppProfileMenu(AppState* app_state);
diff --git a/chrome/browser/chrome_find_request_manager_browsertest.cc b/chrome/browser/chrome_find_request_manager_browsertest.cc index 6b14197..e622c3e 100644 --- a/chrome/browser/chrome_find_request_manager_browsertest.cc +++ b/chrome/browser/chrome_find_request_manager_browsertest.cc
@@ -7,6 +7,7 @@ #include "base/path_service.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" +#include "base/test/scoped_feature_list.h" #include "base/threading/thread_restrictions.h" #include "build/build_config.h" #include "chrome/browser/pdf/pdf_extension_test_util.h" @@ -27,6 +28,7 @@ #include "net/dns/mock_host_resolver.h" #include "net/test/embedded_test_server/controllable_http_response.h" #include "pdf/document_loader_impl.h" +#include "pdf/pdf_features.h" #include "third_party/blink/public/mojom/frame/find_in_page.mojom.h" namespace content { @@ -90,6 +92,20 @@ DISALLOW_COPY_AND_ASSIGN(ChromeFindRequestManagerTest); }; +class ChromeFindRequestManagerTestWithPdfPartialLoading + : public ChromeFindRequestManagerTest { + public: + ChromeFindRequestManagerTestWithPdfPartialLoading() { + feature_list_.InitWithFeatures( + {chrome_pdf::features::kPdfIncrementalLoading, + chrome_pdf::features::kPdfPartialLoading}, + {}); + } + + private: + base::test::ScopedFeatureList feature_list_; +}; + // Tests searching in a full-page PDF. // Flaky on Windows ASAN: crbug.com/1030368. #if defined(OS_WIN) && defined(ADDRESS_SANITIZER) @@ -157,7 +173,8 @@ // Tests searching in a PDF received in chunks via range-requests. See also // https://crbug.com/1027173. -IN_PROC_BROWSER_TEST_F(ChromeFindRequestManagerTest, FindInChunkedPDF) { +IN_PROC_BROWSER_TEST_F(ChromeFindRequestManagerTestWithPdfPartialLoading, + FindInChunkedPDF) { constexpr uint32_t kStalledResponseSize = chrome_pdf::DocumentLoaderImpl::kDefaultRequestSize + 123;
diff --git a/chrome/browser/chromeos/backdrop_wallpaper_handlers/backdrop_wallpaper_handlers.cc b/chrome/browser/chromeos/backdrop_wallpaper_handlers/backdrop_wallpaper_handlers.cc index 8977c0c3..445d3ad 100644 --- a/chrome/browser/chromeos/backdrop_wallpaper_handlers/backdrop_wallpaper_handlers.cc +++ b/chrome/browser/chromeos/backdrop_wallpaper_handlers/backdrop_wallpaper_handlers.cc
@@ -11,6 +11,7 @@ #include "chrome/browser/chromeos/backdrop_wallpaper_handlers/backdrop_wallpaper.pb.h" #include "chrome/browser/net/system_network_context_manager.h" #include "chrome/common/extensions/api/wallpaper_private.h" +#include "chromeos/constants/chromeos_features.h" #include "chromeos/constants/chromeos_switches.h" #include "chromeos/constants/devicetype.h" #include "content/public/browser/browser_thread.h" @@ -50,6 +51,10 @@ chromeos::switches::kTestWallpaperServer)) { base::ReplaceFirstSubstringAfterOffset(&url, 0, "clients3", "chromecast-dev.sandbox"); + } else if (base::FeatureList::IsEnabled( + chromeos::features::kUseWallpaperStagingUrl)) { + base::ReplaceFirstSubstringAfterOffset(&url, 0, "clients3", + "chromecast-staging.sandbox"); } return url; }
diff --git a/chrome/browser/chromeos/policy/auto_enrollment_client_impl.cc b/chrome/browser/chromeos/policy/auto_enrollment_client_impl.cc index 63667b3..1eb01ba7 100644 --- a/chrome/browser/chromeos/policy/auto_enrollment_client_impl.cc +++ b/chrome/browser/chromeos/policy/auto_enrollment_client_impl.cc
@@ -51,6 +51,18 @@ base::TimeDelta::FromSeconds(15); // UMA histogram names. +constexpr char kUMAHashDanceSuccessTime[] = + "Enterprise.AutoEnrollmentHashDanceSuccessTime"; +constexpr char kUMAPrivateSetMembershipHashDanceComparison[] = + "Enterprise.AutoEnrollmentPrivateSetMembershipHashDanceComparison"; +constexpr char kUMAPrivateSetMembershipSuccessTime[] = + "Enterprise.AutoEnrollmentPrivateSetMembershipSuccessTime"; +constexpr char kUMAPrivateSetMembershipRequestStatus[] = + "Enterprise.AutoEnrollmentPrivateSetMembershipRequestStatus"; + +// The following histogram names where added before private set membership +// existed. They are only recorded for hash dance. + constexpr char kUMAProtocolTime[] = "Enterprise.AutoEnrollmentProtocolTime"; constexpr char kUMABucketDownloadTime[] = "Enterprise.AutoEnrollmentBucketDownloadTime"; @@ -259,6 +271,12 @@ return; } + // Report the psm attempt and start the timer to measure successful private + // set membership requests. + base::UmaHistogramEnumeration(kUMAPrivateSetMembershipRequestStatus, + PrivateSetMembershipStatus::kAttempt); + time_start_ = base::TimeTicks::Now(); + on_completion_callback_ = std::move(callback); // Start the protocol and its timeout timer. @@ -311,9 +329,17 @@ } private: - void OnTimeout() { StoreErrorAndStop(); } + void OnTimeout() { + base::UmaHistogramEnumeration(kUMAPrivateSetMembershipRequestStatus, + PrivateSetMembershipStatus::kTimeout); + StoreErrorAndStop(); + } void StoreErrorAndStop() { + // Record the error. Note that a timeout is also recorded as error. + base::UmaHistogramEnumeration(kUMAPrivateSetMembershipRequestStatus, + PrivateSetMembershipStatus::kError); + // Stop the private set membership timer. private_set_membership_timeout_.Stop(); @@ -482,6 +508,11 @@ LOG(WARNING) << "PSM query request completed successfully"; + base::UmaHistogramEnumeration( + kUMAPrivateSetMembershipRequestStatus, + PrivateSetMembershipStatus::kSuccessfulDetermination); + RecordPrivateSetMembershipSuccessTimeHistogram(); + // The RLWE query response has been processed successfully. Extract // the membership response, and report the result. psm_rlwe::MembershipResponseMap membership_responses_map = @@ -538,6 +569,23 @@ std::move(callback)); } + // Record UMA histogram for timing of successful private set membership + // request. + void RecordPrivateSetMembershipSuccessTimeHistogram() { + // These values determine bucketing of the histogram, they should not be + // changed. + static const base::TimeDelta kMin = base::TimeDelta::FromMilliseconds(1); + static const base::TimeDelta kMax = base::TimeDelta::FromSeconds(25); + static const int kBuckets = 50; + + base::TimeTicks now = base::TimeTicks::Now(); + if (!time_start_.is_null()) { + base::TimeDelta delta = now - time_start_; + base::UmaHistogramCustomTimes(kUMAPrivateSetMembershipSuccessTime, delta, + kMin, kMax, kBuckets); + } + } + // Private Set Membership RLWE client, used for preparing PSM requests and // parsing PSM responses. std::unique_ptr<psm_rlwe::PrivateMembershipRlweClient> @@ -575,6 +623,9 @@ // membership protocol. base::OneShotTimer private_set_membership_timeout_; + // The time when the private set membership request started. + base::TimeTicks time_start_; + // A sequence checker to prevent the race condition of having the possibility // of the destructor being called and any of the callbacks. SEQUENCE_CHECKER(sequence_checker_); @@ -857,7 +908,7 @@ // Drop the previous job and reset state. request_job_.reset(); state_ = AUTO_ENROLLMENT_STATE_PENDING; - time_start_ = base::Time::Now(); + time_start_ = base::TimeTicks::Now(); modulus_updates_received_ = 0; has_server_state_ = false; device_state_available_ = false; @@ -877,7 +928,7 @@ // Client still running, but our owner isn't interested in the result // anymore. Wait until the protocol completes to measure the extra time // needed. - time_extra_start_ = base::Time::Now(); + time_extra_start_ = base::TimeTicks::Now(); progress_callback_.Reset(); } } @@ -927,7 +978,8 @@ state_download_message_processor_( std::move(state_download_message_processor)), private_set_membership_helper_(std::move(private_set_membership_helper)), - uma_suffix_(uma_suffix) { + uma_suffix_(uma_suffix), + recorded_psm_hash_dance_comparison_(false) { DCHECK_LE(current_power_, power_limit_); DCHECK(!progress_callback_.is_null()); } @@ -1015,6 +1067,18 @@ void AutoEnrollmentClientImpl::ReportProgress(AutoEnrollmentState state) { state_ = state; + // If hash dance finished with an error or result, record comparison with + // private set membership. Note that hash dance might be retried but for + // recording we only care about the first attempt. + // If |private_set_membership_helper_| is non-null, a private set membership + // request has been made at this point because it is executed before hash + // dance. + const bool has_hash_dance_result = (state != AUTO_ENROLLMENT_STATE_IDLE && + state != AUTO_ENROLLMENT_STATE_PENDING); + if (private_set_membership_helper_ && !recorded_psm_hash_dance_comparison_ && + has_hash_dance_result) { + RecordPrivateSetMembershipHashDanceComparison(); + } if (progress_callback_.is_null()) { base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, this); } else { @@ -1067,7 +1131,7 @@ // Record the time when the bucket download request is started. Note that the // time may be set multiple times. This is fine, only the last request is the // one where the hash bucket is actually downloaded. - time_start_bucket_download_ = base::Time::Now(); + time_start_bucket_download_ = base::TimeTicks::Now(); VLOG(1) << "Request bucket #" << remainder; std::unique_ptr<DMServerJobConfiguration> config = std::make_unique< @@ -1209,6 +1273,10 @@ local_state_->CommitPendingWrite(); VLOG(1) << "Received has_state=" << has_server_state_; progress = true; + // Report timing if hash dance finished successfully and if the caller is + // still interested in the result. + if (!progress_callback_.is_null()) + RecordHashDanceSuccessTimeHistogram(); } // Bucket download done, update UMA. @@ -1269,6 +1337,8 @@ } void AutoEnrollmentClientImpl::UpdateBucketDownloadTimingHistograms() { + // These values determine bucketing of the histogram, they should not be + // changed. // The minimum time can't be 0, must be at least 1. static const base::TimeDelta kMin = base::TimeDelta::FromMilliseconds(1); static const base::TimeDelta kMax = base::TimeDelta::FromMinutes(5); @@ -1276,7 +1346,7 @@ static const base::TimeDelta kZero = base::TimeDelta::FromMilliseconds(0); static const int kBuckets = 50; - base::Time now = base::Time::Now(); + base::TimeTicks now = base::TimeTicks::Now(); if (!time_start_.is_null()) { base::TimeDelta delta = now - time_start_; base::UmaHistogramCustomTimes(kUMAProtocolTime + uma_suffix_, delta, kMin, @@ -1297,4 +1367,74 @@ kBuckets); } +void AutoEnrollmentClientImpl::RecordHashDanceSuccessTimeHistogram() { + // These values determine bucketing of the histogram, they should not be + // changed. + static const base::TimeDelta kMin = base::TimeDelta::FromMilliseconds(1); + static const base::TimeDelta kMax = base::TimeDelta::FromSeconds(25); + static const int kBuckets = 50; + + base::TimeTicks now = base::TimeTicks::Now(); + if (!time_start_.is_null()) { + base::TimeDelta delta = now - time_start_; + base::UmaHistogramCustomTimes(kUMAHashDanceSuccessTime + uma_suffix_, delta, + kMin, kMax, kBuckets); + } +} + +void AutoEnrollmentClientImpl::RecordPrivateSetMembershipHashDanceComparison() { + // Private set membership timeout is enforced in the helper class. This method + // should only be called after private set membership request finished or ran + // into timeout. + DCHECK(private_set_membership_helper_); + DCHECK(!private_set_membership_helper_->IsCheckMembershipInProgress()); + + // Make sure to only record once per instance. + recorded_psm_hash_dance_comparison_ = true; + + bool private_set_membership_decision = + private_set_membership_helper_->GetPrivateSetMembershipCachedDecision(); + bool private_set_membership_error = + private_set_membership_helper_->HasPrivateSetMembershipError(); + + bool hash_dance_decision = has_server_state_; + bool hash_dance_error = false; + switch (state_) { + case AUTO_ENROLLMENT_STATE_TRIGGER_ENROLLMENT: + case AUTO_ENROLLMENT_STATE_NO_ENROLLMENT: + case AUTO_ENROLLMENT_STATE_TRIGGER_ZERO_TOUCH: + case AUTO_ENROLLMENT_STATE_DISABLED: + hash_dance_error = false; + break; + case AUTO_ENROLLMENT_STATE_CONNECTION_ERROR: + case AUTO_ENROLLMENT_STATE_SERVER_ERROR: + hash_dance_error = true; + break; + // This method should only be called if hash dance finished. + case AUTO_ENROLLMENT_STATE_IDLE: + case AUTO_ENROLLMENT_STATE_PENDING: + default: + NOTREACHED(); + } + + auto comparison = PrivateSetMembershipHashDanceComparison::kEqualResults; + if (!hash_dance_error && !private_set_membership_error) { + comparison = + (hash_dance_decision == private_set_membership_decision) + ? PrivateSetMembershipHashDanceComparison::kEqualResults + : PrivateSetMembershipHashDanceComparison::kDifferentResults; + } else if (hash_dance_error && !private_set_membership_error) { + comparison = + PrivateSetMembershipHashDanceComparison::kPSMSuccessHashDanceError; + } else if (!hash_dance_error && private_set_membership_error) { + comparison = + PrivateSetMembershipHashDanceComparison::kPSMErrorHashDanceSuccess; + } else { + comparison = PrivateSetMembershipHashDanceComparison::kBothError; + } + + base::UmaHistogramEnumeration(kUMAPrivateSetMembershipHashDanceComparison, + comparison); +} + } // namespace policy
diff --git a/chrome/browser/chromeos/policy/auto_enrollment_client_impl.h b/chrome/browser/chromeos/policy/auto_enrollment_client_impl.h index 68c34e8..932fd18f 100644 --- a/chrome/browser/chromeos/policy/auto_enrollment_client_impl.h +++ b/chrome/browser/chromeos/policy/auto_enrollment_client_impl.h
@@ -47,6 +47,27 @@ // Upon a failed determination it won't allow another membership check. class PrivateSetMembershipHelper; +// These values are persisted to logs. Entries should not be renumbered and +// numeric values should never be reused. +enum class PrivateSetMembershipStatus { + kAttempt = 0, + kSuccessfulDetermination = 1, + kError = 2, + kTimeout = 3, + kMaxValue = kTimeout, +}; + +// These values are persisted to logs. Entries should not be renumbered and +// numeric values should never be reused. +enum class PrivateSetMembershipHashDanceComparison { + kEqualResults = 0, + kDifferentResults = 1, + kPSMErrorHashDanceSuccess = 2, + kPSMSuccessHashDanceError = 3, + kBothError = 4, + kMaxValue = kBothError, +}; + // Interacts with the device management service and determines whether this // machine should automatically enter the Enterprise Enrollment screen during // OOBE. @@ -194,6 +215,14 @@ // Updates UMA histograms for bucket download timings. void UpdateBucketDownloadTimingHistograms(); + // Updates the UMA histogram for successful hash dance. + void RecordHashDanceSuccessTimeHistogram(); + + // Records the UMA histogram comparing results of hash dance and private set + // membership. This function should be called after PSM and hash dance + // requests finished. + void RecordPrivateSetMembershipHashDanceComparison(); + // Callback to invoke when the protocol generates a relevant event. This can // be either successful completion or an error that requires external action. ProgressCallback progress_callback_; @@ -253,17 +282,22 @@ // If |time_start_| is not null, the protocol is still running. // If |time_extra_start_| is not null, the protocol is still running but our // owner has relinquished ownership. - base::Time time_start_; - base::Time time_extra_start_; + base::TimeTicks time_start_; + base::TimeTicks time_extra_start_; // The time when the bucket download part of the protocol started. - base::Time time_start_bucket_download_; + base::TimeTicks time_start_bucket_download_; // The UMA histogram suffix. Will be ".ForcedReenrollment" for an // |AutoEnrollmentClient| used for FRE and ".InitialEnrollment" for an // |AutoEnrollmentclient| used for initial enrollment. const std::string uma_suffix_; + // Whether this instance already recorded the comparison of private set + // membership and hash dance. This is required because we do not want to + // record the result again on a hash dance retry. + bool recorded_psm_hash_dance_comparison_ = false; + DISALLOW_COPY_AND_ASSIGN(AutoEnrollmentClientImpl); };
diff --git a/chrome/browser/chromeos/policy/browser_policy_connector_chromeos.cc b/chrome/browser/chromeos/policy/browser_policy_connector_chromeos.cc index 3352ae4..ee6a2f0 100644 --- a/chrome/browser/chromeos/policy/browser_policy_connector_chromeos.cc +++ b/chrome/browser/chromeos/policy/browser_policy_connector_chromeos.cc
@@ -477,6 +477,10 @@ RestartDeviceCloudPolicyInitializer(); } +bool BrowserPolicyConnectorChromeOS::IsCommandLineSwitchSupported() const { + return true; +} + std::vector<std::unique_ptr<policy::ConfigurationPolicyProvider>> BrowserPolicyConnectorChromeOS::CreatePolicyProviders() { auto providers = ChromeBrowserPolicyConnector::CreatePolicyProviders();
diff --git a/chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h b/chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h index b47e167..9d7b7f0 100644 --- a/chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h +++ b/chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h
@@ -226,6 +226,10 @@ chromeos::AffiliationIDSet GetDeviceAffiliationIDs() const; + // BrowserPolicyConnector: + // Always returns true as command line flag can be set under dev mode only. + bool IsCommandLineSwitchSupported() const override; + protected: // ChromeBrowserPolicyConnector: std::vector<std::unique_ptr<policy::ConfigurationPolicyProvider>>
diff --git a/chrome/browser/chromeos/policy/extension_install_event_log_collector.cc b/chrome/browser/chromeos/policy/extension_install_event_log_collector.cc index 137ca4b..e1bbb06a 100644 --- a/chrome/browser/chromeos/policy/extension_install_event_log_collector.cc +++ b/chrome/browser/chromeos/policy/extension_install_event_log_collector.cc
@@ -124,6 +124,8 @@ return em::ExtensionInstallReportLogEvent::CRX_FETCH_URL_EMPTY; case extensions::InstallStageTracker::FailureReason::CRX_FETCH_URL_INVALID: return em::ExtensionInstallReportLogEvent::CRX_FETCH_URL_INVALID; + case extensions::InstallStageTracker::FailureReason::OVERRIDDEN_BY_SETTINGS: + return em::ExtensionInstallReportLogEvent::OVERRIDDEN_BY_SETTINGS; default: NOTREACHED(); }
diff --git a/chrome/browser/chromeos/policy/system_log_uploader.cc b/chrome/browser/chromeos/policy/system_log_uploader.cc index 5b5d063c..9148c6c 100644 --- a/chrome/browser/chromeos/policy/system_log_uploader.cc +++ b/chrome/browser/chromeos/policy/system_log_uploader.cc
@@ -28,6 +28,7 @@ #include "chrome/browser/chromeos/policy/upload_job_impl.h" #include "chrome/browser/device_identity/device_oauth2_token_service.h" #include "chrome/browser/device_identity/device_oauth2_token_service_factory.h" +#include "chrome/browser/policy/chrome_browser_policy_connector.h" #include "chrome/browser/policy/chrome_policy_conversions_client.h" #include "chrome/browser/profiles/profile_manager.h" #include "chrome/common/chrome_features.h" @@ -267,7 +268,8 @@ } std::string GetUploadUrl() { - return BrowserPolicyConnector::GetDeviceManagementUrl() + + return g_browser_process->browser_policy_connector() + ->GetDeviceManagementUrl() + kSystemLogUploadUrlTail; }
diff --git a/chrome/browser/chromeos/profiles/profile_helper.cc b/chrome/browser/chromeos/profiles/profile_helper.cc index 955ccd46..249740f 100644 --- a/chrome/browser/chromeos/profiles/profile_helper.cc +++ b/chrome/browser/chromeos/profiles/profile_helper.cc
@@ -62,6 +62,7 @@ "40FF1103292F40C34066E023B8BE8CAE18306EAE", // Chromeos help "3C654B3B6682CA194E75AD044CEDE927675DDEE8", // Easy unlock "75C7F4B720314B6CB1B5817CD86089DB95CD2461", // ChromeVox + "4D725C894DA4CF1F4D96C60F0D83BD745EB530CA", // Switch Access }; // As defined in /chromeos/dbus/cryptohome/cryptohome_client.cc.
diff --git a/chrome/browser/component_updater/first_party_sets_component_installer.cc b/chrome/browser/component_updater/first_party_sets_component_installer.cc new file mode 100644 index 0000000..4af1937 --- /dev/null +++ b/chrome/browser/component_updater/first_party_sets_component_installer.cc
@@ -0,0 +1,162 @@ +// 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/component_updater/first_party_sets_component_installer.h" + +#include "base/bind.h" +#include "base/feature_list.h" +#include "base/files/file_util.h" +#include "base/logging.h" +#include "base/memory/ref_counted.h" +#include "base/optional.h" +#include "base/path_service.h" +#include "base/stl_util.h" +#include "base/task/post_task.h" +#include "base/task/thread_pool.h" +#include "base/version.h" +#include "components/component_updater/component_updater_paths.h" +#include "services/network/public/cpp/features.h" + +using component_updater::ComponentUpdateService; + +namespace { + +constexpr base::FilePath::CharType kFirstPartySetsSetsFileName[] = + FILE_PATH_LITERAL("sets.json"); + +// The SHA256 of the SubjectPublicKeyInfo used to sign the extension. +// The extension id is: gonpemdgkjcecdgbnaabipppbmgfggbe +constexpr uint8_t kFirstPartySetsPublicKeySHA256[32] = { + 0x6e, 0xdf, 0x4c, 0x36, 0xa9, 0x24, 0x23, 0x61, 0xd0, 0x01, 0x8f, + 0xff, 0x1c, 0x65, 0x66, 0x14, 0xa8, 0x46, 0x37, 0xe6, 0xeb, 0x80, + 0x8b, 0x8f, 0xb0, 0xb6, 0x18, 0xa7, 0xcd, 0x3d, 0xbb, 0xfb}; + +constexpr char kFirstPartySetsManifestName[] = "First-Party Sets"; + +constexpr base::FilePath::CharType kFirstPartySetsRelativeInstallDir[] = + FILE_PATH_LITERAL("FirstPartySetsPreloaded"); + +// Reads the sets as raw JSON from their storage file, returning the raw sets on +// success and nullopt on failure. +base::Optional<std::string> LoadSetsFromDisk(const base::FilePath& pb_path) { + if (pb_path.empty()) + return base::nullopt; + + VLOG(1) << "Reading First-Party Sets from file: " << pb_path.value(); + std::string result; + if (!base::ReadFileToString(pb_path, &result)) { + // The file won't exist on new installations, so this is not always an + // error. + VLOG(1) << "Failed reading from " << pb_path.value(); + return base::nullopt; + } + return result; +} + +} // namespace + +namespace component_updater { + +FirstPartySetsComponentInstallerPolicy::FirstPartySetsComponentInstallerPolicy( + base::RepeatingCallback<void(const std::string&)> on_sets_ready) + : on_sets_ready_(std::move(on_sets_ready)) {} + +FirstPartySetsComponentInstallerPolicy:: + ~FirstPartySetsComponentInstallerPolicy() = default; + +bool FirstPartySetsComponentInstallerPolicy:: + SupportsGroupPolicyEnabledComponentUpdates() const { + // False since this is a data, non-binary component. + return false; +} + +bool FirstPartySetsComponentInstallerPolicy::RequiresNetworkEncryption() const { + // Update checks and pings associated with this component do not require + // confidentiality, since the component is identical for all users. + return false; +} + +update_client::CrxInstaller::Result +FirstPartySetsComponentInstallerPolicy::OnCustomInstall( + const base::DictionaryValue& manifest, + const base::FilePath& install_dir) { + return update_client::CrxInstaller::Result(0); // Nothing custom here. +} + +void FirstPartySetsComponentInstallerPolicy::OnCustomUninstall() {} + +base::FilePath FirstPartySetsComponentInstallerPolicy::GetInstalledPath( + const base::FilePath& base) { + return base.Append(kFirstPartySetsSetsFileName); +} + +void FirstPartySetsComponentInstallerPolicy::ComponentReady( + const base::Version& version, + const base::FilePath& install_dir, + std::unique_ptr<base::DictionaryValue> manifest) { + VLOG(1) << "First-Party Sets Component ready, version " << version.GetString() + << " in " << install_dir.value(); + + base::ThreadPool::PostTaskAndReplyWithResult( + FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT}, + base::BindOnce(&LoadSetsFromDisk, GetInstalledPath(install_dir)), + base::BindOnce( + [](base::RepeatingCallback<void(const std::string&)> on_sets_ready, + base::Optional<std::string> raw_sets) { + if (raw_sets.has_value()) + on_sets_ready.Run(*raw_sets); + }, + on_sets_ready_)); +} + +// Called during startup and installation before ComponentReady(). +bool FirstPartySetsComponentInstallerPolicy::VerifyInstallation( + const base::DictionaryValue& manifest, + const base::FilePath& install_dir) const { + // No need to actually validate the sets here, since we'll do the validation + // in the Network Service. + return base::PathExists(GetInstalledPath(install_dir)); +} + +base::FilePath FirstPartySetsComponentInstallerPolicy::GetRelativeInstallDir() + const { + return base::FilePath(kFirstPartySetsRelativeInstallDir); +} + +void FirstPartySetsComponentInstallerPolicy::GetHash( + std::vector<uint8_t>* hash) const { + hash->assign(kFirstPartySetsPublicKeySHA256, + kFirstPartySetsPublicKeySHA256 + + base::size(kFirstPartySetsPublicKeySHA256)); +} + +std::string FirstPartySetsComponentInstallerPolicy::GetName() const { + return kFirstPartySetsManifestName; +} + +update_client::InstallerAttributes +FirstPartySetsComponentInstallerPolicy::GetInstallerAttributes() const { + return update_client::InstallerAttributes(); +} + +std::vector<std::string> FirstPartySetsComponentInstallerPolicy::GetMimeTypes() + const { + return {}; +} + +void RegisterFirstPartySetsComponent(ComponentUpdateService* cus) { + if (!base::FeatureList::IsEnabled(network::features::kFirstPartySets)) + return; + VLOG(1) << "Registering First-Party Sets component."; + auto installer = base::MakeRefCounted<ComponentInstaller>( + std::make_unique<FirstPartySetsComponentInstallerPolicy>( + /*on_sets_ready=*/base::BindRepeating( + [](const std ::string& raw_sets) { + // TODO(cfredric): forward to NetworkService here. + VLOG(1) << "Received Sets: \"" << raw_sets << "\""; + }))); + installer->Register(cus, base::OnceClosure()); +} + +} // namespace component_updater
diff --git a/chrome/browser/component_updater/first_party_sets_component_installer.h b/chrome/browser/component_updater/first_party_sets_component_installer.h new file mode 100644 index 0000000..063334553 --- /dev/null +++ b/chrome/browser/component_updater/first_party_sets_component_installer.h
@@ -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. + +#ifndef CHROME_BROWSER_COMPONENT_UPDATER_FIRST_PARTY_SETS_COMPONENT_INSTALLER_H_ +#define CHROME_BROWSER_COMPONENT_UPDATER_FIRST_PARTY_SETS_COMPONENT_INSTALLER_H_ + +#include <stdint.h> + +#include <memory> +#include <string> +#include <vector> + +#include "base/callback.h" +#include "base/values.h" +#include "components/component_updater/component_installer.h" + +namespace base { +class FilePath; +} // namespace base + +namespace component_updater { + +class ComponentUpdateService; + +class FirstPartySetsComponentInstallerPolicy : public ComponentInstallerPolicy { + public: + // |on_sets_ready| will be called on the UI thread when the sets are ready. It + // is exposed here for testing. + explicit FirstPartySetsComponentInstallerPolicy( + base::RepeatingCallback<void(const std::string&)> on_sets_ready); + ~FirstPartySetsComponentInstallerPolicy() override; + + FirstPartySetsComponentInstallerPolicy( + const FirstPartySetsComponentInstallerPolicy&) = delete; + FirstPartySetsComponentInstallerPolicy operator=( + const FirstPartySetsComponentInstallerPolicy&) = delete; + + private: + FRIEND_TEST_ALL_PREFIXES(FirstPartySetsComponentInstallerTest, LoadsSets); + + // The following methods override ComponentInstallerPolicy. + bool SupportsGroupPolicyEnabledComponentUpdates() const override; + bool RequiresNetworkEncryption() const override; + update_client::CrxInstaller::Result OnCustomInstall( + const base::DictionaryValue& manifest, + const base::FilePath& install_dir) override; + void OnCustomUninstall() override; + bool VerifyInstallation(const base::DictionaryValue& manifest, + const base::FilePath& install_dir) const override; + void ComponentReady(const base::Version& version, + const base::FilePath& install_dir, + std::unique_ptr<base::DictionaryValue> manifest) override; + base::FilePath GetRelativeInstallDir() const override; + void GetHash(std::vector<uint8_t>* hash) const override; + std::string GetName() const override; + update_client::InstallerAttributes GetInstallerAttributes() const override; + std::vector<std::string> GetMimeTypes() const override; + + static base::FilePath GetInstalledPath(const base::FilePath& base); + + base::RepeatingCallback<void(const std::string&)> on_sets_ready_; +}; + +// Call once during startup to make the component update service aware of +// the First-Party Sets component. +void RegisterFirstPartySetsComponent(ComponentUpdateService* cus); + +} // namespace component_updater + +#endif // CHROME_BROWSER_COMPONENT_UPDATER_FIRST_PARTY_SETS_COMPONENT_INSTALLER_H_
diff --git a/chrome/browser/component_updater/first_party_sets_component_installer_unittest.cc b/chrome/browser/component_updater/first_party_sets_component_installer_unittest.cc new file mode 100644 index 0000000..97c4f072 --- /dev/null +++ b/chrome/browser/component_updater/first_party_sets_component_installer_unittest.cc
@@ -0,0 +1,77 @@ +// 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/component_updater/first_party_sets_component_installer.h" + +#include "base/files/file_util.h" +#include "base/files/scoped_temp_dir.h" +#include "base/run_loop.h" +#include "base/sequence_checker.h" +#include "base/test/bind_test_util.h" +#include "base/test/scoped_feature_list.h" +#include "base/test/task_environment.h" +#include "base/threading/thread_task_runner_handle.h" +#include "base/version.h" +#include "chrome/common/pref_names.h" +#include "chrome/test/base/testing_browser_process.h" +#include "components/component_updater/mock_component_updater_service.h" +#include "services/network/public/cpp/features.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace component_updater { + +namespace { +using ::testing::_; +} // namespace + +class FirstPartySetsComponentInstallerTest : public ::testing::Test { + public: + FirstPartySetsComponentInstallerTest() { + CHECK(component_install_dir_.CreateUniqueTempDir()); + } + + protected: + base::test::TaskEnvironment env_; + + base::ScopedTempDir component_install_dir_; +}; + +TEST_F(FirstPartySetsComponentInstallerTest, FeatureDisabled) { + base::test::ScopedFeatureList scoped_list; + scoped_list.InitAndDisableFeature(network::features::kFirstPartySets); + auto service = + std::make_unique<component_updater::MockComponentUpdateService>(); + EXPECT_CALL(*service, RegisterComponent(_)).Times(0); + RegisterFirstPartySetsComponent(service.get()); + + env_.RunUntilIdle(); +} + +TEST_F(FirstPartySetsComponentInstallerTest, LoadsSets) { + base::test::ScopedFeatureList scoped_list; + scoped_list.InitAndEnableFeature(network::features::kFirstPartySets); + + SEQUENCE_CHECKER(sequence_checker); + const std::string expectation = "some first party sets"; + base::RunLoop run_loop; + auto policy = std::make_unique<FirstPartySetsComponentInstallerPolicy>( + base::BindLambdaForTesting([&](const std::string& got) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker); + EXPECT_EQ(got, expectation); + run_loop.Quit(); + })); + + ASSERT_TRUE( + base::WriteFile(FirstPartySetsComponentInstallerPolicy::GetInstalledPath( + component_install_dir_.GetPath()), + expectation)); + + policy->ComponentReady(base::Version(), component_install_dir_.GetPath(), + std::make_unique<base::DictionaryValue>()); + + run_loop.Run(); +} + +} // namespace component_updater
diff --git a/chrome/browser/component_updater/origin_trials_component_installer.cc b/chrome/browser/component_updater/origin_trials_component_installer.cc index ae36148..dbac2b8 100644 --- a/chrome/browser/component_updater/origin_trials_component_installer.cc +++ b/chrome/browser/component_updater/origin_trials_component_installer.cc
@@ -146,8 +146,7 @@ return std::vector<std::string>(); } -void RegisterOriginTrialsComponent(ComponentUpdateService* cus, - const base::FilePath& user_data_dir) { +void RegisterOriginTrialsComponent(ComponentUpdateService* cus) { auto installer = base::MakeRefCounted<ComponentInstaller>( std::make_unique<OriginTrialsComponentInstallerPolicy>()); installer->Register(cus, base::OnceClosure());
diff --git a/chrome/browser/component_updater/origin_trials_component_installer.h b/chrome/browser/component_updater/origin_trials_component_installer.h index 81df45b2..03c059e 100644 --- a/chrome/browser/component_updater/origin_trials_component_installer.h +++ b/chrome/browser/component_updater/origin_trials_component_installer.h
@@ -49,8 +49,7 @@ // Call once during startup to make the component update service aware of // the origin trials update component. -void RegisterOriginTrialsComponent(ComponentUpdateService* cus, - const base::FilePath& user_data_dir); +void RegisterOriginTrialsComponent(ComponentUpdateService* cus); } // namespace component_updater
diff --git a/chrome/browser/component_updater/registration.cc b/chrome/browser/component_updater/registration.cc index d5d00c9..302cca1f3 100644 --- a/chrome/browser/component_updater/registration.cc +++ b/chrome/browser/component_updater/registration.cc
@@ -13,6 +13,7 @@ #include "chrome/browser/component_updater/crl_set_component_installer.h" #include "chrome/browser/component_updater/crowd_deny_component_installer.h" #include "chrome/browser/component_updater/file_type_policies_component_installer.h" +#include "chrome/browser/component_updater/first_party_sets_component_installer.h" #include "chrome/browser/component_updater/floc_blocklist_component_installer.h" #include "chrome/browser/component_updater/games_component_installer.h" #include "chrome/browser/component_updater/mei_preload_component_installer.h" @@ -126,6 +127,7 @@ cus, g_browser_process->GetApplicationLocale()); RegisterOptimizationHintsComponent(cus, is_off_the_record_profile); RegisterTrustTokenKeyCommitmentsComponentIfTrustTokensEnabled(cus); + RegisterFirstPartySetsComponent(cus); base::FilePath path; if (base::PathService::Get(chrome::DIR_USER_DATA, &path)) { @@ -140,8 +142,6 @@ // Chrome OS: On Chrome OS, this cleanup is delayed until user login. component_updater::DeleteLegacySTHSet(path); #endif - - RegisterOriginTrialsComponent(cus, path); } RegisterSSLErrorAssistantComponent(cus); RegisterFileTypePoliciesComponent(cus); @@ -152,6 +152,7 @@ component_updater::RegisterCRLSetComponent(cus); #endif // !defined(OS_CHROMEOS) + RegisterOriginTrialsComponent(cus); RegisterMediaEngagementPreloadComponent(cus, base::OnceClosure()); #if defined(OS_WIN)
diff --git a/chrome/browser/devtools/devtools_sanity_browsertest.cc b/chrome/browser/devtools/devtools_sanity_browsertest.cc index e85be3f..c997b14b 100644 --- a/chrome/browser/devtools/devtools_sanity_browsertest.cc +++ b/chrome/browser/devtools/devtools_sanity_browsertest.cc
@@ -29,6 +29,7 @@ #include "base/threading/thread_restrictions.h" #include "base/threading/thread_task_runner_handle.h" #include "build/build_config.h" +#include "chrome/browser/browser_process.h" #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/devtools/device/tcp_device_provider.h" #include "chrome/browser/devtools/devtools_window_testing.h" @@ -66,6 +67,7 @@ #include "components/javascript_dialogs/app_modal_dialog_view.h" #include "components/keep_alive_registry/keep_alive_registry.h" #include "components/keep_alive_registry/keep_alive_types.h" +#include "components/language/core/browser/pref_names.h" #include "components/policy/core/common/mock_configuration_policy_provider.h" #include "components/policy/core/common/policy_map.h" #include "components/policy/policy_constants.h" @@ -2578,24 +2580,53 @@ CloseDevToolsWindow(); } +namespace { + class DevToolsLocalizationTest : public DevToolsSanityTest { - void SetUpCommandLine(base::CommandLine* command_line) override { - command_line->AppendSwitchASCII(switches::kLang, "es-ES"); + public: + bool NavigatorLanguageMatches(const std::string& expected_locale) { + bool result = false; + const bool execute_result = content::ExecuteScriptAndExtractBool( + main_web_contents(), + "window.domAutomationController.send(window.navigator.language === " + "'" + + expected_locale + "')", + &result); + return execute_result && result; } }; -// Make it run on Windows only since the browser language on Mac -// is tied to the OS language and --lang flag won't work -#if defined(OS_WIN) -IN_PROC_BROWSER_TEST_F(DevToolsLocalizationTest, testNavigatorLanguage) { - bool result = false; - OpenDevToolsWindow("about:blank", true); - ASSERT_TRUE(content::ExecuteScriptAndExtractBool( - main_web_contents(), - "window.domAutomationController.send(window.navigator.language === " - "'es-ES')", - &result)); - EXPECT_TRUE(result); +} // namespace + +IN_PROC_BROWSER_TEST_F(DevToolsLocalizationTest, + NavigatorLanguageMatchesApplicationLocaleDocked) { + g_browser_process->SetApplicationLocale("es"); + + OpenDevToolsWindow("about:blank", /* is_docked */ true); + EXPECT_TRUE(NavigatorLanguageMatches("es")); CloseDevToolsWindow(); } -#endif // defined(OS_WIN) + +IN_PROC_BROWSER_TEST_F(DevToolsLocalizationTest, + NavigatorLanguageMatchesApplicationLocaleUndocked) { + g_browser_process->SetApplicationLocale("es"); + + OpenDevToolsWindow("about:blank", /* is_docked */ false); + EXPECT_TRUE(NavigatorLanguageMatches("es")); + CloseDevToolsWindow(); +} + +IN_PROC_BROWSER_TEST_F(DevToolsLocalizationTest, + AcceptedLanguageChangesWhileDevToolsIsOpen) { + g_browser_process->SetApplicationLocale("es"); + + OpenDevToolsWindow("about:blank", true); + EXPECT_TRUE(NavigatorLanguageMatches("es")); + + PrefService* prefs = browser()->profile()->GetPrefs(); + prefs->SetString(language::prefs::kAcceptLanguages, "de-DE"); + + EXPECT_TRUE(NavigatorLanguageMatches("es")); + + CloseDevToolsWindow(); +}
diff --git a/chrome/browser/devtools/devtools_ui_bindings.cc b/chrome/browser/devtools/devtools_ui_bindings.cc index 441559ec..e457463 100644 --- a/chrome/browser/devtools/devtools_ui_bindings.cc +++ b/chrome/browser/devtools/devtools_ui_bindings.cc
@@ -130,6 +130,10 @@ "DevTools.ColorPicker.FixedColor"; static const char kDevToolsComputedStyleGroupingHistogram[] = "DevTools.ComputedStyleGrouping"; +static const char kDevtoolsIssuesPanelIssueExpandedHistogram[] = + "DevTools.IssuesPanelIssueExpanded"; +static const char kDevtoolsIssuesPanelResourceOpenedHistogram[] = + "DevTools.IssuesPanelResourceOpened"; static const char kRemotePageActionInspect[] = "inspect"; static const char kRemotePageActionReload[] = "reload"; @@ -677,9 +681,6 @@ frontend_loaded_(false) { g_devtools_ui_bindings_instances.Get().push_back(this); frontend_contents_observer_.reset(new FrontendWebContentsObserver(this)); - web_contents_->GetMutableRendererPrefs()->can_accept_load_drops = false; - web_contents_->GetMutableRendererPrefs()->accept_languages = - g_browser_process->GetApplicationLocale(); file_helper_.reset(new DevToolsFileHelper(web_contents_, profile_, this)); file_system_indexer_ = new DevToolsFileSystemIndexer(); @@ -1311,6 +1312,10 @@ base::UmaHistogramExactLinear(name, sample, boundary_value); else if (name == kDevToolsComputedStyleGroupingHistogram) base::UmaHistogramExactLinear(name, sample, boundary_value); + else if (name == kDevtoolsIssuesPanelIssueExpandedHistogram) + base::UmaHistogramExactLinear(name, sample, boundary_value); + else if (name == kDevtoolsIssuesPanelResourceOpenedHistogram) + base::UmaHistogramExactLinear(name, sample, boundary_value); else frontend_host_->BadMessageRecieved(); }
diff --git a/chrome/browser/devtools/devtools_window.cc b/chrome/browser/devtools/devtools_window.cc index ec271f2f..fc368fb 100644 --- a/chrome/browser/devtools/devtools_window.cc +++ b/chrome/browser/devtools/devtools_window.cc
@@ -17,6 +17,7 @@ #include "base/metrics/user_metrics.h" #include "base/time/time.h" #include "base/values.h" +#include "chrome/browser/browser_process.h" #include "chrome/browser/certificate_viewer.h" #include "chrome/browser/devtools/chrome_devtools_manager_delegate.h" #include "chrome/browser/devtools/devtools_eye_dropper.h" @@ -39,6 +40,7 @@ #include "components/javascript_dialogs/app_modal_dialog_manager.h" #include "components/keep_alive_registry/keep_alive_types.h" #include "components/keep_alive_registry/scoped_keep_alive.h" +#include "components/language/core/browser/pref_names.h" #include "components/pref_registry/pref_registry_syncable.h" #include "components/prefs/scoped_user_pref_update.h" #include "components/sessions/content/session_tab_helper.h" @@ -66,6 +68,7 @@ #include "net/base/escape.h" #include "third_party/blink/public/common/input/web_gesture_event.h" #include "third_party/blink/public/common/input/web_input_event.h" +#include "third_party/blink/public/mojom/renderer_preferences.mojom.h" #include "third_party/blink/public/public_buildflags.h" #include "ui/base/page_transition_types.h" #include "ui/events/keycodes/dom/keycode_converter.h" @@ -860,7 +863,7 @@ main_web_contents_->SetInitialFocus(); PrefsTabHelper::CreateForWebContents(main_web_contents_); - main_web_contents_->SyncRendererPrefs(); + OverrideAndSyncDevToolsRendererPrefs(); DoAction(action); return; @@ -1021,6 +1024,12 @@ g_creation_callbacks.Get()); for (const auto& callback : copy) callback.Run(this); + + pref_change_registrar_.Init(profile_->GetPrefs()); + pref_change_registrar_.Add( + language::prefs::kAcceptLanguages, + base::BindRepeating(&DevToolsWindow::OnLocaleChanged, + base::Unretained(this))); } // static @@ -1579,7 +1588,7 @@ OwnedMainWebContents::TakeWebContents( std::move(owned_main_web_contents_)), -1, ui::PAGE_TRANSITION_AUTO_TOPLEVEL, TabStripModel::ADD_ACTIVE); - main_web_contents_->SyncRendererPrefs(); + OverrideAndSyncDevToolsRendererPrefs(); } BrowserWindow* DevToolsWindow::GetInspectedBrowserWindow() { @@ -1681,3 +1690,14 @@ void DevToolsWindow::OnReattachMainTargetComplete(base::Value) { std::move(reattach_complete_callback_).Run(); } + +void DevToolsWindow::OnLocaleChanged() { + OverrideAndSyncDevToolsRendererPrefs(); +} + +void DevToolsWindow::OverrideAndSyncDevToolsRendererPrefs() { + main_web_contents_->GetMutableRendererPrefs()->can_accept_load_drops = false; + main_web_contents_->GetMutableRendererPrefs()->accept_languages = + g_browser_process->GetApplicationLocale(); + main_web_contents_->SyncRendererPrefs(); +}
diff --git a/chrome/browser/devtools/devtools_window.h b/chrome/browser/devtools/devtools_window.h index 5149147..2d481b5 100644 --- a/chrome/browser/devtools/devtools_window.h +++ b/chrome/browser/devtools/devtools_window.h
@@ -384,6 +384,15 @@ void OnReattachMainTargetComplete(base::Value); + // Called when the accepted language changes. |navigator.language| of the + // DevTools window should match the application language. When the user + // changes the accepted language then this listener flips the language back + // to the application language for the DevTools renderer process. + // Please note that |navigator.language| will have the wrong language for + // a very short period of time (until this handler has reset it again). + void OnLocaleChanged(); + void OverrideAndSyncDevToolsRendererPrefs(); + std::unique_ptr<ObserverWithAccessor> inspected_contents_observer_; FrontendType frontend_type_; @@ -432,6 +441,8 @@ base::OnceCallback<void()> reattach_complete_callback_; + PrefChangeRegistrar pref_change_registrar_; + friend class DevToolsEventForwarder; DISALLOW_COPY_AND_ASSIGN(DevToolsWindow); };
diff --git a/chrome/browser/download/save_page_browsertest.cc b/chrome/browser/download/save_page_browsertest.cc index 51f9d39f..1450ce297 100644 --- a/chrome/browser/download/save_page_browsertest.cc +++ b/chrome/browser/download/save_page_browsertest.cc
@@ -535,8 +535,7 @@ }; // Disabled on multiple platforms due to flakiness. crbug.com/580766 -#if defined(OS_CHROMEOS) || \ - (defined(OS_WIN) || defined(OS_LINUX)) && defined(NDEBUG) +#if defined(OS_CHROMEOS) || defined(OS_WIN) || defined(OS_LINUX) #define MAYBE_SaveHTMLOnlyTabDestroy DISABLED_SaveHTMLOnlyTabDestroy #else #define MAYBE_SaveHTMLOnlyTabDestroy SaveHTMLOnlyTabDestroy
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 a442f53..7ffbb997 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
@@ -216,8 +216,6 @@ public: PasswordCheckDelegateTest() { prefs_.registry()->RegisterDoublePref(kLastTimePasswordCheckCompleted, 0.0); - scoped_feature_list_.InitAndEnableFeature( - password_manager::features::kPasswordCheck); } void RunUntilIdle() { task_env_.RunUntilIdle(); } @@ -232,13 +230,8 @@ PasswordCheckDelegate& delegate() { return delegate_; } void EnableWellKnownChangePasswordFeatureFlag() { - scoped_feature_list_.Reset(); - scoped_feature_list_.InitWithFeatures( - { - password_manager::features::kPasswordCheck, - password_manager::features::kWellKnownChangePassword, - }, - {}); + scoped_feature_list_.InitAndEnableFeature( + password_manager::features::kWellKnownChangePassword); } private:
diff --git a/chrome/browser/extensions/extension_management.cc b/chrome/browser/extensions/extension_management.cc index c6a79618..4530035 100644 --- a/chrome/browser/extensions/extension_management.cc +++ b/chrome/browser/extensions/extension_management.cc
@@ -502,6 +502,8 @@ continue; } internal::IndividualSettings* by_id = AccessById(extension_id); + const bool included_in_forcelist = + by_id->installation_mode == InstallationMode::INSTALLATION_FORCED; if (!by_id->Parse(subdict, internal::IndividualSettings::SCOPE_INDIVIDUAL)) { settings_by_id_.erase(extension_id); @@ -511,6 +513,16 @@ SYSLOG(WARNING) << "Malformed Extension Management settings for " << extension_id << "."; } + // If applying the ExtensionSettings policy changes installation mode + // from force-installed to anything else, the extension might not get + // installed and will get stuck in CREATED stage. + if (included_in_forcelist && + by_id->installation_mode != + InstallationMode::INSTALLATION_FORCED) { + install_stage_tracker->ReportFailure( + extension_id, + InstallStageTracker::FailureReason::OVERRIDDEN_BY_SETTINGS); + } } } }
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 bf585a2..e3a2d3e6 100644 --- a/chrome/browser/extensions/forced_extensions/force_installed_metrics_unittest.cc +++ b/chrome/browser/extensions/forced_extensions/force_installed_metrics_unittest.cc
@@ -193,6 +193,18 @@ base::RunLoop().RunUntilIdle(); } + void SetupExtensionManagementPref() { + std::unique_ptr<base::DictionaryValue> extension_entry = + DictionaryBuilder() + .Set("installation_mode", "allowed") + .Set(ExternalProviderImpl::kExternalUpdateUrl, kExtensionUpdateUrl) + .Build(); + prefs_->SetManagedPref(pref_names::kExtensionManagement, + DictionaryBuilder() + .Set(kExtensionId1, std::move(extension_entry)) + .Build()); + } + void SetupEmptyForceList() { std::unique_ptr<base::Value> dict = DictionaryBuilder().Build(); prefs_->SetManagedPref(pref_names::kInstallForceList, std::move(dict)); @@ -299,6 +311,23 @@ EXPECT_EQ(1u, ready_call_count_); } +// Verifies that failure is reported for the extensions which are listed in +// forced list, and their installation mode are overridden by ExtensionSettings +// policy to something else. +TEST_F(ForceInstalledMetricsTest, ExtensionSettingsOverrideForcedList) { + SetupForceList(); + SetupExtensionManagementPref(); + auto ext2 = ExtensionBuilder(kExtensionName2).SetID(kExtensionId2).Build(); + tracker_->OnExtensionLoaded(profile_, ext2.get()); + // ForceInstalledMetrics shuts down timer because all extension are either + // loaded or failed. + EXPECT_FALSE(fake_timer_->IsRunning()); + EXPECT_EQ(1u, loaded_call_count_); + histogram_tester_.ExpectBucketCount( + kFailureReasonsCWS, + InstallStageTracker::FailureReason::OVERRIDDEN_BY_SETTINGS, 1); +} + TEST_F(ForceInstalledMetricsTest, ObserversOnlyCalledOnce) { // Start with a non-empty force-list, and install them, which triggers // observer.
diff --git a/chrome/browser/extensions/forced_extensions/install_stage_tracker.h b/chrome/browser/extensions/forced_extensions/install_stage_tracker.h index 6a3878d1..84424e7 100644 --- a/chrome/browser/extensions/forced_extensions/install_stage_tracker.h +++ b/chrome/browser/extensions/forced_extensions/install_stage_tracker.h
@@ -184,9 +184,13 @@ // The download of the crx failed. CRX_FETCH_URL_INVALID = 26, + // Applying the ExtensionSettings policy changed installation mode from + // force-installed to anything else. + OVERRIDDEN_BY_SETTINGS = 27, + // Magic constant used by the histogram macros. // Always update it to the max value. - kMaxValue = CRX_FETCH_URL_INVALID, + kMaxValue = OVERRIDDEN_BY_SETTINGS, }; // Status for the app returned by server while fetching manifest when status
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json index da69301..09c70413 100644 --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json
@@ -4563,6 +4563,12 @@ "expiry_milestone": -1 }, { + "name": "use-wallpaper-staging-url", + "owners": [ "cros-customization@google.com", "hsuregan", "khorimoto" ], + // This flag is required for QA and dogfood testing. + "expiry_milestone": -1 + }, + { "name": "use-winrt-midi-api", "owners": [ "toyoshim" ], "expiry_milestone": 86
diff --git a/chrome/browser/flag-never-expire-list.json b/chrome/browser/flag-never-expire-list.json index 1f476ec0..9def851e 100644 --- a/chrome/browser/flag-never-expire-list.json +++ b/chrome/browser/flag-never-expire-list.json
@@ -95,6 +95,7 @@ "use-fake-device-for-media-stream", "use_messages_staging_url", "use-sync-sandbox", + "use-wallpaper-staging-url", "wallet-service-use-sandbox", "webxr-runtime" ]
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index c5f0c535..221ba13 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -156,6 +156,11 @@ "Use lookalike URL suggestions to suggest navigations to users who " "face domain not found error."; +const char kUseWallpaperStagingUrlName[] = "Use Wallpaper staging URL"; +const char kUseWallpaperStagingUrlDescription[] = + "Use the staging server as part of the Wallpaper App to verify " + "additions/removals of wallpapers."; + const char kUseMessagesStagingUrlName[] = "Use Messages staging URL"; const char kUseMessagesStagingUrlDescription[] = "Use the staging server as part of the \"Messages\" feature under "
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index 3744848..627bfd0 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -114,6 +114,9 @@ extern const char kUseLookalikesForNavigationSuggestionsName[]; extern const char kUseLookalikesForNavigationSuggestionsDescription[]; +extern const char kUseWallpaperStagingUrlName[]; +extern const char kUseWallpaperStagingUrlDescription[]; + extern const char kUseMessagesStagingUrlName[]; extern const char kUseMessagesStagingUrlDescription[];
diff --git a/chrome/browser/nearby_sharing/certificates/nearby_share_certificate_manager.cc b/chrome/browser/nearby_sharing/certificates/nearby_share_certificate_manager.cc index 109c3d3..2b0524f 100644 --- a/chrome/browser/nearby_sharing/certificates/nearby_share_certificate_manager.cc +++ b/chrome/browser/nearby_sharing/certificates/nearby_share_certificate_manager.cc
@@ -17,13 +17,17 @@ } void NearbyShareCertificateManager::Start() { - DCHECK(!is_running_); + if (is_running_) + return; + is_running_ = true; OnStart(); } void NearbyShareCertificateManager::Stop() { - DCHECK(is_running_); + if (!is_running_) + return; + is_running_ = false; OnStop(); }
diff --git a/chrome/browser/nearby_sharing/contacts/nearby_share_contact_manager.cc b/chrome/browser/nearby_sharing/contacts/nearby_share_contact_manager.cc index 02be5f0..941e1b7 100644 --- a/chrome/browser/nearby_sharing/contacts/nearby_share_contact_manager.cc +++ b/chrome/browser/nearby_sharing/contacts/nearby_share_contact_manager.cc
@@ -17,13 +17,17 @@ } void NearbyShareContactManager::Start() { - DCHECK(!is_running_); + if (is_running_) + return; + is_running_ = true; OnStart(); } void NearbyShareContactManager::Stop() { - DCHECK(is_running_); + if (!is_running_) + return; + is_running_ = false; OnStop(); }
diff --git a/chrome/browser/nearby_sharing/contacts/nearby_share_contact_manager_impl.cc b/chrome/browser/nearby_sharing/contacts/nearby_share_contact_manager_impl.cc index 56211c48..7a84f36 100644 --- a/chrome/browser/nearby_sharing/contacts/nearby_share_contact_manager_impl.cc +++ b/chrome/browser/nearby_sharing/contacts/nearby_share_contact_manager_impl.cc
@@ -13,6 +13,7 @@ #include "chrome/browser/nearby_sharing/contacts/nearby_share_contact_downloader.h" #include "chrome/browser/nearby_sharing/contacts/nearby_share_contact_downloader_impl.h" #include "chrome/browser/nearby_sharing/local_device_data/nearby_share_local_device_data_manager.h" +#include "chrome/browser/nearby_sharing/logging/logging.h" #include "chrome/browser/nearby_sharing/proto/device_rpc.pb.h" #include "chrome/browser/nearby_sharing/proto/rpc_resources.pb.h" #include "chrome/browser/nearby_sharing/scheduling/nearby_share_scheduler.h" @@ -151,6 +152,8 @@ } void NearbyShareContactManagerImpl::OnContactsDownloadRequested() { + NS_LOG(VERBOSE) << __func__ << ": Nearby Share contacts download requested."; + DCHECK(!contact_downloader_); contact_downloader_ = NearbyShareContactDownloaderImpl::Factory::Create( only_download_if_changed_, local_device_data_manager_->GetId(), @@ -167,6 +170,13 @@ base::Optional<std::vector<nearbyshare::proto::ContactRecord>> contacts) { contact_downloader_.reset(); + NS_LOG(VERBOSE) << __func__ << ": Nearby Share contacts download succeeded." + << "\n Did contacts change since last upload? " + << (did_contacts_change_since_last_upload ? "Yes." : "No.") + << "\n Were contacts returned? " + << (contacts.has_value() ? "Yes." : "No.") + << "\n Number of contacts returned: " + << (contacts.has_value() ? contacts->size() : 0u); if (contacts) { // A complete list of contacts was returned. Do not download list again // until contacts change or until explicitly requested. @@ -217,9 +227,13 @@ void NearbyShareContactManagerImpl::OnContactsUploadRequested() { DCHECK_EQ(UploadState::kIdle, upload_state_); + NS_LOG(VERBOSE) << __func__ + << ": Nearby Share contact upload requested. Waiting to " + << "download full contact list."; + // Because the user's contact list is not persisted locally, we have to - // retrieve the full contact list ContactRecord protos from the server before - // uploading the list of Contact protos to the server. + // retrieve the full contact list ContactRecord protos from the server + // before uploading the list of Contact protos to the server. upload_state_ = UploadState::kWaitingForDownload; DownloadContacts(/*only_download_if_changed=*/false); } @@ -227,6 +241,8 @@ void NearbyShareContactManagerImpl::StartContactsUpload( bool did_contacts_change_since_last_upload, const std::vector<nearbyshare::proto::ContactRecord>& contacts) { + NS_LOG(VERBOSE) << __func__ + << ": Starting contacts upload to Nearby Share server."; upload_state_ = UploadState::kInProgress; local_device_data_manager_->UploadContacts( ContactRecordsToContacts(GetAllowedContacts(), contacts), @@ -238,6 +254,10 @@ void NearbyShareContactManagerImpl::OnContactsUploadFinished( bool did_contacts_change_since_last_upload, bool success) { + NS_LOG(VERBOSE) << __func__ << ": Upload of contacts to Nearby Share server " + << (success ? "succeeded." : "failed.") + << " Did contacts change since last upload? " + << (did_contacts_change_since_last_upload ? "Yes." : "No."); if (success) { NotifyContactsUploaded(did_contacts_change_since_last_upload); }
diff --git a/chrome/browser/nearby_sharing/local_device_data/nearby_share_local_device_data_manager.cc b/chrome/browser/nearby_sharing/local_device_data/nearby_share_local_device_data_manager.cc index 871f797b..5e457d9 100644 --- a/chrome/browser/nearby_sharing/local_device_data/nearby_share_local_device_data_manager.cc +++ b/chrome/browser/nearby_sharing/local_device_data/nearby_share_local_device_data_manager.cc
@@ -19,13 +19,17 @@ } void NearbyShareLocalDeviceDataManager::Start() { - DCHECK(!is_running_); + if (is_running_) + return; + is_running_ = true; OnStart(); } void NearbyShareLocalDeviceDataManager::Stop() { - DCHECK(is_running_); + if (!is_running_) + return; + is_running_ = false; OnStop(); }
diff --git a/chrome/browser/nearby_sharing/nearby_sharing_service_impl.cc b/chrome/browser/nearby_sharing/nearby_sharing_service_impl.cc index f66f0609..d0b87ff 100644 --- a/chrome/browser/nearby_sharing/nearby_sharing_service_impl.cc +++ b/chrome/browser/nearby_sharing/nearby_sharing_service_impl.cc
@@ -237,6 +237,12 @@ nearby_notification_manager_ = std::make_unique<NearbyNotificationManager>( notification_display_service, this, prefs, profile_); + + if (settings_.GetEnabled()) { + local_device_data_manager_->Start(); + contact_manager_->Start(); + certificate_manager_->Start(); + } } NearbySharingServiceImpl::~NearbySharingServiceImpl() { @@ -287,6 +293,12 @@ settings_receiver_.reset(); + if (settings_.GetEnabled()) { + local_device_data_manager_->Stop(); + contact_manager_->Stop(); + certificate_manager_->Stop(); + } + // |profile_| has now been shut down so we shouldn't use it anymore. profile_ = nullptr; } @@ -789,11 +801,17 @@ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (enabled) { NS_LOG(VERBOSE) << __func__ << ": Nearby sharing enabled!"; + local_device_data_manager_->Start(); + contact_manager_->Start(); + certificate_manager_->Start(); } else { NS_LOG(VERBOSE) << __func__ << ": Nearby sharing disabled!"; StopAdvertising(); StopScanning(); nearby_connections_manager_->Shutdown(); + local_device_data_manager_->Stop(); + contact_manager_->Stop(); + certificate_manager_->Stop(); } InvalidateSurfaceState(); }
diff --git a/chrome/browser/nearby_sharing/scheduling/BUILD.gn b/chrome/browser/nearby_sharing/scheduling/BUILD.gn index 375d81ca..7055ef73 100644 --- a/chrome/browser/nearby_sharing/scheduling/BUILD.gn +++ b/chrome/browser/nearby_sharing/scheduling/BUILD.gn
@@ -21,6 +21,7 @@ deps = [ "//base", "//base/util/values:values_util", + "//chrome/browser/nearby_sharing/logging", "//components/prefs", "//content/public/browser", "//services/network/public/cpp",
diff --git a/chrome/browser/nearby_sharing/scheduling/nearby_share_scheduler_base.cc b/chrome/browser/nearby_sharing/scheduling/nearby_share_scheduler_base.cc index db320b9..c500349 100644 --- a/chrome/browser/nearby_sharing/scheduling/nearby_share_scheduler_base.cc +++ b/chrome/browser/nearby_sharing/scheduling/nearby_share_scheduler_base.cc
@@ -5,12 +5,15 @@ #include "chrome/browser/nearby_sharing/scheduling/nearby_share_scheduler_base.h" #include <algorithm> +#include <sstream> #include <utility> +#include "base/i18n/time_formatting.h" #include "base/numerics/clamped_math.h" #include "base/strings/string_number_conversions.h" #include "base/time/clock.h" #include "base/util/values/values_util.h" +#include "chrome/browser/nearby_sharing/logging/logging.h" #include "components/prefs/pref_service.h" #include "components/prefs/scoped_user_pref_update.h" #include "content/public/browser/network_service_instance.h" @@ -67,6 +70,9 @@ base::Time now = clock_->Now(); SetLastAttemptTime(now); + NS_LOG(VERBOSE) << "Nearby Share scheduler \"" << pref_name_ + << "\" latest attempt " << (success ? "succeeded" : "failed"); + if (success) { SetLastSuccessTime(now); SetNumConsecutiveFailures(0); @@ -76,6 +82,7 @@ SetIsWaitingForResult(false); Reschedule(); + PrintSchedulerState(); } void NearbyShareSchedulerBase::Reschedule() { @@ -139,6 +146,8 @@ void NearbyShareSchedulerBase::OnStart() { Reschedule(); + NS_LOG(VERBOSE) << "Starting Nearby Share scheduler \"" << pref_name_ << "\""; + PrintSchedulerState(); } void NearbyShareSchedulerBase::OnStop() { @@ -241,3 +250,46 @@ SetHasPendingImmediateRequest(false); NotifyOfRequest(); } + +void NearbyShareSchedulerBase::PrintSchedulerState() const { + base::Optional<base::Time> last_attempt_time = GetLastAttemptTime(); + base::Optional<base::Time> last_success_time = GetLastSuccessTime(); + base::Optional<base::TimeDelta> time_until_next_request = + GetTimeUntilNextRequest(); + + std::stringstream ss; + ss << "State of Nearby Share scheduler \"" << pref_name_ << "\":" + << "\n Last attempt time: "; + if (last_attempt_time) { + ss << base::TimeFormatShortDateAndTimeWithTimeZone(*last_attempt_time); + } else { + ss << "Never"; + } + + ss << "\n Last success time: "; + if (last_success_time) { + ss << base::TimeFormatShortDateAndTimeWithTimeZone(*last_success_time); + } else { + ss << "Never"; + } + + ss << "\n Time until next request: "; + if (time_until_next_request) { + base::string16 next_request_delay; + bool success = base::TimeDurationFormatWithSeconds( + *time_until_next_request, + base::DurationFormatWidth::DURATION_WIDTH_NARROW, &next_request_delay); + if (success) { + ss << next_request_delay; + } + } else { + ss << "Never"; + } + + ss << "\n Is waiting for result? " << (IsWaitingForResult() ? "Yes" : "No"); + ss << "\n Pending immediate request? " + << (HasPendingImmediateRequest() ? "Yes" : "No"); + ss << "\n Num consecutive failures: " << GetNumConsecutiveFailures(); + + NS_LOG(VERBOSE) << ss.str(); +}
diff --git a/chrome/browser/nearby_sharing/scheduling/nearby_share_scheduler_base.h b/chrome/browser/nearby_sharing/scheduling/nearby_share_scheduler_base.h index cc3bdc36..065239a 100644 --- a/chrome/browser/nearby_sharing/scheduling/nearby_share_scheduler_base.h +++ b/chrome/browser/nearby_sharing/scheduling/nearby_share_scheduler_base.h
@@ -101,6 +101,8 @@ // connectivity is restored. void OnTimerFired(); + void PrintSchedulerState() const; + bool retry_failures_; bool require_connectivity_; std::string pref_name_;
diff --git a/chrome/browser/page_load_metrics/observers/ad_metrics/ads_page_load_metrics_observer_browsertest.cc b/chrome/browser/page_load_metrics/observers/ad_metrics/ads_page_load_metrics_observer_browsertest.cc index 72f4cce..9076e58 100644 --- a/chrome/browser/page_load_metrics/observers/ad_metrics/ads_page_load_metrics_observer_browsertest.cc +++ b/chrome/browser/page_load_metrics/observers/ad_metrics/ads_page_load_metrics_observer_browsertest.cc
@@ -433,7 +433,7 @@ PageAdDensityIgnoreDisplayNoneFrame #endif IN_PROC_BROWSER_TEST_F(AdsPageLoadMetricsObserverBrowserTest, - PageAdDensityIgnoreDisplayNoneFrame) { + MAYBE_PageAdDensityIgnoreDisplayNoneFrame) { base::HistogramTester histogram_tester; ukm::TestAutoSetUkmRecorder ukm_recorder; auto waiter = CreatePageLoadMetricsTestWaiter();
diff --git a/chrome/browser/page_load_metrics/observers/ukm_page_load_metrics_observer.cc b/chrome/browser/page_load_metrics/observers/ukm_page_load_metrics_observer.cc index 39bbf3d..f8e3c20e 100644 --- a/chrome/browser/page_load_metrics/observers/ukm_page_load_metrics_observer.cc +++ b/chrome/browser/page_load_metrics/observers/ukm_page_load_metrics_observer.cc
@@ -99,21 +99,6 @@ return data; } -int8_t ComputeMedianForThroughput(const base::flat_map<int8_t, int>& data) { - int total_samples = 0; - for (const auto& e : data) - total_samples += e.second; - int half_samples = total_samples / 2; - int current_samples = 0; - for (const auto& e : data) { - current_samples += e.second; - if (current_samples > half_samples) - return e.first; - } - NOTREACHED(); - return 0; -} - bool ValidatePercent(int8_t percent) { if (percent >= 0 && percent <= 100) return true; @@ -612,9 +597,6 @@ ReportMainResourceTimingMetrics(timing, &builder); builder.Record(ukm::UkmRecorder::Get()); - - if (throughput_source_id_ != ukm::kInvalidSourceId) - ReportThroughputUkm(); } void UkmPageLoadMetricsObserver::RecordInternalTimingMetrics( @@ -1038,29 +1020,6 @@ ++main_throughput_data_[main_throughput_percent->percent]; } -void UkmPageLoadMetricsObserver::ReportThroughputUkm() { - DCHECK_NE(throughput_source_id_, ukm::kInvalidSourceId); - - ukm::builders::Graphics_Smoothness_PercentDroppedFrames builder( - throughput_source_id_); - if (aggregated_throughput_data_.size() > 0) { - builder.SetSlowerThread_Universal( - ComputeMedianForThroughput(aggregated_throughput_data_)); - aggregated_throughput_data_.clear(); - } - if (impl_throughput_data_.size() > 0) { - builder.SetCompositorThread_Universal( - ComputeMedianForThroughput(impl_throughput_data_)); - impl_throughput_data_.clear(); - } - if (main_throughput_data_.size() > 0) { - builder.SetMainThread_Universal( - ComputeMedianForThroughput(main_throughput_data_)); - main_throughput_data_.clear(); - } - builder.Record(ukm::UkmRecorder::Get()); -} - void UkmPageLoadMetricsObserver::OnCpuTimingUpdate( content::RenderFrameHost* subframe_rfh, const page_load_metrics::mojom::CpuTiming& timing) {
diff --git a/chrome/browser/page_load_metrics/observers/ukm_page_load_metrics_observer.h b/chrome/browser/page_load_metrics/observers/ukm_page_load_metrics_observer.h index c42eafa7..952045e 100644 --- a/chrome/browser/page_load_metrics/observers/ukm_page_load_metrics_observer.h +++ b/chrome/browser/page_load_metrics/observers/ukm_page_load_metrics_observer.h
@@ -149,9 +149,6 @@ void RecordInputTimingMetrics(); - // Report throughput to Ukm. - void ReportThroughputUkm(); - // Captures the site engagement score for the committed URL and // returns the score rounded to the nearest 10. base::Optional<int64_t> GetRoundedSiteEngagementScore() const;
diff --git a/chrome/browser/paint_preview/android/BUILD.gn b/chrome/browser/paint_preview/android/BUILD.gn index a3d2cf39..2c6db38 100644 --- a/chrome/browser/paint_preview/android/BUILD.gn +++ b/chrome/browser/paint_preview/android/BUILD.gn
@@ -25,14 +25,12 @@ "java/src/org/chromium/chrome/browser/paint_preview/services/PaintPreviewDemoServiceFactory.java", "java/src/org/chromium/chrome/browser/paint_preview/services/PaintPreviewTabService.java", "java/src/org/chromium/chrome/browser/paint_preview/services/PaintPreviewTabServiceFactory.java", - "java/src/org/chromium/chrome/browser/paint_preview/services/PaintPreviewTabServiceNativeInitObserver.java", ] deps = [ ":java_resources", "//base:base_java", "//base:jni_java", - "//chrome/browser/android/lifecycle:java", "//chrome/browser/flags:java", "//chrome/browser/tab:java", "//chrome/browser/tabmodel:java",
diff --git a/chrome/browser/paint_preview/android/java/src/org/chromium/chrome/browser/paint_preview/TabbedPaintPreviewPlayer.java b/chrome/browser/paint_preview/android/java/src/org/chromium/chrome/browser/paint_preview/TabbedPaintPreviewPlayer.java index f55de96..019a157 100644 --- a/chrome/browser/paint_preview/android/java/src/org/chromium/chrome/browser/paint_preview/TabbedPaintPreviewPlayer.java +++ b/chrome/browser/paint_preview/android/java/src/org/chromium/chrome/browser/paint_preview/TabbedPaintPreviewPlayer.java
@@ -153,10 +153,7 @@ boolean hasCapture = mPaintPreviewTabService.hasCaptureForTab(mTab.getId()); mInitializing = hasCapture; mMetricsHelper.recordHadCapture(hasCapture); - if (!hasCapture) { - mPaintPreviewTabService.stopWarmCompositor(); - return false; - } + if (!hasCapture) return false; mFirstMeaningfulPaintHappened = false; mPlayerManager = new PlayerManager(mTab.getUrl(), mTab.getContext(), @@ -190,7 +187,6 @@ * nothing if there is no view showing. */ private void removePaintPreview(@ExitCause int exitCause) { - mPaintPreviewTabService.stopWarmCompositor(); mOnDismissed = null; mInitializing = false; if (mTab == null || mPlayerManager == null) return;
diff --git a/chrome/browser/paint_preview/android/java/src/org/chromium/chrome/browser/paint_preview/services/PaintPreviewTabService.java b/chrome/browser/paint_preview/android/java/src/org/chromium/chrome/browser/paint_preview/services/PaintPreviewTabService.java index afdabe0..a4ffdebd 100644 --- a/chrome/browser/paint_preview/android/java/src/org/chromium/chrome/browser/paint_preview/services/PaintPreviewTabService.java +++ b/chrome/browser/paint_preview/android/java/src/org/chromium/chrome/browser/paint_preview/services/PaintPreviewTabService.java
@@ -116,17 +116,6 @@ } /** - * Stops the pre-warmed compositor service if it isn't needed. - * @return Whether a pre-warmed compositor service was actually stopped. - */ - public boolean stopWarmCompositor() { - if (mNativePaintPreviewTabService == 0) return false; - - return PaintPreviewTabServiceJni.get().stopWarmCompositorAndroid( - mNativePaintPreviewTabService); - } - - /** * Should be called when all tabs are restored. Registers a {@link TabModelSelectorTabObserver} * for the regular to capture and delete paint previews as needed. Audits restored tabs to * remove any failed deletions. @@ -153,7 +142,8 @@ AUDIT_START_DELAY_MS); } - private void auditOnStart(TabModel regularTabModel) { + @VisibleForTesting + void auditOnStart(TabModel regularTabModel) { int tabCount = regularTabModel.getCount(); int[] tabIds = new int[tabCount]; for (int i = 0; i < tabCount; i++) { @@ -236,6 +226,5 @@ void auditArtifactsAndroid(long nativePaintPreviewTabService, int[] activeTabIds); boolean isCacheInitializedAndroid(long nativePaintPreviewTabService); String getPathAndroid(long nativePaintPreviewTabService); - boolean stopWarmCompositorAndroid(long nativePaintPreviewTabService); } }
diff --git a/chrome/browser/paint_preview/android/java/src/org/chromium/chrome/browser/paint_preview/services/PaintPreviewTabServiceNativeInitObserver.java b/chrome/browser/paint_preview/android/java/src/org/chromium/chrome/browser/paint_preview/services/PaintPreviewTabServiceNativeInitObserver.java deleted file mode 100644 index 33b1feab..0000000 --- a/chrome/browser/paint_preview/android/java/src/org/chromium/chrome/browser/paint_preview/services/PaintPreviewTabServiceNativeInitObserver.java +++ /dev/null
@@ -1,27 +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. - -package org.chromium.chrome.browser.paint_preview.services; - -import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher; -import org.chromium.chrome.browser.lifecycle.NativeInitObserver; - -/** - * Watches for native init to pre-warm the compositor. - */ -public class PaintPreviewTabServiceNativeInitObserver implements NativeInitObserver { - private ActivityLifecycleDispatcher mActvityLifecycleDispatcher; - - public PaintPreviewTabServiceNativeInitObserver( - ActivityLifecycleDispatcher activityLifecycleDispatcher) { - mActvityLifecycleDispatcher = activityLifecycleDispatcher; - } - - @Override - public void onFinishNativeInitialization() { - // Warms-up the service and prepares the compositor service. - PaintPreviewTabServiceFactory.getServiceInstance(); - mActvityLifecycleDispatcher.unregister(this); - } -}
diff --git a/chrome/browser/paint_preview/paint_preview_compositor_browsertest.cc b/chrome/browser/paint_preview/paint_preview_compositor_browsertest.cc index 2524069..b765dd6 100644 --- a/chrome/browser/paint_preview/paint_preview_compositor_browsertest.cc +++ b/chrome/browser/paint_preview/paint_preview_compositor_browsertest.cc
@@ -18,7 +18,6 @@ #include "components/paint_preview/browser/paint_preview_base_service_test_factory.h" #include "components/paint_preview/browser/paint_preview_compositor_client_impl.h" #include "components/paint_preview/browser/paint_preview_compositor_service_impl.h" -#include "components/paint_preview/browser/warm_compositor.h" #include "components/paint_preview/public/paint_preview_compositor_client.h" #include "components/paint_preview/public/paint_preview_compositor_service.h" #include "components/services/paint_preview_compositor/public/mojom/paint_preview_compositor.mojom.h" @@ -199,28 +198,4 @@ EXPECT_FALSE(IsBoundAndConnected(compositor.get())); } -IN_PROC_BROWSER_TEST_F(PaintPreviewCompositorBrowserTest, PreWarmCompositor) { - // Start with warm compositor. - WarmCompositor* warm_compositor = WarmCompositor::GetInstance(); - warm_compositor->WarmupCompositor(); - auto compositor_service = ToCompositorServiceImpl( - warm_compositor->GetOrStartCompositorService(base::DoNothing())); - EXPECT_FALSE(warm_compositor->StopCompositor()); - EXPECT_NE(compositor_service, nullptr); - compositor_service.reset(); - EXPECT_EQ(compositor_service, nullptr); - - // Start and stop. - warm_compositor->WarmupCompositor(); - EXPECT_TRUE(warm_compositor->StopCompositor()); - - // Verify it is still possible to start if the compositor was prematurely - // stopped. - compositor_service = ToCompositorServiceImpl( - warm_compositor->GetOrStartCompositorService(base::DoNothing())); - EXPECT_NE(compositor_service, nullptr); - compositor_service.reset(); - EXPECT_EQ(compositor_service, nullptr); -} - } // namespace paint_preview
diff --git a/chrome/browser/paint_preview/services/paint_preview_tab_service.cc b/chrome/browser/paint_preview/services/paint_preview_tab_service.cc index 332544e6..a78ee55 100644 --- a/chrome/browser/paint_preview/services/paint_preview_tab_service.cc +++ b/chrome/browser/paint_preview/services/paint_preview_tab_service.cc
@@ -13,7 +13,6 @@ #include "base/task/post_task.h" #include "base/task/task_traits.h" #include "components/paint_preview/browser/file_manager.h" -#include "components/paint_preview/browser/warm_compositor.h" #include "ui/gfx/geometry/rect.h" #if defined(OS_ANDROID) @@ -56,16 +55,12 @@ const base::FilePath& profile_dir, base::StringPiece ascii_feature_name, std::unique_ptr<PaintPreviewPolicy> policy, - bool is_off_the_record, - bool prewarm_compositor) + bool is_off_the_record) : PaintPreviewBaseService(profile_dir, ascii_feature_name, std::move(policy), is_off_the_record), cache_ready_(false) { - if (prewarm_compositor) - WarmCompositor::GetInstance()->WarmupCompositor(); - GetTaskRunner()->PostTaskAndReplyWithResult( FROM_HERE, base::BindOnce(&FileManager::ListUsedKeys, GetFileManager()), base::BindOnce(&PaintPreviewTabService::InitializeCache, @@ -160,11 +155,6 @@ weak_ptr_factory_.GetWeakPtr(), active_tab_ids)); } -bool PaintPreviewTabService::StopWarmCompositor() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - return WarmCompositor::GetInstance()->StopCompositor(); -} - void PaintPreviewTabService::GetCapturedPaintPreviewProto( const DirectoryKey& key, base::Optional<base::TimeDelta> expiry_horizon, @@ -219,10 +209,6 @@ return base::android::ConvertUTF8ToJavaString( env, GetFileManager()->GetPath().AsUTF8Unsafe()); } - -jboolean PaintPreviewTabService::StopWarmCompositorAndroid(JNIEnv* env) { - return static_cast<jboolean>(StopWarmCompositor()); -} #endif // defined(OS_ANDROID) void PaintPreviewTabService::InitializeCache(
diff --git a/chrome/browser/paint_preview/services/paint_preview_tab_service.h b/chrome/browser/paint_preview/services/paint_preview_tab_service.h index 2f708ef..0a591c7 100644 --- a/chrome/browser/paint_preview/services/paint_preview_tab_service.h +++ b/chrome/browser/paint_preview/services/paint_preview_tab_service.h
@@ -41,8 +41,7 @@ PaintPreviewTabService(const base::FilePath& profile_dir, base::StringPiece ascii_feature_name, std::unique_ptr<PaintPreviewPolicy> policy, - bool is_off_the_record, - bool prewarm_compositor = true); + bool is_off_the_record); ~PaintPreviewTabService() override; enum Status { @@ -79,9 +78,6 @@ // occurred. void AuditArtifacts(const std::vector<int>& active_tab_ids); - // Stops the pre-warmed compositor service. - bool StopWarmCompositor(); - // Override for GetCapturedPaintPreviewProto. Defaults expiry horizon to 72 // hrs if not specified. void GetCapturedPaintPreviewProto( @@ -104,7 +100,6 @@ const base::android::JavaParamRef<jintArray>& j_tab_ids); jboolean IsCacheInitializedAndroid(JNIEnv* env); base::android::ScopedJavaLocalRef<jstring> GetPathAndroid(JNIEnv* env); - jboolean StopWarmCompositorAndroid(JNIEnv* env); base::android::ScopedJavaGlobalRef<jobject> GetJavaRef() { return java_ref_; } #endif // defined(OS_ANDROID)
diff --git a/chrome/browser/paint_preview/services/paint_preview_tab_service_unittest.cc b/chrome/browser/paint_preview/services/paint_preview_tab_service_unittest.cc index 76a37d5..86d91bf8a 100644 --- a/chrome/browser/paint_preview/services/paint_preview_tab_service_unittest.cc +++ b/chrome/browser/paint_preview/services/paint_preview_tab_service_unittest.cc
@@ -85,7 +85,7 @@ ChromeRenderViewHostTestHarness::SetUp(); EXPECT_TRUE(temp_dir_.CreateUniqueTempDir()); service_ = std::make_unique<PaintPreviewTabService>( - temp_dir_.GetPath(), kFeatureName, nullptr, false, false); + temp_dir_.GetPath(), kFeatureName, nullptr, false); task_environment()->RunUntilIdle(); EXPECT_TRUE(service_->CacheInitialized()); } @@ -119,7 +119,7 @@ } return std::make_unique<PaintPreviewTabService>(GetPath(), kFeatureName, - nullptr, false, false); + nullptr, false); } private:
diff --git a/chrome/browser/password_check/android/DEPS b/chrome/browser/password_check/android/DEPS index 7ea4d93..c78d4d2 100644 --- a/chrome/browser/password_check/android/DEPS +++ b/chrome/browser/password_check/android/DEPS
@@ -1,4 +1,5 @@ include_rules = [ "+chrome/android", "+chrome/browser/ui/android", + "+content/public/android", ] \ No newline at end of file
diff --git a/chrome/browser/password_check/android/internal/BUILD.gn b/chrome/browser/password_check/android/internal/BUILD.gn index 4e394ab..feeb49ee 100644 --- a/chrome/browser/password_check/android/internal/BUILD.gn +++ b/chrome/browser/password_check/android/internal/BUILD.gn
@@ -67,6 +67,7 @@ "//chrome/browser/ui/android/strings:ui_strings_grd", "//components/browser_ui/widget/android:java", "//components/embedder_support/android:util_java", + "//content/public/android:content_java", "//third_party/android_deps:androidx_annotation_annotation_java", "//third_party/android_deps:androidx_appcompat_appcompat_java", "//third_party/android_deps:androidx_appcompat_appcompat_resources_java",
diff --git a/chrome/browser/password_check/android/internal/java/src/org/chromium/chrome/browser/password_check/PasswordCheckMediator.java b/chrome/browser/password_check/android/internal/java/src/org/chromium/chrome/browser/password_check/PasswordCheckMediator.java index 7cce3cce..fca7aa28 100644 --- a/chrome/browser/password_check/android/internal/java/src/org/chromium/chrome/browser/password_check/PasswordCheckMediator.java +++ b/chrome/browser/password_check/android/internal/java/src/org/chromium/chrome/browser/password_check/PasswordCheckMediator.java
@@ -25,12 +25,15 @@ import android.content.DialogInterface; import android.util.Pair; +import androidx.annotation.VisibleForTesting; import androidx.appcompat.app.AlertDialog; +import org.chromium.base.task.PostTask; import org.chromium.chrome.browser.password_check.helper.PasswordCheckChangePasswordHelper; import org.chromium.chrome.browser.password_check.helper.PasswordCheckIconHelper; import org.chromium.chrome.browser.password_check.helper.PasswordCheckReauthenticationHelper; import org.chromium.chrome.browser.password_check.helper.PasswordCheckReauthenticationHelper.ReauthReason; +import org.chromium.content_public.browser.UiThreadTaskTraits; import org.chromium.ui.modelutil.ListModel; import org.chromium.ui.modelutil.MVCListAdapter.ListItem; import org.chromium.ui.modelutil.PropertyModel; @@ -46,6 +49,8 @@ */ class PasswordCheckMediator implements PasswordCheckCoordinator.CredentialEventHandler, PasswordCheck.Observer { + private static long sStatusUpdateDelayMillis = 1000; + private final PasswordCheckReauthenticationHelper mReauthenticationHelper; private final PasswordCheckChangePasswordHelper mChangePasswordDelegate; private PropertyModel mModel; @@ -53,6 +58,7 @@ private Runnable mLaunchCheckupInAccount; private HashSet<CompromisedCredential> mPreCheckSet; private final PasswordCheckIconHelper mIconHelper; + private long mLastStatusUpdate; PasswordCheckMediator(PasswordCheckChangePasswordHelper changePasswordDelegate, PasswordCheckReauthenticationHelper reauthenticationHelper, @@ -106,6 +112,7 @@ .with(LAUNCH_ACCOUNT_CHECKUP_ACTION, mLaunchCheckupInAccount) .with(RESTART_BUTTON_ACTION, this::startCheckManually) .build())); + mLastStatusUpdate = System.currentTimeMillis(); } if (items.size() > 1) items.removeRange(1, items.size() - 1); @@ -120,6 +127,19 @@ @Override public void onPasswordCheckStatusChanged(@PasswordCheckUIStatus int status) { + long currentTime = System.currentTimeMillis(); + + if (shouldDelayStatusChange(status, currentTime)) { + mLastStatusUpdate += sStatusUpdateDelayMillis; + PostTask.postDelayedTask(UiThreadTaskTraits.DEFAULT, + () -> changePasswordCheckStatus(status), mLastStatusUpdate - currentTime); + } else { + mLastStatusUpdate = currentTime; + changePasswordCheckStatus(status); + } + } + + private void changePasswordCheckStatus(@PasswordCheckUIStatus int status) { // There is no UI representation of a canceled check. This status can be sent when // the bridge and the password check UI are being torn down while a check is running. if (status == PasswordCheckUIStatus.CANCELED) return; @@ -139,8 +159,9 @@ header = items.get(0).model; } header.set(CHECK_STATUS, status); - header.set( - CHECK_PROGRESS, status == PasswordCheckUIStatus.RUNNING ? UNKNOWN_PROGRESS : null); + Pair<Integer, Integer> progress = header.get(CHECK_PROGRESS); + if (progress == null) progress = UNKNOWN_PROGRESS; + header.set(CHECK_PROGRESS, status == PasswordCheckUIStatus.RUNNING ? progress : null); Long checkTimestamp = null; Integer compromisedCredentialCount = null; if (status == PasswordCheckUIStatus.IDLE) { @@ -164,7 +185,10 @@ assert remainingInQueue >= 0; PropertyModel header = items.get(0).model; - header.set(CHECK_STATUS, PasswordCheckUIStatus.RUNNING); + if (header.get(CHECK_STATUS) != PasswordCheckUIStatus.RUNNING) { + mLastStatusUpdate = System.currentTimeMillis(); + header.set(CHECK_STATUS, PasswordCheckUIStatus.RUNNING); + } header.set( CHECK_PROGRESS, new Pair<>(alreadyProcessed, alreadyProcessed + remainingInQueue)); header.set(CHECK_TIMESTAMP, null); @@ -304,6 +328,16 @@ && mModel.get(ITEMS).get(0).model.get(CHECK_STATUS) == PasswordCheckUIStatus.RUNNING; } + + private boolean shouldDelayStatusChange( + @PasswordCheckUIStatus int newStatus, long currentTime) { + ListModel<ListItem> items = mModel.get(ITEMS); + return items.size() > 0 + && items.get(0).model.get(CHECK_STATUS) == PasswordCheckUIStatus.RUNNING + && newStatus != PasswordCheckUIStatus.RUNNING + && mLastStatusUpdate + sStatusUpdateDelayMillis > currentTime; + } + private ListItem createEntryForCredential(CompromisedCredential credential) { PropertyModel credentialModel = new PropertyModel @@ -360,4 +394,9 @@ return originComparisonResult == 0 ? usernameComparisonResult : originComparisonResult; }); } + + @VisibleForTesting + protected static void setStatusUpdateDelayMillis(long statusUpdateDelayMillis) { + sStatusUpdateDelayMillis = statusUpdateDelayMillis; + } }
diff --git a/chrome/browser/password_check/android/junit/src/org/chromium/chrome/browser/password_check/PasswordCheckControllerTest.java b/chrome/browser/password_check/android/junit/src/org/chromium/chrome/browser/password_check/PasswordCheckControllerTest.java index 9927266..043bc85 100644 --- a/chrome/browser/password_check/android/junit/src/org/chromium/chrome/browser/password_check/PasswordCheckControllerTest.java +++ b/chrome/browser/password_check/android/junit/src/org/chromium/chrome/browser/password_check/PasswordCheckControllerTest.java
@@ -129,6 +129,7 @@ mChangePasswordDelegate, mReauthenticationHelper, mIconHelper); PasswordCheckFactory.setPasswordCheckForTesting(mPasswordCheck); mMediator.initialize(mModel, mDelegate, PasswordCheckReferrer.PASSWORD_SETTINGS, () -> {}); + PasswordCheckMediator.setStatusUpdateDelayMillis(0); } @Test
diff --git a/chrome/browser/payments/BUILD.gn b/chrome/browser/payments/BUILD.gn index 279923a5..ff5578a 100644 --- a/chrome/browser/payments/BUILD.gn +++ b/chrome/browser/payments/BUILD.gn
@@ -15,6 +15,7 @@ "iframe_csp_browsertest.cc", "ignore_payment_method_browsertest.cc", "journey_logger_browsertest.cc", + "load_and_remove_iframe_with_many_payment_requests_browsertest.cc", "payment_handler_capabilities_browsertest.cc", "payment_handler_change_shipping_address_option_browsertest.cc", "payment_handler_enable_delegations_browsertest.cc",
diff --git a/chrome/browser/payments/android/journey_logger_android.cc b/chrome/browser/payments/android/journey_logger_android.cc index 1b11d69..eb5df50 100644 --- a/chrome/browser/payments/android/journey_logger_android.cc +++ b/chrome/browser/payments/android/journey_logger_android.cc
@@ -184,6 +184,7 @@ const JavaParamRef<jobject>& jweb_contents) { content::WebContents* web_contents = content::WebContents::FromJavaWebContents(jweb_contents); + DCHECK(web_contents); // Verified in Java before invoking this function. return reinterpret_cast<jlong>(new JourneyLoggerAndroid( jis_incognito, ukm::GetSourceIdForWebContentsDocument(web_contents))); }
diff --git a/chrome/browser/payments/android/payment_app_service_bridge.cc b/chrome/browser/payments/android/payment_app_service_bridge.cc index ea6fc8d..4a00569 100644 --- a/chrome/browser/payments/android/payment_app_service_bridge.cc +++ b/chrome/browser/payments/android/payment_app_service_bridge.cc
@@ -95,6 +95,9 @@ auto* render_frame_host = content::RenderFrameHost::FromJavaRenderFrameHost(jrender_frame_host); + if (!render_frame_host) // The frame is being unloaded. + return; + std::string top_origin = ConvertJavaStringToUTF8(jtop_origin); scoped_refptr<payments::PaymentManifestWebDataService> web_data_service =
diff --git a/chrome/browser/payments/android/service_worker_payment_app_bridge.cc b/chrome/browser/payments/android/service_worker_payment_app_bridge.cc index ac949fc..2d4ac9ba 100644 --- a/chrome/browser/payments/android/service_worker_payment_app_bridge.cc +++ b/chrome/browser/payments/android/service_worker_payment_app_bridge.cc
@@ -124,7 +124,7 @@ jint reason) { content::WebContents* web_contents = content::WebContents::FromJavaWebContents(jweb_contents); - + DCHECK(web_contents); // Verified in Java before invoking this function. content::PaymentAppProvider::GetInstance()->OnClosingOpenedWindow( web_contents, static_cast<payments::mojom::PaymentEventResponseType>(reason));
diff --git a/chrome/browser/payments/android/ssl_validity_checker_android.cc b/chrome/browser/payments/android/ssl_validity_checker_android.cc index 6f9a5939..3590be3 100644 --- a/chrome/browser/payments/android/ssl_validity_checker_android.cc +++ b/chrome/browser/payments/android/ssl_validity_checker_android.cc
@@ -17,6 +17,7 @@ const base::android::JavaParamRef<jobject>& jweb_contents) { content::WebContents* web_contents = content::WebContents::FromJavaWebContents(jweb_contents); + // SslValidityChecker checks for null `web_contents` parameter. return base::android::ConvertUTF8ToJavaString( env, SslValidityChecker::GetInvalidSslCertificateErrorMessage(web_contents)); @@ -26,6 +27,7 @@ jboolean JNI_SslValidityChecker_IsValidPageInPaymentHandlerWindow( JNIEnv* env, const base::android::JavaParamRef<jobject>& jweb_contents) { + // SslValidityChecker checks for null `web_contents` parameter. return SslValidityChecker::IsValidPageInPaymentHandlerWindow( content::WebContents::FromJavaWebContents(jweb_contents)); }
diff --git a/chrome/browser/payments/load_and_remove_iframe_with_many_payment_requests_browsertest.cc b/chrome/browser/payments/load_and_remove_iframe_with_many_payment_requests_browsertest.cc new file mode 100644 index 0000000..79989330 --- /dev/null +++ b/chrome/browser/payments/load_and_remove_iframe_with_many_payment_requests_browsertest.cc
@@ -0,0 +1,42 @@ +// 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/test/payments/payment_request_platform_browsertest_base.h" +#include "content/public/test/browser_test.h" +#include "content/public/test/browser_test_utils.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace payments { +namespace { + +class LoadAndRemoveIframeWithManyPaymentRequestsTest + : public PaymentRequestPlatformBrowserTestBase { + public: + void RunTest(const std::string& iframe_hostname) { + NavigateTo("a.com", "/load_and_remove_iframe.html"); + + // EvalJs waits for JavaScript promise to resolve. + EXPECT_EQ("success", + content::EvalJs(GetActiveWebContents(), + content::JsReplace( + "loadAndRemoveIframe($1, /*timeout=*/100);", + https_server() + ->GetURL(iframe_hostname, + "/create_many_requests.html") + .spec()))); + } +}; + +IN_PROC_BROWSER_TEST_F(LoadAndRemoveIframeWithManyPaymentRequestsTest, + CrossOriginNoCrash) { + RunTest(/*iframe_hostname=*/"b.com"); +} + +IN_PROC_BROWSER_TEST_F(LoadAndRemoveIframeWithManyPaymentRequestsTest, + SameOriginNoCrash) { + RunTest(/*iframe_hostname=*/"a.com"); +} + +} // namespace +} // namespace payments
diff --git a/chrome/browser/policy/chrome_browser_policy_connector.cc b/chrome/browser/policy/chrome_browser_policy_connector.cc index 41af54f..f359971c 100644 --- a/chrome/browser/policy/chrome_browser_policy_connector.cc +++ b/chrome/browser/policy/chrome_browser_policy_connector.cc
@@ -32,6 +32,7 @@ #include "components/policy/core/common/policy_service.h" #include "components/policy/core/common/policy_types.h" #include "components/policy/policy_constants.h" +#include "content/public/common/content_switches.h" #include "extensions/buildflags/buildflags.h" #include "services/network/public/cpp/shared_url_loader_factory.h" @@ -61,6 +62,9 @@ #endif namespace policy { +namespace { +bool command_line_enabled_for_testing = false; +} // namespace ChromeBrowserPolicyConnector::ChromeBrowserPolicyConnector() : BrowserPolicyConnector(base::Bind(&BuildHandlerList)) { @@ -81,9 +85,8 @@ PrefService* local_state, scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory) { std::unique_ptr<DeviceManagementService::Configuration> configuration( - new DeviceManagementServiceConfiguration( - BrowserPolicyConnector::GetDeviceManagementUrl(), - BrowserPolicyConnector::GetRealtimeReportingUrl())); + new DeviceManagementServiceConfiguration(GetDeviceManagementUrl(), + GetRealtimeReportingUrl())); std::unique_ptr<DeviceManagementService> device_management_service( new DeviceManagementService(std::move(configuration))); device_management_service->ScheduleInitialization( @@ -126,6 +129,20 @@ return provider ? provider : platform_provider_; } +bool ChromeBrowserPolicyConnector::IsCommandLineSwitchSupported() const { + if (command_line_enabled_for_testing) + return true; + + version_info::Channel channel = chrome::GetChannel(); + return channel != version_info::Channel::STABLE && + channel != version_info::Channel::BETA; +} + +// static +void ChromeBrowserPolicyConnector::EnableCommandLineSupportForTesting() { + command_line_enabled_for_testing = true; +} + std::vector<std::unique_ptr<policy::ConfigurationPolicyProvider>> ChromeBrowserPolicyConnector::CreatePolicyProviders() { auto providers = BrowserPolicyConnector::CreatePolicyProviders();
diff --git a/chrome/browser/policy/chrome_browser_policy_connector.h b/chrome/browser/policy/chrome_browser_policy_connector.h index da267559..29456ba1 100644 --- a/chrome/browser/policy/chrome_browser_policy_connector.h +++ b/chrome/browser/policy/chrome_browser_policy_connector.h
@@ -66,8 +66,15 @@ } #endif - protected: // BrowserPolicyConnector: + // Command line switch only supports Dev and Canary channel, trunk and browser + // tests on Win, Mac, Linux and Android. + bool IsCommandLineSwitchSupported() const override; + + static void EnableCommandLineSupportForTesting(); + + protected: + // BrowserPolicyConnectorBase:: std::vector<std::unique_ptr<policy::ConfigurationPolicyProvider>> CreatePolicyProviders() override;
diff --git a/chrome/browser/policy/cloud/chrome_browser_cloud_management_browsertest.cc b/chrome/browser/policy/cloud/chrome_browser_cloud_management_browsertest.cc index 8f898f6..799cf5c 100644 --- a/chrome/browser/policy/cloud/chrome_browser_cloud_management_browsertest.cc +++ b/chrome/browser/policy/cloud/chrome_browser_cloud_management_browsertest.cc
@@ -462,6 +462,7 @@ base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); command_line->AppendSwitchASCII(switches::kDeviceManagementUrl, test_server_.GetServiceURL().spec()); + ChromeBrowserPolicyConnector::EnableCommandLineSupportForTesting(); histogram_tester_.ExpectTotalCount(kEnrollmentResultMetrics, 0); } @@ -602,6 +603,7 @@ base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); command_line->AppendSwitchASCII(switches::kDeviceManagementUrl, test_server_->GetServiceURL().spec()); + ChromeBrowserPolicyConnector::EnableCommandLineSupportForTesting(); } #if !BUILDFLAG(GOOGLE_CHROME_BRANDING) @@ -762,6 +764,7 @@ base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); command_line->AppendSwitchASCII(switches::kDeviceManagementUrl, test_server_->GetServiceURL().spec()); + ChromeBrowserPolicyConnector::EnableCommandLineSupportForTesting(); } #if !BUILDFLAG(GOOGLE_CHROME_BRANDING)
diff --git a/chrome/browser/policy/cloud/cloud_policy_browsertest.cc b/chrome/browser/policy/cloud/cloud_policy_browsertest.cc index 8a69bc50..e1b3e6e 100644 --- a/chrome/browser/policy/cloud/cloud_policy_browsertest.cc +++ b/chrome/browser/policy/cloud/cloud_policy_browsertest.cc
@@ -197,6 +197,7 @@ base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); command_line->AppendSwitchASCII(switches::kDeviceManagementUrl, url); + ChromeBrowserPolicyConnector::EnableCommandLineSupportForTesting(); } void CreatedBrowserMainParts(
diff --git a/chrome/browser/policy/cloud/cloud_policy_manager_browsertest.cc b/chrome/browser/policy/cloud/cloud_policy_manager_browsertest.cc index 896c836..b08f6e3 100644 --- a/chrome/browser/policy/cloud/cloud_policy_manager_browsertest.cc +++ b/chrome/browser/policy/cloud/cloud_policy_manager_browsertest.cc
@@ -151,6 +151,7 @@ base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); command_line->AppendSwitchASCII(switches::kDeviceManagementUrl, "http://localhost"); + ChromeBrowserPolicyConnector::EnableCommandLineSupportForTesting(); // Set retry delay to prevent timeouts. policy::DeviceManagementService::SetRetryDelayForTesting(0);
diff --git a/chrome/browser/policy/cloud/component_cloud_policy_browsertest.cc b/chrome/browser/policy/cloud/component_cloud_policy_browsertest.cc index a2e39169..4a37d23 100644 --- a/chrome/browser/policy/cloud/component_cloud_policy_browsertest.cc +++ b/chrome/browser/policy/cloud/component_cloud_policy_browsertest.cc
@@ -122,6 +122,7 @@ std::string url = test_server_.GetServiceURL().spec(); base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); command_line->AppendSwitchASCII(switches::kDeviceManagementUrl, url); + ChromeBrowserPolicyConnector::EnableCommandLineSupportForTesting(); extensions::ExtensionBrowserTest::SetUpInProcessBrowserTestFixture(); }
diff --git a/chrome/browser/policy/cloud/user_policy_signin_service_browsertest.cc b/chrome/browser/policy/cloud/user_policy_signin_service_browsertest.cc index 0e00305..0f63f6c 100644 --- a/chrome/browser/policy/cloud/user_policy_signin_service_browsertest.cc +++ b/chrome/browser/policy/cloud/user_policy_signin_service_browsertest.cc
@@ -9,6 +9,7 @@ #include "base/command_line.h" #include "base/values.h" #include "chrome/browser/browser_process.h" +#include "chrome/browser/policy/chrome_browser_policy_connector.h" #include "chrome/browser/policy/profile_policy_connector.h" #include "chrome/browser/signin/identity_manager_factory.h" #include "chrome/browser/ui/browser.h" @@ -195,6 +196,7 @@ command_line->AppendSwitchASCII(switches::kGaiaUrl, base_url.spec()); command_line->AppendSwitchASCII(switches::kLsoUrl, base_url.spec()); command_line->AppendSwitchASCII(switches::kGoogleApisUrl, base_url.spec()); + policy::ChromeBrowserPolicyConnector::EnableCommandLineSupportForTesting(); fake_gaia_.Initialize(); // Configure Sync server. command_line->AppendSwitch(switches::kDisableSync);
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/i_tutorial/components/i_tutorial.js b/chrome/browser/resources/chromeos/accessibility/chromevox/i_tutorial/components/i_tutorial.js index dc93de8..3082c734 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/i_tutorial/components/i_tutorial.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/i_tutorial/components/i_tutorial.js
@@ -67,6 +67,18 @@ interactiveMode: {type: Boolean, value: false}, + nudgeIntervalId: {type: Number}, + + /** @const */ + NUDGE_INTERVAL_TIME_MS: {type: Number, value: 45 * 1000}, + + nudgeCounter: {type: Number, value: 0}, + + /** @type {Array<function(): void>} */ + nudgeArray: {type: Array}, + + isPracticeAreaActive: {type: Boolean, value: false}, + // Labels and text content. chooseYourExperience: { @@ -440,10 +452,23 @@ ready() { document.addEventListener('keydown', this.onKeyDown.bind(this)); this.hideAllScreens(); + this.initializeNudges(); this.$.lessonTemplate.addEventListener('dom-change', (evt) => { // Executes once all lessons have been added to the dom. this.show(); }); + this.$.tutorial.addEventListener('focus', this.onFocus.bind(this), true); + this.addEventListener('startpractice', (evt) => { + // Stop nudges when the practice area opens. This is because the practice + // area can provide hints and we don't want nudges to conflict with them. + this.stopNudges(); + this.isPracticeAreaActive = true; + }); + this.addEventListener('endpractice', (evt) => { + // When the practice area closes, it's safe to resume nudges. + this.startNudges(); + this.isPracticeAreaActive = false; + }); }, /** Shows the tutorial */ @@ -456,6 +481,7 @@ } else { this.showMainMenu(); } + this.startNudges(); }, /** @@ -675,6 +701,7 @@ /** @private */ exit() { + this.stopNudges(); this.dispatchEvent(new CustomEvent('closetutorial', {})); }, @@ -725,4 +752,84 @@ evt.stopPropagation(); } }, + + /** @private */ + startNudges() { + this.stopNudges(); + this.nudgeIntervalId = + setInterval(this.giveNudge.bind(this), this.NUDGE_INTERVAL_TIME_MS); + }, + + /** @private */ + stopNudges() { + this.nudgeCounter = 0; + if (this.nudgeIntervalId) { + clearInterval(this.nudgeIntervalId); + } + }, + + /** @private */ + giveNudge() { + if (this.nudgeCounter < 0 || this.nudgeCounter >= this.nudgeArray.length) { + this.stopNudges(); + return; + } + + this.nudgeArray[this.nudgeCounter](); + this.nudgeCounter += 1; + }, + + /** + * @param {string} text + * @private + */ + requestSpeech(text) { + this.dispatchEvent( + new CustomEvent('requestspeech', {composed: true, detail: {text}})); + }, + + /** @private */ + requestFullyDescribe() { + this.dispatchEvent( + new CustomEvent('requestfullydescribe', {composed: true})); + }, + + /** @private */ + initializeNudges() { + const maybeGiveNudge = (msg) => { + if (this.interactiveMode) { + // Do not announce message since ChromeVox blocks actions in interactive + // mode. + return; + } + + this.requestSpeech(msg); + }; + + this.nudgeArray = [ + this.requestFullyDescribe.bind(this), + this.requestFullyDescribe.bind(this), + this.requestFullyDescribe.bind(this), + maybeGiveNudge.bind( + this, 'Hint: Hold Search and press the arrow keys to navigate.'), + maybeGiveNudge.bind( + this, 'Hint: Press Search + Space to activate the current item.'), + this.requestSpeech.bind( + this, 'Hint: Press Escape if you would like to exit this tutorial.') + ]; + }, + + /** + * @param {Event} evt + * @private + */ + onFocus(evt) { + // Restart nudges whenever focus changes, as long as the practice area is + // inactive. + if (this.isPracticeAreaActive) { + return; + } + + this.startNudges(); + } });
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/i_tutorial/components/tutorial_lesson.js b/chrome/browser/resources/chromeos/accessibility/chromevox/i_tutorial/components/tutorial_lesson.js index a2fd4815..b8a7450 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/i_tutorial/components/tutorial_lesson.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/i_tutorial/components/tutorial_lesson.js
@@ -134,6 +134,7 @@ /** @private */ startPractice() { + this.notifyStartPractice(); this.$.practice.showModal(); this.startHints(); this.$.practiceTitle.focus(); @@ -141,10 +142,21 @@ /** @private */ endPractice() { + this.notifyEndPractice(); this.stopHints(); this.$.startPractice.focus(); }, + /** @private */ + notifyStartPractice() { + this.dispatchEvent(new CustomEvent('startpractice', {composed: true})); + }, + + /** @private */ + notifyEndPractice() { + this.dispatchEvent(new CustomEvent('endpractice', {composed: true})); + }, + // Methods for tracking the state of the practice area. @@ -204,7 +216,6 @@ } }, - // Methods for managing hints. /** @private */
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/panel/panel.js b/chrome/browser/resources/chromeos/accessibility/chromevox/panel/panel.js index 05695f8..ffdf1d1e1 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/panel/panel.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/panel/panel.js
@@ -1219,6 +1219,11 @@ chrome.extension.getBackgroundPage()['ChromeVoxState']['instance']; background.destroyUserActionMonitor(); }); + $('i-tutorial').addEventListener('requestfullydescribe', (evt) => { + const commandHandler = + chrome.extension.getBackgroundPage()['CommandHandler']; + commandHandler.onCommand('fullyDescribe'); + }); } /**
diff --git a/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_or.xtb b/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_or.xtb index fb785384..170120c 100644 --- a/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_or.xtb +++ b/chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings_or.xtb
@@ -280,6 +280,7 @@ <translation id="3103579948980282461">ମଧ୍ୟମ ବାଇଗଣୀ ନାଲି</translation> <translation id="3104705064753753826">ଅଲର୍ଟ ଡାଇଲଗ୍</translation> <translation id="3109724472072898302">ସଙ୍କୁଚିତ କରାଗଲା</translation> +<translation id="311015743332597320">ଚାରି ଆଙ୍ଗୁଠିରେ ଡାହାଣକୁ ସ୍ୱାଇପ୍ କରନ୍ତୁ</translation> <translation id="3112457281078985179">ChromeVoxକୁ ଚାଲୁ କିମ୍ବା ବନ୍ଦ କରିବାକୁ Control+Alt+Zକୁ ବ୍ୟବହାର କରନ୍ତୁ।</translation> <translation id="3131002934070407451">ନମ୍ବରକୁ ଏପରି ଭାବେ ପଢ଼ନ୍ତୁ:</translation> <translation id="3134461040845705080">rdonly</translation> @@ -901,6 +902,7 @@ <translation id="812886159861361726"><ph name="FILE_NAME" /> ଡାଉନ୍ଲୋଡ୍ ହେବା ବନ୍ଦ ହୋଇଗଲା</translation> <translation id="8129445297241948503">ଉପରେ କୌଣସି ସେଲ୍ ନାହିଁ</translation> <translation id="8138880386467279117">ସ୍ପର୍ଶ</translation> +<translation id="8173092779156526980">ଚାରି ଆଙ୍ଗୁଠିରେ ବାମକୁ ସ୍ୱାଇପ୍ କରନ୍ତୁ</translation> <translation id="817440585505441544">{COUNT,plural, =1{ଟି ଅଣ୍ଡରସ୍କୋର୍}other{#ଟି ଅଣ୍ଡରସ୍କୋର୍}}</translation> <translation id="8184828902145951186">ଧାଡ଼ି</translation> <translation id="8186185314313222077">ପୂର୍ଣ୍ଣସ୍କ୍ରିନ୍ ଟୋଗଲ୍ କରନ୍ତୁ</translation>
diff --git a/chrome/browser/resources/settings/autofill_page/autofill_page.html b/chrome/browser/resources/settings/autofill_page/autofill_page.html index c6e70b9e..6510541 100644 --- a/chrome/browser/resources/settings/autofill_page/autofill_page.html +++ b/chrome/browser/resources/settings/autofill_page/autofill_page.html
@@ -49,8 +49,7 @@ </passwords-device-section> </settings-subpage> </template> - <template is="dom-if" route-path="/passwords/check" - no-search="[[!enablePasswordCheck_]]"> + <template is="dom-if" route-path="/passwords/check"> <settings-subpage associated-control="[[$$('#passwordManagerButton')]]" page-title="$i18n{checkPasswords}"
diff --git a/chrome/browser/resources/settings/autofill_page/autofill_page.js b/chrome/browser/resources/settings/autofill_page/autofill_page.js index 5c972a9..ede7841 100644 --- a/chrome/browser/resources/settings/autofill_page/autofill_page.js +++ b/chrome/browser/resources/settings/autofill_page/autofill_page.js
@@ -62,12 +62,6 @@ type: String, computed: 'computePasswordManagerSubLabel_(compromisedPasswordsCount)', }, - - /** @private */ - enablePasswordCheck_: { - type: Boolean, - value: () => loadTimeData.getBoolean('enablePasswordCheck'), - }, }, /** @@ -102,10 +96,6 @@ * @private */ computePasswordManagerSubLabel_() { - if (!this.enablePasswordCheck_) { - return ''; - } - return this.leakedPasswords.length > 0 ? this.compromisedPasswordsCount : ''; },
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 0a41382..59156a82 100644 --- a/chrome/browser/resources/settings/autofill_page/passwords_list_handler.html +++ b/chrome/browser/resources/settings/autofill_page/passwords_list_handler.html
@@ -12,11 +12,9 @@ <slot name="body"></slot> <cr-action-menu id="menu" role-description="$i18n{menu}"> - <template is="dom-if" if="[[enablePasswordCheck_]]"> - <button id="menuCopyPassword" class="dropdown-item" - hidden$="[[activePassword.entry.federationText]]" - on-click="onMenuCopyPasswordButtonTap_">$i18n{copyPassword}</button> - </template> + <button id="menuCopyPassword" class="dropdown-item" + hidden$="[[activePassword.entry.federationText]]" + on-click="onMenuCopyPasswordButtonTap_">$i18n{copyPassword}</button> <button id="menuEditPassword" class="dropdown-item" on-click="onMenuEditPasswordTap_"> [[getMenuEditPasswordName_(isEditDialog_)]]
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 9834dc35..14f5547 100644 --- a/chrome/browser/resources/settings/autofill_page/passwords_list_handler.js +++ b/chrome/browser/resources/settings/autofill_page/passwords_list_handler.js
@@ -74,14 +74,6 @@ // </if> /** @private */ - enablePasswordCheck_: { - type: Boolean, - value() { - return loadTimeData.getBoolean('enablePasswordCheck'); - } - }, - - /** @private */ editPasswordsInSettings_: { type: Boolean, value() {
diff --git a/chrome/browser/resources/settings/autofill_page/passwords_section.html b/chrome/browser/resources/settings/autofill_page/passwords_section.html index 75ac76d..2c62d14 100644 --- a/chrome/browser/resources/settings/autofill_page/passwords_section.html +++ b/chrome/browser/resources/settings/autofill_page/passwords_section.html
@@ -98,51 +98,49 @@ label="$i18n{passwordsAutosigninLabel}" sub-label="$i18n{passwordsAutosigninDescription}"> </settings-toggle-button> - <template is="dom-if" if="[[enablePasswordCheck_]]"> - <div id="checkPasswordsBannerContainer" class="cr-row" - hidden$="[[!shouldShowBanner_]]"> - <picture> - <source - srcset="chrome://settings/images/password_check_neutral_dark.svg" - media="(prefers-color-scheme: dark)"> - <img id="banner" alt="" - src="chrome://settings/images/password_check_neutral.svg"> - </picture> + <div id="checkPasswordsBannerContainer" class="cr-row" + hidden$="[[!shouldShowBanner_]]"> + <picture> + <source + srcset="chrome://settings/images/password_check_neutral_dark.svg" + media="(prefers-color-scheme: dark)"> + <img id="banner" alt="" + src="chrome://settings/images/password_check_neutral.svg"> + </picture> + </div> + <div id="checkPasswordsButtonRow" class="cr-row continuation" + hidden$="[[!shouldShowBanner_]]"> + <div class="flex cr-padded-text"> + <div>$i18n{checkPasswords}</div> + <div class="secondary">$i18n{checkPasswordsDescription}</div> </div> - <div id="checkPasswordsButtonRow" class="cr-row continuation" - hidden$="[[!shouldShowBanner_]]"> - <div class="flex cr-padded-text"> - <div>$i18n{checkPasswords}</div> - <div class="secondary">$i18n{checkPasswordsDescription}</div> - </div> - <cr-button id="checkPasswordsButton" class="action-button cr-button-gap" - on-click="onCheckPasswordsClick_"> + <cr-button id="checkPasswordsButton" class="action-button cr-button-gap" + on-click="onCheckPasswordsClick_"> + $i18n{checkPasswords} + </cr-button> + </div> + <div class="cr-row" id="checkPasswordsLinkRow" + on-click="onCheckPasswordsClick_" actionable + hidden$="[[shouldShowBanner_]]"> + <iron-icon icon="cr:warning" id="checkPasswordWarningIcon" + hidden$="[[!hasLeakedCredentials_]]"></iron-icon> + <div class="flex cr-padded-text"> + <div> $i18n{checkPasswords} - </cr-button> - </div> - <div class="cr-row" id="checkPasswordsLinkRow" - on-click="onCheckPasswordsClick_" actionable - hidden$="[[shouldShowBanner_]]"> - <iron-icon icon="cr:warning" id="checkPasswordWarningIcon" - hidden$="[[!hasLeakedCredentials_]]"></iron-icon> - <div class="flex cr-padded-text"> - <div> - $i18n{checkPasswords} - </div> - <div class="secondary" id="checkPasswordLeakCount" - hidden$="[[!hasLeakedCredentials_]]"> - [[compromisedPasswordsCount]] - </div> - <div class="secondary" id="checkPasswordLeakDescription" - hidden$="[[hasLeakedCredentials_]]"> - $i18n{checkPasswordsDescription} - </div> </div> - <cr-icon-button id="icon" class="subpage-arrow" - aria-label="$i18n{checkPasswords}"> - </cr-icon-button> + <div class="secondary" id="checkPasswordLeakCount" + hidden$="[[!hasLeakedCredentials_]]"> + [[compromisedPasswordsCount]] + </div> + <div class="secondary" id="checkPasswordLeakDescription" + hidden$="[[hasLeakedCredentials_]]"> + $i18n{checkPasswordsDescription} + </div> </div> - </template> + <cr-icon-button id="icon" class="subpage-arrow" + aria-label="$i18n{checkPasswords}"> + </cr-icon-button> + </div> <div id="manageLink" class="cr-row two-line" hidden$="[[hidePasswordsLink_]]"> <!-- This div lays out the link correctly, relative to the text. -->
diff --git a/chrome/browser/resources/settings/autofill_page/passwords_section.js b/chrome/browser/resources/settings/autofill_page/passwords_section.js index 9c4287a..c9ed577f 100644 --- a/chrome/browser/resources/settings/autofill_page/passwords_section.js +++ b/chrome/browser/resources/settings/autofill_page/passwords_section.js
@@ -120,14 +120,6 @@ }, /** @private */ - enablePasswordCheck_: { - type: Boolean, - value() { - return loadTimeData.getBoolean('enablePasswordCheck'); - } - }, - - /** @private */ signedIn_: { type: Boolean, value: true, @@ -328,11 +320,9 @@ // 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. - if (this.enablePasswordCheck_) { - this.focusConfig.set(assert(routes.CHECK_PASSWORDS).path, () => { - focusWithoutInk(assert(this.$$('#icon'))); - }); - } + this.focusConfig.set(assert(routes.CHECK_PASSWORDS).path, () => { + focusWithoutInk(assert(this.$$('#icon'))); + }); }, /** @override */
diff --git a/chrome/browser/resources/settings/chromeos/os_about_page/os_about_page.html b/chrome/browser/resources/settings/chromeos/os_about_page/os_about_page.html index d528dc9..c7015db0 100644 --- a/chrome/browser/resources/settings/chromeos/os_about_page/os_about_page.html +++ b/chrome/browser/resources/settings/chromeos/os_about_page/os_about_page.html
@@ -154,13 +154,15 @@ </a> </div> </cr-link-row> - <template is="dom-if" if="[[hasReleaseNotes_]]"> + <template is="dom-if" if="[[showReleaseNotesOnline_(hasReleaseNotes_, + hasInternetConnection_)]]"> <cr-link-row class="hr" id="releaseNotesOnline" - hidden="[[!hasInternetConnection_]]" on-click="onReleaseNotesTap_" label="$i18n{aboutShowReleaseNotes}" external></cr-link-row> + </template> + <template is="dom-if" if="[[showReleaseNotesOffline_(hasReleaseNotes_, + hasInternetConnection_)]]"> <cr-link-row class="hr" id="releaseNotesOffline" - hidden="[[hasInternetConnection_]]" on-click="onReleaseNotesTap_" label="$i18n{aboutShowReleaseNotes}" title="$i18n{aboutReleaseNotesOffline}" external></cr-link-row>
diff --git a/chrome/browser/resources/settings/chromeos/os_about_page/os_about_page.js b/chrome/browser/resources/settings/chromeos/os_about_page/os_about_page.js index 8d48bf7..498acd3 100644 --- a/chrome/browser/resources/settings/chromeos/os_about_page/os_about_page.js +++ b/chrome/browser/resources/settings/chromeos/os_about_page/os_about_page.js
@@ -317,6 +317,23 @@ }, /** + * @return {boolean} + * @private + */ + showReleaseNotesOnline_() { + return this.hasReleaseNotes_ && this.hasInternetConnection_; + }, + + /** + * @return {boolean} + * @private + */ + showReleaseNotesOffline_() { + return this.hasReleaseNotes_ && !this.hasInternetConnection_; + }, + + + /** * @return {string} * @private */
diff --git a/chrome/browser/resources/settings/languages_page/languages_page.js b/chrome/browser/resources/settings/languages_page/languages_page.js index deb7972f..f0545ed 100644 --- a/chrome/browser/resources/settings/languages_page/languages_page.js +++ b/chrome/browser/resources/settings/languages_page/languages_page.js
@@ -106,9 +106,6 @@ return []; }, }, - - /** @private {string|undefined} */ - languageSyncedWithBrowserEnableSpellchecking_: String, // </if> /** @@ -641,29 +638,12 @@ // Hide list of spell check languages if there is only 1 language // and we don't need to display any errors for that language + + // TODO(crbug/1124888): Make hideSpellCheckLanugages_ a computed property this.hideSpellCheckLanguages_ = !singleLanguage.isManaged && singleLanguage.downloadDictionaryFailureCount === 0; - - // Turn off spell check if spell check for the 1 remaining language is - // off - if (!singleLanguage.spellCheckEnabled) { - this.setPrefValue('browser.enable_spellchecking', false); - this.languageSyncedWithBrowserEnableSpellchecking_ = - singleLanguage.language.code; - } - - // Undo the sync if spell check appeared as turned off for the language - // because a download was still in progress. This only occurs when - // Settings is loaded for the very first time and dictionaries have not - // been downloaded yet. - if (this.languageSyncedWithBrowserEnableSpellchecking_ === - singleLanguage.language.code && - singleLanguage.spellCheckEnabled) { - this.setPrefValue('browser.enable_spellchecking', true); - } } else { this.hideSpellCheckLanguages_ = false; - this.languageSyncedWithBrowserEnableSpellchecking_ = undefined; } },
diff --git a/chrome/browser/resources/settings/route.js b/chrome/browser/resources/settings/route.js index 162b5ec..8f61f71e 100644 --- a/chrome/browser/resources/settings/route.js +++ b/chrome/browser/resources/settings/route.js
@@ -132,15 +132,12 @@ if (visibility.autofill !== false) { r.AUTOFILL = r.BASIC.createSection('/autofill', 'autofill'); r.PASSWORDS = r.AUTOFILL.createChild('/passwords'); + r.CHECK_PASSWORDS = r.PASSWORDS.createChild('check'); if (loadTimeData.getBoolean('enableAccountStorage')) { r.DEVICE_PASSWORDS = r.PASSWORDS.createChild('device'); } - if (loadTimeData.getBoolean('enablePasswordCheck')) { - r.CHECK_PASSWORDS = r.PASSWORDS.createChild('check'); - } - r.PAYMENTS = r.AUTOFILL.createChild('/payments'); r.ADDRESSES = r.AUTOFILL.createChild('/addresses'); }
diff --git a/chrome/browser/sharing/sharing_ui_controller.h b/chrome/browser/sharing/sharing_ui_controller.h index 7f03554..43b86775 100644 --- a/chrome/browser/sharing/sharing_ui_controller.h +++ b/chrome/browser/sharing/sharing_ui_controller.h
@@ -24,7 +24,6 @@ #include "components/sync/protocol/device_info_specifics.pb.h" #include "components/sync_device_info/device_info.h" #include "ui/views/controls/styled_label.h" -#include "ui/views/controls/styled_label_listener.h" #include "url/origin.h" class SharingDialog;
diff --git a/chrome/browser/spellchecker/spellcheck_service.cc b/chrome/browser/spellchecker/spellcheck_service.cc index 563483f..0925657 100644 --- a/chrome/browser/spellchecker/spellcheck_service.cc +++ b/chrome/browser/spellchecker/spellcheck_service.cc
@@ -829,8 +829,15 @@ // If there are no hunspell dictionaries to load, then immediately let the // renderers know the new state. - if (hunspell_dictionaries_.empty()) + if (hunspell_dictionaries_.empty()) { +#if !defined(OS_MAC) + // Only update non-MacOS platform because basic spell check on Mac OS + // is controlled by OS and doesn't depend on users' dictionaries pref + user_prefs::UserPrefs::Get(context_)->SetBoolean( + spellcheck::prefs::kSpellCheckEnable, false); +#endif // !defined(OS_MAC) InitForAllRenderers(); + } } void SpellcheckService::OnUseSpellingServiceChanged() {
diff --git a/chrome/browser/spellchecker/spellcheck_service_browsertest.cc b/chrome/browser/spellchecker/spellcheck_service_browsertest.cc index b90df83..da20411c 100644 --- a/chrome/browser/spellchecker/spellcheck_service_browsertest.cc +++ b/chrome/browser/spellchecker/spellcheck_service_browsertest.cc
@@ -149,11 +149,6 @@ spellcheck->OnCustomDictionaryChanged(change); } - void SetSingleLanguageDictionary(const std::string& single_dictionary) { - prefs_->SetString(spellcheck::prefs::kSpellCheckDictionary, - single_dictionary); - } - void SetMultiLingualDictionaries(const std::string& multiple_dictionaries) { base::ListValue dictionaries_value; dictionaries_value.AppendStrings( @@ -335,6 +330,16 @@ GetPrefs()->GetBoolean(spellcheck::prefs::kSpellCheckUseSpellingService)); } +#if !defined(OS_MAC) +IN_PROC_BROWSER_TEST_F(SpellcheckServiceBrowserTest, + DisableSpellcheckIfDictionaryIsEmpty) { + InitSpellcheck(true, "", "en-US"); + SetMultiLingualDictionaries(""); + + EXPECT_FALSE(GetPrefs()->GetBoolean(spellcheck::prefs::kSpellCheckEnable)); +} +#endif // !defined(OS_MAC) + // Removing a spellcheck language from accept languages should remove it from // spellcheck languages list as well. IN_PROC_BROWSER_TEST_F(SpellcheckServiceBrowserTest,
diff --git a/chrome/browser/sync/profile_sync_service_android.cc b/chrome/browser/sync/profile_sync_service_android.cc index 713e0fa..d790875 100644 --- a/chrome/browser/sync/profile_sync_service_android.cc +++ b/chrome/browser/sync/profile_sync_service_android.cc
@@ -392,6 +392,20 @@ return sync_service_->RequiresClientUpgrade(); } +void ProfileSyncServiceAndroid::SetDecoupledFromAndroidMasterSync( + JNIEnv* env, + const base::android::JavaParamRef<jobject>& obj) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + sync_service_->SetDecoupledFromAndroidMasterSync(); +} + +jboolean ProfileSyncServiceAndroid::GetDecoupledFromAndroidMasterSync( + JNIEnv* env, + const base::android::JavaParamRef<jobject>& obj) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + return sync_service_->GetDecoupledFromAndroidMasterSync(); +} + jboolean ProfileSyncServiceAndroid::IsPassphrasePrompted( JNIEnv* env, const JavaParamRef<jobject>& obj) {
diff --git a/chrome/browser/sync/profile_sync_service_android.h b/chrome/browser/sync/profile_sync_service_android.h index 74a55033..28dbd24 100644 --- a/chrome/browser/sync/profile_sync_service_android.h +++ b/chrome/browser/sync/profile_sync_service_android.h
@@ -131,6 +131,12 @@ jboolean RequiresClientUpgrade( JNIEnv* env, const base::android::JavaParamRef<jobject>& obj); + void SetDecoupledFromAndroidMasterSync( + JNIEnv* env, + const base::android::JavaParamRef<jobject>& obj); + jboolean GetDecoupledFromAndroidMasterSync( + JNIEnv* env, + const base::android::JavaParamRef<jobject>& obj); // Pure SyncPrefs calls. jboolean IsPassphrasePrompted(
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings.grd b/chrome/browser/ui/android/strings/android_chrome_strings.grd index 34bb275..6294de4 100644 --- a/chrome/browser/ui/android/strings/android_chrome_strings.grd +++ b/chrome/browser/ui/android/strings/android_chrome_strings.grd
@@ -2491,9 +2491,6 @@ <message name="IDS_SIGNIN_PROMO_CHOOSE_ANOTHER_ACCOUNT" desc="Button that the user can press if they want to select a different account before signing in. This button is shown below 'Continue as Joe Doe' button that signs user in with default account."> Choose another account </message> - <message name="IDS_SIGNIN_PROMO_STATUS_MESSAGE" desc="Title string for 'Turn on sync' sync promos."> - Sync is off - </message> <message name="IDS_SYNC_PROMO_TURN_ON_SYNC" desc="Button that the user can press if they want to turn on sync with this account."> Turn on sync </message>
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_SIGNIN_PROMO_STATUS_MESSAGE.png.sha1 b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_SIGNIN_PROMO_STATUS_MESSAGE.png.sha1 deleted file mode 100644 index 305d3b01..0000000 --- a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_SIGNIN_PROMO_STATUS_MESSAGE.png.sha1 +++ /dev/null
@@ -1 +0,0 @@ -e9f89af85ba18833c1eb62aa3654062ab3da1146 \ No newline at end of file
diff --git a/chrome/browser/ui/android/strings/translations/android_chrome_strings_bn.xtb b/chrome/browser/ui/android/strings/translations/android_chrome_strings_bn.xtb index c4d54d0..48f911d 100644 --- a/chrome/browser/ui/android/strings/translations/android_chrome_strings_bn.xtb +++ b/chrome/browser/ui/android/strings/translations/android_chrome_strings_bn.xtb
@@ -1,6 +1,7 @@ <?xml version="1.0" ?> <!DOCTYPE translationbundle> <translationbundle lang="bn"> +<translation id="1013149566889033026">একটি নতুন ছদ্মবেশী মোড খুলে যাবে</translation> <translation id="1028699632127661925"><ph name="DEVICE_NAME" />-এ পাঠানো হচ্ছে...</translation> <translation id="103269572468856066">এই সাইট ও অ্যাপের ডেটাও মুছে ফেলতে চান?</translation> <translation id="1036348656032585052">বন্ধ করুন</translation> @@ -345,6 +346,7 @@ <translation id="3775705724665058594">আপনার ডিভাইসে পাঠান</translation> <translation id="3778956594442850293">হোম স্ক্রিনে যোগ করা হয়েছে</translation> <translation id="3789841737615482174">ইনস্টল করুন</translation> +<translation id="3800748312755064483">কিছু সময়ের সাইন-ইন করুন</translation> <translation id="3810838688059735925">ভিডিও</translation> <translation id="3810973564298564668">পরিচালনা</translation> <translation id="3819178904835489326"><ph name="NUMBER_OF_DOWNLOADS" />টি ডাউনলোড মোছা হয়েছে</translation>
diff --git a/chrome/browser/ui/passwords/manage_passwords_ui_controller.cc b/chrome/browser/ui/passwords/manage_passwords_ui_controller.cc index c488d5b..1bdc604 100644 --- a/chrome/browser/ui/passwords/manage_passwords_ui_controller.cc +++ b/chrome/browser/ui/passwords/manage_passwords_ui_controller.cc
@@ -616,15 +616,8 @@ void ManagePasswordsUIController::NavigateToPasswordCheckup( password_manager::PasswordCheckReferrer referrer) { - if (base::FeatureList::IsEnabled( - password_manager::features::kPasswordCheck)) { - chrome::ShowPasswordCheck( - chrome::FindBrowserWithWebContents(web_contents())); - password_manager::LogPasswordCheckReferrer(referrer); - } else { - NavigateToPasswordCheckupPage( - Profile::FromBrowserContext(web_contents()->GetBrowserContext())); - } + chrome::ShowPasswordCheck(chrome::FindBrowserWithWebContents(web_contents())); + password_manager::LogPasswordCheckReferrer(referrer); } void ManagePasswordsUIController::EnableSync(const AccountInfo& account,
diff --git a/chrome/browser/ui/thumbnails/thumbnail_tab_helper.cc b/chrome/browser/ui/thumbnails/thumbnail_tab_helper.cc index feeb1cf6..8692627 100644 --- a/chrome/browser/ui/thumbnails/thumbnail_tab_helper.cc +++ b/chrome/browser/ui/thumbnails/thumbnail_tab_helper.cc
@@ -284,6 +284,7 @@ return; start_video_capture_time_ = base::TimeTicks::Now(); + got_first_frame_ = false; // Figure out how large we want the capture target to be. last_frame_capture_info_ = @@ -304,11 +305,18 @@ } void ThumbnailTabHelper::StopVideoCapture() { - if (video_capturer_) { - video_capturer_->Stop(); - video_capturer_.reset(); + if (!video_capturer_) { + DCHECK_EQ(start_video_capture_time_, base::TimeTicks()); + return; } + video_capturer_->Stop(); + video_capturer_.reset(); + + UMA_HISTOGRAM_MEDIUM_TIMES( + "Tab.Preview.VideoCaptureDuration", + base::TimeTicks::Now() - start_video_capture_time_); + start_video_capture_time_ = base::TimeTicks(); } @@ -344,10 +352,10 @@ return; } - if (start_video_capture_time_ != base::TimeTicks()) { + if (!got_first_frame_) { UMA_HISTOGRAM_TIMES("Tab.Preview.TimeToFirstUsableFrameAfterStartCapture", time_of_call - start_video_capture_time_); - start_video_capture_time_ = base::TimeTicks(); + got_first_frame_ = true; } // The SkBitmap's pixels will be marked as immutable, but the installPixels()
diff --git a/chrome/browser/ui/thumbnails/thumbnail_tab_helper.h b/chrome/browser/ui/thumbnails/thumbnail_tab_helper.h index c2660bcd..9ba8bff 100644 --- a/chrome/browser/ui/thumbnails/thumbnail_tab_helper.h +++ b/chrome/browser/ui/thumbnails/thumbnail_tab_helper.h
@@ -99,6 +99,9 @@ // Times for computing metrics. base::TimeTicks start_video_capture_time_; + // Whether the first frame has been received after StartVideoCapture(). + bool got_first_frame_ = false; + // The thumbnail maintained by this instance. scoped_refptr<ThumbnailImage> thumbnail_;
diff --git a/chrome/browser/ui/views/apps/app_dialog/app_uninstall_dialog_view.cc b/chrome/browser/ui/views/apps/app_dialog/app_uninstall_dialog_view.cc index e3916e22..632e052 100644 --- a/chrome/browser/ui/views/apps/app_dialog/app_uninstall_dialog_view.cc +++ b/chrome/browser/ui/views/apps/app_dialog/app_uninstall_dialog_view.cc
@@ -191,27 +191,13 @@ } void AppUninstallDialogView::InitializeCheckbox(const GURL& app_launch_url) { - std::unique_ptr<views::StyledLabel> checkbox_label; std::vector<base::string16> replacements; - size_t offset; - base::string16 learn_more_text = - l10n_util::GetStringUTF16(IDS_APP_UNINSTALL_PROMPT_LEARN_MORE); - replacements.push_back(url_formatter::FormatUrlForSecurityDisplay( app_launch_url, url_formatter::SchemeDisplay::OMIT_CRYPTOGRAPHIC)); - if (google_util::IsGoogleHostname(app_launch_url.host_piece(), - google_util::ALLOW_SUBDOMAIN)) { - replacements.push_back(learn_more_text); - - checkbox_label = std::make_unique<views::StyledLabel>(this); - std::vector<size_t> offsets; - checkbox_label->SetText(l10n_util::GetStringFUTF16( - IDS_APP_UNINSTALL_PROMPT_REMOVE_DATA_CHECKBOX_FOR_GOOGLE, replacements, - &offsets)); - DCHECK_EQ(replacements.size(), offsets.size()); - offset = offsets.back(); - } else { + const bool is_google = google_util::IsGoogleHostname( + app_launch_url.host_piece(), google_util::ALLOW_SUBDOMAIN); + if (!is_google) { auto domain = net::registry_controlled_domains::GetDomainAndRegistry( app_launch_url, net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES); @@ -219,17 +205,21 @@ domain[0] = base::ToUpperASCII(domain[0]); replacements.push_back(base::ASCIIToUTF16(domain)); - replacements.push_back(learn_more_text); - - checkbox_label = std::make_unique<views::StyledLabel>(this); - std::vector<size_t> offsets; - checkbox_label->SetText(l10n_util::GetStringFUTF16( - IDS_APP_UNINSTALL_PROMPT_REMOVE_DATA_CHECKBOX_FOR_NON_GOOGLE, - replacements, &offsets)); - DCHECK_EQ(replacements.size(), offsets.size()); - offset = offsets.back(); } + base::string16 learn_more_text = + l10n_util::GetStringUTF16(IDS_APP_UNINSTALL_PROMPT_LEARN_MORE); + replacements.push_back(learn_more_text); + + auto checkbox_label = std::make_unique<views::StyledLabel>(this); + std::vector<size_t> offsets; + checkbox_label->SetText(l10n_util::GetStringFUTF16( + is_google ? IDS_APP_UNINSTALL_PROMPT_REMOVE_DATA_CHECKBOX_FOR_GOOGLE + : IDS_APP_UNINSTALL_PROMPT_REMOVE_DATA_CHECKBOX_FOR_NON_GOOGLE, + replacements, &offsets)); + DCHECK_EQ(replacements.size(), offsets.size()); + const size_t offset = offsets.back(); + checkbox_label->AddStyleRange( gfx::Range(offset, offset + learn_more_text.length()), views::StyledLabel::RangeStyleInfo::CreateForLink());
diff --git a/chrome/browser/ui/views/apps/app_info_dialog/app_info_summary_panel.cc b/chrome/browser/ui/views/apps/app_info_dialog/app_info_summary_panel.cc index 536151b..824ed57 100644 --- a/chrome/browser/ui/views/apps/app_info_dialog/app_info_summary_panel.cc +++ b/chrome/browser/ui/views/apps/app_info_dialog/app_info_summary_panel.cc
@@ -200,7 +200,8 @@ std::make_unique<views::Combobox>(launch_options_combobox_model_.get()); launch_options_combobox->SetAccessibleName( l10n_util::GetStringUTF16(IDS_APPLICATION_INFO_LAUNCH_OPTIONS_ACCNAME)); - launch_options_combobox->set_listener(this); + launch_options_combobox->set_callback(base::BindRepeating( + &AppInfoSummaryPanel::OnPerformAction, base::Unretained(this))); launch_options_combobox->SetSelectedIndex( launch_options_combobox_model_->GetIndexForLaunchType(GetLaunchType())); @@ -224,12 +225,9 @@ } void AppInfoSummaryPanel::OnPerformAction(views::Combobox* combobox) { - if (combobox == launch_options_combobox_) { - SetLaunchType(launch_options_combobox_model_->GetLaunchTypeAtIndex( - launch_options_combobox_->GetSelectedIndex())); - } else { - NOTREACHED(); - } + DCHECK(combobox == launch_options_combobox_); + SetLaunchType(launch_options_combobox_model_->GetLaunchTypeAtIndex( + launch_options_combobox_->GetSelectedIndex())); } void AppInfoSummaryPanel::StartCalculatingAppSize() {
diff --git a/chrome/browser/ui/views/apps/app_info_dialog/app_info_summary_panel.h b/chrome/browser/ui/views/apps/app_info_dialog/app_info_summary_panel.h index 78618f02..d57a5bf 100644 --- a/chrome/browser/ui/views/apps/app_info_dialog/app_info_summary_panel.h +++ b/chrome/browser/ui/views/apps/app_info_dialog/app_info_summary_panel.h
@@ -13,7 +13,6 @@ #include "base/memory/weak_ptr.h" #include "chrome/browser/ui/views/apps/app_info_dialog/app_info_panel.h" #include "extensions/common/constants.h" -#include "ui/views/controls/combobox/combobox_listener.h" class LaunchOptionsComboboxModel; class Profile; @@ -31,7 +30,6 @@ // The summary panel of the app info dialog, which provides basic information // and controls related to the app. class AppInfoSummaryPanel : public AppInfoPanel, - public views::ComboboxListener, public base::SupportsWeakPtr<AppInfoSummaryPanel> { public: AppInfoSummaryPanel(Profile* profile, const extensions::Extension* app); @@ -45,8 +43,8 @@ void AddLaunchOptionControl(views::View* vertical_stack); void AddSubviews(); - // Overridden from views::ComboboxListener: - void OnPerformAction(views::Combobox* combobox) override; + // Called when the combobox selection changes. + void OnPerformAction(views::Combobox* combobox); // Called asynchronously to calculate and update the size of the app displayed // in the dialog.
diff --git a/chrome/browser/ui/views/autofill/autofill_popup_view_native_views.cc b/chrome/browser/ui/views/autofill/autofill_popup_view_native_views.cc index a7f79db5..ca5d8e9 100644 --- a/chrome/browser/ui/views/autofill/autofill_popup_view_native_views.cc +++ b/chrome/browser/ui/views/autofill/autofill_popup_view_native_views.cc
@@ -970,7 +970,7 @@ AutofillPopupViewNativeViews* popup_view, int line_number) : popup_view_(popup_view), line_number_(line_number) { - set_notify_enter_exit_on_child(true); + SetNotifyEnterExitOnChild(true); } void AutofillPopupRowView::Init() {
diff --git a/chrome/browser/ui/views/autofill/payments/card_unmask_prompt_views.cc b/chrome/browser/ui/views/autofill/payments/card_unmask_prompt_views.cc index 7d839d8..4f41556 100644 --- a/chrome/browser/ui/views/autofill/payments/card_unmask_prompt_views.cc +++ b/chrome/browser/ui/views/autofill/payments/card_unmask_prompt_views.cc
@@ -360,12 +360,14 @@ // Add the month and year comboboxes if the expiration date is needed. auto month_input = std::make_unique<views::Combobox>(&month_combobox_model_); - month_input->set_listener(this); + month_input->set_callback(base::BindRepeating( + &CardUnmaskPromptViews::OnPerformAction, base::Unretained(this))); month_input->SetAccessibleName( l10n_util::GetStringUTF16(IDS_AUTOFILL_CARD_UNMASK_EXPIRATION_MONTH)); month_input_ = input_row->AddChildView(std::move(month_input)); auto year_input = std::make_unique<views::Combobox>(&year_combobox_model_); - year_input->set_listener(this); + year_input->set_callback(base::BindRepeating( + &CardUnmaskPromptViews::OnPerformAction, base::Unretained(this))); year_input->SetAccessibleName( l10n_util::GetStringUTF16(IDS_AUTOFILL_CARD_UNMASK_EXPIRATION_YEAR)); year_input_ = input_row->AddChildView(std::move(year_input));
diff --git a/chrome/browser/ui/views/autofill/payments/card_unmask_prompt_views.h b/chrome/browser/ui/views/autofill/payments/card_unmask_prompt_views.h index ef01c5e..54c6c44d 100644 --- a/chrome/browser/ui/views/autofill/payments/card_unmask_prompt_views.h +++ b/chrome/browser/ui/views/autofill/payments/card_unmask_prompt_views.h
@@ -11,16 +11,16 @@ #include "chrome/browser/ui/autofill/payments/autofill_dialog_models.h" #include "components/autofill/core/browser/ui/payments/card_unmask_prompt_view.h" #include "ui/views/bubble/bubble_dialog_delegate_view.h" -#include "ui/views/controls/combobox/combobox_listener.h" #include "ui/views/controls/textfield/textfield_controller.h" #include "ui/views/window/dialog_delegate.h" namespace content { class WebContents; -} +} // namespace content namespace views { class Checkbox; +class Combobox; class Label; class Textfield; class Throbber; @@ -31,7 +31,6 @@ class CardUnmaskPromptController; class CardUnmaskPromptViews : public CardUnmaskPromptView, - public views::ComboboxListener, public views::BubbleDialogDelegateView, public views::TextfieldController { public: @@ -39,7 +38,7 @@ content::WebContents* web_contents); ~CardUnmaskPromptViews() override; - // CardUnmaskPromptView + // CardUnmaskPromptView: void Show() override; void ControllerGone() override; void DisableAndWaitForVerification() override; @@ -66,9 +65,6 @@ void ContentsChanged(views::Textfield* sender, const base::string16& new_contents) override; - // views::ComboboxListener - void OnPerformAction(views::Combobox* combobox) override; - private: friend class CardUnmaskPromptViewTesterViews; @@ -83,6 +79,8 @@ void LinkClicked(); + void OnPerformAction(views::Combobox* combobox); + CardUnmaskPromptController* controller_; content::WebContents* web_contents_;
diff --git a/chrome/browser/ui/views/autofill/payments/local_card_migration_dialog_view.cc b/chrome/browser/ui/views/autofill/payments/local_card_migration_dialog_view.cc index db1bfd38..98b4fe8 100644 --- a/chrome/browser/ui/views/autofill/payments/local_card_migration_dialog_view.cc +++ b/chrome/browser/ui/views/autofill/payments/local_card_migration_dialog_view.cc
@@ -305,14 +305,13 @@ AddChildView(new views::Separator()); - legal_message_container_ = new LegalMessageView( + legal_message_container_ = AddChildView(std::make_unique<LegalMessageView>( controller->GetLegalMessageLines(), base::BindRepeating( &LocalCardMigrationDialogController::OnLegalMessageLinkClicked, - base::Unretained(controller_))); + base::Unretained(controller_)))); legal_message_container_->SetBorder( views::CreateEmptyBorder(kMigrationDialogInsets)); - AddChildView(legal_message_container_); } ~LocalCardMigrationOfferView() override {}
diff --git a/chrome/browser/ui/views/autofill/payments/payments_view_util.cc b/chrome/browser/ui/views/autofill/payments/payments_view_util.cc index c45dc07..c7449ff8 100644 --- a/chrome/browser/ui/views/autofill/payments/payments_view_util.cc +++ b/chrome/browser/ui/views/autofill/payments/payments_view_util.cc
@@ -4,6 +4,7 @@ #include "chrome/browser/ui/views/autofill/payments/payments_view_util.h" +#include "base/util/ranges/algorithm.h" #include "build/branding_buildflags.h" #include "chrome/app/vector_icons/vector_icons.h" #include "chrome/browser/ui/views/chrome_layout_provider.h" @@ -148,26 +149,18 @@ } } -LegalMessageView::~LegalMessageView() {} +LegalMessageView::~LegalMessageView() = default; void LegalMessageView::StyledLabelLinkClicked(views::StyledLabel* label, const gfx::Range& range, int event_flags) { - // Index of |label| within its parent's view hierarchy is the same as the - // legal message line index. DCHECK this assumption to guard against future - // layout changes. - DCHECK_EQ(label->parent()->children().size(), legal_message_lines_.size()); - - const std::vector<LegalMessageLine::Link>& links = - legal_message_lines_[label->parent()->GetIndexOf(label)].links(); - for (const LegalMessageLine::Link& link : links) { - if (link.range == range) { - callback_.Run(link.url); - return; - } - } - // |range| was not found. - NOTREACHED(); + const int label_index = GetIndexOf(label); + DCHECK_LT(size_t{label_index}, legal_message_lines_.size()); + const auto& links = legal_message_lines_[label_index].links(); + const auto it = + util::ranges::find(links, range, &LegalMessageLine::Link::range); + DCHECK(it != links.end()); + callback_.Run(it->url); } PaymentsBubbleClosedReason GetPaymentsBubbleClosedReasonFromWidgetClosedReason(
diff --git a/chrome/browser/ui/views/autofill/payments/save_card_offer_bubble_views.cc b/chrome/browser/ui/views/autofill/payments/save_card_offer_bubble_views.cc index c9f6f55a0ea..bfec965 100644 --- a/chrome/browser/ui/views/autofill/payments/save_card_offer_bubble_views.cc +++ b/chrome/browser/ui/views/autofill/payments/save_card_offer_bubble_views.cc
@@ -127,11 +127,6 @@ DialogModelChanged(); } -void SaveCardOfferBubbleViews::OnPerformAction(views::Combobox* sender) { - DCHECK(month_input_dropdown_ == sender || year_input_dropdown_ == sender); - DialogModelChanged(); -} - SaveCardOfferBubbleViews::~SaveCardOfferBubbleViews() {} std::unique_ptr<views::View> SaveCardOfferBubbleViews::CreateMainContentView() { @@ -231,7 +226,8 @@ // Set up the month and year comboboxes. month_input_dropdown_ = new views::Combobox(&month_combobox_model_); - month_input_dropdown_->set_listener(this); + month_input_dropdown_->set_closure(base::BindRepeating( + &SaveCardOfferBubbleViews::DialogModelChanged, base::Unretained(this))); month_input_dropdown_->SetAccessibleName( l10n_util::GetStringUTF16(IDS_AUTOFILL_DIALOG_PLACEHOLDER_EXPIRY_MONTH)); month_input_dropdown_->SetID(DialogViewId::EXPIRATION_DATE_DROPBOX_MONTH); @@ -245,7 +241,8 @@ } year_input_dropdown_ = new views::Combobox(&year_combobox_model_); - year_input_dropdown_->set_listener(this); + year_input_dropdown_->set_closure(base::BindRepeating( + &SaveCardOfferBubbleViews::DialogModelChanged, base::Unretained(this))); year_input_dropdown_->SetAccessibleName( l10n_util::GetStringUTF16(IDS_AUTOFILL_DIALOG_PLACEHOLDER_EXPIRY_YEAR)); year_input_dropdown_->SetID(DialogViewId::EXPIRATION_DATE_DROPBOX_YEAR);
diff --git a/chrome/browser/ui/views/autofill/payments/save_card_offer_bubble_views.h b/chrome/browser/ui/views/autofill/payments/save_card_offer_bubble_views.h index 8d8a458..16255f3 100644 --- a/chrome/browser/ui/views/autofill/payments/save_card_offer_bubble_views.h +++ b/chrome/browser/ui/views/autofill/payments/save_card_offer_bubble_views.h
@@ -8,12 +8,15 @@ #include "chrome/browser/ui/autofill/payments/autofill_dialog_models.h" #include "chrome/browser/ui/views/autofill/payments/payments_view_util.h" #include "chrome/browser/ui/views/autofill/payments/save_card_bubble_views.h" -#include "ui/views/controls/combobox/combobox_listener.h" #include "ui/views/controls/textfield/textfield_controller.h" namespace content { class WebContents; -} +} // namespace content + +namespace views { +class Combobox; +} // namespace views namespace autofill { @@ -22,7 +25,6 @@ // previously saved. It includes a description of the card that is being saved // and an [Save] button. (Non-material UI's include a [No Thanks] button). class SaveCardOfferBubbleViews : public SaveCardBubbleViews, - public views::ComboboxListener, public views::TextfieldController { public: // Bubble will be anchored to |anchor_view|. @@ -39,10 +41,9 @@ void ContentsChanged(views::Textfield* sender, const base::string16& new_contents) override; - // views::ComboboxListener: - void OnPerformAction(views::Combobox* combobox) override; - private: + ~SaveCardOfferBubbleViews() override; + std::unique_ptr<views::View> CreateMainContentView() override; std::unique_ptr<views::View> CreateRequestExpirationDateView(); @@ -50,8 +51,6 @@ void LinkClicked(const GURL& url); - ~SaveCardOfferBubbleViews() override; - views::Textfield* cardholder_name_textfield_ = nullptr; LegalMessageView* legal_message_view_ = nullptr;
diff --git a/chrome/browser/ui/views/content_setting_bubble_contents.cc b/chrome/browser/ui/views/content_setting_bubble_contents.cc index 71d620e3..5fb0211 100644 --- a/chrome/browser/ui/views/content_setting_bubble_contents.cc +++ b/chrome/browser/ui/views/content_setting_bubble_contents.cc
@@ -89,7 +89,7 @@ // and/or camera). class MediaMenuBlock : public views::View { public: - MediaMenuBlock(views::ComboboxListener* listener, + MediaMenuBlock(views::Combobox::PerformActionCallback callback, ContentSettingBubbleModel::MediaMenuMap media) { const ChromeLayoutProvider* provider = ChromeLayoutProvider::Get(); @@ -137,7 +137,7 @@ auto combobox = std::make_unique<views::Combobox>(std::move(combobox_model)); combobox->SetEnabled(combobox_enabled); - combobox->set_listener(listener); + combobox->set_callback(callback); combobox->SetSelectedIndex(combobox_selected_index); layout->AddView(std::move(combobox)); } @@ -517,7 +517,10 @@ // Layout code for the media device menus. if (content_setting_bubble_model_->AsMediaStreamBubbleModel()) { rows.push_back( - {std::make_unique<MediaMenuBlock>(this, bubble_content.media_menus), + {std::make_unique<MediaMenuBlock>( + base::BindRepeating(&ContentSettingBubbleContents::OnPerformAction, + base::Unretained(this)), + bubble_content.media_menus), LayoutRowType::INDENTED}); }
diff --git a/chrome/browser/ui/views/content_setting_bubble_contents.h b/chrome/browser/ui/views/content_setting_bubble_contents.h index 13044feb..795c132 100644 --- a/chrome/browser/ui/views/content_setting_bubble_contents.h +++ b/chrome/browser/ui/views/content_setting_bubble_contents.h
@@ -18,14 +18,14 @@ #include "ui/views/controls/button/button.h" #include "ui/views/controls/button/checkbox.h" #include "ui/views/controls/button/radio_button.h" -#include "ui/views/controls/combobox/combobox_listener.h" namespace views { +class Combobox; class ImageButton; class RadioButton; class LabelButton; class Link; -} +} // namespace views // ContentSettingBubbleContents is used when the user turns on different kinds // of content blocking (e.g. "block images"). When viewing a page with blocked @@ -39,7 +39,6 @@ class ContentSettingBubbleContents : public content::WebContentsObserver, public views::BubbleDialogDelegateView, public views::ButtonListener, - public views::ComboboxListener, public ContentSettingBubbleModel::Owner { public: ContentSettingBubbleContents( @@ -81,6 +80,8 @@ void LinkClicked(views::Link* source, int event_flags); void CustomLinkClicked(); + void OnPerformAction(views::Combobox* combobox); + // content::WebContentsObserver: void DidFinishNavigation( content::NavigationHandle* navigation_handle) override; @@ -90,8 +91,6 @@ // views::ButtonListener: void ButtonPressed(views::Button* sender, const ui::Event& event) override; - // views::ComboboxListener: - void OnPerformAction(views::Combobox* combobox) override; // Provides data for this bubble. std::unique_ptr<ContentSettingBubbleModel> content_setting_bubble_model_;
diff --git a/chrome/browser/ui/views/extensions/extensions_menu_item_view.cc b/chrome/browser/ui/views/extensions/extensions_menu_item_view.cc index de7a8b7..c7de8af 100644 --- a/chrome/browser/ui/views/extensions/extensions_menu_item_view.cc +++ b/chrome/browser/ui/views/extensions/extensions_menu_item_view.cc
@@ -54,7 +54,7 @@ model_(ToolbarActionsModel::Get(browser->profile())) { // Set so the extension button receives enter/exit on children to retain hover // status when hovering child views. - set_notify_enter_exit_on_child(true); + SetNotifyEnterExitOnChild(true); context_menu_controller_ = std::make_unique<ExtensionContextMenuController>( nullptr, controller_.get());
diff --git a/chrome/browser/ui/views/global_media_controls/media_notification_container_impl_view.cc b/chrome/browser/ui/views/global_media_controls/media_notification_container_impl_view.cc index 1111ea9d..731fdec 100644 --- a/chrome/browser/ui/views/global_media_controls/media_notification_container_impl_view.cc +++ b/chrome/browser/ui/views/global_media_controls/media_notification_container_impl_view.cc
@@ -80,7 +80,7 @@ SetLayoutManager(std::make_unique<views::BoxLayout>( views::BoxLayout::Orientation::kVertical)); SetPreferredSize(kNormalSize); - set_notify_enter_exit_on_child(true); + SetNotifyEnterExitOnChild(true); SetFocusBehavior(views::View::FocusBehavior::ALWAYS); SetTooltipText( l10n_util::GetStringUTF16(IDS_GLOBAL_MEDIA_CONTROLS_BACK_TO_TAB));
diff --git a/chrome/browser/ui/views/location_bar/icon_label_bubble_view.cc b/chrome/browser/ui/views/location_bar/icon_label_bubble_view.cc index 2ca68f51..8b91b74 100644 --- a/chrome/browser/ui/views/location_bar/icon_label_bubble_view.cc +++ b/chrome/browser/ui/views/location_bar/icon_label_bubble_view.cc
@@ -148,7 +148,7 @@ UpdateBorder(); - set_notify_enter_exit_on_child(true); + SetNotifyEnterExitOnChild(true); // Flip the canvas in RTL so the separator is drawn on the correct side. separator_view_->EnableCanvasFlippingForRTLUI(true);
diff --git a/chrome/browser/ui/views/location_bar/zoom_bubble_view.cc b/chrome/browser/ui/views/location_bar/zoom_bubble_view.cc index a8252d8..c296287 100644 --- a/chrome/browser/ui/views/location_bar/zoom_bubble_view.cc +++ b/chrome/browser/ui/views/location_bar/zoom_bubble_view.cc
@@ -294,7 +294,7 @@ chrome::FindBrowserWithWebContents(web_contents)->session_id()) { SetButtons(ui::DIALOG_BUTTON_NONE); - set_notify_enter_exit_on_child(true); + SetNotifyEnterExitOnChild(true); if (immersive_mode_controller_) immersive_mode_controller_->AddObserver(this); UseCompactMargins();
diff --git a/chrome/browser/ui/views/media_router/cast_dialog_sink_button.cc b/chrome/browser/ui/views/media_router/cast_dialog_sink_button.cc index af665c7..9638e46 100644 --- a/chrome/browser/ui/views/media_router/cast_dialog_sink_button.cc +++ b/chrome/browser/ui/views/media_router/cast_dialog_sink_button.cc
@@ -10,7 +10,6 @@ #include "base/strings/utf_string_conversions.h" #include "build/branding_buildflags.h" #include "chrome/app/vector_icons/vector_icons.h" -#include "chrome/browser/ui/views/chrome_layout_provider.h" #include "chrome/browser/ui/views/chrome_typography.h" #include "chrome/browser/ui/views/media_router/cast_dialog_helper.h" #include "chrome/grit/generated_resources.h" @@ -21,11 +20,11 @@ #include "ui/base/ui_base_types.h" #include "ui/gfx/color_palette.h" #include "ui/gfx/paint_vector_icon.h" +#include "ui/native_theme/native_theme.h" #include "ui/views/animation/ink_drop_impl.h" +#include "ui/views/controls/color_tracking_icon_view.h" #include "ui/views/controls/styled_label.h" #include "ui/views/controls/throbber.h" -#include "ui/views/layout/fill_layout.h" -#include "ui/views/layout/layout_provider.h" #include "ui/views/vector_icons.h" #if BUILDFLAG(GOOGLE_CHROME_BRANDING) @@ -36,25 +35,6 @@ namespace { -// A view that represents the primary icon for a sink issue. This class is used -// to ensure its color is kept in sync with current theme. -class SinkIssueIconView : public views::ImageView { - public: - SinkIssueIconView() { - SetBorder(views::CreateEmptyBorder(kPrimaryIconBorder)); - } - ~SinkIssueIconView() override = default; - - // views::ImageView: - void OnThemeChanged() override { - views::ImageView::OnThemeChanged(); - const SkColor icon_color = GetNativeTheme()->GetSystemColor( - ui::NativeTheme::kColorId_DefaultIconColor); - SetImage(gfx::CreateVectorIcon(::vector_icons::kInfoOutlineIcon, - kPrimaryIconSize, icon_color)); - } -}; - gfx::ImageSkia CreateSinkIcon(SinkIconType icon_type, bool enabled = true) { const gfx::VectorIcon* vector_icon; switch (icon_type) { @@ -112,7 +92,10 @@ return CreatePrimaryIconView(gfx::CreateVectorIcon( kGenericStopIcon, kPrimaryIconSize, gfx::kGoogleBlue500)); } else if (sink.issue) { - return std::make_unique<SinkIssueIconView>(); + auto icon = std::make_unique<views::ColorTrackingIconView>( + ::vector_icons::kInfoOutlineIcon, kPrimaryIconSize); + icon->SetBorder(views::CreateEmptyBorder(kPrimaryIconBorder)); + return icon; } else if (sink.state == UIMediaSinkState::CONNECTING || sink.state == UIMediaSinkState::DISCONNECTING) { return CreateThrobber();
diff --git a/chrome/browser/ui/views/page_info/page_info_bubble_view.cc b/chrome/browser/ui/views/page_info/page_info_bubble_view.cc index c46a47c6..e75f219 100644 --- a/chrome/browser/ui/views/page_info/page_info_bubble_view.cc +++ b/chrome/browser/ui/views/page_info/page_info_bubble_view.cc
@@ -49,7 +49,6 @@ #include "components/dom_distiller/core/url_constants.h" #include "components/dom_distiller/core/url_utils.h" #include "components/page_info/page_info.h" -#include "components/password_manager/core/common/password_manager_features.h" #include "components/safe_browsing/buildflags.h" #include "components/strings/grit/components_chromium_strings.h" #include "components/strings/grit/components_strings.h" @@ -60,6 +59,7 @@ #include "ui/base/l10n/l10n_util.h" #include "ui/base/models/simple_menu_model.h" #include "ui/base/resource/resource_bundle.h" +#include "ui/base/window_open_disposition.h" #include "ui/gfx/canvas.h" #include "ui/gfx/font_list.h" #include "ui/gfx/geometry/insets.h" @@ -129,9 +129,9 @@ } // namespace -// |BubbleHeaderView| is the UI element (view) that represents the header of the -// |PageInfoBubbleView|. The header shows the status of the site's -// identity check and the name of the site's identity. +// BubbleHeaderView is the UI element (view) that represents the header of a +// PageInfoBubbleView. The header shows the status of the site's identity check +// and the name of the site's identity. class BubbleHeaderView : public views::View, public views::StyledLabelListener { public: BubbleHeaderView(PageInfoBubbleView* bubble, int side_margin); @@ -238,7 +238,7 @@ views::GridLayout::FILL, views::GridLayout::LEADING); } -BubbleHeaderView::~BubbleHeaderView() {} +BubbleHeaderView::~BubbleHeaderView() = default; void BubbleHeaderView::StyledLabelLinkClicked(views::StyledLabel* label, const gfx::Range& range, @@ -318,17 +318,9 @@ password_reuse_button_container_->RemoveAllChildViews(true /* delete */); } - int change_password_template = 0; - if (is_saved_password && !base::FeatureList::IsEnabled( - password_manager::features::kPasswordCheck)) { - change_password_template = 0; - } else { - change_password_template = - is_saved_password && base::FeatureList::IsEnabled( - password_manager::features::kPasswordCheck) - ? IDS_PAGE_INFO_CHECK_PASSWORDS_BUTTON - : IDS_PAGE_INFO_CHANGE_PASSWORD_BUTTON; - } + int change_password_template = is_saved_password + ? IDS_PAGE_INFO_CHECK_PASSWORDS_BUTTON + : IDS_PAGE_INFO_CHANGE_PASSWORD_BUTTON; std::unique_ptr<views::MdTextButton> change_password_button; if (change_password_template) { @@ -481,8 +473,9 @@ } else { web_contents()->OpenURL(content::OpenURLParams( GURL(chrome::kPageInfoHelpCenterURL), content::Referrer(), - WindowOpenDisposition::NEW_FOREGROUND_TAB, ui::PAGE_TRANSITION_LINK, - false)); + ui::DispositionFromEventFlags( + event_flags, WindowOpenDisposition::NEW_FOREGROUND_TAB), + ui::PAGE_TRANSITION_LINK, false)); presenter_->RecordPageInfoAction( PageInfo::PAGE_INFO_CONNECTION_HELP_OPENED); }
diff --git a/chrome/browser/ui/views/page_info/page_info_bubble_view_browsertest.cc b/chrome/browser/ui/views/page_info/page_info_bubble_view_browsertest.cc index e9b53f3..f3289306 100644 --- a/chrome/browser/ui/views/page_info/page_info_bubble_view_browsertest.cc +++ b/chrome/browser/ui/views/page_info/page_info_bubble_view_browsertest.cc
@@ -7,7 +7,6 @@ #include "base/run_loop.h" #include "base/scoped_observer.h" #include "base/test/metrics/histogram_tester.h" -#include "base/test/scoped_feature_list.h" #include "build/build_config.h" #include "chrome/browser/safe_browsing/chrome_password_protection_service.h" #include "chrome/browser/ssl/security_state_tab_helper.h" @@ -29,7 +28,6 @@ #include "components/content_settings/core/common/content_settings_types.h" #include "components/page_info/page_info.h" #include "components/password_manager/core/browser/password_manager_metrics_util.h" -#include "components/password_manager/core/common/password_manager_features.h" #include "components/safe_browsing/content/password_protection/metrics_util.h" #include "components/safe_browsing/core/features.h" #include "components/strings/grit/components_strings.h" @@ -130,11 +128,7 @@ class PageInfoBubbleViewBrowserTest : public DialogBrowserTest { public: - PageInfoBubbleViewBrowserTest() { - feature_list_.InitAndEnableFeature( - password_manager::features::kPasswordCheck); - } - + PageInfoBubbleViewBrowserTest() = default; // DialogBrowserTest: void ShowUi(const std::string& name) override { // Bubble dialogs' bounds may exceed the display's work area. @@ -386,7 +380,6 @@ private: std::vector<PageInfoBubbleView::PageInfoBubbleViewID> expected_identifiers_; - base::test::ScopedFeatureList feature_list_; DISALLOW_COPY_AND_ASSIGN(PageInfoBubbleViewBrowserTest); };
diff --git a/chrome/browser/ui/views/page_info/permission_selector_row.cc b/chrome/browser/ui/views/page_info/permission_selector_row.cc index 2d043bc..c9a0cb3 100644 --- a/chrome/browser/ui/views/page_info/permission_selector_row.cc +++ b/chrome/browser/ui/views/page_info/permission_selector_row.cc
@@ -23,7 +23,6 @@ #include "ui/gfx/color_utils.h" #include "ui/gfx/image/image.h" #include "ui/views/controls/combobox/combobox.h" -#include "ui/views/controls/combobox/combobox_listener.h" #include "ui/views/controls/image_view.h" #include "ui/views/controls/label.h" #include "ui/views/layout/grid_layout.h" @@ -93,8 +92,7 @@ } // The |PermissionCombobox| provides a combobox for selecting a permission type. -class PermissionCombobox : public views::Combobox, - public views::ComboboxListener { +class PermissionCombobox : public views::Combobox { public: PermissionCombobox(ComboboxModelAdapter* model, bool enabled, @@ -109,8 +107,7 @@ gfx::Size CalculatePreferredSize() const override; private: - // views::ComboboxListener: - void OnPerformAction(Combobox* combobox) override; + void OnPerformAction(Combobox* combobox); ComboboxModelAdapter* model_; @@ -124,7 +121,8 @@ bool enabled, bool use_default) : views::Combobox(model), model_(model) { - set_listener(this); + set_callback(base::BindRepeating(&PermissionCombobox::OnPerformAction, + base::Unretained(this))); SetEnabled(enabled); UpdateSelectedIndex(use_default); SetSizeToLargestLabel(false);
diff --git a/chrome/browser/ui/views/page_info/safety_tip_page_info_bubble_view.cc b/chrome/browser/ui/views/page_info/safety_tip_page_info_bubble_view.cc index 3889bf3..b2a3e43d 100644 --- a/chrome/browser/ui/views/page_info/safety_tip_page_info_bubble_view.cc +++ b/chrome/browser/ui/views/page_info/safety_tip_page_info_bubble_view.cc
@@ -260,6 +260,10 @@ views::StyledLabel* label, const gfx::Range& range, int event_flags) { + OpenHelpCenter(); +} + +void SafetyTipPageInfoBubbleView::OpenHelpCenter() { action_taken_ = SafetyTipInteraction::kLearnMore; OpenHelpCenterFromSafetyTip(web_contents()); }
diff --git a/chrome/browser/ui/views/page_info/safety_tip_page_info_bubble_view.h b/chrome/browser/ui/views/page_info/safety_tip_page_info_bubble_view.h index 9892c4c..9cb8fcd 100644 --- a/chrome/browser/ui/views/page_info/safety_tip_page_info_bubble_view.h +++ b/chrome/browser/ui/views/page_info/safety_tip_page_info_bubble_view.h
@@ -62,7 +62,8 @@ private: friend class SafetyTipPageInfoBubbleViewBrowserTest; - views::StyledLabel* GetLearnMoreLinkForTesting() { return info_button_; } + void OpenHelpCenter(); + views::Button* GetLeaveButtonForTesting() { return leave_button_; } const security_state::SafetyTipStatus safety_tip_status_;
diff --git a/chrome/browser/ui/views/page_info/safety_tip_page_info_bubble_view_browsertest.cc b/chrome/browser/ui/views/page_info/safety_tip_page_info_bubble_view_browsertest.cc index c4ff0b9..94632483ec 100644 --- a/chrome/browser/ui/views/page_info/safety_tip_page_info_bubble_view_browsertest.cc +++ b/chrome/browser/ui/views/page_info/safety_tip_page_info_bubble_view_browsertest.cc
@@ -308,8 +308,7 @@ // This class is a friend to SafetyTipPageInfoBubbleView. auto* bubble = static_cast<SafetyTipPageInfoBubbleView*>( PageInfoBubbleViewBase::GetPageInfoBubbleForTesting()); - bubble->StyledLabelLinkClicked(bubble->GetLearnMoreLinkForTesting(), - gfx::Range(), 0); + bubble->OpenHelpCenter(); } void CloseWarningLeaveSite(Browser* browser) {
diff --git a/chrome/browser/ui/views/passwords/credentials_item_view.cc b/chrome/browser/ui/views/passwords/credentials_item_view.cc index e0d59ba9..121dfa23 100644 --- a/chrome/browser/ui/views/passwords/credentials_item_view.cc +++ b/chrome/browser/ui/views/passwords/credentials_item_view.cc
@@ -64,7 +64,7 @@ int upper_text_style, int lower_text_style) : Button(button_listener), form_(form) { - set_notify_enter_exit_on_child(true); + SetNotifyEnterExitOnChild(true); views::BoxLayout* layout = SetLayoutManager(std::make_unique<views::BoxLayout>( views::BoxLayout::Orientation::kHorizontal));
diff --git a/chrome/browser/ui/views/passwords/password_items_view.cc b/chrome/browser/ui/views/passwords/password_items_view.cc index 09e83482..4e340564 100644 --- a/chrome/browser/ui/views/passwords/password_items_view.cc +++ b/chrome/browser/ui/views/passwords/password_items_view.cc
@@ -36,6 +36,7 @@ #include "ui/views/controls/button/image_button.h" #include "ui/views/controls/button/image_button_factory.h" #include "ui/views/controls/button/md_text_button.h" +#include "ui/views/controls/color_tracking_icon_view.h" #include "ui/views/controls/image_view.h" #include "ui/views/controls/label.h" #include "ui/views/controls/link.h" @@ -61,23 +62,6 @@ UNDO_COLUMN_SET }; -// And ImageView that holds a kGlobeIcon of gfx::kFaviconSize and adapts to -// changes in theme color. Used as a fallback option when the page has no -// favicon. -class GlobeIconImageView : public views::ImageView { - public: - GlobeIconImageView() = default; - ~GlobeIconImageView() override = default; - - // views::View: - void OnThemeChanged() override { - views::ImageView::OnThemeChanged(); - const SkColor icon_color = GetNativeTheme()->GetSystemColor( - ui::NativeTheme::kColorId_DefaultIconColor); - SetImage(gfx::CreateVectorIcon(kGlobeIcon, gfx::kFaviconSize, icon_color)); - } -}; - PasswordItemsViewColumnSetType InferColumnSetTypeFromCredentials( const std::vector<autofill::PasswordForm>& credentials) { if (std::any_of(credentials.begin(), credentials.end(), @@ -310,7 +294,8 @@ // Use a globe fallback until the actual favicon is loaded. if (parent_->favicon_.IsEmpty()) { - layout->AddView(std::make_unique<GlobeIconImageView>()); + layout->AddView(std::make_unique<views::ColorTrackingIconView>( + kGlobeIcon, gfx::kFaviconSize)); } else { auto favicon_view = std::make_unique<views::ImageView>(); favicon_view->SetImage(parent_->favicon_.AsImageSkia());
diff --git a/chrome/browser/ui/views/passwords/password_save_update_with_account_store_view.cc b/chrome/browser/ui/views/passwords/password_save_update_with_account_store_view.cc index fd35f04e..83b9c59 100644 --- a/chrome/browser/ui/views/passwords/password_save_update_with_account_store_view.cc +++ b/chrome/browser/ui/views/passwords/password_save_update_with_account_store_view.cc
@@ -376,7 +376,9 @@ controller_.GetPrimaryAccountEmail(), controller_.GetPrimaryAccountAvatar(ComboboxIconSize()), controller_.IsUsingAccountStore()); - destination_dropdown->set_listener(this); + destination_dropdown->set_callback(base::BindRepeating( + &PasswordSaveUpdateWithAccountStoreView::OnPerformAction, + base::Unretained(this))); destination_dropdown_ = destination_dropdown.get(); } const autofill::PasswordForm& password_form = controller_.pending_password();
diff --git a/chrome/browser/ui/views/passwords/password_save_update_with_account_store_view.h b/chrome/browser/ui/views/passwords/password_save_update_with_account_store_view.h index 070d99f..f464c2f3 100644 --- a/chrome/browser/ui/views/passwords/password_save_update_with_account_store_view.h +++ b/chrome/browser/ui/views/passwords/password_save_update_with_account_store_view.h
@@ -8,7 +8,6 @@ #include "chrome/browser/ui/passwords/bubble_controllers/save_update_with_account_store_bubble_controller.h" #include "chrome/browser/ui/views/passwords/password_bubble_view_base.h" #include "ui/views/controls/button/button.h" -#include "ui/views/controls/combobox/combobox_listener.h" #include "ui/views/layout/animating_layout_manager.h" #include "ui/views/view.h" @@ -33,7 +32,6 @@ class PasswordSaveUpdateWithAccountStoreView : public PasswordBubbleViewBase, public views::ButtonListener, - public views::ComboboxListener, public views::WidgetObserver, public views::AnimatingLayoutManager::Observer { public: @@ -65,10 +63,6 @@ // views::ButtonListener: void ButtonPressed(views::Button* sender, const ui::Event& event) override; - // views::ComboboxListener: - // Used for the destination combobox. - void OnPerformAction(views::Combobox* combobox) override; - // views::WidgetObserver: void OnWidgetDestroying(views::Widget* widget) override; @@ -91,6 +85,8 @@ void UpdateUsernameAndPasswordInModel(); void UpdateBubbleUIElements(); + void OnPerformAction(views::Combobox* combobox); + // Whether we should show the IPH informing the user about the destination // picker and that they can now select where to store the passwords. It // creates (if needed) and queries the |iph_tracker_|
diff --git a/chrome/browser/ui/views/payments/cvc_unmask_view_controller.cc b/chrome/browser/ui/views/payments/cvc_unmask_view_controller.cc index 92acaa37..2c51a8e 100644 --- a/chrome/browser/ui/views/payments/cvc_unmask_view_controller.cc +++ b/chrome/browser/ui/views/payments/cvc_unmask_view_controller.cc
@@ -189,14 +189,16 @@ layout->StartRow(views::GridLayout::kFixedSize, 1); if (requesting_expiration) { auto month = std::make_unique<views::Combobox>(&month_combobox_model_); - month->set_listener(this); + month->set_closure(base::BindRepeating( + &CvcUnmaskViewController::OnPerformAction, base::Unretained(this))); month->SetID(static_cast<int>(DialogViewID::CVC_MONTH)); month->SelectValue(credit_card_.Expiration2DigitMonthAsString()); month->SetInvalid(true); layout->AddView(std::move(month)); auto year = std::make_unique<views::Combobox>(&year_combobox_model_); - year->set_listener(this); + year->set_closure(base::BindRepeating( + &CvcUnmaskViewController::OnPerformAction, base::Unretained(this))); year->SetID(static_cast<int>(DialogViewID::CVC_YEAR)); year->SelectValue(credit_card_.Expiration4DigitYearAsString()); year->SetInvalid(true); @@ -383,7 +385,7 @@ UpdatePayButtonState(); } -void CvcUnmaskViewController::OnPerformAction(views::Combobox* combobox) { +void CvcUnmaskViewController::OnPerformAction() { if (!dialog()->IsInteractive()) return;
diff --git a/chrome/browser/ui/views/payments/cvc_unmask_view_controller.h b/chrome/browser/ui/views/payments/cvc_unmask_view_controller.h index 76ec94c..d81e5f0 100644 --- a/chrome/browser/ui/views/payments/cvc_unmask_view_controller.h +++ b/chrome/browser/ui/views/payments/cvc_unmask_view_controller.h
@@ -15,7 +15,6 @@ #include "components/autofill/core/browser/payments/full_card_request.h" #include "components/autofill/core/browser/payments/payments_client.h" #include "components/autofill/core/browser/payments/risk_data_loader.h" -#include "ui/views/controls/combobox/combobox_listener.h" #include "ui/views/controls/textfield/textfield_controller.h" namespace autofill { @@ -40,7 +39,6 @@ : public PaymentRequestSheetController, public autofill::RiskDataLoader, public autofill::payments::FullCardRequest::UIDelegate, - public views::ComboboxListener, public views::TextfieldController { public: CvcUnmaskViewController( @@ -91,8 +89,7 @@ void ContentsChanged(views::Textfield* sender, const base::string16& new_contents) override; - // views::ComboboxListener: - void OnPerformAction(views::Combobox* combobox) override; + void OnPerformAction(); autofill::MonthComboboxModel month_combobox_model_; autofill::YearComboboxModel year_combobox_model_;
diff --git a/chrome/browser/ui/views/payments/editor_view_controller.cc b/chrome/browser/ui/views/payments/editor_view_controller.cc index 3473bb59..5305585d 100644 --- a/chrome/browser/ui/views/payments/editor_view_controller.cc +++ b/chrome/browser/ui/views/payments/editor_view_controller.cc
@@ -214,7 +214,8 @@ // Using autofill field type as a view ID. combobox->SetID(GetInputFieldViewId(field.type)); - combobox->set_listener(this); + combobox->set_callback(base::BindRepeating( + &EditorViewController::OnPerformAction, base::Unretained(this))); comboboxes_.insert(std::make_pair(combobox.get(), field)); return combobox; } @@ -227,8 +228,7 @@ } void EditorViewController::OnPerformAction(views::Combobox* sender) { - ValidatingCombobox* sender_cast = static_cast<ValidatingCombobox*>(sender); - sender_cast->OnContentsChanged(); + static_cast<ValidatingCombobox*>(sender)->OnContentsChanged(); primary_button()->SetEnabled(ValidateInputFields()); }
diff --git a/chrome/browser/ui/views/payments/editor_view_controller.h b/chrome/browser/ui/views/payments/editor_view_controller.h index 0bcb91a..ac7eec7 100644 --- a/chrome/browser/ui/views/payments/editor_view_controller.h +++ b/chrome/browser/ui/views/payments/editor_view_controller.h
@@ -18,7 +18,6 @@ #include "chrome/browser/ui/views/payments/payment_request_sheet_controller.h" #include "chrome/browser/ui/views/payments/validation_delegate.h" #include "components/autofill/core/browser/field_types.h" -#include "ui/views/controls/combobox/combobox_listener.h" #include "ui/views/controls/textfield/textfield_controller.h" #include "ui/views/view.h" @@ -77,8 +76,7 @@ // The PaymentRequestSheetController subtype for the editor screens of the // Payment Request flow. class EditorViewController : public PaymentRequestSheetController, - public views::TextfieldController, - public views::ComboboxListener { + public views::TextfieldController { public: using TextFieldsMap = std::unordered_map<ValidatingTextfield*, const EditorField>; @@ -152,8 +150,8 @@ bool ShouldShowSecondaryButton() override; void FillContentView(views::View* content_view) override; - // views::ComboboxListener: - void OnPerformAction(views::Combobox* combobox) override; + // Combobox callback. + virtual void OnPerformAction(views::Combobox* combobox); // Update the editor view by removing all it's child views and recreating // the input fields returned by GetFieldDefinitions. Note that
diff --git a/chrome/browser/ui/views/payments/payment_sheet_view_controller.cc b/chrome/browser/ui/views/payments/payment_sheet_view_controller.cc index b18ec56..41d72284 100644 --- a/chrome/browser/ui/views/payments/payment_sheet_view_controller.cc +++ b/chrome/browser/ui/views/payments/payment_sheet_view_controller.cc
@@ -575,13 +575,10 @@ views::StyledLabel* label, const gfx::Range& range, int event_flags) { - if (!dialog()->IsInteractive()) - return; - - // The only thing that can trigger this is the user clicking on the "settings" - // link in the data attribution text. - chrome::ShowSettingsSubPageForProfile(dialog()->GetProfile(), - chrome::kPaymentsSubPage); + if (dialog()->IsInteractive()) { + chrome::ShowSettingsSubPageForProfile(dialog()->GetProfile(), + chrome::kPaymentsSubPage); + } } void PaymentSheetViewController::UpdatePayButtonState(bool enabled) {
diff --git a/chrome/browser/ui/views/payments/payment_sheet_view_controller.h b/chrome/browser/ui/views/payments/payment_sheet_view_controller.h index b51467e08..e7d29c2 100644 --- a/chrome/browser/ui/views/payments/payment_sheet_view_controller.h +++ b/chrome/browser/ui/views/payments/payment_sheet_view_controller.h
@@ -13,10 +13,6 @@ #include "components/payments/content/payment_request_state.h" #include "ui/views/controls/styled_label_listener.h" -namespace views { -class StyledLabel; -} - namespace payments { class PaymentRequestDialogView;
diff --git a/chrome/browser/ui/views/safe_browsing/password_reuse_modal_warning_dialog.cc b/chrome/browser/ui/views/safe_browsing/password_reuse_modal_warning_dialog.cc index ccba3bf..387c357 100644 --- a/chrome/browser/ui/views/safe_browsing/password_reuse_modal_warning_dialog.cc +++ b/chrome/browser/ui/views/safe_browsing/password_reuse_modal_warning_dialog.cc
@@ -14,7 +14,6 @@ #include "chrome/grit/theme_resources.h" #include "components/constrained_window/constrained_window_views.h" #include "components/password_manager/core/browser/password_manager_metrics_util.h" -#include "components/password_manager/core/common/password_manager_features.h" #include "components/safe_browsing/buildflags.h" #include "components/safe_browsing/content/password_protection/metrics_util.h" #include "components/strings/grit/components_strings.h" @@ -88,11 +87,7 @@ case safe_browsing::ReusedPasswordAccountType::NON_GAIA_ENTERPRISE: return l10n_util::GetStringUTF16(IDS_PAGE_INFO_CHANGE_PASSWORD_BUTTON); case safe_browsing::ReusedPasswordAccountType::SAVED_PASSWORD: - if (base::FeatureList::IsEnabled( - password_manager::features::kPasswordCheck)) { - return l10n_util::GetStringUTF16(IDS_PAGE_INFO_CHECK_PASSWORDS_BUTTON); - } - return l10n_util::GetStringUTF16(IDS_CLOSE); + return l10n_util::GetStringUTF16(IDS_PAGE_INFO_CHECK_PASSWORDS_BUTTON); default: return l10n_util::GetStringUTF16(IDS_PAGE_INFO_PROTECT_ACCOUNT_BUTTON); } @@ -126,10 +121,8 @@ password_type_(password_type) { bool show_check_passwords = false; #if BUILDFLAG(FULL_SAFE_BROWSING) - show_check_passwords = base::FeatureList::IsEnabled( - password_manager::features::kPasswordCheck) && - password_type_.account_type() == - ReusedPasswordAccountType::SAVED_PASSWORD; + show_check_passwords = password_type_.account_type() == + ReusedPasswordAccountType::SAVED_PASSWORD; #endif SetShowIcon(true); if (password_type.account_type() !=
diff --git a/chrome/browser/ui/views/safe_browsing/prompt_for_scanning_modal_dialog.cc b/chrome/browser/ui/views/safe_browsing/prompt_for_scanning_modal_dialog.cc index 13d0b312..8f20af1 100644 --- a/chrome/browser/ui/views/safe_browsing/prompt_for_scanning_modal_dialog.cc +++ b/chrome/browser/ui/views/safe_browsing/prompt_for_scanning_modal_dialog.cc
@@ -123,7 +123,9 @@ int event_flags) { web_contents_->OpenURL(content::OpenURLParams( GURL(chrome::kAdvancedProtectionDownloadLearnMoreURL), - content::Referrer(), WindowOpenDisposition::NEW_FOREGROUND_TAB, + content::Referrer(), + ui::DispositionFromEventFlags(event_flags, + WindowOpenDisposition::NEW_FOREGROUND_TAB), ui::PAGE_TRANSITION_LINK, /*is_renderer_initiated=*/false)); }
diff --git a/chrome/browser/ui/views/send_tab_to_self/send_tab_to_self_bubble_device_button.cc b/chrome/browser/ui/views/send_tab_to_self/send_tab_to_self_bubble_device_button.cc index 470ee82..fce4014 100644 --- a/chrome/browser/ui/views/send_tab_to_self/send_tab_to_self_bubble_device_button.cc +++ b/chrome/browser/ui/views/send_tab_to_self/send_tab_to_self_bubble_device_button.cc
@@ -10,44 +10,29 @@ #include "base/strings/utf_string_conversions.h" #include "base/time/time.h" #include "chrome/app/vector_icons/vector_icons.h" +#include "chrome/browser/ui/views/hover_button.h" #include "chrome/grit/generated_resources.h" #include "components/send_tab_to_self/target_device_info.h" #include "components/sync/protocol/sync.pb.h" #include "ui/base/l10n/l10n_util.h" -#include "ui/gfx/color_palette.h" -#include "ui/gfx/paint_vector_icon.h" -#include "ui/native_theme/native_theme.h" +#include "ui/views/controls/button/button.h" +#include "ui/views/controls/color_tracking_icon_view.h" namespace send_tab_to_self { namespace { -// IconView wraps the vector icon to track the color of the current Widget's -// NativeTheme. -class IconView : public views::ImageView { - public: - explicit IconView(const sync_pb::SyncEnums::DeviceType device_type) - : vector_icon_{device_type == sync_pb::SyncEnums::TYPE_PHONE - ? &kHardwareSmartphoneIcon - : &kHardwareComputerIcon} { - constexpr auto kPrimaryIconBorder = gfx::Insets(6); - SetBorder(views::CreateEmptyBorder(kPrimaryIconBorder)); - } - ~IconView() override = default; - - // views::View: - void OnThemeChanged() override { - views::ImageView::OnThemeChanged(); - const SkColor icon_color = GetNativeTheme()->GetSystemColor( - ui::NativeTheme::kColorId_DefaultIconColor); - SetImage( - gfx::CreateVectorIcon(*vector_icon_, kPrimaryIconSize, icon_color)); - } - - private: +std::unique_ptr<views::ColorTrackingIconView> CreateIcon( + const sync_pb::SyncEnums::DeviceType device_type) { static constexpr int kPrimaryIconSize = 20; - const gfx::VectorIcon* vector_icon_; -}; + auto icon = std::make_unique<views::ColorTrackingIconView>( + device_type == sync_pb::SyncEnums::TYPE_PHONE ? kHardwareSmartphoneIcon + : kHardwareComputerIcon, + kPrimaryIconSize); + constexpr auto kPrimaryIconBorder = gfx::Insets(6); + icon->SetBorder(views::CreateEmptyBorder(kPrimaryIconBorder)); + return icon; +} base::string16 GetLastUpdatedTime(const TargetDeviceInfo& device_info) { int time_in_days = @@ -72,7 +57,7 @@ const TargetDeviceInfo& device_info, int button_tag) : HoverButton(button_listener, - std::make_unique<IconView>(device_info.device_type), + CreateIcon(device_info.device_type), base::UTF8ToUTF16(device_info.device_name), GetLastUpdatedTime(device_info)) { device_name_ = device_info.device_name;
diff --git a/chrome/browser/ui/views/session_crashed_bubble_view.cc b/chrome/browser/ui/views/session_crashed_bubble_view.cc index 5c3b65f..7ff37ed 100644 --- a/chrome/browser/ui/views/session_crashed_bubble_view.cc +++ b/chrome/browser/ui/views/session_crashed_bubble_view.cc
@@ -40,6 +40,7 @@ #include "content/public/browser/browser_thread.h" #include "ui/base/buildflags.h" #include "ui/base/l10n/l10n_util.h" +#include "ui/base/window_open_disposition.h" #include "ui/views/controls/button/checkbox.h" #include "ui/views/controls/button/label_button_border.h" #include "ui/views/controls/button/menu_button.h" @@ -294,7 +295,9 @@ int event_flags) { browser_->OpenURL(content::OpenURLParams( GURL("https://support.google.com/chrome/answer/96817"), - content::Referrer(), WindowOpenDisposition::NEW_FOREGROUND_TAB, + content::Referrer(), + ui::DispositionFromEventFlags(event_flags, + WindowOpenDisposition::NEW_FOREGROUND_TAB), ui::PAGE_TRANSITION_LINK, false)); RecordBubbleHistogramValue(SESSION_CRASHED_BUBBLE_HELP); }
diff --git a/chrome/browser/ui/views/sharing/sharing_dialog_view.cc b/chrome/browser/ui/views/sharing/sharing_dialog_view.cc index a0160ecb..72e6fde 100644 --- a/chrome/browser/ui/views/sharing/sharing_dialog_view.cc +++ b/chrome/browser/ui/views/sharing/sharing_dialog_view.cc
@@ -26,10 +26,10 @@ #include "ui/strings/grit/ui_strings.h" #include "ui/views/border.h" #include "ui/views/bubble/bubble_frame_view.h" +#include "ui/views/controls/color_tracking_icon_view.h" #include "ui/views/controls/scroll_view.h" #include "ui/views/controls/styled_label.h" #include "ui/views/layout/box_layout.h" -#include "ui/views/layout/fill_layout.h" #include "url/origin.h" #if defined(OS_CHROMEOS) @@ -39,23 +39,6 @@ namespace { -class VectorIconView : public views::ImageView { - public: - explicit VectorIconView(const gfx::VectorIcon& icon) : icon_(icon) {} - - // views::ImageView - void OnThemeChanged() override { - ImageView::OnThemeChanged(); - constexpr int kPrimaryIconSize = 20; - const SkColor color = GetNativeTheme()->GetSystemColor( - ui::NativeTheme::kColorId_DefaultIconColor); - SetImage(gfx::CreateVectorIcon(icon_, kPrimaryIconSize, color)); - } - - private: - const gfx::VectorIcon& icon_; -}; - class HeaderImageView : public NonAccessibleImageView { public: explicit HeaderImageView(const views::BubbleFrameView* frame_view, @@ -283,6 +266,7 @@ } void SharingDialogView::InitListView() { + constexpr int kPrimaryIconSize = 20; int tag = 0; const gfx::Insets device_border = gfx::Insets(kSharingDialogSpacing, kSharingDialogSpacing * 2, @@ -297,10 +281,11 @@ // Devices: LogSharingDevicesToShow(data_.prefix, kSharingUiDialog, data_.devices.size()); for (const auto& device : data_.devices) { - auto icon = std::make_unique<VectorIconView>( + auto icon = std::make_unique<views::ColorTrackingIconView>( device->device_type() == sync_pb::SyncEnums::TYPE_TABLET ? kTabletIcon - : kHardwareSmartphoneIcon); + : kHardwareSmartphoneIcon, + kPrimaryIconSize); auto dialog_button = std::make_unique<HoverButton>( this, std::move(icon), base::UTF8ToUTF16(device->client_name()), @@ -317,7 +302,8 @@ for (const auto& app : data_.apps) { std::unique_ptr<views::ImageView> icon; if (app.vector_icon) { - icon = std::make_unique<VectorIconView>(*app.vector_icon); + icon = std::make_unique<views::ColorTrackingIconView>(*app.vector_icon, + kPrimaryIconSize); } else { icon = std::make_unique<views::ImageView>(); icon->SetImage(app.image.AsImageSkia());
diff --git a/chrome/browser/ui/views/sharing/sharing_dialog_view_unittest.cc b/chrome/browser/ui/views/sharing/sharing_dialog_view_unittest.cc index cf4fdd0..7742249 100644 --- a/chrome/browser/ui/views/sharing/sharing_dialog_view_unittest.cc +++ b/chrome/browser/ui/views/sharing/sharing_dialog_view_unittest.cc
@@ -21,6 +21,7 @@ #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/base/l10n/l10n_util.h" +#include "ui/events/event_constants.h" #include "ui/events/event_utils.h" #include "ui/strings/grit/ui_strings.h" #include "ui/views/bubble/bubble_dialog_delegate_view.h" @@ -180,8 +181,7 @@ auto dialog_data = CreateDialogData(/*devices=*/0, /*apps=*/0); auto dialog = CreateDialogView(std::move(dialog_data)); - dialog->StyledLabelLinkClicked(/*label=*/nullptr, /*range=*/{}, - /*event_flags=*/0); + dialog->StyledLabelLinkClicked(nullptr, gfx::Range(), ui::EF_NONE); } TEST_F(SharingDialogViewTest, HelpTextClickedOnlyApps) { @@ -191,8 +191,7 @@ auto dialog_data = CreateDialogData(/*devices=*/0, /*apps=*/1); auto dialog = CreateDialogView(std::move(dialog_data)); - dialog->StyledLabelLinkClicked(/*label=*/nullptr, /*range=*/{}, - /*event_flags=*/0); + dialog->StyledLabelLinkClicked(nullptr, gfx::Range(), ui::EF_NONE); } TEST_F(SharingDialogViewTest, ThemeChangedEmptyList) {
diff --git a/chrome/browser/ui/views/tabs/tab.cc b/chrome/browser/ui/views/tabs/tab.cc index 83651a9..80e5df4b 100644 --- a/chrome/browser/ui/views/tabs/tab.cc +++ b/chrome/browser/ui/views/tabs/tab.cc
@@ -193,7 +193,7 @@ // So we get don't get enter/exit on children and don't prematurely stop the // hover. - set_notify_enter_exit_on_child(true); + SetNotifyEnterExitOnChild(true); SetID(VIEW_ID_TAB);
diff --git a/chrome/browser/ui/views/tabs/tab_strip.cc b/chrome/browser/ui/views/tabs/tab_strip.cc index b059df3..d262a0d6 100644 --- a/chrome/browser/ui/views/tabs/tab_strip.cc +++ b/chrome/browser/ui/views/tabs/tab_strip.cc
@@ -2449,7 +2449,7 @@ void TabStrip::Init() { SetID(VIEW_ID_TAB_STRIP); // So we get enter/exit on children to switch stacked layout on and off. - set_notify_enter_exit_on_child(true); + SetNotifyEnterExitOnChild(true); tab_controls_container_ = AddChildView(std::make_unique<TabControlsContainer>());
diff --git a/chrome/browser/ui/views/translate/translate_bubble_view.cc b/chrome/browser/ui/views/translate/translate_bubble_view.cc index aef57f39..a8152b0e 100644 --- a/chrome/browser/ui/views/translate/translate_bubble_view.cc +++ b/chrome/browser/ui/views/translate/translate_bubble_view.cc
@@ -834,7 +834,8 @@ } source_language_combobox->SetID(COMBOBOX_ID_SOURCE_LANGUAGE); - source_language_combobox->set_listener(this); + source_language_combobox->set_callback(base::BindRepeating( + &TranslateBubbleView::OnPerformAction, base::Unretained(this))); source_language_combobox_ = source_language_combobox.get(); auto advanced_done_button = std::make_unique<views::MdTextButton>( @@ -866,7 +867,8 @@ std::make_unique<views::Combobox>(target_language_combobox_model_.get()); target_language_combobox->SetID(COMBOBOX_ID_TARGET_LANGUAGE); - target_language_combobox->set_listener(this); + target_language_combobox->set_callback(base::BindRepeating( + &TranslateBubbleView::OnPerformAction, base::Unretained(this))); target_language_combobox_ = target_language_combobox.get(); auto advanced_done_button = std::make_unique<views::MdTextButton>(
diff --git a/chrome/browser/ui/views/translate/translate_bubble_view.h b/chrome/browser/ui/views/translate/translate_bubble_view.h index 4766176..e328162 100644 --- a/chrome/browser/ui/views/translate/translate_bubble_view.h +++ b/chrome/browser/ui/views/translate/translate_bubble_view.h
@@ -25,7 +25,6 @@ #include "content/public/browser/web_contents_observer.h" #include "ui/base/models/simple_menu_model.h" #include "ui/views/controls/button/button.h" -#include "ui/views/controls/combobox/combobox_listener.h" #include "ui/views/controls/image_view.h" #include "ui/views/controls/label.h" #include "ui/views/controls/menu/menu_runner.h" @@ -37,13 +36,13 @@ namespace views { class Checkbox; +class Combobox; class LabelButton; class View; } // namespace views class TranslateBubbleView : public LocationBarBubbleDelegateView, public views::ButtonListener, - public views::ComboboxListener, public ui::SimpleMenuModel::Delegate, public views::TabbedPaneListener { public: @@ -81,6 +80,8 @@ TranslateBubbleModel* model() { return model_.get(); } + void OnPerformAction(views::Combobox* combobox); + // LocationBarBubbleDelegateView: void Init() override; View* GetInitiallyFocusedView() override; @@ -94,9 +95,6 @@ // views::ButtonListener: void ButtonPressed(views::Button* source, const ui::Event& event) override; - // views::ComboboxListener: - void OnPerformAction(views::Combobox* combobox) override; - // ui::SimpleMenuModel::Delegate: bool IsCommandIdChecked(int command_id) const override; bool IsCommandIdEnabled(int command_id) const override;
diff --git a/chrome/browser/ui/webui/settings/settings_ui.cc b/chrome/browser/ui/webui/settings/settings_ui.cc index 95f4711b..920b416 100644 --- a/chrome/browser/ui/webui/settings/settings_ui.cc +++ b/chrome/browser/ui/webui/settings/settings_ui.cc
@@ -264,10 +264,6 @@ base::FeatureList::IsEnabled(safe_browsing::kEnhancedProtection)); html_source->AddBoolean( - "enablePasswordCheck", - base::FeatureList::IsEnabled(password_manager::features::kPasswordCheck)); - - html_source->AddBoolean( "passwordsWeaknessCheck", base::FeatureList::IsEnabled( password_manager::features::kPasswordsWeaknessCheck));
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt index fcd99ee..45eead8 100644 --- a/chrome/build/linux.pgo.txt +++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@ -chrome-linux-master-1595370378-ba0a034250ef2251ee8fa7ce722cfaaf39079474.profdata +chrome-linux-master-1599738815-c7c05d9aad543471c0ca5060fdc90a37df9de6fc.profdata
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt index 13a4d46..c1b6510 100644 --- a/chrome/build/mac.pgo.txt +++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@ -chrome-mac-master-1599716388-02eae1071f5b6fe6862d29aa135a2ecf5509f01d.profdata +chrome-mac-master-1599738815-ff1bf13166c585a2e1282bb43357481f321e4e87.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt index e9848f9b..35f8b78 100644 --- a/chrome/build/win64.pgo.txt +++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@ -chrome-win64-master-1599651808-28c874736fb144e9b48a72308f081ee03ad277c7.profdata +chrome-win64-master-1599738815-40f6ae90536e6d0f415f1d4a37e068148427b479.profdata
diff --git a/chrome/renderer/autofill/fake_mojo_password_manager_driver.cc b/chrome/renderer/autofill/fake_mojo_password_manager_driver.cc index cb57ba1..710e810 100644 --- a/chrome/renderer/autofill/fake_mojo_password_manager_driver.cc +++ b/chrome/renderer/autofill/fake_mojo_password_manager_driver.cc
@@ -67,16 +67,12 @@ called_check_safe_browsing_reputation_cnt_++; } -void FakeMojoPasswordManagerDriver::ShowManualFallbackForSaving( +void FakeMojoPasswordManagerDriver::InformAboutUserInput( const autofill::FormData& form_data) { - called_show_manual_fallback_for_saving_count_++; + called_inform_about_user_input_count_++; form_data_maybe_submitted_ = form_data; } -void FakeMojoPasswordManagerDriver::HideManualFallbackForSaving() { - called_show_manual_fallback_for_saving_count_ = 0; -} - void FakeMojoPasswordManagerDriver::FocusedInputChanged( autofill::mojom::FocusedFieldType focused_field_type) { last_focused_field_type_ = focused_field_type;
diff --git a/chrome/renderer/autofill/fake_mojo_password_manager_driver.h b/chrome/renderer/autofill/fake_mojo_password_manager_driver.h index 0baa9b0d..30410ea7 100644 --- a/chrome/renderer/autofill/fake_mojo_password_manager_driver.h +++ b/chrome/renderer/autofill/fake_mojo_password_manager_driver.h
@@ -111,8 +111,8 @@ return called_check_safe_browsing_reputation_cnt_; } - int called_show_manual_fallback_for_saving_count() const { - return called_show_manual_fallback_for_saving_count_; + int called_inform_about_user_input_count() const { + return called_inform_about_user_input_count_; } autofill::mojom::FocusedFieldType last_focused_field_type() const { @@ -143,9 +143,8 @@ void CheckSafeBrowsingReputation(const GURL& form_action, const GURL& frame_url) override; - void ShowManualFallbackForSaving( - const autofill::FormData& form_data) override; - void HideManualFallbackForSaving() override; + void InformAboutUserInput(const autofill::FormData& form_data) override; + void FocusedInputChanged( autofill::mojom::FocusedFieldType focused_field_type) override; void LogFirstFillingResult(autofill::FormRendererId form_renderer_id, @@ -181,9 +180,8 @@ // Records number of times CheckSafeBrowsingReputation() gets called. int called_check_safe_browsing_reputation_cnt_ = 0; - // Records the number of request to show manual fallback for password saving. - // If it is zero, the fallback is not available. - int called_show_manual_fallback_for_saving_count_ = 0; + // Records the number of request to inform about user input. + int called_inform_about_user_input_count_ = 0; // Records the last focused field type that FocusedInputChanged() was called // with.
diff --git a/chrome/renderer/autofill/password_autofill_agent_browsertest.cc b/chrome/renderer/autofill/password_autofill_agent_browsertest.cc index fcf5582ab..9fcfe54 100644 --- a/chrome/renderer/autofill/password_autofill_agent_browsertest.cc +++ b/chrome/renderer/autofill/password_autofill_agent_browsertest.cc
@@ -56,6 +56,7 @@ #include "third_party/blink/public/web/win/web_font_rendering.h" #endif +using autofill::FormRendererId; using autofill::FormTracker; using autofill::mojom::FocusedFieldType; using autofill::mojom::PasswordFormFieldPredictionType; @@ -461,8 +462,8 @@ password_element_.UniqueRendererFormControlId()); WebFormElement form = password_element_.Form(); fill_data_.form_renderer_id = - form.IsNull() ? autofill::FormRendererId() - : autofill::FormRendererId(form.UniqueRendererFormId()); + form.IsNull() ? FormRendererId() + : FormRendererId(form.UniqueRendererFormId()); } void UpdateUsernameAndPasswordElements() { @@ -674,18 +675,18 @@ << "Some expected masks are missed in FormData"; } - autofill::FormRendererId GetFormUniqueRendererId(const WebString& form_id) { + FormRendererId GetFormUniqueRendererId(const WebString& form_id) { WebLocalFrame* frame = GetMainFrame(); if (!frame) - return autofill::FormRendererId(); + return FormRendererId(); WebFormElement web_form = frame->GetDocument().GetElementById(form_id).To<WebFormElement>(); - return autofill::FormRendererId(web_form.UniqueRendererFormId()); + return FormRendererId(web_form.UniqueRendererFormId()); } void ExpectFormDataWithUsernameAndPasswordsAndEvent( const autofill::FormData& form_data, - autofill::FormRendererId form_renderer_id, + FormRendererId form_renderer_id, const std::string& username_value, const std::string& password_value, const std::string& new_password_value, @@ -698,7 +699,7 @@ } void ExpectFormSubmittedWithUsernameAndPasswords( - autofill::FormRendererId form_renderer_id, + FormRendererId form_renderer_id, const std::string& username_value, const std::string& password_value, const std::string& new_password_value) { @@ -712,7 +713,7 @@ } void ExpectSameDocumentNavigationWithUsernameAndPasswords( - autofill::FormRendererId form_renderer_id, + FormRendererId form_renderer_id, const std::string& username_value, const std::string& password_value, const std::string& new_password_value, @@ -959,7 +960,7 @@ WebFormElement form_element = document.GetElementById("LoginTestForm").To<WebFormElement>(); fill_data_.form_renderer_id = - autofill::FormRendererId(form_element.UniqueRendererFormId()); + FormRendererId(form_element.UniqueRendererFormId()); SimulateOnFillPasswordForm(fill_data_); histogram_tester_.ExpectTotalCount( @@ -1482,7 +1483,7 @@ // Neither field should have been autocompleted. CheckTextFieldsDOMState("user1", false, std::string(), false); base::RunLoop().RunUntilIdle(); - EXPECT_EQ(0, fake_driver_.called_show_manual_fallback_for_saving_count()); + EXPECT_EQ(0, fake_driver_.called_inform_about_user_input_count()); // Only password field should be autocompleted. EXPECT_TRUE(password_autofill_agent_->FillSuggestion( @@ -1490,7 +1491,7 @@ ASCIIToUTF16(kAlicePassword))); CheckTextFieldsDOMState("user1", false, kAlicePassword, true); base::RunLoop().RunUntilIdle(); - EXPECT_EQ(1, fake_driver_.called_show_manual_fallback_for_saving_count()); + EXPECT_EQ(1, fake_driver_.called_inform_about_user_input_count()); // Try Filling with a different password. Only password should be changed. EXPECT_TRUE(password_autofill_agent_->FillSuggestion( @@ -1498,7 +1499,7 @@ ASCIIToUTF16(kCarolPassword))); CheckTextFieldsDOMState("user1", false, kCarolPassword, true); base::RunLoop().RunUntilIdle(); - EXPECT_EQ(2, fake_driver_.called_show_manual_fallback_for_saving_count()); + EXPECT_EQ(2, fake_driver_.called_inform_about_user_input_count()); } // Tests that |FillSuggestion| properly fills the password if the username field @@ -1807,7 +1808,7 @@ WebFormElement form_element = document.GetElementById("LoginTestForm").To<WebFormElement>(); fill_data_.form_renderer_id = - autofill::FormRendererId(form_element.UniqueRendererFormId()); + FormRendererId(form_element.UniqueRendererFormId()); SimulateOnFillPasswordForm(fill_data_); @@ -2100,7 +2101,7 @@ // PasswordAutofillAgent can still remember the username and the password // typed by the user. TEST_F(PasswordAutofillAgentTest, - DISABLED_RememberLastNonEmptyUsernameAndPasswordOnSubmit_ScriptCleared) { + RememberLastNonEmptyUsernameAndPasswordOnSubmit_ScriptCleared) { LoadHTML(kSignupFormHTML); WebInputElement username_element = GetInputElementByID("random_info"); ASSERT_FALSE(username_element.IsNull()); @@ -2128,8 +2129,9 @@ // Observe that the PasswordAutofillAgent still remembered the last non-empty // username and password and sent that to the browser. - ExpectFormSubmittedWithUsernameAndPasswords(GetFormUniqueRendererId("form"), - "username", "", "random"); + ExpectFormSubmittedWithUsernameAndPasswords( + FormRendererId(username_element.Form().UniqueRendererFormId()), + "username", "", "random"); fake_driver_.form_data_submitted(); } @@ -2157,7 +2159,7 @@ // Similar to RememberLastNonEmptyPasswordOnSubmit_ScriptCleared, but uses the // new password instead of the current password. TEST_F(PasswordAutofillAgentTest, - DISABLED_RememberLastNonEmptyUsernameAndPasswordOnSubmit_New) { + RememberLastNonEmptyUsernameAndPasswordOnSubmit_New) { const char kNewPasswordFormHTML[] = "<FORM name='LoginTestForm' action='http://www.bidule.com'>" " <INPUT type='text' id='username' autocomplete='username'/>" @@ -2180,7 +2182,8 @@ // Observe that the PasswordAutofillAgent still remembered the last non-empty // password and sent that to the browser. ExpectFormSubmittedWithUsernameAndPasswords( - GetFormUniqueRendererId("LoginTestForm"), "temp", "", "random"); + FormRendererId(username_element_.Form().UniqueRendererFormId()), "temp", + "", "random"); } // The user first accepts a suggestion, but then overwrites the password. This @@ -2812,7 +2815,7 @@ FireAjaxSucceeded(); ExpectSameDocumentNavigationWithUsernameAndPasswords( - autofill::FormRendererId(), "Bob", "mypassword", "", + FormRendererId(), "Bob", "mypassword", "", SubmissionIndicatorEvent::XHR_SUCCEEDED); } @@ -2836,7 +2839,7 @@ base::RunLoop().RunUntilIdle(); ExpectSameDocumentNavigationWithUsernameAndPasswords( - autofill::FormRendererId(), "Bob", "mypassword", "", + FormRendererId(), "Bob", "mypassword", "", SubmissionIndicatorEvent::DOM_MUTATION_AFTER_XHR); } @@ -2871,7 +2874,7 @@ PromptForAJAXSubmitAfterDeletingParentElement) { LoadHTML(kDivWrappedFormHTML); UpdateUsernameAndPasswordElements(); - autofill::FormRendererId renderer_id = GetFormUniqueRendererId("form"); + FormRendererId renderer_id = GetFormUniqueRendererId("form"); SimulateUsernameTyping("Bob"); SimulatePasswordTyping("mypassword"); @@ -3304,7 +3307,7 @@ FireAjaxSucceeded(); ExpectSameDocumentNavigationWithUsernameAndPasswords( - autofill::FormRendererId(), "Alice", "mypassword", "", + FormRendererId(), "Alice", "mypassword", "", SubmissionIndicatorEvent::XHR_SUCCEEDED); } } @@ -3330,7 +3333,7 @@ base::RunLoop().RunUntilIdle(); ExpectSameDocumentNavigationWithUsernameAndPasswords( - autofill::FormRendererId(), "Alice", "mypassword", "", + FormRendererId(), "Alice", "mypassword", "", SubmissionIndicatorEvent::DOM_MUTATION_AFTER_XHR); } @@ -3468,8 +3471,7 @@ SameDocumentNavigationSubmissionUsernameIsEmpty) { username_element_.SetValue(WebString()); SimulatePasswordTyping("random"); - autofill::FormRendererId renderer_id = - GetFormUniqueRendererId("LoginTestForm"); + FormRendererId renderer_id = GetFormUniqueRendererId("LoginTestForm"); // Simulate that JavaScript removes the submitted form from DOM. That means // that a submission was successful. @@ -3557,42 +3559,41 @@ TEST_F(PasswordAutofillAgentTest, ManualFallbackForSaving) { EXPECT_CALL(fake_pw_client_, PresaveGeneratedPassword(_, _)).Times(0); - // The users enters a username. No password - no fallback. + // The users enters a username. Inform the driver regardless. SimulateUsernameTyping(kUsernameName); - EXPECT_EQ(0, fake_driver_.called_show_manual_fallback_for_saving_count()); + EXPECT_EQ(1, fake_driver_.called_inform_about_user_input_count()); // The user enters a password. SimulatePasswordTyping(kPasswordName); // SimulateUsernameTyping/SimulatePasswordTyping calls // PasswordAutofillAgent::UpdateStateForTextChange only once. - EXPECT_EQ(1, fake_driver_.called_show_manual_fallback_for_saving_count()); + EXPECT_EQ(2, fake_driver_.called_inform_about_user_input_count()); // Remove one character from the password value. SimulateUserTypingASCIICharacter(ui::VKEY_BACK, true); - EXPECT_EQ(2, fake_driver_.called_show_manual_fallback_for_saving_count()); + EXPECT_EQ(3, fake_driver_.called_inform_about_user_input_count()); // Add one character to the username value. SetFocused(username_element_); SimulateUserTypingASCIICharacter('a', true); - EXPECT_EQ(3, fake_driver_.called_show_manual_fallback_for_saving_count()); + EXPECT_EQ(4, fake_driver_.called_inform_about_user_input_count()); // Remove username value. SimulateUsernameTyping(""); - EXPECT_EQ(4, fake_driver_.called_show_manual_fallback_for_saving_count()); + EXPECT_EQ(5, fake_driver_.called_inform_about_user_input_count()); - // Change the password. Despite of empty username the fallback is still - // there. + // Change the password. SetFocused(password_element_); SimulateUserTypingASCIICharacter('a', true); - EXPECT_EQ(5, fake_driver_.called_show_manual_fallback_for_saving_count()); + EXPECT_EQ(6, fake_driver_.called_inform_about_user_input_count()); - // Remove password value. The fallback should be disabled. + // Remove password value. Inform the driver too. SimulatePasswordTyping(""); - EXPECT_EQ(0, fake_driver_.called_show_manual_fallback_for_saving_count()); + EXPECT_EQ(7, fake_driver_.called_inform_about_user_input_count()); - // The user enters new password. Show the fallback again. + // The user enters new password. SimulateUserTypingASCIICharacter('a', true); - EXPECT_EQ(1, fake_driver_.called_show_manual_fallback_for_saving_count()); + EXPECT_EQ(8, fake_driver_.called_inform_about_user_input_count()); } TEST_F(PasswordAutofillAgentTest, ManualFallbackForSaving_PasswordChangeForm) { @@ -3600,37 +3601,37 @@ UpdateUrlForHTML(kPasswordChangeFormHTML); UpdateUsernameAndPasswordElements(); - // No password to save yet - no fallback. + // No password to save yet - still we should inform the driver. SimulateUsernameTyping(kUsernameName); - EXPECT_EQ(0, fake_driver_.called_show_manual_fallback_for_saving_count()); + EXPECT_EQ(1, fake_driver_.called_inform_about_user_input_count()); // The user enters in the current password field. The fallback should be // available to save the entered value. SimulatePasswordTyping(kPasswordName); // SimulateUsernameTyping/SimulatePasswordTyping calls // PasswordAutofillAgent::UpdateStateForTextChange only once. - EXPECT_EQ(1, fake_driver_.called_show_manual_fallback_for_saving_count()); + EXPECT_EQ(2, fake_driver_.called_inform_about_user_input_count()); - // The user types into the new password field. The fallback should be updated. + // The user types into the new password field. Inform the driver. WebInputElement new_password = GetInputElementByID("newpassword"); ASSERT_FALSE(new_password.IsNull()); SetFocused(new_password); SimulateUserTypingASCIICharacter('a', true); - EXPECT_EQ(2, fake_driver_.called_show_manual_fallback_for_saving_count()); + EXPECT_EQ(3, fake_driver_.called_inform_about_user_input_count()); - // Edits of the confirmation password field trigger fallback updates. + // Edits of the confirmation password field trigger informing the driver. WebInputElement confirmation_password = GetInputElementByID("confirmpassword"); ASSERT_FALSE(confirmation_password.IsNull()); SetFocused(confirmation_password); SimulateUserTypingASCIICharacter('a', true); - EXPECT_EQ(3, fake_driver_.called_show_manual_fallback_for_saving_count()); + EXPECT_EQ(4, fake_driver_.called_inform_about_user_input_count()); - // Clear all password fields. The fallback should be disabled. + // Clear all password fields. The driver should be informed. SimulatePasswordTyping(""); SimulateUserInputChangeForElement(&new_password, ""); SimulateUserInputChangeForElement(&confirmation_password, ""); - EXPECT_EQ(0, fake_driver_.called_show_manual_fallback_for_saving_count()); + EXPECT_EQ(5, fake_driver_.called_inform_about_user_input_count()); } // Tests that information about Gaia reauthentication form is sent to the
diff --git a/chrome/renderer/autofill/password_generation_agent_browsertest.cc b/chrome/renderer/autofill/password_generation_agent_browsertest.cc index e7b7d736..4467efa 100644 --- a/chrome/renderer/autofill/password_generation_agent_browsertest.cc +++ b/chrome/renderer/autofill/password_generation_agent_browsertest.cc
@@ -895,21 +895,20 @@ LoadHTMLWithUserGesture(kAccountCreationFormHTML); SimulateElementRightClick("first_password"); SelectGenerationFallbackAndExpect(true); - EXPECT_EQ(0, fake_driver_.called_show_manual_fallback_for_saving_count()); + EXPECT_EQ(0, fake_driver_.called_inform_about_user_input_count()); base::string16 password = base::ASCIIToUTF16("random_password"); EXPECT_CALL(fake_pw_client_, PresaveGeneratedPassword(_, Eq(password))) .WillOnce(testing::InvokeWithoutArgs([this]() { // Make sure that generation event was propagated to the browser before // the fallback showing. Otherwise, the fallback for saving provides a // save bubble instead of a confirmation bubble. - EXPECT_EQ(0, - fake_driver_.called_show_manual_fallback_for_saving_count()); + EXPECT_EQ(0, fake_driver_.called_inform_about_user_input_count()); })); password_generation_->GeneratedPasswordAccepted(password); fake_driver_.Flush(); // Two fallback requests are expected because generation changes either new // password and confirmation fields. - EXPECT_EQ(2, fake_driver_.called_show_manual_fallback_for_saving_count()); + EXPECT_EQ(2, fake_driver_.called_inform_about_user_input_count()); } TEST_F(PasswordGenerationAgentTest, FormClassifierDisabled) {
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index 1c415d2..93b8ed83 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -773,6 +773,7 @@ "//mojo/public/cpp/system", "//net", "//net:test_support", + "//pdf:features", "//ppapi/buildflags", "//printing/buildflags", "//rlz/buildflags", @@ -3258,6 +3259,7 @@ "../browser/component_updater/autofill_states_component_installer_unittest.cc", "../browser/component_updater/chrome_component_updater_configurator_unittest.cc", "../browser/component_updater/crl_set_component_installer_unittest.cc", + "../browser/component_updater/first_party_sets_component_installer_unittest.cc", "../browser/component_updater/floc_blocklist_component_installer_unittest.cc", "../browser/component_updater/games_component_installer_unittest.cc", "../browser/component_updater/optimization_hints_component_installer_unittest.cc",
diff --git a/chrome/test/data/webui/settings/autofill_page_test.js b/chrome/test/data/webui/settings/autofill_page_test.js index c5b81de2..853eeea 100644 --- a/chrome/test/data/webui/settings/autofill_page_test.js +++ b/chrome/test/data/webui/settings/autofill_page_test.js
@@ -300,13 +300,6 @@ let passwordManager; let pluralString; - suiteSetup(function() { - // Forces navigation to Google Password Manager to be off by default. - loadTimeData.overrideValues({ - enablePasswordCheck: true, - }); - }); - setup(function() { openWindowProxy = new TestOpenWindowProxy(); OpenWindowProxyImpl.instance_ = openWindowProxy;
diff --git a/chrome/test/data/webui/settings/chromeos/os_about_page_tests.js b/chrome/test/data/webui/settings/chromeos/os_about_page_tests.js index 10e6f55f..b8eac4f 100644 --- a/chrome/test/data/webui/settings/chromeos/os_about_page_tests.js +++ b/chrome/test/data/webui/settings/chromeos/os_about_page_tests.js
@@ -300,8 +300,7 @@ async function checkReleaseNotesOnline(isShowing) { await aboutBrowserProxy.whenCalled('getEnabledReleaseNotes'); const releaseNotesOnlineEl = page.$$('#releaseNotesOnline'); - assertTrue(!!releaseNotesOnlineEl); - assertEquals(isShowing, !releaseNotesOnlineEl.hidden); + assertEquals(isShowing, !!releaseNotesOnlineEl); } /** @@ -313,8 +312,7 @@ async function checkReleaseNotesOffline(isShowing) { await aboutBrowserProxy.whenCalled('getEnabledReleaseNotes'); const releaseNotesOfflineEl = page.$$('#releaseNotesOffline'); - assertTrue(!!releaseNotesOfflineEl); - assertEquals(isShowing, !releaseNotesOfflineEl.hidden); + assertEquals(isShowing, !!releaseNotesOfflineEl); } /** @@ -324,9 +322,9 @@ async function checkReleaseNotesDisabled() { await aboutBrowserProxy.whenCalled('getEnabledReleaseNotes'); const releaseNotesOnlineEl = page.$$('#releaseNotesOnline'); - assertTrue(!releaseNotesOnlineEl); + assertFalse(!!releaseNotesOnlineEl); const releaseNotesOfflineEl = page.$$('#releaseNotesOffline'); - assertTrue(!releaseNotesOfflineEl); + assertFalse(!!releaseNotesOfflineEl); } aboutBrowserProxy.setReleaseNotes(false);
diff --git a/chrome/test/data/webui/settings/cr_settings_v3_browsertest.js b/chrome/test/data/webui/settings/cr_settings_v3_browsertest.js index dfbf541f..d350758 100644 --- a/chrome/test/data/webui/settings/cr_settings_v3_browsertest.js +++ b/chrome/test/data/webui/settings/cr_settings_v3_browsertest.js
@@ -217,11 +217,6 @@ get browsePreload() { return 'chrome://settings/test_loader.html?module=settings/passwords_section_test.js'; } - - /** @override */ - get featureListInternal() { - return {enabled: ['password_manager::features::kPasswordCheck']}; - } }; // Flaky on Debug builds https://crbug.com/1090931 @@ -287,11 +282,6 @@ get browsePreload() { return 'chrome://settings/test_loader.html?module=settings/password_check_test.js'; } - - /** @override */ - get featureListInternal() { - return {enabled: ['password_manager::features::kPasswordCheck']}; - } }; TEST_F('CrSettingsPasswordsCheckV3Test', 'All', function() { @@ -304,15 +294,6 @@ get browsePreload() { return 'chrome://settings/test_loader.html?module=settings/safety_check_page_test.js'; } - - /** @override */ - get featureListInternal() { - return { - enabled: [ - 'password_manager::features::kPasswordCheck', - ], - }; - } }; TEST_F('CrSettingsSafetyCheckPageV3Test', 'All', function() {
diff --git a/chrome/test/data/webui/settings/languages_page_tests.js b/chrome/test/data/webui/settings/languages_page_tests.js index 116b558a..4ea94d99 100644 --- a/chrome/test/data/webui/settings/languages_page_tests.js +++ b/chrome/test/data/webui/settings/languages_page_tests.js
@@ -631,27 +631,34 @@ const list = languagesPage.$.spellCheckLanguagesList; assertFalse(list.hidden); + assertTrue(languagesPage.$$('#enableSpellcheckingToggle').checked); + assertDeepEquals( + ['en-US'], languageHelper.getPref('spellcheck.dictionaries').value); - languageHelper.setPrefValue('intl.accept_languages', 'en-US'); - if (isChromeOS) { - languageHelper.setPrefValue( - 'settings.language.preferred_languages', 'en-US'); - } - - // Update supported languages to just 1 language English with spell - // check disabled for that language - languageHelper.setPrefValue('spellcheck.dictionaries', []); + // Update supported languages to just 1 language should hide list. + languageHelper.setPrefValue(languagesPref, 'en-US'); + flush(); assertTrue(list.hidden); - assertFalse(languageHelper.getPref('browser.enable_spellchecking').value); - // Update supported languages to just 1 language English that finished - // downloading and is now ready - languageHelper.setPrefValue('spellcheck.dictionaries', ['en-US']); - languageHelper.set('languages.enabled.0.downloadDictionaryStatus', { - isReady: true, - }); + // Disable spell check should keep list hidden and remove the single + // language from dictionaries. + languagesPage.$$('#enableSpellcheckingToggle').click(); + flush(); + assertTrue(list.hidden); - assertTrue(languageHelper.getPref('browser.enable_spellchecking').value); + assertFalse(languagesPage.$$('#enableSpellcheckingToggle').checked); + assertDeepEquals( + [], languageHelper.getPref('spellcheck.dictionaries').value); + + // Enable spell check should keep list hidden and add the single language + // to dictionaries. + languagesPage.$$('#enableSpellcheckingToggle').click(); + flush(); + + assertTrue(list.hidden); + assertTrue(languagesPage.$$('#enableSpellcheckingToggle').checked); + assertDeepEquals( + ['en-US'], languageHelper.getPref('spellcheck.dictionaries').value); }); test('no supported languages', () => {
diff --git a/chrome/test/data/webui/settings/password_check_test.js b/chrome/test/data/webui/settings/password_check_test.js index b4a7ca5..0c1602d0 100644 --- a/chrome/test/data/webui/settings/password_check_test.js +++ b/chrome/test/data/webui/settings/password_check_test.js
@@ -120,10 +120,6 @@ /** @type {TestPasswordManagerProxy} */ let passwordManager = null; - suiteSetup(function() { - loadTimeData.overrideValues({enablePasswordCheck: true}); - }); - setup(function() { PolymerTest.clearBody(); // Override the PasswordManagerImpl for testing.
diff --git a/chrome/test/data/webui/settings/passwords_section_test.js b/chrome/test/data/webui/settings/passwords_section_test.js index 137d601..66de7a11 100644 --- a/chrome/test/data/webui/settings/passwords_section_test.js +++ b/chrome/test/data/webui/settings/passwords_section_test.js
@@ -319,10 +319,6 @@ /** @type {TestPluralStringProxy} */ let pluralString = null; - suiteSetup(function() { - loadTimeData.overrideValues({enablePasswordCheck: true}); - }); - setup(function() { PolymerTest.clearBody(); // Override the PasswordManagerImpl for testing.
diff --git a/chrome/test/data/webui/settings/safety_check_page_test.js b/chrome/test/data/webui/settings/safety_check_page_test.js index 9942d54..de8713d 100644 --- a/chrome/test/data/webui/settings/safety_check_page_test.js +++ b/chrome/test/data/webui/settings/safety_check_page_test.js
@@ -551,7 +551,6 @@ buttonClass: 'action-button', }); - loadTimeData.overrideValues({enablePasswordCheck: true}); const passwordManager = new TestPasswordManagerProxy(); PasswordManagerImpl.instance_ = passwordManager;
diff --git a/chrome/updater/control_service_in_process.cc b/chrome/updater/control_service_in_process.cc index 58a338eb..96eedb64 100644 --- a/chrome/updater/control_service_in_process.cc +++ b/chrome/updater/control_service_in_process.cc
@@ -4,12 +4,19 @@ #include "chrome/updater/control_service_in_process.h" +#include <string> +#include <vector> + #include "base/bind.h" #include "base/callback.h" +#include "base/files/file_path.h" +#include "base/files/file_util.h" #include "base/logging.h" #include "base/threading/sequenced_task_runner_handle.h" #include "base/time/time.h" #include "chrome/updater/configurator.h" +#include "chrome/updater/constants.h" +#include "chrome/updater/persisted_data.h" #include "chrome/updater/prefs.h" #include "chrome/updater/update_service_in_process.h" #include "components/prefs/pref_service.h" @@ -19,11 +26,18 @@ ControlServiceInProcess::ControlServiceInProcess( scoped_refptr<updater::Configurator> config) : config_(config), + persisted_data_( + base::MakeRefCounted<PersistedData>(config_->GetPrefService())), main_task_runner_(base::SequencedTaskRunnerHandle::Get()) {} void ControlServiceInProcess::Run(base::OnceClosure callback) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + RemoveApps(); + MaybeCheckForUpdates(std::move(callback)); +} + +void ControlServiceInProcess::MaybeCheckForUpdates(base::OnceClosure callback) { const base::Time lastUpdateTime = config_->GetPrefService()->GetTime(kPrefUpdateTime); @@ -58,6 +72,20 @@ base::BindOnce(std::move(callback)), config_)); } +void ControlServiceInProcess::RemoveApps() { + for (const auto& app_id : persisted_data_->GetAppIds()) { + // Skip if app_id is equal to updater app id. + if (app_id == kUpdaterAppId) + continue; + + const base::FilePath ecp = persisted_data_->GetExistenceCheckerPath(app_id); + if (!ecp.empty() && base::PathExists(ecp)) { + if (!persisted_data_->RemoveApp(app_id)) + VLOG(0) << "Could not remove registration of app " << app_id; + } + } +} + void ControlServiceInProcess::Uninitialize() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); PrefsCommitPendingWrites(config_->GetPrefService());
diff --git a/chrome/updater/control_service_in_process.h b/chrome/updater/control_service_in_process.h index 1c1e9ce0..c5abd6a 100644 --- a/chrome/updater/control_service_in_process.h +++ b/chrome/updater/control_service_in_process.h
@@ -17,6 +17,7 @@ namespace updater { class Configurator; +class PersistedData; // All functions and callbacks must be called on the same sequence. class ControlServiceInProcess : public ControlService { @@ -33,7 +34,16 @@ SEQUENCE_CHECKER(sequence_checker_); + // Checks for updates of all registered applications if it has been longer + // than the last check time by NextCheckDelay() amount defined in the config. + void MaybeCheckForUpdates(base::OnceClosure callback); + + // Provides a way to remove apps from the persisted data if the app is no + // longer installed on the machine. + void RemoveApps(); + scoped_refptr<updater::Configurator> config_; + scoped_refptr<updater::PersistedData> persisted_data_; scoped_refptr<base::SequencedTaskRunner> main_task_runner_; };
diff --git a/chrome/updater/persisted_data.cc b/chrome/updater/persisted_data.cc index 360ef2b..5d5e375 100644 --- a/chrome/updater/persisted_data.cc +++ b/chrome/updater/persisted_data.cc
@@ -103,6 +103,17 @@ SetTag(rq.app_id, rq.tag); } +bool PersistedData::RemoveApp(const std::string& id) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + if (!pref_service_) + return false; + + DictionaryPrefUpdate update(pref_service_, kPersistedDataPreference); + base::Value* apps = update->FindDictKey("apps"); + + return apps ? apps->RemoveKey(id) : false; +} + std::vector<std::string> PersistedData::GetAppIds() const { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
diff --git a/chrome/updater/persisted_data.h b/chrome/updater/persisted_data.h index f0078e7..212ef5f 100644 --- a/chrome/updater/persisted_data.h +++ b/chrome/updater/persisted_data.h
@@ -65,6 +65,9 @@ // persistent data store. void RegisterApp(const RegistrationRequest& rq); + // This function removes a registered application from the persistent store. + bool RemoveApp(const std::string& id); + // Returns the app ids of the applications registered in prefs, if the // application has a valid version. std::vector<std::string> GetAppIds() const; @@ -83,7 +86,6 @@ void SetString(const std::string& id, const std::string& key, const std::string& value); - SEQUENCE_CHECKER(sequence_checker_); PrefService* pref_service_ = nullptr; // Not owned by this class.
diff --git a/chrome/updater/persisted_data_unittest.cc b/chrome/updater/persisted_data_unittest.cc index aee84bc..000114a 100644 --- a/chrome/updater/persisted_data_unittest.cc +++ b/chrome/updater/persisted_data_unittest.cc
@@ -2,12 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "chrome/updater/persisted_data.h" + #include <memory> #include <string> +#include "base/files/file_path.h" #include "base/stl_util.h" #include "base/version.h" -#include "chrome/updater/persisted_data.h" #include "chrome/updater/registration_data.h" #include "components/prefs/testing_pref_service.h" #include "components/update_client/update_client.h" @@ -82,4 +84,36 @@ metadata->GetProductVersion("someappid").GetString().c_str()); } +TEST(PersistedDataTest, RemoveAppId) { + auto pref = std::make_unique<TestingPrefServiceSimple>(); + update_client::RegisterPrefs(pref->registry()); + auto metadata = base::MakeRefCounted<PersistedData>(pref.get()); + + RegistrationRequest data; + data.app_id = "someappid"; + data.brand_code = "somebrand"; + data.tag = "arandom-tag=likethis"; + data.version = base::Version("1.0"); + data.existence_checker_path = + base::FilePath(FILE_PATH_LITERAL("some/file/path")); + + metadata->RegisterApp(data); + + data.app_id = "someappid2"; + data.brand_code = "somebrand"; + data.tag = "arandom-tag=likethis"; + data.version = base::Version("2.0"); + data.existence_checker_path = + base::FilePath(FILE_PATH_LITERAL("some/file/path")); + + metadata->RegisterApp(data); + EXPECT_EQ(size_t{2}, metadata->GetAppIds().size()); + + metadata->RemoveApp("someappid"); + EXPECT_EQ(size_t{1}, metadata->GetAppIds().size()); + + metadata->RemoveApp("someappid2"); + EXPECT_TRUE(metadata->GetAppIds().empty()); +} + } // namespace updater
diff --git a/chromecast/BUILD.gn b/chromecast/BUILD.gn index be67795..28f4caf4 100644 --- a/chromecast/BUILD.gn +++ b/chromecast/BUILD.gn
@@ -94,6 +94,12 @@ "//ui/base:ui_base_unittests", ] + if (enable_chromecast_extensions) { + tests += [ + "//chromecast/browser/accessibility/flutter:cast_accessibility_unittests", + ] + } + if (!is_cast_audio_only) { tests += [ "//gpu:gpu_unittests" ]
diff --git a/chromecast/browser/accessibility/flutter/BUILD.gn b/chromecast/browser/accessibility/flutter/BUILD.gn new file mode 100644 index 0000000..88815d5c --- /dev/null +++ b/chromecast/browser/accessibility/flutter/BUILD.gn
@@ -0,0 +1,49 @@ +# Copyright 2019 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("//chromecast/build/tests/cast_test.gni") +import("//chromecast/chromecast.gni") + +cast_source_set("accessibility") { + sources = [ + "ax_tree_source_flutter.cc", + "ax_tree_source_flutter.h", + "flutter_accessibility_helper_bridge.cc", + "flutter_accessibility_helper_bridge.h", + "flutter_semantics_node.h", + "flutter_semantics_node_wrapper.cc", + "flutter_semantics_node_wrapper.h", + ] + public_deps = [ "//ui/accessibility" ] + deps = [ + "//base", + "//chromecast/base", + "//chromecast/browser", + "//chromecast/browser/accessibility/proto:gallium_accessibility_proto", + "//chromecast/common", + "//components/exo", + "//content/public/browser", + "//extensions/browser/api", + "//skia", + "//third_party/grpc:grpcpp", + "//ui/views", + ] +} + +test("cast_accessibility_unittests") { + sources = [ "ax_tree_source_flutter_unittest.cc" ] + + deps = [ + ":accessibility", + "//base", + "//base/test:run_all_unittests", + "//chromecast/browser", + "//extensions/browser/api", + "//skia", + "//testing/gmock", + "//testing/gtest", + "//third_party/protobuf:protobuf_lite", + "//ui/views", + ] +}
diff --git a/chromecast/browser/accessibility/flutter/DEPS b/chromecast/browser/accessibility/flutter/DEPS new file mode 100644 index 0000000..a1bbce47 --- /dev/null +++ b/chromecast/browser/accessibility/flutter/DEPS
@@ -0,0 +1,13 @@ +include_rules = [ + "+chromecast/browser", + "+chromecast/common/extensions_api", + "+components/exo", + "+content/browser", + "+content/public/browser", + "+extensions/browser", + '+third_party/grpc', + "+ui/accessibility", + "+ui/aura", + "+ui/gfx", + "+ui/views", +]
diff --git a/chromecast/browser/accessibility/flutter/ax_tree_source_flutter.cc b/chromecast/browser/accessibility/flutter/ax_tree_source_flutter.cc new file mode 100644 index 0000000..57105b9 --- /dev/null +++ b/chromecast/browser/accessibility/flutter/ax_tree_source_flutter.cc
@@ -0,0 +1,641 @@ +// Copyright 2019 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 "chromecast/browser/accessibility/flutter/ax_tree_source_flutter.h" + +#include <stack> + +#include "base/check_op.h" +#include "base/strings/string_number_conversions.h" +#include "chromecast/browser/accessibility/flutter/flutter_semantics_node_wrapper.h" +#include "chromecast/browser/ui/aura/accessibility/automation_manager_aura.h" +#include "content/public/browser/tts_controller.h" +#include "content/public/browser/tts_utterance.h" +#include "extensions/browser/api/automation_internal/automation_event_router.h" +#include "extensions/browser/api/automation_internal/automation_event_router_interface.h" +#include "ui/accessibility/aura/aura_window_properties.h" +#include "ui/aura/window.h" +#include "ui/views/view.h" +#include "ui/views/widget/widget.h" +#include "ui/views/widget/widget_delegate.h" + +namespace { +ax::mojom::Event ToAXEvent( + gallium::castos::OnAccessibilityEventRequest_EventType flutter_event_type) { + switch (flutter_event_type) { + case gallium::castos::OnAccessibilityEventRequest_EventType_FOCUSED: + return ax::mojom::Event::kFocus; + case gallium::castos::OnAccessibilityEventRequest_EventType_CLICKED: + case gallium::castos::OnAccessibilityEventRequest_EventType_LONG_CLICKED: + return ax::mojom::Event::kClicked; + case gallium::castos::OnAccessibilityEventRequest_EventType_TEXT_CHANGED: + return ax::mojom::Event::kTextChanged; + case gallium::castos:: + OnAccessibilityEventRequest_EventType_TEXT_SELECTION_CHANGED: + return ax::mojom::Event::kTextSelectionChanged; + case gallium::castos::OnAccessibilityEventRequest_EventType_HOVER_ENTER: + return ax::mojom::Event::kHover; + case gallium::castos::OnAccessibilityEventRequest_EventType_SCROLLED: + return ax::mojom::Event::kScrollPositionChanged; + case gallium::castos::OnAccessibilityEventRequest_EventType_CONTENT_CHANGED: + return ax::mojom::Event::kChildrenChanged; + case gallium::castos:: + OnAccessibilityEventRequest_EventType_WINDOW_STATE_CHANGED: + return ax::mojom::Event::kLayoutComplete; + default: + return ax::mojom::Event::kNone; + } +} +} // namespace + +namespace chromecast { +namespace accessibility { + +AXTreeSourceFlutter::AXTreeWebContentsObserver::AXTreeWebContentsObserver( + content::WebContents* web_contents, + AXTreeSourceFlutter* ax_tree_source) + : WebContentsObserver(web_contents), ax_tree_source_(ax_tree_source) {} + +void AXTreeSourceFlutter::AXTreeWebContentsObserver::RenderFrameHostChanged( + content::RenderFrameHost* old_host, + content::RenderFrameHost* new_host) { + ax_tree_source_->UpdateTree(); +} + +constexpr int kInvalidId = -1; + +AXTreeSourceFlutter::AXTreeSourceFlutter( + Delegate* delegate, + content::BrowserContext* browser_context, + extensions::AutomationEventRouterInterface* event_router) + : current_tree_serializer_(std::make_unique<AXTreeFlutterSerializer>(this)), + root_id_(kInvalidId), + window_id_(kInvalidId), + focused_id_(kInvalidId), + delegate_(delegate), + browser_context_(browser_context), + event_router_(event_router + ? event_router + : extensions::AutomationEventRouter::GetInstance()) { + DCHECK(delegate_); +} + +AXTreeSourceFlutter::~AXTreeSourceFlutter() { + Reset(); +} + +void AXTreeSourceFlutter::NotifyAccessibilityEvent( + const gallium::castos::OnAccessibilityEventRequest* event_data) { + DCHECK(event_data); + + if (event_data->node_data_size() > 0) { + // Remember most recent tree in case we need to update parents + // of child trees with new ax tree ids (i.e. due to embedded webview + // navigation) + last_event_data_ = *event_data; + } + + // First find out if we know what to do with this event type from flutter. + ax::mojom::Event translated_event = ToAXEvent(event_data->event_type()); + if (translated_event == ax::mojom::Event::kNone) { + LOG(INFO) << "Ignoring unknown flutter ax event " + << event_data->event_type() << ". No mapping available."; + return; + } + + // b/150992421 - We sometimes get nodes that have been reparented. + // Any node that is reparented must first be deleted from its old + // parent before appearing under a new one. The tree serializer + // should be handling this case for us but isn't so the tree + // update fails. As a workaround until this is fixed upstream, we + // will identify these nodes ourselves and provide a separate update + // that will delete them prior to the full update. + reparented_children_.clear(); + std::vector<int32_t> parents_with_deleted_children; + for (int i = 0; i < event_data->node_data_size(); ++i) { + const SemanticsNode& node = event_data->node_data(i); + for (int j = 0; j < node.child_node_ids_size(); ++j) { + int child_id = node.child_node_ids(j); + auto it = parent_map_.find(child_id); + if (it != parent_map_.end()) { + if (node.node_id() != it->second) { + // Remember this child and who its parent was. + reparented_children_.push_back(child_id); + parents_with_deleted_children.push_back(it->second); + } + } + } + } + + if (event_data->node_data_size() > 0) { + // Unless there are new nodes, don't clear previous maps so we + // can detect reparenting above. + tree_map_.clear(); + parent_map_.clear(); + cached_computed_bounds_.clear(); + } + + window_id_ = event_data->window_id(); + + // The following loops perform caching to prepare for AXTreeSerializer. + // First, we need to cache parent links, which are implied by a node's child + // ids. Next, we cache the nodes by id. During this process, we can detect + // the root node based upon the parent links we cached above. Finally, we + // cache each node's computed bounds, based on its descendants. + std::map<int32_t, int32_t> all_parent_map; + std::map<int32_t, std::vector<int32_t>> all_children_map; + for (int i = 0; i < event_data->node_data_size(); ++i) { + const SemanticsNode& node = event_data->node_data(i); + for (int j = 0; j < node.child_node_ids_size(); ++j) { + all_children_map[node.node_id()].push_back(node.child_node_ids(j)); + all_parent_map[node.child_node_ids(j)] = node.node_id(); + } + } + + // Now copy just the relevant subtree containing the source_id into the + // |parent_map_|. + root_id_ = event_data->source_id(); + // Walk up to the root from the source_id. + for (auto it = all_parent_map.find(root_id_); it != all_parent_map.end(); + it = all_parent_map.find(root_id_)) { + root_id_ = it->second; + } + + // Walk back down through children map to populate parent_map_. + std::stack<int32_t> stack; + stack.push(root_id_); + while (!stack.empty()) { + int32_t parent = stack.top(); + stack.pop(); + for (int32_t child_id : all_children_map[parent]) { + parent_map_[child_id] = parent; + stack.push(child_id); + } + } + + std::vector<std::string> new_child_trees; + for (int i = 0; i < event_data->node_data_size(); ++i) { + int32_t id = event_data->node_data(i).node_id(); + // Only map nodes in the parent_map and the root. + // This avoids adding other subtrees that are not interesting. + if (parent_map_.find(id) == parent_map_.end() && id != root_id_) + continue; + const SemanticsNode& node = event_data->node_data(i); + tree_map_[id] = std::make_unique<FlutterSemanticsNodeWrapper>(this, &node); + if (tree_map_[id]->IsFocused()) { + focused_id_ = id; + } + // Place focus on the node that holds a child tree. When the + // child tree is removed, focus will be placed back on the root. + if (node.has_plugin_id()) { + std::string ax_tree_id = node.plugin_id(); + new_child_trees.push_back(ax_tree_id); + + if (std::find(child_trees_.begin(), child_trees_.end(), ax_tree_id) == + child_trees_.end()) { + if (ax_tree_id.rfind("T:", 0) == 0) { + int web_contents_id; + base::StringToInt(ax_tree_id.substr(2), &web_contents_id); + std::vector<CastWebContents*> all_contents = + CastWebContents::GetAll(); + for (CastWebContents* contents : all_contents) { + if (contents->id() == web_contents_id && + child_tree_observers_.find(web_contents_id) == + child_tree_observers_.end()) { + child_tree_observers_[contents->id()] = std::make_unique< + AXTreeSourceFlutter::AXTreeWebContentsObserver>( + contents->web_contents(), this); + contents->AddObserver(this); + break; + } + } + } + } + + focused_id_ = node.node_id(); + } + } + + // Do we need to put focus back on the root after a child tree + // has been removed? + bool need_focus_clear = false; + for (std::string id : child_trees_) { + // Is this old child tree still known? + if (std::find(new_child_trees.begin(), new_child_trees.end(), id) == + new_child_trees.end()) { + // No, clear focus. + need_focus_clear = true; + focused_id_ = root_id_; + break; + } + } + child_trees_ = new_child_trees; + + // Assuming |nodeData| is in pre-order, compute cached bounds in post-order to + // avoid an O(n^2) amount of work as the computed bounds uses descendant + // bounds. + for (int i = 0; i < event_data->node_data_size(); ++i) { + int32_t id = event_data->node_data(i).node_id(); + if (parent_map_.find(id) == parent_map_.end() && id != root_id_) + continue; + cached_computed_bounds_[id] = ComputeEnclosingBounds(tree_map_[id].get()); + } + + // If focus was not set from above, set it now on the root node. + if (focused_id_ < 0 && root_id_ >= 0) { + focused_id_ = root_id_; + } + + ExtensionMsg_AccessibilityEventBundleParams event_bundle; + event_bundle.tree_id = ax_tree_id(); + + event_bundle.events.emplace_back(); + ui::AXEvent& event = event_bundle.events.back(); + event.event_type = translated_event; + event.id = event_data->source_id(); + + if (event_data->event_type() == + gallium::castos::OnAccessibilityEventRequest_EventType_CONTENT_CHANGED) { + current_tree_serializer_->InvalidateSubtree(GetFromId(event.id)); + } + + if (event_data->event_type() != + gallium::castos::OnAccessibilityEventRequest_EventType_HOVER_ENTER && + event_data->event_type() != + gallium::castos::OnAccessibilityEventRequest_EventType_HOVER_EXIT) { + // For every parent whose child has been moved, serialize an update. + // This update will filter all the children that have moved. + for (int32_t nid : parents_with_deleted_children) { + event_bundle.updates.emplace_back(); + current_tree_serializer_->SerializeChanges(GetFromId(nid), + &event_bundle.updates.back()); + } + + // If there were any children that were reparented, invalidate the entire + // tree so the new parents get the children. + if (reparented_children_.size() > 0) { + current_tree_serializer_->InvalidateSubtree(GetFromId(root_id_)); + } + + // Clear reparented children. + reparented_children_.clear(); + + event_bundle.updates.emplace_back(); + current_tree_serializer_->SerializeChanges(GetFromId(event.id), + &event_bundle.updates.back()); + + HandleLiveRegions(&event_bundle.events); + + // b/162311902: For nodes that have scroll extents, rapidly changing the + // value will result in queueing up the values and speak out one by one. + // Here we handle the tts natively. + HandleNativeTTS(); + } + + // Place focus back on the root if a child tree has disappeared + if (need_focus_clear) { + event_bundle.events.emplace_back(); + ui::AXEvent& focus_event = event_bundle.events.back(); + focus_event.event_type = ax::mojom::Event::kFocus; + focus_event.id = root_id_; + focus_event.event_from = ax::mojom::EventFrom::kNone; + } + + if (event_router_) + event_router_->DispatchAccessibilityEvents(event_bundle); +} + +void AXTreeSourceFlutter::NotifyActionResult(const ui::AXActionData& data, + bool result) { + if (!event_router_) + return; + + event_router_->DispatchActionResult(data, result, browser_context_); +} + +bool AXTreeSourceFlutter::GetTreeData(ui::AXTreeData* data) const { + DCHECK(data); + data->tree_id = ax_tree_id(); + if (focused_id_ >= 0) { + data->focus_id = focused_id_; + } else if (root_id_ >= 0) { + data->focus_id = root_id_; + } + return true; +} + +FlutterSemanticsNode* AXTreeSourceFlutter::GetRoot() const { + return GetFromId(root_id_); +} + +FlutterSemanticsNode* AXTreeSourceFlutter::GetFromId(int32_t id) const { + auto it = tree_map_.find(id); + if (it == tree_map_.end()) + return nullptr; + return it->second.get(); +} + +int32_t AXTreeSourceFlutter::GetId(FlutterSemanticsNode* info_data) const { + if (!info_data) + return kInvalidId; + return info_data->GetId(); +} + +void AXTreeSourceFlutter::GetChildren( + FlutterSemanticsNode* info_data, + std::vector<FlutterSemanticsNode*>* out_children) const { + if (!info_data) + return; + + info_data->GetChildren(out_children); + if (out_children->empty()) + return; + + // Filter out any reparented children so the update doesn't see them. + auto it = out_children->begin(); + while (it != out_children->end()) { + if (std::find(reparented_children_.begin(), reparented_children_.end(), + (*it)->GetId()) != reparented_children_.end()) { + it = out_children->erase(it); + } else { + ++it; + } + } + + std::map<int32_t, size_t> id_to_index; + for (size_t i = 0; i < out_children->size(); i++) + id_to_index[(*out_children)[i]->GetId()] = i; + + // Sort children based on their enclosing bounding rectangles, based on their + // descendants. + std::sort( + out_children->begin(), out_children->end(), + [this, id_to_index](auto left, auto right) { + auto left_bounds = ComputeEnclosingBounds(left); + auto right_bounds = ComputeEnclosingBounds(right); + + if (left_bounds.IsEmpty() || right_bounds.IsEmpty()) { + return id_to_index.at(left->GetId()) < id_to_index.at(right->GetId()); + } + + // Left to right sort (non-overlapping). + if (!left_bounds.Intersects(right_bounds)) { + return left_bounds.x() < right_bounds.x(); + } + + // Overlapping + // Left to right. + int left_difference = left_bounds.x() - right_bounds.x(); + if (left_difference != 0) { + return left_difference < 0; + } + + // Top to bottom. + int top_difference = left_bounds.y() - right_bounds.y(); + if (top_difference != 0) { + return top_difference < 0; + } + + // Larger to smaller. + int height_difference = left_bounds.height() - right_bounds.height(); + if (height_difference != 0) { + return height_difference > 0; + } + + int width_difference = left_bounds.width() - right_bounds.width(); + if (width_difference != 0) { + return width_difference > 0; + } + + // The rects are equal. + return id_to_index.at(left->GetId()) < id_to_index.at(right->GetId()); + }); +} + +FlutterSemanticsNode* AXTreeSourceFlutter::GetParent( + FlutterSemanticsNode* info_data) const { + if (!info_data) + return nullptr; + auto it = parent_map_.find(info_data->GetId()); + if (it != parent_map_.end()) + return GetFromId(it->second); + return nullptr; +} + +bool AXTreeSourceFlutter::IsValid(FlutterSemanticsNode* info_data) const { + return info_data; +} + +bool AXTreeSourceFlutter::IsIgnored(FlutterSemanticsNode* info_data) const { + return false; +} + +bool AXTreeSourceFlutter::IsEqual(FlutterSemanticsNode* info_data1, + FlutterSemanticsNode* info_data2) const { + if (!info_data1 || !info_data2) + return false; + return info_data1->GetId() == info_data2->GetId(); +} + +FlutterSemanticsNode* AXTreeSourceFlutter::GetNull() const { + return nullptr; +} + +void AXTreeSourceFlutter::SerializeNode(FlutterSemanticsNode* info_data, + ui::AXNodeData* out_data) const { + if (!info_data) + return; + + int32_t id = info_data->GetId(); + out_data->id = id; + if (id == root_id_) { + out_data->role = ax::mojom::Role::kRootWebArea; + } else { + info_data->PopulateAXRole(out_data); + } + + info_data->Serialize(out_data); +} + +const gfx::Rect AXTreeSourceFlutter::GetBounds( + FlutterSemanticsNode* info_data) const { + DCHECK(info_data); + DCHECK_NE(root_id_, kInvalidId); + + gfx::Rect node_bounds = info_data->GetBounds(); + + // TODO(rmrossi): If embedded flutter is ever not full screen, we will have + // to pass in the embedded object tag's screen coordinates to this function + // and set the offset of the root node here separately from other nodes. + // The bounds of the root node are supposed to be relative to its container + // but since we are full screen, we leave them alone. See + // ax_tree_source_arc.cc for an example. + if (info_data->GetId() == root_id_) { + gfx::Rect root_bounds = GetFromId(root_id_)->GetBounds(); + // No offset applied since we are full screen. See TODO above. + return root_bounds; + } + // Bounds of non-root node is relative to its tree's root. + gfx::Rect root_bounds = GetFromId(root_id_)->GetBounds(); + node_bounds.Offset(-1 * root_bounds.x(), -1 * root_bounds.y()); + return node_bounds; +} + +gfx::Rect AXTreeSourceFlutter::ComputeEnclosingBounds( + FlutterSemanticsNode* info_data) const { + gfx::Rect computed_bounds; + // Exit early if the node or window is invisible. + if (!info_data->IsVisibleToUser()) + return computed_bounds; + + ComputeEnclosingBoundsInternal(info_data, &computed_bounds); + return computed_bounds; +} + +void AXTreeSourceFlutter::ComputeEnclosingBoundsInternal( + FlutterSemanticsNode* info_data, + gfx::Rect* computed_bounds) const { + auto cached_bounds = cached_computed_bounds_.find(info_data->GetId()); + if (cached_bounds != cached_computed_bounds_.end()) { + computed_bounds->Union(cached_bounds->second); + return; + } + + if (!info_data->IsVisibleToUser()) + return; + + if (info_data->CanBeAccessibilityFocused()) { + // Only consider nodes that can possibly be accessibility focused. + computed_bounds->Union(info_data->GetBounds()); + return; + } + + std::vector<FlutterSemanticsNode*> children; + info_data->GetChildren(&children); + if (children.empty()) + return; + + for (FlutterSemanticsNode* child : children) + ComputeEnclosingBoundsInternal(child, computed_bounds); +} + +void AXTreeSourceFlutter::PerformAction(const ui::AXActionData& data) { + delegate_->OnAction(data); +} + +void AXTreeSourceFlutter::Reset() { + tree_map_.clear(); + parent_map_.clear(); + cached_computed_bounds_.clear(); + current_tree_serializer_ = std::make_unique<AXTreeFlutterSerializer>(this); + root_id_ = kInvalidId; + focused_id_ = kInvalidId; + if (!event_router_) + return; + event_router_->DispatchTreeDestroyedEvent(ax_tree_id(), browser_context_); +} + +void AXTreeSourceFlutter::HandleNativeTTS() { + std::map<int32_t, std::string> new_native_tts_name_cache; + + // Cache current native tts name cache. + for (const auto& it : tree_map_) { + FlutterSemanticsNode* node_info = it.second.get(); + if (!node_info->IsRapidChangingSlider()) + continue; + + std::vector<std::string> names; + if (node_info->HasLabelHint()) { + names.push_back(node_info->GetLabelHint()); + } + if (node_info->HasValue()) { + names.push_back(node_info->GetValue()); + } + + new_native_tts_name_cache[node_info->GetId()] = + base::JoinString(names, " "); + } + + // Compare to the previous one, and send out TTS if needed. + for (const auto& it : new_native_tts_name_cache) { + auto prev_it = native_tts_name_cache_.find(it.first); + if (prev_it != native_tts_name_cache_.end() && + prev_it->second != it.second) { + // Send to TTS controller. + std::unique_ptr<content::TtsUtterance> utterance = + content::TtsUtterance::Create(browser_context_); + utterance->SetText(it.second); + + auto* tts_controller = content::TtsController::GetInstance(); + tts_controller->Stop(); + tts_controller->SpeakOrEnqueue(std::move(utterance)); + } + } + + std::swap(native_tts_name_cache_, new_native_tts_name_cache); +} + +void AXTreeSourceFlutter::HandleLiveRegions(std::vector<ui::AXEvent>* events) { + std::map<int32_t, std::string> new_live_region_map; + + // Cache current live region's name. + for (const auto& it : tree_map_) { + FlutterSemanticsNode* node_info = it.second.get(); + if (!node_info->IsLiveRegion()) + continue; + + std::stack<FlutterSemanticsNode*> stack; + stack.push(node_info); + while (!stack.empty()) { + FlutterSemanticsNode* node = stack.top(); + stack.pop(); + DCHECK(node); + + ui::AXNodeData data; + SerializeNode(node, &data); + std::string name; + data.GetStringAttribute(ax::mojom::StringAttribute::kName, &name); + new_live_region_map[node->GetId()] = name; + + std::vector<FlutterSemanticsNode*> children; + node->GetChildren(&children); + for (FlutterSemanticsNode* child : children) + stack.push(child); + } + } + + // Compare to the previous one, and add an event if needed. + for (const auto& it : new_live_region_map) { + auto prev_it = live_region_name_cache_.find(it.first); + if (prev_it == live_region_name_cache_.end()) + continue; + + if (prev_it->second != it.second) { + events->emplace_back(); + ui::AXEvent& event = events->back(); + event.event_type = ax::mojom::Event::kLiveRegionChanged; + event.id = it.first; + } + } + + std::swap(live_region_name_cache_, new_live_region_map); +} + +void AXTreeSourceFlutter::UpdateTree() { + // Update the tree with last known flutter nodes. + // TODO: A more efficient update would be to isolate just the parent node + // whose child has changed. Consider giving the node to the observer + // class on creation and passing through here. + NotifyAccessibilityEvent(&last_event_data_); +} + +void AXTreeSourceFlutter::OnPageStopped(CastWebContents* cast_web_contents, + int error_code) { + // Webview is gone. Stop observing. + cast_web_contents->RemoveObserver(this); + child_tree_observers_.erase(cast_web_contents->id()); +} + +} // namespace accessibility +} // namespace chromecast
diff --git a/chromecast/browser/accessibility/flutter/ax_tree_source_flutter.h b/chromecast/browser/accessibility/flutter/ax_tree_source_flutter.h new file mode 100644 index 0000000..1d1e8ad --- /dev/null +++ b/chromecast/browser/accessibility/flutter/ax_tree_source_flutter.h
@@ -0,0 +1,202 @@ +// Copyright 2019 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 CHROMECAST_BROWSER_ACCESSIBILITY_FLUTTER_AX_TREE_SOURCE_FLUTTER_H_ +#define CHROMECAST_BROWSER_ACCESSIBILITY_FLUTTER_AX_TREE_SOURCE_FLUTTER_H_ + +#include <stdint.h> +#include <map> +#include <memory> +#include <string> +#include <vector> + +#include "base/containers/flat_map.h" +#include "chromecast/browser/accessibility/proto/cast_server_accessibility.pb.h" +#include "chromecast/browser/cast_web_contents.h" +#include "content/public/browser/web_contents.h" +#include "content/public/browser/web_contents_observer.h" +#include "ui/accessibility/ax_action_handler.h" +#include "ui/accessibility/ax_node.h" +#include "ui/accessibility/ax_node_data.h" +#include "ui/accessibility/ax_tree_data.h" +#include "ui/accessibility/ax_tree_serializer.h" +#include "ui/accessibility/ax_tree_source.h" + +namespace aura { +class Window; +} // namespace aura + +namespace content { +class BrowserContext; +} // namespace content + +namespace extensions { +class AutomationEventRouterInterface; +} // namespace extensions + +namespace ui { +struct AXEvent; +} // namespace ui + +namespace chromecast { +namespace accessibility { + +class FlutterSemanticsNode; + +// This class translates accessibility trees found in the gallium accessibility +// OnAccessibilityEventRequest proto into a tree update Chrome's accessibility +// API can work with. +class AXTreeSourceFlutter : public ui::AXTreeSource<FlutterSemanticsNode*, + ui::AXNodeData, + ui::AXTreeData>, + public CastWebContents::Observer, + public ui::AXActionHandler { + public: + class Delegate { + public: + virtual ~Delegate() {} + virtual void OnAction(const ui::AXActionData& data) = 0; + }; + + AXTreeSourceFlutter( + Delegate* delegate, + content::BrowserContext* browser_context, + extensions::AutomationEventRouterInterface* event_router = nullptr); + AXTreeSourceFlutter(const AXTreeSourceFlutter&) = delete; + ~AXTreeSourceFlutter() override; + AXTreeSourceFlutter& operator=(const AXTreeSourceFlutter&) = delete; + + // AXTreeSource implementation. + bool GetTreeData(ui::AXTreeData* data) const override; + + // AXTreeSource implementation used by FlutterAccessibilityInfoData + // subclasses. + FlutterSemanticsNode* GetRoot() const override; + FlutterSemanticsNode* GetFromId(int32_t id) const override; + void SerializeNode(FlutterSemanticsNode* node, + ui::AXNodeData* out_data) const override; + FlutterSemanticsNode* GetParent(FlutterSemanticsNode* node) const override; + + // Notifies automation of an accessibility event. + void NotifyAccessibilityEvent( + const ::gallium::castos::OnAccessibilityEventRequest* event_data); + + // Notifies automation of a result to an action. + void NotifyActionResult(const ui::AXActionData& data, bool result); + + // Attaches tree to an aura window and gives it system focus. + void Focus(aura::Window* window); + + // Gets the window id of this tree. + int32_t window_id() const { return window_id_; } + + // Returns bounds of a node which can be passed to AXNodeData.location. Bounds + // are returned in the following coordinates depending on whether it's root or + // not. + // - Root node is relative to its container. + // - Non-root node is relative to the root node of this tree. + const gfx::Rect GetBounds(FlutterSemanticsNode* node) const; + + void UpdateTree(); + + // CastWebContents::Observer + void OnPageStopped(CastWebContents* cast_web_contents, + int error_code) override; + + private: + class AXTreeWebContentsObserver : public content::WebContentsObserver { + public: + AXTreeWebContentsObserver( + content::WebContents* web_contents, + chromecast::accessibility::AXTreeSourceFlutter* ax_tree_source); + + void RenderFrameHostChanged(content::RenderFrameHost* old_host, + content::RenderFrameHost* new_host) override; + + private: + chromecast::accessibility::AXTreeSourceFlutter* ax_tree_source_; + + DISALLOW_COPY_AND_ASSIGN(AXTreeWebContentsObserver); + }; + + using AXTreeFlutterSerializer = ui:: + AXTreeSerializer<FlutterSemanticsNode*, ui::AXNodeData, ui::AXTreeData>; + + friend class AXTreeSourceFlutterTest; + + // AXTreeSource overrides. + int32_t GetId(FlutterSemanticsNode* node) const override; + void GetChildren( + FlutterSemanticsNode* node, + std::vector<FlutterSemanticsNode*>* out_children) const override; + bool IsValid(FlutterSemanticsNode* node) const override; + bool IsIgnored(FlutterSemanticsNode* node) const override; + bool IsEqual(FlutterSemanticsNode* node1, + FlutterSemanticsNode* node2) const override; + FlutterSemanticsNode* GetNull() const override; + + // Computes the smallest rect that encloses all of the descendants of |node|. + gfx::Rect ComputeEnclosingBounds(FlutterSemanticsNode* node) const; + + // Helper to recursively compute bounds for |node|. Returns true if non-empty + // bounds were encountered. + void ComputeEnclosingBoundsInternal(FlutterSemanticsNode* node, + gfx::Rect* computed_bounds) const; + + // AXHostDelegate implementation. + void PerformAction(const ui::AXActionData& data) override; + + // Resets tree state. + void Reset(); + + // Detects live region changes and generates events for them. + void HandleLiveRegions(std::vector<ui::AXEvent>* events); + + // Detects rapidly changing nodes and use native TTS instead. + void HandleNativeTTS(); + + std::unique_ptr<AXTreeFlutterSerializer> current_tree_serializer_; + int32_t root_id_; + int32_t window_id_; + int32_t focused_id_; + + // A delegate that handles accessibility actions on behalf of this tree. The + // delegate is valid during the lifetime of this tree. + Delegate* delegate_; + content::BrowserContext* const browser_context_; + extensions::AutomationEventRouterInterface* const event_router_; + + // Maps a node id to its tree data. + base::flat_map<int32_t /* node_id */, std::unique_ptr<FlutterSemanticsNode>> + tree_map_; + + // Maps a node id to its parent. + base::flat_map<int32_t /* node_id */, int32_t /* parent_node_id */> + parent_map_; + + // Mapping from ArcAccessibilityInfoData ID to its cached computed bounds. + // This simplifies bounds calculations. + base::flat_map<int32_t, gfx::Rect> cached_computed_bounds_; + + // Cache from node id to computed name for live region. + std::map<int32_t, std::string> live_region_name_cache_; + + // Cache form node id to tts string for native tts components. + std::map<int32_t, std::string> native_tts_name_cache_; + + std::vector<int32_t> reparented_children_; + std::vector<std::string> child_trees_; + + // Maps web contents id to the web contents observer + base::flat_map<int32_t, std::unique_ptr<AXTreeWebContentsObserver>> + child_tree_observers_; + + // Copy of most recent tree data + gallium::castos::OnAccessibilityEventRequest last_event_data_; +}; + +} // namespace accessibility +} // namespace chromecast + +#endif // CHROMECAST_BROWSER_ACCESSIBILITY_FLUTTER_AX_TREE_SOURCE_FLUTTER_H_
diff --git a/chromecast/browser/accessibility/flutter/ax_tree_source_flutter_unittest.cc b/chromecast/browser/accessibility/flutter/ax_tree_source_flutter_unittest.cc new file mode 100644 index 0000000..168344f0 --- /dev/null +++ b/chromecast/browser/accessibility/flutter/ax_tree_source_flutter_unittest.cc
@@ -0,0 +1,636 @@ +// Copyright 2019 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 "chromecast/browser/accessibility/flutter/ax_tree_source_flutter.h" + +#include <string> + +#include "chromecast/browser/accessibility/flutter/flutter_semantics_node_wrapper.h" +#include "extensions/browser/api/automation_internal/automation_event_router_interface.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "ui/accessibility/ax_action_data.h" + +using ::testing::StrictMock; + +using ::gallium::castos::ActionProperties; +using ::gallium::castos::BooleanProperties; +using ::gallium::castos::OnAccessibilityEventRequest; +using ::gallium::castos::OnAccessibilityEventRequest_EventType_FOCUSED; +using ::gallium::castos::Rect; + +namespace chromecast { +namespace accessibility { + +class MockAutomationEventRouter + : public extensions::AutomationEventRouterInterface { + public: + MockAutomationEventRouter() {} + ~MockAutomationEventRouter() override = default; + void DispatchAccessibilityEvents( + const ExtensionMsg_AccessibilityEventBundleParams& events) override { + for (const auto& event : events.events) + event_count_[event.event_type]++; + } + MOCK_METHOD(void, + DispatchAccessibilityLocationChange, + (const ExtensionMsg_AccessibilityLocationChangeParams&), + (override)); + MOCK_METHOD(void, + DispatchTreeDestroyedEvent, + (ui::AXTreeID, content::BrowserContext*), + (override)); + MOCK_METHOD(void, + DispatchActionResult, + (const ui::AXActionData&, bool, content::BrowserContext*), + (override)); + std::map<ax::mojom::Event, int> event_count_; +}; + +class AXTreeSourceFlutterTest : public testing::Test, + public AXTreeSourceFlutter::Delegate { + public: + AXTreeSourceFlutterTest() + : tree_( + std::make_unique<AXTreeSourceFlutter>(this, + nullptr /* browser_context */, + &router_)) {} + AXTreeSourceFlutterTest(const AXTreeSourceFlutterTest&) = delete; + ~AXTreeSourceFlutterTest() override { + EXPECT_CALL(router_, DispatchTreeDestroyedEvent).Times(1); + } + AXTreeSourceFlutterTest& operator=(const AXTreeSourceFlutterTest&) = delete; + + protected: + void CallNotifyAccessibilityEvent(OnAccessibilityEventRequest* event_data) { + tree_->NotifyAccessibilityEvent(event_data); + } + + void CallGetChildren(SemanticsNode* node, + std::vector<FlutterSemanticsNode*>* out_children) const { + FlutterSemanticsNodeWrapper node_data(tree_.get(), node); + tree_->GetChildren(&node_data, out_children); + } + + void CallSerializeNode(SemanticsNode* node, + std::unique_ptr<ui::AXNodeData>* out_data) const { + ASSERT_TRUE(out_data); + FlutterSemanticsNodeWrapper node_data(tree_.get(), node); + *out_data = std::make_unique<ui::AXNodeData>(); + tree_->SerializeNode(&node_data, out_data->get()); + } + + FlutterSemanticsNode* CallGetFromId(int32_t id) const { + return tree_->GetFromId(id); + } + + bool CallGetTreeData(ui::AXTreeData* data) { + return tree_->GetTreeData(data); + } + + int GetDispatchedEventCount(ax::mojom::Event type) { + return router_.event_count_[type]; + } + + void SetRect(Rect* rect, int left, int top, int right, int bottom) { + rect->set_left(left); + rect->set_top(top); + rect->set_right(right); + rect->set_bottom(bottom); + } + + SemanticsNode* AddChild(OnAccessibilityEventRequest* event, + SemanticsNode* parent, + int id, + int x, + int y, + int w, + int h, + bool click) { + BooleanProperties* boolean_properties; + ActionProperties* action_properties; + + SemanticsNode* new_node = event->add_node_data(); + new_node->set_node_id(id); + Rect* bounds = new_node->mutable_bounds_in_screen(); + SetRect(bounds, x, y, x + w, y + h); + boolean_properties = new_node->mutable_boolean_properties(); + boolean_properties->set_is_button(click); + if (click) { + new_node->set_label("Button"); + } + action_properties = new_node->mutable_action_properties(); + action_properties->set_tap(click); + + parent->add_child_node_ids(id); + return new_node; + } + + private: + void OnAction(const ui::AXActionData& data) override {} + + MockAutomationEventRouter router_; + std::unique_ptr<AXTreeSourceFlutter> tree_; +}; + +TEST_F(AXTreeSourceFlutterTest, ReorderChildrenByLayout) { + BooleanProperties* boolean_properties; + ActionProperties* action_properties; + + OnAccessibilityEventRequest event; + event.set_source_id(0); + event.set_window_id(1); + event.set_event_type(OnAccessibilityEventRequest_EventType_FOCUSED); + + // 0 + // / \ + // 1 2 + SemanticsNode* root = event.add_node_data(); + root->set_node_id(0); + root->add_child_node_ids(1); + root->add_child_node_ids(2); + + // Child button 1. + SemanticsNode* button1 = event.add_node_data(); + button1->set_node_id(1); + button1->set_label("Button"); + boolean_properties = button1->mutable_boolean_properties(); + boolean_properties->set_is_button(true); + boolean_properties->set_is_hidden(false); + action_properties = button1->mutable_action_properties(); + action_properties->set_tap(true); + + // Another child button. + SemanticsNode* button2 = event.add_node_data(); + button2->set_node_id(2); + button2->set_label("Button"); + boolean_properties = button2->mutable_boolean_properties(); + boolean_properties->set_is_button(true); + boolean_properties->set_is_hidden(false); + action_properties = button2->mutable_action_properties(); + action_properties->set_tap(true); + + // Non-overlapping: 2 + // 1 + // Expect left(2) to right(1) + Rect* bounds1 = button1->mutable_bounds_in_screen(); + Rect* bounds2 = button2->mutable_bounds_in_screen(); + SetRect(bounds1, 100, 100, 200, 200); + SetRect(bounds2, 0, 0, 50, 50); + + // Trigger an update which refreshes the computed bounds used for reordering. + CallNotifyAccessibilityEvent(&event); + EXPECT_EQ(1, GetDispatchedEventCount(ax::mojom::Event::kFocus)); + std::vector<FlutterSemanticsNode*> order; + order.clear(); + CallGetChildren(root, &order); + ASSERT_EQ(2U, order.size()); + EXPECT_EQ(2, order[0]->GetId()); + EXPECT_EQ(1, order[1]->GetId()); + + // Non-overlapping: 2 + // 1 + // Expect left(1) to right(2) + SetRect(bounds1, 0, 50, 50, 50); + SetRect(bounds2, 100, 0, 200, 200); + CallNotifyAccessibilityEvent(&event); + EXPECT_EQ(2, GetDispatchedEventCount(ax::mojom::Event::kFocus)); + order.clear(); + CallGetChildren(root, &order); + ASSERT_EQ(2U, order.size()); + EXPECT_EQ(1, order[0]->GetId()); + EXPECT_EQ(2, order[1]->GetId()); + + // Non-overlapping: 1 + // 2 + // Expect left(1) to right(2) + SetRect(bounds1, 0, 0, 50, 50); + SetRect(bounds2, 100, 100, 200, 200); + CallNotifyAccessibilityEvent(&event); + EXPECT_EQ(3, GetDispatchedEventCount(ax::mojom::Event::kFocus)); + order.clear(); + CallGetChildren(root, &order); + ASSERT_EQ(2U, order.size()); + EXPECT_EQ(1, order[0]->GetId()); + EXPECT_EQ(2, order[1]->GetId()); + + // Non-overlapping: 1 + // 2 + // Expect left(2) to right(1) + SetRect(bounds1, 100, 0, 200, 50); + SetRect(bounds2, 0, 100, 50, 200); + CallNotifyAccessibilityEvent(&event); + EXPECT_EQ(4, GetDispatchedEventCount(ax::mojom::Event::kFocus)); + order.clear(); + CallGetChildren(root, &order); + ASSERT_EQ(2U, order.size()); + EXPECT_EQ(2, order[0]->GetId()); + EXPECT_EQ(1, order[1]->GetId()); + + // Overlapping: Same y, 2_x < 1_x + // Expect left(2) to right(1) + SetRect(bounds1, 101, 100, 200, 200); + SetRect(bounds2, 100, 100, 200, 200); + CallNotifyAccessibilityEvent(&event); + EXPECT_EQ(5, GetDispatchedEventCount(ax::mojom::Event::kFocus)); + order.clear(); + CallGetChildren(root, &order); + ASSERT_EQ(2U, order.size()); + EXPECT_EQ(2, order[0]->GetId()); + EXPECT_EQ(1, order[1]->GetId()); + + // Overlapping: Same y, 1_x < 2_x + // Expect left(1) to right(2) + SetRect(bounds1, 100, 100, 200, 200); + SetRect(bounds2, 101, 100, 200, 200); + CallNotifyAccessibilityEvent(&event); + EXPECT_EQ(6, GetDispatchedEventCount(ax::mojom::Event::kFocus)); + order.clear(); + CallGetChildren(root, &order); + ASSERT_EQ(2U, order.size()); + EXPECT_EQ(1, order[0]->GetId()); + EXPECT_EQ(2, order[1]->GetId()); + + // Overlapping, 1st_x == 2nd_x + // Expect top(2) to bottom(1) + SetRect(bounds1, 100, 100, 200, 200); + SetRect(bounds2, 100, 99, 200, 199); + CallNotifyAccessibilityEvent(&event); + EXPECT_EQ(7, GetDispatchedEventCount(ax::mojom::Event::kFocus)); + order.clear(); + CallGetChildren(root, &order); + ASSERT_EQ(2U, order.size()); + EXPECT_EQ(2, order[0]->GetId()); + EXPECT_EQ(1, order[1]->GetId()); + + // Overlapping, 1st_x > 2nd_x + // Expect left(1) to right(2) + SetRect(bounds1, 100, 100, 200, 200); + SetRect(bounds2, 99, 100, 200, 199); + CallNotifyAccessibilityEvent(&event); + EXPECT_EQ(8, GetDispatchedEventCount(ax::mojom::Event::kFocus)); + order.clear(); + CallGetChildren(root, &order); + ASSERT_EQ(2U, order.size()); + EXPECT_EQ(2, order[0]->GetId()); + EXPECT_EQ(1, order[1]->GetId()); + + // Same top,left,x + // Expect larger(2) to smaller(1) + SetRect(bounds1, 100, 100, 200, 110); + SetRect(bounds2, 100, 100, 200, 200); + CallNotifyAccessibilityEvent(&event); + EXPECT_EQ(9, GetDispatchedEventCount(ax::mojom::Event::kFocus)); + order.clear(); + CallGetChildren(root, &order); + ASSERT_EQ(2U, order.size()); + EXPECT_EQ(2, order[0]->GetId()); + EXPECT_EQ(1, order[1]->GetId()); + + // Same top,left,y + // Expect larger(2) to smaller(1) + SetRect(bounds1, 100, 100, 110, 200); + SetRect(bounds2, 100, 100, 200, 200); + CallNotifyAccessibilityEvent(&event); + EXPECT_EQ(10, GetDispatchedEventCount(ax::mojom::Event::kFocus)); + order.clear(); + CallGetChildren(root, &order); + ASSERT_EQ(2U, order.size()); + EXPECT_EQ(2, order[0]->GetId()); + EXPECT_EQ(1, order[1]->GetId()); + + // Same top,left,x + // Expect larger(1) to smaller(2) + SetRect(bounds1, 100, 100, 200, 200); + SetRect(bounds2, 100, 100, 200, 110); + CallNotifyAccessibilityEvent(&event); + EXPECT_EQ(11, GetDispatchedEventCount(ax::mojom::Event::kFocus)); + order.clear(); + CallGetChildren(root, &order); + ASSERT_EQ(2U, order.size()); + EXPECT_EQ(1, order[0]->GetId()); + EXPECT_EQ(2, order[1]->GetId()); + + // Same top,left,y + // Expect larger(1) to smaller(2) + SetRect(bounds1, 100, 100, 200, 200); + SetRect(bounds2, 100, 100, 110, 200); + CallNotifyAccessibilityEvent(&event); + EXPECT_EQ(12, GetDispatchedEventCount(ax::mojom::Event::kFocus)); + order.clear(); + CallGetChildren(root, &order); + ASSERT_EQ(2U, order.size()); + EXPECT_EQ(1, order[0]->GetId()); + EXPECT_EQ(2, order[1]->GetId()); +} + +// This tree was taken from real tree data. When the enclosing +// bounds have been computed for children and they don't overlap, +// we should prefer left to right ordering as it aligns +// better with the way the UI is laid out. Preferring top +// to bottom usually results in a strange ordering which +// may make sense if you knew what the enclosing bounds were +// but does not behave with what you would expect visually. +TEST_F(AXTreeSourceFlutterTest, ReorderChildrenByLayoutPreferLeftToRight) { + OnAccessibilityEventRequest event; + + event.set_source_id(0); + event.set_window_id(1); + event.set_event_type(OnAccessibilityEventRequest_EventType_FOCUSED); + + SemanticsNode* root = event.add_node_data(); + root->set_node_id(0); + Rect* bounds = root->mutable_bounds_in_screen(); + SetRect(bounds, 0, 0, 1280, 800); + + SemanticsNode* child; + AddChild(&event, root, 17, 0, 0, 422, 800, true); + + child = AddChild(&event, root, 29, 1022, 0, 257, 800, false); + child = AddChild(&event, child, 30, 1022, 55, 257, 690, true); + AddChild(&event, child, 31, 1232, 165, 47, 150, false); + AddChild(&event, child, 32, 1232, 165, 47, 150, false); + + child = AddChild(&event, root, 18, 422, 0, 600, 800, false); + child = AddChild(&event, child, 19, 422, 55, 570, 690, false); + AddChild(&event, child, 20, 507, 95, 445, 40, false); + AddChild(&event, child, 21, 463, 186, 488, 70, true); + AddChild(&event, child, 22, 463, 283, 488, 70, true); + AddChild(&event, child, 23, 463, 381, 488, 70, true); + AddChild(&event, child, 24, 463, 478, 488, 70, true); + + // Enclosing bounds for 29 end up being smaller y + // than enclosing bounds for 18 but 18 is left of 29 + // so order should be 17,18,29 + + CallNotifyAccessibilityEvent(&event); + EXPECT_EQ(1, GetDispatchedEventCount(ax::mojom::Event::kFocus)); + std::vector<FlutterSemanticsNode*> ordered; + CallGetChildren(root, &ordered); + ASSERT_EQ(3U, ordered.size()); + EXPECT_EQ(17, ordered[0]->GetId()); + EXPECT_EQ(18, ordered[1]->GetId()); + EXPECT_EQ(29, ordered[2]->GetId()); +} + +TEST_F(AXTreeSourceFlutterTest, AccessibleNameComputation) { + ActionProperties* action_properties; + + OnAccessibilityEventRequest event; + event.set_source_id(0); + event.set_window_id(1); + event.set_event_type(OnAccessibilityEventRequest_EventType_FOCUSED); + + // 0 + // / \ + // 1 2 + SemanticsNode* root = event.add_node_data(); + root->set_node_id(0); + root->add_child_node_ids(1); + root->add_child_node_ids(2); + + // Child. + SemanticsNode* child1 = event.add_node_data(); + child1->set_node_id(1); + + // Another child. + SemanticsNode* child2 = event.add_node_data(); + child2->set_node_id(2); + + // Populate the tree source with the data. + CallNotifyAccessibilityEvent(&event); + EXPECT_EQ(1, GetDispatchedEventCount(ax::mojom::Event::kFocus)); + + // No attributes. + std::unique_ptr<ui::AXNodeData> data; + CallSerializeNode(root, &data); + std::string name; + ASSERT_FALSE( + data->GetStringAttribute(ax::mojom::StringAttribute::kName, &name)); + EXPECT_EQ("", name); + + // Label (empty). + root->set_label(""); + CallSerializeNode(root, &data); + ASSERT_TRUE( + data->GetStringAttribute(ax::mojom::StringAttribute::kName, &name)); + EXPECT_EQ("", name); + + // Label (non-empty). + root->set_label("label text"); + CallSerializeNode(root, &data); + ASSERT_TRUE( + data->GetStringAttribute(ax::mojom::StringAttribute::kName, &name)); + EXPECT_EQ("label text", name); + + // Hint (empty), Label (non-empty). + root->set_hint(""); + CallSerializeNode(root, &data); + ASSERT_TRUE( + data->GetStringAttribute(ax::mojom::StringAttribute::kName, &name)); + EXPECT_EQ("label text", name); + + // Hint (non-empty), Label (empty). + root->set_hint("hint"); + root->clear_label(); + CallSerializeNode(root, &data); + ASSERT_TRUE( + data->GetStringAttribute(ax::mojom::StringAttribute::kName, &name)); + EXPECT_EQ("hint", name); + + // Name from contents. + + // Root node has no name, but has descendants with name. + root->clear_hint(); + root->clear_label(); + // Name from contents only happens if a node is clickable. + action_properties = root->mutable_action_properties(); + action_properties->set_tap(true); + child1->set_label("child1 label text"); + child2->set_label("child2 label text"); + CallSerializeNode(root, &data); + ASSERT_TRUE( + data->GetStringAttribute(ax::mojom::StringAttribute::kName, &name)); + ASSERT_EQ("child1 label text child2 label text", name); + + // If the node has a name, it should override the contents. + root->set_label("root label text"); + CallSerializeNode(root, &data); + ASSERT_TRUE( + data->GetStringAttribute(ax::mojom::StringAttribute::kName, &name)); + ASSERT_EQ("root label text", name); + + // Clearing both clickable and name from root, the name should not be + // populated. + root->clear_label(); + action_properties->clear_tap(); + CallSerializeNode(root, &data); + ASSERT_FALSE( + data->GetStringAttribute(ax::mojom::StringAttribute::kName, &name)); +} + +// Flutter's 'hidden' attribute should not translate to the node being +// ignored or in any way not a11y focusable. +TEST_F(AXTreeSourceFlutterTest, NeverHidden) { + OnAccessibilityEventRequest event; + event.set_source_id(0); + event.set_window_id(1); + event.set_event_type(OnAccessibilityEventRequest_EventType_FOCUSED); + + BooleanProperties* boolean_properties; + SemanticsNode* root = event.add_node_data(); + root->add_child_node_ids(1); + SemanticsNode* child1 = event.add_node_data(); + child1->set_node_id(1); + child1->set_label("some label text"); + boolean_properties = child1->mutable_boolean_properties(); + boolean_properties->set_is_hidden(true); + + CallNotifyAccessibilityEvent(&event); + EXPECT_EQ(1, GetDispatchedEventCount(ax::mojom::Event::kFocus)); + + std::unique_ptr<ui::AXNodeData> data; + CallSerializeNode(child1, &data); + + ASSERT_TRUE(data->role == ax::mojom::Role::kStaticText); + ASSERT_FALSE(data->HasState(ax::mojom::State::kInvisible)); +} + +TEST_F(AXTreeSourceFlutterTest, GetTreeDataAppliesFocus) { + OnAccessibilityEventRequest event; + event.set_source_id(5); + event.set_window_id(1); + event.set_event_type(OnAccessibilityEventRequest_EventType_FOCUSED); + + SemanticsNode* root = event.add_node_data(); + root->set_node_id(5); + + CallNotifyAccessibilityEvent(&event); + EXPECT_EQ(1, GetDispatchedEventCount(ax::mojom::Event::kFocus)); + ui::AXTreeData data; + + // If no node claimed focus, the root node should get it. + EXPECT_TRUE(CallGetTreeData(&data)); + EXPECT_EQ(5, data.focus_id); + + // Add a child node with focus. + root->add_child_node_ids(6); + SemanticsNode* child = event.add_node_data(); + child->set_node_id(6); + child->mutable_boolean_properties()->set_is_focused(true); + + CallNotifyAccessibilityEvent(&event); + EXPECT_EQ(2, GetDispatchedEventCount(ax::mojom::Event::kFocus)); + + EXPECT_TRUE(CallGetTreeData(&data)); + EXPECT_EQ(6, data.focus_id); +} + +TEST_F(AXTreeSourceFlutterTest, LiveRegion) { + OnAccessibilityEventRequest event; + event.set_source_id(1); + event.set_window_id(1); + event.set_event_type(OnAccessibilityEventRequest_EventType_FOCUSED); + + SemanticsNode* root = event.add_node_data(); + root->set_node_id(10); + root->add_child_node_ids(1); + root->add_child_node_ids(2); + BooleanProperties* boolean_properties = root->mutable_boolean_properties(); + boolean_properties->set_is_live_region(true); + + // Add child nodes. + SemanticsNode* node1 = event.add_node_data(); + node1->set_node_id(1); + node1->set_label("text 1"); + + SemanticsNode* node2 = event.add_node_data(); + node2->set_node_id(2); + node2->set_label("text 2"); + + CallNotifyAccessibilityEvent(&event); + EXPECT_EQ(1, GetDispatchedEventCount(ax::mojom::Event::kFocus)); + + std::unique_ptr<ui::AXNodeData> data; + CallSerializeNode(root, &data); + std::string status; + ASSERT_TRUE(data->GetStringAttribute( + ax::mojom::StringAttribute::kContainerLiveStatus, &status)); + ASSERT_EQ(status, "polite"); + + EXPECT_EQ(0, GetDispatchedEventCount(ax::mojom::Event::kLiveRegionChanged)); + + // Modify text of node1. + node1->set_label("modified text 1"); + CallNotifyAccessibilityEvent(&event); + + EXPECT_EQ(1, GetDispatchedEventCount(ax::mojom::Event::kLiveRegionChanged)); +} + +TEST_F(AXTreeSourceFlutterTest, ResetFocus) { + // + // tree 1: no child tree + // + OnAccessibilityEventRequest event; + + event.set_source_id(0); + event.set_window_id(1); + event.set_event_type(OnAccessibilityEventRequest_EventType_FOCUSED); + + SemanticsNode* root = event.add_node_data(); + root->set_node_id(0); + Rect* bounds = root->mutable_bounds_in_screen(); + SetRect(bounds, 0, 0, 1280, 800); + + SemanticsNode* child; + AddChild(&event, root, 1, 0, 0, 800, 600, false); + + child = AddChild(&event, root, 2, 0, 0, 400, 600, false); + child = AddChild(&event, root, 3, 400, 0, 400, 600, false); + + CallNotifyAccessibilityEvent(&event); + + // initial focus on root + ui::AXTreeData tree_data; + CallGetTreeData(&tree_data); + ASSERT_EQ(0, tree_data.focus_id); + + // + // tree 2: add a node with a child tree id + // + OnAccessibilityEventRequest event2; + + event2.set_source_id(0); + event2.set_window_id(1); + event2.set_event_type(OnAccessibilityEventRequest_EventType_FOCUSED); + + SemanticsNode* root2 = event2.add_node_data(); + root2->set_node_id(0); + Rect* bounds2 = root2->mutable_bounds_in_screen(); + SetRect(bounds2, 0, 0, 1280, 800); + + AddChild(&event2, root2, 1, 0, 0, 800, 600, false); + + child = AddChild(&event2, root2, 2, 0, 0, 400, 600, false); + child = AddChild(&event2, root2, 3, 400, 0, 400, 600, false); + child = AddChild(&event2, root2, 4, 0, 0, 200, 200, false); + child->set_plugin_id("1234"); + + // focus should move to node with child tree + CallNotifyAccessibilityEvent(&event2); + CallGetTreeData(&tree_data); + ASSERT_EQ(4, tree_data.focus_id); + + // + // tree 2: back to initial tree + // + CallNotifyAccessibilityEvent(&event); + CallGetTreeData(&tree_data); + + // focus back to root + ASSERT_EQ(0, tree_data.focus_id); +} + +} // namespace accessibility +} // namespace chromecast
diff --git a/chromecast/browser/accessibility/flutter/flutter_accessibility_helper_bridge.cc b/chromecast/browser/accessibility/flutter/flutter_accessibility_helper_bridge.cc new file mode 100644 index 0000000..b166f61e --- /dev/null +++ b/chromecast/browser/accessibility/flutter/flutter_accessibility_helper_bridge.cc
@@ -0,0 +1,196 @@ +// Copyright 2019 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 "chromecast/browser/accessibility/flutter/flutter_accessibility_helper_bridge.h" + +#include <utility> + +#include "base/task/post_task.h" +#include "chromecast/browser/accessibility/accessibility_manager.h" +#include "chromecast/browser/accessibility/proto/gallium_server_accessibility.grpc.pb.h" +#include "chromecast/browser/cast_browser_process.h" +#include "components/exo/fullscreen_shell_surface.h" +#include "components/exo/shell_surface_util.h" +#include "components/exo/surface.h" +#include "content/public/browser/browser_context.h" +#include "content/public/browser/browser_task_traits.h" +#include "content/public/browser/browser_thread.h" +#include "ui/accessibility/aura/aura_window_properties.h" +#include "ui/accessibility/ax_action_data.h" +#include "ui/aura/window.h" +#include "ui/aura/window_tree_host.h" +#include "ui/views/view.h" +#include "ui/views/widget/widget.h" + +namespace chromecast { +namespace gallium { +namespace accessibility { + +using ::gallium::castos:: + OnAccessibilityActionRequest_AccessibilityActionType_CUSTOM_ACTION; +using ::gallium::castos:: + // NOLINTNEXTLINE(whitespace/line_length) + OnAccessibilityActionRequest_AccessibilityActionType_DID_GAIN_ACCESSIBILITY_FOCUS; +using ::gallium::castos:: + // NOLINTNEXTLINE(whitespace/line_length) + OnAccessibilityActionRequest_AccessibilityActionType_DID_LOSE_ACCESSIBILITY_FOCUS; +using ::gallium::castos:: + OnAccessibilityActionRequest_AccessibilityActionType_SCROLL_DOWN; +using ::gallium::castos:: + OnAccessibilityActionRequest_AccessibilityActionType_SCROLL_LEFT; +using ::gallium::castos:: + OnAccessibilityActionRequest_AccessibilityActionType_SCROLL_RIGHT; +using ::gallium::castos:: + OnAccessibilityActionRequest_AccessibilityActionType_SCROLL_UP; +using ::gallium::castos:: + OnAccessibilityActionRequest_AccessibilityActionType_SET_SELECTION; +using ::gallium::castos:: + OnAccessibilityActionRequest_AccessibilityActionType_SHOW_ON_SCREEN; +using ::gallium::castos:: + OnAccessibilityActionRequest_AccessibilityActionType_TAP; + +FlutterAccessibilityHelperBridge::FlutterAccessibilityHelperBridge( + Delegate* bridge_delegate, + content::BrowserContext* browser_context) + : tree_source_( + std::make_unique<AXTreeSourceFlutter>(this, browser_context)), + bridge_delegate_(bridge_delegate) {} + +FlutterAccessibilityHelperBridge::~FlutterAccessibilityHelperBridge() = default; + +void FlutterAccessibilityHelperBridge::AccessibilityStateChanged(bool value) { + if (value) { + aura::Window* window = chromecast::shell::CastBrowserProcess::GetInstance() + ->accessibility_manager() + ->window_tree_host() + ->window(); + + // Find the full screen shell surface for the exo::Surface representing + // the ui. We must ensure our tree id is the child ax tree id for + // that view so when the root window is serialized, the flutter ax tree + // will be parented by that view. + bool found = false; + if (window) { + for (aura::Window* child : window->children()) { + exo::Surface* surface = exo::GetShellMainSurface(child); + if (surface) { + views::Widget* widget = + views::Widget::GetWidgetForNativeWindow(child); + if (widget) { + exo::FullscreenShellSurface* full_screen_shell_surface = + static_cast<exo::FullscreenShellSurface*>( + widget->widget_delegate()); + full_screen_shell_surface->SetChildAxTreeId( + tree_source_->ax_tree_id()); + full_screen_shell_surface->GetContentsView() + ->NotifyAccessibilityEvent(ax::mojom::Event::kChildrenChanged, + false); + child->Focus(); + found = true; + } + break; + } + } + } + + if (!found) { + LOG(ERROR) << "Could not find full screen shell surface for ax tree."; + } + } +} + +void FlutterAccessibilityHelperBridge::OnAccessibilityEventRequestInternal( + std::unique_ptr<::gallium::castos::OnAccessibilityEventRequest> + event_data) { + // Tell the tree source to serialize these changes. + tree_source_->NotifyAccessibilityEvent(event_data.get()); +} + +bool FlutterAccessibilityHelperBridge::OnAccessibilityEventRequest( + const ::gallium::castos::OnAccessibilityEventRequest* event_data) { + std::unique_ptr<::gallium::castos::OnAccessibilityEventRequest> event = + std::make_unique<::gallium::castos::OnAccessibilityEventRequest>( + *event_data); + + base::PostTask(FROM_HERE, {content::BrowserThread::UI}, + base::BindOnce(&FlutterAccessibilityHelperBridge:: + OnAccessibilityEventRequestInternal, + base::Unretained(this), std::move(event))); + return true; +} + +void FlutterAccessibilityHelperBridge::OnAction(const ui::AXActionData& data) { + // Called by tree source to dispatch ax action to flutter. Translate this + // to gallium accessibility proto and forward to the delegate for + // dispatching. + ::gallium::castos::OnAccessibilityActionRequest request; + request.set_node_id(data.target_node_id); + + switch (data.action) { + case ax::mojom::Action::kDoDefault: + request.set_action_type( + OnAccessibilityActionRequest_AccessibilityActionType_TAP); + break; + case ax::mojom::Action::kScrollToMakeVisible: + request.set_action_type( + OnAccessibilityActionRequest_AccessibilityActionType_SHOW_ON_SCREEN); + break; + case ax::mojom::Action::kScrollBackward: + request.set_action_type( + OnAccessibilityActionRequest_AccessibilityActionType_SCROLL_LEFT); + break; + case ax::mojom::Action::kScrollForward: + request.set_action_type( + OnAccessibilityActionRequest_AccessibilityActionType_SCROLL_RIGHT); + break; + case ax::mojom::Action::kScrollUp: + request.set_action_type( + OnAccessibilityActionRequest_AccessibilityActionType_SCROLL_UP); + break; + case ax::mojom::Action::kScrollDown: + request.set_action_type( + OnAccessibilityActionRequest_AccessibilityActionType_SCROLL_DOWN); + break; + case ax::mojom::Action::kScrollLeft: + request.set_action_type( + OnAccessibilityActionRequest_AccessibilityActionType_SCROLL_LEFT); + break; + case ax::mojom::Action::kScrollRight: + request.set_action_type( + OnAccessibilityActionRequest_AccessibilityActionType_SCROLL_RIGHT); + break; + case ax::mojom::Action::kCustomAction: + request.set_action_type( + OnAccessibilityActionRequest_AccessibilityActionType_CUSTOM_ACTION); + request.set_custom_action_id(data.custom_action_id); + break; + case ax::mojom::Action::kSetAccessibilityFocus: + request.set_action_type( + // NOLINTNEXTLINE(whitespace/line_length) + OnAccessibilityActionRequest_AccessibilityActionType_DID_GAIN_ACCESSIBILITY_FOCUS); + break; + case ax::mojom::Action::kClearAccessibilityFocus: + request.set_action_type( + // NOLINTNEXTLINE(whitespace/line_length) + OnAccessibilityActionRequest_AccessibilityActionType_DID_LOSE_ACCESSIBILITY_FOCUS); + break; + case ax::mojom::Action::kGetTextLocation: + request.set_action_type( + OnAccessibilityActionRequest_AccessibilityActionType_SET_SELECTION); + request.set_start_index(data.start_index); + request.set_end_index(data.end_index); + break; + default: + LOG(WARNING) << "Cast ax action " << data.action + << " not mapped to flutter action - dropped."; + + return; + } + + bridge_delegate_->SendAccessibilityAction(request); +} + +} // namespace accessibility +} // namespace gallium +} // namespace chromecast
diff --git a/chromecast/browser/accessibility/flutter/flutter_accessibility_helper_bridge.h b/chromecast/browser/accessibility/flutter/flutter_accessibility_helper_bridge.h new file mode 100644 index 0000000..8b902cba --- /dev/null +++ b/chromecast/browser/accessibility/flutter/flutter_accessibility_helper_bridge.h
@@ -0,0 +1,74 @@ +// Copyright 2019 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 CHROMECAST_BROWSER_ACCESSIBILITY_FLUTTER_FLUTTER_ACCESSIBILITY_HELPER_BRIDGE_H_ +#define CHROMECAST_BROWSER_ACCESSIBILITY_FLUTTER_FLUTTER_ACCESSIBILITY_HELPER_BRIDGE_H_ + +#include <memory> + +#include "chromecast/browser/accessibility/flutter/ax_tree_source_flutter.h" + +using chromecast::accessibility::AXTreeSourceFlutter; + +namespace content { +class BrowserContext; +} // namespace content + +namespace gallium { +namespace castos { +class OnAccessibilityEventRequest; +class OnAccessibilityActionRequest; +} // namespace castos +} // namespace gallium + +namespace chromecast { +namespace gallium { +namespace accessibility { + +// FlutterAccessibilityHelperBridge receives Flutter accessibility +// events from gallium, translates them to chrome tree updates and dispatches +// them to chromecast accessibility services. +class FlutterAccessibilityHelperBridge : public AXTreeSourceFlutter::Delegate { + public: + class Delegate { + public: + virtual void SendAccessibilityAction( + ::gallium::castos::OnAccessibilityActionRequest request) = 0; + + protected: + virtual ~Delegate() = default; + }; + + FlutterAccessibilityHelperBridge(Delegate* bridge_delegate, + content::BrowserContext* browser_context); + FlutterAccessibilityHelperBridge(const FlutterAccessibilityHelperBridge&) = + delete; + ~FlutterAccessibilityHelperBridge() override; + FlutterAccessibilityHelperBridge& operator=( + const FlutterAccessibilityHelperBridge&) = delete; + + // Receive an accessibility event from flutter. + bool OnAccessibilityEventRequest( + const ::gallium::castos::OnAccessibilityEventRequest* event_data); + + // AXTreeSourceArc::Delegate implementation: + // Dispatch a chrome accessibility action to flutter. + void OnAction(const ui::AXActionData& data) override; + + void AccessibilityStateChanged(bool value); + + private: + void OnAccessibilityEventRequestInternal( + std::unique_ptr<::gallium::castos::OnAccessibilityEventRequest> + event_data); + + std::unique_ptr<AXTreeSourceFlutter> tree_source_; + Delegate* bridge_delegate_; +}; + +} // namespace accessibility +} // namespace gallium +} // namespace chromecast + +#endif // CHROMECAST_BROWSER_ACCESSIBILITY_FLUTTER_FLUTTER_ACCESSIBILITY_HELPER_BRIDGE_H_
diff --git a/chromecast/browser/accessibility/flutter/flutter_semantics_node.h b/chromecast/browser/accessibility/flutter/flutter_semantics_node.h new file mode 100644 index 0000000..e140adca --- /dev/null +++ b/chromecast/browser/accessibility/flutter/flutter_semantics_node.h
@@ -0,0 +1,50 @@ +// Copyright 2019 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 CHROMECAST_BROWSER_ACCESSIBILITY_FLUTTER_FLUTTER_SEMANTICS_NODE_H_ +#define CHROMECAST_BROWSER_ACCESSIBILITY_FLUTTER_FLUTTER_SEMANTICS_NODE_H_ + +#include <ui/gfx/geometry/rect.h> + +#include <string> +#include <vector> + +namespace ui { +struct AXNodeData; +} // namespace ui + +namespace chromecast { +namespace accessibility { + +// FlutterSemanticsNode represents a single flutter semantics object from +// flutter. This class is used by AXTreeSourceFlutter to encapsulate +// flutter information which maps to a single AXNodeData. +class FlutterSemanticsNode { + public: + virtual ~FlutterSemanticsNode() = default; + + virtual int32_t GetId() const = 0; + virtual const gfx::Rect GetBounds() const = 0; + virtual bool IsVisibleToUser() const = 0; + virtual bool IsFocused() const = 0; + virtual bool IsLiveRegion() const = 0; + virtual bool IsRapidChangingSlider() const = 0; + virtual bool CanBeAccessibilityFocused() const = 0; + virtual void PopulateAXRole(ui::AXNodeData* out_data) const = 0; + virtual void PopulateAXState(ui::AXNodeData* out_data) const = 0; + virtual void Serialize(ui::AXNodeData* out_data) const = 0; + virtual void GetChildren( + std::vector<FlutterSemanticsNode*>* children) const = 0; + virtual void ComputeNameFromContents( + std::vector<std::string>* names) const = 0; + virtual bool HasLabelHint() const = 0; + virtual std::string GetLabelHint() const = 0; + virtual bool HasValue() const = 0; + virtual std::string GetValue() const = 0; +}; + +} // namespace accessibility +} // namespace chromecast + +#endif // CHROMECAST_BROWSER_ACCESSIBILITY_FLUTTER_FLUTTER_SEMANTICS_NODE_H_
diff --git a/chromecast/browser/accessibility/flutter/flutter_semantics_node_wrapper.cc b/chromecast/browser/accessibility/flutter/flutter_semantics_node_wrapper.cc new file mode 100644 index 0000000..e08501a8 --- /dev/null +++ b/chromecast/browser/accessibility/flutter/flutter_semantics_node_wrapper.cc
@@ -0,0 +1,594 @@ +// Copyright 2019 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 "chromecast/browser/accessibility/flutter/flutter_semantics_node_wrapper.h" + +#include "base/check.h" +#include "base/strings/string_util.h" +#include "chromecast/browser/accessibility/flutter/ax_tree_source_flutter.h" +#include "chromecast/browser/cast_web_contents.h" +#include "content/public/browser/render_frame_host.h" +#include "content/public/browser/web_contents.h" +#include "ui/accessibility/ax_tree_id_registry.h" + +using gallium::castos::ActionProperties; +using gallium::castos::BooleanProperties; + +namespace chromecast { +namespace accessibility { + +FlutterSemanticsNodeWrapper::FlutterSemanticsNodeWrapper( + AXTreeSourceFlutter* tree_source, + const SemanticsNode* node) + : tree_source_(tree_source), node_ptr_(node) { + DCHECK(tree_source_); + DCHECK(node_ptr_); +} + +int32_t FlutterSemanticsNodeWrapper::GetId() const { + return node_ptr_->node_id(); +} + +const gfx::Rect FlutterSemanticsNodeWrapper::GetBounds() const { + if (node_ptr_->has_bounds_in_screen()) { + return gfx::Rect(node_ptr_->bounds_in_screen().left(), + node_ptr_->bounds_in_screen().top(), + node_ptr_->bounds_in_screen().right() - + node_ptr_->bounds_in_screen().left(), + node_ptr_->bounds_in_screen().bottom() - + node_ptr_->bounds_in_screen().top()); + } + return gfx::Rect(0, 0, 0, 0); +} + +bool FlutterSemanticsNodeWrapper::IsVisibleToUser() const { + if (node_ptr_->has_boolean_properties()) { + const BooleanProperties& boolean_properties = + node_ptr_->boolean_properties(); + return !boolean_properties.is_hidden(); + } + return true; +} + +bool FlutterSemanticsNodeWrapper::IsFocused() const { + if (node_ptr_->has_boolean_properties()) { + const BooleanProperties& boolean_properties = + node_ptr_->boolean_properties(); + return boolean_properties.is_focused(); + } + return false; +} + +bool FlutterSemanticsNodeWrapper::IsLiveRegion() const { + const BooleanProperties& boolean_properties = node_ptr_->boolean_properties(); + return boolean_properties.is_live_region(); +} + +bool FlutterSemanticsNodeWrapper::CanBeAccessibilityFocused() const { + // In Chrome, this means: + // a node with a non-generic role and: + // actionable nodes or top level scrollables with a name + ui::AXNodeData data; + PopulateAXRole(&data); + bool non_generic_role = data.role != ax::mojom::Role::kGenericContainer && + data.role != ax::mojom::Role::kGroup; + bool actionable = node_ptr_->action_properties().tap() || + node_ptr_->action_properties().long_press(); + bool top_level_scrollable = + HasLabelHint() && (node_ptr_->action_properties().scroll_up() || + node_ptr_->action_properties().scroll_down() || + node_ptr_->action_properties().scroll_left() || + node_ptr_->action_properties().scroll_right()); + return non_generic_role && (actionable || top_level_scrollable); +} + +void FlutterSemanticsNodeWrapper::PopulateAXRole( + ui::AXNodeData* out_data) const { + const BooleanProperties& boolean_properties = node_ptr_->boolean_properties(); + const ActionProperties& action_properties = node_ptr_->action_properties(); + + if (boolean_properties.is_text_field()) { + out_data->role = ax::mojom::Role::kTextField; + return; + } + + if (boolean_properties.is_header()) { + out_data->role = ax::mojom::Role::kHeading; + return; + } + + // b/148808637: Flutter allows buttons to be containers but ChromeVox + // expects buttons to be atomic. If we allow this node to be marked a + // button and it contains other clickable nodes, none of those nodes will + // be focusable by the user. This means no button that is also a + // container of other actionable items will ever be read as 'button' + // by the screen reader. However, buttons that have no actionable + // descendants will still say 'Button' as expected. + if (boolean_properties.is_button() && !AnyChildIsActionable() && + HasLabelHint() && GetLabelHint().length() > 0) { + out_data->role = ax::mojom::Role::kButton; + return; + } + + if (boolean_properties.is_image() && + node_ptr_->child_node_ids().size() == 0) { + out_data->role = ax::mojom::Role::kImage; + return; + } + + if (action_properties.increase() || action_properties.decrease()) { + out_data->role = ax::mojom::Role::kSlider; + return; + } + + bool has_checked_state = boolean_properties.has_checked_state(); + bool has_toggled_state = boolean_properties.has_toggled_state(); + + if (has_checked_state) { + if (boolean_properties.is_in_mutually_exclusive_group()) { + out_data->role = ax::mojom::Role::kRadioButton; + } else { + out_data->role = ax::mojom::Role::kCheckBox; + } + return; + } + if (has_toggled_state) { + out_data->role = ax::mojom::Role::kSwitch; + return; + } + + // b/149934151 : Flutter sends us nodes with labels that + // have children. Don't mark these as static text or + // no children will ever be focused properly via swipe + // navigation. Only nodes that have labels with no children + // should get the static text role. Use kHeader role + // instead as it is allowed to be a container. + if (HasLabelHint() && GetLabelHint().length() > 0) { + if (node_ptr_->child_node_ids().size() == 0) { + if (HasTapOrPress()) { + out_data->role = ax::mojom::Role::kButton; + } else { + out_data->role = ax::mojom::Role::kStaticText; + } + } else { + if (IsListItem()) { + out_data->role = ax::mojom::Role::kListBoxOption; + } else { + out_data->role = ax::mojom::Role::kHeader; + } + } + return; + } + + if (node_ptr_->scroll_children() > 0) { + out_data->role = ax::mojom::Role::kList; + return; + } + + out_data->role = ax::mojom::Role::kGenericContainer; +} + +FlutterSemanticsNodeWrapper* FlutterSemanticsNodeWrapper::IsListItem() const { + // To consider it a list item, the node has to have a ancestor that has scroll + // children. + std::vector<FlutterSemanticsNodeWrapper*> ancestors; + FlutterSemanticsNodeWrapper* node = static_cast<FlutterSemanticsNodeWrapper*>( + tree_source_->GetFromId(GetId())); + + while (node) { + FlutterSemanticsNodeWrapper* parent = + static_cast<FlutterSemanticsNodeWrapper*>( + tree_source_->GetParent(node)); + if (parent) + ancestors.push_back(parent); + node = parent; + } + + // |ancestors| is with order from closest ancestor to root. Find the closest + // ancestor that has scroll children and in between there is no actionable + // nodes. + for (FlutterSemanticsNodeWrapper* ancestor : ancestors) { + if (!ancestor->IsActionable()) { + if (ancestor->node()->scroll_children() > 0) { + return ancestor; + } + } else { + break; + } + } + + return nullptr; +} + +void FlutterSemanticsNodeWrapper::GetActionableChildren( + std::vector<FlutterSemanticsNodeWrapper*>* out_children) const { + std::vector<FlutterSemanticsNode*> children; + GetChildren(&children); + + for (FlutterSemanticsNode* child : children) { + FlutterSemanticsNodeWrapper* child_wrapper = + static_cast<FlutterSemanticsNodeWrapper*>(child); + + if (child_wrapper->HasTapOrPress() || + child_wrapper->AnyChildIsActionable()) { + out_children->push_back(child_wrapper); + } + } +} + +bool FlutterSemanticsNodeWrapper::IsDescendant( + FlutterSemanticsNodeWrapper* ancestor) const { + FlutterSemanticsNodeWrapper* parent = + static_cast<FlutterSemanticsNodeWrapper*>( + tree_source_->GetParent(tree_source_->GetFromId(GetId()))); + + while (parent) { + if (parent == ancestor) + return true; + parent = static_cast<FlutterSemanticsNodeWrapper*>( + tree_source_->GetParent(parent)); + } + + return false; +} + +bool FlutterSemanticsNodeWrapper::IsRapidChangingSlider() const { + return (node_ptr_->scroll_extent_min() || node_ptr_->scroll_extent_min() || + node_ptr_->action_properties().increase() || + node_ptr_->action_properties().decrease()); +} + +void FlutterSemanticsNodeWrapper::PopulateAXState( + ui::AXNodeData* out_data) const { + const BooleanProperties& boolean_properties = node_ptr_->boolean_properties(); + + if (boolean_properties.is_obscured()) { + out_data->AddState(ax::mojom::State::kProtected); + } + + if (boolean_properties.is_text_field()) { + out_data->AddState(ax::mojom::State::kEditable); + } + + if (IsFocusable()) { + out_data->AddState(ax::mojom::State::kFocusable); + } + + if (boolean_properties.has_checked_state()) { + out_data->SetCheckedState(boolean_properties.is_checked() + ? ax::mojom::CheckedState::kTrue + : ax::mojom::CheckedState::kFalse); + } + + if (boolean_properties.has_toggled_state()) { + out_data->SetCheckedState(boolean_properties.is_toggled() + ? ax::mojom::CheckedState::kTrue + : ax::mojom::CheckedState::kFalse); + } + + // Put this back after b/148875421 is resolved. Flutter is sending + // many elements with a disabled flag which causes the reader to + // speak 'Disabled' even though it is not. + // if (!boolean_properties.is_enabled()) { + // out_data->SetRestriction(ax::mojom::Restriction::kDisabled); + //} +} + +void FlutterSemanticsNodeWrapper::Serialize(ui::AXNodeData* out_data) const { + PopulateAXState(out_data); + + const BooleanProperties& boolean_properties = node_ptr_->boolean_properties(); + const ActionProperties& action_properties = node_ptr_->action_properties(); + + // b/162311902: For nodes that have scroll extents and can be changed rapidly, + // set the name as empty so that ChromeVox will skip speaking them. + if (IsRapidChangingSlider()) { + out_data->SetName(""); + } else if (HasLabelHint()) { + out_data->SetName(GetLabelHint()); + } else if (IsActionable()) { + // Compute the name by joining all nodes with names. + std::vector<std::string> names; + ComputeNameFromContents(&names); + if (!names.empty()) + out_data->SetName(base::JoinString(names, " ")); + } + + if (HasValue()) { + out_data->SetValue(GetValue()); + } + + out_data->AddBoolAttribute(ax::mojom::BoolAttribute::kClickable, + IsActionable()); + out_data->AddBoolAttribute(ax::mojom::BoolAttribute::kScrollable, + IsScrollable()); + + if (boolean_properties.is_selected()) { + out_data->AddBoolAttribute(ax::mojom::BoolAttribute::kSelected, true); + } + + if (node_ptr_->has_hint()) { + out_data->AddStringAttribute(ax::mojom::StringAttribute::kPlaceholder, + node_ptr_->hint()); + } + + // Set bounds + if (tree_source_->GetRoot()->GetId() != -1) { + // TODO(rmrossi) Pass in nullptr for now for active window. Root node will + // get bounds relative to 0,0 anyway since we are full screen. This may + // change if flutter is ever not full screen in which case we will have + // to pass in the bounds of whatever container it resides in. + const gfx::Rect& local_bounds = + tree_source_->GetBounds(tree_source_->GetFromId(GetId())); + out_data->relative_bounds.bounds.SetRect(local_bounds.x(), local_bounds.y(), + local_bounds.width(), + local_bounds.height()); + } + + if (node_ptr_->has_text_selection_base()) { + out_data->AddIntAttribute(ax::mojom::IntAttribute::kTextSelStart, + node_ptr_->text_selection_base()); + } + + if (node_ptr_->has_text_selection_extent()) { + out_data->AddIntAttribute(ax::mojom::IntAttribute::kTextSelEnd, + node_ptr_->text_selection_extent()); + } + + if (action_properties.has_scroll_left() || + action_properties.has_scroll_up()) { + out_data->AddAction(ax::mojom::Action::kScrollBackward); + } + + if (action_properties.has_scroll_right() || + action_properties.has_scroll_down()) { + out_data->AddAction(ax::mojom::Action::kScrollForward); + } + + if (action_properties.set_selection()) { + out_data->AddAction(ax::mojom::Action::kSetSelection); + } + + if (action_properties.increase()) { + out_data->AddAction(ax::mojom::Action::kIncrement); + } + + if (action_properties.decrease()) { + out_data->AddAction(ax::mojom::Action::kDecrement); + } + + if (IsScrollable()) { + const float position = node_ptr_->scroll_position(); + const float min = node_ptr_->scroll_extent_min(); + const float max = node_ptr_->scroll_extent_max(); + if (node_ptr_->action_properties().scroll_up() || + node_ptr_->action_properties().scroll_down()) { + out_data->AddIntAttribute(ax::mojom::IntAttribute::kScrollY, position); + out_data->AddIntAttribute(ax::mojom::IntAttribute::kScrollYMin, min); + out_data->AddIntAttribute(ax::mojom::IntAttribute::kScrollYMax, max); + } else if (node_ptr_->action_properties().scroll_left() || + node_ptr_->action_properties().scroll_right()) { + out_data->AddIntAttribute(ax::mojom::IntAttribute::kScrollX, position); + out_data->AddIntAttribute(ax::mojom::IntAttribute::kScrollXMin, min); + out_data->AddIntAttribute(ax::mojom::IntAttribute::kScrollXMax, max); + } + } + + if (node_ptr_->custom_actions_size() > 0) { + std::vector<int32_t> ids; + std::vector<std::string> labels; + for (int i = 0; i < node_ptr_->custom_actions_size(); i++) { + ids.push_back(node_ptr_->custom_actions(i).id()); + labels.push_back(node_ptr_->custom_actions(i).label()); + } + out_data->AddAction(ax::mojom::Action::kCustomAction); + out_data->AddIntListAttribute(ax::mojom::IntListAttribute::kCustomActionIds, + ids); + out_data->AddStringListAttribute( + ax::mojom::StringListAttribute::kCustomActionDescriptions, labels); + } + + if (node_ptr_->has_plugin_id()) { + std::string ax_tree_id = node_ptr_->plugin_id(); + if (ax_tree_id.rfind("T:", 0) == 0) { + // This is a cast web contents id. Find the matching + // CastWebContents and find the ax tree id from there. + int web_contents_id; + base::StringToInt(ax_tree_id.substr(2), &web_contents_id); + std::vector<CastWebContents*> all_contents = CastWebContents::GetAll(); + // There will likely only ever be one active at any time. + for (CastWebContents* contents : all_contents) { + if (contents->id() == web_contents_id) { + content::WebContents* web_contents = contents->web_contents(); + out_data->AddStringAttribute( + ax::mojom::StringAttribute::kChildTreeId, + web_contents->GetMainFrame()->GetAXTreeID().ToString()); + break; + } + } + } else { + // Use the value as a tree id. + out_data->AddStringAttribute(ax::mojom::StringAttribute::kChildTreeId, + ax_tree_id); + } + } + + if (boolean_properties.is_live_region()) { + out_data->AddStringAttribute( + ax::mojom::StringAttribute::kContainerLiveStatus, "polite"); + out_data->AddStringAttribute( + ax::mojom::StringAttribute::kContainerLiveRelevant, "text"); + } + + if (out_data->role == ax::mojom::Role::kListBoxOption) { + // Find the ancestor whose role is kList. + FlutterSemanticsNodeWrapper* ancestor = IsListItem(); + + std::vector<FlutterSemanticsNodeWrapper*> ancestor_actionable_children; + ancestor->GetActionableChildren(&ancestor_actionable_children); + + // kSetSize should be the number of actionable children that the scrollable + // ancestor has. + out_data->AddIntAttribute(ax::mojom::IntAttribute::kSetSize, + ancestor_actionable_children.size()); + + // Find which children tree that this node is in. + for (size_t i = 0; i < ancestor_actionable_children.size(); ++i) { + if (IsDescendant(ancestor_actionable_children[i])) { + out_data->AddIntAttribute(ax::mojom::IntAttribute::kPosInSet, i + 1); + break; + } + } + } + + if (out_data->role == ax::mojom::Role::kList) { + // Find the size of actionable children. + std::vector<FlutterSemanticsNodeWrapper*> actionable_children; + GetActionableChildren(&actionable_children); + + out_data->AddIntAttribute(ax::mojom::IntAttribute::kSetSize, + actionable_children.size()); + } +} + +void FlutterSemanticsNodeWrapper::GetChildren( + std::vector<FlutterSemanticsNode*>* children) const { + for (auto id : node_ptr_->child_node_ids()) { + FlutterSemanticsNode* node = tree_source_->GetFromId(id); + if (node) { + children->push_back(tree_source_->GetFromId(id)); + } else { + LOG(ERROR) << "Node id present for which there is no child node given"; + } + } +} + +bool FlutterSemanticsNodeWrapper::AnyChildIsActionable() const { + // b/156940104 - If this node is host to a child tree, we + // can assume at least one of it's child nodes is actionable. + // Otherwise, none of it's descendants will be traversed by + // the reader. + if (node_ptr_->has_plugin_id()) { + return true; + } + for (auto child_id : node_ptr_->child_node_ids()) { + FlutterSemanticsNodeWrapper* child = + static_cast<FlutterSemanticsNodeWrapper*>( + tree_source_->GetFromId(child_id)); + if (child->HasTapOrPress()) { + return true; + } + if (child->AnyChildIsActionable()) { + return true; + } + } + return false; +} + +bool FlutterSemanticsNodeWrapper::HasTapOrPress() const { + return node_ptr_->boolean_properties().is_button() || + node_ptr_->action_properties().tap() || + node_ptr_->action_properties().long_press(); +} + +bool FlutterSemanticsNodeWrapper::IsActionable() const { + // When flutter tells us a generic container is actionable, do not allow this + // unless all children of this node are NOT actionable. Otherwise, the + // tree walker will consider this node a leaf and it will not navigate to + // any actionable children. + bool actionable = HasTapOrPress(); + + ui::AXNodeData data; + PopulateAXRole(&data); + if (actionable && data.role == ax::mojom::Role::kGenericContainer && + AnyChildIsActionable()) { + actionable = false; + } + // If this node is actionable but is also the host for a child tree, + // don't make it actionable or else chromevox won't traverse into + // any child. + if (node_ptr_->has_plugin_id()) { + actionable = false; + } + return actionable; +} + +bool FlutterSemanticsNodeWrapper::IsScrollable() const { + return node_ptr_->action_properties().scroll_up() || + node_ptr_->action_properties().scroll_down() || + node_ptr_->action_properties().scroll_left() || + node_ptr_->action_properties().scroll_right(); +} + +bool FlutterSemanticsNodeWrapper::IsFocusable() const { + const BooleanProperties& boolean_properties = node_ptr_->boolean_properties(); + if (boolean_properties.scopes_route()) + return false; + + bool focusable_flags = + boolean_properties.has_checked_state() || + boolean_properties.is_checked() || boolean_properties.is_selected() || + HasTapOrPress() || boolean_properties.is_text_field() || + boolean_properties.is_focused() || + boolean_properties.has_enabled_state() || + boolean_properties.is_enabled() || + boolean_properties.is_in_mutually_exclusive_group() || + boolean_properties.is_header() || boolean_properties.is_obscured() || + boolean_properties.names_route() || + (boolean_properties.is_image() && + node_ptr_->child_node_ids().size() == 0) || + boolean_properties.is_live_region() || + boolean_properties.has_toggled_state() || boolean_properties.is_toggled(); + + // b/149934151 : If a node has a label but also has children, don't + // mark it focusable, otherwise none of its children will be navigable + // via swipe nav. It's role wlil be a generic container (see above). + return focusable_flags || (HasLabelHint() && !GetLabelHint().empty() && + node_ptr_->child_node_ids().size() == 0); +} + +bool FlutterSemanticsNodeWrapper::HasLabelHint() const { + return node_ptr_->has_label() || node_ptr_->has_hint(); +} + +std::string FlutterSemanticsNodeWrapper::GetLabelHint() const { + // TODO(rmrossi): Find out whether this order of precedence makes sense + if (node_ptr_->has_label() && node_ptr_->label().length() > 0) { + return node_ptr_->label(); + } + if (node_ptr_->has_hint() && node_ptr_->hint().length() > 0) { + return node_ptr_->hint(); + } + return ""; +} + +void FlutterSemanticsNodeWrapper::ComputeNameFromContents( + std::vector<std::string>* names) const { + DCHECK(names); + std::string name; + if (HasLabelHint()) { + name = GetLabelHint(); + if (!name.empty()) { + names->push_back(name); + return; + } + } + + std::vector<FlutterSemanticsNode*> children; + GetChildren(&children); + for (const FlutterSemanticsNode* child : children) { + child->ComputeNameFromContents(names); + } +} + +bool FlutterSemanticsNodeWrapper::HasValue() const { + return node_ptr_->has_value(); +} + +std::string FlutterSemanticsNodeWrapper::GetValue() const { + return node_ptr_->value(); +} + +} // namespace accessibility +} // namespace chromecast
diff --git a/chromecast/browser/accessibility/flutter/flutter_semantics_node_wrapper.h b/chromecast/browser/accessibility/flutter/flutter_semantics_node_wrapper.h new file mode 100644 index 0000000..658f588f --- /dev/null +++ b/chromecast/browser/accessibility/flutter/flutter_semantics_node_wrapper.h
@@ -0,0 +1,74 @@ +// Copyright 2019 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 CHROMECAST_BROWSER_ACCESSIBILITY_FLUTTER_FLUTTER_SEMANTICS_NODE_WRAPPER_H_ +#define CHROMECAST_BROWSER_ACCESSIBILITY_FLUTTER_FLUTTER_SEMANTICS_NODE_WRAPPER_H_ + +#include <string> +#include <vector> + +#include "chromecast/browser/accessibility/flutter/flutter_semantics_node.h" +#include "chromecast/browser/accessibility/proto/cast_server_accessibility.pb.h" +#include "ui/accessibility/ax_enum_util.h" +#include "ui/accessibility/ax_node_data.h" + +namespace chromecast { +namespace accessibility { + +using gallium::castos::SemanticsNode; + +class AXTreeSourceFlutter; + +// A wrapper class for a SemanticsNode proto object. +// This is used by AXTreeSourceFlutter to create accessibility tree updates +// from semantics trees sent to us from the flutter process. +class FlutterSemanticsNodeWrapper : public FlutterSemanticsNode { + public: + FlutterSemanticsNodeWrapper(AXTreeSourceFlutter* tree_source, + const SemanticsNode* node); + FlutterSemanticsNodeWrapper(const FlutterSemanticsNodeWrapper&) = delete; + FlutterSemanticsNodeWrapper& operator=(const FlutterSemanticsNodeWrapper&) = + delete; + + // FlutterSemanticsNode implementation: + int32_t GetId() const override; + const gfx::Rect GetBounds() const override; + bool IsVisibleToUser() const override; + bool IsFocused() const override; + bool IsLiveRegion() const override; + bool IsRapidChangingSlider() const override; + bool CanBeAccessibilityFocused() const override; + void PopulateAXRole(ui::AXNodeData* out_data) const override; + void PopulateAXState(ui::AXNodeData* out_data) const override; + void Serialize(ui::AXNodeData* out_data) const override; + void GetChildren(std::vector<FlutterSemanticsNode*>* children) const override; + bool HasLabelHint() const override; + std::string GetLabelHint() const override; + bool HasValue() const override; + std::string GetValue() const override; + + const SemanticsNode* node() { return node_ptr_; } + + private: + bool AnyChildIsActionable() const; + bool HasTapOrPress() const; + bool IsActionable() const; + bool IsScrollable() const; + bool IsFocusable() const; + void ComputeNameFromContents(std::vector<std::string>* names) const override; + void GetActionableChildren( + std::vector<FlutterSemanticsNodeWrapper*>* out_children) const; + // Check if this is a list item and return the node of its ancestor whose role + // is kList + FlutterSemanticsNodeWrapper* IsListItem() const; + bool IsDescendant(FlutterSemanticsNodeWrapper* ancestor) const; + + AXTreeSourceFlutter* const tree_source_; + const SemanticsNode* const node_ptr_; +}; + +} // namespace accessibility +} // namespace chromecast + +#endif // CHROMECAST_BROWSER_ACCESSIBILITY_FLUTTER_FLUTTER_SEMANTICS_NODE_WRAPPER_H_
diff --git a/chromecast/browser/accessibility/proto/BUILD.gn b/chromecast/browser/accessibility/proto/BUILD.gn new file mode 100644 index 0000000..e1e606b --- /dev/null +++ b/chromecast/browser/accessibility/proto/BUILD.gn
@@ -0,0 +1,16 @@ +import("//third_party/protobuf/proto_library.gni") + +proto_library("gallium_accessibility_proto") { + sources = [ + "cast_server_accessibility.proto", + "gallium_server_accessibility.proto", + ] + + deps = [ + "//third_party/grpc:grpcpp", + "//third_party/protobuf:protobuf_lite", + ] + + generator_plugin_label = "//third_party/grpc:grpc_cpp_plugin" + generator_plugin_suffix = ".grpc.pb" +}
diff --git a/chromecast/browser/accessibility/proto/cast_server_accessibility.proto b/chromecast/browser/accessibility/proto/cast_server_accessibility.proto new file mode 100644 index 0000000..25dfe56 --- /dev/null +++ b/chromecast/browser/accessibility/proto/cast_server_accessibility.proto
@@ -0,0 +1,116 @@ +syntax = "proto2"; + +package gallium.castos; + +option optimize_for = LITE_RUNTIME; + +message Rect { + optional int32 left = 1; + optional int32 top = 2; + optional int32 right = 3; + optional int32 bottom = 4; +} + +message BooleanProperties { + optional bool has_checked_state = 1; + optional bool is_checked = 2; + optional bool is_selected = 3; + optional bool is_button = 4; + optional bool is_text_field = 5; + optional bool is_focused = 6; + optional bool has_enabled_state = 7; + optional bool is_enabled = 8; + optional bool is_in_mutually_exclusive_group = 9; + optional bool is_header = 10; + optional bool is_obscured = 11; + optional bool scopes_route = 12; + optional bool names_route = 13; + optional bool is_hidden = 14; + optional bool is_image = 15; + optional bool is_live_region = 16; + optional bool has_toggled_state = 17; + optional bool is_toggled = 18; + optional bool has_implicit_scrolling = 19; +} + +message ActionProperties { + optional bool tap = 1; + optional bool long_press = 2; + optional bool scroll_left = 3; + optional bool scroll_right = 4; + optional bool scroll_up = 5; + optional bool scroll_down = 6; + optional bool increase = 7; + optional bool decrease = 8; + optional bool show_on_screen = 9; + optional bool move_cursor_forward_by_character = 10; + optional bool move_cursor_backward_by_character = 11; + optional bool set_selection = 12; + optional bool copy = 13; + optional bool cut = 14; + optional bool paste = 15; + optional bool did_gain_accessibility_focus = 16; + optional bool did_lose_accessibility_focus = 17; + optional bool custom_action = 18; + optional bool dismiss = 19; + optional bool move_cursor_forward_by_word = 20; + optional bool move_cursor_backward_by_word = 21; +}; + +message CustomAction { + optional int32 id = 1; + optional string label = 2; +} + +message SemanticsNode { + optional int32 node_id = 1; + optional Rect bounds_in_screen = 2; + optional int32 window_id = 3; + repeated int32 child_node_ids = 4; + optional BooleanProperties boolean_properties = 5; + optional ActionProperties action_properties = 6; + optional string value = 7; + optional string label = 8; + optional string hint = 9; + optional string text_direction = 10; + optional int32 resource_id = 11; + optional int32 text_selection_base = 12; + optional int32 text_selection_extent = 13; + optional int32 scroll_children = 14; + optional int32 scroll_index = 15; + optional float scroll_position = 16; + optional int32 scroll_extent_max = 17; + optional int32 scroll_extent_min = 18; + repeated CustomAction custom_actions = 19; + // If set, indicates the semantics information for this node + // is provided by a platform plugin or some other native backed + // entity. + optional string plugin_id = 20; +} + +message OnAccessibilityEventRequest { + enum EventType { + UNSPECIFIED = 0; + FOCUSED = 1; + FOCUS_CLEARED = 2; + HOVER_ENTER = 3; + HOVER_EXIT = 4; + CLICKED = 5; + LONG_CLICKED = 6; + WINDOW_STATE_CHANGED = 7; + TEXT_CHANGED = 8; + TEXT_SELECTION_CHANGED = 9; + CONTENT_CHANGED = 10; + SCROLLED = 11; + } + // Type of event this represents. + optional EventType event_type = 1; + // The node responsible for triggering this event. + optional int32 source_id = 2; + // Unique identifier for flutter window. + optional int32 window_id = 3; + // The 'flattened' semantic tree nodes. + repeated SemanticsNode node_data = 4; +} + +message OnAccessibilityEventResponse {}
diff --git a/chromecast/browser/accessibility/proto/gallium_server_accessibility.proto b/chromecast/browser/accessibility/proto/gallium_server_accessibility.proto new file mode 100644 index 0000000..04918fe --- /dev/null +++ b/chromecast/browser/accessibility/proto/gallium_server_accessibility.proto
@@ -0,0 +1,54 @@ +syntax = "proto2"; + +package gallium.castos; + +option optimize_for = LITE_RUNTIME; + +message OnAccessibilityStateChangedRequest { + optional bool enabled = 1; +} + +message OnAccessibilityStateChangedResponse {} + +message OnAccessibilityActionRequest { + enum AccessibilityActionType { + UNSPECIFIED = 0; + TAP = 1; + LONG_PRESS = 2; + SCROLL_LEFT = 3; + SCROLL_RIGHT = 4; + SCROLL_UP = 5; + SCROLL_DOWN = 6; + INCREASE = 7; + DECREASE = 8; + SHOW_ON_SCREEN = 9; + MOVE_CURSOR_FORWARD_BY_CHARACTER = 10; + MOVE_CURSOR_BACKWARD_BY_CHARACTER = 11; + SET_SELECTION = 12; + COPY = 13; + CUT = 14; + PASTE = 15; + DID_GAIN_ACCESSIBILITY_FOCUS = 16; + DID_LOSE_ACCESSIBILITY_FOCUS = 17; + CUSTOM_ACTION = 18; + DISMISS = 19; + MOVE_CURSOR_FORWARD_BY_WORD = 20; + MOVE_CURSOR_BACKWARD_BY_WORD = 21; + } + + optional int32 node_id = 1; + + optional AccessibilityActionType action_type = 2; + + // custom_action_id must be set if action_type is CUSTOM_ACTION. + optional int32 custom_action_id = 3; + + // window_id where the action is performed. + optional int32 window_id = 4; + + // Parameters specifying indices to get text location of node. + optional int32 start_index = 5; + optional int32 end_index = 6; +} + +message OnAccessibilityActionResponse {}
diff --git a/chromeos/components/telemetry_extension_ui/diagnostics_service.cc b/chromeos/components/telemetry_extension_ui/diagnostics_service.cc index 567cce9..161e6b76 100644 --- a/chromeos/components/telemetry_extension_ui/diagnostics_service.cc +++ b/chromeos/components/telemetry_extension_ui/diagnostics_service.cc
@@ -148,4 +148,18 @@ std::move(callback))); } +void DiagnosticsService::RunFloatingPointAccuracyRoutine( + uint32_t length_seconds, + RunFloatingPointAccuracyRoutineCallback callback) { + GetService()->RunFloatingPointAccuracyRoutine( + length_seconds, + base::BindOnce( + [](health::mojom::DiagnosticsService:: + RunFloatingPointAccuracyRoutineCallback callback, + cros_healthd::mojom::RunRoutineResponsePtr ptr) { + std::move(callback).Run(converters::ConvertPtr(std::move(ptr))); + }, + std::move(callback))); +} + } // namespace chromeos
diff --git a/chromeos/components/telemetry_extension_ui/diagnostics_service.h b/chromeos/components/telemetry_extension_ui/diagnostics_service.h index e6d72ec..38a3da7 100644 --- a/chromeos/components/telemetry_extension_ui/diagnostics_service.h +++ b/chromeos/components/telemetry_extension_ui/diagnostics_service.h
@@ -48,6 +48,9 @@ RunCpuCacheRoutineCallback callback) override; void RunCpuStressRoutine(uint32_t length_seconds, RunCpuStressRoutineCallback callback) override; + void RunFloatingPointAccuracyRoutine( + uint32_t length_seconds, + RunFloatingPointAccuracyRoutineCallback callback) override; // Ensures that |service_| created and connected to the // CrosHealthdProbeService.
diff --git a/chromeos/components/telemetry_extension_ui/mojom/diagnostics_service.mojom b/chromeos/components/telemetry_extension_ui/mojom/diagnostics_service.mojom index bc439965..b158a9e 100644 --- a/chromeos/components/telemetry_extension_ui/mojom/diagnostics_service.mojom +++ b/chromeos/components/telemetry_extension_ui/mojom/diagnostics_service.mojom
@@ -134,6 +134,25 @@ // routine. RunCpuStressRoutine(uint32 length_seconds) => (RunRoutineResponse response); + + // Requests that the FloatingPointAccuracy routine is created and started + // on the platform. This routine executes millions of floating-point + // operations by SSE instructions for a specified amount of time. The routine + // will pass if the result values of the operations and known accurate result + // are the same. + // + // The request: + // * |length_seconds| - length of time, in seconds, to run the floating-point + // routine for. Test will executes millions of + // floating-point operations in length seconds and get + // the result to compare with known accurate results. + // This parameter needs to be strictly greater than zero. + // + // The response: + // * |response| - contains a unique identifier and status for the created + // routine. + RunFloatingPointAccuracyRoutine(uint32 length_seconds) + => (RunRoutineResponse response); }; // Enumeration of each of the diagnostics routines the platform may support.
diff --git a/chromeos/components/telemetry_extension_ui/resources/message_types.js b/chromeos/components/telemetry_extension_ui/resources/message_types.js index d4da227..78607db 100644 --- a/chromeos/components/telemetry_extension_ui/resources/message_types.js +++ b/chromeos/components/telemetry_extension_ui/resources/message_types.js
@@ -29,6 +29,8 @@ DIAGNOSTICS_RUN_AC_POWER_ROUTINE: 'DiagnosticsService.RunAcPowerRoutine', DIAGNOSTICS_RUN_CPU_CACHE_ROUTINE: 'DiagnosticsService.RunCpuCacheRoutine', DIAGNOSTICS_RUN_CPU_STRESS_ROUTINE: 'DiagnosticsService.RunCpuStressRoutine', + DIAGNOSTICS_RUN_FP_ACCURACY_ROUTINE: + 'DiagnosticsService.RunFloatingPointAccuraryRoutine', PROBE_TELEMETRY_INFO: 'ProbeService.ProbeTelemetryInfo', }; @@ -112,6 +114,13 @@ dpsl_internal.DiagnosticsRunCpuStressRoutineRequest; /** + * Request message sent by the unprivileged context to the privileged + * context to run floating point accuracy routine. + * @typedef {{ duration: !number }} + */ +dpsl_internal.DiagnosticsRunFPAccuracyRoutineRequest; + +/** * Response message sent by the privileged context containing routine * information. * @typedef { !Object | !Error }
diff --git a/chromeos/components/telemetry_extension_ui/resources/trusted.js b/chromeos/components/telemetry_extension_ui/resources/trusted.js index cf3c7fec..03e1cb2be 100644 --- a/chromeos/components/telemetry_extension_ui/resources/trusted.js +++ b/chromeos/components/telemetry_extension_ui/resources/trusted.js
@@ -406,6 +406,20 @@ return await getOrCreateDiagnosticsService().runCpuStressRoutine( request.duration); }; + + /** + * Runs floating point accuracy routine. + * @param { !Object } message + * @return { !RunRoutineResponsePromise } + */ + async handleRunFloatingPointAccuracyRoutine(message) { + const request = + /** @type {!dpsl_internal.DiagnosticsRunFPAccuracyRoutineRequest} */ + (message); + this.assertNumberIsPositive(request.duration); + return await getOrCreateDiagnosticsService() + .runFloatingPointAccuracyRoutine(request.duration); + }; }; const diagnosticsProxy = new DiagnosticsProxy(); @@ -722,5 +736,12 @@ message)); untrustedMessagePipe.registerHandler( + dpsl_internal.Message.DIAGNOSTICS_RUN_FP_ACCURACY_ROUTINE, + (message) => diagnosticsProxy.genericRunRoutineHandler( + (message) => + diagnosticsProxy.handleRunFloatingPointAccuracyRoutine(message), + message)); + +untrustedMessagePipe.registerHandler( dpsl_internal.Message.PROBE_TELEMETRY_INFO, (message) => telemetryProxy.handleProbeTelemetryInfo(message));
diff --git a/chromeos/components/telemetry_extension_ui/resources/untrusted.js b/chromeos/components/telemetry_extension_ui/resources/untrusted.js index 1ac484a..0ed8e7c 100644 --- a/chromeos/components/telemetry_extension_ui/resources/untrusted.js +++ b/chromeos/components/telemetry_extension_ui/resources/untrusted.js
@@ -202,6 +202,26 @@ } return response; } + + /** + * Requests floating point accuracy routine to be run for duration seconds. + * @param { !number } duration + * @return { !Promise<!Object> } + * @public + */ + async runFloatingPointAccuracyRoutine(duration) { + const message = + /** @type {!dpsl_internal.DiagnosticsRunFPAccuracyRoutineRequest} */ + ({duration: duration}); + const response = + /** @type {!Object} */ (await messagePipe.sendMessage( + dpsl_internal.Message.DIAGNOSTICS_RUN_FP_ACCURACY_ROUTINE, + message)); + if (response instanceof Error) { + throw response; + } + return response; + } }; /**
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 abf952e..a18a63fe 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
@@ -425,6 +425,22 @@ TEST_F( 'TelemetryExtensionUIBrowserTest', + 'UntrustedDiagnosticsRequestRunFPAccuracyRoutineInvalidInput', async () => { + await runTestInUntrusted( + 'UntrustedDiagnosticsRequestRunFPAccuracyRoutineInvalidInput'); + testDone(); + }); + +TEST_F( + 'TelemetryExtensionUIBrowserTest', + 'UntrustedDiagnosticsRequestRunFPAccuracyRoutine', async () => { + await runTestInUntrusted( + 'UntrustedDiagnosticsRequestRunFPAccuracyRoutine'); + testDone(); + }); + +TEST_F( + 'TelemetryExtensionUIBrowserTest', 'UntrustedRequestTelemetryInfoUnknownCategory', async () => { await runTestInUntrusted('UntrustedRequestTelemetryInfoUnknownCategory'); testDone();
diff --git a/chromeos/components/telemetry_extension_ui/test/untrusted_browsertest.js b/chromeos/components/telemetry_extension_ui/test/untrusted_browsertest.js index 34c62944..4371279 100644 --- a/chromeos/components/telemetry_extension_ui/test/untrusted_browsertest.js +++ b/chromeos/components/telemetry_extension_ui/test/untrusted_browsertest.js
@@ -226,6 +226,38 @@ assertDeepEquals(response, {id: 123456789, status: 'ready'}); }); +// Tests that runFloatingPointAccuracyRoutine throws the correct error when +// invalid number is passed as input. +UNTRUSTED_TEST( + 'UntrustedDiagnosticsRequestRunFPAccuracyRoutineInvalidInput', async () => { + let caughtError1; + try { + await chromeos.diagnostics.runFloatingPointAccuracyRoutine(0); + } catch (error) { + caughtError1 = error; + } + + assertEquals(caughtError1.name, 'RangeError'); + assertEquals(caughtError1.message, `Parameter must be positive.`); + + let caughtError2; + try { + await chromeos.diagnostics.runFloatingPointAccuracyRoutine(-2147483648); + } catch (error) { + caughtError2 = error; + } + + assertEquals(caughtError2.name, 'RangeError'); + assertEquals(caughtError2.message, `Parameter must be positive.`); + }); + +// Tests that runFloatingPointAccuracyRoutine returns the correct Object. +UNTRUSTED_TEST('UntrustedDiagnosticsRequestRunFPAccuracyRoutine', async () => { + const response = + await chromeos.diagnostics.runFloatingPointAccuracyRoutine(5); + assertDeepEquals(response, {id: 123456789, status: 'ready'}); +}); + // Tests that TelemetryInfo can be successfully requested from // from chrome-untrusted://. UNTRUSTED_TEST('UntrustedRequestTelemetryInfo', async () => {
diff --git a/chromeos/constants/chromeos_features.cc b/chromeos/constants/chromeos_features.cc index 9a50d937..b874314 100644 --- a/chromeos/constants/chromeos_features.cc +++ b/chromeos/constants/chromeos_features.cc
@@ -518,6 +518,11 @@ const base::Feature kUseBrowserSyncConsent{"UseBrowserSyncConsent", base::FEATURE_DISABLED_BY_DEFAULT}; +// Use the staging server as part of the Wallpaper App to verify +// additions/removals of wallpapers. +const base::Feature kUseWallpaperStagingUrl{"UseWallpaperStagingUrl", + base::FEATURE_DISABLED_BY_DEFAULT}; + // Use the staging URL as part of the "Messages" feature under "Connected // Devices" settings. const base::Feature kUseMessagesStagingUrl{"UseMessagesStagingUrl",
diff --git a/chromeos/constants/chromeos_features.h b/chromeos/constants/chromeos_features.h index 159f8c15..3b7d1da4 100644 --- a/chromeos/constants/chromeos_features.h +++ b/chromeos/constants/chromeos_features.h
@@ -224,6 +224,8 @@ COMPONENT_EXPORT(CHROMEOS_CONSTANTS) extern const base::Feature kUseBrowserSyncConsent; COMPONENT_EXPORT(CHROMEOS_CONSTANTS) +extern const base::Feature kUseWallpaperStagingUrl; +COMPONENT_EXPORT(CHROMEOS_CONSTANTS) extern const base::Feature kUseMessagesStagingUrl; COMPONENT_EXPORT(CHROMEOS_CONSTANTS) extern const base::Feature kUserActivityPrediction;
diff --git a/chromeos/services/secure_channel/ble_connection_manager_impl.cc b/chromeos/services/secure_channel/ble_connection_manager_impl.cc index ca99a2b..5450228 100644 --- a/chromeos/services/secure_channel/ble_connection_manager_impl.cc +++ b/chromeos/services/secure_channel/ble_connection_manager_impl.cc
@@ -16,7 +16,6 @@ #include "chromeos/services/secure_channel/ble_initiator_failure_type.h" #include "chromeos/services/secure_channel/ble_listener_failure_type.h" #include "chromeos/services/secure_channel/ble_scanner_impl.h" -#include "chromeos/services/secure_channel/ble_synchronizer.h" #include "chromeos/services/secure_channel/ble_weave_client_connection.h" #include "chromeos/services/secure_channel/latency_metrics_logger.h" #include "chromeos/services/secure_channel/public/mojom/secure_channel.mojom.h" @@ -59,15 +58,19 @@ std::unique_ptr<BleConnectionManager> BleConnectionManagerImpl::Factory::Create( scoped_refptr<device::BluetoothAdapter> bluetooth_adapter, BleServiceDataHelper* ble_service_data_helper, + BleSynchronizerBase* ble_synchronizer, + BleScanner* ble_scanner, TimerFactory* timer_factory, base::Clock* clock) { if (test_factory_) { return test_factory_->CreateInstance( - bluetooth_adapter, ble_service_data_helper, timer_factory, clock); + bluetooth_adapter, ble_service_data_helper, ble_synchronizer, + ble_scanner, timer_factory, clock); } return base::WrapUnique(new BleConnectionManagerImpl( - bluetooth_adapter, ble_service_data_helper, timer_factory, clock)); + bluetooth_adapter, ble_service_data_helper, ble_synchronizer, ble_scanner, + timer_factory, clock)); } // static @@ -204,20 +207,18 @@ BleConnectionManagerImpl::BleConnectionManagerImpl( scoped_refptr<device::BluetoothAdapter> bluetooth_adapter, BleServiceDataHelper* ble_service_data_helper, + BleSynchronizerBase* ble_synchronizer, + BleScanner* ble_scanner, TimerFactory* timer_factory, base::Clock* clock) : bluetooth_adapter_(bluetooth_adapter), - ble_service_data_helper_(ble_service_data_helper), clock_(clock), - ble_synchronizer_(BleSynchronizer::Factory::Create(bluetooth_adapter)), + ble_scanner_(ble_scanner), ble_advertiser_( BleAdvertiserImpl::Factory::Create(this /* delegate */, - ble_service_data_helper_, - ble_synchronizer_.get(), + ble_service_data_helper, + ble_synchronizer, timer_factory)), - ble_scanner_(BleScannerImpl::Factory::Create(ble_service_data_helper_, - ble_synchronizer_.get(), - bluetooth_adapter)), secure_channel_disconnector_( SecureChannelDisconnectorImpl::Factory::Create()) { ble_scanner_->AddObserver(this);
diff --git a/chromeos/services/secure_channel/ble_connection_manager_impl.h b/chromeos/services/secure_channel/ble_connection_manager_impl.h index 60e6cf3..e7e3328 100644 --- a/chromeos/services/secure_channel/ble_connection_manager_impl.h +++ b/chromeos/services/secure_channel/ble_connection_manager_impl.h
@@ -49,6 +49,8 @@ static std::unique_ptr<BleConnectionManager> Create( scoped_refptr<device::BluetoothAdapter> bluetooth_adapter, BleServiceDataHelper* ble_service_data_helper, + BleSynchronizerBase* ble_synchronizer, + BleScanner* ble_scanner, TimerFactory* timer_factory, base::Clock* clock = base::DefaultClock::GetInstance()); static void SetFactoryForTesting(Factory* test_factory); @@ -58,6 +60,8 @@ virtual std::unique_ptr<BleConnectionManager> CreateInstance( scoped_refptr<device::BluetoothAdapter> bluetooth_adapter, BleServiceDataHelper* ble_service_data_helper, + BleSynchronizerBase* ble_synchronizer, + BleScanner* ble_scanner, TimerFactory* timer_factory, base::Clock* clock = base::DefaultClock::GetInstance()) = 0; @@ -103,6 +107,8 @@ BleConnectionManagerImpl( scoped_refptr<device::BluetoothAdapter> bluetooth_adapter, BleServiceDataHelper* ble_service_data_helper, + BleSynchronizerBase* ble_synchronizer, + BleScanner* ble_scanner, TimerFactory* timer_factory, base::Clock* clock); @@ -197,12 +203,10 @@ const std::string& remote_device_id); scoped_refptr<device::BluetoothAdapter> bluetooth_adapter_; - BleServiceDataHelper* ble_service_data_helper_; base::Clock* clock_; + BleScanner* ble_scanner_; - std::unique_ptr<BleSynchronizerBase> ble_synchronizer_; std::unique_ptr<BleAdvertiser> ble_advertiser_; - std::unique_ptr<BleScanner> ble_scanner_; std::unique_ptr<SecureChannelDisconnector> secure_channel_disconnector_; using SecureChannelWithRole =
diff --git a/chromeos/services/secure_channel/ble_connection_manager_impl_unittest.cc b/chromeos/services/secure_channel/ble_connection_manager_impl_unittest.cc index 8e6a726a..7fb883a 100644 --- a/chromeos/services/secure_channel/ble_connection_manager_impl_unittest.cc +++ b/chromeos/services/secure_channel/ble_connection_manager_impl_unittest.cc
@@ -22,8 +22,6 @@ #include "chromeos/services/secure_channel/ble_constants.h" #include "chromeos/services/secure_channel/ble_initiator_failure_type.h" #include "chromeos/services/secure_channel/ble_listener_failure_type.h" -#include "chromeos/services/secure_channel/ble_scanner_impl.h" -#include "chromeos/services/secure_channel/ble_synchronizer.h" #include "chromeos/services/secure_channel/ble_weave_client_connection.h" #include "chromeos/services/secure_channel/fake_authenticated_channel.h" #include "chromeos/services/secure_channel/fake_ble_advertiser.h" @@ -56,46 +54,15 @@ constexpr base::TimeDelta kConnectionToAuthenticationTime = base::TimeDelta::FromSeconds(1); -class FakeBleSynchronizerFactory : public BleSynchronizer::Factory { - public: - FakeBleSynchronizerFactory( - scoped_refptr<testing::NiceMock<device::MockBluetoothAdapter>> - expected_mock_adapter) - : expected_mock_adapter_(expected_mock_adapter) {} - - ~FakeBleSynchronizerFactory() override = default; - - FakeBleSynchronizer* instance() { return instance_; } - - private: - // BleSynchronizer::Factory: - std::unique_ptr<BleSynchronizerBase> CreateInstance( - scoped_refptr<device::BluetoothAdapter> bluetooth_adapter) override { - EXPECT_EQ(expected_mock_adapter_, bluetooth_adapter); - EXPECT_FALSE(instance_); - - auto instance = std::make_unique<FakeBleSynchronizer>(); - instance_ = instance.get(); - return instance; - } - - FakeBleSynchronizer* instance_ = nullptr; - - scoped_refptr<testing::NiceMock<device::MockBluetoothAdapter>> - expected_mock_adapter_; - - DISALLOW_COPY_AND_ASSIGN(FakeBleSynchronizerFactory); -}; - class FakeBleAdvertiserFactory : public BleAdvertiserImpl::Factory { public: FakeBleAdvertiserFactory( FakeBleServiceDataHelper* expected_fake_ble_service_data_helper, - FakeBleSynchronizerFactory* fake_ble_synchronizer_factory, + FakeBleSynchronizer* expected_fake_ble_synchronizer, FakeTimerFactory* expected_fake_timer_factory) : expected_fake_ble_service_data_helper_( expected_fake_ble_service_data_helper), - fake_ble_synchronizer_factory_(fake_ble_synchronizer_factory), + expected_fake_ble_synchronizer_(expected_fake_ble_synchronizer), expected_fake_timer_factory_(expected_fake_timer_factory) {} ~FakeBleAdvertiserFactory() override = default; @@ -111,8 +78,7 @@ TimerFactory* timer_factory, scoped_refptr<base::SequencedTaskRunner> sequenced_task_runner) override { EXPECT_EQ(expected_fake_ble_service_data_helper_, ble_service_data_helper); - EXPECT_EQ(fake_ble_synchronizer_factory_->instance(), - ble_synchronizer_base); + EXPECT_EQ(expected_fake_ble_synchronizer_, ble_synchronizer_base); EXPECT_EQ(expected_fake_timer_factory_, timer_factory); EXPECT_FALSE(instance_); @@ -124,55 +90,12 @@ FakeBleAdvertiser* instance_ = nullptr; FakeBleServiceDataHelper* expected_fake_ble_service_data_helper_; - FakeBleSynchronizerFactory* fake_ble_synchronizer_factory_; + FakeBleSynchronizer* expected_fake_ble_synchronizer_; FakeTimerFactory* expected_fake_timer_factory_; DISALLOW_COPY_AND_ASSIGN(FakeBleAdvertiserFactory); }; -class FakeBleScannerFactory : public BleScannerImpl::Factory { - public: - FakeBleScannerFactory( - scoped_refptr<testing::NiceMock<device::MockBluetoothAdapter>> - expected_mock_adapter, - FakeBleServiceDataHelper* expected_fake_ble_service_data_helper, - FakeBleSynchronizerFactory* fake_ble_synchronizer_factory) - : expected_mock_adapter_(expected_mock_adapter), - expected_fake_ble_service_data_helper_( - expected_fake_ble_service_data_helper), - fake_ble_synchronizer_factory_(fake_ble_synchronizer_factory) {} - - ~FakeBleScannerFactory() override = default; - - FakeBleScanner* instance() { return instance_; } - - private: - // BleScannerImpl::Factory: - std::unique_ptr<BleScanner> CreateInstance( - BleServiceDataHelper* service_data_helper, - BleSynchronizerBase* ble_synchronizer_base, - scoped_refptr<device::BluetoothAdapter> adapter) override { - EXPECT_EQ(expected_fake_ble_service_data_helper_, service_data_helper); - EXPECT_EQ(fake_ble_synchronizer_factory_->instance(), - ble_synchronizer_base); - EXPECT_EQ(expected_mock_adapter_, adapter); - EXPECT_FALSE(instance_); - - auto instance = std::make_unique<FakeBleScanner>(); - instance_ = instance.get(); - return instance; - } - - FakeBleScanner* instance_ = nullptr; - - scoped_refptr<testing::NiceMock<device::MockBluetoothAdapter>> - expected_mock_adapter_; - FakeBleServiceDataHelper* expected_fake_ble_service_data_helper_; - FakeBleSynchronizerFactory* fake_ble_synchronizer_factory_; - - DISALLOW_COPY_AND_ASSIGN(FakeBleScannerFactory); -}; - class FakeSecureChannelDisconnectorFactory : public SecureChannelDisconnectorImpl::Factory { public: @@ -338,29 +261,20 @@ fake_ble_service_data_helper_ = std::make_unique<FakeBleServiceDataHelper>(); + fake_ble_synchronizer_ = std::make_unique<FakeBleSynchronizer>(); + fake_ble_scanner_ = std::make_unique<FakeBleScanner>(); fake_timer_factory_ = std::make_unique<FakeTimerFactory>(); test_clock_ = std::make_unique<base::SimpleTestClock>(); test_clock_->SetNow(base::Time::UnixEpoch()); - fake_ble_synchronizer_factory_ = - std::make_unique<FakeBleSynchronizerFactory>(mock_adapter_); - BleSynchronizer::Factory::SetFactoryForTesting( - fake_ble_synchronizer_factory_.get()); - fake_ble_advertiser_factory_ = std::make_unique<FakeBleAdvertiserFactory>( - fake_ble_service_data_helper_.get(), - fake_ble_synchronizer_factory_.get(), fake_timer_factory_.get()); + fake_ble_service_data_helper_.get(), fake_ble_synchronizer_.get(), + fake_timer_factory_.get()); BleAdvertiserImpl::Factory::SetFactoryForTesting( fake_ble_advertiser_factory_.get()); - fake_ble_scanner_factory_ = std::make_unique<FakeBleScannerFactory>( - mock_adapter_, fake_ble_service_data_helper_.get(), - fake_ble_synchronizer_factory_.get()); - BleScannerImpl::Factory::SetFactoryForTesting( - fake_ble_scanner_factory_.get()); - fake_secure_channel_disconnector_factory_ = std::make_unique<FakeSecureChannelDisconnectorFactory>(); SecureChannelDisconnectorImpl::Factory::SetFactoryForTesting( @@ -383,13 +297,12 @@ manager_ = BleConnectionManagerImpl::Factory::Create( mock_adapter_, fake_ble_service_data_helper_.get(), + fake_ble_synchronizer_.get(), fake_ble_scanner_.get(), fake_timer_factory_.get(), test_clock_.get()); } void TearDown() override { - BleSynchronizer::Factory::SetFactoryForTesting(nullptr); BleAdvertiserImpl::Factory::SetFactoryForTesting(nullptr); - BleScannerImpl::Factory::SetFactoryForTesting(nullptr); SecureChannelDisconnectorImpl::Factory::SetFactoryForTesting(nullptr); weave::BluetoothLowEnergyWeaveClientConnection::Factory:: SetFactoryForTesting(nullptr); @@ -420,13 +333,13 @@ if (expected_to_add_request) { EXPECT_EQ(connection_priority, *fake_ble_advertiser()->GetPriorityForRequest(device_id_pair)); - EXPECT_TRUE(fake_ble_scanner()->HasScanRequest(ConnectionAttemptDetails( + EXPECT_TRUE(fake_ble_scanner_->HasScanRequest(ConnectionAttemptDetails( device_id_pair, ConnectionMedium::kBluetoothLowEnergy, ConnectionRole::kInitiatorRole))); } else { EXPECT_FALSE( fake_ble_advertiser()->GetPriorityForRequest(device_id_pair)); - EXPECT_FALSE(fake_ble_scanner()->HasScanRequest(ConnectionAttemptDetails( + EXPECT_FALSE(fake_ble_scanner_->HasScanRequest(ConnectionAttemptDetails( device_id_pair, ConnectionMedium::kBluetoothLowEnergy, ConnectionRole::kInitiatorRole))); } @@ -445,13 +358,13 @@ if (expected_to_update_priority) { EXPECT_EQ(connection_priority, *fake_ble_advertiser()->GetPriorityForRequest(device_id_pair)); - EXPECT_TRUE(fake_ble_scanner()->HasScanRequest(ConnectionAttemptDetails( + EXPECT_TRUE(fake_ble_scanner_->HasScanRequest(ConnectionAttemptDetails( device_id_pair, ConnectionMedium::kBluetoothLowEnergy, ConnectionRole::kInitiatorRole))); } else { EXPECT_FALSE( fake_ble_advertiser()->GetPriorityForRequest(device_id_pair)); - EXPECT_FALSE(fake_ble_scanner()->HasScanRequest(ConnectionAttemptDetails( + EXPECT_FALSE(fake_ble_scanner_->HasScanRequest(ConnectionAttemptDetails( device_id_pair, ConnectionMedium::kBluetoothLowEnergy, ConnectionRole::kInitiatorRole))); } @@ -462,7 +375,7 @@ ConnectionRole::kInitiatorRole); manager_->CancelBleInitiatorConnectionAttempt(device_id_pair); EXPECT_FALSE(fake_ble_advertiser()->GetPriorityForRequest(device_id_pair)); - EXPECT_FALSE(fake_ble_scanner()->HasScanRequest(ConnectionAttemptDetails( + EXPECT_FALSE(fake_ble_scanner_->HasScanRequest(ConnectionAttemptDetails( device_id_pair, ConnectionMedium::kBluetoothLowEnergy, ConnectionRole::kInitiatorRole))); } @@ -486,11 +399,11 @@ should_cancel_attempt_on_failure)); if (expected_to_add_request) { - EXPECT_TRUE(fake_ble_scanner()->HasScanRequest(ConnectionAttemptDetails( + EXPECT_TRUE(fake_ble_scanner_->HasScanRequest(ConnectionAttemptDetails( device_id_pair, ConnectionMedium::kBluetoothLowEnergy, ConnectionRole::kListenerRole))); } else { - EXPECT_FALSE(fake_ble_scanner()->HasScanRequest(ConnectionAttemptDetails( + EXPECT_FALSE(fake_ble_scanner_->HasScanRequest(ConnectionAttemptDetails( device_id_pair, ConnectionMedium::kBluetoothLowEnergy, ConnectionRole::kListenerRole))); } @@ -507,11 +420,11 @@ connection_priority); if (expected_to_update_priority) { - EXPECT_TRUE(fake_ble_scanner()->HasScanRequest(ConnectionAttemptDetails( + EXPECT_TRUE(fake_ble_scanner_->HasScanRequest(ConnectionAttemptDetails( device_id_pair, ConnectionMedium::kBluetoothLowEnergy, ConnectionRole::kListenerRole))); } else { - EXPECT_FALSE(fake_ble_scanner()->HasScanRequest(ConnectionAttemptDetails( + EXPECT_FALSE(fake_ble_scanner_->HasScanRequest(ConnectionAttemptDetails( device_id_pair, ConnectionMedium::kBluetoothLowEnergy, ConnectionRole::kListenerRole))); } @@ -521,7 +434,7 @@ RemoveFromRemoteDeviceIdToMetadataMap(device_id_pair, ConnectionRole::kListenerRole); manager_->CancelBleListenerConnectionAttempt(device_id_pair); - EXPECT_FALSE(fake_ble_scanner()->HasScanRequest(ConnectionAttemptDetails( + EXPECT_FALSE(fake_ble_scanner_->HasScanRequest(ConnectionAttemptDetails( device_id_pair, ConnectionMedium::kBluetoothLowEnergy, ConnectionRole::kListenerRole))); } @@ -562,7 +475,7 @@ fake_weave_client_connection_factory_->set_expected_bluetooth_device( mock_bluetooth_device.get()); - fake_ble_scanner()->NotifyReceivedAdvertisementFromDevice( + fake_ble_scanner_->NotifyReceivedAdvertisementFromDevice( remote_device, mock_bluetooth_device.get(), ConnectionMedium::kBluetoothLowEnergy, connection_role); @@ -572,7 +485,7 @@ ->GetAllRequestsForRemoteDevice(remote_device.GetDeviceId()) .empty()); EXPECT_TRUE( - fake_ble_scanner() + fake_ble_scanner_ ->GetAllScanRequestsForRemoteDevice(remote_device.GetDeviceId()) .empty()); @@ -649,7 +562,7 @@ *fake_ble_advertiser()->GetPriorityForRequest( std::get<0>(tuple))); EXPECT_TRUE( - fake_ble_scanner()->HasScanRequest(ConnectionAttemptDetails( + fake_ble_scanner_->HasScanRequest(ConnectionAttemptDetails( std::get<0>(tuple), ConnectionMedium::kBluetoothLowEnergy, ConnectionRole::kInitiatorRole))); break; @@ -657,7 +570,7 @@ case ConnectionRole::kListenerRole: { EXPECT_TRUE( - fake_ble_scanner()->HasScanRequest(ConnectionAttemptDetails( + fake_ble_scanner_->HasScanRequest(ConnectionAttemptDetails( std::get<0>(tuple), ConnectionMedium::kBluetoothLowEnergy, ConnectionRole::kListenerRole))); break; @@ -696,7 +609,7 @@ *fake_ble_advertiser()->GetPriorityForRequest( std::get<0>(tuple))); EXPECT_TRUE( - fake_ble_scanner()->HasScanRequest(ConnectionAttemptDetails( + fake_ble_scanner_->HasScanRequest(ConnectionAttemptDetails( std::get<0>(tuple), ConnectionMedium::kBluetoothLowEnergy, ConnectionRole::kInitiatorRole))); break; @@ -704,7 +617,7 @@ case ConnectionRole::kListenerRole: { EXPECT_TRUE( - fake_ble_scanner()->HasScanRequest(ConnectionAttemptDetails( + fake_ble_scanner_->HasScanRequest(ConnectionAttemptDetails( std::get<0>(tuple), ConnectionMedium::kBluetoothLowEnergy, ConnectionRole::kListenerRole))); break; @@ -851,10 +764,6 @@ return fake_ble_advertiser_factory_->instance(); } - FakeBleScanner* fake_ble_scanner() { - return fake_ble_scanner_factory_->instance(); - } - FakeSecureChannelDisconnector* fake_secure_channel_disconnector() { return fake_secure_channel_disconnector_factory_->instance(); } @@ -876,9 +785,7 @@ std::vector<std::pair<DeviceIdPair, BleListenerFailureType>> ble_listener_failures_; - std::unique_ptr<FakeBleSynchronizerFactory> fake_ble_synchronizer_factory_; std::unique_ptr<FakeBleAdvertiserFactory> fake_ble_advertiser_factory_; - std::unique_ptr<FakeBleScannerFactory> fake_ble_scanner_factory_; std::unique_ptr<FakeSecureChannelDisconnectorFactory> fake_secure_channel_disconnector_factory_; std::unique_ptr<FakeWeaveClientConnectionFactory> @@ -889,6 +796,8 @@ scoped_refptr<testing::NiceMock<device::MockBluetoothAdapter>> mock_adapter_; std::unique_ptr<FakeBleServiceDataHelper> fake_ble_service_data_helper_; + std::unique_ptr<FakeBleSynchronizer> fake_ble_synchronizer_; + std::unique_ptr<FakeBleScanner> fake_ble_scanner_; std::unique_ptr<FakeTimerFactory> fake_timer_factory_; std::unique_ptr<base::SimpleTestClock> test_clock_;
diff --git a/chromeos/services/secure_channel/secure_channel_impl.cc b/chromeos/services/secure_channel/secure_channel_impl.cc index 126c35f1..e190178 100644 --- a/chromeos/services/secure_channel/secure_channel_impl.cc +++ b/chromeos/services/secure_channel/secure_channel_impl.cc
@@ -13,7 +13,9 @@ #include "chromeos/services/secure_channel/active_connection_manager_impl.h" #include "chromeos/services/secure_channel/authenticated_channel.h" #include "chromeos/services/secure_channel/ble_connection_manager_impl.h" +#include "chromeos/services/secure_channel/ble_scanner_impl.h" #include "chromeos/services/secure_channel/ble_service_data_helper_impl.h" +#include "chromeos/services/secure_channel/ble_synchronizer.h" #include "chromeos/services/secure_channel/client_connection_parameters_impl.h" #include "chromeos/services/secure_channel/device_id_pair.h" #include "chromeos/services/secure_channel/pending_connection_manager_impl.h" @@ -68,9 +70,16 @@ remote_device_cache_(multidevice::RemoteDeviceCache::Factory::Create()), ble_service_data_helper_(BleServiceDataHelperImpl::Factory::Create( remote_device_cache_.get())), + ble_synchronizer_(BleSynchronizer::Factory::Create(bluetooth_adapter_)), + ble_scanner_( + BleScannerImpl::Factory::Create(ble_service_data_helper_.get(), + ble_synchronizer_.get(), + bluetooth_adapter_)), ble_connection_manager_(BleConnectionManagerImpl::Factory::Create( bluetooth_adapter_, ble_service_data_helper_.get(), + ble_synchronizer_.get(), + ble_scanner_.get(), timer_factory_.get())), pending_connection_manager_(PendingConnectionManagerImpl::Factory::Create( this /* delegate */,
diff --git a/chromeos/services/secure_channel/secure_channel_impl.h b/chromeos/services/secure_channel/secure_channel_impl.h index 0214dfde..4b3d2aa 100644 --- a/chromeos/services/secure_channel/secure_channel_impl.h +++ b/chromeos/services/secure_channel/secure_channel_impl.h
@@ -29,7 +29,9 @@ namespace secure_channel { class BleConnectionManager; +class BleScanner; class BleServiceDataHelper; +class BleSynchronizerBase; class TimerFactory; // Concrete SecureChannelImpl implementation, which contains three pieces: @@ -173,6 +175,8 @@ std::unique_ptr<TimerFactory> timer_factory_; std::unique_ptr<multidevice::RemoteDeviceCache> remote_device_cache_; std::unique_ptr<BleServiceDataHelper> ble_service_data_helper_; + std::unique_ptr<BleSynchronizerBase> ble_synchronizer_; + std::unique_ptr<BleScanner> ble_scanner_; std::unique_ptr<BleConnectionManager> ble_connection_manager_; std::unique_ptr<PendingConnectionManager> pending_connection_manager_; std::unique_ptr<ActiveConnectionManager> active_connection_manager_;
diff --git a/chromeos/services/secure_channel/secure_channel_service_unittest.cc b/chromeos/services/secure_channel/secure_channel_service_unittest.cc index 9e9f834..68274fd 100644 --- a/chromeos/services/secure_channel/secure_channel_service_unittest.cc +++ b/chromeos/services/secure_channel/secure_channel_service_unittest.cc
@@ -16,12 +16,16 @@ #include "chromeos/components/multidevice/remote_device_test_util.h" #include "chromeos/services/secure_channel/active_connection_manager_impl.h" #include "chromeos/services/secure_channel/ble_connection_manager_impl.h" +#include "chromeos/services/secure_channel/ble_scanner_impl.h" #include "chromeos/services/secure_channel/ble_service_data_helper_impl.h" +#include "chromeos/services/secure_channel/ble_synchronizer.h" #include "chromeos/services/secure_channel/client_connection_parameters_impl.h" #include "chromeos/services/secure_channel/fake_active_connection_manager.h" #include "chromeos/services/secure_channel/fake_authenticated_channel.h" #include "chromeos/services/secure_channel/fake_ble_connection_manager.h" +#include "chromeos/services/secure_channel/fake_ble_scanner.h" #include "chromeos/services/secure_channel/fake_ble_service_data_helper.h" +#include "chromeos/services/secure_channel/fake_ble_synchronizer.h" #include "chromeos/services/secure_channel/fake_client_connection_parameters.h" #include "chromeos/services/secure_channel/fake_connection_delegate.h" #include "chromeos/services/secure_channel/fake_pending_connection_manager.h" @@ -123,16 +127,81 @@ DISALLOW_COPY_AND_ASSIGN(FakeBleServiceDataHelperFactory); }; +class FakeBleSynchronizerFactory : public BleSynchronizer::Factory { + public: + FakeBleSynchronizerFactory() = default; + ~FakeBleSynchronizerFactory() override = default; + + FakeBleSynchronizer* instance() { return instance_; } + + private: + // BleSynchronizer::Factory: + std::unique_ptr<BleSynchronizerBase> CreateInstance( + scoped_refptr<device::BluetoothAdapter> bluetooth_adapter) override { + EXPECT_FALSE(instance_); + + auto instance = std::make_unique<FakeBleSynchronizer>(); + instance_ = instance.get(); + return instance; + } + + FakeBleSynchronizer* instance_ = nullptr; + + DISALLOW_COPY_AND_ASSIGN(FakeBleSynchronizerFactory); +}; + +class FakeBleScannerFactory : public BleScannerImpl::Factory { + public: + FakeBleScannerFactory( + FakeBleServiceDataHelperFactory* fake_ble_service_data_helper_factory, + FakeBleSynchronizerFactory* fake_ble_synchronizer_factory) + : fake_ble_service_data_helper_factory_( + fake_ble_service_data_helper_factory), + fake_ble_synchronizer_factory_(fake_ble_synchronizer_factory) {} + + ~FakeBleScannerFactory() override = default; + + FakeBleScanner* instance() { return instance_; } + + private: + // BleScannerImpl::Factory: + std::unique_ptr<BleScanner> CreateInstance( + BleServiceDataHelper* service_data_helper, + BleSynchronizerBase* ble_synchronizer_base, + scoped_refptr<device::BluetoothAdapter> adapter) override { + EXPECT_EQ(fake_ble_service_data_helper_factory_->instance(), + service_data_helper); + EXPECT_EQ(fake_ble_synchronizer_factory_->instance(), + ble_synchronizer_base); + EXPECT_FALSE(instance_); + + auto instance = std::make_unique<FakeBleScanner>(); + instance_ = instance.get(); + return instance; + } + + FakeBleScanner* instance_ = nullptr; + + FakeBleServiceDataHelperFactory* fake_ble_service_data_helper_factory_; + FakeBleSynchronizerFactory* fake_ble_synchronizer_factory_; + + DISALLOW_COPY_AND_ASSIGN(FakeBleScannerFactory); +}; + class FakeBleConnectionManagerFactory : public BleConnectionManagerImpl::Factory { public: FakeBleConnectionManagerFactory( device::BluetoothAdapter* expected_bluetooth_adapter, FakeBleServiceDataHelperFactory* fake_ble_service_data_helper_factory, + FakeBleSynchronizerFactory* fake_ble_synchronizer_factory, + FakeBleScannerFactory* fake_ble_scanner_factory, FakeTimerFactoryFactory* fake_timer_factory_factory) : expected_bluetooth_adapter_(expected_bluetooth_adapter), fake_ble_service_data_helper_factory_( fake_ble_service_data_helper_factory), + fake_ble_synchronizer_factory_(fake_ble_synchronizer_factory), + fake_ble_scanner_factory_(fake_ble_scanner_factory), fake_timer_factory_factory_(fake_timer_factory_factory) {} ~FakeBleConnectionManagerFactory() override = default; @@ -144,12 +213,16 @@ std::unique_ptr<BleConnectionManager> CreateInstance( scoped_refptr<device::BluetoothAdapter> bluetooth_adapter, BleServiceDataHelper* ble_service_data_helper, + BleSynchronizerBase* ble_synchronizer, + BleScanner* ble_scanner, TimerFactory* timer_factory, base::Clock* clock) override { EXPECT_FALSE(instance_); EXPECT_EQ(expected_bluetooth_adapter_, bluetooth_adapter.get()); EXPECT_EQ(fake_ble_service_data_helper_factory_->instance(), ble_service_data_helper); + EXPECT_EQ(fake_ble_synchronizer_factory_->instance(), ble_synchronizer); + EXPECT_EQ(fake_ble_scanner_factory_->instance(), ble_scanner); EXPECT_EQ(fake_timer_factory_factory_->instance(), timer_factory); auto instance = std::make_unique<FakeBleConnectionManager>(); @@ -159,6 +232,8 @@ device::BluetoothAdapter* expected_bluetooth_adapter_; FakeBleServiceDataHelperFactory* fake_ble_service_data_helper_factory_; + FakeBleSynchronizerFactory* fake_ble_synchronizer_factory_; + FakeBleScannerFactory* fake_ble_scanner_factory_; FakeTimerFactoryFactory* fake_timer_factory_factory_; FakeBleConnectionManager* instance_ = nullptr; @@ -358,10 +433,22 @@ BleServiceDataHelperImpl::Factory::SetFactoryForTesting( fake_ble_service_data_helper_factory_.get()); + fake_ble_synchronizer_factory_ = + std::make_unique<FakeBleSynchronizerFactory>(); + BleSynchronizer::Factory::SetFactoryForTesting( + fake_ble_synchronizer_factory_.get()); + + fake_ble_scanner_factory_ = std::make_unique<FakeBleScannerFactory>( + fake_ble_service_data_helper_factory_.get(), + fake_ble_synchronizer_factory_.get()); + BleScannerImpl::Factory::SetFactoryForTesting( + fake_ble_scanner_factory_.get()); + fake_ble_connection_manager_factory_ = std::make_unique<FakeBleConnectionManagerFactory>( mock_adapter_.get(), fake_ble_service_data_helper_factory_.get(), - fake_timer_factory_factory_.get()); + fake_ble_synchronizer_factory_.get(), + fake_ble_scanner_factory_.get(), fake_timer_factory_factory_.get()); BleConnectionManagerImpl::Factory::SetFactoryForTesting( fake_ble_connection_manager_factory_.get()); @@ -396,6 +483,8 @@ TimerFactoryImpl::Factory::SetFactoryForTesting(nullptr); multidevice::RemoteDeviceCache::Factory::SetFactoryForTesting(nullptr); BleServiceDataHelperImpl::Factory::SetFactoryForTesting(nullptr); + BleSynchronizer::Factory::SetFactoryForTesting(nullptr); + BleScannerImpl::Factory::SetFactoryForTesting(nullptr); BleConnectionManagerImpl::Factory::SetFactoryForTesting(nullptr); PendingConnectionManagerImpl::Factory::SetFactoryForTesting(nullptr); ActiveConnectionManagerImpl::Factory::SetFactoryForTesting(nullptr); @@ -870,6 +959,8 @@ test_remote_device_cache_factory_; std::unique_ptr<FakeBleServiceDataHelperFactory> fake_ble_service_data_helper_factory_; + std::unique_ptr<FakeBleSynchronizerFactory> fake_ble_synchronizer_factory_; + std::unique_ptr<FakeBleScannerFactory> fake_ble_scanner_factory_; std::unique_ptr<FakeBleConnectionManagerFactory> fake_ble_connection_manager_factory_; std::unique_ptr<FakePendingConnectionManagerFactory>
diff --git a/components/autofill/content/common/mojom/autofill_driver.mojom b/components/autofill/content/common/mojom/autofill_driver.mojom index 48c32fa8..6807ea2 100644 --- a/components/autofill/content/common/mojom/autofill_driver.mojom +++ b/components/autofill/content/common/mojom/autofill_driver.mojom
@@ -96,13 +96,10 @@ // Notification that this password form was submitted by the user. PasswordFormSubmitted(FormData form_data); - // Notification that a user starts typing in password fields and the omnibox - // icon with anchored save/update prompt should be available. - ShowManualFallbackForSaving(FormData form_data); - - // Notification that there is no user input in password fields and the - // save/update prompt anchored to the omnibox icon should be removed. - HideManualFallbackForSaving(); + // Notification that a user has modified a password field. This is fired both + // when typing new characters and deleting characters, so the password field + // in `form_data` may or may not be empty + InformAboutUserInput(FormData form_data); // Notification that same-document navigation happened. We use this as a // signal for successful login.
diff --git a/components/autofill/content/renderer/form_tracker.h b/components/autofill/content/renderer/form_tracker.h index 899f98d..7498871 100644 --- a/components/autofill/content/renderer/form_tracker.h +++ b/components/autofill/content/renderer/form_tracker.h
@@ -33,6 +33,7 @@ SELECT_CHANGED, }; + // TODO(crbug.com/1126017): Find a better name for this method. // Invoked when form needs to be saved because of |source|, |element| is // valid if the callback caused by source other than // WILL_SEND_SUBMIT_EVENT, |form| is valid for the callback caused by
diff --git a/components/autofill/content/renderer/password_autofill_agent.cc b/components/autofill/content/renderer/password_autofill_agent.cc index a5e0a581..7e4b315 100644 --- a/components/autofill/content/renderer/password_autofill_agent.cc +++ b/components/autofill/content/renderer/password_autofill_agent.cc
@@ -356,17 +356,6 @@ return false; } -// Whether any of the fields in |form| is a non-empty password field. -bool FormHasNonEmptyPasswordField(const FormData& form) { - for (const auto& field : form.fields) { - if (field.IsPasswordInputElement()) { - if (!field.value.empty() || !field.typed_value.empty()) - return true; - } - } - return false; -} - void AnnotateFieldWithParsingResult(WebDocument doc, FieldRendererId renderer_id, const std::string& text) { @@ -564,7 +553,7 @@ field_data_manager_->UpdateFieldDataMap(element_id, element_value, FieldPropertiesFlags::kUserTyped); - ProvisionallySavePassword(element.Form(), element, RESTRICTION_NONE); + InformBrowserAboutUserInput(element.Form(), element); if (element.IsPasswordFieldForAutofill()) { auto iter = password_to_username_.find(element); @@ -659,8 +648,7 @@ DCHECK(password_input); DCHECK(password_input->IsPasswordFieldForAutofill()); FillField(password_input, credential); - ProvisionallySavePassword(password_input->Form(), *password_input, - RESTRICTION_NONE); + InformBrowserAboutUserInput(password_input->Form(), *password_input); } bool PasswordAutofillAgent::PreviewSuggestion( @@ -1454,29 +1442,23 @@ password->SetAutofillState(password_autofill_state_); } } -void PasswordAutofillAgent::ProvisionallySavePassword( +void PasswordAutofillAgent::InformBrowserAboutUserInput( const WebFormElement& form, - const WebInputElement& element, - ProvisionallySaveRestriction restriction) { + const WebInputElement& element) { DCHECK(!form.IsNull() || !element.IsNull()); + if (!FrameCanAccessPasswordManager()) + return; SetLastUpdatedFormAndField(form, element); std::unique_ptr<FormData> form_data = - (form.IsNull() ? GetFormDataFromUnownedInputElements() - : GetFormDataFromWebForm(form)); + form.IsNull() ? GetFormDataFromUnownedInputElements() + : GetFormDataFromWebForm(form); if (!form_data) return; - bool has_password = FormHasNonEmptyPasswordField(*form_data); - if (restriction == RESTRICTION_NON_EMPTY_PASSWORD && !has_password) + if (!FormHasPasswordField(*form_data)) return; - if (!FrameCanAccessPasswordManager()) - return; - - if (has_password) - GetPasswordManagerDriver()->ShowManualFallbackForSaving(*form_data); - else - GetPasswordManagerDriver()->HideManualFallbackForSaving(); + GetPasswordManagerDriver()->InformAboutUserInput(*form_data); browser_has_form_to_process_ = true; } @@ -1639,8 +1621,7 @@ } DCHECK_EQ(ElementChangeSource::WILL_SEND_SUBMIT_EVENT, source); - ProvisionallySavePassword(form, input_element, - RESTRICTION_NON_EMPTY_PASSWORD); + InformBrowserAboutUserInput(form, input_element); } void PasswordAutofillAgent::OnFormSubmitted(const WebFormElement& form) {
diff --git a/components/autofill/content/renderer/password_autofill_agent.h b/components/autofill/content/renderer/password_autofill_agent.h index 31268fa..3738a1f 100644 --- a/components/autofill/content/renderer/password_autofill_agent.h +++ b/components/autofill/content/renderer/password_autofill_agent.h
@@ -243,12 +243,6 @@ private: using OnPasswordField = util::StrongAlias<class OnPasswordFieldTag, bool>; - // Ways to restrict which passwords are saved in ProvisionallySavePassword. - enum ProvisionallySaveRestriction { - RESTRICTION_NONE, - RESTRICTION_NON_EMPTY_PASSWORD - }; - // Enumeration representing possible Touch To Fill states. This is used to // make sure that Touch To Fill will only be shown in response to the first // password form focus during a frame's life time and to suppress the soft @@ -397,14 +391,12 @@ void FillPasswordFieldAndSave(blink::WebInputElement* password_input, const base::string16& credential); - // Saves |form| and |input| in |provisionally_saved_form_|, as long as it - // satisfies |restriction|. |form| and |input| are the elements user has just - // been interacting with before the form save. |form| or |input| can be null - // but not both at the same time. For example: if the form is unowned, |form| - // will be null; if the user has submitted the form, |input| will be null. - void ProvisionallySavePassword(const blink::WebFormElement& form, - const blink::WebInputElement& input, - ProvisionallySaveRestriction restriction); + // |form| and |input| are the elements user has just been interacting with + // before the form save. |form| or |input| can be null but not both at the + // same time. For example: if the form is unowned, |form| will be null; if the + // user has submitted the form, |input| will be null. + void InformBrowserAboutUserInput(const blink::WebFormElement& form, + const blink::WebInputElement& input); // This function attempts to fill |username_element| and |password_element| // with values from |fill_data|. The |username_element| and |password_element|
diff --git a/components/autofill/content/renderer/renderer_save_password_progress_logger_unittest.cc b/components/autofill/content/renderer/renderer_save_password_progress_logger_unittest.cc index 9b45786f..6c76bdbd 100644 --- a/components/autofill/content/renderer/renderer_save_password_progress_logger_unittest.cc +++ b/components/autofill/content/renderer/renderer_save_password_progress_logger_unittest.cc
@@ -50,10 +50,7 @@ void PasswordFormSubmitted(const autofill::FormData& form_data) override {} - void ShowManualFallbackForSaving( - const autofill::FormData& form_data) override {} - - void HideManualFallbackForSaving() override {} + void InformAboutUserInput(const autofill::FormData& form_data) override {} void SameDocumentNavigation(autofill::mojom::SubmissionIndicatorEvent submission_indication_event) override {}
diff --git a/components/autofill/core/browser/autofill_metrics.cc b/components/autofill/core/browser/autofill_metrics.cc index f102f93e..67bedb21 100644 --- a/components/autofill/core/browser/autofill_metrics.cc +++ b/components/autofill/core/browser/autofill_metrics.cc
@@ -49,6 +49,11 @@ GROUP_ADDRESS_STATE, GROUP_ADDRESS_ZIP, GROUP_ADDRESS_COUNTRY, + GROUP_ADDRESS_HOME_STREET_NAME, + GROUP_ADDRESS_HOME_DEPENDENT_STREET_NAME, + GROUP_ADDRESS_HOME_HOUSE_NUMBER, + GROUP_ADDRESS_HOME_PREMISE_NAME, + GROUP_ADDRESS_HOME_SUBPREMISE, GROUP_PHONE, GROUP_FAX, // Deprecated. GROUP_EMAIL, @@ -158,6 +163,21 @@ case ADDRESS_HOME_COUNTRY: group = GROUP_ADDRESS_COUNTRY; break; + case ADDRESS_HOME_STREET_NAME: + group = GROUP_ADDRESS_HOME_STREET_NAME; + break; + case ADDRESS_HOME_DEPENDENT_STREET_NAME: + group = GROUP_ADDRESS_HOME_DEPENDENT_STREET_NAME; + break; + case ADDRESS_HOME_HOUSE_NUMBER: + group = GROUP_ADDRESS_HOME_HOUSE_NUMBER; + break; + case ADDRESS_HOME_PREMISE_NAME: + group = GROUP_ADDRESS_HOME_PREMISE_NAME; + break; + case ADDRESS_HOME_SUBPREMISE: + group = GROUP_ADDRESS_HOME_SUBPREMISE; + break; default: NOTREACHED() << field_type << " has no group assigned (ambiguous)"; group = GROUP_AMBIGUOUS;
diff --git a/components/autofill/core/browser/form_structure.cc b/components/autofill/core/browser/form_structure.cc index 3b7b0ea1c..b108c47 100644 --- a/components/autofill/core/browser/form_structure.cc +++ b/components/autofill/core/browser/form_structure.cc
@@ -1115,6 +1115,30 @@ cached_field = it->second; } + // If the unique renderer id (or the name) is not stable due to some Java + // Script magic in the website, use the field signature as a fallback + // solution to find the field in the cached form. + // TODO(crbug.com/1125624): Remove feature check once trial ended. + if (!cached_field && + base::FeatureList::IsEnabled( + features::kAutofillRetrieveFromCacheWithFieldSignatureAsFallback)) { + // Iterates over the fields to find the field with the same form + // signature. + for (size_t i = 0; i < cached_form.field_count(); ++i) { + auto* const cfield = cached_form.field(i); + if (field->GetFieldSignature() == cfield->GetFieldSignature()) { + // If there are multiple matches, do not retrieve the field and stop + // the process. + if (cached_field) { + cached_field = nullptr; + break; + } else { + cached_field = cfield; + } + } + } + } + if (cached_field) { if (!only_server_and_autofill_state) { // Transfer attributes of the cached AutofillField to the newly created
diff --git a/components/autofill/core/browser/payments/legal_message_line.h b/components/autofill/core/browser/payments/legal_message_line.h index 4d9f2659..e99a588b 100644 --- a/components/autofill/core/browser/payments/legal_message_line.h +++ b/components/autofill/core/browser/payments/legal_message_line.h
@@ -33,6 +33,7 @@ gfx::Range range; GURL url; }; + using Links = std::vector<Link>; LegalMessageLine(); LegalMessageLine(const LegalMessageLine& other); @@ -75,7 +76,7 @@ bool escape_apostrophes = false); const base::string16& text() const { return text_; } - const std::vector<Link>& links() const { return links_; } + const Links& links() const { return links_; } private: friend class TestLegalMessageLine; @@ -83,7 +84,7 @@ bool ParseLine(const base::Value& line, bool escape_apostrophes); base::string16 text_; - std::vector<Link> links_; + Links links_; }; } // namespace autofill
diff --git a/components/autofill/core/browser/payments/test_legal_message_line.h b/components/autofill/core/browser/payments/test_legal_message_line.h index 1fdfcd66..111e904 100644 --- a/components/autofill/core/browser/payments/test_legal_message_line.h +++ b/components/autofill/core/browser/payments/test_legal_message_line.h
@@ -21,8 +21,7 @@ TestLegalMessageLine(const std::string& ascii_text) { set_text(ascii_text); } - TestLegalMessageLine(const std::string& ascii_text, - const std::vector<Link>& links) { + TestLegalMessageLine(const std::string& ascii_text, const Links& links) { set_text(ascii_text); set_links(links); } @@ -33,7 +32,7 @@ text_ = base::ASCIIToUTF16(ascii_text); } - void set_links(const std::vector<Link>& links) { links_ = links; } + void set_links(const Links& links) { links_ = links; } private: DISALLOW_COPY_AND_ASSIGN(TestLegalMessageLine);
diff --git a/components/autofill/core/common/autofill_features.cc b/components/autofill/core/common/autofill_features.cc index fae996c..55747282 100644 --- a/components/autofill/core/common/autofill_features.cc +++ b/components/autofill/core/common/autofill_features.cc
@@ -159,6 +159,13 @@ "AutofillRetrieveFromCacheWithRendererIds", base::FEATURE_DISABLED_BY_DEFAULT}; +// When enabled, Autofill will try to retrieve cached fields by signatures as a +// fallback that is useful if unique renderer ids are unstable. +// TODO(crbug.com/1125624): Remove experiment once trial ended. +const base::Feature kAutofillRetrieveFromCacheWithFieldSignatureAsFallback{ + "AutofillRetrieveFromCacheWithFieldSignatureAsFallback", + base::FEATURE_DISABLED_BY_DEFAULT}; + // When enabled, autofill suggestions are displayed in the keyboard accessory // instead of the regular popup. const base::Feature kAutofillKeyboardAccessory{
diff --git a/components/autofill/core/common/autofill_features.h b/components/autofill/core/common/autofill_features.h index 37457fb..adcfb2e 100644 --- a/components/autofill/core/common/autofill_features.h +++ b/components/autofill/core/common/autofill_features.h
@@ -45,6 +45,8 @@ extern const base::Feature kAutofillImportPrefilledCountryAndStateValues; extern const base::Feature kAutofillKeepInitialFormValuesInCache; extern const base::Feature kAutofillRetrieveFromCacheWithRendererIds; +extern const base::Feature + kAutofillRetrieveFromCacheWithFieldSignatureAsFallback; extern const base::Feature kAutofillKeyboardAccessory; extern const base::Feature kAutofillLabelAffixRemoval; extern const base::Feature kAutofillPruneSuggestions;
diff --git a/components/autofill/core/common/form_data.cc b/components/autofill/core/common/form_data.cc index e2199e3..0861134 100644 --- a/components/autofill/core/common/form_data.cc +++ b/components/autofill/core/common/form_data.cc
@@ -142,6 +142,16 @@ FormFieldData::IdentityComparator()); } +bool FormHasNonEmptyPasswordField(const FormData& form) { + for (const auto& field : form.fields) { + if (field.IsPasswordInputElement()) { + if (!field.value.empty() || !field.typed_value.empty()) + return true; + } + } + return false; +} + std::ostream& operator<<(std::ostream& os, const FormData& form) { os << base::UTF16ToUTF8(form.name) << " " << form.url << " " << form.action << " " << form.main_frame_origin << " " << form.is_form_tag << " "
diff --git a/components/autofill/core/common/form_data.h b/components/autofill/core/common/form_data.h index 9b59194..b57d18df 100644 --- a/components/autofill/core/common/form_data.h +++ b/components/autofill/core/common/form_data.h
@@ -120,6 +120,9 @@ #endif }; +// Whether any of the fields in |form| is a non-empty password field. +bool FormHasNonEmptyPasswordField(const FormData& form); + // For testing. std::ostream& operator<<(std::ostream& os, const FormData& form);
diff --git a/components/page_info/android/BUILD.gn b/components/page_info/android/BUILD.gn index 45a865ffe..e8a135a 100644 --- a/components/page_info/android/BUILD.gn +++ b/components/page_info/android/BUILD.gn
@@ -51,9 +51,9 @@ "java/res/layout/connection_info.xml", "java/res/layout/cookie_controls_view.xml", "java/res/layout/page_info.xml", + "java/res/layout/page_info_container.xml", "java/res/layout/page_info_permission_row.xml", "java/res/layout/page_info_row.xml", - "java/res/layout/page_info_subpage.xml", "java/res/layout/page_info_v2.xml", "java/res/values/colors.xml", "java/res/values/dimens.xml", @@ -77,16 +77,16 @@ "java/src/org/chromium/components/page_info/ConnectionInfoView.java", "java/src/org/chromium/components/page_info/CookieControlsView.java", "java/src/org/chromium/components/page_info/PageInfoConnectionController.java", + "java/src/org/chromium/components/page_info/PageInfoContainer.java", "java/src/org/chromium/components/page_info/PageInfoController.java", "java/src/org/chromium/components/page_info/PageInfoControllerDelegate.java", "java/src/org/chromium/components/page_info/PageInfoCookiesController.java", "java/src/org/chromium/components/page_info/PageInfoCookiesPreference.java", "java/src/org/chromium/components/page_info/PageInfoDialog.java", "java/src/org/chromium/components/page_info/PageInfoFeatureList.java", - "java/src/org/chromium/components/page_info/PageInfoMainPageController.java", + "java/src/org/chromium/components/page_info/PageInfoMainController.java", "java/src/org/chromium/components/page_info/PageInfoPermissionsController.java", "java/src/org/chromium/components/page_info/PageInfoRowView.java", - "java/src/org/chromium/components/page_info/PageInfoSubpage.java", "java/src/org/chromium/components/page_info/PageInfoSubpageController.java", "java/src/org/chromium/components/page_info/PageInfoView.java", "java/src/org/chromium/components/page_info/PageInfoViewV2.java",
diff --git a/components/page_info/android/java/res/layout/page_info_subpage.xml b/components/page_info/android/java/res/layout/page_info_container.xml similarity index 75% rename from components/page_info/android/java/res/layout/page_info_subpage.xml rename to components/page_info/android/java/res/layout/page_info_container.xml index a7afe4f..b70ba73 100644 --- a/components/page_info/android/java/res/layout/page_info_subpage.xml +++ b/components/page_info/android/java/res/layout/page_info_container.xml
@@ -14,14 +14,26 @@ android:background="@color/sheet_bg_color" android:orientation="vertical"> + <TextView + android:id="@+id/page_info_truncated_url" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center_horizontal" + android:ellipsize="end" + android:layout_marginVertical="16dp" + android:lineSpacingExtra="6dp" + android:textAlignment="center" + android:textAppearance="@style/TextAppearance.TextLarge.Primary" /> + <view - android:id="@+id/subpage_url" + android:id="@+id/page_info_url" class="org.chromium.components.page_info.PageInfoView$ElidedUrlTextView" android:layout_width="match_parent" android:layout_height="wrap_content" android:ellipsize="end" android:lineSpacingExtra="6dp" android:paddingVertical="16dp" + android:visibility="gone" android:textAlignment="center" android:textAppearance="@style/TextAppearance.TextLarge.Primary" /> @@ -30,7 +42,8 @@ android:layout_height="wrap_content" android:orientation="horizontal" android:gravity="center_vertical" - android:paddingHorizontal="16dp"> + android:paddingHorizontal="16dp" + android:id="@+id/page_info_subpage_header"> <org.chromium.ui.widget.ChromeImageButton android:id="@+id/subpage_back_button" @@ -45,7 +58,7 @@ app:tint="@color/default_icon_color" /> <TextView - android:id="@+id/subpage_title" + android:id="@+id/page_info_subpage_title" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginVertical="12dp" @@ -54,7 +67,7 @@ <!-- Programmatically add page specific inner view here --> <FrameLayout - android:id="@+id/placeholder" + android:id="@+id/page_info_content" android:layout_width="match_parent" android:layout_height="match_parent" />
diff --git a/components/page_info/android/java/res/layout/page_info_v2.xml b/components/page_info/android/java/res/layout/page_info_v2.xml index e8c05c6..c068351 100644 --- a/components/page_info/android/java/res/layout/page_info_v2.xml +++ b/components/page_info/android/java/res/layout/page_info_v2.xml
@@ -17,32 +17,7 @@ <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" - android:orientation="vertical" - android:paddingBottom="12dp" - android:paddingEnd="@dimen/page_info_popup_padding_sides" - android:paddingStart="@dimen/page_info_popup_padding_sides" > - - <TextView - android:id="@+id/page_info_truncated_url" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="center_horizontal" - android:ellipsize="end" - android:layout_marginTop="16dp" - android:lineSpacingExtra="6dp" - android:textAlignment="center" - android:textAppearance="@style/TextAppearance.TextLarge.Primary" /> - - <view class="org.chromium.components.page_info.PageInfoView$ElidedUrlTextView" - android:id="@+id/page_info_url" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:ellipsize="end" - android:lineSpacingExtra="6dp" - android:layout_marginTop="16dp" - android:textAlignment="viewStart" - android:textAppearance="@style/TextAppearance.TextLarge.Primary" /> - + android:orientation="vertical"> <View android:id="@+id/page_info_preview_separator" android:layout_marginTop="16dp"
diff --git a/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoConnectionController.java b/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoConnectionController.java index 624e480..2ed3af89 100644 --- a/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoConnectionController.java +++ b/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoConnectionController.java
@@ -17,7 +17,7 @@ */ public class PageInfoConnectionController implements PageInfoSubpageController, ConnectionInfoView.ConnectionInfoDelegate { - private PageInfoMainPageController mMainController; + private PageInfoMainController mMainController; private final WebContents mWebContents; private final VrHandler mVrHandler; private PageInfoRowView mRowView; @@ -25,8 +25,8 @@ private ConnectionInfoView mInfoView; private ViewGroup mContainer; - public PageInfoConnectionController(PageInfoMainPageController mainController, - PageInfoRowView view, WebContents webContents, VrHandler vrHandler) { + public PageInfoConnectionController(PageInfoMainController mainController, PageInfoRowView view, + WebContents webContents, VrHandler vrHandler) { mMainController = mainController; mWebContents = webContents; mVrHandler = vrHandler;
diff --git a/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoContainer.java b/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoContainer.java new file mode 100644 index 0000000..070bf76 --- /dev/null +++ b/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoContainer.java
@@ -0,0 +1,103 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.components.page_info; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.FrameLayout; +import android.widget.TextView; + +import org.chromium.ui.widget.ChromeImageButton; + +/** + * Represents the url, a sub page header and container for page info content. + */ +public class PageInfoContainer extends FrameLayout { + /** Parameters to configure the view of page info subpage. */ + public static class Params { + // Whether the URL title should be shown. + public boolean urlTitleShown; + // The URL to be shown at the top of the page. + public CharSequence url; + // The length of the URL's origin in number of characters. + public int urlOriginLength; + // The URL to show in truncated state. + public String truncatedUrl; + + public Runnable urlTitleClickCallback; + public Runnable urlTitleLongClickCallback; + public Runnable backButtonClickCallback; + } + private PageInfoView.ElidedUrlTextView mUrlTitle; + private TextView mTruncatedUrlTitle; + + private final View mSubpageHeader; + private TextView mSubpageTitle; + private final FrameLayout mContent; + + public PageInfoContainer(Context context) { + super(context); + LayoutInflater.from(context).inflate(R.layout.page_info_container, this, true); + mSubpageHeader = findViewById(R.id.page_info_subpage_header); + mSubpageTitle = findViewById(R.id.page_info_subpage_title); + mContent = findViewById(R.id.page_info_content); + } + + public void setParams(Params params) { + mUrlTitle = findViewById(R.id.page_info_url); + initializeUrlView(mUrlTitle, params); + mUrlTitle.setUrl(params.url, params.urlOriginLength); + // Adjust the mUrlTitle for displaying the non-truncated URL. + mUrlTitle.toggleTruncation(); + + mTruncatedUrlTitle = findViewById(R.id.page_info_truncated_url); + // Use a separate view for truncated URL display. + initializeUrlView(mTruncatedUrlTitle, params); + mTruncatedUrlTitle = findViewById(R.id.page_info_truncated_url); + mTruncatedUrlTitle.setText(params.truncatedUrl); + + ChromeImageButton backButton = findViewById(R.id.subpage_back_button); + backButton.setOnClickListener(v -> params.backButtonClickCallback.run()); + } + + private void initializeUrlView(View view, Params params) { + if (!params.urlTitleShown) { + view.setVisibility(GONE); + } + if (params.urlTitleClickCallback != null) { + view.setOnClickListener(v -> { params.urlTitleClickCallback.run(); }); + } + if (params.urlTitleLongClickCallback != null) { + view.setOnLongClickListener(v -> { + params.urlTitleLongClickCallback.run(); + return true; + }); + } + } + + public void toggleUrlTruncation() { + mUrlTitle.setVisibility(mTruncatedUrlTitle.getVisibility()); + mTruncatedUrlTitle.setVisibility(mUrlTitle.getVisibility() == VISIBLE ? GONE : VISIBLE); + } + + public void setFavicon(Drawable favicon) { + int padding = + getResources().getDimensionPixelSize(R.dimen.page_info_popup_button_padding_sides); + int size = getResources().getDimensionPixelSize(R.dimen.page_info_favicon_size); + + favicon.setBounds(0, 0, size, size); + mTruncatedUrlTitle.setCompoundDrawablePadding(padding); + mTruncatedUrlTitle.setCompoundDrawablesRelative(favicon, null, null, null); + } + + public void showPage(View view, CharSequence title, boolean isMainPage) { + mContent.removeAllViews(); + mContent.addView(view); + mSubpageHeader.setVisibility(isMainPage ? GONE : VISIBLE); + mSubpageTitle.setText(title); + } +}
diff --git a/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoController.java b/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoController.java index a7a1355..459c4db 100644 --- a/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoController.java +++ b/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoController.java
@@ -18,9 +18,7 @@ import android.text.style.ForegroundColorSpan; import android.text.style.TextAppearanceSpan; import android.view.View; -import android.view.ViewGroup; import android.view.Window; -import android.widget.FrameLayout; import androidx.annotation.IntDef; import androidx.annotation.VisibleForTesting; @@ -66,9 +64,9 @@ /** * Java side of Android implementation of the page info UI. */ -public class PageInfoController - implements PageInfoMainPageController, ModalDialogProperties.Controller, - SystemSettingsActivityRequiredListener, CookieControlsObserver { +public class PageInfoController implements PageInfoMainController, ModalDialogProperties.Controller, + SystemSettingsActivityRequiredListener, + CookieControlsObserver { @IntDef({OpenedFromSource.MENU, OpenedFromSource.TOOLBAR, OpenedFromSource.VR}) @Retention(RetentionPolicy.SOURCE) public @interface OpenedFromSource { @@ -85,9 +83,12 @@ // A pointer to the C++ object for this UI. private long mNativePageInfoController; - // The view inside the popup. + // The view inside the popup or the main PageInfo view. private PageInfoView mView; + // The view inside the popup (V2). + private PageInfoContainer mContainer; + // The dialog the view is placed in. private PageInfoDialog mDialog; @@ -95,12 +96,6 @@ // URL'. private String mFullUrl; - // The URL to be shown at the top of the page info views. - private SpannableStringBuilder mDisplayUrlBuilder; - - // The length of the URL's origin in number of characters. - private int mUrlOriginLength; - // Whether or not this page is an internal chrome page (e.g. the // chrome://settings page). private boolean mIsInternalPage; @@ -123,15 +118,13 @@ // Whether Version 2 of the PageInfoView is enabled. private boolean mIsV2Enabled; + // Used to show Site settings from Page Info UI. private final PermissionParamsListBuilder mPermissionParamsListBuilder; // Delegate used by PermissionParamsListBuilder. private final PermissionParamsListBuilderDelegate mPermissionParamsListBuilderDelegate; - // The specific subpage being shown at any time, if any. - private PageInfoSubpage mSubpage; - // The current page info subpage controller, if any. private PageInfoSubpageController mSubpageController; @@ -197,33 +190,29 @@ if (mDelegate.isShowingOfflinePage()) { displayUrl = UrlUtilities.stripScheme(mFullUrl); } - mDisplayUrlBuilder = new SpannableStringBuilder(displayUrl); + SpannableStringBuilder displayUrlBuilder = new SpannableStringBuilder(displayUrl); AutocompleteSchemeClassifier autocompleteSchemeClassifier = delegate.createAutocompleteSchemeClassifier(); if (mSecurityLevel == ConnectionSecurityLevel.SECURE) { OmniboxUrlEmphasizer.EmphasizeComponentsResponse emphasizeResponse = OmniboxUrlEmphasizer.parseForEmphasizeComponents( - mDisplayUrlBuilder.toString(), autocompleteSchemeClassifier); + displayUrlBuilder.toString(), autocompleteSchemeClassifier); if (emphasizeResponse.schemeLength > 0) { - mDisplayUrlBuilder.setSpan( + displayUrlBuilder.setSpan( new TextAppearanceSpan(mContext, R.style.TextAppearance_RobotoMediumStyle), 0, emphasizeResponse.schemeLength, Spannable.SPAN_EXCLUSIVE_INCLUSIVE); } } boolean useDarkText = !ColorUtils.inNightMode(mContext); - OmniboxUrlEmphasizer.emphasizeUrl(mDisplayUrlBuilder, mContext.getResources(), + OmniboxUrlEmphasizer.emphasizeUrl(displayUrlBuilder, mContext.getResources(), autocompleteSchemeClassifier, mSecurityLevel, mIsInternalPage, useDarkText, /*emphasizeScheme=*/true); - viewParams.url = mDisplayUrlBuilder; - mUrlOriginLength = OmniboxUrlEmphasizer.getOriginEndIndex( - mDisplayUrlBuilder.toString(), autocompleteSchemeClassifier); - viewParams.urlOriginLength = mUrlOriginLength; + viewParams.url = displayUrlBuilder; + viewParams.urlOriginLength = OmniboxUrlEmphasizer.getOriginEndIndex( + displayUrlBuilder.toString(), autocompleteSchemeClassifier); autocompleteSchemeClassifier.destroy(); - viewParams.truncatedUrl = - UrlFormatter.formatUrlForSecurityDisplay(url, SchemeDisplay.OMIT_HTTP_AND_HTTPS); - if (mDelegate.isSiteSettingsAvailable()) { viewParams.siteSettingsButtonClickCallback = () -> { // Delay while the dialog closes. @@ -265,20 +254,30 @@ : new PageInfoView(mContext, viewParams); if (isSheet(mContext)) mView.setBackgroundColor(Color.WHITE); if (mIsV2Enabled) { - mSubpage = new PageInfoSubpage(mContext); - mSubpage.setBackButtonOnClickListener(view -> exitSubpage()); + mContainer = new PageInfoContainer(mContext); + PageInfoContainer.Params containerParams = new PageInfoContainer.Params(); + containerParams.url = viewParams.url; + containerParams.urlOriginLength = viewParams.urlOriginLength; + containerParams.truncatedUrl = UrlFormatter.formatUrlForSecurityDisplay( + url, SchemeDisplay.OMIT_HTTP_AND_HTTPS); + containerParams.backButtonClickCallback = this::exitSubpage; + containerParams.urlTitleClickCallback = mContainer::toggleUrlTruncation; + containerParams.urlTitleLongClickCallback = viewParams.urlTitleLongClickCallback; + containerParams.urlTitleShown = viewParams.urlTitleShown; + mContainer.setParams(containerParams); + mContainer.showPage(mView, "", true); PageInfoViewV2 view2 = (PageInfoViewV2) mView; mConnectionController = new PageInfoConnectionController( this, view2.getConnectionRowView(), mWebContents, mDelegate.getVrHandler()); mPermissionsController = new PageInfoPermissionsController( - this, view2.getPermissionsRowView(), mDelegate, mDisplayUrlBuilder.toString()); + this, view2.getPermissionsRowView(), mDelegate, mFullUrl); mCookiesController = new PageInfoCookiesController(this, view2.getCookiesRowView(), mDelegate, viewParams.cookieControlsShown, mFullUrl); mDelegate.getFavicon(mFullUrl, favicon -> { if (favicon != null) { - mView.setFavicon(favicon); + mContainer.setFavicon(favicon); } else { - mView.setFavicon( + mContainer.setFavicon( SettingsUtils.getTintedIcon(mContext, R.drawable.ic_globe_24dp)); } }); @@ -336,7 +335,7 @@ } }; - mDialog = new PageInfoDialog(mContext, mView, mSubpage, + mDialog = new PageInfoDialog(mContext, mView, mContainer, webContents.getViewAndroidDelegate().getContainerView(), isSheet(mContext), delegate.getModalDialogManager(), this); mDialog.show(); @@ -503,9 +502,8 @@ } @VisibleForTesting - public PageInfoView getPageInfoViewForTesting() { - // Check that this view is active. - assert mView.getParent() != null; + public View getPageInfoViewForTesting() { + if (mContainer != null) return mContainer; return mView; } @@ -584,33 +582,16 @@ @Override public void launchSubpage(PageInfoSubpageController controller) { mSubpageController = controller; - PageInfoSubpage.Params subpageParams = new PageInfoSubpage.Params(); - subpageParams.url = mDisplayUrlBuilder; - subpageParams.urlOriginLength = mUrlOriginLength; - subpageParams.subpageTitle = mSubpageController.getSubpageTitle(); - mSubpage.updateSubpage(subpageParams); - View subview = mSubpageController.createViewForSubpage(mSubpage); - - ((FrameLayout) mSubpage.findViewById(R.id.placeholder)).addView(subview); - replaceView(mView, mSubpage); + CharSequence title = mSubpageController.getSubpageTitle(); + View subview = mSubpageController.createViewForSubpage(mContainer); + mContainer.showPage(subview, title, false); controller.onSubPageAttached(); } @Override public void exitSubpage() { - replaceView(mSubpage, mView); - ((FrameLayout) mSubpage.findViewById(R.id.placeholder)).removeAllViews(); + mContainer.showPage(mView, "", true); mSubpageController.onSubpageRemoved(); mSubpageController = null; } - - private void replaceView(View currentView, View newView) { - assert currentView.getParent() != null; - assert newView.getParent() == null; - - ViewGroup parent = (ViewGroup) currentView.getParent(); - final int index = parent.indexOfChild(currentView); - parent.removeView(currentView); - parent.addView(newView, index); - } }
diff --git a/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoCookiesController.java b/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoCookiesController.java index 759e2eb..e07aca3 100644 --- a/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoCookiesController.java +++ b/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoCookiesController.java
@@ -23,7 +23,7 @@ */ public class PageInfoCookiesController implements PageInfoSubpageController, CookieControlsObserver { - private PageInfoMainPageController mMainController; + private PageInfoMainController mMainController; private PageInfoRowView mRowView; private CookieControlsBridge mBridge; private PageInfoControllerDelegate mDelegate; @@ -36,9 +36,8 @@ private int mStatus; private boolean mIsEnforced; - public PageInfoCookiesController(PageInfoMainPageController mainController, - PageInfoRowView rowView, PageInfoControllerDelegate delegate, boolean isVisible, - String fullUrl) { + public PageInfoCookiesController(PageInfoMainController mainController, PageInfoRowView rowView, + PageInfoControllerDelegate delegate, boolean isVisible, String fullUrl) { mMainController = mainController; mRowView = rowView; mDelegate = delegate;
diff --git a/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoDialog.java b/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoDialog.java index e88e7b4..81c64885 100644 --- a/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoDialog.java +++ b/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoDialog.java
@@ -39,7 +39,7 @@ @NonNull private final PageInfoView mView; - private final PageInfoSubpage mSubpageView; + private final PageInfoContainer mContainerView; private final boolean mIsSheet; // The dialog implementation. // mSheetDialog is set if the dialog appears as a sheet. Otherwise, mModalDialog is set. @@ -68,11 +68,11 @@ * */ public PageInfoDialog(Context context, @NonNull PageInfoView view, - @Nullable PageInfoSubpage subpageView, View containerView, boolean isSheet, + @Nullable PageInfoContainer subpageView, View containerView, boolean isSheet, @NonNull ModalDialogManager manager, @NonNull ModalDialogProperties.Controller controller) { mView = view; - mSubpageView = subpageView; + mContainerView = subpageView; mIsSheet = isSheet; mManager = manager; mController = controller; @@ -99,7 +99,7 @@ container = new ScrollView(context); } - container.addView(mView); + container.addView(mContainerView != null ? mContainerView : mView); if (isSheet) { mSheetDialog = createSheetDialog(context, container); @@ -163,8 +163,8 @@ // Delay the cleanup by a tiny amount to give this frame a chance to // be displayed before we destroy the dialog. mView.postDelayed(this::superDismiss, CLOSE_CLEANUP_DELAY_MS); - if (mSubpageView != null) { - mSubpageView.postDelayed(this::superDismiss, CLOSE_CLEANUP_DELAY_MS); + if (mContainerView != null) { + mContainerView.postDelayed(this::superDismiss, CLOSE_CLEANUP_DELAY_MS); } }).start(); } @@ -238,8 +238,8 @@ private Animator createAllAnimations(boolean isEnter, Runnable onAnimationEnd) { Animator dialogAnimation = mIsSheet ? createDialogSlideAnimaton(isEnter, mView) : new AnimatorSet(); - Animator subpageDialogAnimation = mIsSheet && mSubpageView != null - ? createDialogSlideAnimaton(isEnter, mSubpageView) + Animator subpageDialogAnimation = mIsSheet && mContainerView != null + ? createDialogSlideAnimaton(isEnter, mContainerView) : new AnimatorSet(); Animator viewAnimation = mView.createEnterExitAnimation(isEnter); AnimatorSet allAnimations = new AnimatorSet();
diff --git a/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoMainPageController.java b/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoMainController.java similarity index 95% rename from components/page_info/android/java/src/org/chromium/components/page_info/PageInfoMainPageController.java rename to components/page_info/android/java/src/org/chromium/components/page_info/PageInfoMainController.java index 8e5a4b2..72ccc1b 100644 --- a/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoMainPageController.java +++ b/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoMainController.java
@@ -9,7 +9,7 @@ /** * Interface for a page info main page controller. */ -public interface PageInfoMainPageController { +public interface PageInfoMainController { /** * Launches the PageInfoSubpage provided by |pageInfoCookiesController|. * @param controller The controller providing a PageInfoSubpage.
diff --git a/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoPermissionsController.java b/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoPermissionsController.java index ff93fdd..3bf0d7fb 100644 --- a/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoPermissionsController.java +++ b/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoPermissionsController.java
@@ -17,14 +17,14 @@ * Class for controlling the page info permissions section. */ public class PageInfoPermissionsController implements PageInfoSubpageController { - private PageInfoMainPageController mMainController; + private PageInfoMainController mMainController; private PageInfoRowView mRowView; private PageInfoControllerDelegate mDelegate; private String mTitle; private String mPageUrl; private SingleWebsiteSettings mSubpageFragment; - public PageInfoPermissionsController(PageInfoMainPageController mainController, + public PageInfoPermissionsController(PageInfoMainController mainController, PageInfoRowView view, PageInfoControllerDelegate delegate, String pageUrl) { mMainController = mainController; mRowView = view;
diff --git a/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoSubpage.java b/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoSubpage.java deleted file mode 100644 index 5fff064..0000000 --- a/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoSubpage.java +++ /dev/null
@@ -1,48 +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. - -package org.chromium.components.page_info; - -import android.content.Context; -import android.view.LayoutInflater; -import android.view.View; -import android.widget.FrameLayout; -import android.widget.TextView; - -import org.chromium.ui.widget.ChromeImageButton; - -/** - * Represents a particular page info subpage. - */ -public class PageInfoSubpage extends FrameLayout { - /** Parameters to configure the view of page info subpage. */ - public static class Params { - // The URL to be shown at the top of the page. - public CharSequence url; - // The length of the URL's origin in number of characters. - public int urlOriginLength; - // The name of the subpage to be displayed. - public String subpageTitle; - } - - private PageInfoView.ElidedUrlTextView mUrlTitle; - private TextView mSubpageTitle; - - public PageInfoSubpage(Context context) { - super(context); - LayoutInflater.from(context).inflate(R.layout.page_info_subpage, this, true); - mUrlTitle = findViewById(R.id.subpage_url); - mSubpageTitle = findViewById(R.id.subpage_title); - } - - public void updateSubpage(Params params) { - mUrlTitle.setUrl(params.url, params.urlOriginLength); - mSubpageTitle.setText(params.subpageTitle); - } - - public void setBackButtonOnClickListener(View.OnClickListener listener) { - ChromeImageButton backButton = findViewById(R.id.subpage_back_button); - backButton.setOnClickListener(listener); - } -}
diff --git a/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoView.java b/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoView.java index 580477c..1c9186a 100644 --- a/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoView.java +++ b/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoView.java
@@ -8,7 +8,6 @@ import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.content.Context; -import android.graphics.drawable.Drawable; import android.text.Layout; import android.util.AttributeSet; import android.view.LayoutInflater; @@ -174,7 +173,6 @@ public CharSequence url; public CharSequence previewLoadOriginalMessage; public int urlOriginLength; - public CharSequence truncatedUrl; } /** Parameters to configure the permission info section */ @@ -344,13 +342,6 @@ mOnUiClosingCallback.run(); } - /** - * Sets a favicon for the current page. - */ - public void setFavicon(Drawable favicon) { - // Not implemented. - } - public void setPermissions(PermissionParams params) { mPermissionsList.removeAllViews(); // If we have at least one permission show the lower permissions area.
diff --git a/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoViewV2.java b/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoViewV2.java index 57d52f2..eefa728 100644 --- a/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoViewV2.java +++ b/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoViewV2.java
@@ -5,11 +5,9 @@ package org.chromium.components.page_info; import android.content.Context; -import android.graphics.drawable.Drawable; import android.view.LayoutInflater; import android.view.View; import android.widget.LinearLayout; -import android.widget.TextView; import java.util.Arrays; import java.util.List; @@ -23,7 +21,6 @@ private PageInfoRowView mConnectionRow; private PageInfoRowView mPermissionsRow; private PageInfoRowView mCookiesRow; - private TextView mTruncatedUrlTitle; public PageInfoViewV2(Context context, PageInfoView.PageInfoViewParams params) { super(context); @@ -32,17 +29,6 @@ } @Override - public void setFavicon(Drawable favicon) { - int padding = - getResources().getDimensionPixelSize(R.dimen.page_info_popup_button_padding_sides); - int size = getResources().getDimensionPixelSize(R.dimen.page_info_favicon_size); - - favicon.setBounds(0, 0, size, size); - mTruncatedUrlTitle.setCompoundDrawablePadding(padding); - mTruncatedUrlTitle.setCompoundDrawablesRelative(favicon, null, null, null); - } - - @Override protected void init(PageInfoView.PageInfoViewParams params) { super.init(params); mRowWrapper = findViewById(R.id.page_info_row_wrapper); @@ -51,23 +37,7 @@ @Override protected void initUrlTitle(PageInfoView.PageInfoViewParams params) { - super.initUrlTitle(params); - // Adjust the mUrlTitle for displaying the non-truncated URL. - mUrlTitle.setTextAlignment(View.TEXT_ALIGNMENT_CENTER); - mUrlTitle.setAlpha(1.0f); - mUrlTitle.setVisibility(GONE); - mUrlTitle.toggleTruncation(); - // Use a separate view for truncated URL display. - mTruncatedUrlTitle = findViewById(R.id.page_info_truncated_url); - mTruncatedUrlTitle.setText(params.truncatedUrl); - if (params.urlTitleLongClickCallback != null) { - mTruncatedUrlTitle.setOnLongClickListener(v -> { - params.urlTitleLongClickCallback.run(); - return true; - }); - } - initializePageInfoViewChild( - mTruncatedUrlTitle, params.urlTitleShown, 0f, params.urlTitleClickCallback); + // URL is initialized in PageInfoContainer. } @Override @@ -108,8 +78,7 @@ @Override public void toggleUrlTruncation() { - mUrlTitle.setVisibility(mTruncatedUrlTitle.getVisibility()); - mTruncatedUrlTitle.setVisibility(mUrlTitle.getVisibility() == VISIBLE ? GONE : VISIBLE); + throw new RuntimeException(); } /** @@ -118,7 +87,7 @@ @Override protected List<View> collectAnimatableViews() { // TODO(crbug.com/1077766): Sort and use rows instead of the rowWrapper. - return Arrays.asList(mTruncatedUrlTitle, mPreviewMessage, mPreviewLoadOriginal, - mPreviewSeparator, mInstantAppButton, mRowWrapper, mSiteSettingsButton); + return Arrays.asList(mPreviewMessage, mPreviewLoadOriginal, mPreviewSeparator, + mInstantAppButton, mRowWrapper, mSiteSettingsButton); } }
diff --git a/components/paint_preview/browser/BUILD.gn b/components/paint_preview/browser/BUILD.gn index fe905fd1..3712dfe 100644 --- a/components/paint_preview/browser/BUILD.gn +++ b/components/paint_preview/browser/BUILD.gn
@@ -26,8 +26,6 @@ "paint_preview_compositor_service_impl.h", "paint_preview_policy.h", "service_sandbox_type.h", - "warm_compositor.cc", - "warm_compositor.h", ] deps = [
diff --git a/components/paint_preview/browser/paint_preview_compositor_service_impl.cc b/components/paint_preview/browser/paint_preview_compositor_service_impl.cc index f1489dd..9a58136 100644 --- a/components/paint_preview/browser/paint_preview_compositor_service_impl.cc +++ b/components/paint_preview/browser/paint_preview_compositor_service_impl.cc
@@ -101,12 +101,6 @@ return !active_clients_.empty(); } -void PaintPreviewCompositorServiceImpl::SetDisconnectHandler( - base::OnceClosure disconnect_handler) { - DCHECK(default_task_runner_->RunsTasksInCurrentSequence()); - user_disconnect_closure_ = std::move(disconnect_handler); -} - void PaintPreviewCompositorServiceImpl::MarkCompositorAsDeleted( const base::UnguessableToken& token) { DCHECK(default_task_runner_->RunsTasksInCurrentSequence()); @@ -127,8 +121,7 @@ void PaintPreviewCompositorServiceImpl::DisconnectHandler() { DCHECK(default_task_runner_->RunsTasksInCurrentSequence()); - if (user_disconnect_closure_) - std::move(user_disconnect_closure_).Run(); + std::move(user_disconnect_closure_).Run(); compositor_service_.reset(); }
diff --git a/components/paint_preview/browser/paint_preview_compositor_service_impl.h b/components/paint_preview/browser/paint_preview_compositor_service_impl.h index 590e6360..8ca3b2010 100644 --- a/components/paint_preview/browser/paint_preview_compositor_service_impl.h +++ b/components/paint_preview/browser/paint_preview_compositor_service_impl.h
@@ -38,9 +38,6 @@ CreateCompositor(base::OnceClosure connected_closure) override; bool HasActiveClients() const override; - // NOTE: this is set by the constructor. However, in some cases it may need to - // be changed. - void SetDisconnectHandler(base::OnceClosure disconnect_handler) override; // Marks the compositor associated with |token| as deleted in the // |active_clients_| set.
diff --git a/components/paint_preview/browser/warm_compositor.cc b/components/paint_preview/browser/warm_compositor.cc deleted file mode 100644 index f5c1d22..0000000 --- a/components/paint_preview/browser/warm_compositor.cc +++ /dev/null
@@ -1,55 +0,0 @@ -// Copyright 2020 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "components/paint_preview/browser/warm_compositor.h" - -#include <utility> - -#include "base/bind.h" -#include "base/memory/singleton.h" -#include "components/paint_preview/browser/compositor_utils.h" - -namespace paint_preview { - -WarmCompositor::WarmCompositor() - : compositor_service_(nullptr, base::OnTaskRunnerDeleter(nullptr)) {} -WarmCompositor::~WarmCompositor() = default; - -// static -WarmCompositor* WarmCompositor::GetInstance() { - return base::Singleton<WarmCompositor, - base::LeakySingletonTraits<WarmCompositor>>::get(); -} - -void WarmCompositor::WarmupCompositor() { - if (compositor_service_) - return; - - compositor_service_ = StartCompositorService(base::BindOnce( - &WarmCompositor::OnDisconnect, weak_ptr_factory_.GetWeakPtr())); -} - -bool WarmCompositor::StopCompositor() { - if (!compositor_service_) - return false; - - compositor_service_.reset(); - return true; -} - -std::unique_ptr<PaintPreviewCompositorService, base::OnTaskRunnerDeleter> -WarmCompositor::GetOrStartCompositorService( - base::OnceClosure disconnect_handler) { - if (!compositor_service_) - return StartCompositorService(std::move(disconnect_handler)); - - compositor_service_->SetDisconnectHandler(std::move(disconnect_handler)); - return std::move(compositor_service_); -} - -void WarmCompositor::OnDisconnect() { - compositor_service_.reset(); -} - -} // namespace paint_preview
diff --git a/components/paint_preview/browser/warm_compositor.h b/components/paint_preview/browser/warm_compositor.h deleted file mode 100644 index defeebe..0000000 --- a/components/paint_preview/browser/warm_compositor.h +++ /dev/null
@@ -1,56 +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 COMPONENTS_PAINT_PREVIEW_BROWSER_WARM_COMPOSITOR_H_ -#define COMPONENTS_PAINT_PREVIEW_BROWSER_WARM_COMPOSITOR_H_ - -#include <memory> - -#include "base/task_runner.h" -#include "components/paint_preview/public/paint_preview_compositor_service.h" - -namespace base { -template <typename T> -struct DefaultSingletonTraits; -} - -namespace paint_preview { - -// A class that can hold a pre-warmed compositor service for use. -class WarmCompositor { - public: - ~WarmCompositor(); - - WarmCompositor(const WarmCompositor&) = delete; - WarmCompositor& operator=(const WarmCompositor&) = delete; - - static WarmCompositor* GetInstance(); - - // Warms up the compositor service. - void WarmupCompositor(); - - // Releases the warmed compositor service if there is one. Returns true if a - // compositor was released. - bool StopCompositor(); - - // Passes the pre-warmed compositor to the caller if one is present. - // Otherwise starts a new compositor. - std::unique_ptr<PaintPreviewCompositorService, base::OnTaskRunnerDeleter> - GetOrStartCompositorService(base::OnceClosure disconnect_handler); - - private: - WarmCompositor(); - friend struct base::DefaultSingletonTraits<WarmCompositor>; - - void OnDisconnect(); - - std::unique_ptr<PaintPreviewCompositorService, base::OnTaskRunnerDeleter> - compositor_service_; - - base::WeakPtrFactory<WarmCompositor> weak_ptr_factory_{this}; -}; - -} // namespace paint_preview - -#endif // COMPONENTS_PAINT_PREVIEW_BROWSER_WARM_COMPOSITOR_H_
diff --git a/components/paint_preview/player/player_compositor_delegate.cc b/components/paint_preview/player/player_compositor_delegate.cc index 3f14d43..8ac4e61 100644 --- a/components/paint_preview/player/player_compositor_delegate.cc +++ b/components/paint_preview/player/player_compositor_delegate.cc
@@ -21,8 +21,8 @@ #include "base/trace_event/common/trace_event_common.h" #include "base/trace_event/trace_event.h" #include "base/unguessable_token.h" +#include "components/paint_preview/browser/compositor_utils.h" #include "components/paint_preview/browser/paint_preview_base_service.h" -#include "components/paint_preview/browser/warm_compositor.h" #include "components/paint_preview/common/proto/paint_preview.pb.h" #include "components/paint_preview/common/recording_map.h" #include "components/paint_preview/common/serialized_recording.h" @@ -120,10 +120,9 @@ TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("paint_preview", "PlayerCompositorDelegate CreateCompositor", TRACE_ID_LOCAL(this)); - paint_preview_compositor_service_ = - WarmCompositor::GetInstance()->GetOrStartCompositorService(base::BindOnce( - &PlayerCompositorDelegate::OnCompositorServiceDisconnected, - weak_factory_.GetWeakPtr())); + paint_preview_compositor_service_ = StartCompositorService( + base::BindOnce(&PlayerCompositorDelegate::OnCompositorServiceDisconnected, + weak_factory_.GetWeakPtr())); paint_preview_compositor_client_ = paint_preview_compositor_service_->CreateCompositor(
diff --git a/components/paint_preview/public/paint_preview_compositor_service.h b/components/paint_preview/public/paint_preview_compositor_service.h index ab934d2..10be79ce 100644 --- a/components/paint_preview/public/paint_preview_compositor_service.h +++ b/components/paint_preview/public/paint_preview_compositor_service.h
@@ -35,9 +35,6 @@ // check if killing this service is safe (i.e. won't drop messages). virtual bool HasActiveClients() const = 0; - // Sets the disconnect handler for this service. - virtual void SetDisconnectHandler(base::OnceClosure disconnect_handler) = 0; - PaintPreviewCompositorService(const PaintPreviewCompositorService&) = delete; PaintPreviewCompositorService& operator=( const PaintPreviewCompositorService&) = delete;
diff --git a/components/password_manager/content/browser/bad_message.h b/components/password_manager/content/browser/bad_message.h index 5d9a0384..5d1a692f 100644 --- a/components/password_manager/content/browser/bad_message.h +++ b/components/password_manager/content/browser/bad_message.h
@@ -34,7 +34,7 @@ CPMD_BAD_ORIGIN_PASSWORD_NO_LONGER_GENERATED = 6, CPMD_BAD_ORIGIN_PRESAVE_GENERATED_PASSWORD = 7, CPMD_BAD_ORIGIN_SAVE_GENERATION_FIELD_DETECTED_BY_CLASSIFIER = 8, - CPMD_BAD_ORIGIN_SHOW_FALLBACK_FOR_SAVING = 9, + CPMD_BAD_ORIGIN_UPON_USER_INPUT_CHANGE = 9, CPMD_BAD_ORIGIN_AUTOMATIC_GENERATION_STATUS_CHANGED = 10, CPMD_BAD_ORIGIN_SHOW_MANUAL_PASSWORD_GENERATION_POPUP = 11, CPMD_BAD_ORIGIN_SHOW_PASSWORD_EDITING_POPUP = 12,
diff --git a/components/password_manager/content/browser/content_password_manager_driver.cc b/components/password_manager/content/browser/content_password_manager_driver.cc index 60599057c..3a015aa 100644 --- a/components/password_manager/content/browser/content_password_manager_driver.cc +++ b/components/password_manager/content/browser/content_password_manager_driver.cc
@@ -246,15 +246,16 @@ LogSiteIsolationMetricsForSubmittedForm(render_frame_host_); } -void ContentPasswordManagerDriver::ShowManualFallbackForSaving( +void ContentPasswordManagerDriver::InformAboutUserInput( const autofill::FormData& form_data) { if (!password_manager::bad_message::CheckChildProcessSecurityPolicyForURL( render_frame_host_, form_data.url, - BadMessageReason::CPMD_BAD_ORIGIN_SHOW_FALLBACK_FOR_SAVING)) + BadMessageReason::CPMD_BAD_ORIGIN_UPON_USER_INPUT_CHANGE)) return; - GetPasswordManager()->ShowManualFallbackForSaving(this, form_data); + GetPasswordManager()->OnInformAboutUserInput(this, form_data); - if (client_->IsIsolationForPasswordSitesEnabled()) { + if (FormHasNonEmptyPasswordField(form_data) && + client_->IsIsolationForPasswordSitesEnabled()) { // This function signals that a password field has been filled (whether by // the user, JS, autofill, or some other means) or a password form has been // submitted. Use this as a heuristic to start site-isolating the form's @@ -266,10 +267,6 @@ } } -void ContentPasswordManagerDriver::HideManualFallbackForSaving() { - GetPasswordManager()->HideManualFallbackForSaving(); -} - void ContentPasswordManagerDriver::SameDocumentNavigation( autofill::mojom::SubmissionIndicatorEvent submission_indication_event) { GetPasswordManager()->OnPasswordFormSubmittedNoChecks(
diff --git a/components/password_manager/content/browser/content_password_manager_driver.h b/components/password_manager/content/browser/content_password_manager_driver.h index 5aa51d0..0d6354c 100644 --- a/components/password_manager/content/browser/content_password_manager_driver.h +++ b/components/password_manager/content/browser/content_password_manager_driver.h
@@ -100,9 +100,7 @@ const std::vector<autofill::FormData>& visible_forms_data, bool did_stop_loading) override; void PasswordFormSubmitted(const autofill::FormData& form_data) override; - void ShowManualFallbackForSaving( - const autofill::FormData& form_data) override; - void HideManualFallbackForSaving() override; + void InformAboutUserInput(const autofill::FormData& form_data) override; void SameDocumentNavigation(autofill::mojom::SubmissionIndicatorEvent submission_indication_event) override; void RecordSavePasswordProgress(const std::string& log) override;
diff --git a/components/password_manager/core/browser/BUILD.gn b/components/password_manager/core/browser/BUILD.gn index 0c9fbb3c..4d48c57 100644 --- a/components/password_manager/core/browser/BUILD.gn +++ b/components/password_manager/core/browser/BUILD.gn
@@ -242,6 +242,8 @@ "ui/post_save_compromised_helper.h", "ui/saved_passwords_presenter.cc", "ui/saved_passwords_presenter.h", + "ui/weak_check_utility.cc", + "ui/weak_check_utility.h", "votes_uploader.cc", "votes_uploader.h", "well_known_change_password_state.cc", @@ -312,6 +314,7 @@ "//third_party/abseil-cpp:absl", "//third_party/protobuf:protobuf_lite", "//third_party/re2", + "//third_party/zxcvbn-cpp", "//ui/base", "//ui/gfx", "//ui/gfx/range", @@ -635,6 +638,7 @@ "ui/insecure_credentials_manager_unittest.cc", "ui/post_save_compromised_helper_unittest.cc", "ui/saved_passwords_presenter_unittest.cc", + "ui/weak_check_utility_unittest.cc", "vote_uploads_test_matchers.h", "votes_uploader_unittest.cc", "well_known_change_password_state_unittest.cc",
diff --git a/components/password_manager/core/browser/DEPS b/components/password_manager/core/browser/DEPS index 7bd83f9f..bed33b2 100644 --- a/components/password_manager/core/browser/DEPS +++ b/components/password_manager/core/browser/DEPS
@@ -26,6 +26,7 @@ "+services/network/public/cpp", "+services/network/public/mojom", "+services/network/test", + "+third_party/zxcvbn-cpp", ] specific_include_rules = {
diff --git a/components/password_manager/core/browser/password_manager.cc b/components/password_manager/core/browser/password_manager.cc index 64fd26fb..b25db13 100644 --- a/components/password_manager/core/browser/password_manager.cc +++ b/components/password_manager/core/browser/password_manager.cc
@@ -488,8 +488,8 @@ renderer_id, value, base::Time::Now(), driver_id); } -void PasswordManager::ShowManualFallbackForSaving(PasswordManagerDriver* driver, - const FormData& form_data) { +void PasswordManager::OnInformAboutUserInput(PasswordManagerDriver* driver, + const FormData& form_data) { PasswordFormManager* manager = ProvisionallySaveForm(form_data, driver, true); if (manager && form_data.is_gaia_with_skip_save_password_form) { @@ -504,7 +504,7 @@ if (client_ && client_->GetMetricsRecorder()) client_->GetMetricsRecorder()->RecordFormManagerAvailable(availability); - ShowManualFallbackForSavingImpl(manager, form_data); + ShowManualFallbackForSaving(manager, form_data); } void PasswordManager::HideManualFallbackForSaving() { @@ -724,8 +724,7 @@ if (manager->UpdateStateOnUserInput(form_id, field_id, field_value)) { ProvisionallySaveForm(*manager->observed_form(), driver, true); if (manager->is_submitted() && !manager->HasGeneratedPassword()) { - ShowManualFallbackForSavingImpl(manager.get(), - *manager->observed_form()); + ShowManualFallbackForSaving(manager.get(), *manager->observed_form()); } else { HideManualFallbackForSaving(); } @@ -1197,10 +1196,19 @@ } } -void PasswordManager::ShowManualFallbackForSavingImpl( +void PasswordManager::ShowManualFallbackForSaving( PasswordFormManager* form_manager, const FormData& form_data) { - if (!form_manager || !form_manager->is_submitted()) + // Where `form_manager` is nullptr, make sure the manual fallback isn't + // shown. One scenario where this is relevant is when the user inputs some + // password and then removes it. Upon removing the password, the + // `form_manager` will become nullptr. + if (!form_manager) { + HideManualFallbackForSaving(); + return; + } + + if (!form_manager->is_submitted()) return; if (!client_->GetProfilePasswordStore()->IsAbleToSavePasswords() ||
diff --git a/components/password_manager/core/browser/password_manager.h b/components/password_manager/core/browser/password_manager.h index c600643cc..e815839 100644 --- a/components/password_manager/core/browser/password_manager.h +++ b/components/password_manager/core/browser/password_manager.h
@@ -166,10 +166,10 @@ autofill::FieldRendererId renderer_id, const base::string16& value); - // Handles a request to show manual fallback for password saving, i.e. the - // omnibox icon with the anchored hidden prompt. - void ShowManualFallbackForSaving(PasswordManagerDriver* driver, - const autofill::FormData& form_data); + // Handles user input and decides whether to show manual fallback for password + // saving, i.e. the omnibox icon with the anchored hidden prompt. + void OnInformAboutUserInput(PasswordManagerDriver* driver, + const autofill::FormData& form_data); // Handles a request to hide manual fallback for password saving. void HideManualFallbackForSaving(); @@ -320,8 +320,8 @@ // Handles a request to show manual fallback for password saving, i.e. the // omnibox icon with the anchored hidden prompt. todo - void ShowManualFallbackForSavingImpl(PasswordFormManager* form_manager, - const autofill::FormData& form_data); + void ShowManualFallbackForSaving(PasswordFormManager* form_manager, + const autofill::FormData& form_data); // Returns the timeout for the disabling Password Manager's prompts. base::TimeDelta GetTimeoutForDisablingPrompts();
diff --git a/components/password_manager/core/browser/password_manager_unittest.cc b/components/password_manager/core/browser/password_manager_unittest.cc index 3a18c20..87ec364 100644 --- a/components/password_manager/core/browser/password_manager_unittest.cc +++ b/components/password_manager/core/browser/password_manager_unittest.cc
@@ -913,7 +913,7 @@ std::unique_ptr<PasswordFormManagerForUI> form_manager_to_save; EXPECT_CALL(client_, ShowManualFallbackForSavingPtr(_, false, true)) .WillOnce(WithArg<0>(SaveToScopedPtr(&form_manager_to_save))); - manager()->ShowManualFallbackForSaving(&driver_, incomplete_match.form_data); + manager()->OnInformAboutUserInput(&driver_, incomplete_match.form_data); ASSERT_TRUE(form_manager_to_save); EXPECT_THAT(form_manager_to_save->GetPendingCredentials(), FormMatches(incomplete_match)); @@ -924,7 +924,7 @@ // because the credential is already in the store. EXPECT_CALL(client_, ShowManualFallbackForSavingPtr(_, false, true)).Times(0); EXPECT_CALL(client_, HideManualFallbackForSaving()); - manager()->ShowManualFallbackForSaving(&driver_, form.form_data); + manager()->OnInformAboutUserInput(&driver_, form.form_data); // The user submits the form. No prompt should pop up. The credential is // updated in background. @@ -939,6 +939,42 @@ user_action_tester.GetActionCount("PasswordManager_LoginPassed")); } +TEST_P(PasswordManagerTest, DoNotSaveWhenUserDeletesPassword) { + PasswordForm form(MakeSimpleForm()); + PasswordForm stored_form = form; + stored_form.password_value = ASCIIToUTF16("old_password"); + EXPECT_CALL(*store_, GetLogins(_, _)) + .WillRepeatedly(WithArg<1>(InvokeConsumer(store_.get(), stored_form))); + + ON_CALL(client_, IsSavingAndFillingEnabled(form.url)) + .WillByDefault(Return(true)); + + std::vector<FormData> observed = {form.form_data}; + manager()->OnPasswordFormsParsed(&driver_, observed); + + // The user is typing a credential manually, the fallback should be available. + std::unique_ptr<PasswordFormManagerForUI> form_manager_to_save; + EXPECT_CALL(client_, ShowManualFallbackForSavingPtr(_, false, true)) + .WillOnce(WithArg<0>(SaveToScopedPtr(&form_manager_to_save))); + manager()->OnInformAboutUserInput(&driver_, form.form_data); + ASSERT_TRUE(form_manager_to_save); + + // The user deletes the password, no manuall fallback should be shown. + PasswordForm empty_password_form(form); + empty_password_form.password_value.clear(); + empty_password_form.form_data.fields[1].value.clear(); + EXPECT_CALL(client_, ShowManualFallbackForSavingPtr).Times(0); + EXPECT_CALL(client_, HideManualFallbackForSaving()); + manager()->OnInformAboutUserInput(&driver_, empty_password_form.form_data); + + // The user submits the form. No prompt should pop up. + OnPasswordFormSubmitted(empty_password_form.form_data); + EXPECT_CALL(client_, PromptUserToSaveOrUpdatePasswordPtr).Times(0); + observed.clear(); + manager()->DidNavigateMainFrame(true); + manager()->OnPasswordFormsParsed(&driver_, observed); +} + // Tests that on Chrome sign-in form credentials are not saved. TEST_P(PasswordManagerTest, DoNotSaveOnChromeSignInForm) { FormData form_data(MakeSimpleFormData()); @@ -957,7 +993,7 @@ FormData typed_credentials(form_data); typed_credentials.fields[1].value = ASCIIToUTF16("pw"); EXPECT_CALL(client_, ShowManualFallbackForSavingPtr(_, _, _)).Times(0); - manager()->ShowManualFallbackForSaving(&driver_, form_data); + manager()->OnInformAboutUserInput(&driver_, form_data); // The user submits the form. No prompt should pop up. OnPasswordFormSubmitted(form_data); @@ -992,7 +1028,7 @@ EXPECT_CALL(client_, HideManualFallbackForSaving()); // The call to manual fallback with |form| equal to already saved should close // the fallback, but it should not prevent sending metrics. - manager()->ShowManualFallbackForSaving(&driver_, form.form_data); + manager()->OnInformAboutUserInput(&driver_, form.form_data); EXPECT_CALL(client_, PromptUserToSaveOrUpdatePasswordPtr(_)).Times(0); EXPECT_CALL(*store_, UpdateLogin(_)); @@ -1812,7 +1848,7 @@ .WillRepeatedly(WithArg<1>(InvokeEmptyConsumerWithForms(store_.get()))); manager()->OnPasswordFormsParsed(&driver_, observed); manager()->OnPasswordFormsRendered(&driver_, observed, true); - manager()->ShowManualFallbackForSaving(&driver_, form.form_data); + manager()->OnInformAboutUserInput(&driver_, form.form_data); std::unique_ptr<PasswordFormManagerForUI> form_manager_to_save; EXPECT_CALL(client_, PromptUserToSaveOrUpdatePasswordPtr(_)) @@ -1843,7 +1879,7 @@ .WillRepeatedly(Return(true)); manager()->OnPasswordFormsParsed(&driver_, observed); manager()->OnPasswordFormsRendered(&driver_, observed, true); - manager()->ShowManualFallbackForSaving(&driver_, form.form_data); + manager()->OnInformAboutUserInput(&driver_, form.form_data); std::unique_ptr<PasswordFormManagerForUI> form_manager_to_save; EXPECT_CALL(client_, PromptUserToSaveOrUpdatePasswordPtr(_)) @@ -2466,7 +2502,7 @@ std::unique_ptr<PasswordFormManagerForUI> form_manager_to_save; EXPECT_CALL(client_, ShowManualFallbackForSavingPtr(_, false, true)) .WillOnce(WithArg<0>(SaveToScopedPtr(&form_manager_to_save))); - manager()->ShowManualFallbackForSaving(&driver_, form.form_data); + manager()->OnInformAboutUserInput(&driver_, form.form_data); ASSERT_TRUE(form_manager_to_save); EXPECT_THAT(form_manager_to_save->GetPendingCredentials(), FormMatches(form)); @@ -2476,7 +2512,7 @@ new_form.form_data.fields[0].value = new_form.username_value; EXPECT_CALL(client_, ShowManualFallbackForSavingPtr(_, false, false)) .WillOnce(WithArg<0>(SaveToScopedPtr(&form_manager_to_save))); - manager()->ShowManualFallbackForSaving(&driver_, new_form.form_data); + manager()->OnInformAboutUserInput(&driver_, new_form.form_data); ASSERT_TRUE(form_manager_to_save); EXPECT_THAT(form_manager_to_save->GetPendingCredentials(), FormMatches(new_form)); @@ -2516,7 +2552,7 @@ // There is no response from the store. Don't show the fallback. EXPECT_CALL(client_, ShowManualFallbackForSavingPtr(_, _, _)).Times(0); - manager()->ShowManualFallbackForSaving(&driver_, form_data); + manager()->OnInformAboutUserInput(&driver_, form_data); // The storage responded. The fallback can be shown. ASSERT_TRUE(store_consumer); @@ -2525,7 +2561,7 @@ std::unique_ptr<PasswordFormManagerForUI> form_manager_to_save; EXPECT_CALL(client_, ShowManualFallbackForSavingPtr(_, false, false)) .WillOnce(WithArg<0>(SaveToScopedPtr(&form_manager_to_save))); - manager()->ShowManualFallbackForSaving(&driver_, form_data); + manager()->OnInformAboutUserInput(&driver_, form_data); } TEST_P(PasswordManagerTest, ManualFallbackForSaving_GeneratedPassword) { @@ -2549,7 +2585,7 @@ .WillOnce(WithArg<0>(SaveToScopedPtr(&form_manager_to_save))); manager()->OnPresaveGeneratedPassword(&driver_, form.form_data, form.password_value); - manager()->ShowManualFallbackForSaving(&driver_, form.form_data); + manager()->OnInformAboutUserInput(&driver_, form.form_data); ASSERT_TRUE(form_manager_to_save); EXPECT_THAT(form_manager_to_save->GetPendingCredentials(), FormMatches(form)); @@ -2560,7 +2596,7 @@ .WillOnce(WithArg<0>(SaveToScopedPtr(&form_manager_to_save))); manager()->OnPresaveGeneratedPassword(&driver_, form.form_data, form.password_value); - manager()->ShowManualFallbackForSaving(&driver_, form.form_data); + manager()->OnInformAboutUserInput(&driver_, form.form_data); // A user removes the generated password. The presaved password is removed, // the fallback is disabled. @@ -2829,7 +2865,7 @@ observed.push_back(form_data); manager()->OnPasswordFormsParsed(&driver_, observed); manager()->OnPasswordFormsRendered(&driver_, observed, true); - manager()->ShowManualFallbackForSaving(&driver_, form_data); + manager()->OnInformAboutUserInput(&driver_, form_data); auto submitted_form_data = form_data; submitted_form_data.fields[0].value = ASCIIToUTF16("username"); @@ -2915,7 +2951,7 @@ std::unique_ptr<PasswordFormManagerForUI> form_manager_to_save; EXPECT_CALL(client_, ShowManualFallbackForSavingPtr(_, false, true)) .WillOnce(WithArg<0>(SaveToScopedPtr(&form_manager_to_save))); - manager()->ShowManualFallbackForSaving(&driver_, form.form_data); + manager()->OnInformAboutUserInput(&driver_, form.form_data); ASSERT_TRUE(form_manager_to_save); EXPECT_THAT(form_manager_to_save->GetPendingCredentials(), FormMatches(form)); @@ -2925,7 +2961,7 @@ new_form.form_data.fields[0].value = new_form.username_value; EXPECT_CALL(client_, ShowManualFallbackForSavingPtr(_, false, false)) .WillOnce(WithArg<0>(SaveToScopedPtr(&form_manager_to_save))); - manager()->ShowManualFallbackForSaving(&driver_, new_form.form_data); + manager()->OnInformAboutUserInput(&driver_, new_form.form_data); ASSERT_TRUE(form_manager_to_save); EXPECT_THAT(form_manager_to_save->GetPendingCredentials(), FormMatches(new_form)); @@ -3066,7 +3102,7 @@ std::unique_ptr<PasswordFormManagerForUI> form_manager_to_save; EXPECT_CALL(client_, ShowManualFallbackForSavingPtr(_, false, false)) .WillOnce(WithArg<0>(SaveToScopedPtr(&form_manager_to_save))); - manager()->ShowManualFallbackForSaving(&driver_, form.form_data); + manager()->OnInformAboutUserInput(&driver_, form.form_data); ASSERT_TRUE(form_manager_to_save); EXPECT_THAT(form_manager_to_save->GetPendingCredentials(), FormMatches(form)); @@ -3245,7 +3281,7 @@ manager()->OnPasswordFormSubmitted(nullptr, form_data); break; case MissingFormManagerTestCase::Signal::Manual: - manager()->ShowManualFallbackForSaving(nullptr, form_data); + manager()->OnInformAboutUserInput(nullptr, form_data); break; case MissingFormManagerTestCase::Signal::None: break; @@ -3355,7 +3391,7 @@ std::unique_ptr<PasswordFormManagerForUI> form_manager_to_save; EXPECT_CALL(client_, ShowManualFallbackForSavingPtr(_, false, false)) .WillOnce(WithArg<0>(SaveToScopedPtr(&form_manager_to_save))); - manager()->ShowManualFallbackForSaving(&driver_, credit_card_form.form_data); + manager()->OnInformAboutUserInput(&driver_, credit_card_form.form_data); ASSERT_TRUE(form_manager_to_save); EXPECT_THAT(form_manager_to_save->GetPendingCredentials(), FormMatches(credit_card_form)); @@ -3677,7 +3713,7 @@ for (size_t i = 0; i < 2; i++) { PasswordForm form(MakeSimpleForm()); manager()->OnPasswordFormsParsed(&driver_, {form.form_data}); - manager()->ShowManualFallbackForSaving(&driver_, form.form_data); + manager()->OnInformAboutUserInput(&driver_, form.form_data); manager()->DidNavigateMainFrame(true /* form_may_be_submitted */); manager()->OnPasswordFormsRendered(&driver_, {} /* observed */, @@ -3708,8 +3744,8 @@ PasswordForm form2(MakeSimpleForm()); manager()->OnPasswordFormsParsed(&driver_, {form1.form_data, form2.form_data}); - manager()->ShowManualFallbackForSaving(&driver_, form1.form_data); - manager()->ShowManualFallbackForSaving(&driver_, form2.form_data); + manager()->OnInformAboutUserInput(&driver_, form1.form_data); + manager()->OnInformAboutUserInput(&driver_, form2.form_data); // Simulate submission in different ways depending on whether // |owned_submitted_form_manager_| should be set and |form_managers_| should
diff --git a/components/password_manager/core/browser/ui/insecure_credentials_manager.cc b/components/password_manager/core/browser/ui/insecure_credentials_manager.cc index e55f03da..313695e7 100644 --- a/components/password_manager/core/browser/ui/insecure_credentials_manager.cc +++ b/components/password_manager/core/browser/ui/insecure_credentials_manager.cc
@@ -8,13 +8,16 @@ #include <iterator> #include <set> +#include "base/bind.h" #include "base/containers/flat_set.h" #include "base/strings/string16.h" #include "base/strings/utf_string_conversions.h" +#include "base/task/post_task.h" #include "components/autofill/core/common/password_form.h" #include "components/password_manager/core/browser/compromised_credentials_table.h" #include "components/password_manager/core/browser/ui/credential_utils.h" #include "components/password_manager/core/browser/ui/saved_passwords_presenter.h" +#include "components/password_manager/core/browser/ui/weak_check_utility.h" #include "components/password_manager/core/common/password_manager_features.h" namespace password_manager { @@ -64,12 +67,13 @@ NOTREACHED(); } -// This function takes two lists of insecure credentials and saved passwords and -// joins them, producing a map that contains CredentialWithPassword as keys and -// vector<autofill::PasswordForm> as values with InsecureCredentialTypeFlags as -// values. +// This function takes three lists of compromised credentials, weak passwords +// and saved passwords and joins them, producing a map that contains +// CredentialWithPassword as keys and vector<autofill::PasswordForm> as values +// with InsecureCredentialTypeFlags as values. CredentialPasswordsMap JoinInsecureCredentialsWithSavedPasswords( - const std::vector<CompromisedCredentials>& credentials, + const std::vector<CompromisedCredentials>& compromised_credentials, + const base::flat_set<base::string16>& weak_passwords, SavedPasswordsPresenter::SavedPasswordsView saved_passwords) { CredentialPasswordsMap credentials_to_forms; @@ -96,7 +100,7 @@ // size of 1, however. std::multiset<autofill::PasswordForm, CredentialWithoutPasswordLess> password_forms(saved_passwords.begin(), saved_passwords.end()); - for (const auto& credential : credentials) { + for (const auto& credential : compromised_credentials) { auto range = password_forms.equal_range(credential); // Make use of a set to only filter out repeated passwords, if any. std::for_each( @@ -106,8 +110,7 @@ credentials_to_forms[compromised_credential]; // Using |= operator to save in a bit mask both Leaked and Phished. - credential_to_form.type = - credential_to_form.type | + credential_to_form.type |= ConvertCompromiseType(credential.compromise_type); // Use the latest time. Relevant when the same credential is both @@ -122,18 +125,35 @@ }); } + for (const auto& form : saved_passwords) { + if (weak_passwords.contains(form.password_value)) { + CredentialView weak_credential(form); + auto& credential_to_form = credentials_to_forms[weak_credential]; + credential_to_form.type |= InsecureCredentialTypeFlags::kWeakCredential; + + // This helps not to create a copy of the |form| in case the credential + // has also been compromised. This is important because we don't want to + // delete the form twice in the RemoveCredential. + if (!IsCompromised(credential_to_form.type)) { + credential_to_form.forms.push_back(form); + } + } + } + return credentials_to_forms; } -std::vector<CredentialWithPassword> ExtractCompromisedCredentials( - const CredentialPasswordsMap& credentials_to_forms) { +std::vector<CredentialWithPassword> ExtractInsecureCredentials( + const CredentialPasswordsMap& credentials_to_forms, + bool (*condition)(const InsecureCredentialTypeFlags&)) { std::vector<CredentialWithPassword> credentials; - credentials.reserve(credentials_to_forms.size()); for (const auto& credential_to_forms : credentials_to_forms) { - CredentialWithPassword credential(credential_to_forms.first); - credential.insecure_type = credential_to_forms.second.type; - credential.create_time = credential_to_forms.second.latest_time; - credentials.push_back(std::move(credential)); + if (condition(credential_to_forms.second.type)) { + CredentialWithPassword credential(credential_to_forms.first); + credential.insecure_type = credential_to_forms.second.type; + credential.create_time = credential_to_forms.second.latest_time; + credentials.push_back(std::move(credential)); + } } return credentials; } @@ -205,6 +225,14 @@ compromised_credentials_reader_.Init(); } +void InsecureCredentialsManager::StartWeakCheck() { + base::ThreadPool::PostTaskAndReplyWithResult( + FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE}, + base::BindOnce(&BulkWeakCheck, presenter_->GetSavedPasswords()), + base::BindOnce(&InsecureCredentialsManager::OnWeakCheckDone, + weak_ptr_factory_.GetWeakPtr())); +} + void InsecureCredentialsManager::SaveCompromisedCredential( const LeakCheckCredential& credential) { // Iterate over all currently saved credentials and mark those as compromised @@ -265,7 +293,12 @@ std::vector<CredentialWithPassword> InsecureCredentialsManager::GetCompromisedCredentials() const { - return ExtractCompromisedCredentials(credentials_to_forms_); + return ExtractInsecureCredentials(credentials_to_forms_, &IsCompromised); +} + +std::vector<CredentialWithPassword> +InsecureCredentialsManager::GetWeakCredentials() const { + return ExtractInsecureCredentials(credentials_to_forms_, &IsWeak); } SavedPasswordsPresenter::SavedPasswordsView @@ -285,29 +318,51 @@ observers_.RemoveObserver(observer); } +void InsecureCredentialsManager::OnWeakCheckDone( + base::flat_set<base::string16> weak_passwords) { + weak_passwords_ = std::move(weak_passwords); + + credentials_to_forms_ = JoinInsecureCredentialsWithSavedPasswords( + compromised_credentials_, weak_passwords_, + presenter_->GetSavedPasswords()); + NotifyWeakCredentialsChanged(); +} + // Re-computes the list of compromised credentials with passwords after // obtaining a new list of compromised credentials. void InsecureCredentialsManager::OnCompromisedCredentialsChanged( const std::vector<CompromisedCredentials>& compromised_credentials) { compromised_credentials_ = compromised_credentials; - UpdateCachedDataAndNotifyObservers(presenter_->GetSavedPasswords()); + + credentials_to_forms_ = JoinInsecureCredentialsWithSavedPasswords( + compromised_credentials_, weak_passwords_, + presenter_->GetSavedPasswords()); + NotifyCompromisedCredentialsChanged(); } // Re-computes the list of insecure credentials with passwords after obtaining a // new list of saved passwords. void InsecureCredentialsManager::OnSavedPasswordsChanged( SavedPasswordsPresenter::SavedPasswordsView saved_passwords) { - UpdateCachedDataAndNotifyObservers(saved_passwords); + credentials_to_forms_ = JoinInsecureCredentialsWithSavedPasswords( + compromised_credentials_, weak_passwords_, saved_passwords); + NotifyCompromisedCredentialsChanged(); + NotifyWeakCredentialsChanged(); } -void InsecureCredentialsManager::UpdateCachedDataAndNotifyObservers( - SavedPasswordsPresenter::SavedPasswordsView saved_passwords) { - credentials_to_forms_ = JoinInsecureCredentialsWithSavedPasswords( - compromised_credentials_, saved_passwords); - std::vector<CredentialWithPassword> credentials = - ExtractCompromisedCredentials(credentials_to_forms_); +void InsecureCredentialsManager::NotifyCompromisedCredentialsChanged() { + std::vector<CredentialWithPassword> compromised_credentials = + ExtractInsecureCredentials(credentials_to_forms_, &IsCompromised); for (auto& observer : observers_) { - observer.OnCompromisedCredentialsChanged(credentials); + observer.OnCompromisedCredentialsChanged(compromised_credentials); + } +} + +void InsecureCredentialsManager::NotifyWeakCredentialsChanged() { + std::vector<CredentialWithPassword> weak_credentials = + ExtractInsecureCredentials(credentials_to_forms_, &IsWeak); + for (auto& observer : observers_) { + observer.OnWeakCredentialsChanged(weak_credentials); } }
diff --git a/components/password_manager/core/browser/ui/insecure_credentials_manager.h b/components/password_manager/core/browser/ui/insecure_credentials_manager.h index 9a823daa..b0a3817 100644 --- a/components/password_manager/core/browser/ui/insecure_credentials_manager.h +++ b/components/password_manager/core/browser/ui/insecure_credentials_manager.h
@@ -8,6 +8,7 @@ #include <map> #include <vector> +#include "base/containers/flat_set.h" #include "base/containers/span.h" #include "base/memory/scoped_refptr.h" #include "base/observer_list.h" @@ -37,6 +38,13 @@ kWeakCredential = 1 << 2, }; +constexpr InsecureCredentialTypeFlags operator&( + InsecureCredentialTypeFlags lhs, + InsecureCredentialTypeFlags rhs) { + return static_cast<InsecureCredentialTypeFlags>(static_cast<int>(lhs) & + static_cast<int>(rhs)); +} + constexpr InsecureCredentialTypeFlags operator|( InsecureCredentialTypeFlags lhs, InsecureCredentialTypeFlags rhs) { @@ -44,6 +52,26 @@ static_cast<int>(rhs)); } +constexpr InsecureCredentialTypeFlags& operator|=( + InsecureCredentialTypeFlags& lhs, + InsecureCredentialTypeFlags rhs) { + lhs = lhs | rhs; + return lhs; +} + +// Checks that |flag| contains at least one of compromised types. +constexpr bool IsCompromised(const InsecureCredentialTypeFlags& flag) { + return (flag & (InsecureCredentialTypeFlags::kCredentialLeaked | + InsecureCredentialTypeFlags::kCredentialPhished)) != + InsecureCredentialTypeFlags::kSecure; +} + +// Checks that |flag| contains weak type. +constexpr bool IsWeak(const InsecureCredentialTypeFlags& flag) { + return (flag & InsecureCredentialTypeFlags::kWeakCredential) != + InsecureCredentialTypeFlags::kSecure; +} + // Simple struct that augments key values of InsecureCredentials and a password. struct CredentialView { CredentialView(std::string signon_realm, @@ -125,6 +153,10 @@ void Init(); + // Computes weak credentials in a separate thread and then passes the result + // to OnWeakCheckDone. + void StartWeakCheck(); + // Marks all saved credentials which have same username & password as // compromised. void SaveCompromisedCredential(const LeakCheckCredential& credential); @@ -141,6 +173,9 @@ // Returns a vector of currently compromised credentials. std::vector<CredentialWithPassword> GetCompromisedCredentials() const; + // Returns a vector of currently weak credentials. + std::vector<CredentialWithPassword> GetWeakCredentials() const; + // Returns password forms which map to provided insecure credential. // In most of the cases vector will have 1 element only. SavedPasswordsPresenter::SavedPasswordsView GetSavedPasswordsFor( @@ -154,6 +189,10 @@ using CredentialPasswordsMap = std::map<CredentialView, CredentialMetadata, PasswordCredentialLess>; + // Updates |weak_passwords| set and notifies observers that weak credentials + // were changed. + void OnWeakCheckDone(base::flat_set<base::string16> weak_passwords); + // CompromisedCredentialsReader::Observer: void OnCompromisedCredentialsChanged( const std::vector<CompromisedCredentials>& compromised_credentials) @@ -163,9 +202,11 @@ void OnSavedPasswordsChanged( SavedPasswordsPresenter::SavedPasswordsView passwords) override; - // Function to update |credentials_to_forms_| and notify observers. - void UpdateCachedDataAndNotifyObservers( - SavedPasswordsPresenter::SavedPasswordsView saved_passwords); + // Notifies observers when compromised credentials have changed. + void NotifyCompromisedCredentialsChanged(); + + // Notifies observers when weak credentials have changed. + void NotifyWeakCredentialsChanged(); // Returns the `profile_store_` or `account_store_` if `form` is stored in the // profile store of the account store accordingly. @@ -186,6 +227,9 @@ // Cache of the most recently obtained compromised credentials. std::vector<CompromisedCredentials> compromised_credentials_; + // Cache of the most recently obtained weak passwords. + base::flat_set<base::string16> weak_passwords_; + // A map that matches CredentialView to corresponding PasswordForms, latest // create_type and combined insecure type. CredentialPasswordsMap credentials_to_forms_; @@ -201,6 +245,8 @@ observed_saved_password_presenter_{this}; base::ObserverList<Observer, /*check_empty=*/true> observers_; + + base::WeakPtrFactory<InsecureCredentialsManager> weak_ptr_factory_{this}; }; } // namespace password_manager
diff --git a/components/password_manager/core/browser/ui/insecure_credentials_manager_unittest.cc b/components/password_manager/core/browser/ui/insecure_credentials_manager_unittest.cc index 170a752..22fa6c1 100644 --- a/components/password_manager/core/browser/ui/insecure_credentials_manager_unittest.cc +++ b/components/password_manager/core/browser/ui/insecure_credentials_manager_unittest.cc
@@ -29,6 +29,11 @@ constexpr char kPassword2[] = "s3cr3t"; constexpr char kPassword3[] = "484her"; +constexpr char kWeakPassword1[] = "123456"; +constexpr char kWeakPassword2[] = "abcdabcdabcdabcdabcdabcdabcdabcdabcdabcda"; +constexpr char kStrongPassword1[] = "fnlsr4@cm^mdls@fkspnsg3d"; +constexpr char kStrongPassword2[] = "pmsFlsnoab4nsl#losb@skpfnsbkjb^klsnbs!cns"; + using autofill::PasswordForm; using ::testing::ElementsAre; using ::testing::ElementsAreArray; @@ -84,11 +89,11 @@ return credential_with_password; } -class CompromisedCredentialsManagerTest : public ::testing::Test { +class InsecureCredentialsManagerTest : public ::testing::Test { protected: - CompromisedCredentialsManagerTest() { store_->Init(/*prefs=*/nullptr); } + InsecureCredentialsManagerTest() { store_->Init(/*prefs=*/nullptr); } - ~CompromisedCredentialsManagerTest() override { + ~InsecureCredentialsManagerTest() override { store_->ShutdownOnUIThread(); task_env_.RunUntilIdle(); } @@ -99,8 +104,8 @@ void RunUntilIdle() { task_env_.RunUntilIdle(); } private: - base::test::SingleThreadTaskEnvironment task_env_{ - base::test::SingleThreadTaskEnvironment::TimeSource::MOCK_TIME}; + base::test::TaskEnvironment task_env_{ + base::test::TaskEnvironment::TimeSource::MOCK_TIME}; scoped_refptr<TestPasswordStore> store_ = base::MakeRefCounted<TestPasswordStore>(); SavedPasswordsPresenter presenter_{store_}; @@ -127,7 +132,7 @@ } // Tests whether adding and removing an observer works as expected. -TEST_F(CompromisedCredentialsManagerTest, +TEST_F(InsecureCredentialsManagerTest, NotifyObserversAboutCompromisedCredentialChanges) { std::vector<CompromisedCredentials> credentials = { MakeCompromised(kExampleCom, kUsername1)}; @@ -172,7 +177,7 @@ // Tests removing a compromised credentials by compromise type triggers an // observer works as expected. -TEST_F(CompromisedCredentialsManagerTest, +TEST_F(InsecureCredentialsManagerTest, NotifyObserversAboutRemovingCompromisedCredentialsByCompromisedType) { CompromisedCredentials phished_credentials = MakeCompromised(kExampleCom, kUsername1, CompromiseType::kPhished); @@ -206,7 +211,7 @@ } // Tests whether adding and removing an observer works as expected. -TEST_F(CompromisedCredentialsManagerTest, +TEST_F(InsecureCredentialsManagerTest, NotifyObserversAboutSavedPasswordsChanges) { StrictMockInsecureCredentialsManagerObserver observer; provider().AddObserver(&observer); @@ -239,7 +244,7 @@ // Tests that the provider is able to join a single password with a compromised // credential. -TEST_F(CompromisedCredentialsManagerTest, JoinSingleCredentials) { +TEST_F(InsecureCredentialsManagerTest, JoinSingleCredentials) { PasswordForm password = MakeSavedPassword(kExampleCom, kUsername1, kPassword1); CompromisedCredentials credential = MakeCompromised(kExampleCom, kUsername1); @@ -256,7 +261,7 @@ // Tests that the provider is able to join a password with a credential that was // compromised in multiple ways. -TEST_F(CompromisedCredentialsManagerTest, JoinPhishedAndLeaked) { +TEST_F(InsecureCredentialsManagerTest, JoinPhishedAndLeaked) { PasswordForm password = MakeSavedPassword(kExampleCom, kUsername1, kPassword1); CompromisedCredentials leaked = @@ -279,7 +284,7 @@ // Tests that the provider reacts whenever the saved passwords or the // compromised credentials change. -TEST_F(CompromisedCredentialsManagerTest, ReactToChangesInBothTables) { +TEST_F(InsecureCredentialsManagerTest, ReactToChangesInBothTables) { std::vector<PasswordForm> passwords = { MakeSavedPassword(kExampleCom, kUsername1, kPassword1), MakeSavedPassword(kExampleCom, kUsername2, kPassword2)}; @@ -320,7 +325,7 @@ // Tests that the provider is able to join multiple passwords with compromised // credentials. -TEST_F(CompromisedCredentialsManagerTest, JoinMultipleCredentials) { +TEST_F(InsecureCredentialsManagerTest, JoinMultipleCredentials) { std::vector<PasswordForm> passwords = { MakeSavedPassword(kExampleCom, kUsername1, kPassword1), MakeSavedPassword(kExampleCom, kUsername2, kPassword2)}; @@ -346,7 +351,7 @@ // Tests that joining a compromised credential with saved passwords with a // different username results in an empty list. -TEST_F(CompromisedCredentialsManagerTest, JoinWitDifferentUsername) { +TEST_F(InsecureCredentialsManagerTest, JoinWitDifferentUsername) { std::vector<PasswordForm> passwords = { MakeSavedPassword(kExampleCom, kUsername2, kPassword1), MakeSavedPassword(kExampleCom, kUsername2, kPassword2)}; @@ -363,7 +368,7 @@ // Tests that joining a compromised credential with saved passwords with a // matching username but different signon_realm results in an empty list. -TEST_F(CompromisedCredentialsManagerTest, JoinWitDifferentSignonRealm) { +TEST_F(InsecureCredentialsManagerTest, JoinWitDifferentSignonRealm) { std::vector<PasswordForm> passwords = { MakeSavedPassword(kExampleOrg, kUsername1, kPassword1), MakeSavedPassword(kExampleOrg, kUsername1, kPassword2)}; @@ -381,7 +386,7 @@ // Tests that joining a compromised credential with multiple saved passwords for // the same signon_realm and username combination results in multiple entries // when the passwords are distinct. -TEST_F(CompromisedCredentialsManagerTest, JoinWithMultipleDistinctPasswords) { +TEST_F(InsecureCredentialsManagerTest, JoinWithMultipleDistinctPasswords) { std::vector<PasswordForm> passwords = { MakeSavedPassword(kExampleCom, kUsername1, kPassword1, "element_1"), MakeSavedPassword(kExampleCom, kUsername1, kPassword2, "element_2")}; @@ -405,7 +410,7 @@ // Tests that joining a compromised credential with multiple saved passwords for // the same signon_realm and username combination results in a single entry // when the passwords are the same. -TEST_F(CompromisedCredentialsManagerTest, JoinWithMultipleRepeatedPasswords) { +TEST_F(InsecureCredentialsManagerTest, JoinWithMultipleRepeatedPasswords) { CompromisedCredentials credential = MakeCompromised(kExampleCom, kUsername1); std::vector<PasswordForm> passwords = { MakeSavedPassword(kExampleCom, kUsername1, kPassword1, "element_1"), @@ -424,7 +429,7 @@ // Tests that verifies mapping compromised credentials to passwords works // correctly. -TEST_F(CompromisedCredentialsManagerTest, MapCompromisedPasswordsToPasswords) { +TEST_F(InsecureCredentialsManagerTest, MapCompromisedPasswordsToPasswords) { std::vector<PasswordForm> passwords = { MakeSavedPassword(kExampleCom, kUsername1, kPassword1, "element_1"), MakeSavedPassword(kExampleCom, kUsername1, kPassword1, "element_2"), @@ -456,9 +461,159 @@ ElementsAreArray(store().stored_passwords().at(kExampleOrg))); } +TEST_F(InsecureCredentialsManagerTest, WeakCredentialsNotFound) { + std::vector<PasswordForm> passwords = { + MakeSavedPassword(kExampleCom, kUsername1, kStrongPassword1), + MakeSavedPassword(kExampleCom, kUsername2, kStrongPassword2)}; + + store().AddLogin(passwords[0]); + store().AddLogin(passwords[1]); + + RunUntilIdle(); + provider().StartWeakCheck(); + RunUntilIdle(); + + EXPECT_THAT(provider().GetWeakCredentials(), IsEmpty()); +} + +TEST_F(InsecureCredentialsManagerTest, DetectedWeakCredential) { + std::vector<PasswordForm> passwords = { + MakeSavedPassword(kExampleCom, kUsername1, kWeakPassword1), + MakeSavedPassword(kExampleCom, kUsername2, kStrongPassword1)}; + + store().AddLogin(passwords[0]); + store().AddLogin(passwords[1]); + + RunUntilIdle(); + provider().StartWeakCheck(); + RunUntilIdle(); + + std::vector<CredentialWithPassword> weak_credentials = + provider().GetWeakCredentials(); + + ASSERT_EQ(weak_credentials.size(), 1u); + EXPECT_EQ(base::UTF16ToUTF8(weak_credentials[0].password), kWeakPassword1); + EXPECT_TRUE(IsWeak(weak_credentials[0].insecure_type)); +} + +// Tests that credentials with the same signon_realm and username, but different +// passwords will be both returned by GetWeakCredentials(). +TEST_F(InsecureCredentialsManagerTest, + FindBothWeakCredentialsWithDifferentPasswords) { + std::vector<PasswordForm> passwords = { + MakeSavedPassword(kExampleCom, kUsername1, kWeakPassword1, "element_1"), + MakeSavedPassword(kExampleCom, kUsername1, kWeakPassword2, "element_2")}; + + store().AddLogin(passwords[0]); + store().AddLogin(passwords[1]); + + RunUntilIdle(); + provider().StartWeakCheck(); + RunUntilIdle(); + + std::vector<CredentialWithPassword> weak_credentials = + provider().GetWeakCredentials(); + + ASSERT_EQ(weak_credentials.size(), 2u); + EXPECT_TRUE(IsWeak(weak_credentials[0].insecure_type)); + EXPECT_TRUE(IsWeak(weak_credentials[1].insecure_type)); +} + +// Tests that credentials with the same signon_realm, username and passwords +// will be joind and GetWeakCredentials() will return one credential. +TEST_F(InsecureCredentialsManagerTest, + JoinWeakCredentialsWithTheSamePasswords) { + std::vector<PasswordForm> passwords = { + MakeSavedPassword(kExampleCom, kUsername1, kWeakPassword1, "element_1"), + MakeSavedPassword(kExampleCom, kUsername1, kWeakPassword1, "element_2")}; + + store().AddLogin(passwords[0]); + store().AddLogin(passwords[1]); + + RunUntilIdle(); + provider().StartWeakCheck(); + RunUntilIdle(); + + std::vector<CredentialWithPassword> weak_credentials = + provider().GetWeakCredentials(); + + ASSERT_EQ(weak_credentials.size(), 1u); + EXPECT_EQ(base::UTF16ToUTF8(weak_credentials[0].password), kWeakPassword1); + EXPECT_TRUE(IsWeak(weak_credentials[0].insecure_type)); +} + +TEST_F(InsecureCredentialsManagerTest, BothWeakAndCompromisedCredentialsExist) { + std::vector<PasswordForm> passwords = { + MakeSavedPassword(kExampleCom, kUsername1, kWeakPassword1), + MakeSavedPassword(kExampleCom, kUsername2, kStrongPassword1)}; + std::vector<CompromisedCredentials> compromised_credentials = { + MakeCompromised(kExampleCom, kUsername1), + MakeCompromised(kExampleCom, kUsername2)}; + + store().AddLogin(passwords[0]); + store().AddLogin(passwords[1]); + store().AddCompromisedCredentials(compromised_credentials[0]); + store().AddCompromisedCredentials(compromised_credentials[1]); + + RunUntilIdle(); + provider().StartWeakCheck(); + RunUntilIdle(); + + std::vector<CredentialWithPassword> returned_weak_credentials = + provider().GetWeakCredentials(); + std::vector<CredentialWithPassword> returned_compromised_credentials = + provider().GetCompromisedCredentials(); + + ASSERT_EQ(returned_weak_credentials.size(), 1u); + EXPECT_EQ(base::UTF16ToUTF8(returned_weak_credentials[0].password), + kWeakPassword1); + EXPECT_TRUE(IsWeak(returned_weak_credentials[0].insecure_type)); + + ASSERT_EQ(returned_compromised_credentials.size(), 2u); + EXPECT_TRUE(IsCompromised(returned_compromised_credentials[0].insecure_type)); + EXPECT_TRUE(IsCompromised(returned_compromised_credentials[1].insecure_type)); +} + +// Checks that for a credential that is both weak and compromised, +// getWeakCredentials and GetCompromisedCredentials will return this credential +// in one instance. +TEST_F(InsecureCredentialsManagerTest, SingleCredentialIsWeakAndCompromised) { + std::vector<PasswordForm> passwords = { + MakeSavedPassword(kExampleCom, kUsername1, kWeakPassword1)}; + std::vector<CompromisedCredentials> compromised_credentials = { + MakeCompromised(kExampleCom, kUsername1)}; + + store().AddLogin(passwords[0]); + store().AddCompromisedCredentials(compromised_credentials[0]); + + RunUntilIdle(); + provider().StartWeakCheck(); + RunUntilIdle(); + + std::vector<CredentialWithPassword> returned_weak_credentials = + provider().GetWeakCredentials(); + std::vector<CredentialWithPassword> returned_compromised_credentials = + provider().GetCompromisedCredentials(); + + // Since the credential is weak and compromised, the |insecure_type| should be + // weak and compromised for elements from |returned_weak_credentials| and + // |returned_compromised_credentials|. + ASSERT_EQ(returned_weak_credentials.size(), 1u); + EXPECT_EQ(base::UTF16ToUTF8(returned_weak_credentials[0].password), + kWeakPassword1); + EXPECT_TRUE(IsWeak(returned_weak_credentials[0].insecure_type)); + EXPECT_TRUE(IsCompromised(returned_weak_credentials[0].insecure_type)); + + ASSERT_EQ(returned_compromised_credentials.size(), 1u); + EXPECT_EQ(base::UTF16ToUTF8(returned_compromised_credentials[0].password), + kWeakPassword1); + EXPECT_TRUE(IsWeak(returned_compromised_credentials[0].insecure_type)); + EXPECT_TRUE(IsCompromised(returned_compromised_credentials[0].insecure_type)); +} + // Test verifies that saving LeakCheckCredential via provider adds expected // compromised credential. -TEST_F(CompromisedCredentialsManagerTest, SaveCompromisedPassword) { +TEST_F(InsecureCredentialsManagerTest, SaveCompromisedPassword) { PasswordForm password_form = MakeSavedPassword(kExampleCom, kUsername1, kPassword1); LeakCheckCredential credential = MakeLeakCredential(kUsername1, kPassword1); @@ -480,7 +635,7 @@ // Test verifies that editing Compromised Credential via provider change the // original password form. -TEST_F(CompromisedCredentialsManagerTest, UpdateCompromisedPassword) { +TEST_F(InsecureCredentialsManagerTest, UpdateCompromisedPassword) { PasswordForm password_form = MakeSavedPassword(kExampleCom, kUsername1, kPassword1); CompromisedCredentials credential = MakeCompromised(kExampleCom, kUsername1); @@ -499,7 +654,7 @@ EXPECT_THAT(provider().GetCompromisedCredentials(), ElementsAre(expected)); } -TEST_F(CompromisedCredentialsManagerTest, RemoveCompromisedCredential) { +TEST_F(InsecureCredentialsManagerTest, RemoveCompromisedCredential) { CompromisedCredentials credential = MakeCompromised(kExampleCom, kUsername1); PasswordForm password = MakeSavedPassword(kExampleCom, kUsername1, kPassword1); @@ -520,14 +675,14 @@ } namespace { -class CompromisedCredentialsManagerWithTwoStoresTest : public ::testing::Test { +class InsecureCredentialsManagerWithTwoStoresTest : public ::testing::Test { protected: - CompromisedCredentialsManagerWithTwoStoresTest() { + InsecureCredentialsManagerWithTwoStoresTest() { profile_store_->Init(/*prefs=*/nullptr); account_store_->Init(/*prefs=*/nullptr); } - ~CompromisedCredentialsManagerWithTwoStoresTest() override { + ~InsecureCredentialsManagerWithTwoStoresTest() override { account_store_->ShutdownOnUIThread(); profile_store_->ShutdownOnUIThread(); task_env_.RunUntilIdle(); @@ -553,7 +708,7 @@ // Tests that verifies mapping compromised credentials to passwords works // correctly. -TEST_F(CompromisedCredentialsManagerWithTwoStoresTest, +TEST_F(InsecureCredentialsManagerWithTwoStoresTest, MapCompromisedPasswordsToPasswords) { // Add credentials for both `kExampleCom` and `kExampleOrg` in both stores // with the same username and difference passwords. For `kUsername1`, the @@ -607,8 +762,7 @@ // Test verifies that saving LeakCheckCredential via provider adds expected // compromised credential to the correct store. -TEST_F(CompromisedCredentialsManagerWithTwoStoresTest, - SaveCompromisedPassword) { +TEST_F(InsecureCredentialsManagerWithTwoStoresTest, SaveCompromisedPassword) { ASSERT_TRUE(profile_store().compromised_credentials().empty()); ASSERT_TRUE(account_store().compromised_credentials().empty()); // Add `kUsername1`,`kPassword1` to both stores. @@ -642,7 +796,7 @@ EXPECT_EQ(2U, account_store().compromised_credentials().size()); } -TEST_F(CompromisedCredentialsManagerWithTwoStoresTest, +TEST_F(InsecureCredentialsManagerWithTwoStoresTest, RemoveCompromisedCredential) { // Add `kUsername1`,`kPassword1` to both stores. profile_store().AddLogin(
diff --git a/components/password_manager/core/browser/ui/weak_check_utility.cc b/components/password_manager/core/browser/ui/weak_check_utility.cc new file mode 100644 index 0000000..7401c3c --- /dev/null +++ b/components/password_manager/core/browser/ui/weak_check_utility.cc
@@ -0,0 +1,73 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/password_manager/core/browser/ui/weak_check_utility.h" + +#include "base/strings/utf_string_conversions.h" +#include "third_party/zxcvbn-cpp/native-src/zxcvbn/matching.hpp" +#include "third_party/zxcvbn-cpp/native-src/zxcvbn/scoring.hpp" +#include "third_party/zxcvbn-cpp/native-src/zxcvbn/time_estimates.hpp" + +namespace password_manager { + +namespace { + +// Passwords longer than this constant should not be checked for weakness using +// the zxcvbn-cpp library. This is because the runtime grows extremely, starting +// at a password length of 40. +// See https://github.com/dropbox/zxcvbn#runtime-latency +// Needs to stay in sync with google3 constant: http://shortn/_1ufIF61G4X +constexpr int kZxcvbnLengthCap = 40; + +// If the password has a score of 2 or less, this password should be marked as +// weak. The lower the password score, the weaker it is. +constexpr int kHighSeverityScore = 0; +constexpr int kLowSeverityScore = 2; + +constexpr int kStrongPasswordScore = 4; + +// Very rough, extremely simplified strength check that only makes sense for +// long passwords. +int SimpleLongPasswordStrengthEstimate(const base::string16& password) { + base::flat_set<base::char16> chars; + + for (auto character : password) { + chars.insert(character); + if (chars.size() > 4) { + return kStrongPasswordScore; + } + } + return kHighSeverityScore; +} + +// Returns the |password| score. +int PasswordWeakCheck(const base::string16& password) { + // zxcvbn's computation time explodes for long passwords, so don't use it for + // those. + if (password.size() > kZxcvbnLengthCap) { + return SimpleLongPasswordStrengthEstimate(password); + } + std::vector<zxcvbn::Match> matches = + zxcvbn::omnimatch(base::UTF16ToUTF8(password)); + zxcvbn::ScoringResult result = zxcvbn::most_guessable_match_sequence( + base::UTF16ToUTF8(password), matches); + return zxcvbn::estimate_attack_times(result.guesses).score; +} + +} // namespace + +base::flat_set<base::string16> BulkWeakCheck( + SavedPasswordsPresenter::SavedPasswordsView saved_passwords) { + std::vector<base::string16> weak_passwords; + + for (const auto& password : saved_passwords) { + if (PasswordWeakCheck(password.password_value) <= kLowSeverityScore) { + weak_passwords.push_back(password.password_value); + } + } + + return base::flat_set<base::string16>(std::move(weak_passwords)); +} + +} // namespace password_manager
diff --git a/components/password_manager/core/browser/ui/weak_check_utility.h b/components/password_manager/core/browser/ui/weak_check_utility.h new file mode 100644 index 0000000..c976b88 --- /dev/null +++ b/components/password_manager/core/browser/ui/weak_check_utility.h
@@ -0,0 +1,20 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_UI_WEAK_CHECK_UTILITY_H_ +#define COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_UI_WEAK_CHECK_UTILITY_H_ + +#include "base/containers/flat_set.h" +#include "base/strings/string16.h" +#include "components/password_manager/core/browser/ui/saved_passwords_presenter.h" + +namespace password_manager { + +// Checks each password for weakness. +base::flat_set<base::string16> BulkWeakCheck( + SavedPasswordsPresenter::SavedPasswordsView passwords); + +} // namespace password_manager + +#endif // COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_UI_WEAK_CHECK_UTILITY_H_
diff --git a/components/password_manager/core/browser/ui/weak_check_utility_unittest.cc b/components/password_manager/core/browser/ui/weak_check_utility_unittest.cc new file mode 100644 index 0000000..8352a150 --- /dev/null +++ b/components/password_manager/core/browser/ui/weak_check_utility_unittest.cc
@@ -0,0 +1,74 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/password_manager/core/browser/ui/weak_check_utility.h" + +#include <vector> +#include "base/strings/utf_string_conversions.h" +#include "components/autofill/core/common/password_form.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace password_manager { + +namespace { + +constexpr char kUsername1[] = "alice"; +constexpr char kUsername2[] = "bob"; + +constexpr char kWeakShortPassword[] = "123456"; +constexpr char kWeakLongPassword[] = + "abcdabcdabcdabcdabcdabcdabcdabcdabcdabcda"; +constexpr char kStrongShortPassword[] = "fnlsr4@cm^mdls@fkspnsg3d"; +constexpr char kStrongLongPassword[] = + "pmsFlsnoab4nsl#losb@skpfnsbkjb^klsnbs!cns"; + +using autofill::PasswordForm; +using ::testing::ElementsAre; + +PasswordForm MakeSavedPassword(base::StringPiece username, + base::StringPiece password) { + PasswordForm form; + form.signon_realm = "https://example.com"; + form.username_value = base::ASCIIToUTF16(username); + form.password_value = base::ASCIIToUTF16(password); + return form; +} + +} // namespace + +TEST(WeakCheckUtilityTest, WeakPasswordsNotFound) { + std::vector<PasswordForm> passwords = { + MakeSavedPassword(kUsername1, kStrongShortPassword), + MakeSavedPassword(kUsername2, kStrongLongPassword)}; + + EXPECT_THAT(BulkWeakCheck(passwords), testing::IsEmpty()); +} + +TEST(WeakCheckUtilityTest, DetectedShortAndLongWeakPasswords) { + std::vector<PasswordForm> passwords = { + MakeSavedPassword(kUsername1, kStrongLongPassword), + MakeSavedPassword(kUsername1, kWeakShortPassword), + MakeSavedPassword(kUsername1, kStrongShortPassword), + MakeSavedPassword(kUsername2, kWeakLongPassword)}; + + base::flat_set<base::string16> weak_passwords = BulkWeakCheck(passwords); + + EXPECT_THAT(weak_passwords, + ElementsAre(base::ASCIIToUTF16(kWeakShortPassword), + base::ASCIIToUTF16(kWeakLongPassword))); +} + +TEST(WeakCheckUtilityTest, WeakPasswordsSetContainsNoCopies) { + std::vector<PasswordForm> passwords = { + MakeSavedPassword(kUsername1, kWeakShortPassword), + MakeSavedPassword(kUsername2, kWeakShortPassword)}; + + base::flat_set<base::string16> weak_passwords = BulkWeakCheck(passwords); + + EXPECT_THAT(weak_passwords, + ElementsAre(base::ASCIIToUTF16(kWeakShortPassword))); +} + +} // namespace password_manager
diff --git a/components/payments/content/android/java/src/org/chromium/components/payments/ComponentPaymentRequestImpl.java b/components/payments/content/android/java/src/org/chromium/components/payments/ComponentPaymentRequestImpl.java index 499abe1..7946ef4 100644 --- a/components/payments/content/android/java/src/org/chromium/components/payments/ComponentPaymentRequestImpl.java +++ b/components/payments/content/android/java/src/org/chromium/components/payments/ComponentPaymentRequestImpl.java
@@ -188,9 +188,9 @@ assert onClosedListener != null; WebContents webContents = WebContentsStatics.fromRenderFrameHost(renderFrameHost); - if (webContents == null) { - abortBeforeInstantiation(client, /*journeyLogger=*/null, ErrorStrings.NO_WEB_CONTENTS, - AbortReason.INVALID_DATA_FROM_RENDERER); + if (webContents == null || webContents.isDestroyed()) { + abortBeforeInstantiation(/*client=*/null, /*journeyLogger=*/null, + ErrorStrings.NO_WEB_CONTENTS, AbortReason.INVALID_DATA_FROM_RENDERER); return null; }
diff --git a/components/payments/content/android/java/src/org/chromium/components/payments/JourneyLogger.java b/components/payments/content/android/java/src/org/chromium/components/payments/JourneyLogger.java index 09ef3b5..d1e5c355 100644 --- a/components/payments/content/android/java/src/org/chromium/components/payments/JourneyLogger.java +++ b/components/payments/content/android/java/src/org/chromium/components/payments/JourneyLogger.java
@@ -20,7 +20,14 @@ private boolean mHasRecorded; + /** + * Creates the journey logger. + * @param isIncognito Whether the user profile is incognito. + * @param webContents The web contents where PaymentRequest API is invoked. Should not be null. + */ public JourneyLogger(boolean isIncognito, WebContents webContents) { + assert webContents != null; + assert !webContents.isDestroyed(); // Note that this pointer could leak the native object. The called must call destroy() to // ensure that the native object is destroyed. mJourneyLoggerAndroid = JourneyLoggerJni.get().initJourneyLoggerAndroid(
diff --git a/components/policy/core/browser/browser_policy_connector.cc b/components/policy/core/browser/browser_policy_connector.cc index adddd65..909751a 100644 --- a/components/policy/core/browser/browser_policy_connector.cc +++ b/components/policy/core/browser/browser_policy_connector.cc
@@ -135,6 +135,24 @@ return false; } +std::string BrowserPolicyConnector::GetDeviceManagementUrl() const { + base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); + if (command_line->HasSwitch(switches::kDeviceManagementUrl) && + IsCommandLineSwitchSupported()) + return command_line->GetSwitchValueASCII(switches::kDeviceManagementUrl); + else + return kDefaultDeviceManagementServerUrl; +} + +std::string BrowserPolicyConnector::GetRealtimeReportingUrl() const { + base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); + if (command_line->HasSwitch(switches::kRealtimeReportingUrl) && + IsCommandLineSwitchSupported()) + return command_line->GetSwitchValueASCII(switches::kRealtimeReportingUrl); + else + return kDefaultRealtimeReportingServerUrl; +} + // static bool BrowserPolicyConnector::IsNonEnterpriseUser(const std::string& username) { TRACE_EVENT0("browser", "BrowserPolicyConnector::IsNonEnterpriseUser"); @@ -166,24 +184,6 @@ } // static -std::string BrowserPolicyConnector::GetDeviceManagementUrl() { - base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); - if (command_line->HasSwitch(switches::kDeviceManagementUrl)) - return command_line->GetSwitchValueASCII(switches::kDeviceManagementUrl); - else - return kDefaultDeviceManagementServerUrl; -} - -// static -std::string BrowserPolicyConnector::GetRealtimeReportingUrl() { - base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); - if (command_line->HasSwitch(switches::kRealtimeReportingUrl)) - return command_line->GetSwitchValueASCII(switches::kRealtimeReportingUrl); - else - return kDefaultRealtimeReportingServerUrl; -} - -// static void BrowserPolicyConnector::RegisterPrefs(PrefRegistrySimple* registry) { registry->RegisterIntegerPref( policy_prefs::kUserPolicyRefreshRate,
diff --git a/components/policy/core/browser/browser_policy_connector.h b/components/policy/core/browser/browser_policy_connector.h index ccf1fdd..b635722e 100644 --- a/components/policy/core/browser/browser_policy_connector.h +++ b/components/policy/core/browser/browser_policy_connector.h
@@ -57,6 +57,12 @@ return device_management_service_.get(); } + // Returns the URL for the device management service endpoint. + std::string GetDeviceManagementUrl() const; + + // Returns the URL for the realtime reporting service endpoint. + std::string GetRealtimeReportingUrl() const; + // Check whether a user is known to be non-enterprise. Domains such as // gmail.com and googlemail.com are known to not be managed. Also returns // false if the username is empty. @@ -67,15 +73,12 @@ // with a nullptr. static void SetNonEnterpriseDomainForTesting(const char* domain); - // Returns the URL for the device management service endpoint. - static std::string GetDeviceManagementUrl(); - - // Returns the URL for the realtime reporting service endpoint. - static std::string GetRealtimeReportingUrl(); - // Registers refresh rate prefs. static void RegisterPrefs(PrefRegistrySimple* registry); + // Returns true if the command line switch of policy can be used. + virtual bool IsCommandLineSwitchSupported() const = 0; + protected: // Builds an uninitialized BrowserPolicyConnector. // Init() should be called to create and start the policy components.
diff --git a/components/policy/proto/device_management_backend.proto b/components/policy/proto/device_management_backend.proto index 1b8e86b..4b6dfaa49 100644 --- a/components/policy/proto/device_management_backend.proto +++ b/components/policy/proto/device_management_backend.proto
@@ -2926,6 +2926,8 @@ CRX_FETCH_URL_EMPTY = 25; CRX_FETCH_URL_INVALID = 26; + + OVERRIDDEN_BY_SETTINGS = 27; } // Stage of extension installing process. See InstallStageTracker::Stage for
diff --git a/components/prerender/browser/prerender_contents.h b/components/prerender/browser/prerender_contents.h index 49e92219..cb07ec2 100644 --- a/components/prerender/browser/prerender_contents.h +++ b/components/prerender/browser/prerender_contents.h
@@ -120,10 +120,8 @@ static Factory* CreateFactory(); - // Start rendering the contents in the prerendered state. If - // |is_control_group| is true, this will go through some of the mechanics of - // starting a prerender, without actually creating the RenderView. |bounds| - // indicates the rectangle that the prerendered page should be in. + // Starts rendering the contents in the prerendered state. + // |bounds| indicates the rectangle that the prerendered page should be in. // |session_storage_namespace| indicates the namespace that the prerendered // page should be part of. virtual void StartPrerendering(
diff --git a/components/signin/ios/browser/account_consistency_service_unittest.mm b/components/signin/ios/browser/account_consistency_service_unittest.mm index 4b97071..ba57fbd 100644 --- a/components/signin/ios/browser/account_consistency_service_unittest.mm +++ b/components/signin/ios/browser/account_consistency_service_unittest.mm
@@ -10,6 +10,7 @@ #include "base/bind.h" #include "base/bind_helpers.h" +#include "base/ios/ios_util.h" #include "base/test/bind_test_util.h" #import "base/test/ios/wait_util.h" #include "base/values.h" @@ -472,6 +473,13 @@ // signon realm returns with a X-Chrome-Manage-Accounts header with ADDSESSION // action. TEST_F(AccountConsistencyServiceTest, ChromeManageAccountsShowAddAccount) { +#if !TARGET_IPHONE_SIMULATOR + // TODO(crbug.com/1126746): Test is failing on iOS 12 device. + if (!base::ios::IsRunningOnOrLater(13, 0, 0)) { + return; + } +#endif + id delegate = [OCMockObject mockForProtocol:@protocol(ManageAccountsDelegate)]; [[delegate expect] onAddAccount];
diff --git a/components/signin/public/android/java/src/org/chromium/components/signin/identitymanager/IdentityManager.java b/components/signin/public/android/java/src/org/chromium/components/signin/identitymanager/IdentityManager.java index a25e4d5f..5f6552c 100644 --- a/components/signin/public/android/java/src/org/chromium/components/signin/identitymanager/IdentityManager.java +++ b/components/signin/public/android/java/src/org/chromium/components/signin/identitymanager/IdentityManager.java
@@ -146,7 +146,7 @@ } /** - * Looks up and returns information for account with given |email_address|. If the account + * Looks up and returns information for account with given |email|. If the account * cannot be found, return a null value. */ public @Nullable CoreAccountInfo
diff --git a/components/signin/public/android/java/src/org/chromium/components/signin/identitymanager/IdentityMutator.java b/components/signin/public/android/java/src/org/chromium/components/signin/identitymanager/IdentityMutator.java index b310b73..609b1af5 100644 --- a/components/signin/public/android/java/src/org/chromium/components/signin/identitymanager/IdentityMutator.java +++ b/components/signin/public/android/java/src/org/chromium/components/signin/identitymanager/IdentityMutator.java
@@ -37,7 +37,7 @@ } /** - * Marks the account with |account_id| as the primary account, and returns whether the operation + * Marks the account with |accountId| as the primary account, and returns whether the operation * succeeded or not. To succeed, this requires that: * - the account is known by the IdentityManager. * - setting the primary account is allowed,
diff --git a/components/strings/components_strings_or.xtb b/components/strings/components_strings_or.xtb index 7d87cef3..8662bd37 100644 --- a/components/strings/components_strings_or.xtb +++ b/components/strings/components_strings_or.xtb
@@ -114,6 +114,7 @@ <translation id="1380591466760231819">ଲେଟର୍ ଫୋଲ୍ଡ</translation> <translation id="138218114945450791">ହାଲୁକା ନୀଳ</translation> <translation id="1382194467192730611">ଆପଣଙ୍କର ଆଡିମିନିଷ୍ଟ୍ରେଟର୍ ଦ୍ୱାରା ଅନୁମତି ଦିଆଯାଇଥିବା USB ଡିଭାଇସ୍</translation> +<translation id="1386623374109090026">ଏନୋଟେସନଗୁଡ଼ିକ</translation> <translation id="139305205187523129"><ph name="HOST_NAME" /> କୌଣସି ଡାଟା ପଠାଇନାହିଁ।</translation> <translation id="1405567553485452995">ହାଲୁକା ସବୁଜ</translation> <translation id="1407135791313364759">ସବୁ ଖୋଲନ୍ତୁ</translation>
diff --git a/components/sync/base/pref_names.cc b/components/sync/base/pref_names.cc index bde36ba..4976db3 100644 --- a/components/sync/base/pref_names.cc +++ b/components/sync/base/pref_names.cc
@@ -45,7 +45,7 @@ // OS user selectable types. const char kSyncOsApps[] = "sync.os_apps"; const char kSyncOsPreferences[] = "sync.os_preferences"; -#endif +#endif // defined(OS_CHROMEOS) // Booleans specifying whether the user has selected to sync the following // user selectable types. @@ -134,6 +134,13 @@ const char kSyncDemographicsBirthYearOffset[] = "sync.demographics_birth_year_offset"; +#if defined(OS_ANDROID) +// Stores whether sync should no longer respect the state of master toggle for +// this user. +const char kSyncDecoupledFromAndroidMasterSync[] = + "sync.decoupled_from_master_sync"; +#endif // defined(OS_ANDROID) + } // namespace prefs } // namespace syncer
diff --git a/components/sync/base/pref_names.h b/components/sync/base/pref_names.h index 8e77052e..2884201 100644 --- a/components/sync/base/pref_names.h +++ b/components/sync/base/pref_names.h
@@ -23,7 +23,7 @@ extern const char kSyncAllOsTypes[]; extern const char kSyncOsApps[]; extern const char kSyncOsPreferences[]; -#endif +#endif // defined(OS_CHROMEOS) extern const char kSyncApps[]; extern const char kSyncAutofill[]; @@ -60,6 +60,10 @@ extern const char kSyncDemographics[]; extern const char kSyncDemographicsBirthYearOffset[]; +#if defined(OS_ANDROID) +extern const char kSyncDecoupledFromAndroidMasterSync[]; +#endif // defined(OS_ANDROID) + // These are not prefs, they are paths inside of kSyncDemographics. extern const char kSyncDemographics_BirthYearPath[]; extern const char kSyncDemographics_GenderPath[];
diff --git a/components/sync/base/sync_prefs.cc b/components/sync/base/sync_prefs.cc index ef07132e..6d0d1f3b 100644 --- a/components/sync/base/sync_prefs.cc +++ b/components/sync/base/sync_prefs.cc
@@ -288,6 +288,10 @@ registry->RegisterStringPref(prefs::kSyncLastRunVersion, std::string()); registry->RegisterBooleanPref(prefs::kEnableLocalSyncBackend, false); registry->RegisterFilePathPref(prefs::kLocalSyncBackendDir, base::FilePath()); +#if defined(OS_ANDROID) + registry->RegisterBooleanPref(prefs::kSyncDecoupledFromAndroidMasterSync, + false); +#endif // defined(OS_ANDROID) // Demographic prefs. registry->RegisterDictionaryPref( @@ -341,6 +345,9 @@ pref_service_->ClearPref(prefs::kSyncCacheGuid); pref_service_->ClearPref(prefs::kSyncBirthday); pref_service_->ClearPref(prefs::kSyncBagOfChips); +#if defined(OS_ANDROID) + pref_service_->ClearPref(prefs::kSyncDecoupledFromAndroidMasterSync); +#endif // defined(OS_ANDROID) // No need to clear kManaged, kEnableLocalSyncBackend or kLocalSyncBackendDir, // since they're never actually set as user preferences. @@ -666,6 +673,18 @@ pref_service_->SetBoolean(prefs::kSyncPassphrasePrompted, value); } +#if defined(OS_ANDROID) +void SyncPrefs::SetDecoupledFromAndroidMasterSync() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + pref_service_->SetBoolean(prefs::kSyncDecoupledFromAndroidMasterSync, true); +} + +bool SyncPrefs::GetDecoupledFromAndroidMasterSync() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + return pref_service_->GetBoolean(prefs::kSyncDecoupledFromAndroidMasterSync); +} +#endif // defined(OS_ANDROID) + void SyncPrefs::GetInvalidationVersions( std::map<ModelType, int64_t>* invalidation_versions) const { const base::DictionaryValue* invalidation_dictionary =
diff --git a/components/sync/base/sync_prefs.h b/components/sync/base/sync_prefs.h index 0e6ac1c7..3b1ed71 100644 --- a/components/sync/base/sync_prefs.h +++ b/components/sync/base/sync_prefs.h
@@ -169,6 +169,17 @@ bool IsPassphrasePrompted() const; void SetPassphrasePrompted(bool value); +#if defined(OS_ANDROID) + // Sets a boolean pref representing that Sync should no longer respect whether + // Android master sync is enabled/disabled. + void SetDecoupledFromAndroidMasterSync(); + + // Gets the value for the boolean pref representing whether Sync should no + // longer respect if Android master sync is enabled/disabled. Returns false + // until |SetDecoupledFromAndroidMasterSync()| is called. + bool GetDecoupledFromAndroidMasterSync(); +#endif // defined(OS_ANDROID) + // For testing. void SetManagedForTest(bool is_managed);
diff --git a/components/sync/driver/profile_sync_service.cc b/components/sync/driver/profile_sync_service.cc index ef2a45d..df884907 100644 --- a/components/sync/driver/profile_sync_service.cc +++ b/components/sync/driver/profile_sync_service.cc
@@ -328,6 +328,12 @@ invalidations_identity_provider_->SetActiveAccountId( GetAuthenticatedAccountInfo().account_id); } + + SyncInvalidationsService* sync_invalidations_service = + sync_client_->GetSyncInvalidationsService(); + if (sync_invalidations_service) { + sync_invalidations_service->SetActive(IsSignedIn()); + } } // If sync is disabled permanently, clean up old data that may be around (e.g. @@ -414,6 +420,12 @@ invalidations_identity_provider_->SetActiveAccountId( GetAuthenticatedAccountInfo().account_id); } + + SyncInvalidationsService* sync_invalidations_service = + sync_client_->GetSyncInvalidationsService(); + if (sync_invalidations_service) { + sync_invalidations_service->SetActive(IsSignedIn()); + } } void ProfileSyncService::CredentialsChanged() { @@ -1966,6 +1978,18 @@ sync_prefs_.SetPassphrasePrompted(prompted); } +#if defined(OS_ANDROID) +void ProfileSyncService::SetDecoupledFromAndroidMasterSync() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + sync_prefs_.SetDecoupledFromAndroidMasterSync(); +} + +bool ProfileSyncService::GetDecoupledFromAndroidMasterSync() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + return sync_prefs_.GetDecoupledFromAndroidMasterSync(); +} +#endif // defined(OS_ANDROID) + SyncEncryptionHandler::Observer* ProfileSyncService::GetEncryptionObserverForTest() { return &crypto_;
diff --git a/components/sync/driver/profile_sync_service.h b/components/sync/driver/profile_sync_service.h index dc38a88..475bd2f 100644 --- a/components/sync/driver/profile_sync_service.h +++ b/components/sync/driver/profile_sync_service.h
@@ -19,6 +19,7 @@ #include "base/sequenced_task_runner.h" #include "base/threading/thread.h" #include "base/time/time.h" +#include "build/build_config.h" #include "components/invalidation/public/identity_provider.h" #include "components/signin/public/identity_manager/identity_manager.h" #include "components/sync/base/model_type.h" @@ -216,6 +217,16 @@ bool IsPassphrasePrompted() const; void SetPassphrasePrompted(bool prompted); +#if defined(OS_ANDROID) + // Persists the fact that sync should no longer respect whether Android master + // sync is enabled. Only called on Android. + void SetDecoupledFromAndroidMasterSync(); + + // Gets the persisted information of whether sync should no longer respect + // if Android master sync is enabled. Only called on Android. + bool GetDecoupledFromAndroidMasterSync(); +#endif // defined(OS_ANDROID) + // Returns whether or not the underlying sync engine has made any // local changes to items that have not yet been synced with the // server.
diff --git a/components/sync/driver/profile_sync_service_unittest.cc b/components/sync/driver/profile_sync_service_unittest.cc index a17bd7b..8eeb6bd 100644 --- a/components/sync/driver/profile_sync_service_unittest.cc +++ b/components/sync/driver/profile_sync_service_unittest.cc
@@ -1648,5 +1648,45 @@ service()->SetInvalidationsForSessionsEnabled(false); } +TEST_F(ProfileSyncServiceTestWithSubscribeForSyncInvalidations, + ShouldActivateSyncInvalidationsServiceWhenSyncIsInitialized) { + CreateService(ProfileSyncService::AUTO_START); + EXPECT_CALL(*sync_invalidations_service(), SetActive(true)).Times(0); + SignIn(); + EXPECT_CALL(*sync_invalidations_service(), SetActive(true)); + InitializeForFirstSync(); +} + +TEST_F(ProfileSyncServiceTestWithSubscribeForSyncInvalidations, + ShouldActivateSyncInvalidationsServiceOnSignIn) { + CreateService(ProfileSyncService::AUTO_START); + EXPECT_CALL(*sync_invalidations_service(), SetActive(false)); + InitializeForFirstSync(); + EXPECT_CALL(*sync_invalidations_service(), SetActive(true)); + SignIn(); +} + +// CrOS does not support signout. +#if !defined(OS_CHROMEOS) +TEST_F(ProfileSyncServiceTestWithSubscribeForSyncInvalidations, + ShouldDectivateSyncInvalidationsServiceOnSignOut) { + CreateService(ProfileSyncService::AUTO_START); + SignIn(); + EXPECT_CALL(*sync_invalidations_service(), SetActive(true)); + InitializeForFirstSync(); + + auto* account_mutator = identity_manager()->GetPrimaryAccountMutator(); + // GetPrimaryAccountMutator() returns nullptr on ChromeOS only. + DCHECK(account_mutator); + + // Sign out. + EXPECT_CALL(*sync_invalidations_service(), SetActive(false)); + account_mutator->ClearPrimaryAccount( + signin::PrimaryAccountMutator::ClearAccountsAction::kDefault, + signin_metrics::SIGNOUT_TEST, + signin_metrics::SignoutDelete::IGNORE_METRIC); +} +#endif + } // namespace } // namespace syncer
diff --git a/components/sync/invalidations/fcm_handler.cc b/components/sync/invalidations/fcm_handler.cc index aee1352..0acc583 100644 --- a/components/sync/invalidations/fcm_handler.cc +++ b/components/sync/invalidations/fcm_handler.cc
@@ -7,6 +7,7 @@ #include <map> #include <utility> +#include "base/bind_helpers.h" #include "base/logging.h" #include "base/time/time.h" #include "components/gcm_driver/gcm_driver.h" @@ -51,6 +52,15 @@ } } +void FCMHandler::StopListeningPermanently() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + if (instance_id_driver_->ExistsInstanceID(app_id_)) { + instance_id_driver_->GetInstanceID(app_id_)->DeleteID( + /*callback=*/base::DoNothing()); + } + StopListening(); +} + const std::string& FCMHandler::GetFCMRegistrationToken() const { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); return fcm_registration_token_;
diff --git a/components/sync/invalidations/fcm_handler.h b/components/sync/invalidations/fcm_handler.h index aa40529..e670e5e 100644 --- a/components/sync/invalidations/fcm_handler.h +++ b/components/sync/invalidations/fcm_handler.h
@@ -40,15 +40,24 @@ FCMHandler& operator=(const FCMHandler&) = delete; // Used to start handling incoming invalidations from the server and to obtain - // an FCM token. Before StartListening() is called for the first time, the - // FCM registration token will be empty. + // an FCM token. This method gets called after sign-in, or during browser + // startup if the user is already signed in. Before StartListening() is called + // for the first time, the FCM registration token will be empty. void StartListening(); // Stop handling incoming invalidations. It doesn't cleanup the FCM // registration token and doesn't unsubscribe from FCM. All incoming - // invalidations will be dropped. + // invalidations will be dropped. This method gets called during browser + // shutdown. void StopListening(); + // Stop handling incoming invalidations and delete Instance ID. This method + // gets called during sign-out. + void StopListeningPermanently(); + + // Returns if the handler is listening for incoming invalidations. + bool IsListening() const; + // Add or remove a new listener which will be notified on each new incoming // invalidation. |listener| must not be nullptr. void AddListener(InvalidationsListener* listener); @@ -74,8 +83,6 @@ const std::string& message_id) override; private: - bool IsListening() const; - // Called when a subscription token is obtained from the GCM server. void DidRetrieveToken(const std::string& subscription_token, instance_id::InstanceID::Result result);
diff --git a/components/sync/invalidations/mock_sync_invalidations_service.h b/components/sync/invalidations/mock_sync_invalidations_service.h index 626a576..c1a8187 100644 --- a/components/sync/invalidations/mock_sync_invalidations_service.h +++ b/components/sync/invalidations/mock_sync_invalidations_service.h
@@ -17,6 +17,7 @@ MockSyncInvalidationsService(); ~MockSyncInvalidationsService() override; + MOCK_METHOD(void, SetActive, (bool active)); MOCK_METHOD(void, AddListener, (InvalidationsListener * listener)); MOCK_METHOD(void, RemoveListener, (InvalidationsListener * listener)); MOCK_METHOD(void,
diff --git a/components/sync/invalidations/sync_invalidations_service.h b/components/sync/invalidations/sync_invalidations_service.h index 434fa20e..475f86f 100644 --- a/components/sync/invalidations/sync_invalidations_service.h +++ b/components/sync/invalidations/sync_invalidations_service.h
@@ -22,6 +22,9 @@ // should be added. class SyncInvalidationsService : public KeyedService { public: + // Start or stop listening to invalidations. + virtual void SetActive(bool active) = 0; + // Add or remove a new listener which will be notified on each new incoming // invalidation. |listener| must not be nullptr. If there is no such // |listener| then RemoveListener will do nothing.
diff --git a/components/sync/invalidations/sync_invalidations_service_impl.cc b/components/sync/invalidations/sync_invalidations_service_impl.cc index 26b1036f..be5f1ee1 100644 --- a/components/sync/invalidations/sync_invalidations_service_impl.cc +++ b/components/sync/invalidations/sync_invalidations_service_impl.cc
@@ -21,11 +21,22 @@ instance_id::InstanceIDDriver* instance_id_driver) { fcm_handler_ = std::make_unique<FCMHandler>(gcm_driver, instance_id_driver, kSenderId, kApplicationId); - fcm_handler_->StartListening(); } SyncInvalidationsServiceImpl::~SyncInvalidationsServiceImpl() = default; +void SyncInvalidationsServiceImpl::SetActive(bool active) { + if (fcm_handler_->IsListening() == active) { + return; + } + + if (active) { + fcm_handler_->StartListening(); + } else { + fcm_handler_->StopListeningPermanently(); + } +} + void SyncInvalidationsServiceImpl::AddListener( InvalidationsListener* listener) { fcm_handler_->AddListener(listener);
diff --git a/components/sync/invalidations/sync_invalidations_service_impl.h b/components/sync/invalidations/sync_invalidations_service_impl.h index 6eb00207..666d945 100644 --- a/components/sync/invalidations/sync_invalidations_service_impl.h +++ b/components/sync/invalidations/sync_invalidations_service_impl.h
@@ -32,6 +32,7 @@ ~SyncInvalidationsServiceImpl() override; // SyncInvalidationsService implementation. + void SetActive(bool active) override; void AddListener(InvalidationsListener* listener) override; void RemoveListener(InvalidationsListener* listener) override; void AddTokenObserver(FCMRegistrationTokenObserver* observer) override;
diff --git a/components/test/data/payments/create_many_requests.html b/components/test/data/payments/create_many_requests.html new file mode 100644 index 0000000..e565b95 --- /dev/null +++ b/components/test/data/payments/create_many_requests.html
@@ -0,0 +1,16 @@ +<!DOCTYPE html> +<!-- +Copyright 2020 The Chromium Authors. All rights reserved. +Use of this source code is governed by a BSD-style license that can be +found in the LICENSE file. +--> +<html lang="en"> +<head> +<meta charset="utf-8"> +<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1"> +<title>Create Many Requests</title> +</head> +<body> +<script src="create_many_requests.js"></script> +</body> +</html>
diff --git a/components/test/data/payments/create_many_requests.js b/components/test/data/payments/create_many_requests.js new file mode 100644 index 0000000..90f2240 --- /dev/null +++ b/components/test/data/payments/create_many_requests.js
@@ -0,0 +1,22 @@ +/* + * 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. + */ + +const supportedInstruments = [{ + supportedMethods: 'secure-payment-confirmation', + data: { + 'credentialIds': [new ArrayBuffer(4)], + 'fallbackUrl': 'localhost:8000', + 'networkData': new ArrayBuffer(4), + }, +}]; + +const details = { + total: {label: 'Total', amount: {currency: 'USD', value: '55.00'}}, +}; + +for (let i = 0; i < 0x1000; i++) { + new PaymentRequest(supportedInstruments, details); +}
diff --git a/components/test/data/payments/load_and_remove_iframe.html b/components/test/data/payments/load_and_remove_iframe.html new file mode 100644 index 0000000..102d37d --- /dev/null +++ b/components/test/data/payments/load_and_remove_iframe.html
@@ -0,0 +1,17 @@ +<!DOCTYPE html> +<!-- +Copyright 2020 The Chromium Authors. All rights reserved. +Use of this source code is governed by a BSD-style license that can be +found in the LICENSE file. +--> +<html lang="en"> +<head> +<meta charset="utf-8"> +<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1"> +<title>Remove Iframe</title> +</head> +<body> +<iframe id="ifrm" allow="payment"></iframe> +<script src="load_and_remove_iframe.js"></script> +</body> +</html>
diff --git a/components/test/data/payments/load_and_remove_iframe.js b/components/test/data/payments/load_and_remove_iframe.js new file mode 100644 index 0000000..43f10830 --- /dev/null +++ b/components/test/data/payments/load_and_remove_iframe.js
@@ -0,0 +1,25 @@ +/* + * Copyright 2020 The Chromium Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/** + * Loads the given `url` into an iframe and then removes it after the `timeout`. + * @param {string} url - The URL to load into the iframe. + * @param {int} timeout - The number of milliseconds to wait before removing the + * iframe. + * @return {Promise<string>} - The string "success". + */ +async function loadAndRemoveIframe(url, timeout) { // eslint-disable-line no-unused-vars, max-len + const frame = document.getElementById('ifrm'); + frame.src = url; + return new Promise((resolve) => { + frame.onload = () => { + window.setTimeout(() => { + frame.parentNode.removeChild(frame); + resolve('success'); + }, timeout); + }; + }); +}
diff --git a/components/viz/service/surfaces/surface.cc b/components/viz/service/surfaces/surface.cc index 49407cf..0b89979 100644 --- a/components/viz/service/surfaces/surface.cc +++ b/components/viz/service/surfaces/surface.cc
@@ -8,6 +8,8 @@ #include <stdint.h> #include <algorithm> +#include <limits> +#include <utility> #include "base/metrics/histogram_functions.h" #include "base/stl_util.h"
diff --git a/content/browser/DEPS b/content/browser/DEPS index bbd8af7..afeee5b4 100644 --- a/content/browser/DEPS +++ b/content/browser/DEPS
@@ -160,8 +160,11 @@ # SiteInstance and BrowsingInstance should not depend on the types of things # that rely on them, like RenderFrameHostImpl or WebContentsImpl. "(site_instance_impl|browsing_instance)\.(cc|h)": [ - "-content/browser/frame_host", + "-content/browser/renderer_host", "-content/browser/web_contents", + # These files do not cycle back to SiteInstance or BrowsingInstance. + "+content/browser/renderer_host/render_process_host_impl.h", + "+content/browser/renderer_host/agent_scheduling_group_host.h", ], "storage_partition_impl_unittest\.cc": [ "+services/network/cookie_manager.h",
diff --git a/content/browser/conversions/impression_declaration_browsertest.cc b/content/browser/conversions/impression_declaration_browsertest.cc index f7a6008..512f757 100644 --- a/content/browser/conversions/impression_declaration_browsertest.cc +++ b/content/browser/conversions/impression_declaration_browsertest.cc
@@ -203,17 +203,10 @@ EXPECT_EQ(1UL, impression_observer.last_impression().impression_data); } -// Flaky on Mac: crbug.com/1099410 -#if defined(OS_MAC) -#define MAYBE_ImpressionTagNavigatesExistingRemoteFrame_ImpressionReceived \ - DISABLED_ImpressionTagNavigatesExistingRemoteFrame_ImpressionReceived -#else -#define MAYBE_ImpressionTagNavigatesExistingRemoteFrame_ImpressionReceived \ - ImpressionTagNavigatesExistingRemoteFrame_ImpressionReceived -#endif +// Flaky: crbug.com/1077216 IN_PROC_BROWSER_TEST_F( ImpressionDeclarationBrowserTest, - MAYBE_ImpressionTagNavigatesExistingRemoteFrame_ImpressionReceived) { + DISABLED_ImpressionTagNavigatesExistingRemoteFrame_ImpressionReceived) { EXPECT_TRUE(NavigateToURL( web_contents(), https_server()->GetURL("b.test", "/page_with_impression_creator.html")));
diff --git a/content/browser/dom_storage/README.md b/content/browser/dom_storage/README.md index 803f475..d16805d8 100644 --- a/content/browser/dom_storage/README.md +++ b/content/browser/dom_storage/README.md
@@ -18,7 +18,7 @@ This object is primarily held by both the [`NavigationControllerImpl`]( -https://cs.chromium.org/chromium/src/content/browser/frame_host/navigation_controller_impl.h?dr=CSs&l=426) +https://cs.chromium.org/chromium/src/content/browser/renderer_host/navigation_controller_impl.h?dr=CSs&l=426) and in the [`ContentPlatformSpecificTabData`]( https://cs.chromium.org/chromium/src/components/sessions/content/content_platform_specific_tab_data.h?dr=C&l=35) which is used to restore tabs. The services stores recent tab @@ -80,7 +80,7 @@ `CreateNewWindowParams` object in [frame.mojom](https://cs.chromium.org/chromium/src/content/common/frame.mojom). If the frame wasn't created from a previous frame, the SessionStorage namespace -object is created [here](https://cs.chromium.org/chromium/src/content/browser/frame_host/navigation_controller_impl.cc?type=cs&l=1904) +object is created [here](https://cs.chromium.org/chromium/src/content/browser/renderer_host/navigation_controller_impl.cc?type=cs&l=1904) and the id is accessed [here](https://cs.chromium.org/chromium/src/content/browser/renderer_host/render_view_host_impl.cc?type=cs&l=321). ## Renderer Connection to Session Storage
diff --git a/content/browser/renderer_host/render_frame_host_manager.cc b/content/browser/renderer_host/render_frame_host_manager.cc index b0818261..ea884b7e 100644 --- a/content/browser/renderer_host/render_frame_host_manager.cc +++ b/content/browser/renderer_host/render_frame_host_manager.cc
@@ -2586,9 +2586,9 @@ int previous_routing_id = GetReplacementRoutingId(existing_proxy, render_frame_host); - return delegate_->CreateRenderFrameForRenderManager( - render_frame_host, previous_routing_id, opener_frame_token, - parent_routing_id, previous_sibling_routing_id); + return render_frame_host->CreateRenderFrame( + previous_routing_id, opener_frame_token, parent_routing_id, + previous_sibling_routing_id); } int RenderFrameHostManager::GetReplacementRoutingId(
diff --git a/content/browser/renderer_host/render_frame_host_manager.h b/content/browser/renderer_host/render_frame_host_manager.h index a80954b..ea7832e0b 100644 --- a/content/browser/renderer_host/render_frame_host_manager.h +++ b/content/browser/renderer_host/render_frame_host_manager.h
@@ -128,12 +128,6 @@ int proxy_routing_id) = 0; virtual void CreateRenderWidgetHostViewForRenderManager( RenderViewHost* render_view_host) = 0; - virtual bool CreateRenderFrameForRenderManager( - RenderFrameHost* render_frame_host, - int proxy_routing_id, - const base::Optional<base::UnguessableToken>& opener_frame_token, - int parent_routing_id, - int previous_sibling_routing_id) = 0; virtual void BeforeUnloadFiredFromRenderManager( bool proceed, const base::TimeTicks& proceed_time,
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc index d62d4f4d..88d4426 100644 --- a/content/browser/web_contents/web_contents_impl.cc +++ b/content/browser/web_contents/web_contents_impl.cc
@@ -7970,35 +7970,6 @@ return true; } -bool WebContentsImpl::CreateRenderFrameForRenderManager( - RenderFrameHost* render_frame_host, - int previous_routing_id, - const base::Optional<base::UnguessableToken>& opener_frame_token, - int parent_routing_id, - int previous_sibling_routing_id) { - TRACE_EVENT2( - "browser,navigation", - "WebContentsImpl::CreateRenderFrameForRenderManager", "render_frame_host", - base::trace_event::ToTracedValue(render_frame_host), "params", - base::trace_event::TracedValue::Build( - {{"previous_routing_id", previous_routing_id}, - {"parent_routing_id", parent_routing_id}, - {"previous_sibling_routing_id", previous_sibling_routing_id}})); - - RenderFrameHostImpl* rfh = - static_cast<RenderFrameHostImpl*>(render_frame_host); - if (!rfh->CreateRenderFrame(previous_routing_id, opener_frame_token, - parent_routing_id, previous_sibling_routing_id)) { - return false; - } - - // TODO(nasko): When RenderWidgetHost is owned by RenderFrameHost, the passed - // RenderFrameHost will have to be associated with the appropriate - // RenderWidgetHostView or a new one should be created here. - - return true; -} - #if defined(OS_ANDROID) base::android::ScopedJavaLocalRef<jobject>
diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h index 0af5c4e..902cfe9 100644 --- a/content/browser/web_contents/web_contents_impl.h +++ b/content/browser/web_contents/web_contents_impl.h
@@ -959,12 +959,6 @@ int proxy_routing_id) override; void CreateRenderWidgetHostViewForRenderManager( RenderViewHost* render_view_host) override; - bool CreateRenderFrameForRenderManager( - RenderFrameHost* render_frame_host, - int previous_routing_id, - const base::Optional<base::UnguessableToken>& opener_frame_token, - int parent_routing_id, - int previous_sibling_routing_id) override; void BeforeUnloadFiredFromRenderManager( bool proceed, const base::TimeTicks& proceed_time,
diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc index 63ec77b..209362d 100644 --- a/content/renderer/render_view_impl.cc +++ b/content/renderer/render_view_impl.cc
@@ -1432,16 +1432,6 @@ this, &RenderViewImpl::SendFrameStateUpdates); } -void RenderViewImpl::SetMouseOverURL(const WebURL& url) { - mouse_over_url_ = GURL(url); - GetWebView()->UpdateTargetURL(mouse_over_url_, focus_url_); -} - -void RenderViewImpl::SetKeyboardFocusURL(const WebURL& url) { - focus_url_ = GURL(url); - GetWebView()->UpdateTargetURL(focus_url_, mouse_over_url_); -} - bool RenderViewImpl::AcceptsLoadDrops() { return renderer_preferences_.can_accept_load_drops; }
diff --git a/content/renderer/render_view_impl.h b/content/renderer/render_view_impl.h index eb9dc07f..71dd97fd 100644 --- a/content/renderer/render_view_impl.h +++ b/content/renderer/render_view_impl.h
@@ -218,8 +218,6 @@ base::i18n::TextDirection main_text_hint, base::string16* sub_text, base::i18n::TextDirection sub_text_hint); - void SetMouseOverURL(const blink::WebURL& url) override; - void SetKeyboardFocusURL(const blink::WebURL& url) override; bool AcceptsLoadDrops() override; void FocusNext() override; void FocusPrevious() override; @@ -381,7 +379,6 @@ void OnSetRendererPrefs( const blink::mojom::RendererPreferences& renderer_prefs); void OnSuppressDialogsUntilSwapOut(); - void OnUpdateTargetURLAck(); void OnUpdateWebPreferences(const WebPreferences& prefs); // Page message handlers ----------------------------------------------------- @@ -409,10 +406,6 @@ // update to inform the browser process. void SendFrameStateUpdates(); - // Update the target url and tell the browser that the target URL has changed. - // If |url| is empty, show |fallback_url|. - void UpdateTargetURL(const GURL& url, const GURL& fallback_url); - // RenderFrameImpl accessible state ------------------------------------------ // The following section is the set of methods that RenderFrameImpl needs // to access RenderViewImpl state. The set of state variables are page-level @@ -496,14 +489,6 @@ // process. int history_list_length_ = 0; - // UI state ------------------------------------------------------------------ - - // The URL the user's mouse is hovering over. - GURL mouse_over_url_; - - // The URL that has keyboard focus. - GURL focus_url_; - // View ---------------------------------------------------------------------- // This class owns this member, and is responsible for calling
diff --git a/docs/accessibility/overview.md b/docs/accessibility/overview.md index ca77b707..de6e382 100644 --- a/docs/accessibility/overview.md +++ b/docs/accessibility/overview.md
@@ -531,7 +531,7 @@ [Node]: https://cs.chromium.org/chromium/src/third_party/blink/renderer/core/dom/node.h [RenderAccessibilityImpl]: https://cs.chromium.org/chromium/src/content/renderer/accessibility/render_accessibility_impl.h [RenderAccessibilityManager]: https://source.chromium.org/chromium/chromium/src/+/master:content/renderer/accessibility/render_accessibility_manager.h -[RenderFrameHostImpl]: https://cs.chromium.org/chromium/src/content/browser/frame_host/render_frame_host_impl.h +[RenderFrameHostImpl]: https://cs.chromium.org/chromium/src/content/browser/renderer_host/render_frame_host_impl.h [ui::AXNodeData]: https://cs.chromium.org/chromium/src/ui/accessibility/ax_node_data.h [WebAXObject]: https://cs.chromium.org/chromium/src/third_party/blink/public/web/web_ax_object.h [automation API]: https://cs.chromium.org/chromium/src/chrome/renderer/resources/extensions/automation
diff --git a/docs/navigation-request-navigation-state.gv b/docs/navigation-request-navigation-state.gv index 30f40975..2affcd00 100644 --- a/docs/navigation-request-navigation-state.gv +++ b/docs/navigation-request-navigation-state.gv
@@ -1,5 +1,5 @@ // Generated with https://crrev.com/c/2220116 and: -// python3 tools/state_transitions/state_graph.py content/browser/frame_host/navigation_request.cc NavigationState +// python3 tools/state_transitions/state_graph.py content/browser/renderer_host/navigation_request.cc NavigationState // // See tools/state_transitions/README.md digraph createflow {
diff --git a/docs/render-frame-host-lifecycle-state.gv b/docs/render-frame-host-lifecycle-state.gv index fffc7b5b..37d8a951 100644 --- a/docs/render-frame-host-lifecycle-state.gv +++ b/docs/render-frame-host-lifecycle-state.gv
@@ -1,5 +1,5 @@ // Generated with https://crrev.com/c/2220116 and: -// python3 tools/state_transitions/state_graph.py content/browser/frame_host/render_frame_host_impl.cc LifecycleState +// python3 tools/state_transitions/state_graph.py content/browser/renderer_host/render_frame_host_impl.cc LifecycleState // // See tools/state_transitions/README.md digraph createflow {
diff --git a/gpu/command_buffer/service/shared_context_state.cc b/gpu/command_buffer/service/shared_context_state.cc index bc48671..eaf0b3a 100644 --- a/gpu/command_buffer/service/shared_context_state.cc +++ b/gpu/command_buffer/service/shared_context_state.cc
@@ -734,45 +734,40 @@ return nullptr; } -bool SharedContextState::CheckResetStatus(bool needs_gl) { +base::Optional<error::ContextLostReason> SharedContextState::GetResetStatus( + bool needs_gl) { DCHECK(!context_lost()); - if (device_needs_reset_) - return true; - if (gr_context_) { // Maybe Skia detected VK_ERROR_DEVICE_LOST. if (gr_context_->abandoned()) { LOG(ERROR) << "SharedContextState context lost via Skia."; - device_needs_reset_ = true; - MarkContextLost(error::kUnknown); - return true; + return error::kUnknown; } if (gr_context_->oomed()) { LOG(ERROR) << "SharedContextState context lost via Skia OOM."; - device_needs_reset_ = true; - MarkContextLost(error::kOutOfMemory); - return true; + return error::kOutOfMemory; } } // Not using GL. if (!GrContextIsGL() && !needs_gl) - return false; + return base::nullopt; // GL is not initialized. if (!context_state_) - return false; + return base::nullopt; - GLenum error = context_state_->api()->glGetErrorFn(); - if (error == GL_OUT_OF_MEMORY) { - LOG(ERROR) << "SharedContextState lost due to GL_OUT_OF_MEMORY"; - MarkContextLost(error::kOutOfMemory); - device_needs_reset_ = true; - return true; + GLenum error; + while ((error = context_state_->api()->glGetErrorFn()) != GL_NO_ERROR) { + if (error == GL_OUT_OF_MEMORY) { + LOG(ERROR) << "SharedContextState lost due to GL_OUT_OF_MEMORY"; + return error::kOutOfMemory; + } + if (error == GL_CONTEXT_LOST_KHR) + break; } - // Checking the reset status is expensive on some OS/drivers // (https://crbug.com/1090232). Rate limit it. constexpr base::TimeDelta kMinCheckDelay = @@ -780,33 +775,42 @@ base::Time now = base::Time::Now(); if (!disable_check_reset_status_throttling_for_test_ && now < last_gl_check_graphics_reset_status_ + kMinCheckDelay) { - return false; + return base::nullopt; } last_gl_check_graphics_reset_status_ = now; GLenum driver_status = context()->CheckStickyGraphicsResetStatus(); if (driver_status == GL_NO_ERROR) - return false; + return base::nullopt; LOG(ERROR) << "SharedContextState context lost via ARB/EXT_robustness. Reset " "status = " << gles2::GLES2Util::GetStringEnum(driver_status); - device_needs_reset_ = true; switch (driver_status) { case GL_GUILTY_CONTEXT_RESET_ARB: - MarkContextLost(error::kGuilty); - break; + return error::kGuilty; case GL_INNOCENT_CONTEXT_RESET_ARB: - MarkContextLost(error::kInnocent); - break; + return error::kInnocent; case GL_UNKNOWN_CONTEXT_RESET_ARB: - MarkContextLost(error::kUnknown); - break; + return error::kUnknown; default: NOTREACHED(); break; } - return true; + return base::nullopt; +} + +bool SharedContextState::CheckResetStatus(bool need_gl) { + DCHECK(!context_lost()); + DCHECK(!device_needs_reset_); + + auto status = GetResetStatus(need_gl); + if (status.has_value()) { + device_needs_reset_ = true; + MarkContextLost(status.value()); + return true; + } + return false; } } // namespace gpu
diff --git a/gpu/command_buffer/service/shared_context_state.h b/gpu/command_buffer/service/shared_context_state.h index 0241632..bcba574 100644 --- a/gpu/command_buffer/service/shared_context_state.h +++ b/gpu/command_buffer/service/shared_context_state.h
@@ -273,6 +273,8 @@ ~SharedContextState() override; + base::Optional<error::ContextLostReason> GetResetStatus(bool needs_gl); + // gpu::GLContextVirtualDelegate implementation. bool initialized() const override; const gles2::ContextState* GetContextState() override;
diff --git a/gpu/ipc/client/shared_image_interface_proxy.cc b/gpu/ipc/client/shared_image_interface_proxy.cc index b7750812..061026e7 100644 --- a/gpu/ipc/client/shared_image_interface_proxy.cc +++ b/gpu/ipc/client/shared_image_interface_proxy.cc
@@ -202,7 +202,7 @@ } base::AutoLock lock(lock_); - AddMailbox(params.mailbox, usage); + AddMailbox(mailbox, usage); return mailbox; }
diff --git a/infra/config/generated/commit-queue.cfg b/infra/config/generated/commit-queue.cfg index d663a1e6..a9e5791 100644 --- a/infra/config/generated/commit-queue.cfg +++ b/infra/config/generated/commit-queue.cfg
@@ -78,6 +78,12 @@ owner_whitelist_group: "project-chromium-robot-committers" } builders { + name: "chrome/try/linux-chrome" + includable_only: true + owner_whitelist_group: "googlers" + owner_whitelist_group: "project-chromium-robot-committers" + } + builders { name: "chrome/try/linux-chrome-beta" includable_only: true owner_whitelist_group: "googlers" @@ -1253,7 +1259,7 @@ } builders { name: "chromium/try/mac-coverage-rel" - experiment_percentage: 7 + experiment_percentage: 10 location_regexp: ".*" location_regexp_exclude: ".+/[+]/docs/.+" location_regexp_exclude: ".+/[+]/infra/config/.+"
diff --git a/infra/config/generated/cq-builders.md b/infra/config/generated/cq-builders.md index 07b7f1d1..f9236d48 100644 --- a/infra/config/generated/cq-builders.md +++ b/infra/config/generated/cq-builders.md
@@ -367,5 +367,5 @@ * [`//services/tracing/.+`](https://cs.chromium.org/chromium/src/services/tracing/) * [mac-coverage-rel](https://ci.chromium.org/p/chromium/builders/try/mac-coverage-rel) ([definition](https://cs.chromium.org/search?q=package:%5Echromium$+file:/cq.star$+-file:/beta/+-file:/stable/+mac-coverage-rel)) ([matching builders](https://cs.chromium.org/search?q=+file:trybots.py+mac-coverage-rel)) - * Experiment percentage: 7 + * Experiment percentage: 10
diff --git a/infra/config/subprojects/chromium/try.star b/infra/config/subprojects/chromium/try.star index f97aacd8..a79fda94 100644 --- a/infra/config/subprojects/chromium/try.star +++ b/infra/config/subprojects/chromium/try.star
@@ -1092,7 +1092,7 @@ builderless = False, use_clang_coverage = True, goma_jobs = goma.jobs.J150, - tryjob = try_.job(experiment_percentage = 7), + tryjob = try_.job(experiment_percentage = 10), ) try_.chromium_mac_builder( @@ -1577,6 +1577,10 @@ ) chrome_internal_verifier( + builder = "linux-chrome", +) + +chrome_internal_verifier( builder = "linux-chrome-beta", branch_selector = branches.STANDARD_RELEASES, )
diff --git a/ios/build/bots/chromium.webrtc.fyi/WebRTC Chromium FYI ios-simulator.json b/ios/build/bots/chromium.webrtc.fyi/WebRTC Chromium FYI ios-simulator.json index 874bc4592..987cc6e 100644 --- a/ios/build/bots/chromium.webrtc.fyi/WebRTC Chromium FYI ios-simulator.json +++ b/ios/build/bots/chromium.webrtc.fyi/WebRTC Chromium FYI ios-simulator.json
@@ -24,21 +24,21 @@ "include": "webrtc_tests.json", "device type": "iPhone 6s Plus", "os": "12.4", - "host os": "Mac-10.14.6", + "host os": "Mac-10.15", "pool": "chromium.tests" }, { "include": "webrtc_tests.json", "device type": "iPhone 6s", "os": "12.4", - "host os": "Mac-10.14.6", + "host os": "Mac-10.15", "pool": "chromium.tests" }, { "include": "webrtc_tests.json", "device type": "iPad Air 2", "os": "12.4", - "host os": "Mac-10.14.6", + "host os": "Mac-10.15", "pool": "chromium.tests" } ]
diff --git a/ios/chrome/app/application_delegate/app_state_unittest.mm b/ios/chrome/app/application_delegate/app_state_unittest.mm index aa118b6..2558b6f 100644 --- a/ios/chrome/app/application_delegate/app_state_unittest.mm +++ b/ios/chrome/app/application_delegate/app_state_unittest.mm
@@ -47,6 +47,7 @@ #import "ios/chrome/browser/ui/util/multi_window_support.h" #include "ios/chrome/test/block_cleanup_test.h" #include "ios/chrome/test/ios_chrome_scoped_testing_chrome_browser_provider.h" +#import "ios/chrome/test/scoped_key_window.h" #include "ios/public/provider/chrome/browser/distribution/app_distribution_provider.h" #include "ios/public/provider/chrome/browser/test_chrome_browser_provider.h" #include "ios/public/provider/chrome/browser/user_feedback/test_user_feedback_provider.h" @@ -625,10 +626,11 @@ // Swizzle Startup Parameters. swizzleHandleStartupParameters(tabOpener, getBrowserState()); - UIWindow* window = [[UIWindow alloc] init]; - AppState* appState = getAppStateWithOpenNTPAndIncognitoBlock(NO, window); + ScopedKeyWindow scopedKeyWindow; + AppState* appState = + getAppStateWithOpenNTPAndIncognitoBlock(NO, scopedKeyWindow.Get()); - ASSERT_EQ(NSUInteger(1), [window subviews].count); + ASSERT_EQ(NSUInteger(1), [scopedKeyWindow.Get() subviews].count); // Action. [appState resumeSessionWithTabOpener:tabOpener @@ -636,7 +638,7 @@ connectionInformation:getConnectionInformationMock()]; // Test. - EXPECT_EQ(NSUInteger(0), [window subviews].count); + EXPECT_EQ(NSUInteger(0), [scopedKeyWindow.Get() subviews].count); EXPECT_EQ(1, getProfileSessionDurationsService()->session_started_count()); EXPECT_EQ(0, getProfileSessionDurationsService()->session_ended_count()); } @@ -678,11 +680,11 @@ id tabSwitcher = [OCMockObject mockForProtocol:@protocol(TabSwitching)]; [[[tabSwitcher stub] andReturnValue:@YES] openNewTabFromTabSwitcher]; + ScopedKeyWindow scopedKeyWindow; + AppState* appState = + getAppStateWithOpenNTPAndIncognitoBlock(YES, scopedKeyWindow.Get()); - UIWindow* window = [[UIWindow alloc] init]; - AppState* appState = getAppStateWithOpenNTPAndIncognitoBlock(YES, window); - - ASSERT_EQ(NSUInteger(1), [window subviews].count); + ASSERT_EQ(NSUInteger(1), [scopedKeyWindow.Get() subviews].count); // Action. [appState resumeSessionWithTabOpener:tabOpener @@ -690,7 +692,7 @@ connectionInformation:getConnectionInformationMock()]; // Test. - EXPECT_EQ(NSUInteger(0), [window subviews].count); + EXPECT_EQ(NSUInteger(0), [scopedKeyWindow.Get() subviews].count); } // Test that -resumeSessionWithTabOpener removes incognito blocker, @@ -743,11 +745,12 @@ id tabSwitcher = [OCMockObject mockForProtocol:@protocol(TabSwitching)]; [[[tabSwitcher stub] andReturnValue:@NO] openNewTabFromTabSwitcher]; - UIWindow* window = [[UIWindow alloc] init]; - AppState* appState = getAppStateWithOpenNTPAndIncognitoBlock(YES, window); + ScopedKeyWindow scopedKeyWindow; + AppState* appState = + getAppStateWithOpenNTPAndIncognitoBlock(YES, scopedKeyWindow.Get()); // incognitoBlocker. - ASSERT_EQ(NSUInteger(1), [window subviews].count); + ASSERT_EQ(NSUInteger(1), [scopedKeyWindow.Get() subviews].count); // Action. [appState resumeSessionWithTabOpener:tabOpener @@ -755,7 +758,7 @@ connectionInformation:getConnectionInformationMock()]; // Test. - EXPECT_EQ(NSUInteger(0), [window subviews].count); + EXPECT_EQ(NSUInteger(0), [scopedKeyWindow.Get() subviews].count); } // Tests that -applicationWillEnterForeground resets components as needed. @@ -887,7 +890,7 @@ // Tests that -applicationDidEnterBackground creates an incognito blocker. TEST_F(AppStateTest, applicationDidEnterBackgroundIncognito) { // Setup. - UIWindow* window = [[UIWindow alloc] init]; + ScopedKeyWindow scopedKeyWindow; id application = [OCMockObject niceMockForClass:[UIApplication class]]; id memoryHelper = [OCMockObject mockForClass:[MemoryWarningHelper class]]; StubBrowserInterfaceProvider* interfaceProvider = getInterfaceProvider(); @@ -897,7 +900,7 @@ id browserLauncher = getBrowserLauncherMock(); BrowserInitializationStageType stage = INITIALIZATION_STAGE_FOREGROUND; - AppState* appState = getAppStateWithRealWindow(window); + AppState* appState = getAppStateWithRealWindow(scopedKeyWindow.Get()); [[startupInformation expect] expireFirstUserActionRecorder]; [[[memoryHelper stub] andReturnValue:@0] foregroundMemoryWarningCount]; @@ -907,7 +910,7 @@ swizzleMetricsMediatorDisableReporting(); - ASSERT_EQ(NSUInteger(0), [window subviews].count); + ASSERT_EQ(NSUInteger(0), [scopedKeyWindow.Get() subviews].count); // Action. [appState applicationDidEnterBackground:application @@ -917,14 +920,14 @@ // Tests. EXPECT_OCMOCK_VERIFY(startupInformation); EXPECT_TRUE(metricsMediatorHasBeenCalled()); - EXPECT_EQ(NSUInteger(1), [window subviews].count); + EXPECT_EQ(NSUInteger(1), [scopedKeyWindow.Get() subviews].count); } // Tests that -applicationDidEnterBackground do nothing if the application has // never been in a Foreground stage. TEST_F(AppStateTest, applicationDidEnterBackgroundStageBackground) { // Setup. - UIWindow* window = [[UIWindow alloc] init]; + ScopedKeyWindow scopedKeyWindow; id application = [OCMockObject mockForClass:[UIApplication class]]; id memoryHelper = [OCMockObject mockForClass:[MemoryWarningHelper class]]; id browserLauncher = getBrowserLauncherMock(); @@ -933,22 +936,23 @@ [[[browserLauncher stub] andReturnValue:@(stage)] browserInitializationStage]; [[[browserLauncher stub] andReturn:nil] interfaceProvider]; - ASSERT_EQ(NSUInteger(0), [window subviews].count); + ASSERT_EQ(NSUInteger(0), [scopedKeyWindow.Get() subviews].count); // Action. - [getAppStateWithRealWindow(window) applicationDidEnterBackground:application - memoryHelper:memoryHelper - incognitoContentVisible:YES]; + [getAppStateWithRealWindow(scopedKeyWindow.Get()) + applicationDidEnterBackground:application + memoryHelper:memoryHelper + incognitoContentVisible:YES]; // Tests. - EXPECT_EQ(NSUInteger(0), [window subviews].count); + EXPECT_EQ(NSUInteger(0), [scopedKeyWindow.Get() subviews].count); } // Tests that -applicationDidEnterBackground does not create an incognito // blocker if there is no incognito tab. TEST_F(AppStateTest, applicationDidEnterBackgroundNoIncognitoBlocker) { // Setup. - UIWindow* window = [[UIWindow alloc] init]; + ScopedKeyWindow scopedKeyWindow; id application = [OCMockObject niceMockForClass:[UIApplication class]]; id memoryHelper = [OCMockObject mockForClass:[MemoryWarningHelper class]]; StubBrowserInterfaceProvider* interfaceProvider = getInterfaceProvider(); @@ -958,7 +962,7 @@ id browserLauncher = getBrowserLauncherMock(); BrowserInitializationStageType stage = INITIALIZATION_STAGE_FOREGROUND; - AppState* appState = getAppStateWithRealWindow(window); + AppState* appState = getAppStateWithRealWindow(scopedKeyWindow.Get()); [[startupInformation expect] expireFirstUserActionRecorder]; [[[memoryHelper stub] andReturnValue:@0] foregroundMemoryWarningCount]; @@ -968,7 +972,7 @@ swizzleMetricsMediatorDisableReporting(); - ASSERT_EQ(NSUInteger(0), [window subviews].count); + ASSERT_EQ(NSUInteger(0), [scopedKeyWindow.Get() subviews].count); // Action. [appState applicationDidEnterBackground:application @@ -978,5 +982,5 @@ // Tests. EXPECT_OCMOCK_VERIFY(startupInformation); EXPECT_TRUE(metricsMediatorHasBeenCalled()); - EXPECT_EQ(NSUInteger(0), [window subviews].count); + EXPECT_EQ(NSUInteger(0), [scopedKeyWindow.Get() subviews].count); }
diff --git a/ios/chrome/app/main_controller.mm b/ios/chrome/app/main_controller.mm index 98f0502..f99fc03 100644 --- a/ios/chrome/app/main_controller.mm +++ b/ios/chrome/app/main_controller.mm
@@ -982,7 +982,6 @@ - (void)scheduleLowPriorityStartupTasks { [_startupTasks initializeOmaha]; - [_startupTasks donateIntents]; // Deferred tasks. [self schedulePrefObserverInitialization];
diff --git a/ios/chrome/app/resources/chrome_localize_strings_config.plist b/ios/chrome/app/resources/chrome_localize_strings_config.plist index 7de946931..7dc24e50 100644 --- a/ios/chrome/app/resources/chrome_localize_strings_config.plist +++ b/ios/chrome/app/resources/chrome_localize_strings_config.plist
@@ -21,6 +21,8 @@ <string>IDS_IOS_SAFE_MODE_CRASH_REPORT_SENT</string> <string>IDS_IOS_SAFE_MODE_RELOAD_CHROME</string> <string>IDS_IOS_SAFE_MODE_AW_SNAP</string> + <string>IDS_IOS_UI_BLOCKED_USE_OTHER_WINDOW_DESCRIPTION</string> + <string>IDS_IOS_UI_BLOCKED_USE_OTHER_WINDOW_SWITCH_WINDOW_ACTION</string> </array> </dict> <dict> @@ -64,12 +66,12 @@ <key>output</key> <string>Z6KvRw</string> </dict> - <dict> - <key>input</key> - <string>IDS_IOS_INTENTS_SEARCH_IN_CHROME_PARAMETER_COMBINATION_TITLE</string> - <key>output</key> - <string>TqBLdA</string> - </dict> + <dict> + <key>input</key> + <string>IDS_IOS_INTENTS_SEARCH_IN_CHROME_PARAMETER_COMBINATION_TITLE</string> + <key>output</key> + <string>TqBLdA</string> + </dict> <dict> <key>input</key> <string>IDS_IOS_INTENTS_OPEN_IN_CHROME_PARAMETER_COMBINATION_TITLE</string>
diff --git a/ios/chrome/app/startup_tasks.h b/ios/chrome/app/startup_tasks.h index a4c8307..2664398 100644 --- a/ios/chrome/app/startup_tasks.h +++ b/ios/chrome/app/startup_tasks.h
@@ -18,8 +18,6 @@ (ChromeBrowserState*)browserState; // Starts Omaha and, if first run, sets install time. For official builds only. - (void)initializeOmaha; -// Donate initial Intents. -- (void)donateIntents; // Registers to receive UIApplicationWillResignActiveNotification. - (void)registerForApplicationWillResignActiveNotification;
diff --git a/ios/chrome/app/startup_tasks.mm b/ios/chrome/app/startup_tasks.mm index 82ced71..7e030fe0 100644 --- a/ios/chrome/app/startup_tasks.mm +++ b/ios/chrome/app/startup_tasks.mm
@@ -77,17 +77,6 @@ object:nil]; } -- (void)donateIntents { - SearchInChromeIntent* searchInChromeIntent = - [[SearchInChromeIntent alloc] init]; - searchInChromeIntent.suggestedInvocationPhrase = l10n_util::GetNSString( - IDS_IOS_INTENTS_SEARCH_IN_CHROME_INVOCATION_PHRASE); - INInteraction* interaction = - [[INInteraction alloc] initWithIntent:searchInChromeIntent response:nil]; - [interaction donateInteractionWithCompletion:^(NSError* _Nullable error){ - }]; -} - #pragma mark - Private methods. + (void)performDeferredInitializationForBrowserState:
diff --git a/ios/chrome/app/strings/ios_strings.grd b/ios/chrome/app/strings/ios_strings.grd index d743994..b7f1e6e 100644 --- a/ios/chrome/app/strings/ios_strings.grd +++ b/ios/chrome/app/strings/ios_strings.grd
@@ -2615,7 +2615,7 @@ Finish what you were doing in your other open Chrome window. </message> <message name="IDS_IOS_UI_BLOCKED_USE_OTHER_WINDOW_SWITCH_WINDOW_ACTION" desc="Button label that appears on a button to switch to some other window, when the user has multiple windows open, and one window is showing a dialog that has to be interacted with before any other window can be used."> - Switch to Open Window. + Switch to Open Window </message> </messages> </release>
diff --git a/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_UI_BLOCKED_USE_OTHER_WINDOW_SWITCH_WINDOW_ACTION.png.sha1 b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_UI_BLOCKED_USE_OTHER_WINDOW_SWITCH_WINDOW_ACTION.png.sha1 index a0d8dad..a4195a29 100644 --- a/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_UI_BLOCKED_USE_OTHER_WINDOW_SWITCH_WINDOW_ACTION.png.sha1 +++ b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_UI_BLOCKED_USE_OTHER_WINDOW_SWITCH_WINDOW_ACTION.png.sha1
@@ -1 +1 @@ -e448023f24ac158305420ed7805ebb815672c2f3 \ No newline at end of file +c95d540e199725667b9c55a84e699a267bcdc70b \ No newline at end of file
diff --git a/ios/chrome/browser/crash_report/breadcrumbs/application_breadcrumbs_logger.h b/ios/chrome/browser/crash_report/breadcrumbs/application_breadcrumbs_logger.h index 83d05ba..b157b0c 100644 --- a/ios/chrome/browser/crash_report/breadcrumbs/application_breadcrumbs_logger.h +++ b/ios/chrome/browser/crash_report/breadcrumbs/application_breadcrumbs_logger.h
@@ -52,10 +52,8 @@ // Observes device orientation. id<NSObject> orientation_observer_; - // Used to avoid logging the same orientation twice as well as logging - // UIDeviceOrientationUnknown on startup (the only place where "unknown" - // shows up). Fewer logs leave more room for more useful logs. - UIDeviceOrientation last_orientation_ = UIDeviceOrientationUnknown; + // Used to avoid logging the same orientation twice. + base::Optional<UIDeviceOrientation> last_orientation_; }; #endif // IOS_CHROME_BROWSER_CRASH_REPORT_BREADCRUMBS_APPLICATION_BREADCRUMBS_LOGGER_H_
diff --git a/ios/chrome/browser/policy/browser_policy_connector_ios.h b/ios/chrome/browser/policy/browser_policy_connector_ios.h index 7627d864..9879b0f0 100644 --- a/ios/chrome/browser/policy/browser_policy_connector_ios.h +++ b/ios/chrome/browser/policy/browser_policy_connector_ios.h
@@ -58,6 +58,11 @@ bool HasMachineLevelPolicies() override; void Shutdown() override; + // BrowserPolicyConnector. + // Always returns true because there is no way for normal users to use command + // line switch anyway. + bool IsCommandLineSwitchSupported() const override; + protected: // BrowserPolicyConnectorBase. std::vector<std::unique_ptr<policy::ConfigurationPolicyProvider>>
diff --git a/ios/chrome/browser/policy/browser_policy_connector_ios.mm b/ios/chrome/browser/policy/browser_policy_connector_ios.mm index f096557..ba1e7bd9 100644 --- a/ios/chrome/browser/policy/browser_policy_connector_ios.mm +++ b/ios/chrome/browser/policy/browser_policy_connector_ios.mm
@@ -58,8 +58,7 @@ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory) { std::unique_ptr<policy::DeviceManagementService::Configuration> configuration( new policy::DeviceManagementServiceConfigurationIOS( - BrowserPolicyConnector::GetDeviceManagementUrl(), - BrowserPolicyConnector::GetRealtimeReportingUrl())); + GetDeviceManagementUrl(), GetRealtimeReportingUrl())); std::unique_ptr<policy::DeviceManagementService> device_management_service( new policy::DeviceManagementService(std::move(configuration))); device_management_service->ScheduleInitialization( @@ -86,6 +85,10 @@ BrowserPolicyConnector::Shutdown(); } +bool BrowserPolicyConnectorIOS::IsCommandLineSwitchSupported() const { + return true; +} + std::vector<std::unique_ptr<policy::ConfigurationPolicyProvider>> BrowserPolicyConnectorIOS::CreatePolicyProviders() { auto providers = BrowserPolicyConnector::CreatePolicyProviders();
diff --git a/ios/chrome/browser/ui/blocking_overlay/BUILD.gn b/ios/chrome/browser/ui/blocking_overlay/BUILD.gn index 55f71f19..ae69f97 100644 --- a/ios/chrome/browser/ui/blocking_overlay/BUILD.gn +++ b/ios/chrome/browser/ui/blocking_overlay/BUILD.gn
@@ -15,6 +15,5 @@ "//ios/chrome/app/strings:ios_strings", "//ios/chrome/common/ui/colors", "//ios/chrome/common/ui/util", - "//ui/base", ] }
diff --git a/ios/chrome/browser/ui/blocking_overlay/blocking_overlay_view_controller.mm b/ios/chrome/browser/ui/blocking_overlay/blocking_overlay_view_controller.mm index 5f62455..f461679 100644 --- a/ios/chrome/browser/ui/blocking_overlay/blocking_overlay_view_controller.mm +++ b/ios/chrome/browser/ui/blocking_overlay/blocking_overlay_view_controller.mm
@@ -8,7 +8,6 @@ #import "ios/chrome/common/ui/colors/semantic_color_names.h" #import "ios/chrome/common/ui/util/constraints_ui_util.h" #include "ios/chrome/grit/ios_strings.h" -#include "ui/base/l10n/l10n_util_mac.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support." @@ -22,6 +21,9 @@ } // namespace +// This view controller is used in Safe Mode. This means everything used here +// must not require any advanced initialization that only happens after safe +// mode. @implementation BlockingOverlayViewController - (void)viewWillAppear:(BOOL)animated { @@ -41,8 +43,11 @@ AddSameConstraints(self.view, backgroundBlurEffect); UILabel* label = [[UILabel alloc] init]; - label.text = - l10n_util::GetNSString(IDS_IOS_UI_BLOCKED_USE_OTHER_WINDOW_DESCRIPTION); + // Here and everywhere, use NSLocalizedString because the usual localization + // method with l10n_util::GetNSString() requires initialization that happens + // after safe mode completes. + label.text = NSLocalizedString( + @"IDS_IOS_UI_BLOCKED_USE_OTHER_WINDOW_DESCRIPTION", @""); label.textColor = [UIColor colorNamed:kGrey800Color]; label.font = [UIFont preferredFontForTextStyle:UIFontTextStyleBody]; label.textAlignment = NSTextAlignmentCenter; @@ -56,9 +61,11 @@ UIButton* button = [[UIButton alloc] init]; button.translatesAutoresizingMaskIntoConstraints = NO; - [button setTitle:l10n_util::GetNSString( - IDS_IOS_UI_BLOCKED_USE_OTHER_WINDOW_SWITCH_WINDOW_ACTION) - forState:UIControlStateNormal]; + [button + setTitle:NSLocalizedString( + @"IDS_IOS_UI_BLOCKED_USE_OTHER_WINDOW_SWITCH_WINDOW_ACTION", + @"") + forState:UIControlStateNormal]; [button setTitleColor:[UIColor colorNamed:kBlueColor] forState:UIControlStateNormal]; button.titleLabel.font =
diff --git a/ios/chrome/browser/ui/elements/selector_coordinator_unittest.mm b/ios/chrome/browser/ui/elements/selector_coordinator_unittest.mm index 429c53f3c..529d9fc 100644 --- a/ios/chrome/browser/ui/elements/selector_coordinator_unittest.mm +++ b/ios/chrome/browser/ui/elements/selector_coordinator_unittest.mm
@@ -9,6 +9,7 @@ #import "ios/chrome/browser/main/test_browser.h" #import "ios/chrome/browser/ui/elements/selector_picker_view_controller.h" #import "ios/chrome/browser/ui/elements/selector_view_controller_delegate.h" +#import "ios/chrome/test/scoped_key_window.h" #include "testing/gtest/include/gtest/gtest.h" #import "testing/gtest_mac.h" #include "testing/platform_test.h" @@ -31,8 +32,8 @@ // that invoking stop dismisses the view and invokes the delegate. TEST_F(SelectorCoordinatorTest, StartAndStop) { base::test::TaskEnvironment task_environment_; - - UIWindow* keyWindow = [[UIApplication sharedApplication] keyWindow]; + ScopedKeyWindow scopedKeyWindow; + UIWindow* keyWindow = scopedKeyWindow.Get(); UIViewController* rootViewController = keyWindow.rootViewController; std::unique_ptr<Browser> browser_ = std::make_unique<TestBrowser>(); SelectorCoordinator* coordinator = @@ -45,9 +46,10 @@ rootViewController.presentedViewController); [coordinator stop]; - base::test::ios::WaitUntilCondition(^{ + bool success = base::test::ios::WaitUntilConditionOrTimeout(1.0, ^{ return !rootViewController.presentedViewController; }); + EXPECT_TRUE(success); }; // Ensure any other presented controllers are dismissed before starting the // coordinator. @@ -59,7 +61,8 @@ TEST_F(SelectorCoordinatorTest, Delegate) { base::test::TaskEnvironment task_environment_; - UIWindow* keyWindow = [[UIApplication sharedApplication] keyWindow]; + ScopedKeyWindow scopedKeyWindow; + UIWindow* keyWindow = scopedKeyWindow.Get(); UIViewController* rootViewController = keyWindow.rootViewController; std::unique_ptr<Browser> browser_ = std::make_unique<TestBrowser>(); SelectorCoordinator* coordinator = @@ -76,9 +79,10 @@ didCompleteWithSelection:testOption]; [coordinator selectorViewController:coordinator.selectorPickerViewController didSelectOption:testOption]; - base::test::ios::WaitUntilCondition(^{ + bool success = base::test::ios::WaitUntilConditionOrTimeout(1.0, ^{ return !rootViewController.presentedViewController; }); + EXPECT_TRUE(success); }; // Ensure any other presented controllers are dismissed before starting the // coordinator.
diff --git a/ios/third_party/material_components_ios/BUILD.gn b/ios/third_party/material_components_ios/BUILD.gn index b891057b..f0b6c10 100644 --- a/ios/third_party/material_components_ios/BUILD.gn +++ b/ios/third_party/material_components_ios/BUILD.gn
@@ -372,11 +372,11 @@ "src/components/Tabs/src/private/MDCItemBarCell+Private.h", "src/components/Tabs/src/private/MDCItemBarCell.h", "src/components/Tabs/src/private/MDCItemBarDelegate.h", - "src/components/Tabs/src/private/MDCItemBarStringConstants.h", "src/components/Tabs/src/private/MDCItemBarStyle.h", "src/components/Tabs/src/private/MDCTabBarIndicatorView.h", "src/components/Tabs/src/private/MDCTabBarPrivateIndicatorContext.h", "src/components/TextControls/src/BaseTextAreas/MDCBaseTextArea.h", + "src/components/TextControls/src/BaseTextAreas/MDCBaseTextAreaDelegate.h", "src/components/TextControls/src/BaseTextAreas/MaterialTextControls+BaseTextAreas.h", "src/components/TextControls/src/BaseTextAreas/private/MDCBaseTextAreaLayout.h", "src/components/TextControls/src/BaseTextAreas/private/MDCBaseTextAreaTextView.h", @@ -1247,7 +1247,6 @@ "src/components/Tabs/src/private/MDCItemBarCell.h", "src/components/Tabs/src/private/MDCItemBarCell.m", "src/components/Tabs/src/private/MDCItemBarDelegate.h", - "src/components/Tabs/src/private/MDCItemBarStringConstants.h", "src/components/Tabs/src/private/MDCItemBarStyle.h", "src/components/Tabs/src/private/MDCItemBarStyle.m", "src/components/Tabs/src/private/MDCTabBarIndicatorView.h", @@ -1256,6 +1255,7 @@ "src/components/Tabs/src/private/MDCTabBarPrivateIndicatorContext.m", "src/components/TextControls/src/BaseTextAreas/MDCBaseTextArea.h", "src/components/TextControls/src/BaseTextAreas/MDCBaseTextArea.m", + "src/components/TextControls/src/BaseTextAreas/MDCBaseTextAreaDelegate.h", "src/components/TextControls/src/BaseTextAreas/MaterialTextControls+BaseTextAreas.h", "src/components/TextControls/src/BaseTextAreas/private/MDCBaseTextAreaLayout.h", "src/components/TextControls/src/BaseTextAreas/private/MDCBaseTextAreaLayout.m", @@ -1634,7 +1634,6 @@ "Dialogs", "PageControl", "Snackbar", - "Tabs", ] foreach(_component, _components) {
diff --git a/ios/web_view/internal/cwv_preferences.mm b/ios/web_view/internal/cwv_preferences.mm index 4d5117ea..bf23e96 100644 --- a/ios/web_view/internal/cwv_preferences.mm +++ b/ios/web_view/internal/cwv_preferences.mm
@@ -72,4 +72,14 @@ password_manager::prefs::kCredentialsEnableService); } +- (void)setPasswordLeakCheckEnabled:(BOOL)enabled { + _prefService->SetBoolean( + password_manager::prefs::kPasswordLeakDetectionEnabled, enabled); +} + +- (BOOL)isPasswordLeakCheckEnabled { + return _prefService->GetBoolean( + password_manager::prefs::kPasswordLeakDetectionEnabled); +} + @end
diff --git a/ios/web_view/internal/cwv_preferences_unittest.mm b/ios/web_view/internal/cwv_preferences_unittest.mm index 973d4ca..efa87cf 100644 --- a/ios/web_view/internal/cwv_preferences_unittest.mm +++ b/ios/web_view/internal/cwv_preferences_unittest.mm
@@ -37,6 +37,8 @@ pref_registry->RegisterBooleanPref( password_manager::prefs::kCredentialsEnableService, true); pref_registry->RegisterBooleanPref(prefs::kOfferTranslateEnabled, true); + pref_registry->RegisterBooleanPref( + password_manager::prefs::kPasswordLeakDetectionEnabled, true); scoped_refptr<PersistentPrefStore> pref_store = new InMemoryPrefStore(); PrefServiceFactory factory; @@ -72,4 +74,18 @@ EXPECT_FALSE(preferences_.translationEnabled); } +// Tests CWVPreferences |passwordAutofillEnabled|. +TEST_F(CWVPreferencesTest, PasswordAutofillEnabled) { + EXPECT_TRUE(preferences_.passwordAutofillEnabled); + preferences_.passwordAutofillEnabled = NO; + EXPECT_FALSE(preferences_.passwordAutofillEnabled); +} + +// Tests CWVPreferences |passwordLeakCheckEnabled|. +TEST_F(CWVPreferencesTest, PasswordLeakCheckEnabled) { + EXPECT_TRUE(preferences_.passwordLeakCheckEnabled); + preferences_.passwordLeakCheckEnabled = NO; + EXPECT_FALSE(preferences_.passwordLeakCheckEnabled); +} + } // namespace ios_web_view
diff --git a/ios/web_view/public/cwv_preferences.h b/ios/web_view/public/cwv_preferences.h index 7e4529d..90bd23d 100644 --- a/ios/web_view/public/cwv_preferences.h +++ b/ios/web_view/public/cwv_preferences.h
@@ -43,6 +43,11 @@ @property(nonatomic, assign, getter=isPasswordAutofillEnabled) BOOL passwordAutofillEnabled; +// Whether or not password leak checks will be performed after successful form +// submission. Defaults to |YES|. +@property(nonatomic, assign, getter=isPasswordLeakCheckEnabled) + BOOL passwordLeakCheckEnabled; + - (instancetype)init NS_UNAVAILABLE; // Resets all translation settings back to default. In particular, this will
diff --git a/media/gpu/v4l2/v4l2_video_decoder.cc b/media/gpu/v4l2/v4l2_video_decoder.cc index cc8d25e..9b8847a 100644 --- a/media/gpu/v4l2/v4l2_video_decoder.cc +++ b/media/gpu/v4l2/v4l2_video_decoder.cc
@@ -569,6 +569,8 @@ << ", Number of queued output buffers: " << output_queue_->QueuedBuffersCount(); + backend_->OnServiceDeviceTask(event); + // Dequeue V4L2 output buffer first to reduce output latency. bool success; while (output_queue_->QueuedBuffersCount() > 0) { @@ -597,8 +599,6 @@ if (!dequeued_buffer) break; } - - backend_->OnServiceDeviceTask(event); } void V4L2VideoDecoder::OutputFrame(scoped_refptr<VideoFrame> frame,
diff --git a/media/gpu/v4l2/v4l2_video_decoder_backend_stateful.cc b/media/gpu/v4l2/v4l2_video_decoder_backend_stateful.cc index 417598f8..e25779ff 100644 --- a/media/gpu/v4l2/v4l2_video_decoder_backend_stateful.cc +++ b/media/gpu/v4l2/v4l2_video_decoder_backend_stateful.cc
@@ -230,18 +230,21 @@ weak_this_)); } +void V4L2StatefulVideoDecoderBackend::ProcessEventQueue() { + while (base::Optional<struct v4l2_event> ev = device_->DequeueEvent()) { + if (ev->type == V4L2_EVENT_SOURCE_CHANGE && + (ev->u.src_change.changes & V4L2_EVENT_SRC_CH_RESOLUTION)) { + ChangeResolution(); + } + } +} + void V4L2StatefulVideoDecoderBackend::OnServiceDeviceTask(bool event) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DVLOGF(3); - if (event) { - while (base::Optional<struct v4l2_event> ev = device_->DequeueEvent()) { - if (ev->type == V4L2_EVENT_SOURCE_CHANGE && - (ev->u.src_change.changes & V4L2_EVENT_SRC_CH_RESOLUTION)) { - ChangeResolution(); - } - } - } + if (event) + ProcessEventQueue(); // We can enqueue dequeued output buffers immediately. EnqueueOutputBuffers(); @@ -384,11 +387,16 @@ // The order here is important! A flush event may come after a resolution // change event (but not the opposite), so we must make sure both events // are processed in the correct order. - if (buffer->IsLast() && resolution_change_cb_) { - std::move(resolution_change_cb_).Run(); - } else if (buffer->IsLast() && flush_cb_) { - // We were waiting for a flush to complete, and received the last buffer. - CompleteFlush(); + if (buffer->IsLast()){ + if (!resolution_change_cb_ && !flush_cb_) + ProcessEventQueue(); + + if (resolution_change_cb_) { + std::move(resolution_change_cb_).Run(); + } else if (flush_cb_) { + // We were waiting for a flush to complete, and received the last buffer. + CompleteFlush(); + } } EnqueueOutputBuffers();
diff --git a/media/gpu/v4l2/v4l2_video_decoder_backend_stateful.h b/media/gpu/v4l2/v4l2_video_decoder_backend_stateful.h index 62d6d71..3b41c34 100644 --- a/media/gpu/v4l2/v4l2_video_decoder_backend_stateful.h +++ b/media/gpu/v4l2/v4l2_video_decoder_backend_stateful.h
@@ -112,6 +112,9 @@ void ScheduleDecodeWork(); + // Process all the event in the event queue + void ProcessEventQueue(); + // Video profile we are decoding. VideoCodecProfile profile_;
diff --git a/media/gpu/vaapi/vp9_vaapi_video_decoder_delegate.cc b/media/gpu/vaapi/vp9_vaapi_video_decoder_delegate.cc index edb382eb..0c5837cb 100644 --- a/media/gpu/vaapi/vp9_vaapi_video_decoder_delegate.cc +++ b/media/gpu/vaapi/vp9_vaapi_video_decoder_delegate.cc
@@ -139,10 +139,8 @@ } if (!vaapi_wrapper_->SubmitBuffers( - {{VAPictureParameterBufferType, - sizeof(VADecPictureParameterBufferVP9), &pic_param}, - {VASliceParameterBufferType, sizeof(VASliceParameterBufferVP9), - &slice_param}, + {{VAPictureParameterBufferType, sizeof(pic_param), &pic_param}, + {VASliceParameterBufferType, sizeof(slice_param), &slice_param}, {VASliceDataBufferType, frame_hdr->frame_size, frame_hdr->data}})) { return false; }
diff --git a/pdf/out_of_process_instance.cc b/pdf/out_of_process_instance.cc index f37df981..bd0a5e0 100644 --- a/pdf/out_of_process_instance.cc +++ b/pdf/out_of_process_instance.cc
@@ -18,7 +18,6 @@ #include "base/callback.h" #include "base/feature_list.h" #include "base/logging.h" -#include "base/memory/scoped_refptr.h" #include "base/memory/weak_ptr.h" #include "base/metrics/histogram_functions.h" #include "base/notreached.h" @@ -1078,9 +1077,10 @@ } } -void OutOfProcessInstance::DidOpen(int32_t result) { +void OutOfProcessInstance::DidOpen(std::unique_ptr<UrlLoader> loader, + int32_t result) { if (result == PP_OK) { - if (!engine()->HandleDocumentLoad(embed_loader_)) { + if (!engine()->HandleDocumentLoad(std::move(loader))) { document_load_state_ = LOAD_STATE_LOADING; DocumentLoadFailed(); } @@ -1089,13 +1089,14 @@ } } -void OutOfProcessInstance::DidOpenPreview(int32_t result) { +void OutOfProcessInstance::DidOpenPreview(std::unique_ptr<UrlLoader> loader, + int32_t result) { if (result == PP_OK) { preview_client_ = std::make_unique<PreviewModeClient>(this); preview_engine_ = std::make_unique<PDFiumEngine>(preview_client_.get(), /*enable_javascript=*/false); - preview_engine_->HandleDocumentLoad(embed_preview_loader_); + preview_engine_->HandleDocumentLoad(std::move(loader)); } else { NOTREACHED(); } @@ -1472,13 +1473,11 @@ } void OutOfProcessInstance::FormDidOpen(int32_t result) { - // TODO: inform the user of success/failure. - if (result != PP_OK) { - LOG(ERROR) << "FormDidOpen failed: " << result; - } + // TODO(crbug.com/719344): Process response. + LOG_IF(ERROR, result != PP_OK) << "FormDidOpen failed: " << result; } -scoped_refptr<UrlLoader> OutOfProcessInstance::CreateUrlLoader() { +std::unique_ptr<UrlLoader> OutOfProcessInstance::CreateUrlLoader() { if (full_) { if (!did_call_start_loading_) { did_call_start_loading_ = true; @@ -2092,18 +2091,17 @@ request.method = "GET"; request.ignore_redirects = true; - scoped_refptr<UrlLoader>& loader = - is_print_preview ? embed_preview_loader_ : embed_loader_; - loader = CreateUrlLoaderInternal(); - loader->Open( + std::unique_ptr<UrlLoader> loader = CreateUrlLoaderInternal(); + UrlLoader* raw_loader = loader.get(); + raw_loader->Open( request, base::BindOnce(is_print_preview ? &OutOfProcessInstance::DidOpenPreview : &OutOfProcessInstance::DidOpen, - weak_factory_.GetWeakPtr())); + weak_factory_.GetWeakPtr(), std::move(loader))); } -scoped_refptr<UrlLoader> OutOfProcessInstance::CreateUrlLoaderInternal() { - auto loader = base::MakeRefCounted<PepperUrlLoader>(this); +std::unique_ptr<UrlLoader> OutOfProcessInstance::CreateUrlLoaderInternal() { + auto loader = std::make_unique<PepperUrlLoader>(this); loader->GrantUniversalAccess(); return loader; }
diff --git a/pdf/out_of_process_instance.h b/pdf/out_of_process_instance.h index ccf5892..48db493f 100644 --- a/pdf/out_of_process_instance.h +++ b/pdf/out_of_process_instance.h
@@ -16,7 +16,6 @@ #include "base/callback.h" #include "base/containers/queue.h" -#include "base/memory/scoped_refptr.h" #include "base/memory/weak_ptr.h" #include "pdf/paint_manager.h" #include "pdf/pdf_view_plugin_base.h" @@ -106,8 +105,8 @@ const PP_PdfPrintSettings_Dev* pdf_print_settings); void FlushCallback(int32_t result); - void DidOpen(int32_t result); - void DidOpenPreview(int32_t result); + void DidOpen(std::unique_ptr<UrlLoader> loader, int32_t result); + void DidOpenPreview(std::unique_ptr<UrlLoader> loader, int32_t result); // PdfViewPluginBase implementation. void ProposeDocumentLayout(const DocumentLayout& layout) override; @@ -145,7 +144,7 @@ void SubmitForm(const std::string& url, const void* data, int length) override; - scoped_refptr<UrlLoader> CreateUrlLoader() override; + std::unique_ptr<UrlLoader> CreateUrlLoader() override; std::vector<SearchStringResult> SearchString(const base::char16* string, const base::char16* term, bool case_sensitive) override; @@ -224,7 +223,7 @@ // Creates a URL loader and allows it to access all urls, i.e. not just the // frame's origin. - scoped_refptr<UrlLoader> CreateUrlLoaderInternal(); + std::unique_ptr<UrlLoader> CreateUrlLoaderInternal(); bool CanSaveEdits() const; void SaveToFile(const std::string& token); @@ -338,11 +337,6 @@ pp::ImageData image_data_; SkBitmap skia_image_data_; // Must be kept in sync with |image_data_|. - // Used when the plugin is embedded in a page and we have to create the loader - // ourself. - scoped_refptr<UrlLoader> embed_loader_; - scoped_refptr<UrlLoader> embed_preview_loader_; - // The current cursor. PP_CursorType_Dev cursor_ = PP_CURSORTYPE_POINTER; @@ -435,7 +429,7 @@ std::string url_; // Used for submitting forms. - scoped_refptr<UrlLoader> form_loader_; + std::unique_ptr<UrlLoader> form_loader_; // The callback for receiving the password from the page. base::OnceCallback<void(const std::string&)> password_callback_;
diff --git a/pdf/pdf_engine.h b/pdf/pdf_engine.h index 9d10140..187892f 100644 --- a/pdf/pdf_engine.h +++ b/pdf/pdf_engine.h
@@ -7,12 +7,12 @@ #include <stdint.h> +#include <memory> #include <string> #include <vector> #include "base/callback.h" #include "base/containers/span.h" -#include "base/memory/scoped_refptr.h" #include "base/optional.h" #include "base/strings/string16.h" #include "base/time/time.h" @@ -221,7 +221,7 @@ int length) {} // Creates and returns new URL loader for partial document requests. - virtual scoped_refptr<UrlLoader> CreateUrlLoader() = 0; + virtual std::unique_ptr<UrlLoader> CreateUrlLoader() = 0; // Searches the given string for "term" and returns the results. Unicode- // aware. @@ -337,7 +337,7 @@ std::vector<gfx::Rect>& ready, std::vector<gfx::Rect>& pending) = 0; virtual void PostPaint() = 0; - virtual bool HandleDocumentLoad(scoped_refptr<UrlLoader> loader) = 0; + virtual bool HandleDocumentLoad(std::unique_ptr<UrlLoader> loader) = 0; virtual bool HandleEvent(const InputEvent& event) = 0; virtual uint32_t QuerySupportedPrintOutputFormats() = 0; virtual void PrintBegin() = 0;
diff --git a/pdf/pdf_view_web_plugin.cc b/pdf/pdf_view_web_plugin.cc index 1882a05..bbefe9b 100644 --- a/pdf/pdf_view_web_plugin.cc +++ b/pdf/pdf_view_web_plugin.cc
@@ -10,7 +10,6 @@ #include <vector> #include "base/check_op.h" -#include "base/memory/scoped_refptr.h" #include "base/thread_annotations.h" #include "base/threading/thread_checker.h" #include "cc/paint/paint_canvas.h" @@ -207,7 +206,7 @@ const void* data, int length) {} -scoped_refptr<UrlLoader> PdfViewWebPlugin::CreateUrlLoader() { +std::unique_ptr<UrlLoader> PdfViewWebPlugin::CreateUrlLoader() { return nullptr; }
diff --git a/pdf/pdf_view_web_plugin.h b/pdf/pdf_view_web_plugin.h index c0e913a..a6c10d2 100644 --- a/pdf/pdf_view_web_plugin.h +++ b/pdf/pdf_view_web_plugin.h
@@ -79,7 +79,7 @@ void SubmitForm(const std::string& url, const void* data, int length) override; - scoped_refptr<UrlLoader> CreateUrlLoader() override; + std::unique_ptr<UrlLoader> CreateUrlLoader() override; std::vector<SearchStringResult> SearchString(const base::char16* string, const base::char16* term, bool case_sensitive) override;
diff --git a/pdf/pdfium/pdfium_engine.cc b/pdf/pdfium/pdfium_engine.cc index 8f865b07..51897a5 100644 --- a/pdf/pdfium/pdfium_engine.cc +++ b/pdf/pdfium/pdfium_engine.cc
@@ -20,7 +20,6 @@ #include "base/check_op.h" #include "base/debug/alias.h" #include "base/feature_list.h" -#include "base/memory/scoped_refptr.h" #include "base/notreached.h" #include "base/stl_util.h" #include "base/strings/string_util.h" @@ -632,7 +631,7 @@ } } -bool PDFiumEngine::HandleDocumentLoad(scoped_refptr<UrlLoader> loader) { +bool PDFiumEngine::HandleDocumentLoad(std::unique_ptr<UrlLoader> loader) { password_tries_remaining_ = kMaxPasswordTries; process_when_pending_request_complete_ = base::FeatureList::IsEnabled(features::kPdfIncrementalLoading);
diff --git a/pdf/pdfium/pdfium_engine.h b/pdf/pdfium/pdfium_engine.h index 6e1be60..fbed9e0 100644 --- a/pdf/pdfium/pdfium_engine.h +++ b/pdf/pdfium/pdfium_engine.h
@@ -93,7 +93,7 @@ std::vector<gfx::Rect>& ready, std::vector<gfx::Rect>& pending) override; void PostPaint() override; - bool HandleDocumentLoad(scoped_refptr<UrlLoader> loader) override; + bool HandleDocumentLoad(std::unique_ptr<UrlLoader> loader) override; bool HandleEvent(const InputEvent& event) override; uint32_t QuerySupportedPrintOutputFormats() override; void PrintBegin() override;
diff --git a/pdf/ppapi_migration/url_loader.h b/pdf/ppapi_migration/url_loader.h index 4c314dc..60db83f 100644 --- a/pdf/ppapi_migration/url_loader.h +++ b/pdf/ppapi_migration/url_loader.h
@@ -11,7 +11,6 @@ #include <string> #include "base/containers/span.h" -#include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" #include "base/optional.h" #include "pdf/ppapi_migration/callback.h" @@ -72,10 +71,11 @@ }; // Abstraction for a Blink or Pepper URL loader. -class UrlLoader : public base::RefCounted<UrlLoader> { +class UrlLoader { public: UrlLoader(const UrlLoader&) = delete; UrlLoader& operator=(const UrlLoader&) = delete; + virtual ~UrlLoader(); // Tries to grant the loader the capability to make unrestricted cross-origin // requests ("universal access," in `blink::SecurityOrigin` terms). Must be @@ -97,13 +97,10 @@ protected: UrlLoader(); - virtual ~UrlLoader(); UrlResponse& mutable_response() { return response_; } private: - friend class base::RefCounted<UrlLoader>; - UrlResponse response_; }; @@ -130,6 +127,7 @@ explicit BlinkUrlLoader(base::WeakPtr<Client> client); BlinkUrlLoader(const BlinkUrlLoader&) = delete; BlinkUrlLoader& operator=(const BlinkUrlLoader&) = delete; + ~BlinkUrlLoader() override; // UrlLoader: void GrantUniversalAccess() override; @@ -154,9 +152,6 @@ void DidFail(const blink::WebURLError& error) override; private: - // Private because the class is RefCounted. - ~BlinkUrlLoader() override; - base::WeakPtr<Client> client_; bool grant_universal_access_ = false; @@ -169,6 +164,7 @@ explicit PepperUrlLoader(pp::InstanceHandle plugin_instance); PepperUrlLoader(const PepperUrlLoader&) = delete; PepperUrlLoader& operator=(const PepperUrlLoader&) = delete; + ~PepperUrlLoader() override; // UrlLoader: void GrantUniversalAccess() override; @@ -180,9 +176,6 @@ void Close() override; private: - // Private because the class is RefCounted. - ~PepperUrlLoader() override; - void DidOpen(ResultCallback callback, int32_t result); pp::InstanceHandle plugin_instance_;
diff --git a/pdf/ppapi_migration/url_loader_unittest.cc b/pdf/ppapi_migration/url_loader_unittest.cc index 5916dbe5..e55deea 100644 --- a/pdf/ppapi_migration/url_loader_unittest.cc +++ b/pdf/ppapi_migration/url_loader_unittest.cc
@@ -9,7 +9,6 @@ #include "base/bind.h" #include "base/callback.h" -#include "base/memory/scoped_refptr.h" #include "base/memory/weak_ptr.h" #include "base/single_thread_task_runner.h" #include "base/test/mock_callback.h" @@ -70,7 +69,7 @@ ON_CALL(mock_client_, CreateAssociatedURLLoader(_)) .WillByDefault( Invoke(this, &BlinkUrlLoaderTest::FakeCreateAssociatedURLLoader)); - loader_ = base::MakeRefCounted<BlinkUrlLoader>(mock_client_.GetWeakPtr()); + loader_ = std::make_unique<BlinkUrlLoader>(mock_client_.GetWeakPtr()); } std::unique_ptr<blink::WebAssociatedURLLoader> FakeCreateAssociatedURLLoader( @@ -82,7 +81,7 @@ NiceMock<MockBlinkUrlLoaderClient> mock_client_; base::MockCallback<ResultCallback> mock_callback_; - scoped_refptr<BlinkUrlLoader> loader_; + std::unique_ptr<BlinkUrlLoader> loader_; std::unique_ptr<MockWebAssociatedURLLoader> mock_url_loader_ = std::make_unique<MockWebAssociatedURLLoader>();
diff --git a/pdf/preview_mode_client.cc b/pdf/preview_mode_client.cc index 756a620..b4511fe8 100644 --- a/pdf/preview_mode_client.cc +++ b/pdf/preview_mode_client.cc
@@ -6,11 +6,11 @@ #include <stdint.h> +#include <memory> #include <string> #include <utility> #include "base/callback.h" -#include "base/memory/scoped_refptr.h" #include "base/notreached.h" #include "pdf/document_layout.h" #include "pdf/ppapi_migration/url_loader.h" @@ -116,7 +116,7 @@ NOTREACHED(); } -scoped_refptr<UrlLoader> PreviewModeClient::CreateUrlLoader() { +std::unique_ptr<UrlLoader> PreviewModeClient::CreateUrlLoader() { NOTREACHED(); return nullptr; }
diff --git a/pdf/preview_mode_client.h b/pdf/preview_mode_client.h index f818a42..4b9c2e6 100644 --- a/pdf/preview_mode_client.h +++ b/pdf/preview_mode_client.h
@@ -62,7 +62,7 @@ void SubmitForm(const std::string& url, const void* data, int length) override; - scoped_refptr<UrlLoader> CreateUrlLoader() override; + std::unique_ptr<UrlLoader> CreateUrlLoader() override; std::vector<SearchStringResult> SearchString(const base::char16* string, const base::char16* term, bool case_sensitive) override;
diff --git a/pdf/test/test_client.cc b/pdf/test/test_client.cc index bdc0ab89..70aa727ef8 100644 --- a/pdf/test/test_client.cc +++ b/pdf/test/test_client.cc
@@ -4,7 +4,8 @@ #include "pdf/test/test_client.h" -#include "base/memory/scoped_refptr.h" +#include <memory> + #include "pdf/document_layout.h" #include "pdf/ppapi_migration/url_loader.h" @@ -35,7 +36,7 @@ return std::string(); } -scoped_refptr<UrlLoader> TestClient::CreateUrlLoader() { +std::unique_ptr<UrlLoader> TestClient::CreateUrlLoader() { return nullptr; }
diff --git a/pdf/test/test_client.h b/pdf/test/test_client.h index 48429bc..521bb04 100644 --- a/pdf/test/test_client.h +++ b/pdf/test/test_client.h
@@ -30,7 +30,7 @@ std::string Prompt(const std::string& question, const std::string& default_answer) override; std::string GetURL() override; - scoped_refptr<UrlLoader> CreateUrlLoader() override; + std::unique_ptr<UrlLoader> CreateUrlLoader() override; std::vector<SearchStringResult> SearchString(const base::char16* string, const base::char16* term, bool case_sensitive) override;
diff --git a/pdf/url_loader_wrapper_impl.cc b/pdf/url_loader_wrapper_impl.cc index afc6920..7266ef72 100644 --- a/pdf/url_loader_wrapper_impl.cc +++ b/pdf/url_loader_wrapper_impl.cc
@@ -9,6 +9,7 @@ #include <stdlib.h> #include <string.h> +#include <memory> #include <string> #include <utility> @@ -100,7 +101,8 @@ } // namespace -URLLoaderWrapperImpl::URLLoaderWrapperImpl(scoped_refptr<UrlLoader> url_loader) +URLLoaderWrapperImpl::URLLoaderWrapperImpl( + std::unique_ptr<UrlLoader> url_loader) : url_loader_(std::move(url_loader)) { SetHeadersFromLoader(); }
diff --git a/pdf/url_loader_wrapper_impl.h b/pdf/url_loader_wrapper_impl.h index c6a1ac5f..deb4b13 100644 --- a/pdf/url_loader_wrapper_impl.h +++ b/pdf/url_loader_wrapper_impl.h
@@ -10,7 +10,6 @@ #include <memory> #include <string> -#include "base/memory/scoped_refptr.h" #include "base/memory/weak_ptr.h" #include "base/timer/timer.h" #include "pdf/ppapi_migration/callback.h" @@ -23,7 +22,7 @@ class URLLoaderWrapperImpl : public URLLoaderWrapper { public: - explicit URLLoaderWrapperImpl(scoped_refptr<UrlLoader> url_loader); + explicit URLLoaderWrapperImpl(std::unique_ptr<UrlLoader> url_loader); URLLoaderWrapperImpl(const URLLoaderWrapperImpl&) = delete; URLLoaderWrapperImpl& operator=(const URLLoaderWrapperImpl&) = delete; ~URLLoaderWrapperImpl() override; @@ -59,7 +58,7 @@ void ReadResponseBodyImpl(ResultCallback callback); - scoped_refptr<UrlLoader> url_loader_; + std::unique_ptr<UrlLoader> url_loader_; std::string response_headers_; int content_length_ = -1;
diff --git a/services/device/BUILD.gn b/services/device/BUILD.gn index dc1fe3e..7cf18e9 100644 --- a/services/device/BUILD.gn +++ b/services/device/BUILD.gn
@@ -234,16 +234,19 @@ "//services/device/vibration", ] - if (!is_linux_without_udev && !is_android) { + if (!is_linux_without_udev) { sources += [ "hid/hid_connection_impl_unittest.cc", - "hid/hid_service_unittest.cc", "hid/input_service_linux_unittest.cc", "hid/test_report_descriptors.cc", "hid/test_report_descriptors.h", "public/cpp/hid/hid_device_filter_unittest.cc", "public/cpp/hid/hid_report_descriptor_unittest.cc", ] + if (!is_fuchsia) { + # Fuchsia does not currently implement HidService. + sources += [ "hid/hid_service_unittest.cc" ] + } if (!is_ios) { sources += [ "hid/hid_connection_unittest.cc" ] deps += [
diff --git a/services/device/nfc/android/java/src/org/chromium/device/nfc/NfcImpl.java b/services/device/nfc/android/java/src/org/chromium/device/nfc/NfcImpl.java index 1fc5cd3..8e3fe97 100644 --- a/services/device/nfc/android/java/src/org/chromium/device/nfc/NfcImpl.java +++ b/services/device/nfc/android/java/src/org/chromium/device/nfc/NfcImpl.java
@@ -533,11 +533,6 @@ private void processPendingWatchOperations() { if (mTagHandler == null || mClient == null || mWatchers.size() == 0) return; - // Skip reading if there is a pending push operation and ignoreRead flag is set. - if (mPendingPushOperation != null && mPendingPushOperation.ndefWriteOptions.ignoreRead) { - return; - } - if (mTagHandler.isTagOutOfRange()) { mTagHandler = null; return;
diff --git a/services/device/nfc/android/junit/src/org/chromium/device/nfc/NFCTest.java b/services/device/nfc/android/junit/src/org/chromium/device/nfc/NFCTest.java index b2f4a4b..2e8b0f3 100644 --- a/services/device/nfc/android/junit/src/org/chromium/device/nfc/NFCTest.java +++ b/services/device/nfc/android/junit/src/org/chromium/device/nfc/NFCTest.java
@@ -1736,7 +1736,6 @@ */ private NdefWriteOptions createNdefWriteOptions() { NdefWriteOptions pushOptions = new NdefWriteOptions(); - pushOptions.ignoreRead = false; pushOptions.overwrite = true; return pushOptions; }
diff --git a/services/device/public/mojom/nfc.mojom b/services/device/public/mojom/nfc.mojom index f45e07c7..c45dc3ef 100644 --- a/services/device/public/mojom/nfc.mojom +++ b/services/device/public/mojom/nfc.mojom
@@ -97,14 +97,9 @@ }; struct NDEFWriteOptions { - // Only the case of |ignore_read| being |true| matters: while this push - // operation is pending, even a NFC tag comes in proximity range, do not read - // it for all active watchers. - bool ignore_read; - // Only the case of |overwrite| being |false| matters: the push operation will - // read the NFC tag regardless of |ignore_read| to determine if it has NDEF - // records on it, and if yes, do not execute write. + // read the NFC tag to determine if it has NDEF records on it, and if yes, do + // not execute write. bool overwrite; };
diff --git a/services/network/public/cpp/content_security_policy/csp_context.h b/services/network/public/cpp/content_security_policy/csp_context.h index 971752c..968b39da 100644 --- a/services/network/public/cpp/content_security_policy/csp_context.h +++ b/services/network/public/cpp/content_security_policy/csp_context.h
@@ -18,7 +18,7 @@ // A CSPContext represents the Document where the Content-Security-Policy are // checked. One must define via its virtual methods how to report violations // and what is the set of scheme that bypass the CSP. Its main implementation -// is in content/browser/frame_host/render_frame_host_impl.h +// is in content/browser/renderer_host/render_frame_host_impl.h class COMPONENT_EXPORT(NETWORK_CPP) CSPContext { public: // This enum represents what set of policies should be checked by
diff --git a/services/network/public/cpp/features.cc b/services/network/public/cpp/features.cc index d09afe0..f5cab38 100644 --- a/services/network/public/cpp/features.cc +++ b/services/network/public/cpp/features.cc
@@ -251,5 +251,9 @@ constexpr base::FeatureParam<double> kSCTAuditingSamplingRate{ &kSCTAuditing, "sampling_rate", 0.0}; +// Enables usage of First Party Sets to determine cookie availability. +constexpr base::Feature kFirstPartySets{"FirstPartySets", + base::FEATURE_DISABLED_BY_DEFAULT}; + } // namespace features } // namespace network
diff --git a/services/network/public/cpp/features.h b/services/network/public/cpp/features.h index 0cc0959..bf27faf 100644 --- a/services/network/public/cpp/features.h +++ b/services/network/public/cpp/features.h
@@ -102,6 +102,9 @@ COMPONENT_EXPORT(NETWORK_CPP) extern const base::FeatureParam<double> kSCTAuditingSamplingRate; +COMPONENT_EXPORT(NETWORK_CPP) +extern const base::Feature kFirstPartySets; + } // namespace features } // namespace network
diff --git a/services/network/public/mojom/web_sandbox_flags.mojom b/services/network/public/mojom/web_sandbox_flags.mojom index 04d3d5b..f4927ca7 100644 --- a/services/network/public/mojom/web_sandbox_flags.mojom +++ b/services/network/public/mojom/web_sandbox_flags.mojom
@@ -6,7 +6,7 @@ // Enum types for the sandbox attributes of the main resource. // TODO(https://crbug.com/1041376): Parse the flags in the network service. // -// See content/browser/frame_host/sandbox_flags.md for more details about how +// See content/browser/renderer_host/sandbox_flags.md for more details about how // the web-layer components (i.e. //content and Blink) consume and apply these // flags.
diff --git a/testing/buildbot/chromium.perf.fyi.json b/testing/buildbot/chromium.perf.fyi.json index 6d321246..e8e49a2 100644 --- a/testing/buildbot/chromium.perf.fyi.json +++ b/testing/buildbot/chromium.perf.fyi.json
@@ -110,10 +110,6 @@ ], "isolate_name": "performance_test_suite", "merge": { - "args": [ - "--lightweight", - "--skip-perf" - ], "script": "//tools/perf/process_perf_results.py" }, "name": "performance_test_suite", @@ -149,14 +145,6 @@ } ] }, - "android-pixel2-processor-perf-fyi": { - "merge": { - "args": [ - "--lightweight" - ], - "script": "//tools/perf/process_perf_results.py" - } - }, "chromeos-kevin-perf-fyi": { "isolated_scripts": [ { @@ -216,10 +204,6 @@ ], "isolate_name": "performance_test_suite", "merge": { - "args": [ - "--lightweight", - "--skip-perf" - ], "script": "//tools/perf/process_perf_results.py" }, "name": "performance_test_suite", @@ -254,14 +238,6 @@ } ] }, - "linux-processor-perf-fyi": { - "merge": { - "args": [ - "--lightweight" - ], - "script": "//tools/perf/process_perf_results.py" - } - }, "win-10_laptop_low_end-perf_HP-Candidate": { "isolated_scripts": [ { @@ -275,10 +251,6 @@ ], "isolate_name": "performance_test_suite", "merge": { - "args": [ - "--lightweight", - "--skip-perf" - ], "script": "//tools/perf/process_perf_results.py" }, "name": "performance_test_suite", @@ -312,13 +284,5 @@ } } ] - }, - "win-10_laptop_low_end-perf_HP-Candidate-processor": { - "merge": { - "args": [ - "--lightweight" - ], - "script": "//tools/perf/process_perf_results.py" - } } }
diff --git a/testing/buildbot/filters/fuchsia.services_unittests.filter b/testing/buildbot/filters/fuchsia.services_unittests.filter index 0163191d..ea9f8e9 100644 --- a/testing/buildbot/filters/fuchsia.services_unittests.filter +++ b/testing/buildbot/filters/fuchsia.services_unittests.filter
@@ -1,28 +1,5 @@ -# https://crbug.com/925652 - There are no |services_|. --HidServiceTest.GetDevices - -# https://crbug.com/925652 - |num_sockets| expectations mismatch. --NetworkContextTest.PreconnectFour --NetworkContextTest.PreconnectTwo - -# https://crbug.com/925653 - IsTracingEnabled() expectations not met. +# https://crbug.com/1125854 - IsTracingEnabled() expectations not met. -TracingConsumerTest.NotifiesOnTracingEnabledWaitsFor* -# https://crbug.com/925653 - Flaky OOM and virtual method crashes. --TracingConsumerTest.FlushProducers --TracingConsumerTest.LargeDataSize --TracingConsumerTest.PrivacyFilterConfig --TracingConsumerTest.PrivacyFilterConfigInJson --TracingConsumerTest.TestConsumerPriority - -# https://crbug.com/925653 - Second socket receives too many packets. +# https://crbug.com/1125855 - Second socket receives too many packets. -UDPSocketTest.JoinMulticastGroup - -# https://crbug.com/925653 - Unexpected address-in-use. --TCPBoundSocketTest.ListenError - -# https://crbug.com/976319 - Flakily times-out due to virtualization overhead. --SimpleURLLoaderTest.OnUploadProgressCallback/* - -# https://crbug.com/986544 - Flakes with mismatched state expectations. --URLLoaderTest.ResourceSchedulerIntegration
diff --git a/testing/buildbot/gn_isolate_map.pyl b/testing/buildbot/gn_isolate_map.pyl index 705846a8..3bb477a 100644 --- a/testing/buildbot/gn_isolate_map.pyl +++ b/testing/buildbot/gn_isolate_map.pyl
@@ -519,6 +519,7 @@ "../../chrome/test/chromedriver/test/run_webdriver_tests.py", "-v", "--chromedriver=chromedriver", + "--log-path=${ISOLATED_OUTDIR}/chromedriver.log", "--output-dir=${ISOLATED_OUTDIR}", "--test-path=../../third_party/blink/web_tests/external/wpt/webdriver/tests/", ],
diff --git a/testing/scripts/representative_perf_test_data/representatives_frame_times_upper_limit.json b/testing/scripts/representative_perf_test_data/representatives_frame_times_upper_limit.json index 91466a0..81e6cdf7 100644 --- a/testing/scripts/representative_perf_test_data/representatives_frame_times_upper_limit.json +++ b/testing/scripts/representative_perf_test_data/representatives_frame_times_upper_limit.json
@@ -86,7 +86,9 @@ "balls_javascript_canvas": { "ci_095": 1.324, "avg": 39.475, - "cpu_wall_time_ratio": 0.556 + "cpu_wall_time_ratio": 0.556, + "experimental": true, + "_comment": "crbug.com/1122037" }, "transform_transitions_js_block": { "ci_095": 0.366, @@ -101,7 +103,9 @@ "fill_shapes": { "ci_095": 0.949, "avg": 32.306, - "cpu_wall_time_ratio": 0.539 + "cpu_wall_time_ratio": 0.539, + "experimental": true, + "_comment": "crbug.com/1122037" }, "css_value_type_shadow": { "ci_095": 18.3,
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index b811187..172a3188 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -661,21 +661,6 @@ ] } ], - "BackgroundPurgeOnMac": [ - { - "platforms": [ - "mac" - ], - "experiments": [ - { - "name": "BackgrounPurgeOnMac", - "enable_features": [ - "PurgeRendererMemoryWhenBackgrounded" - ] - } - ] - } - ], "BackgroundSync": [ { "platforms": [ @@ -930,26 +915,6 @@ ] } ], - "CacheStorageEagerReading": [ - { - "platforms": [ - "windows", - "mac", - "chromeos", - "linux", - "android", - "android_weblayer" - ], - "experiments": [ - { - "name": "Enabled2", - "enable_features": [ - "CacheStorageEagerReading" - ] - } - ] - } - ], "CacheStorageSequenceChromeOS": [ { "platforms": [ @@ -1304,6 +1269,35 @@ ] } ], + "ClientSideDetectionModel": [ + { + "platforms": [ + "chromeos", + "linux", + "mac" + ], + "experiments": [ + { + "name": "EnabledWithVisualModel", + "params": { + "ModelNum": "5" + }, + "enable_features": [ + "ClientSideDetectionModel" + ] + }, + { + "name": "EnabledDomOnly", + "params": { + "ModelNum": "4" + }, + "enable_features": [ + "ClientSideDetectionModel" + ] + } + ] + } + ], "CodeCacheDeletionWithoutFilter": [ { "platforms": [ @@ -2154,12 +2148,12 @@ { "name": "Enabled", "params": { - "BlockExtensionList": "mix_dl_blocked_for_testing", - "SilentBlockExtensionList": "mix_dl_silently_blocked_for_testing", + "BlockExtensionList": "", + "SilentBlockExtensionList": "exe,scr,msi,vb,dmg,pkg,crx", "TreatBlockListAsAllowlist": "false", "TreatSilentBlockListAsAllowlist": "false", "TreatWarnListAsAllowlist": "false", - "WarnExtensionList": "exe,scr,msi,vb,dmg,pkg,crx" + "WarnExtensionList": "zip,iso,rar,7z,tar,gz,bz2" }, "enable_features": [ "TreatUnsafeDownloadsAsActive" @@ -4923,6 +4917,41 @@ ] } ], + "PdfPartialLoading": [ + { + "platforms": [ + "chromeos", + "linux", + "mac", + "windows" + ], + "experiments": [ + { + "name": "Disabled", + "disable_features": [ + "PdfIncrementalLoading", + "PdfPartialLoading" + ] + }, + { + "name": "IncrementalOnly", + "enable_features": [ + "PdfIncrementalLoading" + ], + "disable_features": [ + "PdfPartialLoading" + ] + }, + { + "name": "Enabled", + "enable_features": [ + "PdfIncrementalLoading", + "PdfPartialLoading" + ] + } + ] + } + ], "PerProcessReclaim": [ { "platforms": [ @@ -7155,27 +7184,6 @@ ] } ], - "VisualClientSideDetectionModel": [ - { - "platforms": [ - "chromeos", - "linux", - "mac", - "windows" - ], - "experiments": [ - { - "name": "Enabled", - "params": { - "ModelNum": "5" - }, - "enable_features": [ - "ClientSideDetectionModel" - ] - } - ] - } - ], "VizForWebView": [ { "platforms": [
diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/features.cc index 29c41e9..bb172b6 100644 --- a/third_party/blink/common/features.cc +++ b/third_party/blink/common/features.cc
@@ -143,12 +143,11 @@ // Perform a memory purge after a renderer is backgrounded. Formerly labelled as // the "PurgeAndSuspend" experiment. // -// TODO(adityakeerthi): Disabled by default on Mac and Android for historical +// TODO(https://crbug.com/926186): Disabled by default on Android for historical // reasons. Consider enabling by default if experiment results are positive. -// https://crbug.com/926186 const base::Feature kPurgeRendererMemoryWhenBackgrounded { "PurgeRendererMemoryWhenBackgrounded", -#if defined(OS_MAC) || defined(OS_ANDROID) +#if defined(OS_ANDROID) base::FEATURE_DISABLED_BY_DEFAULT #else base::FEATURE_ENABLED_BY_DEFAULT
diff --git a/third_party/blink/public/web/web_view.h b/third_party/blink/public/web/web_view.h index 1c61630..965eb09 100644 --- a/third_party/blink/public/web/web_view.h +++ b/third_party/blink/public/web/web_view.h
@@ -282,11 +282,6 @@ // Asks the browser process to activate this web view. virtual void Focus() = 0; - // Update the target url and tell the browser that the target URL has changed. - // If |url| is empty, show |fallback_url|. - virtual void UpdateTargetURL(const WebURL& url, - const WebURL& fallback_url) = 0; - // Sets the ratio as computed by computePageScaleConstraints. // TODO(oshima): Remove this once the device scale factor implementation is // fully migrated to use zooming mechanism.
diff --git a/third_party/blink/public/web/web_view_client.h b/third_party/blink/public/web/web_view_client.h index dbf2e36..2e0745c 100644 --- a/third_party/blink/public/web/web_view_client.h +++ b/third_party/blink/public/web/web_view_client.h
@@ -44,7 +44,6 @@ namespace blink { class WebPagePopup; -class WebURL; class WebURLRequest; class WebView; struct WebRect; @@ -103,12 +102,6 @@ // UI ------------------------------------------------------------------ - // Called when hovering over an anchor with the given URL. - virtual void SetMouseOverURL(const WebURL&) {} - - // Called when keyboard focus switches to an anchor with the given URL. - virtual void SetKeyboardFocusURL(const WebURL&) {} - // Called to determine if drag-n-drop operations may initiate a page // navigation. virtual bool AcceptsLoadDrops() { return true; }
diff --git a/third_party/blink/renderer/core/css/resolver/style_builder_converter.cc b/third_party/blink/renderer/core/css/resolver/style_builder_converter.cc index 472fbbf..6a2faf6 100644 --- a/third_party/blink/renderer/core/css/resolver/style_builder_converter.cc +++ b/third_party/blink/renderer/core/css/resolver/style_builder_converter.cc
@@ -1110,8 +1110,7 @@ result = primitive_value.ComputeLength<float>(state.CssToLengthConversionData()); } - double zoomed_result = state.StyleRef().EffectiveZoom() * result; - if (zoomed_result > 0.0 && zoomed_result < 1.0) + if (result > 0.0 && result < 1.0) return 1.0; return clampTo<float>(result, defaultMinimumForClamp<float>(), defaultMaximumForClamp<float>());
diff --git a/third_party/blink/renderer/core/css/resolver/style_cascade.cc b/third_party/blink/renderer/core/css/resolver/style_cascade.cc index ef3bb8c..dd12921 100644 --- a/third_party/blink/renderer/core/css/resolver/style_cascade.cc +++ b/third_party/blink/renderer/core/css/resolver/style_cascade.cc
@@ -550,6 +550,8 @@ int bg_color_alpha = style->VisitedDependentColor(GetCSSPropertyBackgroundColor()).Alpha(); + int visited_bg_color_alpha = + style->ResolvedColor(style->InternalVisitedBackgroundColor()).Alpha(); const SVGComputedStyle& svg_style = style->SvgStyle(); MaybeForceColor(GetCSSPropertyColor(), style->GetColor()); @@ -604,6 +606,10 @@ style->SetBackgroundColor( StyleColor(style->BackgroundColor().ResolveWithAlpha( style->GetCurrentColor(), WebColorScheme::kLight, bg_color_alpha))); + style->SetInternalVisitedBackgroundColor( + StyleColor(style->InternalVisitedBackgroundColor().ResolveWithAlpha( + style->GetCurrentColor(), WebColorScheme::kLight, + visited_bg_color_alpha))); } void StyleCascade::MaybeForceColor(const CSSProperty& property, @@ -626,8 +632,10 @@ CascadePriority* p = map_.Find(name, CascadeOrigin::kUserAgent); if (p) return ValueAt(match_result_, p->GetPosition()); - if (name.Id() == CSSPropertyID::kBackgroundColor) + if (name.Id() == CSSPropertyID::kBackgroundColor || + name.Id() == CSSPropertyID::kInternalVisitedBackgroundColor) { return CSSIdentifierValue::Create(CSSValueID::kCanvas); + } return cssvalue::CSSUnsetValue::Create(); }
diff --git a/third_party/blink/renderer/core/css/resolver/style_cascade_test.cc b/third_party/blink/renderer/core/css/resolver/style_cascade_test.cc index db3d8dc..8937b095 100644 --- a/third_party/blink/renderer/core/css/resolver/style_cascade_test.cc +++ b/third_party/blink/renderer/core/css/resolver/style_cascade_test.cc
@@ -3530,4 +3530,29 @@ EXPECT_EQ("-5s", CssTextAt(map, "animation-delay")); } +TEST_F(StyleCascadeTest, ForcedVisitedBackgroundColor) { + ScopedForcedColorsForTest scoped_feature(true); + ColorSchemeHelper color_scheme_helper(GetDocument()); + color_scheme_helper.SetForcedColors(GetDocument(), ForcedColors::kActive); + UpdateAllLifecyclePhasesForTest(); + + TestCascade cascade(GetDocument()); + cascade.State().Style()->SetInsideLink(EInsideLink::kInsideVisitedLink); + cascade.Add(ParseDeclarationBlock("background-color:#aabbccdd"), + CascadeOrigin::kAuthor, CSSSelector::kMatchVisited); + cascade.Apply(); + + Color forced_bg_color = + StyleColor(CSSValueID::kCanvas).Resolve(Color(), WebColorScheme::kLight); + Color expected_bg_color = + Color(forced_bg_color.Red(), forced_bg_color.Green(), + forced_bg_color.Blue(), 0xdd); + + // Verify that the visited background color alpha channel is preserved in + // Forced Colors Mode. + EXPECT_EQ( + expected_bg_color, + cascade.State().Style()->InternalVisitedBackgroundColor().GetColor()); +} + } // namespace blink
diff --git a/third_party/blink/renderer/core/exported/web_view_impl.cc b/third_party/blink/renderer/core/exported/web_view_impl.cc index 53e01585d..57a29ee2 100644 --- a/third_party/blink/renderer/core/exported/web_view_impl.cc +++ b/third_party/blink/renderer/core/exported/web_view_impl.cc
@@ -372,7 +372,7 @@ void WebViewImpl::HandleMouseLeave(LocalFrame& main_frame, const WebMouseEvent& event) { - web_view_client_->SetMouseOverURL(WebURL()); + SetMouseOverURL(WebURL()); PageWidgetEventHandler::HandleMouseLeave(main_frame, event); } @@ -1521,6 +1521,16 @@ web_widget_ = widget; } +void WebViewImpl::SetMouseOverURL(const KURL& url) { + mouse_over_url_ = url; + UpdateTargetURL(mouse_over_url_, focus_url_); +} + +void WebViewImpl::SetKeyboardFocusURL(const KURL& url) { + focus_url_ = url; + UpdateTargetURL(focus_url_, mouse_over_url_); +} + WebFrameWidgetBase* WebViewImpl::MainFrameWidgetBase() { return web_widget_; } @@ -2958,30 +2968,30 @@ // see |ParamTraits<GURL>|. if (latest_url.GetString().length() > url::kMaxURLChars) latest_url = KURL(); - UpdateTargetURLInBrowser(latest_url); + SendUpdatedTargetURLToBrowser(latest_url); target_url_ = latest_url; target_url_status_ = TARGET_INFLIGHT; } } -void WebViewImpl::UpdateTargetURLInBrowser(const KURL& target_url) { +void WebViewImpl::SendUpdatedTargetURLToBrowser(const KURL& target_url) { if (GetPage()->MainFrame()->IsLocalFrame()) { DCHECK(local_main_frame_host_remote_); local_main_frame_host_remote_->UpdateTargetURL( - target_url, WTF::Bind(&WebViewImpl::TargetURLUpdated, + target_url, WTF::Bind(&WebViewImpl::TargetURLUpdatedInBrowser, weak_ptr_factory_.GetWeakPtr())); } else { DCHECK(remote_main_frame_host_remote_); remote_main_frame_host_remote_->UpdateTargetURL( - target_url, WTF::Bind(&WebViewImpl::TargetURLUpdated, + target_url, WTF::Bind(&WebViewImpl::TargetURLUpdatedInBrowser, weak_ptr_factory_.GetWeakPtr())); } } -void WebViewImpl::TargetURLUpdated() { +void WebViewImpl::TargetURLUpdatedInBrowser() { // Check if there is a targeturl waiting to be sent. if (target_url_status_ == TARGET_PENDING) - UpdateTargetURLInBrowser(pending_target_url_); + SendUpdatedTargetURLToBrowser(pending_target_url_); target_url_status_ = TARGET_NONE; }
diff --git a/third_party/blink/renderer/core/exported/web_view_impl.h b/third_party/blink/renderer/core/exported/web_view_impl.h index b838f6e870..94277a4 100644 --- a/third_party/blink/renderer/core/exported/web_view_impl.h +++ b/third_party/blink/renderer/core/exported/web_view_impl.h
@@ -189,7 +189,6 @@ void UpdatePreferredSize() override; void EnablePreferredSizeChangedMode() override; void Focus() override; - void UpdateTargetURL(const WebURL& url, const WebURL& fallback_url) override; void SetDeviceScaleFactor(float) override; void SetZoomFactorForDeviceScaleFactor(float) override; float ZoomFactorForDeviceScaleFactor() override { @@ -453,6 +452,12 @@ void SetMainFrameWidgetBase(WebViewFrameWidget* widget); WebFrameWidgetBase* MainFrameWidgetBase(); + // Called when hovering over an anchor with the given URL. + void SetMouseOverURL(const KURL&); + + // Called when keyboard focus switches to an anchor with the given URL. + void SetKeyboardFocusURL(const KURL&); + private: FRIEND_TEST_ALL_PREFIXES(WebFrameTest, DivScrollIntoEditableTest); FRIEND_TEST_ALL_PREFIXES(WebFrameTest, @@ -498,8 +503,14 @@ bool SelectionBounds(WebRect& anchor, WebRect& focus) const; WebURL GetURLForDebugTrace(); - void UpdateTargetURLInBrowser(const KURL& target_url); - void TargetURLUpdated(); + // Update the target url locally and tell the browser that the target URL has + // changed. If |url| is empty, show |fallback_url|. + void UpdateTargetURL(const WebURL& url, const WebURL& fallback_url); + + // Helper functions to send the updated target URL to the right render frame + // in the browser process, and to handle its associated reply message. + void SendUpdatedTargetURLToBrowser(const KURL& target_url); + void TargetURLUpdatedInBrowser(); void SetPageScaleFactorAndLocation(float scale, bool is_pinch_gesture_active, @@ -645,6 +656,12 @@ // The next target URL we want to send to the browser. KURL pending_target_url_; + // The URL the user's mouse is hovering over. + KURL mouse_over_url_; + + // The URL that has keyboard focus. + KURL focus_url_; + // Keeps track of the current zoom level. 0 means no zoom, positive numbers // mean zoom in, negative numbers mean zoom out. double zoom_level_ = 0.;
diff --git a/third_party/blink/renderer/core/feature_policy/document_policy_parser.cc b/third_party/blink/renderer/core/feature_policy/document_policy_parser.cc index fd4e78d..a1bd473f 100644 --- a/third_party/blink/renderer/core/feature_policy/document_policy_parser.cc +++ b/third_party/blink/renderer/core/feature_policy/document_policy_parser.cc
@@ -224,7 +224,8 @@ if (parsed_feature.feature == mojom::blink::DocumentPolicyFeature::kDefault) { - default_endpoint = *parsed_feature.endpoint_group; + if (parsed_feature.endpoint_group) + default_endpoint = *parsed_feature.endpoint_group; continue; }
diff --git a/third_party/blink/renderer/core/feature_policy/document_policy_parser_test.cc b/third_party/blink/renderer/core/feature_policy/document_policy_parser_test.cc index f1bcd7e..f8041001 100644 --- a/third_party/blink/renderer/core/feature_policy/document_policy_parser_test.cc +++ b/third_party/blink/renderer/core/feature_policy/document_policy_parser_test.cc
@@ -274,7 +274,26 @@ /* endpoint_map */ {}}, /* messages */ {}, }, - + { + "MissingEndpointGroupForDefaultFeature1", + "*", + /* parsed_policy */ + { + /* feature_state */ {}, + /* endpoint_map */ {}, + }, + /* messages */ {}, + }, + { + "MissingEndpointGroupForDefaultFeature2", + "*,f-bool=?0,f-double=1;report-to=default", + /* parsed_policy */ + {/* feature_state */ { + {kBoolFeature, PolicyValue::CreateBool(false)}, + {kDoubleFeature, PolicyValue::CreateDecDouble(1.0)}}, + /* endpoint_map */ {{kDoubleFeature, "default"}}}, + /* messages */ {}, + }, // // Parse invalid policies. //
diff --git a/third_party/blink/renderer/core/html/canvas/canvas_rendering_context_host.cc b/third_party/blink/renderer/core/html/canvas/canvas_rendering_context_host.cc index c9e1ef8d..b4aaa68 100644 --- a/third_party/blink/renderer/core/html/canvas/canvas_rendering_context_host.cc +++ b/third_party/blink/renderer/core/html/canvas/canvas_rendering_context_host.cc
@@ -128,7 +128,7 @@ DCHECK(LowLatencyEnabled()); provider = CanvasResourceProvider::CreatePassThroughProvider( Size(), FilterQuality(), ColorParams(), - SharedGpuContext::ContextProviderWrapper(), std::move(dispatcher), + SharedGpuContext::ContextProviderWrapper(), dispatcher, RenderingContext()->IsOriginTopLeft()); } if (!provider) { @@ -168,8 +168,7 @@ if (!provider) { provider = CanvasResourceProvider::CreateSharedBitmapProvider( Size(), FilterQuality(), ColorParams(), - CanvasResourceProvider::ShouldInitialize::kCallClear, - std::move(dispatcher)); + CanvasResourceProvider::ShouldInitialize::kCallClear, dispatcher); } if (!provider) { provider = CanvasResourceProvider::CreateBitmapProvider( @@ -209,7 +208,7 @@ provider = CanvasResourceProvider::CreateSwapChainProvider( Size(), FilterQuality(), ColorParams(), CanvasResourceProvider::ShouldInitialize::kCallClear, - SharedGpuContext::ContextProviderWrapper(), std::move(dispatcher), + SharedGpuContext::ContextProviderWrapper(), dispatcher, is_origin_top_left); } // If SwapChain failed or it was not possible, we will try a SharedImage @@ -258,8 +257,7 @@ if (!provider) { provider = CanvasResourceProvider::CreateSharedBitmapProvider( Size(), FilterQuality(), ColorParams(), - CanvasResourceProvider::ShouldInitialize::kCallClear, - std::move(dispatcher)); + CanvasResourceProvider::ShouldInitialize::kCallClear, dispatcher); } if (!provider) { provider = CanvasResourceProvider::CreateBitmapProvider(
diff --git a/third_party/blink/renderer/core/layout/layout_box.cc b/third_party/blink/renderer/core/layout/layout_box.cc index c04e9b9..c747213 100644 --- a/third_party/blink/renderer/core/layout/layout_box.cc +++ b/third_party/blink/renderer/core/layout/layout_box.cc
@@ -1668,6 +1668,18 @@ return MinMaxSizes(); } +MinMaxSizes LayoutBox::IntrinsicLogicalWidths(MinMaxSizesType type) const { + if (type == MinMaxSizesType::kContent && StyleRef().AspectRatio()) { + MinMaxSizes sizes; + if (ComputeLogicalWidthFromAspectRatio(&sizes.min_size)) { + sizes.max_size = sizes.min_size; + return sizes; + } + } + const_cast<LayoutBox*>(this)->UpdateCachedIntrinsicLogicalWidthsIfNeeded(); + return intrinsic_logical_widths_; +} + void LayoutBox::UpdateCachedIntrinsicLogicalWidthsIfNeeded() { if (!IntrinsicLogicalWidthsDirty()) return; @@ -3538,7 +3550,7 @@ bool LayoutBox::ComputeLogicalWidthFromAspectRatio( LayoutUnit* out_logical_width) const { LayoutUnit logical_height_for_ar = kIndefiniteSize; - if (StyleRef().AspectRatio() && StyleRef().LogicalWidth().IsAuto() && + if (StyleRef().AspectRatio() && (StyleRef().LogicalHeight().IsFixed() || StyleRef().LogicalHeight().IsPercentOrCalc())) { logical_height_for_ar = ComputeLogicalHeightUsing( @@ -3618,7 +3630,8 @@ ContainerWidthInInlineDirection(); LayoutBlock* cb = ContainingBlock(); - if (ComputeLogicalWidthFromAspectRatio(&computed_values.extent_)) { + if (StyleRef().LogicalWidth().IsAuto() && + ComputeLogicalWidthFromAspectRatio(&computed_values.extent_)) { /* we're good */ } else if (treat_as_replaced) { computed_values.extent_ = @@ -3722,7 +3735,10 @@ FillAvailableMeasure(available_logical_width)); } - MinMaxSizes sizes = IntrinsicLogicalWidths(); + MinMaxSizesType type = MinMaxSizesType::kContent; + if (logical_width_length.IsMinIntrinsic()) + type = MinMaxSizesType::kIntrinsic; + MinMaxSizes sizes = IntrinsicLogicalWidths(type); if (logical_width_length.IsMinContent() || logical_width_length.IsMinIntrinsic())
diff --git a/third_party/blink/renderer/core/layout/layout_box.h b/third_party/blink/renderer/core/layout/layout_box.h index 7aa3b2e5..ee69d70 100644 --- a/third_party/blink/renderer/core/layout/layout_box.h +++ b/third_party/blink/renderer/core/layout/layout_box.h
@@ -1713,10 +1713,8 @@ virtual MinMaxSizes ComputeIntrinsicLogicalWidths() const = 0; // Returns the (maybe cached) intrinsic logical widths for this layout box. - MinMaxSizes IntrinsicLogicalWidths() const { - const_cast<LayoutBox*>(this)->UpdateCachedIntrinsicLogicalWidthsIfNeeded(); - return intrinsic_logical_widths_; - } + MinMaxSizes IntrinsicLogicalWidths( + MinMaxSizesType type = MinMaxSizesType::kContent) const; // If |IntrinsicLogicalWidthsDirty()| is true, recalculates the intrinsic // logical widths.
diff --git a/third_party/blink/renderer/core/layout/layout_object_child_list.cc b/third_party/blink/renderer/core/layout/layout_object_child_list.cc index 63b241f3..279d65e 100644 --- a/third_party/blink/renderer/core/layout/layout_object_child_list.cc +++ b/third_party/blink/renderer/core/layout/layout_object_child_list.cc
@@ -242,12 +242,8 @@ if (new_child->WasNotifiedOfSubtreeChange()) owner->NotifyAncestorsOfSubtreeChange(); - if (owner->ForceLegacyLayout()) { + if (owner->ForceLegacyLayout() && !new_child->IsLayoutNGObject()) new_child->SetForceLegacyLayout(); - // TODO(crbug.com/943574): This would be a great place to DCHECK that the - // child isn't an NG object, but there are unfortunately cases where this - // actually happens. - } new_child->SetNeedsLayoutAndIntrinsicWidthsRecalc( layout_invalidation_reason::kAddedToLayout);
diff --git a/third_party/blink/renderer/core/layout/min_max_sizes.h b/third_party/blink/renderer/core/layout/min_max_sizes.h index 721ecec..129ddc3 100644 --- a/third_party/blink/renderer/core/layout/min_max_sizes.h +++ b/third_party/blink/renderer/core/layout/min_max_sizes.h
@@ -12,6 +12,11 @@ namespace blink { +// min/max-content take the CSS aspect-ratio property into account. +// In some cases that's undesirable; this enum lets you choose not +// to do that using |kIntrinsic|. +enum class MinMaxSizesType { kContent, kIntrinsic }; + // A struct that holds a pair of two sizes, a "min" size and a "max" size. // Useful for holding a {min,max}-content size pair or a // {min,max}-{width,height}.
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items_builder.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items_builder.cc index 78127ba..8fd4ffd 100644 --- a/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items_builder.cc +++ b/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items_builder.cc
@@ -159,6 +159,7 @@ continue; } + const unsigned children_count = child.children_count; // Children of inline boxes are flattened and added to |items_|, with the // count of descendant items to preserve the tree structure. // @@ -167,14 +168,14 @@ items_.emplace_back(child.rect.offset, std::move(child), writing_mode); // Add all children, including their desendants, skipping this item. - CHECK_GE(child.children_count, 1u); // 0 will loop infinitely. - NGLogicalLineItem* end_child_iter = child_iter + child.children_count; + CHECK_GE(children_count, 1u); // 0 will loop infinitely. + NGLogicalLineItem* end_child_iter = child_iter + children_count; CHECK_LE(end_child_iter - child_begin, child_end - child_begin); AddItems(child_iter + 1, end_child_iter); child_iter = end_child_iter; // All children are added. Compute how many items are actually added. The - // number of items added maybe different from |child.children_count|. + // number of items added may be different from |children_count|. const wtf_size_t item_count = items_.size() - box_start_index; NGFragmentItem& box_item = items_[box_start_index].item; DCHECK_EQ(box_item.DescendantsCount(), 1u);
diff --git a/third_party/blink/renderer/core/layout/ng/ng_block_node.cc b/third_party/blink/renderer/core/layout/ng/ng_block_node.cc index 0a3d370..b2d27a8 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_block_node.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_block_node.cc
@@ -806,8 +806,9 @@ (input.percentage_resolution_block_size == box_->IntrinsicLogicalWidthsPercentageResolutionBlockSize() || !box_->IntrinsicLogicalWidthsChildDependsOnPercentageBlockSize())) { - MinMaxSizes sizes = box_->IsTable() ? box_->PreferredLogicalWidths() - : box_->IntrinsicLogicalWidths(); + MinMaxSizes sizes = box_->IsTable() + ? box_->PreferredLogicalWidths() + : box_->IntrinsicLogicalWidths(input.type); bool depends_on_percentage_block_size = box_->IntrinsicLogicalWidthsDependsOnPercentageBlockSize(); return {sizes, depends_on_percentage_block_size}; @@ -835,8 +836,9 @@ // depend on the *input* %-block-size. if (can_use_cached_intrinsic_inline_sizes && !cache_depends_on_percentage_block_size) { - MinMaxSizes sizes = box_->IsTable() ? box_->PreferredLogicalWidths() - : box_->IntrinsicLogicalWidths(); + MinMaxSizes sizes = box_->IsTable() + ? box_->PreferredLogicalWidths() + : box_->IntrinsicLogicalWidths(input.type); return {sizes, cache_depends_on_percentage_block_size}; } @@ -919,8 +921,9 @@ // meaning for tables. // // Due to this the min/max content contribution is their min/max content size. - MinMaxSizes sizes = box_->IsTable() ? box_->PreferredLogicalWidths() - : box_->IntrinsicLogicalWidths(); + MinMaxSizes sizes = box_->IsTable() + ? box_->PreferredLogicalWidths() + : box_->IntrinsicLogicalWidths(input.type); if (needs_size_reset) box_->ClearOverrideContainingBlockContentSize();
diff --git a/third_party/blink/renderer/core/layout/ng/ng_layout_input_node.h b/third_party/blink/renderer/core/layout/ng/ng_layout_input_node.h index 585c623..ab52557 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_layout_input_node.h +++ b/third_party/blink/renderer/core/layout/ng/ng_layout_input_node.h
@@ -27,11 +27,6 @@ struct MinMaxSizes; struct PhysicalSize; -// min/max-content take the CSS aspect-ratio property into account. -// In some cases that's undesirable; this enum lets you choose not -// to do that using |kIntrinsic|. -enum class MinMaxSizesType { kContent, kIntrinsic }; - // The input to the min/max inline size calculation algorithm for child nodes. // Child nodes within the same formatting context need to know which floats are // beside them.
diff --git a/third_party/blink/renderer/core/page/chrome_client_impl.cc b/third_party/blink/renderer/core/page/chrome_client_impl.cc index 10e7f3c..c9d3cfa3 100644 --- a/third_party/blink/renderer/core/page/chrome_client_impl.cc +++ b/third_party/blink/renderer/core/page/chrome_client_impl.cc
@@ -106,6 +106,7 @@ #include "third_party/blink/renderer/platform/runtime_enabled_features.h" #include "third_party/blink/renderer/platform/text/text_direction.h" #include "third_party/blink/renderer/platform/web_test_support.h" +#include "third_party/blink/renderer/platform/weborigin/kurl.h" #include "third_party/blink/renderer/platform/weborigin/security_origin.h" #include "third_party/blink/renderer/platform/widget/frame_widget.h" #include "third_party/blink/renderer/platform/wtf/text/character_names.h" @@ -224,11 +225,11 @@ } void ChromeClientImpl::SetKeyboardFocusURL(Element* new_focus_element) { - WebURL focus_url; + KURL focus_url; if (new_focus_element && new_focus_element->IsLiveLink() && new_focus_element->ShouldHaveFocusAppearance()) focus_url = new_focus_element->HrefURL(); - web_view_->Client()->SetKeyboardFocusURL(focus_url); + web_view_->SetKeyboardFocusURL(focus_url); } void ChromeClientImpl::StartDragging(LocalFrame* frame, @@ -544,7 +545,7 @@ if (!web_view_->Client()) return; - WebURL url; + KURL url; // Ignore URL if hitTest include scrollbar since we might have both a // scrollbar and an element in the case of overlay scrollbars. @@ -568,7 +569,7 @@ } } - web_view_->Client()->SetMouseOverURL(url); + web_view_->SetMouseOverURL(url); } void ChromeClientImpl::SetToolTip(LocalFrame& frame,
diff --git a/third_party/blink/renderer/core/style/computed_style.h b/third_party/blink/renderer/core/style/computed_style.h index 529d56ff..007775b2 100644 --- a/third_party/blink/renderer/core/style/computed_style.h +++ b/third_party/blink/renderer/core/style/computed_style.h
@@ -2937,6 +2937,7 @@ FRIEND_TEST_ALL_PREFIXES(ComputedStyleTest, InitialVariableNames); FRIEND_TEST_ALL_PREFIXES(ComputedStyleTest, InitialAndInheritedAndNonInheritedVariableNames); + FRIEND_TEST_ALL_PREFIXES(StyleCascadeTest, ForcedVisitedBackgroundColor); }; inline bool ComputedStyle::HasAnyPseudoElementStyles() const {
diff --git a/third_party/blink/renderer/core/svg/animation/smil_animation_sandwich.cc b/third_party/blink/renderer/core/svg/animation/smil_animation_sandwich.cc index 2e8ef9a..126ac9b1 100644 --- a/third_party/blink/renderer/core/svg/animation/smil_animation_sandwich.cc +++ b/third_party/blink/renderer/core/svg/animation/smil_animation_sandwich.cc
@@ -93,23 +93,26 @@ if (!result_element) return false; - // Only reset the animated type to the base value once for - // the lowest priority animation that animates and - // contributes to a particular element/attribute pair. - result_element->ResetAnimatedType(); - // Animations have to be applied lowest to highest prio. // // Only calculate the relevant animations. If we actually set the // animation value, we don't need to calculate what is beneath it // in the sandwich. + bool needs_underlying_value = true; auto* sandwich_start = active_.end(); while (sandwich_start != active_.begin()) { --sandwich_start; - if ((*sandwich_start)->OverwritesUnderlyingAnimationValue()) + if ((*sandwich_start)->OverwritesUnderlyingAnimationValue()) { + needs_underlying_value = false; break; + } } + // Only reset the animated type to the base value once for + // the lowest priority animation that animates and + // contributes to a particular element/attribute pair. + result_element->ResetAnimatedType(needs_underlying_value); + for (auto* sandwich_it = sandwich_start; sandwich_it != active_.end(); sandwich_it++) { (*sandwich_it)->ApplyAnimation(result_element);
diff --git a/third_party/blink/renderer/core/svg/svg_animate_element.cc b/third_party/blink/renderer/core/svg/svg_animate_element.cc index e1b9bea..b403ad0 100644 --- a/third_party/blink/renderer/core/svg/svg_animate_element.cc +++ b/third_party/blink/renderer/core/svg/svg_animate_element.cc
@@ -432,7 +432,7 @@ return true; } -void SVGAnimateElement::ResetAnimatedType() { +void SVGAnimateElement::ResetAnimatedType(bool needs_underlying_value) { DCHECK(targetElement()); if (IsAnimatingSVGDom()) { // SVG DOM animVal animation code-path. @@ -447,7 +447,9 @@ // CSS properties animation code-path. String base_value = - ComputeCSSPropertyValue(targetElement(), css_property_id_); + needs_underlying_value + ? ComputeCSSPropertyValue(targetElement(), css_property_id_) + : g_empty_string; animated_value_ = CreatePropertyForAnimation(base_value); }
diff --git a/third_party/blink/renderer/core/svg/svg_animate_element.h b/third_party/blink/renderer/core/svg/svg_animate_element.h index 7608aef..2576de8 100644 --- a/third_party/blink/renderer/core/svg/svg_animate_element.h +++ b/third_party/blink/renderer/core/svg/svg_animate_element.h
@@ -59,7 +59,7 @@ bool HasValidAnimation() const override; - void ResetAnimatedType() final; + void ResetAnimatedType(bool needs_underlying_value) final; void ClearAnimatedType() final; bool CalculateToAtEndOfDurationValue(
diff --git a/third_party/blink/renderer/core/svg/svg_animate_motion_element.cc b/third_party/blink/renderer/core/svg/svg_animate_motion_element.cc index ba3ac201..4b3b3d2 100644 --- a/third_party/blink/renderer/core/svg/svg_animate_motion_element.cc +++ b/third_party/blink/renderer/core/svg/svg_animate_motion_element.cc
@@ -153,7 +153,7 @@ }); } -void SVGAnimateMotionElement::ResetAnimatedType() { +void SVGAnimateMotionElement::ResetAnimatedType(bool needs_underlying_value) { SVGElement* target_element = targetElement(); DCHECK(target_element); DCHECK(TargetCanHaveMotionTransform(*target_element));
diff --git a/third_party/blink/renderer/core/svg/svg_animate_motion_element.h b/third_party/blink/renderer/core/svg/svg_animate_motion_element.h index 511821e..cef0e9c 100644 --- a/third_party/blink/renderer/core/svg/svg_animate_motion_element.h +++ b/third_party/blink/renderer/core/svg/svg_animate_motion_element.h
@@ -42,7 +42,7 @@ void ParseAttribute(const AttributeModificationParams&) override; - void ResetAnimatedType() override; + void ResetAnimatedType(bool needs_underlying_value) override; void ClearAnimatedType() override; bool CalculateToAtEndOfDurationValue( const String& to_at_end_of_duration_string) override;
diff --git a/third_party/blink/renderer/core/svg/svg_animation_element.h b/third_party/blink/renderer/core/svg/svg_animation_element.h index fba834e..11164d7 100644 --- a/third_party/blink/renderer/core/svg/svg_animation_element.h +++ b/third_party/blink/renderer/core/svg/svg_animation_element.h
@@ -71,7 +71,7 @@ DEFINE_ATTRIBUTE_EVENT_LISTENER(end, kEndEvent) DEFINE_ATTRIBUTE_EVENT_LISTENER(repeat, kRepeatEvent) - virtual void ResetAnimatedType() = 0; + virtual void ResetAnimatedType(bool needs_underlying_value) = 0; virtual void ClearAnimatedType() = 0; virtual void ApplyResultsToTarget() = 0; // Returns true if this animation "sets" the value of the animation. Thus all
diff --git a/third_party/blink/renderer/modules/nfc/ndef_write_options.idl b/third_party/blink/renderer/modules/nfc/ndef_write_options.idl index 81fe17b1..4d7116a 100644 --- a/third_party/blink/renderer/modules/nfc/ndef_write_options.idl +++ b/third_party/blink/renderer/modules/nfc/ndef_write_options.idl
@@ -5,7 +5,6 @@ // https://w3c.github.io/web-nfc/#the-ndefwriteoptions-dictionary dictionary NDEFWriteOptions { - boolean ignoreRead = true; boolean overwrite = true; AbortSignal? signal; };
diff --git a/third_party/blink/renderer/modules/nfc/nfc_type_converters.cc b/third_party/blink/renderer/modules/nfc/nfc_type_converters.cc index 7587b5a4..d05ec7b8 100644 --- a/third_party/blink/renderer/modules/nfc/nfc_type_converters.cc +++ b/third_party/blink/renderer/modules/nfc/nfc_type_converters.cc
@@ -57,9 +57,8 @@ const blink::NDEFWriteOptions* write_options) { // https://w3c.github.io/web-nfc/#the-ndefwriteoptions-dictionary // Default values for NDEFWriteOptions dictionary are: - // ignoreRead = true, overwrite = true + // overwrite = true NDEFWriteOptionsPtr write_options_ptr = NDEFWriteOptions::New(); - write_options_ptr->ignore_read = write_options->ignoreRead(); write_options_ptr->overwrite = write_options->overwrite(); return write_options_ptr;
diff --git a/third_party/blink/renderer/modules/service_worker/service_worker_container.cc b/third_party/blink/renderer/modules/service_worker/service_worker_container.cc index 1846f25..a4a827a 100644 --- a/third_party/blink/renderer/modules/service_worker/service_worker_container.cc +++ b/third_party/blink/renderer/modules/service_worker/service_worker_container.cc
@@ -579,9 +579,10 @@ return registration; } + const int64_t registration_id = info.registration_id; registration = MakeGarbageCollected<ServiceWorkerRegistration>( GetSupplementable()->GetExecutionContext(), std::move(info)); - service_worker_registration_objects_.Set(info.registration_id, registration); + service_worker_registration_objects_.Set(registration_id, registration); return registration; } @@ -591,9 +592,10 @@ return nullptr; ServiceWorker* worker = service_worker_objects_.at(info.version_id); if (!worker) { + const int64_t version_id = info.version_id; worker = ServiceWorker::Create(GetSupplementable()->GetExecutionContext(), std::move(info)); - service_worker_objects_.Set(info.version_id, worker); + service_worker_objects_.Set(version_id, worker); } return worker; }
diff --git a/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc b/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc index ae95a8a..ebfc413c 100644 --- a/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc +++ b/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc
@@ -710,8 +710,9 @@ return nullptr; ::blink::ServiceWorker* worker = service_worker_objects_.at(info.version_id); if (!worker) { + const int64_t version_id = info.version_id; worker = ::blink::ServiceWorker::Create(this, std::move(info)); - service_worker_objects_.Set(info.version_id, worker); + service_worker_objects_.Set(version_id, worker); } return worker; }
diff --git a/third_party/blink/renderer/modules/websockets/dom_websocket.cc b/third_party/blink/renderer/modules/websockets/dom_websocket.cc index 006263c..e4aa818 100644 --- a/third_party/blink/renderer/modules/websockets/dom_websocket.cc +++ b/third_party/blink/renderer/modules/websockets/dom_websocket.cc
@@ -73,9 +73,6 @@ #include "third_party/blink/renderer/platform/wtf/text/string_utf8_adaptor.h" #include "third_party/blink/renderer/platform/wtf/wtf_size_t.h" -static const size_t kMaxByteSizeForHistogram = 100 * 1000 * 1000; -static const int32_t kBucketCountForMessageSizeHistogram = 50; - namespace blink { DOMWebSocket::EventQueue::EventQueue(EventTarget* target) @@ -357,8 +354,6 @@ return; } RecordSendTypeHistogram(WebSocketSendType::kArrayBuffer); - RecordSendMessageSizeHistogram(WebSocketSendType::kArrayBuffer, - binary_data->ByteLengthAsSizeT()); DCHECK(channel_); buffered_amount_ += binary_data->ByteLengthAsSizeT(); channel_->Send(*binary_data, 0, binary_data->ByteLengthAsSizeT(), @@ -380,8 +375,6 @@ return; } RecordSendTypeHistogram(WebSocketSendType::kArrayBufferView); - RecordSendMessageSizeHistogram(WebSocketSendType::kArrayBufferView, - array_buffer_view.View()->byteLengthAsSizeT()); DCHECK(channel_); buffered_amount_ += array_buffer_view.View()->byteLengthAsSizeT(); channel_->Send(*array_buffer_view.View()->buffer(), @@ -404,9 +397,6 @@ } uint64_t size = binary_data->size(); RecordSendTypeHistogram(WebSocketSendType::kBlob); - RecordSendMessageSizeHistogram( - WebSocketSendType::kBlob, - clampTo<size_t>(size, 0, kMaxByteSizeForHistogram)); buffered_amount_ += size; DCHECK(channel_); @@ -569,15 +559,12 @@ } auto* blob = MakeGarbageCollected<Blob>( BlobDataHandle::Create(std::move(blob_data), size)); - RecordReceiveMessageSizeHistogram(WebSocketReceiveType::kBlob, size); event_queue_->Dispatch(MessageEvent::Create(blob, origin_string_)); break; } case kBinaryTypeArrayBuffer: DOMArrayBuffer* array_buffer = DOMArrayBuffer::Create(data); - RecordReceiveMessageSizeHistogram(WebSocketReceiveType::kArrayBuffer, - size); event_queue_->Dispatch( MessageEvent::Create(array_buffer, origin_string_)); break; @@ -633,60 +620,6 @@ base::UmaHistogramEnumeration("WebCore.WebSocket.SendType", type); } -void DOMWebSocket::RecordSendMessageSizeHistogram(WebSocketSendType type, - size_t size) { - // Truncate |size| to avoid overflowing int32_t. - int32_t size_to_count = clampTo<int32_t>(size, 0, kMaxByteSizeForHistogram); - switch (type) { - case WebSocketSendType::kArrayBuffer: - base::UmaHistogramCustomCounts( - "WebCore.WebSocket.MessageSize.Send.ArrayBuffer", size_to_count, 1, - kMaxByteSizeForHistogram, kBucketCountForMessageSizeHistogram); - return; - - case WebSocketSendType::kArrayBufferView: - base::UmaHistogramCustomCounts( - "WebCore.WebSocket.MessageSize.Send.ArrayBufferView", size_to_count, - 1, kMaxByteSizeForHistogram, kBucketCountForMessageSizeHistogram); - return; - - case WebSocketSendType::kBlob: - base::UmaHistogramCustomCounts("WebCore.WebSocket.MessageSize.Send.Blob", - size_to_count, 1, kMaxByteSizeForHistogram, - kBucketCountForMessageSizeHistogram); - return; - - case WebSocketSendType::kString: - NOTREACHED(); - return; - } - NOTREACHED(); -} - -void DOMWebSocket::RecordReceiveMessageSizeHistogram(WebSocketReceiveType type, - size_t size) { - // Truncate |size| to avoid overflowing int32_t. - int32_t size_to_count = clampTo<int32_t>(size, 0, kMaxByteSizeForHistogram); - switch (type) { - case WebSocketReceiveType::kArrayBuffer: - base::UmaHistogramCustomCounts( - "WebCore.WebSocket.MessageSize.Receive.ArrayBuffer", size_to_count, 1, - kMaxByteSizeForHistogram, kBucketCountForMessageSizeHistogram); - return; - - case WebSocketReceiveType::kBlob: - base::UmaHistogramCustomCounts( - "WebCore.WebSocket.MessageSize.Receive.Blob", size_to_count, 1, - kMaxByteSizeForHistogram, kBucketCountForMessageSizeHistogram); - return; - - case WebSocketReceiveType::kString: - NOTREACHED(); - return; - } - NOTREACHED(); -} - void DOMWebSocket::Trace(Visitor* visitor) const { visitor->Trace(channel_); visitor->Trace(event_queue_);
diff --git a/third_party/blink/renderer/modules/websockets/dom_websocket.h b/third_party/blink/renderer/modules/websockets/dom_websocket.h index fb8a9375..883b63d 100644 --- a/third_party/blink/renderer/modules/websockets/dom_websocket.h +++ b/third_party/blink/renderer/modules/websockets/dom_websocket.h
@@ -202,13 +202,6 @@ kMaxValue = kBlob, }; - enum class WebSocketReceiveType { - kString, - kArrayBuffer, - kBlob, - kMaxValue = kBlob, - }; - enum BinaryType { kBinaryTypeBlob, kBinaryTypeArrayBuffer }; // This function is virtual for unittests. @@ -244,8 +237,6 @@ void ReleaseChannel(); void RecordSendTypeHistogram(WebSocketSendType); - void RecordSendMessageSizeHistogram(WebSocketSendType, size_t); - void RecordReceiveMessageSizeHistogram(WebSocketReceiveType, size_t); Member<WebSocketChannel> channel_;
diff --git a/third_party/blink/web_tests/FlagExpectations/disable-layout-ng b/third_party/blink/web_tests/FlagExpectations/disable-layout-ng index f652d28..4ca87ce1 100644 --- a/third_party/blink/web_tests/FlagExpectations/disable-layout-ng +++ b/third_party/blink/web_tests/FlagExpectations/disable-layout-ng
@@ -119,7 +119,6 @@ ### external/wpt/css/css-sizing/ crbug.com/1045668 external/wpt/css/css-sizing/aspect-ratio/abspos-001.tentative.html [ Failure ] -crbug.com/1045668 external/wpt/css/css-sizing/aspect-ratio/abspos-002.tentative.html [ Failure ] crbug.com/1045668 external/wpt/css/css-sizing/aspect-ratio/abspos-003.tentative.html [ Failure ] crbug.com/1045668 external/wpt/css/css-sizing/aspect-ratio/abspos-004.tentative.html [ Failure ] crbug.com/1045668 external/wpt/css/css-sizing/aspect-ratio/abspos-005.tentative.html [ Failure ] @@ -143,11 +142,6 @@ crbug.com/1045668 external/wpt/css/css-sizing/aspect-ratio/block-aspect-ratio-028.tentative.html [ Failure ] crbug.com/1045668 external/wpt/css/css-sizing/aspect-ratio/flex-aspect-ratio-008.tentative.html [ Failure ] crbug.com/1045668 external/wpt/css/css-sizing/aspect-ratio/flex-aspect-ratio-009.tentative.html [ Failure ] -crbug.com/1045668 external/wpt/css/css-sizing/aspect-ratio/intrinsic-size-001.tentative.html [ Failure ] -crbug.com/1045668 external/wpt/css/css-sizing/aspect-ratio/intrinsic-size-002.tentative.html [ Failure ] -crbug.com/1045668 external/wpt/css/css-sizing/aspect-ratio/intrinsic-size-004.tentative.html [ Failure ] -crbug.com/1045668 external/wpt/css/css-sizing/aspect-ratio/intrinsic-size-006.tentative.html [ Failure ] -crbug.com/1045668 external/wpt/css/css-sizing/aspect-ratio/intrinsic-size-008.tentative.html [ Failure ] crbug.com/1045668 external/wpt/css/css-sizing/aspect-ratio/percentage-resolution-001.tentative.html [ Failure ] crbug.com/1045668 external/wpt/css/css-sizing/aspect-ratio/percentage-resolution-002.tentative.html [ Failure ] crbug.com/1045668 external/wpt/css/css-sizing/aspect-ratio/percentage-resolution-004.tentative.html [ Failure ]
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index 83ee34d..7b0a852d 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -2537,6 +2537,10 @@ crbug.com/1105958 external/wpt/payment-request/payment-is-showing.https.html [ Timeout ] # ====== New tests from wpt-importer added here ====== +crbug.com/626703 [ Linux ] external/wpt/css/css-text/white-space/eol-spaces-bidi-002.html [ Failure ] +crbug.com/626703 [ Mac ] external/wpt/css/css-text/white-space/eol-spaces-bidi-002.html [ Failure ] +crbug.com/626703 [ Mac11.0 ] external/wpt/css/css-text/white-space/eol-spaces-bidi-002.html [ Failure ] +crbug.com/626703 [ Win ] external/wpt/css/css-text/white-space/eol-spaces-bidi-002.html [ Failure ] crbug.com/626703 [ Linux ] external/wpt/css/css-text/white-space/trailing-ogham-002.html [ Failure ] crbug.com/626703 [ Mac ] external/wpt/css/css-text/white-space/trailing-ogham-002.html [ Failure ] crbug.com/626703 [ Mac11.0 ] external/wpt/css/css-text/white-space/trailing-ogham-002.html [ Failure ] @@ -6600,6 +6604,7 @@ # Flaky timeout crbug.com/1092048 external/wpt/FileAPI/blob/Blob-stream.any.html [ Pass Timeout ] +crbug.com/1092048 external/wpt/FileAPI/blob/Blob-stream.any.worker.html [ Pass Timeout ] # Sheriff 2020-08-04: New wpt tests are failing crbug.com/1112771 external/wpt/webhid/idlharness.https.window.html [ Failure ]
diff --git a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json index dce9bc7..d78b75b 100644 --- a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json +++ b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json
@@ -43527,6 +43527,71 @@ {} ] ], + "border-width-small-values-001-a.html": [ + "d5354a3585469bbec045a8d14193fc3332e83d0f", + [ + null, + [ + [ + "/css/css-backgrounds/reference/border-width-small-values-001-ref.html", + "!=" + ] + ], + {} + ] + ], + "border-width-small-values-001-b.html": [ + "ccb5004a64f584a5d26ed636519f945dd3c7580f", + [ + null, + [ + [ + "/css/css-backgrounds/reference/border-width-small-values-001-ref.html", + "!=" + ] + ], + {} + ] + ], + "border-width-small-values-001-c.html": [ + "43651fe2312bbdb1f4a5bd2914ee8e94c6c4076f", + [ + null, + [ + [ + "/css/css-backgrounds/reference/border-width-small-values-001-ref.html", + "!=" + ] + ], + {} + ] + ], + "border-width-small-values-001-d.html": [ + "11ff8b5c5553d5bff1ceff5da36a4342a650610c", + [ + null, + [ + [ + "/css/css-backgrounds/reference/border-width-small-values-001-ref.html", + "!=" + ] + ], + {} + ] + ], + "border-width-small-values-001-e.html": [ + "5fc44349834938dc6b3d6ba60334bcd7737d1a40", + [ + null, + [ + [ + "/css/css-backgrounds/reference/border-width-small-values-001-ref.html", + "!=" + ] + ], + {} + ] + ], "box-shadow-005.html": [ "705ced279d30e6113eed68b819b287f7e48219cd", [ @@ -100025,7 +100090,7 @@ ] ], "eol-spaces-bidi-001.html": [ - "976ce7c639f10d2137da1492f50ea74c769c1091", + "b8bcbe17b738d40e4facffc0285282fe20002d30", [ null, [ @@ -100037,6 +100102,19 @@ {} ] ], + "eol-spaces-bidi-002.html": [ + "0efba0a363fc8353775263928223773a9d10e3b4", + [ + null, + [ + [ + "/css/css-text/white-space/reference/eol-spaces-bidi-002-ref.html", + "==" + ] + ], + {} + ] + ], "line-edge-white-space-collapse-001.html": [ "4e144e6c330191435f183936c2ab2437ec4f7609", [ @@ -168965,6 +169043,10 @@ "99dd2f0beb2a6a9b5bcf79408d1fbf089b8e15ec", [] ], + "border-width-small-values-001-ref.html": [ + "26177acb379017189f4deceb5519217fd97d2c51", + [] + ], "box-shadow-005-ref.html": [ "81a5cbf6b8e06f6435bc133287f128ed6af8ed62", [] @@ -188887,7 +188969,11 @@ [] ], "eol-spaces-bidi-001-ref.html": [ - "37da6649f9b776cb046a2bacdeb24968d27a2af8", + "430706c55697597681c71202dd4cb18da8b5de37", + [] + ], + "eol-spaces-bidi-002-ref.html": [ + "30a4ffd303d55f6228b886aa658822975601967a", [] ], "line-edge-white-space-collapse-001-ref.html": [ @@ -205412,7 +205498,7 @@ [] ], "generic-sensor-tests.js": [ - "129ccd48543d6dfbc3f1e339443d44a3d864ce7b", + "26ff691959917b7b4921900f0603dcc23867c0ca", [] ], "resources": { @@ -229803,7 +229889,7 @@ ], "resources": { "shapedetection-helpers.js": [ - "bdb0e857d788ab0b2778cc9946386ead3d224b2c", + "05424de893dc9ac59d7f40c436bb73c9523da52f", [] ] } @@ -338664,7 +338750,7 @@ ] ], "none.https.html": [ - "0fbd4165a5f19f19a4e6cca3ee43bba88f0336b5", + "24b1fce1764d74a01c4eeb21c3d9e05de1bb12ba", [ null, { @@ -339217,6 +339303,24 @@ ], "reporting": { "access-reporting": { + "access-from-coop-page-to-openee_coop-ro.https.html": [ + "fc7c192b6b69303067c01ee407a67e9eed9201d2", + [ + null, + { + "timeout": "long" + } + ] + ], + "access-from-coop-page-to-opener_coop-ro.https.html": [ + "d7384e21195c16e558fe85fadfaca45e56c149cb", + [ + null, + { + "timeout": "long" + } + ] + ], "access-from-coop-page-to-other_coop-ro.https.html": [ "e5cc726c5e0b38c8d25cd3ee8fb80f227e1c3e19", [ @@ -339226,8 +339330,8 @@ } ] ], - "access-to-coop-page-from-other_coop-ro.https.html": [ - "c349b9a708e7cb579db921cc1d574869dc0b081c", + "access-to-coop-page-from-openee_coop-ro.https.html": [ + "e54d5e3fe1c34113bd79849df4e3bfc16739d467", [ null, { @@ -339235,7 +339339,7 @@ } ] ], - "openee-accessed_openee-coop-ro.https.html": [ + "access-to-coop-page-from-opener_coop-ro.https.html": [ "ef969738c33f8cacc8a269f5159e60900f98a7c7", [ null, @@ -339244,26 +339348,8 @@ } ] ], - "openee-accessed_opener-coop-ro.https.html": [ - "fc7c192b6b69303067c01ee407a67e9eed9201d2", - [ - null, - { - "timeout": "long" - } - ] - ], - "opener-accessed_openee-coop-ro.https.html": [ - "d7384e21195c16e558fe85fadfaca45e56c149cb", - [ - null, - { - "timeout": "long" - } - ] - ], - "opener-accessed_opener-coop-ro.https.html": [ - "e54d5e3fe1c34113bd79849df4e3bfc16739d467", + "access-to-coop-page-from-other_coop-ro.https.html": [ + "c349b9a708e7cb579db921cc1d574869dc0b081c", [ null, { @@ -346749,6 +346835,13 @@ ] ], "sizes": { + "implicit-sizes-ignores-width.html": [ + "db61db351eacb5f38ce6767a55a61e588f5580e5", + [ + null, + {} + ] + ], "parse-a-sizes-attribute-display-none.html": [ "6aa77ebf85b9de2757e80abb32c32fd2c8021958", [ @@ -386322,7 +386415,7 @@ ] ], "detection-on-worker.https.worker.js": [ - "94b8e37d7272ea8f882d856d49fb9be334f1ffe5", + "3981c6fdc8e12839d3aa30206fa16d8af1faf513", [ "shape-detection/detection-on-worker.https.worker.html", {}
diff --git a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-width-small-values-001-a.html b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-width-small-values-001-a.html new file mode 100644 index 0000000..d5354a3 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-width-small-values-001-a.html
@@ -0,0 +1,8 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Backgrounds and Borders Test: border-width small values</title> +<link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com"> +<link rel="help" href="https://drafts.csswg.org/css-backgrounds/#border-width"> +<link rel="mismatch" href="reference/border-width-small-values-001-ref.html"> +<meta name="assert" content="Tese tests check that small values for border-width (greater than 0px and lower than 1px) are visible."> +<div style="border: 0.1px solid black;">The test passes if this text has a border</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-width-small-values-001-b.html b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-width-small-values-001-b.html new file mode 100644 index 0000000..ccb5004 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-width-small-values-001-b.html
@@ -0,0 +1,8 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Backgrounds and Borders Test: border-width small values</title> +<link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com"> +<link rel="help" href="https://drafts.csswg.org/css-backgrounds/#border-width"> +<link rel="mismatch" href="reference/border-width-small-values-001-ref.html"> +<meta name="assert" content="Tese tests check that small values for border-width (greater than 0px and lower than 1px) are visible."> +<div style="border: 0.25px solid black;">The test passes if this text has a border</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-width-small-values-001-c.html b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-width-small-values-001-c.html new file mode 100644 index 0000000..43651fe --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-width-small-values-001-c.html
@@ -0,0 +1,8 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Backgrounds and Borders Test: border-width small values</title> +<link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com"> +<link rel="help" href="https://drafts.csswg.org/css-backgrounds/#border-width"> +<link rel="mismatch" href="reference/border-width-small-values-001-ref.html"> +<meta name="assert" content="Tese tests check that small values for border-width (greater than 0px and lower than 1px) are visible."> +<div style="border: 0.5px solid black;">The test passes if this text has a border</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-width-small-values-001-d.html b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-width-small-values-001-d.html new file mode 100644 index 0000000..11ff8b5 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-width-small-values-001-d.html
@@ -0,0 +1,8 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Backgrounds and Borders Test: border-width small values</title> +<link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com"> +<link rel="help" href="https://drafts.csswg.org/css-backgrounds/#border-width"> +<link rel="mismatch" href="reference/border-width-small-values-001-ref.html"> +<meta name="assert" content="Tese tests check that small values for border-width (greater than 0px and lower than 1px) are visible."> +<div style="border: 0.7px solid black;">The test passes if this text has a border</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-width-small-values-001-e.html b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-width-small-values-001-e.html new file mode 100644 index 0000000..5fc44349 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/border-width-small-values-001-e.html
@@ -0,0 +1,8 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Backgrounds and Borders Test: border-width small values</title> +<link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com"> +<link rel="help" href="https://drafts.csswg.org/css-backgrounds/#border-width"> +<link rel="mismatch" href="reference/border-width-small-values-001-ref.html"> +<meta name="assert" content="Tese tests check that small values for border-width (greater than 0px and lower than 1px) are visible."> +<div style="border: 0.9px solid black;">The test passes if this text has a border</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/reference/border-width-small-values-001-ref.html b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/reference/border-width-small-values-001-ref.html new file mode 100644 index 0000000..26177ac --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/reference/border-width-small-values-001-ref.html
@@ -0,0 +1,5 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Backgrounds and Borders Reference Test: border-width small values</title> +<link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com"> +<div>The test passes if this text has a border</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text/white-space/eol-spaces-bidi-001.html b/third_party/blink/web_tests/external/wpt/css/css-text/white-space/eol-spaces-bidi-001.html index 976ce7c..b8bcbe1 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-text/white-space/eol-spaces-bidi-001.html +++ b/third_party/blink/web_tests/external/wpt/css/css-text/white-space/eol-spaces-bidi-001.html
@@ -1,44 +1,46 @@ <!DOCTYPE html> <meta charset="utf-8"> -<title>CSS Text level 3 Test: collapsible white space at end-of-line and bidi</title> -<link rel="author" title="Florian Rivoal" href="http://florian.rivoal.net/"> +<title>CSS Text 3 test: trailing collapsible spaces and bidi</title> +<link rel="author" title="Florian Rivoal" href="https://florian.rivoal.net/"> <link rel="help" href="https://drafts.csswg.org/css-text-3/#white-space-phase-2"> <link rel="match" href="reference/eol-spaces-bidi-001-ref.html"> -<meta name="assert" content="Collapsible space at the end of the line prior to bidi reordering are removed."> +<meta name="assert" content="Space before a line break is removed even if reordered to the middle of line by bidi reordering"> + <style> div { - font-family: monospace; - border: solid blue; - font-size: 1.5em; - margin-bottom:1em; - display: inline-block; + font-family: monospace; + border: solid blue; + font-size: 1.5em; } .ref { - white-space: pre; - border-color: orange; + border-color: orange; + white-space: pre; } .w5 { width: 5ch; } .w6 { width: 6ch; } .w7 { width: 7ch; } -.w8 { width: 8ch; } -.blue { background: #aaaaff; } -.red { background: #ffaaaa; } -.green { background: #aaffaa; } -.pink { background: #ffaaff; } -.yellow { background: #ffffaa; } - +.blue { background: #aaaaff; } +.red { background: #ffaaaa; } +.green { background: #aaffaa; } +.pink { background: #ffaaff; } +.yellow { background: #ffffaa; } </style> -<p>Test passes if the content of each blue box (on the left) is laid out identically to the content of the orange box to its right. + +<p>Test passes if each pair of blue / orange boxes are identical (except for the color of their border). <div class=w5><span class=pink> </span>A<span class=blue> </span>B<span class=red> </span>ا<span class=green> </span>ب<span class=yellow> </span></div> -<div class="ref w5">A<span class=blue> </span>B<span class=red> </span>ا<br>ب</div> -<br> + +<div class="w5 ref">A<span class=blue> </span>B<span class=red> </span>ا<br>ب</div> + +<hr> + <div class=w6><span class=pink> </span>A<span class=blue> </span>B<span class=red> </span>ا<span class=green> </span>ب<span class=yellow> </span></div> -<div class="ref w6">A<span class=blue> </span>B<span class=red> </span>ا<br>ب</div> -<br> + +<div class="w6 ref">A<span class=blue> </span>B<span class=red> </span>ا<br>ب</div> + +<hr> + <div class=w7><span class=pink> </span>A<span class=blue> </span>B<span class=red> </span>ا<span class=green> </span>ب<span class=yellow> </span></div> -<div class="ref w7">A<span class=blue> </span>B<span class=red> </span>ا<span class=green> </span>ب</div> -<br> -<div class=w8><span class=pink> </span>A<span class=blue> </span>B<span class=red> </span>ا<span class=green> </span>ب<span class=yellow> </span></div> -<div class="ref w8">A<span class=blue> </span>B<span class=red> </span>ا<span class=green> </span>ب</div> + +<div class="w7 ref">A<span class=blue> </span>B<span class=red> </span>ا<span class=green> </span>ب</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text/white-space/eol-spaces-bidi-002.html b/third_party/blink/web_tests/external/wpt/css/css-text/white-space/eol-spaces-bidi-002.html new file mode 100644 index 0000000..0efba0a3 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-text/white-space/eol-spaces-bidi-002.html
@@ -0,0 +1,69 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Text 3 test: trailing pre-wrap spaces and bidi</title> +<link rel="author" title="Florian Rivoal" href="https://florian.rivoal.net/"> +<link rel="help" href="https://drafts.csswg.org/css-text-3/#white-space-phase-2"> +<link rel="help" href="https://www.w3.org/TR/css-writing-modes/#text-direction"> +<link rel="help" href="http://www.unicode.org/reports/tr9/#L1"> +<link rel="match" href="reference/eol-spaces-bidi-002-ref.html"> +<meta name="assert" content="Use UAX9L1 to determine which space is at the end of the line, taking into account that such spaces, when pre-wrap, must hang."> + +<style> +div { + font-family: monospace; + border: solid blue; + font-size: 1.5em; + white-space: pre-wrap; +} +.ref { + border-color: orange; + white-space: pre; +} +.w6 { width: 6ch; } +.w7 { width: 7ch; } +.w8 { width: 8ch; } +.w9 { width: 9ch; } + +.blue { background: #aaaaff; } +.red { background: #ffaaaa; } +.green { background: #aaffaa; } +.pink { background: #ffaaff; } +.yellow { background: #ffffaa; } +</style> + +<p>Test passes if each pair of blue / orange boxes are identical (except for the color of their border). + + +<!-- not coloring the space between ا and ب in this particular case, + because per UAX9 L1 and css-text-3 4.1.2 point 4 bullet 2: + this space MUST be at the end of the line and hang, + but also the UA MAY collapse it's advance width. + Not giving it a color lets the test pass either way. +--> + +<div class="w6"><span class=pink> </span>A<span class=blue> </span>B<span class=red> </span>ا<span> </span>ب<span class=yellow> </span></div> +<div class="w6 ref"><span class=pink> </span>A<span class=blue> </span>B<span class=red> </span>ا<br>ب<span class=yellow> </span></div> + +<hr> + +<div class="w7"><span class=pink> </span>A<span class=blue> </span>B<span class=red> </span>ا<span class=green> </span>ب<span class=yellow> </span></div> +<div class="w7 ref"><span class=pink> </span>A<span class=blue> </span>B<span class=red> </span>ا<span class=green> </span><br>ب<span class=yellow> </span></div> + +<hr> + +<!-- not coloring the last space in this particular case, + because per 4.1.2 point 4 bullet 2: + this space MUST hang, + but also the UA MAY collapse it's advance width. + So we know for sure it won't cause a line break, + but it may or may not be visible at the end of the line. + Not giving it a color lets the test pass either way. +--> + +<div class="w8"><span class=pink> </span>A<span class=blue> </span>B<span class=red> </span>ا<span class=green> </span>ب<span> </span></div> +<div class="w8 ref"><span class=pink> </span>A<span class=blue> </span>B<span class=red> </span>ا<span class=green> </span>ب</div> + +<hr> + +<div class="w9"><span class=pink> </span>A<span class=blue> </span>B<span class=red> </span>ا<span class=green> </span>ب<span class=yellow> </span></div> +<div class="w9 ref"><span class=pink> </span>A<span class=blue> </span>B<span class=red> </span>ا<span class=green> </span>ب<span class=yellow> </span></div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text/white-space/reference/eol-spaces-bidi-001-ref.html b/third_party/blink/web_tests/external/wpt/css/css-text/white-space/reference/eol-spaces-bidi-001-ref.html index 37da664..430706c 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-text/white-space/reference/eol-spaces-bidi-001-ref.html +++ b/third_party/blink/web_tests/external/wpt/css/css-text/white-space/reference/eol-spaces-bidi-001-ref.html
@@ -1,39 +1,38 @@ <!DOCTYPE html> <meta charset="utf-8"> -<title>CSS test reference</title> -<link rel="author" title="Florian Rivoal" href="http://florian.rivoal.net/"> +<title>CSS Text 3 test reference</title> +<link rel="author" title="Florian Rivoal" href="https://florian.rivoal.net/"> + <style> div { - font-family: monospace; - border: solid blue; - font-size: 1.5em; - margin-bottom:1em; - display: inline-block; - white-space: pre; + font-family: monospace; + border: solid blue; + font-size: 1.5em; + white-space: pre; } .ref { - border-color: orange; + border-color: orange; } .w5 { width: 5ch; } .w6 { width: 6ch; } .w7 { width: 7ch; } -.w8 { width: 8ch; } -.blue { background: #aaaaff; } -.red { background: #ffaaaa; } -.green { background: #aaffaa; } - +.blue { background: #aaaaff; } +.red { background: #ffaaaa; } +.green { background: #aaffaa; } </style> -<p>Test passes if the content of each blue box (on the left) is laid out identically to the content of the orange box to its right. + +<p>Test passes if each pair of blue / orange boxes are identical (except for the color of their border). <div class="w5">A<span class=blue> </span>B<span class=red> </span>ا<br>ب</div> -<div class="ref w5">A<span class=blue> </span>B<span class=red> </span>ا<br>ب</div> -<br> +<div class="w5 ref">A<span class=blue> </span>B<span class=red> </span>ا<br>ب</div> + +<hr> + <div class="w6">A<span class=blue> </span>B<span class=red> </span>ا<br>ب</div> -<div class="ref w6">A<span class=blue> </span>B<span class=red> </span>ا<br>ب</div> -<br> +<div class="w6 ref">A<span class=blue> </span>B<span class=red> </span>ا<br>ب</div> + +<hr> + <div class="w7">A<span class=blue> </span>B<span class=red> </span>ا<span class=green> </span>ب</div> -<div class="ref w7">A<span class=blue> </span>B<span class=red> </span>ا<span class=green> </span>ب</div> -<br> -<div class="w8">A<span class=blue> </span>B<span class=red> </span>ا<span class=green> </span>ب</div> -<div class="ref w8">A<span class=blue> </span>B<span class=red> </span>ا<span class=green> </span>ب</div> +<div class="w7 ref">A<span class=blue> </span>B<span class=red> </span>ا<span class=green> </span>ب</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text/white-space/reference/eol-spaces-bidi-002-ref.html b/third_party/blink/web_tests/external/wpt/css/css-text/white-space/reference/eol-spaces-bidi-002-ref.html new file mode 100644 index 0000000..30a4ffd --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-text/white-space/reference/eol-spaces-bidi-002-ref.html
@@ -0,0 +1,48 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Text 3 test reference</title> +<link rel="author" title="Florian Rivoal" href="https://florian.rivoal.net/"> + +<style> +div { + font-family: monospace; + border: solid blue; + font-size: 1.5em; + white-space: pre; +} +.ref { + border-color: orange; +} +.w6 { width: 6ch; } +.w7 { width: 7ch; } +.w8 { width: 8ch; } +.w9 { width: 9ch; } + +.blue { background: #aaaaff; } +.red { background: #ffaaaa; } +.green { background: #aaffaa; } +.pink { background: #ffaaff; } +.yellow { background: #ffffaa; } +</style> + +<p>Test passes if each pair of blue / orange boxes are identical (except for the color of their border). + + +<div class="w6"><span class=pink> </span>A<span class=blue> </span>B<span class=red> </span>ا<br>ب<span class=yellow> </span></div> +<div class="w6 ref"><span class=pink> </span>A<span class=blue> </span>B<span class=red> </span>ا<br>ب<span class=yellow> </span></div> + +<hr> + +<div class="w7"><span class=pink> </span>A<span class=blue> </span>B<span class=red> </span>ا<span class=green> </span><br>ب<span class=yellow> </span></div> +<div class="w7 ref"><span class=pink> </span>A<span class=blue> </span>B<span class=red> </span>ا<span class=green> </span><br>ب<span class=yellow> </span></div> + +<hr> + +<div class="w8"><span class=pink> </span>A<span class=blue> </span>B<span class=red> </span>ا<span class=green> </span>ب</div> +<div class="w8 ref"><span class=pink> </span>A<span class=blue> </span>B<span class=red> </span>ا<span class=green> </span>ب</div> + +<hr> + +<div class="w9"><span class=pink> </span>A<span class=blue> </span>B<span class=red> </span>ا<span class=green> </span>ب<span class=yellow> </span></div> +<div class="w9 ref"><span class=pink> </span>A<span class=blue> </span>B<span class=red> </span>ا<span class=green> </span>ب<span class=yellow> </span></div> +
diff --git a/third_party/blink/web_tests/external/wpt/forced-colors-mode/forced-colors-mode-40-ref.html b/third_party/blink/web_tests/external/wpt/forced-colors-mode/forced-colors-mode-39-ref.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/forced-colors-mode/forced-colors-mode-40-ref.html rename to third_party/blink/web_tests/external/wpt/forced-colors-mode/forced-colors-mode-39-ref.html
diff --git a/third_party/blink/web_tests/external/wpt/forced-colors-mode/forced-colors-mode-40.html b/third_party/blink/web_tests/external/wpt/forced-colors-mode/forced-colors-mode-39.html similarity index 87% rename from third_party/blink/web_tests/external/wpt/forced-colors-mode/forced-colors-mode-40.html rename to third_party/blink/web_tests/external/wpt/forced-colors-mode/forced-colors-mode-39.html index 7b02b41..7b69fc9 100644 --- a/third_party/blink/web_tests/external/wpt/forced-colors-mode/forced-colors-mode-40.html +++ b/third_party/blink/web_tests/external/wpt/forced-colors-mode/forced-colors-mode-39.html
@@ -2,7 +2,7 @@ <meta charset="utf-8"> <title>Forced colors mode - pseudo elements.</title> <link rel="help" href="https://www.w3.org/TR/css-color-adjust-1/#forced-colors-properties"> -<link rel=match href="forced-colors-mode-40-ref.html"> +<link rel=match href="forced-colors-mode-39-ref.html"> <style> p::before { background: blue;
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/the-img-element/sizes/implicit-sizes-ignores-width.html b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/the-img-element/sizes/implicit-sizes-ignores-width.html new file mode 100644 index 0000000..db61db35 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/html/semantics/embedded-content/the-img-element/sizes/implicit-sizes-ignores-width.html
@@ -0,0 +1,19 @@ +<!doctype html> +<title>Implicit sizes ignores width</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<style> +img {width: auto;} +</style> +<img srcset="../srcset/resources/image.png 100w" sizes="400px" id="sizes"> +<img srcset="../srcset/resources/image.png 100w" width="400" id="width"> +<script> +setup({explicit_done:true}); +onload = () => { + test(() => { + assert_equals(document.getElementById("sizes").width, 400); + assert_equals(document.getElementById("width").width, window.innerWidth); + done(); + }); +}; +</script>
diff --git a/third_party/blink/web_tests/external/wpt/resources/chromium/nfc-mock.js b/third_party/blink/web_tests/external/wpt/resources/chromium/nfc-mock.js index 1a7e158..4c5f68b 100644 --- a/third_party/blink/web_tests/external/wpt/resources/chromium/nfc-mock.js +++ b/third_party/blink/web_tests/external/wpt/resources/chromium/nfc-mock.js
@@ -94,10 +94,10 @@ // Compares NDEFWriteOptions structures that were provided to API and // received by the mock mojo service. function assertNDEFWriteOptionsEqual(provided, received) { - if (provided.ignoreRead !== undefined) - assert_equals(provided.ignoreRead, !!received.ignoreRead); + if (provided.overwrite !== undefined) + assert_equals(provided.overwrite, !!received.overwrite); else - assert_equals(!!received.ignore_read, true); + assert_equals(!!received.overwrite, true); } // Compares NDEFReaderOptions structures that were provided to API and @@ -319,8 +319,9 @@ this.reading_messages_.push(message); // Ignores reading if NFC operation is suspended. if(this.operations_suspended_) return; - // Ignores reading if NDEFWriteOptions.ignoreRead is true. - if (this.pending_write_options_ && this.pending_write_options_.ignoreRead) + // when overwrite is false, the write algorithm will read the NFC tag + // to determine if it has NDEF records on it. + if (this.pending_write_options_ && this.pending_write_options_.overwrite) return; // Triggers onWatch if the new message matches existing watchers. for (let watcher of this.watchers_) {
diff --git a/third_party/blink/web_tests/external/wpt/web-nfc/NDEFWriter_write.https.html b/third_party/blink/web_tests/external/wpt/web-nfc/NDEFWriter_write.https.html index e2bbd57b..57fd300 100644 --- a/third_party/blink/web_tests/external/wpt/web-nfc/NDEFWriter_write.https.html +++ b/third_party/blink/web_tests/external/wpt/web-nfc/NDEFWriter_write.https.html
@@ -382,57 +382,21 @@ nfc_test(async (t, mockNFC) => { const writer = new NDEFWriter(); await writer.write(test_text_data); - assertNDEFWriteOptionsEqual(createNDEFWriteOptions(true), - mockNFC.writeOptions()); + assertNDEFWriteOptionsEqual({overwrite: true}, mockNFC.writeOptions()); }, "Check that default NDEFWriteOptions values are correctly set."); nfc_test(async (t, mockNFC) => { const writer = new NDEFWriter(); - let ndefWriteOptions = createNDEFWriteOptions(false); - await writer.write(test_text_data, ndefWriteOptions); - assertNDEFWriteOptionsEqual(ndefWriteOptions, mockNFC.writeOptions()); + await writer.write(test_text_data, {overwrite: false}); + assertNDEFWriteOptionsEqual({overwrite: false}, mockNFC.writeOptions()); }, "Check that provided NDEFWriteOptions values are correctly converted."); nfc_test(async (t, mockNFC) => { - const reader = new NDEFReader(); - const message = createMessage([createTextRecord(test_text_data)]); - const controller = new AbortController(); - const readerWatcher = new EventWatcher(t, reader, ["reading", "error"]); - await reader.scan({ signal: controller.signal }); - - const writer = new NDEFWriter(); - await writer.write(test_text_data, { ignoreRead: false }); - assertNDEFMessagesEqual(test_text_data, mockNFC.pushedMessage()); - - mockNFC.setReadingMessage(message); - await readerWatcher.wait_for("reading").then(event => { - controller.abort(); - assertWebNDEFMessagesEqual(event.message, new NDEFMessage(message)); - }); - -}, "NDEFWriter.write should read data when ignoreRead is false."); - -nfc_test(async (t, mockNFC) => { - const reader = new NDEFReader(); - const message = createMessage([createTextRecord(test_text_data)]); - // Ignore reading if NDEFWriteOptions.ignoreRead is true - reader.onreading = t.unreached_func("reading event should not be fired."); - await reader.scan(); - - const writer = new NDEFWriter(); - await writer.write(test_text_data, { ignoreRead: true }); - mockNFC.setReadingMessage(message); - assertNDEFMessagesEqual(test_text_data, mockNFC.pushedMessage()); -}, "NDEFWriter.write should ignore reading data when ignoreRead is true."); - -nfc_test(async (t, mockNFC) => { const writer1 = new NDEFWriter(); const writer2 = new NDEFWriter(); - const ndefWriteOptions1 = createNDEFWriteOptions( false); - const ndefWriteOptions2 = createNDEFWriteOptions(true); - const p1 = writer1.write(test_text_data, ndefWriteOptions1); - const p2 = writer2.write(test_url_data, ndefWriteOptions2); + const p1 = writer1.write(test_text_data, {overwrite: false}); + const p2 = writer2.write(test_url_data, {overwrite: true}); await new Promise((resolve, reject) => { // Make first push pending @@ -445,7 +409,7 @@ }); p2.then(() => { assertNDEFMessagesEqual(test_url_data, mockNFC.pushedMessage()); - assertNDEFWriteOptionsEqual(ndefWriteOptions2, mockNFC.writeOptions()); + assertNDEFWriteOptionsEqual( {overwrite: true}, mockNFC.writeOptions()); assert_equals(err, "AbortError", "the pending push should be aborted"); resolve(); }); @@ -478,7 +442,7 @@ nfc_test(async (t, mockNFC) => { const writer = new NDEFWriter(); - await writer.write(test_text_data, { overwrite: false }); + await writer.write(test_text_data, {overwrite: false}); assertNDEFMessagesEqual(test_text_data, mockNFC.pushedMessage()); }, "NDEFWriter.write should succeed to write data to an unformatted NFC device \ when the NDEFWriteOptions.overwrite is false."); @@ -487,14 +451,14 @@ const writer = new NDEFWriter(); await writer.write(test_buffer_data); assertNDEFMessagesEqual(test_buffer_data, mockNFC.pushedMessage()); - await writer.write(test_text_data, { overwrite: true }); + await writer.write(test_text_data, {overwrite: true}); assertNDEFMessagesEqual(test_text_data, mockNFC.pushedMessage()); }, "NDEFWriter.write should succeed to overwrite the existing data \ when the NDEFWriteOptions.overwrite is true."); nfc_test(async (t, mockNFC) => { const writer = new NDEFWriter(); - const p = writer.write(test_text_data, { overwrite: false }); + const p = writer.write(test_text_data, {overwrite: false}); mockNFC.setIsFormattedTag(true); await promise_rejects_dom(t, 'NotAllowedError', p); }, "NDEFWriter.write should fail when there are NDEF records on the NFC device \
diff --git a/third_party/blink/web_tests/external/wpt/web-nfc/resources/nfc-helpers.js b/third_party/blink/web_tests/external/wpt/web-nfc/resources/nfc-helpers.js index aa698e15..13cbe49 100644 --- a/third_party/blink/web_tests/external/wpt/web-nfc/resources/nfc-helpers.js +++ b/third_party/blink/web_tests/external/wpt/web-nfc/resources/nfc-helpers.js
@@ -149,10 +149,6 @@ return createRecord('url', url, test_record_id); } -function createNDEFWriteOptions(ignoreRead) { - return {ignoreRead}; -} - // Compares NDEFMessageSource that was provided to the API // (e.g. NDEFWriter.write), and NDEFMessage that was received by the // mock NFC service.
diff --git a/third_party/blink/web_tests/platform/linux/svg/zoom/page/zoom-img-preserveAspectRatio-support-1-expected.png b/third_party/blink/web_tests/platform/linux/svg/zoom/page/zoom-img-preserveAspectRatio-support-1-expected.png index b8f8dc68..78dee36 100644 --- a/third_party/blink/web_tests/platform/linux/svg/zoom/page/zoom-img-preserveAspectRatio-support-1-expected.png +++ b/third_party/blink/web_tests/platform/linux/svg/zoom/page/zoom-img-preserveAspectRatio-support-1-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.14/svg/zoom/page/zoom-img-preserveAspectRatio-support-1-expected.png b/third_party/blink/web_tests/platform/mac-mac10.14/svg/zoom/page/zoom-img-preserveAspectRatio-support-1-expected.png index 74c7653..b33fc2e 100644 --- a/third_party/blink/web_tests/platform/mac-mac10.14/svg/zoom/page/zoom-img-preserveAspectRatio-support-1-expected.png +++ b/third_party/blink/web_tests/platform/mac-mac10.14/svg/zoom/page/zoom-img-preserveAspectRatio-support-1-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/svg/zoom/page/zoom-background-images-expected.png b/third_party/blink/web_tests/platform/mac/svg/zoom/page/zoom-background-images-expected.png index 6f31c28c..e42d5ea 100644 --- a/third_party/blink/web_tests/platform/mac/svg/zoom/page/zoom-background-images-expected.png +++ b/third_party/blink/web_tests/platform/mac/svg/zoom/page/zoom-background-images-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/svg/zoom/page/zoom-img-preserveAspectRatio-support-1-expected.png b/third_party/blink/web_tests/platform/mac/svg/zoom/page/zoom-img-preserveAspectRatio-support-1-expected.png index 31a8223f..40178f0 100644 --- a/third_party/blink/web_tests/platform/mac/svg/zoom/page/zoom-img-preserveAspectRatio-support-1-expected.png +++ b/third_party/blink/web_tests/platform/mac/svg/zoom/page/zoom-img-preserveAspectRatio-support-1-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/svg/zoom/page/zoom-svg-through-object-with-auto-size-expected.png b/third_party/blink/web_tests/platform/mac/svg/zoom/page/zoom-svg-through-object-with-auto-size-expected.png index ab2a007..3e4a3034 100644 --- a/third_party/blink/web_tests/platform/mac/svg/zoom/page/zoom-svg-through-object-with-auto-size-expected.png +++ b/third_party/blink/web_tests/platform/mac/svg/zoom/page/zoom-svg-through-object-with-auto-size-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/svg/zoom/page/zoom-background-images-expected.png b/third_party/blink/web_tests/platform/win/svg/zoom/page/zoom-background-images-expected.png index 942f4668..6498018 100644 --- a/third_party/blink/web_tests/platform/win/svg/zoom/page/zoom-background-images-expected.png +++ b/third_party/blink/web_tests/platform/win/svg/zoom/page/zoom-background-images-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/svg/zoom/page/zoom-img-preserveAspectRatio-support-1-expected.png b/third_party/blink/web_tests/platform/win/svg/zoom/page/zoom-img-preserveAspectRatio-support-1-expected.png index 16663ac7..15db67c 100644 --- a/third_party/blink/web_tests/platform/win/svg/zoom/page/zoom-img-preserveAspectRatio-support-1-expected.png +++ b/third_party/blink/web_tests/platform/win/svg/zoom/page/zoom-img-preserveAspectRatio-support-1-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/svg/zoom/page/zoom-svg-through-object-with-auto-size-expected.png b/third_party/blink/web_tests/platform/win/svg/zoom/page/zoom-svg-through-object-with-auto-size-expected.png index aa1d3ca0..9e835b4b 100644 --- a/third_party/blink/web_tests/platform/win/svg/zoom/page/zoom-svg-through-object-with-auto-size-expected.png +++ b/third_party/blink/web_tests/platform/win/svg/zoom/page/zoom-svg-through-object-with-auto-size-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/regress/regress-1117258.html b/third_party/blink/web_tests/regress/regress-1117258.html new file mode 100644 index 0000000..8f801fd7 --- /dev/null +++ b/third_party/blink/web_tests/regress/regress-1117258.html
@@ -0,0 +1,35 @@ +<title>Regression tests for crbug.com/1117258</title> +<script src="../resources/testharness.js"></script> +<script src="../resources/testharnessreport.js"></script> + +<script> +async_test((test) => { + function worker_code() { + self.addEventListener('message', () => { + let code = [ + 0x0, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00 + ]; + let wasm_blob = URL.createObjectURL( + new Blob([new Uint8Array(code)], { type: "application/wasm" }) + ); + let controller = new AbortController(); + let signal = controller.signal; + Object.defineProperty(WebAssembly.Module.prototype, 'then', { + get: function () { + controller.abort(); + } + }); + WebAssembly.compileStreaming(fetch(wasm_blob, { signal })).finally( + () => self.postMessage('success') + ); + }); + } + let blob = new Blob(['(', worker_code.toString(), ')()']); + let worker = new Worker(window.URL.createObjectURL(blob)); + worker.addEventListener('message', (message) => { + assert_equals(message.data, 'success'); + test.done(); + }); + worker.postMessage('start'); +}, 'Regression test for crbug.com/1117258'); +</script>
diff --git a/third_party/blink/web_tests/wpt_internal/css/css-backgrounds/border-width-zoom-001-ref.html b/third_party/blink/web_tests/wpt_internal/css/css-backgrounds/border-width-zoom-001-ref.html new file mode 100644 index 0000000..dd26ea3 --- /dev/null +++ b/third_party/blink/web_tests/wpt_internal/css/css-backgrounds/border-width-zoom-001-ref.html
@@ -0,0 +1,15 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Backgrounds and Borders Reference Test: border-width zoom</title> +<link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com"> +<style> + div { width: 75px; height: 75px; } +</style> +<p>The test passses if you see 4 boxes with green border, the last 2 ones with a thicker border.</p> +<div style="border: solid 0.75px green;"></div> +<br> +<div style="border: solid 0.75px green; border-radius: 15px;"></div> +</br> +<div style="border: solid 5px green;"></div> +<br> +<div style="border: solid 5px green; border-radius: 10px;"></div>
diff --git a/third_party/blink/web_tests/wpt_internal/css/css-backgrounds/border-width-zoom-001.html b/third_party/blink/web_tests/wpt_internal/css/css-backgrounds/border-width-zoom-001.html new file mode 100644 index 0000000..d45e77a --- /dev/null +++ b/third_party/blink/web_tests/wpt_internal/css/css-backgrounds/border-width-zoom-001.html
@@ -0,0 +1,16 @@ +<!DOCTYPE html> +<!-- This test has to be internal because "zoom" property is not standard and is not supported by all browsers. --> +<meta charset="utf-8"> +<title>CSS Backgrounds and Borders Test: border-width zoom</title> +<link rel="author" title="Manuel Rego Casasnovas" href="mailto:rego@igalia.com"> +<link rel="help" href="https://drafts.csswg.org/css-backgrounds/#border-width"> +<link rel="match" href="border-width-zoom-001-ref.html"> +<meta name="assert" content="Tese tests check that border-width with different zoom values are properly rendered and always visible."> +<p>The test passses if you see 4 boxes with green border, the last 2 ones with a thicker border.</p> +<div style="zoom: 1.5; border: solid 0.5px green; width: 50px; height: 50px;"></div> +<br> +<div style="zoom: 1.5; border: solid 0.5px green; width: 50px; height: 50px; border-radius: 10px;"></div> +</br> +<div style="zoom: 0.1; border: solid 50px green; width: 750px; height: 750px;"></div> +<br> +<div style="zoom: 0.1; border: solid 50px green; width: 750px; height: 750px; border-radius: 100px;"></div>
diff --git a/third_party/crashpad/README.chromium b/third_party/crashpad/README.chromium index 25886a79..de8fc93 100644 --- a/third_party/crashpad/README.chromium +++ b/third_party/crashpad/README.chromium
@@ -2,7 +2,7 @@ Short Name: crashpad URL: https://crashpad.chromium.org/ Version: unknown -Revision: 0cccdc0b7ec32bd31e789b3945a08c04ef775834 +Revision: 9a5a789123d7528d1c1cb71e66134fe0d7a9d37a License: Apache 2.0 License File: crashpad/LICENSE Security Critical: yes
diff --git a/third_party/crashpad/crashpad/DEPS b/third_party/crashpad/crashpad/DEPS index 3640572..3ecc47d 100644 --- a/third_party/crashpad/crashpad/DEPS +++ b/third_party/crashpad/crashpad/DEPS
@@ -42,7 +42,7 @@ '7bde79cc274d06451bf65ae82c012a5d3e476b5a', 'crashpad/third_party/mini_chromium/mini_chromium': Var('chromium_git') + '/chromium/mini_chromium@' + - '891e31d0b649ec9fa98ca5745f9dcd14a34de34c', + 'e0008f2714a76c7f2a3854fa75774427a886d6b9', 'crashpad/third_party/libfuzzer/src': Var('chromium_git') + '/chromium/llvm-project/compiler-rt/lib/fuzzer.git@' + 'fda403cf93ecb8792cb1d061564d89a6553ca020', @@ -81,26 +81,6 @@ 'condition': 'checkout_fuchsia and host_os == "linux"', 'dep_type': 'cipd' }, - 'crashpad/third_party/fuchsia/qemu/mac-amd64': { - 'packages': [ - { - 'package': 'fuchsia/qemu/mac-amd64', - 'version': 'latest' - }, - ], - 'condition': 'checkout_fuchsia and host_os == "mac"', - 'dep_type': 'cipd' - }, - 'crashpad/third_party/fuchsia/qemu/linux-amd64': { - 'packages': [ - { - 'package': 'fuchsia/qemu/linux-amd64', - 'version': 'latest' - }, - ], - 'condition': 'checkout_fuchsia and host_os == "linux"', - 'dep_type': 'cipd' - }, 'crashpad/third_party/fuchsia/sdk/mac-amd64': { 'packages': [ {
diff --git a/third_party/crashpad/crashpad/build/ios/convert_gn_xcodeproj.py b/third_party/crashpad/crashpad/build/ios/convert_gn_xcodeproj.py index 3bbbb4e..d546279 100755 --- a/third_party/crashpad/crashpad/build/ios/convert_gn_xcodeproj.py +++ b/third_party/crashpad/crashpad/build/ios/convert_gn_xcodeproj.py
@@ -29,6 +29,7 @@ import json import hashlib import os +import re import shutil import subprocess import sys @@ -37,239 +38,244 @@ class XcodeProject(object): - def __init__(self, objects, counter=0): - self.objects = objects - self.counter = 0 + def __init__(self, objects, counter = 0): + self.objects = objects + self.counter = 0 - def AddObject(self, parent_name, obj): - while True: - self.counter += 1 - str_id = "%s %s %d" % (parent_name, obj['isa'], self.counter) - new_id = hashlib.sha1( - str_id.encode("utf-8")).hexdigest()[:24].upper() + def AddObject(self, parent_name, obj): + while True: + self.counter += 1 + str_id = "%s %s %d" % (parent_name, obj['isa'], self.counter) + new_id = hashlib.sha1(str_id.encode("utf-8")).hexdigest()[:24].upper() - # Make sure ID is unique. It's possible there could be an id - # conflict since this is run after GN runs. - if new_id not in self.objects: - self.objects[new_id] = obj - return new_id + # Make sure ID is unique. It's possible there could be an id conflict + # since this is run after GN runs. + if new_id not in self.objects: + self.objects[new_id] = obj + return new_id def check_output(command): - """Wrapper around subprocess.check_output that decode output as utf-8.""" - return subprocess.check_output(command).decode('utf-8') + """Wrapper around subprocess.check_output that decode output as utf-8.""" + return subprocess.check_output(command).decode('utf-8') def CopyFileIfChanged(source_path, target_path): - """Copy |source_path| to |target_path| if different.""" - target_dir = os.path.dirname(target_path) - if not os.path.isdir(target_dir): - os.makedirs(target_dir) - if not os.path.exists(target_path) or \ - not filecmp.cmp(source_path, target_path): - shutil.copyfile(source_path, target_path) + """Copy |source_path| to |target_path| if different.""" + target_dir = os.path.dirname(target_path) + if not os.path.isdir(target_dir): + os.makedirs(target_dir) + if not os.path.exists(target_path) or \ + not filecmp.cmp(source_path, target_path): + shutil.copyfile(source_path, target_path) def CopyTreeIfChanged(source, target): - """Copy |source| to |target| recursively; files are copied iff changed.""" - if os.path.isfile(source): - return CopyFileIfChanged(source, target) - if not os.path.isdir(target): - os.makedirs(target) - for name in os.listdir(source): - CopyTreeIfChanged(os.path.join(source, name), - os.path.join(target, name)) + """Copy |source| to |target| recursively; files are copied iff changed.""" + if os.path.isfile(source): + return CopyFileIfChanged(source, target) + if not os.path.isdir(target): + os.makedirs(target) + for name in os.listdir(source): + CopyTreeIfChanged( + os.path.join(source, name), + os.path.join(target, name)) def LoadXcodeProjectAsJSON(project_dir): - """Return Xcode project at |path| as a JSON string.""" - return check_output([ - 'plutil', '-convert', 'json', '-o', '-', - os.path.join(project_dir, 'project.pbxproj') - ]) + """Return Xcode project at |path| as a JSON string.""" + return check_output([ + 'plutil', '-convert', 'json', '-o', '-', + os.path.join(project_dir, 'project.pbxproj')]) def WriteXcodeProject(output_path, json_string): - """Save Xcode project to |output_path| as XML.""" - with tempfile.NamedTemporaryFile() as temp_file: - temp_file.write(json_string.encode("utf-8")) - temp_file.flush() - subprocess.check_call(['plutil', '-convert', 'xml1', temp_file.name]) - CopyFileIfChanged(temp_file.name, - os.path.join(output_path, 'project.pbxproj')) + """Save Xcode project to |output_path| as XML.""" + with tempfile.NamedTemporaryFile() as temp_file: + temp_file.write(json_string.encode("utf-8")) + temp_file.flush() + subprocess.check_call(['plutil', '-convert', 'xml1', temp_file.name]) + CopyFileIfChanged( + temp_file.name, + os.path.join(output_path, 'project.pbxproj')) def UpdateXcodeProject(project_dir, configurations, root_dir): - """Update inplace Xcode project to support multiple configurations. + """Update inplace Xcode project to support multiple configurations. - Args: - project_dir: path to the input Xcode project - configurations: list of string corresponding to the configurations that - need to be supported by the tweaked Xcode projects, must contains at - least one value. - root_dir: path to the root directory used to find markdown files - """ - json_data = json.loads(LoadXcodeProjectAsJSON(project_dir)) - project = XcodeProject(json_data['objects']) + Args: + project_dir: path to the input Xcode project + configurations: list of string corresponding to the configurations that + need to be supported by the tweaked Xcode projects, must contains at + least one value. + root_dir: path to the root directory used to find markdown files + """ + json_data = json.loads(LoadXcodeProjectAsJSON(project_dir)) + project = XcodeProject(json_data['objects']) - objects_to_remove = [] - for value in list(project.objects.values()): - isa = value['isa'] + objects_to_remove = [] + for value in list(project.objects.values()): + isa = value['isa'] - # Teach build shell script to look for the configuration and platform. - if isa == 'PBXShellScriptBuildPhase': - value['shellScript'] = value['shellScript'].replace( - 'ninja -C .', - 'ninja -C "../${CONFIGURATION}${EFFECTIVE_PLATFORM_NAME}"') + # Teach build shell script to look for the configuration and platform. + if isa == 'PBXShellScriptBuildPhase': + shell_path = value['shellPath'] + if shell_path.endswith('/sh'): + value['shellScript'] = value['shellScript'].replace( + 'ninja -C .', + 'ninja -C "../${CONFIGURATION}${EFFECTIVE_PLATFORM_NAME}"') + elif re.search('[ /]python[23]?$', shell_path): + value['shellScript'] = value['shellScript'].replace( + 'ninja_params = [ \'-C\', \'.\' ]', + 'ninja_params = [ \'-C\', \'../\' + os.environ[\'CONFIGURATION\']' + ' + os.environ[\'EFFECTIVE_PLATFORM_NAME\'] ]') - # Add new configuration, using the first one as default. - if isa == 'XCConfigurationList': - value['defaultConfigurationName'] = configurations[0] - objects_to_remove.extend(value['buildConfigurations']) + # Add new configuration, using the first one as default. + if isa == 'XCConfigurationList': + value['defaultConfigurationName'] = configurations[0] + objects_to_remove.extend(value['buildConfigurations']) - build_config_template = project.objects[value['buildConfigurations'] - [0]] - build_config_template['buildSettings']['CONFIGURATION_BUILD_DIR'] =\ - '$(PROJECT_DIR)/../$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)' + build_config_template = project.objects[value['buildConfigurations'][0]] + build_config_template['buildSettings']['CONFIGURATION_BUILD_DIR'] = \ + '$(PROJECT_DIR)/../$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)' - value['buildConfigurations'] = [] - for configuration in configurations: - new_build_config = copy.copy(build_config_template) - new_build_config['name'] = configuration - value['buildConfigurations'].append( - project.AddObject('products', new_build_config)) + value['buildConfigurations'] = [] + for configuration in configurations: + new_build_config = copy.copy(build_config_template) + new_build_config['name'] = configuration + value['buildConfigurations'].append( + project.AddObject('products', new_build_config)) - for object_id in objects_to_remove: - del project.objects[object_id] + for object_id in objects_to_remove: + del project.objects[object_id] - source = GetOrCreateRootGroup(project, json_data['rootObject'], 'Source') - AddMarkdownToProject(project, root_dir, source) - SortFileReferencesByName(project, source) + source = GetOrCreateRootGroup(project, json_data['rootObject'], 'Source') + AddMarkdownToProject(project, root_dir, source) + SortFileReferencesByName(project, source) - objects = collections.OrderedDict(sorted(project.objects.items())) - WriteXcodeProject(project_dir, json.dumps(json_data)) + objects = collections.OrderedDict(sorted(project.objects.items())) + WriteXcodeProject(project_dir, json.dumps(json_data)) def CreateGroup(project, parent_group, group_name, path=None): - group_object = { - 'children': [], - 'isa': 'PBXGroup', - 'name': group_name, - 'sourceTree': '<group>', - } - if path is not None: - group_object['path'] = path - parent_group_name = parent_group.get('name', '') - group_object_key = project.AddObject(parent_group_name, group_object) - parent_group['children'].append(group_object_key) - return group_object + group_object = { + 'children': [], + 'isa': 'PBXGroup', + 'name': group_name, + 'sourceTree': '<group>', + } + if path is not None: + group_object['path'] = path + parent_group_name = parent_group.get('name', '') + group_object_key = project.AddObject(parent_group_name, group_object) + parent_group['children'].append(group_object_key) + return group_object def GetOrCreateRootGroup(project, root_object, group_name): - main_group = project.objects[project.objects[root_object]['mainGroup']] - for child_key in main_group['children']: - child = project.objects[child_key] - if child['name'] == group_name: - return child - return CreateGroup(project, main_group, group_name, path='../..') + main_group = project.objects[project.objects[root_object]['mainGroup']] + for child_key in main_group['children']: + child = project.objects[child_key] + if child['name'] == group_name: + return child + return CreateGroup(project, main_group, group_name, path='../..') class ObjectKey(object): - """Wrapper around PBXFileReference and PBXGroup for sorting. - A PBXGroup represents a "directory" containing a list of files in an - Xcode project; it can contain references to a list of directories or - files. + """Wrapper around PBXFileReference and PBXGroup for sorting. - A PBXFileReference represents a "file". + A PBXGroup represents a "directory" containing a list of files in an + Xcode project; it can contain references to a list of directories or + files. - The type is stored in the object "isa" property as a string. Since we - want to sort all directories before all files, the < and > operators - are defined so that if "isa" is different, they are sorted in the - reverse of alphabetic ordering, otherwise the name (or path) property - is checked and compared in alphabetic order. - """ + A PBXFileReference represents a "file". - def __init__(self, obj): - self.isa = obj['isa'] - if 'name' in obj: - self.name = obj['name'] - else: - self.name = obj['path'] + The type is stored in the object "isa" property as a string. Since we + want to sort all directories before all files, the < and > operators + are defined so that if "isa" is different, they are sorted in the + reverse of alphabetic ordering, otherwise the name (or path) property + is checked and compared in alphabetic order. + """ - def __lt__(self, other): - if self.isa != other.isa: - return self.isa > other.isa - return self.name < other.name + def __init__(self, obj): + self.isa = obj['isa'] + if 'name' in obj: + self.name = obj['name'] + else: + self.name = obj['path'] - def __gt__(self, other): - if self.isa != other.isa: - return self.isa < other.isa - return self.name > other.name + def __lt__(self, other): + if self.isa != other.isa: + return self.isa > other.isa + return self.name < other.name - def __eq__(self, other): - return self.isa == other.isa and self.name == other.name + def __gt__(self, other): + if self.isa != other.isa: + return self.isa < other.isa + return self.name > other.name + + def __eq__(self, other): + return self.isa == other.isa and self.name == other.name def SortFileReferencesByName(project, group_object): - SortFileReferencesByNameWithSortKey( - project, group_object, lambda ref: ObjectKey(project.objects[ref])) + SortFileReferencesByNameWithSortKey( + project, group_object, lambda ref: ObjectKey(project.objects[ref])) def SortFileReferencesByNameWithSortKey(project, group_object, sort_key): - group_object['children'].sort(key=sort_key) - for key in group_object['children']: - child = project.objects[key] - if child['isa'] == 'PBXGroup': - SortFileReferencesByNameWithSortKey(project, child, sort_key) + group_object['children'].sort(key=sort_key) + for key in group_object['children']: + child = project.objects[key] + if child['isa'] == 'PBXGroup': + SortFileReferencesByNameWithSortKey(project, child, sort_key) def AddMarkdownToProject(project, root_dir, group_object): - list_files_cmd = ['git', '-C', root_dir, 'ls-files', '*.md'] - paths = check_output(list_files_cmd).splitlines() - ios_internal_dir = os.path.join(root_dir, 'ios_internal') - if os.path.exists(ios_internal_dir): - list_files_cmd = ['git', '-C', ios_internal_dir, 'ls-files', '*.md'] - ios_paths = check_output(list_files_cmd).splitlines() - paths.extend([os.path.join("ios_internal", path) for path in ios_paths]) - for path in paths: - new_markdown_entry = { - "fileEncoding": "4", - "isa": "PBXFileReference", - "lastKnownFileType": "net.daringfireball.markdown", - "name": os.path.basename(path), - "path": path, - "sourceTree": "<group>" - } - new_markdown_entry_id = project.AddObject('sources', new_markdown_entry) - folder = GetFolderForPath(project, group_object, os.path.dirname(path)) - folder['children'].append(new_markdown_entry_id) + list_files_cmd = ['git', '-C', root_dir, 'ls-files', '*.md'] + paths = check_output(list_files_cmd).splitlines() + ios_internal_dir = os.path.join(root_dir, 'ios_internal') + if os.path.exists(ios_internal_dir): + list_files_cmd = ['git', '-C', ios_internal_dir, 'ls-files', '*.md'] + ios_paths = check_output(list_files_cmd).splitlines() + paths.extend([os.path.join("ios_internal", path) for path in ios_paths]) + for path in paths: + new_markdown_entry = { + "fileEncoding": "4", + "isa": "PBXFileReference", + "lastKnownFileType": "net.daringfireball.markdown", + "name": os.path.basename(path), + "path": path, + "sourceTree": "<group>" + } + new_markdown_entry_id = project.AddObject('sources', new_markdown_entry) + folder = GetFolderForPath(project, group_object, os.path.dirname(path)) + folder['children'].append(new_markdown_entry_id) def GetFolderForPath(project, group_object, path): - objects = project.objects - if not path: - return group_object - for folder in path.split('/'): - children = group_object['children'] - new_root = None - for child in children: - if objects[child]['isa'] == 'PBXGroup' and \ - objects[child]['name'] == folder: - new_root = objects[child] - break - if not new_root: - # If the folder isn't found we could just cram it into the leaf - # existing folder, but that leads to folders with tons of README.md - # inside. - new_root = CreateGroup(project, group_object, folder) - group_object = new_root + objects = project.objects + if not path: return group_object + for folder in path.split('/'): + children = group_object['children'] + new_root = None + for child in children: + if objects[child]['isa'] == 'PBXGroup' and \ + objects[child]['name'] == folder: + new_root = objects[child] + break + if not new_root: + # If the folder isn't found we could just cram it into the leaf existing + # folder, but that leads to folders with tons of README.md inside. + new_root = CreateGroup(project, group_object, folder) + group_object = new_root + return group_object def ConvertGnXcodeProject(root_dir, input_dir, output_dir, configurations): - '''Tweak the Xcode project generated by gn to support multiple - configurations. + '''Tweak the Xcode project generated by gn to support multiple configurations. The Xcode projects generated by "gn gen --ide" only supports a single platform and configuration (as the platform and configuration are set @@ -285,76 +291,71 @@ least one value. ''' - # Update the project (supports legacy name "products.xcodeproj" or the new - # project name "all.xcodeproj"). - for project_name in ('all.xcodeproj', 'products.xcodeproj'): - if os.path.exists(os.path.join(input_dir, project_name)): - UpdateXcodeProject(os.path.join(input_dir, project_name), - configurations, root_dir) + # Update the project (supports legacy name "products.xcodeproj" or the new + # project name "all.xcodeproj"). + for project_name in ('all.xcodeproj', 'products.xcodeproj'): + if os.path.exists(os.path.join(input_dir, project_name)): + UpdateXcodeProject( + os.path.join(input_dir, project_name), + configurations, root_dir) - CopyTreeIfChanged(os.path.join(input_dir, project_name), - os.path.join(output_dir, project_name)) + CopyTreeIfChanged(os.path.join(input_dir, project_name), + os.path.join(output_dir, project_name)) - else: - shutil.rmtree(os.path.join(output_dir, project_name), - ignore_errors=True) - - # Copy all.xcworkspace if it exists (will be removed in a future gn version). - workspace_name = 'all.xcworkspace' - if os.path.exists(os.path.join(input_dir, workspace_name)): - CopyTreeIfChanged(os.path.join(input_dir, workspace_name), - os.path.join(output_dir, workspace_name)) else: - shutil.rmtree(os.path.join(output_dir, workspace_name), - ignore_errors=True) + shutil.rmtree(os.path.join(output_dir, project_name), ignore_errors=True) + + # Copy all.xcworkspace if it exists (will be removed in a future gn version). + workspace_name = 'all.xcworkspace' + if os.path.exists(os.path.join(input_dir, workspace_name)): + CopyTreeIfChanged(os.path.join(input_dir, workspace_name), + os.path.join(output_dir, workspace_name)) + else: + shutil.rmtree(os.path.join(output_dir, workspace_name), ignore_errors=True) def Main(args): - parser = argparse.ArgumentParser( - description='Convert GN Xcode projects for iOS.') - parser.add_argument( - 'input', help='directory containing [product|all] Xcode projects.') - parser.add_argument( - 'output', help='directory where to generate the iOS configuration.') - parser.add_argument('--add-config', - dest='configurations', - default=[], - action='append', - help='configuration to add to the Xcode project') - parser.add_argument('--root', - type=os.path.abspath, - required=True, - help='root directory of the project') - args = parser.parse_args(args) + parser = argparse.ArgumentParser( + description='Convert GN Xcode projects for iOS.') + parser.add_argument( + 'input', + help='directory containing [product|all] Xcode projects.') + parser.add_argument( + 'output', + help='directory where to generate the iOS configuration.') + parser.add_argument( + '--add-config', dest='configurations', default=[], action='append', + help='configuration to add to the Xcode project') + parser.add_argument( + '--root', type=os.path.abspath, required=True, + help='root directory of the project') + args = parser.parse_args(args) - if not os.path.isdir(args.input): - sys.stderr.write('Input directory does not exists.\n') - return 1 + if not os.path.isdir(args.input): + sys.stderr.write('Input directory does not exists.\n') + return 1 - # Depending on the version of "gn", there should be either one project file - # named "all.xcodeproj" or a project file named "products.xcodeproj" and a - # workspace named "all.xcworkspace". - required_files_sets = [ - set(("all.xcodeproj",)), - set(("products.xcodeproj", "all.xcworkspace")), - ] + # Depending on the version of "gn", there should be either one project file + # named "all.xcodeproj" or a project file named "products.xcodeproj" and a + # workspace named "all.xcworkspace". + required_files_sets = [ + set(("all.xcodeproj",)), + set(("products.xcodeproj", "all.xcworkspace")), + ] - for required_files in required_files_sets: - if required_files.issubset(os.listdir(args.input)): - break - else: - sys.stderr.write( - 'Input directory does not contain all necessary Xcode projects.\n') - return 1 + for required_files in required_files_sets: + if required_files.issubset(os.listdir(args.input)): + break + else: + sys.stderr.write( + 'Input directory does not contain all necessary Xcode projects.\n') + return 1 - if not args.configurations: - sys.stderr.write( - 'At least one configuration required, see --add-config.\n') - return 1 + if not args.configurations: + sys.stderr.write('At least one configuration required, see --add-config.\n') + return 1 - ConvertGnXcodeProject(args.root, args.input, args.output, - args.configurations) - + ConvertGnXcodeProject(args.root, args.input, args.output, args.configurations) if __name__ == '__main__': - sys.exit(Main(sys.argv[1:])) + sys.exit(Main(sys.argv[1:]))
diff --git a/third_party/crashpad/crashpad/build/run_fuchsia_qemu.py b/third_party/crashpad/crashpad/build/run_fuchsia_qemu.py deleted file mode 100755 index 67463e63..0000000 --- a/third_party/crashpad/crashpad/build/run_fuchsia_qemu.py +++ /dev/null
@@ -1,145 +0,0 @@ -#!/usr/bin/env python - -# Copyright 2017 The Crashpad Authors. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -"""Helper script to [re]start or stop a helper Fuchsia QEMU instance to be used -for running tests without a device. -""" - -from __future__ import print_function - -import getpass -import os -import random -import signal -import subprocess -import sys -import tempfile -import time - -try: - from subprocess import DEVNULL -except ImportError: - DEVNULL = open(os.devnull, 'r+b') - -CRASHPAD_ROOT = os.path.join(os.path.dirname(os.path.abspath(__file__)), - os.pardir) - - -def _Stop(pid_file): - if os.path.isfile(pid_file): - with open(pid_file, 'rb') as f: - pid = int(f.read().strip()) - try: - os.kill(pid, signal.SIGTERM) - except: - print('Unable to kill pid %d, continuing' % pid, file=sys.stderr) - os.unlink(pid_file) - - -def _CheckForTun(): - """Check for networking. TODO(scottmg): Currently, this is Linux-specific. - """ - returncode = subprocess.call( - ['tunctl', '-b', '-u', - getpass.getuser(), '-t', 'qemu'], - stdout=DEVNULL, - stderr=DEVNULL) - if returncode != 0: - print('To use QEMU with networking on Linux, configure TUN/TAP. See:', - file=sys.stderr) - print( - ' https://fuchsia.googlesource.com/zircon/+/HEAD/docs/qemu.md#enabling-networking-under-qemu-x86_64-only', - file=sys.stderr) - return 2 - return 0 - - -def _Start(pid_file): - tun_result = _CheckForTun() - if tun_result != 0: - return tun_result - - arch = 'mac-amd64' if sys.platform == 'darwin' else 'linux-amd64' - fuchsia_dir = os.path.join(CRASHPAD_ROOT, 'third_party', 'fuchsia') - qemu_path = os.path.join(fuchsia_dir, 'qemu', arch, 'bin', - 'qemu-system-x86_64') - kernel_data_dir = os.path.join(fuchsia_dir, 'sdk', arch, 'target', 'x86_64') - kernel_path = os.path.join(kernel_data_dir, 'zircon.bin') - initrd_path = os.path.join(kernel_data_dir, 'bootdata.bin') - - mac_tail = ':'.join('%02x' % random.randint(0, 255) for x in range(3)) - instance_name = ( - 'crashpad_qemu_' + - ''.join(chr(random.randint(ord('A'), ord('Z'))) for x in range(8))) - - # These arguments are from the Fuchsia repo in zircon/scripts/run-zircon. - - # yapf: disable - popen = subprocess.Popen([ - qemu_path, - '-m', '2048', - '-nographic', - '-kernel', kernel_path, - '-initrd', initrd_path, - '-smp', '4', - '-serial', 'stdio', - '-monitor', 'none', - '-machine', 'q35', - '-cpu', 'host,migratable=no,+invtsc', - '-enable-kvm', - '-netdev', 'type=tap,ifname=qemu,script=no,downscript=no,id=net0', - '-device', 'e1000,netdev=net0,mac=52:54:00:' + mac_tail, - '-append', 'TERM=dumb zircon.nodename=' + instance_name, - ], - stdin=DEVNULL, - stdout=DEVNULL, - stderr=DEVNULL) - # yapf: enable - - with open(pid_file, 'wb') as f: - f.write('%d\n' % popen.pid) - - for i in range(10): - netaddr_path = os.path.join(fuchsia_dir, 'sdk', arch, 'tools', - 'netaddr') - if subprocess.call([netaddr_path, '--nowait', instance_name], - stdout=open(os.devnull), - stderr=open(os.devnull)) == 0: - break - time.sleep(.5) - else: - print('instance did not respond after start', file=sys.stderr) - return 1 - - return 0 - - -def main(args): - if len(args) != 1 or args[0] not in ('start', 'stop'): - print('usage: run_fuchsia_qemu.py start|stop', file=sys.stderr) - return 1 - - command = args[0] - - pid_file = os.path.join(tempfile.gettempdir(), 'crashpad_fuchsia_qemu_pid') - _Stop(pid_file) - if command == 'start': - return _Start(pid_file) - - return 0 - - -if __name__ == '__main__': - sys.exit(main(sys.argv[1:]))
diff --git a/third_party/crashpad/crashpad/build/run_tests.py b/third_party/crashpad/crashpad/build/run_tests.py index 5e70d7b..f48652ff 100755 --- a/third_party/crashpad/crashpad/build/run_tests.py +++ b/third_party/crashpad/crashpad/build/run_tests.py
@@ -313,144 +313,6 @@ _adb_shell(['rm', '-rf', device_temp_dir]) -def _GetFuchsiaSDKRoot(): - arch = 'mac-amd64' if sys.platform == 'darwin' else 'linux-amd64' - return os.path.join(CRASHPAD_DIR, 'third_party', 'fuchsia', 'sdk', arch) - - -def _GenerateFuchsiaRuntimeDepsFiles(binary_dir, tests): - """Ensures a <binary_dir>/<test>.runtime_deps file exists for each test.""" - targets_file = os.path.join(binary_dir, 'targets.txt') - with open(targets_file, 'wb') as f: - f.write('//:' + '\n//:'.join(tests) + '\n') - gn_path = _FindGNFromBinaryDir(binary_dir) - subprocess.check_call([ - gn_path, '--root=' + CRASHPAD_DIR, 'gen', binary_dir, - '--runtime-deps-list-file=' + targets_file - ]) - - # Run again so that --runtime-deps-list-file isn't in the regen rule. See - # https://crbug.com/814816. - subprocess.check_call( - [gn_path, '--root=' + CRASHPAD_DIR, 'gen', binary_dir]) - - -def _HandleOutputFromFuchsiaLogListener(process, done_message): - """Pass through the output from |process| (which should be an instance of - Fuchsia's loglistener) until a special termination |done_message| is - encountered. - - Also attempts to determine if any tests failed by inspecting the log output, - and returns False if there were failures. - """ - success = True - while True: - line = process.stdout.readline().rstrip() - if 'FAILED TEST' in line: - success = False - elif done_message in line and 'echo ' not in line: - break - print(line) - return success - - -def _RunOnFuchsiaTarget(binary_dir, test, device_name, extra_command_line): - """Runs the given Fuchsia |test| executable on the given |device_name|. The - device must already be booted. - - Copies the executable and its runtime dependencies as specified by GN to the - target in /tmp using `netcp`, runs the binary on the target, and logs output - back to stdout on this machine via `loglistener`. - """ - sdk_root = _GetFuchsiaSDKRoot() - - # Run loglistener and filter the output to know when the test is done. - loglistener_process = subprocess.Popen( - [os.path.join(sdk_root, 'tools', 'loglistener'), device_name], - stdout=subprocess.PIPE, - stdin=open(os.devnull), - stderr=open(os.devnull)) - - runtime_deps_file = os.path.join(binary_dir, test + '.runtime_deps') - with open(runtime_deps_file, 'rb') as f: - runtime_deps = f.read().splitlines() - - def netruncmd(*args): - """Runs a list of commands on the target device. Each command is escaped - by using pipes.quote(), and then each command is chained by shell ';'. - """ - netruncmd_path = os.path.join(sdk_root, 'tools', 'netruncmd') - final_args = ' ; '.join( - ' '.join(pipes.quote(x) for x in command) for command in args) - subprocess.check_call([netruncmd_path, device_name, final_args]) - - try: - unique_id = uuid.uuid4().hex - test_root = '/tmp/%s_%s' % (test, unique_id) - tmp_root = test_root + '/tmp' - staging_root = test_root + '/pkg' - - # Make a staging directory tree on the target. - directories_to_create = [ - tmp_root, - '%s/bin' % staging_root, - '%s/assets' % staging_root - ] - netruncmd(['mkdir', '-p'] + directories_to_create) - - def netcp(local_path): - """Uses `netcp` to copy a file or directory to the device. Files - located inside the build dir are stored to /pkg/bin, otherwise to - /pkg/assets. .so files are stored somewhere completely different, - into /boot/lib (!). This is because the loader service does not yet - correctly handle the namespace in which the caller is being run, and - so can only load .so files from a couple hardcoded locations, the - only writable one of which is /boot/lib, so we copy all .so files - there. This bug is filed upstream as ZX-1619. - """ - in_binary_dir = local_path.startswith(binary_dir + '/') - if in_binary_dir: - if local_path.endswith('.so'): - target_path = os.path.join('/boot/lib', - local_path[len(binary_dir) + 1:]) - else: - target_path = os.path.join(staging_root, 'bin', - local_path[len(binary_dir) + 1:]) - else: - relative_path = os.path.relpath(local_path, CRASHPAD_DIR) - target_path = os.path.join(staging_root, 'assets', - relative_path) - netcp_path = os.path.join(sdk_root, 'tools', 'netcp') - subprocess.check_call( - [netcp_path, local_path, device_name + ':' + target_path], - stderr=open(os.devnull)) - - # Copy runtime deps into the staging tree. - for dep in runtime_deps: - local_path = os.path.normpath(os.path.join(binary_dir, dep)) - if os.path.isdir(local_path): - for root, dirs, files in os.walk(local_path): - for f in files: - netcp(os.path.join(root, f)) - else: - netcp(local_path) - - done_message = 'TERMINATED: ' + unique_id - namespace_command = [ - 'namespace', '/pkg=' + staging_root, '/tmp=' + tmp_root, - '/svc=/svc', '--replace-child-argv0=/pkg/bin/' + test, '--', - staging_root + '/bin/' + test - ] + extra_command_line - netruncmd(namespace_command, ['echo', done_message]) - - success = _HandleOutputFromFuchsiaLogListener(loglistener_process, - done_message) - if not success: - raise subprocess.CalledProcessError(1, test) - finally: - netruncmd(['rm', '-rf', test_root]) - - def _RunOnIOSTarget(binary_dir, test, is_xcuitest=False): """Runs the given iOS |test| app on iPhone 8 with the default OS version.""" @@ -544,7 +406,6 @@ target_os = _BinaryDirTargetOS(args.binary_dir) is_android = target_os == 'android' - is_fuchsia = target_os == 'fuchsia' is_ios = target_os == 'ios' tests = [ @@ -575,21 +436,6 @@ return 2 android_device = devices[0] print('Using autodetected Android device:', android_device) - elif is_fuchsia: - zircon_nodename = os.environ.get('ZIRCON_NODENAME') - if not zircon_nodename: - netls = os.path.join(_GetFuchsiaSDKRoot(), 'tools', 'netls') - popen = subprocess.Popen([netls, '--nowait'], - stdout=subprocess.PIPE) - devices = popen.communicate()[0].splitlines() - if popen.returncode != 0 or len(devices) != 1: - print("Please set ZIRCON_NODENAME to your device's hostname", - file=sys.stderr) - return 2 - zircon_nodename = devices[0].strip().split()[1] - print('Using autodetected Fuchsia device:', zircon_nodename) - _GenerateFuchsiaRuntimeDepsFiles( - args.binary_dir, [t for t in tests if not t.endswith('.py')]) elif is_ios: tests.append('ios_crash_xcuitests') elif IS_WINDOWS_HOST: @@ -618,9 +464,6 @@ if is_android: _RunOnAndroidTarget(args.binary_dir, test, android_device, extra_command_line) - elif is_fuchsia: - _RunOnFuchsiaTarget(args.binary_dir, test, zircon_nodename, - extra_command_line) elif is_ios: _RunOnIOSTarget(args.binary_dir, test,
diff --git a/third_party/crashpad/crashpad/client/BUILD.gn b/third_party/crashpad/crashpad/client/BUILD.gn index f448d35..10b994f 100644 --- a/third_party/crashpad/crashpad/client/BUILD.gn +++ b/third_party/crashpad/crashpad/client/BUILD.gn
@@ -116,6 +116,7 @@ deps += [ "../third_party/fuchsia" ] if (crashpad_is_in_fuchsia) { deps += [ "//sdk/lib/fdio" ] + configs += [ "//build/config:Wno-conversion" ] } } }
diff --git a/third_party/crashpad/crashpad/client/crashpad_client.h b/third_party/crashpad/crashpad/client/crashpad_client.h index 36589727..5d42139 100644 --- a/third_party/crashpad/crashpad/client/crashpad_client.h +++ b/third_party/crashpad/crashpad/client/crashpad_client.h
@@ -33,7 +33,7 @@ #elif defined(OS_WIN) #include <windows.h> #include "util/win/scoped_handle.h" -#elif defined(OS_LINUX) || defined(OS_ANDROID) +#elif defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID) #include <signal.h> #include <ucontext.h> #endif @@ -121,7 +121,7 @@ bool asynchronous_start, const std::vector<base::FilePath>& attachments = {}); -#if defined(OS_ANDROID) || defined(OS_LINUX) || DOXYGEN +#if defined(OS_ANDROID) || defined(OS_LINUX) || defined(OS_CHROMEOS) || DOXYGEN //! \brief Retrieve the socket and process ID for the handler. //! //! `StartHandler()` must have successfully been called before calling this @@ -166,7 +166,7 @@ //! //! \return `true` on success. Otherwise `false` with a message logged. static bool InitializeSignalStackForThread(); -#endif // OS_ANDROID || OS_LINUX || DOXYGEN +#endif // OS_ANDROID || OS_LINUX || OS_CHROMEOS || DOXYGEN #if defined(OS_ANDROID) || DOXYGEN //! \brief Installs a signal handler to execute `/system/bin/app_process` and @@ -337,7 +337,7 @@ int socket); #endif // OS_ANDROID || DOXYGEN -#if defined(OS_LINUX) || defined(OS_ANDROID) || DOXYGEN +#if defined(OS_LINUX) || defined(OS_ANDROID) || defined(OS_CHROMEOS) || DOXYGEN //! \brief Installs a signal handler to launch a handler process in reponse to //! a crash. //! @@ -450,7 +450,7 @@ //! //! \param[in] unhandled_signals The set of unhandled signals void SetUnhandledSignals(const std::set<int>& unhandled_signals); -#endif // OS_LINUX || OS_ANDROID || DOXYGEN +#endif // OS_LINUX || OS_ANDROID || OS_CHROMEOS || DOXYGEN #if defined(OS_IOS) || DOXYGEN //! \brief Configures the process to direct its crashes to the iOS in-process @@ -662,7 +662,7 @@ #elif defined(OS_WIN) std::wstring ipc_pipe_; ScopedKernelHANDLE handler_start_thread_; -#elif defined(OS_LINUX) || defined(OS_ANDROID) +#elif defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID) std::set<int> unhandled_signals_; #endif // OS_APPLE
diff --git a/third_party/crashpad/crashpad/client/crashpad_client_linux.cc b/third_party/crashpad/crashpad/client/crashpad_client_linux.cc index 117ed19..8425d77 100644 --- a/third_party/crashpad/crashpad/client/crashpad_client_linux.cc +++ b/third_party/crashpad/crashpad/client/crashpad_client_linux.cc
@@ -411,7 +411,7 @@ std::move(client_sock), handler_pid, &unhandled_signals_); } -#if defined(OS_ANDROID) || defined(OS_LINUX) +#if defined(OS_ANDROID) || defined(OS_LINUX) || defined(OS_CHROMEOS) // static bool CrashpadClient::GetHandlerSocket(int* sock, pid_t* pid) { auto signal_handler = RequestCrashDumpHandler::Get(); @@ -515,7 +515,7 @@ } return true; } -#endif // OS_ANDROID || OS_LINUX +#endif // OS_ANDROID || OS_LINUX || OS_CHROMEOS #if defined(OS_ANDROID)
diff --git a/third_party/crashpad/crashpad/client/crashpad_client_mac.cc b/third_party/crashpad/crashpad/client/crashpad_client_mac.cc index 3c6d13a..ddcd485f 100644 --- a/third_party/crashpad/crashpad/client/crashpad_client_mac.cc +++ b/third_party/crashpad/crashpad/client/crashpad_client_mac.cc
@@ -14,6 +14,7 @@ #include "client/crashpad_client.h" +#include <Availability.h> #include <errno.h> #include <mach/mach.h> #include <pthread.h> @@ -454,14 +455,15 @@ // The “restartable” behavior can only be selected on OS X 10.10 and later. In // previous OS versions, if the initial client were to crash while attempting // to restart the handler, it would become an unkillable process. - base::mac::ScopedMachSendRight exception_port( - HandlerStarter::InitialStart(handler, - database, - metrics_dir, - url, - annotations, - arguments, - restartable && MacOSXMinorVersion() >= 10)); + base::mac::ScopedMachSendRight exception_port(HandlerStarter::InitialStart( + handler, + database, + metrics_dir, + url, + annotations, + arguments, + restartable && (__MAC_OS_X_VERSION_MIN_REQUIRED >= __MAC_10_10 || + MacOSVersionNumber() >= 10'10'00))); if (!exception_port.is_valid()) { return false; }
diff --git a/third_party/crashpad/crashpad/client/crashpad_info.cc b/third_party/crashpad/crashpad/client/crashpad_info.cc index 12307be5..929c0df 100644 --- a/third_party/crashpad/crashpad/client/crashpad_info.cc +++ b/third_party/crashpad/crashpad/client/crashpad_info.cc
@@ -94,7 +94,8 @@ // static CrashpadInfo* CrashpadInfo::GetCrashpadInfo() { -#if defined(OS_LINUX) || defined(OS_ANDROID) || defined(OS_FUCHSIA) +#if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID) || \ + defined(OS_FUCHSIA) // This otherwise-unused reference is used so that any module that // references GetCrashpadInfo() will also include the note in the // .note.crashpad.info section. That note in turn contains the address of
diff --git a/third_party/crashpad/crashpad/client/simulate_crash.h b/third_party/crashpad/crashpad/client/simulate_crash.h index 68c84e5..18af98f3 100644 --- a/third_party/crashpad/crashpad/client/simulate_crash.h +++ b/third_party/crashpad/crashpad/client/simulate_crash.h
@@ -21,7 +21,7 @@ #include "client/simulate_crash_mac.h" #elif defined(OS_WIN) #include "client/simulate_crash_win.h" -#elif defined(OS_LINUX) || defined(OS_ANDROID) +#elif defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID) #include "client/simulate_crash_linux.h" #endif
diff --git a/third_party/crashpad/crashpad/compat/BUILD.gn b/third_party/crashpad/crashpad/compat/BUILD.gn index f2ffcf5..d98a6a6e 100644 --- a/third_party/crashpad/crashpad/compat/BUILD.gn +++ b/third_party/crashpad/crashpad/compat/BUILD.gn
@@ -57,10 +57,17 @@ # static_library. group(target_name) { forward_variables_from(invoker, "*") + not_needed([ "configs" ]) } } else { static_library(target_name) { - forward_variables_from(invoker, "*") + forward_variables_from(invoker, "*", [ "configs" ]) + if (!(defined(configs))) { + configs = [] + } + if (defined(invoker.configs)) { + configs += invoker.configs + } } } } @@ -70,7 +77,8 @@ if (crashpad_is_mac || crashpad_is_ios) { sources += [ - "mac/AvailabilityMacros.h", + "mac/Availability.h", + "mac/AvailabilityVersions.h", "mac/kern/exc_resource.h", "mac/mach-o/loader.h", "mac/mach/i386/thread_state.h", @@ -171,4 +179,8 @@ if (!crashpad_is_linux && !crashpad_is_android && !crashpad_is_fuchsia) { deps += [ "../third_party/glibc" ] } + + if (crashpad_is_in_fuchsia) { + configs = [ "//build/config:Wno-conversion" ] + } }
diff --git a/third_party/crashpad/crashpad/compat/compat.gyp b/third_party/crashpad/crashpad/compat/compat.gyp index b99d690..1c2eeaf4 100644 --- a/third_party/crashpad/crashpad/compat/compat.gyp +++ b/third_party/crashpad/crashpad/compat/compat.gyp
@@ -38,7 +38,8 @@ 'linux/signal.h', 'linux/sys/ptrace.h', 'linux/sys/user.h', - 'mac/AvailabilityMacros.h', + 'mac/Availability.h', + 'mac/AvailabilityVersions.h', 'mac/kern/exc_resource.h', 'mac/mach/i386/thread_state.h', 'mac/mach/mach.h',
diff --git a/third_party/crashpad/crashpad/compat/mac/Availability.h b/third_party/crashpad/crashpad/compat/mac/Availability.h new file mode 100644 index 0000000..b8f8f2d --- /dev/null +++ b/third_party/crashpad/crashpad/compat/mac/Availability.h
@@ -0,0 +1,28 @@ +// Copyright 2020 The Crashpad Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef CRASHPAD_COMPAT_MAC_AVAILABILITY_H_ +#define CRASHPAD_COMPAT_MAC_AVAILABILITY_H_ + +// Until the 10.15 SDK, the contents of <AvailabilityVersions.h> was in-line in +// <Availability.h>, but since then, it was broken out into its own header. +// This compat version of <Availability.h> allows these macros to always appear +// to be provided by the new header, <AvailabilityVersions.h>, even when an +// older SDK is in use. + +#include_next <Availability.h> + +#include <AvailabilityVersions.h> + +#endif // CRASHPAD_COMPAT_MAC_AVAILABILITY_H_
diff --git a/third_party/crashpad/crashpad/compat/mac/AvailabilityMacros.h b/third_party/crashpad/crashpad/compat/mac/AvailabilityMacros.h deleted file mode 100644 index a83d2a4..0000000 --- a/third_party/crashpad/crashpad/compat/mac/AvailabilityMacros.h +++ /dev/null
@@ -1,74 +0,0 @@ -// Copyright 2014 The Crashpad Authors. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef CRASHPAD_COMPAT_MAC_AVAILABILITYMACROS_H_ -#define CRASHPAD_COMPAT_MAC_AVAILABILITYMACROS_H_ - -#include_next <AvailabilityMacros.h> - -// 10.7 SDK - -#ifndef MAC_OS_X_VERSION_10_7 -#define MAC_OS_X_VERSION_10_7 1070 -#endif - -// 10.8 SDK - -#ifndef MAC_OS_X_VERSION_10_8 -#define MAC_OS_X_VERSION_10_8 1080 -#endif - -// 10.9 SDK - -#ifndef MAC_OS_X_VERSION_10_9 -#define MAC_OS_X_VERSION_10_9 1090 -#endif - -// 10.10 SDK - -#ifndef MAC_OS_X_VERSION_10_10 -#define MAC_OS_X_VERSION_10_10 101000 -#endif - -// 10.11 SDK - -#ifndef MAC_OS_X_VERSION_10_11 -#define MAC_OS_X_VERSION_10_11 101100 -#endif - -// 10.12 SDK - -#ifndef MAC_OS_X_VERSION_10_12 -#define MAC_OS_X_VERSION_10_12 101200 -#endif - -// 10.13 SDK - -#ifndef MAC_OS_X_VERSION_10_13 -#define MAC_OS_X_VERSION_10_13 101300 -#endif - -// 10.14 SDK - -#ifndef MAC_OS_X_VERSION_10_14 -#define MAC_OS_X_VERSION_10_14 101400 -#endif - -// 10.15 SDK - -#ifndef MAC_OS_X_VERSION_10_15 -#define MAC_OS_X_VERSION_10_15 101500 -#endif - -#endif // CRASHPAD_COMPAT_MAC_AVAILABILITYMACROS_H_
diff --git a/third_party/crashpad/crashpad/compat/mac/AvailabilityVersions.h b/third_party/crashpad/crashpad/compat/mac/AvailabilityVersions.h new file mode 100644 index 0000000..0bedb3d --- /dev/null +++ b/third_party/crashpad/crashpad/compat/mac/AvailabilityVersions.h
@@ -0,0 +1,90 @@ +// Copyright 2020 The Crashpad Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef CRASHPAD_COMPAT_MAC_AVAILABILITYVERSIONS_H_ +#define CRASHPAD_COMPAT_MAC_AVAILABILITYVERSIONS_H_ + +#if __has_include_next(<AvailabilityVersions.h>) +#include_next <AvailabilityVersions.h> +#endif + +// 10.7 SDK + +#ifndef __MAC_10_7 +#define __MAC_10_7 1070 +#endif + +// 10.8 SDK + +#ifndef __MAC_10_8 +#define __MAC_10_8 1080 +#endif + +// 10.9 SDK + +#ifndef __MAC_10_9 +#define __MAC_10_9 1090 +#endif + +// 10.10 SDK + +#ifndef __MAC_10_10 +#define __MAC_10_10 101000 +#endif + +// 10.11 SDK + +#ifndef __MAC_10_11 +#define __MAC_10_11 101100 +#endif + +// 10.12 SDK + +#ifndef __MAC_10_12 +#define __MAC_10_12 101200 +#endif + +// 10.13 SDK + +#ifndef __MAC_10_13 +#define __MAC_10_13 101300 +#endif + +#ifndef __MAC_10_13_4 +#define __MAC_10_13_4 101304 +#endif + +// 10.14 SDK + +#ifndef __MAC_10_14 +#define __MAC_10_14 101400 +#endif + +// 10.15 SDK + +#ifndef __MAC_10_15 +#define __MAC_10_15 101500 +#endif + +// 11.0 SDK + +#ifndef __MAC_10_16 +#define __MAC_10_16 101600 +#endif + +#ifndef __MAC_11_0 +#define __MAC_11_0 110000 +#endif + +#endif // CRASHPAD_COMPAT_MAC_AVAILABILITYVERSIONS_H_
diff --git a/third_party/crashpad/crashpad/handler/BUILD.gn b/third_party/crashpad/crashpad/handler/BUILD.gn index 54af697..dc481784 100644 --- a/third_party/crashpad/crashpad/handler/BUILD.gn +++ b/third_party/crashpad/crashpad/handler/BUILD.gn
@@ -185,9 +185,9 @@ if (crashpad_is_in_chromium) { no_default_deps = true + remove_configs = + [ "//build/config/android:default_orderfile_instrumentation" ] } - remove_configs = - [ "//build/config/android:default_orderfile_instrumentation" ] } }
diff --git a/third_party/crashpad/crashpad/handler/handler_main.cc b/third_party/crashpad/crashpad/handler/handler_main.cc index c8001f45..f3730e8 100644 --- a/third_party/crashpad/crashpad/handler/handler_main.cc +++ b/third_party/crashpad/crashpad/handler/handler_main.cc
@@ -60,7 +60,7 @@ #include "handler/linux/cros_crash_report_exception_handler.h" #endif -#if defined(OS_LINUX) || defined(OS_ANDROID) +#if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID) #include <unistd.h> #include "handler/linux/crash_report_exception_handler.h" @@ -86,9 +86,6 @@ #include "util/win/handle.h" #include "util/win/initial_client_data.h" #include "util/win/session_end_watcher.h" -#elif defined(OS_LINUX) -#include "handler/linux/crash_report_exception_handler.h" -#include "handler/linux/exception_handler_server.h" #endif // OS_APPLE namespace crashpad { @@ -125,9 +122,9 @@ " Address_debug_critical_section\n" " use precreated data to register initial client\n" #endif // OS_WIN -#if defined(OS_ANDROID) || defined(OS_LINUX) +#if defined(OS_ANDROID) || defined(OS_LINUX) || defined(OS_CHROMEOS) " --initial-client-fd=FD a socket connected to a client.\n" -#endif // OS_ANDROID || OS_LINUX +#endif // OS_ANDROID || OS_LINUX || OS_CHROMEOS #if defined(OS_APPLE) " --mach-service=SERVICE register SERVICE with the bootstrap server\n" #endif // OS_APPLE @@ -154,7 +151,7 @@ " --reset-own-crash-exception-port-to-system-default\n" " reset the server's exception handler to default\n" #endif // OS_APPLE -#if defined(OS_LINUX) || defined(OS_ANDROID) +#if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID) " --sanitization-information=SANITIZATION_INFORMATION_ADDRESS\n" " the address of a SanitizationInformation struct.\n" " --shared-client-connection the file descriptor provided by\n" @@ -162,7 +159,7 @@ " clients\n" " --trace-parent-with-exception=EXCEPTION_INFORMATION_ADDRESS\n" " request a dump for the handler's parent process\n" -#endif // OS_LINUX || OS_ANDROID +#endif // OS_LINUX || OS_CHROMEOS || OS_ANDROID " --url=URL send crash reports to this Breakpad server URL,\n" " only if uploads are enabled for the database\n" #if defined(OS_CHROMEOS) @@ -197,7 +194,7 @@ std::string mach_service; int handshake_fd; bool reset_own_crash_exception_port_to_system_default; -#elif defined(OS_LINUX) || defined(OS_ANDROID) +#elif defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID) VMAddress exception_information_address; VMAddress sanitization_information_address; int initial_client_fd; @@ -280,7 +277,8 @@ DISALLOW_COPY_AND_ASSIGN(CallMetricsRecordNormalExit); }; -#if defined(OS_APPLE) || defined(OS_LINUX) || defined(OS_ANDROID) +#if defined(OS_APPLE) || defined(OS_LINUX) || defined(OS_CHROMEOS) || \ + defined(OS_ANDROID) void HandleCrashSignal(int sig, siginfo_t* siginfo, void* context) { MetricsRecordExit(Metrics::LifetimeMilestone::kCrashed); @@ -539,9 +537,9 @@ #if defined(OS_WIN) kOptionInitialClientData, #endif // OS_WIN -#if defined(OS_ANDROID) || defined(OS_LINUX) +#if defined(OS_ANDROID) || defined(OS_LINUX) || defined(OS_CHROMEOS) kOptionInitialClientFD, -#endif // OS_ANDROID || OS_LINUX +#endif // OS_ANDROID || OS_LINUX || OS_CHROMEOS #if defined(OS_APPLE) kOptionMachService, #endif // OS_APPLE @@ -562,7 +560,7 @@ #if defined(OS_APPLE) kOptionResetOwnCrashExceptionPortToSystemDefault, #endif // OS_APPLE -#if defined(OS_LINUX) || defined(OS_ANDROID) +#if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID) kOptionSanitizationInformation, kOptionSharedClientConnection, kOptionTraceParentWithException, @@ -597,9 +595,9 @@ nullptr, kOptionInitialClientData}, #endif // OS_APPLE -#if defined(OS_ANDROID) || defined(OS_LINUX) +#if defined(OS_ANDROID) || defined(OS_LINUX) || defined(OS_CHROMEOS) {"initial-client-fd", required_argument, nullptr, kOptionInitialClientFD}, -#endif // OS_ANDROID || OS_LINUX +#endif // OS_ANDROID || OS_LINUX || OS_CHROMEOS #if defined(OS_APPLE) {"mach-service", required_argument, nullptr, kOptionMachService}, #endif // OS_APPLE @@ -635,7 +633,7 @@ nullptr, kOptionResetOwnCrashExceptionPortToSystemDefault}, #endif // OS_APPLE -#if defined(OS_LINUX) || defined(OS_ANDROID) +#if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID) {"sanitization-information", required_argument, nullptr, @@ -648,7 +646,7 @@ required_argument, nullptr, kOptionTraceParentWithException}, -#endif // OS_LINUX || OS_ANDROID +#endif // OS_LINUX || OS_CHROMEOS || OS_ANDROID {"url", required_argument, nullptr, kOptionURL}, #if defined(OS_CHROMEOS) {"use-cros-crash-reporter", @@ -677,7 +675,7 @@ options.handshake_fd = -1; #endif options.identify_client_via_url = true; -#if defined(OS_LINUX) || defined(OS_ANDROID) +#if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID) options.initial_client_fd = kInvalidFileHandle; #endif options.periodic_tasks = true; @@ -733,7 +731,7 @@ break; } #endif // OS_WIN -#if defined(OS_ANDROID) || defined(OS_LINUX) +#if defined(OS_ANDROID) || defined(OS_LINUX) || defined(OS_CHROMEOS) case kOptionInitialClientFD: { if (!base::StringToInt(optarg, &options.initial_client_fd)) { ToolSupport::UsageHint(me, "failed to parse --initial-client-fd"); @@ -741,7 +739,7 @@ } break; } -#endif // OS_ANDROID || OS_LINUX +#endif // OS_ANDROID || OS_LINUX || OS_CHROMEOS case kOptionMetrics: { options.metrics_dir = base::FilePath( ToolSupport::CommandLineArgumentToFilePathStringType(optarg)); @@ -797,7 +795,7 @@ break; } #endif // OS_APPLE -#if defined(OS_LINUX) || defined(OS_ANDROID) +#if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID) case kOptionSanitizationInformation: { if (!StringToNumber(optarg, &options.sanitization_information_address)) { @@ -819,7 +817,7 @@ } break; } -#endif // OS_LINUX || OS_ANDROID +#endif // OS_LINUX || OS_CHROMEOS || OS_ANDROID case kOptionURL: { options.url = optarg; break; @@ -885,7 +883,7 @@ me, "--initial-client-data and --pipe-name are incompatible"); return ExitFailure(); } -#elif defined(OS_LINUX) || defined(OS_ANDROID) +#elif defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID) if (!options.exception_information_address && options.initial_client_fd == kInvalidFileHandle) { ToolSupport::UsageHint( @@ -978,7 +976,7 @@ upload_thread.Get()->Start(); } -#if defined(OS_LINUX) || defined(OS_ANDROID) +#if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID) std::unique_ptr<ExceptionHandlerServer::Delegate> exception_handler; #else std::unique_ptr<CrashReportExceptionHandler> exception_handler; @@ -1029,7 +1027,7 @@ user_stream_sources); #endif // OS_CHROMEOS -#if defined(OS_LINUX) || defined(OS_ANDROID) +#if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID) if (options.exception_information_address) { ExceptionHandlerProtocol::ClientInformation info; info.exception_information_address = options.exception_information_address; @@ -1039,7 +1037,7 @@ ? EXIT_SUCCESS : ExitFailure(); } -#endif // OS_LINUX || OS_ANDROID +#endif // OS_LINUX || OS_CHROMEOS || OS_ANDROID ScopedStoppable prune_thread; if (options.periodic_tasks) { @@ -1101,7 +1099,7 @@ if (!options.pipe_name.empty()) { exception_handler_server.SetPipeName(base::UTF8ToUTF16(options.pipe_name)); } -#elif defined(OS_LINUX) || defined(OS_ANDROID) +#elif defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID) ExceptionHandlerServer exception_handler_server; #endif // OS_APPLE @@ -1123,7 +1121,7 @@ exception_handler_server.InitializeWithInheritedDataForInitialClient( options.initial_client_data, exception_handler.get()); } -#elif defined(OS_LINUX) || defined(OS_ANDROID) +#elif defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID) if (options.initial_client_fd == kInvalidFileHandle || !exception_handler_server.InitializeWithClient( ScopedFileHandle(options.initial_client_fd),
diff --git a/third_party/crashpad/crashpad/minidump/minidump_misc_info_writer.cc b/third_party/crashpad/crashpad/minidump/minidump_misc_info_writer.cc index d2d85115..e17962cd 100644 --- a/third_party/crashpad/crashpad/minidump/minidump_misc_info_writer.cc +++ b/third_party/crashpad/crashpad/minidump/minidump_misc_info_writer.cc
@@ -16,6 +16,7 @@ #include <limits> +#include "base/check_op.h" #include "base/logging.h" #include "base/numerics/safe_conversions.h" #include "base/stl_util.h" @@ -30,8 +31,8 @@ #include "util/numeric/in_range_cast.h" #include "util/numeric/safe_assignment.h" -#if defined(OS_APPLE) -#include <AvailabilityMacros.h> +#if defined(OS_MAC) +#include <Availability.h> #elif defined(OS_ANDROID) #include <android/api-level.h> #endif @@ -66,28 +67,34 @@ return machine_description; } -#if defined(OS_APPLE) -// Converts the value of the MAC_OS_VERSION_MIN_REQUIRED or -// MAC_OS_X_VERSION_MAX_ALLOWED macro from <AvailabilityMacros.h> to a number -// identifying the minor macOS version that it represents. For example, with an -// argument of MAC_OS_X_VERSION_10_6, this function will return 6. -int AvailabilityVersionToMacOSXMinorVersion(int availability) { - // Through MAC_OS_X_VERSION_10_9, the minor version is the tens digit. - if (availability >= 1000 && availability <= 1099) { - return (availability / 10) % 10; - } +#if defined(OS_MAC) +// Converts the value of the __MAC_OS_X_VERSION_MIN_REQUIRED or +// __MAC_OS_X_VERSION_MAX_ALLOWED macro from <Availability.h> to a number +// identifying the macOS version that it represents, in the same format used by +// MacOSVersionNumber(). For example, with an argument of __MAC_10_15, this +// function will return 10'15'00, which is incidentally the same as __MAC_10_15. +// With an argument of __MAC_10_9, this function will return 10'09'00, different +// from __MAC_10_9, which is 10'9'0. +int AvailabilityVersionToMacOSVersionNumber(int availability) { +#if __MAC_OS_X_VERSION_MIN_REQUIRED < __MAC_10_10 + DCHECK_GE(availability, 10'0'0); - // After MAC_OS_X_VERSION_10_9, the older format was insufficient to represent - // versions. Since then, the minor version is the thousands and hundreds - // digits. - if (availability >= 100000 && availability <= 109999) { - return (availability / 100) % 100; + // Until __MAC_10_10, the format is major * 1'0'0 + minor * 1'0 + bugfix. + if (availability >= 10'0'0 && availability <= 10'9'9) { + int minor = (availability / 1'0) % 1'0; + int bugfix = availability % 1'0; + return 10'00'00 + minor * 1'00 + bugfix; } - - return 0; -} #endif + // Since __MAC_10_10, the format is major * 1'00'00 + minor * 1'00 + bugfix. + DCHECK_GE(availability, 10'10'00); + DCHECK_LE(availability, 99'99'99); + + return availability; +} +#endif // OS_MAC + } // namespace namespace internal { @@ -100,11 +107,13 @@ // Caution: the minidump file format only has room for 39 UTF-16 code units // plus a UTF-16 NUL terminator. Don’t let strings get longer than this, or // they will be truncated and a message will be logged. -#if defined(OS_APPLE) +#if defined(OS_MAC) static constexpr char kOS[] = "mac"; +#elif defined(OS_IOS) + static constexpr char kOS[] = "ios"; #elif defined(OS_ANDROID) static constexpr char kOS[] = "android"; -#elif defined(OS_LINUX) +#elif defined(OS_LINUX) || defined(OS_CHROMEOS) static constexpr char kOS[] = "linux"; #elif defined(OS_WIN) static constexpr char kOS[] = "win"; @@ -136,11 +145,11 @@ PACKAGE_VERSION, kOS); -#if defined(OS_APPLE) +#if defined(OS_MAC) debug_build_string += base::StringPrintf( ",%d,%d", - AvailabilityVersionToMacOSXMinorVersion(MAC_OS_X_VERSION_MIN_REQUIRED), - AvailabilityVersionToMacOSXMinorVersion(MAC_OS_X_VERSION_MAX_ALLOWED)); + AvailabilityVersionToMacOSVersionNumber(__MAC_OS_X_VERSION_MIN_REQUIRED), + AvailabilityVersionToMacOSVersionNumber(__MAC_OS_X_VERSION_MAX_ALLOWED)); #elif defined(OS_ANDROID) debug_build_string += base::StringPrintf(",%d", __ANDROID_API__); #endif
diff --git a/third_party/crashpad/crashpad/snapshot/BUILD.gn b/third_party/crashpad/crashpad/snapshot/BUILD.gn index 8615c99..0b452ca 100644 --- a/third_party/crashpad/crashpad/snapshot/BUILD.gn +++ b/third_party/crashpad/crashpad/snapshot/BUILD.gn
@@ -232,7 +232,8 @@ ] } - if (current_cpu == "x86" || current_cpu == "x64") { + if (current_cpu == "x86" || current_cpu == "x64" || + (crashpad_is_mac && current_cpu == "mac_universal")) { sources += [ "x86/cpuid_reader.cc", "x86/cpuid_reader.h", @@ -261,6 +262,10 @@ } configs += [ "..:disable_ubsan" ] + + if (crashpad_is_in_fuchsia) { + configs += [ "//build/config:Wno-conversion" ] + } } # :context is the only part of snapshot that minidump may depend on. @@ -281,6 +286,10 @@ if (crashpad_is_win) { cflags = [ "/wd4201" ] # nonstandard extension used : nameless struct/union } + + if (crashpad_is_in_fuchsia) { + configs += [ "//build/config:Wno-conversion" ] + } } if (crashpad_is_linux) {
diff --git a/third_party/crashpad/crashpad/snapshot/crashpad_types/crashpad_info_reader.cc b/third_party/crashpad/crashpad/snapshot/crashpad_types/crashpad_info_reader.cc index 9d0c781..cedab59a 100644 --- a/third_party/crashpad/crashpad/snapshot/crashpad_types/crashpad_info_reader.cc +++ b/third_party/crashpad/crashpad/snapshot/crashpad_types/crashpad_info_reader.cc
@@ -22,7 +22,7 @@ #if defined(OS_WIN) #include "util/win/traits.h" -#elif defined(OS_LINUX) || defined(OS_ANDROID) +#elif defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID) #include "util/linux/traits.h" #elif defined(OS_FUCHSIA) #include "util/fuchsia/traits.h"
diff --git a/third_party/crashpad/crashpad/snapshot/elf/elf_image_reader_test.cc b/third_party/crashpad/crashpad/snapshot/elf/elf_image_reader_test.cc index 34235a7d..63da92a 100644 --- a/third_party/crashpad/crashpad/snapshot/elf/elf_image_reader_test.cc +++ b/third_party/crashpad/crashpad/snapshot/elf/elf_image_reader_test.cc
@@ -35,7 +35,7 @@ #include "base/fuchsia/fuchsia_logging.h" -#elif defined(OS_LINUX) || defined(OS_ANDROID) +#elif defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID) #include "test/linux/fake_ptrace_connection.h" #include "util/linux/auxiliary_vector.h" @@ -84,7 +84,7 @@ *elf_address = base; } -#elif defined(OS_LINUX) || defined(OS_ANDROID) +#elif defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID) void LocateExecutable(PtraceConnection* connection, ProcessMemory* memory, @@ -133,7 +133,7 @@ ASSERT_TRUE(range.Initialize(&memory, am_64_bit)); VMAddress elf_address; -#if defined(OS_LINUX) || defined(OS_ANDROID) +#if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID) FakePtraceConnection connection; ASSERT_TRUE(connection.Initialize(process)); LocateExecutable(&connection, &memory, &elf_address);
diff --git a/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_annotations_reader_test.cc b/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_annotations_reader_test.cc index 8659a14..aea885a 100644 --- a/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_annotations_reader_test.cc +++ b/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_annotations_reader_test.cc
@@ -112,9 +112,7 @@ break; case kCrashModuleInitialization: - // This crash is triggered by __builtin_trap(), which shows up as - // SIGILL. - SetExpectedChildTermination(kTerminationSignal, SIGILL); + SetExpectedChildTerminationBuiltinTrap(); break; case kCrashDyld: @@ -124,7 +122,8 @@ // _dyld_fatal_error. This changed in 10.12 to use // abort_with_payload(), which appears as SIGABRT to a waiting parent. SetExpectedChildTermination( - kTerminationSignal, MacOSXMinorVersion() < 12 ? SIGTRAP : SIGABRT); + kTerminationSignal, + MacOSVersionNumber() < 10'12'00 ? SIGTRAP : SIGABRT); break; } } @@ -186,8 +185,8 @@ // Mac OS X 10.6 doesn’t have support for CrashReporter annotations // (CrashReporterClient.h), so don’t look for any special annotations in // that version. - int mac_os_x_minor_version = MacOSXMinorVersion(); - if (mac_os_x_minor_version > 7) { + const int macos_version_number = MacOSVersionNumber(); + if (macos_version_number > 10'07'00) { EXPECT_GE(all_annotations_vector.size(), 1u); std::string expected_annotation; @@ -204,7 +203,7 @@ // exec() occurred. See 10.9.5 Libc-997.90.3/sys/_libc_fork_child.c // _libc_fork_child(). expected_annotation = - mac_os_x_minor_version <= 8 + macos_version_number <= 10'08'00 ? "abort() called" : "crashed on child side of fork pre-exec"; break;
diff --git a/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_reader_test.cc b/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_reader_test.cc index 53826bf..f1f3b1de 100644 --- a/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_reader_test.cc +++ b/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_reader_test.cc
@@ -14,7 +14,7 @@ #include "snapshot/mac/mach_o_image_reader.h" -#include <AvailabilityMacros.h> +#include <Availability.h> #include <dlfcn.h> #include <mach-o/dyld.h> #include <mach-o/dyld_images.h> @@ -606,7 +606,7 @@ ASSERT_NO_FATAL_FAILURE(ExpectSymbolTable(mach_header, &image_reader)); } -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7 +#if __MAC_OS_X_VERSION_MAX_ALLOWED >= __MAC_10_7 // If dyld is new enough to record UUIDs, check the UUID of any module that // it says has one. Note that dyld doesn’t record UUIDs of anything that // loaded out of the shared cache, but it should at least have a UUID for the
diff --git a/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_segment_reader.cc b/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_segment_reader.cc index 478b37d..1d7d429f4 100644 --- a/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_segment_reader.cc +++ b/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_segment_reader.cc
@@ -14,6 +14,7 @@ #include "snapshot/mac/mach_o_image_segment_reader.h" +#include <Availability.h> #include <mach-o/loader.h> #include <string.h> @@ -21,6 +22,7 @@ #include "base/logging.h" #include "base/strings/stringprintf.h" +#include "build/build_config.h" #include "snapshot/mac/process_reader_mac.h" #include "util/mac/checked_mach_address_range.h" #include "util/mac/mac_util.h" @@ -39,12 +41,14 @@ bool IsMalformedCLKernelsModule(uint32_t mach_o_file_type, const std::string& module_name, bool* has_timestamp) { +#if defined(ARCH_CPU_X86_FAMILY) if (mach_o_file_type != MH_BUNDLE) { return false; } if (module_name == "cl_kernels") { - if (MacOSXMinorVersion() >= 10) { + if (__MAC_OS_X_VERSION_MIN_REQUIRED >= __MAC_10_10 || + MacOSVersionNumber() >= 10'10'00) { if (has_timestamp) { *has_timestamp = false; } @@ -57,12 +61,14 @@ "/private/var/db/CVMS/cvmsCodeSignObj"; if (module_name.compare( 0, strlen(kCvmsObjectPathPrefix), kCvmsObjectPathPrefix) == 0 && - MacOSXMinorVersion() >= 14) { + (__MAC_OS_X_VERSION_MIN_REQUIRED >= __MAC_10_14 || + MacOSVersionNumber() >= 10'14'00)) { if (has_timestamp) { *has_timestamp = true; } return true; } +#endif // ARCH_CPU_X86_FAMILY return false; }
diff --git a/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_segment_reader.h b/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_segment_reader.h index 1e72785..708cc37d5 100644 --- a/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_segment_reader.h +++ b/third_party/crashpad/crashpad/snapshot/mac/mach_o_image_segment_reader.h
@@ -46,6 +46,9 @@ //! information stored in `MH_OBJECT` images, although `cl_kernels` images claim //! to be `MH_BUNDLE`. //! +//! These `cl_kernels` modules have only been observed on x86, not on arm64. +//! This function always returns `false` on arm64. +//! //! This function is exposed for testing purposes only. //! //! \param[in] mach_o_file_type The Mach-O type of the module being examined.
diff --git a/third_party/crashpad/crashpad/snapshot/mac/process_reader_mac.cc b/third_party/crashpad/crashpad/snapshot/mac/process_reader_mac.cc index ca2c1f7..821fe3c 100644 --- a/third_party/crashpad/crashpad/snapshot/mac/process_reader_mac.cc +++ b/third_party/crashpad/crashpad/snapshot/mac/process_reader_mac.cc
@@ -14,7 +14,7 @@ #include "snapshot/mac/process_reader_mac.h" -#include <AvailabilityMacros.h> +#include <Availability.h> #include <mach-o/loader.h> #include <mach/mach_vm.h> @@ -95,9 +95,12 @@ process_memory_(), task_(TASK_NULL), initialized_(), +#if defined(CRASHPAD_MAC_32_BIT_SUPPORT) is_64_bit_(false), +#endif // CRASHPAD_MAC_32_BIT_SUPPORT initialized_threads_(false), - initialized_modules_(false) {} + initialized_modules_(false) { +} ProcessReaderMac::~ProcessReaderMac() { for (const Thread& thread : threads_) { @@ -117,7 +120,12 @@ return false; } +#if defined(CRASHPAD_MAC_32_BIT_SUPPORT) is_64_bit_ = process_info_.Is64Bit(); +#else // CRASHPAD_MAC_32_BIT_SUPPORT + DCHECK(process_info_.Is64Bit()); +#endif // CRASHPAD_MAC_32_BIT_SUPPORT + task_ = task; INITIALIZATION_STATE_SET_VALID(initialized_); @@ -213,7 +221,7 @@ // This may look for the module that matches the executable path in the same // data set that vmmap uses. -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7 +#if __MAC_OS_X_VERSION_MAX_ALLOWED >= __MAC_10_7 // The task_dyld_info_data_t struct grew in 10.7, adding the format field. // Don’t check this field if it’s not present, which can happen when either // the SDK used at compile time or the kernel at run time are too old and
diff --git a/third_party/crashpad/crashpad/snapshot/mac/process_reader_mac.h b/third_party/crashpad/crashpad/snapshot/mac/process_reader_mac.h index ac57a061..2f8ea9dc 100644 --- a/third_party/crashpad/crashpad/snapshot/mac/process_reader_mac.h +++ b/third_party/crashpad/crashpad/snapshot/mac/process_reader_mac.h
@@ -15,6 +15,7 @@ #ifndef CRASHPAD_SNAPSHOT_MAC_PROCESS_READER_MAC_H_ #define CRASHPAD_SNAPSHOT_MAC_PROCESS_READER_MAC_H_ +#include <Availability.h> #include <mach/mach.h> #include <stdint.h> #include <sys/time.h> @@ -31,6 +32,14 @@ #include "util/posix/process_info.h" #include "util/process/process_memory_mac.h" +#if defined(ARCH_CPU_32_BIT) || \ + (!defined(ARCH_CPU_ARM64) && \ + __MAC_OS_X_VERSION_MIN_REQUIRED < __MAC_10_15) +// There’s no 32-bit x86 environment on macOS 10.15 or later, and there’s no +// 32-bit ARM environment for macOS at all. +#define CRASHPAD_MAC_32_BIT_SUPPORT 1 +#endif // ARCH_CPU_32_BIT || (!ARCH_CPU_ARM64 && DT < 10.15) + namespace crashpad { class MachOImageReader; @@ -116,7 +125,11 @@ bool Initialize(task_t task); //! \return `true` if the target task is a 64-bit process. +#if defined(CRASHPAD_MAC_32_BIT_SUPPORT) || DOXYGEN bool Is64Bit() const { return is_64_bit_; } +#else // CRASHPAD_MAC_32_BIT_SUPPORT + bool Is64Bit() const { return true; } +#endif // CRASHPAD_MAC_32_BIT_SUPPORT //! \return The target task’s process ID. pid_t ProcessID() const { return process_info_.ProcessID(); } @@ -240,10 +253,12 @@ task_t task_; // weak InitializationStateDcheck initialized_; +#if defined(CRASHPAD_MAC_32_BIT_SUPPORT) // This shadows a method of process_info_, but it’s accessed so frequently // that it’s given a first-class field to save a call and a few bit operations // on each access. bool is_64_bit_; +#endif // CRASHPAD_MAC_32_BIT_SUPPORT bool initialized_threads_; bool initialized_modules_;
diff --git a/third_party/crashpad/crashpad/snapshot/mac/process_reader_mac_test.cc b/third_party/crashpad/crashpad/snapshot/mac/process_reader_mac_test.cc index 2d64ff1..a85eeb2 100644 --- a/third_party/crashpad/crashpad/snapshot/mac/process_reader_mac_test.cc +++ b/third_party/crashpad/crashpad/snapshot/mac/process_reader_mac_test.cc
@@ -14,19 +14,22 @@ #include "snapshot/mac/process_reader_mac.h" -#include <AvailabilityMacros.h> -#include <errno.h> +#include <Availability.h> #include <OpenCL/opencl.h> +#include <dlfcn.h> +#include <errno.h> #include <mach-o/dyld.h> #include <mach-o/dyld_images.h> #include <mach/mach.h> #include <string.h> #include <sys/stat.h> +#include <sys/types.h> #include <map> #include <utility> #include "base/check_op.h" +#include "base/logging.h" #include "base/mac/mach_logging.h" #include "base/posix/eintr_wrapper.h" #include "base/stl_util.h" @@ -530,6 +533,75 @@ process_reader_threaded_child.Run(); } +template <typename T> +T GetDyldFunction(const char* symbol) { + static void* dl_handle = []() -> void* { + Dl_info dl_info; + if (!dladdr(reinterpret_cast<void*>(dlopen), &dl_info)) { + LOG(ERROR) << "dladdr: failed"; + return nullptr; + } + + void* dl_handle = + dlopen(dl_info.dli_fname, RTLD_LAZY | RTLD_LOCAL | RTLD_NOLOAD); + DCHECK(dl_handle) << "dlopen: " << dlerror(); + + return dl_handle; + }(); + + if (!dl_handle) { + return nullptr; + } + + return reinterpret_cast<T>(dlsym(dl_handle, symbol)); +} + +void VerifyImageExistenceAndTimestamp(const char* path, time_t timestamp) { + const char* stat_path; + bool timestamp_may_be_0; + +#if __MAC_OS_X_VERSION_MAX_ALLOWED < __MAC_10_16 + static auto _dyld_shared_cache_contains_path = + GetDyldFunction<bool (*)(const char*)>( + "_dyld_shared_cache_contains_path"); +#endif + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunguarded-availability" + if (_dyld_shared_cache_contains_path && + _dyld_shared_cache_contains_path(path)) { +#pragma clang diagnostic pop + // The timestamp will either match the timestamp of the dyld_shared_cache + // file in use, or be 0. + static const char* dyld_shared_cache_file_path = []() -> const char* { + auto dyld_shared_cache_file_path_f = + GetDyldFunction<const char* (*)()>("dyld_shared_cache_file_path"); + + // dyld_shared_cache_file_path should always be present if + // _dyld_shared_cache_contains_path is. + DCHECK(dyld_shared_cache_file_path_f); + + const char* dyld_shared_cache_file_path = dyld_shared_cache_file_path_f(); + DCHECK(dyld_shared_cache_file_path); + + return dyld_shared_cache_file_path; + }(); + + stat_path = dyld_shared_cache_file_path; + timestamp_may_be_0 = true; + } else { + stat_path = path; + timestamp_may_be_0 = false; + } + + struct stat stat_buf; + int rv = stat(stat_path, &stat_buf); + EXPECT_EQ(rv, 0) << ErrnoMessage("stat"); + if (rv == 0 && (!timestamp_may_be_0 || timestamp != 0)) { + EXPECT_EQ(timestamp, stat_buf.st_mtime); + } +} + // cl_kernels images (OpenCL kernels) are weird. They’re not ld output and don’t // exist as files on disk. On OS X 10.10 and 10.11, their Mach-O structure isn’t // perfect. They show up loaded into many executables, so these quirks should be @@ -545,7 +617,10 @@ class ScopedOpenCLNoOpKernel { public: ScopedOpenCLNoOpKernel() - : context_(nullptr), program_(nullptr), kernel_(nullptr) {} + : context_(nullptr), + program_(nullptr), + kernel_(nullptr), + success_(false) {} ~ScopedOpenCLNoOpKernel() { if (kernel_) { @@ -569,12 +644,12 @@ cl_int rv = clGetPlatformIDs(1, &platform_id, nullptr); ASSERT_EQ(rv, CL_SUCCESS) << "clGetPlatformIDs"; -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_10 && \ - MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_10 -// cl_device_id is really available in OpenCL.framework back to 10.5, but in -// the 10.10 SDK and later, OpenCL.framework includes <OpenGL/CGLDevice.h>, -// which has its own cl_device_id that was introduced in 10.10. That -// triggers erroneous availability warnings. +#if __MAC_OS_X_VERSION_MAX_ALLOWED >= __MAC_10_10 && \ + __MAC_OS_X_VERSION_MIN_REQUIRED < __MAC_10_10 + // cl_device_id is really available in OpenCL.framework back to 10.5, but in + // the 10.10 SDK and later, OpenCL.framework includes <OpenGL/CGLDevice.h>, + // which has its own cl_device_id that was introduced in 10.10. That + // triggers erroneous availability warnings. #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wunguarded-availability" #define DISABLED_WUNGUARDED_AVAILABILITY @@ -589,6 +664,14 @@ #endif // DISABLED_WUNGUARDED_AVAILABILITY rv = clGetDeviceIDs(platform_id, CL_DEVICE_TYPE_CPU, 1, &device_id, nullptr); +#if defined(ARCH_CPU_ARM64) + // CL_DEVICE_TYPE_CPU doesn’t seem to work at all on arm64, meaning that + // these weird OpenCL modules probably don’t show up there at all. Keep this + // test even on arm64 in case this ever does start working. + if (rv == CL_INVALID_VALUE) { + return; + } +#endif // ARCH_CPU_ARM64 ASSERT_EQ(rv, CL_SUCCESS) << "clGetDeviceIDs"; context_ = clCreateContext(nullptr, 1, &device_id, nullptr, nullptr, &rv); @@ -626,12 +709,17 @@ kernel_ = clCreateKernel(program_, "NoOp", &rv); ASSERT_EQ(rv, CL_SUCCESS) << "clCreateKernel"; + + success_ = true; } + bool success() const { return success_; } + private: cl_context context_; cl_program program_; cl_kernel kernel_; + bool success_; DISALLOW_COPY_AND_ASSIGN(ScopedOpenCLNoOpKernel); }; @@ -640,11 +728,8 @@ // OpenCL kernels that run on the CPU do not result in cl_kernels images // appearing on that OS version. bool ExpectCLKernels() { -#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_7 - return true; -#else - return MacOSXMinorVersion() >= 7; -#endif + return __MAC_OS_X_VERSION_MIN_REQUIRED >= __MAC_10_7 || + MacOSVersionNumber() >= 10'07'00; } TEST(ProcessReaderMac, SelfModules) { @@ -695,16 +780,12 @@ found_cl_kernels = true; } else { // Hope that the module didn’t change on disk. - struct stat stat_buf; - int rv = stat(dyld_image_name, &stat_buf); - EXPECT_EQ(rv, 0) << ErrnoMessage("stat"); - if (rv == 0) { - EXPECT_EQ(modules[index].timestamp, stat_buf.st_mtime); - } + VerifyImageExistenceAndTimestamp(dyld_image_name, + modules[index].timestamp); } } - EXPECT_EQ(found_cl_kernels, ExpectCLKernels()); + EXPECT_EQ(found_cl_kernels, ExpectCLKernels() && ensure_cl_kernels.success()); size_t index = modules.size() - 1; EXPECT_EQ(modules[index].name, kDyldPath); @@ -724,7 +805,9 @@ class ProcessReaderModulesChild final : public MachMultiprocess { public: - ProcessReaderModulesChild() : MachMultiprocess() {} + explicit ProcessReaderModulesChild(bool ensure_cl_kernels_success) + : MachMultiprocess(), + ensure_cl_kernels_success_(ensure_cl_kernels_success) {} ~ProcessReaderModulesChild() {} @@ -785,16 +868,13 @@ found_cl_kernels = true; } else { // Hope that the module didn’t change on disk. - struct stat stat_buf; - int rv = stat(expect_name.c_str(), &stat_buf); - EXPECT_EQ(rv, 0) << ErrnoMessage("stat"); - if (rv == 0) { - EXPECT_EQ(modules[index].timestamp, stat_buf.st_mtime); - } + VerifyImageExistenceAndTimestamp(expect_name.c_str(), + modules[index].timestamp); } } - EXPECT_EQ(found_cl_kernels, ExpectCLKernels()); + EXPECT_EQ(found_cl_kernels, + ExpectCLKernels() && ensure_cl_kernels_success_); } void MachMultiprocessChild() override { @@ -844,6 +924,8 @@ CheckedReadFileAtEOF(ReadPipeHandle()); } + bool ensure_cl_kernels_success_; + DISALLOW_COPY_AND_ASSIGN(ProcessReaderModulesChild); }; @@ -851,7 +933,8 @@ ScopedOpenCLNoOpKernel ensure_cl_kernels; ASSERT_NO_FATAL_FAILURE(ensure_cl_kernels.SetUp()); - ProcessReaderModulesChild process_reader_modules_child; + ProcessReaderModulesChild process_reader_modules_child( + ensure_cl_kernels.success()); process_reader_modules_child.Run(); }
diff --git a/third_party/crashpad/crashpad/snapshot/mac/process_types.cc b/third_party/crashpad/crashpad/snapshot/mac/process_types.cc index 0a1b7f9..92bc722 100644 --- a/third_party/crashpad/crashpad/snapshot/mac/process_types.cc +++ b/third_party/crashpad/crashpad/snapshot/mac/process_types.cc
@@ -219,7 +219,7 @@ size_t count, \ struct_name<Traits>* specific) { \ return process_reader->Memory()->Read( \ - address, sizeof(struct_name<Traits>[count]), specific); \ + address, count * sizeof(struct_name<Traits>), specific); \ } \ \ } /* namespace internal */ \
diff --git a/third_party/crashpad/crashpad/snapshot/mac/process_types/custom.cc b/third_party/crashpad/crashpad/snapshot/mac/process_types/custom.cc index a76c3eb..0b8d969e 100644 --- a/third_party/crashpad/crashpad/snapshot/mac/process_types/custom.cc +++ b/third_party/crashpad/crashpad/snapshot/mac/process_types/custom.cc
@@ -22,6 +22,7 @@ #include <limits> #include <type_traits> +#include "base/check_op.h" #include "base/logging.h" #include "base/numerics/safe_math.h" #include "base/stl_util.h" @@ -142,9 +143,10 @@ offsetof(dyld_all_image_infos<Traits>, sharedCacheSlide), // 11 offsetof(dyld_all_image_infos<Traits>, sharedCacheUUID), // 12 offsetof(dyld_all_image_infos<Traits>, infoArrayChangeTimestamp), // 13 - offsetof(dyld_all_image_infos<Traits>, end_14), // 14 + offsetof(dyld_all_image_infos<Traits>, end_v14), // 14 std::numeric_limits<size_t>::max(), // 15, see below - sizeof(dyld_all_image_infos<Traits>), // 16 + offsetof(dyld_all_image_infos<Traits>, end_v16), // 16 + sizeof(dyld_all_image_infos<Traits>), // 17 }; if (version >= base::size(kSizeForVersion)) { @@ -160,13 +162,13 @@ // The revised one in macOS 10.13 grew. It’s safe to assume that the // dyld_all_image_infos structure came from the same system that’s now // interpreting it, so use an OS version check. - int mac_os_x_minor_version = MacOSXMinorVersion(); - if (mac_os_x_minor_version == 12) { - return offsetof(dyld_all_image_infos<Traits>, end_14); + const int macos_version_number = MacOSVersionNumber(); + if (macos_version_number / 1'00 == 10'12) { + return offsetof(dyld_all_image_infos<Traits>, end_v14); } - DCHECK_GE(mac_os_x_minor_version, 13); - DCHECK_LE(mac_os_x_minor_version, 14); + DCHECK_GE(macos_version_number, 10'13'00); + DCHECK_LT(macos_version_number, 10'15'00); return offsetof(dyld_all_image_infos<Traits>, platform); }
diff --git a/third_party/crashpad/crashpad/snapshot/mac/process_types/dyld_images.proctype b/third_party/crashpad/crashpad/snapshot/mac/process_types/dyld_images.proctype index 3b040854..589ad09 100644 --- a/third_party/crashpad/crashpad/snapshot/mac/process_types/dyld_images.proctype +++ b/third_party/crashpad/crashpad/snapshot/mac/process_types/dyld_images.proctype
@@ -121,29 +121,40 @@ // the runtimes that use versions 14 and 15 were built with SDKs that did not // have this extra padding, it’s necessary to treat the element at index 4 on // 32-bit systems as outside of the version 14 and 15 structure. This is why - // |reserved| is only declared a 4-element array, with a special end_14 member - // (not present in the native definition) available to indicate the end of the - // native version 14 structure and the 10.12 version 15 structure, preceding - // the padding in the 32-bit structure that would natively be addressed at - // index 4 of |reserved|. Treat reserved_4_32 as only available in version 16 - // of the structure. + // |reserved| is only declared a 4-element array, with a special end_v14 + // member (not present in the native definition) available to indicate the end + // of the native version 14 structure and the 10.12 version 15 structure, + // preceding the padding in the 32-bit structure that would natively be + // addressed at index 4 of |reserved|. Treat reserved_4_32 as only available + // in version 16 of the structure. PROCESS_TYPE_STRUCT_MEMBER(UIntPtr, reserved, [4]) PROCESS_TYPE_STRUCT_MEMBER(Reserved64_64Only, reserved_4_64) PROCESS_TYPE_STRUCT_MEMBER(Reserved64_64Only, reserved_5) PROCESS_TYPE_STRUCT_MEMBER(Reserved64_64Only, reserved_6) PROCESS_TYPE_STRUCT_MEMBER(Reserved64_64Only, reserved_7) PROCESS_TYPE_STRUCT_MEMBER(Reserved64_64Only, reserved_8) - PROCESS_TYPE_STRUCT_MEMBER(Nothing, end_14) + PROCESS_TYPE_STRUCT_MEMBER(Nothing, end_v14) PROCESS_TYPE_STRUCT_MEMBER(Reserved32_32Only, reserved_4_32) - // Version 15 (macOS 10.13). <mach-o/dyld_images.h> incorrectly claims that - // these were introduced at version 16. These fields are not present in macOS - // 10.12, which also identifies its structure as version 15. + // Version 15 (macOS 10.13) + // <mach-o/dyld_images.h> incorrectly claims that these were introduced at + // version 16. These fields are not present in macOS 10.12, which also + // identifies its structure as version 15. PROCESS_TYPE_STRUCT_MEMBER(UIntPtr, compact_dyld_image_info_addr) PROCESS_TYPE_STRUCT_MEMBER(ULong, compact_dyld_image_info_size) // size_t // Version 16 (macOS 10.15) + // The native structure is followed by 4 bytes of padding, marked by the + // end_v16 member later, not present in the native version of the structure. PROCESS_TYPE_STRUCT_MEMBER(uint32_t, platform) // dyld_platform_t + + // Version 17 (macOS 10.16/11.0) + PROCESS_TYPE_STRUCT_MEMBER(uint32_t, aotInfoCount) + PROCESS_TYPE_STRUCT_MEMBER(Nothing, end_v16) + PROCESS_TYPE_STRUCT_MEMBER(Pointer, aotInfoArray) // dyld_aot_image_info* + PROCESS_TYPE_STRUCT_MEMBER(uint64_t, aotInfoArrayChangeTimestamp) + PROCESS_TYPE_STRUCT_MEMBER(UIntPtr, aotSharedCacheBaseAddress) + PROCESS_TYPE_STRUCT_MEMBER(uint8_t, aotSharedCacheUUID, [16]) PROCESS_TYPE_STRUCT_END(dyld_all_image_infos) #endif // ! PROCESS_TYPE_STRUCT_IMPLEMENT_INTERNAL_READ_INTO &&
diff --git a/third_party/crashpad/crashpad/snapshot/mac/process_types_test.cc b/third_party/crashpad/crashpad/snapshot/mac/process_types_test.cc index 0ad2869..b589821 100644 --- a/third_party/crashpad/crashpad/snapshot/mac/process_types_test.cc +++ b/third_party/crashpad/crashpad/snapshot/mac/process_types_test.cc
@@ -14,7 +14,7 @@ #include "snapshot/mac/process_types.h" -#include <AvailabilityMacros.h> +#include <Availability.h> #include <mach/mach.h> #include <string.h> @@ -48,17 +48,17 @@ TEST(ProcessTypes, DyldImagesSelf) { // Get the in-process view of dyld_all_image_infos, and check it for sanity. const dyld_all_image_infos* self_image_infos = DyldGetAllImageInfos(); - const int mac_os_x_minor_version = MacOSXMinorVersion(); + const int macos_version_number = MacOSVersionNumber(); - if (mac_os_x_minor_version >= 15) { + if (macos_version_number >= 10'15'00) { EXPECT_GE(self_image_infos->version, 16u); - } else if (mac_os_x_minor_version >= 12) { + } else if (macos_version_number >= 10'12'00) { EXPECT_GE(self_image_infos->version, 15u); - } else if (mac_os_x_minor_version >= 9) { + } else if (macos_version_number >= 10'09'00) { EXPECT_GE(self_image_infos->version, 13u); - } else if (mac_os_x_minor_version >= 7) { + } else if (macos_version_number >= 10'07'00) { EXPECT_GE(self_image_infos->version, 8u); - } else if (mac_os_x_minor_version >= 6) { + } else if (macos_version_number >= 10'06'00) { EXPECT_GE(self_image_infos->version, 2u); } else { EXPECT_GE(self_image_infos->version, 1u); @@ -68,7 +68,7 @@ if (self_image_infos->version >= 2) { EXPECT_TRUE(self_image_infos->libSystemInitialized); } -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7 +#if __MAC_OS_X_VERSION_MAX_ALLOWED >= __MAC_10_7 if (self_image_infos->version >= 9) { EXPECT_EQ(self_image_infos->dyldAllImageInfosAddress, self_image_infos); } @@ -90,8 +90,8 @@ // This field is only present in the OS X 10.7 SDK (at build time) and kernel // (at run time). -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7 - if (MacOSXMinorVersion() >= 7) { +#if __MAC_OS_X_VERSION_MAX_ALLOWED >= __MAC_10_7 + if (macos_version_number >= 10'07'00) { #if !defined(ARCH_CPU_64_BITS) EXPECT_EQ(dyld_info.all_image_info_format, TASK_DYLD_ALL_IMAGE_INFO_32); #else @@ -103,15 +103,17 @@ ProcessReaderMac process_reader; ASSERT_TRUE(process_reader.Initialize(mach_task_self())); -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_15 +#if __MAC_OS_X_VERSION_MAX_ALLOWED >= __MAC_10_16 + constexpr uint32_t kDyldAllImageInfosVersionInSDK = 17; +#elif __MAC_OS_X_VERSION_MAX_ALLOWED >= __MAC_10_15 constexpr uint32_t kDyldAllImageInfosVersionInSDK = 16; -#elif MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_12 +#elif __MAC_OS_X_VERSION_MAX_ALLOWED >= __MAC_10_12 constexpr uint32_t kDyldAllImageInfosVersionInSDK = 15; -#elif MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_9 +#elif __MAC_OS_X_VERSION_MAX_ALLOWED >= __MAC_10_9 constexpr uint32_t kDyldAllImageInfosVersionInSDK = 14; -#elif MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7 +#elif __MAC_OS_X_VERSION_MAX_ALLOWED >= __MAC_10_7 constexpr uint32_t kDyldAllImageInfosVersionInSDK = 12; -#elif MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 +#elif __MAC_OS_X_VERSION_MAX_ALLOWED >= __MAC_10_6 constexpr uint32_t kDyldAllImageInfosVersionInSDK = 7; #else constexpr uint32_t kDyldAllImageInfosVersionInSDK = 1; @@ -126,13 +128,13 @@ // test can only be performed if the run-time OS natively uses the same format // structure as the SDK. bool test_expected_size_for_version_matches_sdk_sizeof; -#if MAC_OS_X_VERSION_MAX_ALLOWED == MAC_OS_X_VERSION_10_12 +#if __MAC_OS_X_VERSION_MAX_ALLOWED == __MAC_10_12 test_expected_size_for_version_matches_sdk_sizeof = - mac_os_x_minor_version == 12; -#elif MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_13 && \ - MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_15 + macos_version_number / 1'00 == 10'12; +#elif __MAC_OS_X_VERSION_MAX_ALLOWED >= __MAC_10_13 && \ + __MAC_OS_X_VERSION_MAX_ALLOWED < __MAC_10_15 test_expected_size_for_version_matches_sdk_sizeof = - mac_os_x_minor_version >= 13 && mac_os_x_minor_version <= 14; + macos_version_number >= 10'13'00 && macos_version_number < 10'15'00; #else test_expected_size_for_version_matches_sdk_sizeof = true; #endif @@ -144,8 +146,10 @@ } // Make sure that the computed sizes of various versions of this structure are - // correct at different bitnessses. + // correct at different bitnessses. Version 16 and later are unsupported on + // 32-bit systems due to the OS deprecating 32-bit support in macOS 10.15. constexpr size_t kSpecialCase = std::numeric_limits<size_t>::max(); + constexpr size_t kUnsupported = std::numeric_limits<size_t>::max() - 1; constexpr struct { uint32_t version; size_t size_32; @@ -165,14 +169,15 @@ {13, 104, 184}, {14, 164, 304}, {15, kSpecialCase, kSpecialCase}, - {16, 184, 328}, + {16, kUnsupported, 328}, + {17, kUnsupported, 368}, }; for (size_t index = 0; index < base::size(kVersionsAndSizes); ++index) { uint32_t version = kVersionsAndSizes[index].version; SCOPED_TRACE(base::StringPrintf("index %zu, version %u", index, version)); if (version == 15) { - if (mac_os_x_minor_version == 12) { + if (macos_version_number / 1'00 == 10'12) { EXPECT_EQ(process_types::internal::dyld_all_image_infos< process_types::internal::Traits32>:: ExpectedSizeForVersion(version), @@ -181,7 +186,8 @@ process_types::internal::Traits64>:: ExpectedSizeForVersion(version), 304u); - } else if (mac_os_x_minor_version >= 13 && mac_os_x_minor_version <= 14) { + } else if (macos_version_number >= 10'13'00 && + macos_version_number < 10'15'00) { EXPECT_EQ(process_types::internal::dyld_all_image_infos< process_types::internal::Traits32>:: ExpectedSizeForVersion(version), @@ -198,14 +204,18 @@ ASSERT_NE(kVersionsAndSizes[index].size_32, kSpecialCase); ASSERT_NE(kVersionsAndSizes[index].size_64, kSpecialCase); - EXPECT_EQ( - process_types::internal::dyld_all_image_infos< - process_types::internal::Traits32>::ExpectedSizeForVersion(version), - kVersionsAndSizes[index].size_32); - EXPECT_EQ( - process_types::internal::dyld_all_image_infos< - process_types::internal::Traits64>::ExpectedSizeForVersion(version), - kVersionsAndSizes[index].size_64); + if (kVersionsAndSizes[index].size_32 != kUnsupported) { + EXPECT_EQ(process_types::internal::dyld_all_image_infos< + process_types::internal::Traits32>:: + ExpectedSizeForVersion(version), + kVersionsAndSizes[index].size_32); + } + if (kVersionsAndSizes[index].size_64 != kUnsupported) { + EXPECT_EQ(process_types::internal::dyld_all_image_infos< + process_types::internal::Traits64>:: + ExpectedSizeForVersion(version), + kVersionsAndSizes[index].size_64); + } } process_types::dyld_all_image_infos proctype_image_infos; @@ -257,7 +267,7 @@ EXPECT_EQ(proctype_image_infos.systemOrderFlag, implicit_cast<uint64_t>(self_image_infos->systemOrderFlag)); } -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7 +#if __MAC_OS_X_VERSION_MAX_ALLOWED >= __MAC_10_7 if (proctype_image_infos.version >= 8) { EXPECT_EQ(proctype_image_infos.uuidArrayCount, implicit_cast<uint64_t>(self_image_infos->uuidArrayCount)); @@ -299,7 +309,7 @@ implicit_cast<uint64_t>(self_image_infos->sharedCacheSlide)); } #endif -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_9 +#if __MAC_OS_X_VERSION_MAX_ALLOWED >= __MAC_10_9 if (proctype_image_infos.version >= 13) { EXPECT_EQ(memcmp(self_image_infos->sharedCacheUUID, proctype_image_infos.sharedCacheUUID, @@ -307,7 +317,7 @@ 0); } #endif -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_12 +#if __MAC_OS_X_VERSION_MAX_ALLOWED >= __MAC_10_12 if (proctype_image_infos.version >= 15) { EXPECT_EQ(proctype_image_infos.infoArrayChangeTimestamp, self_image_infos->infoArrayChangeTimestamp); @@ -327,7 +337,7 @@ } #endif -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_12 +#if __MAC_OS_X_VERSION_MAX_ALLOWED >= __MAC_10_12 // As dyld_all_image_infos has evolved over time, new fields were added to the // reserved region. process_types::dyld_all_image_infos declares a recent // version of the structure, but an older SDK may declare an older version @@ -352,8 +362,8 @@ } #endif -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_13 - if (proctype_image_infos.version >= 15 && mac_os_x_minor_version >= 13) { +#if __MAC_OS_X_VERSION_MAX_ALLOWED >= __MAC_10_13 + if (proctype_image_infos.version >= 15 && macos_version_number >= 10'13'00) { EXPECT_EQ(proctype_image_infos.compact_dyld_image_info_addr, self_image_infos->compact_dyld_image_info_addr); EXPECT_EQ(proctype_image_infos.compact_dyld_image_info_size, @@ -361,7 +371,7 @@ } #endif -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_15 +#if __MAC_OS_X_VERSION_MAX_ALLOWED >= __MAC_10_15 if (proctype_image_infos.version >= 16) { EXPECT_EQ(proctype_image_infos.platform, self_image_infos->platform); } @@ -399,7 +409,7 @@ } } -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7 +#if __MAC_OS_X_VERSION_MAX_ALLOWED >= __MAC_10_7 if (proctype_image_infos.version >= 8) { std::vector<process_types::dyld_uuid_info> proctype_uuid_info_vector( proctype_image_infos.uuidArrayCount);
diff --git a/third_party/crashpad/crashpad/snapshot/mac/system_snapshot_mac.cc b/third_party/crashpad/crashpad/snapshot/mac/system_snapshot_mac.cc index 62eb814..7a12e74 100644 --- a/third_party/crashpad/crashpad/snapshot/mac/system_snapshot_mac.cc +++ b/third_party/crashpad/crashpad/snapshot/mac/system_snapshot_mac.cc
@@ -14,7 +14,7 @@ #include "snapshot/mac/system_snapshot_mac.h" -#include <AvailabilityMacros.h> +#include <Availability.h> #include <stddef.h> #include <sys/sysctl.h> #include <sys/types.h> @@ -31,6 +31,7 @@ #include "snapshot/mac/process_reader_mac.h" #include "snapshot/posix/timezone.h" #include "util/mac/mac_util.h" +#include "util/mac/sysctl.h" #include "util/numeric/in_range_cast.h" namespace crashpad { @@ -60,26 +61,6 @@ return InRangeCast<T>(int_value, default_value); } -std::string ReadStringSysctlByName(const char* name) { - size_t buf_len; - if (sysctlbyname(name, nullptr, &buf_len, nullptr, 0) != 0) { - PLOG(WARNING) << "sysctlbyname (size) " << name; - return std::string(); - } - - if (buf_len == 0) { - return std::string(); - } - - std::string value(buf_len - 1, '\0'); - if (sysctlbyname(name, &value[0], &buf_len, nullptr, 0) != 0) { - PLOG(WARNING) << "sysctlbyname " << name; - return std::string(); - } - - return value; -} - #if defined(ARCH_CPU_X86_FAMILY) void CallCPUID(uint32_t leaf, uint32_t* eax, @@ -119,15 +100,15 @@ process_reader_ = process_reader; snapshot_time_ = snapshot_time; - // MacOSXVersion() logs its own warnings if it can’t figure anything out. It’s - // not fatal if this happens. The default values are reasonable. + // MacOSVersionComponents() logs its own warnings if it can’t figure anything + // out. It’s not fatal if this happens. The default values are reasonable. std::string os_version_string; - MacOSXVersion(&os_version_major_, - &os_version_minor_, - &os_version_bugfix_, - &os_version_build_, - &os_server_, - &os_version_string); + MacOSVersionComponents(&os_version_major_, + &os_version_minor_, + &os_version_bugfix_, + &os_version_build_, + &os_server_, + &os_version_string); std::string uname_string; utsname uts; @@ -194,9 +175,9 @@ INITIALIZATION_STATE_DCHECK_VALID(initialized_); #if defined(ARCH_CPU_X86_FAMILY) - return ReadStringSysctlByName("machdep.cpu.vendor"); + return ReadStringSysctlByName("machdep.cpu.vendor", true); #elif defined(ARCH_CPU_ARM64) - return ReadStringSysctlByName("machdep.cpu.brand_string"); + return ReadStringSysctlByName("machdep.cpu.brand_string", true); #else #error port to your architecture #endif @@ -205,8 +186,18 @@ void SystemSnapshotMac::CPUFrequency( uint64_t* current_hz, uint64_t* max_hz) const { INITIALIZATION_STATE_DCHECK_VALID(initialized_); +#if defined(ARCH_CPU_X86_FAMILY) *current_hz = ReadIntSysctlByName<uint64_t>("hw.cpufrequency", 0); *max_hz = ReadIntSysctlByName<uint64_t>("hw.cpufrequency_max", 0); +#elif defined(ARCH_CPU_ARM64) + // TODO(https://crashpad.chromium.org/bug/352): When production arm64 + // hardware is available, determine whether CPU frequency is visible anywhere + // (likely via a sysctl or via IOKit) and use it if feasible. + *current_hz = 0; + *max_hz = 0; +#else +#error port to your architecture +#endif } uint32_t SystemSnapshotMac::CPUX86Signature() const { @@ -364,11 +355,11 @@ // xnu-6153.11.26/bsd/kern/kern_sysctl.c (10.14.4 and 10.14.5 xnu source // are not yet available). In newer production kernels, NX is always // enabled. See 10.15.0 xnu-6153.11.26/osfmk/x86_64/pmap.c nx_enabled. -#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_14 +#if __MAC_OS_X_VERSION_MIN_REQUIRED >= __MAC_10_14 const bool nx_always_enabled = true; #else // DT >= 10.14 base::ScopedClearLastError reset_errno; - const bool nx_always_enabled = MacOSXMinorVersion() >= 14; + const bool nx_always_enabled = MacOSVersionNumber() >= 10'14'00; #endif // DT >= 10.14 if (nx_always_enabled) { return true;
diff --git a/third_party/crashpad/crashpad/snapshot/mac/system_snapshot_mac_test.cc b/third_party/crashpad/crashpad/snapshot/mac/system_snapshot_mac_test.cc index e13c9af..bdbc296 100644 --- a/third_party/crashpad/crashpad/snapshot/mac/system_snapshot_mac_test.cc +++ b/third_party/crashpad/crashpad/snapshot/mac/system_snapshot_mac_test.cc
@@ -117,8 +117,10 @@ std::string build; system_snapshot().OSVersion(&major, &minor, &bugfix, &build); - EXPECT_EQ(major, 10); - EXPECT_EQ(minor, MacOSXMinorVersion()); + const int macos_version_number = MacOSVersionNumber(); + EXPECT_EQ(major * 1'00'00 + minor * 1'00 + + (macos_version_number >= 10'13'04 ? bugfix : 0), + macos_version_number); EXPECT_FALSE(build.empty()); }
diff --git a/third_party/crashpad/crashpad/snapshot/sanitized/process_snapshot_sanitized_test.cc b/third_party/crashpad/crashpad/snapshot/sanitized/process_snapshot_sanitized_test.cc index 0484778..931f5cb 100644 --- a/third_party/crashpad/crashpad/snapshot/sanitized/process_snapshot_sanitized_test.cc +++ b/third_party/crashpad/crashpad/snapshot/sanitized/process_snapshot_sanitized_test.cc
@@ -14,8 +14,11 @@ #include "snapshot/sanitized/process_snapshot_sanitized.h" +#include <string.h> + #include "base/macros.h" #include "base/notreached.h" +#include "base/stl_util.h" #include "build/build_config.h" #include "gtest/gtest.h" #include "test/multiprocess_exec.h" @@ -23,7 +26,7 @@ #include "util/misc/address_sanitizer.h" #include "util/numeric/safe_assignment.h" -#if defined(OS_LINUX) || defined(OS_ANDROID) +#if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID) #include <sys/syscall.h> #include "snapshot/linux/process_snapshot_linux.h" @@ -98,7 +101,7 @@ static StringAnnotation<32> non_allowed_annotation(kNonAllowedAnnotationName); non_allowed_annotation.Set(kNonAllowedAnnotationValue); - char string_data[strlen(kSensitiveStackData) + 1]; + char string_data[base::size(kSensitiveStackData)]; strcpy(string_data, kSensitiveStackData); void (*code_pointer)(void) = ChildTestFunction;
diff --git a/third_party/crashpad/crashpad/snapshot/x86/cpuid_reader.cc b/third_party/crashpad/crashpad/snapshot/x86/cpuid_reader.cc index e600141..5834058 100644 --- a/third_party/crashpad/crashpad/snapshot/x86/cpuid_reader.cc +++ b/third_party/crashpad/crashpad/snapshot/x86/cpuid_reader.cc
@@ -16,7 +16,6 @@ #include <stddef.h> -#include "build/build_config.h" #include "snapshot/cpu_context.h" #if defined(OS_WIN) @@ -24,6 +23,8 @@ #include <intrin.h> #endif // OS_WIN +#if defined(ARCH_CPU_X86_FAMILY) + namespace crashpad { namespace internal { @@ -132,3 +133,5 @@ } // namespace internal } // namespace crashpad + +#endif // ARCH_CPU_X86_FAMILY
diff --git a/third_party/crashpad/crashpad/snapshot/x86/cpuid_reader.h b/third_party/crashpad/crashpad/snapshot/x86/cpuid_reader.h index b6782af..39a1ca8 100644 --- a/third_party/crashpad/crashpad/snapshot/x86/cpuid_reader.h +++ b/third_party/crashpad/crashpad/snapshot/x86/cpuid_reader.h
@@ -19,6 +19,10 @@ #include <string> +#include "build/build_config.h" + +#if defined(ARCH_CPU_X86_FAMILY) + namespace crashpad { namespace internal { @@ -65,4 +69,6 @@ } // namespace internal } // namespace crashpad +#endif // ARCH_CPU_X86_FAMILY + #endif // CRASHPAD_SNAPSHOT_X86_CPUID_READER_H_
diff --git a/third_party/crashpad/crashpad/test/mac/dyld.cc b/third_party/crashpad/crashpad/test/mac/dyld.cc index fb2156e..ba1cb56f 100644 --- a/third_party/crashpad/crashpad/test/mac/dyld.cc +++ b/third_party/crashpad/crashpad/test/mac/dyld.cc
@@ -14,10 +14,10 @@ #include "test/mac/dyld.h" -#include <AvailabilityMacros.h> +#include <Availability.h> #include <dlfcn.h> -#include <mach/mach.h> #include <mach-o/dyld.h> +#include <mach/mach.h> #include <stdint.h> #include "base/logging.h" @@ -25,7 +25,7 @@ #include "test/scoped_module_handle.h" #include "util/numeric/safe_assignment.h" -#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_13 +#if __MAC_OS_X_VERSION_MAX_ALLOWED < __MAC_10_13 extern "C" { // A non-public dyld API, declared in 10.12.4 @@ -41,14 +41,14 @@ namespace test { const dyld_all_image_infos* DyldGetAllImageInfos() { -#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_13 +#if __MAC_OS_X_VERSION_MAX_ALLOWED < __MAC_10_13 // When building with the pre-10.13 SDK, the weak_import declaration above is // available and a symbol will be present in the SDK to link against. If the // old interface is also available at run time (running on pre-10.13), use it. if (_dyld_get_all_image_infos) { return _dyld_get_all_image_infos(); } -#elif MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_13 +#elif __MAC_OS_X_VERSION_MIN_REQUIRED < __MAC_10_13 // When building with the 10.13 SDK or later, but able to run on pre-10.13, // look for _dyld_get_all_image_infos in the same module that provides // _dyld_image_count. There’s no symbol in the SDK to link against, so this is
diff --git a/third_party/crashpad/crashpad/test/mac/mach_multiprocess.cc b/third_party/crashpad/crashpad/test/mac/mach_multiprocess.cc index eaa6a174..01b242a 100644 --- a/third_party/crashpad/crashpad/test/mac/mach_multiprocess.cc +++ b/third_party/crashpad/crashpad/test/mac/mach_multiprocess.cc
@@ -14,7 +14,7 @@ #include "test/mac/mach_multiprocess.h" -#include <AvailabilityMacros.h> +#include <Availability.h> #include <bsm/libbsm.h> #include <memory> @@ -150,7 +150,7 @@ // and other processes will be able to look it up and send messages to it, // these checks disambiguate genuine failures later on in the test from those // that would occur if an errant process sends a message to this service. -#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_8 +#if __MAC_OS_X_VERSION_MIN_REQUIRED < __MAC_10_8 uid_t audit_auid; uid_t audit_euid; gid_t audit_egid;
diff --git a/third_party/crashpad/crashpad/test/multiprocess_exec_posix.cc b/third_party/crashpad/crashpad/test/multiprocess_exec_posix.cc index 59aad829..e14a3b8 100644 --- a/third_party/crashpad/crashpad/test/multiprocess_exec_posix.cc +++ b/third_party/crashpad/crashpad/test/multiprocess_exec_posix.cc
@@ -26,7 +26,7 @@ #include "util/misc/scoped_forbid_return.h" #include "util/posix/close_multiple.h" -#if defined(OS_LINUX) +#if defined(OS_LINUX) || defined(OS_CHROMEOS) #include <stdio_ext.h> #endif @@ -90,7 +90,7 @@ int rv; -#if defined(OS_LINUX) +#if defined(OS_LINUX) || defined(OS_CHROMEOS) __fpurge(stdin); #else rv = fpurge(stdin);
diff --git a/third_party/crashpad/crashpad/test/multiprocess_posix.cc b/third_party/crashpad/crashpad/test/multiprocess_posix.cc index 782d5ba9..c16aa08f 100644 --- a/third_party/crashpad/crashpad/test/multiprocess_posix.cc +++ b/third_party/crashpad/crashpad/test/multiprocess_posix.cc
@@ -143,7 +143,7 @@ if (exception_swallower.get()) { ExceptionSwallower::SwallowExceptions(); } -#elif defined(OS_LINUX) || defined(OS_ANDROID) +#elif defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID) if (reason_ == kTerminationSignal && Signals::IsCrashSignal(code_)) { Signals::InstallDefaultHandler(code_); }
diff --git a/third_party/crashpad/crashpad/test/process_type.cc b/third_party/crashpad/crashpad/test/process_type.cc index ac0b865e..f6eec36 100644 --- a/third_party/crashpad/crashpad/test/process_type.cc +++ b/third_party/crashpad/crashpad/test/process_type.cc
@@ -16,7 +16,7 @@ #if defined(OS_FUCHSIA) #include <lib/zx/process.h> -#elif defined(OS_LINUX) || defined(OS_ANDROID) +#elif defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID) #include <unistd.h> #endif @@ -26,7 +26,7 @@ ProcessType GetSelfProcess() { #if defined(OS_FUCHSIA) return zx::process::self(); -#elif defined(OS_LINUX) || defined(OS_ANDROID) +#elif defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID) return getpid(); #elif defined(OS_WIN) return GetCurrentProcess();
diff --git a/third_party/crashpad/crashpad/test/process_type.h b/third_party/crashpad/crashpad/test/process_type.h index d14514e5..cacac04f 100644 --- a/third_party/crashpad/crashpad/test/process_type.h +++ b/third_party/crashpad/crashpad/test/process_type.h
@@ -19,7 +19,7 @@ #if defined(OS_FUCHSIA) #include <lib/zx/process.h> -#elif defined(OS_LINUX) || defined(OS_ANDROID) +#elif defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID) #include <sys/types.h> #elif defined(OS_WIN) #include <windows.h> @@ -32,7 +32,8 @@ #if defined(OS_FUCHSIA) using ProcessType = zx::unowned_process; -#elif defined(OS_LINUX) || defined(OS_ANDROID) || DOXYGEN +#elif defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID) || \ + DOXYGEN //! \brief Alias for platform-specific type to represent a process. using ProcessType = pid_t; #elif defined(OS_WIN)
diff --git a/third_party/crashpad/crashpad/tools/generate_dump.cc b/third_party/crashpad/crashpad/tools/generate_dump.cc index dd62cd7..e22f92a5 100644 --- a/third_party/crashpad/crashpad/tools/generate_dump.cc +++ b/third_party/crashpad/crashpad/tools/generate_dump.cc
@@ -47,7 +47,7 @@ #include "snapshot/win/process_snapshot_win.h" #include "util/win/scoped_process_suspend.h" #include "util/win/xp_compat.h" -#elif defined(OS_LINUX) || defined(OS_ANDROID) +#elif defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID) #include "snapshot/linux/process_snapshot_linux.h" #endif // OS_APPLE @@ -196,7 +196,7 @@ 0)) { return EXIT_FAILURE; } -#elif defined(OS_LINUX) || defined(OS_ANDROID) +#elif defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID) // TODO(jperaza): https://crashpad.chromium.org/bug/30. ProcessSnapshotLinux process_snapshot; if (!process_snapshot.Initialize(nullptr)) {
diff --git a/third_party/crashpad/crashpad/util/BUILD.gn b/third_party/crashpad/crashpad/util/BUILD.gn index 2e1bbee..2585caa 100644 --- a/third_party/crashpad/crashpad/util/BUILD.gn +++ b/third_party/crashpad/crashpad/util/BUILD.gn
@@ -131,6 +131,15 @@ "--arch", "arm64", ] + } else if (crashpad_is_mac && current_cpu == "mac_universal") { + args += [ + "--arch", + "x86_64", + "--arch", + "arm64", + ] + } else { + assert(false, "Unsupported architecture") } } @@ -339,6 +348,8 @@ "mac/mac_util.h", "mac/service_management.cc", "mac/service_management.h", + "mac/sysctl.cc", + "mac/sysctl.h", "mach/bootstrap.cc", "mach/bootstrap.h", "mach/child_port_handshake.cc", @@ -612,6 +623,10 @@ } configs += [ "..:disable_ubsan" ] + + if (crashpad_is_in_fuchsia) { + configs += [ "//build/config:Wno-conversion" ] + } } if (!crashpad_is_android && !crashpad_is_ios) { @@ -742,6 +757,7 @@ "mac/launchd_test.mm", "mac/mac_util_test.mm", "mac/service_management_test.mm", + "mac/sysctl_test.cc", "mach/bootstrap_test.cc", "mach/child_port_handshake_test.cc", "mach/child_port_server_test.cc",
diff --git a/third_party/crashpad/crashpad/util/file/file_io.h b/third_party/crashpad/crashpad/util/file/file_io.h index 6fa0f96d..1f502ad 100644 --- a/third_party/crashpad/crashpad/util/file/file_io.h +++ b/third_party/crashpad/crashpad/util/file/file_io.h
@@ -398,7 +398,7 @@ FileWriteMode mode, FilePermissions permissions); -#if defined(OS_LINUX) +#if defined(OS_LINUX) || defined(OS_CHROMEOS) //! \brief Opens an in-memory file for input and output. //! //! This function first attempts to open the file with `memfd_create()`. If @@ -420,7 +420,7 @@ //! \sa LoggingOpenFileForWrite //! \sa LoggingOpenFileForReadAndWrite FileHandle LoggingOpenMemoryFileForReadAndWrite(const base::FilePath& name); -#endif // OS_LINUX +#endif // OS_LINUX || OS_CHROMEOS //! \brief Wraps OpenFileForReadAndWrite(), logging an error if the operation //! fails.
diff --git a/third_party/crashpad/crashpad/util/file/file_io_posix.cc b/third_party/crashpad/crashpad/util/file/file_io_posix.cc index 001b2d97..2baa811 100644 --- a/third_party/crashpad/crashpad/util/file/file_io_posix.cc +++ b/third_party/crashpad/crashpad/util/file/file_io_posix.cc
@@ -153,7 +153,7 @@ return fd; } -#if defined(OS_LINUX) +#if defined(OS_LINUX) || defined(OS_CHROMEOS) FileHandle LoggingOpenMemoryFileForReadAndWrite(const base::FilePath& name) { DCHECK(name.value().find('/') == std::string::npos);
diff --git a/third_party/crashpad/crashpad/util/file/file_io_test.cc b/third_party/crashpad/crashpad/util/file/file_io_test.cc index 0efded8..52bb6ee 100644 --- a/third_party/crashpad/crashpad/util/file/file_io_test.cc +++ b/third_party/crashpad/crashpad/util/file/file_io_test.cc
@@ -473,7 +473,7 @@ TestOpenFileForWrite(LoggingOpenFileForReadAndWrite); } -#if defined(OS_LINUX) +#if defined(OS_LINUX) || defined(OS_CHROMEOS) TEST(FileIO, LoggingOpenMemoryFileForReadAndWrite) { ScopedFileHandle handle( LoggingOpenMemoryFileForReadAndWrite(base::FilePath("memfile"))); @@ -488,7 +488,7 @@ ASSERT_TRUE(LoggingReadFileExactly(handle.get(), buffer, sizeof(buffer))); EXPECT_EQ(memcmp(buffer, kTestData, sizeof(buffer)), 0); } -#endif // OS_LINUX +#endif // OS_LINUX || OS_CHROMEOS enum class ReadOrWrite : bool { kRead,
diff --git a/third_party/crashpad/crashpad/util/file/file_writer.cc b/third_party/crashpad/crashpad/util/file/file_writer.cc index 6dff975a..73fe708 100644 --- a/third_party/crashpad/crashpad/util/file/file_writer.cc +++ b/third_party/crashpad/crashpad/util/file/file_writer.cc
@@ -171,7 +171,7 @@ return true; } -#if defined(OS_LINUX) +#if defined(OS_LINUX) || defined(OS_CHROMEOS) bool FileWriter::OpenMemfd(const base::FilePath& path) { CHECK(!file_.is_valid()); file_.reset(LoggingOpenMemoryFileForReadAndWrite(path));
diff --git a/third_party/crashpad/crashpad/util/file/file_writer.h b/third_party/crashpad/crashpad/util/file/file_writer.h index 4b99b37..987c0f5 100644 --- a/third_party/crashpad/crashpad/util/file/file_writer.h +++ b/third_party/crashpad/crashpad/util/file/file_writer.h
@@ -131,7 +131,7 @@ FileWriteMode write_mode, FilePermissions permissions); -#if defined(OS_LINUX) +#if defined(OS_LINUX) || defined(OS_CHROMEOS) //! \brief Wraps LoggingOpenMemoryFileForWrite(). //! //! \return `true` if the operation succeeded, `false` if it failed, with an
diff --git a/third_party/crashpad/crashpad/util/linux/exception_handler_protocol.cc b/third_party/crashpad/crashpad/util/linux/exception_handler_protocol.cc index 45590c8..27f180c 100644 --- a/third_party/crashpad/crashpad/util/linux/exception_handler_protocol.cc +++ b/third_party/crashpad/crashpad/util/linux/exception_handler_protocol.cc
@@ -19,9 +19,9 @@ ExceptionHandlerProtocol::ClientInformation::ClientInformation() : exception_information_address(0), sanitization_information_address(0) -#if defined(OS_LINUX) +#if defined(OS_LINUX) || defined(OS_CHROMEOS) , crash_loop_before_time(0) -#endif // OS_LINUX +#endif // OS_LINUX || OS_CHROMEOS {} ExceptionHandlerProtocol::ClientToServerMessage::ClientToServerMessage()
diff --git a/third_party/crashpad/crashpad/util/linux/exception_handler_protocol.h b/third_party/crashpad/crashpad/util/linux/exception_handler_protocol.h index 7312b9d..60b0b1b7 100644 --- a/third_party/crashpad/crashpad/util/linux/exception_handler_protocol.h +++ b/third_party/crashpad/crashpad/util/linux/exception_handler_protocol.h
@@ -52,7 +52,7 @@ //! SanitizationInformation struct, or 0 if there is no such struct. VMAddress sanitization_information_address; -#if defined(OS_LINUX) +#if defined(OS_LINUX) || defined(OS_CHROMEOS) //! \brief Indicates that the client is likely in a crash loop if a crash //! occurs before this timestamp. This value is only used by ChromeOS's //! `/sbin/crash_reporter`.
diff --git a/third_party/crashpad/crashpad/util/mac/mac_util.cc b/third_party/crashpad/crashpad/util/mac/mac_util.cc index 5f79701..10e7aad1 100644 --- a/third_party/crashpad/crashpad/util/mac/mac_util.cc +++ b/third_party/crashpad/crashpad/util/mac/mac_util.cc
@@ -14,20 +14,25 @@ #include "util/mac/mac_util.h" +#include <Availability.h> #include <CoreFoundation/CoreFoundation.h> #include <IOKit/IOKitLib.h> #include <string.h> #include <sys/types.h> #include <sys/utsname.h> +#include "base/check_op.h" #include "base/logging.h" #include "base/mac/foundation_util.h" #include "base/mac/scoped_cftyperef.h" #include "base/mac/scoped_ioobject.h" +#include "base/notreached.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_piece.h" #include "base/strings/stringprintf.h" #include "base/strings/sys_string_conversions.h" +#include "build/build_config.h" +#include "util/mac/sysctl.h" extern "C" { // Private CoreFoundation internals. See 10.9.2 CF-855.14/CFPriv.h and @@ -56,9 +61,10 @@ namespace { +#if __MAC_OS_X_VERSION_MIN_REQUIRED < __MAC_10_13_4 // Returns the running system’s Darwin major version. Don’t call this, it’s an // implementation detail and its result is meant to be cached by -// MacOSXMinorVersion(). +// MacOSVersionNumber(). // // This is very similar to Chromium’s base/mac/mac_util.mm // DarwinMajorVersionInternal(). @@ -92,6 +98,7 @@ return darwin_major_version; } +#endif // DT < 10.13.4 // Helpers for the weak-imported private CoreFoundation internals. @@ -118,9 +125,10 @@ } // Converts |version| to a triplet of version numbers on behalf of -// MacOSXVersion(). Returns true on success. If |version| does not have the -// expected format, returns false. |version| must be in the form "10.9.2" or -// just "10.9". In the latter case, |bugfix| will be set to 0. +// MacOSVersionNumber() and MacOSVersionComponents(). Returns true on success. +// If |version| does not have the expected format, returns false. |version| must +// be in the form "10.9.2" or just "10.9". In the latter case, |bugfix| will be +// set to 0. bool StringToVersionNumbers(const std::string& version, int* major, int* minor, @@ -180,20 +188,62 @@ namespace crashpad { -int MacOSXMinorVersion() { - // The Darwin major version is always 4 greater than the macOS minor version - // for Darwin versions beginning with 6, corresponding to Mac OS X 10.2. - static int mac_os_x_minor_version = DarwinMajorVersion() - 4; - DCHECK(mac_os_x_minor_version >= 2); - return mac_os_x_minor_version; +int MacOSVersionNumber() { + static int macos_version_number = []() { + // kern.osproductversion is a lightweight way to get the operating system + // version from the kernel without having to open any files or spin up any + // threads, but it’s only available in macOS 10.13.4 and later. + std::string macos_version_number_string = ReadStringSysctlByName( + "kern.osproductversion", + __MAC_OS_X_VERSION_MIN_REQUIRED >= __MAC_10_13_4); + if (!macos_version_number_string.empty()) { + int major; + int minor; + int bugfix; + if (StringToVersionNumbers( + macos_version_number_string, &major, &minor, &bugfix)) { + DCHECK_GE(major, 10); + DCHECK_LE(major, 99); + DCHECK_GE(minor, 0); + DCHECK_LE(minor, 99); + DCHECK_GE(bugfix, 0); + DCHECK_LE(bugfix, 99); + return major * 1'00'00 + minor * 1'00 + bugfix; + } + } + +#if __MAC_OS_X_VERSION_MIN_REQUIRED >= __MAC_10_13_4 + // On macOS 10.13.4 and later, the sysctlbyname above should have been + // successful. + NOTREACHED(); + return -1; +#else // DT >= 10.13.4 + // The Darwin major version is always 4 greater than the macOS minor version + // for Darwin versions beginning with 6, corresponding to Mac OS X 10.2, + // through Darwin 19, corresponding to macOS 10.15. + int darwin_major_version = DarwinMajorVersion(); + DCHECK_GE(darwin_major_version, 6); + DCHECK_LE(darwin_major_version, 19); + + int macos_version_number = 10'00'00 + (darwin_major_version - 4) * 1'00; + + // On macOS 10.13.4 and later, the sysctlbyname above should have been + // successful. + DCHECK_LT(macos_version_number, 10'13'04); + + return macos_version_number; +#endif // DT >= 10.13.4 + }(); + + return macos_version_number; } -bool MacOSXVersion(int* major, - int* minor, - int* bugfix, - std::string* build, - bool* server, - std::string* version_string) { +bool MacOSVersionComponents(int* major, + int* minor, + int* bugfix, + std::string* build, + bool* server, + std::string* version_string) { base::ScopedCFTypeRef<CFDictionaryRef> dictionary( TryCFCopyServerVersionDictionary()); if (dictionary) { @@ -217,7 +267,16 @@ success = false; } else { version = base::SysCFStringRefToUTF8(version_cf); - success &= StringToVersionNumbers(version, major, minor, bugfix); + if (!StringToVersionNumbers(version, major, minor, bugfix)) { + success = false; + } else { + DCHECK_GE(*major, 10); + DCHECK_LE(*major, 99); + DCHECK_GE(*minor, 0); + DCHECK_LE(*minor, 99); + DCHECK_GE(*bugfix, 0); + DCHECK_LE(*bugfix, 99); + } } CFStringRef build_cf = base::mac::CFCast<CFStringRef>( @@ -270,8 +329,17 @@ if (platform_expert) { model->assign( IORegistryEntryDataPropertyAsString(platform_expert, CFSTR("model"))); +#if defined(ARCH_CPU_X86_FAMILY) + CFStringRef kBoardProperty = CFSTR("board-id"); +#elif defined(ARCH_CPU_ARM64) + // TODO(https://crashpad.chromium.org/bug/352): When production arm64 + // hardware is available, determine whether board-id works and switch to it + // if feasible, otherwise, determine whether target-type remains a viable + // alternative. + CFStringRef kBoardProperty = CFSTR("target-type"); +#endif board_id->assign(IORegistryEntryDataPropertyAsString(platform_expert, - CFSTR("board-id"))); + kBoardProperty)); } else { model->clear(); board_id->clear();
diff --git a/third_party/crashpad/crashpad/util/mac/mac_util.h b/third_party/crashpad/crashpad/util/mac/mac_util.h index d8b7159..c94e233 100644 --- a/third_party/crashpad/crashpad/util/mac/mac_util.h +++ b/third_party/crashpad/crashpad/util/mac/mac_util.h
@@ -21,14 +21,24 @@ //! \brief Returns the version of the running operating system. //! -//! \return The minor version of the operating system, such as `12` for macOS -//! 10.12.1. +//! \return The version of the operating system, such as `10'15'06` for macOS +//! 10.15.6. +//! +//! The format of the return value matches what is used by the <Availability.h> +//! `__MAC_OS_X_VERSION_MIN_REQUIRED`, `__MAC_OS_X_VERSION_MAX_ALLOWED`, and +//! per-version `__MAC_*` macros, for versions since OS X 10.10. +//! +//! On macOS 10.13.4 and later, this function will return the major, minor, and +//! bugfix components combined into a single number. On older OS versions, only +//! the major and minor components will be returned, and the bugfix component +//! will always be reported as 0. By contrast, MacOSVersionComponents() always +//! returns the bugfix component. //! //! \note This is similar to the base::mac::IsOS*() family of functions, but //! is provided for situations where the caller needs to obtain version //! information beyond what is provided by Chromium’s base, or for when the //! caller needs the actual minor version value. -int MacOSXMinorVersion(); +int MacOSVersionNumber(); //! \brief Returns the version of the running operating system. //! @@ -51,12 +61,12 @@ //! A failure is considered to have occurred if any element could not be //! determined. When this happens, their values will be untouched, but other //! values that could be determined will still be set properly. -bool MacOSXVersion(int* major, - int* minor, - int* bugfix, - std::string* build, - bool* server, - std::string* version_string); +bool MacOSVersionComponents(int* major, + int* minor, + int* bugfix, + std::string* build, + bool* server, + std::string* version_string); //! \brief Returns the model name and board ID of the running system. //!
diff --git a/third_party/crashpad/crashpad/util/mac/mac_util_test.mm b/third_party/crashpad/crashpad/util/mac/mac_util_test.mm index 546c628..aa188e3 100644 --- a/third_party/crashpad/crashpad/util/mac/mac_util_test.mm +++ b/third_party/crashpad/crashpad/util/mac/mac_util_test.mm
@@ -71,15 +71,22 @@ } } -TEST(MacUtil, MacOSXVersion) { +TEST(MacUtil, MacOSVersionComponents) { int major; int minor; int bugfix; std::string build; bool server; std::string version_string; - ASSERT_TRUE( - MacOSXVersion(&major, &minor, &bugfix, &build, &server, &version_string)); + ASSERT_TRUE(MacOSVersionComponents( + &major, &minor, &bugfix, &build, &server, &version_string)); + + EXPECT_GE(major, 10); + EXPECT_LE(major, 99); + EXPECT_GE(minor, 0); + EXPECT_LE(minor, 99); + EXPECT_GE(bugfix, 0); + EXPECT_LE(bugfix, 99); std::string version; if (bugfix) { @@ -108,20 +115,26 @@ EXPECT_EQ(version_string.find(expected_product_name), 0u); } -TEST(MacUtil, MacOSXMinorVersion) { - // Make sure that MacOSXMinorVersion() and MacOSXVersion() agree. The two have - // their own distinct implementations, and the latter was checked against - // sw_vers above. +TEST(MacUtil, MacOSVersionNumber) { + // Make sure that MacOSVersionNumber() and MacOSVersionComponents() agree. The + // two have their own distinct implementations, and the latter was checked + // against sw_vers above. + int macos_version_number = MacOSVersionNumber(); + EXPECT_GE(macos_version_number, 10'00'00); + EXPECT_LE(macos_version_number, 99'99'99); + int major; int minor; int bugfix; std::string build; bool server; std::string version_string; - ASSERT_TRUE( - MacOSXVersion(&major, &minor, &bugfix, &build, &server, &version_string)); + ASSERT_TRUE(MacOSVersionComponents( + &major, &minor, &bugfix, &build, &server, &version_string)); - EXPECT_EQ(MacOSXMinorVersion(), minor); + EXPECT_EQ(macos_version_number, + major * 1'00'00 + minor * 1'00 + + (macos_version_number >= 10'13'04 ? bugfix : 0)); } TEST(MacUtil, MacModelAndBoard) {
diff --git a/third_party/crashpad/crashpad/util/mac/sysctl.cc b/third_party/crashpad/crashpad/util/mac/sysctl.cc new file mode 100644 index 0000000..c364352 --- /dev/null +++ b/third_party/crashpad/crashpad/util/mac/sysctl.cc
@@ -0,0 +1,47 @@ +// Copyright 2020 The Crashpad Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "util/mac/sysctl.h" + +#include <errno.h> +#include <sys/sysctl.h> +#include <sys/types.h> + +#include "base/check_op.h" +#include "base/logging.h" + +namespace crashpad { + +std::string ReadStringSysctlByName(const char* name, bool may_log_enoent) { + size_t buf_len; + if (sysctlbyname(name, nullptr, &buf_len, nullptr, 0) != 0) { + PLOG_IF(WARNING, may_log_enoent || errno != ENOENT) + << "sysctlbyname (size) " << name; + return std::string(); + } + + DCHECK_GE(buf_len, 1u); + + std::string value(buf_len - 1, '\0'); + if (sysctlbyname(name, &value[0], &buf_len, nullptr, 0) != 0) { + PLOG(WARNING) << "sysctlbyname " << name; + return std::string(); + } + + DCHECK_EQ(value[buf_len - 1], '\0'); + + return value; +} + +} // namespace crashpad
diff --git a/third_party/crashpad/crashpad/util/mac/sysctl.h b/third_party/crashpad/crashpad/util/mac/sysctl.h new file mode 100644 index 0000000..cc74704 --- /dev/null +++ b/third_party/crashpad/crashpad/util/mac/sysctl.h
@@ -0,0 +1,36 @@ +// Copyright 2020 The Crashpad Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef CRASHPAD_UTIL_MAC_SYSCTL_H_ +#define CRASHPAD_UTIL_MAC_SYSCTL_H_ + +#include <string> + +namespace crashpad { + +//! \brief Calls `sysctlbyname` to read a string. +//! +//! \param[in] name The string name of the sysctl to raed. +//! \param[in] may_log_enoent If `true`, allows a warning to be logged if the +//! sysctl is not found, indicated by `sysctlbyname` setting `errno` to +//! `ENOENT`. If `false`, no warning will be logged if the sysctl is +//! missing, and an empty string will be returned silently. +//! +//! \return The value of the sysctl read on success. On failure, an empty string +//! with a warning logged, subject to \a may_log_enoent. +std::string ReadStringSysctlByName(const char* name, bool may_log_enoent); + +} // namespace crashpad + +#endif // CRASHPAD_UTIL_MAC_SYSCTL_H_
diff --git a/third_party/crashpad/crashpad/util/mac/sysctl_test.cc b/third_party/crashpad/crashpad/util/mac/sysctl_test.cc new file mode 100644 index 0000000..5aafef16 --- /dev/null +++ b/third_party/crashpad/crashpad/util/mac/sysctl_test.cc
@@ -0,0 +1,35 @@ +// Copyright 2020 The Crashpad Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "util/mac/sysctl.h" + +#include "gtest/gtest.h" + +namespace crashpad { +namespace test { +namespace { + +TEST(Sysctl, ReadStringSysctlByName) { + // kern.ostype is always provided by the kernel, and it’s a constant across + // all versions, so it makes for a good test. + EXPECT_EQ(ReadStringSysctlByName("kern.ostype", true), "Darwin"); + + // Names expected to not exist. + EXPECT_TRUE(ReadStringSysctlByName("kern.scheisskopf", true).empty()); + EXPECT_TRUE(ReadStringSysctlByName("kern.sanders", false).empty()); +} + +} // namespace +} // namespace test +} // namespace crashpad
diff --git a/third_party/crashpad/crashpad/util/mach/exc_server_variants.cc b/third_party/crashpad/crashpad/util/mach/exc_server_variants.cc index e4c2d19..b4052ea 100644 --- a/third_party/crashpad/crashpad/util/mach/exc_server_variants.cc +++ b/third_party/crashpad/crashpad/util/mach/exc_server_variants.cc
@@ -14,7 +14,7 @@ #include "util/mach/exc_server_variants.h" -#include <AvailabilityMacros.h> +#include <Availability.h> #include <string.h> #include <algorithm> @@ -682,8 +682,8 @@ exception_behavior_t behavior, bool set_thread_state) { if (exception == EXC_CRASH -#if !defined(OS_IOS) && MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_11 - && MacOSXMinorVersion() >= 11 +#if defined(OS_MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED < __MAC_10_11 + && MacOSVersionNumber() >= 10'11'00 #endif ) { return KERN_SUCCESS;
diff --git a/third_party/crashpad/crashpad/util/mach/exc_server_variants_test.cc b/third_party/crashpad/crashpad/util/mach/exc_server_variants_test.cc index 227ddfd..38d977f 100644 --- a/third_party/crashpad/crashpad/util/mach/exc_server_variants_test.cc +++ b/third_party/crashpad/crashpad/util/mach/exc_server_variants_test.cc
@@ -31,9 +31,9 @@ #include "util/mach/mach_message.h" #include "util/misc/implicit_cast.h" -#if !defined(OS_IOS) +#if defined(OS_MAC) #include "test/mac/mach_multiprocess.h" -#endif // !OS_IOS +#endif // OS_MAC namespace crashpad { namespace test { @@ -961,7 +961,7 @@ expect_request_ids); } -#if !defined(OS_IOS) +#if defined(OS_MAC) class TestExcServerVariants : public MachMultiprocess, public UniversalMachExcServer::Interface { @@ -975,8 +975,7 @@ flavor_(flavor), state_count_(state_count), handled_(false) { - // This is how the __builtin_trap() in MachMultiprocessChild() appears. - SetExpectedChildTermination(kTerminationSignal, SIGILL); + SetExpectedChildTerminationBuiltinTrap(); } // UniversalMachExcServer::Interface: @@ -1202,7 +1201,7 @@ } } -#endif // !OS_IOS +#endif // OS_MAC TEST(ExcServerVariants, ExcServerSuccessfulReturnValue) { #if defined(OS_IOS) @@ -1210,7 +1209,7 @@ const kern_return_t prefer_not_set_thread_state = KERN_SUCCESS; #else const kern_return_t prefer_not_set_thread_state = - MacOSXMinorVersion() < 11 ? MACH_RCV_PORT_DIED : KERN_SUCCESS; + MacOSVersionNumber() < 10'11'00 ? MACH_RCV_PORT_DIED : KERN_SUCCESS; #endif const struct {
diff --git a/third_party/crashpad/crashpad/util/mach/exception_ports_test.cc b/third_party/crashpad/crashpad/util/mach/exception_ports_test.cc index 6dbc04e..ef79808 100644 --- a/third_party/crashpad/crashpad/util/mach/exception_ports_test.cc +++ b/third_party/crashpad/crashpad/util/mach/exception_ports_test.cc
@@ -25,6 +25,7 @@ #include "base/macros.h" #include "base/notreached.h" #include "base/strings/stringprintf.h" +#include "build/build_config.h" #include "gtest/gtest.h" #include "test/mac/mach_errors.h" #include "test/mac/mach_multiprocess.h" @@ -145,8 +146,7 @@ who_crashes_(who_crashes), handled_(false) { if (who_crashes_ != kNobodyCrashes) { - // This is how the __builtin_trap() in Child::Crash() appears. - SetExpectedChildTermination(kTerminationSignal, SIGILL); + SetExpectedChildTerminationBuiltinTrap(); } } @@ -205,8 +205,14 @@ int signal; ExcCrashRecoverOriginalException(code[0], nullptr, &signal); - // The child crashed with __builtin_trap(), which shows up as SIGILL. - EXPECT_EQ(signal, SIGILL); +#if defined(ARCH_CPU_X86_FAMILY) + constexpr int kBuiltinTrapSignal = SIGILL; +#elif defined(ARCH_CPU_ARM64) + constexpr int kBuiltinTrapSignal = SIGTRAP; +#else +#error Port +#endif + EXPECT_EQ(signal, kBuiltinTrapSignal); } EXPECT_EQ(AuditPIDFromMachMessageTrailer(trailer), 0);
diff --git a/third_party/crashpad/crashpad/util/mach/exception_types.cc b/third_party/crashpad/crashpad/util/mach/exception_types.cc index 2a1f3c0..7fc33f0 100644 --- a/third_party/crashpad/crashpad/util/mach/exception_types.cc +++ b/third_party/crashpad/crashpad/util/mach/exception_types.cc
@@ -15,11 +15,10 @@ #include "util/mach/exception_types.h" #include <Availability.h> -#include <AvailabilityMacros.h> #include <dlfcn.h> #include <errno.h> -#include <libproc.h> #include <kern/exc_resource.h> +#include <libproc.h> #include <strings.h> #include "base/check_op.h" @@ -29,7 +28,7 @@ #include "util/mach/mach_extensions.h" #include "util/numeric/in_range_cast.h" -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_9 +#if __MAC_OS_X_VERSION_MAX_ALLOWED >= __MAC_10_9 extern "C" { @@ -83,13 +82,13 @@ // present on OS X 10.9 and later. If it’s not available, sets errno to ENOSYS // and returns -1. int ProcGetWakemonParams(pid_t pid, int* rate_hz, int* flags) { -#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_9 +#if __MAC_OS_X_VERSION_MAX_ALLOWED < __MAC_10_9 // proc_get_wakemon_params() isn’t in the SDK. Look it up dynamically. static ProcGetWakemonParamsType proc_get_wakemon_params = GetProcGetWakemonParams(); #endif -#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_9 +#if __MAC_OS_X_VERSION_MIN_REQUIRED < __MAC_10_9 // proc_get_wakemon_params() is definitely available if the deployment target // is 10.9 or newer. if (!proc_get_wakemon_params) { @@ -260,7 +259,8 @@ // creation but can be made fatal by calling proc_rlimit_control() with // RLIMIT_CPU_USAGE_MONITOR as the second argument and CPUMON_MAKE_FATAL set // in the flags. - if (MacOSXMinorVersion() >= 10) { + if (__MAC_OS_X_VERSION_MIN_REQUIRED >= __MAC_10_10 || + MacOSVersionNumber() >= 10'10'00) { // In OS X 10.10, the exception code indicates whether the exception is // fatal. See 10.10 xnu-2782.1.97/osfmk/kern/thread.c // THIS_THREAD_IS_CONSUMING_TOO_MUCH_CPU__SENDING_EXC_RESOURCE().
diff --git a/third_party/crashpad/crashpad/util/mach/exception_types_test.cc b/third_party/crashpad/crashpad/util/mach/exception_types_test.cc index c36bdd0..9507c02 100644 --- a/third_party/crashpad/crashpad/util/mach/exception_types_test.cc +++ b/third_party/crashpad/crashpad/util/mach/exception_types_test.cc
@@ -269,7 +269,7 @@ EXC_RESOURCE_ENCODE_TYPE_FLAVOR(RESOURCE_TYPE_CPU, FLAVOR_CPU_MONITOR); EXPECT_TRUE(IsExceptionNonfatalResource(EXC_RESOURCE, code, pid)); - if (MacOSXMinorVersion() >= 10) { + if (MacOSVersionNumber() >= 10'10'00) { // FLAVOR_CPU_MONITOR_FATAL was introduced in OS X 10.10. code = EXC_RESOURCE_ENCODE_TYPE_FLAVOR(RESOURCE_TYPE_CPU, FLAVOR_CPU_MONITOR_FATAL);
diff --git a/third_party/crashpad/crashpad/util/mach/mach_extensions.cc b/third_party/crashpad/crashpad/util/mach/mach_extensions.cc index cefb9bf3..7f80693 100644 --- a/third_party/crashpad/crashpad/util/mach/mach_extensions.cc +++ b/third_party/crashpad/crashpad/util/mach/mach_extensions.cc
@@ -15,7 +15,6 @@ #include "util/mach/mach_extensions.h" #include <Availability.h> -#include <AvailabilityMacros.h> #include <pthread.h> #include "base/mac/mach_logging.h" @@ -50,8 +49,8 @@ #error This code was not ported to iOS versions older than 7 #endif -#if !defined(OS_IOS) && MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_9 - const int mac_os_x_minor_version = MacOSXMinorVersion(); +#if defined(OS_MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED < __MAC_10_9 + const int macos_version_number = MacOSVersionNumber(); #endif // See 10.6.8 xnu-1504.15.3/osfmk/mach/exception_types.h. 10.7 uses the same @@ -67,8 +66,8 @@ EXC_MASK_MACH_SYSCALL | EXC_MASK_RPC_ALERT | EXC_MASK_MACHINE; -#if !defined(OS_IOS) && MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_8 - if (mac_os_x_minor_version < 8) { +#if defined(OS_MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED < __MAC_10_8 + if (macos_version_number < 10'08'00) { return kExcMaskAll_10_6; } #endif @@ -77,8 +76,8 @@ // xnu-2050.48.11/osfmk/mach/exception_types.h. constexpr exception_mask_t kExcMaskAll_10_8 = kExcMaskAll_10_6 | EXC_MASK_RESOURCE; -#if !defined(OS_IOS) && MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_9 - if (mac_os_x_minor_version < 9) { +#if defined(OS_MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED < __MAC_10_9 + if (macos_version_number < 10'09'00) { return kExcMaskAll_10_8; } #endif @@ -97,8 +96,8 @@ #error This code was not ported to iOS versions older than 9 #endif -#if !defined(OS_IOS) && MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_11 - if (MacOSXMinorVersion() < 11) { +#if defined(OS_MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED < __MAC_10_11 + if (MacOSVersionNumber() < 10'11'00) { return kExcMaskValid_10_6; } #endif
diff --git a/third_party/crashpad/crashpad/util/mach/mach_extensions_test.cc b/third_party/crashpad/crashpad/util/mach/mach_extensions_test.cc index 9fd49402..4ff53d94 100644 --- a/third_party/crashpad/crashpad/util/mach/mach_extensions_test.cc +++ b/third_party/crashpad/crashpad/util/mach/mach_extensions_test.cc
@@ -85,14 +85,14 @@ EXPECT_TRUE(exc_mask_all & EXC_MASK_RESOURCE); EXPECT_TRUE(exc_mask_all & EXC_MASK_GUARD); #else // OS_IOS - const int mac_os_x_minor_version = MacOSXMinorVersion(); - if (mac_os_x_minor_version >= 8) { + const int macos_version_number = MacOSVersionNumber(); + if (macos_version_number >= 10'08'00) { EXPECT_TRUE(exc_mask_all & EXC_MASK_RESOURCE); } else { EXPECT_FALSE(exc_mask_all & EXC_MASK_RESOURCE); } - if (mac_os_x_minor_version >= 9) { + if (macos_version_number >= 10'09'00) { EXPECT_TRUE(exc_mask_all & EXC_MASK_GUARD); } else { EXPECT_FALSE(exc_mask_all & EXC_MASK_GUARD); @@ -118,20 +118,20 @@ EXPECT_TRUE(exc_mask_valid & EXC_MASK_GUARD); EXPECT_TRUE(exc_mask_valid & EXC_MASK_CORPSE_NOTIFY); #else // OS_IOS - const int mac_os_x_minor_version = MacOSXMinorVersion(); - if (mac_os_x_minor_version >= 8) { + const int macos_version_number = MacOSVersionNumber(); + if (macos_version_number >= 10'08'00) { EXPECT_TRUE(exc_mask_valid & EXC_MASK_RESOURCE); } else { EXPECT_FALSE(exc_mask_valid & EXC_MASK_RESOURCE); } - if (mac_os_x_minor_version >= 9) { + if (macos_version_number >= 10'09'00) { EXPECT_TRUE(exc_mask_valid & EXC_MASK_GUARD); } else { EXPECT_FALSE(exc_mask_valid & EXC_MASK_GUARD); } - if (mac_os_x_minor_version >= 11) { + if (macos_version_number >= 10'11'00) { EXPECT_TRUE(exc_mask_valid & EXC_MASK_CORPSE_NOTIFY); } else { EXPECT_FALSE(exc_mask_valid & EXC_MASK_CORPSE_NOTIFY);
diff --git a/third_party/crashpad/crashpad/util/mach/mach_message.cc b/third_party/crashpad/crashpad/util/mach/mach_message.cc index 72d71e3..00fe116f 100644 --- a/third_party/crashpad/crashpad/util/mach/mach_message.cc +++ b/third_party/crashpad/crashpad/util/mach/mach_message.cc
@@ -14,7 +14,7 @@ #include "util/mach/mach_message.h" -#include <AvailabilityMacros.h> +#include <Availability.h> #include <limits> @@ -23,9 +23,9 @@ #include "util/misc/clock.h" #include "util/misc/implicit_cast.h" -#if !defined(OS_IOS) +#if defined(OS_MAC) #include <bsm/libbsm.h> -#endif // !OS_IOS +#endif // OS_MAC namespace crashpad { @@ -253,7 +253,7 @@ } } -#if !defined(OS_IOS) +#if defined(OS_MAC) pid_t AuditPIDFromMachMessageTrailer(const mach_msg_trailer_t* trailer) { if (trailer->msgh_trailer_type != MACH_MSG_TRAILER_FORMAT_0) { @@ -269,7 +269,7 @@ const mach_msg_audit_trailer_t* audit_trailer = reinterpret_cast<const mach_msg_audit_trailer_t*>(trailer); -#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_8 +#if __MAC_OS_X_VERSION_MIN_REQUIRED < __MAC_10_8 pid_t audit_pid; audit_token_to_au32(audit_trailer->msgh_audit, nullptr, @@ -287,6 +287,6 @@ return audit_pid; } -#endif // !OS_IOS +#endif // OS_MAC } // namespace crashpad
diff --git a/third_party/crashpad/crashpad/util/mach/mach_message.h b/third_party/crashpad/crashpad/util/mach/mach_message.h index fd8d3d5..c58b6d0 100644 --- a/third_party/crashpad/crashpad/util/mach/mach_message.h +++ b/third_party/crashpad/crashpad/util/mach/mach_message.h
@@ -183,7 +183,7 @@ bool MachMessageDestroyReceivedPort(mach_port_t port, mach_msg_type_name_t port_right_type); -#if !defined(OS_IOS) || DOXYGEN +#if defined(OS_MAC) || DOXYGEN //! \brief Returns the process ID of a Mach message’s sender from its audit //! trailer. @@ -201,7 +201,7 @@ //! audit information. pid_t AuditPIDFromMachMessageTrailer(const mach_msg_trailer_t* trailer); -#endif // !OS_IOS +#endif // OS_MAC } // namespace crashpad
diff --git a/third_party/crashpad/crashpad/util/mach/mach_message_test.cc b/third_party/crashpad/crashpad/util/mach/mach_message_test.cc index 729e3a3..5af954e 100644 --- a/third_party/crashpad/crashpad/util/mach/mach_message_test.cc +++ b/third_party/crashpad/crashpad/util/mach/mach_message_test.cc
@@ -158,7 +158,7 @@ EXPECT_TRUE(MachMessageDestroyReceivedPort(port, MACH_MSG_TYPE_PORT_SEND)); } -#if !defined(OS_IOS) +#if defined(OS_MAC) TEST(MachMessage, AuditPIDFromMachMessageTrailer) { base::mac::ScopedMachReceiveRight port(NewMachPort(MACH_PORT_RIGHT_RECEIVE)); @@ -200,7 +200,7 @@ EXPECT_EQ(AuditPIDFromMachMessageTrailer(&receive.trailer), getpid()); } -#endif // !OS_IOS +#endif // OS_MAC } // namespace } // namespace test
diff --git a/third_party/crashpad/crashpad/util/mach/mig.py b/third_party/crashpad/crashpad/util/mach/mig.py index fa35e006..53a7a5b 100755 --- a/third_party/crashpad/crashpad/util/mach/mig.py +++ b/third_party/crashpad/crashpad/util/mach/mig.py
@@ -14,22 +14,88 @@ # See the License for the specific language governing permissions and # limitations under the License. +import os +import shutil import sys +import tempfile import mig_fix import mig_gen -def main(args): - parsed = mig_gen.parse_args(args) +def _try_remove(*paths): + for path in paths: + try: + os.remove(path) + except OSError: + pass - interface = mig_gen.MigInterface(parsed.user_c, parsed.server_c, - parsed.user_h, parsed.server_h) - mig_gen.generate_interface(parsed.defs, interface, parsed.include, - parsed.sdk, parsed.clang_path, parsed.mig_path, - parsed.migcom_path, parsed.arch) + +def _generate_and_fix(user_c, server_c, user_h, server_h, defs, include, sdk, + clang_path, mig_path, migcom_path, arch): + interface = mig_gen.MigInterface(user_c, server_c, user_h, server_h) + mig_gen.generate_interface(defs, interface, include, sdk, clang_path, + mig_path, migcom_path, arch) mig_fix.fix_interface(interface) +def _wrap_arch_guards(file, arch): + contents = '#if defined(__%s__)\n' % arch + contents += open(file, 'r').read() + contents += '\n#endif /* __%s__ */\n' % arch + return contents + + +def _write_file(path, data): + with open(path, 'w') as file: + file.write(data) + + +def main(args): + parsed = mig_gen.parse_args(args, multiple_arch=True) + + _try_remove(parsed.user_c, parsed.server_c, parsed.user_h, parsed.server_h) + + if len(parsed.arch) <= 1: + _generate_and_fix(parsed.user_c, parsed.server_c, parsed.user_h, + parsed.server_h, parsed.defs, parsed.include, + parsed.sdk, parsed.clang_path, parsed.mig_path, + parsed.migcom_path, + parsed.arch[0] if len(parsed.arch) >= 1 else None) + return 0 + + # Run mig once per architecture, and smush everything together, wrapped in + # in architecture-specific #if guards. + + user_c_data = '' + server_c_data = '' + user_h_data = '' + server_h_data = '' + + for arch in parsed.arch: + # Python 3: use tempfile.TempDirectory instead + temp_dir = tempfile.mkdtemp(prefix=os.path.basename(sys.argv[0]) + '_') + try: + user_c = os.path.join(temp_dir, os.path.basename(parsed.user_c)) + server_c = os.path.join(temp_dir, os.path.basename(parsed.server_c)) + user_h = os.path.join(temp_dir, os.path.basename(parsed.user_h)) + server_h = os.path.join(temp_dir, os.path.basename(parsed.server_h)) + _generate_and_fix(user_c, server_c, user_h, server_h, parsed.defs, + parsed.include, parsed.sdk, parsed.clang_path, + parsed.mig_path, parsed.migcom_path, arch) + + user_c_data += _wrap_arch_guards(user_c, arch) + server_c_data += _wrap_arch_guards(server_c, arch) + user_h_data += _wrap_arch_guards(user_h, arch) + server_h_data += _wrap_arch_guards(server_h, arch) + finally: + shutil.rmtree(temp_dir) + + _write_file(parsed.user_c, user_c_data) + _write_file(parsed.server_c, server_c_data) + _write_file(parsed.user_h, user_h_data) + _write_file(parsed.server_h, server_h_data) + + if __name__ == '__main__': sys.exit(main(sys.argv[1:]))
diff --git a/third_party/crashpad/crashpad/util/mach/mig_gen.py b/third_party/crashpad/crashpad/util/mach/mig_gen.py index dcbf8296..99b4f7e 100755 --- a/third_party/crashpad/crashpad/util/mach/mig_gen.py +++ b/third_party/crashpad/crashpad/util/mach/mig_gen.py
@@ -59,17 +59,25 @@ subprocess.check_call(command) -def parse_args(args): +def parse_args(args, multiple_arch=False): parser = argparse.ArgumentParser() - parser.add_argument('--clang-path', help='Path to Clang') + parser.add_argument('--clang-path', help='Path to clang') parser.add_argument('--mig-path', help='Path to mig') parser.add_argument('--migcom-path', help='Path to migcom') - parser.add_argument('--arch', help='Target architecture') + if not multiple_arch: + parser.add_argument('--arch', help='Target architecture') + else: + parser.add_argument( + '--arch', + default=[], + action='append', + help='Target architecture (may appear multiple times)') parser.add_argument('--sdk', help='Path to SDK') - parser.add_argument('--include', - default=[], - action='append', - help='Additional include directory') + parser.add_argument( + '--include', + default=[], + action='append', + help='Additional include directory (may appear multiple times)') parser.add_argument('defs') parser.add_argument('user_c') parser.add_argument('server_c')
diff --git a/third_party/crashpad/crashpad/util/misc/address_types.h b/third_party/crashpad/crashpad/util/misc/address_types.h index b3c69c0..14942bd 100644 --- a/third_party/crashpad/crashpad/util/misc/address_types.h +++ b/third_party/crashpad/crashpad/util/misc/address_types.h
@@ -25,7 +25,7 @@ #include <mach/mach_types.h> #elif defined(OS_WIN) #include "util/win/address_types.h" -#elif defined(OS_LINUX) || defined(OS_ANDROID) +#elif defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID) #include "util/linux/address_types.h" #elif defined(OS_FUCHSIA) #include <zircon/types.h> @@ -55,7 +55,7 @@ using VMAddress = WinVMAddress; using VMSize = WinVMSize; -#elif defined(OS_LINUX) || defined(OS_ANDROID) +#elif defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID) using VMAddress = LinuxVMAddress; using VMSize = LinuxVMSize;
diff --git a/third_party/crashpad/crashpad/util/misc/capture_context.h b/third_party/crashpad/crashpad/util/misc/capture_context.h index eda4efa..d21a24f 100644 --- a/third_party/crashpad/crashpad/util/misc/capture_context.h +++ b/third_party/crashpad/crashpad/util/misc/capture_context.h
@@ -21,7 +21,7 @@ #include <mach/mach.h> #elif defined(OS_WIN) #include <windows.h> -#elif defined(OS_LINUX) || defined(OS_ANDROID) +#elif defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID) #include <ucontext.h> #elif defined(OS_FUCHSIA) #include <signal.h> @@ -37,7 +37,8 @@ #endif #elif defined(OS_WIN) using NativeCPUContext = CONTEXT; -#elif defined(OS_LINUX) || defined(OS_ANDROID) || defined(OS_FUCHSIA) +#elif defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID) || \ + defined(OS_FUCHSIA) using NativeCPUContext = ucontext_t; #endif // OS_APPLE
diff --git a/third_party/crashpad/crashpad/util/misc/metrics.cc b/third_party/crashpad/crashpad/util/misc/metrics.cc index be75a720..4b87f107 100644 --- a/third_party/crashpad/crashpad/util/misc/metrics.cc +++ b/third_party/crashpad/crashpad/util/misc/metrics.cc
@@ -25,7 +25,7 @@ #define METRICS_OS_NAME "Win" #elif defined(OS_ANDROID) #define METRICS_OS_NAME "Android" -#elif defined(OS_LINUX) +#elif defined(OS_LINUX) || defined(OS_CHROMEOS) #define METRICS_OS_NAME "Linux" #elif defined(OS_FUCHSIA) #define METRICS_OS_NAME "Fuchsia"
diff --git a/third_party/crashpad/crashpad/util/misc/time.h b/third_party/crashpad/crashpad/util/misc/time.h index dffe1a8a..dc992bdc 100644 --- a/third_party/crashpad/crashpad/util/misc/time.h +++ b/third_party/crashpad/crashpad/util/misc/time.h
@@ -69,13 +69,13 @@ #endif // OS_WIN -#if defined(OS_LINUX) || defined(OS_ANDROID) || DOXYGEN +#if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID) || DOXYGEN //! \brief Get the kernel boot time. Subsequent calls to this function may //! return different results due to the system clock being changed or //! imprecision in measuring the boot time. //! \return `true` on success. Otherwise, `false` with a message logged. bool GetBootTime(timespec* ts); -#endif // OS_LINUX || OS_ANDROID || DOXYGEN +#endif // OS_LINUX || OS_CHROMEOS || OS_ANDROID || DOXYGEN } // namespace crashpad
diff --git a/third_party/crashpad/crashpad/util/misc/uuid.cc b/third_party/crashpad/crashpad/util/misc/uuid.cc index e444a07f..681a2353 100644 --- a/third_party/crashpad/crashpad/util/misc/uuid.cc +++ b/third_party/crashpad/crashpad/util/misc/uuid.cc
@@ -93,8 +93,8 @@ uuid_generate(uuid); InitializeFromBytes(uuid); return true; -#elif defined(OS_WIN) || defined(OS_LINUX) || defined(OS_ANDROID) || \ - defined(OS_FUCHSIA) +#elif defined(OS_WIN) || defined(OS_LINUX) || defined(OS_CHROMEOS) || \ + defined(OS_ANDROID) || defined(OS_FUCHSIA) // Linux, Android, and Fuchsia do not provide a UUID generator in a // widely-available system library. On Linux and Android, uuid_generate() // from libuuid is not available everywhere.
diff --git a/third_party/crashpad/crashpad/util/net/http_transport_socket.cc b/third_party/crashpad/crashpad/util/net/http_transport_socket.cc index b9c6c9c..0451d2c 100644 --- a/third_party/crashpad/crashpad/util/net/http_transport_socket.cc +++ b/third_party/crashpad/crashpad/util/net/http_transport_socket.cc
@@ -123,7 +123,7 @@ return false; } } else { -#if defined(OS_LINUX) +#if defined(OS_LINUX) || defined(OS_CHROMEOS) if (SSL_CTX_load_verify_locations( ctx_.get(), nullptr, "/etc/ssl/certs") <= 0) { LOG(ERROR) << "SSL_CTX_load_verify_locations";
diff --git a/third_party/crashpad/crashpad/util/numeric/checked_address_range.cc b/third_party/crashpad/crashpad/util/numeric/checked_address_range.cc index 18d75685..4ba7ff39 100644 --- a/third_party/crashpad/crashpad/util/numeric/checked_address_range.cc +++ b/third_party/crashpad/crashpad/util/numeric/checked_address_range.cc
@@ -22,7 +22,7 @@ #include <mach/mach.h> #elif defined(OS_WIN) #include "util/win/address_types.h" -#elif defined(OS_LINUX) || defined(OS_ANDROID) +#elif defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID) #include "util/linux/address_types.h" #elif defined(OS_FUCHSIA) #include <zircon/types.h> @@ -130,7 +130,7 @@ template class CheckedAddressRangeGeneric<mach_vm_address_t, mach_vm_size_t>; #elif defined(OS_WIN) template class CheckedAddressRangeGeneric<WinVMAddress, WinVMSize>; -#elif defined(OS_LINUX) || defined(OS_ANDROID) +#elif defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID) template class CheckedAddressRangeGeneric<LinuxVMAddress, LinuxVMSize>; #elif defined(OS_FUCHSIA) template class CheckedAddressRangeGeneric<zx_vaddr_t, size_t>;
diff --git a/third_party/crashpad/crashpad/util/posix/close_multiple.cc b/third_party/crashpad/crashpad/util/posix/close_multiple.cc index 4f24df1..0c07832 100644 --- a/third_party/crashpad/crashpad/util/posix/close_multiple.cc +++ b/third_party/crashpad/crashpad/util/posix/close_multiple.cc
@@ -74,7 +74,7 @@ bool CloseMultipleNowOrOnExecUsingFDDir(int min_fd, int preserve_fd) { #if defined(OS_APPLE) static constexpr char kFDDir[] = "/dev/fd"; -#elif defined(OS_LINUX) || defined(OS_ANDROID) +#elif defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID) static constexpr char kFDDir[] = "/proc/self/fd"; #endif @@ -135,7 +135,8 @@ max_fd = std::max(max_fd, getdtablesize()); #endif -#if !(defined(OS_LINUX) || defined(OS_ANDROID)) || defined(OPEN_MAX) +#if !(defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID)) || \ + defined(OPEN_MAX) // Linux does not provide OPEN_MAX. See // https://git.kernel.org/cgit/linux/kernel/git/stable/linux-stable.git/commit/include/linux/limits.h?id=77293034696e3e0b6c8b8fc1f96be091104b3d2b. max_fd = std::max(max_fd, OPEN_MAX); @@ -162,7 +163,7 @@ } else { PLOG(WARNING) << "sysctl"; } -#elif defined(OS_LINUX) || defined(OS_ANDROID) +#elif defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID) // See linux-4.4.27/fs/file.c sysctl_nr_open, referenced by kernel/sys.c // do_prlimit() and kernel/sysctl.c fs_table. Inability to open this file is // not considered an error, because /proc may not be available or usable.
diff --git a/third_party/crashpad/crashpad/util/posix/drop_privileges.cc b/third_party/crashpad/crashpad/util/posix/drop_privileges.cc index 7c1fe84e..75650d5 100644 --- a/third_party/crashpad/crashpad/util/posix/drop_privileges.cc +++ b/third_party/crashpad/crashpad/util/posix/drop_privileges.cc
@@ -73,7 +73,7 @@ CHECK_EQ(setegid(egid), -1); } } -#elif defined(OS_LINUX) || defined(OS_ANDROID) +#elif defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID) PCHECK(setresgid(gid, gid, gid) == 0) << "setresgid"; PCHECK(setresuid(uid, uid, uid) == 0) << "setresuid";
diff --git a/third_party/crashpad/crashpad/util/posix/process_info.h b/third_party/crashpad/crashpad/util/posix/process_info.h index 439284f..d144c04b 100644 --- a/third_party/crashpad/crashpad/util/posix/process_info.h +++ b/third_party/crashpad/crashpad/util/posix/process_info.h
@@ -33,7 +33,7 @@ #include <sys/sysctl.h> #endif -#if defined(OS_LINUX) || defined(OS_ANDROID) +#if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID) #include "util/linux/ptrace_connection.h" #endif @@ -44,7 +44,7 @@ ProcessInfo(); ~ProcessInfo(); -#if defined(OS_LINUX) || defined(OS_ANDROID) || DOXYGEN +#if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID) || DOXYGEN //! \brief Initializes this object with information about the process whose ID //! is \a pid using a PtraceConnection \a connection. //! @@ -59,7 +59,7 @@ //! //! \return `true` on success, `false` on failure with a message logged. bool InitializeWithPtrace(PtraceConnection* connection); -#endif // OS_LINUX || OS_ANDROID || DOXYGEN +#endif // OS_LINUX || OS_CHROMEOS || OS_ANDROID || DOXYGEN #if defined(OS_APPLE) || DOXYGEN //! \brief Initializes this object with information about the process whose ID @@ -168,7 +168,7 @@ private: #if defined(OS_APPLE) kinfo_proc kern_proc_info_; -#elif defined(OS_LINUX) || defined(OS_ANDROID) +#elif defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID) // Some members are marked mutable so that they can be lazily initialized by // const methods. These are always InitializationState-protected so that // multiple successive calls will always produce the same return value and out
diff --git a/third_party/crashpad/crashpad/util/posix/process_info_mac.cc b/third_party/crashpad/crashpad/util/posix/process_info_mac.cc index 9e86e08..672e427 100644 --- a/third_party/crashpad/crashpad/util/posix/process_info_mac.cc +++ b/third_party/crashpad/crashpad/util/posix/process_info_mac.cc
@@ -175,7 +175,14 @@ return false; } - args_size = args_size_estimate + 1; + // TODO(https://crashpad.chromium.org/bug/355): This was increased from + 1 + // to + 32 to work around a new bug in macOS 11.0db6 20A5364e that has + // broken {CTL_KERN, KERN_PROCARGS2} such that it will not work properly + // unless provided with a buffer at least 17 bytes larger than indicated in + // args_size_estimate. If this bug is fixed prior to the 11.0 release, + // remove the workaround and go back to + 1. (A positive offset is needed + // for the reasons described above.) + args_size = args_size_estimate + 32; args.resize(args_size); rv = sysctl(mib, base::size(mib), &args[0], &args_size, nullptr, 0); if (rv != 0) {
diff --git a/third_party/crashpad/crashpad/util/posix/process_info_test.cc b/third_party/crashpad/crashpad/util/posix/process_info_test.cc index 56ee356b..78061847 100644 --- a/third_party/crashpad/crashpad/util/posix/process_info_test.cc +++ b/third_party/crashpad/crashpad/util/posix/process_info_test.cc
@@ -33,7 +33,7 @@ #include "util/misc/implicit_cast.h" #include "util/string/split_string.h" -#if defined(OS_LINUX) || defined(OS_ANDROID) +#if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID) #include "util/linux/direct_ptrace_connection.h" #include "test/linux/fake_ptrace_connection.h" #endif @@ -98,7 +98,7 @@ const std::vector<std::string>& expect_argv = GetMainArguments(); -#if defined(OS_ANDROID) || defined(OS_LINUX) +#if defined(OS_ANDROID) || defined(OS_LINUX) || defined(OS_CHROMEOS) // Prior to Linux 4.2, the kernel only allowed reading a single page from // /proc/<pid>/cmdline, causing any further arguments to be truncated. Disable // testing arguments in this case. @@ -124,7 +124,7 @@ argv_size > static_cast<size_t>(getpagesize())) { return; } -#endif // OS_ANDROID || OS_LINUX +#endif // OS_ANDROID || OS_LINUX || OS_CHROMEOS std::vector<std::string> argv; ASSERT_TRUE(process_info.Arguments(&argv)); @@ -161,13 +161,13 @@ TEST(ProcessInfo, Self) { ProcessInfo process_info; -#if defined(OS_LINUX) || defined(OS_ANDROID) +#if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID) FakePtraceConnection connection; ASSERT_TRUE(connection.Initialize(getpid())); ASSERT_TRUE(process_info.InitializeWithPtrace(&connection)); #else ASSERT_TRUE(process_info.InitializeWithPid(getpid())); -#endif // OS_LINUX || OS_ANDROID +#endif // OS_LINUX || OS_ANDROID || OS_CHROMEOS TestSelfProcess(process_info); } @@ -184,7 +184,7 @@ // PID 1 is expected to be init or the system’s equivalent. This tests reading // information about another process. ProcessInfo process_info; -#if defined(OS_LINUX) || defined(OS_ANDROID) +#if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID) FakePtraceConnection connection; ASSERT_TRUE(connection.Initialize(1)); ASSERT_TRUE(process_info.InitializeWithPtrace(&connection)); @@ -212,7 +212,7 @@ void MultiprocessParent() override { const pid_t pid = ChildPID(); -#if defined(OS_LINUX) || defined(OS_ANDROID) +#if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID) DirectPtraceConnection connection; ASSERT_TRUE(connection.Initialize(pid)); @@ -221,7 +221,7 @@ #else ProcessInfo process_info; ASSERT_TRUE(process_info.InitializeWithPid(pid)); -#endif // OS_LINUX || OS_ANDROID +#endif // OS_LINUX || OS_CHROMEOS || OS_ANDROID EXPECT_EQ(process_info.ProcessID(), pid); EXPECT_EQ(process_info.ParentProcessID(), getpid());
diff --git a/third_party/crashpad/crashpad/util/posix/signals.cc b/third_party/crashpad/crashpad/util/posix/signals.cc index 252aff7..5ba66a3 100644 --- a/third_party/crashpad/crashpad/util/posix/signals.cc +++ b/third_party/crashpad/crashpad/util/posix/signals.cc
@@ -46,10 +46,10 @@ #if defined(SIGEMT) SIGEMT, #endif // defined(SIGEMT) -#if defined(OS_LINUX) +#if defined(OS_LINUX) || defined(OS_CHROMEOS) SIGXCPU, SIGXFSZ, -#endif // defined(OS_LINUX) +#endif // defined(OS_LINUX) || defined(OS_CHROMEOS) }; // These are the non-core-generating but terminating signals. @@ -86,9 +86,9 @@ SIGXCPU, SIGXFSZ, #endif // defined(OS_APPLE) -#if defined(OS_LINUX) +#if defined(OS_LINUX) || defined(OS_CHROMEOS) SIGIO, -#endif // defined(OS_LINUX) +#endif // defined(OS_LINUX) || defined(OS_CHROMEOS) }; bool InstallHandlers(const std::vector<int>& signals, @@ -189,22 +189,25 @@ // pointer), will not reoccur on their own when returning from the signal // handler. // - // Unfortunately, on macOS, when SIGBUS is received asynchronously via kill(), - // siginfo->si_code makes it appear as though it was actually received via a - // hardware fault. See 10.12.3 xnu-3789.41.3/bsd/dev/i386/unix_signal.c - // sendsig(). Asynchronous SIGBUS will not re-raise itself autonomously, but - // this function (acting on information from the kernel) behaves as though it - // will. This isn’t ideal, but asynchronous SIGBUS is an unexpected condition. - // The alternative, to never treat SIGBUS as autonomously re-raising, is a bad - // idea because the explicit re-raise would lose properties associated with - // the the original signal, which are valuable for debugging and are visible - // to a Mach exception handler. Since SIGBUS is normally received - // synchronously in response to a hardware fault, don’t sweat the unexpected - // asynchronous case. + // Unfortunately, on macOS, when SIGBUS (on all CPUs) and SIGILL and SIGSEGV + // (on arm64) is received asynchronously via kill(), siginfo->si_code makes it + // appear as though it was actually received via a hardware fault. See 10.15.6 + // xnu-6153.141.1/bsd/dev/i386/unix_signal.c sendsig() and 10.15.6 + // xnu-6153.141.1/bsd/dev/arm/unix_signal.c sendsig(). Received + // asynchronously, these signals will not re-raise themselves autonomously, + // but this function (acting on information from the kernel) behaves as though + // they will. This isn’t ideal, but these signals occurring asynchronously is + // an unexpected condition. The alternative, to never treat these signals as + // autonomously re-raising, is a bad idea because the explicit re-raise would + // lose properties associated with the the original signal, which are valuable + // for debugging and are visible to a Mach exception handler. Since these + // signals are normally received synchronously in response to a hardware + // fault, don’t sweat the unexpected asynchronous case. // - // SIGSEGV on macOS originating from a general protection fault is a more - // difficult case: si_code is cleared, making the signal appear asynchronous. - // See 10.12.3 xnu-3789.41.3/bsd/dev/i386/unix_signal.c sendsig(). + // SIGSEGV on macOS on x86[_64] originating from a general protection fault is + // a more difficult case: si_code is cleared, making the signal appear + // asynchronous. See 10.15.6 xnu-6153.141.1/bsd/dev/i386/unix_signal.c + // sendsig(). const int sig = siginfo->si_signo; const int code = siginfo->si_code;
diff --git a/third_party/crashpad/crashpad/util/posix/signals_test.cc b/third_party/crashpad/crashpad/util/posix/signals_test.cc index 6b960de..54cc2f1 100644 --- a/third_party/crashpad/crashpad/util/posix/signals_test.cc +++ b/third_party/crashpad/crashpad/util/posix/signals_test.cc
@@ -51,7 +51,7 @@ #endif // !defined(ARCH_CPU_ARM64) #if defined(ARCH_CPU_X86_FAMILY) || defined(ARCH_CPU_ARMEL) sig == SIGILL || -#endif // defined(ARCH_CPU_X86_FAMILY) || defined(ARCH_CPU_ARMEL +#endif // defined(ARCH_CPU_X86_FAMILY) || defined(ARCH_CPU_ARMEL) sig == SIGPIPE || sig == SIGSEGV || #if defined(OS_APPLE) @@ -466,12 +466,16 @@ } #if defined(OS_APPLE) - if (sig == SIGBUS) { - // Signal handlers can’t distinguish between SIGBUS arising out of a - // hardware fault and SIGBUS raised asynchronously. - // Signals::RestoreHandlerAndReraiseSignalOnReturn() assumes that SIGBUS - // comes from a hardware fault, but this test uses raise(), so the - // re-raise test must be skipped. + if (sig == SIGBUS +#if defined(ARCH_CPU_ARM64) + || sig == SIGILL || sig == SIGSEGV +#endif // defined(ARCH_CPU_ARM64) + ) { + // Signal handlers can’t distinguish between these signals arising out of + // hardware faults and raised asynchronously. + // Signals::RestoreHandlerAndReraiseSignalOnReturn() assumes that they + // come from hardware faults, but this test uses raise(), so the re-raise + // test must be skipped. continue; } #endif // defined(OS_APPLE) @@ -493,12 +497,16 @@ } #if defined(OS_APPLE) - if (sig == SIGBUS) { - // Signal handlers can’t distinguish between SIGBUS arising out of a - // hardware fault and SIGBUS raised asynchronously. - // Signals::RestoreHandlerAndReraiseSignalOnReturn() assumes that SIGBUS - // comes from a hardware fault, but this test uses raise(), so the - // re-raise test must be skipped. + if (sig == SIGBUS +#if defined(ARCH_CPU_ARM64) + || sig == SIGILL || sig == SIGSEGV +#endif // defined(ARCH_CPU_ARM64) + ) { + // Signal handlers can’t distinguish between these signals arising out of + // hardware faults and raised asynchronously. + // Signals::RestoreHandlerAndReraiseSignalOnReturn() assumes that they + // come from hardware faults, but this test uses raise(), so the re-raise + // test must be skipped. continue; } #endif // defined(OS_APPLE)
diff --git a/third_party/crashpad/crashpad/util/posix/symbolic_constants_posix.cc b/third_party/crashpad/crashpad/util/posix/symbolic_constants_posix.cc index 13bd7f9..c6e0fec 100644 --- a/third_party/crashpad/crashpad/util/posix/symbolic_constants_posix.cc +++ b/third_party/crashpad/crashpad/util/posix/symbolic_constants_posix.cc
@@ -64,7 +64,7 @@ "INFO", "USR1", "USR2", -#elif defined(OS_LINUX) || defined(OS_ANDROID) +#elif defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID) #if defined(ARCH_CPU_MIPS_FAMILY) "HUP", "INT", @@ -135,7 +135,7 @@ #endif // defined(ARCH_CPU_MIPS_FAMILY) #endif }; -#if defined(OS_LINUX) || defined(OS_ANDROID) +#if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID) // NSIG is 64 to account for real-time signals. static_assert(base::size(kSignalNames) == 32, "kSignalNames length"); #else
diff --git a/third_party/crashpad/crashpad/util/posix/symbolic_constants_posix_test.cc b/third_party/crashpad/crashpad/util/posix/symbolic_constants_posix_test.cc index 266b057..74d5b545 100644 --- a/third_party/crashpad/crashpad/util/posix/symbolic_constants_posix_test.cc +++ b/third_party/crashpad/crashpad/util/posix/symbolic_constants_posix_test.cc
@@ -66,7 +66,7 @@ #if defined(OS_APPLE) {SIGEMT, "SIGEMT", "EMT"}, {SIGINFO, "SIGINFO", "INFO"}, -#elif defined(OS_LINUX) || defined(OS_ANDROID) +#elif defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID) {SIGPWR, "SIGPWR", "PWR"}, #if !defined(ARCH_CPU_MIPS_FAMILY) {SIGSTKFLT, "SIGSTKFLT", "STKFLT"}, @@ -123,7 +123,7 @@ kSignalTestData[index].short_name); } -#if defined(OS_LINUX) || defined(OS_ANDROID) +#if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID) // NSIG is 64 to account for real-time signals. constexpr int kSignalCount = 32; #else
diff --git a/third_party/crashpad/crashpad/util/stdlib/objc.h b/third_party/crashpad/crashpad/util/stdlib/objc.h index faaa453..b5e5b6c 100644 --- a/third_party/crashpad/crashpad/util/stdlib/objc.h +++ b/third_party/crashpad/crashpad/util/stdlib/objc.h
@@ -15,10 +15,10 @@ #ifndef CRASHPAD_UTIL_STDLIB_OBJC_H_ #define CRASHPAD_UTIL_STDLIB_OBJC_H_ -#include <AvailabilityMacros.h> +#include <Availability.h> #include <objc/objc.h> -#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_8 +#if __MAC_OS_X_VERSION_MAX_ALLOWED < __MAC_10_8 // In order for the @NO and @YES literals to work, NO and YES must be defined as // __objc_no and __objc_yes. See
diff --git a/third_party/crashpad/crashpad/util/stdlib/strnlen.cc b/third_party/crashpad/crashpad/util/stdlib/strnlen.cc index 07b0db54..872c0eb 100644 --- a/third_party/crashpad/crashpad/util/stdlib/strnlen.cc +++ b/third_party/crashpad/crashpad/util/stdlib/strnlen.cc
@@ -14,9 +14,9 @@ #include "util/stdlib/strnlen.h" -#if defined(OS_MAC) && MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_7 +#if defined(OS_MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED < __MAC_10_7 -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7 +#if __MAC_OS_X_VERSION_MAX_ALLOWED >= __MAC_10_7 // Redeclare a method only available on Mac OS X 10.7 and later to suppress a // -Wpartial-availability warning. extern "C" { @@ -27,7 +27,7 @@ namespace crashpad { size_t strnlen(const char* string, size_t max_length) { -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7 +#if __MAC_OS_X_VERSION_MAX_ALLOWED >= __MAC_10_7 if (::strnlen) { return ::strnlen(string, max_length); }
diff --git a/third_party/crashpad/crashpad/util/stdlib/strnlen.h b/third_party/crashpad/crashpad/util/stdlib/strnlen.h index b88f2da..59253b7 100644 --- a/third_party/crashpad/crashpad/util/stdlib/strnlen.h +++ b/third_party/crashpad/crashpad/util/stdlib/strnlen.h
@@ -21,7 +21,7 @@ #include "build/build_config.h" #if defined(OS_MAC) -#include <AvailabilityMacros.h> +#include <Availability.h> #endif namespace crashpad { @@ -38,7 +38,7 @@ //! and not all systems’ standard libraries provide an implementation. size_t strnlen(const char* string, size_t max_length); -#if !defined(OS_MAC) || MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_7 +#if !defined(OS_MAC) || __MAC_OS_X_VERSION_MIN_REQUIRED >= __MAC_10_7 inline size_t strnlen(const char* string, size_t max_length) { return ::strnlen(string, max_length); }
diff --git a/third_party/crashpad/crashpad/util/util.gyp b/third_party/crashpad/crashpad/util/util.gyp index 67722332..6cd8bd9 100644 --- a/third_party/crashpad/crashpad/util/util.gyp +++ b/third_party/crashpad/crashpad/util/util.gyp
@@ -102,6 +102,8 @@ 'mac/mac_util.h', 'mac/service_management.cc', 'mac/service_management.h', + 'mac/sysctl.cc', + 'mac/sysctl.h', 'mac/xattr.cc', 'mac/xattr.h', 'mach/child_port.defs',
diff --git a/third_party/crashpad/crashpad/util/util_test.gyp b/third_party/crashpad/crashpad/util/util_test.gyp index 91ca5112..749c532 100644 --- a/third_party/crashpad/crashpad/util/util_test.gyp +++ b/third_party/crashpad/crashpad/util/util_test.gyp
@@ -53,6 +53,7 @@ 'mac/launchd_test.mm', 'mac/mac_util_test.mm', 'mac/service_management_test.mm', + 'mac/sysctl_test.cc', 'mac/xattr_test.cc', 'mach/child_port_handshake_test.cc', 'mach/child_port_server_test.cc',
diff --git a/third_party/subresource-filter-ruleset/README.chromium b/third_party/subresource-filter-ruleset/README.chromium index 866c86b..b729eec4 100644 --- a/third_party/subresource-filter-ruleset/README.chromium +++ b/third_party/subresource-filter-ruleset/README.chromium
@@ -1,6 +1,6 @@ Name: EasyList URL: https://easylist.to/easylist/easylist.txt -Version: 202007281111 +Version: 202008181203 License: Creative Commons Attribution-ShareAlike 3.0 Unported License File: NOT_SHIPPED Security Critical: no
diff --git a/third_party/subresource-filter-ruleset/data/UnindexedRules.sha1 b/third_party/subresource-filter-ruleset/data/UnindexedRules.sha1 index 0cfcc5e..621db55 100644 --- a/third_party/subresource-filter-ruleset/data/UnindexedRules.sha1 +++ b/third_party/subresource-filter-ruleset/data/UnindexedRules.sha1
@@ -1 +1 @@ -502aa54e29d82495a76757c45531d5ff6c63e6f2 \ No newline at end of file +232b6053a78a7b257787cea6357a7c5d7615e858 \ No newline at end of file
diff --git a/third_party/wuffs/README.chromium b/third_party/wuffs/README.chromium index 3ddf4e9..1e25397 100644 --- a/third_party/wuffs/README.chromium +++ b/third_party/wuffs/README.chromium
@@ -1,8 +1,8 @@ Name: Wuffs (Wrangling Untrusted File Formats Safely) Short name: Wuffs URL: https://github.com/google/wuffs -Version: 0.3.0-alpha.11 -Revision: 67503b5bda0274b637671e277ede1e34dd08b1d7 +Version: 0.3.0-alpha.13 +Revision: ba75ce9c5f224a646d92801b0b8ef74f555d490e Security critical: yes License: Apache 2.0
diff --git a/tools/binary_size/libsupersize/static/index.html b/tools/binary_size/libsupersize/static/index.html index 12c2c22..1da1a9a 100644 --- a/tools/binary_size/libsupersize/static/index.html +++ b/tools/binary_size/libsupersize/static/index.html
@@ -140,14 +140,14 @@ <p class="select-wrapper"> <button type="submit" class="text-button" id="submit-button"> Open Size Report - </button> + </button> <i>(Googlers only)</i> </p> </form> </td> </tr> <tr> <td style="text-align: center" colspan=3> - <p>To upload your own .ndjson file, use the upload button within <a href="viewer.html">the viewer</a>.</p> + <p>To upload your own .size file, use the upload button within <a href="viewer.html">the viewer</a>.</p> </td> </tr> </table>
diff --git a/tools/cygprofile/check_orderfile.py b/tools/cygprofile/check_orderfile.py index e8a01bb..d1e98d8a 100755 --- a/tools/cygprofile/check_orderfile.py +++ b/tools/cygprofile/check_orderfile.py
@@ -46,7 +46,7 @@ logging.warning('Missing symbols in verification: %d', missing_count) if misorder_count: logging.warning('%d misordered symbols:\n %s', misorder_count, - '\n '.join(str(x) for x in misordered_syms[:10])) + '\n '.join(str(x) for x in misordered_syms[:threshold])) if misorder_count > threshold: logging.error('%d misordered symbols over threshold %d, failing', misorder_count, threshold) @@ -60,8 +60,11 @@ parser.add_option('--target-arch', action='store', dest='arch', default='arm', choices=['arm', 'arm64', 'x86', 'x86_64', 'x64', 'mips'], help='The target architecture for the binary.') - parser.add_option('--threshold', action='store', dest='threshold', - default=20, type=int, + parser.add_option('--threshold', + action='store', + dest='threshold', + default=80, + type=int, help='The maximum allowed number of out-of-order symbols.') options, argv = parser.parse_args(sys.argv) if len(argv) != 3:
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index f9b01e3c..6685586 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -6432,7 +6432,7 @@ <int value="7" label="CPMD_BAD_ORIGIN_PRESAVE_GENERATED_PASSWORD"/> <int value="8" label="CPMD_BAD_ORIGIN_SAVE_GENERATION_FIELD_DETECTED_BY_CLASSIFIER"/> - <int value="9" label="CPMD_BAD_ORIGIN_SHOW_FALLBACK_FOR_SAVING"/> + <int value="9" label="CPMD_BAD_ORIGIN_UPON_USER_INPUT_CHANGE"/> <int value="10" label="CPMD_BAD_ORIGIN_AUTOMATIC_GENERATION_STATUS_CHANGED"/> <int value="11" label="CPMD_BAD_ORIGIN_SHOW_MANUAL_PASSWORD_GENERATION_POPUP"/> @@ -16336,6 +16336,15 @@ <int value="8" label="More than 50"/> </enum> +<enum name="DevToolsIssuesPanelIssueExpanded"> + <int value="0" label="CrossOriginEmbedderPolicy"/> + <int value="1" label="MixedContent"/> + <int value="2" label="SameSiteCookie"/> + <int value="3" label="HeavyAd"/> + <int value="4" label="ContentSecurityPolicy"/> + <int value="5" label="Other"/> +</enum> + <enum name="DevToolsIssuesPanelOpenedFrom"> <int value="0" label="Console Info Bar"/> <int value="1" label="Learn More Link COEP"/> @@ -16344,6 +16353,17 @@ <int value="4" label="Adorner"/> </enum> +<enum name="DevToolsIssuesPanelResourceOpened"> + <int value="0" label="CrossOriginEmbedderPolicy Cookie opened"/> + <int value="1" label="CrossOriginEmbedderPolicy Element opened"/> + <int value="2" label="MixedContent Request opened"/> + <int value="3" label="SameSiteCookie Cookie opened"/> + <int value="4" label="SameSiteCookie Request opened"/> + <int value="5" label="HeavyAd Element opened"/> + <int value="6" label="ContentSecurityPolicy Directive opened"/> + <int value="7" label="ContentSecurityPolicy Element opened"/> +</enum> + <enum name="DevToolsKeybindSets"> <int value="0" label="devToolsDefault"/> <int value="1" label="vsCode"/> @@ -24623,6 +24643,7 @@ <int value="24" label="IN_PROGRESS"/> <int value="25" label="CRX_FETCH_URL_EMPTY"/> <int value="26" label="CRX_FETCH_URL_INVALID"/> + <int value="27" label="OVERRIDEN_BY_SETTINGS"/> </enum> <enum name="ExtensionInstallationStage"> @@ -42633,6 +42654,7 @@ <int value="88437020" label="FeaturePolicy:enabled"/> <int value="89785725" label="DataReductionProxyEnabledWithNetworkService:disabled"/> + <int value="90551098" label="UseWallpaperStagingUrl:enabled"/> <int value="91938915" label="enable-suggestions-service"/> <int value="92106937" label="CloseTabSuggestions:disabled"/> <int value="92327255" label="DisplayMoveWindowAccels:disabled"/> @@ -43791,6 +43813,7 @@ <int value="1319024729" label="ServiceWorkerServicification:disabled"/> <int value="1319068611" label="SecondaryUiMd:disabled"/> <int value="1319498514" label="NewMacNotificationAPI:disabled"/> + <int value="1319638975" label="UseWallpaperStagingUrl:disabled"/> <int value="1319725131" label="enable-distance-field-text"/> <int value="1320201920" label="enable-touchpad-three-finger-click"/> <int value="1320450434" label="ArcUsbStorageUI:disabled"/> @@ -58184,6 +58207,21 @@ <int value="2" label="ToastButton"/> </enum> +<enum name="PrivateSetMembershipHashDanceComparison"> + <int value="0" label="Equal Results"/> + <int value="1" label="Different Results"/> + <int value="2" label="PSM Error, Hash Dance Success"/> + <int value="3" label="PSM Success, Hash Dance Error"/> + <int value="4" label="Both Error"/> +</enum> + +<enum name="PrivateSetMembershipStatus"> + <int value="0" label="Attempt"/> + <int value="1" label="Successful Determination"/> + <int value="2" label="Error"/> + <int value="3" label="Timeout"/> +</enum> + <enum name="PrivetNotificationsEvent"> <int value="0" label="PRIVET_SERVICE_STARTED"/> <int value="1" label="PRIVET_LISTER_STARTED"/>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index ed22f4cc..c67eef8 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -24242,7 +24242,7 @@ </histogram> <histogram name="Browser.PaintPreview.Capture.UncompressedOnDiskSize" - units="KB" expires_after="2020-10-20"> + units="KB" expires_after="2021-03-08"> <owner>ckitagawa@chromium.org</owner> <owner>mahmoudi@chromium.org</owner> <owner>fredmello@chromium.org</owner> @@ -24275,7 +24275,7 @@ </histogram> <histogram name="Browser.PaintPreview.Player.CompositorProcessStartedCorrectly" - units="BooleanSuccess" expires_after="2020-10-20"> + units="BooleanSuccess" expires_after="2021-03-08"> <owner>ckitagawa@chromium.org</owner> <owner>mahmoudi@chromium.org</owner> <owner>fredmello@chromium.org</owner> @@ -40350,6 +40350,15 @@ </summary> </histogram> +<histogram name="DevTools.IssuesPanelIssueExpanded" + enum="DevToolsIssuesPanelIssueExpanded" expires_after="2021-08-27"> + <owner>yangguo@chromium.org</owner> + <owner>jegarc@microsoft.com</owner> + <summary> + Records which type of issue is expanded in the issues panel. + </summary> +</histogram> + <histogram name="DevTools.IssuesPanelOpenedFrom" enum="DevToolsIssuesPanelOpenedFrom" expires_after="2021-01-24"> <owner>yangguo@chromium.org</owner> @@ -40359,6 +40368,16 @@ </summary> </histogram> +<histogram name="DevTools.IssuesPanelResourceOpened" + enum="DevToolsIssuesPanelResourceOpened" expires_after="2021-08-27"> + <owner>yangguo@chromium.org</owner> + <owner>jegarc@microsoft.com</owner> + <summary> + Records which resource from what issue category is opened in the issue + panel. + </summary> +</histogram> + <histogram name="DevTools.KeybindSetSettingChanged" enum="DevToolsKeybindSets" expires_after="2020-10-31"> <owner>yangguo@chromium.org</owner> @@ -49532,6 +49551,51 @@ </summary> </histogram> +<histogram base="true" name="Enterprise.AutoEnrollmentHashDanceSuccessTime" + units="ms" expires_after="2021-03-01"> +<!-- Name completed by histogram_suffixes name="EnterpriseAutoEnrollmentType". --> + + <owner>amraboelkher@google.com</owner> + <owner>mpolzer@google.com</owner> + <summary> + Duration of the hash dance to determine enrollment state of the device. Only + recorded if the hash dance finished successfully. + </summary> +</histogram> + +<histogram base="true" + name="Enterprise.AutoEnrollmentPrivateSetMembershipHashDanceComparison" + enum="PrivateSetMembershipHashDanceComparison" expires_after="2021-03-01"> + <owner>amraboelkher@google.com</owner> + <owner>mpolzer@google.com</owner> + <summary> + Comparison of hash dance and private set membership results used to + determine the initial enrollment state of the device. + </summary> +</histogram> + +<histogram base="true" + name="Enterprise.AutoEnrollmentPrivateSetMembershipRequestStatus" + enum="PrivateSetMembershipStatus" expires_after="2021-03-01"> + <owner>amraboelkher@google.com</owner> + <owner>mpolzer@google.com</owner> + <summary> + The status of a private set membership request. This request is used to + determine the initial enrollment state of the device. + </summary> +</histogram> + +<histogram base="true" + name="Enterprise.AutoEnrollmentPrivateSetMembershipSuccessTime" units="ms" + expires_after="2021-03-01"> + <owner>amraboelkher@google.com</owner> + <owner>mpolzer@google.com</owner> + <summary> + Duration of the private set membership request to determine enrollment state + of the device. Only recorded if it finished successfully. + </summary> +</histogram> + <histogram base="true" name="Enterprise.AutoEnrollmentProtocolTime" units="ms" expires_after="2021-03-01"> <!-- Name completed by histogram_suffixes name="EnterpriseAutoEnrollmentType". --> @@ -127562,7 +127626,7 @@ </histogram> <histogram name="PasswordManager.AccountStorage.ClearedOnStartup" - enum="PasswordAccountStoreClearedOnStartup" expires_after="M87"> + enum="PasswordAccountStoreClearedOnStartup" expires_after="M90"> <owner>mamir@chromium.org</owner> <owner>treib@chromium.org</owner> <summary> @@ -127572,7 +127636,7 @@ </histogram> <histogram name="PasswordManager.AccountStorage.ClearedOptInForAllAccounts" - units="accounts" expires_after="M87"> + units="accounts" expires_after="M90"> <owner>mamir@chromium.org</owner> <owner>treib@chromium.org</owner> <summary> @@ -127607,7 +127671,7 @@ </histogram> <histogram name="PasswordManager.AccountStorage.NumOptedInAccountsAfterOptIn" - units="accounts" expires_after="M87"> + units="accounts" expires_after="M90"> <owner>mamir@chromium.org</owner> <owner>treib@chromium.org</owner> <summary> @@ -127618,7 +127682,7 @@ </histogram> <histogram name="PasswordManager.AccountStorage.NumOptedInAccountsAfterOptOut" - units="accounts" expires_after="M87"> + units="accounts" expires_after="M90"> <owner>mamir@chromium.org</owner> <owner>treib@chromium.org</owner> <summary> @@ -127685,7 +127749,7 @@ </histogram> <histogram base="true" name="PasswordManager.AccountStore.AccountsPerSiteHiRes" - units="units" expires_after="M87"> + units="units" expires_after="M90"> <owner>jdoerrie@chromium.org</owner> <owner>mamir@chromium.org</owner> <owner>treib@chromium.org</owner> @@ -127700,7 +127764,7 @@ <histogram base="true" name="PasswordManager.AccountStore.BlacklistedSitesHiRes" units="sites" - expires_after="M87"> + expires_after="M90"> <owner>jdoerrie@chromium.org</owner> <owner>mamir@chromium.org</owner> <owner>treib@chromium.org</owner> @@ -127713,7 +127777,7 @@ </histogram> <histogram name="PasswordManager.AccountStore.EmptyUsernames.CountInDatabase" - units="units" expires_after="M87"> + units="units" expires_after="M90"> <owner>vasilii@chromium.org</owner> <owner>jdoerrie@chromium.org</owner> <owner>mamir@chromium.org</owner> @@ -127725,7 +127789,7 @@ </histogram> <histogram name="PasswordManager.AccountStore.InaccessiblePasswords" - units="saved passwords" expires_after="M87"> + units="saved passwords" expires_after="M90"> <owner>vasilii@chromium.org</owner> <owner>mamir@chromium.org</owner> <owner>treib@chromium.org</owner> @@ -127736,7 +127800,7 @@ </histogram> <histogram base="true" name="PasswordManager.AccountStore.TimesPasswordUsed" - units="PasswordUses" expires_after="M87"> + units="PasswordUses" expires_after="M90"> <owner>battre@chromium.org</owner> <owner>jdoerrie@chromium.org</owner> <owner>mamir@chromium.org</owner> @@ -127752,7 +127816,7 @@ <histogram base="true" name="PasswordManager.AccountStore.TotalAccountsHiRes.ByType" units="units" - expires_after="M87"> + expires_after="M90"> <owner>battre@chromium.org</owner> <owner>mamir@chromium.org</owner> <owner>treib@chromium.org</owner> @@ -127767,7 +127831,7 @@ <histogram base="true" name="PasswordManager.AccountStore.TotalAccountsHiRes.WithScheme" - units="accounts" expires_after="M87"> + units="accounts" expires_after="M90"> <owner>battre@chromium.org</owner> <owner>mamir@chromium.org</owner> <owner>treib@chromium.org</owner> @@ -127782,7 +127846,7 @@ </histogram> <histogram name="PasswordManager.AccountStoreVsProfileStore.Additional" - units="accounts" expires_after="M87"> + units="accounts" expires_after="M90"> <owner>mamir@chromium.org</owner> <owner>treib@chromium.org</owner> <summary> @@ -127793,7 +127857,7 @@ </histogram> <histogram name="PasswordManager.AccountStoreVsProfileStore.Conflicting" - units="accounts" expires_after="M87"> + units="accounts" expires_after="M90"> <owner>mamir@chromium.org</owner> <owner>treib@chromium.org</owner> <summary> @@ -127805,7 +127869,7 @@ </histogram> <histogram name="PasswordManager.AccountStoreVsProfileStore.Identical" - units="accounts" expires_after="M87"> + units="accounts" expires_after="M90"> <owner>mamir@chromium.org</owner> <owner>treib@chromium.org</owner> <summary> @@ -127816,7 +127880,7 @@ </histogram> <histogram name="PasswordManager.AccountStoreVsProfileStore.Missing" - units="accounts" expires_after="M87"> + units="accounts" expires_after="M90"> <owner>mamir@chromium.org</owner> <owner>treib@chromium.org</owner> <summary> @@ -128476,7 +128540,7 @@ </histogram> <histogram name="PasswordManager.DefaultPasswordStoreSet" - enum="PasswordManager.Store" expires_after="M87"> + enum="PasswordManager.Store" expires_after="M90"> <owner>mamir@chromium.org</owner> <owner>treib@chromium.org</owner> <summary> @@ -129443,7 +129507,7 @@ </histogram> <histogram name="PasswordManager.MoveUIDismissalReason" - enum="PasswordManagerUIDismissalReason" expires_after="M87"> + enum="PasswordManagerUIDismissalReason" expires_after="M90"> <!-- Name completed by histogram_suffixes name="PasswordAccountStorageUserState" --> <owner>mamir@chromium.org</owner> @@ -130352,7 +130416,7 @@ </histogram> <histogram name="PasswordManager.StoresUsedForFillingInLast28Days" - enum="PasswordManagerFillingSource" expires_after="M87"> + enum="PasswordManagerFillingSource" expires_after="M90"> <owner>mamir@chromium.org</owner> <owner>treib@chromium.org</owner> <summary> @@ -130364,7 +130428,7 @@ </histogram> <histogram name="PasswordManager.StoresUsedForFillingInLast7Days" - enum="PasswordManagerFillingSource" expires_after="M87"> + enum="PasswordManagerFillingSource" expires_after="M90"> <owner>mamir@chromium.org</owner> <owner>treib@chromium.org</owner> <summary> @@ -145227,7 +145291,7 @@ </histogram> <histogram name="Renderer.PaintPreview.Capture.SubframeBlinkCaptureDuration" - units="ms" expires_after="2020-10-20"> + units="ms" expires_after="2021-03-08"> <owner>ckitagawa@chromium.org</owner> <owner>mahmoudi@chromium.org</owner> <owner>fredmello@chromium.org</owner> @@ -145238,7 +145302,7 @@ </histogram> <histogram name="Renderer.PaintPreview.Capture.SubframeSuccess" - enum="BooleanSuccess" expires_after="2020-10-20"> + enum="BooleanSuccess" expires_after="2021-03-08"> <owner>ckitagawa@chromium.org</owner> <owner>mahmoudi@chromium.org</owner> <owner>fredmello@chromium.org</owner> @@ -180435,6 +180499,17 @@ </summary> </histogram> +<histogram name="Tab.Preview.VideoCaptureDuration" units="ms" + expires_after="M89"> + <owner>dfried@chromium.org</owner> + <owner>collinbaker@chromium.org</owner> + <summary> + Measures the total time spent in video capture mode when generating a + preview for a background tab. This is emitted at the end of each capture + session. + </summary> +</histogram> + <histogram name="Tab.PullDownGesture" enum="PullDownGestureAction" expires_after="2020-01-15"> <owner>gambard@chromium.org</owner> @@ -194337,6 +194412,9 @@ <histogram name="WebCore.WebSocket.MessageSize.Receive" units="bytes" expires_after="2020-09-06"> + <obsolete> + Removed as of 2020-09 + </obsolete> <owner>yhirano@chromium.org</owner> <owner>ricea@chromium.org</owner> <summary> @@ -194347,6 +194425,9 @@ <histogram name="WebCore.WebSocket.MessageSize.Send" units="bytes" expires_after="2021-02-28"> + <obsolete> + Removed as of 2020-09 + </obsolete> <owner>yhirano@chromium.org</owner> <owner>ricea@chromium.org</owner> <summary> @@ -206069,6 +206150,7 @@ <suffix name="InitialEnrollment" label="Initial Enrollment Exchange"/> <affected-histogram name="Enterprise.AutoEnrollmentBucketDownloadTime"/> <affected-histogram name="Enterprise.AutoEnrollmentExtraTime"/> + <affected-histogram name="Enterprise.AutoEnrollmentHashDanceSuccessTime"/> <affected-histogram name="Enterprise.AutoEnrollmentProtocolTime"/> <affected-histogram name="Enterprise.AutoEnrollmentRequestNetworkErrorCode"/> <affected-histogram name="Enterprise.AutoEnrollmentRequestStatus"/> @@ -217790,6 +217872,9 @@ </histogram_suffixes> <histogram_suffixes name="SmoothnessSequenceTypes.Universal" separator="."> + <obsolete> + Removed in 9/2020, due to over penalize smoothness. + </obsolete> <suffix name="Universal" label="All frame production"/> <affected-histogram name="Graphics.Smoothness.Checkerboarding"/> <affected-histogram name="Graphics.Smoothness.FrameSequenceLength"/> @@ -219916,12 +220001,18 @@ </histogram_suffixes> <histogram_suffixes name="WebSocketMessageSizeReceive" separator="."> + <obsolete> + Removed as of 2020-09 + </obsolete> <suffix name="ArrayBuffer" label=""/> <suffix name="Blob" label=""/> <affected-histogram name="WebCore.WebSocket.MessageSize.Receive"/> </histogram_suffixes> <histogram_suffixes name="WebSocketMessageSizeSend" separator="."> + <obsolete> + Removed as of 2020-09 + </obsolete> <suffix name="ArrayBuffer" label=""/> <suffix name="ArrayBufferView" label=""/> <suffix name="Blob" label=""/>
diff --git a/tools/metrics/ukm/ukm.xml b/tools/metrics/ukm/ukm.xml index e21e45b3..b929605 100644 --- a/tools/metrics/ukm/ukm.xml +++ b/tools/metrics/ukm/ukm.xml
@@ -4726,6 +4726,9 @@ </summary> </metric> <metric name="CompositorThread.Universal"> + <obsolete> + Removed in 9/2020, due to over penalize smoothness. + </obsolete> <summary> The throughput of the compositor thread for all frame production. </summary> @@ -4773,6 +4776,9 @@ </summary> </metric> <metric name="MainThread.Universal"> + <obsolete> + Removed in 9/2020, due to over penalize smoothness. + </obsolete> <summary> The throughput of the main thread for all frame production. </summary> @@ -4873,6 +4879,9 @@ </aggregation> </metric> <metric name="SlowerThread.Universal"> + <obsolete> + Removed in 9/2020, due to over penalize smoothness. + </obsolete> <summary> The worse throughput of the main and the compositor thread for all frame production.
diff --git a/tools/perf/core/perf_data_generator.py b/tools/perf/core/perf_data_generator.py index 4932fa7..30910aee 100755 --- a/tools/perf/core/perf_data_generator.py +++ b/tools/perf/core/perf_data_generator.py
@@ -97,8 +97,7 @@ 'android-go-perf', 'android-pixel2-perf', 'android-pixel2_webview-perf', 'linux-perf', 'mac-10_12_laptop_low_end-perf', 'mac-10_13_laptop_high_end-perf', 'win-10-perf', - 'win-10_laptop_low_end-perf', 'android-pixel2-perf-fyi', 'linux-perf-fyi', - 'win-10_laptop_low_end-perf_HP-Candidate' + 'win-10_laptop_low_end-perf' ] FYI_BUILDERS = { @@ -222,18 +221,6 @@ 'device_type': 'kevin', }, }, - 'linux-processor-perf-fyi': { - 'platform': 'linux', - 'perf_processor': True, - }, - 'android-pixel2-processor-perf-fyi': { - 'platform': 'linux', - 'perf_processor': True, - }, - 'win-10_laptop_low_end-perf_HP-Candidate-processor': { - 'platform': 'linux', - 'perf_processor': True, - }, } # These configurations are taken from chromium_perf.py in
diff --git a/tools/perf/expectations.config b/tools/perf/expectations.config index 9e11c33..02e1816 100644 --- a/tools/perf/expectations.config +++ b/tools/perf/expectations.config
@@ -200,8 +200,6 @@ crbug.com/1017244 [ desktop ] rendering.desktop/youtube_2018 [ Skip ] crbug.com/1017244 [ desktop ] rendering.desktop/youtube_pinch_2018 [ Skip ] crbug.com/1044962 [ win ] rendering.desktop/camera_to_webgl [ Skip ] -crbug.com/1122037 [ mac ] rendering.desktop/fill_shapes [ Skip ] -crbug.com/1122037 [ mac ] rendering.desktop/balls_javascript_canvas [ Skip ] # Benchmark: rendering.mobile crbug.com/785485 [ android-webview ] rendering.mobile/kevs_3d [ Skip ]
diff --git a/ui/message_center/views/message_popup_view.cc b/ui/message_center/views/message_popup_view.cc index f7a568e..19b670c 100644 --- a/ui/message_center/views/message_popup_view.cc +++ b/ui/message_center/views/message_popup_view.cc
@@ -39,7 +39,7 @@ if (!message_view_->IsManuallyExpandedOrCollapsed()) message_view_->SetExpanded(message_view_->IsAutoExpandingAllowed()); AddChildView(message_view_); - set_notify_enter_exit_on_child(true); + SetNotifyEnterExitOnChild(true); } MessagePopupView::MessagePopupView(MessagePopupCollection* popup_collection)
diff --git a/ui/message_center/views/notification_view_md.cc b/ui/message_center/views/notification_view_md.cc index 723a763..8964ff5 100644 --- a/ui/message_center/views/notification_view_md.cc +++ b/ui/message_center/views/notification_view_md.cc
@@ -629,7 +629,7 @@ CreateOrUpdateViews(notification); UpdateControlButtonsVisibilityWithNotification(notification); - set_notify_enter_exit_on_child(true); + SetNotifyEnterExitOnChild(true); click_activator_ = std::make_unique<ClickActivator>(this); // Reasons to use pretarget handler instead of OnMousePressed:
diff --git a/ui/views/BUILD.gn b/ui/views/BUILD.gn index d38c2dfd6..6f5884d5 100644 --- a/ui/views/BUILD.gn +++ b/ui/views/BUILD.gn
@@ -120,8 +120,8 @@ "controls/button/menu_button_controller.h", "controls/button/radio_button.h", "controls/button/toggle_button.h", + "controls/color_tracking_icon_view.h", "controls/combobox/combobox.h", - "controls/combobox/combobox_listener.h", "controls/combobox/combobox_util.h", "controls/editable_combobox/editable_combobox.h", "controls/focus_ring.h", @@ -332,6 +332,7 @@ "controls/button/menu_button_controller.cc", "controls/button/radio_button.cc", "controls/button/toggle_button.cc", + "controls/color_tracking_icon_view.cc", "controls/combobox/combobox.cc", "controls/combobox/combobox_util.cc", "controls/combobox/empty_combobox_model.cc",
diff --git a/ui/views/bubble/bubble_dialog_model_host.cc b/ui/views/bubble/bubble_dialog_model_host.cc index 45432082..3dfde015 100644 --- a/ui/views/bubble/bubble_dialog_model_host.cc +++ b/ui/views/bubble/bubble_dialog_model_host.cc
@@ -295,7 +295,17 @@ combobox->SetAccessibleName(model->accessible_name(GetPassKey()).empty() ? model->label(GetPassKey()) : model->accessible_name(GetPassKey())); - combobox->set_listener(this); + combobox->set_callback(base::BindRepeating( + [](ui::DialogModelCombobox* model, + util::PassKey<DialogModelHost> pass_key, Combobox* combobox) { + // TODO(pbos): This should be a subscription through the Combobox + // directly, but Combobox right now doesn't support listening to + // selected-index changes. + model->OnSelectedIndexChanged(pass_key, combobox->GetSelectedIndex()); + model->OnPerformAction(pass_key); + }, + model, GetPassKey())); + // TODO(pbos): Add subscription to combobox selected-index changes. combobox->SetSelectedIndex(model->selected_index()); auto* combobox_ptr = combobox.get(); @@ -325,23 +335,6 @@ ->OnTextChanged(GetPassKey(), textfield->GetText()); } -void BubbleDialogModelHost::NotifyComboboxSelectedIndexChanged( - Combobox* combobox) { - view_to_field_[combobox] - ->AsCombobox(GetPassKey()) - ->OnSelectedIndexChanged(GetPassKey(), combobox->GetSelectedIndex()); -} - -void BubbleDialogModelHost::OnPerformAction(Combobox* combobox) { - // TODO(pbos): This should be a subscription through the Combobox directly, - // but Combobox right now doesn't support listening to selected-index changes. - NotifyComboboxSelectedIndexChanged(combobox); - - view_to_field_[combobox] - ->AsCombobox(GetPassKey()) - ->OnPerformAction(GetPassKey()); -} - void BubbleDialogModelHost::OnViewCreatedForField(View* view, ui::DialogModelField* field) { #if DCHECK_IS_ON()
diff --git a/ui/views/bubble/bubble_dialog_model_host.h b/ui/views/bubble/bubble_dialog_model_host.h index 56d174a..a506fb0 100644 --- a/ui/views/bubble/bubble_dialog_model_host.h +++ b/ui/views/bubble/bubble_dialog_model_host.h
@@ -12,7 +12,6 @@ #include "ui/base/models/dialog_model.h" #include "ui/views/bubble/bubble_dialog_delegate_view.h" #include "ui/views/controls/button/button.h" -#include "ui/views/controls/combobox/combobox_listener.h" namespace views { class Combobox; @@ -30,8 +29,7 @@ // DialogModel::host(). This helps minimize platform-specific code from // platform-agnostic model-delegate code. class VIEWS_EXPORT BubbleDialogModelHost : public BubbleDialogDelegateView, - public ui::DialogModelHost, - public ComboboxListener { + public ui::DialogModelHost { public: // Constructs a BubbleDialogModelHost, which for most purposes is to used as a // BubbleDialogDelegateView. The BubbleDialogDelegateView is nominally handed @@ -52,9 +50,6 @@ void SelectAllText(int unique_id) override; void OnFieldAdded(ui::DialogModelField* field) override; - // ComboboxListener: - void OnPerformAction(views::Combobox* combobox) override; - private: void OnWindowClosing(); @@ -72,7 +67,6 @@ void OnViewCreatedForField(View* view, ui::DialogModelField* field); void NotifyTextfieldTextChanged(views::Textfield* textfield); - void NotifyComboboxSelectedIndexChanged(views::Combobox* combobox); View* FieldToView(ui::DialogModelField* field);
diff --git a/ui/views/controls/color_tracking_icon_view.cc b/ui/views/controls/color_tracking_icon_view.cc new file mode 100644 index 0000000..f1fadd8 --- /dev/null +++ b/ui/views/controls/color_tracking_icon_view.cc
@@ -0,0 +1,23 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ui/views/controls/color_tracking_icon_view.h" + +#include "ui/gfx/paint_vector_icon.h" +#include "ui/native_theme/native_theme.h" + +namespace views { + +ColorTrackingIconView::ColorTrackingIconView(const gfx::VectorIcon& icon, + int icon_size) + : icon_(icon), icon_size_(icon_size) {} + +void ColorTrackingIconView::OnThemeChanged() { + ImageView::OnThemeChanged(); + const SkColor color = GetNativeTheme()->GetSystemColor( + ui::NativeTheme::kColorId_DefaultIconColor); + SetImage(gfx::CreateVectorIcon(icon_, icon_size_, color)); +} + +} // namespace views
diff --git a/ui/views/controls/color_tracking_icon_view.h b/ui/views/controls/color_tracking_icon_view.h new file mode 100644 index 0000000..4ab7a54 --- /dev/null +++ b/ui/views/controls/color_tracking_icon_view.h
@@ -0,0 +1,32 @@ +// 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 UI_VIEWS_CONTROLS_COLOR_TRACKING_ICON_VIEW_H_ +#define UI_VIEWS_CONTROLS_COLOR_TRACKING_ICON_VIEW_H_ + +#include "ui/views/controls/image_view.h" + +namespace gfx { +struct VectorIcon; +} + +namespace views { + +// An ImageView that displays |icon| at |icon_size|. Tracks theme changes so the +// icon is always the correct color. +class VIEWS_EXPORT ColorTrackingIconView : public ImageView { + public: + ColorTrackingIconView(const gfx::VectorIcon& icon, int icon_size); + + // ImageView: + void OnThemeChanged() override; + + private: + const gfx::VectorIcon& icon_; + const int icon_size_; +}; + +} // namespace views + +#endif // UI_VIEWS_CONTROLS_COLOR_TRACKING_ICON_VIEW_H_
diff --git a/ui/views/controls/combobox/combobox.cc b/ui/views/controls/combobox/combobox.cc index 3e3d3289..d763e86 100644 --- a/ui/views/controls/combobox/combobox.cc +++ b/ui/views/controls/combobox/combobox.cc
@@ -676,7 +676,7 @@ NotifyAccessibilityEvent(ax::mojom::Event::kValueChanged, true); SchedulePaint(); - callback_.Run(); + callback_.Run(this); // Note |this| may be deleted by |callback_|. }
diff --git a/ui/views/controls/combobox/combobox.h b/ui/views/controls/combobox/combobox.h index d0afff6..4815c16 100644 --- a/ui/views/controls/combobox/combobox.h +++ b/ui/views/controls/combobox/combobox.h
@@ -15,7 +15,6 @@ #include "ui/base/models/combobox_model.h" #include "ui/base/models/combobox_model_observer.h" #include "ui/views/controls/button/button.h" -#include "ui/views/controls/combobox/combobox_listener.h" #include "ui/views/controls/prefix_delegate.h" #include "ui/views/style/typography.h" @@ -45,7 +44,8 @@ public: METADATA_HEADER(Combobox); - using PerformActionCallback = base::RepeatingClosure; + using PerformActionCallback = + base::RepeatingCallback<void(Combobox* combobox)>; static constexpr int kDefaultComboboxTextContext = style::CONTEXT_BUTTON; static constexpr int kDefaultComboboxTextStyle = style::STYLE_PRIMARY; @@ -66,25 +66,19 @@ const gfx::FontList& GetFontList() const; - // TODO(pbos): Migrate users of this to set_callback(). - void set_listener(ComboboxListener* listener) { - if (!listener) { - set_callback(base::DoNothing()); - return; - } - - set_callback(base::BindRepeating( - [](ComboboxListener* listener, Combobox* combobox) { - listener->OnPerformAction(combobox); - }, - listener, this)); - } - // Sets the callback which will be called when a selection has been made. void set_callback(PerformActionCallback callback) { callback_ = std::move(callback); } + // Version of set_callback() that takes a RepeatingClosure by discarding the + // argument. + void set_closure(base::RepeatingClosure closure) { + set_callback(base::BindRepeating( + [](base::RepeatingClosure closure, Combobox*) { closure.Run(); }, + std::move(closure))); + } + // Gets/Sets the selected index. int GetSelectedIndex() const { return selected_index_; } void SetSelectedIndex(int index);
diff --git a/ui/views/controls/combobox/combobox_listener.h b/ui/views/controls/combobox/combobox_listener.h deleted file mode 100644 index 1c5c4b6..0000000 --- a/ui/views/controls/combobox/combobox_listener.h +++ /dev/null
@@ -1,32 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef UI_VIEWS_CONTROLS_COMBOBOX_COMBOBOX_LISTENER_H_ -#define UI_VIEWS_CONTROLS_COMBOBOX_COMBOBOX_LISTENER_H_ - -#include "ui/views/views_export.h" - -namespace views { - -class Combobox; - -// Interface used to notify consumers when something interesting happens to a -// Combobox. -class VIEWS_EXPORT ComboboxListener { - public: - // Invoked when the user does the appropriate gesture that some action should - // be performed. This is invoked if the user clicks on the menu button and - // then clicks an item, and also when the menu is not showing and the does a - // gesture to change the selection (for example, presses the home or end - // keys). This is not invoked when the menu is shown and the user changes the - // selection without closing the menu. - virtual void OnPerformAction(Combobox* combobox) = 0; - - protected: - virtual ~ComboboxListener() = default; -}; - -} // namespace views - -#endif // UI_VIEWS_CONTROLS_COMBOBOX_COMBOBOX_LISTENER_H_
diff --git a/ui/views/controls/combobox/combobox_unittest.cc b/ui/views/controls/combobox/combobox_unittest.cc index 3737d9b..8260527d 100644 --- a/ui/views/controls/combobox/combobox_unittest.cc +++ b/ui/views/controls/combobox/combobox_unittest.cc
@@ -29,7 +29,6 @@ #include "ui/events/keycodes/keyboard_codes.h" #include "ui/events/test/event_generator.h" #include "ui/events/types/event_type.h" -#include "ui/views/controls/combobox/combobox_listener.h" #include "ui/views/style/platform_style.h" #include "ui/views/test/ax_event_counter.h" #include "ui/views/test/combobox_test_api.h" @@ -148,13 +147,12 @@ DISALLOW_COPY_AND_ASSIGN(VectorComboboxModel); }; -class EvilListener : public ComboboxListener { +class EvilListener { public: EvilListener() = default; - ~EvilListener() override = default; + ~EvilListener() = default; - // ComboboxListener: - void OnPerformAction(Combobox* combobox) override { + void OnPerformAction(Combobox* combobox) { delete combobox; deleted_ = true; } @@ -167,12 +165,12 @@ DISALLOW_COPY_AND_ASSIGN(EvilListener); }; -class TestComboboxListener : public views::ComboboxListener { +class TestComboboxListener { public: TestComboboxListener() = default; - ~TestComboboxListener() override = default; + ~TestComboboxListener() = default; - void OnPerformAction(views::Combobox* combobox) override { + void OnPerformAction(views::Combobox* combobox) { perform_action_index_ = combobox->GetSelectedIndex(); actions_performed_++; } @@ -539,7 +537,8 @@ // |combobox| will be deleted on change. TestCombobox* combobox = new TestCombobox(&model); auto evil_listener = std::make_unique<EvilListener>(); - combobox->set_listener(evil_listener.get()); + combobox->set_callback(base::BindRepeating( + &EvilListener::OnPerformAction, base::Unretained(evil_listener.get()))); ASSERT_NO_FATAL_FAILURE(ComboboxTestApi(combobox).PerformActionAt(2)); EXPECT_TRUE(evil_listener->deleted()); } @@ -548,7 +547,8 @@ InitCombobox(nullptr); TestComboboxListener listener; - combobox_->set_listener(&listener); + combobox_->set_callback(base::BindRepeating( + &TestComboboxListener::OnPerformAction, base::Unretained(&listener))); combobox_->Layout(); // Click the left side. The menu is shown. @@ -563,7 +563,8 @@ InitCombobox(nullptr); TestComboboxListener listener; - combobox_->set_listener(&listener); + combobox_->set_callback(base::BindRepeating( + &TestComboboxListener::OnPerformAction, base::Unretained(&listener))); combobox_->Layout(); combobox_->SetEnabled(false); @@ -579,7 +580,8 @@ InitCombobox(nullptr); TestComboboxListener listener; - combobox_->set_listener(&listener); + combobox_->set_callback(base::BindRepeating( + &TestComboboxListener::OnPerformAction, base::Unretained(&listener))); // The click event is ignored. Instead the menu is shown. PressKey(ui::VKEY_RETURN); @@ -592,7 +594,8 @@ InitCombobox(nullptr); TestComboboxListener listener; - combobox_->set_listener(&listener); + combobox_->set_callback(base::BindRepeating( + &TestComboboxListener::OnPerformAction, base::Unretained(&listener))); // The click event is ignored. Instead the menu is shwon. PressKey(ui::VKEY_SPACE); @@ -638,7 +641,8 @@ InitCombobox(nullptr); TestComboboxListener listener; - combobox_->set_listener(&listener); + combobox_->set_callback(base::BindRepeating( + &TestComboboxListener::OnPerformAction, base::Unretained(&listener))); combobox_->Layout(); @@ -757,7 +761,8 @@ InitCombobox(nullptr); TestComboboxListener listener; - combobox_->set_listener(&listener); + combobox_->set_callback(base::BindRepeating( + &TestComboboxListener::OnPerformAction, base::Unretained(&listener))); ui::TextInputClient* input_client = widget_->GetInputMethod()->GetTextInputClient();
diff --git a/ui/views/controls/scroll_view.cc b/ui/views/controls/scroll_view.cc index 79ade55..1242d34 100644 --- a/ui/views/controls/scroll_view.cc +++ b/ui/views/controls/scroll_view.cc
@@ -167,7 +167,7 @@ corner_view_(std::make_unique<ScrollCornerView>()), scroll_with_layers_enabled_(base::FeatureList::IsEnabled( ::features::kUiCompositorScrollWithLayers)) { - set_notify_enter_exit_on_child(true); + SetNotifyEnterExitOnChild(true); // Since |contents_viewport_| is accessed during the AddChildView call, make // sure the field is initialized.
diff --git a/ui/views/controls/scrollbar/overlay_scroll_bar.cc b/ui/views/controls/scrollbar/overlay_scroll_bar.cc index 49efa4d6..e58df08 100644 --- a/ui/views/controls/scrollbar/overlay_scroll_bar.cc +++ b/ui/views/controls/scrollbar/overlay_scroll_bar.cc
@@ -127,7 +127,7 @@ } OverlayScrollBar::OverlayScrollBar(bool horizontal) : ScrollBar(horizontal) { - set_notify_enter_exit_on_child(true); + SetNotifyEnterExitOnChild(true); SetPaintToLayer(); layer()->SetMasksToBounds(true); layer()->SetFillsBoundsOpaquely(false);
diff --git a/ui/views/controls/styled_label_unittest.cc b/ui/views/controls/styled_label_unittest.cc index dfd5ba7..4e5b2cd 100644 --- a/ui/views/controls/styled_label_unittest.cc +++ b/ui/views/controls/styled_label_unittest.cc
@@ -22,7 +22,6 @@ #include "ui/gfx/font_list.h" #include "ui/views/border.h" #include "ui/views/controls/link.h" -#include "ui/views/controls/styled_label_listener.h" #include "ui/views/style/typography.h" #include "ui/views/test/test_layout_provider.h" #include "ui/views/test/test_views.h"
diff --git a/ui/views/examples/box_layout_example.h b/ui/views/examples/box_layout_example.h index 54cc9bb..ad38ddf 100644 --- a/ui/views/examples/box_layout_example.h +++ b/ui/views/examples/box_layout_example.h
@@ -28,14 +28,14 @@ // Set the border insets on the current BoxLayout instance. void UpdateBorderInsets(); - // ComboboxListener + // LayoutExampleBase: void OnPerformAction(Combobox* combobox) override; - // TextfieldController + // TextfieldController: void ContentsChanged(Textfield* sender, const base::string16& new_contents) override; - // LayoutExampleBase + // LayoutExampleBase: void ButtonPressedImpl(Button* sender) override; void CreateAdditionalControls(int vertical_start_pos) override; void UpdateLayoutManager() override;
diff --git a/ui/views/examples/combobox_example.cc b/ui/views/examples/combobox_example.cc index 79f9c20..f5351f01 100644 --- a/ui/views/examples/combobox_example.cc +++ b/ui/views/examples/combobox_example.cc
@@ -46,12 +46,14 @@ combobox_ = container->AddChildView( std::make_unique<Combobox>(std::make_unique<ComboboxModelExample>())); - combobox_->set_listener(this); + combobox_->set_callback(base::BindRepeating(&ComboboxExample::OnPerformAction, + base::Unretained(this))); combobox_->SetSelectedIndex(3); auto* disabled_combobox = container->AddChildView( std::make_unique<Combobox>(std::make_unique<ComboboxModelExample>())); - disabled_combobox->set_listener(this); + disabled_combobox->set_callback(base::BindRepeating( + &ComboboxExample::OnPerformAction, base::Unretained(this))); disabled_combobox->SetSelectedIndex(4); disabled_combobox->SetEnabled(false); }
diff --git a/ui/views/examples/combobox_example.h b/ui/views/examples/combobox_example.h index e48f4c1..41d9a14b 100644 --- a/ui/views/examples/combobox_example.h +++ b/ui/views/examples/combobox_example.h
@@ -7,14 +7,13 @@ #include "base/macros.h" #include "ui/base/models/combobox_model.h" -#include "ui/views/controls/combobox/combobox_listener.h" #include "ui/views/examples/example_base.h" namespace views { +class Combobox; namespace examples { -class VIEWS_EXAMPLES_EXPORT ComboboxExample : public ExampleBase, - public ComboboxListener { +class VIEWS_EXAMPLES_EXPORT ComboboxExample : public ExampleBase { public: ComboboxExample(); ~ComboboxExample() override; @@ -23,8 +22,7 @@ void CreateExampleView(View* container) override; private: - // ComboboxListener: - void OnPerformAction(Combobox* combobox) override; + void OnPerformAction(Combobox* combobox); Combobox* combobox_ = nullptr;
diff --git a/ui/views/examples/dialog_example.cc b/ui/views/examples/dialog_example.cc index b0fc72f..ca6e2ba3 100644 --- a/ui/views/examples/dialog_example.cc +++ b/ui/views/examples/dialog_example.cc
@@ -153,7 +153,8 @@ StartRowWithLabel(layout, "Modal Type"); mode_ = layout->AddView(std::make_unique<Combobox>(&mode_model_)); - mode_->set_listener(this); + mode_->set_closure(base::BindRepeating(&DialogExample::OnPerformAction, + base::Unretained(this))); mode_->SetSelectedIndex(ui::MODAL_TYPE_CHILD); StartRowWithLabel(layout, "Bubble"); @@ -274,12 +275,12 @@ LogStatus("You nearly always want Child Modal for bubbles."); } persistent_bubble_->SetEnabled(bubble_->GetChecked()); - OnPerformAction(mode_); // Validate the modal type. + OnPerformAction(); // Validate the modal type. if (!bubble_->GetChecked() && GetModalType() == ui::MODAL_TYPE_CHILD) { // Do something reasonable when simply unchecking bubble and re-enable. mode_->SetSelectedIndex(ui::MODAL_TYPE_WINDOW); - OnPerformAction(mode_); + OnPerformAction(); } return; } @@ -310,7 +311,7 @@ ResizeDialog(); } -void DialogExample::OnPerformAction(Combobox* combobox) { +void DialogExample::OnPerformAction() { bool enable = bubble_->GetChecked() || GetModalType() != ui::MODAL_TYPE_CHILD; #if defined(OS_APPLE) enable = enable && GetModalType() != ui::MODAL_TYPE_SYSTEM;
diff --git a/ui/views/examples/dialog_example.h b/ui/views/examples/dialog_example.h index 3731846..a4c89058 100644 --- a/ui/views/examples/dialog_example.h +++ b/ui/views/examples/dialog_example.h
@@ -8,7 +8,6 @@ #include "base/macros.h" #include "ui/base/models/simple_combobox_model.h" #include "ui/views/controls/button/button.h" -#include "ui/views/controls/combobox/combobox_listener.h" #include "ui/views/controls/textfield/textfield_controller.h" #include "ui/views/examples/example_base.h" @@ -27,8 +26,7 @@ // An example that exercises BubbleDialogDelegateView or DialogDelegateView. class VIEWS_EXAMPLES_EXPORT DialogExample : public ExampleBase, public ButtonListener, - public TextfieldController, - public ComboboxListener { + public TextfieldController { public: DialogExample(); ~DialogExample() override; @@ -50,6 +48,9 @@ const char* value); void AddCheckbox(GridLayout* layout, Checkbox** member); + // Checkbox callback + void OnPerformAction(); + // Interrogates the configuration Views for DialogDelegate. ui::ModalType GetModalType() const; int GetDialogButtons() const; @@ -67,9 +68,6 @@ void ContentsChanged(Textfield* sender, const base::string16& new_contents) override; - // ComboboxListener: - void OnPerformAction(Combobox* combobox) override; - DialogDelegate* last_dialog_ = nullptr; Label* last_body_label_ = nullptr;
diff --git a/ui/views/examples/examples_window.cc b/ui/views/examples/examples_window.cc index 8b0a5ae3..b023a17c 100644 --- a/ui/views/examples/examples_window.cc +++ b/ui/views/examples/examples_window.cc
@@ -21,7 +21,6 @@ #include "ui/base/ui_base_paths.h" #include "ui/views/background.h" #include "ui/views/controls/combobox/combobox.h" -#include "ui/views/controls/combobox/combobox_listener.h" #include "ui/views/controls/label.h" #include "ui/views/examples/create_examples.h" #include "ui/views/layout/fill_layout.h" @@ -109,8 +108,7 @@ DISALLOW_COPY_AND_ASSIGN(ComboboxModelExampleList); }; -class ExamplesWindowContents : public WidgetDelegateView, - public ComboboxListener { +class ExamplesWindowContents : public WidgetDelegateView { public: ExamplesWindowContents(base::OnceClosure on_close, ExampleVector examples) : on_close_(std::move(on_close)) { @@ -122,7 +120,8 @@ auto combobox = std::make_unique<Combobox>(std::move(combobox_model)); instance_ = this; - combobox->set_listener(this); + combobox->set_callback(base::BindRepeating( + &ExamplesWindowContents::OnPerformAction, base::Unretained(this))); SetBackground(CreateThemedSolidBackground( this, ui::NativeTheme::kColorId_DialogBackground)); @@ -181,10 +180,9 @@ return size; } - // ComboboxListener: - void OnPerformAction(Combobox* combobox) override { + void OnPerformAction(Combobox* combobox) { DCHECK_EQ(combobox, combobox_); - int index = combobox->GetSelectedIndex(); + int index = combobox_->GetSelectedIndex(); DCHECK_LT(index, combobox_model_->GetItemCount()); example_shown_->RemoveAllChildViews(false); example_shown_->AddChildView(combobox_model_->GetItemViewAt(index));
diff --git a/ui/views/examples/flex_layout_example.h b/ui/views/examples/flex_layout_example.h index def9045..640028cd 100644 --- a/ui/views/examples/flex_layout_example.h +++ b/ui/views/examples/flex_layout_example.h
@@ -8,7 +8,6 @@ #include "base/macros.h" #include "ui/views/controls/button/button.h" #include "ui/views/controls/button/label_button.h" -#include "ui/views/controls/combobox/combobox_listener.h" #include "ui/views/controls/textfield/textfield_controller.h" #include "ui/views/examples/layout_example_base.h" #include "ui/views/layout/flex_layout.h" @@ -27,14 +26,10 @@ ~FlexLayoutExample() override; private: - // ComboboxListener + // LayoutExampleBase: void OnPerformAction(Combobox* combobox) override; - - // TextfieldController void ContentsChanged(Textfield* sender, const base::string16& new_contents) override; - - // LayoutExampleBase void ButtonPressedImpl(Button* sender) override; void CreateAdditionalControls(int vertical_start_pos) override; void UpdateLayoutManager() override;
diff --git a/ui/views/examples/label_example.cc b/ui/views/examples/label_example.cc index 61c25bb..4628850 100644 --- a/ui/views/examples/label_example.cc +++ b/ui/views/examples/label_example.cc
@@ -143,6 +143,8 @@ } void LabelExample::OnPerformAction(Combobox* combobox) { + // TODO(pbos): Provide different callbacks for alignment_ and elide_behavior_ + // instead. if (combobox == alignment_) { custom_label_->SetHorizontalAlignment( static_cast<gfx::HorizontalAlignment>(combobox->GetSelectedIndex())); @@ -229,7 +231,8 @@ auto combobox = std::make_unique<Combobox>( std::make_unique<ExampleComboboxModel>(strings, count)); combobox->SetSelectedIndex(0); - combobox->set_listener(this); + combobox->set_callback(base::BindRepeating(&LabelExample::OnPerformAction, + base::Unretained(this))); return layout->AddView(std::move(combobox)); }
diff --git a/ui/views/examples/label_example.h b/ui/views/examples/label_example.h index 2cbe96c..597ce92a 100644 --- a/ui/views/examples/label_example.h +++ b/ui/views/examples/label_example.h
@@ -7,13 +7,13 @@ #include "base/macros.h" #include "ui/views/controls/button/button.h" -#include "ui/views/controls/combobox/combobox_listener.h" #include "ui/views/controls/textfield/textfield_controller.h" #include "ui/views/examples/example_base.h" namespace views { class Checkbox; +class Combobox; class GridLayout; class Label; @@ -21,7 +21,6 @@ class VIEWS_EXAMPLES_EXPORT LabelExample : public ExampleBase, public ButtonListener, - public ComboboxListener, public TextfieldController { public: LabelExample(); @@ -33,8 +32,7 @@ // ButtonListener: void ButtonPressed(Button* button, const ui::Event& event) override; - // ComboboxListener: - void OnPerformAction(Combobox* combobox) override; + void OnPerformAction(Combobox* combobox); // TextfieldController: void ContentsChanged(Textfield* sender,
diff --git a/ui/views/examples/layout_example_base.cc b/ui/views/examples/layout_example_base.cc index dabba6a..6f64367 100644 --- a/ui/views/examples/layout_example_base.cc +++ b/ui/views/examples/layout_example_base.cc
@@ -169,7 +169,8 @@ gfx::Point(label->x() + label->width() + kLayoutExampleVerticalSpacing, *vertical_pos)); combo_box->SizeToPreferredSize(); - combo_box->set_listener(this); + combo_box->set_callback(base::BindRepeating( + &LayoutExampleBase::OnPerformAction, base::Unretained(this))); label->SetSize(gfx::Size(label->width(), combo_box->height())); control_panel_->AddChildView(std::move(label));
diff --git a/ui/views/examples/layout_example_base.h b/ui/views/examples/layout_example_base.h index 7e41f98..fe34e50d 100644 --- a/ui/views/examples/layout_example_base.h +++ b/ui/views/examples/layout_example_base.h
@@ -10,12 +10,13 @@ #include "ui/views/controls/button/button.h" #include "ui/views/controls/button/checkbox.h" #include "ui/views/controls/button/label_button.h" -#include "ui/views/controls/combobox/combobox_listener.h" #include "ui/views/controls/textfield/textfield_controller.h" #include "ui/views/examples/example_base.h" #include "ui/views/view.h" namespace views { +class Combobox; + namespace examples { // Provides an example of a layout manager with arbitrary specific manager and @@ -23,7 +24,6 @@ // manager of choice. class VIEWS_EXAMPLES_EXPORT LayoutExampleBase : public ExampleBase, public ButtonListener, - public ComboboxListener, public TextfieldController { public: // Grouping of multiple textfields that provide insets. @@ -127,6 +127,9 @@ // common controls is done. virtual void ButtonPressedImpl(Button* sender); + // Combobox callback defined by child classes. + virtual void OnPerformAction(views::Combobox* combobox) = 0; + // Performs layout-specific update of the layout manager. virtual void UpdateLayoutManager() = 0;
diff --git a/ui/views/examples/text_example.cc b/ui/views/examples/text_example.cc index 7e0e015..85a8f8bd 100644 --- a/ui/views/examples/text_example.cc +++ b/ui/views/examples/text_example.cc
@@ -154,7 +154,8 @@ auto combobox = std::make_unique<Combobox>( std::make_unique<ExampleComboboxModel>(strings, count)); combobox->SetSelectedIndex(0); - combobox->set_listener(this); + combobox->set_callback(base::BindRepeating(&TextExample::OnPerformAction, + base::Unretained(this))); return layout->AddView(std::move(combobox), kNumColumns - 1, 1); }
diff --git a/ui/views/examples/text_example.h b/ui/views/examples/text_example.h index fc0f5c42..8913a58 100644 --- a/ui/views/examples/text_example.h +++ b/ui/views/examples/text_example.h
@@ -10,18 +10,17 @@ #include "base/macros.h" #include "ui/views/controls/button/button.h" -#include "ui/views/controls/combobox/combobox_listener.h" #include "ui/views/examples/example_base.h" namespace views { class Checkbox; +class Combobox; class GridLayout; namespace examples { class VIEWS_EXAMPLES_EXPORT TextExample : public ExampleBase, - public ButtonListener, - public ComboboxListener { + public ButtonListener { public: TextExample(); ~TextExample() override; @@ -39,12 +38,11 @@ const char* const* strings, int count); + void OnPerformAction(Combobox* combobox); + // ButtonListener: void ButtonPressed(Button* button, const ui::Event& event) override; - // ComboboxListener: - void OnPerformAction(Combobox* combobox) override; - class TextExampleView; // The content of the scroll view. TextExampleView* text_view_;
diff --git a/ui/views/view.cc b/ui/views/view.cc index 3f0483f..759495d 100644 --- a/ui/views/view.cc +++ b/ui/views/view.cc
@@ -1316,6 +1316,14 @@ void View::OnGestureEvent(ui::GestureEvent* event) {} +void View::SetNotifyEnterExitOnChild(bool notify) { + notify_enter_exit_on_child_ = notify; +} + +bool View::GetNotifyEnterExitOnChild() const { + return notify_enter_exit_on_child_; +} + const ui::InputMethod* View::GetInputMethod() const { Widget* widget = const_cast<Widget*>(GetWidget()); return widget ? const_cast<const ui::InputMethod*>(widget->GetInputMethod()) @@ -3013,6 +3021,7 @@ ADD_READONLY_PROPERTY_METADATA(gfx::Size, MaximumSize) ADD_READONLY_PROPERTY_METADATA(gfx::Size, MinimumSize) ADD_PROPERTY_METADATA(bool, Mirrored) +ADD_PROPERTY_METADATA(bool, NotifyEnterExitOnChild) ADD_PROPERTY_METADATA(bool, Visible) END_METADATA
diff --git a/ui/views/view.h b/ui/views/view.h index c63089d..32032125 100644 --- a/ui/views/view.h +++ b/ui/views/view.h
@@ -1069,12 +1069,8 @@ virtual bool OnMouseWheel(const ui::MouseWheelEvent& event); // See field for description. - void set_notify_enter_exit_on_child(bool notify) { - notify_enter_exit_on_child_ = notify; - } - bool notify_enter_exit_on_child() const { - return notify_enter_exit_on_child_; - } + void SetNotifyEnterExitOnChild(bool notify); + bool GetNotifyEnterExitOnChild() const; // Convenience method to retrieve the InputMethod associated with the // Widget that contains this view.
diff --git a/ui/views/view_unittest.cc b/ui/views/view_unittest.cc index 33cf87d..798f71c 100644 --- a/ui/views/view_unittest.cc +++ b/ui/views/view_unittest.cc
@@ -1698,7 +1698,7 @@ TestView* v = new TestView; v->SetBounds(0, 0, 100, 100); root_view->AddChildView(v); - v->set_notify_enter_exit_on_child(true); + v->SetNotifyEnterExitOnChild(true); TestView* v_child = new TestView; v_child->SetBounds(0, 0, 20, 30); @@ -1857,7 +1857,7 @@ TestView* v1 = new TestView; v1->SetBounds(0, 0, 100, 100); root_view->AddChildView(v1); - v1->set_notify_enter_exit_on_child(true); + v1->SetNotifyEnterExitOnChild(true); TestView* v11 = new TestView; v11->SetBounds(0, 0, 20, 30);
diff --git a/ui/views/widget/root_view.cc b/ui/views/widget/root_view.cc index be4c65d5..87beb3fb 100644 --- a/ui/views/widget/root_view.cc +++ b/ui/views/widget/root_view.cc
@@ -506,7 +506,7 @@ if (v && v != this) { if (v != mouse_move_handler_) { if (mouse_move_handler_ != nullptr && - (!mouse_move_handler_->notify_enter_exit_on_child() || + (!mouse_move_handler_->GetNotifyEnterExitOnChild() || !mouse_move_handler_->Contains(v))) { MouseEnterExitEvent exit(event, ui::ET_MOUSE_EXITED); exit.ConvertLocationToTarget(static_cast<View*>(this), @@ -531,7 +531,7 @@ } View* old_handler = mouse_move_handler_; mouse_move_handler_ = v; - if (!mouse_move_handler_->notify_enter_exit_on_child() || + if (!mouse_move_handler_->GetNotifyEnterExitOnChild() || !mouse_move_handler_->Contains(old_handler)) { MouseEnterExitEvent entered(event, ui::ET_MOUSE_ENTERED); entered.ConvertLocationToTarget(static_cast<View*>(this), @@ -728,7 +728,7 @@ View* view, View* sibling) { for (View* p = view->parent(); p; p = p->parent()) { - if (!p->notify_enter_exit_on_child()) + if (!p->GetNotifyEnterExitOnChild()) continue; if (sibling && p->Contains(sibling)) break;
diff --git a/ui/views/widget/root_view_unittest.cc b/ui/views/widget/root_view_unittest.cc index 024f2ff..a733d70 100644 --- a/ui/views/widget/root_view_unittest.cc +++ b/ui/views/widget/root_view_unittest.cc
@@ -695,7 +695,7 @@ subchild->SetBounds(0, 0, 100, 100); // Make mouse enter and exit events get propagated from |subchild| to |child|. - child->set_notify_enter_exit_on_child(true); + child->SetNotifyEnterExitOnChild(true); internal::RootView* root_view = static_cast<internal::RootView*>(widget->GetRootView());
diff --git a/weblayer/browser/password_manager_driver_factory.cc b/weblayer/browser/password_manager_driver_factory.cc index 8bdf396..2b59c275 100644 --- a/weblayer/browser/password_manager_driver_factory.cc +++ b/weblayer/browser/password_manager_driver_factory.cc
@@ -38,16 +38,16 @@ const std::vector<autofill::FormData>& visible_forms_data, bool did_stop_loading) override {} void PasswordFormSubmitted(const autofill::FormData& form_data) override {} - void ShowManualFallbackForSaving( - const autofill::FormData& form_data) override { + void InformAboutUserInput(const autofill::FormData& form_data) override { if (!password_manager::bad_message::CheckChildProcessSecurityPolicyForURL( render_frame_host_, form_data.url, password_manager::BadMessageReason:: - CPMD_BAD_ORIGIN_SHOW_FALLBACK_FOR_SAVING)) { + CPMD_BAD_ORIGIN_UPON_USER_INPUT_CHANGE)) { return; } - if (site_isolation::SiteIsolationPolicy:: + if (FormHasNonEmptyPasswordField(form_data) && + site_isolation::SiteIsolationPolicy:: IsIsolationForPasswordSitesEnabled()) { // This function signals that a password field has been filled (whether by // the user, JS, autofill, or some other means) or a password form has @@ -59,7 +59,6 @@ form_data.url); } } - void HideManualFallbackForSaving() override {} void SameDocumentNavigation(autofill::mojom::SubmissionIndicatorEvent submission_indication_event) override {} void RecordSavePasswordProgress(const std::string& log) override {}
diff --git a/weblayer/shell/android/shell_apk/res/layout/main.xml b/weblayer/shell/android/shell_apk/res/layout/main.xml index eb1c9c1..bf49ade6 100644 --- a/weblayer/shell/android/shell_apk/res/layout/main.xml +++ b/weblayer/shell/android/shell_apk/res/layout/main.xml
@@ -3,28 +3,32 @@ Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. --> -<RelativeLayout +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> - <ImageButton - android:id="@+id/controls_menu_button" - android:layout_width="25dp" - android:layout_height="25dp" - android:scaleType="fitXY" - android:paddingLeft="5px" - android:paddingRight="5px" - android:src="@android:drawable/ic_menu_more" - android:background="@android:color/transparent" /> - <TextView - android:id="@+id/version_text" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_toRightOf="@id/controls_menu_button" - android:paddingTop="5px" /> + <LinearLayout + android:orientation="horizontal" + android:layout_width="match_parent" + android:layout_height="wrap_content"> + <ImageButton + android:id="@+id/controls_menu_button" + android:layout_width="25dp" + android:layout_height="25dp" + android:scaleType="fitXY" + android:paddingLeft="5px" + android:paddingRight="5px" + android:src="@android:drawable/ic_menu_more" + android:background="@android:color/transparent" /> + <TextView + android:id="@+id/version_text" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:paddingTop="5px" /> + </LinearLayout> <FrameLayout android:id="@+id/weblayer" android:layout_width="match_parent" - android:layout_height="match_parent" - android:layout_below="@id/controls_menu_button" /> -</RelativeLayout> + android:layout_height="match_parent" /> +</LinearLayout>